[PATCH wayland-protocols v4 7/7] xdg-shell: Introduce xdg_positioner

Bill Spitzak spitzak at gmail.com
Sat Jul 23 01:40:22 UTC 2016


As attachement, but I think gmail is messing this up:

On Fri, Jul 22, 2016 at 6:39 PM, Bill Spitzak <spitzak at gmail.com> wrote:
> /* Translate xdg_positioner v4 settings to proposed list-of-rectangles api
>  *
>  * I cannot find any proposed implementation, so I have to base this
> off the comments
>  * in the protocol spec, which are somewhat ambiguous. See FIXME notes
> for where I
>  * guessed and may have mis-interpreted the spec.
>  */
>
> #include <limits.h>
> #include <stdio.h>
>
> /* bits for anchor and gravity */
> #define TOP 1
> #define BOTTOM 2
> #define LEFT 4
> #define RIGHT 8
>
> /* bits for constrain_adjustment */
> #define SLIDE_X 1
> #define SLIDE_Y 2
> #define FLIP_X 4
> #define FLIP_Y 8
>
> /* v4 positioner data */
> typedef struct {
>     struct { int width; int height; } size;
>     struct { int x; int y; int width; int height; } anchor_rect;
>     int anchor;
>     int gravity;
>     int constrain_adjustment;
>     struct { int x; int y; } offset;
> } V4Positioner;
>
> /* The new positioner api */
> extern void add_rectangle( int x0, int y0, int x1, int y1 ) {
>     printf("add_rectangle( %d, %d, %d, %d );\n", x0, y0, x1, y1);
> }
>
> /* Possibly the api should support this rather than the 4-number rectangle.
>  * x0,y0 must be upper-left corner, x1,y1 the lower-right corner, x,y
> is preferred
>  * location which must be inside the rectangle.
>  */
> void add_rectangle6( int x, int y, int x0, int y0, int x1, int y1 )
> {
>     if (y > y0) {
>         if (x > x0)
>             add_rectangle(x, y, x0, y0);
>         add_rectangle(x, y, x1, y0);
>     }
>     if (x > x0)
>         add_rectangle(x, y, x0, y1);
>     add_rectangle(x, y, x1, y1);
> }
>
> /* Do one part of a "flip" */
> void single_anchor(const V4Positioner* v4, int anchor, int gravity,
> int constrain_adjustment) {
>
>     int x, y; /* preferred position */
>
>     /* Find anchor point */
>     if (anchor & LEFT)
>         x = v4->anchor_rect.x;
>     else if (anchor & RIGHT)
>         x = v4->anchor_rect.x + v4->anchor_rect.width;
>     else
>         x = v4->anchor_rect.x + v4->anchor_rect.width / 2;
>
>     if (anchor & TOP)
>         y = v4->anchor_rect.y;
>     else if (anchor & BOTTOM)
>         y = v4->anchor_rect.y + v4->anchor_rect.height;
>     else
>         y = v4->anchor_rect.y + v4->anchor_rect.height / 2;
>
>     /* move to top-left of size */
>     if (gravity & LEFT)
>         ;
>     else if (gravity & RIGHT)
>         x -= v4->size.width;
>     else
>         x -= v4->size.width / 2;
>     if (gravity & TOP)
>         ;
>     else if (gravity & BOTTOM)
>         y -= v4->size.height;
>     else
>         y -= v4->size.height / 2;
>
>     /* Handle offset.
>      * FIXME: I am assuming the "widget in the child" is a rectangle
> defined by offset,size.
>      * Documentation seems to imply the meaning of offset depends on
> the gravity, but
>      * that is pretty useless for FLIP setups so I did not do that.
>      */
>     x -= v4->offset.x;
>     y -= v4->offset.y;
>
>     /* Add slide to get resulting rectangles
>      * FIXME: unclear if slide is limited to touch the anchor
> rectangle. I believe
>      * this is not true so I use INT_MAX here.
>      * FIXME: unclear if slide is limited to touch the parent surface.
> My opinion
>      * now is that the compositor can enforce this.
>      */
>     int x0, y0, x1, y1;
>     if (constrain_adjustment & SLIDE_X) {
>         x0 = -INT_MAX;
>         x1 = +INT_MAX;
>     } else {
>         x0 = x1 = x;
>     }
>     if (constrain_adjustment & SLIDE_Y) {
>         y0 = -INT_MAX;
>         y1 = +INT_MAX;
>     } else {
>         y0 = y1 = y;
>     }
>
>     add_rectangle6(x, y, x0, y0, x1, y1);
> }
>
> /* Do the full conversion.
>  * FIXME: This will produce redundant identical rectangles. Preventing
> this requires more
>  * testing for useless flip states.
>  */
> void convert(const V4Positioner* v4) {
>
>     if (v4->constrain_adjustment & FLIP_Y) {
>         /* try the preferred position first, no sliding */
>         single_anchor(v4, v4->anchor, v4->gravity,
> v4->constrain_adjustment & (~SLIDE_Y));
>         /* try the flipped position */
>         single_anchor(v4, v4->anchor ^ (TOP|BOTTOM), v4->gravity ^ (TOP|BOTTOM),
>                       v4->constrain_adjustment & (~SLIDE_Y));
>         /* FIXME: this only does slide on the original side. Unclear
> if slide is on other side too.
>          */
>     }
>
>     /* FIXME: what happens if both FLIP_X and FLIP_Y are set is
> unclear. This version only
>      * tries three locations, not four.
>      */
>     if (v4->constrain_adjustment & FLIP_X) {
>         /* try the preferred position first, no sliding */
>         single_anchor(v4, v4->anchor, v4->gravity,
> v4->constrain_adjustment & (~SLIDE_X));
>         /* try the flipped position */
>         single_anchor(v4, v4->anchor ^ (LEFT|RIGHT), v4->gravity ^ (LEFT|RIGHT),
>                       v4->constrain_adjustment & (~SLIDE_X));
>     }
>
>     /* Do the non-flipped position */
>     single_anchor(v4, v4->anchor, v4->gravity, v4->constrain_adjustment);
> }
>
> int main() {
>     V4Positioner v4;
>
>     v4.size.width = 100;
>     v4.size.height = 100;
>
>     v4.anchor_rect.x = 60;
>     v4.anchor_rect.y = 90;
>     v4.anchor_rect.width = 0;
>     v4.anchor_rect.height = 0;
>
>     v4.anchor = 0;
>     v4.gravity = TOP;
>     v4.constrain_adjustment = FLIP_Y | SLIDE_X;
>
>     v4.offset.x = 0;
>     v4.offset.y = 0;
>
>     convert(&v4);
>     return 0;
> }
-------------- next part --------------
A non-text attachment was scrubbed...
Name: xdg_positioner.c
Type: text/x-csrc
Size: 5256 bytes
Desc: not available
URL: <https://lists.freedesktop.org/archives/wayland-devel/attachments/20160722/3398a689/attachment-0001.c>


More information about the wayland-devel mailing list