1 #include "vnc.h" 2 #include <keyboard.h> 3 #include "utf2ksym.h" 4 5 enum { 6 Xshift = 0xFFE1, 7 Xctl = 0xFFE3, 8 Xmeta = 0xFFE7, 9 Xalt = 0xFFE9 10 }; 11 12 static struct { 13 Rune kbdc; 14 ulong keysym; 15 } ktab[] = { 16 {'\b', 0xff08}, 17 {'\t', 0xff09}, 18 {'\n', 0xff0d}, 19 /* {0x0b, 0xff0b}, */ 20 {'\r', 0xff0d}, 21 {0x1b, 0xff1b}, /* escape */ 22 {Kins, 0xff63}, 23 {0x7F, 0xffff}, 24 {Khome, 0xff50}, 25 {Kend, 0xff57}, 26 {Kpgup, 0xff55}, 27 {Kpgdown, 0xff56}, 28 {Kleft, 0xff51}, 29 {Kup, 0xff52}, 30 {Kright, 0xff53}, 31 {Kdown, 0xff54}, 32 {KF|1, 0xffbe}, 33 {KF|2, 0xffbf}, 34 {KF|3, 0xffc0}, 35 {KF|4, 0xffc1}, 36 {KF|5, 0xffc2}, 37 {KF|6, 0xffc3}, 38 {KF|7, 0xffc4}, 39 {KF|8, 0xffc5}, 40 {KF|9, 0xffc6}, 41 {KF|10, 0xffc7}, 42 {KF|11, 0xffc8}, 43 {KF|12, 0xffc9}, 44 }; 45 46 static char shiftkey[128] = { 47 0, 0, 0, 0, 0, 0, 0, 0, /* nul soh stx etx eot enq ack bel */ 48 0, 0, 0, 0, 0, 0, 0, 0, /* bs ht nl vt np cr so si */ 49 0, 0, 0, 0, 0, 0, 0, 0, /* dle dc1 dc2 dc3 dc4 nak syn etb */ 50 0, 0, 0, 0, 0, 0, 0, 0, /* can em sub esc fs gs rs us */ 51 0, 1, 1, 1, 1, 1, 1, 0, /* sp ! " # $ % & ' */ 52 1, 1, 1, 1, 0, 0, 0, 0, /* ( ) * + , - . / */ 53 0, 0, 0, 0, 0, 0, 0, 0, /* 0 1 2 3 4 5 6 7 */ 54 0, 0, 1, 0, 1, 0, 1, 1, /* 8 9 : ; < = > ? */ 55 1, 1, 1, 1, 1, 1, 1, 1, /* @ A B C D E F G */ 56 1, 1, 1, 1, 1, 1, 1, 1, /* H I J K L M N O */ 57 1, 1, 1, 1, 1, 1, 1, 1, /* P Q R S T U V W */ 58 1, 1, 1, 0, 0, 0, 1, 1, /* X Y Z [ \ ] ^ _ */ 59 0, 0, 0, 0, 0, 0, 0, 0, /* ` a b c d e f g */ 60 0, 0, 0, 0, 0, 0, 0, 0, /* h i j k l m n o */ 61 0, 0, 0, 0, 0, 0, 0, 0, /* p q r s t u v w */ 62 0, 0, 0, 1, 1, 1, 1, 0, /* x y z { | } ~ del */ 63 }; 64 65 ulong 66 runetoksym(Rune r) 67 { 68 int i; 69 70 for(i=0; i<nelem(ktab); i++) 71 if(ktab[i].kbdc == r) 72 return ktab[i].keysym; 73 return r; 74 } 75 76 static void 77 keyevent(Vnc *v, ulong ksym, int down) 78 { 79 vnclock(v); 80 vncwrchar(v, MKey); 81 vncwrchar(v, down); 82 vncwrshort(v, 0); 83 vncwrlong(v, ksym); 84 vncflush(v); 85 vncunlock(v); 86 } 87 88 void 89 readkbd(Vnc *v) 90 { 91 char buf[256], k[10]; 92 ulong ks; 93 int ctlfd, fd, kr, kn, w, shift, ctl, alt; 94 Rune r; 95 96 snprint(buf, sizeof buf, "%s/cons", display->devdir); 97 if((fd = open(buf, OREAD)) < 0) 98 sysfatal("open %s: %r", buf); 99 100 snprint(buf, sizeof buf, "%s/consctl", display->devdir); 101 if((ctlfd = open(buf, OWRITE)) < 0) 102 sysfatal("open %s: %r", buf); 103 write(ctlfd, "rawon", 5); 104 105 kn = 0; 106 shift = alt = ctl = 0; 107 for(;;){ 108 while(!fullrune(k, kn)){ 109 kr = read(fd, k+kn, sizeof k - kn); 110 if(kr <= 0) 111 sysfatal("bad read from kbd"); 112 kn += kr; 113 } 114 w = chartorune(&r, k); 115 kn -= w; 116 memmove(k, &k[w], kn); 117 ks = runetoksym(r); 118 119 switch(r){ 120 case Kalt: 121 alt = !alt; 122 keyevent(v, Xalt, alt); 123 break; 124 case Kctl: 125 ctl = !ctl; 126 keyevent(v, Xctl, ctl); 127 break; 128 case Kshift: 129 shift = !shift; 130 keyevent(v, Xshift, shift); 131 break; 132 default: 133 if(r == ks && r < 0x1A){ /* control key */ 134 keyevent(v, Xctl, 1); 135 keyevent(v, r+0x60, 1); /* 0x60: make capital letter */ 136 keyevent(v, r+0x60, 0); 137 keyevent(v, Xctl, 0); 138 }else{ 139 /* 140 * to send an upper case letter or shifted 141 * punctuation, mac os x vnc server, 142 * at least, needs a `shift' sent first. 143 */ 144 if(!shift && r == ks && r < sizeof shiftkey && shiftkey[r]){ 145 shift = 1; 146 keyevent(v, Xshift, 1); 147 } 148 /* 149 * map an xkeysym onto a utf-8 char. 150 * allows Xvnc to read us, see utf2ksym.h 151 */ 152 if((ks & 0xff00) && ks < nelem(utf2ksym) && utf2ksym[ks] != 0) 153 ks = utf2ksym[ks]; 154 keyevent(v, ks, 1); 155 /* 156 * up event needed by vmware inside linux vnc server, 157 * perhaps others. 158 */ 159 keyevent(v, ks, 0); 160 } 161 162 if(alt){ 163 keyevent(v, Xalt, 0); 164 alt = 0; 165 } 166 if(ctl){ 167 keyevent(v, Xctl, 0); 168 ctl = 0; 169 } 170 if(shift){ 171 keyevent(v, Xshift, 0); 172 shift = 0; 173 } 174 break; 175 } 176 } 177 } 178 179