Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.cpp	(revision 64830)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.cpp	(revision 64831)
@@ -366,13 +366,14 @@
          * This stuff is a part of the active keyboard grabbing functionality.
          * Active keyboard grabbing causes a problems on many window managers - a window cannot
-         * be moved using the mouse. So we additionally grabbing the mouse as well to detect that
-         * user is trying to click outside of internal window geometry. */
-
-         /* Grab the mouse button if the cursor is outside of our views.
+         * be moved using the mouse. So we additionally grab the mouse buttons as well to detect
+         * that the user is trying to click outside of the internal window geometry and release
+         * the keyboard before the target window sees the click. (GNOME Shell's hot corner has
+         * the same problem. At present we just let that problem be.) */
+
+         /* Grab the mouse button.
           * We do not check for failure as we do not currently implement a back-up plan. */
-         if (!isItListenedView(QApplication::widgetAt(QCursor::pos())))
-             xcb_grab_button_checked(QX11Info::connection(), 0, QX11Info::appRootWindow(),
-                                     XCB_EVENT_MASK_BUTTON_PRESS, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC,
-                                     XCB_NONE, XCB_NONE, XCB_BUTTON_INDEX_ANY, XCB_MOD_MASK_ANY);
+         xcb_grab_button_checked(QX11Info::connection(), 0, QX11Info::appRootWindow(),
+                                 XCB_EVENT_MASK_BUTTON_PRESS, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC,
+                                 XCB_NONE, XCB_NONE, XCB_BUTTON_INDEX_ANY, XCB_MOD_MASK_ANY);
         /* And grab the keyboard, using XCB directly, as Qt does not report failure. */
         xcb_grab_keyboard_cookie_t xcbGrabCookie = xcb_grab_keyboard(QX11Info::connection(), false, m_views[m_iKeyboardCaptureViewIndex]->winId(),
@@ -1774,26 +1775,4 @@
                 break;
             }
-#if defined(VBOX_WS_X11) && QT_VERSION >= 0x050000
-            case QEvent::Enter:
-            {
-                /* Release the mouse button grab.
-                 * We do not check for failure as we do not currently implement a back-up plan. */
-                xcb_ungrab_button_checked(QX11Info::connection(), XCB_BUTTON_INDEX_ANY,
-                                          QX11Info::appRootWindow(), XCB_MOD_MASK_ANY);
-
-                break;
-            }
-            case QEvent::Leave:
-            {
-                /* Grab the mouse button if the keyboard is captured.
-                 * We do not check for failure as we do not currently implement a back-up plan. */
-                if (m_fIsKeyboardCaptured)
-                    xcb_grab_button_checked(QX11Info::connection(), 0, QX11Info::appRootWindow(),
-                                            XCB_EVENT_MASK_BUTTON_PRESS, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC,
-                                            XCB_NONE, XCB_NONE, XCB_BUTTON_INDEX_ANY, XCB_MOD_MASK_ANY);
-
-                break;
-            }
-#endif /* VBOX_WS_X11 && QT_VERSION >= 0x050000 */
             case QEvent::KeyPress:
             case QEvent::KeyRelease:
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.cpp	(revision 64830)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMouseHandler.cpp	(revision 64831)
@@ -375,33 +375,28 @@
                 break;
 
-            /* If we see a mouse press outside of our views while the mouse is not
-             * captured, release the keyboard before letting the event owner see it.
-             * This is because some owners cannot deal with failures to grab the
-             * keyboard themselves (e.g. window managers dragging windows).
-             * Only works if we have passively grabbed the mouse button. */
+            /* If we see a mouse press from a grab while the mouse is not captured,
+             * release the keyboard before letting the event owner see it. This is
+             * because some owners cannot deal with failures to grab the keyboard
+             * themselves (e.g. window managers dragging windows). */
 
             /* Cast to XCB button-event: */
             xcb_button_press_event_t *pButtonEvent = static_cast<xcb_button_press_event_t*>(pMessage);
 
-            /* Detect the widget which should receive the event actually: */
-            const QWidget *pWidget = qApp->widgetAt(pButtonEvent->root_x, pButtonEvent->root_y);
-            if (pWidget)
+            /* If this event is from our button grab then it will be reported relative to the root
+             * window and not to ours. In that case release the keyboard capture, re-capture it
+             * delayed, which will fail if we have lost the input focus in the mean-time, replay
+             * the button event for normal delivery (possibly straight back to us, but not relative
+             * to root this time) and tell Qt not to further process this event: */
+            if (pButtonEvent->event == pButtonEvent->root)
             {
-                /* Redirect the event to corresponding widget: */
-                const QPoint pos = pWidget->mapFromGlobal(QPoint(pButtonEvent->root_x, pButtonEvent->root_y));
-                pButtonEvent->event = pWidget->effectiveWinId();
-                pButtonEvent->event_x = pos.x();
-                pButtonEvent->event_y = pos.y();
-                xcb_ungrab_pointer_checked(QX11Info::connection(), pButtonEvent->time);
-                break;
+                machineLogic()->keyboardHandler()->releaseKeyboard();
+                /** @todo It would be nicer to do this in the normal Qt button event
+                  *       handler to avoid avoidable races if the event was not for us. */
+                machineLogic()->keyboardHandler()->captureKeyboard(uScreenId);
+                /* Re-send the event so that the window which it was meant for gets it: */
+                xcb_allow_events_checked(QX11Info::connection(), XCB_ALLOW_REPLAY_POINTER, pButtonEvent->time);
+                /* Do not let Qt see the event: */
+                return true;
             }
-            /* Else if the event happened outside of our view areas then release the keyboard,
-             * but capture it again (delayed) immediately. If the event causes us to loose the
-             * focus then the delayed capture will not happen: */
-            machineLogic()->keyboardHandler()->releaseKeyboard();
-            machineLogic()->keyboardHandler()->captureKeyboard(uScreenId);
-            /* And re-send the event so that the window which it was meant for actually gets it: */
-            xcb_allow_events_checked(QX11Info::connection(), XCB_ALLOW_REPLAY_POINTER, pButtonEvent->time);
-            break;
         }
         default:
@@ -761,4 +756,14 @@
                 {
                     QMouseEvent *pMouseEvent = static_cast<QMouseEvent*>(pEvent);
+#if defined(VBOX_WS_X11) && QT_VERSION >= 0x050000
+                    /* When the keyboard is captured, we also capture mouse button
+                     * events, and release the keyboard and re-capture it delayed
+                     * on every mouse click. When the click is inside our window
+                     * area though the delay is not needed or wanted. Calling
+                     * finaliseCaptureKeyboard() skips the delay if a delayed
+                     * capture is in progress and has no effect if not: */
+                    if (pEvent->type() == QEvent::MouseButtonPress)
+                        machineLogic()->keyboardHandler()->finaliseCaptureKeyboard();
+#endif /* VBOX_WS_X11 && QT_VERSION >= 0x050000 */
                     m_iLastMouseWheelDelta = 0;
                     if (mouseEvent(pMouseEvent->type(), uScreenId,
