From b7599fb766832d0ed14b91414672ecf15582198a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michel=20D=C3=A4nzer?= Date: Tue, 1 Nov 2022 17:30:00 +0100 Subject: [PATCH] wayland/xdg-shell: Defer meta_wayland_xdg_positioner_to_placement call MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From xdg_surface_constructor_get_popup / xdg_popup_reposition (called during Wayland protocol processing) to finish_popup_setup / meta_wayland_xdg_popup_apply_state (called when the popup state is applied). This makes sure that the parent window frame rectangle is up to date in meta_wayland_xdg_positioner_to_placement. v2: * Use meta_wayland_surface_state_new () in meta_wayland_transaction_add_xdg_popup_reposition. v3: * Move xdg_popup_repositioned handling to meta_wayland_xdg_popup_apply_state. v4: * Do not steal pending->xdg_positioner in meta_wayland_xdg_popup_apply_state, fixes leaking the corresponding memory. * Drop MetaWaylandSurfaceState::xdg_popup_repositioned, just use ::xdg_positioner. v5: * Reformat meta_wayland_xdg_positioner_to_placement calls to stay within 80 columns. (Jonas Ã…dahl) Part-of: --- src/wayland/meta-wayland-surface.c | 10 ++++ src/wayland/meta-wayland-surface.h | 4 ++ src/wayland/meta-wayland-transaction.c | 21 ++++++++ src/wayland/meta-wayland-transaction.h | 5 ++ src/wayland/meta-wayland-types.h | 2 + src/wayland/meta-wayland-xdg-shell.c | 66 +++++++++++++++----------- 6 files changed, 80 insertions(+), 28 deletions(-) diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c index 7beb0ab60..c235ead1c 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c @@ -502,6 +502,8 @@ meta_wayland_surface_state_set_default (MetaWaylandSurfaceState *state) state->subsurface_placement_ops = NULL; wl_list_init (&state->presentation_feedback_list); + + state->xdg_popup_reposition_token = 0; } static void @@ -527,6 +529,7 @@ meta_wayland_surface_state_clear (MetaWaylandSurfaceState *state) g_clear_pointer (&state->buffer_damage, cairo_region_destroy); g_clear_pointer (&state->input_region, cairo_region_destroy); g_clear_pointer (&state->opaque_region, cairo_region_destroy); + g_clear_pointer (&state->xdg_positioner, g_free); if (state->buffer) g_clear_signal_handler (&state->buffer_destroy_handler_id, state->buffer); @@ -675,6 +678,13 @@ meta_wayland_surface_state_merge_into (MetaWaylandSurfaceState *from, wl_list_insert_list (&to->presentation_feedback_list, &from->presentation_feedback_list); wl_list_init (&from->presentation_feedback_list); + + if (from->xdg_positioner) + { + g_clear_pointer (&to->xdg_positioner, g_free); + to->xdg_positioner = g_steal_pointer (&from->xdg_positioner); + to->xdg_popup_reposition_token = from->xdg_popup_reposition_token; + } } static void diff --git a/src/wayland/meta-wayland-surface.h b/src/wayland/meta-wayland-surface.h index 307038a2c..7edddf647 100644 --- a/src/wayland/meta-wayland-surface.h +++ b/src/wayland/meta-wayland-surface.h @@ -133,6 +133,10 @@ struct _MetaWaylandSurfaceState struct { gboolean surface_size_changed; } derived; + + /* xdg_popup */ + MetaWaylandXdgPositioner *xdg_positioner; + uint32_t xdg_popup_reposition_token; }; struct _MetaWaylandDragDestFuncs diff --git a/src/wayland/meta-wayland-transaction.c b/src/wayland/meta-wayland-transaction.c index cc77ea663..6bf0376e9 100644 --- a/src/wayland/meta-wayland-transaction.c +++ b/src/wayland/meta-wayland-transaction.c @@ -386,6 +386,27 @@ meta_wayland_transaction_add_subsurface_position (MetaWaylandTransaction *transa entry->has_sub_pos = TRUE; } +void +meta_wayland_transaction_add_xdg_popup_reposition (MetaWaylandTransaction *transaction, + MetaWaylandSurface *surface, + void *xdg_positioner, + uint32_t token) +{ + MetaWaylandTransactionEntry *entry; + MetaWaylandSurfaceState *state; + + entry = meta_wayland_transaction_ensure_entry (transaction, surface); + + if (entry->state) + g_clear_pointer (&entry->state->xdg_positioner, g_free); + else + entry->state = meta_wayland_surface_state_new (); + + state = entry->state; + state->xdg_positioner = xdg_positioner; + state->xdg_popup_reposition_token = token; +} + static void meta_wayland_transaction_entry_merge_into (MetaWaylandTransactionEntry *from, MetaWaylandTransactionEntry *to) diff --git a/src/wayland/meta-wayland-transaction.h b/src/wayland/meta-wayland-transaction.h index a42300f8e..98c662001 100644 --- a/src/wayland/meta-wayland-transaction.h +++ b/src/wayland/meta-wayland-transaction.h @@ -37,6 +37,11 @@ void meta_wayland_transaction_add_subsurface_position (MetaWaylandTransaction *t int x, int y); +void meta_wayland_transaction_add_xdg_popup_reposition (MetaWaylandTransaction *transaction, + MetaWaylandSurface *surface, + void *xdg_positioner, + uint32_t token); + void meta_wayland_transaction_merge_into (MetaWaylandTransaction *from, MetaWaylandTransaction *to); diff --git a/src/wayland/meta-wayland-types.h b/src/wayland/meta-wayland-types.h index 97623df7f..8b1c6f007 100644 --- a/src/wayland/meta-wayland-types.h +++ b/src/wayland/meta-wayland-types.h @@ -67,6 +67,8 @@ typedef struct _MetaWaylandActivation MetaWaylandActivation; typedef struct _MetaWaylandDmaBufManager MetaWaylandDmaBufManager; +typedef struct _MetaWaylandXdgPositioner MetaWaylandXdgPositioner; + typedef struct _MetaXWaylandManager MetaXWaylandManager; #endif diff --git a/src/wayland/meta-wayland-xdg-shell.c b/src/wayland/meta-wayland-xdg-shell.c index 1c2877d3c..240648222 100644 --- a/src/wayland/meta-wayland-xdg-shell.c +++ b/src/wayland/meta-wayland-xdg-shell.c @@ -57,7 +57,7 @@ typedef struct _MetaWaylandXdgShellClient GList *surface_constructors; } MetaWaylandXdgShellClient; -typedef struct _MetaWaylandXdgPositioner +struct _MetaWaylandXdgPositioner { MetaRectangle anchor_rect; int32_t width; @@ -76,7 +76,7 @@ typedef struct _MetaWaylandXdgPositioner gboolean acked_parent_configure; uint32_t parent_configure_serial; -} MetaWaylandXdgPositioner; +}; typedef struct _MetaWaylandXdgSurfaceConstructor { @@ -130,11 +130,7 @@ struct _MetaWaylandXdgPopup struct { MetaWaylandSurface *parent_surface; - /* - * The coordinates/dimensions in the placement rule are in logical pixel - * coordinate space, i.e. not scaled given what monitor the popup is on. - */ - MetaPlacementRule placement_rule; + MetaWaylandXdgPositioner xdg_positioner; MetaWaylandSeat *grab_seat; uint32_t grab_serial; @@ -623,27 +619,17 @@ xdg_popup_reposition (struct wl_client *client, META_WAYLAND_SURFACE_ROLE (xdg_popup); MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (surface_role); - MetaWindow *window; - MetaWindow *parent_window; MetaWaylandXdgPositioner *xdg_positioner; - MetaPlacementRule placement_rule; + MetaWaylandTransaction *transaction; - window = meta_wayland_surface_get_window (surface); - if (!window) - return; + xdg_positioner = g_memdup2 (wl_resource_get_user_data (positioner_resource), + sizeof (MetaWaylandXdgPositioner)); - parent_window = meta_wayland_surface_get_window (xdg_popup->parent_surface); - - xdg_positioner = wl_resource_get_user_data (positioner_resource); - placement_rule = meta_wayland_xdg_positioner_to_placement (xdg_positioner, - parent_window); - - xdg_popup->pending_reposition_token = token; - xdg_popup->pending_repositioned = TRUE; - - scale_placement_rule (&placement_rule, surface); - - meta_window_update_placement_rule (window, &placement_rule); + transaction = meta_wayland_transaction_new (surface->compositor); + meta_wayland_transaction_add_xdg_popup_reposition (transaction, surface, + xdg_positioner, token); + meta_wayland_transaction_ensure_entry (transaction, xdg_popup->parent_surface); + meta_wayland_transaction_commit (transaction); } static const struct xdg_popup_interface meta_wayland_xdg_popup_interface = { @@ -1080,6 +1066,8 @@ finish_popup_setup (MetaWaylandXdgPopup *xdg_popup) uint32_t serial; MetaDisplay *display = meta_get_display (); MetaWindow *window; + MetaWindow *parent_window; + MetaPlacementRule placement_rule; parent_surface = xdg_popup->setup.parent_surface; seat = xdg_popup->setup.grab_seat; @@ -1124,7 +1112,11 @@ finish_popup_setup (MetaWaylandXdgPopup *xdg_popup) window = meta_window_wayland_new (display, surface); meta_wayland_shell_surface_set_window (shell_surface, window); - meta_wayland_xdg_popup_place (xdg_popup, &xdg_popup->setup.placement_rule); + parent_window = meta_wayland_surface_get_window (parent_surface); + placement_rule = + meta_wayland_xdg_positioner_to_placement (&xdg_popup->setup.xdg_positioner, + parent_window); + meta_wayland_xdg_popup_place (xdg_popup, &placement_rule); if (seat) { @@ -1219,6 +1211,25 @@ meta_wayland_xdg_popup_apply_state (MetaWaylandSurfaceRole *surface_role, if (xdg_popup->setup.parent_surface) finish_popup_setup (xdg_popup); + if (pending->xdg_positioner) + { + MetaWindow *window, *parent_window; + MetaPlacementRule placement_rule; + + parent_window = meta_wayland_surface_get_window (xdg_popup->parent_surface); + placement_rule = + meta_wayland_xdg_positioner_to_placement (pending->xdg_positioner, + parent_window); + + xdg_popup->pending_reposition_token = pending->xdg_popup_reposition_token; + xdg_popup->pending_repositioned = TRUE; + + scale_placement_rule (&placement_rule, surface); + + window = meta_wayland_surface_get_window (surface); + meta_window_update_placement_rule (window, &placement_rule); + } + if (!surface->buffer_ref->buffer && xdg_surface_priv->first_buffer_attached) { meta_wayland_xdg_surface_reset (xdg_surface); @@ -2040,8 +2051,7 @@ xdg_surface_constructor_get_popup (struct wl_client *client, meta_wayland_xdg_surface_constructor_finalize (constructor, xdg_surface); xdg_positioner = wl_resource_get_user_data (positioner_resource); - xdg_popup->setup.placement_rule = - meta_wayland_xdg_positioner_to_placement (xdg_positioner, parent_window); + xdg_popup->setup.xdg_positioner = *xdg_positioner; xdg_popup->setup.parent_surface = parent_surface; }