diff --git a/dwl.c b/dwl.c index 42e8198..3b1b999 100644 --- a/dwl.c +++ b/dwl.c @@ -267,6 +267,8 @@ static void unmapnotify(struct wl_listener *listener, void *data); static void unmaplayersurfacenotify(struct wl_listener *listener, void *data); static void view(const Arg *arg); static Client *xytoclient(double x, double y); +static struct wlr_surface *xytolayersurface(struct wl_list *layer_surfaces, + double x, double y, double *sx, double *sy); static Monitor *xytomon(double x, double y); static void zoom(const Arg *arg); @@ -1234,8 +1236,16 @@ void maplayersurfacenotify(struct wl_listener *listener, void *data) { LayerSurface *layersurface = wl_container_of(listener, layersurface, map); + double sx = 0.0, sy = 0.0; + struct wlr_surface *sub = wlr_layer_surface_v1_surface_at( + layersurface->layer_surface, + cursor->x - layersurface->geo.x, + cursor->y - layersurface->geo.y, + &sx, &sy); wlr_surface_send_enter(layersurface->layer_surface->surface, layersurface->layer_surface->output); - /* XXX recheck pointer focus */ + if (sub) + wlr_seat_pointer_notify_enter(seat, sub, sx, sy); + /* XXX check if the layer surface is below a client */ } void @@ -1306,7 +1316,7 @@ motionnotify(uint32_t time) { double sx = 0, sy = 0; struct wlr_surface *surface = NULL; - Client *c; + Client *c = NULL; /* Update selmon (even while dragging a window) */ if (sloppyfocus) @@ -1325,17 +1335,23 @@ motionnotify(uint32_t time) return; } + if ((surface = xytolayersurface(&selmon->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY], + cursor->x, cursor->y, &sx, &sy))) + ; + else if ((surface = xytolayersurface(&selmon->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP], + cursor->x, cursor->y, &sx, &sy))) + ; #ifdef XWAYLAND /* Find an independent under the pointer and send the event along. */ - if ((c = xytoindependent(cursor->x, cursor->y))) { + else if ((c = xytoindependent(cursor->x, cursor->y))) { surface = wlr_surface_surface_at(c->surface.xwayland->surface, cursor->x - c->surface.xwayland->x - c->bw, cursor->y - c->surface.xwayland->y - c->bw, &sx, &sy); /* Otherwise, find the client under the pointer and send the event along. */ - } else + } #endif - if ((c = xytoclient(cursor->x, cursor->y))) { + else if ((c = xytoclient(cursor->x, cursor->y))) { #ifdef XWAYLAND if (c->type != XDGShell) surface = wlr_surface_surface_at(c->surface.xwayland->surface, @@ -1347,6 +1363,13 @@ motionnotify(uint32_t time) cursor->x - c->geom.x - c->bw, cursor->y - c->geom.y - c->bw, &sx, &sy); } + else if ((surface = xytolayersurface(&selmon->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM], + cursor->x, cursor->y, &sx, &sy))) + ; + else if ((surface = xytolayersurface(&selmon->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND], + cursor->x, cursor->y, &sx, &sy))) { // gcc complains without these braces + ; + } /* If there's no client surface under the cursor, set the cursor image to a * default. This is what makes the cursor image appear when you move it * off of a client or over its border. */ @@ -1424,6 +1447,9 @@ pointerfocus(Client *c, struct wlr_surface *surface, double sx, double sy, * of its surfaces, and make keyboard focus follow if desired. */ wlr_seat_pointer_notify_enter(seat, surface, sx, sy); + if (!c) + return; + #if XWAYLAND if (c->type == X11Unmanaged) return; @@ -2126,6 +2152,24 @@ xytoclient(double x, double y) return NULL; } +struct wlr_surface * +xytolayersurface(struct wl_list *layer_surfaces, double x, double y, + double *sx, double *sy) +{ + LayerSurface *layersurface; + wl_list_for_each_reverse(layersurface, layer_surfaces, link) { + struct wlr_surface *sub = wlr_layer_surface_v1_surface_at( + layersurface->layer_surface, + x - layersurface->geo.x, + y - layersurface->geo.y, + sx, sy); + if (sub) + return sub; + + } + return NULL; +} + Monitor * xytomon(double x, double y) {