From 2949c20338eabdd317403f218f5a5fcdaab3ff71 Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Sat, 22 Jun 2024 17:15:51 +0100 Subject: [PATCH] Check-in for weekend - needs more testing --- module/rdp.h | 10 ++- xrdpkeyb/rdpKeyboard.c | 151 ++++++++++++++++++++++------------------- 2 files changed, 89 insertions(+), 72 deletions(-) diff --git a/module/rdp.h b/module/rdp.h index 9122bc9..ac631d1 100644 --- a/module/rdp.h +++ b/module/rdp.h @@ -130,11 +130,19 @@ typedef struct _rdpPointer rdpPointer; struct _rdpKeyboard { - int pause_spe; + /* TODO : Check if these are needed */ int ctrl_down; int alt_down; int shift_down; + int tab_down; + + int skip_numlock; + + int x11_keycode_caps_lock; + int x11_keycode_num_lock; + int x11_keycode_scroll_lock; + /* this is toggled every time num lock key is released, not like the above *_down vars */ int scroll_lock_down; diff --git a/xrdpkeyb/rdpKeyboard.c b/xrdpkeyb/rdpKeyboard.c index 5c2ad9c..dd12504 100644 --- a/xrdpkeyb/rdpKeyboard.c +++ b/xrdpkeyb/rdpKeyboard.c @@ -53,6 +53,8 @@ xrdp keyboard module #include "rdpDraw.h" #include "rdpMisc.h" +#include "xrdp_scancode_defs.h" + /******************************************************************************/ #define LOG_LEVEL 1 #define LLOGLN(_level, _args) \ @@ -79,9 +81,6 @@ xrdp keyboard module /* num lock */ #define NUM_LOCK_KEY_CODE 77 -// From /usr/share/X11/xkb/keycodes/evdev -#define EVDEV_PAUS_KEY_CODE 127 - #define N_PREDEFINED_KEYS \ (sizeof(g_kbdMap) / (sizeof(KeySym) * GLYPHS_PER_KEY)) @@ -249,6 +248,7 @@ sendDownUpKeyEvent(DeviceIntPtr device, int type, int x_scancode) static void check_keysa(rdpKeyboard *keyboard) { + /* TODO : Check if these are needed */ if (keyboard->ctrl_down != 0) { rdpEnqueueKey(keyboard->device, KeyRelease, keyboard->ctrl_down); @@ -266,49 +266,71 @@ check_keysa(rdpKeyboard *keyboard) rdpEnqueueKey(keyboard->device, KeyRelease, keyboard->shift_down); keyboard->shift_down = 0; } + + // Terminate any pause sequence in progress + keyboard->skip_numlock = 0; } /** * @param down - true for KeyDown events, false otherwise * @param param1 - X11 keycode of pressed key * @param param2 - - * @param param3 - scancode of pressed key - * @param param4 - device flags + * @param param3 - keyCode from TS_KEYBOARD_EVENT + * @param param4 - keyboardFlags from TS_KEYBOARD_EVENT ******************************************************************************/ static void KbdAddEvent(rdpKeyboard *keyboard, int down, int param1, int param2, int param3, int param4) { int x_keycode = param1; - int rdp_scancode = param3; - int is_spe = param4 & 512; /* 0x200 */ + int rdp_scancode = SCANCODE_FROM_KBD_EVENT(param3, param4); int type = down ? KeyPress : KeyRelease; - // Create an extended scancode where if the extended bit is set, - // the scancode is >= 0x100 - int ext_rdp_scancode = (param4 & 0x100) | rdp_scancode; - LLOGLN(0, ("KbdAddEvent: down=%d scancode=%09x keycode=%d flags%08x", down, ext_rdp_scancode, x_keycode, param4)); - switch (ext_rdp_scancode) + LLOGLN(0, ("KbdAddEvent: down=%d RDP scancode=%03x " + "PDU keyCode=%04x PDU keyboardFlags=%04x X11 keycode=%04x", + down, rdp_scancode, + param3, param4, x_keycode)); + + if (keyboard->skip_numlock) + { + keyboard->skip_numlock = 0; + if (rdp_scancode == SCANCODE_NUMLOCK_KEY) + { + return; + } + } + switch (rdp_scancode) { - /* Non-repeating keys (except ctrl - see below) */ - case 0x02a: /* left shift */ - case 0x036: /* right shift */ - case 0x03a: /* caps lock */ - case 0x038: /* left alt */ - case 0x046: /* scroll lock */ - case 0x059: /* left meta */ - case 0x05a: /* right meta */ - case 0x138: /* right alt */ - case 0x15b: /* left win key */ - case 0x15c: /* right win key */ - case 0x15d: /* menu key */ + /* Non-repeating keys */ + case SCANCODE_LSHIFT_KEY: + case SCANCODE_RSHIFT_KEY: + case SCANCODE_LCTRL_KEY: + case SCANCODE_RCTRL_KEY: + case SCANCODE_LALT_KEY: + case SCANCODE_RALT_KEY: + case SCANCODE_CAPS_KEY: + case SCANCODE_NUMLOCK_KEY: + case SCANCODE_LWIN_KEY: + case SCANCODE_RWIN_KEY: + case SCANCODE_MENU_KEY: rdpEnqueueKey(keyboard->device, type, x_keycode); break; - case 0x00f: /* tab */ + case SCANCODE_SCROLL_KEY: + // Scroll lock is also non-repeating, but we need to keep + // track of the key state to handle a TS_SYNC_EVENT from + // the client. + if (type == KeyPress) + { + keyboard->scroll_lock_down = !keyboard->scroll_lock_down; + } + rdpEnqueueKey(keyboard->device, type, x_keycode); + break; + + case SCANCODE_TAB_KEY: if (!down && !keyboard->tab_down) { - /* leave x_keycode 0 here, we don't want the tab key up */ + /* Don't generate an event for this */ check_keysa(keyboard); } else @@ -319,42 +341,12 @@ KbdAddEvent(rdpKeyboard *keyboard, int down, int param1, int param2, keyboard->tab_down = down; break; - case 0x01d: /* left ctrl */ - case 0x11d: /* right ctrl */ - + case SCANCODE_PAUSE_KEY: /* The pause key (0xE1 0x1D from the keyboard controller) * is mapped to a combination of ctrl and numlock events - * see [MS-RDPBCGR] 2.2.8.1.1.3.1.1.1 for details */ - if (is_spe) - { - if (down) - { - keyboard->pause_spe = 1; - /* leave x_keycode 0 here, we don't want the control key down */ - } - } - else - { - keyboard->ctrl_down = down ? x_keycode : 0; - rdpEnqueueKey(keyboard->device, type, x_keycode); - } - - break; - - - case 0x045: /* Pause or Num Lock */ - - if (keyboard->pause_spe) - { - x_keycode = EVDEV_PAUS_KEY_CODE; - - if (!down) - { - keyboard->pause_spe = 0; - } - } - - sendDownUpKeyEvent(keyboard->device, type, x_keycode); + rdpEnqueueKey(keyboard->device, type, x_keycode); + keyboard->skip_numlock = 1; break; default: @@ -368,9 +360,6 @@ KbdAddEvent(rdpKeyboard *keyboard, int down, int param1, int param2, } /******************************************************************************/ -/* notes - - scroll lock doesn't seem to be a modifier in X -*/ static void KbdSync(rdpKeyboard *keyboard, int param1) { @@ -378,25 +367,37 @@ KbdSync(rdpKeyboard *keyboard, int param1) xkb_state = XkbStateFieldFromRec(&(keyboard->device->key->xkbInfo->state)); - if ((!(xkb_state & 0x02)) != (!(param1 & 4))) /* caps lock */ + // Caps_Lock is a specific modifier */ + if ((!(xkb_state & LockMask)) != (!(param1 & TS_SYNC_CAPS_LOCK))) { LLOGLN(0, ("KbdSync: toggling caps lock")); - KbdAddEvent(keyboard, 1, 58, 0, 58, 0); - KbdAddEvent(keyboard, 0, 58, 49152, 58, 49152); + rdpEnqueueKey(keyboard->device, KeyPress, + keyboard->x11_keycode_caps_lock); + rdpEnqueueKey(keyboard->device, KeyRelease, + keyboard->x11_keycode_caps_lock); } - if ((!(xkb_state & 0x10)) != (!(param1 & 2))) /* num lock */ + // Num_Lock is normally mapped to mod2 (see 'xmodmap -pm') + if ((!(xkb_state & Mod2Mask)) != (!(param1 & TS_SYNC_NUM_LOCK))) { LLOGLN(0, ("KbdSync: toggling num lock")); - KbdAddEvent(keyboard, 1, 69, 0, 69, 0); - KbdAddEvent(keyboard, 0, 69, 49152, 69, 49152); + rdpEnqueueKey(keyboard->device, KeyPress, + keyboard->x11_keycode_num_lock); + rdpEnqueueKey(keyboard->device, KeyRelease, + keyboard->x11_keycode_num_lock); } - if ((!(keyboard->scroll_lock_down)) != (!(param1 & 1))) /* scroll lock */ + // Scroll lock doesn't have its own modifier, so we need to track + // it ourselves + if ((!(keyboard->scroll_lock_down)) != (!(param1 & TS_SYNC_SCROLL_LOCK))) { LLOGLN(0, ("KbdSync: toggling scroll lock")); - KbdAddEvent(keyboard, 1, 70, 0, 70, 0); - KbdAddEvent(keyboard, 0, 70, 49152, 70, 49152); + rdpEnqueueKey(keyboard->device, KeyPress, + keyboard->x11_keycode_scroll_lock); + rdpEnqueueKey(keyboard->device, KeyRelease, + keyboard->x11_keycode_scroll_lock); + + keyboard->scroll_lock_down = !keyboard->scroll_lock_down; } } @@ -780,10 +781,18 @@ rdpLoadLayout(rdpKeyboard *keyboard, struct xrdp_client_info *client_info) { set.options = client_info->options; } + if (strlen(client_info->xkb_rules) > 0) + { + set.rules = client_info->xkb_rules; + } reload_xkb(keyboard->device, &set); reload_xkb(inputInfo.keyboard, &set); + /* Copy X11 keycodes needed to sync the keyboard */ + keyboard->x11_keycode_caps_lock = client_info->x11_keycode_caps_lock; + keyboard->x11_keycode_num_lock = client_info->x11_keycode_num_lock; + keyboard->x11_keycode_scroll_lock = client_info->x11_keycode_scroll_lock; return 0; }