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:
hujianwei 2022-11-02 08:00:28 +00:00
parent a7a17e02fa
commit 6ad5901c97

View file

@ -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,