summaryrefslogtreecommitdiffstats
path: root/libvncserver/rfbserver.c
diff options
context:
space:
mode:
Diffstat (limited to 'libvncserver/rfbserver.c')
-rw-r--r--libvncserver/rfbserver.c69
1 files changed, 67 insertions, 2 deletions
diff --git a/libvncserver/rfbserver.c b/libvncserver/rfbserver.c
index f565f05..93b6c0f 100644
--- a/libvncserver/rfbserver.c
+++ b/libvncserver/rfbserver.c
@@ -348,6 +348,8 @@ rfbNewTCPOrUDPClient(rfbScreenInfoPtr rfbScreen,
cl->enableCursorPosUpdates = FALSE;
cl->useRichCursorEncoding = FALSE;
cl->enableLastRectEncoding = FALSE;
+ cl->enableKeyboardLedState = FALSE;
+ cl->lastKeyboardLedState = -1;
cl->cursorX = rfbScreen->cursorX;
cl->cursorY = rfbScreen->cursorY;
cl->useNewFBSize = FALSE;
@@ -730,6 +732,40 @@ static rfbBool rectSwapIfLEAndClip(uint16_t* x,uint16_t* y,uint16_t* w,uint16_t*
}
/*
+ * Send keyboard state (PointerPos pseudo-encoding).
+ */
+
+rfbBool
+rfbSendKeyboardLedState(rfbClientPtr cl)
+{
+ rfbFramebufferUpdateRectHeader rect;
+
+ if (cl->ublen + sz_rfbFramebufferUpdateRectHeader > UPDATE_BUF_SIZE) {
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+ }
+
+ rect.encoding = Swap32IfLE(rfbEncodingKeyboardLedState);
+ rect.r.x = Swap16IfLE(cl->lastKeyboardLedState);
+ rect.r.y = 0;
+ rect.r.w = 0;
+ rect.r.h = 0;
+
+ memcpy(&cl->updateBuf[cl->ublen], (char *)&rect,
+ sz_rfbFramebufferUpdateRectHeader);
+ cl->ublen += sz_rfbFramebufferUpdateRectHeader;
+
+ cl->cursorPosBytesSent += sz_rfbFramebufferUpdateRectHeader;
+ cl->cursorPosUpdatesSent++;
+
+ if (!rfbSendUpdateBuf(cl))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+/*
* rfbProcessClientNormalMessage is called when the client has sent a normal
* protocol message.
*/
@@ -911,6 +947,13 @@ rfbProcessClientNormalMessage(rfbClientPtr cl)
cl->useNewFBSize = TRUE;
}
break;
+ case rfbEncodingKeyboardLedState:
+ if (!cl->enableKeyboardLedState) {
+ rfbLog("Enabling KeyboardLedState protocol extension for client "
+ "%s\n", cl->host);
+ cl->enableKeyboardLedState = TRUE;
+ }
+ break;
#ifdef LIBVNCSERVER_HAVE_LIBZ
case rfbEncodingZRLE:
if (cl->preferredEncoding == -1) {
@@ -1175,7 +1218,9 @@ rfbSendFramebufferUpdate(rfbClientPtr cl,
int dx, dy;
rfbBool sendCursorShape = FALSE;
rfbBool sendCursorPos = FALSE;
+ rfbBool sendKeyboardLedState = FALSE;
rfbBool result = TRUE;
+
if(cl->screen->displayHook)
cl->screen->displayHook(cl);
@@ -1216,6 +1261,21 @@ rfbSendFramebufferUpdate(rfbClientPtr cl,
if (cl->enableCursorPosUpdates && cl->cursorWasMoved)
sendCursorPos = TRUE;
+ /*
+ * Do we plan to send a keyboard state update?
+ */
+ if ((cl->enableKeyboardLedState) &&
+ (cl->screen->getKeyboardLedStateHook!=NULL))
+ {
+ int x;
+ x=cl->screen->getKeyboardLedStateHook(cl->screen);
+ if (x!=cl->lastKeyboardLedState)
+ {
+ sendKeyboardLedState = TRUE;
+ cl->lastKeyboardLedState=x;
+ }
+ }
+
LOCK(cl->updateMutex);
/*
@@ -1259,7 +1319,7 @@ rfbSendFramebufferUpdate(rfbClientPtr cl,
sraRgnEmpty(updateRegion) &&
(cl->enableCursorShapeUpdates ||
(cl->cursorX == cl->screen->cursorX && cl->cursorY == cl->screen->cursorY)) &&
- !sendCursorShape && !sendCursorPos) {
+ !sendCursorShape && !sendCursorPos && !sendKeyboardLedState) {
sraRgnDestroy(updateRegion);
UNLOCK(cl->updateMutex);
return TRUE;
@@ -1395,7 +1455,7 @@ rfbSendFramebufferUpdate(rfbClientPtr cl,
}
fu->nRects = Swap16IfLE((uint16_t)(sraRgnCountRects(updateCopyRegion) +
nUpdateRegionRects +
- !!sendCursorShape + !!sendCursorPos));
+ !!sendCursorShape + !!sendCursorPos + !!sendKeyboardLedState));
} else {
fu->nRects = 0xFFFF;
}
@@ -1413,6 +1473,11 @@ rfbSendFramebufferUpdate(rfbClientPtr cl,
goto updateFailed;
}
+ if (sendKeyboardLedState) {
+ if (!rfbSendKeyboardLedState(cl))
+ goto updateFailed;
+ }
+
if (!sraRgnEmpty(updateCopyRegion)) {
if (!rfbSendCopyRegion(cl,updateCopyRegion,dx,dy))
goto updateFailed;