?? xserverdesktop.cc
字號:
class ModifierState {public: ModifierState(DeviceIntPtr dev_, int modIndex_) : dev(dev_), modIndex(modIndex_), nKeys(0), keys(0), pressed(false) { } ~ModifierState() { for (int i = 0; i < nKeys; i++) generateXKeyEvent(keys[i], !pressed); delete [] keys; } void press() { KeyClassPtr keyc = dev->key; if (!(keyc->state & (1<<modIndex))) { tempKeyEvent(keyc->modifierKeyMap[modIndex * keyc->maxKeysPerModifier], true); pressed = true; } } void release() { KeyClassPtr keyc = dev->key; if (keyc->state & (1<<modIndex)) { for (int k = 0; k < keyc->maxKeysPerModifier; k++) { int keycode = keyc->modifierKeyMap[modIndex * keyc->maxKeysPerModifier + k]; if (keycode && IS_PRESSED(keyc, keycode)) tempKeyEvent(keycode, false); } } }private: void tempKeyEvent(int keycode, bool down) { if (keycode) { if (!keys) keys = new int[dev->key->maxKeysPerModifier]; keys[nKeys++] = keycode; generateXKeyEvent(keycode, down); } } void generateXKeyEvent(int keycode, bool down) { xEvent ev; ev.u.u.type = down ? KeyPress : KeyRelease; ev.u.u.detail = keycode; ev.u.keyButtonPointer.time = GetTimeInMillis(); (*dev->c_public.processInputProc)(&ev, dev, 1); vlog.debug("fake keycode %d %s", keycode, down ? "down" : "up"); } DeviceIntPtr dev; int modIndex; int nKeys; int* keys; bool pressed;};// altKeysym is a table of alternative keysyms which have the same meaning.struct altKeysym_t { KeySym a, b;};altKeysym_t altKeysym[] = { { XK_Shift_L, XK_Shift_R }, { XK_Control_L, XK_Control_R }, { XK_Meta_L, XK_Meta_R }, { XK_Alt_L, XK_Alt_R }, { XK_Super_L, XK_Super_R }, { XK_Hyper_L, XK_Hyper_R }, { XK_KP_Space, XK_space }, { XK_KP_Tab, XK_Tab }, { XK_KP_Enter, XK_Return }, { XK_KP_F1, XK_F1 }, { XK_KP_F2, XK_F2 }, { XK_KP_F3, XK_F3 }, { XK_KP_F4, XK_F4 }, { XK_KP_Home, XK_Home }, { XK_KP_Left, XK_Left }, { XK_KP_Up, XK_Up }, { XK_KP_Right, XK_Right }, { XK_KP_Down, XK_Down }, { XK_KP_Page_Up, XK_Page_Up }, { XK_KP_Page_Down, XK_Page_Down }, { XK_KP_End, XK_End }, { XK_KP_Begin, XK_Begin }, { XK_KP_Insert, XK_Insert }, { XK_KP_Delete, XK_Delete }, { XK_KP_Equal, XK_equal }, { XK_KP_Multiply, XK_asterisk }, { XK_KP_Add, XK_plus }, { XK_KP_Separator, XK_comma }, { XK_KP_Subtract, XK_minus }, { XK_KP_Decimal, XK_period }, { XK_KP_Divide, XK_slash }, { XK_KP_0, XK_0 }, { XK_KP_1, XK_1 }, { XK_KP_2, XK_2 }, { XK_KP_3, XK_3 }, { XK_KP_4, XK_4 }, { XK_KP_5, XK_5 }, { XK_KP_6, XK_6 }, { XK_KP_7, XK_7 }, { XK_KP_8, XK_8 }, { XK_KP_9, XK_9 },};// keyEvent() - work out the best keycode corresponding to the keysym sent by// the viewer. This is non-trivial because we can't assume much about the// local keyboard layout. We must also find out which column of the keyboard// mapping the keysym is in, and alter the shift state appropriately. Column 0// means both shift and "mode_switch" (AltGr) must be released, column 1 means// shift must be pressed and mode_switch released, column 2 means shift must be// released and mode_switch pressed, and column 3 means both shift and// mode_switch must be pressed.void XserverDesktop::keyEvent(rdr::U32 keysym, bool down){ if (keysym == XK_Caps_Lock) { vlog.debug("Ignoring caps lock"); return; } DeviceIntPtr dev = (DeviceIntPtr)LookupKeyboardDevice(); KeyClassPtr keyc = dev->key; KeySymsPtr keymap = &keyc->curKeySyms; // find which modifier Mode_switch is on. int modeSwitchMapIndex = 0; for (int i = 3; i < 8; i++) { for (int k = 0; k < keyc->maxKeysPerModifier; k++) { int keycode = keyc->modifierKeyMap[i * keyc->maxKeysPerModifier + k]; for (int j = 0; j < keymap->mapWidth; j++) { if (keycode != 0 && keymap->map[(keycode - keymap->minKeyCode) * keymap->mapWidth + j] == XK_Mode_switch) { modeSwitchMapIndex = i; break; } } } } int col = 0; if (keyc->state & (1<<ShiftMapIndex)) col |= 1; if (modeSwitchMapIndex && (keyc->state & (1<<modeSwitchMapIndex))) col |= 2; int kc = KeysymToKeycode(keymap, keysym, &col); // Sort out the "shifted Tab" mess. If we are sent a shifted Tab, generate a // local shifted Tab regardless of what the "shifted Tab" keysym is on the // local keyboard (it might be Tab, ISO_Left_Tab or HP's private BackTab // keysym, and quite possibly some others too). We never get ISO_Left_Tab // here because it's already been translated in VNCSConnectionST. if (keysym == XK_Tab && (keyc->state & (1<<ShiftMapIndex))) col |= 1; if (kc == 0) { // Not a direct match in the local keyboard mapping. Check for alternative // keysyms with the same meaning. for (int i = 0; i < sizeof(altKeysym) / sizeof(altKeysym_t); i++) { if (keysym == altKeysym[i].a) kc = KeysymToKeycode(keymap, altKeysym[i].b, &col); else if (keysym == altKeysym[i].b) kc = KeysymToKeycode(keymap, altKeysym[i].a, &col); if (kc) break; } } if (kc == 0) { // Last resort - dynamically add a new key to the keyboard mapping. for (kc = keymap->maxKeyCode; kc >= keymap->minKeyCode; kc--) { if (!keymap->map[(kc - keymap->minKeyCode) * keymap->mapWidth]) { keymap->map[(kc - keymap->minKeyCode) * keymap->mapWidth] = keysym; col = 0; SendMappingNotify(MappingKeyboard, kc, 1, serverClient); vlog.info("Added unknown keysym 0x%x to keycode %d",keysym,kc); break; } } if (kc < keymap->minKeyCode) { vlog.info("Keyboard mapping full - ignoring unknown keysym 0x%x",keysym); return; } } // See if it's a modifier key. If so, then don't do any auto-repeat, because // the X server will translate each press into a release followed by a press. for (int i = 0; i < 8; i++) { for (int k = 0; k < keyc->maxKeysPerModifier; k++) { if (kc == keyc->modifierKeyMap[i * keyc->maxKeysPerModifier + k] && IS_PRESSED(keyc,kc) && down) return; } } ModifierState shift(dev, ShiftMapIndex); ModifierState modeSwitch(dev, modeSwitchMapIndex); if (down) { if (col & 1) shift.press(); else shift.release(); if (modeSwitchMapIndex) { if (col & 2) modeSwitch.press(); else modeSwitch.release(); } } vlog.debug("keycode %d %s", kc, down ? "down" : "up"); xEvent ev; ev.u.u.type = down ? KeyPress : KeyRelease; ev.u.u.detail = kc; ev.u.keyButtonPointer.time = GetTimeInMillis(); (*dev->c_public.processInputProc)(&ev, dev, 1);}void XConvertCase(KeySym sym, KeySym *lower, KeySym *upper){ *lower = sym; *upper = sym; switch(sym >> 8) { case 0: /* Latin 1 */ if ((sym >= XK_A) && (sym <= XK_Z)) *lower += (XK_a - XK_A); else if ((sym >= XK_a) && (sym <= XK_z)) *upper -= (XK_a - XK_A); else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis)) *lower += (XK_agrave - XK_Agrave); else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis)) *upper -= (XK_agrave - XK_Agrave); else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn)) *lower += (XK_oslash - XK_Ooblique); else if ((sym >= XK_oslash) && (sym <= XK_thorn)) *upper -= (XK_oslash - XK_Ooblique); break; case 1: /* Latin 2 */ /* Assume the KeySym is a legal value (ignore discontinuities) */ if (sym == XK_Aogonek) *lower = XK_aogonek; else if (sym >= XK_Lstroke && sym <= XK_Sacute) *lower += (XK_lstroke - XK_Lstroke); else if (sym >= XK_Scaron && sym <= XK_Zacute) *lower += (XK_scaron - XK_Scaron); else if (sym >= XK_Zcaron && sym <= XK_Zabovedot) *lower += (XK_zcaron - XK_Zcaron); else if (sym == XK_aogonek) *upper = XK_Aogonek; else if (sym >= XK_lstroke && sym <= XK_sacute) *upper -= (XK_lstroke - XK_Lstroke); else if (sym >= XK_scaron && sym <= XK_zacute) *upper -= (XK_scaron - XK_Scaron); else if (sym >= XK_zcaron && sym <= XK_zabovedot) *upper -= (XK_zcaron - XK_Zcaron); else if (sym >= XK_Racute && sym <= XK_Tcedilla) *lower += (XK_racute - XK_Racute); else if (sym >= XK_racute && sym <= XK_tcedilla) *upper -= (XK_racute - XK_Racute); break; case 2: /* Latin 3 */ /* Assume the KeySym is a legal value (ignore discontinuities) */ if (sym >= XK_Hstroke && sym <= XK_Hcircumflex) *lower += (XK_hstroke - XK_Hstroke); else if (sym >= XK_Gbreve && sym <= XK_Jcircumflex) *lower += (XK_gbreve - XK_Gbreve); else if (sym >= XK_hstroke && sym <= XK_hcircumflex) *upper -= (XK_hstroke - XK_Hstroke); else if (sym >= XK_gbreve && sym <= XK_jcircumflex) *upper -= (XK_gbreve - XK_Gbreve); else if (sym >= XK_Cabovedot && sym <= XK_Scircumflex) *lower += (XK_cabovedot - XK_Cabovedot); else if (sym >= XK_cabovedot && sym <= XK_scircumflex) *upper -= (XK_cabovedot - XK_Cabovedot); break; case 3: /* Latin 4 */ /* Assume the KeySym is a legal value (ignore discontinuities) */ if (sym >= XK_Rcedilla && sym <= XK_Tslash) *lower += (XK_rcedilla - XK_Rcedilla); else if (sym >= XK_rcedilla && sym <= XK_tslash) *upper -= (XK_rcedilla - XK_Rcedilla); else if (sym == XK_ENG) *lower = XK_eng; else if (sym == XK_eng) *upper = XK_ENG; else if (sym >= XK_Amacron && sym <= XK_Umacron) *lower += (XK_amacron - XK_Amacron); else if (sym >= XK_amacron && sym <= XK_umacron) *upper -= (XK_amacron - XK_Amacron); break; case 6: /* Cyrillic */ /* Assume the KeySym is a legal value (ignore discontinuities) */ if (sym >= XK_Serbian_DJE && sym <= XK_Serbian_DZE) *lower -= (XK_Serbian_DJE - XK_Serbian_dje); else if (sym >= XK_Serbian_dje && sym <= XK_Serbian_dze) *upper += (XK_Serbian_DJE - XK_Serbian_dje); else if (sym >= XK_Cyrillic_YU && sym <= XK_Cyrillic_HARDSIGN) *lower -= (XK_Cyrillic_YU - XK_Cyrillic_yu); else if (sym >= XK_Cyrillic_yu && sym <= XK_Cyrillic_hardsign) *upper += (XK_Cyrillic_YU - XK_Cyrillic_yu); break; case 7: /* Greek */ /* Assume the KeySym is a legal value (ignore discontinuities) */ if (sym >= XK_Greek_ALPHAaccent && sym <= XK_Greek_OMEGAaccent) *lower += (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent); else if (sym >= XK_Greek_alphaaccent && sym <= XK_Greek_omegaaccent && sym != XK_Greek_iotaaccentdieresis && sym != XK_Greek_upsilonaccentdieresis) *upper -= (XK_Greek_alphaaccent - XK_Greek_ALPHAaccent); else if (sym >= XK_Greek_ALPHA && sym <= XK_Greek_OMEGA) *lower += (XK_Greek_alpha - XK_Greek_ALPHA); else if (sym >= XK_Greek_alpha && sym <= XK_Greek_omega && sym != XK_Greek_finalsmallsigma) *upper -= (XK_Greek_alpha - XK_Greek_ALPHA); break; }}static KeySym KeyCodetoKeySym(KeySymsPtr keymap, int keycode, int col){ register int per = keymap->mapWidth; register KeySym *syms; KeySym lsym, usym; if ((col < 0) || ((col >= per) && (col > 3)) || (keycode < keymap->minKeyCode) || (keycode > keymap->maxKeyCode)) return NoSymbol; syms = &keymap->map[(keycode - keymap->minKeyCode) * per]; if (col < 4) { if (col > 1) { while ((per > 2) && (syms[per - 1] == NoSymbol)) per--; if (per < 3) col -= 2; } if ((per <= (col|1)) || (syms[col|1] == NoSymbol)) { XConvertCase(syms[col&~1], &lsym, &usym); if (!(col & 1)) return lsym; // I'm commenting out this logic because it's incorrect even though it // was copied from the Xlib sources. The X protocol book quite clearly // states that where a group consists of element 1 being a non-alphabetic // keysym and element 2 being NoSymbol that you treat the second element // as being the same as the first. This also tallies with the behaviour // produced by the installed Xlib on my linux box (I believe this is // because it uses some XKB code rather than the original Xlib code - // compare XKBBind.c with KeyBind.c in lib/X11). // else if (usym == lsym) // return NoSymbol; else return usym; } } return syms[col];}// KeysymToKeycode() - find the keycode and column corresponding to the given// keysym. The value of col passed in should be the column determined from the// current shift state. If the keysym can be found in that column we prefer// that to finding it in a different column (which would require fake events to// alter the shift state).static KeyCode KeysymToKeycode(KeySymsPtr keymap, KeySym ks, int* col){ register int i, j; j = *col; for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) { if (KeyCodetoKeySym(keymap, i, j) == ks) return i; } for (j = 0; j < keymap->mapWidth; j++) { for (i = keymap->minKeyCode; i <= keymap->maxKeyCode; i++) { if (KeyCodetoKeySym(keymap, i, j) == ks) { *col = j; return i; } } } return 0;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -