|
|
c90517 |
From 7bd3a19ad434754a91887c8b4baaaa23e9b30710 Mon Sep 17 00:00:00 2001
|
|
|
c90517 |
From: Ray Strode <rstrode@redhat.com>
|
|
|
c90517 |
Date: Fri, 31 Aug 2018 15:33:00 -0400
|
|
|
c90517 |
Subject: [PATCH 29/48] local-display-factory: defer killing greeter until new
|
|
|
c90517 |
session registers
|
|
|
c90517 |
|
|
|
c90517 |
At the moment we kill the greeter the second the VT change to the new
|
|
|
c90517 |
session happens.
|
|
|
c90517 |
|
|
|
c90517 |
That can cause flicker if the new session doesn't take over the display
|
|
|
c90517 |
quickly enough.
|
|
|
c90517 |
|
|
|
c90517 |
This commit defers killing the greeter until the new display registers.
|
|
|
c90517 |
|
|
|
c90517 |
Closes https://gitlab.gnome.org/GNOME/gdm/issues/413
|
|
|
c90517 |
---
|
|
|
c90517 |
daemon/gdm-display.h | 1 +
|
|
|
c90517 |
daemon/gdm-local-display-factory.c | 43 +++++++++++++++++++++++++-----
|
|
|
c90517 |
2 files changed, 38 insertions(+), 6 deletions(-)
|
|
|
c90517 |
|
|
|
c90517 |
diff --git a/daemon/gdm-display.h b/daemon/gdm-display.h
|
|
|
c90517 |
index 6d5e88df9..33dc3be41 100644
|
|
|
c90517 |
--- a/daemon/gdm-display.h
|
|
|
c90517 |
+++ b/daemon/gdm-display.h
|
|
|
c90517 |
@@ -13,60 +13,61 @@
|
|
|
c90517 |
* GNU General Public License for more details.
|
|
|
c90517 |
*
|
|
|
c90517 |
* You should have received a copy of the GNU General Public License
|
|
|
c90517 |
* along with this program; if not, write to the Free Software
|
|
|
c90517 |
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
c90517 |
*
|
|
|
c90517 |
*/
|
|
|
c90517 |
|
|
|
c90517 |
|
|
|
c90517 |
#ifndef __GDM_DISPLAY_H
|
|
|
c90517 |
#define __GDM_DISPLAY_H
|
|
|
c90517 |
|
|
|
c90517 |
#include <glib-object.h>
|
|
|
c90517 |
#include <gio/gio.h>
|
|
|
c90517 |
|
|
|
c90517 |
G_BEGIN_DECLS
|
|
|
c90517 |
|
|
|
c90517 |
#define GDM_TYPE_DISPLAY (gdm_display_get_type ())
|
|
|
c90517 |
#define GDM_DISPLAY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_DISPLAY, GdmDisplay))
|
|
|
c90517 |
#define GDM_DISPLAY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_DISPLAY, GdmDisplayClass))
|
|
|
c90517 |
#define GDM_IS_DISPLAY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_DISPLAY))
|
|
|
c90517 |
#define GDM_IS_DISPLAY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_DISPLAY))
|
|
|
c90517 |
#define GDM_DISPLAY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_DISPLAY, GdmDisplayClass))
|
|
|
c90517 |
|
|
|
c90517 |
typedef struct GdmDisplayPrivate GdmDisplayPrivate;
|
|
|
c90517 |
|
|
|
c90517 |
typedef enum {
|
|
|
c90517 |
GDM_DISPLAY_UNMANAGED = 0,
|
|
|
c90517 |
GDM_DISPLAY_PREPARED,
|
|
|
c90517 |
GDM_DISPLAY_MANAGED,
|
|
|
c90517 |
+ GDM_DISPLAY_WAITING_TO_FINISH,
|
|
|
c90517 |
GDM_DISPLAY_FINISHED,
|
|
|
c90517 |
GDM_DISPLAY_FAILED,
|
|
|
c90517 |
} GdmDisplayStatus;
|
|
|
c90517 |
|
|
|
c90517 |
typedef struct
|
|
|
c90517 |
{
|
|
|
c90517 |
GObject parent;
|
|
|
c90517 |
GdmDisplayPrivate *priv;
|
|
|
c90517 |
} GdmDisplay;
|
|
|
c90517 |
|
|
|
c90517 |
typedef struct
|
|
|
c90517 |
{
|
|
|
c90517 |
GObjectClass parent_class;
|
|
|
c90517 |
|
|
|
c90517 |
/* methods */
|
|
|
c90517 |
gboolean (*prepare) (GdmDisplay *display);
|
|
|
c90517 |
void (*manage) (GdmDisplay *self);
|
|
|
c90517 |
} GdmDisplayClass;
|
|
|
c90517 |
|
|
|
c90517 |
typedef enum
|
|
|
c90517 |
{
|
|
|
c90517 |
GDM_DISPLAY_ERROR_GENERAL,
|
|
|
c90517 |
GDM_DISPLAY_ERROR_GETTING_USER_INFO,
|
|
|
c90517 |
GDM_DISPLAY_ERROR_GETTING_SESSION_INFO,
|
|
|
c90517 |
} GdmDisplayError;
|
|
|
c90517 |
|
|
|
c90517 |
#define GDM_DISPLAY_ERROR gdm_display_error_quark ()
|
|
|
c90517 |
|
|
|
c90517 |
GQuark gdm_display_error_quark (void);
|
|
|
c90517 |
GType gdm_display_get_type (void);
|
|
|
c90517 |
diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
|
|
|
c90517 |
index 127127005..bc6ac6855 100644
|
|
|
c90517 |
--- a/daemon/gdm-local-display-factory.c
|
|
|
c90517 |
+++ b/daemon/gdm-local-display-factory.c
|
|
|
c90517 |
@@ -241,60 +241,90 @@ gdm_local_display_factory_create_transient_display (GdmLocalDisplayFactory *fact
|
|
|
c90517 |
|
|
|
c90517 |
display = gdm_legacy_display_new (num);
|
|
|
c90517 |
}
|
|
|
c90517 |
#endif
|
|
|
c90517 |
|
|
|
c90517 |
g_object_set (display,
|
|
|
c90517 |
"seat-id", "seat0",
|
|
|
c90517 |
"allow-timed-login", FALSE,
|
|
|
c90517 |
NULL);
|
|
|
c90517 |
|
|
|
c90517 |
store_display (factory, display);
|
|
|
c90517 |
|
|
|
c90517 |
if (! gdm_display_manage (display)) {
|
|
|
c90517 |
display = NULL;
|
|
|
c90517 |
goto out;
|
|
|
c90517 |
}
|
|
|
c90517 |
|
|
|
c90517 |
if (! gdm_display_get_id (display, id, NULL)) {
|
|
|
c90517 |
display = NULL;
|
|
|
c90517 |
goto out;
|
|
|
c90517 |
}
|
|
|
c90517 |
|
|
|
c90517 |
ret = TRUE;
|
|
|
c90517 |
out:
|
|
|
c90517 |
/* ref either held by store or not at all */
|
|
|
c90517 |
g_object_unref (display);
|
|
|
c90517 |
|
|
|
c90517 |
return ret;
|
|
|
c90517 |
}
|
|
|
c90517 |
|
|
|
c90517 |
+static gboolean
|
|
|
c90517 |
+finish_display_on_seat_if_waiting (GdmDisplayStore *display_store,
|
|
|
c90517 |
+ GdmDisplay *display,
|
|
|
c90517 |
+ const char *seat_id)
|
|
|
c90517 |
+{
|
|
|
c90517 |
+ if (gdm_display_get_status (display) != GDM_DISPLAY_WAITING_TO_FINISH)
|
|
|
c90517 |
+ return FALSE;
|
|
|
c90517 |
+
|
|
|
c90517 |
+ g_debug ("GdmLocalDisplayFactory: finish background display\n");
|
|
|
c90517 |
+ gdm_display_stop_greeter_session (display);
|
|
|
c90517 |
+ gdm_display_unmanage (display);
|
|
|
c90517 |
+ gdm_display_finish (display);
|
|
|
c90517 |
+
|
|
|
c90517 |
+ return FALSE;
|
|
|
c90517 |
+}
|
|
|
c90517 |
+
|
|
|
c90517 |
+static void
|
|
|
c90517 |
+finish_waiting_displays_on_seat (GdmLocalDisplayFactory *factory,
|
|
|
c90517 |
+ const char *seat_id)
|
|
|
c90517 |
+{
|
|
|
c90517 |
+ GdmDisplayStore *store;
|
|
|
c90517 |
+
|
|
|
c90517 |
+ store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
|
|
c90517 |
+
|
|
|
c90517 |
+ gdm_display_store_foreach (store,
|
|
|
c90517 |
+ (GdmDisplayStoreFunc) finish_display_on_seat_if_waiting,
|
|
|
c90517 |
+ (gpointer)
|
|
|
c90517 |
+ seat_id);
|
|
|
c90517 |
+}
|
|
|
c90517 |
+
|
|
|
c90517 |
static void
|
|
|
c90517 |
on_display_status_changed (GdmDisplay *display,
|
|
|
c90517 |
GParamSpec *arg1,
|
|
|
c90517 |
GdmLocalDisplayFactory *factory)
|
|
|
c90517 |
{
|
|
|
c90517 |
int status;
|
|
|
c90517 |
int num;
|
|
|
c90517 |
char *seat_id = NULL;
|
|
|
c90517 |
char *session_type = NULL;
|
|
|
c90517 |
char *session_class = NULL;
|
|
|
c90517 |
gboolean is_initial = TRUE;
|
|
|
c90517 |
gboolean is_local = TRUE;
|
|
|
c90517 |
|
|
|
c90517 |
num = -1;
|
|
|
c90517 |
gdm_display_get_x11_display_number (display, &num, NULL);
|
|
|
c90517 |
|
|
|
c90517 |
g_object_get (display,
|
|
|
c90517 |
"seat-id", &seat_id,
|
|
|
c90517 |
"is-initial", &is_initial,
|
|
|
c90517 |
"is-local", &is_local,
|
|
|
c90517 |
"session-type", &session_type,
|
|
|
c90517 |
"session-class", &session_class,
|
|
|
c90517 |
NULL);
|
|
|
c90517 |
|
|
|
c90517 |
status = gdm_display_get_status (display);
|
|
|
c90517 |
|
|
|
c90517 |
g_debug ("GdmLocalDisplayFactory: display status changed: %d", status);
|
|
|
c90517 |
switch (status) {
|
|
|
c90517 |
case GDM_DISPLAY_FINISHED:
|
|
|
c90517 |
/* remove the display number from factory->priv->used_display_numbers
|
|
|
c90517 |
@@ -324,60 +354,63 @@ on_display_status_changed (GdmDisplay *display,
|
|
|
c90517 |
/* Create a new equivalent display if it was static */
|
|
|
c90517 |
if (is_local) {
|
|
|
c90517 |
|
|
|
c90517 |
factory->priv->num_failures++;
|
|
|
c90517 |
|
|
|
c90517 |
if (factory->priv->num_failures > MAX_DISPLAY_FAILURES) {
|
|
|
c90517 |
/* oh shit */
|
|
|
c90517 |
g_warning ("GdmLocalDisplayFactory: maximum number of X display failures reached: check X server log for errors");
|
|
|
c90517 |
} else {
|
|
|
c90517 |
#ifdef ENABLE_WAYLAND_SUPPORT
|
|
|
c90517 |
if (g_strcmp0 (session_type, "wayland") == 0) {
|
|
|
c90517 |
g_free (session_type);
|
|
|
c90517 |
session_type = NULL;
|
|
|
c90517 |
|
|
|
c90517 |
/* workaround logind race for now
|
|
|
c90517 |
* bug 1643874
|
|
|
c90517 |
*/
|
|
|
c90517 |
sleep (2);
|
|
|
c90517 |
}
|
|
|
c90517 |
|
|
|
c90517 |
#endif
|
|
|
c90517 |
create_display (factory, seat_id, session_type, is_initial);
|
|
|
c90517 |
}
|
|
|
c90517 |
}
|
|
|
c90517 |
break;
|
|
|
c90517 |
case GDM_DISPLAY_UNMANAGED:
|
|
|
c90517 |
break;
|
|
|
c90517 |
case GDM_DISPLAY_PREPARED:
|
|
|
c90517 |
break;
|
|
|
c90517 |
case GDM_DISPLAY_MANAGED:
|
|
|
c90517 |
+ finish_waiting_displays_on_seat (factory, seat_id);
|
|
|
c90517 |
+ break;
|
|
|
c90517 |
+ case GDM_DISPLAY_WAITING_TO_FINISH:
|
|
|
c90517 |
break;
|
|
|
c90517 |
default:
|
|
|
c90517 |
g_assert_not_reached ();
|
|
|
c90517 |
break;
|
|
|
c90517 |
}
|
|
|
c90517 |
|
|
|
c90517 |
g_free (seat_id);
|
|
|
c90517 |
g_free (session_type);
|
|
|
c90517 |
g_free (session_class);
|
|
|
c90517 |
}
|
|
|
c90517 |
|
|
|
c90517 |
static gboolean
|
|
|
c90517 |
lookup_by_seat_id (const char *id,
|
|
|
c90517 |
GdmDisplay *display,
|
|
|
c90517 |
gpointer user_data)
|
|
|
c90517 |
{
|
|
|
c90517 |
const char *looking_for = user_data;
|
|
|
c90517 |
char *current;
|
|
|
c90517 |
gboolean res;
|
|
|
c90517 |
|
|
|
c90517 |
g_object_get (G_OBJECT (display), "seat-id", ¤t, NULL);
|
|
|
c90517 |
|
|
|
c90517 |
res = g_strcmp0 (current, looking_for) == 0;
|
|
|
c90517 |
|
|
|
c90517 |
g_free(current);
|
|
|
c90517 |
|
|
|
c90517 |
return res;
|
|
|
c90517 |
}
|
|
|
c90517 |
|
|
|
c90517 |
static gboolean
|
|
|
c90517 |
@@ -561,84 +594,82 @@ on_seat_new (GDBusConnection *connection,
|
|
|
c90517 |
|
|
|
c90517 |
static void
|
|
|
c90517 |
on_seat_removed (GDBusConnection *connection,
|
|
|
c90517 |
const gchar *sender_name,
|
|
|
c90517 |
const gchar *object_path,
|
|
|
c90517 |
const gchar *interface_name,
|
|
|
c90517 |
const gchar *signal_name,
|
|
|
c90517 |
GVariant *parameters,
|
|
|
c90517 |
gpointer user_data)
|
|
|
c90517 |
{
|
|
|
c90517 |
const char *seat;
|
|
|
c90517 |
|
|
|
c90517 |
g_variant_get (parameters, "(&s&o)", &seat, NULL);
|
|
|
c90517 |
delete_display (GDM_LOCAL_DISPLAY_FACTORY (user_data), seat);
|
|
|
c90517 |
}
|
|
|
c90517 |
|
|
|
c90517 |
#if defined(ENABLE_WAYLAND_SUPPORT) && defined(ENABLE_USER_DISPLAY_SERVER)
|
|
|
c90517 |
static gboolean
|
|
|
c90517 |
lookup_by_session_id (const char *id,
|
|
|
c90517 |
GdmDisplay *display,
|
|
|
c90517 |
gpointer user_data)
|
|
|
c90517 |
{
|
|
|
c90517 |
const char *looking_for = user_data;
|
|
|
c90517 |
const char *current;
|
|
|
c90517 |
|
|
|
c90517 |
current = gdm_display_get_session_id (display);
|
|
|
c90517 |
return g_strcmp0 (current, looking_for) == 0;
|
|
|
c90517 |
}
|
|
|
c90517 |
|
|
|
c90517 |
static void
|
|
|
c90517 |
-maybe_stop_greeter_display (GdmDisplay *display)
|
|
|
c90517 |
+maybe_stop_greeter_in_background (GdmDisplay *display)
|
|
|
c90517 |
{
|
|
|
c90517 |
g_autofree char *display_session_type = NULL;
|
|
|
c90517 |
|
|
|
c90517 |
if (gdm_display_get_status (display) != GDM_DISPLAY_MANAGED) {
|
|
|
c90517 |
g_debug ("GdmLocalDisplayFactory: login window not in managed state, so ignoring");
|
|
|
c90517 |
return;
|
|
|
c90517 |
}
|
|
|
c90517 |
|
|
|
c90517 |
g_object_get (G_OBJECT (display),
|
|
|
c90517 |
"session-type", &display_session_type,
|
|
|
c90517 |
NULL);
|
|
|
c90517 |
|
|
|
c90517 |
/* we can only stop greeter for wayland sessions, since
|
|
|
c90517 |
* X server would jump back on exit */
|
|
|
c90517 |
if (g_strcmp0 (display_session_type, "wayland") != 0) {
|
|
|
c90517 |
g_debug ("GdmLocalDisplayFactory: login window is running on Xorg, so ignoring");
|
|
|
c90517 |
return;
|
|
|
c90517 |
}
|
|
|
c90517 |
|
|
|
c90517 |
- g_debug ("GdmLocalDisplayFactory: killing login window since its now unused");
|
|
|
c90517 |
- gdm_display_stop_greeter_session (display);
|
|
|
c90517 |
- gdm_display_unmanage (display);
|
|
|
c90517 |
- gdm_display_finish (display);
|
|
|
c90517 |
+ g_debug ("GdmLocalDisplayFactory: killing login window once its unused");
|
|
|
c90517 |
+ g_object_set (G_OBJECT (display), "status", GDM_DISPLAY_WAITING_TO_FINISH, NULL);
|
|
|
c90517 |
}
|
|
|
c90517 |
|
|
|
c90517 |
static gboolean
|
|
|
c90517 |
on_vt_changed (GIOChannel *source,
|
|
|
c90517 |
GIOCondition condition,
|
|
|
c90517 |
GdmLocalDisplayFactory *factory)
|
|
|
c90517 |
{
|
|
|
c90517 |
GIOStatus status;
|
|
|
c90517 |
static const char *tty_of_initial_vt = "tty" GDM_INITIAL_VT;
|
|
|
c90517 |
g_autofree char *tty_of_previous_vt = NULL;
|
|
|
c90517 |
g_autofree char *tty_of_active_vt = NULL;
|
|
|
c90517 |
g_autofree char *login_session_id = NULL;
|
|
|
c90517 |
g_autofree char *active_session_id = NULL;
|
|
|
c90517 |
const char *session_type = NULL;
|
|
|
c90517 |
int ret;
|
|
|
c90517 |
|
|
|
c90517 |
g_debug ("GdmLocalDisplayFactory: received VT change event");
|
|
|
c90517 |
g_io_channel_seek_position (source, 0, G_SEEK_SET, NULL);
|
|
|
c90517 |
|
|
|
c90517 |
if (condition & G_IO_PRI) {
|
|
|
c90517 |
g_autoptr (GError) error = NULL;
|
|
|
c90517 |
status = g_io_channel_read_line (source, &tty_of_active_vt, NULL, NULL, &error);
|
|
|
c90517 |
|
|
|
c90517 |
if (error != NULL) {
|
|
|
c90517 |
g_warning ("could not read active VT from kernel: %s", error->message);
|
|
|
c90517 |
}
|
|
|
c90517 |
switch (status) {
|
|
|
c90517 |
case G_IO_STATUS_ERROR:
|
|
|
c90517 |
return G_SOURCE_REMOVE;
|
|
|
c90517 |
case G_IO_STATUS_EOF:
|
|
|
c90517 |
@@ -678,61 +709,61 @@ on_vt_changed (GIOChannel *source,
|
|
|
c90517 |
return G_SOURCE_CONTINUE;
|
|
|
c90517 |
}
|
|
|
c90517 |
|
|
|
c90517 |
g_debug ("GdmLocalDisplayFactory: VT changed from %s to %s",
|
|
|
c90517 |
tty_of_previous_vt, factory->priv->tty_of_active_vt);
|
|
|
c90517 |
|
|
|
c90517 |
/* if the old VT was running a wayland login screen kill it
|
|
|
c90517 |
*/
|
|
|
c90517 |
if (gdm_get_login_window_session_id ("seat0", &login_session_id)) {
|
|
|
c90517 |
unsigned int vt;
|
|
|
c90517 |
|
|
|
c90517 |
ret = sd_session_get_vt (login_session_id, &vt;;
|
|
|
c90517 |
if (ret == 0 && vt != 0) {
|
|
|
c90517 |
g_autofree char *tty_of_login_window_vt = NULL;
|
|
|
c90517 |
|
|
|
c90517 |
tty_of_login_window_vt = g_strdup_printf ("tty%u", vt);
|
|
|
c90517 |
|
|
|
c90517 |
g_debug ("GdmLocalDisplayFactory: tty of login window is %s", tty_of_login_window_vt);
|
|
|
c90517 |
if (g_strcmp0 (tty_of_login_window_vt, tty_of_previous_vt) == 0) {
|
|
|
c90517 |
GdmDisplayStore *store;
|
|
|
c90517 |
GdmDisplay *display;
|
|
|
c90517 |
|
|
|
c90517 |
g_debug ("GdmLocalDisplayFactory: VT switched from login window");
|
|
|
c90517 |
|
|
|
c90517 |
store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
|
|
|
c90517 |
display = gdm_display_store_find (store,
|
|
|
c90517 |
lookup_by_session_id,
|
|
|
c90517 |
(gpointer) login_session_id);
|
|
|
c90517 |
|
|
|
c90517 |
if (display != NULL)
|
|
|
c90517 |
- maybe_stop_greeter_display (display);
|
|
|
c90517 |
+ maybe_stop_greeter_in_background (display);
|
|
|
c90517 |
} else {
|
|
|
c90517 |
g_debug ("GdmLocalDisplayFactory: VT not switched from login window");
|
|
|
c90517 |
}
|
|
|
c90517 |
}
|
|
|
c90517 |
}
|
|
|
c90517 |
|
|
|
c90517 |
/* if user jumped back to initial vt and it's empty put a login screen
|
|
|
c90517 |
* on it (unless a login screen is already running elsewhere, then
|
|
|
c90517 |
* jump to that login screen)
|
|
|
c90517 |
*/
|
|
|
c90517 |
if (strcmp (factory->priv->tty_of_active_vt, tty_of_initial_vt) != 0) {
|
|
|
c90517 |
g_debug ("GdmLocalDisplayFactory: active VT is not initial VT, so ignoring");
|
|
|
c90517 |
return G_SOURCE_CONTINUE;
|
|
|
c90517 |
}
|
|
|
c90517 |
|
|
|
c90517 |
ret = sd_seat_get_active ("seat0", &active_session_id, NULL);
|
|
|
c90517 |
|
|
|
c90517 |
if (ret == 0) {
|
|
|
c90517 |
g_autofree char *state = NULL;
|
|
|
c90517 |
ret = sd_session_get_state (active_session_id, &state);
|
|
|
c90517 |
|
|
|
c90517 |
/* if there's something already running on the active VT then bail */
|
|
|
c90517 |
if (ret == 0 && g_strcmp0 (state, "closing") != 0) {
|
|
|
c90517 |
g_debug ("GdmLocalDisplayFactory: initial VT is in use, so ignoring");
|
|
|
c90517 |
return G_SOURCE_CONTINUE;
|
|
|
c90517 |
}
|
|
|
c90517 |
}
|
|
|
c90517 |
|
|
|
c90517 |
if (gdm_local_display_factory_use_wayland ())
|
|
|
c90517 |
session_type = "wayland";
|
|
|
c90517 |
--
|
|
|
c90517 |
2.26.0
|
|
|
c90517 |
|