[PATCH wayland-protocols 1/4 v5] xdg-shell: Introduce xdg_positioner
Bryce Harrington
bryce at osg.samsung.com
Fri Aug 12 19:20:23 UTC 2016
On Fri, Aug 12, 2016 at 12:45:33PM +0800, Jonas Ådahl wrote:
> On Thu, Aug 11, 2016 at 09:36:42PM -0700, Bryce Harrington wrote:
> > On Fri, Aug 12, 2016 at 12:33:42PM +0800, Jonas Ådahl wrote:
> > > On Thu, Aug 11, 2016 at 09:08:15PM -0700, Bryce Harrington wrote:
> > > > On Fri, Aug 12, 2016 at 11:51:38AM +0800, Jonas Ådahl wrote:
> > > > > On Thu, Aug 11, 2016 at 08:39:08PM -0700, Bryce Harrington wrote:
> > > > > > 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.
> > > > >
> > > > > This reads better to me, thanks. I'll amend the wip branch with these
> > > > > changes.
> > > > >
> > > > > >
> > > > > > > + 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.
> > > > >
> > > > > Yes this reads better as well. What it lacks is making it obvious that
> > > > > setting no edges at all (not calling set_anchor or calling with 'none')
> > > > > results in the anchor position being placed in the center of the
> > > > > rectangle. How about adding that in end of the paragraph? I.e. something
> > > > > like this:
> > > > >
> > > > > 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, or in the center of the anchor rectangle
> > > > > if no edge is specified.
> > > >
> > > > Yep, that looks good.
> > >
> > > Great. Amending on the wip branch.
> > >
> > > >
> > > > Btw, the gravity section has a somewhat similar phrasing, so could
> > > > probably be improved by modeling it analogously to this, if you wanted.
> > >
> > > Yes, a similiar way to describe these two requests would be good. Here
> > > is an attempt to do that. What do you think?
> > >
> > > Defines in what direction a surface should be positioned,
> > > relative to the anchor point of the parent surface. If two
> > > orthogonal gravities are specified (e.g. 'bottom' and 'right'),
> > > then the child surface will be placed in the specified
> > > direction; otherwise, the child surface will be centered over
> > > the anchor point on any axis that had no gravity specified.
> >
> > Yep, looks good to me.
>
> Great! Can I add your RB on the wip with these three amendments?
Yep, with these changes applied:
Reviewed-by: Bryce Harrington <bryce at osg.samsung.com>
> Jonas
>
> >
> > Bryce
> >
> > > Jonas
> > >
> > > > > > > + 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