[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