summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIain Lane <iainl@gnome.org>2018-06-12 15:45:35 +0100
committerIain Lane <iainl@gnome.org>2018-07-07 14:12:29 +0100
commit4837ea3434962f10d403fc8b7c65d411926c461b (patch)
tree2c57ea53747d4db55a8bec8a69dcea7582a8881f
parent3fbeeb90726294352df93b66f673401e8fde5d07 (diff)
downloadmutter-4837ea3434962f10d403fc8b7c65d411926c461b.tar.gz
meta-launcher: Find the current user's graphical session, not the pid's
If we're started by systemd --user, we might not be in the same session, but this is nevertheless the one we are interested in.
-rw-r--r--src/backends/native/meta-launcher.c155
1 files changed, 144 insertions, 11 deletions
diff --git a/src/backends/native/meta-launcher.c b/src/backends/native/meta-launcher.c
index 8b066c9ff..15cad0d40 100644
--- a/src/backends/native/meta-launcher.c
+++ b/src/backends/native/meta-launcher.c
@@ -62,20 +62,156 @@ meta_launcher_get_seat_id (MetaLauncher *launcher)
return launcher->seat_id;
}
+static gboolean
+find_systemd_session (gchar **session_id,
+ GError **error)
+{
+ const gchar * const graphical_session_types[] = { "wayland", "x11", "mir", NULL };
+ const gchar * const active_states[] = { "active", "online", NULL };
+ g_autofree gchar *class = NULL;
+ g_autofree gchar *local_session_id = NULL;
+ g_autofree gchar *type = NULL;
+ g_autofree gchar *state = NULL;
+ g_auto (GStrv) sessions = NULL;
+ int n_sessions;
+ int saved_errno;
+
+ g_assert (session_id != NULL);
+ g_assert (error == NULL || *error == NULL);
+
+ saved_errno = sd_uid_get_display (getuid (), &local_session_id);
+ if (saved_errno < 0)
+ {
+ /* no session, maybe there's a greeter session */
+ if (saved_errno == -ENODATA)
+ {
+ n_sessions = sd_uid_get_sessions (getuid (), 1, &sessions);
+ if (n_sessions < 0)
+ {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ "Failed to get all sessions for user %d (%m)",
+ getuid ());
+ return FALSE;
+ }
+
+ if (n_sessions == 0)
+ {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ "User %d has no sessions",
+ getuid ());
+ return FALSE;
+ }
+
+ for (int i = 0; i < n_sessions; ++i)
+ {
+ saved_errno = sd_session_get_class (sessions[i], &class);
+ if (saved_errno < 0)
+ {
+ g_warning ("Couldn't get class for session '%d': %s",
+ i,
+ g_strerror (-saved_errno));
+ continue;
+ }
+
+ if (g_strcmp0 (class, "greeter") == 0)
+ {
+ local_session_id = g_strdup (sessions[i]);
+ break;
+ }
+ }
+
+ if (!local_session_id)
+ {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ "Couldn't find a session or a greeter session for user %d",
+ getuid ());
+ return FALSE;
+ }
+ }
+ else
+ {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ "Couldn't get display for user %d: %s",
+ getuid (),
+ g_strerror (-saved_errno));
+ return FALSE;
+ }
+ }
+
+ /* sd_uid_get_display will return any session if there is no graphical
+ * one, so let's check it really is graphical. */
+ saved_errno = sd_session_get_type (local_session_id, &type);
+ if (saved_errno < 0)
+ {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ "Couldn't get type for session '%s': %s",
+ local_session_id,
+ g_strerror (-saved_errno));
+ return FALSE;
+ }
+
+ if (!g_strv_contains (graphical_session_types, type))
+ {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ "Session '%s' is not a graphical session (type: '%s')",
+ local_session_id,
+ type);
+ return FALSE;
+ }
+
+ /* and display sessions can be 'closing' if they are logged out but
+ * some processes are lingering; we shouldn't consider these */
+ saved_errno = sd_session_get_state (local_session_id, &state);
+ if (saved_errno < 0)
+ {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ "Couldn't get state for session '%s': %s",
+ local_session_id,
+ g_strerror (-saved_errno));
+ return FALSE;
+ }
+
+ if (!g_strv_contains (active_states, state))
+ {
+ g_set_error (error,
+ G_IO_ERROR,
+ G_IO_ERROR_NOT_FOUND,
+ "Session '%s' is not active",
+ local_session_id);
+ return FALSE;
+ }
+
+ *session_id = g_steal_pointer (&local_session_id);
+
+ return TRUE;
+}
+
static Login1Session *
get_session_proxy (GCancellable *cancellable,
GError **error)
{
g_autofree char *proxy_path = NULL;
g_autofree char *session_id = NULL;
+ g_autoptr (GError) local_error = NULL;
Login1Session *session_proxy;
- if (sd_pid_get_session (getpid (), &session_id) < 0)
+ if (!find_systemd_session (&session_id, &local_error))
{
- g_set_error (error,
- G_IO_ERROR,
- G_IO_ERROR_NOT_FOUND,
- "Could not get session ID: %m");
+ g_propagate_prefixed_error (error, local_error, "Could not get session ID: ");
return NULL;
}
@@ -302,17 +438,14 @@ on_active_changed (Login1Session *session,
static gchar *
get_seat_id (GError **error)
{
+ g_autoptr (GError) local_error = NULL;
g_autofree char *session_id = NULL;
char *seat_id = NULL;
int r;
- r = sd_pid_get_session (0, &session_id);
- if (r < 0)
+ if (!find_systemd_session (&session_id, &local_error))
{
- g_set_error (error,
- G_IO_ERROR,
- G_IO_ERROR_NOT_FOUND,
- "Could not get session for PID: %s", g_strerror (-r));
+ g_propagate_prefixed_error (error, local_error, "Could not get session ID: ");
return NULL;
}