0,0 → 1,594 |
http://bugs.winehq.org/show_bug.cgi?id=6971 |
|
diff --git a/configure b/configure |
index 9b1cb22..05baa8d 100755 |
--- a/configure |
+++ b/configure |
@@ -7972,6 +7972,7 @@ fi |
X11/Xcursor/Xcursor.h \ |
X11/extensions/shape.h \ |
X11/extensions/XInput.h \ |
+ X11/extensions/XInput2.h \ |
X11/extensions/XShm.h \ |
X11/extensions/Xcomposite.h \ |
X11/extensions/Xinerama.h \ |
@@ -8168,6 +8169,61 @@ This is an error since --with-xinput was requested." "$LINENO" 5 ;; |
esac |
fi |
|
+ if test "$ac_cv_header_X11_extensions_XInput2_h" = "yes" |
+ then |
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for XIQueryVersion in -lXi" >&5 |
+$as_echo_n "checking for XIQueryVersion in -lXi... " >&6; } |
+if test "${ac_cv_lib_Xi_XIQueryVersion+set}" = set; then : |
+ $as_echo_n "(cached) " >&6 |
+else |
+ ac_check_lib_save_LIBS=$LIBS |
+LIBS="-lXi $X_LIBS $XLIB $X_EXTRA_LIBS $LIBS" |
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext |
+/* end confdefs.h. */ |
+ |
+/* Override any GCC internal prototype to avoid an error. |
+ Use char because int might match the return type of a GCC |
+ builtin and then its argument prototype would still apply. */ |
+#ifdef __cplusplus |
+extern "C" |
+#endif |
+char XIQueryVersion (); |
+int |
+main () |
+{ |
+return XIQueryVersion (); |
+ ; |
+ return 0; |
+} |
+_ACEOF |
+if ac_fn_c_try_link "$LINENO"; then : |
+ ac_cv_lib_Xi_XIQueryVersion=yes |
+else |
+ ac_cv_lib_Xi_XIQueryVersion=no |
+fi |
+rm -f core conftest.err conftest.$ac_objext \ |
+ conftest$ac_exeext conftest.$ac_ext |
+LIBS=$ac_check_lib_save_LIBS |
+fi |
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_Xi_XIQueryVersion" >&5 |
+$as_echo "$ac_cv_lib_Xi_XIQueryVersion" >&6; } |
+if test "x$ac_cv_lib_Xi_XIQueryVersion" = x""yes; then : |
+ |
+$as_echo "#define HAVE_LIBXINPUT2 1" >>confdefs.h |
+ |
+fi |
+ |
+ |
+ fi |
+ if test "$ac_cv_lib_Xi_XIQueryVersion" != "yes"; then : |
+ case "x$with_xinput2" in |
+ x) as_fn_append wine_notices "|libxi ${notice_platform}development files not found, the Xinput2 extension won't be supported." ;; |
+ xno) ;; |
+ *) as_fn_error "libxi ${notice_platform}development files not found, the Xinput2 extension won't be supported. |
+This is an error since --with-xinput2 was requested." "$LINENO" 5 ;; |
+esac |
+fi |
+ |
if test "$ac_cv_header_X11_extensions_XShm_h" = "yes" |
then |
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for XShmQueryExtension in -lXext" >&5 |
diff --git a/configure.ac b/configure.ac |
index 04ed14f..0d4410a 100644 |
--- a/configure.ac |
+++ b/configure.ac |
@@ -897,6 +897,7 @@ then |
X11/Xcursor/Xcursor.h \ |
X11/extensions/shape.h \ |
X11/extensions/XInput.h \ |
+ X11/extensions/XInput2.h \ |
X11/extensions/XShm.h \ |
X11/extensions/Xcomposite.h \ |
X11/extensions/Xinerama.h \ |
@@ -935,6 +936,17 @@ then |
WINE_NOTICE_WITH(xinput,[test "x$ac_cv_lib_soname_Xi" = "x"], |
[libxi ${notice_platform}development files not found, the Xinput extension won't be supported.]) |
|
+ dnl *** Check for X input 2 extension |
+ if test "$ac_cv_header_X11_extensions_XInput2_h" = "yes" |
+ then |
+ AC_CHECK_LIB(Xi, XIQueryVersion, |
+ AC_DEFINE(HAVE_LIBXINPUT2, 1, [Define if you have the XInput 2 extension]),, |
+ $X_LIBS $XLIB $X_EXTRA_LIBS) |
+ |
+ fi |
+ WINE_NOTICE_WITH(xinput2,[test "$ac_cv_lib_Xi_XIQueryVersion" != "yes"], |
+ [libxi ${notice_platform}development files not found, the Xinput2 extension won't be supported.]) |
+ |
dnl *** Check for X Shm extension |
if test "$ac_cv_header_X11_extensions_XShm_h" = "yes" |
then |
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c |
index 06971db..c86ae97 100644 |
--- a/dlls/dinput/dinput_main.c |
+++ b/dlls/dinput/dinput_main.c |
@@ -85,6 +85,16 @@ static const struct dinput_device *dinput_devices[] = |
#define NB_DINPUT_DEVICES (sizeof(dinput_devices)/sizeof(dinput_devices[0])) |
|
static HINSTANCE DINPUT_instance = NULL; |
+static int(*wine_xinput_acquire)(int,HOOKPROC); |
+ |
+static void dinput_init( HINSTANCE inst ) |
+{ |
+ HMODULE x11 = GetModuleHandleA("winex11.drv"); |
+ |
+ DINPUT_instance = inst; |
+ if (x11) |
+ wine_xinput_acquire = (void *)GetProcAddress(x11, "wine_xinput_acquire"); |
+} |
|
BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserv) |
{ |
@@ -92,7 +102,7 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserv) |
{ |
case DLL_PROCESS_ATTACH: |
DisableThreadLibraryCalls(inst); |
- DINPUT_instance = inst; |
+ dinput_init(inst); |
break; |
case DLL_PROCESS_DETACH: |
break; |
@@ -882,6 +892,28 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) |
* DInput hook thread |
*/ |
|
+static LRESULT CALLBACK LL_hook_proc_xi2( int code, WPARAM wparam, LPARAM lparam ) |
+{ |
+ IDirectInputImpl *dinput; |
+ |
+ EnterCriticalSection( &dinput_hook_crit ); |
+ LIST_FOR_EACH_ENTRY( dinput, &direct_input_list, IDirectInputImpl, entry ) |
+ { |
+ IDirectInputDeviceImpl *dev; |
+ |
+ EnterCriticalSection( &dinput->crit ); |
+ LIST_FOR_EACH_ENTRY( dev, &dinput->devices_list, IDirectInputDeviceImpl, entry ) |
+ if (dev->acquired && dev->event_proc) |
+ { |
+ TRACE("calling %p->%p (%lx %lx)\n", dev, dev->event_proc, wparam, lparam); |
+ dev->event_proc( (LPDIRECTINPUTDEVICE8A)dev, wparam, lparam ); |
+ } |
+ LeaveCriticalSection( &dinput->crit ); |
+ } |
+ LeaveCriticalSection( &dinput_hook_crit ); |
+ return 1; |
+} |
+ |
static LRESULT CALLBACK LL_hook_proc( int code, WPARAM wparam, LPARAM lparam ) |
{ |
IDirectInputImpl *dinput; |
@@ -1003,12 +1035,15 @@ static DWORD WINAPI hook_thread_proc(void *param) |
kbd_hook = NULL; |
} |
|
- if (mice_cnt && !mouse_hook) |
- mouse_hook = SetWindowsHookExW( WH_MOUSE_LL, LL_hook_proc, DINPUT_instance, 0 ); |
- else if (!mice_cnt && mouse_hook) |
+ if (!wine_xinput_acquire( (mice_cnt ? 2 : 0) , LL_hook_proc_xi2 )) |
{ |
- UnhookWindowsHookEx( mouse_hook ); |
- mouse_hook = NULL; |
+ if (mice_cnt && !mouse_hook) |
+ mouse_hook = SetWindowsHookExW( WH_MOUSE_LL, LL_hook_proc, DINPUT_instance, 0 ); |
+ else if (!mice_cnt && mouse_hook) |
+ { |
+ UnhookWindowsHookEx( mouse_hook ); |
+ mouse_hook = NULL; |
+ } |
} |
} |
TranslateMessage(&msg); |
diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c |
index 1599157..7390c01 100644 |
--- a/dlls/dinput/mouse.c |
+++ b/dlls/dinput/mouse.c |
@@ -304,7 +304,10 @@ static int dinput_mouse_hook( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM |
{ |
POINT pt, pt1; |
|
- GetCursorPos(&pt); |
+ if (hook->flags & 2) |
+ pt.x = pt.y = 0; |
+ else |
+ GetCursorPos(&pt); |
This->m_state.lX += pt.x = hook->pt.x - pt.x; |
This->m_state.lY += pt.y = hook->pt.y - pt.y; |
|
@@ -330,7 +333,8 @@ static int dinput_mouse_hook( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM |
wdata = pt1.y; |
} |
|
- This->need_warp = This->warp_override != WARP_DISABLE && |
+ This->need_warp = !(hook->flags & 2) && |
+ This->warp_override != WARP_DISABLE && |
(pt.x || pt.y) && |
(dwCoop & DISCL_EXCLUSIVE || This->warp_override == WARP_FORCE_ON); |
break; |
diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c |
index ae0875b..bc9dedf 100644 |
--- a/dlls/winex11.drv/event.c |
+++ b/dlls/winex11.drv/event.c |
@@ -141,9 +141,10 @@ static struct event_handler handlers[MAX_EVENT_HANDLERS] = |
/* ColormapNotify */ |
{ ClientMessage, X11DRV_ClientMessage }, |
{ MappingNotify, X11DRV_MappingNotify }, |
+ { GenericEvent, X11DRV_GenericEvent }, |
}; |
|
-static int nb_event_handlers = 20; /* change this if you add handlers above */ |
+static int nb_event_handlers = 21; /* change this if you add handlers above */ |
|
|
/* return the name of an X event */ |
diff --git a/dlls/winex11.drv/mouse.c b/dlls/winex11.drv/mouse.c |
index 71b31cc..61eb7dc 100644 |
--- a/dlls/winex11.drv/mouse.c |
+++ b/dlls/winex11.drv/mouse.c |
@@ -22,23 +22,10 @@ |
#include "config.h" |
#include "wine/port.h" |
|
-#include <X11/Xlib.h> |
+#include <stdlib.h> |
#include <X11/cursorfont.h> |
#include <stdarg.h> |
- |
-#ifdef SONAME_LIBXCURSOR |
-# include <X11/Xcursor/Xcursor.h> |
-static void *xcursor_handle; |
-# define MAKE_FUNCPTR(f) static typeof(f) * p##f |
-MAKE_FUNCPTR(XcursorImageCreate); |
-MAKE_FUNCPTR(XcursorImageDestroy); |
-MAKE_FUNCPTR(XcursorImageLoadCursor); |
-MAKE_FUNCPTR(XcursorImagesCreate); |
-MAKE_FUNCPTR(XcursorImagesDestroy); |
-MAKE_FUNCPTR(XcursorImagesLoadCursor); |
-MAKE_FUNCPTR(XcursorLibraryLoadCursor); |
-# undef MAKE_FUNCPTR |
-#endif /* SONAME_LIBXCURSOR */ |
+#include <assert.h> |
|
#define NONAMELESSUNION |
#define NONAMELESSSTRUCT |
@@ -53,6 +40,39 @@ MAKE_FUNCPTR(XcursorLibraryLoadCursor); |
#include "wine/unicode.h" |
#include "wine/debug.h" |
|
+#include <X11/Xlib.h> |
+ |
+#define MAKE_FUNCPTR(f) static typeof(f) * p##f |
+ |
+#ifdef SONAME_LIBXCURSOR |
+# include <X11/Xcursor/Xcursor.h> |
+static void *xcursor_handle; |
+MAKE_FUNCPTR(XcursorImageCreate); |
+MAKE_FUNCPTR(XcursorImageDestroy); |
+MAKE_FUNCPTR(XcursorImageLoadCursor); |
+MAKE_FUNCPTR(XcursorImagesCreate); |
+MAKE_FUNCPTR(XcursorImagesDestroy); |
+MAKE_FUNCPTR(XcursorImagesLoadCursor); |
+MAKE_FUNCPTR(XcursorLibraryLoadCursor); |
+#endif /* SONAME_LIBXCURSOR */ |
+ |
+#ifdef HAVE_LIBXINPUT2 |
+# include <X11/extensions/XInput2.h> |
+static void *xinput2_handle; |
+static int xinput2_opcode; |
+static int xinput2_available; |
+static int core_pointer_id; |
+MAKE_FUNCPTR(XQueryExtension); |
+MAKE_FUNCPTR(XIQueryVersion); |
+MAKE_FUNCPTR(XISelectEvents); |
+MAKE_FUNCPTR(XGetEventData); |
+MAKE_FUNCPTR(XFreeEventData); |
+MAKE_FUNCPTR(XIQueryDevice); |
+MAKE_FUNCPTR(XIFreeDeviceInfo); |
+#endif /* HAVE_LIBXINPUT2 */ |
+ |
+#undef MAKE_FUNCPTR |
+ |
WINE_DEFAULT_DEBUG_CHANNEL(cursor); |
|
/**********************************************************************/ |
@@ -130,6 +150,67 @@ void X11DRV_Xcursor_Init(void) |
#endif /* SONAME_LIBXCURSOR */ |
} |
|
+void X11DRV_XInput2_Init(void) |
+{ |
+#ifdef HAVE_LIBXINPUT2 |
+ int event_base, error_base, ret; |
+ int major = 2, minor = 0; /* Need at least v2.0 extension */ |
+ char msg[1024]; |
+ |
+ xinput2_handle = wine_dlopen(SONAME_LIBXI, RTLD_NOW, NULL, 0); |
+ if (!xinput2_handle) /* wine_dlopen failed. */ |
+ { |
+ FIXME("XInput2 failed to load. Using fallback code.\n"); |
+ return; |
+ } |
+#define LOAD_FUNCPTR(f) if (!(p##f = wine_dlsym(xinput2_handle, #f, msg, sizeof(msg)))) \ |
+ { WARN("Error loading \"%s\": %s\n", #f, msg); return; } |
+ LOAD_FUNCPTR(XQueryExtension) |
+ LOAD_FUNCPTR(XIQueryVersion) |
+ LOAD_FUNCPTR(XISelectEvents) |
+ LOAD_FUNCPTR(XGetEventData) |
+ LOAD_FUNCPTR(XFreeEventData) |
+ LOAD_FUNCPTR(XIQueryDevice) |
+ LOAD_FUNCPTR(XIFreeDeviceInfo) |
+#undef LOAD_FUNCPTR |
+ |
+ wine_tsx11_lock(); |
+ if (!pXQueryExtension(gdi_display, "XInputExtension", &xinput2_opcode, &event_base, &error_base)) |
+ { |
+ wine_tsx11_unlock(); |
+ WARN("Failed to query XInputExtension\n"); |
+ return; |
+ } |
+ if ((ret = pXIQueryVersion(gdi_display, &major, &minor)) == Success) |
+ { |
+ XIDeviceInfo *devs; |
+ int num_devs, i; |
+ |
+ /* Find core pointer id. */ |
+ devs = pXIQueryDevice(gdi_display, XIAllMasterDevices, &num_devs); |
+ for (i = 0; i < num_devs; i++) |
+ { |
+ if (devs[i].use == XIMasterPointer) |
+ { |
+ core_pointer_id = devs[i].deviceid; |
+ break; |
+ } |
+ } |
+ pXIFreeDeviceInfo(devs); |
+ } |
+ wine_tsx11_unlock(); |
+ |
+ if (ret != Success) |
+ { |
+ WARN("Failed to get requred Xi2 version. Server supports %d.%d\n", major, minor); |
+ return; |
+ } |
+ TRACE("Server supports Xinput2 extension version %d.%d\n", major, minor); |
+ xinput2_available = 1; |
+ |
+ return; |
+#endif /* HAVE_LIBXINPUT2 */ |
+} |
|
/*********************************************************************** |
* clip_point_to_rect |
@@ -1258,3 +1339,160 @@ void X11DRV_EnterNotify( HWND hwnd, XEvent *xev ) |
X11DRV_send_mouse_input( top_hwnd, hwnd, MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE, |
pt.x, pt.y, 0, EVENT_x11_time_to_win32_time(event->time), 0, 0 ); |
} |
+ |
+#ifdef HAVE_LIBXINPUT2 |
+static HOOKPROC xi2_callback; |
+ |
+static UINT xi2_press_to_mesage(int btn) |
+{ |
+ switch (btn) |
+ { |
+ case 1: return WM_LBUTTONDOWN; |
+ case 2: return WM_MBUTTONDOWN; |
+ case 3: return WM_RBUTTONDOWN; |
+ case 4: case 5: |
+ case 6: case 7: |
+ return WM_MOUSEWHEEL; |
+ case 8: |
+ case 9: return WM_XBUTTONDOWN; |
+ } |
+ return 0; |
+} |
+ |
+static UINT xi2_release_to_mesage(int btn) |
+{ |
+ switch (btn) |
+ { |
+ case 1: return WM_LBUTTONUP; |
+ case 2: return WM_MBUTTONUP; |
+ case 3: return WM_RBUTTONUP; |
+ case 4: case 5: |
+ case 6: case 7: |
+ return WM_MOUSEWHEEL; |
+ case 8: |
+ case 9: return WM_XBUTTONUP; |
+ } |
+ return 0; |
+} |
+#endif |
+ |
+/*********************************************************************** |
+ * X11DRV_GenericEvent |
+ */ |
+void X11DRV_GenericEvent( HWND hwnd, XEvent *xev ) |
+{ |
+#ifdef HAVE_LIBXINPUT2 |
+ XGenericEventCookie *cookie = (XGenericEventCookie*)&xev->xcookie; |
+ Display *display = thread_init_display(); |
+ |
+ assert(xinput2_available); |
+ TRACE("%p %p\n", hwnd, xev); |
+ |
+ if (pXGetEventData(display , cookie) && |
+ cookie->type == GenericEvent && |
+ cookie->extension == xinput2_opcode) |
+ { |
+ XIRawEvent *revent = (XIRawEvent *)cookie->data; |
+ DWORD wData; |
+ MSLLHOOKSTRUCT hook; |
+ |
+ memset(&hook, 0, sizeof(hook)); |
+ hook.time = EVENT_x11_time_to_win32_time(revent->time); |
+ |
+ /* Skip core pointer events */ |
+ if (revent->deviceid != core_pointer_id) |
+ switch (cookie->evtype) |
+ { |
+ case XI_RawMotion: |
+ { |
+ int i = 0; |
+ hook.pt.x = XIMaskIsSet(revent->valuators.mask, 0) ? revent->raw_values[i++] : 0; |
+ hook.pt.y = XIMaskIsSet(revent->valuators.mask, 1) ? revent->raw_values[i++] : 0; |
+ hook.flags = 2; |
+ if (xi2_callback) xi2_callback(0, WM_MOUSEMOVE, (LPARAM)&hook); |
+ break; |
+ } |
+ |
+ case XI_RawButtonPress: |
+ switch (revent->detail) |
+ { |
+ case 4: case 6: wData = WHEEL_DELTA; break; |
+ case 5: case 7: wData = -WHEEL_DELTA; break; |
+ case 8: wData = XBUTTON1; break; |
+ case 9: wData = XBUTTON2; break; |
+ default: wData = 0; |
+ } |
+ hook.mouseData = MAKELONG(0, wData); |
+ if (xi2_callback) xi2_callback(0, xi2_press_to_mesage(revent->detail), (LPARAM)&hook); |
+ break; |
+ |
+ case XI_RawButtonRelease: |
+ switch (revent->detail) |
+ { |
+ case 8: wData = XBUTTON1; break; |
+ case 9: wData = XBUTTON2; break; |
+ default: wData = 0; |
+ } |
+ hook.mouseData = MAKELONG(0, wData); |
+ if (xi2_callback) xi2_callback(0, xi2_release_to_mesage(revent->detail), (LPARAM)&hook); |
+ break; |
+ |
+ case XI_RawKeyPress: |
+ break; |
+ case XI_RawKeyRelease: |
+ break; |
+ } |
+ } |
+ pXFreeEventData(display , &xev->xcookie); |
+#endif |
+} |
+ |
+ |
+#ifdef HAVE_LIBXINPUT2 |
+int CDECL X11DRV_xinput_acquire(int dev_mask, HOOKPROC cb) |
+{ |
+ XIEventMask eventmask; |
+ unsigned char mask[XIMaskLen(XI_RawMotion)] = {0}; |
+ Display *display = thread_init_display(); |
+ int ret; |
+ |
+ TRACE("%d %p\n", dev_mask, cb); |
+ if (!xinput2_available) return 0; |
+ |
+ eventmask.mask = mask; |
+ eventmask.mask_len = sizeof(mask); |
+ eventmask.deviceid = XIAllDevices; |
+ |
+ if (dev_mask & 1) |
+ { |
+ XISetMask(eventmask.mask, XI_RawKeyPress); |
+ XISetMask(eventmask.mask, XI_RawKeyRelease); |
+ } |
+ if (dev_mask & 2) |
+ { |
+ XISetMask(eventmask.mask, XI_RawButtonPress); |
+ XISetMask(eventmask.mask, XI_RawButtonRelease); |
+ XISetMask(eventmask.mask, XI_RawMotion); |
+ } |
+ wine_tsx11_lock(); |
+ ret = pXISelectEvents(display, DefaultRootWindow(display), &eventmask, 1); |
+ wine_tsx11_unlock(); |
+ if (ret != Success) |
+ { |
+ WARN("Failed to set mask: %d\n", ret); |
+ return 0; |
+ } |
+ InterlockedExchangePointer((LPVOID)&xi2_callback, cb); |
+ TRACE("Set Xi2 callback to %p\n", cb); |
+ |
+ return 1; |
+} |
+ |
+#else /* HAVE_LIBXINPUT2 */ |
+int X11DRV_xinput_acquire(int dev_mask, HOOKPROC cb) |
+{ |
+ WARN("xinput2 is not available\n"); |
+ return 0; |
+} |
+ |
+#endif /* HAVE_LIBXINPUT2 */ |
diff --git a/dlls/winex11.drv/winex11.drv.spec b/dlls/winex11.drv/winex11.drv.spec |
index 9476c40..6ead1aa 100644 |
--- a/dlls/winex11.drv/winex11.drv.spec |
+++ b/dlls/winex11.drv/winex11.drv.spec |
@@ -162,3 +162,5 @@ |
@ stdcall ImeProcessKey(long long long ptr) |
@ stdcall ImeGetRegisterWordStyle(long ptr) |
@ stdcall ImeGetImeMenuItems(long long long ptr ptr long) |
+ |
+@ cdecl wine_xinput_acquire(long ptr) X11DRV_xinput_acquire |
diff --git a/dlls/winex11.drv/x11drv.h b/dlls/winex11.drv/x11drv.h |
index f48b51f..d9035ce 100644 |
--- a/dlls/winex11.drv/x11drv.h |
+++ b/dlls/winex11.drv/x11drv.h |
@@ -713,6 +713,7 @@ extern void X11DRV_DestroyNotify( HWND hwnd, XEvent *event ); |
extern void X11DRV_SelectionRequest( HWND hWnd, XEvent *event ); |
extern void X11DRV_SelectionClear( HWND hWnd, XEvent *event ); |
extern void X11DRV_MappingNotify( HWND hWnd, XEvent *event ); |
+extern void X11DRV_GenericEvent( HWND hWnd, XEvent *event ); |
|
extern DWORD EVENT_x11_time_to_win32_time(Time time); |
|
@@ -843,6 +844,8 @@ extern void X11DRV_XIMLookupChars( const char *str, DWORD count ) DECLSPEC_HIDDE |
extern void X11DRV_ForceXIMReset(HWND hwnd) DECLSPEC_HIDDEN; |
extern BOOL X11DRV_SetPreeditState(HWND hwnd, BOOL fOpen); |
|
+extern void X11DRV_XInput2_Init(void); |
+ |
/* FIXME: private functions imported from user32 */ |
extern LRESULT HOOK_CallHooks( INT id, INT code, WPARAM wparam, LPARAM lparam, BOOL unicode ); |
|
diff --git a/dlls/winex11.drv/x11drv_main.c b/dlls/winex11.drv/x11drv_main.c |
index 0d1a7da..f94bba4 100644 |
--- a/dlls/winex11.drv/x11drv_main.c |
+++ b/dlls/winex11.drv/x11drv_main.c |
@@ -562,6 +562,7 @@ static BOOL process_attach(void) |
#ifdef SONAME_LIBXCOMPOSITE |
X11DRV_XComposite_Init(); |
#endif |
+ X11DRV_XInput2_Init(); |
|
#ifdef HAVE_XKB |
if (use_xkb) use_xkb = XkbUseExtension( gdi_display, NULL, NULL ); |
diff --git a/include/config.h.in b/include/config.h.in |
index 46adad8..be06226 100644 |
--- a/include/config.h.in |
+++ b/include/config.h.in |
@@ -367,6 +367,9 @@ |
/* Define to 1 if you have the `ossaudio' library (-lossaudio). */ |
#undef HAVE_LIBOSSAUDIO |
|
+/* Define if you have the XInput 2 extension */ |
+#undef HAVE_LIBXINPUT2 |
+ |
/* Define if you have the libxml2 library */ |
#undef HAVE_LIBXML2 |
|
@@ -1075,6 +1078,9 @@ |
/* Define to 1 if you have the <X11/extensions/Xinerama.h> header file. */ |
#undef HAVE_X11_EXTENSIONS_XINERAMA_H |
|
+/* Define to 1 if you have the <X11/extensions/XInput2.h> header file. */ |
+#undef HAVE_X11_EXTENSIONS_XINPUT2_H |
+ |
/* Define to 1 if you have the <X11/extensions/XInput.h> header file. */ |
#undef HAVE_X11_EXTENSIONS_XINPUT_H |
|