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