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

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