diff --git a/libweston/backend-rdp/rdp.c b/libweston/backend-rdp/rdp.c index 117156b26..09debbae9 100644 --- a/libweston/backend-rdp/rdp.c +++ b/libweston/backend-rdp/rdp.c @@ -1736,10 +1736,8 @@ xf_input_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code) enum wl_keyboard_key_state keyState; freerdp_peer *client = input->context->peer; RdpPeerContext *peerContext = (RdpPeerContext *)input->context; - struct weston_keyboard *keyboard = weston_seat_get_keyboard(peerContext->item.seat); - /* struct rdp_backend *b = peerContext->rdpBackend; */ - bool send_key = false; - bool send_release_key = false; + struct rdp_backend *b = peerContext->rdpBackend; + bool need_release = false; int notify = 0; struct timespec time; @@ -1755,7 +1753,7 @@ xf_input_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code) notify = 1; } - if (keyboard && notify) { + if (notify) { full_code = code; if (flags & KBD_FLAGS_EXTENDED) full_code |= KBD_FLAGS_EXTENDED; @@ -1778,10 +1776,22 @@ xf_input_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code) /* 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); - send_release_key = true; + 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. */ + if ((peerContext->key_state[vk_code>>3] & (1<<(vk_code&0x7))) == 0) { + rdp_debug_verbose(b, "%s: inconsistent key state vk_code:%x\n", + __func__, vk_code); + goto exit; + } + peerContext->key_state[vk_code>>3] &= ~(1<<(vk_code&0x7)); + } 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)); + } /* 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) @@ -1789,43 +1799,30 @@ xf_input_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code) vk_code |= KBDEXT; scan_code = GetKeycodeFromVirtualKeyCode(vk_code, KEYCODE_TYPE_EVDEV); + /*weston_log("code=%x ext=%d vk_code=%x scan_code=%x\n", code, (flags & KBD_FLAGS_EXTENDED) ? 1 : 0, vk_code, scan_code);*/ + weston_compositor_get_time(&time); + notify_key(peerContext->item.seat, &time, + scan_code - 8, keyState, STATE_UPDATE_AUTOMATIC); - /* Ignore release if key is not previously pressed. */ - if (keyState == WL_KEYBOARD_KEY_STATE_RELEASED) { - uint32_t *k, *end; - end = keyboard->keys.data + keyboard->keys.size; - for (k = keyboard->keys.data; k < end; k++) { - if (*k == (scan_code - 8)) { - send_key = true; - break; - } - } - } else { - send_key = true; - } + /*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); - if (send_key) { /*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);*/ - notify_key(peerContext->item.seat, &time, - scan_code - 8, keyState, STATE_UPDATE_AUTOMATIC); - - if (send_release_key) { - /* 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: FREERDP_CB_RETURN(TRUE); } diff --git a/libweston/backend-rdp/rdp.h b/libweston/backend-rdp/rdp.h index 7689210d9..021ebe166 100644 --- a/libweston/backend-rdp/rdp.h +++ b/libweston/backend-rdp/rdp.h @@ -276,6 +276,7 @@ struct rdp_peer_context { bool button_state[5]; bool mouseButtonSwap; + char key_state[0xff/8]; // one bit per key. int verticalAccumWheelRotationPrecise; int verticalAccumWheelRotationDiscrete; int horizontalAccumWheelRotationPrecise; diff --git a/rdprail-shell/shell.c b/rdprail-shell/shell.c index c990d7459..884516f0c 100644 --- a/rdprail-shell/shell.c +++ b/rdprail-shell/shell.c @@ -1459,37 +1459,19 @@ handle_keyboard_focus(struct wl_listener *listener, void *data) { struct weston_keyboard *keyboard = data; struct shell_seat *seat = get_shell_seat(keyboard->seat); - struct weston_surface* new_focused_surface = weston_surface_get_main_surface(keyboard->focus); - struct weston_surface* old_focused_surface = seat->focused_surface; - struct wl_array keys; - wl_array_init(&keys); - - if (new_focused_surface != old_focused_surface) { - if (old_focused_surface) { - struct shell_surface *shsurf = get_shell_surface(old_focused_surface); - if (shsurf) { - shell_surface_lose_keyboard_focus(shsurf); - /* when old focused window is focus proxy surface, server side window is - taking focus, thus let keyboard knows that */ - /* note: "keys" array is empty, thus it begin with no key pressed */ - if (old_focused_surface == shsurf->shell->focus_proxy_surface) - notify_keyboard_focus_in(keyboard->seat, &keys, STATE_UPDATE_AUTOMATIC); - } - } - seat->focused_surface = new_focused_surface; - - if (new_focused_surface) { - struct shell_surface *shsurf = get_shell_surface(seat->focused_surface); - if (shsurf) { - shell_surface_gain_keyboard_focus(shsurf); - /* when new focused window is focus proxy window, client side window is - taking focus and server side window is losing focus, let keyboard to - clear out currently pressed keys */ - if (new_focused_surface == shsurf->shell->focus_proxy_surface) - notify_keyboard_focus_out(keyboard->seat); - } - } + if (seat->focused_surface) { + struct shell_surface *shsurf = get_shell_surface(seat->focused_surface); + if (shsurf) + shell_surface_lose_keyboard_focus(shsurf); + } + + seat->focused_surface = weston_surface_get_main_surface(keyboard->focus); + + if (seat->focused_surface) { + struct shell_surface *shsurf = get_shell_surface(seat->focused_surface); + if (shsurf) + shell_surface_gain_keyboard_focus(shsurf); } }