mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-12-23 02:19:49 +01:00
Merge pull request #972 from emersion/fix-xdg-shell-popups
Fix xdg-shell stable popups
This commit is contained in:
commit
658a00602b
2 changed files with 107 additions and 54 deletions
|
@ -422,6 +422,37 @@ static void xdg_shell_handle_create_positioner(struct wl_client *wl_client,
|
|||
positioner, xdg_positioner_destroy);
|
||||
}
|
||||
|
||||
static bool positioner_anchor_has_edge(enum xdg_positioner_anchor anchor,
|
||||
enum xdg_positioner_anchor edge) {
|
||||
switch (edge) {
|
||||
case XDG_POSITIONER_ANCHOR_TOP:
|
||||
return anchor == XDG_POSITIONER_ANCHOR_TOP ||
|
||||
anchor == XDG_POSITIONER_ANCHOR_TOP_LEFT ||
|
||||
anchor == XDG_POSITIONER_ANCHOR_TOP_RIGHT;
|
||||
case XDG_POSITIONER_ANCHOR_BOTTOM:
|
||||
return anchor == XDG_POSITIONER_ANCHOR_BOTTOM ||
|
||||
anchor == XDG_POSITIONER_ANCHOR_BOTTOM_LEFT ||
|
||||
anchor == XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT;
|
||||
case XDG_POSITIONER_ANCHOR_LEFT:
|
||||
return anchor == XDG_POSITIONER_ANCHOR_LEFT ||
|
||||
anchor == XDG_POSITIONER_ANCHOR_TOP_LEFT ||
|
||||
anchor == XDG_POSITIONER_ANCHOR_BOTTOM_LEFT;
|
||||
case XDG_POSITIONER_ANCHOR_RIGHT:
|
||||
return anchor == XDG_POSITIONER_ANCHOR_RIGHT ||
|
||||
anchor == XDG_POSITIONER_ANCHOR_TOP_RIGHT ||
|
||||
anchor == XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT;
|
||||
default:
|
||||
assert(false); // not reached
|
||||
}
|
||||
}
|
||||
|
||||
static bool positioner_gravity_has_edge(enum xdg_positioner_gravity gravity,
|
||||
enum xdg_positioner_gravity edge) {
|
||||
// gravity and edge enums are the same
|
||||
return positioner_anchor_has_edge((enum xdg_positioner_anchor)gravity,
|
||||
(enum xdg_positioner_anchor)edge);
|
||||
}
|
||||
|
||||
struct wlr_box wlr_xdg_positioner_get_geometry(
|
||||
struct wlr_xdg_positioner *positioner) {
|
||||
struct wlr_box geometry = {
|
||||
|
@ -431,9 +462,11 @@ struct wlr_box wlr_xdg_positioner_get_geometry(
|
|||
.height = positioner->size.height,
|
||||
};
|
||||
|
||||
if (positioner->anchor & XDG_POSITIONER_ANCHOR_TOP) {
|
||||
if (positioner_anchor_has_edge(positioner->anchor,
|
||||
XDG_POSITIONER_ANCHOR_TOP)) {
|
||||
geometry.y += positioner->anchor_rect.y;
|
||||
} else if (positioner->anchor & XDG_POSITIONER_ANCHOR_BOTTOM) {
|
||||
} else if (positioner_anchor_has_edge(positioner->anchor,
|
||||
XDG_POSITIONER_ANCHOR_BOTTOM)) {
|
||||
geometry.y +=
|
||||
positioner->anchor_rect.y + positioner->anchor_rect.height;
|
||||
} else {
|
||||
|
@ -441,26 +474,32 @@ struct wlr_box wlr_xdg_positioner_get_geometry(
|
|||
positioner->anchor_rect.y + positioner->anchor_rect.height / 2;
|
||||
}
|
||||
|
||||
if (positioner->anchor & XDG_POSITIONER_ANCHOR_LEFT) {
|
||||
if (positioner_anchor_has_edge(positioner->anchor,
|
||||
XDG_POSITIONER_ANCHOR_LEFT)) {
|
||||
geometry.x += positioner->anchor_rect.x;
|
||||
} else if (positioner->anchor & XDG_POSITIONER_ANCHOR_RIGHT) {
|
||||
} else if (positioner_anchor_has_edge(positioner->anchor,
|
||||
XDG_POSITIONER_ANCHOR_RIGHT)) {
|
||||
geometry.x += positioner->anchor_rect.x + positioner->anchor_rect.width;
|
||||
} else {
|
||||
geometry.x +=
|
||||
positioner->anchor_rect.x + positioner->anchor_rect.width / 2;
|
||||
}
|
||||
|
||||
if (positioner->gravity & XDG_POSITIONER_GRAVITY_TOP) {
|
||||
if (positioner_gravity_has_edge(positioner->gravity,
|
||||
XDG_POSITIONER_GRAVITY_TOP)) {
|
||||
geometry.y -= geometry.height;
|
||||
} else if (positioner->gravity & XDG_POSITIONER_GRAVITY_BOTTOM) {
|
||||
} else if (positioner_gravity_has_edge(positioner->gravity,
|
||||
XDG_POSITIONER_GRAVITY_BOTTOM)) {
|
||||
geometry.y = geometry.y;
|
||||
} else {
|
||||
geometry.y -= geometry.height / 2;
|
||||
}
|
||||
|
||||
if (positioner->gravity & XDG_POSITIONER_GRAVITY_LEFT) {
|
||||
if (positioner_gravity_has_edge(positioner->gravity,
|
||||
XDG_POSITIONER_GRAVITY_LEFT)) {
|
||||
geometry.x -= geometry.width;
|
||||
} else if (positioner->gravity & XDG_POSITIONER_GRAVITY_RIGHT) {
|
||||
} else if (positioner_gravity_has_edge(positioner->gravity,
|
||||
XDG_POSITIONER_GRAVITY_RIGHT)) {
|
||||
geometry.x = geometry.x;
|
||||
} else {
|
||||
geometry.x -= geometry.width / 2;
|
||||
|
@ -1632,20 +1671,16 @@ void wlr_xdg_popup_get_anchor_point(struct wlr_xdg_popup *popup,
|
|||
} else if (anchor == XDG_POSITIONER_ANCHOR_RIGHT) {
|
||||
sx = rect.x + rect.width;
|
||||
sy = (rect.y + rect.height) / 2;
|
||||
} else if (anchor == (XDG_POSITIONER_ANCHOR_TOP |
|
||||
XDG_POSITIONER_ANCHOR_LEFT)) {
|
||||
} else if (anchor == XDG_POSITIONER_ANCHOR_TOP_LEFT) {
|
||||
sx = rect.x;
|
||||
sy = rect.y;
|
||||
} else if (anchor == (XDG_POSITIONER_ANCHOR_TOP |
|
||||
XDG_POSITIONER_ANCHOR_RIGHT)) {
|
||||
} else if (anchor == XDG_POSITIONER_ANCHOR_TOP_RIGHT) {
|
||||
sx = rect.x + rect.width;
|
||||
sy = rect.y;
|
||||
} else if (anchor == (XDG_POSITIONER_ANCHOR_BOTTOM |
|
||||
XDG_POSITIONER_ANCHOR_LEFT)) {
|
||||
} else if (anchor == XDG_POSITIONER_ANCHOR_BOTTOM_LEFT) {
|
||||
sx = rect.x;
|
||||
sy = rect.y + rect.height;
|
||||
} else if (anchor == (XDG_POSITIONER_ANCHOR_BOTTOM |
|
||||
XDG_POSITIONER_ANCHOR_RIGHT)) {
|
||||
} else if (anchor == XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT) {
|
||||
sx = rect.x + rect.width;
|
||||
sy = rect.y + rect.height;
|
||||
}
|
||||
|
@ -1656,20 +1691,17 @@ void wlr_xdg_popup_get_anchor_point(struct wlr_xdg_popup *popup,
|
|||
|
||||
void wlr_xdg_popup_get_toplevel_coords(struct wlr_xdg_popup *popup,
|
||||
int popup_sx, int popup_sy, int *toplevel_sx, int *toplevel_sy) {
|
||||
assert(strcmp(popup->parent->role, wlr_desktop_xdg_toplevel_role) == 0
|
||||
|| strcmp(popup->parent->role, wlr_desktop_xdg_popup_role) == 0);
|
||||
struct wlr_xdg_surface *parent = popup->parent->role_data;
|
||||
struct wlr_xdg_surface *parent =
|
||||
wlr_xdg_surface_from_wlr_surface(popup->parent);
|
||||
while (parent != NULL && parent->role == WLR_XDG_SURFACE_ROLE_POPUP) {
|
||||
popup_sx += parent->popup->geometry.x;
|
||||
popup_sy += parent->popup->geometry.y;
|
||||
parent = parent->popup->parent->role_data;
|
||||
parent = wlr_xdg_surface_from_wlr_surface(parent->popup->parent);
|
||||
}
|
||||
|
||||
assert(parent);
|
||||
|
||||
*toplevel_sx = popup_sx + parent->geometry.x;
|
||||
*toplevel_sy = popup_sy + parent->geometry.y;
|
||||
|
||||
}
|
||||
|
||||
static void xdg_popup_box_constraints(struct wlr_xdg_popup *popup,
|
||||
|
@ -1837,43 +1869,66 @@ void wlr_xdg_popup_unconstrain_from_box(struct wlr_xdg_popup *popup,
|
|||
}
|
||||
}
|
||||
|
||||
void wlr_positioner_invert_x(struct wlr_xdg_positioner *positioner) {
|
||||
if (positioner->anchor & XDG_POSITIONER_ANCHOR_LEFT) {
|
||||
positioner->anchor &= ~XDG_POSITIONER_ANCHOR_LEFT;
|
||||
positioner->anchor |= XDG_POSITIONER_ANCHOR_RIGHT;
|
||||
} else if (positioner->anchor & XDG_POSITIONER_ANCHOR_RIGHT) {
|
||||
positioner->anchor &= ~XDG_POSITIONER_ANCHOR_RIGHT;
|
||||
positioner->anchor |= XDG_POSITIONER_ANCHOR_LEFT;
|
||||
}
|
||||
|
||||
if (positioner->gravity & XDG_POSITIONER_GRAVITY_RIGHT) {
|
||||
positioner->gravity &= ~XDG_POSITIONER_GRAVITY_RIGHT;
|
||||
positioner->gravity |= XDG_POSITIONER_GRAVITY_LEFT;
|
||||
} else if (positioner->gravity & XDG_POSITIONER_GRAVITY_LEFT) {
|
||||
positioner->gravity &= ~XDG_POSITIONER_GRAVITY_LEFT;
|
||||
positioner->gravity |= XDG_POSITIONER_GRAVITY_RIGHT;
|
||||
static enum xdg_positioner_anchor positioner_anchor_invert_x(
|
||||
enum xdg_positioner_anchor anchor) {
|
||||
switch (anchor) {
|
||||
case XDG_POSITIONER_ANCHOR_LEFT:
|
||||
return XDG_POSITIONER_ANCHOR_RIGHT;
|
||||
case XDG_POSITIONER_ANCHOR_RIGHT:
|
||||
return XDG_POSITIONER_ANCHOR_LEFT;
|
||||
case XDG_POSITIONER_ANCHOR_TOP_LEFT:
|
||||
return XDG_POSITIONER_ANCHOR_TOP_RIGHT;
|
||||
case XDG_POSITIONER_ANCHOR_BOTTOM_LEFT:
|
||||
return XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT;
|
||||
case XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT:
|
||||
return XDG_POSITIONER_ANCHOR_BOTTOM_LEFT;
|
||||
default:
|
||||
return anchor;
|
||||
}
|
||||
}
|
||||
|
||||
void wlr_positioner_invert_y(
|
||||
struct wlr_xdg_positioner *positioner) {
|
||||
if (positioner->anchor & XDG_POSITIONER_ANCHOR_TOP) {
|
||||
positioner->anchor &= ~XDG_POSITIONER_ANCHOR_TOP;
|
||||
positioner->anchor |= XDG_POSITIONER_ANCHOR_BOTTOM;
|
||||
} else if (positioner->anchor & XDG_POSITIONER_ANCHOR_BOTTOM) {
|
||||
positioner->anchor &= ~XDG_POSITIONER_ANCHOR_BOTTOM;
|
||||
positioner->anchor |= XDG_POSITIONER_ANCHOR_TOP;
|
||||
}
|
||||
static enum xdg_positioner_gravity positioner_gravity_invert_x(
|
||||
enum xdg_positioner_gravity gravity) {
|
||||
// gravity and edge enums are the same
|
||||
return (enum xdg_positioner_gravity)positioner_anchor_invert_x(
|
||||
(enum xdg_positioner_anchor)gravity);
|
||||
}
|
||||
|
||||
if (positioner->gravity & XDG_POSITIONER_GRAVITY_TOP) {
|
||||
positioner->gravity &= ~XDG_POSITIONER_GRAVITY_TOP;
|
||||
positioner->gravity |= XDG_POSITIONER_GRAVITY_BOTTOM;
|
||||
} else if (positioner->gravity & XDG_POSITIONER_GRAVITY_BOTTOM) {
|
||||
positioner->gravity &= ~XDG_POSITIONER_GRAVITY_BOTTOM;
|
||||
positioner->gravity |= XDG_POSITIONER_GRAVITY_TOP;
|
||||
static enum xdg_positioner_anchor positioner_anchor_invert_y(
|
||||
enum xdg_positioner_anchor anchor) {
|
||||
switch (anchor) {
|
||||
case XDG_POSITIONER_ANCHOR_TOP:
|
||||
return XDG_POSITIONER_ANCHOR_BOTTOM;
|
||||
case XDG_POSITIONER_ANCHOR_BOTTOM:
|
||||
return XDG_POSITIONER_ANCHOR_TOP;
|
||||
case XDG_POSITIONER_ANCHOR_TOP_LEFT:
|
||||
return XDG_POSITIONER_ANCHOR_BOTTOM_LEFT;
|
||||
case XDG_POSITIONER_ANCHOR_BOTTOM_LEFT:
|
||||
return XDG_POSITIONER_ANCHOR_TOP_LEFT;
|
||||
case XDG_POSITIONER_ANCHOR_BOTTOM_RIGHT:
|
||||
return XDG_POSITIONER_ANCHOR_TOP_RIGHT;
|
||||
default:
|
||||
return anchor;
|
||||
}
|
||||
}
|
||||
|
||||
static enum xdg_positioner_gravity positioner_gravity_invert_y(
|
||||
enum xdg_positioner_gravity gravity) {
|
||||
// gravity and edge enums are the same
|
||||
return (enum xdg_positioner_gravity)positioner_anchor_invert_y(
|
||||
(enum xdg_positioner_anchor)gravity);
|
||||
}
|
||||
|
||||
void wlr_positioner_invert_x(struct wlr_xdg_positioner *positioner) {
|
||||
positioner->anchor = positioner_anchor_invert_x(positioner->anchor);
|
||||
positioner->gravity = positioner_gravity_invert_x(positioner->gravity);
|
||||
}
|
||||
|
||||
void wlr_positioner_invert_y(struct wlr_xdg_positioner *positioner) {
|
||||
positioner->anchor = positioner_anchor_invert_y(positioner->anchor);
|
||||
positioner->gravity = positioner_gravity_invert_y(positioner->gravity);
|
||||
}
|
||||
|
||||
struct xdg_surface_iterator_data {
|
||||
wlr_surface_iterator_func_t user_iterator;
|
||||
void *user_data;
|
||||
|
|
|
@ -1673,12 +1673,10 @@ void wlr_xdg_popup_v6_get_toplevel_coords(struct wlr_xdg_popup_v6 *popup,
|
|||
popup_sy += parent->popup->geometry.y;
|
||||
parent = parent->popup->parent;
|
||||
}
|
||||
|
||||
assert(parent);
|
||||
|
||||
*toplevel_sx = popup_sx + parent->geometry.x;
|
||||
*toplevel_sy = popup_sy + parent->geometry.y;
|
||||
|
||||
}
|
||||
|
||||
static void xdg_popup_v6_box_constraints(struct wlr_xdg_popup_v6 *popup,
|
||||
|
|
Loading…
Reference in a new issue