You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Input.c 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. /* Copyright (C) 2009 TightVNC Team
  2. * Copyright (C) 2009, 2014 Red Hat, Inc.
  3. * Copyright 2013-2015 Pierre Ossman for Cendio AB
  4. *
  5. * This is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This software is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this software; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  18. * USA.
  19. */
  20. #ifdef HAVE_DIX_CONFIG_H
  21. #include <dix-config.h>
  22. #endif
  23. #include "xorg-version.h"
  24. #include "Input.h"
  25. #include "vncExtInit.h"
  26. #include "RFBGlue.h"
  27. #include "inputstr.h"
  28. #if XORG >= 110
  29. #include "inpututils.h"
  30. #endif
  31. #include "mi.h"
  32. #include "mipointer.h"
  33. #include "exevents.h"
  34. #include "scrnintstr.h"
  35. #include "xkbsrv.h"
  36. #include "xkbstr.h"
  37. #include "xserver-properties.h"
  38. extern _X_EXPORT DevPrivateKey CoreDevicePrivateKey;
  39. #include <X11/keysym.h>
  40. #include <X11/Xlib.h>
  41. #include <X11/Xutil.h>
  42. extern const unsigned short code_map_qnum_to_xorgevdev[];
  43. extern const unsigned int code_map_qnum_to_xorgevdev_len;
  44. extern const unsigned short code_map_qnum_to_xorgkbd[];
  45. extern const unsigned int code_map_qnum_to_xorgkbd_len;
  46. #define BUTTONS 7
  47. /* Event queue is shared between all devices. */
  48. #if XORG < 111
  49. static EventList *eventq = NULL;
  50. #endif
  51. DeviceIntPtr vncKeyboardDev;
  52. DeviceIntPtr vncPointerDev;
  53. static int oldButtonMask;
  54. static int cursorPosX, cursorPosY;
  55. static const unsigned short *codeMap;
  56. static unsigned int codeMapLen;
  57. static KeySym pressedKeys[256];
  58. static int vncPointerProc(DeviceIntPtr pDevice, int onoff);
  59. static void vncKeyboardBell(int percent, DeviceIntPtr device,
  60. void * ctrl, int class);
  61. static int vncKeyboardProc(DeviceIntPtr pDevice, int onoff);
  62. static void vncKeysymKeyboardEvent(KeySym keysym, int down);
  63. #define LOG_NAME "Input"
  64. #define LOG_ERROR(...) vncLogError(LOG_NAME, __VA_ARGS__)
  65. #define LOG_STATUS(...) vncLogStatus(LOG_NAME, __VA_ARGS__)
  66. #define LOG_INFO(...) vncLogInfo(LOG_NAME, __VA_ARGS__)
  67. #define LOG_DEBUG(...) vncLogDebug(LOG_NAME, __VA_ARGS__)
  68. /*
  69. * Init input device.
  70. * This has to be called after core pointer/keyboard
  71. * initialization which unfortunately is after extensions
  72. * initialization (which means we cannot call it in
  73. * vncExtensionInit(). Check InitExtensions(),
  74. * InitCoreDevices() and InitInput() calls in dix/main.c.
  75. * Instead we call it from XserverDesktop at an appropriate
  76. * time.
  77. */
  78. void vncInitInputDevice(void)
  79. {
  80. int i, ret;
  81. if ((vncPointerDev != NULL) || (vncKeyboardDev != NULL))
  82. return;
  83. /*
  84. * On Linux we try to provide the same key codes as Xorg with
  85. * the evdev driver. On other platforms we mimic the older
  86. * Xorg KBD driver.
  87. */
  88. #ifdef __linux__
  89. codeMap = code_map_qnum_to_xorgevdev;
  90. codeMapLen = code_map_qnum_to_xorgevdev_len;
  91. #else
  92. codeMap = code_map_qnum_to_xorgkbd;
  93. codeMapLen = code_map_qnum_to_xorgkbd_len;
  94. #endif
  95. for (i = 0;i < 256;i++)
  96. pressedKeys[i] = NoSymbol;
  97. ret = AllocDevicePair(serverClient, "TigerVNC",
  98. &vncPointerDev, &vncKeyboardDev,
  99. vncPointerProc, vncKeyboardProc,
  100. FALSE);
  101. if (ret != Success)
  102. FatalError("Failed to initialize TigerVNC input devices\n");
  103. if (ActivateDevice(vncPointerDev, TRUE) != Success ||
  104. ActivateDevice(vncKeyboardDev, TRUE) != Success)
  105. FatalError("Failed to activate TigerVNC devices\n");
  106. if (!EnableDevice(vncPointerDev, TRUE) ||
  107. !EnableDevice(vncKeyboardDev, TRUE))
  108. FatalError("Failed to activate TigerVNC devices\n");
  109. #if XORG < 111
  110. /* eventq is never free()-ed because it exists during server life. */
  111. if (eventq == NULL)
  112. GetEventList(&eventq);
  113. #endif
  114. vncPrepareInputDevices();
  115. }
  116. #if XORG < 111
  117. static void enqueueEvents(DeviceIntPtr dev, int n)
  118. {
  119. int i;
  120. for (i = 0; i < n; i++) {
  121. /*
  122. * Passing arguments in global variable eventq is probably not
  123. * good programming practise but in this case it is safe and
  124. * clear.
  125. */
  126. mieqEnqueue(dev, (InternalEvent *) (eventq + i)->event);
  127. }
  128. }
  129. #endif /* XORG < 111 */
  130. void vncPointerButtonAction(int buttonMask)
  131. {
  132. int i;
  133. #if XORG < 111
  134. int n;
  135. #endif
  136. #if XORG >= 110
  137. ValuatorMask mask;
  138. #endif
  139. for (i = 0; i < BUTTONS; i++) {
  140. if ((buttonMask ^ oldButtonMask) & (1 << i)) {
  141. int action = (buttonMask & (1<<i)) ?
  142. ButtonPress : ButtonRelease;
  143. #if XORG < 110
  144. n = GetPointerEvents(eventq, vncPointerDev,
  145. action, i + 1,
  146. POINTER_RELATIVE, 0, 0, NULL);
  147. enqueueEvents(vncPointerDev, n);
  148. #elif XORG < 111
  149. valuator_mask_set_range(&mask, 0, 0, NULL);
  150. n = GetPointerEvents(eventq, vncPointerDev,
  151. action, i + 1,
  152. POINTER_RELATIVE, &mask);
  153. enqueueEvents(vncPointerDev, n);
  154. #else
  155. valuator_mask_set_range(&mask, 0, 0, NULL);
  156. QueuePointerEvents(vncPointerDev, action, i + 1,
  157. POINTER_RELATIVE, &mask);
  158. #endif
  159. }
  160. }
  161. oldButtonMask = buttonMask;
  162. }
  163. void vncPointerMove(int x, int y)
  164. {
  165. int valuators[2];
  166. #if XORG < 111
  167. int n;
  168. #endif
  169. #if XORG >= 110
  170. ValuatorMask mask;
  171. #endif
  172. if (cursorPosX == x && cursorPosY == y)
  173. return;
  174. valuators[0] = x;
  175. valuators[1] = y;
  176. #if XORG < 110
  177. n = GetPointerEvents(eventq, vncPointerDev, MotionNotify, 0,
  178. POINTER_ABSOLUTE, 0, 2, valuators);
  179. enqueueEvents(vncPointerDev, n);
  180. #elif XORG < 111
  181. valuator_mask_set_range(&mask, 0, 2, valuators);
  182. n = GetPointerEvents(eventq, vncPointerDev, MotionNotify, 0,
  183. POINTER_ABSOLUTE, &mask);
  184. enqueueEvents(vncPointerDev, n);
  185. #else
  186. valuator_mask_set_range(&mask, 0, 2, valuators);
  187. QueuePointerEvents(vncPointerDev, MotionNotify, 0,
  188. POINTER_ABSOLUTE, &mask);
  189. #endif
  190. cursorPosX = x;
  191. cursorPosY = y;
  192. }
  193. void vncGetPointerPos(int *x, int *y)
  194. {
  195. if (vncPointerDev != NULL) {
  196. ScreenPtr ptrScreen;
  197. miPointerGetPosition(vncPointerDev, &cursorPosX, &cursorPosY);
  198. /* Pointer coordinates are screen relative */
  199. ptrScreen = miPointerGetScreen(vncPointerDev);
  200. cursorPosX += ptrScreen->x;
  201. cursorPosY += ptrScreen->y;
  202. }
  203. *x = cursorPosX;
  204. *y = cursorPosY;
  205. }
  206. static int vncPointerProc(DeviceIntPtr pDevice, int onoff)
  207. {
  208. BYTE map[BUTTONS + 1];
  209. DevicePtr pDev = (DevicePtr)pDevice;
  210. int i;
  211. /*
  212. * NOTE: map[] array is one element longer than btn_labels[] array. This
  213. * is not a bug.
  214. */
  215. Atom btn_labels[BUTTONS];
  216. Atom axes_labels[2];
  217. switch (onoff) {
  218. case DEVICE_INIT:
  219. for (i = 0; i < BUTTONS + 1; i++)
  220. map[i] = i;
  221. btn_labels[0] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_LEFT);
  222. btn_labels[1] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_MIDDLE);
  223. btn_labels[2] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_RIGHT);
  224. btn_labels[3] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_UP);
  225. btn_labels[4] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_WHEEL_DOWN);
  226. btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
  227. btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);
  228. axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
  229. axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);
  230. InitPointerDeviceStruct(pDev, map, BUTTONS, btn_labels,
  231. (PtrCtrlProcPtr)NoopDDA,
  232. GetMotionHistorySize(),
  233. 2, axes_labels);
  234. break;
  235. case DEVICE_ON:
  236. pDev->on = TRUE;
  237. break;
  238. case DEVICE_OFF:
  239. pDev->on = FALSE;
  240. break;
  241. case DEVICE_CLOSE:
  242. vncPointerDev = NULL;
  243. break;
  244. }
  245. return Success;
  246. }
  247. static void vncKeyboardBell(int percent, DeviceIntPtr device,
  248. void * ctrl, int class)
  249. {
  250. if (percent > 0)
  251. vncBell();
  252. }
  253. static void vncKeyboardCtrl(DeviceIntPtr pDevice, KeybdCtrl *ctrl)
  254. {
  255. vncSetLEDState(ctrl->leds);
  256. }
  257. static int vncKeyboardProc(DeviceIntPtr pDevice, int onoff)
  258. {
  259. DevicePtr pDev = (DevicePtr)pDevice;
  260. switch (onoff) {
  261. case DEVICE_INIT:
  262. InitKeyboardDeviceStruct(pDevice, NULL, vncKeyboardBell,
  263. vncKeyboardCtrl);
  264. break;
  265. case DEVICE_ON:
  266. pDev->on = TRUE;
  267. break;
  268. case DEVICE_OFF:
  269. pDev->on = FALSE;
  270. break;
  271. case DEVICE_CLOSE:
  272. vncKeyboardDev = NULL;
  273. break;
  274. }
  275. return Success;
  276. }
  277. static inline void pressKey(DeviceIntPtr dev, int kc, Bool down, const char *msg)
  278. {
  279. int action;
  280. #if XORG < 111
  281. unsigned int n;
  282. #endif
  283. if (msg != NULL)
  284. LOG_DEBUG("%s %d %s", msg, kc, down ? "down" : "up");
  285. action = down ? KeyPress : KeyRelease;
  286. #if XORG < 111
  287. n = GetKeyboardEvents(eventq, dev, action, kc);
  288. enqueueEvents(dev, n);
  289. #elif XORG < 118
  290. QueueKeyboardEvents(dev, action, kc, NULL);
  291. #else
  292. QueueKeyboardEvents(dev, action, kc);
  293. #endif
  294. }
  295. /*
  296. * vncKeyboardEvent() - add X11 events for the given RFB key event
  297. */
  298. void vncKeyboardEvent(KeySym keysym, unsigned xtcode, int down)
  299. {
  300. /* Simple case: the client has specified the key */
  301. if (xtcode && xtcode < codeMapLen) {
  302. int keycode;
  303. keycode = codeMap[xtcode];
  304. if (!keycode) {
  305. /*
  306. * Figure something out based on keysym if we
  307. * cannot find a mapping.
  308. */
  309. if (keysym)
  310. vncKeysymKeyboardEvent(keysym, down);
  311. return;
  312. }
  313. /*
  314. * We update the state table in case we get a mix of
  315. * events with and without key codes.
  316. */
  317. if (down)
  318. pressedKeys[keycode] = keysym;
  319. else
  320. pressedKeys[keycode] = NoSymbol;
  321. pressKey(vncKeyboardDev, keycode, down, "raw keycode");
  322. mieqProcessInputEvents();
  323. return;
  324. }
  325. /*
  326. * Advanced case: We have to figure out a sequence of keys that
  327. * result in the given keysym
  328. */
  329. if (keysym)
  330. vncKeysymKeyboardEvent(keysym, down);
  331. }
  332. /* altKeysym is a table of alternative keysyms which have the same meaning. */
  333. static struct altKeysym_t {
  334. KeySym a, b;
  335. } altKeysym[] = {
  336. { XK_Shift_L, XK_Shift_R },
  337. { XK_Control_L, XK_Control_R },
  338. { XK_Meta_L, XK_Meta_R },
  339. { XK_Alt_L, XK_Alt_R },
  340. { XK_Super_L, XK_Super_R },
  341. { XK_Hyper_L, XK_Hyper_R },
  342. { XK_KP_Space, XK_space },
  343. { XK_KP_Tab, XK_Tab },
  344. { XK_KP_Enter, XK_Return },
  345. { XK_KP_F1, XK_F1 },
  346. { XK_KP_F2, XK_F2 },
  347. { XK_KP_F3, XK_F3 },
  348. { XK_KP_F4, XK_F4 },
  349. { XK_KP_Home, XK_Home },
  350. { XK_KP_Left, XK_Left },
  351. { XK_KP_Up, XK_Up },
  352. { XK_KP_Right, XK_Right },
  353. { XK_KP_Down, XK_Down },
  354. { XK_KP_Page_Up, XK_Page_Up },
  355. { XK_KP_Page_Down, XK_Page_Down },
  356. { XK_KP_End, XK_End },
  357. { XK_KP_Begin, XK_Begin },
  358. { XK_KP_Insert, XK_Insert },
  359. { XK_KP_Delete, XK_Delete },
  360. { XK_KP_Equal, XK_equal },
  361. { XK_KP_Multiply, XK_asterisk },
  362. { XK_KP_Add, XK_plus },
  363. { XK_KP_Separator, XK_comma },
  364. { XK_KP_Subtract, XK_minus },
  365. { XK_KP_Decimal, XK_period },
  366. { XK_KP_Divide, XK_slash },
  367. { XK_KP_0, XK_0 },
  368. { XK_KP_1, XK_1 },
  369. { XK_KP_2, XK_2 },
  370. { XK_KP_3, XK_3 },
  371. { XK_KP_4, XK_4 },
  372. { XK_KP_5, XK_5 },
  373. { XK_KP_6, XK_6 },
  374. { XK_KP_7, XK_7 },
  375. { XK_KP_8, XK_8 },
  376. { XK_KP_9, XK_9 },
  377. { XK_ISO_Level3_Shift, XK_Mode_switch },
  378. };
  379. /*
  380. * vncKeysymKeyboardEvent() - work out the best keycode corresponding
  381. * to the keysym sent by the viewer. This is basically impossible in
  382. * the general case, but we make a best effort by assuming that all
  383. * useful keysyms can be reached using just the Shift and
  384. * Level 3 (AltGr) modifiers. For core keyboards this is basically
  385. * always true, and should be true for most sane, western XKB layouts.
  386. */
  387. static void vncKeysymKeyboardEvent(KeySym keysym, int down)
  388. {
  389. int i;
  390. unsigned state, new_state;
  391. KeyCode keycode;
  392. unsigned level_three_mask;
  393. KeyCode shift_press, level_three_press;
  394. KeyCode shift_release[8], level_three_release[8];
  395. size_t shift_release_count, level_three_release_count;
  396. /*
  397. * Release events must match the press event, so look up what
  398. * keycode we sent for the press.
  399. */
  400. if (!down) {
  401. for (i = 0;i < 256;i++) {
  402. if (pressedKeys[i] == keysym) {
  403. pressedKeys[i] = NoSymbol;
  404. pressKey(vncKeyboardDev, i, FALSE, "keycode");
  405. mieqProcessInputEvents();
  406. return;
  407. }
  408. }
  409. /*
  410. * This can happen quite often as we ignore some
  411. * key presses.
  412. */
  413. LOG_DEBUG("Unexpected release of keysym 0x%x", keysym);
  414. return;
  415. }
  416. /*
  417. * Since we are checking the current state to determine if we need
  418. * to fake modifiers, we must make sure that everything put on the
  419. * input queue is processed before we start. Otherwise, shift may be
  420. * stuck down.
  421. */
  422. mieqProcessInputEvents();
  423. state = vncGetKeyboardState();
  424. keycode = vncKeysymToKeycode(keysym, state, &new_state);
  425. /*
  426. * Shift+Alt is often mapped to Meta, so try that rather than
  427. * allocating a new entry, faking shift, or using the dummy
  428. * key entries that many layouts have.
  429. */
  430. if ((state & ShiftMask) &&
  431. ((keysym == XK_Alt_L) || (keysym == XK_Alt_R))) {
  432. KeyCode alt, meta;
  433. if (keysym == XK_Alt_L) {
  434. alt = vncKeysymToKeycode(XK_Alt_L, state & ~ShiftMask, NULL);
  435. meta = vncKeysymToKeycode(XK_Meta_L, state, NULL);
  436. } else {
  437. alt = vncKeysymToKeycode(XK_Alt_R, state & ~ShiftMask, NULL);
  438. meta = vncKeysymToKeycode(XK_Meta_R, state, NULL);
  439. }
  440. if ((meta != 0) && (alt == meta)) {
  441. LOG_DEBUG("Replacing Shift+Alt with Shift+Meta");
  442. keycode = meta;
  443. new_state = state;
  444. }
  445. }
  446. /* Try some equivalent keysyms if we couldn't find a perfect match */
  447. if (keycode == 0) {
  448. for (i = 0;i < sizeof(altKeysym)/sizeof(altKeysym[0]);i++) {
  449. KeySym altsym;
  450. if (altKeysym[i].a == keysym)
  451. altsym = altKeysym[i].b;
  452. else if (altKeysym[i].b == keysym)
  453. altsym = altKeysym[i].a;
  454. else
  455. continue;
  456. keycode = vncKeysymToKeycode(altsym, state, &new_state);
  457. if (keycode != 0)
  458. break;
  459. }
  460. }
  461. /* No matches. Will have to add a new entry... */
  462. if (keycode == 0) {
  463. keycode = vncAddKeysym(keysym, state);
  464. if (keycode == 0) {
  465. LOG_ERROR("Failure adding new keysym 0x%x", keysym);
  466. return;
  467. }
  468. LOG_INFO("Added unknown keysym 0x%x to keycode %d",
  469. keysym, keycode);
  470. /*
  471. * The state given to addKeysym() is just a hint and
  472. * the actual result might still require some state
  473. * changes.
  474. */
  475. keycode = vncKeysymToKeycode(keysym, state, &new_state);
  476. if (keycode == 0) {
  477. LOG_ERROR("Newly added keysym 0x%x cannot be generated", keysym);
  478. return;
  479. }
  480. }
  481. /*
  482. * X11 generally lets shift toggle the keys on the numeric pad
  483. * the same way NumLock does. This is however not the case on
  484. * other systems like Windows. As a result, some applications
  485. * get confused when we do a fake shift to get the same effect
  486. * that having NumLock active would produce.
  487. *
  488. * Not all clients have proper NumLock synchronisation (so we
  489. * can avoid faking shift) so we try to avoid the fake shifts
  490. * if we can use an alternative keysym.
  491. */
  492. if (((state & ShiftMask) != (new_state & ShiftMask)) &&
  493. vncGetAvoidShiftNumLock() && vncIsAffectedByNumLock(keycode)) {
  494. KeyCode keycode2;
  495. unsigned new_state2;
  496. LOG_DEBUG("Finding alternative to keysym 0x%x to avoid fake shift for numpad", keysym);
  497. for (i = 0;i < sizeof(altKeysym)/sizeof(altKeysym[0]);i++) {
  498. KeySym altsym;
  499. if (altKeysym[i].a == keysym)
  500. altsym = altKeysym[i].b;
  501. else if (altKeysym[i].b == keysym)
  502. altsym = altKeysym[i].a;
  503. else
  504. continue;
  505. keycode2 = vncKeysymToKeycode(altsym, state, &new_state2);
  506. if (keycode2 == 0)
  507. continue;
  508. if (((state & ShiftMask) != (new_state2 & ShiftMask)) &&
  509. vncIsAffectedByNumLock(keycode2))
  510. continue;
  511. break;
  512. }
  513. if (i == sizeof(altKeysym)/sizeof(altKeysym[0]))
  514. LOG_DEBUG("No alternative keysym found");
  515. else {
  516. keycode = keycode2;
  517. new_state = new_state2;
  518. }
  519. }
  520. /*
  521. * "Shifted Tab" is a bit of a mess. Some systems have varying,
  522. * special keysyms for this symbol. VNC mandates that clients
  523. * should always send the plain XK_Tab keysym and the server
  524. * should deduce the meaning based on current Shift state.
  525. * To comply with this, we will find the keycode that sends
  526. * XK_Tab, and make sure that Shift isn't cleared. This can
  527. * possibly result in a different keysym than XK_Tab, but that
  528. * is the desired behaviour.
  529. *
  530. * Note: We never get ISO_Left_Tab here because it's already
  531. * been translated in VNCSConnectionST.
  532. */
  533. if (keysym == XK_Tab && (state & ShiftMask))
  534. new_state |= ShiftMask;
  535. /*
  536. * We need a bigger state change than just shift,
  537. * so we need to know what the mask is for level 3 shifts.
  538. */
  539. if ((new_state & ~ShiftMask) != (state & ~ShiftMask))
  540. level_three_mask = vncGetLevelThreeMask();
  541. else
  542. level_three_mask = 0;
  543. shift_press = level_three_press = 0;
  544. shift_release_count = level_three_release_count = 0;
  545. /* Need a fake press or release of shift? */
  546. if (!(state & ShiftMask) && (new_state & ShiftMask)) {
  547. shift_press = vncPressShift();
  548. if (shift_press == 0) {
  549. LOG_ERROR("Unable to find a modifier key for Shift");
  550. return;
  551. }
  552. pressKey(vncKeyboardDev, shift_press, TRUE, "temp shift");
  553. } else if ((state & ShiftMask) && !(new_state & ShiftMask)) {
  554. shift_release_count = vncReleaseShift(shift_release,
  555. sizeof(shift_release)/sizeof(*shift_release));
  556. if (shift_release_count == 0) {
  557. LOG_ERROR("Unable to find the modifier key(s) for releasing Shift");
  558. return;
  559. }
  560. for (i = 0;i < shift_release_count;i++)
  561. pressKey(vncKeyboardDev, shift_release[i], FALSE, "temp shift");
  562. }
  563. /* Need a fake press or release of level three shift? */
  564. if (!(state & level_three_mask) && (new_state & level_three_mask)) {
  565. level_three_press = vncPressLevelThree();
  566. if (level_three_press == 0) {
  567. LOG_ERROR("Unable to find a modifier key for ISO_Level3_Shift/Mode_Switch");
  568. return;
  569. }
  570. pressKey(vncKeyboardDev, level_three_press, TRUE, "temp level 3 shift");
  571. } else if ((state & level_three_mask) && !(new_state & level_three_mask)) {
  572. level_three_release_count = vncReleaseLevelThree(level_three_release,
  573. sizeof(level_three_release)/sizeof(*level_three_release));
  574. if (level_three_release_count == 0) {
  575. LOG_ERROR("Unable to find the modifier key(s) for releasing ISO_Level3_Shift/Mode_Switch");
  576. return;
  577. }
  578. for (i = 0;i < level_three_release_count;i++)
  579. pressKey(vncKeyboardDev, level_three_release[i], FALSE, "temp level 3 shift");
  580. }
  581. /* Now press the actual key */
  582. pressKey(vncKeyboardDev, keycode, TRUE, "keycode");
  583. /* And store the mapping so that we can do a proper release later */
  584. for (i = 0;i < 256;i++) {
  585. if (i == keycode)
  586. continue;
  587. if (pressedKeys[i] == keysym) {
  588. LOG_ERROR("Keysym 0x%x generated by both keys %d and %d", keysym, i, keycode);
  589. pressedKeys[i] = NoSymbol;
  590. }
  591. }
  592. pressedKeys[keycode] = keysym;
  593. /* Undo any fake level three shift */
  594. if (level_three_press != 0)
  595. pressKey(vncKeyboardDev, level_three_press, FALSE, "temp level 3 shift");
  596. else if (level_three_release_count != 0) {
  597. for (i = 0;i < level_three_release_count;i++)
  598. pressKey(vncKeyboardDev, level_three_release[i], TRUE, "temp level 3 shift");
  599. }
  600. /* Undo any fake shift */
  601. if (shift_press != 0)
  602. pressKey(vncKeyboardDev, shift_press, FALSE, "temp shift");
  603. else if (shift_release_count != 0) {
  604. for (i = 0;i < shift_release_count;i++)
  605. pressKey(vncKeyboardDev, shift_release[i], TRUE, "temp shift");
  606. }
  607. /*
  608. * When faking a modifier we are putting a keycode (which can
  609. * currently activate the desired modifier) on the input
  610. * queue. A future modmap change can change the mapping so
  611. * that this keycode means something else entirely. Guard
  612. * against this by processing the queue now.
  613. */
  614. mieqProcessInputEvents();
  615. }