From f5470f33384713ce62c1628a550f3a52b16a6fe5 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 30 Mar 2018 21:03:35 -0400 Subject: [PATCH] Pass pointer events to surface layers --- sway/input/cursor.c | 78 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 66 insertions(+), 12 deletions(-) diff --git a/sway/input/cursor.c b/sway/input/cursor.c index d814e08e..b498a517 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -9,8 +9,10 @@ #include "list.h" #include "log.h" #include "sway/input/cursor.h" +#include "sway/layers.h" #include "sway/output.h" #include "sway/tree/view.h" +#include "wlr-layer-shell-unstable-v1-protocol.h" static void cursor_update_position(struct sway_cursor *cursor) { double x = cursor->cursor->x; @@ -20,9 +22,35 @@ static void cursor_update_position(struct sway_cursor *cursor) { cursor->y = y; } +static struct wlr_surface *layer_surface_at(struct sway_output *output, + struct wl_list *layer, double ox, double oy, double *sx, double *sy) { + struct sway_layer_surface *sway_layer; + wl_list_for_each_reverse(sway_layer, layer, link) { + struct wlr_surface *wlr_surface = + sway_layer->layer_surface->surface; + double _sx = ox - sway_layer->geo.x; + double _sy = oy - sway_layer->geo.y; + struct wlr_box box = { + .x = sway_layer->geo.x, + .y = sway_layer->geo.y, + .width = wlr_surface->current->width, + .height = wlr_surface->current->height, + }; + // TODO: Test popups/subsurfaces + if (wlr_box_contains_point(&box, ox, oy) && + pixman_region32_contains_point( + &wlr_surface->current->input, _sx, _sy, NULL)) { + *sx = _sx; + *sy = _sy; + return wlr_surface; + } + } + return NULL; +} + /** - * Returns the container at the cursor's position. If the container is a view, - * stores the surface at the cursor's position in `*surface`. + * Returns the container at the cursor's position. If there is a surface at that + * location, it is stored in **surface (it may not be a view). */ static struct sway_container *container_at_cursor(struct sway_cursor *cursor, struct wlr_surface **surface, double *sx, double *sy) { @@ -57,20 +85,47 @@ static struct sway_container *container_at_cursor(struct sway_cursor *cursor, return NULL; } struct sway_output *output = wlr_output->data; + double ox = cursor->x, oy = cursor->y; + wlr_output_layout_output_coords(output_layout, wlr_output, &ox, &oy); // find the focused workspace on the output for this seat - struct sway_container *workspace_cont = + struct sway_container *ws = sway_seat_get_focus_inactive(cursor->seat, output->swayc); - if (workspace_cont != NULL && workspace_cont->type != C_WORKSPACE) { - workspace_cont = container_parent(workspace_cont, C_WORKSPACE); + if (ws && ws->type != C_WORKSPACE) { + ws = container_parent(ws, C_WORKSPACE); } - if (workspace_cont == NULL) { + if (!ws) { return output->swayc; } - struct sway_container *view_cont = container_at(workspace_cont, - cursor->x, cursor->y, surface, sx, sy); - return view_cont != NULL ? view_cont : workspace_cont; + if ((*surface = layer_surface_at(output, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], + ox, oy, sx, sy))) { + return ws; + } + if ((*surface = layer_surface_at(output, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], + ox, oy, sx, sy))) { + return ws; + } + + struct sway_container *c; + if ((c = container_at(ws, cursor->x, cursor->y, surface, sx, sy))) { + return c; + } + + if ((*surface = layer_surface_at(output, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], + ox, oy, sx, sy))) { + return ws; + } + if ((*surface = layer_surface_at(output, + &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], + ox, oy, sx, sy))) { + return ws; + } + + return NULL; } static void cursor_send_pointer_motion(struct sway_cursor *cursor, @@ -78,8 +133,7 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, struct wlr_seat *seat = cursor->seat->wlr_seat; struct wlr_surface *surface = NULL; double sx, sy; - struct sway_container *cont = - container_at_cursor(cursor, &surface, &sx, &sy); + container_at_cursor(cursor, &surface, &sx, &sy); // reset cursor if switching between clients struct wl_client *client = NULL; @@ -93,7 +147,7 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, } // send pointer enter/leave - if (cont != NULL && surface != NULL) { + if (surface != NULL) { wlr_seat_pointer_notify_enter(seat, surface, sx, sy); wlr_seat_pointer_notify_motion(seat, time, sx, sy); } else {