GUACAMOLE-51: Merge lock state synchronziation change for RDP.
This commit is contained in:
commit
2a0d2445c1
@ -31,6 +31,46 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translates the given keysym into the corresponding lock flag, as would be
|
||||||
|
* required by the RDP synchronize event. If the given keysym does not
|
||||||
|
* represent a lock key, zero is returned.
|
||||||
|
*
|
||||||
|
* @param keysym
|
||||||
|
* The keysym to translate into a RDP lock flag.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* The RDP lock flag which corresponds to the given keysym, or zero if the
|
||||||
|
* given keysym does not represent a lock key.
|
||||||
|
*/
|
||||||
|
static int guac_rdp_keyboard_lock_flag(int keysym) {
|
||||||
|
|
||||||
|
/* Translate keysym into corresponding lock flag */
|
||||||
|
switch (keysym) {
|
||||||
|
|
||||||
|
/* Scroll lock */
|
||||||
|
case 0xFF14:
|
||||||
|
return KBD_SYNC_SCROLL_LOCK;
|
||||||
|
|
||||||
|
/* Kana lock */
|
||||||
|
case 0xFF2D:
|
||||||
|
return KBD_SYNC_KANA_LOCK;
|
||||||
|
|
||||||
|
/* Num lock */
|
||||||
|
case 0xFF7F:
|
||||||
|
return KBD_SYNC_NUM_LOCK;
|
||||||
|
|
||||||
|
/* Caps lock */
|
||||||
|
case 0xFFE5:
|
||||||
|
return KBD_SYNC_CAPS_LOCK;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not a lock key */
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Immediately sends an RDP key event having the given scancode and flags.
|
* Immediately sends an RDP key event having the given scancode and flags.
|
||||||
*
|
*
|
||||||
@ -113,6 +153,39 @@ static void guac_rdp_send_unicode_event(guac_rdp_client* rdp_client,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Immediately sends an RDP synchonize event having the given flags. An RDP
|
||||||
|
* synchronize event sets the state of remote lock keys absolutely, where a
|
||||||
|
* lock key will be active only if its corresponding flag is set in the event.
|
||||||
|
*
|
||||||
|
* @param rdp_client
|
||||||
|
* The RDP client instance associated with the RDP session along which the
|
||||||
|
* synchronize event should be sent.
|
||||||
|
*
|
||||||
|
* @param flags
|
||||||
|
* Bitwise OR of the flags representing the lock keys which should be set,
|
||||||
|
* if any, as dictated by the RDP protocol. If no flags are set, then no
|
||||||
|
* lock keys will be active.
|
||||||
|
*/
|
||||||
|
static void guac_rdp_send_synchronize_event(guac_rdp_client* rdp_client,
|
||||||
|
int flags) {
|
||||||
|
|
||||||
|
pthread_mutex_lock(&(rdp_client->rdp_lock));
|
||||||
|
|
||||||
|
/* Skip if not yet connected */
|
||||||
|
freerdp* rdp_inst = rdp_client->rdp_inst;
|
||||||
|
if (rdp_inst == NULL) {
|
||||||
|
pthread_mutex_unlock(&(rdp_client->rdp_lock));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Synchronize lock key states */
|
||||||
|
rdp_inst->input->SynchronizeEvent(rdp_inst->input, flags);
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&(rdp_client->rdp_lock));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads all keysym/scancode mappings declared within the given keymap and its
|
* Loads all keysym/scancode mappings declared within the given keymap and its
|
||||||
* parent keymap, if any. These mappings are stored within the given
|
* parent keymap, if any. These mappings are stored within the given
|
||||||
@ -187,6 +260,11 @@ int guac_rdp_keyboard_send_event(guac_rdp_keyboard* keyboard,
|
|||||||
/* If defined, send event */
|
/* If defined, send event */
|
||||||
if (keysym_desc->scancode != 0) {
|
if (keysym_desc->scancode != 0) {
|
||||||
|
|
||||||
|
/* Update remote lock state as necessary */
|
||||||
|
guac_rdp_keyboard_update_locks(keyboard,
|
||||||
|
keysym_desc->set_locks,
|
||||||
|
keysym_desc->clear_locks);
|
||||||
|
|
||||||
/* If defined, send any prerequesite keys that must be set */
|
/* If defined, send any prerequesite keys that must be set */
|
||||||
if (keysym_desc->set_keysyms != NULL)
|
if (keysym_desc->set_keysyms != NULL)
|
||||||
guac_rdp_keyboard_send_events(keyboard,
|
guac_rdp_keyboard_send_events(keyboard,
|
||||||
@ -270,9 +348,42 @@ void guac_rdp_keyboard_send_events(guac_rdp_keyboard* keyboard,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void guac_rdp_keyboard_update_locks(guac_rdp_keyboard* keyboard,
|
||||||
|
int set_flags, int clear_flags) {
|
||||||
|
|
||||||
|
guac_client* client = keyboard->client;
|
||||||
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
|
|
||||||
|
/* Calculate updated lock flags */
|
||||||
|
int lock_flags = (keyboard->lock_flags | set_flags) & ~clear_flags;
|
||||||
|
|
||||||
|
/* Synchronize remote side only if lock flags have changed */
|
||||||
|
if (lock_flags != keyboard->lock_flags) {
|
||||||
|
guac_rdp_send_synchronize_event(rdp_client, lock_flags);
|
||||||
|
keyboard->lock_flags = lock_flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
|
||||||
|
/* Synchronize lock keys states, if this has not yet been done */
|
||||||
|
if (!keyboard->synchronized) {
|
||||||
|
|
||||||
|
guac_client* client = keyboard->client;
|
||||||
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
|
|
||||||
|
/* Synchronize remote lock key states with local state */
|
||||||
|
guac_rdp_send_synchronize_event(rdp_client, keyboard->lock_flags);
|
||||||
|
keyboard->synchronized = 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Toggle lock flag, if any */
|
||||||
|
if (pressed)
|
||||||
|
keyboard->lock_flags ^= guac_rdp_keyboard_lock_flag(keysym);
|
||||||
|
|
||||||
/* Update keysym state */
|
/* Update keysym state */
|
||||||
if (GUAC_RDP_KEYSYM_STORABLE(keysym))
|
if (GUAC_RDP_KEYSYM_STORABLE(keysym))
|
||||||
GUAC_RDP_KEYSYM_LOOKUP(keyboard->keysym_state, keysym) = pressed;
|
GUAC_RDP_KEYSYM_LOOKUP(keyboard->keysym_state, keysym) = pressed;
|
||||||
|
@ -35,6 +35,19 @@ typedef struct guac_rdp_keyboard {
|
|||||||
*/
|
*/
|
||||||
guac_client* client;
|
guac_client* client;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The local state of all known lock keys, as a bitwise OR of all RDP lock
|
||||||
|
* key flags. Legal flags are KBD_SYNC_SCROLL_LOCK, KBD_SYNC_NUM_LOCK,
|
||||||
|
* KBD_SYNC_CAPS_LOCK, and KBD_SYNC_KANA_LOCK.
|
||||||
|
*/
|
||||||
|
int lock_flags;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the states of remote lock keys (Caps lock, Num lock, etc.) have
|
||||||
|
* been synchronized with local lock key states.
|
||||||
|
*/
|
||||||
|
int synchronized;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The keymap to use when translating keysyms into scancodes or sequences
|
* The keymap to use when translating keysyms into scancodes or sequences
|
||||||
* of scancodes for RDP.
|
* of scancodes for RDP.
|
||||||
@ -127,6 +140,26 @@ int guac_rdp_keyboard_send_event(guac_rdp_keyboard* keyboard,
|
|||||||
void guac_rdp_keyboard_send_events(guac_rdp_keyboard* keyboard,
|
void guac_rdp_keyboard_send_events(guac_rdp_keyboard* keyboard,
|
||||||
const int* keysym_string, int from, int to);
|
const int* keysym_string, int from, int to);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the local state of the lock keys (such as Caps lock or Num lock),
|
||||||
|
* synchronizing the remote state of those keys if it is expected to differ.
|
||||||
|
*
|
||||||
|
* @param keyboard
|
||||||
|
* The guac_rdp_keyboard associated with the current RDP session.
|
||||||
|
*
|
||||||
|
* @param set_flags
|
||||||
|
* The lock key flags which should be set. Legal flags are
|
||||||
|
* KBD_SYNC_SCROLL_LOCK, KBD_SYNC_NUM_LOCK, KBD_SYNC_CAPS_LOCK, and
|
||||||
|
* KBD_SYNC_KANA_LOCK.
|
||||||
|
*
|
||||||
|
* @param clear_flags
|
||||||
|
* The lock key flags which should be cleared. Legal flags are
|
||||||
|
* KBD_SYNC_SCROLL_LOCK, KBD_SYNC_NUM_LOCK, KBD_SYNC_CAPS_LOCK, and
|
||||||
|
* KBD_SYNC_KANA_LOCK.
|
||||||
|
*/
|
||||||
|
void guac_rdp_keyboard_update_locks(guac_rdp_keyboard* keyboard,
|
||||||
|
int set_flags, int clear_flags);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the local state of the given keysym, sending the key events required
|
* Updates the local state of the given keysym, sending the key events required
|
||||||
* to replicate that state remotely (on the RDP server). The key events sent
|
* to replicate that state remotely (on the RDP server). The key events sent
|
||||||
|
@ -44,16 +44,16 @@ map 0x46 ~ 0xff14 # Scroll_Lock
|
|||||||
map +ext 0x3A ~ 0xffe5 # Caps_Lock
|
map +ext 0x3A ~ 0xffe5 # Caps_Lock
|
||||||
|
|
||||||
# Keypad numerals
|
# Keypad numerals
|
||||||
map 0x52 ~ 0xffb0 # KP_0
|
map -shift +num 0x52 ~ 0xffb0 # KP_0
|
||||||
map 0x4F ~ 0xffb1 # KP_1
|
map -shift +num 0x4F ~ 0xffb1 # KP_1
|
||||||
map 0x50 ~ 0xffb2 # KP_2
|
map -shift +num 0x50 ~ 0xffb2 # KP_2
|
||||||
map 0x51 ~ 0xffb3 # KP_3
|
map -shift +num 0x51 ~ 0xffb3 # KP_3
|
||||||
map 0x4B ~ 0xffb4 # KP_4
|
map -shift +num 0x4B ~ 0xffb4 # KP_4
|
||||||
map 0x4C ~ 0xffb5 # KP_5
|
map -shift +num 0x4C ~ 0xffb5 # KP_5
|
||||||
map 0x4D ~ 0xffb6 # KP_6
|
map -shift +num 0x4D ~ 0xffb6 # KP_6
|
||||||
map 0x47 ~ 0xffb7 # KP_7
|
map -shift +num 0x47 ~ 0xffb7 # KP_7
|
||||||
map 0x48 ~ 0xffb8 # KP_8
|
map -shift +num 0x48 ~ 0xffb8 # KP_8
|
||||||
map 0x49 ~ 0xffb9 # KP_9
|
map -shift +num 0x49 ~ 0xffb9 # KP_9
|
||||||
|
|
||||||
# Keypad operators
|
# Keypad operators
|
||||||
map 0x37 ~ 0xffaa # KP_multiply
|
map 0x37 ~ 0xffaa # KP_multiply
|
||||||
|
@ -97,9 +97,11 @@ for my $filename (@ARGV) {
|
|||||||
my $ext_flags = 0;
|
my $ext_flags = 0;
|
||||||
my $set_shift = 0;
|
my $set_shift = 0;
|
||||||
my $set_altgr = 0;
|
my $set_altgr = 0;
|
||||||
|
my $set_num = 0;
|
||||||
|
|
||||||
my $clear_shift = 0;
|
my $clear_shift = 0;
|
||||||
my $clear_altgr = 0;
|
my $clear_altgr = 0;
|
||||||
|
my $clear_num = 0;
|
||||||
|
|
||||||
# Parse ranges and options
|
# Parse ranges and options
|
||||||
foreach $_ (split(/\s+/, $range)) {
|
foreach $_ (split(/\s+/, $range)) {
|
||||||
@ -108,6 +110,7 @@ for my $filename (@ARGV) {
|
|||||||
if ((my $opt) = m/^\+([a-z]+)$/) {
|
if ((my $opt) = m/^\+([a-z]+)$/) {
|
||||||
if ($opt eq "shift") { $set_shift = 1; }
|
if ($opt eq "shift") { $set_shift = 1; }
|
||||||
elsif ($opt eq "altgr") { $set_altgr = 1; }
|
elsif ($opt eq "altgr") { $set_altgr = 1; }
|
||||||
|
elsif ($opt eq "num") { $set_num = 1; }
|
||||||
elsif ($opt eq "ext") { $ext_flags = 1; }
|
elsif ($opt eq "ext") { $ext_flags = 1; }
|
||||||
else {
|
else {
|
||||||
die "$filename: $.: ERROR: "
|
die "$filename: $.: ERROR: "
|
||||||
@ -119,6 +122,7 @@ for my $filename (@ARGV) {
|
|||||||
elsif ((my $opt) = m/^-([a-z]+)$/) {
|
elsif ((my $opt) = m/^-([a-z]+)$/) {
|
||||||
if ($opt eq "shift") { $clear_shift = 1; }
|
if ($opt eq "shift") { $clear_shift = 1; }
|
||||||
elsif ($opt eq "altgr") { $clear_altgr = 1; }
|
elsif ($opt eq "altgr") { $clear_altgr = 1; }
|
||||||
|
elsif ($opt eq "num") { $clear_num = 1; }
|
||||||
else {
|
else {
|
||||||
die "$filename: $.: ERROR: "
|
die "$filename: $.: ERROR: "
|
||||||
. "Invalid clear option\n";
|
. "Invalid clear option\n";
|
||||||
@ -198,6 +202,16 @@ for my $filename (@ARGV) {
|
|||||||
$content .= ", .clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR";
|
$content .= ", .clear_keysyms = GUAC_KEYSYMS_ALL_SHIFT_ALTGR";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Set locks
|
||||||
|
if ($set_num) {
|
||||||
|
$content .= ", .set_locks = KBD_SYNC_NUM_LOCK";
|
||||||
|
}
|
||||||
|
|
||||||
|
# Clear locks
|
||||||
|
if ($clear_num) {
|
||||||
|
$content .= ", .clear_locks = KBD_SYNC_NUM_LOCK";
|
||||||
|
}
|
||||||
|
|
||||||
# Flags
|
# Flags
|
||||||
if ($ext_flags) {
|
if ($ext_flags) {
|
||||||
$content .= ", .flags = KBD_FLAGS_EXTENDED";
|
$content .= ", .flags = KBD_FLAGS_EXTENDED";
|
||||||
|
@ -62,6 +62,22 @@ typedef struct guac_rdp_keysym_desc {
|
|||||||
*/
|
*/
|
||||||
const int* clear_keysyms;
|
const int* clear_keysyms;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bitwise OR of the flags of all lock keys (ie: Caps lock, Num lock, etc.)
|
||||||
|
* which must be active for this keysym to be properly typed. Legal flags
|
||||||
|
* are KBD_SYNC_SCROLL_LOCK, KBD_SYNC_NUM_LOCK, KBD_SYNC_CAPS_LOCK, and
|
||||||
|
* KBD_SYNC_KANA_LOCK.
|
||||||
|
*/
|
||||||
|
int set_locks;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bitwise OR of the flags of all lock keys (ie: Caps lock, Num lock, etc.)
|
||||||
|
* which must be inactive for this keysym to be properly typed. Legal flags
|
||||||
|
* are KBD_SYNC_SCROLL_LOCK, KBD_SYNC_NUM_LOCK, KBD_SYNC_CAPS_LOCK, and
|
||||||
|
* KBD_SYNC_KANA_LOCK.
|
||||||
|
*/
|
||||||
|
int clear_locks;
|
||||||
|
|
||||||
} guac_rdp_keysym_desc;
|
} guac_rdp_keysym_desc;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user