git.strcat.st

/strcat/wm.git/ - summarytreelogarchivereleases

subject
add optional focus-follows-mouse
commit
01e9b3c837ff5fbda1e84a67a089ff100d3c16bc
date
2026-04-28T17:44:33Z
message
modified:   wm.c

diff
 wm.c | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/wm.c b/wm.c
index 8148249..c405bd2 100644
--- a/wm.c
+++ b/wm.c
@@ -8,6 +8,8 @@
 #define cmd_move 2
 #define num_workspaces 9
 
+static const char focus_follows_mouse = 0;
+
 static Window windows[max_windows];
 static int window_workspace[max_windows], window_count, current_workspace;
 
@@ -81,23 +83,30 @@ main(void)
 {
 	Display *display;
 	Window root_window;
+	Window root_return;
+	Window pointer_child;
 	Window drag_window;
 	Window focused_window;
+	Window hover_focused_window;
 	XWindowAttributes window_attrs;
 	XButtonEvent drag_start;
 	XEvent event;
 	Atom control_atom;
 	int is_dragging;
+	int root_x, root_y, win_x, win_y;
+	unsigned int pointer_mask;
 	int i, j;
 
 	is_dragging = 0;
 	drag_window = None;
+	hover_focused_window = None;
 	if ((display = XOpenDisplay(NULL)) == NULL)
 	    return 1;
 
 	root_window = DefaultRootWindow(display);
 	control_atom = XInternAtom(display, "_WM_CTL", False);
-	XSelectInput(display, root_window, SubstructureNotifyMask);
+	XSelectInput(display, root_window, SubstructureNotifyMask |
+	    (focus_follows_mouse ? PointerMotionMask : 0));
 	track_windows(display, root_window);
 	ewmh_init(display, root_window);
 	ewmh_sync(display, root_window, windows, window_workspace, window_count);
@@ -164,6 +173,19 @@ main(void)
 	            window_attrs.y + (drag_start.button == 1 ? y_diff : 0),
 	            max_val(1, window_attrs.width + (drag_start.button == 3 ? x_diff : 0)),
 	            max_val(1, window_attrs.height + (drag_start.button == 3 ? y_diff : 0)));
+	    } else if (focus_follows_mouse && event.type == MotionNotify && !is_dragging) {
+	        while (XCheckTypedEvent(display, MotionNotify, &event))
+	            continue;
+	        if (!XQueryPointer(display, root_window, &root_return, &pointer_child,
+	                &root_x, &root_y, &win_x, &win_y, &pointer_mask))
+	            continue;
+	        if (pointer_child == None || pointer_child == hover_focused_window)
+	            continue;
+	        if (!is_root_child(display, root_window, pointer_child))
+	            continue;
+	        XSetInputFocus(display, pointer_child, RevertToPointerRoot, CurrentTime);
+	        ewmh_set_active_window(display, root_window, pointer_child);
+	        hover_focused_window = pointer_child;
 	    } else if (event.type == ButtonRelease) {
 	        is_dragging = 0;
 	        drag_window = None;