From 8c70b3010714623964d7b86b72fdf89ab5d26ca4 Mon Sep 17 00:00:00 2001
From: dscho <dscho>
Date: Fri, 23 Nov 2001 13:45:40 +0000
Subject: keyboard handling now works.

---
 x11vnc.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 92 insertions(+), 6 deletions(-)

diff --git a/x11vnc.c b/x11vnc.c
index 61962c5..2c261eb 100644
--- a/x11vnc.c
+++ b/x11vnc.c
@@ -18,6 +18,39 @@ Bool gotInput = FALSE;
 
 Bool disconnectAfterFirstClient = TRUE;
 
+/* keyboard handling */
+
+char modifiers[0x100];
+KeyCode keycodes[0x100],leftShiftCode,rightShiftCode,altGrCode;
+
+void init_keycodes()
+{
+  Display *dpy;
+  KeySym key,*keymap;
+  int i,j,minkey,maxkey,syms_per_keycode;
+
+  memset(modifiers,-1,sizeof(modifiers));
+
+  dpy=XOpenDisplay("");
+  XDisplayKeycodes(dpy,&minkey,&maxkey);
+  keymap=XGetKeyboardMapping(dpy,minkey,(maxkey - minkey + 1),&syms_per_keycode);
+
+  for (i = minkey; i <= maxkey; i++)
+    for(j=0;j<syms_per_keycode;j++) {
+      key=keymap[(i-minkey)*syms_per_keycode+j];
+      if(key>=' ' && key<0x100 && i==XKeysymToKeycode(dpy,key)) {
+	keycodes[key]=i;
+	modifiers[key]=j;
+      }
+    }
+
+  leftShiftCode=XKeysymToKeycode(dpy,XK_Shift_L);
+  rightShiftCode=XKeysymToKeycode(dpy,XK_Shift_R);
+  altGrCode=XKeysymToKeycode(dpy,XK_Mode_switch);
+
+  XFree ((char *) keymap);
+}
+
 /* the hooks */
 
 void clientGone(rfbClientPtr cl)
@@ -31,12 +64,63 @@ void newClient(rfbClientPtr cl)
     cl->clientGoneHook = clientGone;
 }
 
+#define LEFTSHIFT 1
+#define RIGHTSHIFT 2
+#define ALTGR 4
+char ModifierState = 0;
+
+/* this function adjusts the modifiers according to mod (as from modifiers) and ModifierState */
+
+void tweakModifiers(char mod,Bool down)
+{
+  Bool isShift=ModifierState&(LEFTSHIFT|RIGHTSHIFT);
+  if(mod<0) return;
+  if(isShift && mod!=1) {
+    if(ModifierState&LEFTSHIFT)
+      XTestFakeKeyEvent(dpy,leftShiftCode,!down,CurrentTime);
+    if(ModifierState&RIGHTSHIFT)
+      XTestFakeKeyEvent(dpy,rightShiftCode,!down,CurrentTime);
+  }
+  if(!isShift && mod==1)
+    XTestFakeKeyEvent(dpy,leftShiftCode,down,CurrentTime);
+
+  if(ModifierState&ALTGR && mod!=2)
+    XTestFakeKeyEvent(dpy,altGrCode,!down,CurrentTime);
+  if(!(ModifierState&ALTGR) && mod==2)
+    XTestFakeKeyEvent(dpy,altGrCode,down,CurrentTime);
+}
+
 void keyboard(Bool down,KeySym keySym,rfbClientPtr cl)
 {
-  KeyCode k = XKeysymToKeycode( dpy,keySym );
-  if(k!=NoSymbol)
-    XTestFakeKeyEvent(dpy,k,down,CurrentTime);
-  gotInput = TRUE;
+#define ADJUSTMOD(sym,state) \
+  if(keySym==sym) { if(down) ModifierState|=state; else ModifierState&=~state; }
+
+  ADJUSTMOD(XK_Shift_L,LEFTSHIFT)
+  ADJUSTMOD(XK_Shift_R,RIGHTSHIFT)
+  ADJUSTMOD(XK_Mode_switch,ALTGR)
+
+  if(keySym>=' ' && keySym<0x100) {
+    KeyCode k;
+    /* if(down)
+       tweakModifiers(modifiers[keySym],True); */
+    tweakModifiers(modifiers[keySym],down);
+    XTestFakeKeyEvent(dpy,XK_Shift_R,True,CurrentTime);
+    k = XKeysymToKeycode( dpy,keySym );
+    if(k!=NoSymbol) {
+      XTestFakeKeyEvent(dpy,k,down,CurrentTime);
+      gotInput = TRUE;
+    }
+    /*XTestFakeKeyEvent(dpy,keycodes[keySym],down,CurrentTime);*/
+    /*if(down)
+      tweakModifiers(modifiers[keySym],False);*/
+    gotInput = TRUE;
+  } else {
+    KeyCode k = XKeysymToKeycode( dpy,keySym );
+    if(k!=NoSymbol) {
+      XTestFakeKeyEvent(dpy,k,down,CurrentTime);
+      gotInput = TRUE;
+    }
+  }
 }
 
 int oldButtonMask = 0;
@@ -132,8 +216,8 @@ void checkForImageUpdates(rfbScreenInfoPtr s,char *b)
 
 int main(int argc,char** argv)
 {
-  Screen *sc;
-  Colormap cm;
+  //Screen *sc;
+  //Colormap cm;
   XImage *framebufferImage;
   char *backupImage;
   int xscreen,i;
@@ -162,6 +246,8 @@ int main(int argc,char** argv)
     dpy = XOpenDisplay("");
   xscreen = DefaultScreen(dpy);
 
+  init_keycodes();
+
   getImage(0,dpy,xscreen,&framebufferImage);
 
   screen = rfbGetScreen(&argc,argv,framebufferImage->width,
-- 
cgit v1.2.3

