From c0f107a83e2b559a474850d21c8ac745e7fa1e04 Mon Sep 17 00:00:00 2001 From: Lauri Kasanen Date: Mon, 3 May 2021 13:52:58 +0300 Subject: [PATCH] Add server-side support for relative mouse motion, kasm-only hack --- common/rfb/InputHandler.h | 1 + common/rfb/SMsgReader.cxx | 2 +- common/rfb/VNCSConnectionST.cxx | 44 +++++++++++++++++++++++++-- common/rfb/VNCSConnectionST.h | 2 +- unix/xserver/hw/vnc/Input.c | 34 +++++++++++++++++++++ unix/xserver/hw/vnc/Input.h | 1 + unix/xserver/hw/vnc/XserverDesktop.cc | 12 ++++++-- unix/xserver/hw/vnc/XserverDesktop.h | 2 +- 8 files changed, 89 insertions(+), 9 deletions(-) diff --git a/common/rfb/InputHandler.h b/common/rfb/InputHandler.h index 806625f..b45f9eb 100644 --- a/common/rfb/InputHandler.h +++ b/common/rfb/InputHandler.h @@ -36,6 +36,7 @@ namespace rfb { rdr::U32 __unused_attr keycode, bool __unused_attr down) { } virtual void pointerEvent(const Point& __unused_attr pos, + const Point& __unused_attr abspos, int __unused_attr buttonMask, const bool __unused_attr skipClick, const bool __unused_attr skipRelease) { } diff --git a/common/rfb/SMsgReader.cxx b/common/rfb/SMsgReader.cxx index 11655b6..aa7f989 100644 --- a/common/rfb/SMsgReader.cxx +++ b/common/rfb/SMsgReader.cxx @@ -220,7 +220,7 @@ void SMsgReader::readPointerEvent() int mask = is->readU8(); int x = is->readU16(); int y = is->readU16(); - handler->pointerEvent(Point(x, y), mask, false, false); + handler->pointerEvent(Point(x, y), Point(0, 0), mask, false, false); } diff --git a/common/rfb/VNCSConnectionST.cxx b/common/rfb/VNCSConnectionST.cxx index 0ad5d49..fa36ef1 100644 --- a/common/rfb/VNCSConnectionST.cxx +++ b/common/rfb/VNCSConnectionST.cxx @@ -681,14 +681,52 @@ void VNCSConnectionST::setPixelFormat(const PixelFormat& pf) setCursor(); } -void VNCSConnectionST::pointerEvent(const Point& pos, int buttonMask, const bool skipClick, const bool skipRelease) +void VNCSConnectionST::pointerEvent(const Point& pos, const Point& abspos, int buttonMask, const bool skipClick, const bool skipRelease) { pointerEventTime = lastEventTime = time(0); server->lastUserInputTime = lastEventTime; if (!(accessRights & AccessPtrEvents)) return; if (!rfb::Server::acceptPointerEvents) return; if (!server->pointerClient || server->pointerClient == this) { - pointerEventPos = pos; + Point newpos = pos; + if (pos.x & 0x4000) { + newpos.x &= ~0x4000; + newpos.y &= ~0x4000; + + if (newpos.x & 0x8000) { + newpos.x &= ~0x8000; + newpos.x = -newpos.x; + } + if (newpos.y & 0x8000) { + newpos.y &= ~0x8000; + newpos.y = -newpos.y; + } + + if (newpos.x < 0) { + if (pointerEventPos.x + newpos.x >= 0) + pointerEventPos.x += newpos.x; + else + pointerEventPos.x = 0; + } else { + pointerEventPos.x += newpos.x; + if (pointerEventPos.x >= cp.width) + pointerEventPos.x = cp.width; + } + + if (newpos.y < 0) { + if (pointerEventPos.y + newpos.y >= 0) + pointerEventPos.y += newpos.y; + else + pointerEventPos.y = 0; + } else { + pointerEventPos.y += newpos.y; + if (pointerEventPos.y >= cp.height) + pointerEventPos.y = cp.height; + } + } else { + pointerEventPos = pos; + } + if (buttonMask) server->pointerClient = this; else @@ -709,7 +747,7 @@ void VNCSConnectionST::pointerEvent(const Point& pos, int buttonMask, const bool } } - server->desktop->pointerEvent(pointerEventPos, buttonMask, skipclick, skiprelease); + server->desktop->pointerEvent(newpos, pointerEventPos, buttonMask, skipclick, skiprelease); } } diff --git a/common/rfb/VNCSConnectionST.h b/common/rfb/VNCSConnectionST.h index 1bc6ba5..7bb0edb 100644 --- a/common/rfb/VNCSConnectionST.h +++ b/common/rfb/VNCSConnectionST.h @@ -175,7 +175,7 @@ namespace rfb { virtual void queryConnection(const char* userName); virtual void clientInit(bool shared); virtual void setPixelFormat(const PixelFormat& pf); - virtual void pointerEvent(const Point& pos, int buttonMask, const bool skipClick, const bool skipRelease); + virtual void pointerEvent(const Point& pos, const Point& abspos, int buttonMask, const bool skipClick, const bool skipRelease); virtual void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down); virtual void framebufferUpdateRequest(const Rect& r, bool incremental); virtual void setDesktopSize(int fb_width, int fb_height, diff --git a/unix/xserver/hw/vnc/Input.c b/unix/xserver/hw/vnc/Input.c index f8ac3fd..7011fcc 100644 --- a/unix/xserver/hw/vnc/Input.c +++ b/unix/xserver/hw/vnc/Input.c @@ -234,6 +234,40 @@ void vncPointerMove(int x, int y) cursorPosY = y; } +void vncPointerMoveRelative(int x, int y, int absx, int absy) +{ + int valuators[2]; +#if XORG < 111 + int n; +#endif +#if XORG >= 110 + ValuatorMask mask; +#endif + +// if (cursorPosX == absx && cursorPosY == absy) +// return; + + valuators[0] = x; + valuators[1] = y; +#if XORG < 110 + n = GetPointerEvents(eventq, vncPointerDev, MotionNotify, 0, + POINTER_RELATIVE, 0, 2, valuators); + enqueueEvents(vncPointerDev, n); +#elif XORG < 111 + valuator_mask_set_range(&mask, 0, 2, valuators); + n = GetPointerEvents(eventq, vncPointerDev, MotionNotify, 0, + POINTER_RELATIVE, &mask); + enqueueEvents(vncPointerDev, n); +#else + valuator_mask_set_range(&mask, 0, 2, valuators); + QueuePointerEvents(vncPointerDev, MotionNotify, 0, + POINTER_RELATIVE, &mask); +#endif + + cursorPosX = absx; + cursorPosY = absy; +} + void vncGetPointerPos(int *x, int *y) { if (vncPointerDev != NULL) { diff --git a/unix/xserver/hw/vnc/Input.h b/unix/xserver/hw/vnc/Input.h index 76680c0..5f6efef 100644 --- a/unix/xserver/hw/vnc/Input.h +++ b/unix/xserver/hw/vnc/Input.h @@ -35,6 +35,7 @@ void vncInitInputDevice(void); void vncPointerButtonAction(int buttonMask, const unsigned char skipclick, const unsigned char skiprelease); void vncPointerMove(int x, int y); +void vncPointerMoveRelative(int x, int y, int absx, int absy); void vncGetPointerPos(int *x, int *y); void vncKeyboardEvent(KeySym keysym, unsigned xtcode, int down); diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc index 872b2ec..6fc3f67 100644 --- a/unix/xserver/hw/vnc/XserverDesktop.cc +++ b/unix/xserver/hw/vnc/XserverDesktop.cc @@ -445,11 +445,17 @@ void XserverDesktop::approveConnection(uint32_t opaqueId, bool accept, // SDesktop callbacks -void XserverDesktop::pointerEvent(const Point& pos, int buttonMask, +void XserverDesktop::pointerEvent(const Point& pos, const Point& abspos, int buttonMask, const bool skipClick, const bool skipRelease) { - vncPointerMove(pos.x + vncGetScreenX(screenIndex), - pos.y + vncGetScreenY(screenIndex)); + if (pos.equals(abspos)) { + vncPointerMove(pos.x + vncGetScreenX(screenIndex), + pos.y + vncGetScreenY(screenIndex)); + } else { + vncPointerMoveRelative(pos.x, pos.y, + abspos.x + vncGetScreenX(screenIndex), + abspos.y + vncGetScreenY(screenIndex)); + } vncPointerButtonAction(buttonMask, skipClick, skipRelease); } diff --git a/unix/xserver/hw/vnc/XserverDesktop.h b/unix/xserver/hw/vnc/XserverDesktop.h index e35f015..0b3f703 100644 --- a/unix/xserver/hw/vnc/XserverDesktop.h +++ b/unix/xserver/hw/vnc/XserverDesktop.h @@ -89,7 +89,7 @@ public: const char* rejectMsg=0); // rfb::SDesktop callbacks - virtual void pointerEvent(const rfb::Point& pos, int buttonMask, + virtual void pointerEvent(const rfb::Point& pos, const rfb::Point& abspos, int buttonMask, const bool skipClick, const bool skipRelease); virtual void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down); virtual unsigned int setScreenLayout(int fb_width, int fb_height,