wine-staging/patches/dinput-Events/0001-dinput-Ensure-X11-input-events-are-handled-even-with.patch

104 lines
4.3 KiB
Diff

From 278d2cd8f466e786bed9fa4a621d627c20c83b8d Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Thu, 18 Dec 2014 01:04:34 +0100
Subject: dinput: Ensure X11 input events are handled even without explicit
message loop. (v4)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This commit basically reverts b22ff8018aca7c365e505f1db7732f7050ae259b.
Michael Müller did a full analysis of this problem, which reveals that the issue
is caused by the way user32 and winex11 works. Wine establishes separate X server
connections for each thread, so each thread needs to call
USER_Driver->pMsgWaitForMultipleObjectsEx from time to time to ensure that events
are properly forwarded to the wineserver. On Windows all this isn't necessary
because the kernel itself is responsible for generating window events, and there
is no need to pass them from the application to the kernel.
A proper fix would mean to rewrite winex11 to always handle X11 events
asynchronously, and without explicit need for a message loop. Since such a rewrite
is rather unlikely and will not happen during the near future, adding a workaround
till a better solution is found. This workaround will have no disadvantage, except
that this isn't a complete fix. Please note that not only hooks are affected by
this issue, also *RawInput* functions show the same issue - which is the reason why
native dinput will still not work (already tested).
Since games use very different code in order to query for input events, we have to
call __wine_check_for_events from multiple locations in the code. See:
* https://bugs.wine-staging.com/show_bug.cgi?id=42
* https://bugs.wine-staging.com/show_bug.cgi?id=149
---
dlls/dinput/device.c | 5 +++--
dlls/dinput/keyboard.c | 2 ++
dlls/dinput/mouse.c | 2 ++
dlls/dinput/tests/mouse.c | 2 ++
4 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index ab43029..501eae8 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;
+
+ MsgWaitForMultipleObjectsEx(0, NULL, 0, QS_ALLINPUT, 0);
+ return DI_OK;
}
HRESULT WINAPI IDirectInputDevice2AImpl_Poll(LPDIRECTINPUTDEVICE8A iface)
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c
index f3ac30e..1e273f6 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;
+ MsgWaitForMultipleObjectsEx(0, NULL, 0, QS_ALLINPUT, 0);
+
EnterCriticalSection(&This->base.crit);
if (TRACE_ON(dinput)) {
diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c
index 132efce..8126c1e 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;
+ MsgWaitForMultipleObjectsEx(0, NULL, 0, QS_ALLINPUT, 0);
+
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.1