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

Commit 0cf9a850c1dbf81466a1b77c9f55610de567320d
Parent: cfe0ae65c9382212efcc9efb1b03ca4f0e78adda
Author: mcol <mcol@posteo.net>
Date: 2021-02-06 22:55:29 +0000
Committer: mcol <mcol@posteo.net>
Committed: 2021-02-06 22:56:22 +0000

Make sure focus falls to the right window when unfocussing

Fixes focus errors when switching desks and toggle scratchpads.
Fixes #24

src/types.h Modified

@@ -51,7 +51,6 @@
     struct wl_list desks;
     int desk_count;
     struct desk *current_desk;
-    bool can_steal_focus;
     struct wl_list marks;
     bool mark_waiting;
     struct mark_indicator mark_indicator;

src/shell.c Modified

@@ -18,6 +18,7 @@
 
 void focus_view(struct view *view, struct wlr_surface *surface) {
     if (view == NULL) {
+	wlr_seat_keyboard_notify_clear_focus(wimp.seat);
 	return;
     }
     struct wlr_seat *seat = wimp.seat;
@@ -135,28 +136,39 @@
 	scratchpad->is_mapped = true;
     }
 
-    if (wimp.can_steal_focus) {
-	focus_view(view, view->surface->surface);
-    }
+    focus_view(view, view->surface->surface);
 }
 
 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) {
-	struct scratchpad *scratchpad = scratchpad_from_view(view);
+	scratchpad = scratchpad_from_view(view);
 	scratchpad->is_mapped = false;
     } else {
 	wl_list_remove(&view->link);
 	wl_list_insert(wimp.current_desk->views.prev, &view->link);
     }
 
-    if (wimp.can_steal_focus) {
-	if (!wl_list_empty(&wimp.current_desk->views)) {
-	    struct view *next_view = wl_container_of(wimp.current_desk->views.next, view, link);
-	    focus_view(next_view, next_view->surface->surface);
+    if (view->surface->surface != wimp.seat->keyboard_state.focused_surface) {
+	return;
+    }
+
+    wl_list_for_each(scratchpad, &wimp.scratchpads, link) {
+	if (scratchpad->is_mapped) {
+	    focus_view(scratchpad->view, scratchpad->view->surface->surface);
+	    return;
 	}
     }
+
+    if (!wl_list_empty(&wimp.current_desk->views)) {
+	view = wl_container_of(wimp.current_desk->views.next, view, link);
+	focus_view(view, view->surface->surface);
+	return;
+    };
+
+    focus_view(NULL, NULL);
 }
 
 

src/main.c Modified

@@ -31,7 +31,6 @@
     .on_drag2 = NULL,
     .on_drag3 = NULL,
     .on_pinch = NULL,
-    .can_steal_focus = true,
     .desk_count = 0,
     .mark_waiting = false,
     .mark_indicator.box.width = 25,

src/desk.c Modified

@@ -1,5 +1,6 @@
 #include "config.h"
 #include "desk.h"
+#include "scratchpad.h"
 #include "shell.h"
 #include "types.h"
 
@@ -52,22 +53,29 @@
 
 
 void set_desk(struct desk *desk) {
-    struct view *view;
-    if (desk != wimp.current_desk) {
-	wimp.can_steal_focus = false;
-	wl_list_for_each(view, &wimp.current_desk->views, link) {
-	    unmap_view(view);
-	}
-	wimp.current_desk = desk;
-	wl_list_for_each(view, &wimp.current_desk->views, link) {
-	    map_view(view);
-	}
-	wimp.can_steal_focus = true;
-	if (!wl_list_empty(&desk->views)) {
-	    view = wl_container_of(desk->views.next, view, link);
-	    focus_view(view, view->surface->surface);
+    if (desk == wimp.current_desk) {
+	return;
+    }
+
+    wimp.current_desk = desk;
+
+    // If a scratchpad is focussed, keep it focussed.
+    struct scratchpad *scratchpad;
+    wl_list_for_each(scratchpad, &wimp.scratchpads, link) {
+	if (scratchpad->view && scratchpad->is_mapped) {
+	    if (scratchpad->view->surface->surface == wimp.seat->keyboard_state.focused_surface) {
+		return;
+	    }
 	}
     }
+
+    // Otherwise focus the next view on the new desktop if there is one.
+    if (wl_list_empty(&desk->views)) {
+	focus_view(NULL, NULL);
+    } else {
+	struct view *view = wl_container_of(desk->views.next, view, link);
+	focus_view(view, view->surface->surface);
+    }
 }
 
 
@@ -83,13 +91,10 @@
 
 
 void view_to_desk(struct view *view, int index) {
-    wimp.can_steal_focus = false;
     struct desk *desk = desk_from_index(index);
     if (desk) {
 	wl_list_remove(&view->link);
-	desk == wimp.current_desk ? map_view(view) : unmap_view(view);
 	wl_list_insert(&desk->views, &view->link);
-	wimp.can_steal_focus = true;
 	if (!wl_list_empty(&wimp.current_desk->views)) {
 	    struct view *next_view = wl_container_of(wimp.current_desk->views.next, view, link);
 	    focus_view(next_view, next_view->surface->surface);