diff --git a/desktop/output.c b/desktop/output.c index 06054a5..c5aa3cc 100644 --- a/desktop/output.c +++ b/desktop/output.c @@ -31,6 +31,28 @@ #include "util.h" #include "view.h" +void +cage_output_surface_at(struct cg_output *output, double lx, double ly, struct wlr_surface **surface, double *sx, + double *sy) +{ + struct cg_view *view; + wl_list_for_each (view, &output->views, link) { + // TODO: this only works because all views are currently maximized on a single output. + // When multi-monitor setups and dialogs are added, this will need extending. + double view_sx = lx; + double view_sy = ly; + + double _sx, _sy; + struct wlr_surface *_surface = cage_view_wlr_surface_at(view, view_sx, view_sy, &_sx, &_sy); + if (_surface != NULL) { + *sx = _sx; + *sy = _sy; + *surface = _surface; + break; + } + } +} + void cage_output_damage_whole(struct cg_output *output) { diff --git a/desktop/output.h b/desktop/output.h index fa7701a..7043fb7 100644 --- a/desktop/output.h +++ b/desktop/output.h @@ -25,6 +25,11 @@ struct cg_output { struct wl_list link; // cg_server::outputs }; +/** + * Iterates over all the views on an output and attempts to find the surface under the cursor. + */ +void cage_output_surface_at(struct cg_output *output, double lx, double ly, struct wlr_surface **surface, double *sx, + double *sy); void cage_output_damage_whole(struct cg_output *output); void cage_output_damage_region(struct cg_output *output, struct wlr_box *region); void cage_output_damage_surface(struct cg_output *output, struct wlr_surface *surface, int sx, int sy); diff --git a/desktop/view.c b/desktop/view.c index 8686f88..b580e4c 100644 --- a/desktop/view.c +++ b/desktop/view.c @@ -112,6 +112,17 @@ cage_view_damage_part(struct cg_view *view) cage_view_for_each_surface(view, damage_surface_iterator, NULL); } +struct wlr_surface * +cage_view_wlr_surface_at(struct cg_view *view, double sx, double sy, double *sub_x, double *sub_y) +{ + assert(view != NULL); + assert(sub_x != NULL); + assert(sub_y != NULL); + assert(view->impl->wlr_surface_at != NULL); + + return view->impl->wlr_surface_at(view, sx, sy, sub_x, sub_y); +} + void cage_view_activate(struct cg_view *view, bool activate) { diff --git a/desktop/view.h b/desktop/view.h index c628a40..207fc48 100644 --- a/desktop/view.h +++ b/desktop/view.h @@ -74,6 +74,15 @@ struct cg_view_impl { * Activate a view. */ void (*activate)(struct cg_view *view, bool activate); + + /** + * XDG toplevels may have nested surfaces, such as popup windows + * for context menus or tooltips. This tests if any of those are + * underneath the coordinates lx and ly (in output Layout Coordinates). + * If so, it sets the surface pointer to that wlr_surface and the + * sx and sy coordinates to the coordinates relative to that + * surface's top-left corner. */ + struct wlr_surface *(*wlr_surface_at)(struct cg_view *view, double sx, double sy, double *sub_x, double *sub_y); }; bool cage_view_is_primary(struct cg_view *view); @@ -82,6 +91,7 @@ void cage_view_for_each_surface(struct cg_view *view, wlr_surface_iterator_func_ char *cage_view_get_title(struct cg_view *view); void cage_view_damage_whole(struct cg_view *view); void cage_view_damage_part(struct cg_view *view); +struct wlr_surface *cage_view_wlr_surface_at(struct cg_view *view, double sx, double sy, double *sub_x, double *sub_y); void cage_view_activate(struct cg_view *view, bool activate); bool cage_view_is_mapped(struct cg_view *view); void cage_view_unmap(struct cg_view *view); diff --git a/desktop/xdg_shell.c b/desktop/xdg_shell.c index 41e19d1..e4b5732 100644 --- a/desktop/xdg_shell.c +++ b/desktop/xdg_shell.c @@ -66,6 +66,13 @@ get_title(struct cg_view *view) return xdg_shell_view->xdg_surface->toplevel->title; } +static struct wlr_surface * +wlr_surface_at(struct cg_view *view, double sx, double sy, double *sub_x, double *sub_y) +{ + struct cg_xdg_shell_view *xdg_shell_view = xdg_shell_view_from_view(view); + return wlr_xdg_surface_surface_at(xdg_shell_view->xdg_surface, sx, sy, sub_x, sub_y); +} + static void activate(struct cg_view *view, bool activate) { @@ -153,6 +160,7 @@ static const struct cg_view_impl xdg_shell_view_impl = { .is_primary = is_primary, .get_title = get_title, .activate = activate, + .wlr_surface_at = wlr_surface_at, }; void