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;
|
return 1;
|
||||||
|
|
||||||
/* Press dead key */
|
/* Press dead key */
|
||||||
guac_rdp_keyboard_update_keysym(keyboard, key->dead_keysym, 1);
|
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_keyboard_update_keysym(keyboard, key->dead_keysym, 0, GUAC_RDP_KEY_SOURCE_SYNTHETIC);
|
||||||
|
|
||||||
/* Press base key */
|
/* Press base key */
|
||||||
guac_rdp_keyboard_update_keysym(keyboard, key->base_keysym, 1);
|
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_keyboard_update_keysym(keyboard, key->base_keysym, 0, GUAC_RDP_KEY_SOURCE_SYNTHETIC);
|
||||||
|
|
||||||
/* Decomposed key successfully typed */
|
/* Decomposed key successfully typed */
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -141,7 +141,7 @@ int guac_rdp_user_key_handler(guac_user* user, int keysym, int pressed) {
|
|||||||
|
|
||||||
/* Update keysym state */
|
/* Update keysym state */
|
||||||
retval = guac_rdp_keyboard_update_keysym(rdp_client->keyboard,
|
retval = guac_rdp_keyboard_update_keysym(rdp_client->keyboard,
|
||||||
keysym, pressed);
|
keysym, pressed, GUAC_RDP_KEY_SOURCE_CLIENT);
|
||||||
|
|
||||||
complete:
|
complete:
|
||||||
pthread_rwlock_unlock(&(rdp_client->lock));
|
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 */
|
/* Press/release Shift as needed */
|
||||||
if (set_flags & GUAC_RDP_KEYMAP_MODIFIER_SHIFT) {
|
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) {
|
else if (clear_flags & GUAC_RDP_KEYMAP_MODIFIER_SHIFT) {
|
||||||
guac_rdp_keyboard_update_keysym(keyboard, 0xFFE1, 0);
|
guac_rdp_keyboard_update_keysym(keyboard, 0xFFE1, 0, GUAC_RDP_KEY_SOURCE_SYNTHETIC);
|
||||||
guac_rdp_keyboard_update_keysym(keyboard, 0xFFE2, 0);
|
guac_rdp_keyboard_update_keysym(keyboard, 0xFFE2, 0, GUAC_RDP_KEY_SOURCE_SYNTHETIC);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Press/release AltGr as needed */
|
/* Press/release AltGr as needed */
|
||||||
if (set_flags & GUAC_RDP_KEYMAP_MODIFIER_ALTGR) {
|
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) {
|
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 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 */
|
/* Synchronize lock keys states, if this has not yet been done */
|
||||||
if (!keyboard->synchronized) {
|
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);
|
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;
|
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
|
#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,
|
* A representation of a single key within the overall local keyboard,
|
||||||
* including the definition of that key within the RDP server's keymap and
|
* 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];
|
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;
|
} guac_rdp_keyboard;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -234,11 +260,24 @@ void guac_rdp_keyboard_update_modifiers(guac_rdp_keyboard* keyboard,
|
|||||||
* @param pressed
|
* @param pressed
|
||||||
* Zero if the keysym is being released, non-zero otherwise.
|
* 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
|
* @return
|
||||||
* Zero if the keys were successfully sent, non-zero otherwise.
|
* Zero if the keys were successfully sent, non-zero otherwise.
|
||||||
*/
|
*/
|
||||||
int guac_rdp_keyboard_update_keysym(guac_rdp_keyboard* keyboard,
|
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
|
#endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user