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.
This commit is contained in:
Iain Lane 2018-06-12 15:45:35 +01:00
parent 3fbeeb9072
commit 4837ea3434

View File

@ -62,20 +62,156 @@ meta_launcher_get_seat_id (MetaLauncher *launcher)
return launcher->seat_id; 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 * static Login1Session *
get_session_proxy (GCancellable *cancellable, get_session_proxy (GCancellable *cancellable,
GError **error) GError **error)
{ {
g_autofree char *proxy_path = NULL; g_autofree char *proxy_path = NULL;
g_autofree char *session_id = NULL; g_autofree char *session_id = NULL;
g_autoptr (GError) local_error = NULL;
Login1Session *session_proxy; 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_propagate_prefixed_error (error, local_error, "Could not get session ID: ");
G_IO_ERROR,
G_IO_ERROR_NOT_FOUND,
"Could not get session ID: %m");
return NULL; return NULL;
} }
@ -302,17 +438,14 @@ on_active_changed (Login1Session *session,
static gchar * static gchar *
get_seat_id (GError **error) get_seat_id (GError **error)
{ {
g_autoptr (GError) local_error = NULL;
g_autofree char *session_id = NULL; g_autofree char *session_id = NULL;
char *seat_id = NULL; char *seat_id = NULL;
int r; int r;
r = sd_pid_get_session (0, &session_id); if (!find_systemd_session (&session_id, &local_error))
if (r < 0)
{ {
g_set_error (error, g_propagate_prefixed_error (error, local_error, "Could not get session ID: ");
G_IO_ERROR,
G_IO_ERROR_NOT_FOUND,
"Could not get session for PID: %s", g_strerror (-r));
return NULL; return NULL;
} }