[gnome-remote-desktop] session-rdp: Add handling for the PAUSE key (XKB_KEY_Pause)



commit 33b296b789d39f3748668af5b92720bee8d2eb48
Author: Pascal Nowack <Pascal Nowack gmx de>
Date:   Mon Feb 15 01:10:01 2021 +0100

    session-rdp: Add handling for the PAUSE key (XKB_KEY_Pause)
    
    Unlike other key events, the PAUSE key is not submitted as a keycode.
    Instead RDP uses a special sequence of the CTRL and Numlock key to
    emit the key:
    
    1. CTRL-key DOWN (in combination with the KBD_FLAGS_EXTENDED1 flag)
    2. Numlock-key DOWN
    3. CTRL-key UP (in combination with the KBD_FLAGS_EXTENDED1 flag)
    4. Numlock-key UP
    
    When this sequence is received, emit a PAUSE-key down and a PAUSE-key
    release event, as RDP only emits this sequence when the PAUSE-key is
    pressed.
    When the PAUSE-key is released on the client side, the RDP client won't
    notify the server about it, so the PAUSE-key must be released by
    gnome-remote-desktop upon sending the key-down event.

 src/grd-session-rdp.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)
---
diff --git a/src/grd-session-rdp.c b/src/grd-session-rdp.c
index 7447aaa..fef9345 100644
--- a/src/grd-session-rdp.c
+++ b/src/grd-session-rdp.c
@@ -53,6 +53,14 @@ typedef enum _PointerType
   POINTER_TYPE_NORMAL  = 1 << 1,
 } PointerType;
 
+typedef enum _PauseKeyState
+{
+  PAUSE_KEY_STATE_NONE,
+  PAUSE_KEY_STATE_CTRL_DOWN,
+  PAUSE_KEY_STATE_NUMLOCK_DOWN,
+  PAUSE_KEY_STATE_CTRL_UP,
+} PauseKeyState;
+
 typedef struct _Pointer
 {
   uint8_t *bitmap;
@@ -87,6 +95,7 @@ struct _GrdSessionRdp
 
   GHashTable *pressed_keys;
   GHashTable *pressed_unicode_keys;
+  PauseKeyState pause_key_state;
 
   GrdRdpEventQueue *rdp_event_queue;
 
@@ -1249,6 +1258,62 @@ rdp_input_extended_mouse_event (rdpInput *rdp_input,
   return TRUE;
 }
 
+static gboolean
+is_pause_key_sequence (GrdSessionRdp *session_rdp,
+                       uint16_t       vkcode,
+                       uint16_t       flags)
+{
+  GrdRdpEventQueue *rdp_event_queue = session_rdp->rdp_event_queue;
+
+  switch (session_rdp->pause_key_state)
+    {
+    case PAUSE_KEY_STATE_NONE:
+      if (vkcode == VK_LCONTROL &&
+          flags & KBD_FLAGS_DOWN &&
+          flags & KBD_FLAGS_EXTENDED1)
+        {
+          session_rdp->pause_key_state = PAUSE_KEY_STATE_CTRL_DOWN;
+          return TRUE;
+        }
+      return FALSE;
+    case PAUSE_KEY_STATE_CTRL_DOWN:
+      if (vkcode == VK_NUMLOCK &&
+          flags & KBD_FLAGS_DOWN)
+        {
+          session_rdp->pause_key_state = PAUSE_KEY_STATE_NUMLOCK_DOWN;
+          return TRUE;
+        }
+      break;
+    case PAUSE_KEY_STATE_NUMLOCK_DOWN:
+      if (vkcode == VK_LCONTROL &&
+          !(flags & KBD_FLAGS_DOWN) &&
+          flags & KBD_FLAGS_EXTENDED1)
+        {
+          session_rdp->pause_key_state = PAUSE_KEY_STATE_CTRL_UP;
+          return TRUE;
+        }
+      break;
+    case PAUSE_KEY_STATE_CTRL_UP:
+      if (vkcode == VK_NUMLOCK &&
+          !(flags & KBD_FLAGS_DOWN))
+        {
+          session_rdp->pause_key_state = PAUSE_KEY_STATE_NONE;
+          grd_rdp_event_queue_add_input_event_keyboard_keysym (
+            rdp_event_queue, XKB_KEY_Pause, GRD_KEY_STATE_PRESSED);
+          grd_rdp_event_queue_add_input_event_keyboard_keysym (
+            rdp_event_queue, XKB_KEY_Pause, GRD_KEY_STATE_RELEASED);
+
+          return TRUE;
+        }
+      break;
+    }
+
+  g_warning ("Received invalid pause key sequence");
+  session_rdp->pause_key_state = PAUSE_KEY_STATE_NONE;
+
+  return FALSE;
+}
+
 static BOOL
 rdp_input_keyboard_event (rdpInput *rdp_input,
                           uint16_t  flags,
@@ -1278,6 +1343,9 @@ rdp_input_keyboard_event (rdpInput *rdp_input,
   key_state = flags & KBD_FLAGS_DOWN ? GRD_KEY_STATE_PRESSED
                                      : GRD_KEY_STATE_RELEASED;
 
+  if (is_pause_key_sequence (session_rdp, vkcode, flags))
+    return TRUE;
+
   if (flags & KBD_FLAGS_DOWN)
     {
       if (!g_hash_table_add (session_rdp->pressed_keys,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]