[gnome-remote-desktop] rdp-event-queue: Add API methods for kbd lock state synchronization
- From: Jonas Ådahl <jadahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-remote-desktop] rdp-event-queue: Add API methods for kbd lock state synchronization
- Date: Thu, 4 Mar 2021 18:03:17 +0000 (UTC)
commit 36c3e086510344a6fdf578b373e61e3606b9dd29
Author: Pascal Nowack <Pascal Nowack gmx de>
Date: Tue Feb 23 15:03:17 2021 +0100
rdp-event-queue: Add API methods for kbd lock state synchronization
In order to be able to handle keyboard lock states correctly, add API
methods to push a synchronization event or to synchronize mutters
current lock states with the states saved in gnome-remote-desktop.
When pushing a synchronization event, replace the old existing
synchronization event, as every synchronization event contains all new
wanted keyboard lock states, so only the last pushed one is necessary
to handle.
After pushing the synchronization event, queue a flush.
Additionally, when processing all queued events, only handle the
synchronization event, when mutter notified gnome-remote-desktop about
the changed lock states before.
This is necessary, since otherwise race conditions can happen.
For example, gnome-remote-desktop would toggle a lock key again,
although the tracked lock state in gnome-remote-desktop doesn't match
the one in mutter and therefore toggling the lock key again will lead
to the unwanted lock state.
When such situation happens, don't handle the synchronization event.
Instead, queue a flush, when all lock states have been updated in
gnome-remote-desktop.
src/grd-rdp-event-queue.c | 117 +++++++++++++++++++++++++++++++++++++++++++---
src/grd-rdp-event-queue.h | 10 ++++
2 files changed, 121 insertions(+), 6 deletions(-)
---
diff --git a/src/grd-rdp-event-queue.c b/src/grd-rdp-event-queue.c
index b3fb18b..cd03bbf 100644
--- a/src/grd-rdp-event-queue.c
+++ b/src/grd-rdp-event-queue.c
@@ -21,6 +21,8 @@
#include "grd-rdp-event-queue.h"
+#include <xkbcommon/xkbcommon-keysyms.h>
+
typedef enum _RdpEventType
{
RDP_EVENT_TYPE_NONE,
@@ -72,6 +74,12 @@ typedef struct _RdpEvent
} input_ptr_axis;
} RdpEvent;
+typedef struct _RdpSynchronizationEvent
+{
+ gboolean caps_lock_state;
+ gboolean num_lock_state;
+} RdpSynchronizationEvent;
+
struct _GrdRdpEventQueue
{
GObject parent;
@@ -79,8 +87,14 @@ struct _GrdRdpEventQueue
GrdSessionRdp *session_rdp;
GSource *flush_source;
- GMutex queue_mutex;
+ GMutex event_mutex;
GQueue *queue;
+ RdpSynchronizationEvent *rdp_sync_event;
+
+ gboolean pending_sync_caps_lock;
+ gboolean pending_sync_num_lock;
+ gboolean caps_lock_state;
+ gboolean num_lock_state;
};
G_DEFINE_TYPE (GrdRdpEventQueue, grd_rdp_event_queue, G_TYPE_OBJECT);
@@ -89,9 +103,9 @@ static void
queue_rdp_event (GrdRdpEventQueue *rdp_event_queue,
RdpEvent *rdp_event)
{
- g_mutex_lock (&rdp_event_queue->queue_mutex);
+ g_mutex_lock (&rdp_event_queue->event_mutex);
g_queue_push_tail (rdp_event_queue->queue, rdp_event);
- g_mutex_unlock (&rdp_event_queue->queue_mutex);
+ g_mutex_unlock (&rdp_event_queue->event_mutex);
g_source_set_ready_time (rdp_event_queue->flush_source, 0);
}
@@ -173,12 +187,98 @@ grd_rdp_event_queue_add_input_event_pointer_axis (GrdRdpEventQueue *rdp_event
queue_rdp_event (rdp_event_queue, rdp_event);
}
+void
+grd_rdp_event_queue_update_caps_lock_state (GrdRdpEventQueue *rdp_event_queue,
+ gboolean caps_lock_state)
+{
+ rdp_event_queue->caps_lock_state = caps_lock_state;
+ rdp_event_queue->pending_sync_caps_lock = FALSE;
+
+ if (rdp_event_queue->pending_sync_num_lock)
+ return;
+
+ g_source_set_ready_time (rdp_event_queue->flush_source, 0);
+}
+
+void
+grd_rdp_event_queue_update_num_lock_state (GrdRdpEventQueue *rdp_event_queue,
+ gboolean num_lock_state)
+{
+ rdp_event_queue->num_lock_state = num_lock_state;
+ rdp_event_queue->pending_sync_num_lock = FALSE;
+
+ if (rdp_event_queue->pending_sync_caps_lock)
+ return;
+
+ g_source_set_ready_time (rdp_event_queue->flush_source, 0);
+}
+
+void
+grd_rdp_event_queue_add_synchronization_event (GrdRdpEventQueue *rdp_event_queue,
+ gboolean caps_lock_state,
+ gboolean num_lock_state)
+{
+ RdpSynchronizationEvent *rdp_sync_event;
+
+ rdp_sync_event = g_malloc0 (sizeof (RdpSynchronizationEvent));
+ rdp_sync_event->caps_lock_state = caps_lock_state;
+ rdp_sync_event->num_lock_state = num_lock_state;
+
+ g_mutex_lock (&rdp_event_queue->event_mutex);
+ g_clear_pointer (&rdp_event_queue->rdp_sync_event, g_free);
+ rdp_event_queue->rdp_sync_event = rdp_sync_event;
+ g_mutex_unlock (&rdp_event_queue->event_mutex);
+
+ g_source_set_ready_time (rdp_event_queue->flush_source, 0);
+}
+
+static void
+handle_synchronization_event (GrdRdpEventQueue *rdp_event_queue)
+{
+ GrdSession *session = GRD_SESSION (rdp_event_queue->session_rdp);
+ RdpSynchronizationEvent *rdp_sync_event;
+
+ rdp_sync_event = g_steal_pointer (&rdp_event_queue->rdp_sync_event);
+
+ if (rdp_sync_event->caps_lock_state != rdp_event_queue->caps_lock_state)
+ {
+ g_debug ("Synchronizing caps lock state to be %s",
+ rdp_sync_event->caps_lock_state ? "locked": "unlocked");
+
+ grd_session_notify_keyboard_keysym (session, XKB_KEY_Caps_Lock,
+ GRD_KEY_STATE_PRESSED);
+ grd_session_notify_keyboard_keysym (session, XKB_KEY_Caps_Lock,
+ GRD_KEY_STATE_RELEASED);
+
+ rdp_event_queue->pending_sync_caps_lock = TRUE;
+ }
+ if (rdp_sync_event->num_lock_state != rdp_event_queue->num_lock_state)
+ {
+ g_debug ("Synchronizing num lock state to be %s",
+ rdp_sync_event->num_lock_state ? "locked": "unlocked");
+
+ grd_session_notify_keyboard_keysym (session, XKB_KEY_Num_Lock,
+ GRD_KEY_STATE_PRESSED);
+ grd_session_notify_keyboard_keysym (session, XKB_KEY_Num_Lock,
+ GRD_KEY_STATE_RELEASED);
+
+ rdp_event_queue->pending_sync_num_lock = TRUE;
+ }
+
+ g_free (rdp_sync_event);
+}
+
static void
process_rdp_events (GrdRdpEventQueue *rdp_event_queue)
{
GrdSession *session = GRD_SESSION (rdp_event_queue->session_rdp);
RdpEvent *rdp_event;
+ if (rdp_event_queue->rdp_sync_event &&
+ !rdp_event_queue->pending_sync_caps_lock &&
+ !rdp_event_queue->pending_sync_num_lock)
+ handle_synchronization_event (rdp_event_queue);
+
while ((rdp_event = g_queue_pop_head (rdp_event_queue->queue)))
{
switch (rdp_event->type)
@@ -222,9 +322,9 @@ flush_rdp_events (gpointer user_data)
{
GrdRdpEventQueue *rdp_event_queue = user_data;
- g_mutex_lock (&rdp_event_queue->queue_mutex);
+ g_mutex_lock (&rdp_event_queue->event_mutex);
process_rdp_events (rdp_event_queue);
- g_mutex_unlock (&rdp_event_queue->queue_mutex);
+ g_mutex_unlock (&rdp_event_queue->event_mutex);
return G_SOURCE_CONTINUE;
}
@@ -279,6 +379,8 @@ grd_rdp_event_queue_dispose (GObject *object)
* Process all events to ensure that remaining keysym-released events are sent
*/
process_rdp_events (rdp_event_queue);
+
+ g_clear_pointer (&rdp_event_queue->rdp_sync_event, g_free);
g_queue_free_full (rdp_event_queue->queue, free_rdp_event);
g_source_destroy (rdp_event_queue->flush_source);
@@ -292,7 +394,10 @@ grd_rdp_event_queue_init (GrdRdpEventQueue *rdp_event_queue)
{
rdp_event_queue->queue = g_queue_new ();
- g_mutex_init (&rdp_event_queue->queue_mutex);
+ g_mutex_init (&rdp_event_queue->event_mutex);
+
+ rdp_event_queue->pending_sync_caps_lock = TRUE;
+ rdp_event_queue->pending_sync_num_lock = TRUE;
}
static void
diff --git a/src/grd-rdp-event-queue.h b/src/grd-rdp-event-queue.h
index 41f6497..ab81c43 100644
--- a/src/grd-rdp-event-queue.h
+++ b/src/grd-rdp-event-queue.h
@@ -53,4 +53,14 @@ void grd_rdp_event_queue_add_input_event_pointer_axis (GrdRdpEventQueue *rdp_
double dy,
GrdPointerAxisFlags flags);
+void grd_rdp_event_queue_update_caps_lock_state (GrdRdpEventQueue *rdp_event_queue,
+ gboolean caps_lock_state);
+
+void grd_rdp_event_queue_update_num_lock_state (GrdRdpEventQueue *rdp_event_queue,
+ gboolean num_lock_state);
+
+void grd_rdp_event_queue_add_synchronization_event (GrdRdpEventQueue *rdp_event_queue,
+ gboolean caps_lock_state,
+ gboolean num_lock_state);
+
#endif /* GRD_RDP_EVENT_QUEUE_H */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]