Skip to content
Commits on Source (8)
......@@ -42,6 +42,11 @@
#include <libweston/backend-rdp.h>
#include "pixman-renderer.h"
/* This can be removed when we bump FreeRDP dependency past 3.0.0 in the future */
#ifndef KBD_PERSIAN
#define KBD_PERSIAN 0x50429
#endif
static void
rdp_peer_refresh_rfx(pixman_region32_t *damage, pixman_image_t *image, freerdp_peer *peer)
{
......@@ -727,7 +732,7 @@ struct rdp_to_xkb_keyboard_layout rdp_keyboards[] = {
{KBD_ITALIAN, "it", 0},
{KBD_ITALIAN_142, "it", "nodeadkeys"},
{KBD_JAPANESE, "jp", 0},
{KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002, "jp", "kana"},
{KBD_JAPANESE_INPUT_SYSTEM_MS_IME2002, "jp", 0},
{KBD_KOREAN, "kr", 0},
{KBD_KOREAN_INPUT_SYSTEM_IME_2000, "kr", "kr104"},
{KBD_DUTCH, "nl", 0},
......@@ -753,7 +758,8 @@ struct rdp_to_xkb_keyboard_layout rdp_keyboards[] = {
{KBD_ESTONIAN, "ee", 0},
{KBD_LATVIAN, "lv", 0},
{KBD_LITHUANIAN_IBM, "lt", "ibm"},
{KBD_FARSI, "af", 0},
{KBD_FARSI, "ir", "pes"},
{KBD_PERSIAN, "af", "basic"},
{KBD_VIETNAMESE, "vn", 0},
{KBD_ARMENIAN_EASTERN, "am", 0},
{KBD_AZERI_LATIN, 0, 0},
......@@ -805,13 +811,58 @@ struct rdp_to_xkb_keyboard_layout rdp_keyboards[] = {
{KBD_IRISH, 0, 0},
{KBD_BOSNIAN_CYRILLIC, "ba", "us"},
{KBD_UNITED_STATES_DVORAK, "us", "dvorak"},
{KBD_PORTUGUESE_BRAZILIAN_ABNT2, "br", "nativo"},
{KBD_PORTUGUESE_BRAZILIAN_ABNT2, "br", "abnt2"},
{KBD_CANADIAN_MULTILINGUAL_STANDARD, "ca", "multix"},
{KBD_GAELIC, "ie", "CloGaelach"},
{0x00000000, 0, 0},
};
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));
xkbRuleNames->model = "pc105";
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;
break;
}
}
/* Korean keyboard support (KeyboardType 8, LangID 0x412) */
if (KeyboardType == KBD_TYPE_KOREAN && ((KeyboardLayout & 0xFFFF) == 0x412)) {
/* TODO: PC/AT 101 Enhanced Korean Keyboard (Type B) and (Type C) are not supported yet
because default Xkb settings for Korean layout don'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) */
} else if (KeyboardType != KBD_TYPE_JAPANESE && ((KeyboardLayout & 0xFFFF) == 0x411)) {
/* when Japanese keyboard layout is used without a Japanese 106/109
* keyboard (keyboard type 7), use the "us" layout, since the "jp"
* layout in xkb expects the Japanese 106/109 keyboard layout.
*/
xkbRuleNames->layout = "us";
xkbRuleNames->variant = 0;
}
weston_log("%s: matching model=%s layout=%s variant=%s options=%s\n",
__func__, xkbRuleNames->model, xkbRuleNames->layout,
xkbRuleNames->variant, xkbRuleNames->options);
}
static BOOL
xf_peer_activate(freerdp_peer* client)
{
......@@ -824,7 +875,6 @@ xf_peer_activate(freerdp_peer* client)
struct xkb_rule_names xkbRuleNames;
struct xkb_keymap *keymap;
struct weston_output *weston_output;
int i;
pixman_box32_t box;
pixman_region32_t damage;
char seat_name[50];
......@@ -889,17 +939,10 @@ xf_peer_activate(freerdp_peer* client)
settings->KeyboardLayout, settings->KeyboardType, settings->KeyboardSubType,
settings->KeyboardFunctionKey);
memset(&xkbRuleNames, 0, sizeof(xkbRuleNames));
xkbRuleNames.model = "pc105";
for (i = 0; rdp_keyboards[i].rdpLayoutCode; i++) {
if (rdp_keyboards[i].rdpLayoutCode == settings->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;
}
}
convert_rdp_keyboard_to_xkb_rule_names(settings->KeyboardType,
settings->KeyboardSubType,
settings->KeyboardLayout,
&xkbRuleNames);
keymap = NULL;
if (xkbRuleNames.layout) {
......@@ -1194,6 +1237,7 @@ xf_input_synchronize_event(rdpInput *input, UINT32 flags)
RdpPeerContext *peerCtx = (RdpPeerContext *)input->context;
struct rdp_backend *b = peerCtx->rdpBackend;
struct rdp_output *output = peerCtx->rdpBackend->output;
struct weston_keyboard *keyboard;
pixman_box32_t box;
pixman_region32_t damage;
......@@ -1204,6 +1248,19 @@ xf_input_synchronize_event(rdpInput *input, UINT32 flags)
flags & KBD_SYNC_CAPS_LOCK ? 1 : 0,
flags & KBD_SYNC_KANA_LOCK ? 1 : 0);
keyboard = weston_seat_get_keyboard(peerCtx->item.seat);
if (keyboard) {
uint32_t value = 0;
if (flags & KBD_SYNC_NUM_LOCK)
value |= WESTON_NUM_LOCK;
if (flags & KBD_SYNC_CAPS_LOCK)
value |= WESTON_CAPS_LOCK;
weston_keyboard_set_locks(keyboard,
WESTON_NUM_LOCK | WESTON_CAPS_LOCK,
value);
}
/* sends a full refresh */
box.x1 = 0;
box.y1 = 0;
......@@ -1223,7 +1280,9 @@ 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;
bool send_release_key = false;
int notify = 0;
struct timespec time;
......@@ -1243,9 +1302,37 @@ 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);
if (flags & KBD_FLAGS_EXTENDED)
vk_code |= KBDEXT;
/* Korean keyboard support:
* WinPR's GetVirtualKeyCodeFromVirtualScanCode() can't handle hangul/hanja keys
* hanja and hangeul keys are only present on Korean 103 keyboard (Type 8:SubType 6) */
if (client->settings->KeyboardType == 8 &&
client->settings->KeyboardSubType == 6 &&
((full_code == (KBD_FLAGS_EXTENDED | ATKBD_RET_HANJA)) ||
(full_code == (KBD_FLAGS_EXTENDED | ATKBD_RET_HANGEUL)))) {
if (full_code == (KBD_FLAGS_EXTENDED | ATKBD_RET_HANJA))
vk_code = VK_HANJA;
else if (full_code == (KBD_FLAGS_EXTENDED | ATKBD_RET_HANGEUL))
vk_code = VK_HANGUL;
/* 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
*/
/* Similarly, for RDP there is no release for those 2 Korean keys,
* thus generate release right after press. */
if (keyState != WL_KEYBOARD_KEY_STATE_PRESSED) {
weston_log("RDP: Received invalid key release\n");
return TRUE;
}
send_release_key = true;
} else {
vk_code = GetVirtualKeyCodeFromVirtualScanCode(full_code, client->settings->KeyboardType);
}
/* 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);
......@@ -1254,6 +1341,13 @@ xf_input_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code)
weston_compositor_get_time(&time);
notify_key(peerContext->item.seat, &time,
scan_code - 8, keyState, STATE_UPDATE_AUTOMATIC);
if (send_release_key) {
notify_key(peerContext->item.seat, &time,
scan_code - 8,
WL_KEYBOARD_KEY_STATE_RELEASED,
STATE_UPDATE_AUTOMATIC);
}
}
return TRUE;
......
......@@ -51,6 +51,20 @@
#define DEFAULT_AXIS_STEP_DISTANCE 10
#define DEFAULT_PIXEL_FORMAT PIXEL_FORMAT_BGRA32
/* https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getkeyboardtype
* defines a keyboard type that isn't currently defined in FreeRDP, but is
* available for RDP connections */
#ifndef KBD_TYPE_KOREAN
#define KBD_TYPE_KOREAN 8
#endif
/* WinPR's GetVirtualKeyCodeFromVirtualScanCode() can't handle hangul/hanja keys */
/* 0x1f1 and 0x1f2 keys are only exists on Korean 103 keyboard (Type 8:SubType 6) */
/* From Linux's keyboard driver at drivers/input/keyboard/atkbd.c */
#define ATKBD_RET_HANJA 0xf1
#define ATKBD_RET_HANGEUL 0xf2
struct rdp_output;
struct rdp_backend {
......@@ -134,6 +148,9 @@ typedef struct rdp_peer_context RdpPeerContext;
void
rdp_debug_print(struct weston_log_scope *log_scope, bool cont, char *fmt, ...);
void
convert_rdp_keyboard_to_xkb_rule_names(UINT32 KeyboardType, UINT32 KeyboardSubType, UINT32 KeyboardLayout, struct xkb_rule_names *xkbRuleNames);
static inline struct rdp_head *
to_rdp_head(struct weston_head *base)
{
......