From e8fc45da63718b17388de2b0f2ba268d75bfd80f Mon Sep 17 00:00:00 2001 From: Chris Down Date: Mon, 27 Apr 2020 16:10:10 +0100 Subject: [PATCH] follow=keyboard: Fall back to follow=mouse instead of XDefaultScreen() In dwm and similar window managers, it's common to often have empty tags, and navigate to them with the intent to create clients there. If I navigate to one of those empty tags with a dunst notification visible and follow=keyboard set, the notification warps over to the default screen. If I then open a client, it then warps back, which is pretty jarring. This is mostly an artefact of the implementation of follow=keyboard -- if we fail to get a focused window, we use the default screen. However this case isn't necessarily really a "failure" on window managers like dwm where it's a common occurrence to end up with no clients on the screen, whereas that would be significantly rarer on (say) GNOME or KDE. A guess that's more likely to fit user expectations is falling back to where the mouse pointer currently is, since this indicates the currently focused monitor that the window manager would create a client on. This avoids warping back to that monitor again when a client is created. --- src/x11/screen.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/src/x11/screen.c b/src/x11/screen.c index 7c3347f..ac7123b 100644 --- a/src/x11/screen.c +++ b/src/x11/screen.c @@ -303,6 +303,7 @@ bool window_is_fullscreen(Window window) struct screen_info *get_active_screen(void) { int ret = 0; + bool force_follow_mouse = false; if (settings.monitor > 0 && settings.monitor < screens_len) { ret = settings.monitor; goto sc_cleanup; @@ -321,7 +322,26 @@ struct screen_info *get_active_screen(void) Window root = RootWindow(xctx.dpy, DefaultScreen(xctx.dpy)); - if (settings.f_mode == FOLLOW_MOUSE) { + if (settings.f_mode == FOLLOW_KEYBOARD) { + Window focused = get_focused_window(); + + if (focused == 0) { + /* + * This can happen in the case that the user + * just has the root window open, eg. in empty + * tags in dwm or similar window managers. In + * that case, fall back to FOLLOW_MOUSE, since + * it probably still has the right screen. + */ + force_follow_mouse = true; + } else { + Window child_return; + XTranslateCoordinates(xctx.dpy, focused, root, + 0, 0, &x, &y, &child_return); + } + } + + if (settings.f_mode == FOLLOW_MOUSE || force_follow_mouse) { int dummy; unsigned int dummy_ui; Window dummy_win; @@ -337,21 +357,6 @@ struct screen_info *get_active_screen(void) &dummy_ui); } - if (settings.f_mode == FOLLOW_KEYBOARD) { - - Window focused = get_focused_window(); - - if (focused == 0) { - /* something went wrong. Fall back to default */ - ret = XDefaultScreen(xctx.dpy); - goto sc_cleanup; - } - - Window child_return; - XTranslateCoordinates(xctx.dpy, focused, root, - 0, 0, &x, &y, &child_return); - } - for (int i = 0; i < screens_len; i++) { if (INRECT(x, y, screens[i].x, screens[i].y, screens[i].w, screens[i].h)) {