@ -32,7 +32,7 @@ static struct wlr_output_head_v1 *head_from_resource(
static const struct zwlr_output_mode_v1_interface output_mode_impl ;
static const struct zwlr_output_mode_v1_interface output_mode_impl ;
// Can return NULL if the mode is inert
// Can return NULL if the mode is custom or inert
static struct wlr_output_mode * mode_from_resource (
static struct wlr_output_mode * mode_from_resource (
struct wl_resource * resource ) {
struct wl_resource * resource ) {
assert ( wl_resource_instance_of ( resource ,
assert ( wl_resource_instance_of ( resource ,
@ -86,6 +86,28 @@ static struct wlr_output_head_v1 *head_create(
return head ;
return head ;
}
}
static void head_destroy_custom_mode_resources ( struct wlr_output_head_v1 * head ) {
struct wl_resource * resource , * tmp ;
wl_resource_for_each_safe ( resource , tmp , & head - > mode_resources ) {
if ( wl_resource_get_user_data ( resource ) ! = NULL ) {
continue ;
}
zwlr_output_mode_v1_send_finished ( resource ) ;
wl_list_remove ( wl_resource_get_link ( resource ) ) ;
wl_list_init ( wl_resource_get_link ( resource ) ) ;
}
}
static bool head_has_custom_mode_resources ( const struct wlr_output_head_v1 * head ) {
struct wl_resource * resource ;
wl_resource_for_each ( resource , & head - > mode_resources ) {
if ( wl_resource_get_user_data ( resource ) = = NULL ) {
return true ;
}
}
return false ;
}
static void config_head_destroy (
static void config_head_destroy (
struct wlr_output_configuration_head_v1 * config_head ) {
struct wlr_output_configuration_head_v1 * config_head ) {
@ -161,12 +183,12 @@ static void config_head_handle_set_mode(struct wl_client *client,
return ;
return ;
}
}
// Mode can be NULL if the output doesn't support modes (in which case we
// Mode can be NULL if the output uses a custom mode (in which case we
// expose only one "virtual" mode, the current mode)
// expose a virtual mode with user data set to NULL).
struct wlr_output_mode * mode = mode_from_resource ( mode_resource ) ;
struct wlr_output_mode * mode = mode_from_resource ( mode_resource ) ;
struct wlr_output * output = config_head - > state . output ;
struct wlr_output * output = config_head - > state . output ;
bool found = ( mode = = NULL & & wl_list_empty ( & output - > modes ) ) ;
bool found = mode = = NULL ;
struct wlr_output_mode * m ;
struct wlr_output_mode * m ;
wl_list_for_each ( m , & output - > modes , link ) {
wl_list_for_each ( m , & output - > modes , link ) {
if ( mode = = m ) {
if ( mode = = m ) {
@ -737,9 +759,6 @@ static void head_send_state(struct wlr_output_head_v1 *head,
}
}
if ( state & HEAD_STATE_MODE ) {
if ( state & HEAD_STATE_MODE ) {
assert ( head - > state . mode ! = NULL | |
wl_list_empty ( & head - > state . output - > modes ) ) ;
bool found = false ;
bool found = false ;
struct wl_resource * mode_resource ;
struct wl_resource * mode_resource ;
wl_resource_for_each ( mode_resource , & head - > mode_resources ) {
wl_resource_for_each ( mode_resource , & head - > mode_resources ) {
@ -847,8 +866,8 @@ static void manager_send_head(struct wlr_output_manager_v1 *manager,
head_send_mode ( head , head_resource , mode ) ;
head_send_mode ( head , head_resource , mode ) ;
}
}
if ( wl_list_empty ( & output - > modes ) ) {
if ( output - > current_mode = = NULL ) {
// Output doesn't support modes . Send a virtual one.
// Output doesn't have a fixed mode set . Send a virtual one.
head_send_mode ( head , head_resource , NULL ) ;
head_send_mode ( head , head_resource , NULL ) ;
}
}
@ -907,6 +926,15 @@ static bool manager_update_head(struct wlr_output_manager_v1 *manager,
}
}
}
}
if ( next - > mode = = NULL & & ! head_has_custom_mode_resources ( head ) ) {
struct wl_resource * resource ;
wl_resource_for_each ( resource , & head - > resources ) {
head_send_mode ( head , resource , NULL ) ;
}
} else if ( next - > mode ! = NULL ) {
head_destroy_custom_mode_resources ( head ) ;
}
if ( state ! = 0 ) {
if ( state ! = 0 ) {
* current = * next ;
* current = * next ;