Re: [hackers] [dwm][patch] Stop input focus on pointers unselected monitor

From: Hiltjo Posthuma <hiltjo_AT_codemadness.org>
Date: Wed, 16 Aug 2023 10:07:16 +0200

On Tue, Aug 15, 2023 at 10:43:32AM +0100, Christopher Lang wrote:
> When the pointer is on an unselected monitor and is not moving, it
> should not interfere what window is selected/focused.
>
> 1:
>
> From https://tronche.com/gui/x/xlib/events/input-focus/normal-and-grabbed.html:
> When the focus moves from window A to window B, A is an inferior of B,
> and the pointer is in window P, the X server does the following:
> It generates a FocusOut event on window A...
> It generates a FocusOut event on each win...
> It generates a FocusIn event on window B,...
> If window P is an inferior of window B but window P is not window A or
> an inferior or ancestor of window A, it generates a FocusIn event on
> each window below window B, down to and including window P, with the
> detail member of each XFocusInEvent structure set to NotifyPointer.
>
> If focusmon selects a monitor with no clients then XSetInputFocus is
> called on the root window. Due to the above rules, an FocusIn event is sent
> to the window under the pointer which may be on another monitor. Now a
> window on one monitor is getting our keyboard input but another monitor
> is selected. In this undesirable state, a killclient shortcut (for
> example) will not destroy the window that is accepting input.
>
> We fix this by focusing on the bar window instead of root when an empty
> monitor is selected. Windows on other monitors are not a children of the
> bar window so they will not be focused by a NotifyPointer event.
>
> 2:
>
> If a window is moved from the selected monitor to the monitor under the
> pointer and the rearrangement of windows on the second monitor causes a
> different window to be under the pointer, then an enternotify event is
> sent for that window. This causes that window to be focused and the
> second monitor to be selected. If the arrangement on the second monitor
> did not cause the pointer to be under a different window then the
> selected monitor would not change (very unpredictable behaviour!).
>
> We fix this by suppressing all enternotify events at the end of an
> arrange(NULL) call.
> ---
> dwm.c | 11 ++++++++---
> 1 file changed, 8 insertions(+), 3 deletions(-)
>
> diff --git a/dwm.c b/dwm.c
> index f1d86b2..5b71b33 100644
> --- a/dwm.c
> +++ b/dwm.c
> _AT_@ -382,6 +382,7 @@ applysizehints(Client *c, int *x, int *y, int *w, int *h, int interact)
> void
> arrange(Monitor *m)
> {
> + XEvent ev;
> if (m)
> showhide(m->stack);
> else for (m = mons; m; m = m->next)
> _AT_@ -389,8 +390,12 @@ arrange(Monitor *m)
> if (m) {
> arrangemon(m);
> restack(m);
> - } else for (m = mons; m; m = m->next)
> - arrangemon(m);
> + } else {
> + for (m = mons; m; m = m->next)
> + arrangemon(m);
> + XSync(dpy, False);
> + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev));
> + }
> }
>
> void
> _AT_@ -804,7 +809,7 @@ focus(Client *c)
> XSetWindowBorder(dpy, c->win, scheme[SchemeSel][ColBorder].pixel);
> setfocus(c);
> } else {
> - XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
> + XSetInputFocus(dpy, selmon->barwin, RevertToPointerRoot, CurrentTime);
> XDeleteProperty(dpy, root, netatom[NetActiveWindow]);
> }
> selmon->sel = c;
> --
> 2.41.0
>
>

Hi,

Thanks for the patch. I'm not yet sure about it.

If there are any other multi-monitor users, please test this and share your
opinion of if the change makes sense to you.

-- 
Kind regards,
Hiltjo
Received on Wed Aug 16 2023 - 10:07:16 CEST

This archive was generated by hypermail 2.3.0 : Wed Aug 16 2023 - 10:12:49 CEST