[gdm/x-gdm-sessionregisters: 3/4] Allow sessions to register with GDM



commit 40b31d38f4ae2d3d16940ab454a182d2db60cda3
Author: Iain Lane <iainl gnome org>
Date:   Tue May 7 16:00:14 2019 +0100

    Allow sessions to register with GDM
    
    Recording when sessions start, for Wayland → Xorg fallback or
    transitioning to the user session, is currently done with timeouts.
    
    This isn't ideal, because on some very slow machines the timeout can be
    hit before the session has had a chance to fail: if gnome-session takes
    more than 3 seconds to fail then the session will be considered to have
    exited rather than failed, and so we don't do Xorg fallback.
    
    We can do this more reliably if we allow sessions to optionally register
    themselves with GDM. Then we will know when they've started, so can shut
    down the greeter or fall back to Xorg as appropriate. The mechanism is
    that they specify X-GDM-SessionRegisters=true in their file, and then
    call RegsterSession on the DisplayManager interface on the bus (added in
    the previous commit) to say that they've started up.
    
    If X-GDM-SessionRegisters is missing or false, GDM will call the same
    method for them after 10 seconds.
    
    Closes: #483

 common/gdm-common.h                |  2 +
 daemon/gdm-display.c               | 18 ++------
 daemon/gdm-local-display-factory.c | 93 +++++++++++++++++++++++++++++++-------
 daemon/gdm-session.c               | 47 +++++++++++++++++--
 daemon/gdm-session.h               |  1 +
 daemon/gdm-wayland-session.c       | 81 +++++++++++++++++++++++++--------
 daemon/gdm-x-session.c             | 82 +++++++++++++++++++++++++--------
 7 files changed, 252 insertions(+), 72 deletions(-)
---
diff --git a/common/gdm-common.h b/common/gdm-common.h
index 07812b10..58814aa2 100644
--- a/common/gdm-common.h
+++ b/common/gdm-common.h
@@ -27,6 +27,8 @@
 #include <pwd.h>
 #include <errno.h>
 
+#define REGISTER_SESSION_TIMEOUT 10
+
 #define        VE_IGNORE_EINTR(expr) \
         do {                         \
                 errno = 0;           \
diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c
index fb76fd16..8c106222 100644
--- a/daemon/gdm-display.c
+++ b/daemon/gdm-display.c
@@ -66,7 +66,6 @@ typedef struct _GdmDisplayPrivate
         char                 *x11_display_name;
         int                   status;
         time_t                creation_time;
-        GTimer               *server_timer;
 
         char                 *x11_cookie;
         gsize                 x11_cookie_size;
@@ -93,7 +92,7 @@ typedef struct _GdmDisplayPrivate
         guint                 allow_timed_login : 1;
         guint                 have_existing_user_accounts : 1;
         guint                 doing_initial_setup : 1;
-        guint                 registered : 1;
+        guint                 session_registered : 1;
 } GdmDisplayPrivate;
 
 enum {
@@ -600,8 +599,6 @@ gdm_display_manage (GdmDisplay *self)
                 }
         }
 
-        g_timer_start (priv->server_timer);
-
         if (g_strcmp0 (priv->session_class, "greeter") == 0) {
                 if (GDM_DISPLAY_GET_CLASS (self)->manage != NULL) {
                         GDM_DISPLAY_GET_CLASS (self)->manage (self);
@@ -673,7 +670,6 @@ gboolean
 gdm_display_unmanage (GdmDisplay *self)
 {
         GdmDisplayPrivate *priv;
-        gdouble elapsed;
 
         g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE);
 
@@ -683,8 +679,6 @@ gdm_display_unmanage (GdmDisplay *self)
 
         gdm_display_disconnect (self);
 
-        g_timer_stop (priv->server_timer);
-
         if (priv->user_access_file != NULL) {
                 gdm_display_access_file_close (priv->user_access_file);
                 g_object_unref (priv->user_access_file);
@@ -697,9 +691,8 @@ gdm_display_unmanage (GdmDisplay *self)
                 priv->access_file = NULL;
         }
 
-        elapsed = g_timer_elapsed (priv->server_timer, NULL);
-        if (elapsed < 3) {
-                g_warning ("GdmDisplay: display lasted %lf seconds", elapsed);
+        if (!priv->session_registered) {
+                g_warning ("GdmDisplay: Session never registered, failing");
                 _gdm_display_set_status (self, GDM_DISPLAY_FAILED);
         } else {
                 _gdm_display_set_status (self, GDM_DISPLAY_UNMANAGED);
@@ -1408,7 +1401,6 @@ gdm_display_init (GdmDisplay *self)
         priv = gdm_display_get_instance_private (self);
 
         priv->creation_time = time (NULL);
-        priv->server_timer = g_timer_new ();
 }
 
 static void
@@ -1446,10 +1438,6 @@ gdm_display_finalize (GObject *object)
                 g_object_unref (priv->user_access_file);
         }
 
-        if (priv->server_timer != NULL) {
-                g_timer_destroy (priv->server_timer);
-        }
-
         G_OBJECT_CLASS (gdm_display_parent_class)->finalize (object);
 }
 
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index 7dd74a62..29e9f5f1 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -66,7 +66,7 @@ struct _GdmLocalDisplayFactory
 #if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
         unsigned int     active_vt;
         guint            active_vt_watch_id;
-        guint            wait_to_finish_timeout_id;
+        guint            wait_to_register_id;
 #endif
 };
 
@@ -605,19 +605,59 @@ lookup_by_session_id (const char *id,
 
 #if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
 static gboolean
-wait_to_finish_timeout (GdmLocalDisplayFactory *factory)
+lookup_by_vt (const char *id,
+              GdmDisplay *display,
+              gpointer user_data)
 {
+        unsigned int vt_to_find = *(unsigned int *) user_data;
+        unsigned int vt;
+        int ret;
+        const char *display_session_id;
+
+        display_session_id = gdm_display_get_session_id (display);
+
+        ret = sd_session_get_vt (display_session_id, &vt);
+
+        if (ret < 0) {
+                g_debug ("Couldn't look up session %s: %s",
+                         display_session_id,
+                         strerror (-ret));
+                return FALSE;
+        }
+
+        return (vt_to_find == vt);
+}
+
+static void
+on_session_registered_cb (GObject *gobject,
+                          GParamSpec *pspec,
+                          gpointer user_data)
+{
+        GdmDisplay *display = GDM_DISPLAY (gobject);
+        GdmLocalDisplayFactory *factory = GDM_LOCAL_DISPLAY_FACTORY (user_data);
+        gboolean registered;
+
+        g_object_get (display, "session-registered", &registered, NULL);
+
+        if (!registered)
+                return;
+
+        g_debug ("GdmLocalDisplayFactory: session registered on display, killing login screen");
+
         finish_waiting_displays_on_seat (factory, "seat0");
-        factory->wait_to_finish_timeout_id = 0;
-        return G_SOURCE_REMOVE;
+
+        g_signal_handler_disconnect (factory, factory->wait_to_register_id);
+        factory->wait_to_register_id = 0;
 }
 
 static void
 maybe_stop_greeter_in_background (GdmLocalDisplayFactory *factory,
-                                  GdmDisplay             *display)
+                                  GdmDisplay             *display,
+                                  GdmDisplay             *new_display)
 {
         g_autofree char *display_session_type = NULL;
         gboolean doing_initial_setup = FALSE;
+        gboolean registered;
 
         if (gdm_display_get_status (display) != GDM_DISPLAY_MANAGED) {
                 g_debug ("GdmLocalDisplayFactory: login window not in managed state, so ignoring");
@@ -642,17 +682,36 @@ maybe_stop_greeter_in_background (GdmLocalDisplayFactory *factory,
                 return;
         }
 
+        g_debug ("GdmLocalDisplayFactory: old display: %p, new display: %p",
+                 display,
+                 new_display);
+
         g_debug ("GdmLocalDisplayFactory: killing login window once its unused");
+
         g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_WAITING_TO_FINISH, NULL);
 
-        /* We stop the greeter after a timeout to avoid flicker */
-        if (factory->wait_to_finish_timeout_id != 0)
-                g_source_remove (factory->wait_to_finish_timeout_id);
+        /* We stop the greeter once the new session has started fully, when it
+         * registers with us */
+        g_object_get (G_OBJECT (new_display),
+                      "session-registered", &registered,
+                      NULL);
 
-        factory->wait_to_finish_timeout_id =
-                g_timeout_add_seconds (WAIT_TO_FINISH_TIMEOUT,
-                                       (GSourceFunc)wait_to_finish_timeout,
-                                       factory);
+        if (registered) {
+                g_debug ("GdmLocalDisplayFactory: new display already registered, killing greeter");
+                finish_waiting_displays_on_seat (factory, "seat0");
+                return;
+        }
+
+        g_debug ("GdmLocalDisplayFactory: new display not yet registered, waiting to kill greeter");
+
+        if (factory->wait_to_register_id != 0)
+                g_signal_handler_disconnect (new_display, factory->wait_to_register_id);
+
+        factory->wait_to_register_id = g_signal_connect_object (new_display,
+                                                                "notify::session-registered",
+                                                                G_CALLBACK (on_session_registered_cb),
+                                                                factory,
+                                                                0);
 }
 
 static gboolean
@@ -741,6 +800,7 @@ on_vt_changed (GIOChannel    *source,
                         if (login_window_vt == previous_vt) {
                                 GdmDisplayStore *store;
                                 GdmDisplay *display;
+                                GdmDisplay *new_display = NULL;
 
                                 g_debug ("GdmLocalDisplayFactory: VT switched from login window");
 
@@ -748,9 +808,12 @@ on_vt_changed (GIOChannel    *source,
                                 display = gdm_display_store_find (store,
                                                                   lookup_by_session_id,
                                                                   (gpointer) login_session_id);
+                                new_display = gdm_display_store_find (store,
+                                                                      lookup_by_vt,
+                                                                      (gpointer) &new_vt);
 
                                 if (display != NULL)
-                                        maybe_stop_greeter_in_background (factory, display);
+                                        maybe_stop_greeter_in_background (factory, display, new_display);
                         } else {
                                 g_debug ("GdmLocalDisplayFactory: VT not switched from login window");
                         }
@@ -831,10 +894,6 @@ gdm_local_display_factory_stop_monitor (GdmLocalDisplayFactory *factory)
                 factory->seat_removed_id = 0;
         }
 #if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
-        if (factory->wait_to_finish_timeout_id != 0) {
-                g_source_remove (factory->wait_to_finish_timeout_id);
-                factory->wait_to_finish_timeout_id = 0;
-        }
         if (factory->active_vt_watch_id) {
                 g_source_remove (factory->active_vt_watch_id);
                 factory->active_vt_watch_id = 0;
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
index 6a116a85..d0e09b53 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -2837,6 +2837,7 @@ gdm_session_start_session (GdmSession *self,
         gboolean                allow_remote_connections = FALSE;
         char                   *command;
         char                   *program;
+        gboolean               register_session;
 
         g_return_if_fail (GDM_IS_SESSION (self));
         g_return_if_fail (self->session_conversation == NULL);
@@ -2862,6 +2863,8 @@ gdm_session_start_session (GdmSession *self,
                 run_launcher = TRUE;
         }
 
+        register_session = !gdm_session_session_registers (self);
+
         if (self->selected_program == NULL) {
                 gboolean run_xsession_script;
 
@@ -2879,12 +2882,14 @@ gdm_session_start_session (GdmSession *self,
 
                 if (run_launcher) {
                         if (is_x11) {
-                                program = g_strdup_printf (LIBEXECDIR "/gdm-x-session %s %s\"%s\"",
+                                program = g_strdup_printf (LIBEXECDIR "/gdm-x-session %s%s %s\"%s\"",
+                                                           register_session ? "--register-session " : "",
                                                            run_xsession_script? "--run-script " : "",
                                                            allow_remote_connections? 
"--allow-remote-connections " : "",
                                                            command);
                         } else {
-                                program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session \"%s\"",
+                                program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session %s\"%s\"",
+                                                           register_session ? "--register-session " : "",
                                                            command);
                         }
                 } else if (run_xsession_script) {
@@ -2897,10 +2902,12 @@ gdm_session_start_session (GdmSession *self,
         } else {
                 if (run_launcher) {
                         if (is_x11) {
-                                program = g_strdup_printf (LIBEXECDIR "/gdm-x-session \"%s\"",
+                                program = g_strdup_printf (LIBEXECDIR "/gdm-x-session %s\"%s\"",
+                                                           register_session ? "--register-session " : "",
                                                            self->selected_program);
                         } else {
-                                program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session \"%s\"",
+                                program = g_strdup_printf (LIBEXECDIR "/gdm-wayland-session %s\"%s\"",
+                                                           register_session ? "--register-session " : "",
                                                            self->selected_program);
                         }
                 } else {
@@ -3177,6 +3184,38 @@ update_session_type (GdmSession *self)
 #endif
 }
 
+gboolean
+gdm_session_session_registers (GdmSession *self)
+{
+        g_autoptr(GError) error = NULL;
+        g_autoptr(GKeyFile) key_file = NULL;
+        gboolean session_registers = FALSE;
+        g_autofree char *filename = NULL;
+
+        g_return_val_if_fail (self != NULL, FALSE);
+        g_return_val_if_fail (GDM_IS_SESSION (self), FALSE);
+
+        filename = get_session_filename (self);
+
+        key_file = load_key_file_for_file (self, filename, NULL);
+
+        session_registers = g_key_file_get_boolean (key_file,
+                                                    G_KEY_FILE_DESKTOP_GROUP,
+                                                    "X-GDM-SessionRegisters",
+                                                    &error);
+        if (!session_registers &&
+            error != NULL &&
+            !g_error_matches (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND)) {
+                g_warning ("GdmSession: Couldn't read session file '%s'", filename);
+                return FALSE;
+        }
+
+        g_debug ("GdmSession: '%s' %s self", filename,
+                 session_registers ? "registers" : "does not register");
+
+        return session_registers;
+}
+
 gboolean
 gdm_session_bypasses_xsession (GdmSession *self)
 {
diff --git a/daemon/gdm-session.h b/daemon/gdm-session.h
index 98acb4f6..3b64ecd2 100644
--- a/daemon/gdm-session.h
+++ b/daemon/gdm-session.h
@@ -76,6 +76,7 @@ const char       *gdm_session_get_display_device          (GdmSession     *sessi
 const char       *gdm_session_get_display_seat_id         (GdmSession     *session);
 const char       *gdm_session_get_session_id              (GdmSession     *session);
 gboolean          gdm_session_bypasses_xsession           (GdmSession     *session);
+gboolean          gdm_session_session_registers           (GdmSession     *session);
 GdmSessionDisplayMode gdm_session_get_display_mode  (GdmSession     *session);
 
 #ifdef ENABLE_WAYLAND_SUPPORT
diff --git a/daemon/gdm-wayland-session.c b/daemon/gdm-wayland-session.c
index 94f49e19..35679b19 100644
--- a/daemon/gdm-wayland-session.c
+++ b/daemon/gdm-wayland-session.c
@@ -45,6 +45,7 @@ typedef struct
 
         GSubprocess     *bus_subprocess;
         GDBusConnection *bus_connection;
+        GdmDBusManager  *display_manager_proxy;
         char            *bus_address;
 
         char           **environment;
@@ -53,6 +54,8 @@ typedef struct
         char         *session_command;
         int           session_exit_status;
 
+        guint         register_session_id;
+
         GMainLoop    *main_loop;
 
         guint32       debug_enabled : 1;
@@ -385,29 +388,14 @@ static gboolean
 register_display (State        *state,
                   GCancellable *cancellable)
 {
-        GdmDBusManager  *manager = NULL;
         GError          *error = NULL;
         gboolean         registered = FALSE;
         GVariantBuilder  details;
 
-        manager = gdm_dbus_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
-                                                           G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
-                                                           G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
-                                                           "org.gnome.DisplayManager",
-                                                           "/org/gnome/DisplayManager/Manager",
-                                                           cancellable,
-                                                           &error);
-
-        if (!manager) {
-                g_debug ("could not contact display manager: %s", error->message);
-                g_error_free (error);
-                goto out;
-        }
-
         g_variant_builder_init (&details, G_VARIANT_TYPE ("a{ss}"));
         g_variant_builder_add (&details, "{ss}", "session-type", "wayland");
 
-        registered = gdm_dbus_manager_call_register_display_sync (manager,
+        registered = gdm_dbus_manager_call_register_display_sync (state->display_manager_proxy,
                                                                   g_variant_builder_end (&details),
                                                                   cancellable,
                                                                   &error);
@@ -416,8 +404,6 @@ register_display (State        *state,
                 g_error_free (error);
         }
 
-out:
-        g_clear_object (&manager);
         return registered;
 }
 
@@ -439,6 +425,7 @@ clear_state (State **out_state)
         g_clear_object (&state->session_subprocess);
         g_clear_pointer (&state->environment, g_strfreev);
         g_clear_pointer (&state->main_loop, g_main_loop_unref);
+        g_clear_handle_id (&state->register_session_id, g_source_remove);
         *out_state = NULL;
 }
 
@@ -454,6 +441,49 @@ on_sigterm (State *state)
         return G_SOURCE_CONTINUE;
 }
 
+static gboolean
+register_session_timeout_cb (gpointer user_data)
+{
+        State *state;
+        GError *error = NULL;
+
+        state = (State *) user_data;
+
+        gdm_dbus_manager_call_register_session_sync (state->display_manager_proxy,
+                                                     g_variant_new ("a{sv}", NULL),
+                                                     state->cancellable,
+                                                     &error);
+
+        if (error != NULL) {
+                g_warning ("Could not register session: %s", error->message);
+                g_error_free (error);
+        }
+
+        return G_SOURCE_REMOVE;
+}
+
+static gboolean
+connect_to_display_manager (State *state)
+{
+        g_autoptr (GError) error = NULL;
+
+        state->display_manager_proxy = gdm_dbus_manager_proxy_new_for_bus_sync (
+                G_BUS_TYPE_SYSTEM,
+                G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+                "org.gnome.DisplayManager",
+                "/org/gnome/DisplayManager/Manager",
+                state->cancellable,
+                &error);
+
+        if (state->display_manager_proxy == NULL) {
+                g_printerr ("gdm-wayland-session: could not contact display manager: %s\n",
+                            error->message);
+                return FALSE;
+        }
+
+        return TRUE;
+}
+
 int
 main (int    argc,
       char **argv)
@@ -464,7 +494,10 @@ main (int    argc,
         gboolean         debug = FALSE;
         gboolean         ret;
         int              exit_status = EX_OK;
+        static gboolean  register_session = FALSE;
+
         static GOptionEntry entries []   = {
+                { "register-session", 0, 0, G_OPTION_ARG_NONE, &register_session, "Register session after a 
delay", NULL },
                 { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args, "", "" },
                 { NULL }
         };
@@ -528,6 +561,9 @@ main (int    argc,
                 goto out;
         }
 
+        if (!connect_to_display_manager (state))
+                goto out;
+
         ret = register_display (state, state->cancellable);
 
         if (!ret) {
@@ -536,6 +572,15 @@ main (int    argc,
                 goto out;
         }
 
+        if (register_session) {
+                g_debug ("gdm-wayland-session: Will register session in %d seconds", 
REGISTER_SESSION_TIMEOUT);
+                state->register_session_id = g_timeout_add_seconds (REGISTER_SESSION_TIMEOUT,
+                                                                    register_session_timeout_cb,
+                                                                    state);
+        } else {
+                g_debug ("gdm-wayland-session: Session will register itself");
+        }
+
         g_main_loop_run (state->main_loop);
 
         /* Only use exit status of session if we're here because it exit */
diff --git a/daemon/gdm-x-session.c b/daemon/gdm-x-session.c
index 3b2fcef4..0205799c 100644
--- a/daemon/gdm-x-session.c
+++ b/daemon/gdm-x-session.c
@@ -51,6 +51,7 @@ typedef struct
 
         GSubprocess     *bus_subprocess;
         GDBusConnection *bus_connection;
+        GdmDBusManager  *display_manager_proxy;
         char            *bus_address;
 
         char           **environment;
@@ -59,6 +60,8 @@ typedef struct
         char         *session_command;
         int           session_exit_status;
 
+        guint         register_session_id;
+
         GMainLoop    *main_loop;
 
         guint32       debug_enabled : 1;
@@ -737,30 +740,15 @@ static gboolean
 register_display (State        *state,
                   GCancellable *cancellable)
 {
-        GdmDBusManager  *manager = NULL;
         GError          *error = NULL;
         gboolean         registered = FALSE;
         GVariantBuilder  details;
 
-        manager = gdm_dbus_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
-                                                           G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
-                                                           G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
-                                                           "org.gnome.DisplayManager",
-                                                           "/org/gnome/DisplayManager/Manager",
-                                                           cancellable,
-                                                           &error);
-
-        if (!manager) {
-                g_debug ("could not contact display manager: %s", error->message);
-                g_error_free (error);
-                goto out;
-        }
-
         g_variant_builder_init (&details, G_VARIANT_TYPE ("a{ss}"));
         g_variant_builder_add (&details, "{ss}", "session-type", "x11");
         g_variant_builder_add (&details, "{ss}", "x11-display-name", state->display_name);
 
-        registered = gdm_dbus_manager_call_register_display_sync (manager,
+        registered = gdm_dbus_manager_call_register_display_sync (state->display_manager_proxy,
                                                                   g_variant_builder_end (&details),
                                                                   cancellable,
                                                                   &error);
@@ -769,8 +757,6 @@ register_display (State        *state,
                 g_error_free (error);
         }
 
-out:
-        g_clear_object (&manager);
         return registered;
 }
 
@@ -795,6 +781,7 @@ clear_state (State **out_state)
         g_clear_pointer (&state->auth_file, g_free);
         g_clear_pointer (&state->display_name, g_free);
         g_clear_pointer (&state->main_loop, g_main_loop_unref);
+        g_clear_handle_id (&state->register_session_id, g_source_remove);
         *out_state = NULL;
 }
 
@@ -810,6 +797,49 @@ on_sigterm (State *state)
         return G_SOURCE_CONTINUE;
 }
 
+static gboolean
+register_session_timeout_cb (gpointer user_data)
+{
+        State *state;
+        GError *error = NULL;
+
+        state = (State *) user_data;
+
+        gdm_dbus_manager_call_register_session_sync (state->display_manager_proxy,
+                                                     g_variant_new ("a{sv}", NULL),
+                                                     state->cancellable,
+                                                     &error);
+
+        if (error != NULL) {
+                g_warning ("Could not register session: %s", error->message);
+                g_error_free (error);
+        }
+
+        return G_SOURCE_REMOVE;
+}
+
+static gboolean
+connect_to_display_manager (State *state)
+{
+        g_autoptr (GError) error = NULL;
+
+        state->display_manager_proxy = gdm_dbus_manager_proxy_new_for_bus_sync (
+                G_BUS_TYPE_SYSTEM,
+                G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+                "org.gnome.DisplayManager",
+                "/org/gnome/DisplayManager/Manager",
+                state->cancellable,
+                &error);
+
+        if (state->display_manager_proxy == NULL) {
+                g_printerr ("gdm-x-session: could not contact display manager: %s\n",
+                            error->message);
+                return FALSE;
+        }
+
+        return TRUE;
+}
+
 int
 main (int    argc,
       char **argv)
@@ -822,9 +852,12 @@ main (int    argc,
         gboolean         debug = FALSE;
         gboolean         ret;
         int              exit_status = EX_OK;
+        static gboolean  register_session = FALSE;
+
         static GOptionEntry entries []   = {
                 { "run-script", 'r', 0, G_OPTION_ARG_NONE, &run_script, N_("Run program through 
/etc/gdm/Xsession wrapper script"), NULL },
                 { "allow-remote-connections", 'a', 0, G_OPTION_ARG_NONE, &allow_remote_connections, 
N_("Listen on TCP socket"), NULL },
+                { "register-session", 0, 0, G_OPTION_ARG_NONE, &register_session, "Register session after a 
delay", NULL },
                 { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args, "", "" },
                 { NULL }
         };
@@ -896,6 +929,7 @@ main (int    argc,
                 goto out;
         }
 
+
         ret = register_display (state, state->cancellable);
 
         if (!ret) {
@@ -904,6 +938,9 @@ main (int    argc,
                 goto out;
         }
 
+        if (!connect_to_display_manager (state))
+                goto out;
+
         ret = spawn_session (state, run_script, state->cancellable);
 
         if (!ret) {
@@ -912,6 +949,15 @@ main (int    argc,
                 goto out;
         }
 
+        if (register_session) {
+                g_debug ("gdm-x-session: Will register session in %d seconds", REGISTER_SESSION_TIMEOUT);
+                state->register_session_id = g_timeout_add_seconds (REGISTER_SESSION_TIMEOUT,
+                                                                    register_session_timeout_cb,
+                                                                    state);
+        } else {
+                g_debug ("gdm-x-session: Session will register itself");
+        }
+
         g_main_loop_run (state->main_loop);
 
         /* Only use exit status of session if we're here because it exit */


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