diff --git a/client/X11/xf_event.c b/client/X11/xf_event.c index 02c7690bf..4514fb9ae 100644 --- a/client/X11/xf_event.c +++ b/client/X11/xf_event.c @@ -496,6 +496,8 @@ static BOOL xf_event_KeyPress(xfContext* xfc, XEvent* event, BOOL app) static BOOL xf_event_KeyRelease(xfContext* xfc, XEvent* event, BOOL app) { XEvent nextEvent; + KeySym keysym; + char str[256]; if (XPending(xfc->display)) { @@ -509,7 +511,8 @@ static BOOL xf_event_KeyRelease(xfContext* xfc, XEvent* event, BOOL app) } } - xf_keyboard_key_release(xfc, event->xkey.keycode); + XLookupString((XKeyEvent*) event, str, sizeof(str), &keysym, NULL); + xf_keyboard_key_release(xfc, event->xkey.keycode, keysym); return TRUE; } diff --git a/client/X11/xf_keyboard.c b/client/X11/xf_keyboard.c index 2cdcc93dc..8e08b7194 100644 --- a/client/X11/xf_keyboard.c +++ b/client/X11/xf_keyboard.c @@ -43,6 +43,9 @@ #include #define TAG CLIENT_TAG("x11") +static BOOL firstPressRightCtrl = TRUE; +static BOOL ungrabKeyboardWithRightCtrl = TRUE; + BOOL xf_keyboard_action_script_init(xfContext* xfc) { FILE* keyScript; @@ -160,12 +163,15 @@ void xf_keyboard_key_press(xfContext* xfc, BYTE keycode, KeySym keysym) xf_keyboard_send_key(xfc, TRUE, keycode); } -void xf_keyboard_key_release(xfContext* xfc, BYTE keycode) +void xf_keyboard_key_release(xfContext* xfc, BYTE keycode, KeySym keysym) { if (keycode < 8) return; xfc->KeyboardState[keycode] = FALSE; + + xf_keyboard_handle_special_keys_release(xfc, keysym); + xf_keyboard_send_key(xfc, FALSE, keycode); } @@ -458,6 +464,24 @@ BOOL xf_keyboard_handle_special_keys(xfContext* xfc, KeySym keysym) XF_MODIFIER_KEYS mod = { 0 }; xk_keyboard_get_modifier_keys(xfc, &mod); + // remember state of RightCtrl to ungrab keyboard if next action is release of RightCtrl + // do not return anything such that the key could be used by client if ungrab is not the goal + if (keysym == XK_Control_R) + { + if (mod.RightCtrl && firstPressRightCtrl) + { + // Right Ctrl is pressed, getting ready to ungrab + ungrabKeyboardWithRightCtrl = TRUE; + firstPressRightCtrl = FALSE; + } + } + else + { + // some other key has been pressed, abort ungrabbing + if (ungrabKeyboardWithRightCtrl) + ungrabKeyboardWithRightCtrl = FALSE; + } + if (!xf_keyboard_execute_action_script(xfc, &mod, keysym)) { return TRUE; @@ -485,17 +509,6 @@ BOOL xf_keyboard_handle_special_keys(xfContext* xfc, KeySym keysym) return TRUE; } } - - // Ungrab keyboard - if (mod.RightCtrl) - { - if (!xfc->fullscreen) - { - xf_toggle_control(xfc); - } - XUngrabKeyboard(xfc->display, CurrentTime); - return TRUE; - } #if 0 /* set to 1 to enable multi touch gesture simulation via keyboard */ #ifdef WITH_XRENDER @@ -578,6 +591,33 @@ BOOL xf_keyboard_handle_special_keys(xfContext* xfc, KeySym keysym) return FALSE; } +void xf_keyboard_handle_special_keys_release(xfContext* xfc, KeySym keysym) +{ + if (keysym != XK_Control_R) + return; + + firstPressRightCtrl = TRUE; + + if (!ungrabKeyboardWithRightCtrl) + return; + + // all requirements for ungrab are fulfilled, ungrabbing now + XF_MODIFIER_KEYS mod = { 0 }; + xk_keyboard_get_modifier_keys(xfc, &mod); + + if (!mod.RightCtrl) + { + if (!xfc->fullscreen) + { + xf_toggle_control(xfc); + } + XUngrabKeyboard(xfc->display, CurrentTime); + } + + // ungrabbed + ungrabKeyboardWithRightCtrl = FALSE; +} + BOOL xf_keyboard_set_indicators(rdpContext* context, UINT16 led_flags) { xfContext* xfc = (xfContext*) context; diff --git a/client/X11/xf_keyboard.h b/client/X11/xf_keyboard.h index 606fdcff9..4392dc6bb 100644 --- a/client/X11/xf_keyboard.h +++ b/client/X11/xf_keyboard.h @@ -48,7 +48,7 @@ BOOL xf_keyboard_init(xfContext* xfc); void xf_keyboard_free(xfContext* xfc); void xf_keyboard_clear(xfContext* xfc); void xf_keyboard_key_press(xfContext* xfc, BYTE keycode, KeySym keysym); -void xf_keyboard_key_release(xfContext* xfc, BYTE keycode); +void xf_keyboard_key_release(xfContext* xfc, BYTE keycode, KeySym keysym); void xf_keyboard_release_all_keypress(xfContext* xfc); BOOL xf_keyboard_key_pressed(xfContext* xfc, KeySym keysym); void xf_keyboard_send_key(xfContext* xfc, BOOL down, BYTE keycode); @@ -57,6 +57,7 @@ BOOL xf_keyboard_get_key_state(xfContext* xfc, int state, int keysym); UINT32 xf_keyboard_get_toggle_keys_state(xfContext* xfc); void xf_keyboard_focus_in(xfContext* xfc); BOOL xf_keyboard_handle_special_keys(xfContext* xfc, KeySym keysym); +void xf_keyboard_handle_special_keys_release(xfContext* xfc, KeySym keysym); BOOL xf_keyboard_set_indicators(rdpContext* context, UINT16 led_flags); #endif /* __XF_KEYBOARD_H */