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
runetoksym(Rune r)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
keyevent(Vnc * v,ulong ksym,int down)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
readkbd(Vnc * v)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