<div dir="ltr">I've emerged from my bike shed in order to join this expert-level shedcraftsmanship discussion.<br><br><div class="gmail_quote"><div dir="ltr">On Thu, Apr 14, 2016 at 4:28 AM Jonas Ådahl <<a href="mailto:jadahl@gmail.com">jadahl@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">xdg_positioner is a method for declarative positioning of child surfaces<br>
(currently only xdg_popup surfaces). A client creates a description of a<br>
positioning logic using the xdg_positioner interface. The xdg_positioner<br>
object is then used when creating a xdg_popup for describing how the<br>
child surface should be positioned in relation to the parent surface.<br>
<br>
Signed-off-by: Jonas Ådahl <<a href="mailto:jadahl@gmail.com" target="_blank">jadahl@gmail.com</a>><br>
Signed-off-by: Mike Blumenkrantz <<a href="mailto:zmike@samsung.com" target="_blank">zmike@samsung.com</a>><br>
---<br>
 unstable/xdg-shell/xdg-shell-unstable-v6.xml | 206 ++++++++++++++++++++++++++-<br>
 1 file changed, 204 insertions(+), 2 deletions(-)<br>
<br>
diff --git a/unstable/xdg-shell/xdg-shell-unstable-v6.xml b/unstable/xdg-shell/xdg-shell-unstable-v6.xml<br>
index a2a6f12..2b51802 100644<br>
--- a/unstable/xdg-shell/xdg-shell-unstable-v6.xml<br>
+++ b/unstable/xdg-shell/xdg-shell-unstable-v6.xml<br>
@@ -57,6 +57,15 @@<br>
       </description><br>
     </request><br>
<br>
+    <request name="create_positioner"><br>
+      <description summary="create a positioner object"><br>
+       Create a positioner object. A positioner object is used to position<br>
+       surfaces relative to some parent surface. See the interface description<br></blockquote><div><br></div><div>If this is going to operate based on a surface's parent (ie. set_parent) then it should read "A position object is used to position its surface(s) relative to their parent surface (see set_parent)" in order to avoid any confusion.</div><div><br></div><div>Moreover, I'm thinking this object needs to somehow be tethered to a single toplevel hierarchy; the current text has no restrictions about the positioner's use, meaning that it could be used for eg.</div><div><br></div><div>Surface A</div><div>[Positioner P]</div><div>Popup A</div><div><br></div><div>Surface B</div><div>[Positioner P]</div><div>Popup B</div><div>[Positioner P]</div><div>Popup B2</div><div><br></div><div>which would be confusing, and could also lead to annoying calculation issues if Surface A was huge and Surface B was tiny.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+       for details.<br>
+      </description><br>
+      <arg name="id" type="new_id" interface="zxdg_positioner_v6"/><br>
+    </request><br>
+<br>
     <request name="get_xdg_surface"><br>
       <description summary="create a shell surface from a surface"><br>
        This creates an xdg_surface for the given surface. While xdg_surface<br>
@@ -96,6 +105,186 @@<br>
     </event><br>
   </interface><br>
<br>
+  <interface name="zxdg_positioner_v6" version="1"><br>
+    <description summary="child surface positioner"><br>
+      The xdg_positioner provides an interface for constructing positioning<br>
+      rules used for positioning a child surface relative to another surface<br></blockquote><div><br></div><div>Same as above.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+      in a certain way. It allows methods for defining a rule that will make<br>
+      the child surface stay within the border of the visible area of the<br></blockquote><div><br></div><div>I'd rather have this specifically reference "the positioner's surface(s)" or similar instead of "the child surface" in order to keep context within the positioner interface.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+      screen, with different ways in which the child surface should change<br>
+      its position, including sliding along an axis, or flipping around a<br>
+      rectangle.<br>
+<br>
+      See the various requests for details about possible rules.<br>
+<br>
+      An xdg_positioner object may be re-used when positioning different<br></blockquote><div><br></div><div>Saying "re-used" here makes it sound like the positioner can only have one surface attached to it at a time. I think something like "...may continue to be applied to any xdg_popup surfaces until destroyed..." would be more clear.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+      surfaces until destroyed using xdg_positioner.destroy.<br>
+    </description><br>
+<br>
+    <enum name="error"><br>
+      <entry name="invalid_input" value="0" summary="invalid input provided"/><br>
+    </enum><br>
+<br>
+    <request name="destroy" type="destructor"><br>
+      <description summary="destroy the xdg_positioner object"><br>
+       Notify the compositor that the xdg_positioner will no longer be used.<br></blockquote><div><br></div><div>Should this include an explicit note about what to do with surfaces which were using the positioner, eg. "No changes should be made to users of the positioner upon its destruction" ?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+      </description><br>
+    </request><br>
+<br>
+    <request name="set_anchor_rect"><br>
+      <description summary="set the anchor rectangle of the parent surface"><br></blockquote><div><br></div><div>"set the anchor rectangle within the parent surface"</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+       Specify the anchor rectangle of the parent surface that the child<br>
+       surface will be placed relative to. The rectangle is relative to the<br>
+       window geometry as defined by xdg_surface.set_window_geometry of the<br>
+       parent surface. The rectangle must be at least be 1x1 large.<br>
+<br>
+       When used to position a child surface, the attach rectangle may not<br>
+       extend outside of the window geometry of the parent surface.<br></blockquote><div><br></div><div>I think this also needs to be clarified to something like "The positioner's attach rectangle may not extend outside the window geometry of the user surface's parent" in order to handle the case where the positioner is used for multiple surfaces with different parents in the same hierarchy chain (assuming this is going to be allowed).</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+      </description><br>
+      <arg name="x" type="int" summary="x position of anchor rectangle"/><br>
+      <arg name="y" type="int" summary="y position of anchor rectangle"/><br>
+      <arg name="width" type="int" summary="width of anchor rectangle"/><br>
+      <arg name="height" type="int" summary="height of anchor rectangle"/><br>
+    </request><br>
+<br>
+    <enum name="anchor"><br>
+      <entry name="none" value="0"<br>
+            summary="the center of the anchor rectangle"/><br>
+      <entry name="left" value="1"<br>
+            summary="the left edge of the anchor rectangle"/><br>
+      <entry name="right" value="2"<br>
+            summary="the right edge of the anchor rectangle"/><br>
+      <entry name="top" value="4"<br>
+            summary="the top edge of the anchor rectangle"/><br>
+      <entry name="bottom" value="8"<br>
+            summary="the bottom edge of the anchor rectangle"/><br>
+    </enum><br>
+<br>
+    <request name="set_anchor"><br>
+      <description summary="set anchor rect anchor edges"><br>
+       Set the anchor edges of the anchor rectangle. The anchor edges<br>
+       defines where on the anchor rectangle the child surface should<br>
+       positioned relative to. An anchor is a bit mask of zero to two values of<br></blockquote><div><br></div><div>I understand what you mean by "zero to two", but saying "zero values of the anchor enum" is a bit weird since 0/none is an enum value.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+       the anchor enum. Two values on the same axis (for example left and<br>
+       right) may not be combined.<br></blockquote><div><br></div><div>Are we defining an error for this case or ?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
+       If no anchor is set on any axis, the anchor position will be positioned<br>
+       at the center of the anchor rectangle on the unset axis. The default<br>
+       value is "none".<br>
+      </description><br>
+      <arg name="anchor" type="uint" bitfield="true"<br>
+          summary="bit mask of anchor edges"/><br>
+    </request><br>
+<br>
+    <enum name="gravity"><br>
+      <entry name="none" value="0"<br>
+            summary="center above the anchor position"/><br></blockquote><div><br></div><div>I think maybe you meant "center over" ?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+      <entry name="left" value="1"<br>
+            summary="position to the left of the anchor position"/><br>
+      <entry name="right" value="2"<br>
+            summary="position to the right of the anchor position"/><br>
+      <entry name="top" value="4"<br>
+            summary="position above the anchor position"/><br>
+      <entry name="bottom" value="8"<br>
+            summary="position below the anchor position"/><br>
+    </enum><br>
+<br>
+    <request name="set_gravity"><br>
+      <description summary="set child surface gravity"><br>
+       The gravity defines in what direction a surface would be positioned,<br>
+       relative to the anchor position on the parent surface. A gravity<br>
+       is a bit mask of zero to two values of the gravity enum. Two values<br>
+       on the same axis (for example left and right) may not be combined.<br>
+<br>
+       If no gravity is set on an axis, the gravity for that axis will be<br>
+       equivalent to setting "none" for that axis, resulting in the child being<br>
+       centered over the anchor on that axis.<br></blockquote><div><br></div><div>I think for all cases of "anchor" and "anchor position" in this request and the preceding enum we should probably be strict in using the term "anchor rectangle" in order to maintain consistency.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+      </description><br>
+      <arg name="gravity" type="uint" bitfield="true"<br>
+          summary="bit mask of gravity directions"/><br>
+    </request><br>
+<br>
+    <enum name="constrain_action"><br></blockquote><div><br></div><div>I don't like the use of "action" here as, to me, it seems to imply user action rather than compositor calculations. Maybe something more like "fallback_position" or "position_adjustment"?</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+      <entry name="none" value="0"><br>
+       <description summary="don't move the child surface when constrained"><br>
+         Don't alter the surface position even if it is constrained on some<br>
+         axis, for example partially outside the edge of monitor.<br>
+       </description><br>
+      </entry><br>
+      <entry name="slide_x" value="1"><br>
+       <description summary="move along the X-axis until unconstrained"><br>
+         Slide the surface along the X-axis until it is no longer constrained.<br>
+         If the left side of the surface is constrained, slide towards the<br>
+         right; if the right side of the surface is constrained, slide towards<br>
+         the left. If both sides are ends up being constrained, the behaviour is<br></blockquote><div><br></div><div>I think the directionality here should be based on the gravity, eg. if LEFT gravity is used then it tries to move left if possible, moving right afterward only if a leftward movement is impossible or does not solve the positioning. This handles the case of both sides being constrained since the compositor is then unable to perform any positioning corrections.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+         undefined.<br>
+       </description><br>
+      </entry><br>
+      <entry name="slide_y" value="2"><br>
+       <description summary="move along the Y-axis until unconstrained"><br>
+         Slide the surface along the Y-axis until it is no longer constrained.<br>
+         If the top side of the surface is constrained, slide towards the<br>
+         bottom; if the bottom side of the surface is constrained, slide towards<br>
+         the top. If both sides are ends up being constrained, the behaviour is<br>
+         undefined.<br>
+       </description><br>
+      </entry><br>
+      <entry name="flip_x" value="4"><br>
+       <description summary="invert the anchor and gravity on the X-axis"><br>
+         Invert the anchor and gravity on the X-axis if the surface is<br>
+         constrained on the X-axis. For example, if the left edge of the<br>
+         surface is constrained, the gravity is 'left' and the anchor is<br>
+         'left', change the gravity to 'right' and the anchor to 'right'. If<br>
+         the resulting position after inverting ends up also being constrained,<br>
+         the behaviour is undefined.<br>
+       </description><br>
+      </entry><br>
+      <entry name="flip_y" value="8"><br>
+       <description summary="invert the anchor and gravity on the Y-axis"><br>
+         Invert the anchor and gravity on the Y-axis if the surface is<br>
+         constrained on the Y-axis. For example, if the bottom edge of the<br>
+         surface is constrained, the gravity is 'bottom' and the anchor is<br>
+         'bottom', change the gravity to 'top' and the anchor to 'top'. If<br>
+         the resulting position after inverting ends up also being constrained,<br>
+         the behaviour is undefined.<br>
+       </description><br>
+      </entry><br>
+    </enum><br>
+<br>
+    <request name="set_constrain_action"><br>
+      <description summary="set the action to be done when constrained"><br></blockquote><div><br></div><div>Same as my above comment re:action.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+       Specify how the window should be positioned if the originally intended<br>
+       position caused the surface to be constrained, meaning partially outside<br></blockquote><div><br></div><div>Probably "meaning at least partially" to cover the case where the surface is completely outside the screen.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+       positioning boundaries set by the compositor. The action is set by<br>
+       constructing a bitmask with one bit per axis set describing the action<br>
+       to be taken when the surface is constrained on that axis. If no bit for<br>
+       one axis is set, the compositor will assume that the child surface<br>
+       should not change its position on that axis when constrained. The<br>
+       default action is none.<br>
+      </description><br>
+      <arg name="constrain_action" type="uint" bitfield="true"<br>
+          summary="bit mask of constrain actions"/><br>
+    </request><br>
+<br>
+    <request name="set_offset"><br>
+      <description summary="set surface position offset"><br>
+       Specify the surface position offset relative to the position of the<br>
+       anchor on the anchor rectangle and the anchor on the surface. For<br>
+       example if the anchor of the anchor rectangle is at (x, y), the surface<br>
+       has the gravity bottom|right, and the offset is (ox, oy), the calculated<br>
+       surface position will be (x + ox, y + oy). The offset position of the<br>
+       surface is the one used for constraint testing. See<br>
+       set_constraint_actions.<br>
+<br>
+       An example use case is placing a popup menu on top of a user interface<br>
+       element, while aligning the user interface element of the parent surface<br>
+       with some user interface element placed somewhere in the popup surface.<br>
+      </description><br>
+      <arg name="x" type="int" summary="surface position x offset"/><br></blockquote><div><br></div><div>These should probably be "anchor rectangle x/y offset"</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+      <arg name="y" type="int" summary="surface position y offset"/><br>
+    </request><br>
+  </interface><br>
+<br>
   <interface name="zxdg_surface_v6" version="1"><br>
     <description summary="desktop user interface surface base interface"><br>
       An interface that may be implemented by a wl_surface, for<br>
@@ -167,8 +356,7 @@<br>
       </description><br>
       <arg name="id" type="new_id" interface="zxdg_popup_v6"/><br>
       <arg name="parent" type="object" interface="zxdg_surface_v6"/><br>
-      <arg name="x" type="int"/><br>
-      <arg name="y" type="int"/><br>
+      <arg name="positioner" type="object" interface="zxdg_positioner_v6"/><br>
     </request><br>
<br>
     <request name="set_window_geometry"><br>
@@ -675,6 +863,20 @@<br>
       <arg name="serial" type="uint" summary="the serial of the user event"/><br>
     </request><br>
<br>
+    <event name="configure"><br>
+      <description summary="configure the popup surface"><br>
+       This event asks the popup surface to configure itself given the<br>
+       configuration. It is not sent by itself but is a latched state finalized<br>
+       by the xdg_surface.configure event.<br>
+<br>
+       The x and y arguments represents the position the popup was placed at<br>
+       given the xdg_positioner rule, relative to the upper left corner of the<br>
+       window geometry of the parent surface.<br>
+      </description><br>
+      <arg name="x" type="int" summary="X position relative to parent surface"/><br>
+      <arg name="y" type="int" summary="Y position relative to parent surface"/><br>
+    </event><br>
+<br></blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">     <event name="popup_done"><br>
       <description summary="popup interaction is done"><br>
        The popup_done event is sent out when a popup is dismissed by the<br>
--<br>
2.4.3<br>
<br>
_______________________________________________<br>
wayland-devel mailing list<br>
<a href="mailto:wayland-devel@lists.freedesktop.org" target="_blank">wayland-devel@lists.freedesktop.org</a><br>
<a href="https://lists.freedesktop.org/mailman/listinfo/wayland-devel" rel="noreferrer" target="_blank">https://lists.freedesktop.org/mailman/listinfo/wayland-devel</a><br>
</blockquote></div></div>