From 2103194f794c9c5260583ceb7d7bbaf73f783f48 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 25 Oct 2017 20:12:12 +1100 Subject: Fix T53004: XWayland ignores cursor-warp calls There is currently a limitation in XWayland, the cursor needs to be hidden during warp calls. --- intern/ghost/CMakeLists.txt | 7 ++++ intern/ghost/intern/GHOST_SystemX11.cpp | 72 +++++++++++++++++++++++++++------ intern/ghost/intern/GHOST_WindowX11.cpp | 6 ++- 3 files changed, 71 insertions(+), 14 deletions(-) (limited to 'intern/ghost') diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index 31e92c94eed..5a97da28d17 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -219,6 +219,13 @@ elseif(WITH_X11) ) endif() + if(WITH_X11_XFIXES) + add_definitions(-DWITH_X11_XFIXES) + list(APPEND INC_SYS + ${X11_Xfixes_INCLUDE_PATH} + ) + endif() + if(WITH_X11_ALPHA) add_definitions(-DWITH_X11_ALPHA) endif() diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index 8fff565338f..9b617a34e1a 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -61,6 +61,12 @@ #include #endif +#ifdef WITH_X11_XFIXES +# include +/* Workaround for XWayland grab glitch: T53004. */ +#define WITH_XWAYLAND_HACK +#endif + /* for XIWarpPointer */ #ifdef WITH_X11_XINPUT # include @@ -95,6 +101,10 @@ static GHOST_TKey convertXKey(KeySym key); static char *txt_cut_buffer = NULL; static char *txt_select_buffer = NULL; +#ifdef WITH_XWAYLAND_HACK +static bool use_xwayland_hack = false; +#endif + using namespace std; GHOST_SystemX11:: @@ -176,7 +186,11 @@ GHOST_SystemX11( if (use_xkb) { XkbSetDetectableAutoRepeat(m_display, true, NULL); } - + +#ifdef WITH_XWAYLAND_HACK + use_xwayland_hack = getenv("WAYLAND_DISPLAY") != NULL; +#endif + #ifdef WITH_X11_XINPUT /* detect if we have xinput (for reuse) */ { @@ -1472,23 +1486,21 @@ getButtons( return GHOST_kSuccess; } - -GHOST_TSuccess -GHOST_SystemX11:: -getCursorPosition( - GHOST_TInt32& x, - GHOST_TInt32& y) const +static GHOST_TSuccess getCursorPosition_impl( + Display *display, + GHOST_TInt32& x, + GHOST_TInt32& y, + Window *child_return) { - - Window root_return, child_return; int rx, ry, wx, wy; unsigned int mask_return; + Window root_return; if (XQueryPointer( - m_display, - RootWindow(m_display, DefaultScreen(m_display)), + display, + RootWindow(display, DefaultScreen(display)), &root_return, - &child_return, + child_return, &rx, &ry, &wx, &wy, &mask_return @@ -1498,10 +1510,20 @@ getCursorPosition( else { x = rx; y = ry; - } + } return GHOST_kSuccess; } +GHOST_TSuccess +GHOST_SystemX11:: +getCursorPosition( + GHOST_TInt32& x, + GHOST_TInt32& y) const +{ + Window child_return; + return getCursorPosition_impl(m_display, x, y, &child_return); +} + GHOST_TSuccess GHOST_SystemX11:: @@ -1515,13 +1537,29 @@ setCursorPosition( * current pointer position. */ int cx, cy; + +#ifdef WITH_XWAYLAND_HACK + Window child_return = None; + if (getCursorPosition_impl(m_display, cx, cy, &child_return) == GHOST_kFailure) { + return GHOST_kFailure; + } +#else if (getCursorPosition(cx, cy) == GHOST_kFailure) { return GHOST_kFailure; } +#endif int relx = x - cx; int rely = y - cy; +#ifdef WITH_XWAYLAND_HACK + if (use_xwayland_hack) { + if (child_return != None) { + XFixesHideCursor(m_display, child_return); + } + } +#endif + #ifdef WITH_X11_XINPUT if ((m_xinput_version.present) && (m_xinput_version.major_version >= 2)) @@ -1538,6 +1576,14 @@ setCursorPosition( XWarpPointer(m_display, None, None, 0, 0, 0, 0, relx, rely); } +#ifdef WITH_XWAYLAND_HACK + if (use_xwayland_hack) { + if (child_return != None) { + XFixesShowCursor(m_display, child_return); + } + } +#endif + XSync(m_display, 0); /* Sync to process all requests */ return GHOST_kSuccess; diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index 9e019b233f6..1abdec37403 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -1526,7 +1526,6 @@ setWindowCursorGrab( else { if (m_cursorGrab == GHOST_kGrabHide) { m_system->setCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]); - setWindowCursorVisibility(true); } if (m_cursorGrab != GHOST_kGrabNormal) { @@ -1550,6 +1549,11 @@ setWindowCursorGrab( } } + /* Perform this last so to workaround XWayland bug, see: T53004. */ + if (m_cursorGrab == GHOST_kGrabHide) { + setWindowCursorVisibility(true); + } + /* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */ setCursorGrabAccum(0, 0); m_cursorGrabBounds.m_l = m_cursorGrabBounds.m_r = -1; /* disable */ -- cgit v1.2.3