diff options
Diffstat (limited to 'daemon/gdm-local-display-factory.c')
-rw-r--r-- | daemon/gdm-local-display-factory.c | 257 |
1 files changed, 130 insertions, 127 deletions
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c index 9cdf1985..a533d558 100644 --- a/daemon/gdm-local-display-factory.c +++ b/daemon/gdm-local-display-factory.c @@ -26,9 +26,7 @@ #include <glib.h> #include <glib/gi18n.h> #include <glib-object.h> - -#include <dbus/dbus.h> -#include <dbus/dbus-glib-lowlevel.h> +#include <gio/gio.h> #ifdef WITH_SYSTEMD #include <systemd/sd-daemon.h> @@ -55,12 +53,17 @@ struct GdmLocalDisplayFactoryPrivate { - DBusGConnection *connection; - DBusGProxy *proxy; + GdmDBusLocalDisplayFactory *skeleton; + GDBusConnection *connection; GHashTable *displays; /* FIXME: this needs to be per seat? */ guint num_failures; + +#ifdef WITH_SYSTEMD + guint seat_new_id; + guint seat_removed_id; +#endif }; enum { @@ -384,143 +387,108 @@ delete_display (GdmLocalDisplayFactory *factory, static gboolean gdm_local_display_factory_sync_seats (GdmLocalDisplayFactory *factory) { - DBusError error; - DBusMessage *message, *reply; - DBusMessageIter iter, sub, sub2; - - dbus_error_init (&error); - - message = dbus_message_new_method_call ( - "org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - "ListSeats"); - if (message == NULL) { - g_warning ("GdmLocalDisplayFactory: Failed to allocate message"); - return FALSE; - } - - reply = dbus_connection_send_with_reply_and_block (dbus_g_connection_get_connection (factory->priv->connection), message, -1, &error); - dbus_message_unref (message); - - if (reply == NULL) { - g_warning ("GdmLocalDisplayFactory: Failed to issue method call: %s", error.message); - dbus_error_free (&error); - return FALSE; - } - - if (!dbus_message_iter_init (reply, &iter) || - dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY || - dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_STRUCT) { - g_warning ("GdmLocalDisplayFactory: Failed to parse reply."); - dbus_message_unref (reply); + GError *error = NULL; + GVariant *result; + GVariant *array; + GVariantIter iter; + const char *seat; + + result = g_dbus_connection_call_sync (factory->priv->connection, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "ListSeats", + NULL, + G_VARIANT_TYPE ("(a(so))"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, &error); + + if (!result) { + g_warning ("GdmLocalDisplayFactory: Failed to issue method call: %s", error->message); + g_clear_error (&error); return FALSE; } - dbus_message_iter_recurse (&iter, &sub); - - while (dbus_message_iter_get_arg_type (&sub) != DBUS_TYPE_INVALID) { - const char *seat; - - if (dbus_message_iter_get_arg_type (&sub) != DBUS_TYPE_STRUCT) { - g_warning ("GdmLocalDisplayFactory: Failed to parse reply."); - dbus_message_unref (reply); - return FALSE; - } - - dbus_message_iter_recurse (&sub, &sub2); - - if (dbus_message_iter_get_arg_type (&sub2) != DBUS_TYPE_STRING) { - g_warning ("GdmLocalDisplayFactory: Failed to parse reply."); - dbus_message_unref (reply); - return FALSE; - } + array = g_variant_get_child_value (result, 0); + g_variant_iter_init (&iter, array); - dbus_message_iter_get_basic (&sub2, &seat); + while (g_variant_iter_loop (&iter, "(&so)", &seat, NULL)) create_display (factory, seat); - dbus_message_iter_next (&sub); - } - - dbus_message_unref (reply); + g_variant_unref (result); + g_variant_unref (array); return TRUE; } -static DBusHandlerResult -on_seat_signal (DBusConnection *connection, - DBusMessage *message, - void *user_data) +static void +on_seat_new (GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) { - GdmLocalDisplayFactory *factory = user_data; - DBusError error; + const char *seat; - dbus_error_init (&error); - - if (dbus_message_is_signal (message, "org.freedesktop.login1.Manager", "SeatNew") || - dbus_message_is_signal (message, "org.freedesktop.login1.Manager", "SeatRemoved")) { - const char *seat; - - dbus_message_get_args (message, - &error, - DBUS_TYPE_STRING, &seat, - DBUS_TYPE_INVALID); - - if (dbus_error_is_set (&error)) { - g_warning ("GdmLocalDisplayFactory: Failed to decode seat message: %s", error.message); - dbus_error_free (&error); - } else { + g_variant_get (parameters, "(&s)", &seat); + create_display (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat); +} - if (strcmp (dbus_message_get_member (message), "SeatNew") == 0) { - create_display (factory, seat); - } else { - delete_display (factory, seat); - } - } - } +static void +on_seat_removed (GDBusConnection *connection, + const gchar *sender_name, + const gchar *object_path, + const gchar *interface_name, + const gchar *signal_name, + GVariant *parameters, + gpointer user_data) +{ + const char *seat; - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + g_variant_get (parameters, "(&s)", &seat); + delete_display (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat); } static void gdm_local_display_factory_start_monitor (GdmLocalDisplayFactory *factory) { - DBusError error; - - dbus_error_init (&error); - - dbus_bus_add_match (dbus_g_connection_get_connection (factory->priv->connection), - "type='signal'," - "sender='org.freedesktop.login1'," - "path='/org/freedesktop/login1'," - "interface='org.freedesktop.login1.Manager'," - "member='SeatNew'", - &error); - - if (dbus_error_is_set (&error)) { - g_warning ("GdmLocalDisplayFactory: Failed to add match for SeatNew: %s", error.message); - dbus_error_free (&error); - } - - dbus_bus_add_match (dbus_g_connection_get_connection (factory->priv->connection), - "type='signal'," - "sender='org.freedesktop.login1'," - "path='/org/freedesktop/login1'," - "interface='org.freedesktop.login1.Manager'," - "member='SeatRemoved'", - &error); - - if (dbus_error_is_set (&error)) { - g_warning ("GdmLocalDisplayFactory: Failed to add match for SeatNew: %s", error.message); - dbus_error_free (&error); - } - - dbus_connection_add_filter (dbus_g_connection_get_connection (factory->priv->connection), on_seat_signal, factory, NULL); + factory->priv->seat_new_id = g_dbus_connection_signal_subscribe (factory->priv->connection, + "org.freedesktop.login1", + "org.freedesktop.login1.Manager", + "SeatNew", + "/org/freedesktop/login1", + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + on_seat_new, + g_object_ref (factory), + g_object_unref); + factory->priv->seat_removed_id = g_dbus_connection_signal_subscribe (factory->priv->connection, + "org.freedesktop.login1", + "org.freedesktop.login1.Manager", + "SeatRemoved", + "/org/freedesktop/login1", + NULL, + G_DBUS_SIGNAL_FLAGS_NONE, + on_seat_removed, + g_object_ref (factory), + g_object_unref); } static void gdm_local_display_factory_stop_monitor (GdmLocalDisplayFactory *factory) { - dbus_connection_remove_filter (dbus_g_connection_get_connection (factory->priv->connection), on_seat_signal, factory); + if (factory->priv->seat_new_id) { + g_dbus_connection_signal_unsubscribe (factory->priv->connection, + factory->priv->seat_new_id); + factory->priv->seat_new_id = 0; + } + if (factory->priv->seat_removed_id) { + g_dbus_connection_signal_unsubscribe (factory->priv->connection, + factory->priv->seat_removed_id); + factory->priv->seat_removed_id = 0; + } } #endif @@ -587,21 +555,55 @@ gdm_local_display_factory_get_property (GObject *object, } static gboolean +handle_create_transient_display (GdmDBusLocalDisplayFactory *skeleton, + GDBusMethodInvocation *invocation, + GdmLocalDisplayFactory *factory) +{ + GError *error = NULL; + gboolean created; + char *id = NULL; + + created = gdm_local_display_factory_create_transient_display (factory, + &id, + &error); + if (!created) { + g_dbus_method_invocation_return_gerror (invocation, error); + } else { + gdm_dbus_local_display_factory_complete_create_transient_display (skeleton, invocation, id); + } + + g_free (id); + return TRUE; +} + +static gboolean register_factory (GdmLocalDisplayFactory *factory) { GError *error = NULL; error = NULL; - factory->priv->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); + factory->priv->connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error); if (factory->priv->connection == NULL) { - if (error != NULL) { - g_critical ("error getting system bus: %s", error->message); - g_error_free (error); - } + g_critical ("error getting system bus: %s", error->message); + g_error_free (error); exit (1); } - dbus_g_connection_register_g_object (factory->priv->connection, GDM_LOCAL_DISPLAY_FACTORY_DBUS_PATH, G_OBJECT (factory)); + factory->priv->skeleton = GDM_DBUS_LOCAL_DISPLAY_FACTORY (gdm_dbus_local_display_factory_skeleton_new ()); + + g_signal_connect (factory->priv->skeleton, + "handle-create-transient-display", + G_CALLBACK (handle_create_transient_display), + factory); + + if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (factory->priv->skeleton), + factory->priv->connection, + GDM_LOCAL_DISPLAY_FACTORY_DBUS_PATH, + &error)) { + g_critical ("error exporting LocalDisplayFactory object: %s", error->message); + g_error_free (error); + exit (1); + } return TRUE; } @@ -641,8 +643,6 @@ gdm_local_display_factory_class_init (GdmLocalDisplayFactoryClass *klass) factory_class->stop = gdm_local_display_factory_stop; g_type_class_add_private (klass, sizeof (GdmLocalDisplayFactoryPrivate)); - - dbus_g_object_type_install_info (GDM_TYPE_LOCAL_DISPLAY_FACTORY, &dbus_glib_gdm_local_display_factory_object_info); } static void @@ -665,6 +665,9 @@ gdm_local_display_factory_finalize (GObject *object) g_return_if_fail (factory->priv != NULL); + g_clear_object (&factory->priv->connection); + g_clear_object (&factory->priv->skeleton); + g_hash_table_destroy (factory->priv->displays); #ifdef WITH_SYSTEMD |