diff --git a/libweston/backend-rdp/rdp.c b/libweston/backend-rdp/rdp.c index 09debbae9..117156b26 100644 --- a/libweston/backend-rdp/rdp.c +++ b/libweston/backend-rdp/rdp.c @@ -1736,8 +1736,10 @@ 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 rdp_backend *b = peerContext->rdpBackend; - bool need_release = false; + 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; int notify = 0; struct timespec time; @@ -1753,7 +1755,7 @@ xf_input_keyboard_event(rdpInput *input, UINT16 flags, UINT16 code) notify = 1; } - if (notify) { + if (keyboard && notify) { full_code = code; if (flags & KBD_FLAGS_EXTENDED) full_code |= KBD_FLAGS_EXTENDED; @@ -1776,22 +1778,10 @@ 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); - need_release = true; + send_release_key = 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) @@ -1799,30 +1789,43 @@ 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); - - /*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); + /* 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; + } + 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 021ebe166..7689210d9 100644 --- a/libweston/backend-rdp/rdp.h +++ b/libweston/backend-rdp/rdp.h @@ -276,7 +276,6 @@ 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 884516f0c..c990d7459 100644 --- a/rdprail-shell/shell.c +++ b/rdprail-shell/shell.c @@ -1459,19 +1459,37 @@ 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); + } + } - 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); + 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); + } + } } }