Patch [#26799] embedded blenderplayer not receiving keyboard input by Sebastian Korczak
authorDalai Felinto <dfelinto@gmail.com>
Sat, 7 May 2011 22:28:56 +0000 (22:28 +0000)
committerDalai Felinto <dfelinto@gmail.com>
Sat, 7 May 2011 22:28:56 +0000 (22:28 +0000)
(patch co-reviewed by Nathan Letwory)

Overview: GHOST using rawinput for keyboard input. GHOST window receives WM_INPUT only when it is the active window. Child window cannot be active, so when embedding blenderplayer, WM_INPUT is consumed by top level parent window (for Burster it is the web browser window). Patch register raw input device as 'inputsink' - it makes GHOST window receives all keyboard messages. Window procedure check if GHOST window is active or focused.

::TranslateMessage(&msg) generates WM_CHAR etc. messages from WM_KEYDOWN, WM_KEYUP etc. Because of using RawInput only WM_INPUT messages are processed, so we doesn't need WM_CHAR, WM_KEYDOWN etc. [this is why ::TranslateMessage is no longer getting called].

Note: It's responsibility of the parent window (aka the wrapper) to send WM_SETFOCUS to child window (embedded blenderplayer).
However some parent windows (e.g. webbrowsers) will not send WM_SETFOCUS to the child window when someone clicks on it.
In those cases the blenderplayer needs to be patched to call setFocus(&msg); in the event of WM_LBUTTONDOWN (see GHOST_SystemWin32.cpp)

intern/ghost/intern/GHOST_SystemWin32.cpp
intern/ghost/intern/GHOST_WindowWin32.cpp

index 2fdddda835dadfdcb3d1077ecb62eb1b819e44b6..455a166ece0926f72f962b7df25d43faefe65799 100644 (file)
@@ -304,7 +304,6 @@ bool GHOST_SystemWin32::processEvents(bool waitForEvent)
 
                // Process all the events waiting for us
                while (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE) != 0) {
-                       ::TranslateMessage(&msg);
                        ::DispatchMessage(&msg);
                        anyProcessed = true;
                }
@@ -819,6 +818,11 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
                                // Keyboard events, processed
                                ////////////////////////////////////////////////////////////////////////
                                case WM_INPUT:
+                                       // check WM_INPUT from input sink when ghost window is not in the foreground
+                                       if (wParam == RIM_INPUTSINK) {
+                                               if (GetFocus() != hwnd) // WM_INPUT message not for this window
+                                                       return 0;
+                                       } //else wPAram == RIM_INPUT
                                        event = processKeyEvent(window, wParam, lParam);
                                        if (!event) {
                                                GHOST_PRINT("GHOST_SystemWin32::wndProc: key event ")
index a89b2608bb45c1136ab323dc79037d584d532a69..aae1509fda15ec3d5aeb9526a3ce810e7bef3002 100644 (file)
@@ -307,6 +307,15 @@ GHOST_WindowWin32::GHOST_WindowWin32(
                }
        }
 
+       if (parentwindowhwnd != 0) {
+               RAWINPUTDEVICE device = {0};
+               device.usUsagePage      = 0x01; /* usUsagePage & usUsage for keyboard*/
+               device.usUsage          = 0x06; /* http://msdn.microsoft.com/en-us/windows/hardware/gg487473.aspx */
+               device.dwFlags |= RIDEV_INPUTSINK; // makes WM_INPUT is visible for ghost when has parent window
+               device.hwndTarget = m_hWnd;
+               RegisterRawInputDevices(&device, 1, sizeof(device));
+       }
+
        m_wintab = ::LoadLibrary("Wintab32.dll");
        if (m_wintab) {
                GHOST_WIN32_WTInfo fpWTInfo = ( GHOST_WIN32_WTInfo ) ::GetProcAddress( m_wintab, "WTInfoA" );