Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.cpp	(revision 59402)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.cpp	(revision 59403)
@@ -950,5 +950,158 @@
 # elif defined(Q_WS_WIN)
 
-#  warning "implement me!"
+    /* Ignore this event if m_fSkipKeyboardEvents is set by winSkipKeyboardEvents(). */
+    if (m_fSkipKeyboardEvents)
+        return false;
+
+    /* Cast to MSG event: */
+    MSG *pMsg = static_cast<MSG*>(pMessage);
+
+    /* Depending on message type: */
+    switch (pMsg->message)
+    {
+        /* Watch for key-events: */
+        case WM_KEYDOWN:
+        case WM_KEYUP:
+        case WM_SYSKEYDOWN:
+        case WM_SYSKEYUP:
+        {
+            /* Check for our own special flag to ignore this event.
+             * That flag could only be set later in this function
+             * so having it here means this event came here
+             * for the second time already. */
+            if (pMsg->lParam & (0x1 << 25))
+            {
+                /* Remove that flag as well: */
+                pMsg->lParam &= ~(0x1 << 25);
+                fResult = false;
+                break;
+            }
+
+            /* Scan codes 0x80 and 0x00 should be filtered out: */
+            unsigned uScan = (pMsg->lParam >> 16) & 0x7F;
+            if (!uScan)
+            {
+                fResult = true;
+                break;
+            }
+
+            /* Get the virtual key: */
+            int iVKey = pMsg->wParam;
+
+            /* Calculate flags: */
+            int iFlags = 0;
+            if (pMsg->lParam & 0x1000000)
+                iFlags |= KeyExtended;
+            if (!(pMsg->lParam & 0x80000000))
+                iFlags |= KeyPressed;
+
+            /* Make sure AltGr monitor exists: */
+            AssertPtrReturn(m_pAltGrMonitor, false);
+            {
+                /* Filter event out if we are sure that this is a fake left control event: */
+                if (m_pAltGrMonitor->isCurrentEventDefinitelyFake(uScan, iFlags & KeyPressed, iFlags & KeyExtended))
+                {
+                    fResult = true;
+                    break;
+                }
+                /* Update AltGR monitor state from key-event: */
+                m_pAltGrMonitor->updateStateFromKeyEvent(uScan, iFlags & KeyPressed, iFlags & KeyExtended);
+                /* And release left Ctrl key early (if required): */
+                if (m_pAltGrMonitor->isLeftControlReleaseNeeded())
+                    keyboard().PutScancode(0x1D | 0x80);
+            }
+
+            /* Check for special Korean keys. Based on the keyboard layout selected
+             * on the host, the scan code in lParam might be 0x71/0x72 or 0xF1/0xF2.
+             * In either case, we must deliver 0xF1/0xF2 scan code to the guest when
+             * the key is pressed and nothing when it's released. */
+            if (uScan == 0x71 || uScan == 0x72)
+            {
+                uScan |= 0x80;
+                iFlags = KeyPressed;   /* Because a release would be ignored. */
+                iVKey = VK_PROCESSKEY; /* In case it was 0xFF. */
+            }
+
+            /* When one of the SHIFT keys is held and one of the cursor movement
+             * keys is pressed, Windows duplicates SHIFT press/release messages,
+             * but with the virtual keycode set to 0xFF. These virtual keys are also
+             * sent in some other situations (Pause, PrtScn, etc.). Filter out such messages. */
+            if (iVKey == 0xFF)
+            {
+                fResult = true;
+                break;
+            }
+
+            /* Handle special virtual keys: */
+            switch (iVKey)
+            {
+                case VK_SHIFT:
+                case VK_CONTROL:
+                case VK_MENU:
+                {
+                    /* Overcome Win32 modifier key generalization: */
+                    int iKeyscan = uScan;
+                    if (iFlags & KeyExtended)
+                        iKeyscan |= 0xE000;
+                    switch (iKeyscan)
+                    {
+                        case 0x002A: iVKey = VK_LSHIFT;   break;
+                        case 0x0036: iVKey = VK_RSHIFT;   break;
+                        case 0x001D: iVKey = VK_LCONTROL; break;
+                        case 0xE01D: iVKey = VK_RCONTROL; break;
+                        case 0x0038: iVKey = VK_LMENU;    break;
+                        case 0xE038: iVKey = VK_RMENU;    break;
+                    }
+                    break;
+                }
+                case VK_NUMLOCK:
+                    /* Win32 sets the extended bit for the NumLock key. Reset it: */
+                    iFlags &= ~KeyExtended;
+                    break;
+                case VK_SNAPSHOT:
+                    iFlags |= KeyPrint;
+                    break;
+                case VK_PAUSE:
+                    iFlags |= KeyPause;
+                    break;
+            }
+
+            /* Finally, handle parsed key-event: */
+            fResult = keyEvent(iVKey, uScan, iFlags, uScreenId);
+
+            /* Always let Windows see key releases to prevent stuck keys.
+             * Hopefully this won't cause any other issues. */
+            if (pMsg->message == WM_KEYUP || pMsg->message == WM_SYSKEYUP)
+            {
+                fResult = false;
+                break;
+            }
+
+            /* Above keyEvent() returned that it didn't processed the event, but since the
+             * keyboard is captured, we don't want to pass it to Windows. We just want
+             * to let Qt process the message (to handle non-alphanumeric <HOST>+key
+             * shortcuts for example). So send it directly to the window with the
+             * special flag in the reserved area of lParam (to avoid recursion). */
+            if (!fResult && m_fIsKeyboardCaptured)
+            {
+                ::SendMessage(pMsg->hwnd, pMsg->message,
+                              pMsg->wParam, pMsg->lParam | (0x1 << 25));
+                fResult = true;
+                break;
+            }
+
+            /* These special keys have to be handled by Windows as well to update the
+             * internal modifier state and to enable/disable the keyboard LED: */
+            if (iVKey == VK_NUMLOCK || iVKey == VK_CAPITAL || iVKey == VK_LSHIFT || iVKey == VK_RSHIFT)
+            {
+                fResult = false;
+                break;
+            }
+
+            break;
+        }
+        default:
+            break;
+    }
 
 # elif defined(Q_WS_X11)
@@ -1497,5 +1650,7 @@
     long dummyResult;
     return m_views[m_iKeyboardHookViewIndex]->winEvent(&message, &dummyResult);
-#endif /* QT_VERSION < 0x050000 */
+#else /* QT_VERSION >= 0x050000 */
+    return m_views[m_iKeyboardHookViewIndex]->nativeEvent(&message);
+#endif /* QT_VERSION >= 0x050000 */
 }
 
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp	(revision 59402)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.cpp	(revision 59403)
@@ -72,9 +72,9 @@
 
 /* Qt includes: */
-#ifdef Q_WS_X11
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
 # if QT_VERSION >= 0x050000
 #  include <QAbstractNativeEventFilter>
 # endif /* QT_VERSION >= 0x050000 */
-#endif /* Q_WS_X11 */
+#endif /* Q_WS_WIN || Q_WS_X11 */
 
 /* GUI includes: */
@@ -130,5 +130,5 @@
 
 
-#ifdef Q_WS_X11
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
 # if QT_VERSION >= 0x050000
 /** QAbstractNativeEventFilter extension
@@ -147,5 +147,6 @@
     {
         /* Redirect event to parent: */
-        return m_pParent->nativeEvent(eventType, pMessage, pResult);
+        Q_UNUSED(eventType); Q_UNUSED(pResult);
+        return m_pParent->nativeEvent(pMessage);
     }
 
@@ -156,5 +157,5 @@
 };
 # endif /* QT_VERSION >= 0x050000 */
-#endif /* Q_WS_X11 */
+#endif /* Q_WS_WIN || Q_WS_X11 */
 
 
@@ -661,9 +662,9 @@
     , m_fIsDraggingFromGuest(false)
 #endif
-#ifdef Q_WS_X11
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
 # if QT_VERSION >= 0x050000
     , m_pPrivateEventFilter(0)
 # endif /* QT_VERSION >= 0x050000 */
-#endif /* Q_WS_X11 */
+#endif /* Q_WS_WIN || Q_WS_X11 */
 {
 }
@@ -843,5 +844,5 @@
     machineWindow()->installEventFilter(this);
 
-#ifdef Q_WS_X11
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
 # if QT_VERSION >= 0x050000
     /* Prepare private event-filter: */
@@ -849,5 +850,5 @@
     qApp->installNativeEventFilter(m_pPrivateEventFilter);
 # endif /* QT_VERSION >= 0x050000 */
-#endif /* Q_WS_X11 */
+#endif /* Q_WS_WIN || Q_WS_X11 */
 }
 
@@ -879,5 +880,5 @@
 void UIMachineView::cleanupFilters()
 {
-#ifdef Q_WS_X11
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
 # if QT_VERSION >= 0x050000
     /* Cleanup private event-filter: */
@@ -886,5 +887,5 @@
     m_pPrivateEventFilter = 0;
 # endif /* QT_VERSION >= 0x050000 */
-#endif /* Q_WS_X11 */
+#endif /* Q_WS_WIN || Q_WS_X11 */
 }
 
@@ -1884,5 +1885,5 @@
 #else /* QT_VERSION >= 0x050000 */
 
-bool UIMachineView::nativeEvent(const QByteArray &eventType, void *pMessage, long *pResult)
+bool UIMachineView::nativeEvent(void *pMessage)
 {
 # if defined(Q_WS_MAC)
@@ -1892,5 +1893,24 @@
 # elif defined(Q_WS_WIN)
 
-#  warning "implement me!"
+    /* Cast to generic MSG event: */
+    MSG *pEvent = static_cast<MSG*>(pMessage);
+
+    /* Check if some MSG event should be filtered out.
+     * Returning @c true means filtering-out,
+     * Returning @c false means passing event to Qt. */
+    switch (pEvent->message)
+    {
+        /* Watch for key-events: */
+        case WM_KEYDOWN:
+        case WM_SYSKEYDOWN:
+        case WM_KEYUP:
+        case WM_SYSKEYUP:
+        {
+            /* Delegate key-event handling to the keyboard-handler: */
+            return machineLogic()->keyboardHandler()->nativeEventFilter(pMessage, screenId());
+        }
+        default:
+            break;
+    }
 
 # elif defined(Q_WS_X11)
Index: /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.h
===================================================================
--- /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.h	(revision 59402)
+++ /trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineView.h	(revision 59403)
@@ -60,8 +60,11 @@
 # if QT_VERSION < 0x050000
 typedef union _XEvent XEvent;
-# else /* QT_VERSION >= 0x050000 */
+# endif /* QT_VERSION < 0x050000 */
+#endif /* Q_WS_X11 */
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
+# if QT_VERSION >= 0x050000
 class PrivateEventFilter;
 # endif /* QT_VERSION >= 0x050000 */
-#endif /* Q_WS_X11 */
+#endif /* Q_WS_WIN || Q_WS_X11 */
 #ifdef VBOX_WITH_DRAG_AND_DROP
  class CDnDTarget;
@@ -372,5 +375,5 @@
       *           the Qt itself because it has another signature,
       *           only by the keyboard-hook of the keyboard-handler. */
-    virtual bool nativeEvent(const QByteArray &eventType, void *pMessage, long *pResult);
+    virtual bool nativeEvent(void *pMessage);
 #endif /* QT_VERSION >= 0x050000 */
 
@@ -430,5 +433,5 @@
 #endif
 
-#ifdef Q_WS_X11
+#if defined(Q_WS_WIN) || defined(Q_WS_X11)
 # if QT_VERSION >= 0x050000
     /** X11: Holds the native event filter instance. */
@@ -438,5 +441,5 @@
     friend class PrivateEventFilter;
 # endif /* QT_VERSION >= 0x050000 */
-#endif /* Q_WS_X11 */
+#endif /* Q_WS_WIN || Q_WS_X11 */
 
     /* Friend classes: */
