Fix T53004: XWayland ignores cursor-warp calls

There is currently a limitation in XWayland,
the cursor needs to be hidden during warp calls.
This commit is contained in:
Campbell Barton 2017-10-25 20:12:12 +11:00
parent 83877632a3
commit 2103194f79
Notes: blender-bot 2023-02-14 06:30:01 +01:00
Referenced by issue #53683, 2.79a release
Referenced by issue #53004, Moving objects (G key) has broken behavior on linux/wayland
4 changed files with 82 additions and 14 deletions

View File

@ -285,6 +285,7 @@ endif()
if(WITH_X11)
option(WITH_X11_XINPUT "Enable X11 Xinput (tablet support and unicode input)" ON)
option(WITH_X11_XF86VMODE "Enable X11 video mode switching" ON)
option(WITH_X11_XFIXES "Enable X11 XWayland cursor warping workaround" ON)
option(WITH_X11_ALPHA "Enable X11 transparent background" ON)
endif()
@ -687,6 +688,7 @@ if(WITH_GHOST_SDL OR WITH_HEADLESS)
set(WITH_X11 OFF)
set(WITH_X11_XINPUT OFF)
set(WITH_X11_XF86VMODE OFF)
set(WITH_X11_XFIXES OFF)
set(WITH_X11_ALPHA OFF)
set(WITH_GHOST_XDND OFF)
set(WITH_INPUT_IME OFF)
@ -838,6 +840,14 @@ if(WITH_X11)
endif()
endif()
if(WITH_X11_XFIXES)
if(X11_Xfixes_LIB)
list(APPEND PLATFORM_LINKLIBS ${X11_Xfixes_LIB})
else()
set(WITH_X11_XFIXES OFF)
endif()
endif()
if(WITH_X11_ALPHA)
find_library(X11_Xrender_LIB Xrender ${X11_LIB_SEARCH_PATH})
mark_as_advanced(X11_Xrender_LIB)
@ -1707,6 +1717,7 @@ if(FIRST_RUN)
info_cfg_option(WITH_INSTALL_PORTABLE)
info_cfg_option(WITH_X11_ALPHA)
info_cfg_option(WITH_X11_XF86VMODE)
info_cfg_option(WITH_X11_XFIXES)
info_cfg_option(WITH_X11_XINPUT)
info_cfg_option(WITH_MEM_JEMALLOC)
info_cfg_option(WITH_MEM_VALGRIND)

View File

@ -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()

View File

@ -61,6 +61,12 @@
#include <X11/XF86keysym.h>
#endif
#ifdef WITH_X11_XFIXES
# include <X11/extensions/Xfixes.h>
/* Workaround for XWayland grab glitch: T53004. */
#define WITH_XWAYLAND_HACK
#endif
/* for XIWarpPointer */
#ifdef WITH_X11_XINPUT
# include <X11/extensions/XInput2.h>
@ -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;

View File

@ -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 */