From d784770ca9340c39aa2e1a27dc7b9a47fd3c462b Mon Sep 17 00:00:00 2001 From: IoIxD Date: Sun, 4 Jan 2026 13:01:44 -0700 Subject: [PATCH] wayland: popup positioning --- include/Mw/LowLevel/Wayland.h | 2 +- src/backend/wayland.c | 27 ++++++++++++++++++--------- src/widget/submenu.c | 1 + 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index 1e8e1e1..cd96424 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -74,7 +74,7 @@ struct _MwLLWaylandPopup { struct xdg_positioner* xdg_positioner; struct xdg_surface_listener xdg_surface_listener; struct xdg_wm_base* xdg_wm_base; - MwLL parent; + MwLL topmost_parent; }; /* Shared set of anything needed for a shm buffer. */ diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 5d5dcda..f6532fa 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -1263,12 +1263,14 @@ struct xdg_popup_listener popup_listener = { }; /* Popup setup function */ -static void setup_popup(MwLL r) { +static void setup_popup(MwLL r, int x, int y) { int i; struct xdg_surface* xdg_surface; MwLL topmost_parent = r->wayland.parent; r->wayland.type = MWLL_WAYLAND_POPUP; + r->wayland.x = x; + r->wayland.y = y; while(topmost_parent->wayland.type != MWLL_WAYLAND_TOPLEVEL) { topmost_parent = topmost_parent->wayland.parent; @@ -1276,6 +1278,7 @@ static void setup_popup(MwLL r) { r->wayland.popup = malloc(sizeof(struct _MwLLWaylandPopup)); memset(r->wayland.popup, 0, sizeof(struct _MwLLWaylandPopup)); + r->wayland.popup->topmost_parent = topmost_parent; setup_callbacks(&r->wayland); @@ -1288,14 +1291,16 @@ static void setup_popup(MwLL r) { return; } - r->wayland.popup->xdg_wm_base = WAYLAND_GET_INTERFACE(r->wayland, xdg_wm_base)->context; + r->wayland.popup->xdg_wm_base = WAYLAND_GET_INTERFACE(topmost_parent->wayland, xdg_wm_base)->context; r->wayland.popup->xdg_positioner = xdg_wm_base_create_positioner(r->wayland.popup->xdg_wm_base); xdg_positioner_set_size(r->wayland.popup->xdg_positioner, r->wayland.ww, r->wayland.wh); + xdg_positioner_set_anchor(r->wayland.popup->xdg_positioner, XDG_POSITIONER_ANCHOR_NONE); xdg_positioner_set_anchor_rect( - r->wayland.popup->xdg_positioner, 0, 0, - 1, 1); + r->wayland.popup->xdg_positioner, 0, 0, 1, 1); + printf("%d, %d\n", x, y); + xdg_positioner_set_offset(r->wayland.popup->xdg_positioner, x, y); xdg_surface = topmost_parent->wayland.toplevel->xdg_surface; @@ -1450,13 +1455,17 @@ static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsign } static void MwLLSetXYImpl(MwLL handle, int x, int y) { + region_invalidate(handle); + handle->wayland.x = x; + handle->wayland.y = y; if(handle->wayland.type == MWLL_WAYLAND_SUBLEVEL) { - region_invalidate(handle); - handle->wayland.x = x; - handle->wayland.y = y; wl_subsurface_set_position(handle->wayland.sublevel->subsurface, x, y); - region_setup(handle); } + if(handle->wayland.type == MWLL_WAYLAND_POPUP) { + destroy_popup(handle); + setup_popup(handle, x, y); + } + region_setup(handle); MwLLDispatch(handle, draw, NULL); } @@ -1761,7 +1770,7 @@ static void MwLLDetachImpl(MwLL handle, MwPoint* point) { switch(handle->wayland.type_to_be) { case MWLL_WAYLAND_POPUP: - setup_popup(handle); + setup_popup(handle, point->x, point->y); return; default: setup_toplevel(handle, point->x, point->y); diff --git a/src/widget/submenu.c b/src/widget/submenu.c index 59673e3..54ee8ea 100644 --- a/src/widget/submenu.c +++ b/src/widget/submenu.c @@ -188,6 +188,7 @@ static void mwSubMenuAppearImpl(MwWidget handle, MwMenu menu, MwPoint* point, in MwNy, rc.height - sz.height, NULL); } + MwLLEndStateChange(handle->lowlevel); MwVaApply(handle,