diff --git a/kiwmi/desktop/popup.c b/kiwmi/desktop/popup.c index bea2fbf..64324c8 100644 --- a/kiwmi/desktop/popup.c +++ b/kiwmi/desktop/popup.c @@ -8,12 +8,15 @@ #include "desktop/popup.h" #include +#include #include #include #include +#include "desktop/desktop.h" #include "desktop/desktop_surface.h" #include "desktop/layer_shell.h" +#include "desktop/output.h" #include "desktop/view.h" struct kiwmi_desktop_surface * @@ -46,6 +49,49 @@ popup_get_desktop_surface(struct wlr_xdg_popup *popup) return NULL; } +static void +popup_unconstrain( + struct wlr_xdg_popup *popup, + struct kiwmi_desktop_surface *desktop_surface) +{ + struct kiwmi_output *output = desktop_surface_get_output(desktop_surface); + if (!output) { + return; + } + + struct wlr_output *wlr_output = output->wlr_output; + + int lx, ly; + desktop_surface_get_pos(desktop_surface, &lx, &ly); + + if (desktop_surface->type == KIWMI_DESKTOP_SURFACE_VIEW) { + // wlroots expects surface-local, not view-local coords + struct kiwmi_view *view = + wl_container_of(desktop_surface, view, desktop_surface); + lx -= view->geom.x; + ly -= view->geom.y; + } + + double ox = lx; + double oy = ly; + wlr_output_layout_output_coords( + output->desktop->output_layout, wlr_output, &ox, &oy); + + int output_width; + int output_height; + wlr_output_effective_resolution(wlr_output, &output_width, &output_height); + + // Relative to the desktop_surface + struct wlr_box output_box = { + .x = -ox, + .y = -oy, + .width = output_width, + .height = output_height, + }; + + wlr_xdg_popup_unconstrain_from_box(popup, &output_box); +} + void popup_attach( struct wlr_xdg_popup *popup, @@ -61,6 +107,8 @@ popup_attach( } } + popup_unconstrain(popup, desktop_surface); + struct wlr_scene_node *node = wlr_scene_xdg_surface_create(&parent_tree->node, popup->base); if (!node) { diff --git a/kiwmi/desktop/xdg_shell.c b/kiwmi/desktop/xdg_shell.c index eb195cb..0901701 100644 --- a/kiwmi/desktop/xdg_shell.c +++ b/kiwmi/desktop/xdg_shell.c @@ -48,54 +48,6 @@ popup_extension_destroy_notify(struct wl_listener *listener, void *UNUSED(data)) view_child_destroy(popup); } -static void -popup_unconstrain(struct kiwmi_view_child *popup) -{ - if (popup->type != KIWMI_VIEW_CHILD_XDG_POPUP) { - wlr_log(WLR_ERROR, "Expected an xdg_popup kiwmi_view_child"); - return; - } - - struct kiwmi_view *view = popup->view; - - // Prefer output at view center - struct wlr_output *output = wlr_output_layout_output_at( - view->desktop->output_layout, - view->x + view->geom.width / 2, - view->y + view->geom.height / 2); - - if (!output) { - // Retry with view top-left corner (if its center is off-screen) - output = wlr_output_layout_output_at( - view->desktop->output_layout, view->x, view->y); - } - - if (!output) { - wlr_log( - WLR_ERROR, "View's output not found, popups may end up invisible"); - return; - } - - double view_ox = view->x; - double view_oy = view->y; - wlr_output_layout_output_coords( - view->desktop->output_layout, output, &view_ox, &view_oy); - - int output_width; - int output_height; - wlr_output_effective_resolution(output, &output_width, &output_height); - - // relative to the view - struct wlr_box output_box = { - .x = -view_ox, - .y = -view_oy, - .width = output_width, - .height = output_height, - }; - - wlr_xdg_popup_unconstrain_from_box(popup->wlr_xdg_popup, &output_box); -} - static void popup_reconfigure(struct kiwmi_view_child *popup) { @@ -103,15 +55,6 @@ popup_reconfigure(struct kiwmi_view_child *popup) wlr_log(WLR_ERROR, "Expected an xdg_popup view_child"); return; } - - popup_unconstrain(popup); - - struct kiwmi_view_child *subchild; - wl_list_for_each (subchild, &popup->children, link) { - if (subchild->impl && subchild->impl->reconfigure) { - subchild->impl->reconfigure(subchild); - } - } } static const struct kiwmi_view_child_impl xdg_popup_view_child_impl = { @@ -146,8 +89,6 @@ view_child_popup_create( child->extension_destroy.notify = popup_extension_destroy_notify; wl_signal_add(&wlr_popup->base->events.destroy, &child->extension_destroy); - popup_unconstrain(child); - return child; }