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),
encodings.push_back(pseudoEncodingCursor);
encodings.push_back(pseudoEncodingXCursor);
}
+ if (supportsCursorPosition) {
+ encodings.push_back(pseudoEncodingVMwareCursorPosition);
+ }
if (supportsDesktopResize) {
encodings.push_back(pseudoEncodingDesktopSize);
encodings.push_back(pseudoEncodingExtendedDesktopSize);
// Optional capabilities that a subclass is expected to set to true
// if supported
bool supportsLocalCursor;
+ bool supportsCursorPosition;
bool supportsDesktopResize;
bool supportsLEDState;
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[]);
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());
compressLevel(2), qualityLevel(-1), fineQualityLevel(-1),
subsampling(subsampleUndefined),
width_(0), height_(0), name_(0),
- ledState_(ledUnknown)
+ cursorPos_(0, 0), ledState_(ledUnknown)
{
setName("");
cursor_ = new Cursor(other);
}
+void ClientParams::setCursorPos(const Point& pos)
+{
+ cursorPos_ = pos;
+}
+
bool ClientParams::supportsEncoding(rdr::S32 encoding) const
{
return encodings_.count(encoding) != 0;
return false;
}
+bool ClientParams::supportsCursorPosition() const
+{
+ if (supportsEncoding(pseudoEncodingVMwareCursorPosition))
+ return true;
+ return false;
+}
+
bool ClientParams::supportsDesktopSize() const
{
if (supportsEncoding(pseudoEncodingExtendedDesktopSize))
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);
// Wrappers to check for functionality rather than specific
// encodings
bool supportsLocalCursor() const;
+ bool supportsCursorPosition() const;
bool supportsDesktopSize() const;
bool supportsLEDState() const;
bool supportsFence() const;
PixelFormat pf_;
char* name_;
Cursor* cursor_;
+ Point cursorPos_;
std::set<rdr::S32> encodings_;
unsigned int ledState_;
rdr::U32 clipFlags;
// VMware-specific
const int pseudoEncodingVMwareCursor = 0x574d5664;
+ const int pseudoEncodingVMwareCursorPosition = 0x574d5666;
const int pseudoEncodingVMwareLEDState = 0x574d5668;
// UltraVNC-specific
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*);
{
}
+void CConn::setCursorPos(const rfb::Point&)
+{
+}
+
void CConn::framebufferUpdateStart()
{
CConnection::framebufferUpdateStart();
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);
{
}
+void CConn::setCursorPos(const rfb::Point&)
+{
+}
+
void CConn::framebufferUpdateStart()
{
CConnection::framebufferUpdateStart();
sock = socket;
supportsLocalCursor = true;
+ supportsCursorPosition = true;
supportsDesktopResize = true;
supportsLEDState = false;
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);
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[]);
#ifdef __APPLE__
#include "cocoa.h"
+#include <Carbon/Carbon.h>
#endif
#define EDGE_SCROLL_SIZE 32
// 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
}
}
+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();
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);