Add support for notifying clients about pointer movements
This change adds support for the VMware Mouse Position pseudo-encoding[1], which is used to notify VNC clients when X11 clients call `XWarpPointer()`[2]. This function is called by SDL (and other similar libraries) when they detect that the server does not support native relative motion, like some RFB clients. With this, RFB clients can choose to adjust the local cursor position under certain circumstances to match what the server has set. For instance, if pointer lock has been enabled on the client's machine and the cursor is not being drawn locally, the local position of the cursor is irrelevant, so the RFB client can use what the server sends as the canonical absolute position of the cursor. This ultimately enables the possibility of games (especially FPS games) to behave how users expect (if the clients implement the corresponding change). Part of: #619 1: https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst#vmware-cursor-position-pseudo-encoding 2: https://tronche.com/gui/x/xlib/input/XWarpPointer.html 3: https://hg.libsdl.org/SDL/file/28e3b60e2131/src/events/SDL_mouse.c#l804
This commit is contained in:
@@ -241,6 +241,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 {
|
||||
@@ -358,7 +367,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
|
||||
|
||||
@@ -66,6 +66,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);
|
||||
|
||||
@@ -418,6 +418,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
|
||||
|
||||
@@ -86,6 +86,7 @@ void vncAddCopied(int scrIdx, const struct UpdateRect *extents,
|
||||
|
||||
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);
|
||||
|
||||
@@ -65,6 +65,9 @@ typedef struct _vncHooksScreenRec {
|
||||
RestoreAreasProcPtr RestoreAreas;
|
||||
#endif
|
||||
DisplayCursorProcPtr DisplayCursor;
|
||||
#if XORG >= 119
|
||||
CursorWarpedToProcPtr CursorWarpedTo;
|
||||
#endif
|
||||
ScreenBlockHandlerProcPtr BlockHandler;
|
||||
#ifdef RENDER
|
||||
CompositeProcPtr Composite;
|
||||
@@ -137,6 +140,12 @@ static RegionPtr vncHooksRestoreAreas(WindowPtr pWin, RegionPtr prgnExposed);
|
||||
#endif
|
||||
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 <= 112
|
||||
static void vncHooksBlockHandler(int i, pointer blockData, pointer pTimeout,
|
||||
pointer pReadmask);
|
||||
@@ -316,6 +325,9 @@ int vncHooksInit(int scrIdx)
|
||||
wrap(vncHooksScreen, pScreen, RestoreAreas, vncHooksRestoreAreas);
|
||||
#endif
|
||||
wrap(vncHooksScreen, pScreen, DisplayCursor, vncHooksDisplayCursor);
|
||||
#if XORG >= 119
|
||||
wrap(vncHooksScreen, pScreen, CursorWarpedTo, vncHooksCursorWarpedTo);
|
||||
#endif
|
||||
wrap(vncHooksScreen, pScreen, BlockHandler, vncHooksBlockHandler);
|
||||
#ifdef RENDER
|
||||
ps = GetPictureScreenIfSet(pScreen);
|
||||
@@ -725,6 +737,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.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user