|
|
400dab |
From 0ff911467265831006aac6216060dbecff84c1cb Mon Sep 17 00:00:00 2001
|
|
|
400dab |
From: Hans de Goede <hdegoede@redhat.com>
|
|
|
400dab |
Date: Tue, 4 Sep 2018 10:56:45 +0200
|
|
|
400dab |
Subject: [PATCH 30/51] daemon: Move the waiting the session to have taken over
|
|
|
400dab |
the fb to gdm-local-display-factory
|
|
|
400dab |
|
|
|
400dab |
Commit 708618746683 ("gdm-wayland-session,gdm-x-session: register after
|
|
|
400dab |
delay") delayed displays changing their status from PREPARED to MANAGED
|
|
|
400dab |
so that their status would not change until the session has had a change
|
|
|
400dab |
to install its own framebuffer and tell the GPU to scanout this new fb.
|
|
|
400dab |
|
|
|
400dab |
Commit 74ee77717df7 ("local-display-factory: defer killing greeter until
|
|
|
400dab |
new session registers") uses this to avoid a flicker when transitioning
|
|
|
400dab |
from the greeter to the user-session by deferring the stopping of the
|
|
|
400dab |
greeter-session until the new display moves to the MANAGED state.
|
|
|
400dab |
|
|
|
400dab |
But this only works when transitioning to a new user-session, when moving
|
|
|
400dab |
to an existing user-session (fast user switching) the display already
|
|
|
400dab |
is in MANAGED state and instead of deferring the stopping of the greeter
|
|
|
400dab |
commit 74ee77717df7 causes us to now never stop the greeter-session.
|
|
|
400dab |
|
|
|
400dab |
This commit fixes this by starting a timeout when switching away from
|
|
|
400dab |
the initial-vt and letting that timeout stop the greeter-session.
|
|
|
400dab |
|
|
|
400dab |
This commit removes the finish_waiting_displays_on_seat() call when the
|
|
|
400dab |
display's status changes to MANAGED, so that we still only have one code
|
|
|
400dab |
path stopping the greeter and not two.
|
|
|
400dab |
|
|
|
400dab |
This means we also no longer need to delay registering the display. So this
|
|
|
400dab |
commit removes the code adding the delay (reverts commit 74ee77717df7).
|
|
|
400dab |
|
|
|
400dab |
Note this commit uses a delay of 10 seconds, rather then 2 seconds. The
|
|
|
400dab |
transition to a new user-session takes about 8 seconds on my budget
|
|
|
400dab |
Apollo Lake based laptop (with SSD).
|
|
|
400dab |
|
|
|
400dab |
Note this all really is a workaround, the proper solution for this would
|
|
|
400dab |
be able to tell the kernel to keep the greeter framebuffer around until
|
|
|
400dab |
a new framebuffer is installed. There is a patch to add a new unref_fb
|
|
|
400dab |
ioctl for this: https://www.spinics.net/lists/dri-devel/msg140912.html .
|
|
|
400dab |
We need to get this patch upstream and teach mutter to use it.
|
|
|
400dab |
---
|
|
|
400dab |
daemon/gdm-local-display-factory.c | 29 ++++++++++++++++++++++++++---
|
|
|
400dab |
daemon/gdm-wayland-session.c | 23 +++++++----------------
|
|
|
400dab |
daemon/gdm-x-session.c | 25 ++++++++-----------------
|
|
|
400dab |
3 files changed, 41 insertions(+), 36 deletions(-)
|
|
|
400dab |
|
|
|
400dab |
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
|
|
|
400dab |
index bc6ac6855..be6b377be 100644
|
|
|
400dab |
--- a/daemon/gdm-local-display-factory.c
|
|
|
400dab |
+++ b/daemon/gdm-local-display-factory.c
|
|
|
400dab |
@@ -22,76 +22,78 @@
|
|
|
400dab |
|
|
|
400dab |
#include <stdlib.h>
|
|
|
400dab |
#include <stdio.h>
|
|
|
400dab |
|
|
|
400dab |
#include <glib.h>
|
|
|
400dab |
#include <glib/gi18n.h>
|
|
|
400dab |
#include <glib-object.h>
|
|
|
400dab |
#include <gio/gio.h>
|
|
|
400dab |
|
|
|
400dab |
#include <systemd/sd-login.h>
|
|
|
400dab |
|
|
|
400dab |
#include "gdm-common.h"
|
|
|
400dab |
#include "gdm-manager.h"
|
|
|
400dab |
#include "gdm-display-factory.h"
|
|
|
400dab |
#include "gdm-local-display-factory.h"
|
|
|
400dab |
#include "gdm-local-display-factory-glue.h"
|
|
|
400dab |
|
|
|
400dab |
#include "gdm-settings-keys.h"
|
|
|
400dab |
#include "gdm-settings-direct.h"
|
|
|
400dab |
#include "gdm-display-store.h"
|
|
|
400dab |
#include "gdm-local-display.h"
|
|
|
400dab |
#include "gdm-legacy-display.h"
|
|
|
400dab |
|
|
|
400dab |
#define GDM_LOCAL_DISPLAY_FACTORY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_LOCAL_DISPLAY_FACTORY, GdmLocalDisplayFactoryPrivate))
|
|
|
400dab |
|
|
|
400dab |
#define GDM_DBUS_PATH "/org/gnome/DisplayManager"
|
|
|
400dab |
#define GDM_LOCAL_DISPLAY_FACTORY_DBUS_PATH GDM_DBUS_PATH "/LocalDisplayFactory"
|
|
|
400dab |
#define GDM_MANAGER_DBUS_NAME "org.gnome.DisplayManager.LocalDisplayFactory"
|
|
|
400dab |
|
|
|
400dab |
#define MAX_DISPLAY_FAILURES 5
|
|
|
400dab |
+#define WAIT_TO_FINISH_TIMEOUT 10 /* seconds */
|
|
|
400dab |
|
|
|
400dab |
struct GdmLocalDisplayFactoryPrivate
|
|
|
400dab |
{
|
|
|
400dab |
GdmDBusLocalDisplayFactory *skeleton;
|
|
|
400dab |
GDBusConnection *connection;
|
|
|
400dab |
GHashTable *used_display_numbers;
|
|
|
400dab |
|
|
|
400dab |
/* FIXME: this needs to be per seat? */
|
|
|
400dab |
guint num_failures;
|
|
|
400dab |
|
|
|
400dab |
guint seat_new_id;
|
|
|
400dab |
guint seat_removed_id;
|
|
|
400dab |
|
|
|
400dab |
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
|
|
400dab |
char *tty_of_active_vt;
|
|
|
400dab |
guint active_vt_watch_id;
|
|
|
400dab |
+ guint wait_to_finish_timeout_id;
|
|
|
400dab |
#endif
|
|
|
400dab |
};
|
|
|
400dab |
|
|
|
400dab |
enum {
|
|
|
400dab |
PROP_0,
|
|
|
400dab |
};
|
|
|
400dab |
|
|
|
400dab |
static void gdm_local_display_factory_class_init (GdmLocalDisplayFactoryClass *klass);
|
|
|
400dab |
static void gdm_local_display_factory_init (GdmLocalDisplayFactory *factory);
|
|
|
400dab |
static void gdm_local_display_factory_finalize (GObject *object);
|
|
|
400dab |
|
|
|
400dab |
static GdmDisplay *create_display (GdmLocalDisplayFactory *factory,
|
|
|
400dab |
const char *seat_id,
|
|
|
400dab |
const char *session_type,
|
|
|
400dab |
gboolean initial_display);
|
|
|
400dab |
|
|
|
400dab |
static void on_display_status_changed (GdmDisplay *display,
|
|
|
400dab |
GParamSpec *arg1,
|
|
|
400dab |
GdmLocalDisplayFactory *factory);
|
|
|
400dab |
|
|
|
400dab |
static gboolean gdm_local_display_factory_sync_seats (GdmLocalDisplayFactory *factory);
|
|
|
400dab |
static gpointer local_display_factory_object = NULL;
|
|
|
400dab |
static gboolean lookup_by_session_id (const char *id,
|
|
|
400dab |
GdmDisplay *display,
|
|
|
400dab |
gpointer user_data);
|
|
|
400dab |
|
|
|
400dab |
G_DEFINE_TYPE (GdmLocalDisplayFactory, gdm_local_display_factory, GDM_TYPE_DISPLAY_FACTORY)
|
|
|
400dab |
|
|
|
400dab |
GQuark
|
|
|
400dab |
gdm_local_display_factory_error_quark (void)
|
|
|
400dab |
@@ -354,61 +356,60 @@ on_display_status_changed (GdmDisplay *display,
|
|
|
400dab |
/* Create a new equivalent display if it was static */
|
|
|
400dab |
if (is_local) {
|
|
|
400dab |
|
|
|
400dab |
factory->priv->num_failures++;
|
|
|
400dab |
|
|
|
400dab |
if (factory->priv->num_failures > MAX_DISPLAY_FAILURES) {
|
|
|
400dab |
/* oh shit */
|
|
|
400dab |
g_warning ("GdmLocalDisplayFactory: maximum number of X display failures reached: check X server log for errors");
|
|
|
400dab |
} else {
|
|
|
400dab |
#ifdef ENABLE_WAYLAND_SUPPORT
|
|
|
400dab |
if (g_strcmp0 (session_type, "wayland") == 0) {
|
|
|
400dab |
g_free (session_type);
|
|
|
400dab |
session_type = NULL;
|
|
|
400dab |
|
|
|
400dab |
/* workaround logind race for now
|
|
|
400dab |
* bug 1643874
|
|
|
400dab |
*/
|
|
|
400dab |
g_usleep (2 * G_USEC_PER_SEC);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
#endif
|
|
|
400dab |
create_display (factory, seat_id, session_type, is_initial);
|
|
|
400dab |
}
|
|
|
400dab |
}
|
|
|
400dab |
break;
|
|
|
400dab |
case GDM_DISPLAY_UNMANAGED:
|
|
|
400dab |
break;
|
|
|
400dab |
case GDM_DISPLAY_PREPARED:
|
|
|
400dab |
break;
|
|
|
400dab |
case GDM_DISPLAY_MANAGED:
|
|
|
400dab |
- finish_waiting_displays_on_seat (factory, seat_id);
|
|
|
400dab |
break;
|
|
|
400dab |
case GDM_DISPLAY_WAITING_TO_FINISH:
|
|
|
400dab |
break;
|
|
|
400dab |
default:
|
|
|
400dab |
g_assert_not_reached ();
|
|
|
400dab |
break;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
g_free (seat_id);
|
|
|
400dab |
g_free (session_type);
|
|
|
400dab |
g_free (session_class);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static gboolean
|
|
|
400dab |
lookup_by_seat_id (const char *id,
|
|
|
400dab |
GdmDisplay *display,
|
|
|
400dab |
gpointer user_data)
|
|
|
400dab |
{
|
|
|
400dab |
const char *looking_for = user_data;
|
|
|
400dab |
char *current;
|
|
|
400dab |
gboolean res;
|
|
|
400dab |
|
|
|
400dab |
g_object_get (G_OBJECT (display), "seat-id", ¤t, NULL);
|
|
|
400dab |
|
|
|
400dab |
res = g_strcmp0 (current, looking_for) == 0;
|
|
|
400dab |
|
|
|
400dab |
g_free(current);
|
|
|
400dab |
|
|
|
400dab |
return res;
|
|
|
400dab |
}
|
|
|
400dab |
@@ -593,83 +594,101 @@ on_seat_new (GDBusConnection *connection,
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
on_seat_removed (GDBusConnection *connection,
|
|
|
400dab |
const gchar *sender_name,
|
|
|
400dab |
const gchar *object_path,
|
|
|
400dab |
const gchar *interface_name,
|
|
|
400dab |
const gchar *signal_name,
|
|
|
400dab |
GVariant *parameters,
|
|
|
400dab |
gpointer user_data)
|
|
|
400dab |
{
|
|
|
400dab |
const char *seat;
|
|
|
400dab |
|
|
|
400dab |
g_variant_get (parameters, "(&s&o)", &seat, NULL);
|
|
|
400dab |
delete_display (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
|
|
400dab |
static gboolean
|
|
|
400dab |
lookup_by_session_id (const char *id,
|
|
|
400dab |
GdmDisplay *display,
|
|
|
400dab |
gpointer user_data)
|
|
|
400dab |
{
|
|
|
400dab |
const char *looking_for = user_data;
|
|
|
400dab |
const char *current;
|
|
|
400dab |
|
|
|
400dab |
current = gdm_display_get_session_id (display);
|
|
|
400dab |
return g_strcmp0 (current, looking_for) == 0;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
+static gboolean
|
|
|
400dab |
+wait_to_finish_timeout (GdmLocalDisplayFactory *factory)
|
|
|
400dab |
+{
|
|
|
400dab |
+ finish_waiting_displays_on_seat (factory, "seat0");
|
|
|
400dab |
+ factory->priv->wait_to_finish_timeout_id = 0;
|
|
|
400dab |
+ return G_SOURCE_REMOVE;
|
|
|
400dab |
+}
|
|
|
400dab |
+
|
|
|
400dab |
static void
|
|
|
400dab |
-maybe_stop_greeter_in_background (GdmDisplay *display)
|
|
|
400dab |
+maybe_stop_greeter_in_background (GdmLocalDisplayFactory *factory,
|
|
|
400dab |
+ GdmDisplay *display)
|
|
|
400dab |
{
|
|
|
400dab |
g_autofree char *display_session_type = NULL;
|
|
|
400dab |
|
|
|
400dab |
if (gdm_display_get_status (display) != GDM_DISPLAY_MANAGED) {
|
|
|
400dab |
g_debug ("GdmLocalDisplayFactory: login window not in managed state, so ignoring");
|
|
|
400dab |
return;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
g_object_get (G_OBJECT (display),
|
|
|
400dab |
"session-type", &display_session_type,
|
|
|
400dab |
NULL);
|
|
|
400dab |
|
|
|
400dab |
/* we can only stop greeter for wayland sessions, since
|
|
|
400dab |
* X server would jump back on exit */
|
|
|
400dab |
if (g_strcmp0 (display_session_type, "wayland") != 0) {
|
|
|
400dab |
g_debug ("GdmLocalDisplayFactory: login window is running on Xorg, so ignoring");
|
|
|
400dab |
return;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
g_debug ("GdmLocalDisplayFactory: killing login window once its unused");
|
|
|
400dab |
g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_WAITING_TO_FINISH, NULL);
|
|
|
400dab |
+
|
|
|
400dab |
+ /* We stop the greeter after a timeout to avoid flicker */
|
|
|
400dab |
+ if (factory->priv->wait_to_finish_timeout_id != 0)
|
|
|
400dab |
+ g_source_remove (factory->priv->wait_to_finish_timeout_id);
|
|
|
400dab |
+
|
|
|
400dab |
+ factory->priv->wait_to_finish_timeout_id =
|
|
|
400dab |
+ g_timeout_add_seconds (WAIT_TO_FINISH_TIMEOUT,
|
|
|
400dab |
+ (GSourceFunc)wait_to_finish_timeout,
|
|
|
400dab |
+ factory);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static gboolean
|
|
|
400dab |
on_vt_changed (GIOChannel *source,
|
|
|
400dab |
GIOCondition condition,
|
|
|
400dab |
GdmLocalDisplayFactory *factory)
|
|
|
400dab |
{
|
|
|
400dab |
GIOStatus status;
|
|
|
400dab |
static const char *tty_of_initial_vt = "tty" GDM_INITIAL_VT;
|
|
|
400dab |
g_autofree char *tty_of_previous_vt = NULL;
|
|
|
400dab |
g_autofree char *tty_of_active_vt = NULL;
|
|
|
400dab |
g_autofree char *login_session_id = NULL;
|
|
|
400dab |
g_autofree char *active_session_id = NULL;
|
|
|
400dab |
const char *session_type = NULL;
|
|
|
400dab |
int ret;
|
|
|
400dab |
|
|
|
400dab |
g_debug ("GdmLocalDisplayFactory: received VT change event");
|
|
|
400dab |
g_io_channel_seek_position (source, 0, G_SEEK_SET, NULL);
|
|
|
400dab |
|
|
|
400dab |
if (condition & G_IO_PRI) {
|
|
|
400dab |
g_autoptr (GError) error = NULL;
|
|
|
400dab |
status = g_io_channel_read_line (source, &tty_of_active_vt, NULL, NULL, &error);
|
|
|
400dab |
|
|
|
400dab |
if (error != NULL) {
|
|
|
400dab |
g_warning ("could not read active VT from kernel: %s", error->message);
|
|
|
400dab |
}
|
|
|
400dab |
switch (status) {
|
|
|
400dab |
case G_IO_STATUS_ERROR:
|
|
|
400dab |
return G_SOURCE_REMOVE;
|
|
|
400dab |
case G_IO_STATUS_EOF:
|
|
|
400dab |
@@ -709,61 +728,61 @@ on_vt_changed (GIOChannel *source,
|
|
|
400dab |
return G_SOURCE_CONTINUE;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
g_debug ("GdmLocalDisplayFactory: VT changed from %s to %s",
|
|
|
400dab |
tty_of_previous_vt, factory->priv->tty_of_active_vt);
|
|
|
400dab |
|
|
|
400dab |
/* if the old VT was running a wayland login screen kill it
|
|
|
400dab |
*/
|
|
|
400dab |
if (gdm_get_login_window_session_id ("seat0", &login_session_id)) {
|
|
|
400dab |
unsigned int vt;
|
|
|
400dab |
|
|
|
400dab |
ret = sd_session_get_vt (login_session_id, &vt;;
|
|
|
400dab |
if (ret == 0 && vt != 0) {
|
|
|
400dab |
g_autofree char *tty_of_login_window_vt = NULL;
|
|
|
400dab |
|
|
|
400dab |
tty_of_login_window_vt = g_strdup_printf ("tty%u", vt);
|
|
|
400dab |
|
|
|
400dab |
g_debug ("GdmLocalDisplayFactory: tty of login window is %s", tty_of_login_window_vt);
|
|
|
400dab |
if (g_strcmp0 (tty_of_login_window_vt, tty_of_previous_vt) == 0) {
|
|
|
400dab |
GdmDisplayStore *store;
|
|
|
400dab |
GdmDisplay *display;
|
|
|
400dab |
|
|
|
400dab |
g_debug ("GdmLocalDisplayFactory: VT switched from login window");
|
|
|
400dab |
|
|
|
400dab |
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
|
|
400dab |
display = gdm_display_store_find (store,
|
|
|
400dab |
lookup_by_session_id,
|
|
|
400dab |
(gpointer) login_session_id);
|
|
|
400dab |
|
|
|
400dab |
if (display != NULL)
|
|
|
400dab |
- maybe_stop_greeter_in_background (display);
|
|
|
400dab |
+ maybe_stop_greeter_in_background (factory, display);
|
|
|
400dab |
} else {
|
|
|
400dab |
g_debug ("GdmLocalDisplayFactory: VT not switched from login window");
|
|
|
400dab |
}
|
|
|
400dab |
}
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
/* if user jumped back to initial vt and it's empty put a login screen
|
|
|
400dab |
* on it (unless a login screen is already running elsewhere, then
|
|
|
400dab |
* jump to that login screen)
|
|
|
400dab |
*/
|
|
|
400dab |
if (strcmp (factory->priv->tty_of_active_vt, tty_of_initial_vt) != 0) {
|
|
|
400dab |
g_debug ("GdmLocalDisplayFactory: active VT is not initial VT, so ignoring");
|
|
|
400dab |
return G_SOURCE_CONTINUE;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
ret = sd_seat_get_active ("seat0", &active_session_id, NULL);
|
|
|
400dab |
|
|
|
400dab |
if (ret == 0) {
|
|
|
400dab |
g_autofree char *state = NULL;
|
|
|
400dab |
ret = sd_session_get_state (active_session_id, &state);
|
|
|
400dab |
|
|
|
400dab |
/* if there's something already running on the active VT then bail */
|
|
|
400dab |
if (ret == 0 && g_strcmp0 (state, "closing") != 0) {
|
|
|
400dab |
g_debug ("GdmLocalDisplayFactory: initial VT is in use, so ignoring");
|
|
|
400dab |
return G_SOURCE_CONTINUE;
|
|
|
400dab |
}
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
if (gdm_local_display_factory_use_wayland ())
|
|
|
400dab |
session_type = "wayland";
|
|
|
400dab |
@@ -803,60 +822,64 @@ gdm_local_display_factory_start_monitor (GdmLocalDisplayFactory *factory)
|
|
|
400dab |
g_object_unref);
|
|
|
400dab |
|
|
|
400dab |
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
|
|
400dab |
io_channel = g_io_channel_new_file ("/sys/class/tty/tty0/active", "r", NULL);
|
|
|
400dab |
|
|
|
400dab |
if (io_channel != NULL) {
|
|
|
400dab |
factory->priv->active_vt_watch_id =
|
|
|
400dab |
g_io_add_watch (io_channel,
|
|
|
400dab |
G_IO_PRI,
|
|
|
400dab |
(GIOFunc)
|
|
|
400dab |
on_vt_changed,
|
|
|
400dab |
factory);
|
|
|
400dab |
}
|
|
|
400dab |
#endif
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
gdm_local_display_factory_stop_monitor (GdmLocalDisplayFactory *factory)
|
|
|
400dab |
{
|
|
|
400dab |
if (factory->priv->seat_new_id) {
|
|
|
400dab |
g_dbus_connection_signal_unsubscribe (factory->priv->connection,
|
|
|
400dab |
factory->priv->seat_new_id);
|
|
|
400dab |
factory->priv->seat_new_id = 0;
|
|
|
400dab |
}
|
|
|
400dab |
if (factory->priv->seat_removed_id) {
|
|
|
400dab |
g_dbus_connection_signal_unsubscribe (factory->priv->connection,
|
|
|
400dab |
factory->priv->seat_removed_id);
|
|
|
400dab |
factory->priv->seat_removed_id = 0;
|
|
|
400dab |
}
|
|
|
400dab |
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
|
|
400dab |
+ if (factory->priv->wait_to_finish_timeout_id != 0) {
|
|
|
400dab |
+ g_source_remove (factory->priv->wait_to_finish_timeout_id);
|
|
|
400dab |
+ factory->priv->wait_to_finish_timeout_id = 0;
|
|
|
400dab |
+ }
|
|
|
400dab |
if (factory->priv->active_vt_watch_id) {
|
|
|
400dab |
g_source_remove (factory->priv->active_vt_watch_id);
|
|
|
400dab |
factory->priv->active_vt_watch_id = 0;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
g_clear_pointer (&factory->priv->tty_of_active_vt, g_free);
|
|
|
400dab |
#endif
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
on_display_added (GdmDisplayStore *display_store,
|
|
|
400dab |
const char *id,
|
|
|
400dab |
GdmLocalDisplayFactory *factory)
|
|
|
400dab |
{
|
|
|
400dab |
GdmDisplay *display;
|
|
|
400dab |
|
|
|
400dab |
display = gdm_display_store_lookup (display_store, id);
|
|
|
400dab |
|
|
|
400dab |
if (display != NULL) {
|
|
|
400dab |
g_signal_connect_object (display, "notify::status",
|
|
|
400dab |
G_CALLBACK (on_display_status_changed),
|
|
|
400dab |
factory,
|
|
|
400dab |
0);
|
|
|
400dab |
|
|
|
400dab |
g_object_weak_ref (G_OBJECT (display), (GWeakNotify)on_display_disposed, factory);
|
|
|
400dab |
}
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
on_display_removed (GdmDisplayStore *display_store,
|
|
|
400dab |
diff --git a/daemon/gdm-wayland-session.c b/daemon/gdm-wayland-session.c
|
|
|
400dab |
index de1991b34..94f49e19c 100644
|
|
|
400dab |
--- a/daemon/gdm-wayland-session.c
|
|
|
400dab |
+++ b/daemon/gdm-wayland-session.c
|
|
|
400dab |
@@ -427,75 +427,60 @@ init_state (State **state)
|
|
|
400dab |
static State state_allocation;
|
|
|
400dab |
|
|
|
400dab |
*state = &state_allocation;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
clear_state (State **out_state)
|
|
|
400dab |
{
|
|
|
400dab |
State *state = *out_state;
|
|
|
400dab |
|
|
|
400dab |
g_clear_object (&state->cancellable);
|
|
|
400dab |
g_clear_object (&state->bus_connection);
|
|
|
400dab |
g_clear_object (&state->session_subprocess);
|
|
|
400dab |
g_clear_pointer (&state->environment, g_strfreev);
|
|
|
400dab |
g_clear_pointer (&state->main_loop, g_main_loop_unref);
|
|
|
400dab |
*out_state = NULL;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static gboolean
|
|
|
400dab |
on_sigterm (State *state)
|
|
|
400dab |
{
|
|
|
400dab |
g_cancellable_cancel (state->cancellable);
|
|
|
400dab |
|
|
|
400dab |
if (g_main_loop_is_running (state->main_loop)) {
|
|
|
400dab |
g_main_loop_quit (state->main_loop);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
return G_SOURCE_CONTINUE;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
-static gboolean
|
|
|
400dab |
-on_registration_delay_complete (State *state)
|
|
|
400dab |
-{
|
|
|
400dab |
- gboolean ret;
|
|
|
400dab |
-
|
|
|
400dab |
- ret = register_display (state, state->cancellable);
|
|
|
400dab |
-
|
|
|
400dab |
- if (!ret) {
|
|
|
400dab |
- g_printerr ("Unable to register display with display manager\n");
|
|
|
400dab |
- g_main_loop_quit (state->main_loop);
|
|
|
400dab |
- }
|
|
|
400dab |
-
|
|
|
400dab |
- return G_SOURCE_REMOVE;
|
|
|
400dab |
-}
|
|
|
400dab |
-
|
|
|
400dab |
int
|
|
|
400dab |
main (int argc,
|
|
|
400dab |
char **argv)
|
|
|
400dab |
{
|
|
|
400dab |
State *state = NULL;
|
|
|
400dab |
GOptionContext *context = NULL;
|
|
|
400dab |
static char **args = NULL;
|
|
|
400dab |
gboolean debug = FALSE;
|
|
|
400dab |
gboolean ret;
|
|
|
400dab |
int exit_status = EX_OK;
|
|
|
400dab |
static GOptionEntry entries [] = {
|
|
|
400dab |
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args, "", "" },
|
|
|
400dab |
{ NULL }
|
|
|
400dab |
};
|
|
|
400dab |
|
|
|
400dab |
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
|
|
|
400dab |
textdomain (GETTEXT_PACKAGE);
|
|
|
400dab |
setlocale (LC_ALL, "");
|
|
|
400dab |
|
|
|
400dab |
gdm_log_init ();
|
|
|
400dab |
|
|
|
400dab |
context = g_option_context_new (_("GNOME Display Manager Wayland Session Launcher"));
|
|
|
400dab |
g_option_context_add_main_entries (context, entries, NULL);
|
|
|
400dab |
|
|
|
400dab |
g_option_context_parse (context, &argc, &argv, NULL);
|
|
|
400dab |
g_option_context_free (context);
|
|
|
400dab |
|
|
|
400dab |
if (args == NULL || args[0] == NULL || args[1] != NULL) {
|
|
|
400dab |
g_warning ("gdm-wayland-session takes one argument (the session)");
|
|
|
400dab |
exit_status = EX_USAGE;
|
|
|
400dab |
@@ -516,49 +501,55 @@ main (int argc,
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
gdm_settings_direct_get_boolean (GDM_KEY_DEBUG, &debug);
|
|
|
400dab |
state->debug_enabled = debug;
|
|
|
400dab |
|
|
|
400dab |
gdm_log_set_debug (debug);
|
|
|
400dab |
|
|
|
400dab |
state->main_loop = g_main_loop_new (NULL, FALSE);
|
|
|
400dab |
state->cancellable = g_cancellable_new ();
|
|
|
400dab |
|
|
|
400dab |
g_unix_signal_add (SIGTERM, (GSourceFunc) on_sigterm, state);
|
|
|
400dab |
|
|
|
400dab |
ret = spawn_bus (state, state->cancellable);
|
|
|
400dab |
|
|
|
400dab |
if (!ret) {
|
|
|
400dab |
g_printerr ("Unable to run session message bus\n");
|
|
|
400dab |
exit_status = EX_SOFTWARE;
|
|
|
400dab |
goto out;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
import_environment (state, state->cancellable);
|
|
|
400dab |
|
|
|
400dab |
ret = spawn_session (state, state->cancellable);
|
|
|
400dab |
|
|
|
400dab |
if (!ret) {
|
|
|
400dab |
g_printerr ("Unable to run session\n");
|
|
|
400dab |
exit_status = EX_SOFTWARE;
|
|
|
400dab |
goto out;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
- g_timeout_add_seconds (2, (GSourceFunc) on_registration_delay_complete, state);
|
|
|
400dab |
+ ret = register_display (state, state->cancellable);
|
|
|
400dab |
+
|
|
|
400dab |
+ if (!ret) {
|
|
|
400dab |
+ g_printerr ("Unable to register display with display manager\n");
|
|
|
400dab |
+ exit_status = EX_SOFTWARE;
|
|
|
400dab |
+ goto out;
|
|
|
400dab |
+ }
|
|
|
400dab |
|
|
|
400dab |
g_main_loop_run (state->main_loop);
|
|
|
400dab |
|
|
|
400dab |
/* Only use exit status of session if we're here because it exit */
|
|
|
400dab |
|
|
|
400dab |
if (state->session_subprocess == NULL) {
|
|
|
400dab |
exit_status = state->session_exit_status;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
out:
|
|
|
400dab |
if (state != NULL) {
|
|
|
400dab |
signal_subprocesses (state);
|
|
|
400dab |
wait_on_subprocesses (state);
|
|
|
400dab |
clear_state (&state);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
return exit_status;
|
|
|
400dab |
}
|
|
|
400dab |
diff --git a/daemon/gdm-x-session.c b/daemon/gdm-x-session.c
|
|
|
400dab |
index 412999cf5..3b2fcef47 100644
|
|
|
400dab |
--- a/daemon/gdm-x-session.c
|
|
|
400dab |
+++ b/daemon/gdm-x-session.c
|
|
|
400dab |
@@ -783,75 +783,60 @@ init_state (State **state)
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static void
|
|
|
400dab |
clear_state (State **out_state)
|
|
|
400dab |
{
|
|
|
400dab |
State *state = *out_state;
|
|
|
400dab |
|
|
|
400dab |
g_clear_object (&state->cancellable);
|
|
|
400dab |
g_clear_object (&state->bus_connection);
|
|
|
400dab |
g_clear_object (&state->session_subprocess);
|
|
|
400dab |
g_clear_object (&state->x_subprocess);
|
|
|
400dab |
g_clear_pointer (&state->environment, g_strfreev);
|
|
|
400dab |
g_clear_pointer (&state->auth_file, g_free);
|
|
|
400dab |
g_clear_pointer (&state->display_name, g_free);
|
|
|
400dab |
g_clear_pointer (&state->main_loop, g_main_loop_unref);
|
|
|
400dab |
*out_state = NULL;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
static gboolean
|
|
|
400dab |
on_sigterm (State *state)
|
|
|
400dab |
{
|
|
|
400dab |
g_cancellable_cancel (state->cancellable);
|
|
|
400dab |
|
|
|
400dab |
if (g_main_loop_is_running (state->main_loop)) {
|
|
|
400dab |
g_main_loop_quit (state->main_loop);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
return G_SOURCE_CONTINUE;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
-static gboolean
|
|
|
400dab |
-on_registration_delay_complete (State *state)
|
|
|
400dab |
-{
|
|
|
400dab |
- gboolean ret;
|
|
|
400dab |
-
|
|
|
400dab |
- ret = register_display (state, state->cancellable);
|
|
|
400dab |
-
|
|
|
400dab |
- if (!ret) {
|
|
|
400dab |
- g_printerr ("Unable to register display with display manager\n");
|
|
|
400dab |
- g_main_loop_quit (state->main_loop);
|
|
|
400dab |
- }
|
|
|
400dab |
-
|
|
|
400dab |
- return G_SOURCE_REMOVE;
|
|
|
400dab |
-}
|
|
|
400dab |
-
|
|
|
400dab |
int
|
|
|
400dab |
main (int argc,
|
|
|
400dab |
char **argv)
|
|
|
400dab |
{
|
|
|
400dab |
State *state = NULL;
|
|
|
400dab |
GOptionContext *context = NULL;
|
|
|
400dab |
static char **args = NULL;
|
|
|
400dab |
static gboolean run_script = FALSE;
|
|
|
400dab |
static gboolean allow_remote_connections = FALSE;
|
|
|
400dab |
gboolean debug = FALSE;
|
|
|
400dab |
gboolean ret;
|
|
|
400dab |
int exit_status = EX_OK;
|
|
|
400dab |
static GOptionEntry entries [] = {
|
|
|
400dab |
{ "run-script", 'r', 0, G_OPTION_ARG_NONE, &run_script, N_("Run program through /etc/gdm/Xsession wrapper script"), NULL },
|
|
|
400dab |
{ "allow-remote-connections", 'a', 0, G_OPTION_ARG_NONE, &allow_remote_connections, N_("Listen on TCP socket"), NULL },
|
|
|
400dab |
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args, "", "" },
|
|
|
400dab |
{ NULL }
|
|
|
400dab |
};
|
|
|
400dab |
|
|
|
400dab |
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
|
|
|
400dab |
textdomain (GETTEXT_PACKAGE);
|
|
|
400dab |
setlocale (LC_ALL, "");
|
|
|
400dab |
|
|
|
400dab |
gdm_log_init ();
|
|
|
400dab |
|
|
|
400dab |
context = g_option_context_new (_("GNOME Display Manager X Session Launcher"));
|
|
|
400dab |
g_option_context_add_main_entries (context, entries, NULL);
|
|
|
400dab |
|
|
|
400dab |
g_option_context_parse (context, &argc, &argv, NULL);
|
|
|
400dab |
g_option_context_free (context);
|
|
|
400dab |
@@ -884,57 +869,63 @@ main (int argc,
|
|
|
400dab |
state->cancellable = g_cancellable_new ();
|
|
|
400dab |
|
|
|
400dab |
g_unix_signal_add (SIGTERM, (GSourceFunc) on_sigterm, state);
|
|
|
400dab |
|
|
|
400dab |
ret = spawn_x_server (state, allow_remote_connections, state->cancellable);
|
|
|
400dab |
|
|
|
400dab |
if (!ret) {
|
|
|
400dab |
g_printerr ("Unable to run X server\n");
|
|
|
400dab |
exit_status = EX_SOFTWARE;
|
|
|
400dab |
goto out;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
ret = spawn_bus (state, state->cancellable);
|
|
|
400dab |
|
|
|
400dab |
if (!ret) {
|
|
|
400dab |
g_printerr ("Unable to run session message bus\n");
|
|
|
400dab |
exit_status = EX_SOFTWARE;
|
|
|
400dab |
goto out;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
import_environment (state, state->cancellable);
|
|
|
400dab |
|
|
|
400dab |
ret = update_bus_environment (state, state->cancellable);
|
|
|
400dab |
|
|
|
400dab |
if (!ret) {
|
|
|
400dab |
g_printerr ("Unable to update bus environment\n");
|
|
|
400dab |
exit_status = EX_SOFTWARE;
|
|
|
400dab |
goto out;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
+ ret = register_display (state, state->cancellable);
|
|
|
400dab |
+
|
|
|
400dab |
+ if (!ret) {
|
|
|
400dab |
+ g_printerr ("Unable to register display with display manager\n");
|
|
|
400dab |
+ exit_status = EX_SOFTWARE;
|
|
|
400dab |
+ goto out;
|
|
|
400dab |
+ }
|
|
|
400dab |
+
|
|
|
400dab |
ret = spawn_session (state, run_script, state->cancellable);
|
|
|
400dab |
|
|
|
400dab |
if (!ret) {
|
|
|
400dab |
g_printerr ("Unable to run session\n");
|
|
|
400dab |
exit_status = EX_SOFTWARE;
|
|
|
400dab |
goto out;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
- g_timeout_add_seconds (2, (GSourceFunc) on_registration_delay_complete, state);
|
|
|
400dab |
-
|
|
|
400dab |
g_main_loop_run (state->main_loop);
|
|
|
400dab |
|
|
|
400dab |
/* Only use exit status of session if we're here because it exit */
|
|
|
400dab |
|
|
|
400dab |
if (state->session_subprocess == NULL) {
|
|
|
400dab |
exit_status = state->session_exit_status;
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
out:
|
|
|
400dab |
if (state != NULL) {
|
|
|
400dab |
signal_subprocesses (state);
|
|
|
400dab |
wait_on_subprocesses (state);
|
|
|
400dab |
clear_state (&state);
|
|
|
400dab |
}
|
|
|
400dab |
|
|
|
400dab |
return exit_status;
|
|
|
400dab |
}
|
|
|
400dab |
--
|
|
|
400dab |
2.27.0
|
|
|
400dab |
|