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