diff --git a/doc/rdesktop.1 b/doc/rdesktop.1 index c48fc0c..30042f8 100644 --- a/doc/rdesktop.1 +++ b/doc/rdesktop.1 @@ -92,6 +92,11 @@ size, in pixels. The special word "standard" means 18 pixels. .BR "-T " Sets the window title. .TP +.BR "-N" +Enable numlock syncronization between the Xserver and the remote RDP +session. This is useful with applications that looks at the numlock +state, but might cause problems with some Xservers like Xvnc. +.TP .BR "-a <bpp>" Sets the colour depth for the connection (8, 15, 16 or 24). More than 8 bpp are only supported when connecting to Windows XP diff --git a/keymaps/common b/keymaps/common index f773de6..f53c885 100644 --- a/keymaps/common +++ b/keymaps/common @@ -116,38 +116,38 @@ KP_Subtract 0x4a KP_Add 0x4e KP_Enter 0x9c -KP_Decimal 0x53 -KP_Separator 0x53 +KP_Decimal 0x53 numlock +KP_Separator 0x53 numlock KP_Delete 0x53 -KP_0 0x52 +KP_0 0x52 numlock KP_Insert 0x52 -KP_1 0x4f +KP_1 0x4f numlock KP_End 0x4f -KP_2 0x50 +KP_2 0x50 numlock KP_Down 0x50 -KP_3 0x51 +KP_3 0x51 numlock KP_Next 0x51 -KP_4 0x4b +KP_4 0x4b numlock KP_Left 0x4b -KP_5 0x4c +KP_5 0x4c numlock KP_Begin 0x4c -KP_6 0x4d +KP_6 0x4d numlock KP_Right 0x4d -KP_7 0x47 +KP_7 0x47 numlock KP_Home 0x47 -KP_8 0x48 +KP_8 0x48 numlock KP_Up 0x48 -KP_9 0x49 +KP_9 0x49 numlock KP_Prior 0x49 # diff --git a/keymaps/pt-br b/keymaps/pt-br index 46a96ce..54bafc5 100644 --- a/keymaps/pt-br +++ b/keymaps/pt-br @@ -60,7 +60,7 @@ period 0x34 greater 0x34 shift semicolon 0x35 colon 0x35 shift -comma 0x53 +comma 0x53 numlock backslash 0x56 bar 0x56 shift slash 0x73 diff --git a/rdesktop.c b/rdesktop.c index 6ad5905..1463885 100644 --- a/rdesktop.c +++ b/rdesktop.c @@ -66,6 +66,7 @@ BOOL g_grab_keyboard = True; BOOL g_hide_decorations = False; BOOL g_use_rdp5 = True; BOOL g_console_session = False; +BOOL g_numlock_sync = False; extern BOOL g_owncolmap; #ifdef WITH_RDPSND @@ -110,6 +111,7 @@ usage(char *program) fprintf(stderr, " -K: keep window manager key bindings\n"); fprintf(stderr, " -S: caption button size (single application mode)\n"); fprintf(stderr, " -T: window title\n"); + fprintf(stderr, " -N: enable numlock syncronization\n"); fprintf(stderr, " -a: connection colour depth\n"); fprintf(stderr, " -r: enable specified device redirection (currently: sound)\n"); fprintf(stderr, " -0: attach to console\n"); @@ -229,7 +231,7 @@ main(int argc, char *argv[]) #define VNCOPT #endif - while ((c = getopt(argc, argv, VNCOPT "u:d:s:c:p:n:k:g:fbeEmCDKS:T:a:r:045h?")) != -1) + while ((c = getopt(argc, argv, VNCOPT "u:d:s:c:p:n:k:g:fbeEmCDKS:T:Na:r:045h?")) != -1) { switch (c) { @@ -368,6 +370,10 @@ main(int argc, char *argv[]) STRNCPY(g_title, optarg, sizeof(g_title)); break; + case 'N': + g_numlock_sync = True; + break; + case 'a': g_server_bpp = strtol(optarg, NULL, 10); if (g_server_bpp != 8 && g_server_bpp != 16 && g_server_bpp != 15 diff --git a/xkeymap.c b/xkeymap.c index ba25e22..c5be513 100644 --- a/xkeymap.c +++ b/xkeymap.c @@ -44,6 +44,7 @@ extern int keylayout; extern int g_win_button_size; extern BOOL g_enable_compose; extern BOOL g_use_rdp5; +extern BOOL g_numlock_sync; static BOOL keymap_loaded; static key_translation keymap[KEYMAP_SIZE]; @@ -186,6 +187,11 @@ xkeymap_read(char *mapname) 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); @@ -361,6 +367,12 @@ handle_special_keys(uint32 keysym, unsigned int state, uint32 ev_time, BOOL pres if (g_win_button_size && (get_key_state(state, XK_Alt_L) || get_key_state(state, XK_Alt_R))) return True; + case XK_Num_Lock: + /* FIXME: We might want to do RDP_INPUT_SYNCHRONIZE here, if g_numlock_sync */ + if (!g_numlock_sync) + /* Inhibit */ + return True; + } return False; @@ -507,6 +519,33 @@ ensure_remote_modifiers(uint32 ev_time, key_translation tr) if (is_modifier(tr.scancode)) return; + if (!g_numlock_sync) + { + /* 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); + } + } + + /* 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)) @@ -613,7 +652,8 @@ reset_modifier_keys() reset_winkey(ev_time); - rdp_send_input(ev_time, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(state), 0); + if (g_numlock_sync) + rdp_send_input(ev_time, RDP_INPUT_SYNCHRONIZE, 0, ui_get_numlock_state(state), 0); } @@ -652,6 +692,18 @@ update_modifier_state(uint8 scancode, BOOL pressed) 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 && !g_numlock_sync) + { + BOOL newNumLockState; + newNumLockState = + (MASK_HAS_BITS + (remote_modifier_state, MapNumLockMask) == False); + MASK_CHANGE_BIT(remote_modifier_state, + MapNumLockMask, newNumLockState); + } } #ifdef WITH_DEBUG_KBD