Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 30 additions & 28 deletions libweston/backend-rdp/rdp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -1776,53 +1778,53 @@ 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)
if (flags & KBD_FLAGS_EXTENDED)
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);*/
/* 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 (need_release) {
/* send release of same key */
if (send_key) {
send_release_key:
weston_compositor_get_time(&time);
notify_key(peerContext->item.seat, &time,
scan_code - 8, WL_KEYBOARD_KEY_STATE_RELEASED, STATE_UPDATE_AUTOMATIC);
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",
/*rdp_debug(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 (send_release_key) {
send_release_key = false;
assert(keyState == WL_KEYBOARD_KEY_STATE_PRESSED);
keyState = WL_KEYBOARD_KEY_STATE_RELEASED;
goto send_release_key;
}
}
}

exit:
FREERDP_CB_RETURN(TRUE);
}

Expand Down
1 change: 0 additions & 1 deletion libweston/backend-rdp/rdp.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
86 changes: 77 additions & 9 deletions rdprail-shell/shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ struct rotate_grab {

struct shell_seat {
struct weston_seat *seat;
struct desktop_shell *shell;
struct wl_listener seat_destroy_listener;
struct weston_surface *focused_surface;

Expand Down Expand Up @@ -230,6 +231,9 @@ find_shell_output_from_weston_output(struct desktop_shell *shell,
static void
shell_surface_update_child_surface_layers(struct shell_surface *shsurf);

static void
shell_backend_request_window_activate(void *shell_context, struct weston_seat *seat, struct weston_surface *surface);

#define ICON_STRIDE( W, BPP ) ((((W) * (BPP) + 31) / 32) * 4)

static int cached_tm_mday = -1;
Expand Down Expand Up @@ -1459,20 +1463,59 @@ handle_keyboard_focus(struct wl_listener *listener, void *data)
{
struct weston_keyboard *keyboard = data;
struct shell_seat *seat = get_shell_seat(keyboard->seat);
struct desktop_shell *shell = seat->shell;
struct weston_surface* new_focused_surface = weston_surface_get_main_surface(keyboard->focus);
struct weston_surface* old_focused_surface = seat->focused_surface;

if (shell->debugLevel >= RDPRAIL_SHELL_DEBUG_LEVEL_VERBOSE) {
struct weston_desktop_surface *old_desktop_surface = NULL;
struct weston_desktop_surface *new_desktop_surface = NULL;
const char *old_title = NULL;
const char *new_title = NULL;

if (old_focused_surface)
old_desktop_surface = weston_surface_get_desktop_surface(old_focused_surface);
if (new_focused_surface)
new_desktop_surface = weston_surface_get_desktop_surface(new_focused_surface);
if (old_desktop_surface)
old_title = weston_desktop_surface_get_title(old_desktop_surface);
if (new_desktop_surface)
new_title = weston_desktop_surface_get_title(new_desktop_surface);

shell_rdp_debug_verbose(shell, "%s: moving focus from %p:%s to %p:%s\n", __func__,
old_focused_surface, old_title, new_focused_surface, new_title);
}

if (seat->focused_surface) {
struct shell_surface *shsurf = get_shell_surface(seat->focused_surface);
if (old_focused_surface) {
struct shell_surface *shsurf = get_shell_surface(old_focused_surface);
if (shsurf)
shell_surface_lose_keyboard_focus(shsurf);
}

seat->focused_surface = weston_surface_get_main_surface(keyboard->focus);
seat->focused_surface = new_focused_surface;

if (seat->focused_surface) {
struct shell_surface *shsurf = get_shell_surface(seat->focused_surface);
if (new_focused_surface) {
struct shell_surface *shsurf = get_shell_surface(new_focused_surface);
if (shsurf)
shell_surface_gain_keyboard_focus(shsurf);
}

if (new_focused_surface == shell->focus_proxy_surface) {
/* When new focused window is focus proxy window, client side window is
taking focus and server side window is losing focus, thus let keyboard
to clear out currently pressed keys. This is because once server side
window is gone from client desktop, the client no longer sends keyboard
inputs including key release, thus if any keys are currently at pressed
state, it doesn't recieve release for those keys from RDP client. */
while (keyboard->keys.size) {
struct timespec time;
uint32_t *k = keyboard->keys.data;
weston_compositor_get_time(&time);
notify_key(seat->seat, &time, *k,
WL_KEYBOARD_KEY_STATE_RELEASED, STATE_UPDATE_AUTOMATIC);
/* shell_rdp_debug_verbose(shell, "%s: released key:0x%x\n", __func__, *k); */
}
}
}

/* The surface will be inserted into the list immediately after the link
Expand Down Expand Up @@ -1935,7 +1978,7 @@ shell_seat_caps_changed(struct wl_listener *listener, void *data)
}

static struct shell_seat *
create_shell_seat(struct weston_seat *seat)
create_shell_seat(struct desktop_shell *shell, struct weston_seat *seat)
{
struct shell_seat *shseat;

Expand All @@ -1946,6 +1989,7 @@ create_shell_seat(struct weston_seat *seat)
}

shseat->seat = seat;
shseat->shell = shell;

shseat->seat_destroy_listener.notify = destroy_shell_seat;
wl_signal_add(&seat->destroy_signal,
Expand Down Expand Up @@ -3740,7 +3784,26 @@ desktop_shell_set_focus_proxy(struct wl_client *client,
struct wl_resource *surface_resource)
{
struct desktop_shell *shell = wl_resource_get_user_data(resource);
shell->focus_proxy_surface = wl_resource_get_user_data(surface_resource);
struct weston_surface *surface;
struct shell_surface *shsurf;

surface = wl_resource_get_user_data(surface_resource);
if (!surface) {
shell_rdp_debug(shell, "%s: surface is NULL\n", __func__);
return;
}

shsurf = get_shell_surface(surface);
if (!shsurf) {
shell_rdp_debug(shell, "%s: surface:%p is not shell surface\n", __func__, surface);
return;
}

shell->focus_proxy_surface = surface;

/* Update the surface’s layer. This brings it to the top of the stacking
* order as appropriate. */
shell_surface_update_layer(shsurf);
}

static const struct weston_rdprail_shell_interface rdprail_shell_implementation = {
Expand Down Expand Up @@ -4074,8 +4137,12 @@ static void
handle_seat_created(struct wl_listener *listener, void *data)
{
struct weston_seat *seat = data;
struct desktop_shell *shell;

shell = container_of(listener, struct desktop_shell,
seat_create_listener);

create_shell_seat(seat);
create_shell_seat(shell, seat);
}

struct shell_workarea_change {
Expand Down Expand Up @@ -4114,7 +4181,8 @@ shell_reposition_view_on_workarea_change(struct weston_view *view, void *data)
but if it does, the server has no way to tell where it goes, thus here forcing
backend to resend window state to client, this force window state, especially
window position keeps in sync between server and client. */
rail_state->forceUpdateWindowState = true;
if (rail_state)
rail_state->forceUpdateWindowState = true;

/* If view's upper-left is within 10% of bottom-right of workarea boundary, adjust the position. */
int new_workarea_width = (int)workarea_change->new_workarea.width;
Expand Down