[Bf-blender-cvs] [2103194f794] master: Fix T53004: XWayland ignores cursor-warp calls

Campbell Barton noreply at git.blender.org
Wed Oct 25 11:10:57 CEST 2017


Commit: 2103194f794c9c5260583ceb7d7bbaf73f783f48
Author: Campbell Barton
Date:   Wed Oct 25 20:12:12 2017 +1100
Branches: master
https://developer.blender.org/rB2103194f794c9c5260583ceb7d7bbaf73f783f48

Fix T53004: XWayland ignores cursor-warp calls

There is currently a limitation in XWayland,
the cursor needs to be hidden during warp calls.

===================================================================

M	CMakeLists.txt
M	intern/ghost/CMakeLists.txt
M	intern/ghost/intern/GHOST_SystemX11.cpp
M	intern/ghost/intern/GHOST_WindowX11.cpp

===================================================================

diff --git a/CMakeLists.txt b/CMakeLists.txt
index b3a0dfa96eb..4492e9c2cb0 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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)
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 <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;
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 */



More information about the Bf-blender-cvs mailing list