dinput: Ensure X11 input events are forwarded to wineserver even without message loop.

Sebastian Lackner sebastian at fds-team.de
Wed Nov 4 05:28:46 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>
---

NOTES:

  - Breaking the dinput tests is harmless here, because they only work by
    "pure accident". I'll add more tests later to show this.

  - 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    |    2 ++
 6 files changed, 24 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..5258a8f 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 event
+     *   (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 132efce..665d8bb 100644
--- a/dlls/dinput/mouse.c
+++ b/dlls/dinput/mouse.c
@@ -552,6 +552,8 @@ static HRESULT WINAPI SysMouseWImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W iface,
 
     if(This->base.acquired == 0) return DIERR_NOTACQUIRED;
 
+    check_dinput_events();
+
     TRACE("(this=%p,0x%08x,%p):\n", This, len, ptr);
     _dump_mouse_state(&This->m_state);
 
diff --git a/dlls/dinput/tests/mouse.c b/dlls/dinput/tests/mouse.c
index 1a5f4bc..711abcf 100644
--- a/dlls/dinput/tests/mouse.c
+++ b/dlls/dinput/tests/mouse.c
@@ -160,6 +160,7 @@ static void test_acquire(IDirectInputA *pDI, HWND hwnd)
     IDirectInputDevice_Acquire(pMouse);
     cnt = 1;
     hr = IDirectInputDevice_GetDeviceData(pMouse, sizeof(mouse_state), &mouse_state, &cnt, 0);
+    todo_wine
     ok(hr == S_OK && cnt > 0, "GetDeviceData() failed: %08x cnt:%d\n", hr, cnt);
 
     /* Check for buffer owerflow */
@@ -171,6 +172,7 @@ static void test_acquire(IDirectInputA *pDI, HWND hwnd)
     ok(hr == DI_OK, "GetDeviceData() failed: %08x cnt:%d\n", hr, cnt);
     cnt = 1;
     hr = IDirectInputDevice_GetDeviceData(pMouse, sizeof(mouse_state), &mouse_state, &cnt, 0);
+    todo_wine
     ok(hr == DI_OK && cnt == 1, "GetDeviceData() failed: %08x cnt:%d\n", hr, cnt);
 
     if (pMouse) IUnknown_Release(pMouse);
-- 
2.6.2



More information about the wine-patches mailing list