diff options
-rw-r--r-- | include/wlr/types/wlr_wl_shell.h | 9 | ||||
-rw-r--r-- | rootston/desktop.c | 21 | ||||
-rw-r--r-- | rootston/wl_shell.c | 37 |
3 files changed, 67 insertions, 0 deletions
diff --git a/include/wlr/types/wlr_wl_shell.h b/include/wlr/types/wlr_wl_shell.h index 162874e9..6133b80d 100644 --- a/include/wlr/types/wlr_wl_shell.h +++ b/include/wlr/types/wlr_wl_shell.h @@ -125,4 +125,13 @@ void wlr_wl_shell_surface_configure(struct wlr_wl_shell_surface *surface, void wlr_wl_shell_surface_popup_done(struct wlr_wl_shell_surface *surface); bool wlr_wl_shell_surface_is_transient(struct wlr_wl_shell_surface *surface); +/** + * Find a popup within this surface at the surface-local coordinates. Returns + * the popup and coordinates in the topmost surface coordinate system or NULL if + * no popup is found at that location. + */ +struct wlr_wl_shell_surface *wlr_wl_shell_surface_popup_at( + struct wlr_wl_shell_surface *surface, double sx, double sy, + double *popup_sx, double *popup_sy); + #endif diff --git a/rootston/desktop.c b/rootston/desktop.c index bef0fad4..d5cac575 100644 --- a/rootston/desktop.c +++ b/rootston/desktop.c @@ -103,6 +103,12 @@ struct roots_view *view_at(struct roots_desktop *desktop, double lx, double ly, for (int i = desktop->views->length - 1; i >= 0; --i) { struct roots_view *view = desktop->views->items[i]; + if (view->type == ROOTS_WL_SHELL_VIEW && + view->wl_shell_surface->state == + WLR_WL_SHELL_SURFACE_STATE_POPUP) { + continue; + } + double view_sx = lx - view->x; double view_sy = ly - view->y; @@ -138,6 +144,21 @@ struct roots_view *view_at(struct roots_desktop *desktop, double lx, double ly, } } + if (view->type == ROOTS_WL_SHELL_VIEW) { + // TODO: test if this works with rotated views + double popup_sx, popup_sy; + struct wlr_wl_shell_surface *popup = + wlr_wl_shell_surface_popup_at(view->wl_shell_surface, + view_sx, view_sy, &popup_sx, &popup_sy); + + if (popup) { + *sx = view_sx - popup_sx; + *sy = view_sy - popup_sy; + *surface = popup->surface; + return view; + } + } + double sub_x, sub_y; struct wlr_subsurface *subsurface = wlr_surface_subsurface_at(view->wlr_surface, diff --git a/rootston/wl_shell.c b/rootston/wl_shell.c index 34f53c7a..a629575b 100644 --- a/rootston/wl_shell.c +++ b/rootston/wl_shell.c @@ -138,3 +138,40 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) { roots_surface->view = view; list_add(desktop->views, view); } + +struct wlr_wl_shell_surface *wlr_wl_shell_surface_popup_at( + struct wlr_wl_shell_surface *surface, double sx, double sy, + double *popup_sx, double *popup_sy) { + struct wlr_wl_shell_surface *popup; + wl_list_for_each(popup, &surface->children, child_link) { + double _popup_sx = popup->transient_state->x; + double _popup_sy = popup->transient_state->y; + int popup_width = + popup->surface->current->buffer_width; + int popup_height = + popup->surface->current->buffer_height; + + struct wlr_wl_shell_surface *_popup = + wlr_wl_shell_surface_popup_at(popup, + popup->transient_state->x, + popup->transient_state->y, + popup_sx, popup_sy); + if (_popup) { + *popup_sx = sx + _popup_sx; + *popup_sy = sy + _popup_sy; + return _popup; + } + + if ((sx > _popup_sx && sx < _popup_sx + popup_width) && + (sy > _popup_sy && sy < _popup_sy + popup_height)) { + if (pixman_region32_contains_point(&popup->surface->current->input, + sx - _popup_sx, sy - _popup_sy, NULL)) { + *popup_sx = _popup_sx; + *popup_sy = _popup_sy; + return popup; + } + } + } + + return NULL; +} |