Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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