gimp but for windows: a wayland compositor
git clone https://github.com/m-col/wimp
Files | Refs | Readme

Commit 23600c53fbdf886fcbc2fc4a5913c75d26821e26
Parent: 3e5fc4b2bd41458c4e5a6c8cebb76c5578ee49a8
Author: mcol <mcol@posteo.net>
Date: 2021-01-30 22:05:01 +0000
Committer: mcol <mcol@posteo.net>
Committed: 2021-01-30 22:05:01 +0000

Let the pointer interact with layer surfaces

src/shell.c Modified

@@ -24,7 +24,7 @@
     if (prev_surface == surface) {
 	return;
     }
-    if (prev_surface) {
+    if (prev_surface && wlr_surface_is_xdg_surface(prev_surface)) {
 	struct wlr_xdg_surface *previous = wlr_xdg_surface_from_wlr_surface(
 	    seat->keyboard_state.focused_surface
 	);

src/layer_shell.c Modified

@@ -97,7 +97,7 @@
     lview->surface->mapped = false;
     layer(lview->output);
 
-    if (wimp.focussed_layer_view == lview) {
+    if (wimp.focussed_layer_view == lview && !wl_list_empty(&wimp.current_desk->views)) {
 	struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(wimp.seat);
 	struct view *view = wl_container_of(wimp.current_desk->views.next, view, link);
 	wlr_seat_keyboard_notify_enter(

src/cursor.h Modified

@@ -3,10 +3,7 @@
 
 #include "types.h"
 
-struct view *view_at(
-    double lx, double ly, struct wlr_surface **surface, double *sx, double *sy
-);
-
+void *under_pointer(struct wlr_surface **surface, double *sx, double *sy, bool *is_layer);
 void set_up_cursor();
 
 #endif

src/cursor.c Modified

@@ -2,6 +2,7 @@
 #include <linux/input-event-codes.h>
 #include <unistd.h>
 #include <wlr/types/wlr_cursor.h>
+#include <wlr/types/wlr_layer_shell_v1.h>
 #include <wlr/types/wlr_pointer_gestures_v1.h>
 #include <wlr/types/wlr_xcursor_manager.h>
 
@@ -46,28 +47,68 @@
 }
 
 
-struct view *view_at(
-    double lx, double ly, struct wlr_surface **surface, double *sx, double *sy
-) {
+void *under_pointer(struct wlr_surface **surface, double *sx, double *sy, bool *is_layer) {
+    double x = wimp.cursor->x;
+    double y = wimp.cursor->y;
+    double tsx, tsy;
     struct view *view;
-    lx /= wimp.current_desk->zoom;
-    ly /= wimp.current_desk->zoom;
-    double _sx, _sy;
+    struct layer_view *lview;
+    struct wlr_surface *tsurface;
+    struct wlr_output *wlr_output = wlr_output_layout_output_at(wimp.output_layout, x, y);
+    struct output *output = wlr_output->data;
+
+    // overlay and top layers
+    uint32_t above[] = { ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY, ZWLR_LAYER_SHELL_V1_LAYER_TOP };
+    size_t nlayers = sizeof(above) / sizeof(above[0]);
+    for (size_t i = 0; i < nlayers; i++) {
+	wl_list_for_each(lview, &output->layer_views[above[i]], link) {
+	    tsurface = wlr_layer_surface_v1_surface_at(
+		lview->surface, x - lview->geo.x, y - lview->geo.y, &tsx, &tsy
+	    );
+	    if (tsurface) {
+		*sx = tsx;
+		*sy = tsy;
+		*surface = tsurface;
+		*is_layer = true;
+		return lview;
+	    }
+	}
+    }
+
+    // clients
+    double zx = x / wimp.current_desk->zoom;
+    double zy = y / wimp.current_desk->zoom;
 
     wl_list_for_each(view, &wimp.current_desk->views, link) {
-	double view_sx = lx - view->x;
-	double view_sy = ly - view->y;
-	struct wlr_surface *_surface = NULL;
-	_surface = wlr_xdg_surface_surface_at(
-	    view->surface, view_sx, view_sy, &_sx, &_sy
+	tsurface = wlr_xdg_surface_surface_at(
+	    view->surface, zx - view->x, zy - view->y, &tsx, &tsy
 	);
-	if (_surface != NULL) {
-	    *sx = _sx;
-	    *sy = _sy;
-	    *surface = _surface;
+	if (tsurface) {
+	    *sx = tsx;
+	    *sy = tsy;
+	    *surface = tsurface;
+	    *is_layer = false;
 	    return view;
 	}
     }
+
+    // bottom and background layers
+    uint32_t below[] = { ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM, ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND };
+    for (size_t i = 0; i < nlayers; i++) {
+	wl_list_for_each(lview, &output->layer_views[below[i]], link) {
+	    tsurface = wlr_layer_surface_v1_surface_at(
+		lview->surface, x - lview->geo.x, y - lview->geo.y, &tsx, &tsy
+	    );
+	    if (tsurface) {
+		*sx = tsx;
+		*sy = tsy;
+		*surface = tsurface;
+		*is_layer = true;
+		return lview;
+	    }
+	}
+    }
+
     return NULL;
 }
 
@@ -78,14 +119,13 @@
     struct wlr_surface *surface;
     struct view *view;
     double zoom = wimp.current_desk->zoom;
-    dx /= zoom;
-    dy /= zoom;
 
     switch (wimp.cursor_mode) {
 	case CURSOR_PASSTHROUGH:
 	    seat = wimp.seat;
 	    surface = NULL;
-	    view = view_at(wimp.cursor->x, wimp.cursor->y, &surface, &sx, &sy);
+	    bool is_layer;
+	    view = under_pointer(&surface, &sx, &sy, &is_layer);
 	    if (!view) {
 		wlr_xcursor_manager_set_cursor_image(wimp.cursor_manager, "left_ptr", wimp.cursor);
 	    }
@@ -103,8 +143,8 @@
 	case CURSOR_MOD:
 	    if (wimp.on_mouse_motion) {
 		struct motion motion = {
-		    .dx = dx,
-		    .dy = dy,
+		    .dx = dx / zoom,
+		    .dy = dy / zoom,
 		    .is_percentage = false,
 		};
 		wimp.on_mouse_motion(&motion);
@@ -139,6 +179,9 @@
 static void on_cursor_button(struct wl_listener *listener, void *data) {
     struct wlr_event_pointer_button *event = data;
     wlr_seat_pointer_notify_button(wimp.seat, event->time_msec, event->button, event->state);
+    double sx, sy;
+    struct wlr_surface *surface;
+    bool is_layer;
 
     if (event->state == WLR_BUTTON_RELEASED) {
 	if (wimp.cursor_mode == CURSOR_MOD) {
@@ -156,8 +199,9 @@
 	if (wimp.grabbed_view) {
 	    wimp.grabbed_view = NULL;
 	}
+    }
 
-    } else if (wimp.cursor_mode == CURSOR_MOD) {
+    else if (wimp.cursor_mode == CURSOR_MOD) {
 	bool grab = true;
 	switch (event->button) {
 	    case BTN_LEFT:
@@ -173,18 +217,15 @@
 		grab = false;
 	}
 	if (grab) {
-	    struct wlr_surface *surface;
-	    double sx, sy;
-	    wimp.grabbed_view = view_at(wimp.cursor->x, wimp.cursor->y, &surface, &sx, &sy);
+	    wimp.grabbed_view = under_pointer(&surface, &sx, &sy, &is_layer);
 	}
+    }
 
-    } else {
-	double sx, sy;
-	struct wlr_surface *surface;
-	struct view *view = view_at(
-	    wimp.cursor->x, wimp.cursor->y, &surface, &sx, &sy
-	);
-	focus_view(view, surface);
+    else {
+	struct view *view = under_pointer(&surface, &sx, &sy, &is_layer);
+	if (!is_layer) {
+	    focus_view(view, surface);
+	}
     }
 }
 

src/action.c Modified

@@ -52,8 +52,9 @@
     } else {
 	double sx, sy;
 	struct wlr_surface *surface;
-	view = view_at(wimp.cursor->x, wimp.cursor->y, &surface, &sx, &sy);
-	if (!view) {
+	bool is_layer;
+	view = under_pointer(&surface, &sx, &sy, &is_layer);
+	if (!view || is_layer) {
 	    return;
 	}
     }
@@ -277,8 +278,9 @@
 
 void toggle_fullscreen(void *data) {
     struct wlr_surface *surface = wimp.seat->keyboard_state.focused_surface;
-    if (!surface)
+    if (!surface || !wlr_surface_is_xdg_surface(surface)) {
 	return;
+    }
     struct wlr_xdg_surface *xdg_surface = wlr_xdg_surface_from_wlr_surface(surface);
     struct view *view = wl_container_of(wimp.current_desk->views.next, view, link);
     fullscreen_xdg_surface(view, xdg_surface, NULL);