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

Commit 35fb5518f44b97e24c96c75da753efbe14e20559
Parent: aa7ab1a348e62e41d361b2e2bd589cf6f99e7af1
Author: mcol <mcol@posteo.net>
Date: 2021-02-12 10:07:11 +0000
Committer: mcol <mcol@posteo.net>
Committed: 2021-02-12 10:07:11 +0000

Fix focussing and damage tracking for layer shell surfaces

src/shell.h Modified

@@ -5,7 +5,9 @@
 
 void unmap_view(struct view *view);
 void map_view(struct view *view);
+void focus(void *aview, struct wlr_surface *surface, bool is_layer);
 void focus_view(struct view *view, struct wlr_surface *surface);
+void find_focus();
 void pan_to_view(struct view *view);
 void fullscreen_xdg_surface(
     struct view *view, struct wlr_xdg_surface *xdg_surface, struct wlr_output *output

src/shell.c Modified

@@ -1,3 +1,4 @@
+#include <wlr/types/wlr_layer_shell_v1.h>
 #include <wlr/types/wlr_output_damage.h>
 #include <wlr/types/wlr_xdg_shell.h>
 #include <wlr/util/edges.h>
@@ -18,22 +19,60 @@
 }
 
 
-void focus_view(struct view *view, struct wlr_surface *surface) {
+void focus(void *data, struct wlr_surface *surface, bool is_layer) {
     /* view can be NULL. In that case focus is removed from any focussed surface. */
     /* surface can be NULL. In that case focus goes to view->surface->surface. */
+    struct layer_view *lview;
+    struct view *view;
+    if (data) {
+	if (is_layer) {
+	    lview = (struct layer_view *)data;
+	    if (!surface) {
+		surface = lview->surface->surface;
+	    }
+	} else {
+	    view = (struct view *)data;
+	    if (!surface) {
+		surface = view->surface->surface;
+	    }
+	}
+    }
     struct wlr_surface *prev_surface = wimp.seat->keyboard_state.focused_surface;
-    if (prev_surface == surface) {
+
+    if (surface == prev_surface) {
 	return;
     }
     wlr_seat_keyboard_notify_clear_focus(wimp.seat);
 
     if (prev_surface && wlr_surface_is_xdg_surface(prev_surface)) {
-	struct wlr_xdg_surface *previous = wlr_xdg_surface_from_wlr_surface(prev_surface);
-	wlr_xdg_toplevel_set_activated(previous, false);
-	damage_by_view(previous->data, true);
+	struct wlr_xdg_surface *prev_xdg_surface = wlr_xdg_surface_from_wlr_surface(prev_surface);
+	wlr_xdg_toplevel_set_activated(prev_xdg_surface, false);
+	damage_by_view(prev_xdg_surface->data, true);
+    }
+
+    if (!data) {
+	wimp.focussed_layer_view = NULL;
+	return;
     }
 
-    if (view) {
+    struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(wimp.seat);
+
+    if (is_layer) {
+	if (!lview->surface->mapped || !lview->surface->current.keyboard_interactive) {
+	    return;
+	}
+	if (!surface) {
+	    surface = lview->surface->surface;
+	}
+	wlr_seat_keyboard_notify_enter(
+	    wimp.seat, surface, keyboard->keycodes,
+	    keyboard->num_keycodes, &keyboard->modifiers
+	);
+	wlr_surface_send_enter(surface, lview->surface->output);
+	wimp.focussed_layer_view = lview;
+	damage_by_lview(lview);
+
+    } else {
 	if (view->is_scratchpad) {
 	    struct scratchpad *scratchpad = scratchpad_from_view(view);
 	    scratchpad->is_mapped = true;
@@ -47,9 +86,8 @@
 	if (wlr_surface_is_xdg_surface(surface)) {
 	    wlr_xdg_toplevel_set_activated(view->surface, true);
 	}
-	struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(wimp.seat);
 	wlr_seat_keyboard_notify_enter(
-	    wimp.seat, view->surface->surface, keyboard->keycodes,
+	    wimp.seat, surface, keyboard->keycodes,
 	    keyboard->num_keycodes, &keyboard->modifiers
 	);
 	damage_by_view(view, true);
@@ -57,6 +95,30 @@
 }
 
 
+void focus_view(struct view *view, struct wlr_surface *surface) {
+    focus(view, surface, false);
+}
+
+
+void find_focus() {
+    struct scratchpad *scratchpad;
+    wl_list_for_each(scratchpad, &wimp.scratchpads, link) {
+	if (scratchpad->is_mapped) {
+	    focus_view(scratchpad->view, NULL);
+	    return;
+	}
+    }
+
+    if (!wl_list_empty(&wimp.current_desk->views)) {
+	struct view *view = wl_container_of(wimp.current_desk->views.next, view, link);
+	focus_view(view, NULL);
+	return;
+    };
+
+    focus_view(NULL, NULL);
+}
+
+
 void pan_to_view(struct view *view) {
     int border_width = wimp.current_desk->border_width;
     double x = view->x - border_width;
@@ -183,10 +245,9 @@
 
 static void on_unmap(struct wl_listener *listener, void *data) {
     struct view *view = wl_container_of(listener, view, unmap_listener);
-    struct scratchpad *scratchpad;
 
     if (view->is_scratchpad) {
-	scratchpad = scratchpad_from_view(view);
+	struct scratchpad *scratchpad = scratchpad_from_view(view);
 	scratchpad->is_mapped = false;
     } else {
 	wl_list_remove(&view->link);
@@ -196,26 +257,9 @@
     wl_list_remove(&view->commit_listener.link);
     damage_by_view(view, true);
 
-    if (view->surface->surface != wimp.seat->keyboard_state.focused_surface) {
-	return;
+    if (view->surface->surface == wimp.seat->keyboard_state.focused_surface) {
+	find_focus();
     }
-
-    wl_list_for_each(scratchpad, &wimp.scratchpads, link) {
-	if (scratchpad->is_mapped) {
-	    focus_view(scratchpad->view, NULL);
-	    return;
-	}
-    }
-
-    if (!wl_list_empty(&wimp.current_desk->views)) {
-	struct view *next = wl_container_of(wimp.current_desk->views.next, view, link);
-	if (view != next) {
-	    focus_view(next, NULL);
-	    return;
-	}
-    };
-
-    focus_view(NULL, NULL);
 }
 
 

src/output.h Modified

@@ -6,6 +6,7 @@
 void set_up_outputs();
 void damage_box(struct wlr_box *geo, bool add_borders);
 void damage_by_view(struct view *view, bool with_borders);
+void damage_by_lview(struct layer_view *lview);
 void damage_all_outputs();
 
 #endif

src/output.c Modified

@@ -258,6 +258,11 @@
 }
 
 
+void damage_by_lview(struct layer_view *lview) {
+    damage_box(&lview->geo, false);
+}
+
+
 void damage_all_outputs() {
     struct output *output;
     wl_list_for_each(output, &wimp.outputs, link) {

src/layer_shell.c Modified

@@ -3,6 +3,7 @@
 
 #include "layer_shell.h"
 #include "output.h"
+#include "shell.h"
 
 
 static void layer(struct output *output) {
@@ -61,18 +62,18 @@
 	ZWLR_LAYER_SHELL_V1_LAYER_TOP,
     };
     size_t nlayers = sizeof(layers_above_shell) / sizeof(layers_above_shell[0]);
-    struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(wimp.seat);
+    bool found = false;
     for (size_t i = 0; i < nlayers; ++i) {
 	wl_list_for_each_reverse(lview, &output->layer_views[layers_above_shell[i]], link) {
 	    if (lview->surface->current.keyboard_interactive && lview->surface->mapped) {
-		wlr_seat_keyboard_notify_enter(
-		    wimp.seat, lview->surface->surface, keyboard->keycodes,
-		    keyboard->num_keycodes, &keyboard->modifiers
-		);
-		wimp.focussed_layer_view = lview;
+		focus(lview, NULL, true);
+		found = true;
 		break;
 	    }
 	}
+	if (found) {
+	    break;
+	}
     }
 
     wlr_output_damage_add_whole(output->wlr_output_damage);
@@ -94,7 +95,7 @@
 
 static void on_commit(struct wl_listener *listener, void *data) {
     struct layer_view *lview = wl_container_of(listener, lview, commit_listener);
-    damage_box(&lview->geo, false);
+    damage_by_lview(lview);
 }
 
 
@@ -102,15 +103,9 @@
     struct layer_view *lview = wl_container_of(listener, lview, unmap_listener);
     lview->surface->mapped = false;
     layer(lview->output);
-
-    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(
-	    wimp.seat, view->surface->surface, keyboard->keycodes,
-	    keyboard->num_keycodes, &keyboard->modifiers
-	);
+    if (wimp.focussed_layer_view == lview) {
 	wimp.focussed_layer_view = NULL;
+	find_focus();
     }
 }
 

src/cursor.c Modified

@@ -158,7 +158,6 @@
     double sx, sy;
     struct wlr_seat *seat;
     struct wlr_surface *surface;
-    struct view *view;
     double zoom = wimp.current_desk->zoom;
 
     switch (wimp.cursor_mode) {
@@ -166,7 +165,7 @@
 	    seat = wimp.seat;
 	    surface = NULL;
 	    bool is_layer;
-	    view = under_pointer(&surface, &sx, &sy, &is_layer);
+	    struct view *view = under_pointer(&surface, &sx, &sy, &is_layer);
 	    if (!view) {
 		wlr_xcursor_manager_set_cursor_image(wimp.cursor_manager, "left_ptr", wimp.cursor);
 	    }
@@ -176,7 +175,7 @@
 		    wlr_seat_pointer_notify_motion(seat, time, sx, sy);
 		}
 		if (wimp.auto_focus && seat->keyboard_state.focused_surface != surface) {
-		    focus_view(view, surface);
+		    focus(view, surface, is_layer);
 		}
 	    } else {
 		wlr_seat_pointer_clear_focus(seat);