diff --git a/src/backends/native/meta-barrier-native.c b/src/backends/native/meta-barrier-native.c index bdb006fb1..ebc1beaeb 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 *context; }; G_DEFINE_TYPE (MetaBarrierImplNative, @@ -340,6 +342,48 @@ 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 +emit_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->context); +} + static void emit_barrier_event (MetaBarrierImplNative *self, guint32 time, @@ -350,7 +394,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 +432,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); + emit_event (self, event); } static void @@ -479,6 +517,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 +563,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 +591,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->context); self->is_active = FALSE; } @@ -565,10 +610,13 @@ meta_barrier_impl_native_new (MetaBarrier *barrier) self->barrier = barrier; self->is_active = TRUE; + self->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 +644,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; }