diff options
27 files changed, 212 insertions, 12 deletions
diff --git a/common/rfb/CConnection.cxx b/common/rfb/CConnection.cxx index 9a9593e2..1c949009 100644 --- a/common/rfb/CConnection.cxx +++ b/common/rfb/CConnection.cxx @@ -43,8 +43,8 @@ static LogWriter vlog("CConnection"); CConnection::CConnection() : csecurity(0), - supportsLocalCursor(false), supportsDesktopResize(false), - supportsLEDState(false), + supportsLocalCursor(false), supportsCursorPosition(false), + supportsDesktopResize(false), supportsLEDState(false), is(0), os(0), reader_(0), writer_(0), shared(false), state_(RFBSTATE_UNINITIALISED), @@ -805,6 +805,9 @@ void CConnection::updateEncodings() encodings.push_back(pseudoEncodingCursor); encodings.push_back(pseudoEncodingXCursor); } + if (supportsCursorPosition) { + encodings.push_back(pseudoEncodingVMwareCursorPosition); + } if (supportsDesktopResize) { encodings.push_back(pseudoEncodingDesktopSize); encodings.push_back(pseudoEncodingExtendedDesktopSize); diff --git a/common/rfb/CConnection.h b/common/rfb/CConnection.h index deab50ae..d5d07ca0 100644 --- a/common/rfb/CConnection.h +++ b/common/rfb/CConnection.h @@ -239,6 +239,7 @@ namespace rfb { // Optional capabilities that a subclass is expected to set to true // if supported bool supportsLocalCursor; + bool supportsCursorPosition; bool supportsDesktopResize; bool supportsLEDState; diff --git a/common/rfb/CMsgHandler.h b/common/rfb/CMsgHandler.h index 5b14806a..43d8df24 100644 --- a/common/rfb/CMsgHandler.h +++ b/common/rfb/CMsgHandler.h @@ -52,6 +52,7 @@ namespace rfb { const ScreenSet& layout); virtual void setCursor(int width, int height, const Point& hotspot, const rdr::U8* data) = 0; + virtual void setCursorPos(const Point& pos) = 0; virtual void setPixelFormat(const PixelFormat& pf); virtual void setName(const char* name); virtual void fence(rdr::U32 flags, unsigned len, const char data[]); diff --git a/common/rfb/CMsgReader.cxx b/common/rfb/CMsgReader.cxx index f69e21de..2c823d56 100644 --- a/common/rfb/CMsgReader.cxx +++ b/common/rfb/CMsgReader.cxx @@ -165,6 +165,10 @@ bool CMsgReader::readMsg() case pseudoEncodingVMwareCursor: ret = readSetVMwareCursor(dataRect.width(), dataRect.height(), dataRect.tl); break; + case pseudoEncodingVMwareCursorPosition: + handler->setCursorPos(dataRect.tl); + ret = true; + break; case pseudoEncodingDesktopName: ret = readSetDesktopName(dataRect.tl.x, dataRect.tl.y, dataRect.width(), dataRect.height()); diff --git a/common/rfb/ClientParams.cxx b/common/rfb/ClientParams.cxx index 6f075a24..c0cc3641 100644 --- a/common/rfb/ClientParams.cxx +++ b/common/rfb/ClientParams.cxx @@ -30,7 +30,7 @@ ClientParams::ClientParams() compressLevel(2), qualityLevel(-1), fineQualityLevel(-1), subsampling(subsampleUndefined), width_(0), height_(0), name_(0), - ledState_(ledUnknown) + cursorPos_(0, 0), ledState_(ledUnknown) { setName(""); @@ -85,6 +85,11 @@ void ClientParams::setCursor(const Cursor& other) cursor_ = new Cursor(other); } +void ClientParams::setCursorPos(const Point& pos) +{ + cursorPos_ = pos; +} + bool ClientParams::supportsEncoding(rdr::S32 encoding) const { return encodings_.count(encoding) != 0; @@ -182,6 +187,13 @@ bool ClientParams::supportsLocalCursor() const return false; } +bool ClientParams::supportsCursorPosition() const +{ + if (supportsEncoding(pseudoEncodingVMwareCursorPosition)) + return true; + return false; +} + bool ClientParams::supportsDesktopSize() const { if (supportsEncoding(pseudoEncodingExtendedDesktopSize)) diff --git a/common/rfb/ClientParams.h b/common/rfb/ClientParams.h index 3894ef2d..202cef4e 100644 --- a/common/rfb/ClientParams.h +++ b/common/rfb/ClientParams.h @@ -77,6 +77,9 @@ namespace rfb { const Cursor& cursor() const { return *cursor_; } void setCursor(const Cursor& cursor); + const Point& cursorPos() const { return cursorPos_; } + void setCursorPos(const Point& pos); + bool supportsEncoding(rdr::S32 encoding) const; void setEncodings(int nEncodings, const rdr::S32* encodings); @@ -91,6 +94,7 @@ namespace rfb { // Wrappers to check for functionality rather than specific // encodings bool supportsLocalCursor() const; + bool supportsCursorPosition() const; bool supportsDesktopSize() const; bool supportsLEDState() const; bool supportsFence() const; @@ -110,6 +114,7 @@ namespace rfb { PixelFormat pf_; char* name_; Cursor* cursor_; + Point cursorPos_; std::set<rdr::S32> encodings_; unsigned int ledState_; rdr::U32 clipFlags; diff --git a/common/rfb/SMsgWriter.cxx b/common/rfb/SMsgWriter.cxx index a29ed9d8..2f40c0a6 100644 --- a/common/rfb/SMsgWriter.cxx +++ b/common/rfb/SMsgWriter.cxx @@ -42,7 +42,8 @@ SMsgWriter::SMsgWriter(ClientParams* client_, rdr::OutStream* os_) : client(client_), os(os_), nRectsInUpdate(0), nRectsInHeader(0), needSetDesktopName(false), needCursor(false), - needLEDState(false), needQEMUKeyEvent(false) + needCursorPos(false), needLEDState(false), + needQEMUKeyEvent(false) { } @@ -269,6 +270,14 @@ void SMsgWriter::writeCursor() needCursor = true; } +void SMsgWriter::writeCursorPos() +{ + if (!client->supportsEncoding(pseudoEncodingVMwareCursorPosition)) + throw Exception("Client does not support cursor position"); + + needCursorPos = true; +} + void SMsgWriter::writeLEDState() { if (!client->supportsEncoding(pseudoEncodingLEDState) && @@ -294,6 +303,8 @@ bool SMsgWriter::needFakeUpdate() return true; if (needCursor) return true; + if (needCursorPos) + return true; if (needLEDState) return true; if (needQEMUKeyEvent) @@ -340,6 +351,8 @@ void SMsgWriter::writeFramebufferUpdateStart(int nRects) nRects++; if (needCursor) nRects++; + if (needCursorPos) + nRects++; if (needLEDState) nRects++; if (needQEMUKeyEvent) @@ -455,6 +468,18 @@ void SMsgWriter::writePseudoRects() needCursor = false; } + if (needCursorPos) { + const Point& cursorPos = client->cursorPos(); + + if (client->supportsEncoding(pseudoEncodingVMwareCursorPosition)) { + writeSetVMwareCursorPositionRect(cursorPos.x, cursorPos.y); + } else { + throw Exception("Client does not support cursor position"); + } + + needCursorPos = false; + } + if (needSetDesktopName) { writeSetDesktopNameRect(client->name()); needSetDesktopName = false; @@ -650,6 +675,20 @@ void SMsgWriter::writeSetVMwareCursorRect(int width, int height, os->writeBytes(data, width*height*4); } +void SMsgWriter::writeSetVMwareCursorPositionRect(int hotspotX, int hotspotY) +{ + if (!client->supportsEncoding(pseudoEncodingVMwareCursorPosition)) + throw Exception("Client does not support cursor position"); + if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader) + throw Exception("SMsgWriter::writeSetVMwareCursorRect: nRects out of sync"); + + os->writeS16(hotspotX); + os->writeS16(hotspotY); + os->writeU16(0); + os->writeU16(0); + os->writeU32(pseudoEncodingVMwareCursorPosition); +} + void SMsgWriter::writeLEDStateRect(rdr::U8 state) { if (!client->supportsEncoding(pseudoEncodingLEDState) && diff --git a/common/rfb/SMsgWriter.h b/common/rfb/SMsgWriter.h index 2cea44d1..49381bad 100644 --- a/common/rfb/SMsgWriter.h +++ b/common/rfb/SMsgWriter.h @@ -83,6 +83,9 @@ namespace rfb { // immediately. void writeCursor(); + // Notifies the client that the cursor pointer was moved by the server. + void writeCursorPos(); + // Same for LED state message void writeLEDState(); @@ -141,6 +144,7 @@ namespace rfb { void writeSetVMwareCursorRect(int width, int height, int hotspotX, int hotspotY, const rdr::U8* data); + void writeSetVMwareCursorPositionRect(int hotspotX, int hotspotY); void writeLEDStateRect(rdr::U8 state); void writeQEMUKeyEventRect(); @@ -152,6 +156,7 @@ namespace rfb { bool needSetDesktopName; bool needCursor; + bool needCursorPos; bool needLEDState; bool needQEMUKeyEvent; diff --git a/common/rfb/VNCSConnectionST.cxx b/common/rfb/VNCSConnectionST.cxx index 668bae0e..a966e66c 100644 --- a/common/rfb/VNCSConnectionST.cxx +++ b/common/rfb/VNCSConnectionST.cxx @@ -370,6 +370,15 @@ void VNCSConnectionST::renderedCursorChange() } } +// cursorPositionChange() is called whenever the cursor has changed position by +// the server. If the client supports being informed about these changes then +// it will arrange for the new cursor position to be sent to the client. + +void VNCSConnectionST::cursorPositionChange() +{ + setCursorPos(); +} + // needRenderedCursor() returns true if this client needs the server-side // rendered cursor. This may be because it does not support local cursor or // because the current cursor position has not been set by this client. @@ -1123,6 +1132,21 @@ void VNCSConnectionST::setCursor() writer()->writeCursor(); } +// setCursorPos() is called whenever the cursor has changed position by the +// server. If the client supports being informed about these changes then it +// will arrange for the new cursor position to be sent to the client. + +void VNCSConnectionST::setCursorPos() +{ + if (state() != RFBSTATE_NORMAL) + return; + + if (client.supportsCursorPosition()) { + client.setCursorPos(server->getCursorPos()); + writer()->writeCursorPos(); + } +} + void VNCSConnectionST::setDesktopName(const char *name) { client.setName(name); diff --git a/common/rfb/VNCSConnectionST.h b/common/rfb/VNCSConnectionST.h index 6d95008d..72b0c529 100644 --- a/common/rfb/VNCSConnectionST.h +++ b/common/rfb/VNCSConnectionST.h @@ -93,6 +93,11 @@ namespace rfb { // cursor. void renderedCursorChange(); + // cursorPositionChange() is called whenever the cursor has changed position by + // the server. If the client supports being informed about these changes then + // it will arrange for the new cursor position to be sent to the client. + void cursorPositionChange(); + // needRenderedCursor() returns true if this client needs the server-side // rendered cursor. This may be because it does not support local cursor // or because the current cursor position has not been set by this client. @@ -155,6 +160,7 @@ namespace rfb { void screenLayoutChange(rdr::U16 reason); void setCursor(); + void setCursorPos(); void setDesktopName(const char *name); void setLEDState(unsigned int state); diff --git a/common/rfb/VNCServer.h b/common/rfb/VNCServer.h index 5d04da53..4535b562 100644 --- a/common/rfb/VNCServer.h +++ b/common/rfb/VNCServer.h @@ -97,8 +97,10 @@ namespace rfb { virtual void setCursor(int width, int height, const Point& hotspot, const rdr::U8* cursorData) = 0; - // setCursorPos() tells the server the current position of the cursor. - virtual void setCursorPos(const Point& p) = 0; + // setCursorPos() tells the server the current position of the cursor, and + // whether the server initiated that change (e.g. through another X11 + // client calling XWarpPointer()). + virtual void setCursorPos(const Point& p, bool warped) = 0; // setName() tells the server what desktop title to supply to clients virtual void setName(const char* name) = 0; diff --git a/common/rfb/VNCServerST.cxx b/common/rfb/VNCServerST.cxx index b32cac59..39cdde1f 100644 --- a/common/rfb/VNCServerST.cxx +++ b/common/rfb/VNCServerST.cxx @@ -429,14 +429,17 @@ void VNCServerST::setCursor(int width, int height, const Point& newHotspot, } } -void VNCServerST::setCursorPos(const Point& pos) +void VNCServerST::setCursorPos(const Point& pos, bool warped) { if (!cursorPos.equals(pos)) { cursorPos = pos; renderedCursorInvalid = true; std::list<VNCSConnectionST*>::iterator ci; - for (ci = clients.begin(); ci != clients.end(); ci++) + for (ci = clients.begin(); ci != clients.end(); ci++) { (*ci)->renderedCursorChange(); + if (warped) + (*ci)->cursorPositionChange(); + } } } diff --git a/common/rfb/VNCServerST.h b/common/rfb/VNCServerST.h index fd20cc37..159e3a4b 100644 --- a/common/rfb/VNCServerST.h +++ b/common/rfb/VNCServerST.h @@ -99,7 +99,7 @@ namespace rfb { virtual void add_copied(const Region &dest, const Point &delta); virtual void setCursor(int width, int height, const Point& hotspot, const rdr::U8* data); - virtual void setCursorPos(const Point& p); + virtual void setCursorPos(const Point& p, bool warped); virtual void setName(const char* name_); virtual void setLEDState(unsigned state); diff --git a/common/rfb/encodings.h b/common/rfb/encodings.h index cf0c8572..f7ad7890 100644 --- a/common/rfb/encodings.h +++ b/common/rfb/encodings.h @@ -61,6 +61,7 @@ namespace rfb { // VMware-specific const int pseudoEncodingVMwareCursor = 0x574d5664; + const int pseudoEncodingVMwareCursorPosition = 0x574d5666; const int pseudoEncodingVMwareLEDState = 0x574d5668; // UltraVNC-specific diff --git a/tests/perf/decperf.cxx b/tests/perf/decperf.cxx index a6c65a22..23f3fe24 100644 --- a/tests/perf/decperf.cxx +++ b/tests/perf/decperf.cxx @@ -66,6 +66,7 @@ public: virtual void initDone(); virtual void setPixelFormat(const rfb::PixelFormat& pf); virtual void setCursor(int, int, const rfb::Point&, const rdr::U8*); + virtual void setCursorPos(const rfb::Point&); virtual void framebufferUpdateStart(); virtual void framebufferUpdateEnd(); virtual void setColourMapEntries(int, int, rdr::U16*); @@ -144,6 +145,10 @@ void CConn::setCursor(int, int, const rfb::Point&, const rdr::U8*) { } +void CConn::setCursorPos(const rfb::Point&) +{ +} + void CConn::framebufferUpdateStart() { CConnection::framebufferUpdateStart(); diff --git a/tests/perf/encperf.cxx b/tests/perf/encperf.cxx index 9f30cab7..69121ffa 100644 --- a/tests/perf/encperf.cxx +++ b/tests/perf/encperf.cxx @@ -95,6 +95,7 @@ public: virtual void initDone() {}; virtual void resizeFramebuffer(); virtual void setCursor(int, int, const rfb::Point&, const rdr::U8*); + virtual void setCursorPos(const rfb::Point&); virtual void framebufferUpdateStart(); virtual void framebufferUpdateEnd(); virtual bool dataRect(const rfb::Rect&, int); @@ -216,6 +217,10 @@ void CConn::setCursor(int, int, const rfb::Point&, const rdr::U8*) { } +void CConn::setCursorPos(const rfb::Point&) +{ +} + void CConn::framebufferUpdateStart() { CConnection::framebufferUpdateStart(); diff --git a/unix/x0vncserver/XDesktop.cxx b/unix/x0vncserver/XDesktop.cxx index eb36467e..e8e74fa7 100644 --- a/unix/x0vncserver/XDesktop.cxx +++ b/unix/x0vncserver/XDesktop.cxx @@ -217,7 +217,7 @@ void XDesktop::poll() { &x, &y, &wx, &wy, &mask); x -= geometry->offsetLeft(); y -= geometry->offsetTop(); - server->setCursorPos(rfb::Point(x, y)); + server->setCursorPos(rfb::Point(x, y), false); } } diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc index 6f707299..7ebad353 100644 --- a/unix/xserver/hw/vnc/XserverDesktop.cc +++ b/unix/xserver/hw/vnc/XserverDesktop.cc @@ -261,6 +261,15 @@ void XserverDesktop::setCursor(int width, int height, int hotX, int hotY, delete [] cursorData; } +void XserverDesktop::setCursorPos(int x, int y, bool warped) +{ + try { + server->setCursorPos(Point(x, y), warped); + } catch (rdr::Exception& e) { + vlog.error("XserverDesktop::setCursorPos: %s",e.str()); + } +} + void XserverDesktop::add_changed(const rfb::Region ®ion) { try { @@ -377,7 +386,7 @@ void XserverDesktop::blockHandler(int* timeout) if (oldCursorPos.x != cursorX || oldCursorPos.y != cursorY) { oldCursorPos.x = cursorX; oldCursorPos.y = cursorY; - server->setCursorPos(oldCursorPos); + server->setCursorPos(oldCursorPos, false); } // Trigger timers and check when the next will expire diff --git a/unix/xserver/hw/vnc/XserverDesktop.h b/unix/xserver/hw/vnc/XserverDesktop.h index cc50f9e9..383e0bbf 100644 --- a/unix/xserver/hw/vnc/XserverDesktop.h +++ b/unix/xserver/hw/vnc/XserverDesktop.h @@ -67,6 +67,7 @@ public: void setDesktopName(const char* name); void setCursor(int width, int height, int hotX, int hotY, const unsigned char *rgbaData); + void setCursorPos(int x, int y, bool warped); void add_changed(const rfb::Region ®ion); void add_copied(const rfb::Region &dest, const rfb::Point &delta); void handleSocketEvent(int fd, bool read, bool write); diff --git a/unix/xserver/hw/vnc/vncExtInit.cc b/unix/xserver/hw/vnc/vncExtInit.cc index a45c5bde..6c4612d1 100644 --- a/unix/xserver/hw/vnc/vncExtInit.cc +++ b/unix/xserver/hw/vnc/vncExtInit.cc @@ -400,6 +400,11 @@ void vncSetCursor(int width, int height, int hotX, int hotY, desktop[scr]->setCursor(width, height, hotX, hotY, rgbaData); } +void vncSetCursorPos(int scrIdx, int x, int y) +{ + desktop[scrIdx]->setCursorPos(x, y, true); +} + void vncPreScreenResize(int scrIdx) { // We need to prevent the RFB core from accessing the framebuffer diff --git a/unix/xserver/hw/vnc/vncExtInit.h b/unix/xserver/hw/vnc/vncExtInit.h index 23c0c669..36e52032 100644 --- a/unix/xserver/hw/vnc/vncExtInit.h +++ b/unix/xserver/hw/vnc/vncExtInit.h @@ -81,6 +81,7 @@ void vncAddCopied(int scrIdx, int nRects, void vncSetCursor(int width, int height, int hotX, int hotY, const unsigned char *rgbaData); +void vncSetCursorPos(int scrIdx, int x, int y); void vncPreScreenResize(int scrIdx); void vncPostScreenResize(int scrIdx, int success, int width, int height); diff --git a/unix/xserver/hw/vnc/vncHooks.c b/unix/xserver/hw/vnc/vncHooks.c index a8ab917b..d206e342 100644 --- a/unix/xserver/hw/vnc/vncHooks.c +++ b/unix/xserver/hw/vnc/vncHooks.c @@ -62,6 +62,9 @@ typedef struct _vncHooksScreenRec { CopyWindowProcPtr CopyWindow; ClearToBackgroundProcPtr ClearToBackground; DisplayCursorProcPtr DisplayCursor; +#if XORG >= 119 + CursorWarpedToProcPtr CursorWarpedTo; +#endif ScreenBlockHandlerProcPtr BlockHandler; #ifdef RENDER CompositeProcPtr Composite; @@ -113,6 +116,12 @@ static void vncHooksClearToBackground(WindowPtr pWin, int x, int y, int w, int h, Bool generateExposures); static Bool vncHooksDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr cursor); +#if XORG >= 119 +static void vncHooksCursorWarpedTo(DeviceIntPtr pDev, + ScreenPtr pScreen_, ClientPtr pClient, + WindowPtr pWindow, SpritePtr pSprite, + int x, int y); +#endif #if XORG <= 118 static void vncHooksBlockHandler(ScreenPtr pScreen, void * pTimeout, void * pReadmask); @@ -271,6 +280,9 @@ int vncHooksInit(int scrIdx) wrap(vncHooksScreen, pScreen, CopyWindow, vncHooksCopyWindow); wrap(vncHooksScreen, pScreen, ClearToBackground, vncHooksClearToBackground); wrap(vncHooksScreen, pScreen, DisplayCursor, vncHooksDisplayCursor); +#if XORG >= 119 + wrap(vncHooksScreen, pScreen, CursorWarpedTo, vncHooksCursorWarpedTo); +#endif wrap(vncHooksScreen, pScreen, BlockHandler, vncHooksBlockHandler); #ifdef RENDER ps = GetPictureScreenIfSet(pScreen); @@ -631,6 +643,20 @@ out: return ret; } +// CursorWarpedTo - notify that the cursor was warped + +#if XORG >= 119 +static void vncHooksCursorWarpedTo(DeviceIntPtr pDev, + ScreenPtr pScreen_, ClientPtr pClient, + WindowPtr pWindow, SpritePtr pSprite, + int x, int y) +{ + SCREEN_PROLOGUE(pScreen_, CursorWarpedTo); + vncSetCursorPos(pScreen->myNum, x, y); + SCREEN_EPILOGUE(CursorWarpedTo); +} +#endif + // BlockHandler - ignore any changes during the block handler - it's likely // these are just drawing the cursor. diff --git a/vncviewer/CConn.cxx b/vncviewer/CConn.cxx index 4894ddf7..e1f5f70a 100644 --- a/vncviewer/CConn.cxx +++ b/vncviewer/CConn.cxx @@ -84,6 +84,7 @@ CConn::CConn(const char* vncServerName, network::Socket* socket=NULL) sock = socket; supportsLocalCursor = true; + supportsCursorPosition = true; supportsDesktopResize = true; supportsLEDState = false; @@ -430,6 +431,11 @@ void CConn::setCursor(int width, int height, const Point& hotspot, desktop->setCursor(width, height, hotspot, data); } +void CConn::setCursorPos(const Point& pos) +{ + desktop->setCursorPos(pos); +} + void CConn::fence(rdr::U32 flags, unsigned len, const char data[]) { CMsgHandler::fence(flags, len, data); diff --git a/vncviewer/CConn.h b/vncviewer/CConn.h index ad3fb797..e662ec87 100644 --- a/vncviewer/CConn.h +++ b/vncviewer/CConn.h @@ -63,6 +63,7 @@ public: void setCursor(int width, int height, const rfb::Point& hotspot, const rdr::U8* data); + void setCursorPos(const rfb::Point& pos); void fence(rdr::U32 flags, unsigned len, const char data[]); diff --git a/vncviewer/DesktopWindow.cxx b/vncviewer/DesktopWindow.cxx index 6dc85f4a..5401b191 100644 --- a/vncviewer/DesktopWindow.cxx +++ b/vncviewer/DesktopWindow.cxx @@ -51,6 +51,7 @@ #ifdef __APPLE__ #include "cocoa.h" +#include <Carbon/Carbon.h> #endif #define EDGE_SCROLL_SIZE 32 @@ -186,6 +187,14 @@ DesktopWindow::DesktopWindow(int w, int h, const char *name, // Show hint about menu key Fl::add_timeout(0.5, menuOverlay, this); + + // By default we get a slight delay when we warp the pointer, something + // we don't want or we'll get jerky movement +#ifdef __APPLE__ + CGEventSourceRef event = CGEventSourceCreate(kCGEventSourceStateCombinedSessionState); + CGEventSourceSetLocalEventsSuppressionInterval(event, 0); + CFRelease(event); +#endif } @@ -322,6 +331,29 @@ void DesktopWindow::setCursor(int width, int height, } +void DesktopWindow::setCursorPos(const rfb::Point& pos) +{ + if (!mouseGrabbed) { + // Do nothing if we do not have the mouse captured. + return; + } +#if defined(WIN32) + SetCursorPos(pos.x + x_root() + viewport->x(), + pos.y + y_root() + viewport->y()); +#elif defined(__APPLE__) + CGPoint new_pos; + new_pos.x = pos.x + x_root() + viewport->x(); + new_pos.y = pos.y + y_root() + viewport->y(); + CGWarpMouseCursorPosition(new_pos); +#else // Assume this is Xlib + Window rootwindow = DefaultRootWindow(fl_display); + XWarpPointer(fl_display, rootwindow, rootwindow, 0, 0, 0, 0, + pos.x + x_root() + viewport->x(), + pos.y + y_root() + viewport->y()); +#endif +} + + void DesktopWindow::show() { Fl_Window::show(); diff --git a/vncviewer/DesktopWindow.h b/vncviewer/DesktopWindow.h index ef3dbb08..67be6c6a 100644 --- a/vncviewer/DesktopWindow.h +++ b/vncviewer/DesktopWindow.h @@ -66,6 +66,9 @@ public: void setCursor(int width, int height, const rfb::Point& hotspot, const rdr::U8* data); + // Server-provided cursor position + void setCursorPos(const rfb::Point& pos); + // Change client LED state void setLEDState(unsigned int state); diff --git a/win/rfb_win32/SDisplay.cxx b/win/rfb_win32/SDisplay.cxx index 06eccd9a..a9ee3615 100644 --- a/win/rfb_win32/SDisplay.cxx +++ b/win/rfb_win32/SDisplay.cxx @@ -417,7 +417,7 @@ SDisplay::processEvent(HANDLE event) { // Update the cursor position // NB: First translate from Screen coordinates to Desktop Point desktopPos = info.position.translate(screenRect.tl.negate()); - server->setCursorPos(desktopPos); + server->setCursorPos(desktopPos, false); old_cursor = info; } |