--- sourceforge.net/trunk/rdesktop/xkeymap.c 2002/09/17 16:57:07 183 +++ sourceforge.net/trunk/rdesktop/xkeymap.c 2002/11/18 15:31:19 260 @@ -1,7 +1,7 @@ /* rdesktop: A Remote Desktop Protocol client. User interface services - X keyboard mapping - Copyright (C) Matthew Chapman 1999-2001 + Copyright (C) Matthew Chapman 1999-2002 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 @@ -19,13 +19,11 @@ */ #include -#include -#include -#include -#include +#define XK_MISCELLANY +#include #include #include -#include +#include #include "rdesktop.h" #include "scancodes.h" @@ -38,11 +36,12 @@ extern int keylayout; extern BOOL enable_compose; +static BOOL keymap_loaded; static key_translation keymap[KEYMAP_SIZE]; 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) @@ -70,7 +69,8 @@ xkeymap_read(char *mapname) { FILE *fp; - char line[KEYMAP_MAX_LINE_LENGTH], path[PATH_MAX]; + char line[KEYMAP_MAX_LINE_LENGTH]; + char path[PATH_MAX], inplace_path[PATH_MAX]; unsigned int line_num = 0; unsigned int line_length = 0; char *keyname, *p; @@ -85,8 +85,16 @@ fp = fopen(path, "r"); if (fp == NULL) { - error("Failed to open keymap %s\n", path); - return False; + /* in case we are running from the source tree */ + strcpy(inplace_path, "keymaps/"); + strncat(inplace_path, mapname, sizeof(inplace_path) - sizeof("keymaps/")); + + fp = fopen(inplace_path, "r"); + if (fp == NULL) + { + error("Failed to open keymap %s\n", path); + return False; + } } /* FIXME: More tolerant on white space */ @@ -206,10 +214,21 @@ xkeymap_init(void) { unsigned int max_keycode; - int i; + char *mapname_ptr; + + /* Make keymapname lowercase */ + mapname_ptr = keymapname; + while (*mapname_ptr) + { + *mapname_ptr = tolower(*mapname_ptr); + mapname_ptr++; + } if (strcmp(keymapname, "none")) - xkeymap_read(keymapname); + { + if (xkeymap_read(keymapname)) + keymap_loaded = True; + } XDisplayKeycodes(display, &min_keycode, (int *) &max_keycode); } @@ -217,18 +236,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_Return: + if ((get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R)) + && (get_key_state(state, XK_Control_L) + || get_key_state(state, XK_Control_R))) { - xwin_toggle_fullscreen(); + /* Ctrl-Alt-Enter: toggle full screen */ + if (pressed) + xwin_toggle_fullscreen(); return True; } break; + case XK_Break: + /* 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 release sequence */ + return True; + + 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; + case XK_Meta_L: /* Windows keys */ case XK_Super_L: case XK_Hyper_L: @@ -246,14 +307,13 @@ rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LCTRL); } return True; - break; } return False; } 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 }; @@ -278,13 +338,13 @@ 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)); + if (keymap_loaded) + error("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)) @@ -299,11 +359,11 @@ tr.modifiers = MapLeftShiftMask; } - fprintf(stderr, "Sending guessed scancode 0x%x\n", tr.scancode); + 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; @@ -330,7 +390,7 @@ } char * -get_ksname(KeySym keysym) +get_ksname(uint32 keysym) { char *ksname = NULL; @@ -385,12 +445,8 @@ /* Left shift is down */ rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_LSHIFT); else - { - assert(MASK_HAS_BITS(remote_modifier_state, MapRightShiftMask)); /* Right shift is down */ rdp_send_scancode(ev_time, RDP_KEYRELEASE, SCANCODE_CHAR_RSHIFT); - } - } } @@ -435,35 +491,39 @@ void -reset_modifier_keys() +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(XK_Shift_L)) + 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(XK_Shift_R)) + 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(XK_Control_L)) + 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(XK_Control_R)) + 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(XK_Alt_L)) + 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(XK_Alt_R) && !get_key_state(XK_Mode_switch)) + !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; @@ -471,7 +531,7 @@ old_modifier_state = remote_modifier_state; #endif - switch (modifiers) + switch (scancode) { case SCANCODE_CHAR_LSHIFT: MASK_CHANGE_BIT(remote_modifier_state, MapLeftShiftMask, pressed); @@ -525,7 +585,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));