Annotation of /trunk/tigervnc/patches/tigervnc-1.0.1-r3887.patch
Parent Directory | Revision Log
Revision 1201 -
(hide annotations)
(download)
Mon Nov 22 23:25:59 2010 UTC (13 years, 11 months ago) by niro
File size: 35721 byte(s)
Mon Nov 22 23:25:59 2010 UTC (13 years, 11 months ago) by niro
File size: 35721 byte(s)
-patches for 1.0.1 against xorg-server-1.7
1 | niro | 1201 | Index: unix/xserver/hw/vnc/Input.cc |
2 | =================================================================== | ||
3 | --- unix/xserver/hw/vnc/Input.cc (revision 3886) | ||
4 | +++ unix/xserver/hw/vnc/Input.cc (revision 3887) | ||
5 | @@ -21,13 +21,49 @@ | ||
6 | #include <dix-config.h> | ||
7 | #endif | ||
8 | |||
9 | +#include <rfb/LogWriter.h> | ||
10 | #include "Input.h" | ||
11 | #include "xorg-version.h" | ||
12 | +#include "vncExtInit.h" | ||
13 | |||
14 | extern "C" { | ||
15 | +#define public c_public | ||
16 | +#define class c_class | ||
17 | +#include "inputstr.h" | ||
18 | #include "mi.h" | ||
19 | +#ifndef XKB_IN_SERVER | ||
20 | +#define XKB_IN_SERVER | ||
21 | +#endif | ||
22 | +#ifdef XKB | ||
23 | +/* | ||
24 | + * This include is needed to use XkbConvertCase instead of XConvertCase even if | ||
25 | + * we don't use XKB extension. | ||
26 | + */ | ||
27 | +#include <xkbsrv.h> | ||
28 | +#endif | ||
29 | +#if XORG >= 16 | ||
30 | +#include "exevents.h" | ||
31 | +extern void | ||
32 | +CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master); | ||
33 | +#endif | ||
34 | +#include <X11/keysym.h> | ||
35 | +#include <X11/Xutil.h> | ||
36 | +#undef public | ||
37 | +#undef class | ||
38 | } | ||
39 | |||
40 | +using namespace rdr; | ||
41 | +using namespace rfb; | ||
42 | + | ||
43 | +static LogWriter vlog("Input"); | ||
44 | + | ||
45 | +#define BUTTONS 5 | ||
46 | +static int pointerProc(DeviceIntPtr pDevice, int onoff); | ||
47 | + | ||
48 | +static int keyboardProc(DeviceIntPtr pDevice, int onoff); | ||
49 | +static KeySym KeyCodetoKeySym(KeySymsPtr keymap, int keycode, int col); | ||
50 | +static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col); | ||
51 | + | ||
52 | /* Event queue is shared between all devices. */ | ||
53 | #if XORG == 15 | ||
54 | static xEvent *eventq = NULL; | ||
55 | @@ -70,10 +106,6 @@ | ||
56 | } | ||
57 | } | ||
58 | |||
59 | -/* Pointer device pre-declarations */ | ||
60 | -#define BUTTONS 5 | ||
61 | -static int pointerProc(DeviceIntPtr pDevice, int onoff); | ||
62 | - | ||
63 | /* Pointer device methods */ | ||
64 | |||
65 | PointerDevice::PointerDevice(rfb::VNCServerST *_server) | ||
66 | @@ -165,3 +197,569 @@ | ||
67 | return Success; | ||
68 | } | ||
69 | |||
70 | +/* KeyboardDevice methods */ | ||
71 | + | ||
72 | +KeyboardDevice::KeyboardDevice(void) | ||
73 | +{ | ||
74 | + dev = AddInputDevice( | ||
75 | +#if XORG >= 16 | ||
76 | + serverClient, | ||
77 | +#endif | ||
78 | + keyboardProc, TRUE); | ||
79 | + RegisterKeyboardDevice(dev); | ||
80 | + initEventq(); | ||
81 | +} | ||
82 | + | ||
83 | +#define IS_PRESSED(keyc, keycode) \ | ||
84 | + ((keyc)->down[(keycode) >> 3] & (1 << ((keycode) & 7))) | ||
85 | + | ||
86 | +/* | ||
87 | + * ModifierState is a class which helps simplify generating a "fake" press or | ||
88 | + * release of shift, ctrl, alt, etc. An instance of the class is created for | ||
89 | + * every modifier which may need to be pressed or released. Then either | ||
90 | + * press() or release() may be called to make sure that the corresponding keys | ||
91 | + * are in the right state. The destructor of the class automatically reverts | ||
92 | + * to the previous state. Each modifier may have multiple keys associated with | ||
93 | + * it, so in the case of a fake release, this may involve releasing more than | ||
94 | + * one key. | ||
95 | + */ | ||
96 | + | ||
97 | +class ModifierState { | ||
98 | +public: | ||
99 | + ModifierState(DeviceIntPtr _dev, int _modIndex) | ||
100 | + : modIndex(_modIndex), nKeys(0), keys(0), pressed(false), | ||
101 | + dev(_dev) {} | ||
102 | + | ||
103 | + ~ModifierState() | ||
104 | + { | ||
105 | + for (int i = 0; i < nKeys; i++) | ||
106 | + generateXKeyEvent(keys[i], !pressed); | ||
107 | + delete [] keys; | ||
108 | + } | ||
109 | + | ||
110 | + void press() | ||
111 | + { | ||
112 | + KeyClassPtr keyc = dev->key; | ||
113 | + if (!(keyc->state & (1 << modIndex))) { | ||
114 | + int index = modIndex * keyc->maxKeysPerModifier; | ||
115 | + tempKeyEvent(keyc->modifierKeyMap[index], true); | ||
116 | + pressed = true; | ||
117 | + } | ||
118 | + } | ||
119 | + | ||
120 | + void release() | ||
121 | + { | ||
122 | + KeyClassPtr keyc = dev->key; | ||
123 | + if ((keyc->state & (1 << modIndex)) == 0) | ||
124 | + return; | ||
125 | + | ||
126 | + for (int k = 0; k < keyc->maxKeysPerModifier; k++) { | ||
127 | + int index = modIndex * keyc->maxKeysPerModifier + k; | ||
128 | + int keycode = keyc->modifierKeyMap[index]; | ||
129 | + if (keycode && IS_PRESSED(keyc, keycode)) | ||
130 | + tempKeyEvent(keycode, false); | ||
131 | + } | ||
132 | + } | ||
133 | + | ||
134 | +private: | ||
135 | + void tempKeyEvent(int keycode, bool down) | ||
136 | + { | ||
137 | + if (keycode) { | ||
138 | + if (!keys) keys = new int[dev->key->maxKeysPerModifier]; | ||
139 | + keys[nKeys++] = keycode; | ||
140 | + generateXKeyEvent(keycode, down); | ||
141 | + } | ||
142 | + } | ||
143 | + | ||
144 | + void generateXKeyEvent(int keycode, bool down) | ||
145 | + { | ||
146 | + int n, action; | ||
147 | + | ||
148 | + action = down ? KeyPress : KeyRelease; | ||
149 | + n = GetKeyboardEvents(eventq, dev, action, keycode); | ||
150 | + enqueueEvents(dev, n); | ||
151 | + | ||
152 | + vlog.debug("fake keycode %d %s", keycode, | ||
153 | + down ? "down" : "up"); | ||
154 | + } | ||
155 | + | ||
156 | + int modIndex; | ||
157 | + int nKeys; | ||
158 | + int *keys; | ||
159 | + bool pressed; | ||
160 | + DeviceIntPtr dev; | ||
161 | +}; | ||
162 | + | ||
163 | + | ||
164 | +/* altKeysym is a table of alternative keysyms which have the same meaning. */ | ||
165 | + | ||
166 | +static struct altKeysym_t { | ||
167 | + KeySym a, b; | ||
168 | +} altKeysym[] = { | ||
169 | + { XK_Shift_L, XK_Shift_R }, | ||
170 | + { XK_Control_L, XK_Control_R }, | ||
171 | + { XK_Meta_L, XK_Meta_R }, | ||
172 | + { XK_Alt_L, XK_Alt_R }, | ||
173 | + { XK_Super_L, XK_Super_R }, | ||
174 | + { XK_Hyper_L, XK_Hyper_R }, | ||
175 | + { XK_KP_Space, XK_space }, | ||
176 | + { XK_KP_Tab, XK_Tab }, | ||
177 | + { XK_KP_Enter, XK_Return }, | ||
178 | + { XK_KP_F1, XK_F1 }, | ||
179 | + { XK_KP_F2, XK_F2 }, | ||
180 | + { XK_KP_F3, XK_F3 }, | ||
181 | + { XK_KP_F4, XK_F4 }, | ||
182 | + { XK_KP_Home, XK_Home }, | ||
183 | + { XK_KP_Left, XK_Left }, | ||
184 | + { XK_KP_Up, XK_Up }, | ||
185 | + { XK_KP_Right, XK_Right }, | ||
186 | + { XK_KP_Down, XK_Down }, | ||
187 | + { XK_KP_Page_Up, XK_Page_Up }, | ||
188 | + { XK_KP_Page_Down, XK_Page_Down }, | ||
189 | + { XK_KP_End, XK_End }, | ||
190 | + { XK_KP_Begin, XK_Begin }, | ||
191 | + { XK_KP_Insert, XK_Insert }, | ||
192 | + { XK_KP_Delete, XK_Delete }, | ||
193 | + { XK_KP_Equal, XK_equal }, | ||
194 | + { XK_KP_Multiply, XK_asterisk }, | ||
195 | + { XK_KP_Add, XK_plus }, | ||
196 | + { XK_KP_Separator, XK_comma }, | ||
197 | + { XK_KP_Subtract, XK_minus }, | ||
198 | + { XK_KP_Decimal, XK_period }, | ||
199 | + { XK_KP_Divide, XK_slash }, | ||
200 | + { XK_KP_0, XK_0 }, | ||
201 | + { XK_KP_1, XK_1 }, | ||
202 | + { XK_KP_2, XK_2 }, | ||
203 | + { XK_KP_3, XK_3 }, | ||
204 | + { XK_KP_4, XK_4 }, | ||
205 | + { XK_KP_5, XK_5 }, | ||
206 | + { XK_KP_6, XK_6 }, | ||
207 | + { XK_KP_7, XK_7 }, | ||
208 | + { XK_KP_8, XK_8 }, | ||
209 | + { XK_KP_9, XK_9 }, | ||
210 | +}; | ||
211 | + | ||
212 | +/* | ||
213 | + * keyEvent() - work out the best keycode corresponding to the keysym sent by | ||
214 | + * the viewer. This is non-trivial because we can't assume much about the | ||
215 | + * local keyboard layout. We must also find out which column of the keyboard | ||
216 | + * mapping the keysym is in, and alter the shift state appropriately. Column 0 | ||
217 | + * means both shift and "mode_switch" (AltGr) must be released, column 1 means | ||
218 | + * shift must be pressed and mode_switch released, column 2 means shift must be | ||
219 | + * released and mode_switch pressed, and column 3 means both shift and | ||
220 | + * mode_switch must be pressed. | ||
221 | + * | ||
222 | + * Magic, which dynamically adds keysym<->keycode mapping depends on X.Org | ||
223 | + * version. Quick explanation of that "magic": | ||
224 | + * | ||
225 | + * 1.5 | ||
226 | + * - has only one core keyboard so we have to keep core keyboard mapping | ||
227 | + * synchronized with vncKeyboardDevice. Do it via SwitchCoreKeyboard() | ||
228 | + * | ||
229 | + * 1.6 (aka MPX - Multi pointer X) | ||
230 | + * - multiple master devices (= core devices) exists, keep vncKeyboardDevice | ||
231 | + * synchronized with proper master device | ||
232 | + */ | ||
233 | + | ||
234 | +void KeyboardDevice::keyEvent(rdr::U32 keysym, bool down) | ||
235 | +{ | ||
236 | + DeviceIntPtr master; | ||
237 | + KeyClassPtr keyc = dev->key; | ||
238 | + KeySymsPtr keymap = &keyc->curKeySyms; | ||
239 | + KeySym *map = keymap->map; | ||
240 | + KeyCode minKeyCode = keymap->minKeyCode; | ||
241 | + KeyCode maxKeyCode = keymap->maxKeyCode; | ||
242 | + int mapWidth = keymap->mapWidth; | ||
243 | + unsigned int i, n; | ||
244 | + int j, k, action; | ||
245 | + | ||
246 | + if (keysym == XK_Caps_Lock) { | ||
247 | + vlog.debug("Ignoring caps lock"); | ||
248 | + return; | ||
249 | + } | ||
250 | + | ||
251 | + /* find which modifier Mode_switch is on. */ | ||
252 | + int modeSwitchMapIndex = 0; | ||
253 | + for (i = 3; i < 8; i++) { | ||
254 | + for (k = 0; k < keyc->maxKeysPerModifier; k++) { | ||
255 | + int index = i * keyc->maxKeysPerModifier + k; | ||
256 | + int keycode = keyc->modifierKeyMap[index]; | ||
257 | + | ||
258 | + if (keycode == 0) | ||
259 | + continue; | ||
260 | + | ||
261 | + for (j = 0; j < mapWidth; j++) { | ||
262 | + if (map[(keycode - minKeyCode) * mapWidth + j] | ||
263 | + == XK_Mode_switch) { | ||
264 | + modeSwitchMapIndex = i; | ||
265 | + goto ModeSwitchFound; | ||
266 | + } | ||
267 | + } | ||
268 | + } | ||
269 | + } | ||
270 | +ModeSwitchFound: | ||
271 | + | ||
272 | + int col = 0; | ||
273 | + if ((keyc->state & (1 << ShiftMapIndex)) != 0) | ||
274 | + col |= 1; | ||
275 | + if (modeSwitchMapIndex != 0 && | ||
276 | + ((keyc->state & (1 << modeSwitchMapIndex))) != 0) | ||
277 | + col |= 2; | ||
278 | + | ||
279 | + int kc = KeysymToKeycode(keymap, keysym, &col); | ||
280 | + | ||
281 | + /* | ||
282 | + * Sort out the "shifted Tab" mess. If we are sent a shifted Tab, | ||
283 | + * generate a local shifted Tab regardless of what the "shifted Tab" | ||
284 | + * keysym is on the local keyboard (it might be Tab, ISO_Left_Tab or | ||
285 | + * HP's private BackTab keysym, and quite possibly some others too). | ||
286 | + * We never get ISO_Left_Tab here because it's already been translated | ||
287 | + * in VNCSConnectionST. | ||
288 | + */ | ||
289 | + if (keysym == XK_Tab && ((keyc->state & (1 << ShiftMapIndex))) != 0) | ||
290 | + col |= 1; | ||
291 | + | ||
292 | + if (kc == 0) { | ||
293 | + /* | ||
294 | + * Not a direct match in the local keyboard mapping. Check for | ||
295 | + * alternative keysyms with the same meaning. | ||
296 | + */ | ||
297 | + for (i = 0; i < sizeof(altKeysym) / sizeof(altKeysym_t); i++) { | ||
298 | + if (keysym == altKeysym[i].a) | ||
299 | + kc = KeysymToKeycode(keymap, altKeysym[i].b, | ||
300 | + &col); | ||
301 | + else if (keysym == altKeysym[i].b) | ||
302 | + kc = KeysymToKeycode(keymap, altKeysym[i].a, | ||
303 | + &col); | ||
304 | + if (kc) | ||
305 | + break; | ||
306 | + } | ||
307 | + } | ||
308 | + | ||
309 | + if (kc == 0) { | ||
310 | + /* Dynamically add a new key to the keyboard mapping. */ | ||
311 | + for (kc = maxKeyCode; kc >= minKeyCode; kc--) { | ||
312 | + if (map[(kc - minKeyCode) * mapWidth] != 0) | ||
313 | + continue; | ||
314 | + | ||
315 | + map[(kc - minKeyCode) * mapWidth] = keysym; | ||
316 | + col = 0; | ||
317 | + | ||
318 | + vlog.info("Added unknown keysym 0x%x to keycode %d", | ||
319 | + keysym, kc); | ||
320 | +#if XORG == 15 | ||
321 | + master = inputInfo.keyboard; | ||
322 | +#else | ||
323 | + master = dev->u.master; | ||
324 | +#endif | ||
325 | + void *slave = dixLookupPrivate(&master->devPrivates, | ||
326 | + CoreDevicePrivateKey); | ||
327 | + if (dev == slave) { | ||
328 | + dixSetPrivate(&master->devPrivates, | ||
329 | + CoreDevicePrivateKey, NULL); | ||
330 | +#if XORG == 15 | ||
331 | + SwitchCoreKeyboard(dev); | ||
332 | +#else | ||
333 | + CopyKeyClass(dev, master); | ||
334 | +#endif | ||
335 | + } | ||
336 | + break; | ||
337 | + } | ||
338 | + } | ||
339 | + | ||
340 | + if (kc < minKeyCode) { | ||
341 | + vlog.info("Keyboard mapping full - ignoring unknown keysym " | ||
342 | + "0x%x",keysym); | ||
343 | + return; | ||
344 | + } | ||
345 | + | ||
346 | + /* | ||
347 | + * See if it's a modifier key. If so, then don't do any auto-repeat, | ||
348 | + * because the X server will translate each press into a release | ||
349 | + * followed by a press. | ||
350 | + */ | ||
351 | + for (i = 0; i < 8; i++) { | ||
352 | + for (k = 0; k < keyc->maxKeysPerModifier; k++) { | ||
353 | + int index = i * keyc->maxKeysPerModifier + k; | ||
354 | + if (kc == keyc->modifierKeyMap[index] && | ||
355 | + IS_PRESSED(keyc,kc) && down) | ||
356 | + return; | ||
357 | + } | ||
358 | + } | ||
359 | + | ||
360 | + ModifierState shift(dev, ShiftMapIndex); | ||
361 | + ModifierState modeSwitch(dev, modeSwitchMapIndex); | ||
362 | + if (down) { | ||
363 | + if (col & 1) | ||
364 | + shift.press(); | ||
365 | + else | ||
366 | + shift.release(); | ||
367 | + if (modeSwitchMapIndex) { | ||
368 | + if (col & 2) | ||
369 | + modeSwitch.press(); | ||
370 | + else | ||
371 | + modeSwitch.release(); | ||
372 | + } | ||
373 | + } | ||
374 | + | ||
375 | + vlog.debug("keycode %d %s", kc, down ? "down" : "up"); | ||
376 | + action = down ? KeyPress : KeyRelease; | ||
377 | + n = GetKeyboardEvents(eventq, dev, action, kc); | ||
378 | + enqueueEvents(dev, n); | ||
379 | +} | ||
380 | + | ||
381 | +static KeySym KeyCodetoKeySym(KeySymsPtr keymap, int keycode, int col) | ||
382 | +{ | ||
383 | + int per = keymap->mapWidth; | ||
384 | + KeySym *syms; | ||
385 | + KeySym lsym, usym; | ||
386 | + | ||
387 | + if ((col < 0) || ((col >= per) && (col > 3)) || | ||
388 | + (keycode < keymap->minKeyCode) || (keycode > keymap->maxKeyCode)) | ||
389 | + return NoSymbol; | ||
390 | + | ||
391 | + syms = &keymap->map[(keycode - keymap->minKeyCode) * per]; | ||
392 | + if (col >= 4) | ||
393 | + return syms[col]; | ||
394 | + | ||
395 | + if (col > 1) { | ||
396 | + while ((per > 2) && (syms[per - 1] == NoSymbol)) | ||
397 | + per--; | ||
398 | + if (per < 3) | ||
399 | + col -= 2; | ||
400 | + } | ||
401 | + | ||
402 | + if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) { | ||
403 | + XConvertCase(syms[col&~1], &lsym, &usym); | ||
404 | + if (!(col & 1)) | ||
405 | + return lsym; | ||
406 | + /* | ||
407 | + * I'm commenting out this logic because it's incorrect even | ||
408 | + * though it was copied from the Xlib sources. The X protocol | ||
409 | + * book quite clearly states that where a group consists of | ||
410 | + * element 1 being a non-alphabetic keysym and element 2 being | ||
411 | + * NoSymbol that you treat the second element as being the | ||
412 | + * same as the first. This also tallies with the behaviour | ||
413 | + * produced by the installed Xlib on my linux box (I believe | ||
414 | + * this is because it uses some XKB code rather than the | ||
415 | + * original Xlib code - compare XKBBind.c with KeyBind.c in | ||
416 | + * lib/X11). | ||
417 | + */ | ||
418 | +#if 0 | ||
419 | + else if (usym == lsym) | ||
420 | + return NoSymbol; | ||
421 | +#endif | ||
422 | + else | ||
423 | + return usym; | ||
424 | + } | ||
425 | + | ||
426 | + return syms[col]; | ||
427 | +} | ||
428 | + | ||
429 | +/* | ||
430 | + * KeysymToKeycode() - find the keycode and column corresponding to the given | ||
431 | + * keysym. The value of col passed in should be the column determined from the | ||
432 | + * current shift state. If the keysym can be found in that column we prefer | ||
433 | + * that to finding it in a different column (which would require fake events to | ||
434 | + * alter the shift state). | ||
435 | + */ | ||
436 | +static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col) | ||
437 | +{ | ||
438 | + int i, j; | ||
439 | + | ||
440 | + j = *col; | ||
441 | + for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) { | ||
442 | + if (KeyCodetoKeySym(keymap, i, j) == ks) | ||
443 | + return i; | ||
444 | + } | ||
445 | + | ||
446 | + for (j = 0; j < keymap->mapWidth; j++) { | ||
447 | + for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) { | ||
448 | + if (KeyCodetoKeySym(keymap, i, j) == ks) { | ||
449 | + *col = j; | ||
450 | + return i; | ||
451 | + } | ||
452 | + } | ||
453 | + } | ||
454 | + | ||
455 | + return 0; | ||
456 | +} | ||
457 | + | ||
458 | +/* Fairly standard US PC Keyboard */ | ||
459 | + | ||
460 | +#define MIN_KEY 8 | ||
461 | +#define MAX_KEY 255 | ||
462 | +#define MAP_LEN (MAX_KEY - MIN_KEY + 1) | ||
463 | +#define KEYSYMS_PER_KEY 2 | ||
464 | +KeySym keyboardMap[MAP_LEN * KEYSYMS_PER_KEY] = { | ||
465 | + NoSymbol, NoSymbol, | ||
466 | + XK_Escape, NoSymbol, | ||
467 | + XK_1, XK_exclam, | ||
468 | + XK_2, XK_at, | ||
469 | + XK_3, XK_numbersign, | ||
470 | + XK_4, XK_dollar, | ||
471 | + XK_5, XK_percent, | ||
472 | + XK_6, XK_asciicircum, | ||
473 | + XK_7, XK_ampersand, | ||
474 | + XK_8, XK_asterisk, | ||
475 | + XK_9, XK_parenleft, | ||
476 | + XK_0, XK_parenright, | ||
477 | + XK_minus, XK_underscore, | ||
478 | + XK_equal, XK_plus, | ||
479 | + XK_BackSpace, NoSymbol, | ||
480 | + XK_Tab, NoSymbol, | ||
481 | + XK_q, XK_Q, | ||
482 | + XK_w, XK_W, | ||
483 | + XK_e, XK_E, | ||
484 | + XK_r, XK_R, | ||
485 | + XK_t, XK_T, | ||
486 | + XK_y, XK_Y, | ||
487 | + XK_u, XK_U, | ||
488 | + XK_i, XK_I, | ||
489 | + XK_o, XK_O, | ||
490 | + XK_p, XK_P, | ||
491 | + XK_bracketleft, XK_braceleft, | ||
492 | + XK_bracketright, XK_braceright, | ||
493 | + XK_Return, NoSymbol, | ||
494 | + XK_Control_L, NoSymbol, | ||
495 | + XK_a, XK_A, | ||
496 | + XK_s, XK_S, | ||
497 | + XK_d, XK_D, | ||
498 | + XK_f, XK_F, | ||
499 | + XK_g, XK_G, | ||
500 | + XK_h, XK_H, | ||
501 | + XK_j, XK_J, | ||
502 | + XK_k, XK_K, | ||
503 | + XK_l, XK_L, | ||
504 | + XK_semicolon, XK_colon, | ||
505 | + XK_apostrophe, XK_quotedbl, | ||
506 | + XK_grave, XK_asciitilde, | ||
507 | + XK_Shift_L, NoSymbol, | ||
508 | + XK_backslash, XK_bar, | ||
509 | + XK_z, XK_Z, | ||
510 | + XK_x, XK_X, | ||
511 | + XK_c, XK_C, | ||
512 | + XK_v, XK_V, | ||
513 | + XK_b, XK_B, | ||
514 | + XK_n, XK_N, | ||
515 | + XK_m, XK_M, | ||
516 | + XK_comma, XK_less, | ||
517 | + XK_period, XK_greater, | ||
518 | + XK_slash, XK_question, | ||
519 | + XK_Shift_R, NoSymbol, | ||
520 | + XK_KP_Multiply, NoSymbol, | ||
521 | + XK_Alt_L, XK_Meta_L, | ||
522 | + XK_space, NoSymbol, | ||
523 | + /* XK_Caps_Lock */ NoSymbol, NoSymbol, | ||
524 | + XK_F1, NoSymbol, | ||
525 | + XK_F2, NoSymbol, | ||
526 | + XK_F3, NoSymbol, | ||
527 | + XK_F4, NoSymbol, | ||
528 | + XK_F5, NoSymbol, | ||
529 | + XK_F6, NoSymbol, | ||
530 | + XK_F7, NoSymbol, | ||
531 | + XK_F8, NoSymbol, | ||
532 | + XK_F9, NoSymbol, | ||
533 | + XK_F10, NoSymbol, | ||
534 | + XK_Num_Lock, XK_Pointer_EnableKeys, | ||
535 | + XK_Scroll_Lock, NoSymbol, | ||
536 | + XK_KP_Home, XK_KP_7, | ||
537 | + XK_KP_Up, XK_KP_8, | ||
538 | + XK_KP_Prior, XK_KP_9, | ||
539 | + XK_KP_Subtract, NoSymbol, | ||
540 | + XK_KP_Left, XK_KP_4, | ||
541 | + XK_KP_Begin, XK_KP_5, | ||
542 | + XK_KP_Right, XK_KP_6, | ||
543 | + XK_KP_Add, NoSymbol, | ||
544 | + XK_KP_End, XK_KP_1, | ||
545 | + XK_KP_Down, XK_KP_2, | ||
546 | + XK_KP_Next, XK_KP_3, | ||
547 | + XK_KP_Insert, XK_KP_0, | ||
548 | + XK_KP_Delete, XK_KP_Decimal, | ||
549 | + NoSymbol, NoSymbol, | ||
550 | + NoSymbol, NoSymbol, | ||
551 | + NoSymbol, NoSymbol, | ||
552 | + XK_F11, NoSymbol, | ||
553 | + XK_F12, NoSymbol, | ||
554 | + XK_Home, NoSymbol, | ||
555 | + XK_Up, NoSymbol, | ||
556 | + XK_Prior, NoSymbol, | ||
557 | + XK_Left, NoSymbol, | ||
558 | + NoSymbol, NoSymbol, | ||
559 | + XK_Right, NoSymbol, | ||
560 | + XK_End, NoSymbol, | ||
561 | + XK_Down, NoSymbol, | ||
562 | + XK_Next, NoSymbol, | ||
563 | + XK_Insert, NoSymbol, | ||
564 | + XK_Delete, NoSymbol, | ||
565 | + XK_KP_Enter, NoSymbol, | ||
566 | + XK_Control_R, NoSymbol, | ||
567 | + XK_Pause, XK_Break, | ||
568 | + XK_Print, XK_Execute, | ||
569 | + XK_KP_Divide, NoSymbol, | ||
570 | + XK_Alt_R, XK_Meta_R, | ||
571 | +}; | ||
572 | + | ||
573 | +static Bool GetMappings(KeySymsPtr pKeySyms, CARD8 *pModMap) | ||
574 | +{ | ||
575 | + int i; | ||
576 | + | ||
577 | + for (i = 0; i < MAP_LENGTH; i++) | ||
578 | + pModMap[i] = NoSymbol; | ||
579 | + | ||
580 | + for (i = 0; i < MAP_LEN; i++) { | ||
581 | + if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Caps_Lock) | ||
582 | + pModMap[i + MIN_KEY] = LockMask; | ||
583 | + else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_L || | ||
584 | + keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_R) | ||
585 | + pModMap[i + MIN_KEY] = ShiftMask; | ||
586 | + else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_L || | ||
587 | + keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_R) | ||
588 | + pModMap[i + MIN_KEY] = ControlMask; | ||
589 | + else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_L || | ||
590 | + keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_R) | ||
591 | + pModMap[i + MIN_KEY] = Mod1Mask; | ||
592 | + } | ||
593 | + | ||
594 | + pKeySyms->minKeyCode = MIN_KEY; | ||
595 | + pKeySyms->maxKeyCode = MAX_KEY; | ||
596 | + pKeySyms->mapWidth = KEYSYMS_PER_KEY; | ||
597 | + pKeySyms->map = keyboardMap; | ||
598 | + | ||
599 | + return TRUE; | ||
600 | +} | ||
601 | + | ||
602 | +static void keyboardBell(int percent, DeviceIntPtr device, pointer ctrl, | ||
603 | + int class_) | ||
604 | +{ | ||
605 | + if (percent > 0) | ||
606 | + vncBell(); | ||
607 | +} | ||
608 | + | ||
609 | +static int keyboardProc(DeviceIntPtr pDevice, int onoff) | ||
610 | +{ | ||
611 | + KeySymsRec keySyms; | ||
612 | + CARD8 modMap[MAP_LENGTH]; | ||
613 | + DevicePtr pDev = (DevicePtr)pDevice; | ||
614 | + | ||
615 | + switch (onoff) { | ||
616 | + case DEVICE_INIT: | ||
617 | + GetMappings(&keySyms, modMap); | ||
618 | + InitKeyboardDeviceStruct(pDev, &keySyms, modMap, keyboardBell, | ||
619 | + (KbdCtrlProcPtr)NoopDDA); | ||
620 | + break; | ||
621 | + case DEVICE_ON: | ||
622 | + pDev->on = TRUE; | ||
623 | + break; | ||
624 | + case DEVICE_OFF: | ||
625 | + pDev->on = FALSE; | ||
626 | + break; | ||
627 | +#if 0 | ||
628 | + case DEVICE_CLOSE: | ||
629 | + break; | ||
630 | +#endif | ||
631 | + } | ||
632 | + | ||
633 | + return Success; | ||
634 | +} | ||
635 | + | ||
636 | Index: unix/xserver/hw/vnc/Input.h | ||
637 | =================================================================== | ||
638 | --- unix/xserver/hw/vnc/Input.h (revision 3886) | ||
639 | +++ unix/xserver/hw/vnc/Input.h (revision 3887) | ||
640 | @@ -58,4 +58,17 @@ | ||
641 | rfb::Point cursorPos, oldCursorPos; | ||
642 | }; | ||
643 | |||
644 | +/* Represents keyboard device. */ | ||
645 | +class KeyboardDevice { | ||
646 | +public: | ||
647 | + /* Create new Keyboard device instance. */ | ||
648 | + KeyboardDevice(void); | ||
649 | + | ||
650 | + void Press(rdr::U32 keysym) { keyEvent(keysym, true); } | ||
651 | + void Release(rdr::U32 keysym) { keyEvent(keysym, false); } | ||
652 | +private: | ||
653 | + void keyEvent(rdr::U32 keysym, bool down); | ||
654 | + DeviceIntPtr dev; | ||
655 | +}; | ||
656 | + | ||
657 | #endif | ||
658 | Index: unix/xserver/hw/vnc/XserverDesktop.cc | ||
659 | =================================================================== | ||
660 | --- unix/xserver/hw/vnc/XserverDesktop.cc (revision 3886) | ||
661 | +++ unix/xserver/hw/vnc/XserverDesktop.cc (revision 3887) | ||
662 | @@ -50,26 +50,7 @@ | ||
663 | |||
664 | extern char *display; | ||
665 | |||
666 | -#include "inputstr.h" | ||
667 | -#include "servermd.h" | ||
668 | #include "colormapst.h" | ||
669 | -#include "resource.h" | ||
670 | -#include "cursorstr.h" | ||
671 | -#include "windowstr.h" | ||
672 | -#include "mi.h" | ||
673 | -#define XK_CYRILLIC | ||
674 | -#include <X11/keysym.h> | ||
675 | -#ifndef XKB_IN_SERVER | ||
676 | -#define XKB_IN_SERVER | ||
677 | -#endif | ||
678 | -#ifdef XKB | ||
679 | -#include <xkbsrv.h> | ||
680 | -#endif | ||
681 | -#if XORG >= 16 | ||
682 | -#include "exevents.h" | ||
683 | -extern void | ||
684 | -CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master); | ||
685 | -#endif | ||
686 | #ifdef RANDR | ||
687 | #include "randrstr.h" | ||
688 | #endif | ||
689 | @@ -77,15 +58,6 @@ | ||
690 | #undef class | ||
691 | } | ||
692 | |||
693 | -static DeviceIntPtr vncKeyboardDevice = NULL; | ||
694 | -#if XORG == 15 | ||
695 | -static xEvent *eventq = NULL; | ||
696 | -#else | ||
697 | -static EventList *eventq = NULL; | ||
698 | -#endif | ||
699 | - | ||
700 | -static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff); | ||
701 | - | ||
702 | using namespace rfb; | ||
703 | using namespace network; | ||
704 | |||
705 | @@ -102,8 +74,6 @@ | ||
706 | "rejecting the connection", | ||
707 | 10); | ||
708 | |||
709 | -static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col); | ||
710 | - | ||
711 | static rdr::U8 reverseBits[] = { | ||
712 | 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, | ||
713 | 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, | ||
714 | @@ -193,33 +163,8 @@ | ||
715 | if (httpListener) | ||
716 | httpServer = new FileHTTPServer(this); | ||
717 | |||
718 | -#if XORG == 15 | ||
719 | - /* | ||
720 | - * XXX eventq is never free()-ed because it has to exist during server life | ||
721 | - * */ | ||
722 | - if (!eventq) | ||
723 | - eventq = (xEvent *) xcalloc(sizeof(xEvent), GetMaximumEventsNum()); | ||
724 | - if (!eventq) | ||
725 | - FatalError("Couldn't allocate eventq\n"); | ||
726 | -#else | ||
727 | - GetEventList(&eventq); | ||
728 | -#endif | ||
729 | - | ||
730 | - /* | ||
731 | - * NOTE: | ||
732 | - * We _might_ have to call ActivateDevice function for both keyboard and | ||
733 | - * mouse. For Xvnc it's not needed but I have to check libvnc.so module. | ||
734 | - */ | ||
735 | - if (vncKeyboardDevice == NULL) { | ||
736 | - vncKeyboardDevice = AddInputDevice( | ||
737 | -#if XORG >= 16 | ||
738 | - serverClient, | ||
739 | -#endif | ||
740 | - vfbKeybdProc, TRUE); | ||
741 | - RegisterKeyboardDevice(vncKeyboardDevice); | ||
742 | - } | ||
743 | - | ||
744 | pointerDevice = new PointerDevice(server); | ||
745 | + keyboardDevice = new KeyboardDevice(); | ||
746 | } | ||
747 | |||
748 | XserverDesktop::~XserverDesktop() | ||
749 | @@ -229,6 +174,7 @@ | ||
750 | TimerFree(deferredUpdateTimer); | ||
751 | TimerFree(dummyTimer); | ||
752 | delete pointerDevice; | ||
753 | + delete keyboardDevice; | ||
754 | delete httpServer; | ||
755 | delete server; | ||
756 | } | ||
757 | @@ -854,533 +800,10 @@ | ||
758 | } | ||
759 | } | ||
760 | |||
761 | -// | ||
762 | -// Keyboard handling | ||
763 | -// | ||
764 | - | ||
765 | -#define IS_PRESSED(keyc, keycode) \ | ||
766 | - ((keyc)->down[(keycode) >> 3] & (1 << ((keycode) & 7))) | ||
767 | - | ||
768 | -// ModifierState is a class which helps simplify generating a "fake" press | ||
769 | -// or release of shift, ctrl, alt, etc. An instance of the class is created | ||
770 | -// for every modifier which may need to be pressed or released. Then either | ||
771 | -// press() or release() may be called to make sure that the corresponding keys | ||
772 | -// are in the right state. The destructor of the class automatically reverts | ||
773 | -// to the previous state. Each modifier may have multiple keys associated with | ||
774 | -// it, so in the case of a fake release, this may involve releasing more than | ||
775 | -// one key. | ||
776 | - | ||
777 | -class ModifierState { | ||
778 | -public: | ||
779 | - ModifierState(int modIndex_) | ||
780 | - : modIndex(modIndex_), nKeys(0), keys(0), pressed(false) | ||
781 | - { | ||
782 | - } | ||
783 | - ~ModifierState() { | ||
784 | - for (int i = 0; i < nKeys; i++) | ||
785 | - generateXKeyEvent(keys[i], !pressed); | ||
786 | - delete [] keys; | ||
787 | - } | ||
788 | - void press() { | ||
789 | - KeyClassPtr keyc = vncKeyboardDevice->key; | ||
790 | - if (!(keyc->state & (1<<modIndex))) { | ||
791 | - tempKeyEvent(keyc->modifierKeyMap[modIndex * keyc->maxKeysPerModifier], | ||
792 | - true); | ||
793 | - pressed = true; | ||
794 | - } | ||
795 | - } | ||
796 | - void release() { | ||
797 | - KeyClassPtr keyc = vncKeyboardDevice->key; | ||
798 | - if (keyc->state & (1<<modIndex)) { | ||
799 | - for (int k = 0; k < keyc->maxKeysPerModifier; k++) { | ||
800 | - int keycode | ||
801 | - = keyc->modifierKeyMap[modIndex * keyc->maxKeysPerModifier + k]; | ||
802 | - if (keycode && IS_PRESSED(keyc, keycode)) | ||
803 | - tempKeyEvent(keycode, false); | ||
804 | - } | ||
805 | - } | ||
806 | - } | ||
807 | -private: | ||
808 | - void tempKeyEvent(int keycode, bool down) { | ||
809 | - if (keycode) { | ||
810 | - if (!keys) keys = new int[vncKeyboardDevice->key->maxKeysPerModifier]; | ||
811 | - keys[nKeys++] = keycode; | ||
812 | - generateXKeyEvent(keycode, down); | ||
813 | - } | ||
814 | - } | ||
815 | - void generateXKeyEvent(int keycode, bool down) { | ||
816 | - int i, n; | ||
817 | - n = GetKeyboardEvents (eventq, vncKeyboardDevice, | ||
818 | - down ? KeyPress : KeyRelease, keycode); | ||
819 | - for (i = 0; i < n; i++) { | ||
820 | - mieqEnqueue (vncKeyboardDevice, | ||
821 | -#if XORG == 15 | ||
822 | - eventq + i | ||
823 | -#else | ||
824 | - (eventq + i)->event | ||
825 | -#endif | ||
826 | - ); | ||
827 | - } | ||
828 | - vlog.debug("fake keycode %d %s", keycode, down ? "down" : "up"); | ||
829 | - } | ||
830 | - int modIndex; | ||
831 | - int nKeys; | ||
832 | - int* keys; | ||
833 | - bool pressed; | ||
834 | -}; | ||
835 | - | ||
836 | - | ||
837 | -// altKeysym is a table of alternative keysyms which have the same meaning. | ||
838 | - | ||
839 | -struct altKeysym_t { | ||
840 | - KeySym a, b; | ||
841 | -}; | ||
842 | - | ||
843 | -altKeysym_t altKeysym[] = { | ||
844 | - { XK_Shift_L, XK_Shift_R }, | ||
845 | - { XK_Control_L, XK_Control_R }, | ||
846 | - { XK_Meta_L, XK_Meta_R }, | ||
847 | - { XK_Alt_L, XK_Alt_R }, | ||
848 | - { XK_Super_L, XK_Super_R }, | ||
849 | - { XK_Hyper_L, XK_Hyper_R }, | ||
850 | - { XK_KP_Space, XK_space }, | ||
851 | - { XK_KP_Tab, XK_Tab }, | ||
852 | - { XK_KP_Enter, XK_Return }, | ||
853 | - { XK_KP_F1, XK_F1 }, | ||
854 | - { XK_KP_F2, XK_F2 }, | ||
855 | - { XK_KP_F3, XK_F3 }, | ||
856 | - { XK_KP_F4, XK_F4 }, | ||
857 | - { XK_KP_Home, XK_Home }, | ||
858 | - { XK_KP_Left, XK_Left }, | ||
859 | - { XK_KP_Up, XK_Up }, | ||
860 | - { XK_KP_Right, XK_Right }, | ||
861 | - { XK_KP_Down, XK_Down }, | ||
862 | - { XK_KP_Page_Up, XK_Page_Up }, | ||
863 | - { XK_KP_Page_Down, XK_Page_Down }, | ||
864 | - { XK_KP_End, XK_End }, | ||
865 | - { XK_KP_Begin, XK_Begin }, | ||
866 | - { XK_KP_Insert, XK_Insert }, | ||
867 | - { XK_KP_Delete, XK_Delete }, | ||
868 | - { XK_KP_Equal, XK_equal }, | ||
869 | - { XK_KP_Multiply, XK_asterisk }, | ||
870 | - { XK_KP_Add, XK_plus }, | ||
871 | - { XK_KP_Separator, XK_comma }, | ||
872 | - { XK_KP_Subtract, XK_minus }, | ||
873 | - { XK_KP_Decimal, XK_period }, | ||
874 | - { XK_KP_Divide, XK_slash }, | ||
875 | - { XK_KP_0, XK_0 }, | ||
876 | - { XK_KP_1, XK_1 }, | ||
877 | - { XK_KP_2, XK_2 }, | ||
878 | - { XK_KP_3, XK_3 }, | ||
879 | - { XK_KP_4, XK_4 }, | ||
880 | - { XK_KP_5, XK_5 }, | ||
881 | - { XK_KP_6, XK_6 }, | ||
882 | - { XK_KP_7, XK_7 }, | ||
883 | - { XK_KP_8, XK_8 }, | ||
884 | - { XK_KP_9, XK_9 }, | ||
885 | -}; | ||
886 | - | ||
887 | -/* | ||
888 | - * keyEvent() - work out the best keycode corresponding to the keysym sent by | ||
889 | - * the viewer. This is non-trivial because we can't assume much about the | ||
890 | - * local keyboard layout. We must also find out which column of the keyboard | ||
891 | - * mapping the keysym is in, and alter the shift state appropriately. Column 0 | ||
892 | - * means both shift and "mode_switch" (AltGr) must be released, column 1 means | ||
893 | - * shift must be pressed and mode_switch released, column 2 means shift must be | ||
894 | - * released and mode_switch pressed, and column 3 means both shift and | ||
895 | - * mode_switch must be pressed. | ||
896 | - * | ||
897 | - * Magic, which dynamically adds keysym<->keycode mapping depends on X.Org | ||
898 | - * version. Quick explanation of that "magic": | ||
899 | - * | ||
900 | - * 1.5 | ||
901 | - * - has only one core keyboard so we have to keep core keyboard mapping | ||
902 | - * synchronized with vncKeyboardDevice. Do it via SwitchCoreKeyboard() | ||
903 | - * | ||
904 | - * 1.6 (aka MPX - Multi pointer X) | ||
905 | - * - multiple master devices (= core devices) exists, keep vncKeyboardDevice | ||
906 | - * synchronized with proper master device | ||
907 | - */ | ||
908 | - | ||
909 | void XserverDesktop::keyEvent(rdr::U32 keysym, bool down) | ||
910 | { | ||
911 | - DeviceIntPtr master; | ||
912 | - KeyClassPtr keyc = vncKeyboardDevice->key; | ||
913 | - KeySymsPtr keymap = &keyc->curKeySyms; | ||
914 | - unsigned int i, n; | ||
915 | - int j, k; | ||
916 | - | ||
917 | - if (keysym == XK_Caps_Lock) { | ||
918 | - vlog.debug("Ignoring caps lock"); | ||
919 | - return; | ||
920 | - } | ||
921 | - | ||
922 | - // find which modifier Mode_switch is on. | ||
923 | - int modeSwitchMapIndex = 0; | ||
924 | - for (i = 3; i < 8; i++) { | ||
925 | - for (k = 0; k < keyc->maxKeysPerModifier; k++) { | ||
926 | - int keycode = keyc->modifierKeyMap[i * keyc->maxKeysPerModifier + k]; | ||
927 | - for (j = 0; j < keymap->mapWidth; j++) { | ||
928 | - if (keycode != 0 && | ||
929 | - keymap->map[(keycode - keymap->minKeyCode) | ||
930 | - * keymap->mapWidth + j] == XK_Mode_switch) | ||
931 | - { | ||
932 | - modeSwitchMapIndex = i; | ||
933 | - break; | ||
934 | - } | ||
935 | - } | ||
936 | - } | ||
937 | - } | ||
938 | - | ||
939 | - int col = 0; | ||
940 | - if (keyc->state & (1<<ShiftMapIndex)) col |= 1; | ||
941 | - if (modeSwitchMapIndex && (keyc->state & (1<<modeSwitchMapIndex))) col |= 2; | ||
942 | - | ||
943 | - int kc = KeysymToKeycode(keymap, keysym, &col); | ||
944 | - | ||
945 | - // Sort out the "shifted Tab" mess. If we are sent a shifted Tab, generate a | ||
946 | - // local shifted Tab regardless of what the "shifted Tab" keysym is on the | ||
947 | - // local keyboard (it might be Tab, ISO_Left_Tab or HP's private BackTab | ||
948 | - // keysym, and quite possibly some others too). We never get ISO_Left_Tab | ||
949 | - // here because it's already been translated in VNCSConnectionST. | ||
950 | - if (keysym == XK_Tab && (keyc->state & (1<<ShiftMapIndex))) | ||
951 | - col |= 1; | ||
952 | - | ||
953 | - if (kc == 0) { | ||
954 | - // Not a direct match in the local keyboard mapping. Check for alternative | ||
955 | - // keysyms with the same meaning. | ||
956 | - for (i = 0; i < sizeof(altKeysym) / sizeof(altKeysym_t); i++) { | ||
957 | - if (keysym == altKeysym[i].a) | ||
958 | - kc = KeysymToKeycode(keymap, altKeysym[i].b, &col); | ||
959 | - else if (keysym == altKeysym[i].b) | ||
960 | - kc = KeysymToKeycode(keymap, altKeysym[i].a, &col); | ||
961 | - if (kc) break; | ||
962 | - } | ||
963 | - } | ||
964 | - | ||
965 | - if (kc == 0) { | ||
966 | - // Last resort - dynamically add a new key to the keyboard mapping. | ||
967 | - for (kc = keymap->maxKeyCode; kc >= keymap->minKeyCode; kc--) { | ||
968 | - if (!keymap->map[(kc - keymap->minKeyCode) * keymap->mapWidth]) { | ||
969 | - keymap->map[(kc - keymap->minKeyCode) * keymap->mapWidth] = keysym; | ||
970 | - col = 0; | ||
971 | - | ||
972 | - vlog.info("Added unknown keysym 0x%x to keycode %d",keysym,kc); | ||
973 | - | ||
974 | -#if XORG == 15 | ||
975 | - master = inputInfo.keyboard; | ||
976 | -#else | ||
977 | - master = vncKeyboardDevice->u.master; | ||
978 | -#endif | ||
979 | - if (vncKeyboardDevice == | ||
980 | - dixLookupPrivate(&master->devPrivates, CoreDevicePrivateKey)) { | ||
981 | - dixSetPrivate(&master->devPrivates, CoreDevicePrivateKey, NULL); | ||
982 | -#if XORG == 15 | ||
983 | - SwitchCoreKeyboard(vncKeyboardDevice); | ||
984 | -#else | ||
985 | - CopyKeyClass(vncKeyboardDevice, master); | ||
986 | -#endif | ||
987 | - } | ||
988 | - break; | ||
989 | - } | ||
990 | - } | ||
991 | - if (kc < keymap->minKeyCode) { | ||
992 | - vlog.info("Keyboard mapping full - ignoring unknown keysym 0x%x",keysym); | ||
993 | - return; | ||
994 | - } | ||
995 | - } | ||
996 | - | ||
997 | - // See if it's a modifier key. If so, then don't do any auto-repeat, because | ||
998 | - // the X server will translate each press into a release followed by a press. | ||
999 | - for (i = 0; i < 8; i++) { | ||
1000 | - for (k = 0; k < keyc->maxKeysPerModifier; k++) { | ||
1001 | - if (kc == keyc->modifierKeyMap[i * keyc->maxKeysPerModifier + k] && | ||
1002 | - IS_PRESSED(keyc,kc) && down) | ||
1003 | - return; | ||
1004 | - } | ||
1005 | - } | ||
1006 | - | ||
1007 | - ModifierState shift(ShiftMapIndex); | ||
1008 | - ModifierState modeSwitch(modeSwitchMapIndex); | ||
1009 | - if (down) { | ||
1010 | - if (col & 1) | ||
1011 | - shift.press(); | ||
1012 | - else | ||
1013 | - shift.release(); | ||
1014 | - if (modeSwitchMapIndex) { | ||
1015 | - if (col & 2) | ||
1016 | - modeSwitch.press(); | ||
1017 | - else | ||
1018 | - modeSwitch.release(); | ||
1019 | - } | ||
1020 | - } | ||
1021 | - vlog.debug("keycode %d %s", kc, down ? "down" : "up"); | ||
1022 | - n = GetKeyboardEvents (eventq, vncKeyboardDevice, down ? | ||
1023 | - KeyPress : KeyRelease, kc); | ||
1024 | - for (i = 0; i < n; i++) { | ||
1025 | - mieqEnqueue (vncKeyboardDevice, | ||
1026 | -#if XORG == 15 | ||
1027 | - eventq + i | ||
1028 | -#else | ||
1029 | - (eventq + i)->event | ||
1030 | -#endif | ||
1031 | - ); | ||
1032 | - } | ||
1033 | + if (down) | ||
1034 | + keyboardDevice->Press(keysym); | ||
1035 | + else | ||
1036 | + keyboardDevice->Release(keysym); | ||
1037 | } | ||
1038 | - | ||
1039 | -static KeySym KeyCodetoKeySym(KeySymsPtr keymap, int keycode, int col) | ||
1040 | -{ | ||
1041 | - register int per = keymap->mapWidth; | ||
1042 | - register KeySym *syms; | ||
1043 | - KeySym lsym, usym; | ||
1044 | - | ||
1045 | - if ((col < 0) || ((col >= per) && (col > 3)) || | ||
1046 | - (keycode < keymap->minKeyCode) || (keycode > keymap->maxKeyCode)) | ||
1047 | - return NoSymbol; | ||
1048 | - | ||
1049 | - syms = &keymap->map[(keycode - keymap->minKeyCode) * per]; | ||
1050 | - if (col < 4) { | ||
1051 | - if (col > 1) { | ||
1052 | - while ((per > 2) && (syms[per - 1] == NoSymbol)) | ||
1053 | - per--; | ||
1054 | - if (per < 3) | ||
1055 | - col -= 2; | ||
1056 | - } | ||
1057 | - if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) { | ||
1058 | - XConvertCase(syms[col&~1], &lsym, &usym); | ||
1059 | - if (!(col & 1)) | ||
1060 | - return lsym; | ||
1061 | - // I'm commenting out this logic because it's incorrect even though it | ||
1062 | - // was copied from the Xlib sources. The X protocol book quite clearly | ||
1063 | - // states that where a group consists of element 1 being a non-alphabetic | ||
1064 | - // keysym and element 2 being NoSymbol that you treat the second element | ||
1065 | - // as being the same as the first. This also tallies with the behaviour | ||
1066 | - // produced by the installed Xlib on my linux box (I believe this is | ||
1067 | - // because it uses some XKB code rather than the original Xlib code - | ||
1068 | - // compare XKBBind.c with KeyBind.c in lib/X11). | ||
1069 | - // else if (usym == lsym) | ||
1070 | - // return NoSymbol; | ||
1071 | - else | ||
1072 | - return usym; | ||
1073 | - } | ||
1074 | - } | ||
1075 | - return syms[col]; | ||
1076 | -} | ||
1077 | - | ||
1078 | -// KeysymToKeycode() - find the keycode and column corresponding to the given | ||
1079 | -// keysym. The value of col passed in should be the column determined from the | ||
1080 | -// current shift state. If the keysym can be found in that column we prefer | ||
1081 | -// that to finding it in a different column (which would require fake events to | ||
1082 | -// alter the shift state). | ||
1083 | - | ||
1084 | -static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col) | ||
1085 | -{ | ||
1086 | - register int i, j; | ||
1087 | - | ||
1088 | - j = *col; | ||
1089 | - for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) { | ||
1090 | - if (KeyCodetoKeySym(keymap, i, j) == ks) | ||
1091 | - return i; | ||
1092 | - } | ||
1093 | - | ||
1094 | - for (j = 0; j < keymap->mapWidth; j++) { | ||
1095 | - for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) { | ||
1096 | - if (KeyCodetoKeySym(keymap, i, j) == ks) { | ||
1097 | - *col = j; | ||
1098 | - return i; | ||
1099 | - } | ||
1100 | - } | ||
1101 | - } | ||
1102 | - return 0; | ||
1103 | -} | ||
1104 | - | ||
1105 | -/* Fairly standard US PC Keyboard */ | ||
1106 | - | ||
1107 | -#define VFB_MIN_KEY 8 | ||
1108 | -#define VFB_MAX_KEY 255 | ||
1109 | -#define VFB_MAP_LEN (VFB_MAX_KEY - VFB_MIN_KEY + 1) | ||
1110 | -#define KEYSYMS_PER_KEY 2 | ||
1111 | -KeySym keyboardMap[VFB_MAP_LEN * KEYSYMS_PER_KEY] = { | ||
1112 | - NoSymbol, NoSymbol, | ||
1113 | - XK_Escape, NoSymbol, | ||
1114 | - XK_1, XK_exclam, | ||
1115 | - XK_2, XK_at, | ||
1116 | - XK_3, XK_numbersign, | ||
1117 | - XK_4, XK_dollar, | ||
1118 | - XK_5, XK_percent, | ||
1119 | - XK_6, XK_asciicircum, | ||
1120 | - XK_7, XK_ampersand, | ||
1121 | - XK_8, XK_asterisk, | ||
1122 | - XK_9, XK_parenleft, | ||
1123 | - XK_0, XK_parenright, | ||
1124 | - XK_minus, XK_underscore, | ||
1125 | - XK_equal, XK_plus, | ||
1126 | - XK_BackSpace, NoSymbol, | ||
1127 | - XK_Tab, NoSymbol, | ||
1128 | - XK_q, XK_Q, | ||
1129 | - XK_w, XK_W, | ||
1130 | - XK_e, XK_E, | ||
1131 | - XK_r, XK_R, | ||
1132 | - XK_t, XK_T, | ||
1133 | - XK_y, XK_Y, | ||
1134 | - XK_u, XK_U, | ||
1135 | - XK_i, XK_I, | ||
1136 | - XK_o, XK_O, | ||
1137 | - XK_p, XK_P, | ||
1138 | - XK_bracketleft, XK_braceleft, | ||
1139 | - XK_bracketright, XK_braceright, | ||
1140 | - XK_Return, NoSymbol, | ||
1141 | - XK_Control_L, NoSymbol, | ||
1142 | - XK_a, XK_A, | ||
1143 | - XK_s, XK_S, | ||
1144 | - XK_d, XK_D, | ||
1145 | - XK_f, XK_F, | ||
1146 | - XK_g, XK_G, | ||
1147 | - XK_h, XK_H, | ||
1148 | - XK_j, XK_J, | ||
1149 | - XK_k, XK_K, | ||
1150 | - XK_l, XK_L, | ||
1151 | - XK_semicolon, XK_colon, | ||
1152 | - XK_apostrophe, XK_quotedbl, | ||
1153 | - XK_grave, XK_asciitilde, | ||
1154 | - XK_Shift_L, NoSymbol, | ||
1155 | - XK_backslash, XK_bar, | ||
1156 | - XK_z, XK_Z, | ||
1157 | - XK_x, XK_X, | ||
1158 | - XK_c, XK_C, | ||
1159 | - XK_v, XK_V, | ||
1160 | - XK_b, XK_B, | ||
1161 | - XK_n, XK_N, | ||
1162 | - XK_m, XK_M, | ||
1163 | - XK_comma, XK_less, | ||
1164 | - XK_period, XK_greater, | ||
1165 | - XK_slash, XK_question, | ||
1166 | - XK_Shift_R, NoSymbol, | ||
1167 | - XK_KP_Multiply, NoSymbol, | ||
1168 | - XK_Alt_L, XK_Meta_L, | ||
1169 | - XK_space, NoSymbol, | ||
1170 | - /*XK_Caps_Lock*/ NoSymbol, NoSymbol, | ||
1171 | - XK_F1, NoSymbol, | ||
1172 | - XK_F2, NoSymbol, | ||
1173 | - XK_F3, NoSymbol, | ||
1174 | - XK_F4, NoSymbol, | ||
1175 | - XK_F5, NoSymbol, | ||
1176 | - XK_F6, NoSymbol, | ||
1177 | - XK_F7, NoSymbol, | ||
1178 | - XK_F8, NoSymbol, | ||
1179 | - XK_F9, NoSymbol, | ||
1180 | - XK_F10, NoSymbol, | ||
1181 | - XK_Num_Lock, XK_Pointer_EnableKeys, | ||
1182 | - XK_Scroll_Lock, NoSymbol, | ||
1183 | - XK_KP_Home, XK_KP_7, | ||
1184 | - XK_KP_Up, XK_KP_8, | ||
1185 | - XK_KP_Prior, XK_KP_9, | ||
1186 | - XK_KP_Subtract, NoSymbol, | ||
1187 | - XK_KP_Left, XK_KP_4, | ||
1188 | - XK_KP_Begin, XK_KP_5, | ||
1189 | - XK_KP_Right, XK_KP_6, | ||
1190 | - XK_KP_Add, NoSymbol, | ||
1191 | - XK_KP_End, XK_KP_1, | ||
1192 | - XK_KP_Down, XK_KP_2, | ||
1193 | - XK_KP_Next, XK_KP_3, | ||
1194 | - XK_KP_Insert, XK_KP_0, | ||
1195 | - XK_KP_Delete, XK_KP_Decimal, | ||
1196 | - NoSymbol, NoSymbol, | ||
1197 | - NoSymbol, NoSymbol, | ||
1198 | - NoSymbol, NoSymbol, | ||
1199 | - XK_F11, NoSymbol, | ||
1200 | - XK_F12, NoSymbol, | ||
1201 | - XK_Home, NoSymbol, | ||
1202 | - XK_Up, NoSymbol, | ||
1203 | - XK_Prior, NoSymbol, | ||
1204 | - XK_Left, NoSymbol, | ||
1205 | - NoSymbol, NoSymbol, | ||
1206 | - XK_Right, NoSymbol, | ||
1207 | - XK_End, NoSymbol, | ||
1208 | - XK_Down, NoSymbol, | ||
1209 | - XK_Next, NoSymbol, | ||
1210 | - XK_Insert, NoSymbol, | ||
1211 | - XK_Delete, NoSymbol, | ||
1212 | - XK_KP_Enter, NoSymbol, | ||
1213 | - XK_Control_R, NoSymbol, | ||
1214 | - XK_Pause, XK_Break, | ||
1215 | - XK_Print, XK_Execute, | ||
1216 | - XK_KP_Divide, NoSymbol, | ||
1217 | - XK_Alt_R, XK_Meta_R, | ||
1218 | -}; | ||
1219 | - | ||
1220 | -static Bool GetMappings(KeySymsPtr pKeySyms, CARD8 *pModMap) | ||
1221 | -{ | ||
1222 | - int i; | ||
1223 | - | ||
1224 | - for (i = 0; i < MAP_LENGTH; i++) | ||
1225 | - pModMap[i] = NoSymbol; | ||
1226 | - | ||
1227 | - for (i = 0; i < VFB_MAP_LEN; i++) { | ||
1228 | - if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Caps_Lock) | ||
1229 | - pModMap[i + VFB_MIN_KEY] = LockMask; | ||
1230 | - else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_L || | ||
1231 | - keyboardMap[i * KEYSYMS_PER_KEY] == XK_Shift_R) | ||
1232 | - pModMap[i + VFB_MIN_KEY] = ShiftMask; | ||
1233 | - else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_L || | ||
1234 | - keyboardMap[i * KEYSYMS_PER_KEY] == XK_Control_R) { | ||
1235 | - pModMap[i + VFB_MIN_KEY] = ControlMask; | ||
1236 | - } | ||
1237 | - else if (keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_L || | ||
1238 | - keyboardMap[i * KEYSYMS_PER_KEY] == XK_Alt_R) | ||
1239 | - pModMap[i + VFB_MIN_KEY] = Mod1Mask; | ||
1240 | - } | ||
1241 | - | ||
1242 | - pKeySyms->minKeyCode = VFB_MIN_KEY; | ||
1243 | - pKeySyms->maxKeyCode = VFB_MAX_KEY; | ||
1244 | - pKeySyms->mapWidth = KEYSYMS_PER_KEY; | ||
1245 | - pKeySyms->map = keyboardMap; | ||
1246 | - | ||
1247 | - return TRUE; | ||
1248 | -} | ||
1249 | - | ||
1250 | -static void vfbBell(int percent, DeviceIntPtr device, pointer ctrl, int class_) | ||
1251 | -{ | ||
1252 | - if (percent > 0) | ||
1253 | - vncBell(); | ||
1254 | -} | ||
1255 | - | ||
1256 | -static int vfbKeybdProc(DeviceIntPtr pDevice, int onoff) | ||
1257 | -{ | ||
1258 | - KeySymsRec keySyms; | ||
1259 | - CARD8 modMap[MAP_LENGTH]; | ||
1260 | - DevicePtr pDev = (DevicePtr)pDevice; | ||
1261 | -#ifdef XKB | ||
1262 | - XkbComponentNamesRec names; | ||
1263 | -#endif | ||
1264 | - | ||
1265 | - switch (onoff) | ||
1266 | - { | ||
1267 | - case DEVICE_INIT: | ||
1268 | - GetMappings(&keySyms, modMap); | ||
1269 | -#ifdef XKB | ||
1270 | - if (!noXkbExtension) { | ||
1271 | - memset(&names, 0, sizeof (names)); | ||
1272 | - XkbSetRulesDflts("base", "pc105", "us", NULL, NULL); | ||
1273 | - XkbInitKeyboardDeviceStruct(pDevice, &names, &keySyms, modMap, | ||
1274 | - (BellProcPtr)vfbBell, | ||
1275 | - (KbdCtrlProcPtr)NoopDDA); | ||
1276 | - } else | ||
1277 | -#endif | ||
1278 | - { | ||
1279 | - InitKeyboardDeviceStruct(pDev, &keySyms, modMap, | ||
1280 | - (BellProcPtr)vfbBell, (KbdCtrlProcPtr)NoopDDA); | ||
1281 | - } | ||
1282 | - break; | ||
1283 | - case DEVICE_ON: | ||
1284 | - pDev->on = TRUE; | ||
1285 | - break; | ||
1286 | - case DEVICE_OFF: | ||
1287 | - pDev->on = FALSE; | ||
1288 | - break; | ||
1289 | - case DEVICE_CLOSE: | ||
1290 | - break; | ||
1291 | - } | ||
1292 | - return Success; | ||
1293 | -} | ||
1294 | - | ||
1295 | Index: unix/xserver/hw/vnc/XserverDesktop.h | ||
1296 | =================================================================== | ||
1297 | --- unix/xserver/hw/vnc/XserverDesktop.h (revision 3886) | ||
1298 | +++ unix/xserver/hw/vnc/XserverDesktop.h (revision 3887) | ||
1299 | @@ -123,6 +123,7 @@ | ||
1300 | void deferUpdate(); | ||
1301 | ScreenPtr pScreen; | ||
1302 | PointerDevice *pointerDevice; | ||
1303 | + KeyboardDevice *keyboardDevice; | ||
1304 | OsTimerPtr deferredUpdateTimer, dummyTimer; | ||
1305 | rfb::VNCServerST* server; | ||
1306 | rfb::HTTPServer* httpServer; |