CConnection::CConnection() | CConnection::CConnection() | ||||
: csecurity(0), | : csecurity(0), | ||||
supportsLocalCursor(false), supportsDesktopResize(false), | |||||
supportsLEDState(false), | |||||
supportsLocalCursor(false), supportsCursorPosition(false), | |||||
supportsDesktopResize(false), supportsLEDState(false), | |||||
is(0), os(0), reader_(0), writer_(0), | is(0), os(0), reader_(0), writer_(0), | ||||
shared(false), | shared(false), | ||||
state_(RFBSTATE_UNINITIALISED), | state_(RFBSTATE_UNINITIALISED), | ||||
encodings.push_back(pseudoEncodingCursor); | encodings.push_back(pseudoEncodingCursor); | ||||
encodings.push_back(pseudoEncodingXCursor); | encodings.push_back(pseudoEncodingXCursor); | ||||
} | } | ||||
if (supportsCursorPosition) { | |||||
encodings.push_back(pseudoEncodingVMwareCursorPosition); | |||||
} | |||||
if (supportsDesktopResize) { | if (supportsDesktopResize) { | ||||
encodings.push_back(pseudoEncodingDesktopSize); | encodings.push_back(pseudoEncodingDesktopSize); | ||||
encodings.push_back(pseudoEncodingExtendedDesktopSize); | encodings.push_back(pseudoEncodingExtendedDesktopSize); |
// Optional capabilities that a subclass is expected to set to true | // Optional capabilities that a subclass is expected to set to true | ||||
// if supported | // if supported | ||||
bool supportsLocalCursor; | bool supportsLocalCursor; | ||||
bool supportsCursorPosition; | |||||
bool supportsDesktopResize; | bool supportsDesktopResize; | ||||
bool supportsLEDState; | bool supportsLEDState; | ||||
const ScreenSet& layout); | const ScreenSet& layout); | ||||
virtual void setCursor(int width, int height, const Point& hotspot, | virtual void setCursor(int width, int height, const Point& hotspot, | ||||
const rdr::U8* data) = 0; | const rdr::U8* data) = 0; | ||||
virtual void setCursorPos(const Point& pos) = 0; | |||||
virtual void setPixelFormat(const PixelFormat& pf); | virtual void setPixelFormat(const PixelFormat& pf); | ||||
virtual void setName(const char* name); | virtual void setName(const char* name); | ||||
virtual void fence(rdr::U32 flags, unsigned len, const char data[]); | virtual void fence(rdr::U32 flags, unsigned len, const char data[]); |
case pseudoEncodingVMwareCursor: | case pseudoEncodingVMwareCursor: | ||||
ret = readSetVMwareCursor(dataRect.width(), dataRect.height(), dataRect.tl); | ret = readSetVMwareCursor(dataRect.width(), dataRect.height(), dataRect.tl); | ||||
break; | break; | ||||
case pseudoEncodingVMwareCursorPosition: | |||||
handler->setCursorPos(dataRect.tl); | |||||
ret = true; | |||||
break; | |||||
case pseudoEncodingDesktopName: | case pseudoEncodingDesktopName: | ||||
ret = readSetDesktopName(dataRect.tl.x, dataRect.tl.y, | ret = readSetDesktopName(dataRect.tl.x, dataRect.tl.y, | ||||
dataRect.width(), dataRect.height()); | dataRect.width(), dataRect.height()); |
compressLevel(2), qualityLevel(-1), fineQualityLevel(-1), | compressLevel(2), qualityLevel(-1), fineQualityLevel(-1), | ||||
subsampling(subsampleUndefined), | subsampling(subsampleUndefined), | ||||
width_(0), height_(0), name_(0), | width_(0), height_(0), name_(0), | ||||
ledState_(ledUnknown) | |||||
cursorPos_(0, 0), ledState_(ledUnknown) | |||||
{ | { | ||||
setName(""); | setName(""); | ||||
cursor_ = new Cursor(other); | cursor_ = new Cursor(other); | ||||
} | } | ||||
void ClientParams::setCursorPos(const Point& pos) | |||||
{ | |||||
cursorPos_ = pos; | |||||
} | |||||
bool ClientParams::supportsEncoding(rdr::S32 encoding) const | bool ClientParams::supportsEncoding(rdr::S32 encoding) const | ||||
{ | { | ||||
return encodings_.count(encoding) != 0; | return encodings_.count(encoding) != 0; | ||||
return false; | return false; | ||||
} | } | ||||
bool ClientParams::supportsCursorPosition() const | |||||
{ | |||||
if (supportsEncoding(pseudoEncodingVMwareCursorPosition)) | |||||
return true; | |||||
return false; | |||||
} | |||||
bool ClientParams::supportsDesktopSize() const | bool ClientParams::supportsDesktopSize() const | ||||
{ | { | ||||
if (supportsEncoding(pseudoEncodingExtendedDesktopSize)) | if (supportsEncoding(pseudoEncodingExtendedDesktopSize)) |
const Cursor& cursor() const { return *cursor_; } | const Cursor& cursor() const { return *cursor_; } | ||||
void setCursor(const Cursor& cursor); | void setCursor(const Cursor& cursor); | ||||
const Point& cursorPos() const { return cursorPos_; } | |||||
void setCursorPos(const Point& pos); | |||||
bool supportsEncoding(rdr::S32 encoding) const; | bool supportsEncoding(rdr::S32 encoding) const; | ||||
void setEncodings(int nEncodings, const rdr::S32* encodings); | void setEncodings(int nEncodings, const rdr::S32* encodings); | ||||
// Wrappers to check for functionality rather than specific | // Wrappers to check for functionality rather than specific | ||||
// encodings | // encodings | ||||
bool supportsLocalCursor() const; | bool supportsLocalCursor() const; | ||||
bool supportsCursorPosition() const; | |||||
bool supportsDesktopSize() const; | bool supportsDesktopSize() const; | ||||
bool supportsLEDState() const; | bool supportsLEDState() const; | ||||
bool supportsFence() const; | bool supportsFence() const; | ||||
PixelFormat pf_; | PixelFormat pf_; | ||||
char* name_; | char* name_; | ||||
Cursor* cursor_; | Cursor* cursor_; | ||||
Point cursorPos_; | |||||
std::set<rdr::S32> encodings_; | std::set<rdr::S32> encodings_; | ||||
unsigned int ledState_; | unsigned int ledState_; | ||||
rdr::U32 clipFlags; | rdr::U32 clipFlags; |
: client(client_), os(os_), | : client(client_), os(os_), | ||||
nRectsInUpdate(0), nRectsInHeader(0), | nRectsInUpdate(0), nRectsInHeader(0), | ||||
needSetDesktopName(false), needCursor(false), | needSetDesktopName(false), needCursor(false), | ||||
needLEDState(false), needQEMUKeyEvent(false) | |||||
needCursorPos(false), needLEDState(false), | |||||
needQEMUKeyEvent(false) | |||||
{ | { | ||||
} | } | ||||
needCursor = true; | needCursor = true; | ||||
} | } | ||||
void SMsgWriter::writeCursorPos() | |||||
{ | |||||
if (!client->supportsEncoding(pseudoEncodingVMwareCursorPosition)) | |||||
throw Exception("Client does not support cursor position"); | |||||
needCursorPos = true; | |||||
} | |||||
void SMsgWriter::writeLEDState() | void SMsgWriter::writeLEDState() | ||||
{ | { | ||||
if (!client->supportsEncoding(pseudoEncodingLEDState) && | if (!client->supportsEncoding(pseudoEncodingLEDState) && | ||||
return true; | return true; | ||||
if (needCursor) | if (needCursor) | ||||
return true; | return true; | ||||
if (needCursorPos) | |||||
return true; | |||||
if (needLEDState) | if (needLEDState) | ||||
return true; | return true; | ||||
if (needQEMUKeyEvent) | if (needQEMUKeyEvent) | ||||
nRects++; | nRects++; | ||||
if (needCursor) | if (needCursor) | ||||
nRects++; | nRects++; | ||||
if (needCursorPos) | |||||
nRects++; | |||||
if (needLEDState) | if (needLEDState) | ||||
nRects++; | nRects++; | ||||
if (needQEMUKeyEvent) | if (needQEMUKeyEvent) | ||||
needCursor = false; | 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) { | if (needSetDesktopName) { | ||||
writeSetDesktopNameRect(client->name()); | writeSetDesktopNameRect(client->name()); | ||||
needSetDesktopName = false; | needSetDesktopName = false; | ||||
os->writeBytes(data, width*height*4); | 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) | void SMsgWriter::writeLEDStateRect(rdr::U8 state) | ||||
{ | { | ||||
if (!client->supportsEncoding(pseudoEncodingLEDState) && | if (!client->supportsEncoding(pseudoEncodingLEDState) && |
// immediately. | // immediately. | ||||
void writeCursor(); | void writeCursor(); | ||||
// Notifies the client that the cursor pointer was moved by the server. | |||||
void writeCursorPos(); | |||||
// Same for LED state message | // Same for LED state message | ||||
void writeLEDState(); | void writeLEDState(); | ||||
void writeSetVMwareCursorRect(int width, int height, | void writeSetVMwareCursorRect(int width, int height, | ||||
int hotspotX, int hotspotY, | int hotspotX, int hotspotY, | ||||
const rdr::U8* data); | const rdr::U8* data); | ||||
void writeSetVMwareCursorPositionRect(int hotspotX, int hotspotY); | |||||
void writeLEDStateRect(rdr::U8 state); | void writeLEDStateRect(rdr::U8 state); | ||||
void writeQEMUKeyEventRect(); | void writeQEMUKeyEventRect(); | ||||
bool needSetDesktopName; | bool needSetDesktopName; | ||||
bool needCursor; | bool needCursor; | ||||
bool needCursorPos; | |||||
bool needLEDState; | bool needLEDState; | ||||
bool needQEMUKeyEvent; | bool needQEMUKeyEvent; | ||||
} | } | ||||
} | } | ||||
// 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 | // needRenderedCursor() returns true if this client needs the server-side | ||||
// rendered cursor. This may be because it does not support local cursor or | // 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. | // because the current cursor position has not been set by this client. | ||||
writer()->writeCursor(); | 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) | void VNCSConnectionST::setDesktopName(const char *name) | ||||
{ | { | ||||
client.setName(name); | client.setName(name); |
// cursor. | // cursor. | ||||
void renderedCursorChange(); | 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 | // needRenderedCursor() returns true if this client needs the server-side | ||||
// rendered cursor. This may be because it does not support local cursor | // 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. | // or because the current cursor position has not been set by this client. | ||||
void screenLayoutChange(rdr::U16 reason); | void screenLayoutChange(rdr::U16 reason); | ||||
void setCursor(); | void setCursor(); | ||||
void setCursorPos(); | |||||
void setDesktopName(const char *name); | void setDesktopName(const char *name); | ||||
void setLEDState(unsigned int state); | void setLEDState(unsigned int state); | ||||
virtual void setCursor(int width, int height, const Point& hotspot, | virtual void setCursor(int width, int height, const Point& hotspot, | ||||
const rdr::U8* cursorData) = 0; | 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 | // setName() tells the server what desktop title to supply to clients | ||||
virtual void setName(const char* name) = 0; | virtual void setName(const char* name) = 0; |
} | } | ||||
} | } | ||||
void VNCServerST::setCursorPos(const Point& pos) | |||||
void VNCServerST::setCursorPos(const Point& pos, bool warped) | |||||
{ | { | ||||
if (!cursorPos.equals(pos)) { | if (!cursorPos.equals(pos)) { | ||||
cursorPos = pos; | cursorPos = pos; | ||||
renderedCursorInvalid = true; | renderedCursorInvalid = true; | ||||
std::list<VNCSConnectionST*>::iterator ci; | std::list<VNCSConnectionST*>::iterator ci; | ||||
for (ci = clients.begin(); ci != clients.end(); ci++) | |||||
for (ci = clients.begin(); ci != clients.end(); ci++) { | |||||
(*ci)->renderedCursorChange(); | (*ci)->renderedCursorChange(); | ||||
if (warped) | |||||
(*ci)->cursorPositionChange(); | |||||
} | |||||
} | } | ||||
} | } | ||||
virtual void add_copied(const Region &dest, const Point &delta); | virtual void add_copied(const Region &dest, const Point &delta); | ||||
virtual void setCursor(int width, int height, const Point& hotspot, | virtual void setCursor(int width, int height, const Point& hotspot, | ||||
const rdr::U8* data); | 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 setName(const char* name_); | ||||
virtual void setLEDState(unsigned state); | virtual void setLEDState(unsigned state); | ||||
// VMware-specific | // VMware-specific | ||||
const int pseudoEncodingVMwareCursor = 0x574d5664; | const int pseudoEncodingVMwareCursor = 0x574d5664; | ||||
const int pseudoEncodingVMwareCursorPosition = 0x574d5666; | |||||
const int pseudoEncodingVMwareLEDState = 0x574d5668; | const int pseudoEncodingVMwareLEDState = 0x574d5668; | ||||
// UltraVNC-specific | // UltraVNC-specific |
virtual void initDone(); | virtual void initDone(); | ||||
virtual void setPixelFormat(const rfb::PixelFormat& pf); | virtual void setPixelFormat(const rfb::PixelFormat& pf); | ||||
virtual void setCursor(int, int, const rfb::Point&, const rdr::U8*); | virtual void setCursor(int, int, const rfb::Point&, const rdr::U8*); | ||||
virtual void setCursorPos(const rfb::Point&); | |||||
virtual void framebufferUpdateStart(); | virtual void framebufferUpdateStart(); | ||||
virtual void framebufferUpdateEnd(); | virtual void framebufferUpdateEnd(); | ||||
virtual void setColourMapEntries(int, int, rdr::U16*); | virtual void setColourMapEntries(int, int, rdr::U16*); | ||||
{ | { | ||||
} | } | ||||
void CConn::setCursorPos(const rfb::Point&) | |||||
{ | |||||
} | |||||
void CConn::framebufferUpdateStart() | void CConn::framebufferUpdateStart() | ||||
{ | { | ||||
CConnection::framebufferUpdateStart(); | CConnection::framebufferUpdateStart(); |
virtual void initDone() {}; | virtual void initDone() {}; | ||||
virtual void resizeFramebuffer(); | virtual void resizeFramebuffer(); | ||||
virtual void setCursor(int, int, const rfb::Point&, const rdr::U8*); | virtual void setCursor(int, int, const rfb::Point&, const rdr::U8*); | ||||
virtual void setCursorPos(const rfb::Point&); | |||||
virtual void framebufferUpdateStart(); | virtual void framebufferUpdateStart(); | ||||
virtual void framebufferUpdateEnd(); | virtual void framebufferUpdateEnd(); | ||||
virtual bool dataRect(const rfb::Rect&, int); | virtual bool dataRect(const rfb::Rect&, int); | ||||
{ | { | ||||
} | } | ||||
void CConn::setCursorPos(const rfb::Point&) | |||||
{ | |||||
} | |||||
void CConn::framebufferUpdateStart() | void CConn::framebufferUpdateStart() | ||||
{ | { | ||||
CConnection::framebufferUpdateStart(); | CConnection::framebufferUpdateStart(); |
&x, &y, &wx, &wy, &mask); | &x, &y, &wx, &wy, &mask); | ||||
x -= geometry->offsetLeft(); | x -= geometry->offsetLeft(); | ||||
y -= geometry->offsetTop(); | y -= geometry->offsetTop(); | ||||
server->setCursorPos(rfb::Point(x, y)); | |||||
server->setCursorPos(rfb::Point(x, y), false); | |||||
} | } | ||||
} | } | ||||
delete [] cursorData; | 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) | void XserverDesktop::add_changed(const rfb::Region ®ion) | ||||
{ | { | ||||
try { | try { | ||||
if (oldCursorPos.x != cursorX || oldCursorPos.y != cursorY) { | if (oldCursorPos.x != cursorX || oldCursorPos.y != cursorY) { | ||||
oldCursorPos.x = cursorX; | oldCursorPos.x = cursorX; | ||||
oldCursorPos.y = cursorY; | oldCursorPos.y = cursorY; | ||||
server->setCursorPos(oldCursorPos); | |||||
server->setCursorPos(oldCursorPos, false); | |||||
} | } | ||||
// Trigger timers and check when the next will expire | // Trigger timers and check when the next will expire |
void setDesktopName(const char* name); | void setDesktopName(const char* name); | ||||
void setCursor(int width, int height, int hotX, int hotY, | void setCursor(int width, int height, int hotX, int hotY, | ||||
const unsigned char *rgbaData); | const unsigned char *rgbaData); | ||||
void setCursorPos(int x, int y, bool warped); | |||||
void add_changed(const rfb::Region ®ion); | void add_changed(const rfb::Region ®ion); | ||||
void add_copied(const rfb::Region &dest, const rfb::Point &delta); | void add_copied(const rfb::Region &dest, const rfb::Point &delta); | ||||
void handleSocketEvent(int fd, bool read, bool write); | void handleSocketEvent(int fd, bool read, bool write); |
desktop[scr]->setCursor(width, height, hotX, hotY, rgbaData); | 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) | void vncPreScreenResize(int scrIdx) | ||||
{ | { | ||||
// We need to prevent the RFB core from accessing the framebuffer | // We need to prevent the RFB core from accessing the framebuffer |
void vncSetCursor(int width, int height, int hotX, int hotY, | void vncSetCursor(int width, int height, int hotX, int hotY, | ||||
const unsigned char *rgbaData); | const unsigned char *rgbaData); | ||||
void vncSetCursorPos(int scrIdx, int x, int y); | |||||
void vncPreScreenResize(int scrIdx); | void vncPreScreenResize(int scrIdx); | ||||
void vncPostScreenResize(int scrIdx, int success, int width, int height); | void vncPostScreenResize(int scrIdx, int success, int width, int height); |
CopyWindowProcPtr CopyWindow; | CopyWindowProcPtr CopyWindow; | ||||
ClearToBackgroundProcPtr ClearToBackground; | ClearToBackgroundProcPtr ClearToBackground; | ||||
DisplayCursorProcPtr DisplayCursor; | DisplayCursorProcPtr DisplayCursor; | ||||
#if XORG >= 119 | |||||
CursorWarpedToProcPtr CursorWarpedTo; | |||||
#endif | |||||
ScreenBlockHandlerProcPtr BlockHandler; | ScreenBlockHandlerProcPtr BlockHandler; | ||||
#ifdef RENDER | #ifdef RENDER | ||||
CompositeProcPtr Composite; | CompositeProcPtr Composite; | ||||
int h, Bool generateExposures); | int h, Bool generateExposures); | ||||
static Bool vncHooksDisplayCursor(DeviceIntPtr pDev, | static Bool vncHooksDisplayCursor(DeviceIntPtr pDev, | ||||
ScreenPtr pScreen, CursorPtr cursor); | 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 | #if XORG <= 118 | ||||
static void vncHooksBlockHandler(ScreenPtr pScreen, void * pTimeout, | static void vncHooksBlockHandler(ScreenPtr pScreen, void * pTimeout, | ||||
void * pReadmask); | void * pReadmask); | ||||
wrap(vncHooksScreen, pScreen, CopyWindow, vncHooksCopyWindow); | wrap(vncHooksScreen, pScreen, CopyWindow, vncHooksCopyWindow); | ||||
wrap(vncHooksScreen, pScreen, ClearToBackground, vncHooksClearToBackground); | wrap(vncHooksScreen, pScreen, ClearToBackground, vncHooksClearToBackground); | ||||
wrap(vncHooksScreen, pScreen, DisplayCursor, vncHooksDisplayCursor); | wrap(vncHooksScreen, pScreen, DisplayCursor, vncHooksDisplayCursor); | ||||
#if XORG >= 119 | |||||
wrap(vncHooksScreen, pScreen, CursorWarpedTo, vncHooksCursorWarpedTo); | |||||
#endif | |||||
wrap(vncHooksScreen, pScreen, BlockHandler, vncHooksBlockHandler); | wrap(vncHooksScreen, pScreen, BlockHandler, vncHooksBlockHandler); | ||||
#ifdef RENDER | #ifdef RENDER | ||||
ps = GetPictureScreenIfSet(pScreen); | ps = GetPictureScreenIfSet(pScreen); | ||||
return ret; | 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 | // BlockHandler - ignore any changes during the block handler - it's likely | ||||
// these are just drawing the cursor. | // these are just drawing the cursor. | ||||
sock = socket; | sock = socket; | ||||
supportsLocalCursor = true; | supportsLocalCursor = true; | ||||
supportsCursorPosition = true; | |||||
supportsDesktopResize = true; | supportsDesktopResize = true; | ||||
supportsLEDState = false; | supportsLEDState = false; | ||||
desktop->setCursor(width, height, hotspot, data); | 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[]) | void CConn::fence(rdr::U32 flags, unsigned len, const char data[]) | ||||
{ | { | ||||
CMsgHandler::fence(flags, len, data); | CMsgHandler::fence(flags, len, data); |
void setCursor(int width, int height, const rfb::Point& hotspot, | void setCursor(int width, int height, const rfb::Point& hotspot, | ||||
const rdr::U8* data); | const rdr::U8* data); | ||||
void setCursorPos(const rfb::Point& pos); | |||||
void fence(rdr::U32 flags, unsigned len, const char data[]); | void fence(rdr::U32 flags, unsigned len, const char data[]); | ||||
#ifdef __APPLE__ | #ifdef __APPLE__ | ||||
#include "cocoa.h" | #include "cocoa.h" | ||||
#include <Carbon/Carbon.h> | |||||
#endif | #endif | ||||
#define EDGE_SCROLL_SIZE 32 | #define EDGE_SCROLL_SIZE 32 | ||||
// Show hint about menu key | // Show hint about menu key | ||||
Fl::add_timeout(0.5, menuOverlay, this); | 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 | |||||
} | } | ||||
} | } | ||||
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() | void DesktopWindow::show() | ||||
{ | { | ||||
Fl_Window::show(); | Fl_Window::show(); |
void setCursor(int width, int height, const rfb::Point& hotspot, | void setCursor(int width, int height, const rfb::Point& hotspot, | ||||
const rdr::U8* data); | const rdr::U8* data); | ||||
// Server-provided cursor position | |||||
void setCursorPos(const rfb::Point& pos); | |||||
// Change client LED state | // Change client LED state | ||||
void setLEDState(unsigned int state); | void setLEDState(unsigned int state); | ||||
// Update the cursor position | // Update the cursor position | ||||
// NB: First translate from Screen coordinates to Desktop | // NB: First translate from Screen coordinates to Desktop | ||||
Point desktopPos = info.position.translate(screenRect.tl.negate()); | Point desktopPos = info.position.translate(screenRect.tl.negate()); | ||||
server->setCursorPos(desktopPos); | |||||
server->setCursorPos(desktopPos, false); | |||||
old_cursor = info; | old_cursor = info; | ||||
} | } |