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"
|
||||
|
||||
#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 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;
|
||||
|
||||
/* Code mostly copied from weston. I cannot understand
|
||||
xdg_positioner due to the terrible documentation. */
|
||||
DebugPrint ("anchor: %s, gravity: %s",
|
||||
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;
|
||||
y = positioner->offset_y;
|
||||
|
@ -245,6 +274,9 @@ CalculatePosition (Positioner *positioner, int *x_out, int *y_out)
|
|||
anchor_width = positioner->anchor_width;
|
||||
anchor_height = positioner->anchor_height;
|
||||
|
||||
/* First, compute the point at which the surface will be
|
||||
anchored. */
|
||||
|
||||
switch (positioner->anchor)
|
||||
{
|
||||
case AnchorGravityTop:
|
||||
|
@ -281,6 +313,26 @@ CalculatePosition (Positioner *positioner, int *x_out, int *y_out)
|
|||
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)
|
||||
{
|
||||
case AnchorGravityTop:
|
||||
|
@ -310,6 +362,7 @@ CalculatePosition (Positioner *positioner, int *x_out, int *y_out)
|
|||
case AnchorGravityRight:
|
||||
case AnchorGravityTopRight:
|
||||
case AnchorGravityBottomRight:
|
||||
x = x;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -332,6 +385,10 @@ TrySlideX (Positioner *positioner, int x, int width, int cx, int cwidth)
|
|||
cx1 = cx + cwidth - 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. */
|
||||
|
||||
if (x >= cx && x1 <= cx1)
|
||||
|
@ -360,6 +417,9 @@ TrySlideX (Positioner *positioner, int x, int width, int cx, int cwidth)
|
|||
case AnchorGravityRight:
|
||||
case AnchorGravityTopRight:
|
||||
case AnchorGravityBottomRight:
|
||||
/* There is no X axis gravity. Choose some arbitrary
|
||||
default. */
|
||||
default:
|
||||
if (x1 > cx1)
|
||||
/* If x1 extends past cx1, move it back. */
|
||||
new_x = x - (x1 - cx1);
|
||||
|
@ -369,6 +429,8 @@ TrySlideX (Positioner *positioner, int x, int width, int cx, int cwidth)
|
|||
break;
|
||||
}
|
||||
|
||||
DebugPrint ("new X: %d", new_x);
|
||||
|
||||
return new_x;
|
||||
}
|
||||
|
||||
|
@ -409,6 +471,9 @@ TrySlideY (Positioner *positioner, int y, int height, int cy, int cheight)
|
|||
case AnchorGravityBottom:
|
||||
case AnchorGravityBottomLeft:
|
||||
case AnchorGravityBottomRight:
|
||||
/* When there is no Y axis gravity, choose some arbitrary
|
||||
default. */
|
||||
default:
|
||||
if (y1 > cy1)
|
||||
/* If y1 eytends past cy1, move it back. */
|
||||
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)
|
||||
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
|
||||
gravity and X anchor flipped. */
|
||||
new = *positioner;
|
||||
|
@ -464,7 +533,7 @@ TryFlipX (Positioner *positioner, int x, int width, int cx, int cwidth,
|
|||
break;
|
||||
|
||||
case AnchorGravityBottomRight:
|
||||
new.gravity = AnchorGravityBottomRight;
|
||||
new.gravity = AnchorGravityBottomLeft;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -491,7 +560,7 @@ TryFlipX (Positioner *positioner, int x, int width, int cx, int cwidth,
|
|||
break;
|
||||
|
||||
case AnchorGravityBottomRight:
|
||||
new.anchor = AnchorGravityBottomRight;
|
||||
new.anchor = AnchorGravityBottomLeft;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -502,16 +571,27 @@ TryFlipX (Positioner *positioner, int x, int width, int cx, int cwidth,
|
|||
&& positioner->anchor == new.anchor)
|
||||
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. */
|
||||
CalculatePosition (&new, &new_x, NULL);
|
||||
|
||||
/* Scale that position. */
|
||||
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 + offset < cx
|
||||
|| new_x + offset + width - 1 > cx1)
|
||||
return x;
|
||||
{
|
||||
DebugPrint ("position (%d) is still constrained",
|
||||
new_x + offset);
|
||||
return x;
|
||||
}
|
||||
|
||||
/* Return the new X. */
|
||||
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. */
|
||||
goto finish;
|
||||
|
||||
#ifdef DEBUG_POSITIONER
|
||||
|
||||
fputs ("ApplyConstraintAdjustments: constraint adjustments are: ", stderr);
|
||||
|
||||
if (positioner->constraint_adjustment
|
||||
& XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_X)
|
||||
x = TrySlideX (positioner, x + off_x, width,
|
||||
cx, cwidth) - off_x;
|
||||
fputs ("SLIDE_X ", stderr);
|
||||
|
||||
if (positioner->constraint_adjustment
|
||||
& XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_SLIDE_Y)
|
||||
y = TrySlideY (positioner, y + off_y, height,
|
||||
cy, cheight) - off_y;
|
||||
fputs ("SLIDE_Y ", stderr);
|
||||
|
||||
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
|
||||
& XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X)
|
||||
|
@ -735,6 +837,16 @@ ApplyConstraintAdjustment (Positioner *positioner, Role *parent, int x,
|
|||
y = TryFlipY (positioner, y + off_y, height,
|
||||
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
|
||||
& XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X)
|
||||
TryResizeX (x + off_x, width, cx, cwidth,
|
||||
|
|
Loading…
Add table
Reference in a new issue