summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordscho <dscho>2006-03-28 14:49:21 +0000
committerdscho <dscho>2006-03-28 14:49:21 +0000
commit1602b345f3e7e508b043133d5c289d9984e39f18 (patch)
tree0698f886cd49a803dcfbbd08ab5b4cd4c7a9fd73
parent5920dc18d75a53690ed8690867f501c51595daf1 (diff)
downloadlibtdevnc-1602b345f3e7e508b043133d5c289d9984e39f18.tar.gz
libtdevnc-1602b345f3e7e508b043133d5c289d9984e39f18.zip
add KeyboardLedState extension
-rw-r--r--ChangeLog4
-rw-r--r--client_examples/SDLvncviewer.c8
-rw-r--r--libvncclient/rfbproto.c21
-rw-r--r--libvncclient/vncviewer.c7
-rw-r--r--libvncserver/main.c1
-rw-r--r--libvncserver/rfbserver.c69
-rw-r--r--rfb/rfb.h9
-rw-r--r--rfb/rfbclient.h6
-rw-r--r--rfb/rfbproto.h1
9 files changed, 122 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 416b4a1..69d3ec8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,7 @@
+2006-03-28 Steven Carr <scarr@jsa-usa.com>
+ * SDLvncviewer.c, rfbproto.c, vncviewer.c, main.c, rfbserver.c,
+ rfb.h, rfbclient.h, rfbproto.h: add new encoding: KeyboardLedState
+
2006-03-28 Karl Runge <runge@karlrunge.com>
* classes/ssl: patch to tightvnc Java viewer for SSL support
plus other fixes (richcursor colors, Tab keysym, etc).
diff --git a/client_examples/SDLvncviewer.c b/client_examples/SDLvncviewer.c
index b32c49b..2e33b09 100644
--- a/client_examples/SDLvncviewer.c
+++ b/client_examples/SDLvncviewer.c
@@ -143,6 +143,12 @@ static void update(rfbClient* cl,int x,int y,int w,int h) {
SDL_UpdateRect(rfbClientGetClientData(cl, SDL_Init), x, y, w, h);
}
+static void kbd_leds(rfbClient* cl, int value, int pad) {
+ /* note: pad is for future expansion 0=unused */
+ fprintf(stderr,"Led State= 0x%02X\n", value);
+ fflush(stderr);
+}
+
#ifdef __MINGW32__
#define LOG_TO_FILE
#endif
@@ -203,6 +209,8 @@ int main(int argc,char** argv) {
cl=rfbGetClient(8,3,4);
cl->MallocFrameBuffer=resize;
cl->GotFrameBufferUpdate=update;
+ cl->HandleKeyboardLedState=kbd_leds;
+
if(!rfbInitClient(cl,&argc,argv))
return 1;
diff --git a/libvncclient/rfbproto.c b/libvncclient/rfbproto.c
index 7f79c92..fe58a5e 100644
--- a/libvncclient/rfbproto.c
+++ b/libvncclient/rfbproto.c
@@ -521,6 +521,7 @@ SetFormatAndEncodings(rfbClient* client)
rfbEncodingQualityLevel0);
}
+
if (client->appData.useRemoteCursor) {
if (se->nEncodings < MAX_ENCODINGS)
encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingXCursor);
@@ -530,6 +531,11 @@ SetFormatAndEncodings(rfbClient* client)
encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingPointerPos);
}
+ /* Let's receive keyboard state encoding if available */
+ if (se->nEncodings < MAX_ENCODINGS) {
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingKeyboardLedState);
+ }
+
if (se->nEncodings < MAX_ENCODINGS && requestLastRectEncoding) {
encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingLastRect);
}
@@ -586,6 +592,11 @@ SetFormatAndEncodings(rfbClient* client)
encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingPointerPos);
}
+ /* Keyboard State Encodings */
+ if (se->nEncodings < MAX_ENCODINGS) {
+ encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingKeyboardLedState);
+ }
+
encs[se->nEncodings++] = rfbClientSwap32IfLE(rfbEncodingLastRect);
}
@@ -785,6 +796,16 @@ HandleRFBServerMessage(rfbClient* client)
}
continue;
}
+
+ if (rect.encoding == rfbEncodingKeyboardLedState) {
+ /* OK! We have received a keyboard state message!!! */
+ client->KeyboardLedStateEnabled = 1;
+ if (client->HandleKeyboardLedState!=NULL)
+ client->HandleKeyboardLedState(client, rect.r.x, 0);
+ // stash it for the future
+ client->CurrentKeyboardLedState = rect.r.x;
+ continue;
+ }
if ((rect.r.x + rect.r.w > client->si.framebufferWidth) ||
(rect.r.y + rect.r.h > client->si.framebufferHeight))
diff --git a/libvncclient/vncviewer.c b/libvncclient/vncviewer.c
index 8ad5928..635b987 100644
--- a/libvncclient/vncviewer.c
+++ b/libvncclient/vncviewer.c
@@ -116,7 +116,10 @@ rfbClient* rfbGetClient(int bitsPerSample,int samplesPerPixel,
client->programName="";
client->serverHost="";
client->serverPort=5900;
-
+
+ client->CurrentKeyboardLedState = 0;
+ client->HandleKeyboardLedState = DummyPoint;
+
client->format.bitsPerPixel = bytesPerPixel*8;
client->format.depth = bitsPerSample*samplesPerPixel;
client->appData.requestedDepth=client->format.depth;
@@ -171,6 +174,8 @@ rfbClient* rfbGetClient(int bitsPerSample,int samplesPerPixel,
client->GetPassword = ReadPassword;
client->MallocFrameBuffer = MallocFrameBuffer;
client->Bell = Dummy;
+ client->CurrentKeyboardLedState = 0;
+ client->HandleKeyboardLedState = DummyPoint;
return client;
}
diff --git a/libvncserver/main.c b/libvncserver/main.c
index c618280..3aa9673 100644
--- a/libvncserver/main.c
+++ b/libvncserver/main.c
@@ -854,6 +854,7 @@ rfbScreenInfoPtr rfbGetScreen(int* argc,char** argv,
screen->setTranslateFunction = rfbSetTranslateFunction;
screen->newClientHook = rfbDefaultNewClientHook;
screen->displayHook = NULL;
+ screen->getKeyboardLedStateHook = NULL;
/* initialize client list and iterator mutex */
rfbClientListInit(screen);
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;
diff --git a/rfb/rfb.h b/rfb/rfb.h
index cf4665b..ffba2cd 100644
--- a/rfb/rfb.h
+++ b/rfb/rfb.h
@@ -135,6 +135,9 @@ typedef rfbBool (*rfbSetTranslateFunctionProcPtr)(struct _rfbClientRec* cl);
typedef rfbBool (*rfbPasswordCheckProcPtr)(struct _rfbClientRec* cl,const char* encryptedPassWord,int len);
typedef enum rfbNewClientAction (*rfbNewClientHookPtr)(struct _rfbClientRec* cl);
typedef void (*rfbDisplayHookPtr)(struct _rfbClientRec* cl);
+/* support the capability to view the caps/num/scroll states of the X server */
+typedef int (*rfbGetKeyboardLedStateHookPtr)(struct _rfbScreenInfo* screen);
+
typedef struct {
uint32_t count;
@@ -295,6 +298,9 @@ typedef struct _rfbScreenInfo
/* displayHook is called just before a frame buffer update */
rfbDisplayHookPtr displayHook;
+ /* These hooks are called to pass keyboard state back to the client */
+ rfbGetKeyboardLedStateHookPtr getKeyboardLedStateHook;
+
#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
MUTEX(cursorMutex);
rfbBool backgroundLoop;
@@ -478,7 +484,8 @@ typedef struct _rfbClientRec {
int tightQualityLevel;
#endif
#endif
-
+ int lastKeyboardLedState; /* keep track of last value so we can send *change* events */
+ rfbBool enableKeyboardLedState; /* client supports KeyboardState encoding */
rfbBool enableLastRectEncoding; /* client supports LastRect encoding */
rfbBool enableCursorShapeUpdates; /* client supports cursor shape updates */
rfbBool enableCursorPosUpdates; /* client supports cursor position updates */
diff --git a/rfb/rfbclient.h b/rfb/rfbclient.h
index a7d77bb..1dfd56a 100644
--- a/rfb/rfbclient.h
+++ b/rfb/rfbclient.h
@@ -94,6 +94,7 @@ typedef struct {
struct _rfbClient;
+typedef void (*HandleKeyboardLedStateProc)(struct _rfbClient* client, int value, int pad);
typedef rfbBool (*HandleCursorPosProc)(struct _rfbClient* client, int x, int y);
typedef void (*SoftCursorLockAreaProc)(struct _rfbClient* client, int x, int y, int w, int h);
typedef void (*SoftCursorUnlockScreenProc)(struct _rfbClient* client);
@@ -196,7 +197,12 @@ typedef struct _rfbClient {
rfbVNCRec* vncRec;
+ /* Keyboard State support (is 'Caps Lock' set on the remote display???) */
+ int KeyboardLedStateEnabled;
+ int CurrentKeyboardLedState;
+
/* hooks */
+ HandleKeyboardLedStateProc HandleKeyboardLedState;
HandleCursorPosProc HandleCursorPos;
SoftCursorLockAreaProc SoftCursorLockArea;
SoftCursorUnlockScreenProc SoftCursorUnlockScreen;
diff --git a/rfb/rfbproto.h b/rfb/rfbproto.h
index cadbce4..5cd103a 100644
--- a/rfb/rfbproto.h
+++ b/rfb/rfbproto.h
@@ -445,6 +445,7 @@ typedef struct {
#define rfbEncodingXCursor 0xFFFFFF10
#define rfbEncodingRichCursor 0xFFFFFF11
#define rfbEncodingPointerPos 0xFFFFFF18
+#define rfbEncodingKeyboardLedState 0xFFFFFF19
#define rfbEncodingLastRect 0xFFFFFF20
#define rfbEncodingNewFBSize 0xFFFFFF21