Grab buttons on managed window instead of parent

This fixes an issue that is quite possibly a bug in Chromium. Given the
following steps:

1. Run a Chromium-based web browser
2. Visit a site with a menu that opens on hover
3. Hover over the menu to open it
4. Click an item in the menu

The expectation is to be clicking the menu item. Instead the menu would
close and the click would pass through to the element underneath.

This issue could be worked around by passing the following option to
Chromium:

  --disable-features=SendMouseLeaveEvents

In the source code, this feature is explained as follows:

  This feature allows native ET_MOUSE_EXIT events to be passed through
  to blink as mouse leave events. Traditionally these events were
  converted to mouse move events due to a number of inconsistencies on
  the native platforms. crbug.com/450631

With the buttons grabbed on the parent window, Chromium would receive
the following sequence of events (as reported by xev):

  LeaveNotify event, serial 36, synthetic NO, window 0x3600001,
    root 0x1dd, subw 0x0, time 1129083356, (10,677), root:(970,693),
    mode NotifyGrab, detail NotifyAncestor, same_screen YES,
    focus YES, state 256

  EnterNotify event, serial 36, synthetic NO, window 0x3600001,
    root 0x1dd, subw 0x0, time 1129083358, (10,677), root:(970,693),
    mode NotifyUngrab, detail NotifyAncestor, same_screen YES,
    focus YES, state 256

  KeymapNotify event, serial 36, synthetic NO, window 0x0,
    keys:  221 0   0   0   0   0   0   0   0   0   0   0   0   0   0   0
           0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0

  ButtonPress event, serial 36, synthetic NO, window 0x3600001,
    root 0x1dd, subw 0x0, time 1129083356, (10,677), root:(970,693),
    state 0x0, button 1, same_screen YES

  ButtonRelease event, serial 36, synthetic NO, window 0x3600001,
    root 0x1dd, subw 0x0, time 1129083460, (10,677), root:(970,693),
    state 0x100, button 1, same_screen YES

One of the events before ButtonPress triggers the problem. Considering
the workaround this is almost certainly LeaveNotify.

These LeaveNotify and EnterNotify events are "pseudo-motion" events due
to the activation and de-activation of StumpWM's grab on the parent
window.

After these changes, the sequence of events becomes much cleaner:

  ButtonPress event, serial 36, synthetic NO, window 0x3600001,
    root 0x1dd, subw 0x0, time 1129083356, (10,677), root:(970,693),
    state 0x0, button 1, same_screen YES

  ButtonRelease event, serial 36, synthetic NO, window 0x3600001,
    root 0x1dd, subw 0x0, time 1129083460, (10,677), root:(970,693),
    state 0x100, button 1, same_screen YES

This brings StumpWM in line with other tested window managers.

Fixes #527
Fixes #894
This commit is contained in:
Joram Schrijver 2022-08-06 21:21:34 +02:00
parent 625db975a8
commit d5230923c4
No known key found for this signature in database
GPG key ID: F6B867A471F962F4
2 changed files with 13 additions and 2 deletions

View file

@ -631,8 +631,19 @@ the window in it's frame."
(let ((button (decode-button-code code))
(screen (find-screen window))
(mode-line (find-mode-line-by-window window))
(win (find-window-by-parent window (top-windows))))
(win))
(run-hook-with-args *click-hook* screen code x y)
(cond
((setf win (find-window window))
;; We received the event at the parent window, but it occurred in
;; the window itself. We need to adjust the coordinates to make them
;; relative to the parent window.
(setf x (+ x (xlib:drawable-x window))
y (+ y (xlib:drawable-y window))))
((setf win (find-window-by-parent window (top-windows)))
;; The click happened on the parent window, so the coordinates are
;; correct.
))
(cond
((and screen (not child))
(group-button-press (screen-current-group screen) button x y :root)

View file

@ -672,7 +672,7 @@ and bottom_end_x."
(unless (eq (xlib:window-map-state (window-xwin window)) :unmapped)
(incf (window-unmap-ignores window)))
(xlib:reparent-window (window-xwin window) master-window 0 0)
(xwin-grab-buttons master-window)
(xwin-grab-buttons xwin)
;; ;; we need to update these values since they get set to 0,0 on reparent
;; (setf (window-x window) 0
;; (window-y window) 0)