aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/wlr/types/wlr_surface.h7
-rw-r--r--include/wlr/types/wlr_xdg_shell_v6.h8
-rw-r--r--rootston/desktop.c76
-rw-r--r--types/wlr_surface.c32
-rw-r--r--types/wlr_xdg_shell_v6.c41
5 files changed, 92 insertions, 72 deletions
diff --git a/include/wlr/types/wlr_surface.h b/include/wlr/types/wlr_surface.h
index 9f898b38..03376788 100644
--- a/include/wlr/types/wlr_surface.h
+++ b/include/wlr/types/wlr_surface.h
@@ -122,4 +122,11 @@ void wlr_surface_make_subsurface(struct wlr_surface *surface,
*/
struct wlr_surface *wlr_surface_get_main_surface(struct wlr_surface *surface);
+/**
+ * Find a subsurface within this surface at the surface-local coordinates.
+ * Returns the surface and coordinates in the topmost surface coordinate system
+ * or NULL if no subsurface is found at that location.
+ */
+struct wlr_subsurface *wlr_surface_subsurface_at(struct wlr_surface *surface,
+ double sx, double sy, double *sub_x, double *sub_y);
#endif
diff --git a/include/wlr/types/wlr_xdg_shell_v6.h b/include/wlr/types/wlr_xdg_shell_v6.h
index 00295ec1..48da6604 100644
--- a/include/wlr/types/wlr_xdg_shell_v6.h
+++ b/include/wlr/types/wlr_xdg_shell_v6.h
@@ -206,4 +206,12 @@ void wlr_xdg_toplevel_v6_set_resizing(struct wlr_xdg_surface_v6 *surface,
*/
void wlr_xdg_toplevel_v6_send_close(struct wlr_xdg_surface_v6 *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_xdg_surface_v6 *wlr_xdg_surface_v6_popup_at(
+ struct wlr_xdg_surface_v6 *surface, double sx, double sy,
+ double *popup_sx, double *popup_sy);
#endif
diff --git a/rootston/desktop.c b/rootston/desktop.c
index 001cefe0..bef0fad4 100644
--- a/rootston/desktop.c
+++ b/rootston/desktop.c
@@ -98,75 +98,6 @@ bool view_initialize(struct roots_view *view) {
return centered;
}
-static struct wlr_subsurface *subsurface_at(struct wlr_surface *surface,
- double sx, double sy, double *sub_x, double *sub_y) {
- struct wlr_subsurface *subsurface;
- wl_list_for_each(subsurface, &surface->subsurface_list, parent_link) {
- double _sub_x = subsurface->surface->current->subsurface_position.x;
- double _sub_y = subsurface->surface->current->subsurface_position.y;
- struct wlr_subsurface *sub =
- subsurface_at(subsurface->surface, _sub_x + sx, _sub_y + sy,
- sub_x, sub_y);
- if (sub) {
- // TODO: This won't work for nested subsurfaces. Convert sub_x and
- // sub_y to the parent coordinate system
- return sub;
- }
-
- int sub_width = subsurface->surface->current->buffer_width;
- int sub_height = subsurface->surface->current->buffer_height;
- if ((sx > _sub_x && sx < _sub_x + sub_width) &&
- (sy > _sub_y && sy < _sub_y + sub_height)) {
- if (pixman_region32_contains_point(
- &subsurface->surface->current->input,
- sx - _sub_x, sy - _sub_y, NULL)) {
- *sub_x = _sub_x;
- *sub_y = _sub_y;
- return subsurface;
- }
- }
- }
-
- return NULL;
-}
-
-static struct wlr_xdg_surface_v6 *xdg_v6_popup_at(
- struct wlr_xdg_surface_v6 *surface, double sx, double sy,
- double *popup_sx, double *popup_sy) {
- // XXX: I think this is so complicated because we're mixing geometry
- // coordinates with surface coordinates. Input handling should only deal
- // with surface coordinates.
- struct wlr_xdg_surface_v6 *popup;
- wl_list_for_each(popup, &surface->popups, popup_link) {
- double _popup_sx = surface->geometry->x + popup->popup_state->geometry.x;
- double _popup_sy = surface->geometry->y + popup->popup_state->geometry.y;
- int popup_width = popup->popup_state->geometry.width;
- int popup_height = popup->popup_state->geometry.height;
-
- struct wlr_xdg_surface_v6 *_popup =
- xdg_v6_popup_at(popup, sx - _popup_sx + popup->geometry->x,
- sy - _popup_sy + popup->geometry->y, popup_sx, popup_sy);
- if (_popup) {
- *popup_sx = *popup_sx + _popup_sx - popup->geometry->x;
- *popup_sy = *popup_sy + _popup_sy - popup->geometry->y;
- 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 + popup->geometry->x,
- sy - _popup_sy + popup->geometry->y, NULL)) {
- *popup_sx = _popup_sx - popup->geometry->x;
- *popup_sy = _popup_sy - popup->geometry->y;
- return popup;
- }
- }
- }
-
- return NULL;
-}
-
struct roots_view *view_at(struct roots_desktop *desktop, double lx, double ly,
struct wlr_surface **surface, double *sx, double *sy) {
for (int i = desktop->views->length - 1; i >= 0; --i) {
@@ -196,8 +127,8 @@ struct roots_view *view_at(struct roots_desktop *desktop, double lx, double ly,
// TODO: test if this works with rotated views
double popup_sx, popup_sy;
struct wlr_xdg_surface_v6 *popup =
- xdg_v6_popup_at(view->xdg_surface_v6, view_sx, view_sy,
- &popup_sx, &popup_sy);
+ wlr_xdg_surface_v6_popup_at(view->xdg_surface_v6,
+ view_sx, view_sy, &popup_sx, &popup_sy);
if (popup) {
*sx = view_sx - popup_sx;
@@ -209,7 +140,8 @@ struct roots_view *view_at(struct roots_desktop *desktop, double lx, double ly,
double sub_x, sub_y;
struct wlr_subsurface *subsurface =
- subsurface_at(view->wlr_surface, view_sx, view_sy, &sub_x, &sub_y);
+ wlr_surface_subsurface_at(view->wlr_surface,
+ view_sx, view_sy, &sub_x, &sub_y);
if (subsurface) {
*sx = view_sx - sub_x;
*sy = view_sy - sub_y;
diff --git a/types/wlr_surface.c b/types/wlr_surface.c
index b4f7b30f..71a09bb5 100644
--- a/types/wlr_surface.c
+++ b/types/wlr_surface.c
@@ -844,3 +844,35 @@ struct wlr_surface *wlr_surface_get_main_surface(struct wlr_surface *surface) {
return surface;
}
+
+struct wlr_subsurface *wlr_surface_subsurface_at(struct wlr_surface *surface,
+ double sx, double sy, double *sub_x, double *sub_y) {
+ struct wlr_subsurface *subsurface;
+ wl_list_for_each(subsurface, &surface->subsurface_list, parent_link) {
+ double _sub_x = subsurface->surface->current->subsurface_position.x;
+ double _sub_y = subsurface->surface->current->subsurface_position.y;
+ struct wlr_subsurface *sub =
+ wlr_surface_subsurface_at(subsurface->surface, _sub_x + sx,
+ _sub_y + sy, sub_x, sub_y);
+ if (sub) {
+ // TODO: This won't work for nested subsurfaces. Convert sub_x and
+ // sub_y to the parent coordinate system
+ return sub;
+ }
+
+ int sub_width = subsurface->surface->current->buffer_width;
+ int sub_height = subsurface->surface->current->buffer_height;
+ if ((sx > _sub_x && sx < _sub_x + sub_width) &&
+ (sy > _sub_y && sy < _sub_y + sub_height)) {
+ if (pixman_region32_contains_point(
+ &subsurface->surface->current->input,
+ sx - _sub_x, sy - _sub_y, NULL)) {
+ *sub_x = _sub_x;
+ *sub_y = _sub_y;
+ return subsurface;
+ }
+ }
+ }
+
+ return NULL;
+}
diff --git a/types/wlr_xdg_shell_v6.c b/types/wlr_xdg_shell_v6.c
index 5f2554f8..a16d3319 100644
--- a/types/wlr_xdg_shell_v6.c
+++ b/types/wlr_xdg_shell_v6.c
@@ -1301,3 +1301,44 @@ void wlr_xdg_toplevel_v6_send_close(struct wlr_xdg_surface_v6 *surface) {
assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL);
zxdg_toplevel_v6_send_close(surface->toplevel_state->resource);
}
+
+struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6_popup_at(
+ struct wlr_xdg_surface_v6 *surface, double sx, double sy,
+ double *popup_sx, double *popup_sy) {
+ // XXX: I think this is so complicated because we're mixing geometry
+ // coordinates with surface coordinates. Input handling should only deal
+ // with surface coordinates.
+ struct wlr_xdg_surface_v6 *popup;
+ wl_list_for_each(popup, &surface->popups, popup_link) {
+ double _popup_sx =
+ surface->geometry->x + popup->popup_state->geometry.x;
+ double _popup_sy =
+ surface->geometry->y + popup->popup_state->geometry.y;
+ int popup_width = popup->popup_state->geometry.width;
+ int popup_height = popup->popup_state->geometry.height;
+
+ struct wlr_xdg_surface_v6 *_popup =
+ wlr_xdg_surface_v6_popup_at(popup,
+ sx - _popup_sx + popup->geometry->x,
+ sy - _popup_sy + popup->geometry->y,
+ popup_sx, popup_sy);
+ if (_popup) {
+ *popup_sx = *popup_sx + _popup_sx - popup->geometry->x;
+ *popup_sy = *popup_sy + _popup_sy - popup->geometry->y;
+ 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 + popup->geometry->x,
+ sy - _popup_sy + popup->geometry->y, NULL)) {
+ *popup_sx = _popup_sx - popup->geometry->x;
+ *popup_sy = _popup_sy - popup->geometry->y;
+ return popup;
+ }
+ }
+ }
+
+ return NULL;
+}