When using a (non-effect) TabBox clicking outside the TabBox closes it (as it should), but doesn't release the pointer grab. Pointer events are thus bound to the new selected window. Reproducible: Always Steps to Reproduce: 1. Press Alt+Tab 2. Wait till window is shown 3. Click outside the window Actual Results: Pointer is grabbed Expected Results: Pointer should no longer be grabbed. This is a regression compared to 4.11. Client::updateMouseGrab() is called and the (un)grabButton calls look fine and do not fail. Note that the code has been in general broken for quite some time. TabBox::establishTabBoxGrab() sets a m_forcedGlobalMouseGrab to true and in Client::updateMouseGrab() there is a check for this, but it's on Workspace. This must have been broken since TabBox got split out from Workspace. Fixing this does not solve the problem, though.
porting Client::grabButton, ::ungrabButton and ::updateMouseGrab back to the code from 4.11 does not fix the issue.
not passing the mouse events to TabBox at all (and thus not closing) doesn't improve the situation.
The 4.11 updateMouseGrab() code looks wrong. "if (isActive() && !workspace()->forcedGlobalMouseGrab())" for the tabbox calling (on the active windows and inactive have passive grabs anyway) this would by now read "true" since workspace()->forcedGlobalMouseGrab() is never set. However the logics read twisted to me (this should only process if forcedGlobalMouseGrab is true, otherwise the ungrab process should occur) One undesired consequence of this would be that the active window is *always* passively grabbed (recall the weird issue about that gtk+ input painting application?) The ONLY purpose of grabbing the active window (here) is to close the tabbox if you click anywhere (clicking on an inactive window should always work) - if that doesn't happen there can be two reasons: 1. no (unbroken) tabbox closing calls 2. sth. else holds an active grab on the mouse (no input events for any other window, passive grab or not) -> twist the !workspace()->forcedGlobalMouseGrab() (now Tabbox::self()) check - the branch should be entered when this is true. -> can you "sleep 5; xprop" with the tabbox on screen? -> do you enter THE CORRECT TabBox::handleMouseEvent() function? -> it's broken somewhere there ;-)
just did another hour of playing around. twisting the condition did of course not help and after spending some thinking of what it should do I think it's correct: the isActive() branch should not be entered in case of a TabBox grab. The interesting finding is: I commented out the close() from the mouse click event handler in TabBox and added a debug statement to see that this path is taken. If I click anywhere the mouse gets frozen in this case already, any further clicks have no effect at all. There is at max the debug message once, although the grab doesn't get updated (enough debug statements to be sure it wasn't entered).
Checked QWidget::mouseGrabber() value, resp. the ability to cause an active grab w/ eg. xprop?
after the mouse is frozen, xprop fails with: "xprop: error: Can't grab the mouse." Now the big question is: where does the grab happen? It's not in KWin's source (only grab happens during move/resize) and I set break points on xcb_grab_pointer, xcb_grab_pointer_unchecked and XGrabPointer and it never hit.
Just checked how to get info on who holds the grab: [513706.466] (II) Printing all currently active device grabs: [513706.466] Active grab 0x49600054 (core) on device 'Virtual core pointer' (2): [513706.466] client pid 18726 kwin --replace [513706.466] at 513703453 (from passive grab) (device frozen, state 6) [513706.466] core event mask 0x4 [513706.466] passive grab type 4, detail 0x0, activating key 0 [513706.466] owner-events false, kb 1 ptr 0, confine 0, cursor 0x0 [513706.466] (II) End list of active device grabs
While TabBox is active prior to clicking anywhere: [514374.896] Active grab 0x9800000 (core) on device 'Virtual core keyboard' (3): [514374.896] client pid 18776 kwin --replace [514374.897] at 514370923 (from active grab) (device thawed, state 1) [514374.897] core event mask 0x3 [514374.897] owner-events false, kb 1 ptr 1, confine 0, cursor 0x0 [514374.897] (II) End list of active device grabs And while TabBox is active after clicking anywhere: [514431.004] (II) Printing all currently active device grabs: [514431.005] Active grab 0x4980016a (core) on device 'Virtual core pointer' (2): [514431.005] client pid 18776 kwin --replace [514431.005] at 514428449 (from passive grab) (device frozen, state 6) [514431.005] core event mask 0x4 [514431.005] passive grab type 4, detail 0x0, activating key 0 [514431.005] owner-events false, kb 1 ptr 0, confine 0, cursor 0x0 [514431.005] Active grab 0x9800000 (core) on device 'Virtual core keyboard' (3): [514431.005] client pid 18776 kwin --replace [514431.005] at 514427482 (from active grab) (device thawed, state 1) [514431.005] core event mask 0x3 [514431.005] owner-events false, kb 1 ptr 1, confine 0, cursor 0x0 [514431.005] (II) End list of active device grabs
pointer is passively grabbed, but device is frozen, ie. XAllowEvents doesn't happen. try reverting the xcb call to XLib variant.
while actually the tabbox wouldn't require a sync passive grab at all, does it?
(In reply to comment #10) > while actually the tabbox wouldn't require a sync passive grab at all, does > it? nope, I just changed the branch to async and that fixes the problem.
(In reply to comment #11) > (In reply to comment #10) > > while actually the tabbox wouldn't require a sync passive grab at all, does > > it? > > nope, I just changed the branch to async and that fixes the problem. nope again, I can still reproduce it (but sometimes it works).
also with XAllowEvents I'm still able to reproduce. The pattern is that I'm allowed to click once outside, afterwards it freezes (I had the close() call removed).
And here we go (working solution): diff --git a/tabbox/tabbox.cpp b/tabbox/tabbox.cpp index 7b659ff..688ebd9 100644 --- a/tabbox/tabbox.cpp +++ b/tabbox/tabbox.cpp @@ -851,7 +851,7 @@ void TabBox::delayedShow() bool TabBox::handleMouseEvent(xcb_button_press_event_t *e) { - xcb_allow_events(connection(), XCB_ALLOW_ASYNC_POINTER, xTime()); + xcb_allow_events(connection(), XCB_ALLOW_ASYNC_POINTER, XCB_CURRENT_TIME); if (!m_isShown && isDisplayed()) { // tabbox has been replaced, check effects if (effects && static_cast<EffectsHandlerImpl*>(effects)->checkInputWindowEvent(e)) @@ -881,7 +881,7 @@ bool TabBox::handleMouseEvent(xcb_button_press_event_t *e) bool TabBox::handleMouseEvent(xcb_motion_notify_event_t *e) { - xcb_allow_events(connection(), XCB_ALLOW_ASYNC_POINTER, xTime()); + xcb_allow_events(connection(), XCB_ALLOW_ASYNC_POINTER, XCB_CURRENT_TIME); if (!m_isShown && isDisplayed()) { // tabbox has been replaced, check effects if (effects && static_cast<EffectsHandlerImpl*>(effects)->checkInputWindowEvent(e))
one more for the lazy timeupdate... ;-) "ShipIt!" we should maybe seek to reduce xTime() invocation as much as possible and sync on call?
> we should maybe seek to reduce xTime() invocation as much as possible and > sync on call? agree
Git commit b83f63edf211343e93175aa8ba0607c04a2b35e3 by Martin Gräßlin. Committed on 01/06/2014 at 15:20. Pushed by graesslin into branch 'master'. [tabbox] Use XCB_CURRENT_TIME for xcb_allow_event M +2 -2 tabbox/tabbox.cpp http://commits.kde.org/kwin/b83f63edf211343e93175aa8ba0607c04a2b35e3
*** Bug 334876 has been marked as a duplicate of this bug. ***