diff --git a/include/types/wlr_data_device.h b/include/types/wlr_data_device.h index ee423f80d..972294ffe 100644 --- a/include/types/wlr_data_device.h +++ b/include/types/wlr_data_device.h @@ -13,6 +13,8 @@ struct wlr_client_data_source { struct wl_resource *resource; }; +extern const struct wlr_surface_role drag_icon_surface_role; + struct wlr_data_offer *data_offer_create(struct wl_client *client, struct wlr_data_source *source, uint32_t version); void data_offer_update_action(struct wlr_data_offer *offer); diff --git a/include/types/wlr_xdg_shell.h b/include/types/wlr_xdg_shell.h index 74f13bbef..7a17d2864 100644 --- a/include/types/wlr_xdg_shell.h +++ b/include/types/wlr_xdg_shell.h @@ -10,8 +10,8 @@ struct wlr_xdg_positioner_resource { struct wlr_xdg_positioner attrs; }; -#define XDG_TOPLEVEL_ROLE "xdg_toplevel" -#define XDG_POPUP_ROLE "xdg_popup" +extern const struct wlr_surface_role xdg_toplevel_surface_role; +extern const struct wlr_surface_role xdg_popup_surface_role; uint32_t schedule_xdg_surface_configure(struct wlr_xdg_surface *surface); struct wlr_xdg_surface *create_xdg_surface( @@ -19,6 +19,7 @@ struct wlr_xdg_surface *create_xdg_surface( uint32_t id); void unmap_xdg_surface(struct wlr_xdg_surface *surface); void destroy_xdg_surface(struct wlr_xdg_surface *surface); +void handle_xdg_surface_committed(struct wlr_surface *wlr_surface); void create_xdg_positioner(struct wlr_xdg_client *client, uint32_t id); struct wlr_xdg_positioner_resource *get_xdg_positioner_from_resource( diff --git a/include/types/wlr_xdg_shell_v6.h b/include/types/wlr_xdg_shell_v6.h index b53259982..030c10e42 100644 --- a/include/types/wlr_xdg_shell_v6.h +++ b/include/types/wlr_xdg_shell_v6.h @@ -10,8 +10,8 @@ struct wlr_xdg_positioner_v6_resource { struct wlr_xdg_positioner_v6 attrs; }; -#define XDG_TOPLEVEL_V6_ROLE "xdg_toplevel_v6" -#define XDG_POPUP_V6_ROLE "xdg_popup_v6" +extern const struct wlr_surface_role xdg_toplevel_v6_surface_role; +extern const struct wlr_surface_role xdg_popup_v6_surface_role; uint32_t schedule_xdg_surface_v6_configure(struct wlr_xdg_surface_v6 *surface); struct wlr_xdg_surface_v6 *create_xdg_surface_v6( @@ -19,6 +19,7 @@ struct wlr_xdg_surface_v6 *create_xdg_surface_v6( uint32_t id); void unmap_xdg_surface_v6(struct wlr_xdg_surface_v6 *surface); void destroy_xdg_surface_v6(struct wlr_xdg_surface_v6 *surface); +void handle_xdg_surface_v6_committed(struct wlr_surface *wlr_surface); void create_xdg_positioner_v6(struct wlr_xdg_client_v6 *client, uint32_t id); struct wlr_xdg_positioner_v6_resource *get_xdg_positioner_v6_from_resource( diff --git a/include/wlr/types/wlr_layer_shell.h b/include/wlr/types/wlr_layer_shell.h index 7cc6a5b8e..2848a1154 100644 --- a/include/wlr/types/wlr_layer_shell.h +++ b/include/wlr/types/wlr_layer_shell.h @@ -76,7 +76,7 @@ struct wlr_layer_surface { struct wlr_layer_surface_state server_pending; struct wlr_layer_surface_state current; - struct wl_listener surface_destroy_listener; + struct wl_listener surface_destroy; struct { struct wl_signal destroy; diff --git a/include/wlr/types/wlr_seat.h b/include/wlr/types/wlr_seat.h index 92d0a2333..1c7a14720 100644 --- a/include/wlr/types/wlr_seat.h +++ b/include/wlr/types/wlr_seat.h @@ -540,4 +540,6 @@ bool wlr_seat_validate_grab_serial(struct wlr_seat *seat, uint32_t serial); struct wlr_seat_client *wlr_seat_client_from_resource( struct wl_resource *resource); +bool wlr_surface_is_pointer_cursor(struct wlr_surface *surface); + #endif diff --git a/include/wlr/types/wlr_surface.h b/include/wlr/types/wlr_surface.h index b89da87a9..93f456cdf 100644 --- a/include/wlr/types/wlr_surface.h +++ b/include/wlr/types/wlr_surface.h @@ -36,6 +36,11 @@ struct wlr_surface_state { struct wl_listener buffer_destroy; }; +struct wlr_surface_role { + const char *name; + void (*commit)(struct wlr_surface *surface); +}; + struct wlr_surface { struct wl_resource *resource; struct wlr_renderer *renderer; @@ -68,7 +73,9 @@ struct wlr_surface { * the previous commit. */ struct wlr_surface_state current, pending, previous; - const char *role; // the lifetime-bound role or null + + const struct wlr_surface_role *role; // the lifetime-bound role or NULL + void *role_data; // role-specific data struct { struct wl_signal commit; @@ -76,10 +83,6 @@ struct wlr_surface { struct wl_signal destroy; } events; - // surface commit callback for the role that runs before all others - void (*role_committed)(struct wlr_surface *surface, void *role_data); - void *role_data; - struct wl_list subsurfaces; // wlr_subsurface::parent_link // wlr_subsurface::parent_pending_link @@ -137,7 +140,8 @@ struct wlr_surface *wlr_surface_create(struct wl_client *client, * Set the lifetime role for this surface. Returns 0 on success or -1 if the * role cannot be set. */ -int wlr_surface_set_role(struct wlr_surface *surface, const char *role, +bool wlr_surface_set_role(struct wlr_surface *surface, + const struct wlr_surface_role *role, void *role_data, struct wl_resource *error_resource, uint32_t error_code); /** @@ -200,14 +204,6 @@ struct wlr_box; */ void wlr_surface_get_extends(struct wlr_surface *surface, struct wlr_box *box); -/** - * Set a callback for surface commit that runs before all the other callbacks. - * This is intended for use by the surface role. - */ -void wlr_surface_set_role_committed(struct wlr_surface *surface, - void (*role_committed)(struct wlr_surface *surface, void *role_data), - void *role_data); - struct wlr_surface *wlr_surface_from_resource(struct wl_resource *resource); /** diff --git a/include/wlr/types/wlr_wl_shell.h b/include/wlr/types/wlr_wl_shell.h index e2d4b5bb1..c4cc1999a 100644 --- a/include/wlr/types/wlr_wl_shell.h +++ b/include/wlr/types/wlr_wl_shell.h @@ -69,7 +69,7 @@ struct wlr_wl_shell_surface { char *title; char *class; - struct wl_listener surface_destroy_listener; + struct wl_listener surface_destroy; struct wlr_wl_shell_surface *parent; struct wl_list popup_link; @@ -152,7 +152,7 @@ struct wlr_surface *wlr_wl_shell_surface_surface_at( bool wlr_surface_is_wl_shell_surface(struct wlr_surface *surface); -struct wlr_wl_surface *wlr_wl_shell_surface_from_wlr_surface( +struct wlr_wl_shell_surface *wlr_wl_shell_surface_from_wlr_surface( struct wlr_surface *surface); /** diff --git a/include/wlr/types/wlr_xdg_shell.h b/include/wlr/types/wlr_xdg_shell.h index 79e029d4e..9c0e6adc0 100644 --- a/include/wlr/types/wlr_xdg_shell.h +++ b/include/wlr/types/wlr_xdg_shell.h @@ -163,7 +163,8 @@ struct wlr_xdg_surface { struct wlr_box next_geometry; struct wlr_box geometry; - struct wl_listener surface_destroy_listener; + struct wl_listener surface_destroy; + struct wl_listener surface_commit; struct { struct wl_signal destroy; diff --git a/include/wlr/types/wlr_xdg_shell_v6.h b/include/wlr/types/wlr_xdg_shell_v6.h index fdfb23c51..2e1b6f11c 100644 --- a/include/wlr/types/wlr_xdg_shell_v6.h +++ b/include/wlr/types/wlr_xdg_shell_v6.h @@ -161,7 +161,8 @@ struct wlr_xdg_surface_v6 { struct wlr_box next_geometry; struct wlr_box geometry; - struct wl_listener surface_destroy_listener; + struct wl_listener surface_destroy; + struct wl_listener surface_commit; struct { struct wl_signal destroy; diff --git a/types/data_device/wlr_data_device.c b/types/data_device/wlr_data_device.c index a51f23ef5..40974de7f 100644 --- a/types/data_device/wlr_data_device.c +++ b/types/data_device/wlr_data_device.c @@ -56,10 +56,8 @@ static void data_device_start_drag(struct wl_client *client, if (icon_resource) { icon = wlr_surface_from_resource(icon_resource); - } - if (icon) { - if (wlr_surface_set_role(icon, "wl_data_device-icon", - icon_resource, WL_DATA_DEVICE_ERROR_ROLE) < 0) { + if (!wlr_surface_set_role(icon, &drag_icon_surface_role, NULL, + icon_resource, WL_DATA_DEVICE_ERROR_ROLE)) { return; } } diff --git a/types/data_device/wlr_drag.c b/types/data_device/wlr_drag.c index bae098c52..7f3b346d3 100644 --- a/types/data_device/wlr_drag.c +++ b/types/data_device/wlr_drag.c @@ -324,7 +324,7 @@ static void drag_icon_destroy(struct wlr_drag_icon *icon) { } drag_icon_set_mapped(icon, false); wlr_signal_emit_safe(&icon->events.destroy, icon); - wlr_surface_set_role_committed(icon->surface, NULL, NULL); + icon->surface->role_data = NULL; wl_list_remove(&icon->surface_destroy.link); wl_list_remove(&icon->seat_client_destroy.link); wl_list_remove(&icon->link); @@ -338,15 +338,24 @@ static void drag_icon_handle_surface_destroy(struct wl_listener *listener, drag_icon_destroy(icon); } -static void drag_icon_handle_surface_commit(struct wlr_surface *surface, - void *role_data) { - struct wlr_drag_icon *icon = role_data; +static void drag_icon_surface_role_commit(struct wlr_surface *surface) { + assert(surface->role == &drag_icon_surface_role); + struct wlr_drag_icon *icon = surface->role_data; + if (icon == NULL) { + return; + } + icon->sx += icon->surface->current.dx; icon->sy += icon->surface->current.dy; drag_icon_set_mapped(icon, wlr_surface_has_buffer(surface)); } +const struct wlr_surface_role drag_icon_surface_role = { + .name = "wl_data_device-icon", + .commit = drag_icon_surface_role_commit, +}; + static void drag_icon_handle_seat_client_destroy(struct wl_listener *listener, void *data) { struct wlr_drag_icon *icon = @@ -375,12 +384,11 @@ static struct wlr_drag_icon *drag_icon_create( wl_signal_add(&icon->surface->events.destroy, &icon->surface_destroy); icon->surface_destroy.notify = drag_icon_handle_surface_destroy; - wlr_surface_set_role_committed(icon->surface, - drag_icon_handle_surface_commit, icon); - wl_signal_add(&client->events.destroy, &icon->seat_client_destroy); icon->seat_client_destroy.notify = drag_icon_handle_seat_client_destroy; + icon->surface->role_data = icon; + wl_list_insert(&client->seat->drag_icons, &icon->link); wlr_signal_emit_safe(&client->seat->events.new_drag_icon, icon); diff --git a/types/seat/wlr_seat_pointer.c b/types/seat/wlr_seat_pointer.c index 3271c090d..e54b79bf6 100644 --- a/types/seat/wlr_seat_pointer.c +++ b/types/seat/wlr_seat_pointer.c @@ -60,6 +60,10 @@ static struct wlr_seat_client *seat_client_from_pointer_resource( return wl_resource_get_user_data(resource); } +static const struct wlr_surface_role pointer_cursor_surface_role = { + .name = "wl_pointer-cursor", +}; + static void pointer_set_cursor(struct wl_client *client, struct wl_resource *pointer_resource, uint32_t serial, struct wl_resource *surface_resource, @@ -73,8 +77,8 @@ static void pointer_set_cursor(struct wl_client *client, struct wlr_surface *surface = NULL; if (surface_resource != NULL) { surface = wlr_surface_from_resource(surface_resource); - if (wlr_surface_set_role(surface, "wl_pointer-cursor", surface_resource, - WL_POINTER_ERROR_ROLE) < 0) { + if (!wlr_surface_set_role(surface, &pointer_cursor_surface_role, NULL, + surface_resource, WL_POINTER_ERROR_ROLE)) { return; } } @@ -351,3 +355,7 @@ void seat_client_destroy_pointer(struct wl_resource *resource) { } wl_resource_set_user_data(resource, NULL); } + +bool wlr_surface_is_pointer_cursor(struct wlr_surface *surface) { + return surface->role == &pointer_cursor_surface_role; +} diff --git a/types/wlr_compositor.c b/types/wlr_compositor.c index 5aec40028..7702a7788 100644 --- a/types/wlr_compositor.c +++ b/types/wlr_compositor.c @@ -10,11 +10,10 @@ #define COMPOSITOR_VERSION 4 #define SUBCOMPOSITOR_VERSION 1 -static const char *subsurface_role = "wl_subsurface"; +extern const struct wlr_surface_role subsurface_role; bool wlr_surface_is_subsurface(struct wlr_surface *surface) { - return surface->role != NULL && - strcmp(surface->role, subsurface_role) == 0; + return surface->role == &subsurface_role; } struct wlr_subsurface *wlr_subsurface_from_wlr_surface( @@ -73,8 +72,8 @@ static void subcompositor_handle_get_subsurface(struct wl_client *client, return; } - if (wlr_surface_set_role(surface, subsurface_role, resource, - WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE) < 0) { + if (!wlr_surface_set_role(surface, &subsurface_role, NULL, + resource, WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE)) { return; } diff --git a/types/wlr_layer_shell.c b/types/wlr_layer_shell.c index c39339561..5d610ece9 100644 --- a/types/wlr_layer_shell.c +++ b/types/wlr_layer_shell.c @@ -11,8 +11,6 @@ #include "util/signal.h" #include "wlr-layer-shell-unstable-v1-protocol.h" -static const char *zwlr_layer_surface_role = "zwlr_layer_surface"; - static void resource_handle_destroy(struct wl_client *client, struct wl_resource *resource) { wl_resource_destroy(resource); @@ -35,8 +33,10 @@ static struct wlr_layer_surface *layer_surface_from_resource( return wl_resource_get_user_data(resource); } +static const struct wlr_surface_role layer_surface_role; + bool wlr_surface_is_layer_surface(struct wlr_surface *surface) { - return strcmp(surface->role, zwlr_layer_surface_role) == 0; + return surface->role == &layer_surface_role; } struct wlr_layer_surface *wlr_layer_surface_from_wlr_surface( @@ -181,9 +181,8 @@ static void layer_surface_destroy(struct wlr_layer_surface *surface) { } wlr_signal_emit_safe(&surface->events.destroy, surface); wl_resource_set_user_data(surface->resource, NULL); - wl_list_remove(&surface->surface_destroy_listener.link); - wl_list_init(&surface->surface_destroy_listener.link); - wlr_surface_set_role_committed(surface->surface, NULL, NULL); + surface->surface->role_data = NULL; + wl_list_remove(&surface->surface_destroy.link); wl_list_remove(&surface->link); free(surface->namespace); free(surface); @@ -251,9 +250,12 @@ void wlr_layer_surface_close(struct wlr_layer_surface *surface) { zwlr_layer_surface_v1_send_closed(surface->resource); } -static void handle_surface_committed(struct wlr_surface *wlr_surface, - void *role_data) { - struct wlr_layer_surface *surface = role_data; +static void layer_surface_role_commit(struct wlr_surface *wlr_surface) { + struct wlr_layer_surface *surface = + wlr_layer_surface_from_wlr_surface(wlr_surface); + if (surface == NULL) { + return; + } if (surface->closed) { // Ignore commits after the compositor has closed it @@ -305,10 +307,15 @@ static void handle_surface_committed(struct wlr_surface *wlr_surface, } } +static const struct wlr_surface_role layer_surface_role = { + .name = "zwlr_layer_surface_v1", + .commit = layer_surface_role_commit, +}; + static void handle_surface_destroyed(struct wl_listener *listener, void *data) { struct wlr_layer_surface *layer_surface = - wl_container_of(listener, layer_surface, surface_destroy_listener); + wl_container_of(listener, layer_surface, surface_destroy); layer_surface_destroy(layer_surface); } @@ -322,11 +329,6 @@ static void layer_shell_handle_get_layer_surface(struct wl_client *wl_client, struct wlr_surface *wlr_surface = wlr_surface_from_resource(surface_resource); - if (wlr_surface_set_role(wlr_surface, zwlr_layer_surface_role, - client_resource, ZWLR_LAYER_SHELL_V1_ERROR_ROLE)) { - return; - } - struct wlr_layer_surface *surface = calloc(1, sizeof(struct wlr_layer_surface)); if (surface == NULL) { @@ -334,6 +336,12 @@ static void layer_shell_handle_get_layer_surface(struct wl_client *wl_client, return; } + if (!wlr_surface_set_role(wlr_surface, &layer_surface_role, surface, + client_resource, ZWLR_LAYER_SHELL_V1_ERROR_ROLE)) { + free(surface); + return; + } + surface->shell = shell; surface->surface = wlr_surface; if (output_resource) { @@ -368,15 +376,13 @@ static void layer_shell_handle_get_layer_surface(struct wl_client *wl_client, wl_list_init(&surface->popups); wl_signal_init(&surface->events.destroy); - wl_signal_add(&surface->surface->events.destroy, - &surface->surface_destroy_listener); - surface->surface_destroy_listener.notify = handle_surface_destroyed; wl_signal_init(&surface->events.map); wl_signal_init(&surface->events.unmap); wl_signal_init(&surface->events.new_popup); - wlr_surface_set_role_committed(surface->surface, - handle_surface_committed, surface); + wl_signal_add(&surface->surface->events.destroy, + &surface->surface_destroy); + surface->surface_destroy.notify = handle_surface_destroyed; wlr_log(WLR_DEBUG, "new layer_surface %p (res %p)", surface, surface->resource); diff --git a/types/wlr_output.c b/types/wlr_output.c index 440c31513..601cf16cd 100644 --- a/types/wlr_output.c +++ b/types/wlr_output.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -816,7 +817,8 @@ static void output_cursor_handle_destroy(struct wl_listener *listener, void wlr_output_cursor_set_surface(struct wlr_output_cursor *cursor, struct wlr_surface *surface, int32_t hotspot_x, int32_t hotspot_y) { - if (surface && strcmp(surface->role, "wl_pointer-cursor") != 0) { + if (surface && !wlr_surface_is_pointer_cursor(surface)) { + wlr_log(L_ERROR, "Tried to set a cursor surface with invalid role"); return; } diff --git a/types/wlr_surface.c b/types/wlr_surface.c index 77f7e90b8..3277b37f8 100644 --- a/types/wlr_surface.c +++ b/types/wlr_surface.c @@ -370,8 +370,8 @@ static void surface_commit_pending(struct wlr_surface *surface) { } } - if (surface->role_committed) { - surface->role_committed(surface, surface->role_data); + if (surface->role && surface->role->commit) { + surface->role->commit(surface); } wlr_signal_emit_safe(&surface->events.commit, surface); @@ -632,25 +632,25 @@ bool wlr_surface_has_buffer(struct wlr_surface *surface) { return wlr_surface_get_texture(surface) != NULL; } -int wlr_surface_set_role(struct wlr_surface *surface, const char *role, +bool wlr_surface_set_role(struct wlr_surface *surface, + const struct wlr_surface_role *role, void *role_data, struct wl_resource *error_resource, uint32_t error_code) { - assert(role); + assert(role != NULL); - if (surface->role == NULL || - surface->role == role || - strcmp(surface->role, role) == 0) { - surface->role = role; - - return 0; + if (surface->role != NULL && surface->role != role) { + if (error_resource != NULL) { + wl_resource_post_error(error_resource, error_code, + "Cannot assign role %s to wl_surface@%d, already has role %s\n", + role->name, wl_resource_get_id(surface->resource), + surface->role->name); + } + return false; } - wl_resource_post_error(error_resource, error_code, - "Cannot assign role %s to wl_surface@%d, already has role %s\n", - role, - wl_resource_get_id(surface->resource), - surface->role); - - return -1; + assert(surface->role_data == NULL); + surface->role = role; + surface->role_data = role_data; + return true; } static const struct wl_subsurface_interface subsurface_implementation; @@ -788,8 +788,12 @@ static const struct wl_subsurface_interface subsurface_implementation = { .set_desync = subsurface_handle_set_desync, }; -static void subsurface_role_committed(struct wlr_surface *surface, void *data) { - struct wlr_subsurface *subsurface = data; +static void subsurface_role_commit(struct wlr_surface *surface) { + struct wlr_subsurface *subsurface = + wlr_subsurface_from_wlr_surface(surface); + if (subsurface == NULL) { + return; + } if (subsurface->current.x != subsurface->pending.x || subsurface->current.y != subsurface->pending.y) { @@ -816,6 +820,11 @@ static void subsurface_role_committed(struct wlr_surface *surface, void *data) { } } +const struct wlr_surface_role subsurface_role = { + .name = "wl_subsurface", + .commit = subsurface_role_commit, +}; + static void subsurface_handle_parent_destroy(struct wl_listener *listener, void *data) { struct wlr_subsurface *subsurface = @@ -874,8 +883,7 @@ struct wlr_subsurface *wlr_subsurface_create(struct wlr_surface *surface, wl_list_insert(parent->subsurface_pending_list.prev, &subsurface->parent_pending_link); - wlr_surface_set_role_committed(surface, subsurface_role_committed, - subsurface); + surface->role_data = subsurface; struct wl_list *resource_link = wl_resource_get_link(subsurface->resource); if (resource_list != NULL) { @@ -964,13 +972,6 @@ void wlr_surface_send_frame_done(struct wlr_surface *surface, } } -void wlr_surface_set_role_committed(struct wlr_surface *surface, - void (*role_committed)(struct wlr_surface *surface, void *role_data), - void *role_data) { - surface->role_committed = role_committed; - surface->role_data = role_data; -} - static void surface_for_each_surface(struct wlr_surface *surface, int x, int y, wlr_surface_iterator_func_t iterator, void *user_data) { iterator(surface, x, y, user_data); diff --git a/types/wlr_wl_shell.c b/types/wlr_wl_shell.c index 020c60809..3543b2871 100644 --- a/types/wlr_wl_shell.c +++ b/types/wlr_wl_shell.c @@ -10,17 +10,16 @@ #include #include "util/signal.h" -static const char *wlr_wl_shell_surface_role = "wl-shell-surface"; +static const struct wlr_surface_role shell_surface_role; bool wlr_surface_is_wl_shell_surface(struct wlr_surface *surface) { - return surface->role != NULL && - strcmp(surface->role, wlr_wl_shell_surface_role) == 0; + return surface->role == &shell_surface_role; } -struct wlr_wl_surface *wlr_wl_shell_surface_from_wlr_surface( +struct wlr_wl_shell_surface *wlr_wl_shell_surface_from_wlr_surface( struct wlr_surface *surface) { assert(wlr_surface_is_wl_shell_surface(surface)); - return (struct wlr_wl_surface *)surface->role_data; + return (struct wlr_wl_shell_surface *)surface->role_data; } static void shell_pointer_grab_end(struct wlr_seat_pointer_grab *grab) { @@ -446,9 +445,9 @@ static void shell_surface_destroy(struct wlr_wl_shell_surface *surface) { } wl_list_remove(&surface->popup_link); + surface->surface->role_data = NULL; wl_list_remove(&surface->link); - wl_list_remove(&surface->surface_destroy_listener.link); - wlr_surface_set_role_committed(surface->surface, NULL, NULL); + wl_list_remove(&surface->surface_destroy.link); wl_event_source_remove(surface->ping_timer); free(surface->transient_state); free(surface->title); @@ -466,12 +465,17 @@ static void shell_surface_resource_destroy(struct wl_resource *resource) { static void shell_surface_handle_surface_destroy(struct wl_listener *listener, void *data) { struct wlr_wl_shell_surface *surface = - wl_container_of(listener, surface, surface_destroy_listener); + wl_container_of(listener, surface, surface_destroy); shell_surface_destroy(surface); } -static void handle_surface_committed(struct wlr_surface *wlr_surface, - void *role_data) { - struct wlr_wl_shell_surface *surface = role_data; + +static void shell_surface_role_commit(struct wlr_surface *wlr_surface) { + struct wlr_wl_shell_surface *surface = + wlr_wl_shell_surface_from_wlr_surface(wlr_surface); + if (surface == NULL) { + return; + } + if (!surface->configured && wlr_surface_has_buffer(surface->surface) && surface->state != WLR_WL_SHELL_SURFACE_STATE_NONE) { @@ -490,6 +494,11 @@ static void handle_surface_committed(struct wlr_surface *wlr_surface, } } +static const struct wlr_surface_role shell_surface_role = { + .name = "wl_shell_surface", + .commit = shell_surface_role_commit, +}; + static int shell_surface_ping_timeout(void *user_data) { struct wlr_wl_shell_surface *surface = user_data; wlr_signal_emit_safe(&surface->events.ping_timeout, surface); @@ -510,10 +519,6 @@ static void shell_protocol_get_shell_surface(struct wl_client *client, struct wl_resource *shell_resource, uint32_t id, struct wl_resource *surface_resource) { struct wlr_surface *surface = wlr_surface_from_resource(surface_resource); - if (wlr_surface_set_role(surface, wlr_wl_shell_surface_role, - shell_resource, WL_SHELL_ERROR_ROLE)) { - return; - } struct wlr_wl_shell *wl_shell = shell_from_resource(shell_resource); struct wlr_wl_shell_surface *wl_surface = @@ -522,6 +527,13 @@ static void shell_protocol_get_shell_surface(struct wl_client *client, wl_resource_post_no_memory(shell_resource); return; } + + if (!wlr_surface_set_role(surface, &shell_surface_role, wl_surface, + shell_resource, WL_SHELL_ERROR_ROLE)) { + free(wl_surface); + return; + } + wl_list_init(&wl_surface->grab_link); wl_list_init(&wl_surface->popup_link); wl_list_init(&wl_surface->popups); @@ -557,12 +569,8 @@ static void shell_protocol_get_shell_surface(struct wl_client *client, wl_signal_init(&wl_surface->events.set_class); wl_signal_add(&wl_surface->surface->events.destroy, - &wl_surface->surface_destroy_listener); - wl_surface->surface_destroy_listener.notify = - shell_surface_handle_surface_destroy; - - wlr_surface_set_role_committed(surface, handle_surface_committed, - wl_surface); + &wl_surface->surface_destroy); + wl_surface->surface_destroy.notify = shell_surface_handle_surface_destroy; struct wl_display *display = wl_client_get_display(client); struct wl_event_loop *loop = wl_display_get_event_loop(display); diff --git a/types/xdg_shell/wlr_xdg_popup.c b/types/xdg_shell/wlr_xdg_popup.c index bd9691477..26d248e18 100644 --- a/types/xdg_shell/wlr_xdg_popup.c +++ b/types/xdg_shell/wlr_xdg_popup.c @@ -212,6 +212,11 @@ static void xdg_popup_handle_resource_destroy(struct wl_resource *resource) { } } +const struct wlr_surface_role xdg_popup_surface_role = { + .name = "xdg_popup", + .commit = handle_xdg_surface_committed, +}; + void create_xdg_popup(struct wlr_xdg_surface *xdg_surface, struct wlr_xdg_surface *parent, struct wlr_xdg_positioner_resource *positioner, int32_t id) { @@ -223,8 +228,8 @@ void create_xdg_popup(struct wlr_xdg_surface *xdg_surface, return; } - if (wlr_surface_set_role(xdg_surface->surface, XDG_POPUP_ROLE, - xdg_surface->resource, XDG_WM_BASE_ERROR_ROLE)) { + if (!wlr_surface_set_role(xdg_surface->surface, &xdg_popup_surface_role, + xdg_surface, xdg_surface->resource, XDG_WM_BASE_ERROR_ROLE)) { return; } diff --git a/types/xdg_shell/wlr_xdg_surface.c b/types/xdg_shell/wlr_xdg_surface.c index 14afb91ed..dc98a3a51 100644 --- a/types/xdg_shell/wlr_xdg_surface.c +++ b/types/xdg_shell/wlr_xdg_surface.c @@ -6,9 +6,8 @@ #include "util/signal.h" bool wlr_surface_is_xdg_surface(struct wlr_surface *surface) { - return surface->role != NULL && - (strcmp(surface->role, XDG_TOPLEVEL_ROLE) == 0 || - strcmp(surface->role, XDG_POPUP_ROLE) == 0); + return surface->role == &xdg_toplevel_surface_role || + surface->role == &xdg_popup_surface_role; } struct wlr_xdg_surface *wlr_xdg_surface_from_wlr_surface( @@ -294,9 +293,10 @@ static void xdg_surface_handle_resource_destroy(struct wl_resource *resource) { } } -static void handle_surface_committed(struct wlr_surface *wlr_surface, - void *role_data) { - struct wlr_xdg_surface *surface = role_data; +static void xdg_surface_handle_surface_commit(struct wl_listener *listener, + void *data) { + struct wlr_xdg_surface *surface = + wl_container_of(listener, surface, surface_commit); if (wlr_surface_has_buffer(surface->surface) && !surface->configured) { wl_resource_post_error(surface->resource, @@ -305,6 +305,21 @@ static void handle_surface_committed(struct wlr_surface *wlr_surface, return; } + if (surface->role == WLR_XDG_SURFACE_ROLE_NONE) { + wl_resource_post_error(surface->resource, + XDG_SURFACE_ERROR_NOT_CONSTRUCTED, + "xdg_surface must have a role"); + return; + } +} + +void handle_xdg_surface_committed(struct wlr_surface *wlr_surface) { + struct wlr_xdg_surface *surface = + wlr_xdg_surface_from_wlr_surface(wlr_surface); + if (surface == NULL) { + return; + } + if (surface->has_next_geometry) { surface->has_next_geometry = false; surface->geometry.x = surface->next_geometry.x; @@ -315,10 +330,7 @@ static void handle_surface_committed(struct wlr_surface *wlr_surface, switch (surface->role) { case WLR_XDG_SURFACE_ROLE_NONE: - wl_resource_post_error(surface->resource, - XDG_SURFACE_ERROR_NOT_CONSTRUCTED, - "xdg_surface must have a role"); - break; + assert(false); case WLR_XDG_SURFACE_ROLE_TOPLEVEL: handle_xdg_surface_toplevel_committed(surface); break; @@ -346,7 +358,7 @@ static void handle_surface_committed(struct wlr_surface *wlr_surface, static void xdg_surface_handle_surface_destroy(struct wl_listener *listener, void *data) { struct wlr_xdg_surface *xdg_surface = - wl_container_of(listener, xdg_surface, surface_destroy_listener); + wl_container_of(listener, xdg_surface, surface_destroy); destroy_xdg_surface(xdg_surface); } @@ -391,12 +403,12 @@ struct wlr_xdg_surface *create_xdg_surface( wl_signal_init(&xdg_surface->events.unmap); wl_signal_add(&xdg_surface->surface->events.destroy, - &xdg_surface->surface_destroy_listener); - xdg_surface->surface_destroy_listener.notify = - xdg_surface_handle_surface_destroy; + &xdg_surface->surface_destroy); + xdg_surface->surface_destroy.notify = xdg_surface_handle_surface_destroy; - wlr_surface_set_role_committed(xdg_surface->surface, - handle_surface_committed, xdg_surface); + wl_signal_add(&xdg_surface->surface->events.commit, + &xdg_surface->surface_commit); + xdg_surface->surface_commit.notify = xdg_surface_handle_surface_commit; wlr_log(WLR_DEBUG, "new xdg_surface %p (res %p)", xdg_surface, xdg_surface->resource); @@ -434,9 +446,10 @@ void destroy_xdg_surface(struct wlr_xdg_surface *surface) { } wl_resource_set_user_data(surface->resource, NULL); + surface->surface->role_data = NULL; wl_list_remove(&surface->link); - wl_list_remove(&surface->surface_destroy_listener.link); - wlr_surface_set_role_committed(surface->surface, NULL, NULL); + wl_list_remove(&surface->surface_destroy.link); + wl_list_remove(&surface->surface_commit.link); free(surface); } diff --git a/types/xdg_shell/wlr_xdg_toplevel.c b/types/xdg_shell/wlr_xdg_toplevel.c index 9430a7d24..f04aa654a 100644 --- a/types/xdg_shell/wlr_xdg_toplevel.c +++ b/types/xdg_shell/wlr_xdg_toplevel.c @@ -447,10 +447,15 @@ static void xdg_toplevel_handle_resource_destroy(struct wl_resource *resource) { } } +const struct wlr_surface_role xdg_toplevel_surface_role = { + .name = "xdg_toplevel", + .commit = handle_xdg_surface_committed, +}; + void create_xdg_toplevel(struct wlr_xdg_surface *xdg_surface, uint32_t id) { - if (wlr_surface_set_role(xdg_surface->surface, XDG_TOPLEVEL_ROLE, - xdg_surface->resource, XDG_WM_BASE_ERROR_ROLE)) { + if (!wlr_surface_set_role(xdg_surface->surface, &xdg_toplevel_surface_role, + xdg_surface, xdg_surface->resource, XDG_WM_BASE_ERROR_ROLE)) { return; } diff --git a/types/xdg_shell_v6/wlr_xdg_popup_v6.c b/types/xdg_shell_v6/wlr_xdg_popup_v6.c index 378ae9631..59af020f2 100644 --- a/types/xdg_shell_v6/wlr_xdg_popup_v6.c +++ b/types/xdg_shell_v6/wlr_xdg_popup_v6.c @@ -249,6 +249,11 @@ void handle_xdg_surface_v6_popup_committed(struct wlr_xdg_surface_v6 *surface) { } } +const struct wlr_surface_role xdg_popup_v6_surface_role = { + .name = "xdg_popup_v6", + .commit = handle_xdg_surface_v6_committed, +}; + void create_xdg_popup_v6(struct wlr_xdg_surface_v6 *xdg_surface, struct wlr_xdg_surface_v6 *parent, struct wlr_xdg_positioner_v6_resource *positioner, int32_t id) { @@ -260,8 +265,8 @@ void create_xdg_popup_v6(struct wlr_xdg_surface_v6 *xdg_surface, return; } - if (wlr_surface_set_role(xdg_surface->surface, XDG_POPUP_V6_ROLE, - xdg_surface->resource, ZXDG_SHELL_V6_ERROR_ROLE)) { + if (!wlr_surface_set_role(xdg_surface->surface, &xdg_popup_v6_surface_role, + xdg_surface, xdg_surface->resource, ZXDG_SHELL_V6_ERROR_ROLE)) { return; } diff --git a/types/xdg_shell_v6/wlr_xdg_surface_v6.c b/types/xdg_shell_v6/wlr_xdg_surface_v6.c index 65db82560..ca729c48b 100644 --- a/types/xdg_shell_v6/wlr_xdg_surface_v6.c +++ b/types/xdg_shell_v6/wlr_xdg_surface_v6.c @@ -6,9 +6,8 @@ #include "util/signal.h" bool wlr_surface_is_xdg_surface_v6(struct wlr_surface *surface) { - return surface->role != NULL && - (strcmp(surface->role, XDG_TOPLEVEL_V6_ROLE) == 0 || - strcmp(surface->role, XDG_POPUP_V6_ROLE) == 0); + return surface->role == &xdg_toplevel_v6_surface_role || + surface->role == &xdg_popup_v6_surface_role; } struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6_from_wlr_surface( @@ -119,9 +118,10 @@ void destroy_xdg_surface_v6(struct wlr_xdg_surface_v6 *surface) { } wl_resource_set_user_data(surface->resource, NULL); + surface->surface->role_data = NULL; wl_list_remove(&surface->link); - wl_list_remove(&surface->surface_destroy_listener.link); - wlr_surface_set_role_committed(surface->surface, NULL, NULL); + wl_list_remove(&surface->surface_destroy.link); + wl_list_remove(&surface->surface_commit.link); free(surface); } @@ -347,13 +347,14 @@ void wlr_xdg_surface_v6_send_close(struct wlr_xdg_surface_v6 *surface) { static void xdg_surface_handle_surface_destroy(struct wl_listener *listener, void *data) { struct wlr_xdg_surface_v6 *xdg_surface = - wl_container_of(listener, xdg_surface, surface_destroy_listener); + wl_container_of(listener, xdg_surface, surface_destroy); destroy_xdg_surface_v6(xdg_surface); } -static void handle_surface_committed(struct wlr_surface *wlr_surface, - void *role_data) { - struct wlr_xdg_surface_v6 *surface = role_data; +static void xdg_surface_handle_surface_commit(struct wl_listener *listener, + void *data) { + struct wlr_xdg_surface_v6 *surface = + wl_container_of(listener, surface, surface_commit); if (wlr_surface_has_buffer(surface->surface) && !surface->configured) { wl_resource_post_error(surface->resource, @@ -362,6 +363,21 @@ static void handle_surface_committed(struct wlr_surface *wlr_surface, return; } + if (surface->role == WLR_XDG_SURFACE_V6_ROLE_NONE) { + wl_resource_post_error(surface->resource, + ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED, + "xdg_surface must have a role"); + return; + } +} + +void handle_xdg_surface_v6_committed(struct wlr_surface *wlr_surface) { + struct wlr_xdg_surface_v6 *surface = + wlr_xdg_surface_v6_from_wlr_surface(wlr_surface); + if (surface == NULL) { + return; + } + if (surface->has_next_geometry) { surface->has_next_geometry = false; surface->geometry.x = surface->next_geometry.x; @@ -372,10 +388,7 @@ static void handle_surface_committed(struct wlr_surface *wlr_surface, switch (surface->role) { case WLR_XDG_SURFACE_V6_ROLE_NONE: - wl_resource_post_error(surface->resource, - ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED, - "xdg_surface must have a role"); - break; + assert(false); case WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL: handle_xdg_surface_v6_toplevel_committed(surface); break; @@ -449,12 +462,12 @@ struct wlr_xdg_surface_v6 *create_xdg_surface_v6( wl_signal_init(&xdg_surface->events.unmap); wl_signal_add(&xdg_surface->surface->events.destroy, - &xdg_surface->surface_destroy_listener); - xdg_surface->surface_destroy_listener.notify = - xdg_surface_handle_surface_destroy; + &xdg_surface->surface_destroy); + xdg_surface->surface_destroy.notify = xdg_surface_handle_surface_destroy; - wlr_surface_set_role_committed(xdg_surface->surface, - handle_surface_committed, xdg_surface); + wl_signal_add(&xdg_surface->surface->events.commit, + &xdg_surface->surface_commit); + xdg_surface->surface_commit.notify = xdg_surface_handle_surface_commit; wlr_log(WLR_DEBUG, "new xdg_surface %p (res %p)", xdg_surface, xdg_surface->resource); diff --git a/types/xdg_shell_v6/wlr_xdg_toplevel_v6.c b/types/xdg_shell_v6/wlr_xdg_toplevel_v6.c index 1f0053054..43ca99f0c 100644 --- a/types/xdg_shell_v6/wlr_xdg_toplevel_v6.c +++ b/types/xdg_shell_v6/wlr_xdg_toplevel_v6.c @@ -417,10 +417,15 @@ static void xdg_toplevel_handle_resource_destroy(struct wl_resource *resource) { } } +const struct wlr_surface_role xdg_toplevel_v6_surface_role = { + .name = "xdg_toplevel_v6", + .commit = handle_xdg_surface_v6_committed, +}; + void create_xdg_toplevel_v6(struct wlr_xdg_surface_v6 *xdg_surface, uint32_t id) { - if (wlr_surface_set_role(xdg_surface->surface, XDG_TOPLEVEL_V6_ROLE, - xdg_surface->resource, ZXDG_SHELL_V6_ERROR_ROLE)) { + if (!wlr_surface_set_role(xdg_surface->surface, &xdg_toplevel_v6_surface_role, + xdg_surface, xdg_surface->resource, ZXDG_SHELL_V6_ERROR_ROLE)) { return; } diff --git a/xwayland/xwm.c b/xwayland/xwm.c index 2a73a449f..368418a36 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -79,11 +79,10 @@ const char *atom_map[ATOM_LAST] = { "XdndActionPrivate", }; -const char *wlr_xwayland_surface_role = "wlr_xwayland_surface"; +static const struct wlr_surface_role xwayland_surface_role; bool wlr_surface_is_xwayland_surface(struct wlr_surface *surface) { - return surface->role != NULL && - strcmp(surface->role, wlr_xwayland_surface_role) == 0; + return surface->role == &xwayland_surface_role; } struct wlr_xwayland_surface *wlr_xwayland_surface_from_wlr_surface( @@ -314,7 +313,7 @@ static void xwayland_surface_destroy( if (xsurface->surface) { wl_list_remove(&xsurface->surface_destroy.link); - wlr_surface_set_role_committed(xsurface->surface, NULL, NULL); + xsurface->surface->role_data = NULL; } wl_event_source_remove(xsurface->ping_timer); @@ -640,9 +639,12 @@ static void read_surface_property(struct wlr_xwm *xwm, free(reply); } -static void handle_surface_commit(struct wlr_surface *wlr_surface, - void *role_data) { - struct wlr_xwayland_surface *surface = role_data; +static void xwayland_surface_role_commit(struct wlr_surface *wlr_surface) { + assert(wlr_surface->role == &xwayland_surface_role); + struct wlr_xwayland_surface *surface = wlr_surface->role_data; + if (surface == NULL) { + return; + } if (!surface->mapped && wlr_surface_has_buffer(surface->surface)) { wlr_signal_emit_safe(&surface->events.map, surface); @@ -650,6 +652,11 @@ static void handle_surface_commit(struct wlr_surface *wlr_surface, } } +static const struct wlr_surface_role xwayland_surface_role = { + .name = "wlr_xwayland_surface", + .commit = xwayland_surface_role_commit, +}; + static void handle_surface_destroy(struct wl_listener *listener, void *data) { struct wlr_xwayland_surface *surface = wl_container_of(listener, surface, surface_destroy); @@ -658,6 +665,12 @@ static void handle_surface_destroy(struct wl_listener *listener, void *data) { static void xwm_map_shell_surface(struct wlr_xwm *xwm, struct wlr_xwayland_surface *xsurface, struct wlr_surface *surface) { + if (!wlr_surface_set_role(surface, &xwayland_surface_role, xsurface, + NULL, 0)) { + wlr_log(L_ERROR, "Failed to set xwayland surface role"); + return; + } + xsurface->surface = surface; // read all surface properties @@ -678,10 +691,6 @@ static void xwm_map_shell_surface(struct wlr_xwm *xwm, read_surface_property(xwm, xsurface, props[i]); } - wlr_surface_set_role(xsurface->surface, wlr_xwayland_surface_role, NULL, 0); - wlr_surface_set_role_committed(xsurface->surface, handle_surface_commit, - xsurface); - xsurface->surface_destroy.notify = handle_surface_destroy; wl_signal_add(&surface->events.destroy, &xsurface->surface_destroy); } @@ -701,8 +710,8 @@ static void xsurface_unmap(struct wlr_xwayland_surface *surface) { } if (surface->surface) { - wlr_surface_set_role_committed(surface->surface, NULL, NULL); wl_list_remove(&surface->surface_destroy.link); + surface->surface->role_data = NULL; surface->surface = NULL; } }