Contents of /trunk/tigervnc/patches/tigervnc-1.0.1-r3887.patch
Parent Directory | Revision Log
Revision 1201 -
(show annotations)
(download)
Mon Nov 22 23:25:59 2010 UTC (13 years, 10 months ago) by niro
File size: 35721 byte(s)
Mon Nov 22 23:25:59 2010 UTC (13 years, 10 months ago) by niro
File size: 35721 byte(s)
-patches for 1.0.1 against xorg-server-1.7
1 | 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; |