--- sourceforge.net/trunk/rdesktop/xkeymap.c 2002/09/14 13:47:24 123 +++ sourceforge.net/trunk/rdesktop/xkeymap.c 2002/09/26 14:04:30 203 @@ -19,12 +19,11 @@ */ #include -#include -#include -#include -#include +#define XK_MISCELLANY +#include #include #include +#include #include "rdesktop.h" #include "scancodes.h" @@ -41,7 +40,7 @@ static int min_keycode; static uint16 remote_modifier_state = 0; -static void update_modifier_state(uint16 modifiers, BOOL pressed); +static void update_modifier_state(uint8 scancode, BOOL pressed); static void add_to_keymap(char *keyname, uint8 scancode, uint16 modifiers, char *mapname) @@ -205,7 +204,6 @@ xkeymap_init(void) { unsigned int max_keycode; - int i; if (strcmp(keymapname, "none")) xkeymap_read(keymapname); @@ -216,16 +214,60 @@ /* Handles, for example, multi-scancode keypresses (which is not possible via keymap-files) */ BOOL -handle_special_keys(KeySym keysym, uint32 ev_time, BOOL pressed) +handle_special_keys(uint32 keysym, unsigned int state, uint32 ev_time, BOOL pressed) { switch (keysym) { - case XK_Break: /* toggle full screen */ - if (pressed && (get_key_state(XK_Alt_L) || get_key_state(XK_Alt_R))) + case XK_Break: + if (get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R)) { - xwin_toggle_fullscreen(); - return True; + /* toggle full screen */ + if (pressed) + xwin_toggle_fullscreen(); + } + else + { + /* Send Break sequence E0 46 E0 C6 */ + if (pressed) + { + rdp_send_scancode(ev_time, RDP_KEYPRESS, + (SCANCODE_EXTENDED | 0x46)); + rdp_send_scancode(ev_time, RDP_KEYPRESS, + (SCANCODE_EXTENDED | 0xc6)); + } + /* No break sequence */ + } + + return True; + break; + + case XK_Pause: + /* According to MS Keyboard Scan Code + Specification, pressing Pause should result + in E1 1D 45 E1 9D C5. I'm not exactly sure + of how this is supposed to be sent via + RDP. The code below seems to work, but with + the side effect that Left Ctrl stays + down. Therefore, we release it when Pause + is released. */ + if (pressed) + { + rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0); + rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x1d, 0); + rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x45, 0); + rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xe1, 0); + rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0x9d, 0); + rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYPRESS, 0xc5, 0); + } + else + { + // Release Left Ctrl + rdp_send_input(ev_time, RDP_INPUT_SCANCODE, RDP_KEYRELEASE, 0x1d, + 0); + } + + return True; break; case XK_Meta_L: /* Windows keys */ @@ -252,7 +294,7 @@ key_translation -xkeymap_translate_key(KeySym keysym, unsigned int keycode, unsigned int state) +xkeymap_translate_key(uint32 keysym, unsigned int keycode, unsigned int state) { key_translation tr = { 0, 0 }; @@ -277,23 +319,31 @@ if (tr.scancode != 0) { - DEBUG_KBD - (("Found key translation, scancode=0x%x, modifiers=0x%x\n", - tr.scancode, tr.modifiers)); + DEBUG_KBD(("Found key translation, scancode=0x%x, modifiers=0x%x\n", + tr.scancode, tr.modifiers)); return tr; } - fprintf(stderr, "No translation for (keysym 0x%lx, %s)\n", keysym, get_ksname(keysym)); + DEBUG_KBD(("No translation for (keysym 0x%lx, %s)\n", keysym, get_ksname(keysym))); /* not in keymap, try to interpret the raw scancode */ if ((keycode >= min_keycode) && (keycode <= 0x60)) { tr.scancode = keycode - min_keycode; - fprintf(stderr, "Sending guessed scancode 0x%x\n", tr.scancode); + + /* The modifiers to send for this key should be + obtained from the local state. Currently, only + shift is implemented. */ + if (state & ShiftMask) + { + tr.modifiers = MapLeftShiftMask; + } + + DEBUG_KBD(("Sending guessed scancode 0x%x\n", tr.scancode)); } else { - fprintf(stderr, "No good guess for keycode 0x%x found\n", keycode); + DEBUG_KBD(("No good guess for keycode 0x%x found\n", keycode)); } return tr; @@ -320,7 +370,7 @@ } char * -get_ksname(KeySym keysym) +get_ksname(uint32 keysym) { char *ksname = NULL; @@ -353,20 +403,30 @@ break; } - /* Shift */ + /* Shift. Left shift and right shift are treated as equal; either is fine. */ if (MASK_HAS_BITS(tr.modifiers, MapShiftMask) != MASK_HAS_BITS(remote_modifier_state, MapShiftMask)) { /* The remote modifier state is not correct */ - if (MASK_HAS_BITS(tr.modifiers, MapShiftMask)) + if (MASK_HAS_BITS(tr.modifiers, MapLeftShiftMask)) { - /* Needs this modifier. Send down. */ + /* Needs left shift. Send down. */ rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_LSHIFT); } + else if (MASK_HAS_BITS(tr.modifiers, MapRightShiftMask)) + { + /* Needs right shift. Send down. */ + rdp_send_scancode(ev_time, RDP_KEYPRESS, SCANCODE_CHAR_RSHIFT); + } else { - /* Should not use this modifier. Send up. */ - rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT); + /* Should not use this modifier. Send up for shift currently pressed. */ + if (MASK_HAS_BITS(remote_modifier_state, MapLeftShiftMask)) + /* Left shift is down */ + rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT); + else + /* Right shift is down */ + rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT); } } @@ -410,8 +470,36 @@ } +void +reset_modifier_keys(unsigned int state) +{ + /* reset keys */ + uint32 ev_time; + ev_time = time(NULL); + + if (MASK_HAS_BITS(remote_modifier_state, MapLeftShiftMask) && !get_key_state(state, XK_Shift_L)) + rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT); + + if (MASK_HAS_BITS(remote_modifier_state, MapRightShiftMask) && !get_key_state(state, XK_Shift_R)) + rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT); + + if (MASK_HAS_BITS(remote_modifier_state, MapLeftCtrlMask) && !get_key_state(state, XK_Control_L)) + rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL); + + if (MASK_HAS_BITS(remote_modifier_state, MapRightCtrlMask) && !get_key_state(state, XK_Control_R)) + rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RCTRL); + + if (MASK_HAS_BITS(remote_modifier_state, MapLeftAltMask) && !get_key_state(state, XK_Alt_L)) + rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LALT); + + 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); +} + + static void -update_modifier_state(uint16 modifiers, BOOL pressed) +update_modifier_state(uint8 scancode, BOOL pressed) { #ifdef WITH_DEBUG_KBD uint16 old_modifier_state; @@ -419,7 +507,7 @@ old_modifier_state = remote_modifier_state; #endif - switch (modifiers) + switch (scancode) { case SCANCODE_CHAR_LSHIFT: MASK_CHANGE_BIT(remote_modifier_state, MapLeftShiftMask, pressed); @@ -473,7 +561,7 @@ /* Send keyboard input */ void -rdp_send_scancode(uint32 time, uint16 flags, uint16 scancode) +rdp_send_scancode(uint32 time, uint16 flags, uint8 scancode) { update_modifier_state(scancode, !(flags & RDP_KEYRELEASE));