instance->update->BeginPaint = wl_begin_paint;
instance->update->EndPaint = wl_end_paint;
instance->update->DesktopResize = wl_resize_display;
- freerdp_keyboard_init(instance->context->settings->KeyboardLayout);
+ freerdp_keyboard_init_ex(instance->context->settings->KeyboardLayout,
+ instance->context->settings->KeyboardRemappingList);
if (!(context->disp = wlf_disp_new(context)))
return FALSE;
{
xf_keyboard_clear(xfc);
xfc->KeyboardLayout = xfc->context.settings->KeyboardLayout;
- xfc->KeyboardLayout = freerdp_keyboard_init(xfc->KeyboardLayout);
+ xfc->KeyboardLayout =
+ freerdp_keyboard_init_ex(xfc->KeyboardLayout, xfc->context.settings->KeyboardRemappingList);
xfc->context.settings->KeyboardLayout = xfc->KeyboardLayout;
if (xfc->modifierMap)
settings->KeyboardLayout = (UINT32)val;
}
+ CommandLineSwitchCase(arg, "kbd-remap")
+ {
+ if (!copy_value(arg->Value, &settings->KeyboardRemappingList))
+ return COMMAND_LINE_ERROR_MEMORY;
+ }
CommandLineSwitchCase(arg, "kbd-lang")
{
LONGLONG val;
"List keyboard layouts" },
{ "kbd-lang-list", COMMAND_LINE_VALUE_OPTIONAL | COMMAND_LINE_PRINT, NULL, NULL, NULL, -1, NULL,
"List keyboard languages" },
+ { "kbd-remap", COMMAND_LINE_VALUE_REQUIRED,
+ "List of <key>=<value>,... pairs to remap scancodes", NULL, NULL, -1, NULL,
+ "Keyboard scancode remapping" },
{ "kbd-subtype", COMMAND_LINE_VALUE_REQUIRED, "<id>", NULL, NULL, -1, NULL,
"Keyboard subtype" },
{ "kbd-type", COMMAND_LINE_VALUE_REQUIRED, "<id>", NULL, NULL, -1, NULL, "Keyboard type" },
#endif
FREERDP_API DWORD freerdp_keyboard_init(DWORD keyboardLayoutId);
+ FREERDP_API DWORD freerdp_keyboard_init_ex(DWORD keyboardLayoutId,
+ const char* keyboardRemappingList);
FREERDP_API RDP_KEYBOARD_LAYOUT* freerdp_keyboard_get_layouts(DWORD types);
FREERDP_API void freerdp_keyboard_layouts_free(RDP_KEYBOARD_LAYOUT* layouts);
FREERDP_API const char* freerdp_keyboard_get_layout_name_from_id(DWORD keyboardLayoutId);
#define FreeRDP_BitmapCacheV2CellInfo (2502)
#define FreeRDP_ColorPointerFlag (2560)
#define FreeRDP_PointerCacheSize (2561)
+#define FreeRDP_KeyboardRemappingList (2622)
#define FreeRDP_KeyboardCodePage (2623)
#define FreeRDP_KeyboardLayout (2624)
#define FreeRDP_KeyboardType (2625)
/* Pointer Capabilities */
ALIGN64 BOOL ColorPointerFlag; /* 2560 */
ALIGN64 UINT32 PointerCacheSize; /* 2561 */
- UINT64 padding2624[2623 - 2562]; /* 2562 */
+ UINT64 padding2624[2622 - 2562]; /* 2562 */
/* Input Capabilities */
+ ALIGN64 char* KeyboardRemappingList; /* 2622 */
ALIGN64 UINT32 KeyboardCodePage; /* 2623 */
ALIGN64 UINT32 KeyboardLayout; /* 2624 */
ALIGN64 UINT32 KeyboardType; /* 2625 */
case FreeRDP_KerberosRealm:
return settings->KerberosRealm;
+ case FreeRDP_KeyboardRemappingList:
+ return settings->KeyboardRemappingList;
+
case FreeRDP_NtlmSamFile:
return settings->NtlmSamFile;
settings->KerberosRealm = (val ? _strdup(val) : NULL);
return (!val || settings->KerberosRealm != NULL);
+ case FreeRDP_KeyboardRemappingList:
+ if (cleanup)
+ free(settings->KeyboardRemappingList);
+ settings->KeyboardRemappingList = (val ? _strdup(val) : NULL);
+ return (!val || settings->KeyboardRemappingList != NULL);
+
case FreeRDP_NtlmSamFile:
if (cleanup)
free(settings->NtlmSamFile);
{ FreeRDP_ImeFileName, 7, "FreeRDP_ImeFileName" },
{ FreeRDP_KerberosKdc, 7, "FreeRDP_KerberosKdc" },
{ FreeRDP_KerberosRealm, 7, "FreeRDP_KerberosRealm" },
+ { FreeRDP_KeyboardRemappingList, 7, "FreeRDP_KeyboardRemappingList" },
{ FreeRDP_NtlmSamFile, 7, "FreeRDP_NtlmSamFile" },
{ FreeRDP_Password, 7, "FreeRDP_Password" },
{ FreeRDP_PasswordHash, 7, "FreeRDP_PasswordHash" },
FreeRDP_ImeFileName,
FreeRDP_KerberosKdc,
FreeRDP_KerberosRealm,
+ FreeRDP_KeyboardRemappingList,
FreeRDP_NtlmSamFile,
FreeRDP_Password,
FreeRDP_PasswordHash,
#endif
-DWORD VIRTUAL_SCANCODE_TO_X11_KEYCODE[256][2];
-DWORD X11_KEYCODE_TO_VIRTUAL_SCANCODE[256];
+static DWORD VIRTUAL_SCANCODE_TO_X11_KEYCODE[256][2] = { 0 };
+static DWORD X11_KEYCODE_TO_VIRTUAL_SCANCODE[256] = { 0 };
+static DWORD REMAPPING_TABLE[0x10000] = { 0 };
int freerdp_detect_keyboard(DWORD* keyboardLayoutId)
{
return keyboardLayoutId;
}
+DWORD freerdp_keyboard_init_ex(DWORD keyboardLayoutId, const char* keyboardRemappingList)
+{
+ DWORD rc = freerdp_keyboard_init(keyboardLayoutId);
+
+ memset(REMAPPING_TABLE, 0, sizeof(REMAPPING_TABLE));
+ if (keyboardRemappingList)
+ {
+ char* copy = _strdup(keyboardRemappingList);
+ char* context = NULL;
+ char* token;
+ if (!copy)
+ goto fail;
+ token = strtok_s(copy, ",", &context);
+ while (token)
+ {
+ DWORD key, value;
+ int rc = sscanf(token, "%" PRIu32 "=%" PRIu32, &key, &value);
+ if (rc != 2)
+ rc = sscanf(token, "%" PRIx32 "=%" PRIx32 "", &key, &value);
+ if (rc != 2)
+ rc = sscanf(token, "%" PRIu32 "=%" PRIx32, &key, &value);
+ if (rc != 2)
+ rc = sscanf(token, "%" PRIx32 "=%" PRIu32, &key, &value);
+ if (rc != 2)
+ goto fail;
+ if (key >= ARRAYSIZE(REMAPPING_TABLE))
+ goto fail;
+ REMAPPING_TABLE[key] = value;
+ token = strtok_s(NULL, ",", &context);
+ }
+ fail:
+ free(copy);
+ }
+ return rc;
+}
+
DWORD freerdp_keyboard_get_rdp_scancode_from_x11_keycode(DWORD keycode)
{
- DEBUG_KBD("x11 keycode: %02" PRIX32 " -> rdp code: %02" PRIX8 "%s", keycode,
- RDP_SCANCODE_CODE(X11_KEYCODE_TO_VIRTUAL_SCANCODE[keycode]),
- RDP_SCANCODE_EXTENDED(X11_KEYCODE_TO_VIRTUAL_SCANCODE[keycode]) ? " extended" : "");
+ const DWORD scancode = X11_KEYCODE_TO_VIRTUAL_SCANCODE[keycode];
+ const DWORD remapped = REMAPPING_TABLE[scancode];
+ DEBUG_KBD("x11 keycode: %02" PRIX32 " -> rdp code: [%04" PRIx16 "] %02" PRIX8 "%s", keycode,
+ scancode, RDP_SCANCODE_CODE(scancode),
+ RDP_SCANCODE_EXTENDED(scancode) ? " extended" : "");
- return X11_KEYCODE_TO_VIRTUAL_SCANCODE[keycode];
+ if (remapped != 0)
+ {
+ DEBUG_KBD("remapped scancode: [%04" PRIx16 "] %02" PRIX8 "[%s] -> [%04" PRIx16 "] %02" PRIX8
+ "[%s]",
+ scancode, RDP_SCANCODE_CODE(scancode),
+ RDP_SCANCODE_EXTENDED(scancode) ? " extended" : "", remapped,
+ RDP_SCANCODE_CODE(remapped), RDP_SCANCODE_EXTENDED(remapped) ? " extended" : "");
+ return remapped;
+ }
+ return scancode;
}
DWORD freerdp_keyboard_get_x11_keycode_from_rdp_scancode(DWORD scancode, BOOL extended)