[DINPUT] Sync with Wine Staging 1.7.55. CORE-10536
authorAmine Khaldi <amine.khaldi@reactos.org>
Tue, 24 Nov 2015 10:51:48 +0000 (10:51 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Tue, 24 Nov 2015 10:51:48 +0000 (10:51 +0000)
svn path=/trunk/; revision=70086

reactos/dll/directx/wine/dinput/device.c
reactos/dll/directx/wine/dinput/dinput_main.c
reactos/dll/directx/wine/dinput/dinput_private.h
reactos/dll/directx/wine/dinput/keyboard.c
reactos/dll/directx/wine/dinput/mouse.c
reactos/media/doc/README.WINE

index 82059a3..b33286a 100644 (file)
@@ -1618,13 +1618,8 @@ HRESULT WINAPI IDirectInputDevice2WImpl_Poll(LPDIRECTINPUTDEVICE8W iface)
 
     if (!This->acquired) return DIERR_NOTACQUIRED;
 
-#ifndef __REACTOS__
-    __wine_check_for_events( QS_ALLINPUT );
+    check_dinput_events();
     return DI_OK;
-#else
-    /* Devices do not need to be polled on ReactOS. */
-    return DI_NOEFFECT;
-#endif
 }
 
 HRESULT WINAPI IDirectInputDevice2AImpl_Poll(LPDIRECTINPUTDEVICE8A iface)
index 8d24efb..c63ab38 100644 (file)
@@ -320,6 +320,39 @@ static DWORD diactionformat_priorityW(LPDIACTIONFORMATW lpdiaf, DWORD genre)
     return priorityFlags;
 }
 
+#if defined __i386__ && defined _MSC_VER
+__declspec(naked) BOOL enum_callback_wrapper(void *callback, const void *instance, void *ref)
+{
+    __asm
+    {
+        push ebp
+        mov ebp, esp
+        push [ebp+16]
+        push [ebp+12]
+        call [ebp+8]
+        leave
+        ret
+    }
+}
+#elif defined __i386__ && defined __GNUC__
+extern BOOL enum_callback_wrapper(void *callback, const void *instance, void *ref);
+__ASM_GLOBAL_FUNC( enum_callback_wrapper,
+    "pushl %ebp\n\t"
+    __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
+    __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
+    "movl %esp,%ebp\n\t"
+    __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
+    "pushl 16(%ebp)\n\t"
+    "pushl 12(%ebp)\n\t"
+    "call *8(%ebp)\n\t"
+    "leave\n\t"
+    __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
+    __ASM_CFI(".cfi_same_value %ebp\n\t")
+    "ret" )
+#else
+#define enum_callback_wrapper(callback, instance, ref) (callback)((instance), (ref))
+#endif
+
 /******************************************************************************
  *     IDirectInputA_EnumDevices
  */
@@ -352,7 +385,7 @@ static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
             TRACE("  - checking device %u ('%s')\n", i, dinput_devices[i]->name);
             r = dinput_devices[i]->enum_deviceA(dwDevType, dwFlags, &devInstance, This->dwVersion, j);
             if (r == S_OK)
-                if (lpCallback(&devInstance,pvRef) == DIENUM_STOP)
+                if (enum_callback_wrapper(lpCallback, &devInstance, pvRef) == DIENUM_STOP)
                     return S_OK;
         }
     }
@@ -392,7 +425,7 @@ static HRESULT WINAPI IDirectInputWImpl_EnumDevices(
             TRACE("  - checking device %u ('%s')\n", i, dinput_devices[i]->name);
             r = dinput_devices[i]->enum_deviceW(dwDevType, dwFlags, &devInstance, This->dwVersion, j);
             if (r == S_OK)
-                if (lpCallback(&devInstance,pvRef) == DIENUM_STOP)
+                if (enum_callback_wrapper(lpCallback, &devInstance, pvRef) == DIENUM_STOP)
                     return S_OK;
         }
     }
@@ -1464,7 +1497,7 @@ static DWORD WINAPI hook_thread_proc(void *param)
 
     /* Force creation of the message queue */
     PeekMessageW( &msg, 0, 0, 0, PM_NOREMOVE );
-    SetEvent(*(LPHANDLE)param);
+    SetEvent(param);
 
     while (GetMessageW( &msg, 0, 0, 0 ))
     {
@@ -1532,6 +1565,7 @@ static DWORD WINAPI hook_thread_proc(void *param)
 }
 
 static DWORD hook_thread_id;
+static HANDLE hook_thread_event;
 
 static CRITICAL_SECTION_DEBUG dinput_critsect_debug =
 {
@@ -1550,24 +1584,21 @@ static BOOL check_hook_thread(void)
     TRACE("IDirectInputs left: %d\n", list_count(&direct_input_list));
     if (!list_empty(&direct_input_list) && !hook_thread)
     {
-        HANDLE event;
-
-        event = CreateEventW(NULL, FALSE, FALSE, NULL);
-        hook_thread = CreateThread(NULL, 0, hook_thread_proc, &event, 0, &hook_thread_id);
-        if (event && hook_thread)
-        {
-            HANDLE handles[2];
-            handles[0] = event;
-            handles[1] = hook_thread;
-            WaitForMultipleObjects(2, handles, FALSE, INFINITE);
-        }
+        hook_thread_event = CreateEventW(NULL, FALSE, FALSE, NULL);
+        hook_thread = CreateThread(NULL, 0, hook_thread_proc, hook_thread_event, 0, &hook_thread_id);
         LeaveCriticalSection(&dinput_hook_crit);
-        CloseHandle(event);
     }
     else if (list_empty(&direct_input_list) && hook_thread)
     {
         DWORD tid = hook_thread_id;
 
+        if (hook_thread_event) /* if thread is not started yet */
+        {
+            WaitForSingleObject(hook_thread_event, INFINITE);
+            CloseHandle(hook_thread_event);
+            hook_thread_event = NULL;
+        }
+
         hook_thread_id = 0;
         PostThreadMessageW(tid, WM_USER+0x10, 0, 0);
         LeaveCriticalSection(&dinput_hook_crit);
@@ -1608,11 +1639,34 @@ void check_dinput_hooks(LPDIRECTINPUTDEVICE8W iface)
         callwndproc_hook = NULL;
     }
 
+    if (hook_thread_event) /* if thread is not started yet */
+    {
+        WaitForSingleObject(hook_thread_event, INFINITE);
+        CloseHandle(hook_thread_event);
+        hook_thread_event = NULL;
+    }
+
     PostThreadMessageW( hook_thread_id, WM_USER+0x10, 1, 0 );
 
     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)
+     */
+#ifndef __REACTOS__
+    MsgWaitForMultipleObjectsEx(0, NULL, 0, QS_ALLINPUT, 0);
+#endif
+}
+
 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved)
 {
     switch(reason)
index 2c4b7de..a4692a4 100644 (file)
@@ -79,6 +79,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;
index 294ccfd..ec7a58a 100644 (file)
@@ -319,9 +319,7 @@ static HRESULT WINAPI SysKeyboardWImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W ifac
     if (len != This->base.data_format.user_df->dwDataSize )
         return DIERR_INVALIDPARAM;
 
-#ifndef __REACTOS__
-    __wine_check_for_events( QS_ALLINPUT );
-#endif
+    check_dinput_events();
 
     EnterCriticalSection(&This->base.crit);
 
index 73f7b58..bcf9e13 100644 (file)
@@ -530,17 +530,15 @@ static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
 static HRESULT WINAPI SysMouseWImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W iface, DWORD len, LPVOID ptr)
 {
     SysMouseImpl *This = impl_from_IDirectInputDevice8W(iface);
+    TRACE("(%p)->(%u,%p)\n", This, len, ptr);
 
     if(This->base.acquired == 0) return DIERR_NOTACQUIRED;
 
-#ifndef __REACTOS__
-    __wine_check_for_events( QS_ALLINPUT );
-#endif
+    check_dinput_events();
 
-    TRACE("(this=%p,0x%08x,%p):\n", This, len, ptr);
+    EnterCriticalSection(&This->base.crit);
     _dump_mouse_state(&This->m_state);
 
-    EnterCriticalSection(&This->base.crit);
     /* Copy the current mouse state */
     fill_DataFormat(ptr, len, &This->m_state, &This->base.data_format);
 
index 2067101..b9b561d 100644 (file)
@@ -30,7 +30,7 @@ reactos/dll/directx/wine/d3dx9_24 => 43 # Synced to WineStaging-1.7.55
 reactos/dll/directx/wine/d3dxof         # Synced to WineStaging-1.7.47
 reactos/dll/directx/wine/ddraw          # Synced to WineStaging-1.7.55
 reactos/dll/directx/wine/devenum        # Synced to WineStaging-1.7.55
-reactos/dll/directx/wine/dinput         # Synced to WineStaging-1.7.47
+reactos/dll/directx/wine/dinput         # Synced to WineStaging-1.7.55
 reactos/dll/directx/wine/dinput8        # Synced to WineStaging-1.7.47
 reactos/dll/directx/wine/dmusic         # Synced to WineStaging-1.7.47
 reactos/dll/directx/wine/dplay          # Synced to WineStaging-1.7.47