--- sourceforge.net/trunk/rdesktop/xkeymap.c 2003/08/27 22:51:33 450 +++ sourceforge.net/trunk/rdesktop/xkeymap.c 2003/11/11 14:01:31 548 @@ -1,7 +1,9 @@ /* rdesktop: A Remote Desktop Protocol client. User interface services - X keyboard mapping + Copyright (C) Matthew Chapman 1999-2002 + Copyright (C) Peter Astrand 2003 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -36,10 +38,12 @@ #define KEYMAP_MAX_LINE_LENGTH 80 extern Display *g_display; +extern Window g_wnd; extern char keymapname[16]; extern int keylayout; extern int g_win_button_size; extern BOOL g_enable_compose; +extern BOOL g_use_rdp5; static BOOL keymap_loaded; static key_translation keymap[KEYMAP_SIZE]; @@ -182,11 +186,6 @@ MASK_ADD_BITS(modifiers, MapLeftShiftMask); } - if (strstr(line_rest, "numlock")) - { - MASK_ADD_BITS(modifiers, MapNumLockMask); - } - if (strstr(line_rest, "localstate")) { MASK_ADD_BITS(modifiers, MapLocalStateMask); @@ -239,6 +238,55 @@ XDisplayKeycodes(g_display, &min_keycode, (int *) &max_keycode); } +static void +send_winkey(uint32 ev_time, BOOL pressed, BOOL leftkey) +{ + uint8 winkey; + + if (leftkey) + winkey = SCANCODE_CHAR_LWIN; + else + winkey = SCANCODE_CHAR_RWIN; + + if (pressed) + { + if (g_use_rdp5) + { + rdp_send_scancode(ev_time, RDP_KEYPRESS, winkey); + } + else + { + /* RDP4 doesn't support winkey. Fake with Ctrl-Esc */ + rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_LCTRL); + rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_ESC); + } + } + else + { + /* key released */ + if (g_use_rdp5) + { + rdp_send_scancode(ev_time, RDP_KEYRELEASE, winkey); + } + else + { + rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_ESC); + rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL); + } + } +} + +static void +reset_winkey(uint32 ev_time) +{ + if (g_use_rdp5) + { + /* For some reason, it seems to suffice to release + *either* the left or right winkey. */ + rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LWIN); + } +} + /* Handles, for example, multi-scancode keypresses (which is not possible via keymap-files) */ BOOL @@ -299,19 +347,13 @@ case XK_Meta_L: /* Windows keys */ case XK_Super_L: case XK_Hyper_L: + send_winkey(ev_time, pressed, True); + return True; + case XK_Meta_R: case XK_Super_R: case XK_Hyper_R: - if (pressed) - { - rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_LCTRL); - rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_ESC); - } - else - { - rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_ESC); - rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL); - } + send_winkey(ev_time, pressed, False); return True; case XK_space: @@ -415,17 +457,44 @@ return ksname; } +static BOOL +is_modifier(uint8 scancode) +{ + switch (scancode) + { + case SCANCODE_CHAR_LSHIFT: + case SCANCODE_CHAR_RSHIFT: + case SCANCODE_CHAR_LCTRL: + case SCANCODE_CHAR_RCTRL: + case SCANCODE_CHAR_LALT: + case SCANCODE_CHAR_RALT: + case SCANCODE_CHAR_LWIN: + case SCANCODE_CHAR_RWIN: + case SCANCODE_CHAR_NUMLOCK: + return True; + default: + break; + } + return False; +} + void -save_remote_modifiers() +save_remote_modifiers(uint8 scancode) { + if (is_modifier(scancode)) + return; + saved_remote_modifier_state = remote_modifier_state; } void -restore_remote_modifiers(uint32 ev_time) +restore_remote_modifiers(uint32 ev_time, uint8 scancode) { key_translation dummy; + if (is_modifier(scancode)) + return; + dummy.scancode = 0; dummy.modifiers = saved_remote_modifier_state; ensure_remote_modifiers(ev_time, dummy); @@ -435,44 +504,8 @@ ensure_remote_modifiers(uint32 ev_time, key_translation tr) { /* If this key is a modifier, do nothing */ - switch (tr.scancode) - { - case SCANCODE_CHAR_LSHIFT: - case SCANCODE_CHAR_RSHIFT: - case SCANCODE_CHAR_LCTRL: - case SCANCODE_CHAR_RCTRL: - case SCANCODE_CHAR_LALT: - case SCANCODE_CHAR_RALT: - case SCANCODE_CHAR_LWIN: - case SCANCODE_CHAR_RWIN: - case SCANCODE_CHAR_NUMLOCK: - return; - default: - break; - } - - /* NumLock */ - if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask) - != MASK_HAS_BITS(remote_modifier_state, MapNumLockMask)) - { - /* The remote modifier state is not correct */ - uint16 new_remote_state; - - if (MASK_HAS_BITS(tr.modifiers, MapNumLockMask)) - { - DEBUG_KBD(("Remote NumLock state is incorrect, activating NumLock.\n")); - new_remote_state = KBD_FLAG_NUMLOCK; - remote_modifier_state = MapNumLockMask; - } - else - { - DEBUG_KBD(("Remote NumLock state is incorrect, deactivating NumLock.\n")); - new_remote_state = 0; - remote_modifier_state = 0; - } - - rdp_send_input(0, RDP_INPUT_SYNCHRONIZE, 0, new_remote_state, 0); - } + if (is_modifier(tr.scancode)) + return; /* Shift. Left shift and right shift are treated as equal; either is fine. */ if (MASK_HAS_BITS(tr.modifiers, MapShiftMask) @@ -522,9 +555,35 @@ } +unsigned int +read_keyboard_state() +{ + unsigned int state; + Window wdummy; + int dummy; + + XQueryPointer(g_display, g_wnd, &wdummy, &wdummy, &dummy, &dummy, &dummy, &dummy, &state); + return state; +} + + +uint16 +ui_get_numlock_state(unsigned int state) +{ + uint16 numlock_state = 0; + + if (get_key_state(state, XK_Num_Lock)) + numlock_state = KBD_FLAG_NUMLOCK; + + return numlock_state; +} + + void -reset_modifier_keys(unsigned int state) +reset_modifier_keys() { + unsigned int state = read_keyboard_state(); + /* reset keys */ uint32 ev_time; ev_time = time(NULL); @@ -551,6 +610,10 @@ if (MASK_HAS_BITS(remote_modifier_state, MapRightAltMask) && !get_key_state(state, XK_Alt_R) && !get_key_state(state, XK_Mode_switch)) rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RALT); + + reset_winkey(ev_time); + + rdp_send_input(ev_time, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(state), 0); } @@ -589,19 +652,6 @@ case SCANCODE_CHAR_RWIN: MASK_CHANGE_BIT(remote_modifier_state, MapRightWinMask, pressed); break; - case SCANCODE_CHAR_NUMLOCK: - /* KeyReleases for NumLocks are sent immediately. Toggle the - modifier state only on Keypress */ - if (pressed) - { - BOOL newNumLockState; - newNumLockState = - (MASK_HAS_BITS - (remote_modifier_state, MapNumLockMask) == False); - MASK_CHANGE_BIT(remote_modifier_state, - MapNumLockMask, newNumLockState); - } - break; } #ifdef WITH_DEBUG_KBD