Skip to content

Commit

Permalink
support Korean 101a and 103 keyboard (#25)
Browse files Browse the repository at this point in the history
Co-authored-by: Hideyuki Nagase <hideyukn@ntdev.microsoft.com>
  • Loading branch information
hideyukn88 and Hideyuki Nagase authored Jun 17, 2021
1 parent 9c4dead commit af24155
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 10 deletions.
69 changes: 61 additions & 8 deletions libweston/backend-rdp/rdp.c
Original file line number Diff line number Diff line change
Expand Up @@ -1118,28 +1118,43 @@ static const char *rdp_keyboard_types[] = {
"pc102",/* 4: IBM enhanced (101- or 102-key) keyboard */
"", /* 5: Nokia 1050 and similar keyboards */
"", /* 6: Nokia 9140 and similar keyboards */
"jp106" /* 7: Japanese keyboard */ /* alternative ja106 */
"jp106",/* 7: Japanese keyboard */ /* alternative ja106 */
"pc102" /* 8: Korean keyboard which is based on pc101, + 2 special Korean keys */
};

void
convert_rdp_keyboard_to_xkb_rule_names(
UINT32 KeyboardType,
UINT32 KeyboardSubType,
UINT32 KeyboardLayout,
struct xkb_rule_names *xkbRuleNames)
{
int i;
memset(xkbRuleNames, 0, sizeof(*xkbRuleNames));
if (KeyboardType <= 7)
if (KeyboardType <= ARRAY_LENGTH(rdp_keyboard_types))
xkbRuleNames->model = rdp_keyboard_types[KeyboardType];
for (i = 0; rdp_keyboards[i].rdpLayoutCode; i++) {
if (rdp_keyboards[i].rdpLayoutCode == KeyboardLayout) {
xkbRuleNames->layout = rdp_keyboards[i].xkbLayout;
xkbRuleNames->variant = rdp_keyboards[i].xkbVariant;
weston_log("%s: matching layout=%s variant=%s\n", __FUNCTION__,
xkbRuleNames->layout, xkbRuleNames->variant);
break;
}
}
/* Korean keyboard support (KeyboardType 8, LangID 0x412) */
if (KeyboardType == 8 && ((KeyboardLayout & 0xFFFF) == 0x412)) {
/* TODO: PC/AT 101 Enhanced Korean Keyboard (Type B) and (Type C) is not supported yet
because default Xkb settings for Korean layout doesn't have corresponding
configuration.
(Type B): KeyboardSubType:4: rctrl_hangul/ratl_hanja
(Type C): KeyboardSubType:5: shift_space_hangul/crtl_space_hanja */
if (KeyboardSubType == 0 ||
KeyboardSubType == 3) // PC/AT 101 Enhanced Korean Keyboard (Type A)
xkbRuleNames->variant = "kr104"; // kr(ralt_hangul)/kr(rctrl_hanja)
else if (KeyboardSubType == 6) // PC/AT 103 Enhanced Korean Keyboard
xkbRuleNames->variant = "kr106"; // kr(hw_keys)
}
weston_log("%s: matching layout=%s variant=%s options=%s\n", __FUNCTION__,
xkbRuleNames->layout, xkbRuleNames->variant, xkbRuleNames->options);
}

static BOOL
Expand Down Expand Up @@ -1320,6 +1335,7 @@ xf_peer_activate(freerdp_peer* client)
settings->KeyboardFunctionKey);

convert_rdp_keyboard_to_xkb_rule_names(settings->KeyboardType,
settings->KeyboardSubType,
settings->KeyboardLayout,
&xkbRuleNames);

Expand Down Expand Up @@ -1656,8 +1672,10 @@ xf_input_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code)
{
uint32_t scan_code, vk_code, full_code;
enum wl_keyboard_key_state keyState;
freerdp_peer *client = input->context->peer;
RdpPeerContext *peerContext = (RdpPeerContext *)input->context;
struct rdp_backend *b = peerContext->rdpBackend;
bool need_release = false;

int notify = 0;
struct timespec time;
Expand All @@ -1678,7 +1696,28 @@ xf_input_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code)
if (flags & KBD_FLAGS_EXTENDED)
full_code |= KBD_FLAGS_EXTENDED;

vk_code = GetVirtualKeyCodeFromVirtualScanCode(full_code, 4);
/* Korean keyboard support */
/* WinPR's GetVirtualKeyCodeFromVirtualScanCode() can't handle hangul/hanja keys */
/* 0x1f1 and 0x1f2 keys are only exists on Korean 103 keyboard (Type 8:SubType 6) */
if (client->settings->KeyboardType == 8 &&
client->settings->KeyboardSubType == 6 &&
((full_code == 0x1f1) || (full_code == 0x1f2))) {
if (full_code == 0x1f1)
vk_code = VK_HANGUL;
else if (full_code == 0x1f2)
vk_code = VK_HANJA;
/* From Linux's keyboard driver at drivers/input/keyboard/atkbd.c */
/*
* HANGEUL and HANJA keys do not send release events so we need to
* generate such events ourselves
*/
/* RDP works same, there is no release for those 2 Korean keys,
* thus generate release right after press. */
assert(keyState == WL_KEYBOARD_KEY_STATE_PRESSED);
need_release = true;
} else {
vk_code = GetVirtualKeyCodeFromVirtualScanCode(full_code, client->settings->KeyboardType);
}
assert(vk_code <= 0xFF);
if (keyState == WL_KEYBOARD_KEY_STATE_RELEASED) {
/* Ignore release if key is not previously pressed. */
Expand All @@ -1688,11 +1727,14 @@ xf_input_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code)
goto exit;
}
peerContext->key_state[vk_code>>3] &= ~(1<<(vk_code&0x7));
} else {
} else if (!need_release /* when release is issued right after, no need to save state */) {
peerContext->key_state[vk_code>>3] |= (1<<(vk_code&0x7));
}
if (flags & KBD_FLAGS_EXTENDED)
vk_code |= KBDEXT;
/* Korean keyboard support */
/* WinPR's GetKeycodeFromVirtualKeyCode() expects no extended bit for VK_HANGUL and VK_HANJA */
if (vk_code != VK_HANGUL && vk_code != VK_HANJA)
if (flags & KBD_FLAGS_EXTENDED)
vk_code |= KBDEXT;

scan_code = GetKeycodeFromVirtualKeyCode(vk_code, KEYCODE_TYPE_EVDEV);

Expand All @@ -1705,6 +1747,17 @@ xf_input_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code)
/*rdp_debug_verbose(b, "RDP backend: %s code=%x ext=%d vk_code=%x scan_code=%x pressed=%d, idle_inhibit=%d\n",
__func__, code, (flags & KBD_FLAGS_EXTENDED) ? 1 : 0,
vk_code, scan_code, keyState, b->compositor->idle_inhibit);*/

if (need_release) {
/* send release of same key */
weston_compositor_get_time(&time);
notify_key(peerContext->item.seat, &time,
scan_code - 8, WL_KEYBOARD_KEY_STATE_RELEASED, STATE_UPDATE_AUTOMATIC);

/*rdp_debug_verbose(b, "RDP backend: %s code=%x ext=%d vk_code=%x scan_code=%x pressed=%d, idle_inhibit=%d\n",
__func__, code, (flags & KBD_FLAGS_EXTENDED) ? 1 : 0,
vk_code, scan_code, keyState, b->compositor->idle_inhibit);*/
}
}

exit:
Expand Down
2 changes: 1 addition & 1 deletion libweston/backend-rdp/rdp.h
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ typedef struct rdp_peer_context RdpPeerContext;
/* To enable rdp_debug message, add "--logger-scopes=rdp-backend". */

// rdp.c
void convert_rdp_keyboard_to_xkb_rule_names(UINT32 KeyboardType, UINT32 KeyboardLayout, struct xkb_rule_names *xkbRuleNames);
void convert_rdp_keyboard_to_xkb_rule_names(UINT32 KeyboardType, UINT32 KeyboardSubType, UINT32 KeyboardLayout, struct xkb_rule_names *xkbRuleNames);
struct rdp_head * rdp_head_create(struct weston_compositor *compositor, BOOL isPrimary, struct rdp_monitor_mode *monitorMode);
void rdp_head_destroy(struct weston_compositor *compositor, struct rdp_head *head);

Expand Down
8 changes: 7 additions & 1 deletion libweston/backend-rdp/rdprail.c
Original file line number Diff line number Diff line change
Expand Up @@ -827,8 +827,10 @@ rail_client_LanguageImeInfo_callback(int fd, uint32_t mask, void *arg)
if (languageImeInfo->ProfileType == TF_PROFILETYPE_KEYBOARDLAYOUT) {
struct xkb_rule_names xkbRuleNames;
struct xkb_keymap *keymap = NULL;
settings->KeyboardLayout = languageImeInfo->KeyboardLayout;
convert_rdp_keyboard_to_xkb_rule_names(settings->KeyboardType,
languageImeInfo->KeyboardLayout,
settings->KeyboardSubType,
settings->KeyboardLayout,
&xkbRuleNames);
if (xkbRuleNames.layout) {
keymap = xkb_keymap_new_from_names(b->compositor->xkb_context,
Expand All @@ -838,6 +840,10 @@ rail_client_LanguageImeInfo_callback(int fd, uint32_t mask, void *arg)
xkb_keymap_unref(keymap);
}
}
if (!keymap) {
rdp_debug_error(b, "%s: Failed to switch to kbd_layout:0x%x kbd_type:0x%x kbd_subType:0x%x\n",
__func__, settings->KeyboardLayout, settings->KeyboardType, settings->KeyboardSubType);
}
}

RDP_DISPATCH_DISPLAY_LOOP_COMPLETED(peerCtx, data);
Expand Down

0 comments on commit af24155

Please sign in to comment.