[PATCH wayland-protocols v4 7/7] xdg-shell: Introduce xdg_positioner
Bill Spitzak
spitzak at gmail.com
Sat Jul 23 01:39:19 UTC 2016
/* 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;
}
More information about the wayland-devel
mailing list