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