[PATCH wayland-protocols v2] xdg-shell: Add support for synchronized popup moving

Jonas Ådahl jadahl at gmail.com
Mon Oct 28 11:00:11 UTC 2019

This commit adds protocol additions making it possible to reposition an
already mapped popup.

Repositioning can be done in two ways: implicit and explicit.

Implicit popup moving is done by setting a adjustment flag on the
positioner used to create it that will cause the compositor to adjust
the position as the conditions used to constrain it change.

These changes may include, for example, changes in the position of the
parent window or the geometry of the work area. To allow the client to
update its content in response to the updated position, the client must
ack the configure event, optionally with new content. Until the client
acks this configure event, the existing positioner will continue to be

Explicit popup moving is done using a new request on xdg_popup:
xdg_popup.reposition. What it does is change the parameters used for
positioning a popup by providing a new xdg_positioner object. This
request is coupled with a new event; xdg_popup.repositioned, sent
together with the configure events (xdg_popup.configure and
xdg_surface.configure) to notify about the completion of the reposition
request. The reposition request also takes a token that is later passed
via the repositioned event; this is done so that a client may determine
for which reposition request the compositor has sent configure events.

Both these methods by themself are racy regarding inter-surface
synchronization. In order to avoid race conditions when applying new
states, a new request is also added to xdg_surface:
xdg_surface.sync_with_popup. This request is a one-shot request to defer
application of the to be committed surface state until the state of the
passed popup surface is applied.

Lastly, a request to couple a xdg_positioner object with a configure
event is added in order for a compositor to pair a popup reposition
request with a pending configure event. This is necessary to, for
example, properly constrain a popup given a yet-to-be-applied parent
state. An example of when this may be necessary is an interactive resize
where both the toplevel position and the relative popup position

Signed-off-by: Jonas Ådahl <jadahl at gmail.com>
Reviewed-by: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>

Changes since v1:

 - Renamed move to reposition, and moved to repositioned, to not be
   confused with xdg_toplevel.move. (David)
 - Added invalid_popup error sent sync_with_popup() is passed
   an invalid popup.
 - Clarify that multiple calls to sync_with_popup() is accumulacitve.


 stable/xdg-shell/xdg-shell.xml | 86 ++++++++++++++++++++++++++++++++--
 1 file changed, 81 insertions(+), 5 deletions(-)

diff --git a/stable/xdg-shell/xdg-shell.xml b/stable/xdg-shell/xdg-shell.xml
index 3a87a9e..3ee13de 100644
--- a/stable/xdg-shell/xdg-shell.xml
+++ b/stable/xdg-shell/xdg-shell.xml
@@ -29,7 +29,7 @@
-  <interface name="xdg_wm_base" version="2">
+  <interface name="xdg_wm_base" version="3">
     <description summary="create desktop-style surfaces">
       The xdg_wm_base interface is exposed as a global object enabling clients
       to turn their wl_surfaces into windows in a desktop environment. It
@@ -115,7 +115,7 @@
-  <interface name="xdg_positioner" version="2">
+  <interface name="xdg_positioner" version="3">
     <description summary="child surface positioner">
       The xdg_positioner provides a collection of rules for the placement of a
       child surface relative to a parent surface. Rules can be defined to ensure
@@ -357,9 +357,32 @@
       <arg name="x" type="int" summary="surface position x offset"/>
       <arg name="y" type="int" summary="surface position y offset"/>
+    <!-- Version 3 additions -->
+    <request name="set_reactive" since="3">
+      <description summary="continuously reconstrain the surface">
+	When set reactive, the surface is reconstrained if the conditions used
+	for constraining changed, e.g. the parent window moved.
+	When set reactive, an xdg_popup.configure event is sent with updated
+	geometry, followed by an xdg_surface.configure event, which will
+	reflect the newly-calculated constrained geometry for the popup.
+      </description>
+    </request>
+    <request name="set_parent_configure_serial" since="3">
+      <description summary="set serial number of parent configure event">
+	Set the serial of a xdg_surface.configure event this positioner will be
+	used in response to. The compositor can use this to make assumptions about
+	how the popup will be positioned on the next commit.
+      </description>
+      <arg name="serial" type="uint"
+	   summary="serial of parent configure event"/>
+    </request>
-  <interface name="xdg_surface" version="2">
+  <interface name="xdg_surface" version="3">
     <description summary="desktop user interface surface base interface">
       An interface that may be implemented by a wl_surface, for
       implementations that provide a desktop-style user interface.
@@ -406,6 +429,7 @@
       <entry name="not_constructed" value="1"/>
       <entry name="already_constructed" value="2"/>
       <entry name="unconfigured_buffer" value="3"/>
+      <entry name="invalid_popup" value="4"/>
     <request name="destroy" type="destructor">
@@ -526,9 +550,25 @@
       <arg name="serial" type="uint" summary="serial of the configure event"/>
+    <!-- Version 3 additions -->
+    <request name="sync_with_popup" since="3">
+      <description summary="synchronize with popup state">
+	Defer applying this surface's state until the state of the specified
+	xdg_popup surface is next applied.
+	Repeatedly calling this method has no additional effect until after the
+	next commit.
+	The direct parent of the popup must be this surface. If it is not, a
+	invalid_popup error is raised.
+      </description>
+      <arg name="popup" type="object" interface="xdg_popup"/>
+    </request>
-  <interface name="xdg_toplevel" version="2">
+  <interface name="xdg_toplevel" version="3">
     <description summary="toplevel surface">
       This interface defines an xdg_surface role which allows a surface to,
       among other things, set window-like properties such as maximize,
@@ -1019,7 +1059,7 @@
-  <interface name="xdg_popup" version="2">
+  <interface name="xdg_popup" version="3">
     <description summary="short-lived, popup surfaces for menus">
       A popup surface is a short-lived, temporary surface. It can be used to
       implement for example menus, popovers, tooltips and other similar user
@@ -1143,5 +1183,41 @@
+    <!-- Version 3 additions -->
+    <request name="reposition" since="3">
+      <description summary="recalculate the popup's location">
+	Reposition an already-mapped popup. The popup will be placed given the
+	details in the passed xdg_positioner object, and a
+	xdg_popup.repositioned followed by xdg_popup.configure and
+	xdg_surface.configure will be emitted in response.
+	The passed token will be sent in the corresponding xdg_popup.repositioned
+	event. The new popup position will not take effect until the
+	corresponding configure event is acknowledged by the client. See
+	xdg_popup.repositioned for details. The token itself is opaque, and has no
+	other special meaning.
+      </description>
+      <arg name="positioner" type="object" interface="xdg_positioner"/>
+      <arg name="token" type="uint" summary="reposition request token"/>
+    </request>
+    <event name="repositioned" since="3">
+      <description summary="signal the completion of a repositioned request">
+	The repositioned event is to notify about the completion of a
+	xdg_popup.repositioned request. The token argument is the token passed
+	in the xdg_popup.repositioned request.
+	Immediately after this event is emitted, xdg_popup.configure and
+	xdg_surface.configure will be sent with the updated size and position,
+	as well as a new configure serial.
+	The client should optionally update the content of the popup, but must
+	acknowledge the new popup configuration for the new position to take
+	effect. See xdg_surface.ack_configure for details.
+      </description>
+      <arg name="token" type="uint" summary="reposition request token"/>
+    </event>

More information about the wayland-devel mailing list