From d98ca07a649407a2be8cae1e66265f1bba785b04 Mon Sep 17 00:00:00 2001
From: Guido Cella <guidocella91@gmail.com>
Date: Fri, 4 Sep 2020 07:38:14 +0200
Subject: enable pointer on layer surfaces

---
 dwl.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 49 insertions(+), 5 deletions(-)

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)
 {
-- 
cgit v1.2.3