GUACAMOLE-518: Automatically release any automatically-pressed keys after user has released all keys on the client side.
This commit is contained in:
parent
cb6ffd06e6
commit
48b3d5038f
@ -162,12 +162,12 @@ int guac_rdp_decompose_keysym(guac_rdp_keyboard* keyboard, int keysym) {
|
||||
return 1;
|
||||
|
||||
/* Press dead key */
|
||||
guac_rdp_keyboard_update_keysym(keyboard, key->dead_keysym, 1);
|
||||
guac_rdp_keyboard_update_keysym(keyboard, key->dead_keysym, 0);
|
||||
guac_rdp_keyboard_update_keysym(keyboard, key->dead_keysym, 1, GUAC_RDP_KEY_SOURCE_SYNTHETIC);
|
||||
guac_rdp_keyboard_update_keysym(keyboard, key->dead_keysym, 0, GUAC_RDP_KEY_SOURCE_SYNTHETIC);
|
||||
|
||||
/* Press base key */
|
||||
guac_rdp_keyboard_update_keysym(keyboard, key->base_keysym, 1);
|
||||
guac_rdp_keyboard_update_keysym(keyboard, key->base_keysym, 0);
|
||||
guac_rdp_keyboard_update_keysym(keyboard, key->base_keysym, 1, GUAC_RDP_KEY_SOURCE_SYNTHETIC);
|
||||
guac_rdp_keyboard_update_keysym(keyboard, key->base_keysym, 0, GUAC_RDP_KEY_SOURCE_SYNTHETIC);
|
||||
|
||||
/* Decomposed key successfully typed */
|
||||
return 0;
|
||||
|
@ -141,7 +141,7 @@ int guac_rdp_user_key_handler(guac_user* user, int keysym, int pressed) {
|
||||
|
||||
/* Update keysym state */
|
||||
retval = guac_rdp_keyboard_update_keysym(rdp_client->keyboard,
|
||||
keysym, pressed);
|
||||
keysym, pressed, GUAC_RDP_KEY_SOURCE_CLIENT);
|
||||
|
||||
complete:
|
||||
pthread_rwlock_unlock(&(rdp_client->lock));
|
||||
|
@ -607,25 +607,25 @@ void guac_rdp_keyboard_update_modifiers(guac_rdp_keyboard* keyboard,
|
||||
|
||||
/* Press/release Shift as needed */
|
||||
if (set_flags & GUAC_RDP_KEYMAP_MODIFIER_SHIFT) {
|
||||
guac_rdp_keyboard_update_keysym(keyboard, 0xFFE1, 1);
|
||||
guac_rdp_keyboard_update_keysym(keyboard, 0xFFE1, 1, GUAC_RDP_KEY_SOURCE_SYNTHETIC);
|
||||
}
|
||||
else if (clear_flags & GUAC_RDP_KEYMAP_MODIFIER_SHIFT) {
|
||||
guac_rdp_keyboard_update_keysym(keyboard, 0xFFE1, 0);
|
||||
guac_rdp_keyboard_update_keysym(keyboard, 0xFFE2, 0);
|
||||
guac_rdp_keyboard_update_keysym(keyboard, 0xFFE1, 0, GUAC_RDP_KEY_SOURCE_SYNTHETIC);
|
||||
guac_rdp_keyboard_update_keysym(keyboard, 0xFFE2, 0, GUAC_RDP_KEY_SOURCE_SYNTHETIC);
|
||||
}
|
||||
|
||||
/* Press/release AltGr as needed */
|
||||
if (set_flags & GUAC_RDP_KEYMAP_MODIFIER_ALTGR) {
|
||||
guac_rdp_keyboard_update_keysym(keyboard, 0xFE03, 1);
|
||||
guac_rdp_keyboard_update_keysym(keyboard, 0xFE03, 1, GUAC_RDP_KEY_SOURCE_SYNTHETIC);
|
||||
}
|
||||
else if (clear_flags & GUAC_RDP_KEYMAP_MODIFIER_ALTGR) {
|
||||
guac_rdp_keyboard_update_keysym(keyboard, 0xFE03, 0);
|
||||
guac_rdp_keyboard_update_keysym(keyboard, 0xFE03, 0, GUAC_RDP_KEY_SOURCE_SYNTHETIC);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int guac_rdp_keyboard_update_keysym(guac_rdp_keyboard* keyboard,
|
||||
int keysym, int pressed) {
|
||||
int keysym, int pressed, guac_rdp_key_source source) {
|
||||
|
||||
/* Synchronize lock keys states, if this has not yet been done */
|
||||
if (!keyboard->synchronized) {
|
||||
@ -673,7 +673,39 @@ int guac_rdp_keyboard_update_keysym(guac_rdp_keyboard* keyboard,
|
||||
guac_rdp_keyboard_send_missing_key(keyboard, keysym);
|
||||
}
|
||||
|
||||
if (source == GUAC_RDP_KEY_SOURCE_CLIENT) {
|
||||
|
||||
/* Update tracking of client-side keyboard state but only for keys
|
||||
* which are tracked server-side, as well (to ensure that the key count
|
||||
* remains correct, even if a user sends extra unbalanced or excessive
|
||||
* press and release events) */
|
||||
if (key != NULL) {
|
||||
if (pressed)
|
||||
keyboard->user_pressed_keys++;
|
||||
else
|
||||
keyboard->user_pressed_keys--;
|
||||
}
|
||||
|
||||
/* Reset RDP server keyboard state (releasing any automatically pressed
|
||||
* keys) once all keys have been released on the client side */
|
||||
if (keyboard->user_pressed_keys == 0)
|
||||
guac_rdp_keyboard_reset(keyboard);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void guac_rdp_keyboard_reset(guac_rdp_keyboard* keyboard) {
|
||||
|
||||
/* Release all pressed keys */
|
||||
for (int i = 0; i < keyboard->num_keys; i++) {
|
||||
guac_rdp_key* key = &keyboard->keys[i];
|
||||
if (key->pressed != NULL)
|
||||
guac_rdp_keyboard_update_keysym(keyboard, key->pressed->keysym, 0,
|
||||
GUAC_RDP_KEY_SOURCE_SYNTHETIC);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,24 @@
|
||||
*/
|
||||
#define GUAC_RDP_KEY_MAX_DEFINITIONS 4
|
||||
|
||||
/**
|
||||
* All possible sources of RDP key events tracked by guac_rdp_keyboard.
|
||||
*/
|
||||
typedef enum guac_rdp_key_source {
|
||||
|
||||
/**
|
||||
* The key event was received directly from the Guacamole client via a
|
||||
* "key" instruction.
|
||||
*/
|
||||
GUAC_RDP_KEY_SOURCE_CLIENT = 0,
|
||||
|
||||
/**
|
||||
* The key event is being synthesized internally within the RDP support.
|
||||
*/
|
||||
GUAC_RDP_KEY_SOURCE_SYNTHETIC = 1
|
||||
|
||||
} guac_rdp_key_source;
|
||||
|
||||
/**
|
||||
* A representation of a single key within the overall local keyboard,
|
||||
* including the definition of that key within the RDP server's keymap and
|
||||
@ -130,6 +148,14 @@ typedef struct guac_rdp_keyboard {
|
||||
*/
|
||||
guac_rdp_key* keys_by_keysym[0x20000];
|
||||
|
||||
/**
|
||||
* The total number of keys that the user of the connection is currently
|
||||
* holding down. This value indicates only the client-side keyboard state.
|
||||
* It DOES NOT indicate the number of keys currently pressed within the RDP
|
||||
* server.
|
||||
*/
|
||||
int user_pressed_keys;
|
||||
|
||||
} guac_rdp_keyboard;
|
||||
|
||||
/**
|
||||
@ -234,11 +260,24 @@ void guac_rdp_keyboard_update_modifiers(guac_rdp_keyboard* keyboard,
|
||||
* @param pressed
|
||||
* Zero if the keysym is being released, non-zero otherwise.
|
||||
*
|
||||
* @param source
|
||||
* The source of the key event represented by this call to
|
||||
* guac_rdp_keyboard_update_keysym().
|
||||
*
|
||||
* @return
|
||||
* Zero if the keys were successfully sent, non-zero otherwise.
|
||||
*/
|
||||
int guac_rdp_keyboard_update_keysym(guac_rdp_keyboard* keyboard,
|
||||
int keysym, int pressed);
|
||||
int keysym, int pressed, guac_rdp_key_source source);
|
||||
|
||||
/**
|
||||
* Releases all currently pressed keys, sending key release events to the RDP
|
||||
* server as necessary. Lock states (Caps Lock, etc.) are not affected.
|
||||
*
|
||||
* @param keyboard
|
||||
* The guac_rdp_keyboard associated with the current RDP session.
|
||||
*/
|
||||
void guac_rdp_keyboard_reset(guac_rdp_keyboard* keyboard);
|
||||
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user