From 7919b65eca9632f288ab48d9cac9fb625747a55f Mon Sep 17 00:00:00 2001 From: hujianwei Date: Mon, 14 Nov 2022 10:26:58 +0000 Subject: [PATCH] Fix xdg-positioner implementation * compositor.h (struct _Positioner): New struct. * positioner.c (struct _Positioner): Move to compositor.h. (RetainPositioner, ReleasePositioner): Remove functions. (HandleResourceDestroy): Destroy positioner instead. (XLCreateXdgPositioner): Remove reference-counting logic. (XLRetainPositioner, XLReleasePositioner): Delete functions. (XLPositionerIsReactive): Delete function. * xdg_popup.c (struct _XdgPopup): Make positioner a struct instead of a pointer. (DestroyBacking, InternalReposition, Reposition) (HandleParentConfigure, HandleParentResize, XLGetXdgPopup): Copy positioner instead of taking a reference. --- compositor.h | 24 +++++++++++++++++++--- positioner.c | 56 +--------------------------------------------------- xdg_popup.c | 43 ++++++++++++++++++++++++---------------- 3 files changed, 48 insertions(+), 75 deletions(-) diff --git a/compositor.h b/compositor.h index 7e742ab..fb3a601 100644 --- a/compositor.h +++ b/compositor.h @@ -1395,13 +1395,31 @@ extern void XLXdgRoleReplyPing (Role *); typedef struct _Positioner Positioner; +/* This structure is public because positioners must be copied into + xdg_popups. */ + +struct _Positioner +{ + /* The fields below mean what they do in the xdg_shell protocol + spec. */ + int width, height; + int anchor_x, anchor_y; + int anchor_width, anchor_height; + unsigned int anchor, gravity, constraint; + int offset_x, offset_y; + Bool reactive; + int parent_width, parent_height; + uint32_t constraint_adjustment; + + /* The wl_resource corresponding to this positioner. Not valid when + embedded in i.e. an xdg_popup. */ + struct wl_resource *resource; +}; + extern void XLCreateXdgPositioner (struct wl_client *, struct wl_resource *, uint32_t); extern void XLPositionerCalculateGeometry (Positioner *, Role *, int *, int *, int *, int *); -extern void XLRetainPositioner (Positioner *); -extern void XLReleasePositioner (Positioner *); -extern Bool XLPositionerIsReactive (Positioner *); extern void XLCheckPositionerComplete (Positioner *); /* Defined in xdg_toplevel.c. */ diff --git a/positioner.c b/positioner.c index 841819a..15e885b 100644 --- a/positioner.c +++ b/positioner.c @@ -61,26 +61,6 @@ enum _AnchorGravity AnchorGravityBottomRight, }; -struct _Positioner -{ - /* The fields below mean what they do in the xdg_shell protocol - spec. */ - int width, height; - int anchor_x, anchor_y; - int anchor_width, anchor_height; - unsigned int anchor, gravity, constraint; - int offset_x, offset_y; - Bool reactive; - int parent_width, parent_height; - uint32_t constraint_adjustment; - - /* The wl_resource corresponding to this positioner. */ - struct wl_resource *resource; - - /* The number of references to this positioner. */ - int refcount; -}; - /* Surface used to handle scaling during constraint adjustment calculation. */ static double scale_adjustment_factor; @@ -226,28 +206,13 @@ static const struct xdg_positioner_interface xdg_positioner_impl = .set_parent_configure = SetParentConfigure, }; -static void -RetainPositioner (Positioner *positioner) -{ - positioner->refcount++; -} - -static void -ReleasePositioner (Positioner *positioner) -{ - if (--positioner->refcount) - return; - - XLFree (positioner); -} - static void HandleResourceDestroy (struct wl_resource *resource) { Positioner *positioner; positioner = wl_resource_get_user_data (resource); - ReleasePositioner (positioner); + XLFree (positioner); } static void @@ -920,25 +885,6 @@ XLCreateXdgPositioner (struct wl_client *client, struct wl_resource *resource, &xdg_positioner_impl, positioner, HandleResourceDestroy); - RetainPositioner (positioner); -} - -void -XLRetainPositioner (Positioner *positioner) -{ - RetainPositioner (positioner); -} - -void -XLReleasePositioner (Positioner *positioner) -{ - ReleasePositioner (positioner); -} - -Bool -XLPositionerIsReactive (Positioner *positioner) -{ - return positioner->reactive; } void diff --git a/xdg_popup.c b/xdg_popup.c index 869dc47..3b678ca 100644 --- a/xdg_popup.c +++ b/xdg_popup.c @@ -77,7 +77,7 @@ struct _XdgPopup uint32_t conf_serial, position_serial; /* The associated positioner. */ - Positioner *positioner; + Positioner positioner; /* Any pending seat on which a grab should be asserted. */ Seat *pending_grab_seat; @@ -138,8 +138,7 @@ DestroyBacking (XdgPopup *popup) if (popup->pending_callback_key) XLSeatCancelDestroyListener (popup->pending_callback_key); - /* Release the positioner and free the popup. */ - XLReleasePositioner (popup->positioner); + /* Free the popup. */ XLFree (popup); } @@ -449,7 +448,7 @@ InternalReposition (XdgPopup *popup) if (!popup->role || !popup->parent) return; - XLPositionerCalculateGeometry (popup->positioner, + XLPositionerCalculateGeometry (&popup->positioner, popup->parent, &x, &y, &width, &height); @@ -664,16 +663,17 @@ Reposition (struct wl_client *client, struct wl_resource *resource, struct wl_resource *positioner_resource, uint32_t token) { XdgPopup *popup; + Positioner *positioner; popup = wl_resource_get_user_data (resource); - XLReleasePositioner (popup->positioner); - popup->positioner - = wl_resource_get_user_data (positioner_resource); - XLRetainPositioner (popup->positioner); - /* Make sure that the positioner is complete. */ - XLCheckPositionerComplete (popup->positioner); + positioner = wl_resource_get_user_data (positioner_resource); + XLCheckPositionerComplete (positioner); + + /* Copy the positioner to the popup. */ + popup->positioner = *positioner; + popup->positioner.resource = NULL; xdg_popup_send_repositioned (resource, token); InternalReposition (popup); @@ -750,7 +750,7 @@ HandleParentConfigure (void *data, XEvent *xevent) popup = data; - if (XLPositionerIsReactive (popup->positioner)) + if (popup->positioner.reactive) InternalReposition (popup); } @@ -761,7 +761,7 @@ HandleParentResize (void *data) popup = data; - if (XLPositionerIsReactive (popup->positioner)) + if (popup->positioner.reactive) InternalReposition (popup); } @@ -784,11 +784,12 @@ static const struct xdg_popup_interface xdg_popup_impl = void XLGetXdgPopup (struct wl_client *client, struct wl_resource *resource, uint32_t id, struct wl_resource *parent_resource, - struct wl_resource *positioner) + struct wl_resource *positioner_resource) { XdgPopup *popup; Role *role, *parent; void *key; + Positioner *positioner; popup = XLSafeMalloc (sizeof *popup); role = wl_resource_get_user_data (resource); @@ -831,11 +832,19 @@ XLGetXdgPopup (struct wl_client *client, struct wl_resource *resource, popup->reconstrain_callback_key = key; } - popup->positioner = wl_resource_get_user_data (positioner); - XLRetainPositioner (popup->positioner); - /* Make sure that the positioner is complete. */ - XLCheckPositionerComplete (popup->positioner); + positioner = wl_resource_get_user_data (positioner_resource); + XLCheckPositionerComplete (positioner); + + /* Save the positioner into the popup. The spec says: + + At the time of the request, the compositor makes a copy of the + rules specified by the xdg_positioner. Thus, after the request + is complete the xdg_positioner object can be destroyed or + reused; further changes to the object will have no effect on + previous usages. */ + popup->positioner = *positioner; + popup->positioner.resource = NULL; wl_resource_set_implementation (popup->resource, &xdg_popup_impl, popup, HandleResourceDestroy);