[2/2] dinput: Ensure X11 input events are forwarded to wineserver even without message loop. (v2)

Sebastian Lackner sebastian at fds-team.de
Thu Nov 5 08:57:29 CST 2015


This commit basically reverts b22ff8018aca7c365e505f1db7732f7050ae259b.

Windows does not do that, but our current implementation of winex11
requires periodic event polling to forward events to the wineserver.

Signed-off-by: Sebastian Lackner <sebastian at fds-team.de>
Signed-off-by: Michael Müller <michael at fds-team.de>
---

Changes in v2:

* Do not remove todo_wine, instead flush window events after CreateWindow.
  With my window manager there is otherwise a focus loss event somewhere
  in the middle of the tests.

NOTES:

- Adding it to the warp check is not sufficient, because some games
  do not trigger this code.

- A similar version of the patch was in the Staging tree for a long
  time, and no performance slowdown regressions have been reported
  so far. However, if there are such reports during the stable testing
  period, additional checks can be added easily, to call
  MsgWaitForMultipleObjectsEx() less frequently. I'm hesitating a bit
  to add this right now, because user input could feel delayed.

- This version of the patch has been tested for > 2 weeks, without
  any regression reports.

- Yes, I asked Michael before adding his signoff. I still take
  responsibility for any regressions this patch might cause.

 dlls/dinput/device.c         |    5 +++--
 dlls/dinput/dinput_main.c    |   14 ++++++++++++++
 dlls/dinput/dinput_private.h |    1 +
 dlls/dinput/keyboard.c       |    2 ++
 dlls/dinput/mouse.c          |    2 ++
 dlls/dinput/tests/mouse.c    |    3 +++
 6 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index ab43029..1ba6ffc 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -1631,8 +1631,9 @@ HRESULT WINAPI IDirectInputDevice2WImpl_Poll(LPDIRECTINPUTDEVICE8W iface)
     IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
 
     if (!This->acquired) return DIERR_NOTACQUIRED;
-    /* Because wine devices do not need to be polled, just return DI_NOEFFECT */
-    return DI_NOEFFECT;
+
+    check_dinput_events();
+    return DI_OK;
 }
 
 HRESULT WINAPI IDirectInputDevice2AImpl_Poll(LPDIRECTINPUTDEVICE8A iface)
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index 18840b2..cdd5afe 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -1632,6 +1632,20 @@ void check_dinput_hooks(LPDIRECTINPUTDEVICE8W iface)
     LeaveCriticalSection(&dinput_hook_crit);
 }
 
+void check_dinput_events(void)
+{
+    /* Windows does not do that, but our current implementation of winex11
+     * requires periodic event polling to forward events to the wineserver.
+     *
+     * We have to call this function from multiple places, because:
+     * - some games do not explicitly poll for mouse events
+     *   (for example Culpa Innata)
+     * - some games only poll the device, and neither keyboard nor mouse
+     *   (for example Civilization: Call to Power 2)
+     */
+    MsgWaitForMultipleObjectsEx(0, NULL, 0, QS_ALLINPUT, 0);
+}
+
 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved)
 {
     switch(reason)
diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h
index 022a7a9..176c0e0 100644
--- a/dlls/dinput/dinput_private.h
+++ b/dlls/dinput/dinput_private.h
@@ -63,6 +63,7 @@ extern const struct dinput_device joystick_linuxinput_device DECLSPEC_HIDDEN;
 extern const struct dinput_device joystick_osx_device DECLSPEC_HIDDEN;
 
 extern void check_dinput_hooks(LPDIRECTINPUTDEVICE8W) DECLSPEC_HIDDEN;
+extern void check_dinput_events(void) DECLSPEC_HIDDEN;
 typedef int (*DI_EVENT_PROC)(LPDIRECTINPUTDEVICE8A, WPARAM, LPARAM);
 
 extern void _copy_diactionformatAtoW(LPDIACTIONFORMATW, LPDIACTIONFORMATA) DECLSPEC_HIDDEN;
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c
index f3ac30e..4c3c38e 100644
--- a/dlls/dinput/keyboard.c
+++ b/dlls/dinput/keyboard.c
@@ -335,6 +335,8 @@ static HRESULT WINAPI SysKeyboardWImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W ifac
     if (len != This->base.data_format.user_df->dwDataSize )
         return DIERR_INVALIDPARAM;
 
+    check_dinput_events();
+
     EnterCriticalSection(&This->base.crit);
 
     if (TRACE_ON(dinput)) {
diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c
index 17f313f..c86ca31 100644
--- a/dlls/dinput/mouse.c
+++ b/dlls/dinput/mouse.c
@@ -553,6 +553,8 @@ static HRESULT WINAPI SysMouseWImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W iface,
 
     if(This->base.acquired == 0) return DIERR_NOTACQUIRED;
 
+    check_dinput_events();
+
     EnterCriticalSection(&This->base.crit);
     _dump_mouse_state(&This->m_state);
 
diff --git a/dlls/dinput/tests/mouse.c b/dlls/dinput/tests/mouse.c
index 1a5f4bc..34940e4 100644
--- a/dlls/dinput/tests/mouse.c
+++ b/dlls/dinput/tests/mouse.c
@@ -93,6 +93,7 @@ static void test_acquire(IDirectInputA *pDI, HWND hwnd)
     DIPROPDWORD di_op;
     DIDEVICEOBJECTDATA mouse_state;
     DWORD cnt;
+    MSG msg;
     int i;
 
     if (! SetForegroundWindow(hwnd))
@@ -130,6 +131,8 @@ static void test_acquire(IDirectInputA *pDI, HWND hwnd)
      * loose mouse input */
     hwnd2 = CreateWindowA("static", "Temporary", WS_VISIBLE, 10, 210, 200, 200, NULL, NULL, NULL,
                           NULL);
+    ok(hwnd2 != NULL, "CreateWindowA failed with %u\n", GetLastError());
+    while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) DispatchMessageA(&msg);
 
     hr = IDirectInputDevice_GetDeviceState(pMouse, sizeof(m_state), &m_state);
     ok(hr == DIERR_NOTACQUIRED, "GetDeviceState() should have failed: %08x\n", hr);
-- 
2.6.2



More information about the wine-patches mailing list