Blame SOURCES/tigervnc-fix-ghost-cursor-in-zaphod-mode.patch

b66c58
From f783d5c8b567199178b6690f347e060a69d2aa36 Mon Sep 17 00:00:00 2001
b66c58
From: Jan Grulich <jgrulich@redhat.com>
b66c58
Date: Thu, 11 Aug 2022 13:15:29 +0200
b66c58
Subject: [PATCH] x0vncserver: update/display cursor only on correct screen in
b66c58
 zaphod mode
b66c58
b66c58
We have to check whether we update cursor position/shape only in case
b66c58
the cursor is on our display, otherwise in zaphod mode, ie. when having
b66c58
two instances of x0vncserver on screens :0.0 and :0.1 we would be having
b66c58
the cursor duplicated and actually not funcional (aka ghost cursor) as
b66c58
it would be actually not present. We also additionally watch EnterNotify
b66c58
and LeaveNotify events in order to show/hide cursor accordingly.
b66c58
b66c58
Change made with help from Olivier Fourdan <ofourdan@redhat.com>
b66c58
---
b66c58
 unix/x0vncserver/XDesktop.cxx | 60 +++++++++++++++++++++++++++++++----
b66c58
 1 file changed, 53 insertions(+), 7 deletions(-)
b66c58
b66c58
diff --git a/unix/x0vncserver/XDesktop.cxx b/unix/x0vncserver/XDesktop.cxx
b66c58
index f2046e43e..f07fd78bf 100644
b66c58
--- a/unix/x0vncserver/XDesktop.cxx
b66c58
+++ b/unix/x0vncserver/XDesktop.cxx
b66c58
@@ -192,7 +192,8 @@ XDesktop::XDesktop(Display* dpy_, Geometry *geometry_)
b66c58
                    RRScreenChangeNotifyMask | RRCrtcChangeNotifyMask);
b66c58
     /* Override TXWindow::init input mask */
b66c58
     XSelectInput(dpy, DefaultRootWindow(dpy),
b66c58
-                 PropertyChangeMask | StructureNotifyMask | ExposureMask);
b66c58
+                 PropertyChangeMask | StructureNotifyMask |
b66c58
+                 ExposureMask | EnterWindowMask | LeaveWindowMask);
b66c58
   } else {
b66c58
 #endif
b66c58
     vlog.info("RANDR extension not present");
b66c58
@@ -217,11 +218,13 @@ void XDesktop::poll() {
b66c58
     Window root, child;
b66c58
     int x, y, wx, wy;
b66c58
     unsigned int mask;
b66c58
-    XQueryPointer(dpy, DefaultRootWindow(dpy), &root, &child,
b66c58
-                  &x, &y, &wx, &wy, &mask);
b66c58
-    x -= geometry->offsetLeft();
b66c58
-    y -= geometry->offsetTop();
b66c58
-    server->setCursorPos(rfb::Point(x, y), false);
b66c58
+
b66c58
+    if (XQueryPointer(dpy, DefaultRootWindow(dpy), &root, &child,
b66c58
+                      &x, &y, &wx, &wy, &mask)) {
b66c58
+      x -= geometry->offsetLeft();
b66c58
+      y -= geometry->offsetTop();
b66c58
+      server->setCursorPos(rfb::Point(x, y), false);
b66c58
+    }
b66c58
   }
b66c58
 }
b66c58
b66c58
@@ -253,7 +256,14 @@ void XDesktop::start(VNCServer* vs) {
b66c58
 #endif
b66c58
b66c58
 #ifdef HAVE_XFIXES
b66c58
-  setCursor();
b66c58
+  Window root, child;
b66c58
+  int x, y, wx, wy;
b66c58
+  unsigned int mask;
b66c58
+  // Check whether the cursor is initially on our screen
b66c58
+  if (XQueryPointer(dpy, DefaultRootWindow(dpy), &root, &child,
b66c58
+                    &x, &y, &wx, &wy, &mask))
b66c58
+    setCursor();
b66c58
+
b66c58
 #endif
b66c58
b66c58
   server->setLEDState(ledState);
b66c58
@@ -701,6 +711,15 @@ bool XDesktop::handleGlobalEvent(XEvent* ev) {
b66c58
     if (cev->subtype != XFixesDisplayCursorNotify)
b66c58
       return false;
b66c58
b66c58
+    Window root, child;
b66c58
+    int x, y, wx, wy;
b66c58
+    unsigned int mask;
b66c58
+
b66c58
+    // Check whether the cursor is initially on our screen
b66c58
+    if (!XQueryPointer(dpy, DefaultRootWindow(dpy), &root, &child,
b66c58
+                      &x, &y, &wx, &wy, &mask))
b66c58
+      return false;
b66c58
+
b66c58
     return setCursor();
b66c58
 #endif
b66c58
 #ifdef HAVE_XRANDR
b66c58
@@ -753,6 +772,33 @@ bool XDesktop::handleGlobalEvent(XEvent* ev) {
b66c58
b66c58
     return true;
b66c58
 #endif
b66c58
+#ifdef HAVE_XFIXES
b66c58
+  } else if (ev->type == EnterNotify) {
b66c58
+    XCrossingEvent* cev;
b66c58
+
b66c58
+    if (!running)
b66c58
+      return true;
b66c58
+
b66c58
+    cev = (XCrossingEvent*)ev;
b66c58
+
b66c58
+    if (cev->window != cev->root)
b66c58
+      return false;
b66c58
+
b66c58
+    return setCursor();
b66c58
+  } else if (ev->type == LeaveNotify) {
b66c58
+    XCrossingEvent* cev;
b66c58
+
b66c58
+    if (!running)
b66c58
+      return true;
b66c58
+
b66c58
+    cev = (XCrossingEvent*)ev;
b66c58
+
b66c58
+    if (cev->window == cev->root)
b66c58
+      return false;
b66c58
+
b66c58
+    server->setCursor(0, 0, Point(), NULL);
b66c58
+    return true;
b66c58
+#endif
b66c58
   }
b66c58
b66c58
   return false;