diff options
-rw-r--r-- | common/gdm-common.h | 2 | ||||
-rw-r--r-- | configure.ac | 6 | ||||
-rw-r--r-- | daemon/gdm-display.c | 44 | ||||
-rw-r--r-- | daemon/gdm-local-display-factory.c | 100 | ||||
-rw-r--r-- | daemon/gdm-manager.c | 30 | ||||
-rw-r--r-- | daemon/gdm-manager.xml | 3 | ||||
-rw-r--r-- | daemon/gdm-server.c | 2 | ||||
-rw-r--r-- | daemon/gdm-session-worker.c | 2 | ||||
-rw-r--r-- | daemon/gdm-session.c | 47 | ||||
-rw-r--r-- | daemon/gdm-session.h | 1 | ||||
-rw-r--r-- | daemon/gdm-wayland-session.c | 81 | ||||
-rw-r--r-- | daemon/gdm-x-session.c | 81 |
12 files changed, 292 insertions, 107 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/configure.ac b/configure.ac index e54017f2..0a1c6c19 100644 --- a/configure.ac +++ b/configure.ac @@ -1416,12 +1416,12 @@ AC_ARG_WITH(initial-vt, AS_HELP_STRING([--with-initial-vt=<nr>], [Initial virtual terminal to use])) if ! test -z "$with_initial_vt"; then - GDM_INITIAL_VT="$with_initial_vt" + GDM_INITIAL_VT=$with_initial_vt else - GDM_INITIAL_VT="1" + GDM_INITIAL_VT=1 fi AC_SUBST(GDM_INITIAL_VT) -AC_DEFINE_UNQUOTED(GDM_INITIAL_VT, "$GDM_INITIAL_VT", [Initial Virtual Terminal]) +AC_DEFINE_UNQUOTED(GDM_INITIAL_VT, $GDM_INITIAL_VT, [Initial Virtual Terminal]) # Set configuration choices. # diff --git a/daemon/gdm-display.c b/daemon/gdm-display.c index a8747785..8f4fbc71 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,6 +92,7 @@ typedef struct _GdmDisplayPrivate guint allow_timed_login : 1; guint have_existing_user_accounts : 1; guint doing_initial_setup : 1; + guint session_registered : 1; } GdmDisplayPrivate; enum { @@ -115,6 +115,7 @@ enum { PROP_ALLOW_TIMED_LOGIN, PROP_HAVE_EXISTING_USER_ACCOUNTS, PROP_DOING_INITIAL_SETUP, + PROP_SESSION_REGISTERED, }; static void gdm_display_class_init (GdmDisplayClass *klass); @@ -598,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); @@ -671,7 +670,6 @@ gboolean gdm_display_unmanage (GdmDisplay *self) { GdmDisplayPrivate *priv; - gdouble elapsed; g_return_val_if_fail (GDM_IS_DISPLAY (self), FALSE); @@ -681,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); @@ -695,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); @@ -872,6 +867,17 @@ _gdm_display_set_is_local (GdmDisplay *self, } static void +_gdm_display_set_session_registered (GdmDisplay *self, + gboolean registered) +{ + GdmDisplayPrivate *priv; + + priv = gdm_display_get_instance_private (self); + g_debug ("GdmDisplay: session registered: %s", registered? "yes" : "no"); + priv->session_registered = registered; +} + +static void _gdm_display_set_launch_environment (GdmDisplay *self, GdmLaunchEnvironment *launch_environment) { @@ -959,6 +965,9 @@ gdm_display_set_property (GObject *object, case PROP_IS_INITIAL: _gdm_display_set_is_initial (self, g_value_get_boolean (value)); break; + case PROP_SESSION_REGISTERED: + _gdm_display_set_session_registered (self, g_value_get_boolean (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -1031,6 +1040,9 @@ gdm_display_get_property (GObject *object, case PROP_DOING_INITIAL_SETUP: g_value_set_boolean (value, priv->doing_initial_setup); break; + case PROP_SESSION_REGISTERED: + g_value_set_boolean (value, priv->session_registered); + break; case PROP_ALLOW_TIMED_LOGIN: g_value_set_boolean (value, priv->allow_timed_login); break; @@ -1356,6 +1368,14 @@ gdm_display_class_init (GdmDisplayClass *klass) FALSE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, + PROP_SESSION_REGISTERED, + g_param_spec_boolean ("session-registered", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_LAUNCH_ENVIRONMENT, g_param_spec_object ("launch-environment", NULL, @@ -1381,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 @@ -1419,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); } @@ -1720,7 +1735,6 @@ void gdm_display_stop_greeter_session (GdmDisplay *self) { GdmDisplayPrivate *priv; - GError *error = NULL; priv = gdm_display_get_instance_private (self); diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c index 98daca48..ee41308b 100644 --- a/daemon/gdm-local-display-factory.c +++ b/daemon/gdm-local-display-factory.c @@ -64,9 +64,8 @@ struct _GdmLocalDisplayFactory guint seat_removed_id; #if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER) - char *tty_of_active_vt; + unsigned int active_vt; guint active_vt_watch_id; - guint wait_to_finish_timeout_id; #endif }; @@ -299,6 +298,25 @@ finish_waiting_displays_on_seat (GdmLocalDisplayFactory *factory, } 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", ®istered, NULL); + + if (!registered) + return; + + g_debug ("GdmLocalDisplayFactory: session registered on display, looking for any background displays to kill"); + + finish_waiting_displays_on_seat (factory, "seat0"); +} + +static void on_display_status_changed (GdmDisplay *display, GParamSpec *arg1, GdmLocalDisplayFactory *factory) @@ -376,6 +394,13 @@ on_display_status_changed (GdmDisplay *display, case GDM_DISPLAY_PREPARED: break; case GDM_DISPLAY_MANAGED: +#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER) + g_signal_connect_object (display, + "notify::session-registered", + G_CALLBACK (on_session_registered_cb), + factory, + 0); +#endif break; case GDM_DISPLAY_WAITING_TO_FINISH: break; @@ -604,14 +629,6 @@ 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) -{ - finish_waiting_displays_on_seat (factory, "seat0"); - factory->wait_to_finish_timeout_id = 0; - return G_SOURCE_REMOVE; -} - static void maybe_stop_greeter_in_background (GdmLocalDisplayFactory *factory, GdmDisplay *display) @@ -643,16 +660,8 @@ maybe_stop_greeter_in_background (GdmLocalDisplayFactory *factory, } 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); - - factory->wait_to_finish_timeout_id = - g_timeout_add_seconds (WAIT_TO_FINISH_TIMEOUT, - (GSourceFunc)wait_to_finish_timeout, - factory); + g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_WAITING_TO_FINISH, NULL); } static gboolean @@ -661,13 +670,12 @@ on_vt_changed (GIOChannel *source, GdmLocalDisplayFactory *factory) { GIOStatus status; - static const char *tty_of_initial_vt = "tty" GDM_INITIAL_VT; - g_autofree char *tty_of_previous_vt = NULL; g_autofree char *tty_of_active_vt = NULL; g_autofree char *login_session_id = NULL; g_autofree char *active_session_id = NULL; + unsigned int previous_vt, new_vt; const char *session_type = NULL; - int ret; + int ret, n_returned; g_debug ("GdmLocalDisplayFactory: received VT change event"); g_io_channel_seek_position (source, 0, G_SEEK_SET, NULL); @@ -703,38 +711,43 @@ on_vt_changed (GIOChannel *source, g_strchomp (tty_of_active_vt); + errno = 0; + n_returned = sscanf (tty_of_active_vt, "tty%u", &new_vt); + + if (n_returned != 1 || errno != 0) { + g_critical ("GdmLocalDisplayFactory: Couldn't read active VT (got '%s')", + tty_of_active_vt); + return G_SOURCE_CONTINUE; + } + /* don't do anything if we're on the same VT we were before */ - if (g_strcmp0 (tty_of_active_vt, factory->tty_of_active_vt) == 0) { + if (new_vt == factory->active_vt) { g_debug ("GdmLocalDisplayFactory: VT changed to the same VT, ignoring"); return G_SOURCE_CONTINUE; } - tty_of_previous_vt = g_steal_pointer (&factory->tty_of_active_vt); - factory->tty_of_active_vt = g_steal_pointer (&tty_of_active_vt); + previous_vt = factory->active_vt; + factory->active_vt = new_vt; /* don't do anything at start up */ - if (tty_of_previous_vt == NULL) { - g_debug ("GdmLocalDisplayFactory: VT is %s at startup", - factory->tty_of_active_vt); + if (previous_vt == 0) { + g_debug ("GdmLocalDisplayFactory: VT is %u at startup", + factory->active_vt); return G_SOURCE_CONTINUE; } - g_debug ("GdmLocalDisplayFactory: VT changed from %s to %s", - tty_of_previous_vt, factory->tty_of_active_vt); + g_debug ("GdmLocalDisplayFactory: VT changed from %u to %u", + previous_vt, factory->active_vt); /* if the old VT was running a wayland login screen kill it */ if (gdm_get_login_window_session_id ("seat0", &login_session_id)) { - unsigned int vt; - - ret = sd_session_get_vt (login_session_id, &vt); - if (ret == 0 && vt != 0) { - g_autofree char *tty_of_login_window_vt = NULL; - - tty_of_login_window_vt = g_strdup_printf ("tty%u", vt); + unsigned int login_window_vt; - g_debug ("GdmLocalDisplayFactory: tty of login window is %s", tty_of_login_window_vt); - if (g_strcmp0 (tty_of_login_window_vt, tty_of_previous_vt) == 0) { + ret = sd_session_get_vt (login_session_id, &login_window_vt); + if (ret == 0 && login_window_vt != 0) { + g_debug ("GdmLocalDisplayFactory: VT of login window is %u", login_window_vt); + if (login_window_vt == previous_vt) { GdmDisplayStore *store; GdmDisplay *display; @@ -744,7 +757,6 @@ on_vt_changed (GIOChannel *source, display = gdm_display_store_find (store, lookup_by_session_id, (gpointer) login_session_id); - if (display != NULL) maybe_stop_greeter_in_background (factory, display); } else { @@ -757,7 +769,7 @@ on_vt_changed (GIOChannel *source, * on it (unless a login screen is already running elsewhere, then * jump to that login screen) */ - if (strcmp (factory->tty_of_active_vt, tty_of_initial_vt) != 0) { + if (factory->active_vt != GDM_INITIAL_VT) { g_debug ("GdmLocalDisplayFactory: active VT is not initial VT, so ignoring"); return G_SOURCE_CONTINUE; } @@ -827,16 +839,10 @@ 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; } - - g_clear_pointer (&factory->tty_of_active_vt, g_free); #endif } diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c index 980aa62d..23e3b85d 100644 --- a/daemon/gdm-manager.c +++ b/daemon/gdm-manager.c @@ -804,6 +804,35 @@ gdm_manager_handle_register_display (GdmDBusManager *manager, } static gboolean +gdm_manager_handle_register_session (GdmDBusManager *manager, + GDBusMethodInvocation *invocation, + GVariant *details) +{ + GdmManager *self = GDM_MANAGER (manager); + GdmDisplay *display; + const char *sender; + GDBusConnection *connection; + + sender = g_dbus_method_invocation_get_sender (invocation); + connection = g_dbus_method_invocation_get_connection (invocation); + + get_display_and_details_for_bus_sender (self, connection, sender, &display, + NULL, NULL, NULL, NULL, NULL, NULL, NULL); + + g_debug ("GdmManager: trying to register new session on display %p", display); + + if (display != NULL) + g_object_set (G_OBJECT (display), "session-registered", TRUE, NULL); + else + g_debug ("GdmManager: No display, not registering"); + + gdm_dbus_manager_complete_register_session (GDM_DBUS_MANAGER (manager), + invocation); + + return TRUE; +} + +static gboolean gdm_manager_handle_open_session (GdmDBusManager *manager, GDBusMethodInvocation *invocation) { @@ -1159,6 +1188,7 @@ static void manager_interface_init (GdmDBusManagerIface *interface) { interface->handle_register_display = gdm_manager_handle_register_display; + interface->handle_register_session = gdm_manager_handle_register_session; interface->handle_open_session = gdm_manager_handle_open_session; interface->handle_open_reauthentication_channel = gdm_manager_handle_open_reauthentication_channel; } diff --git a/daemon/gdm-manager.xml b/daemon/gdm-manager.xml index f11f3fb7..92ef1d02 100644 --- a/daemon/gdm-manager.xml +++ b/daemon/gdm-manager.xml @@ -4,6 +4,9 @@ <method name="RegisterDisplay"> <arg name="details" direction="in" type="a{ss}"/> </method> + <method name="RegisterSession"> + <arg name="details" direction="in" type="a{sv}"/> + </method> <method name="OpenSession"> <arg name="address" direction="out" type="s"/> </method> diff --git a/daemon/gdm-server.c b/daemon/gdm-server.c index 7962de22..1ba00d45 100644 --- a/daemon/gdm-server.c +++ b/daemon/gdm-server.c @@ -753,7 +753,7 @@ gdm_server_start (GdmServer *server) /* Hardcode the VT for the initial X server, but nothing else */ if (server->is_initial) { - vtarg = "vt" GDM_INITIAL_VT; + vtarg = "vt" G_STRINGIFY (GDM_INITIAL_VT); } /* fork X server process */ diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c index 640cdbb6..a5f90c4b 100644 --- a/daemon/gdm-session-worker.c +++ b/daemon/gdm-session-worker.c @@ -2224,7 +2224,7 @@ set_up_for_new_vt (GdmSessionWorker *worker) } if (worker->priv->display_is_initial) { - session_vt = atoi (GDM_INITIAL_VT); + session_vt = GDM_INITIAL_VT; } else { if (ioctl(fd, VT_OPENQRY, &session_vt) < 0) { g_debug ("GdmSessionWorker: couldn't open new VT: %m"); 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 { @@ -3178,6 +3185,38 @@ update_session_type (GdmSession *self) } 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) { GError *error; 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, ®ister_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..58865a6c 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, ®ister_session, "Register session after a delay", NULL }, { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args, "", "" }, { NULL } }; @@ -896,6 +929,9 @@ main (int argc, goto out; } + if (!connect_to_display_manager (state)) + goto out; + ret = register_display (state, state->cancellable); if (!ret) { @@ -912,6 +948,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 */ |