summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRay Strode <halfline@gmail.com>2023-05-08 13:54:13 +0000
committerRay Strode <halfline@gmail.com>2023-05-08 13:54:13 +0000
commit208cc826a71e8c0f3cd33f5711c78fc3cc85e2e4 (patch)
treed5352a280cd865a47a906f06ecf6874fe1b9fa49
parentd07f5dcd65a5d9bdd836c259dd760f59fce9a6df (diff)
parentea2b25c883055f95f027519a2e9f7c46f474fb43 (diff)
downloadgdm-208cc826a71e8c0f3cd33f5711c78fc3cc85e2e4.tar.gz
Merge branch 'wayland-mutliseat-enablement' into 'main'
Multiseat enablement for Wayland (gdm side) Closes #654 See merge request GNOME/gdm!174
-rw-r--r--daemon/gdm-local-display-factory.c118
-rw-r--r--daemon/gdm-manager.c3
-rw-r--r--daemon/gdm-session-worker.c43
-rw-r--r--daemon/gdm-session.c5
4 files changed, 102 insertions, 67 deletions
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
index 0b7e8928..e8fb4779 100644
--- a/daemon/gdm-local-display-factory.c
+++ b/daemon/gdm-local-display-factory.c
@@ -513,8 +513,10 @@ on_display_status_changed (GdmDisplay *display,
int status;
int num;
char *seat_id = NULL;
+ char *seat_active_session = NULL;
char *session_type = NULL;
char *session_class = NULL;
+ char *session_id = NULL;
gboolean is_initial = TRUE;
gboolean is_local = TRUE;
@@ -531,8 +533,11 @@ on_display_status_changed (GdmDisplay *display,
"is-local", &is_local,
"session-type", &session_type,
"session-class", &session_class,
+ "session-id", &session_id,
NULL);
+ sd_seat_get_active (seat_id, &seat_active_session, NULL);
+
status = gdm_display_get_status (display);
g_debug ("GdmLocalDisplayFactory: display status changed: %d", status);
@@ -545,17 +550,18 @@ on_display_status_changed (GdmDisplay *display,
}
gdm_display_factory_queue_purge_displays (GDM_DISPLAY_FACTORY (factory));
- /* if this is a local display, do a full resync. Only
- * seats without displays will get created anyway. This
- * ensures we get a new login screen when the user logs out,
- * if there isn't one.
+ /* if this is a local display, ensure that we get a login
+ * screen when the user logs out.
*/
if (is_local &&
- (g_strcmp0 (session_class, "greeter") != 0 || factory->active_vt == GDM_INITIAL_VT)) {
+ ((g_strcmp0 (session_class, "greeter") != 0 &&
+ (!seat_active_session || g_strcmp0(session_id, seat_active_session) == 0)) ||
+ factory->active_vt == GDM_INITIAL_VT ||
+ g_strcmp0 (seat_id, "seat0") != 0)) {
/* reset num failures */
factory->num_failures = 0;
- gdm_local_display_factory_sync_seats (factory);
+ ensure_display_for_seat (factory, seat_id);
}
break;
case GDM_DISPLAY_FAILED:
@@ -596,8 +602,10 @@ on_display_status_changed (GdmDisplay *display,
}
g_free (seat_id);
+ g_free (seat_active_session);
g_free (session_type);
g_free (session_class);
+ g_free (session_id);
}
static gboolean
@@ -633,6 +641,21 @@ lookup_prepared_display_by_seat_id (const char *id,
return lookup_by_seat_id (id, display, user_data);
}
+static gboolean
+lookup_managed_display_by_seat_id (const char *id,
+ GdmDisplay *display,
+ gpointer user_data)
+{
+ int status;
+
+ status = gdm_display_get_status (display);
+
+ if (status != GDM_DISPLAY_MANAGED)
+ return FALSE;
+
+ return lookup_by_seat_id (id, display, user_data);
+}
+
#ifdef HAVE_UDEV
static gboolean
udev_is_settled (GdmLocalDisplayFactory *factory)
@@ -747,7 +770,7 @@ get_display_for_seat (GdmLocalDisplayFactory *factory,
if (is_seat0)
display = gdm_display_store_find (store, lookup_prepared_display_by_seat_id, (gpointer) seat_id);
else
- display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id);
+ display = gdm_display_store_find (store, lookup_managed_display_by_seat_id, (gpointer) seat_id);
return display;
}
@@ -758,6 +781,7 @@ ensure_display_for_seat (GdmLocalDisplayFactory *factory,
{
gboolean seat_supports_graphics;
gboolean is_seat0;
+ gboolean falling_back;
g_auto (GStrv) session_types = NULL;
const char *legacy_session_types[] = { "x11", NULL };
GdmDisplay *display = NULL;
@@ -767,13 +791,6 @@ ensure_display_for_seat (GdmLocalDisplayFactory *factory,
g_debug ("GdmLocalDisplayFactory: display for seat %s requested", seat_id);
- /* Ensure we don't create the same display more than once */
- display = get_display_for_seat (factory, seat_id);
- if (display != NULL) {
- g_debug ("GdmLocalDisplayFactory: display for %s already created", seat_id);
- return;
- }
-
/* If we already have a login window, switch to it */
if (gdm_get_login_window_session_id (seat_id, &login_session_id)) {
GdmDisplay *display;
@@ -828,24 +845,16 @@ ensure_display_for_seat (GdmLocalDisplayFactory *factory,
}
is_seat0 = g_strcmp0 (seat_id, "seat0") == 0;
- if (is_seat0) {
- gboolean falling_back;
- falling_back = factory->num_failures > 0;
- session_types = gdm_local_display_factory_get_session_types (factory, falling_back);
+ falling_back = factory->num_failures > 0;
+ session_types = gdm_local_display_factory_get_session_types (factory, falling_back);
- if (session_types == NULL) {
- g_debug ("GdmLocalDisplayFactory: Both Wayland and Xorg are unavailable");
- seat_supports_graphics = FALSE;
- } else {
- g_debug ("GdmLocalDisplayFactory: New displays on seat0 will use %s%s",
- session_types[0], falling_back? " fallback" : "");
- }
+ if (session_types == NULL) {
+ g_debug ("GdmLocalDisplayFactory: Both Wayland and Xorg are unavailable");
+ seat_supports_graphics = FALSE;
} else {
- g_debug ("GdmLocalDisplayFactory: New displays on seat %s will use X11 fallback", seat_id);
- /* Force legacy X11 for all auxiliary seats */
- seat_supports_graphics = TRUE;
- session_types = g_strdupv ((char **) legacy_session_types);
+ g_debug ("GdmLocalDisplayFactory: New displays on seat0 will use %s%s",
+ session_types[0], falling_back? " fallback" : "");
}
/* For seat0, we have a fallback logic to still try starting it after
@@ -902,18 +911,23 @@ ensure_display_for_seat (GdmLocalDisplayFactory *factory,
g_debug ("GdmLocalDisplayFactory: %s login display for seat %s requested",
session_types[0], seat_id);
+ /* Ensure we don't create the same display more than once */
+ display = get_display_for_seat (factory, seat_id);
+ if (display != NULL) {
+ g_debug ("GdmLocalDisplayFactory: display for %s already created", seat_id);
+ return;
+ }
+
g_debug ("GdmLocalDisplayFactory: Adding display on seat %s", seat_id);
#ifdef ENABLE_USER_DISPLAY_SERVER
if (g_strcmp0 (preferred_display_server, "wayland") == 0 ||
g_strcmp0 (preferred_display_server, "xorg") == 0) {
- if (is_seat0) {
- display = gdm_local_display_new ();
- g_object_set (G_OBJECT (display),
- "session-type", session_types[0],
- "supported-session-types", session_types,
- NULL);
- }
+ display = gdm_local_display_new ();
+ g_object_set (G_OBJECT (display),
+ "session-type", session_types[0],
+ "supported-session-types", session_types,
+ NULL);
}
#endif
@@ -1037,19 +1051,39 @@ on_seat_properties_changed (GDBusConnection *connection,
const gchar *seat = NULL;
g_autoptr(GVariant) changed_props = NULL;
g_autoptr(GVariant) changed_prop = NULL;
+ g_autoptr(GVariant) reply = NULL;
+ g_autoptr(GVariant) reply_value = NULL;
+ g_autoptr(GError) error = NULL;
g_autofree const gchar **invalidated_props = NULL;
gboolean changed = FALSE;
int ret;
- /* Extract seat id, i.e. the last element of the object path. */
- seat = strrchr (object_path, '/');
- if (seat == NULL)
+ /* Acquire seat name */
+ reply = g_dbus_connection_call_sync (connection,
+ sender_name,
+ object_path,
+ "org.freedesktop.DBus.Properties",
+ "Get",
+ g_variant_new ("(ss)",
+ "org.freedesktop.login1.Seat",
+ "Id"),
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1, NULL, &error);
+
+ if (reply == NULL) {
+ g_debug ("could not acquire seat name: %s", error->message);
return;
- seat += 1;
+ }
+
+ g_variant_get (reply, "(v)", &reply_value);
- /* Valid seat IDs must start with seat, i.e. ignore "auto" */
- if (!g_str_has_prefix (seat, "seat"))
+ seat = g_variant_get_string (reply_value, NULL);
+
+ if (seat == NULL) {
+ g_debug ("seat name is not string");
return;
+ }
g_variant_get (parameters, "(s@a{sv}^a&s)", NULL, &changed_props, &invalidated_props);
diff --git a/daemon/gdm-manager.c b/daemon/gdm-manager.c
index 8611e2ed..b08b564a 100644
--- a/daemon/gdm-manager.c
+++ b/daemon/gdm-manager.c
@@ -1644,8 +1644,7 @@ create_display_for_user_session (GdmManager *self,
const char *session_id)
{
GdmDisplay *display;
- /* at the moment we only create GdmLocalDisplay objects on seat0 */
- const char *seat_id = "seat0";
+ g_autofree const char *seat_id = gdm_session_get_display_seat_id (session);
display = gdm_local_display_new ();
diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
index 13e259c3..dd05658d 100644
--- a/daemon/gdm-session-worker.c
+++ b/daemon/gdm-session-worker.c
@@ -1224,10 +1224,13 @@ gdm_session_worker_initialize_pam (GdmSessionWorker *worker,
g_debug ("GdmSessionWorker: state SETUP_COMPLETE");
gdm_session_worker_set_state (worker, GDM_SESSION_WORKER_STATE_SETUP_COMPLETE);
- /* Temporarily set PAM_TTY with the login VT,
- PAM_TTY will be reset with the users VT right before the user session is opened */
- g_snprintf (tty_string, 256, "/dev/tty%d", GDM_INITIAL_VT);
- pam_set_item (worker->pam_handle, PAM_TTY, tty_string);
+ if (strcmp (seat_id, "seat0") == 0) {
+ /* Temporarily set PAM_TTY with the login VT,
+ PAM_TTY will be reset with the users VT right before the user session is opened */
+ g_snprintf (tty_string, 256, "/dev/tty%d", GDM_INITIAL_VT);
+ pam_set_item (worker->pam_handle, PAM_TTY, tty_string);
+ }
+
if (!display_is_local)
worker->password_is_required = TRUE;
@@ -2340,22 +2343,24 @@ gdm_session_worker_open_session (GdmSessionWorker *worker,
g_assert (worker->state == GDM_SESSION_WORKER_STATE_ACCOUNT_DETAILS_SAVED);
g_assert (geteuid () == 0);
- switch (worker->display_mode) {
- case GDM_SESSION_DISPLAY_MODE_REUSE_VT:
- if (!set_up_for_current_vt (worker, error)) {
- return FALSE;
- }
- break;
- case GDM_SESSION_DISPLAY_MODE_NEW_VT:
- case GDM_SESSION_DISPLAY_MODE_LOGIND_MANAGED:
- if (!set_up_for_new_vt (worker)) {
- g_set_error (error,
- GDM_SESSION_WORKER_ERROR,
- GDM_SESSION_WORKER_ERROR_OPENING_SESSION,
- "Unable to open VT");
- return FALSE;
+ if (g_strcmp0 (worker->display_seat_id, "seat0") == 0) {
+ switch (worker->display_mode) {
+ case GDM_SESSION_DISPLAY_MODE_REUSE_VT:
+ if (!set_up_for_current_vt (worker, error)) {
+ return FALSE;
+ }
+ break;
+ case GDM_SESSION_DISPLAY_MODE_NEW_VT:
+ case GDM_SESSION_DISPLAY_MODE_LOGIND_MANAGED:
+ if (!set_up_for_new_vt (worker)) {
+ g_set_error (error,
+ GDM_SESSION_WORKER_ERROR,
+ GDM_SESSION_WORKER_ERROR_OPENING_SESSION,
+ "Unable to open VT");
+ return FALSE;
+ }
+ break;
}
- break;
}
flags = 0;
diff --git a/daemon/gdm-session.c b/daemon/gdm-session.c
index 0b438651..ebb9213d 100644
--- a/daemon/gdm-session.c
+++ b/daemon/gdm-session.c
@@ -3363,11 +3363,8 @@ gdm_session_get_display_mode (GdmSession *self)
self->is_program_session? "yes" : "no",
self->display_seat_id);
- /* Non-seat0 sessions share their X server with their login screen
- * for now.
- */
if (g_strcmp0 (self->display_seat_id, "seat0") != 0) {
- return GDM_SESSION_DISPLAY_MODE_REUSE_VT;
+ return GDM_SESSION_DISPLAY_MODE_LOGIND_MANAGED;
}
#ifdef ENABLE_USER_DISPLAY_SERVER