forked from 12to11/12to11
Fix some positioner bugs
* positioner.c (DebugPrint): New macro. (CalculatePosition, TrySlideX): Add more instrumentation. Add defaults when no gravity is specified. (TrySlideY): Add defaults when no gravity is specified. (TryFlipX): Fix incorrect inversion of AnchorGravityBottomRight. (ApplyConstraintAdjustment): Add more instrumentation.
This commit is contained in:
parent
a7a17e02fa
commit
6ad5901c97
1 changed files with 121 additions and 9 deletions
130
positioner.c
130
positioner.c
|
@ -24,6 +24,27 @@ along with 12to11. If not, see <https://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
#include "compositor.h"
|
#include "compositor.h"
|
||||||
|
|
||||||
|
#ifdef DEBUG_POSITIONER
|
||||||
|
#define DebugPrint(format, args...) \
|
||||||
|
fprintf (stderr, "%s: " format "\n", __FUNCTION__, ## args)
|
||||||
|
|
||||||
|
static const char *anchor_gravity_names[] =
|
||||||
|
{
|
||||||
|
"AnchorGravityNone",
|
||||||
|
"AnchorGravityTop",
|
||||||
|
"AnchorGravityBottom",
|
||||||
|
"AnchorGravityLeft",
|
||||||
|
"AnchorGravityRight",
|
||||||
|
"AnchorGravityTopLeft",
|
||||||
|
"AnchorGravityBottomLeft",
|
||||||
|
"AnchorGravityTopRight",
|
||||||
|
"AnchorGravityBottomRight",
|
||||||
|
};
|
||||||
|
|
||||||
|
#else
|
||||||
|
#define DebugPrint(fmt, ...) ((void) 0)
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef enum _AnchorGravity Anchor;
|
typedef enum _AnchorGravity Anchor;
|
||||||
typedef enum _AnchorGravity Gravity;
|
typedef enum _AnchorGravity Gravity;
|
||||||
|
|
||||||
|
@ -234,8 +255,16 @@ CalculatePosition (Positioner *positioner, int *x_out, int *y_out)
|
||||||
{
|
{
|
||||||
int x, y, anchor_x, anchor_y, anchor_width, anchor_height;
|
int x, y, anchor_x, anchor_y, anchor_width, anchor_height;
|
||||||
|
|
||||||
/* Code mostly copied from weston. I cannot understand
|
DebugPrint ("anchor: %s, gravity: %s",
|
||||||
xdg_positioner due to the terrible documentation. */
|
anchor_gravity_names[positioner->anchor],
|
||||||
|
anchor_gravity_names[positioner->gravity]);
|
||||||
|
|
||||||
|
/* This function calculates an offset from the origin of the parent
|
||||||
|
window geometry (in the X coordinate system where the value of
|
||||||
|
the Y axis increases as the position grows downwards.) The
|
||||||
|
offset is derived by first computing an anchor point, and then
|
||||||
|
placing the surface at that anchor in accordance with the
|
||||||
|
gravity. */
|
||||||
|
|
||||||
x = positioner->offset_x;
|
x = positioner->offset_x;
|
||||||
y = positioner->offset_y;
|
y = positioner->offset_y;
|
||||||
|
@ -245,6 +274,9 @@ CalculatePosition (Positioner *positioner, int *x_out, int *y_out)
|
||||||
anchor_width = positioner->anchor_width;
|
anchor_width = positioner->anchor_width;
|
||||||
anchor_height = positioner->anchor_height;
|
anchor_height = positioner->anchor_height;
|
||||||
|
|
||||||
|
/* First, compute the point at which the surface will be
|
||||||
|
anchored. */
|
||||||
|
|
||||||
switch (positioner->anchor)
|
switch (positioner->anchor)
|
||||||
{
|
{
|
||||||
case AnchorGravityTop:
|
case AnchorGravityTop:
|
||||||
|
@ -281,6 +313,26 @@ CalculatePosition (Positioner *positioner, int *x_out, int *y_out)
|
||||||
x += anchor_x + anchor_width / 2;
|
x += anchor_x + anchor_width / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Next, compute where the surface should be. positioner->gravity
|
||||||
|
specifies the corner opposite to the one that should be touching
|
||||||
|
the anchor. For example:
|
||||||
|
|
||||||
|
(anchor)
|
||||||
|
+ ------>
|
||||||
|
|
|
||||||
|
|
|
||||||
|
v
|
||||||
|
|
||||||
|
would be the directions in which the surface rectangle would
|
||||||
|
extend if the gravity were to be AnchorGravityBottomRight. And:
|
||||||
|
|
||||||
|
^
|
||||||
|
|
|
||||||
|
|
|
||||||
|
<-----+ (anchor)
|
||||||
|
|
||||||
|
would be the those directions were it AnchorGravityTopLeft. */
|
||||||
|
|
||||||
switch (positioner->gravity)
|
switch (positioner->gravity)
|
||||||
{
|
{
|
||||||
case AnchorGravityTop:
|
case AnchorGravityTop:
|
||||||
|
@ -310,6 +362,7 @@ CalculatePosition (Positioner *positioner, int *x_out, int *y_out)
|
||||||
case AnchorGravityRight:
|
case AnchorGravityRight:
|
||||||
case AnchorGravityTopRight:
|
case AnchorGravityTopRight:
|
||||||
case AnchorGravityBottomRight:
|
case AnchorGravityBottomRight:
|
||||||
|
x = x;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -332,6 +385,10 @@ TrySlideX (Positioner *positioner, int x, int width, int cx, int cwidth)
|
||||||
cx1 = cx + cwidth - 1;
|
cx1 = cx + cwidth - 1;
|
||||||
x1 = x + width - 1;
|
x1 = x + width - 1;
|
||||||
|
|
||||||
|
DebugPrint ("trying to slide X %d (width %d) according to"
|
||||||
|
" constraint X %d and constraint width %d", x,
|
||||||
|
width, cx, cwidth);
|
||||||
|
|
||||||
/* See if the rect is unconstrained on the X axis. */
|
/* See if the rect is unconstrained on the X axis. */
|
||||||
|
|
||||||
if (x >= cx && x1 <= cx1)
|
if (x >= cx && x1 <= cx1)
|
||||||
|
@ -360,6 +417,9 @@ TrySlideX (Positioner *positioner, int x, int width, int cx, int cwidth)
|
||||||
case AnchorGravityRight:
|
case AnchorGravityRight:
|
||||||
case AnchorGravityTopRight:
|
case AnchorGravityTopRight:
|
||||||
case AnchorGravityBottomRight:
|
case AnchorGravityBottomRight:
|
||||||
|
/* There is no X axis gravity. Choose some arbitrary
|
||||||
|
default. */
|
||||||
|
default:
|
||||||
if (x1 > cx1)
|
if (x1 > cx1)
|
||||||
/* If x1 extends past cx1, move it back. */
|
/* If x1 extends past cx1, move it back. */
|
||||||
new_x = x - (x1 - cx1);
|
new_x = x - (x1 - cx1);
|
||||||
|
@ -369,6 +429,8 @@ TrySlideX (Positioner *positioner, int x, int width, int cx, int cwidth)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DebugPrint ("new X: %d", new_x);
|
||||||
|
|
||||||
return new_x;
|
return new_x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -409,6 +471,9 @@ TrySlideY (Positioner *positioner, int y, int height, int cy, int cheight)
|
||||||
case AnchorGravityBottom:
|
case AnchorGravityBottom:
|
||||||
case AnchorGravityBottomLeft:
|
case AnchorGravityBottomLeft:
|
||||||
case AnchorGravityBottomRight:
|
case AnchorGravityBottomRight:
|
||||||
|
/* When there is no Y axis gravity, choose some arbitrary
|
||||||
|
default. */
|
||||||
|
default:
|
||||||
if (y1 > cy1)
|
if (y1 > cy1)
|
||||||
/* If y1 eytends past cy1, move it back. */
|
/* If y1 eytends past cy1, move it back. */
|
||||||
new_y = y - (y1 - cy1);
|
new_y = y - (y1 - cy1);
|
||||||
|
@ -437,6 +502,10 @@ TryFlipX (Positioner *positioner, int x, int width, int cx, int cwidth,
|
||||||
if (x >= cx && x1 <= cx1)
|
if (x >= cx && x1 <= cx1)
|
||||||
return x;
|
return x;
|
||||||
|
|
||||||
|
DebugPrint ("x %d width %d found to be constrained by "
|
||||||
|
"constraint x %d constraint width %d", x, width,
|
||||||
|
cx, cwidth);
|
||||||
|
|
||||||
/* Otherwise, create a copy of the positioner, but with the X
|
/* Otherwise, create a copy of the positioner, but with the X
|
||||||
gravity and X anchor flipped. */
|
gravity and X anchor flipped. */
|
||||||
new = *positioner;
|
new = *positioner;
|
||||||
|
@ -464,7 +533,7 @@ TryFlipX (Positioner *positioner, int x, int width, int cx, int cwidth,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AnchorGravityBottomRight:
|
case AnchorGravityBottomRight:
|
||||||
new.gravity = AnchorGravityBottomRight;
|
new.gravity = AnchorGravityBottomLeft;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -491,7 +560,7 @@ TryFlipX (Positioner *positioner, int x, int width, int cx, int cwidth,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AnchorGravityBottomRight:
|
case AnchorGravityBottomRight:
|
||||||
new.anchor = AnchorGravityBottomRight;
|
new.anchor = AnchorGravityBottomLeft;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,16 +571,27 @@ TryFlipX (Positioner *positioner, int x, int width, int cx, int cwidth,
|
||||||
&& positioner->anchor == new.anchor)
|
&& positioner->anchor == new.anchor)
|
||||||
return x;
|
return x;
|
||||||
|
|
||||||
|
DebugPrint ("new anchor: %s, anchor point: %d, %d; gravity: %s",
|
||||||
|
anchor_gravity_names[new.anchor],
|
||||||
|
positioner->anchor_x, positioner->anchor_y,
|
||||||
|
anchor_gravity_names[new.gravity]);
|
||||||
|
|
||||||
/* Otherwise, compute a new position using the new positioner. */
|
/* Otherwise, compute a new position using the new positioner. */
|
||||||
CalculatePosition (&new, &new_x, NULL);
|
CalculatePosition (&new, &new_x, NULL);
|
||||||
|
|
||||||
/* Scale that position. */
|
/* Scale that position. */
|
||||||
new_x *= scale_adjustment_factor;
|
new_x *= scale_adjustment_factor;
|
||||||
|
|
||||||
|
DebugPrint ("new x position is %d", new_x + offset);
|
||||||
|
|
||||||
/* If new_x is still constrained, use the previous position. */
|
/* If new_x is still constrained, use the previous position. */
|
||||||
if (new_x + offset < cx
|
if (new_x + offset < cx
|
||||||
|| new_x + offset + width - 1 > cx1)
|
|| new_x + offset + width - 1 > cx1)
|
||||||
return x;
|
{
|
||||||
|
DebugPrint ("position (%d) is still constrained",
|
||||||
|
new_x + offset);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return the new X. */
|
/* Return the new X. */
|
||||||
return new_x + offset;
|
return new_x + offset;
|
||||||
|
@ -715,15 +795,37 @@ ApplyConstraintAdjustment (Positioner *positioner, Role *parent, int x,
|
||||||
/* There is no output in which to constrain this popup. */
|
/* There is no output in which to constrain this popup. */
|
||||||
goto finish;
|
goto finish;
|
||||||
|
|
||||||
|
#ifdef DEBUG_POSITIONER
|
||||||
|
|
||||||
|
fputs ("ApplyConstraintAdjustments: constraint adjustments are: ", stderr);
|
||||||
|
|
||||||
if (positioner->constraint_adjustment
|
if (positioner->constraint_adjustment
|
||||||
& XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X)
|
& XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X)
|
||||||
x = TrySlideX (positioner, x + off_x, width,
|
fputs ("SLIDE_X ", stderr);
|
||||||
cx, cwidth) - off_x;
|
|
||||||
|
|
||||||
if (positioner->constraint_adjustment
|
if (positioner->constraint_adjustment
|
||||||
& XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y)
|
& XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y)
|
||||||
y = TrySlideY (positioner, y + off_y, height,
|
fputs ("SLIDE_Y ", stderr);
|
||||||
cy, cheight) - off_y;
|
|
||||||
|
if (positioner->constraint_adjustment
|
||||||
|
& XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X)
|
||||||
|
fputs ("FLIP_X ", stderr);
|
||||||
|
|
||||||
|
if (positioner->constraint_adjustment
|
||||||
|
& XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y)
|
||||||
|
fputs ("FLIP_Y ", stderr);
|
||||||
|
|
||||||
|
if (positioner->constraint_adjustment
|
||||||
|
& XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X)
|
||||||
|
fputs ("RESIZE_X ", stderr);
|
||||||
|
|
||||||
|
if (positioner->constraint_adjustment
|
||||||
|
& XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y)
|
||||||
|
fputs ("RESIZE_X ", stderr);
|
||||||
|
|
||||||
|
fprintf (stderr, "\n");
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
if (positioner->constraint_adjustment
|
if (positioner->constraint_adjustment
|
||||||
& XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X)
|
& XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X)
|
||||||
|
@ -735,6 +837,16 @@ ApplyConstraintAdjustment (Positioner *positioner, Role *parent, int x,
|
||||||
y = TryFlipY (positioner, y + off_y, height,
|
y = TryFlipY (positioner, y + off_y, height,
|
||||||
cy, cheight, off_y) - off_y;
|
cy, cheight, off_y) - off_y;
|
||||||
|
|
||||||
|
if (positioner->constraint_adjustment
|
||||||
|
& XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X)
|
||||||
|
x = TrySlideX (positioner, x + off_x, width,
|
||||||
|
cx, cwidth) - off_x;
|
||||||
|
|
||||||
|
if (positioner->constraint_adjustment
|
||||||
|
& XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y)
|
||||||
|
y = TrySlideY (positioner, y + off_y, height,
|
||||||
|
cy, cheight) - off_y;
|
||||||
|
|
||||||
if (positioner->constraint_adjustment
|
if (positioner->constraint_adjustment
|
||||||
& XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X)
|
& XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X)
|
||||||
TryResizeX (x + off_x, width, cx, cwidth,
|
TryResizeX (x + off_x, width, cx, cwidth,
|
||||||
|
|
Loading…
Add table
Reference in a new issue