summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2020-08-11 20:21:08 +0200
committerMarge Bot <marge-bot@gnome.org>2020-11-27 15:14:33 +0000
commite76a7f43e02d360b624425816181a28144b61faf (patch)
tree09272f73cb2d991588a07380a5b542680701b08c
parentb789d38f680ec4b547143c66cbe18994b1d06796 (diff)
downloadmutter-e76a7f43e02d360b624425816181a28144b61faf.tar.gz
backends/native: Protect MetaBarrierManagerNative
While barriers will be added from the main thread, the native barrier manager will sit close to the MetaSeatImpl in its own thread. Add the necessary locking so that we can pass MetaBarrierImplNative from the UI thread to the input thread, and ensure the MetaBarrier signals are still emitted in the UI thread. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1403>
-rw-r--r--src/backends/native/meta-barrier-native.c64
1 files changed, 57 insertions, 7 deletions
diff --git a/src/backends/native/meta-barrier-native.c b/src/backends/native/meta-barrier-native.c
index bdb006fb1..8db73ee06 100644
--- a/src/backends/native/meta-barrier-native.c
+++ b/src/backends/native/meta-barrier-native.c
@@ -43,6 +43,7 @@
struct _MetaBarrierManagerNative
{
GHashTable *barriers;
+ GMutex mutex;
};
typedef enum
@@ -77,6 +78,7 @@ struct _MetaBarrierImplNative
int trigger_serial;
guint32 last_event_time;
MetaBarrierDirection blocked_dir;
+ GMainContext *main_context;
};
G_DEFINE_TYPE (MetaBarrierImplNative,
@@ -340,6 +342,49 @@ typedef struct _MetaBarrierEventData
float dy;
} MetaBarrierEventData;
+typedef struct
+{
+ MetaBarrierEvent *event;
+ MetaBarrier *barrier;
+ MetaBarrierState state;
+} MetaBarrierIdleData;
+
+static gboolean
+emit_event_idle (MetaBarrierIdleData *idle_data)
+{
+ if (idle_data->state == META_BARRIER_STATE_HELD)
+ _meta_barrier_emit_hit_signal (idle_data->barrier, idle_data->event);
+ else
+ _meta_barrier_emit_left_signal (idle_data->barrier, idle_data->event);
+
+ meta_barrier_event_unref (idle_data->event);
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+queue_event (MetaBarrierImplNative *self,
+ MetaBarrierEvent *event)
+{
+ MetaBarrierIdleData *idle_data;
+ GSource *source;
+
+ idle_data = g_new0 (MetaBarrierIdleData, 1);
+ idle_data->state = self->state;
+ idle_data->barrier = self->barrier;
+ idle_data->event = event;
+
+ source = g_idle_source_new ();
+ g_source_set_priority (source, G_PRIORITY_HIGH);
+ g_source_set_callback (source,
+ (GSourceFunc) emit_event_idle,
+ idle_data,
+ g_free);
+
+ g_source_attach (source, self->main_context);
+ g_source_unref (source);
+}
+
static void
emit_barrier_event (MetaBarrierImplNative *self,
guint32 time,
@@ -350,7 +395,6 @@ emit_barrier_event (MetaBarrierImplNative *self,
float dx,
float dy)
{
- MetaBarrier *barrier = self->barrier;
MetaBarrierEvent *event = g_slice_new0 (MetaBarrierEvent);
MetaBarrierState old_state = self->state;
@@ -389,12 +433,7 @@ emit_barrier_event (MetaBarrierImplNative *self,
self->last_event_time = time;
- if (self->state == META_BARRIER_STATE_HELD)
- _meta_barrier_emit_hit_signal (barrier, event);
- else
- _meta_barrier_emit_left_signal (barrier, event);
-
- meta_barrier_event_unref (event);
+ queue_event (self, event);
}
static void
@@ -479,6 +518,8 @@ meta_barrier_manager_native_process (MetaBarrierManagerNative *manager,
if (!clutter_input_device_get_coords (device, NULL, &prev_pos))
return;
+ g_mutex_lock (&manager->mutex);
+
prev_x = prev_pos.x;
prev_y = prev_pos.y;
@@ -523,6 +564,8 @@ meta_barrier_manager_native_process (MetaBarrierManagerNative *manager,
g_hash_table_foreach (manager->barriers,
maybe_emit_barrier_event,
&barrier_event_data);
+
+ g_mutex_unlock (&manager->mutex);
}
static gboolean
@@ -549,7 +592,10 @@ _meta_barrier_impl_native_destroy (MetaBarrierImpl *impl)
{
MetaBarrierImplNative *self = META_BARRIER_IMPL_NATIVE (impl);
+ g_mutex_lock (&self->manager->mutex);
g_hash_table_remove (self->manager->barriers, self);
+ g_mutex_unlock (&self->manager->mutex);
+ g_main_context_unref (self->main_context);
self->is_active = FALSE;
}
@@ -565,10 +611,13 @@ meta_barrier_impl_native_new (MetaBarrier *barrier)
self->barrier = barrier;
self->is_active = TRUE;
+ self->main_context = g_main_context_ref_thread_default ();
manager = meta_seat_native_get_barrier_manager (META_SEAT_NATIVE (seat));
self->manager = manager;
+ g_mutex_lock (&manager->mutex);
g_hash_table_add (manager->barriers, self);
+ g_mutex_unlock (&manager->mutex);
return META_BARRIER_IMPL (self);
}
@@ -596,6 +645,7 @@ meta_barrier_manager_native_new (void)
manager = g_new0 (MetaBarrierManagerNative, 1);
manager->barriers = g_hash_table_new (NULL, NULL);
+ g_mutex_init (&manager->mutex);
return manager;
}