[PATCH wayland-protocols 1/4 v5] xdg-shell: Introduce xdg_positioner

Bryce Harrington bryce at osg.samsung.com
Fri Aug 12 03:39:08 UTC 2016


On Fri, Jul 29, 2016 at 12:04:53PM +0800, Jonas Ådahl wrote:
> xdg_positioner is a method for declarative positioning of child surfaces
> (currently only xdg_popup surfaces). A client creates a description of a
> positioning logic using the xdg_positioner interface. The xdg_positioner
> object is then used when creating a xdg_popup for describing how the
> child surface should be positioned in relation to the parent surface.
> 
> Signed-off-by: Jonas Ådahl <jadahl at gmail.com>
> Signed-off-by: Mike Blumenkrantz <zmike at samsung.com>
> Acked-by: Yong Bakos <ybakos at humanoriented.com>
> Acked-by: Quentin Glidic <sardemff7+git at sardemff7.net>
> ---
> 
> Changes since v4:
> 
>  - Changed the description of xdg_positioner.set_anchor and
>    xdg_positioner.set_gravity with the intention of clarifying semantics
>    (especially when not setting a anchor/gravity on one or more axes).
> 
> 
> 
>  unstable/xdg-shell/xdg-shell-unstable-v6.xml | 276 ++++++++++++++++++++++++++-
>  1 file changed, 273 insertions(+), 3 deletions(-)
> 
> diff --git a/unstable/xdg-shell/xdg-shell-unstable-v6.xml b/unstable/xdg-shell/xdg-shell-unstable-v6.xml
> index 0771668..1d59a0e 100644
> --- a/unstable/xdg-shell/xdg-shell-unstable-v6.xml
> +++ b/unstable/xdg-shell/xdg-shell-unstable-v6.xml
> @@ -45,6 +45,8 @@
>  	     summary="the client specified an invalid popup parent surface"/>
>        <entry name="invalid_surface_state" value="4"
>  	     summary="the client provided an invalid surface state"/>
> +      <entry name="invalid_positioner" value="5"
> +	     summary="the client provided an invalid positioner"/>
>      </enum>
>  
>      <request name="destroy" type="destructor">
> @@ -57,6 +59,15 @@
>        </description>
>      </request>
>  
> +    <request name="create_positioner">
> +      <description summary="create a positioner object">
> +	Create a positioner object. A positioner object is used to position
> +	surfaces relative to some parent surface. See the interface description
> +	and xdg_surface.get_popup for details.
> +      </description>
> +      <arg name="id" type="new_id" interface="zxdg_positioner_v6"/>
> +    </request>
> +
>      <request name="get_xdg_surface">
>        <description summary="create a shell surface from a surface">
>  	This creates an xdg_surface for the given surface. While xdg_surface
> @@ -101,6 +112,250 @@
>      </event>
>    </interface>
>  
> +  <interface name="zxdg_positioner_v6" version="1">
> +    <description summary="child surface positioner">
> +      The xdg_positioner provides an interface for constructing positioning
> +      rules used for positioning a child surface relative to a parent surface
> +      in a certain way. It allows methods for defining a rule that will make
> +      the child surface stay within the border of the visible area of the
> +      screen, with different ways in which the child surface should change
> +      its position, including sliding along an axis, or flipping around a
> +      rectangle.
> +
> +      See the various requests for details about possible rules.
> +
> +      Semantically, an xdg_positioner is a collection of positioning rules. When
> +      used for positioning a surface, for example when passed as an argument to
> +      xdg_surface.get_popup, the compositor copies the rules that were set up at
> +      the time of the request. Making any changes or destroying the object after
> +      it was used has no effect on previous usages.

This description is a bit wordy; I took a shot at copyediting it to be
slightly more concise:

  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 the child surface remains within the visible area's borders,
  and to specify how the child surface changes its position, such as
  sliding along an axis, or flipping around a rectangle.

  See the various requests for details about possible rules.

  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.

> +      For an xdg_positioner object to be considered complete, it must have a
> +      non-zero size set by set_size, and a non-zero anchor rectangle set by
> +      set_anchor_rect. Passing an incomplete xdg_positioner object when
> +      positioning a surface raises an error.
> +    </description>
> +
> +    <enum name="error">
> +      <entry name="invalid_input" value="0" summary="invalid input provided"/>
> +    </enum>
> +
> +    <request name="destroy" type="destructor">
> +      <description summary="destroy the xdg_positioner object">
> +	Notify the compositor that the xdg_positioner will no longer be used.
> +      </description>
> +    </request>
> +
> +    <request name="set_size">
> +      <description summary="set the size of the to-be positioned rectangle">
> +	Set the size of the surface that is to be positioned with the positioner
> +	object. The size is in surface-local coordinates and corresponds to the
> +	window geometry. See xdg_surface.set_window_geometry.
> +
> +	If a zero or negative size is set the invalid_input error is raised.
> +      </description>
> +      <arg name="width" type="int" summary="width of positioned rectangle"/>
> +      <arg name="height" type="int" summary="height of positioned rectangle"/>
> +    </request>
> +
> +    <request name="set_anchor_rect">
> +      <description summary="set the anchor rectangle within the parent surface">
> +	Specify the anchor rectangle within the parent surface that the child
> +	surface will be placed relative to. The rectangle is relative to the
> +	window geometry as defined by xdg_surface.set_window_geometry of the
> +	parent surface. The rectangle must be at least 1x1 large.
> +
> +	When the xdg_positioner object is used to position a child surface, the
> +	anchor rectangle may not extend outside the window geometry of the
> +	positioned child's parent surface.
> +
> +	If a zero or negative size is set the invalid_input error is raised.
> +      </description>
> +      <arg name="x" type="int" summary="x position of anchor rectangle"/>
> +      <arg name="y" type="int" summary="y position of anchor rectangle"/>
> +      <arg name="width" type="int" summary="width of anchor rectangle"/>
> +      <arg name="height" type="int" summary="height of anchor rectangle"/>
> +    </request>
> +
> +    <enum name="anchor" bitfield="true">
> +      <entry name="none" value="0"
> +	     summary="the center of the anchor rectangle"/>
> +      <entry name="top" value="1"
> +	     summary="the top edge of the anchor rectangle"/>
> +      <entry name="bottom" value="2"
> +	     summary="the bottom edge of the anchor rectangle"/>
> +      <entry name="left" value="4"
> +	     summary="the left edge of the anchor rectangle"/>
> +      <entry name="right" value="8"
> +	     summary="the right edge of the anchor rectangle"/>
> +    </enum>
> +
> +    <request name="set_anchor">
> +      <description summary="set anchor rectangle anchor edges">
> +	Set the anchor edges of the anchor rectangle. The set anchor edge(s) are
> +	used to derive an anchor point on the anchor rectangle the child
> +	surface should be positioned relative to.
> +
> +	An anchor edge represents where on an axis the anchor point should be
> +	located. If no anchor edge is set on an axis, the anchor point will
> +	be positioned at the center on that axis. For example if the 'top' and
> +	'left' anchor edges are set, the derived anchor point will be in the top
> +	left position of the rectangle, while if only the 'top' anchor edge is
> +	set, the derived anchor point will be on the left edge of the rectangle
> +	but centered on the y axis.

I think this could benefit from some further wordsmithing.  The word
'anchor' appears too often, and I think the examples could be integrated
more directly with the definitions.  How does this strike you?

	Defines a set of edges for the anchor rectangle.  These are used
	to derive an anchor point that the child surface will be
	positioned relative to.  If two orthogonal edges are specified
	(e.g. 'top' and 'left'), then the anchor point will be the
	intersection of the edges (e.g. the top left position of the
	rectangle); otherwise, the derived anchor point will be centered
	on the specified edge.

Bryce

> +	The default value is "none".
> +
> +	If two values on the same axis (for example left and right) are set the
> +	invalid_input error is raised.
> +      </description>
> +      <arg name="anchor" type="uint" enum="anchor"
> +	   summary="bit mask of anchor edges"/>
> +    </request>
> +
> +    <enum name="gravity" bitfield="true">
> +      <entry name="none" value="0"
> +	     summary="center over the anchor edge"/>
> +      <entry name="top" value="1"
> +	     summary="position above the anchor edge"/>
> +      <entry name="bottom" value="2"
> +	     summary="position below the anchor edge"/>
> +      <entry name="left" value="4"
> +	     summary="position to the left of the anchor edge"/>
> +      <entry name="right" value="8"
> +	     summary="position to the right of the anchor edge"/>
> +    </enum>
> +
> +    <request name="set_gravity">
> +      <description summary="set child surface gravity">
> +	Set the gravity of the surface child surface. The gravity defines in
> +	what direction a surface should be positioned, relative to the anchor
> +	point on the parent surface.
> +
> +	The gravity is derived from up to two values of the gravity enum, making
> +	up the gravity on different axes. If no gravity is set on an axis, the
> +	gravity is assumed to be none, meaning the surface will be centered over
> +	the anchor point on that axis. For example if the gravity 'bottom' and
> +	'right' is set, the child surface will be positioned below and right of
> +	the anchor point on the parent surface, while if only the gravity
> +	'bottom' is set, the child surface will be positioned below the anchor
> +	point, but centered on the x axis.
> +
> +	If two values on the same axis (for example left and right) are set the
> +	invalid_input error is raised.
> +      </description>
> +      <arg name="gravity" type="uint" enum="gravity"
> +	   summary="bit mask of gravity directions"/>
> +    </request>
> +
> +    <enum name="constrain_adjustment" bitfield="true">
> +      <entry name="none" value="0">
> +	<description summary="don't move the child surface when constrained">
> +	  Don't alter the surface position even if it is constrained on some
> +	  axis, for example partially outside the edge of a monitor.
> +	</description>
> +      </entry>
> +      <entry name="slide_x" value="1">
> +	<description summary="move along the x axis until unconstrained">
> +	  Slide the surface along the x axis until it is no longer constrained.
> +
> +	  First try to slide towards the direction of the gravity on the x axis
> +	  until either the edge in the opposite direction of the gravity is
> +	  unconstrained or the edge in the direction of the gravity is
> +	  constrained.
> +
> +	  Then try to slide towards the opposite direction of the gravity on the
> +	  x axis until either the edge in the direction of the gravity is
> +	  unconstrained or the edge in the opposite direction of the gravity is
> +	  constrained.
> +
> +	  If 'slide_x' is combined with 'flip_x', 'flip_x' takes precedence.
> +	</description>
> +      </entry>
> +      <entry name="slide_y" value="2">
> +	<description summary="move along the y axis until unconstrained">
> +	  Slide the surface along the y axis until it is no longer constrained.
> +
> +	  First try to slide towards the direction of the gravity on the y axis
> +	  until either the edge in the opposite direction of the gravity is
> +	  unconstrained or the edge in the direction of the gravity is
> +	  constrained.
> +
> +	  Then try to slide towards the opposite direction of the gravity on the
> +	  y axis until either the edge in the direction of the gravity is
> +	  unconstrained or the edge in the opposite direction of the gravity is
> +	  constrained.
> +
> +	  If 'slide_y' is combined with 'flip_y', 'flip_y' takes precedence.
> +	</description>
> +      </entry>
> +      <entry name="flip_x" value="4">
> +	<description summary="invert the anchor and gravity on the x axis">
> +	  Invert the anchor and gravity on the x axis if the surface is
> +	  constrained on the x axis. For example, if the left edge of the
> +	  surface is constrained, the gravity is 'left' and the anchor is
> +	  'left', change the gravity to 'right' and the anchor to 'right'.
> +
> +	  If the adjusted position also ends up being constrained, the resulting
> +	  position will be the one before the adjustment. If the resulting
> +	  position is still constrained, and 'flip_x' is combined with
> +	  'slide_x', the position is adjusted according to 'slide_x'.
> +	</description>
> +      </entry>
> +      <entry name="flip_y" value="8">
> +	<description summary="invert the anchor and gravity on the y axis">
> +	  Invert the anchor and gravity on the y axis if the surface is
> +	  constrained on the y axis. For example, if the bottom edge of the
> +	  surface is constrained, the gravity is 'bottom' and the anchor is
> +	  'bottom', change the gravity to 'top' and the anchor to 'top'.
> +
> +	  If the adjusted position also ends up being constrained, the resulting
> +	  position will be the one before the adjustment. If the resulting
> +	  position is still constrained, and 'flip_y' is combined with
> +	  'slide_y', the position is adjusted according to 'slide_y'.
> +	</description>
> +      </entry>
> +    </enum>
> +
> +    <request name="set_constrain_adjustment">
> +      <description summary="set the adjustment to be done when constrained">
> +	Specify how the window should be positioned if the originally intended
> +	position caused the surface to be constrained, meaning at least
> +	partially outside positioning boundaries set by the compositor. The
> +	adjustment is set by constructing a bitmask describing the adjustment to
> +	be made when the surface is constrained on that axis.
> +
> +	If no bit for one axis is set, the compositor will assume that the child
> +	surface should not change its position on that axis when constrained.
> +
> +	If more than one bit for one axis is set, the order of how adjustments
> +	are applied is specified in the corresponding adjustment descriptions.
> +
> +	The default adjustment is none.
> +      </description>
> +      <arg name="constrain_adjustment" type="uint"
> +	   summary="bit mask of constrain adjustments"/>
> +    </request>
> +
> +    <request name="set_offset">
> +      <description summary="set surface position offset">
> +	Specify the surface position offset relative to the position of the
> +	anchor on the anchor rectangle and the anchor on the surface. For
> +	example if the anchor of the anchor rectangle is at (x, y), the surface
> +	has the gravity bottom|right, and the offset is (ox, oy), the calculated
> +	surface position will be (x + ox, y + oy). The offset position of the
> +	surface is the one used for constraint testing. See
> +	set_constrain_adjustment.
> +
> +	An example use case is placing a popup menu on top of a user interface
> +	element, while aligning the user interface element of the parent surface
> +	with some user interface element placed somewhere in the popup surface.
> +      </description>
> +      <arg name="x" type="int" summary="surface position x offset"/>
> +      <arg name="y" type="int" summary="surface position y offset"/>
> +    </request>
> +  </interface>
> +
>    <interface name="zxdg_surface_v6" version="1">
>      <description summary="desktop user interface surface base interface">
>        An interface that may be implemented by a wl_surface, for
> @@ -169,8 +424,7 @@
>        </description>
>        <arg name="id" type="new_id" interface="zxdg_popup_v6"/>
>        <arg name="parent" type="object" interface="zxdg_surface_v6"/>
> -      <arg name="x" type="int"/>
> -      <arg name="y" type="int"/>
> +      <arg name="positioner" type="object" interface="zxdg_positioner_v6"/>
>      </request>
>  
>      <request name="set_window_geometry">
> @@ -734,7 +988,7 @@
>  	button press, key press, or touch down event. The serial number of the
>  	event should be passed as 'serial'.
>  
> -	The parent of a grabbing popup must either be a xdg_toplevel surface or
> +	The parent of a grabbing popup must either be an xdg_toplevel surface or
>  	another xdg_popup with an explicit grab. If the parent is another
>  	xdg_popup it means that the popups are nested, with this popup now being
>  	the topmost popup.
> @@ -769,6 +1023,22 @@
>        <arg name="serial" type="uint" summary="the serial of the user event"/>
>      </request>
>  
> +    <event name="configure">
> +      <description summary="configure the popup surface">
> +	This event asks the popup surface to configure itself given the
> +	configuration. The configured state should not be applied immediately.
> +	See xdg_surface.configure for details.
> +
> +	The x and y arguments represent the position the popup was placed at
> +	given the xdg_positioner rule, relative to the upper left corner of the
> +	window geometry of the parent surface.
> +      </description>
> +      <arg name="x" type="int"
> +	   summary="x position relative to parent surface window geometry"/>
> +      <arg name="y" type="int"
> +	   summary="y position relative to parent surface window geometry"/>
> +    </event>
> +
>      <event name="popup_done">
>        <description summary="popup interaction is done">
>  	The popup_done event is sent out when a popup is dismissed by the
> -- 
> 2.7.4
> 
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list