As attachement, but I think gmail is messing this up: On Fri, Jul 22, 2016 at 6:39 PM, Bill Spitzak <spit...@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; > }
/* 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, that is what I think the * documentation says. Not entirely clear however. */ } /* 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)); /* FIXME: this only does slide on the original side, that is what I think the * documentation says. Not entirely clear however. */ } /* 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; }
_______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/wayland-devel