[gdm] multi-seat patch

Lennart Poettering lennart at fedoraproject.org
Tue Feb 7 23:21:47 UTC 2012


commit cd51e710738ec9bfecd17cdddf5127e44cc57d11
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Feb 8 00:21:40 2012 +0100

    multi-seat patch

 gdm.spec         |   78 +-
 multi-seat.patch | 2372 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 2414 insertions(+), 36 deletions(-)
---
diff --git a/gdm.spec b/gdm.spec
index 97463ce..78862ac 100644
--- a/gdm.spec
+++ b/gdm.spec
@@ -8,14 +8,13 @@
 %define desktop_file_utils_version 0.2.90
 %define gail_version 1.2.0
 %define nss_version 3.11.1
-%define consolekit_version 0.3.0-9
 %define fontconfig_version 2.6.0
 %define _default_patch_fuzz 999
 
 Summary: The GNOME Display Manager
 Name: gdm
 Version: 3.2.1.1
-Release: 10%{?dist}
+Release: 11%{?dist}
 Epoch: 1
 License: GPLv2+
 Group: User Interface/X
@@ -42,7 +41,7 @@ Requires: system-logos
 Requires: xorg-x11-server-utils
 Requires: setxkbmap
 Requires: xorg-x11-xinit
-Requires: ConsoleKit >= %{consolekit_version}
+Requires: systemd >= 39
 Requires: accountsservice
 Requires: gnome-settings-daemon >= 2.21.92
 Requires: iso-codes
@@ -104,6 +103,9 @@ Provides: gdm-plugin-fingerprint = %{epoch}:%{version}-%{release}
 # already upstream
 Patch0: auth-fixes.patch
 
+# Multi-seat stuff
+Patch50: multi-seat.patch
+
 # Fedora-specific
 Patch98: plymouth.patch
 Patch99: gdm-3.0.0-fedora-logo.patch
@@ -136,6 +138,7 @@ Development files and headers for writing GDM greeters.
 %prep
 %setup -q
 %patch0 -p1 -b .auth-fixes
+%patch50 -p1 -b .multi-seat
 %patch98 -p1 -b .plymouth
 %patch99 -p1 -b .fedora-logo
 
@@ -387,6 +390,9 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor >&/dev/null || :
 %{_libdir}/girepository-1.0/GdmGreeter-1.0.typelib
 
 %changelog
+* Tue Feb  7 2012 Lennart Poettering <lpoetter at redhat.com> - 1:3.2.1.1-11
+- Add multi-seat patch from gdm git master
+
 * Thu Jan 26 2012 Ray Strode <rstrode at redhat.com> 3.2.1.1-10
 - Drop system-icon-theme requirement since we don't depend
   on it anymore
@@ -860,7 +866,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor >&/dev/null || :
 - Rework "force X on vt1" code to work after the user logs out
 
 * Wed Oct 15 2008 Matthias Clasen  <mclasen at redhat.com> - 1:2.24.0-9
-- Save some space 
+- Save some space
 
 * Fri Oct  3 2008 Matthias Clasen  <mclasen at redhat.com> - 1:2.24.0-8
 - Don't show a non-functional help menuitem
@@ -1186,7 +1192,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor >&/dev/null || :
 
 * Fri Nov 30 2007 Matthias Clasen <mclasen at redhat.com> - 1:2.21.2-0.2007.11.20.4
 - Use the new "substack" support in pam to make keyring unlocking work
- 
+
 * Tue Nov 20 2007 Ray Strode <rstrode at redhat.com> - 1:2.21.2-0.2007.11.20.3
 - use metacity for now
 
@@ -1244,7 +1250,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor >&/dev/null || :
 
 * Mon Oct  1 2007 Ray Strode <rstrode at redhat.com> - 1:2.20.0-10
 - apply upstream patch from Brady Anderson <brady.anderson at gmail.com>
-  to fix writing out .dmrc file when setting default language 
+  to fix writing out .dmrc file when setting default language
   (upstream bug 453916)
 
 * Fri Sep 28 2007 Ray Strode <rstrode at redhat.com> - 1:2.20.0-9
@@ -1324,7 +1330,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor >&/dev/null || :
 - Require gnome-keyring-pam
 
 * Mon Aug  6 2007 Ray Strode <rstrode at redhat.com> - 1:2.19.5-5
-- change previous patch to drop even more code 
+- change previous patch to drop even more code
 
 * Mon Aug  6 2007 Ray Strode <rstrode at redhat.com> - 1:2.19.5-4
 - turn off dwellmouselistener if devices don't send core events.
@@ -1506,7 +1512,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor >&/dev/null || :
   in gdmsetup
 
 * Tue Sep 19 2006 Ray Strode <rstrode at redhat.com> - 1:2.16.0-8.fc6
-- Add as_IN, si_LK to language list (bug 203917) 
+- Add as_IN, si_LK to language list (bug 203917)
 
 * Mon Sep 18 2006 Ray Strode <rstrode at redhat.com> - 1:2.16.0-7.fc6
 - fix a problem recently introduced in the smart card forking
@@ -1676,7 +1682,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor >&/dev/null || :
 
 * Tue Feb 28 2006 Ray Strode <rstrode at redhat.com> - 1:2.13.0.9-1
 - Update to 2.13.0.9
-- Use new %%post section, written by 
+- Use new %%post section, written by
   Michal Jaegermann <michal at harddata.com> (bug 183082)
 
 * Sat Feb 25 2006 Ray Strode <rstrode at redhat.com> - 1:2.13.0.8-6
@@ -1732,7 +1738,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor >&/dev/null || :
 - add new theme by Diana Fong, Máirín Duffy, and me
 
 * Mon Jan 16 2006 Ray Strode <rstrode at redhat.com> - 1:2.13.0.4-4
-- improve migration snippet (bug 177443). 
+- improve migration snippet (bug 177443).
 
 * Fri Jan 13 2006 Ray Strode <rstrode at redhat.com> - 1:2.13.0.4-3
 - migrate X server configuration for pre-modular X configurations.
@@ -1818,7 +1824,7 @@ p
 * Mon May 23 2005 Ray Strode <rstrode at redhat.com> 1:2.6.0.8-16
 - Make sure username/password incorrect message gets displayed
   (bug 158127).
-- reread system locale before starting gdm in early login mode 
+- reread system locale before starting gdm in early login mode
   (bug 158376).
 
 * Thu May 19 2005 Ray Strode <rstrode at redhat.com> 1:2.6.0.8-15
@@ -1842,7 +1848,7 @@ p
 - silence %%postun
 
 * Tue Apr 26 2005 Ray Strode <rstrode at redhat.com> 1:2.6.0.8-9
-- Change default standard greeter theme to clearlooks and 
+- Change default standard greeter theme to clearlooks and
   default graphical greeter theme to Bluecurve specifically.
 
 - Change default path values (bug 154280)
@@ -1898,7 +1904,7 @@ p
   user's home directory (fixes bug 149899)
 
 * Thu Feb 10 2005 Ray Strode <rstrode at redhat.com> 1:2.6.0.7-2
-- Turn off "switchdesk" mode by default which accidentally got 
+- Turn off "switchdesk" mode by default which accidentally got
   turned on by default in 2.6.0.5-4
 
 * Wed Feb  2 2005 Matthias Clasen <mclasen at redhat.com> 1:2.6.0.7-1
@@ -1911,28 +1917,28 @@ p
 * Thu Dec 9 2004 Dan Walsh <dwalsh at redhat.com> 1:2.6.0.5-10
 - Remove pam_selinux from gdmsetup pam file
 
-* Wed Dec  1 2004  Ray Strode  <rstrode at redhat.com> 1:2.6.0.5-9 
-- Look up and use username instead of assuming that user entered 
+* Wed Dec  1 2004  Ray Strode  <rstrode at redhat.com> 1:2.6.0.5-9
+- Look up and use username instead of assuming that user entered
   login is cannonical.  Patch from
   Mike Patnode <mike.patnode at centrify.com> (fixes bug 141380).
 
-* Thu Nov 11 2004  Ray Strode  <rstrode at redhat.com> 1:2.6.0.5-8 
+* Thu Nov 11 2004  Ray Strode  <rstrode at redhat.com> 1:2.6.0.5-8
 - Sort session list so that default session comes out on top
   (fixes bug 107324)
 
-* Wed Nov 10 2004  Ray Strode  <rstrode at redhat.com> 1:2.6.0.5-7 
+* Wed Nov 10 2004  Ray Strode  <rstrode at redhat.com> 1:2.6.0.5-7
 - Make desktop file symlink instead of absolute (bug 104390)
 - Add flexiserver back to menus
 
-* Wed Oct 20 2004  Ray Strode  <rstrode at redhat.com> 1:2.6.0.5-6 
+* Wed Oct 20 2004  Ray Strode  <rstrode at redhat.com> 1:2.6.0.5-6
 - Clean up xses if the session was successfullly completed.
   (fixes bug #136382)
 
-* Tue Oct 19 2004  Ray Strode  <rstrode at redhat.com> 1:2.6.0.5-5 
+* Tue Oct 19 2004  Ray Strode  <rstrode at redhat.com> 1:2.6.0.5-5
 - Prefer nb_NO over no_NO for Norwegian (fixes bug #136033)
 
 * Thu Oct  7 2004 Alexander Larsson <alexl at redhat.com> - 1:2.6.0.5-4
-- Change default greeter theme to "Default", require 
+- Change default greeter theme to "Default", require
   redhat-artwork with Default symlink.
 
 * Wed Sep 29 2004 Ray Strode <rstrode at redhat.com> 1:2.6.0.5-3
@@ -2171,14 +2177,14 @@ p
 * Wed Aug 28 2002 Havoc Pennington <hp at redhat.com>
 - put /usr/X11R6/bin in path for now fixes #72781
 - use proper i18n algorithm for word wrap, #71937
-- remove greek text from language picker due to lack 
+- remove greek text from language picker due to lack
   of greek font
 - reorder PAM config file #72657
 
 * Wed Aug 28 2002 Havoc Pennington <hp at redhat.com>
 - improve gdmsetup icon
 - remove GNOME session, we will instead put it in gnome-session
-- apply patch from george to make gdmphotosetup file selector 
+- apply patch from george to make gdmphotosetup file selector
   work
 
 * Mon Aug 26 2002 Elliot Lee <sopwith at redhat.com> 2.4.0.7-6
@@ -2198,7 +2204,7 @@ p
 - rename Gnome session to GNOME, this was just bugging me
 
 * Thu Aug  8 2002 Havoc Pennington <hp at redhat.com>
-- 2.4.0.7 with bugfixes George kindly did for me, 
+- 2.4.0.7 with bugfixes George kindly did for me,
   including mnemonics for the graphical greeter
 - use Wonderland gtk theme for the nongraphical greeter
 - remove patches that are now upstream
@@ -2213,7 +2219,7 @@ p
 
 * Tue Jun 25 2002 Owen Taylor <otaylor at redhat.com>
 - Require redhat-artwork, make the default greeter theme Wonderland
-- Look for all configuration in .gnome2 not .gnome. This avoids problems 
+- Look for all configuration in .gnome2 not .gnome. This avoids problems
   with changes in the set of session/lang.
 - Remove English from locale.alias, make most locales UTF-8
 - Call find_lang with the right name
@@ -2295,7 +2301,7 @@ p
 
 * Thu Jul 19 2001 Havoc Pennington <hp at redhat.com>
 - depend on usermode, xinitrc
- 
+
 * Thu Jul 19 2001 Havoc Pennington <hp at redhat.com>
 - build requires pam-devel, should fix #49448
 
@@ -2315,7 +2321,7 @@ p
 - upgrade to 2.2.3.1, pray this fixes more than it breaks
 
 * Thu Jul 05 2001 Havoc Pennington <hp at redhat.com>
-- add "rpm" user to those not to show in greeter 
+- add "rpm" user to those not to show in greeter
 
 * Tue Jul 03 2001 Havoc Pennington <hp at redhat.com>
 - Upgrade to 2.2.3
@@ -2325,7 +2331,7 @@ p
 - Prereq for scrollkeeper-update
 
 * Thu May 30 2001 Havoc Pennington <hp at redhat.com>
-- New CVS snap with the "no weird sessions" options; 
+- New CVS snap with the "no weird sessions" options;
   more default settings changes
 
 * Wed May 30 2001 Havoc Pennington <hp at redhat.com>
@@ -2334,8 +2340,8 @@ p
 * Wed May 30 2001 Havoc Pennington <hp at redhat.com>
 - After, oh, 2 years or so, finally upgrade version and set
   release to 1. Remove all hacks and patches, pretty much;
-  this will break a few things, will be putting them back 
-  via GNOME CVS. All changes should go in 'gdm2' module in 
+  this will break a few things, will be putting them back
+  via GNOME CVS. All changes should go in 'gdm2' module in
   CVS for now.
 
   This RPM enables all kinds of features that I'm going to turn
@@ -2371,7 +2377,7 @@ p
 
 * Sun Aug 13 2000 Owen Taylor <otaylor at redhat.com>
 - Return to toplevel main loop and start Xdcmp if enabled
-  (Bug #16106) 
+  (Bug #16106)
 
 * Fri Aug 11 2000 Jonathan Blandford <jrb at redhat.com>
 - Up Epoch and release
@@ -2417,7 +2423,7 @@ p
 * Fri Feb 04 2000 Havoc Pennington <hp at redhat.com>
 - Modify Default.session and Failsafe.session not to add -login option to bash
 - exec the session scripts with the user's shell with a hyphen prepended
-- doesn't seem to actually work yet with tcsh, but it doesn't seem to 
+- doesn't seem to actually work yet with tcsh, but it doesn't seem to
   break anything. needs a look to see why it doesn't work
 
 * Fri Feb 04 2000 Havoc Pennington <hp at redhat.com>
@@ -2429,12 +2435,12 @@ p
 - remove docs/gdm-manual.txt which doesn't seem to exist from %doc
 
 * Fri Feb 04 2000 Havoc Pennington <hp at redhat.com>
-- Enhance 8877 fix by not deleting the "Please login" 
+- Enhance 8877 fix by not deleting the "Please login"
   message
 
 * Fri Feb 04 2000 Havoc Pennington <hp at redhat.com>
-- Try to fix bug 8877 by clearing the message below 
-  the entry box when the prompt changes. may turn 
+- Try to fix bug 8877 by clearing the message below
+  the entry box when the prompt changes. may turn
   out to be a bad idea.
 
 * Mon Jan 17 2000 Elliot Lee <sopwith at redhat.com>
@@ -2474,10 +2480,10 @@ p
 * Mon Apr 19 1999 Michael Fulbright <drmike at redhat.com>
 - fix to handling ancient gdm config files with non-standard language specs
 - dont close display connection for xdmcp connections, else we die if remote
-  end dies. 
+  end dies.
 
 * Fri Apr 16 1999 Michael Fulbright <drmike at redhat.com>
-- fix language handling to set GDM_LANG variable so gnome-session 
+- fix language handling to set GDM_LANG variable so gnome-session
   can pick it up
 
 * Wed Apr 14 1999 Michael Fulbright <drmike at redhat.com>
diff --git a/multi-seat.patch b/multi-seat.patch
new file mode 100644
index 0000000..b966da6
--- /dev/null
+++ b/multi-seat.patch
@@ -0,0 +1,2372 @@
+From 3ed96cac0c49d0687fc273d11bad51772d8233ed Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart at poettering.net>
+Date: Tue, 24 Jan 2012 04:16:24 +0100
+Subject: [PATCH 01/11] slave: whitespace cleanup
+
+---
+ daemon/gdm-slave.c |    4 ++--
+ 1 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c
+index 787ef89..c0705fd 100644
+--- a/daemon/gdm-slave.c
++++ b/daemon/gdm-slave.c
+@@ -541,8 +541,8 @@ gdm_slave_set_windowpath (GdmSlave *slave)
+                 return;
+         }
+         if (XGetWindowProperty (slave->priv->server_display,
+-                DefaultRootWindow (slave->priv->server_display), prop, 0, 1, 
+-                False, AnyPropertyType, &actualtype, &actualformat, 
++                DefaultRootWindow (slave->priv->server_display), prop, 0, 1,
++                False, AnyPropertyType, &actualtype, &actualformat,
+                 &nitems, &bytes_after, &buf)) {
+                 g_debug ("no XFree86_VT property\n");
+                 return;
+-- 
+1.7.9
+
+
+From 1a5f9a0f7a65e796e044ff2f3f793e8268d31623 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart at poettering.net>
+Date: Fri, 13 Jan 2012 03:53:15 +0100
+Subject: [PATCH 02/11] welcome-session: get rid of register-ck-session
+ property since it is unused
+
+Nothing was using register-ck-session and it has no effect, hence let's
+get rid of this dead code.
+---
+ daemon/Makefile.am           |    6 ------
+ daemon/gdm-chooser-session.c |    1 -
+ daemon/gdm-greeter-session.c |    1 -
+ daemon/gdm-welcome-session.c |   25 +------------------------
+ 4 files changed, 1 insertions(+), 32 deletions(-)
+
+diff --git a/daemon/Makefile.am b/daemon/Makefile.am
+index 65e82b8..a153c43 100644
+--- a/daemon/Makefile.am
++++ b/daemon/Makefile.am
+@@ -115,8 +115,6 @@ gdm_simple_slave_SOURCES = 		\
+ 	simple-slave-main.c 		\
+ 	gdm-greeter-server.c		\
+ 	gdm-greeter-server.h		\
+-	ck-connector.h			\
+-	ck-connector.c			\
+ 	gdm-welcome-session.c		\
+ 	gdm-welcome-session.h		\
+ 	gdm-greeter-session.c		\
+@@ -156,8 +154,6 @@ gdm_factory_slave_SOURCES = 		\
+ 	factory-slave-main.c 		\
+ 	gdm-greeter-server.c		\
+ 	gdm-greeter-server.h		\
+-	ck-connector.h			\
+-	ck-connector.c			\
+ 	gdm-welcome-session.c		\
+ 	gdm-welcome-session.h		\
+ 	gdm-greeter-session.c		\
+@@ -232,8 +228,6 @@ gdm_xdmcp_chooser_slave_SOURCES = 		\
+ 	xdmcp-chooser-slave-main.c 		\
+ 	gdm-chooser-server.c			\
+ 	gdm-chooser-server.h			\
+-	ck-connector.h				\
+-	ck-connector.c				\
+ 	gdm-session.c				\
+ 	gdm-session.h				\
+ 	gdm-session-direct.c			\
+diff --git a/daemon/gdm-chooser-session.c b/daemon/gdm-chooser-session.c
+index da0f2ab..6aa60a6 100644
+--- a/daemon/gdm-chooser-session.c
++++ b/daemon/gdm-chooser-session.c
+@@ -81,7 +81,6 @@ gdm_chooser_session_new (const char *display_name,
+                                "server-dbus-path", GDM_CHOOSER_SERVER_DBUS_PATH,
+                                "server-dbus-interface", GDM_CHOOSER_SERVER_DBUS_INTERFACE,
+                                "server-env-var-name", "GDM_CHOOSER_DBUS_ADDRESS",
+-                               "register-ck-session", FALSE,
+                                "x11-display-name", display_name,
+                                "x11-display-device", display_device,
+                                "x11-display-hostname", display_hostname,
+diff --git a/daemon/gdm-greeter-session.c b/daemon/gdm-greeter-session.c
+index 8032065..44259ab 100644
+--- a/daemon/gdm-greeter-session.c
++++ b/daemon/gdm-greeter-session.c
+@@ -82,7 +82,6 @@ gdm_greeter_session_new (const char *display_name,
+                                "server-dbus-path", GDM_GREETER_SERVER_DBUS_PATH,
+                                "server-dbus-interface", GDM_GREETER_SERVER_DBUS_INTERFACE,
+                                "server-env-var-name", "GDM_GREETER_DBUS_ADDRESS",
+-                               "register-ck-session", TRUE,
+                                "x11-display-name", display_name,
+                                "x11-display-seat-id", seat_id,
+                                "x11-display-device", display_device,
+diff --git a/daemon/gdm-welcome-session.c b/daemon/gdm-welcome-session.c
+index 41144a8..8721fe7 100644
+--- a/daemon/gdm-welcome-session.c
++++ b/daemon/gdm-welcome-session.c
+@@ -42,7 +42,6 @@
+ #include <dbus/dbus-glib-lowlevel.h>
+ 
+ #include "gdm-common.h"
+-#include "ck-connector.h"
+ 
+ #include "gdm-session.h"
+ #include "gdm-session-direct.h"
+@@ -78,7 +77,6 @@ struct GdmWelcomeSessionPrivate
+         char           *server_dbus_path;
+         char           *server_dbus_interface;
+         char           *server_env_var_name;
+-        gboolean        register_ck_session;
+ 
+         char           *server_address;
+ };
+@@ -98,8 +96,7 @@ enum {
+         PROP_COMMAND,
+         PROP_SERVER_DBUS_PATH,
+         PROP_SERVER_DBUS_INTERFACE,
+-        PROP_SERVER_ENV_VAR_NAME,
+-        PROP_REGISTER_CK_SESSION,
++        PROP_SERVER_ENV_VAR_NAME
+ };
+ 
+ enum {
+@@ -1040,13 +1037,6 @@ _gdm_welcome_session_set_server_env_var_name (GdmWelcomeSession *welcome_session
+ }
+ 
+ static void
+-_gdm_welcome_session_set_register_ck_session (GdmWelcomeSession *welcome_session,
+-                                              gboolean           val)
+-{
+-        welcome_session->priv->register_ck_session = val;
+-}
+-
+-static void
+ gdm_welcome_session_set_property (GObject      *object,
+                                   guint         prop_id,
+                                   const GValue *value,
+@@ -1093,9 +1083,6 @@ gdm_welcome_session_set_property (GObject      *object,
+         case PROP_SERVER_DBUS_INTERFACE:
+                 _gdm_welcome_session_set_server_dbus_interface (self, g_value_get_string (value));
+                 break;
+-        case PROP_REGISTER_CK_SESSION:
+-                _gdm_welcome_session_set_register_ck_session (self, g_value_get_boolean (value));
+-                break;
+         case PROP_SERVER_ENV_VAR_NAME:
+                 _gdm_welcome_session_set_server_env_var_name (self, g_value_get_string (value));
+                 break;
+@@ -1155,9 +1142,6 @@ gdm_welcome_session_get_property (GObject    *object,
+         case PROP_SERVER_DBUS_INTERFACE:
+                 g_value_set_string (value, self->priv->server_dbus_interface);
+                 break;
+-        case PROP_REGISTER_CK_SESSION:
+-                g_value_set_boolean (value, self->priv->register_ck_session);
+-                break;
+         case PROP_SERVER_ENV_VAR_NAME:
+                 g_value_set_string (value, self->priv->server_env_var_name);
+                 break;
+@@ -1279,13 +1263,6 @@ gdm_welcome_session_class_init (GdmWelcomeSessionClass *klass)
+                                                               "command",
+                                                               NULL,
+                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+-        g_object_class_install_property (object_class,
+-                                         PROP_REGISTER_CK_SESSION,
+-                                         g_param_spec_boolean ("register-ck-session",
+-                                                               NULL,
+-                                                               NULL,
+-                                                               FALSE,
+-                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+         signals [STARTED] =
+                 g_signal_new ("started",
+                               G_OBJECT_CLASS_TYPE (object_class),
+-- 
+1.7.9
+
+
+From 02697e774c2f669d1d4109fc1de975407740409b Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart at poettering.net>
+Date: Wed, 27 Jul 2011 01:18:55 +0200
+Subject: [PATCH 03/11] build-sys: add configure option --with-systemd
+
+---
+ configure.ac |   25 +++++++++++++++++++++++++
+ 1 files changed, 25 insertions(+), 0 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index 30397c5..dec31a9 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -272,6 +272,11 @@ AC_ARG_WITH(console-kit,
+                            [Add ConsoleKit support @<:@default=auto@:>@]),,
+             with_console_kit=auto)
+ 
++AC_ARG_WITH(systemd,
++            AS_HELP_STRING([--with-systemd],
++                           [Add systemd support @<:@default=auto@:>@]),,
++            with_systemd=auto)
++
+ AC_ARG_WITH(at-spi-registryd-directory,
+             AS_HELP_STRING([--with-at-spi-registryd-directory],
+ 	                   [Specify the directory of at-spi-registryd @<:@default=libexecdir@:>@])],,
+@@ -927,6 +932,25 @@ AM_CONDITIONAL(WITH_CONSOLE_KIT, test x$use_console_kit = xyes)
+ AC_SUBST(WITH_CONSOLE_KIT)
+ 
+ dnl ---------------------------------------------------------------------------
++dnl - Check for systemd support
++dnl ---------------------------------------------------------------------------
++
++use_systemd=no
++if test "x$with_systemd" != "xno" ; then
++        PKG_CHECK_MODULES(SYSTEMD,
++                libsystemd-daemon
++                libsystemd-login
++        )
++        AC_SUBST(SYSTEMD_CFLAGS)
++        AC_SUBST(SYSTEMD_LIBS)
++
++	use_systemd=yes
++	AC_DEFINE(WITH_SYSTEMD, 1, [Define to enable systemd support])
++fi
++AM_CONDITIONAL(WITH_SYSTEMD, test x$use_systemd = xyes)
++AC_SUBST(WITH_SYSTEMD)
++
++dnl ---------------------------------------------------------------------------
+ dnl - Check for D-Bus
+ dnl ---------------------------------------------------------------------------
+ 
+@@ -1511,6 +1535,7 @@ echo \
+         XDMCP support:            ${XDMCP_SUPPORT}
+         SELinux support:          ${with_selinux}
+         ConsoleKit support:       ${use_console_kit}
++        systemd support:          ${use_systemd}
+         UPower support:           ${have_upower}
+         Build with RBAC:          ${msg_rbac_shutdown}
+ "
+-- 
+1.7.9
+
+
+From a58b27ff573109f0d9a8971fbc80e797d6cc2733 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart at poettering.net>
+Date: Tue, 24 Jan 2012 04:15:26 +0100
+Subject: [PATCH 04/11] slave: add native systemd implementations of
+ locking/session activation
+
+---
+ daemon/Makefile.am |    5 +
+ daemon/gdm-slave.c |  251 +++++++++++++++++++++++++++++++++++++++++++++++++---
+ 2 files changed, 242 insertions(+), 14 deletions(-)
+
+diff --git a/daemon/Makefile.am b/daemon/Makefile.am
+index a153c43..43d416e 100644
+--- a/daemon/Makefile.am
++++ b/daemon/Makefile.am
+@@ -24,6 +24,7 @@ AM_CPPFLAGS = \
+ 	$(XLIB_CFLAGS)					\
+ 	$(WARN_CFLAGS)					\
+ 	$(DEBUG_CFLAGS)					\
++	$(SYSTEMD_CFLAGS)				\
+ 	-DLANG_CONFIG_FILE=\"$(LANG_CONFIG_FILE)\"	\
+ 	$(NULL)
+ 
+@@ -148,6 +149,7 @@ gdm_simple_slave_LDADD = 			\
+ 	$(DAEMON_LIBS)				\
+ 	$(EXTRA_DAEMON_LIBS)                    \
+ 	$(LIBXKLAVIER_LIBS)			\
++	$(SYSTEMD_LIBS) 			\
+ 	$(NULL)
+ 
+ gdm_factory_slave_SOURCES = 		\
+@@ -188,6 +190,7 @@ gdm_factory_slave_LDADD = 			\
+ 	$(top_builddir)/common/libgdmcommon.la	\
+ 	$(XLIB_LIBS)				\
+ 	$(DAEMON_LIBS)				\
++	$(SYSTEMD_LIBS) 			\
+ 	$(NULL)
+ 
+ gdm_product_slave_SOURCES = 		\
+@@ -222,6 +225,7 @@ gdm_product_slave_LDADD = 			\
+ 	$(DAEMON_LIBS)				\
+ 	$(EXTRA_DAEMON_LIBS)                    \
+ 	$(LIBXKLAVIER_LIBS)			\
++	$(SYSTEMD_LIBS) 			\
+ 	$(NULL)
+ 
+ gdm_xdmcp_chooser_slave_SOURCES = 		\
+@@ -254,6 +258,7 @@ gdm_xdmcp_chooser_slave_LDADD = 		\
+ 	$(DAEMON_LIBS)				\
+ 	$(EXTRA_DAEMON_LIBS)                    \
+ 	$(LIBXKLAVIER_LIBS)			\
++	$(SYSTEMD_LIBS) 			\
+ 	$(top_builddir)/common/libgdmcommon.la	\
+ 	$(NULL)
+ 
+diff --git a/daemon/gdm-slave.c b/daemon/gdm-slave.c
+index c0705fd..371b9bd 100644
+--- a/daemon/gdm-slave.c
++++ b/daemon/gdm-slave.c
+@@ -51,6 +51,11 @@
+ #include <libxklavier/xklavier.h>
+ #endif
+ 
++#ifdef WITH_SYSTEMD
++#include <systemd/sd-login.h>
++#include <systemd/sd-daemon.h>
++#endif
++
+ #include "gdm-common.h"
+ #include "gdm-xerrors.h"
+ 
+@@ -1198,6 +1203,8 @@ _get_uid_and_gid_for_user (const char *username,
+         return TRUE;
+ }
+ 
++#ifdef WITH_CONSOLE_KIT
++
+ static gboolean
+ x11_session_is_on_seat (GdmSlave        *slave,
+                         const char      *session_id,
+@@ -1295,9 +1302,63 @@ x11_session_is_on_seat (GdmSlave        *slave,
+         return ret;
+ }
+ 
+-char *
+-gdm_slave_get_primary_session_id_for_user (GdmSlave   *slave,
+-                                           const char *username)
++#endif
++
++#ifdef WITH_SYSTEMD
++static char*
++gdm_slave_get_primary_session_id_for_user_from_systemd (GdmSlave   *slave,
++                                                        const char *username)
++{
++        int     res, i;
++        char  **sessions;
++        uid_t   uid;
++        char   *primary_ssid;
++
++        primary_ssid = NULL;
++
++        res = sd_seat_can_multi_session (slave->priv->display_seat_id);
++        if (res < 0) {
++                g_warning ("GdmSlave: Failed to determine whether seat is multi-session capable: %s", strerror (-res));
++                return NULL;
++        } else if (res == 0) {
++                g_debug ("GdmSlave: seat is unable to activate sessions");
++                return NULL;
++        }
++
++        if (! _get_uid_and_gid_for_user (username, &uid, NULL)) {
++                g_debug ("GdmSlave: unable to determine uid for user: %s", username);
++                return NULL;
++        }
++
++        res = sd_seat_get_sessions (slave->priv->display_seat_id, &sessions, NULL, NULL);
++        if (res < 0) {
++                g_warning ("GdmSlave: Failed to get sessions on seat: %s", strerror (-res));
++                return NULL;
++        }
++
++        for (i = 0; sessions[i] != NULL; i++) {
++
++                if (primary_ssid == NULL) {
++                        uid_t other;
++
++                        res = sd_session_get_uid (sessions[i], &other);
++                        if (res > 0 && other == uid) {
++                                primary_ssid = g_strdup (sessions[i]);
++                        }
++                }
++
++                free (sessions[i]);
++        }
++
++        free (sessions);
++        return primary_ssid;
++}
++#endif
++
++#ifdef WITH_CONSOLE_KIT
++static char *
++gdm_slave_get_primary_session_id_for_user_from_ck (GdmSlave   *slave,
++                                                   const char *username)
+ {
+         gboolean    res;
+         gboolean    can_activate_sessions;
+@@ -1309,11 +1370,6 @@ gdm_slave_get_primary_session_id_for_user (GdmSlave   *slave,
+         int         i;
+         uid_t       uid;
+ 
+-        if (slave->priv->display_seat_id == NULL || slave->priv->display_seat_id[0] == '\0') {
+-                g_debug ("GdmSlave: display seat ID is not set; can't switch sessions");
+-                return NULL;
+-        }
+-
+         manager_proxy = NULL;
+         primary_ssid = NULL;
+         sessions = NULL;
+@@ -1396,11 +1452,91 @@ gdm_slave_get_primary_session_id_for_user (GdmSlave   *slave,
+ 
+         return primary_ssid;
+ }
++#endif
++
++char *
++gdm_slave_get_primary_session_id_for_user (GdmSlave   *slave,
++                                           const char *username)
++{
++
++        if (slave->priv->display_seat_id == NULL || slave->priv->display_seat_id[0] == '\0') {
++                g_debug ("GdmSlave: display seat ID is not set; can't switch sessions");
++                return NULL;
++        }
+ 
++#ifdef WITH_SYSTEMD
++        if (sd_booted () > 0) {
++                return gdm_slave_get_primary_session_id_for_user_from_systemd (slave, username);
++        }
++#endif
++
++#ifdef WITH_CONSOLE_KIT
++        return gdm_slave_get_primary_session_id_for_user_from_ck (slave, username);
++#else
++        return NULL;
++#endif
++}
++
++#ifdef WITH_SYSTEMD
+ static gboolean
+-activate_session_id (GdmSlave   *slave,
+-                     const char *seat_id,
+-                     const char *session_id)
++activate_session_id_for_systemd (GdmSlave   *slave,
++                                 const char *seat_id,
++                                 const char *session_id)
++{
++        DBusError    local_error;
++        DBusMessage *message;
++        DBusMessage *reply;
++        gboolean     ret;
++
++        ret = FALSE;
++        reply = NULL;
++
++        dbus_error_init (&local_error);
++
++        message = dbus_message_new_method_call ("org.freedesktop.login1",
++                                                "/org/freedesktop/login1",
++                                                "org.freedesktop.login1.Manager",
++                                                "ActivateSessionOnSeat");
++        if (message == NULL) {
++                goto out;
++        }
++
++        if (! dbus_message_append_args (message,
++                                        DBUS_TYPE_STRING, &session_id,
++                                        DBUS_TYPE_STRING, &seat_id,
++                                        DBUS_TYPE_INVALID)) {
++                goto out;
++        }
++
++        reply = dbus_connection_send_with_reply_and_block (dbus_g_connection_get_connection (slave->priv->connection),
++                                                           message,
++                                                           -1,
++                                                           &local_error);
++        if (dbus_error_is_set (&local_error)) {
++                g_warning ("GdmSlave: Unable to activate session: %s", local_error.message);
++                dbus_error_free (&local_error);
++                goto out;
++        }
++
++        ret = TRUE;
++
++ out:
++        if (message != NULL) {
++                dbus_message_unref (message);
++        }
++        if (reply != NULL) {
++                dbus_message_unref (reply);
++        }
++
++        return ret;
++}
++#endif
++
++#ifdef WITH_CONSOLE_KIT
++static gboolean
++activate_session_id_for_ck (GdmSlave   *slave,
++                            const char *seat_id,
++                            const char *session_id)
+ {
+         DBusError    local_error;
+         DBusMessage *message;
+@@ -1448,16 +1584,82 @@ activate_session_id (GdmSlave   *slave,
+ 
+         return ret;
+ }
++#endif
++
++static gboolean
++activate_session_id (GdmSlave   *slave,
++                     const char *seat_id,
++                     const char *session_id)
++{
++
++#ifdef WITH_SYSTEMD
++        if (sd_booted () > 0) {
++                return activate_session_id_for_systemd (slave, seat_id, session_id);
++        }
++#endif
++
++#ifdef WITH_CONSOLE_KIT
++        return activate_session_id_for_ck (slave, seat_id, session_id);
++#else
++        return FALSE;
++#endif
++}
+ 
++#ifdef WITH_SYSTEMD
+ static gboolean
+-session_unlock (GdmSlave   *slave,
+-                const char *ssid)
++session_unlock_for_systemd (GdmSlave   *slave,
++                            const char *ssid)
++{
++        DBusError       error;
++        DBusMessage    *message;
++        DBusMessage    *reply;
++
++        dbus_error_init (&error);
++
++        message = dbus_message_new_method_call ("org.freedesktop.login",
++                                                "/org/freedesktop/login1",
++                                                "org.freedesktop.login1.Manager",
++                                                "UnlockSession");
++
++        if (message == NULL) {
++                g_debug ("GdmSlave: couldn't allocate the D-Bus message");
++                return FALSE;
++        }
++
++        if (! dbus_message_append_args (message,
++                                        DBUS_TYPE_STRING, &ssid,
++                                        DBUS_TYPE_INVALID)) {
++                g_debug ("GdmSlave: couldn't attach the D-Bus message data");
++                return FALSE;
++        }
++
++        reply = dbus_connection_send_with_reply_and_block (dbus_g_connection_get_connection (slave->priv->connection),
++                                                           message,
++                                                           -1, &error);
++        dbus_message_unref(message);
++        if (reply != NULL) {
++                dbus_message_unref(reply);
++        }
++
++        if (dbus_error_is_set (&error)) {
++                g_warning ("GdmSlave: Unable to unlock session: %s", error.message);
++                dbus_error_free (&error);
++                return FALSE;
++        }
++
++        return TRUE;
++}
++#endif
++
++#ifdef WITH_CONSOLE_KIT
++static gboolean
++session_unlock_for_ck (GdmSlave   *slave,
++                       const char *ssid)
+ {
+         DBusError       error;
+         DBusMessage    *message;
+         DBusMessage    *reply;
+ 
+-        g_debug ("ConsoleKit: Unlocking session %s", ssid);
+         message = dbus_message_new_method_call (CK_NAME,
+                                                 ssid,
+                                                 CK_SESSION_INTERFACE,
+@@ -1485,6 +1687,27 @@ session_unlock (GdmSlave   *slave,
+ 
+         return TRUE;
+ }
++#endif
++
++static gboolean
++session_unlock (GdmSlave   *slave,
++                const char *ssid)
++{
++
++        g_debug ("ConsoleKit: Unlocking session %s", ssid);
++
++#ifdef WITH_SYSTEMD
++        if (sd_booted () > 0) {
++                return session_unlock_for_systemd (slave, ssid);
++        }
++#endif
++
++#ifdef WITH_CONSOLE_KIT
++        return session_unlock_for_ck (slave, ssid);
++#else
++        return TRUE;
++#endif
++}
+ 
+ gboolean
+ gdm_slave_switch_to_user_session (GdmSlave   *slave,
+-- 
+1.7.9
+
+
+From c77c03e6ca67ea670de89babbbfd9648b2fec9bd Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart at poettering.net>
+Date: Wed, 27 Jul 2011 01:27:22 +0200
+Subject: [PATCH 05/11] build-sys: make CK support optional
+
+---
+ daemon/Makefile.am |    8 ++++++--
+ 1 files changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/daemon/Makefile.am b/daemon/Makefile.am
+index 43d416e..b228fea 100644
+--- a/daemon/Makefile.am
++++ b/daemon/Makefile.am
+@@ -264,8 +264,6 @@ gdm_xdmcp_chooser_slave_LDADD = 		\
+ 
+ gdm_session_worker_SOURCES = 			\
+ 	session-worker-main.c 			\
+-	ck-connector.h				\
+-	ck-connector.c				\
+ 	gdm-session-settings.h			\
+ 	gdm-session-settings.c			\
+ 	gdm-session-auditor.h			\
+@@ -274,6 +272,12 @@ gdm_session_worker_SOURCES = 			\
+ 	gdm-session-worker.c			\
+ 	$(NULL)
+ 
++if WITH_CONSOLE_KIT
++gdm_session_worker_SOURCES += 			\
++	ck-connector.h				\
++	ck-connector.c
++endif
++
+ if HAVE_LIBAUDIT
+ gdm_session_worker_SOURCES += gdm-session-linux-auditor.h       \
+ 	                      gdm-session-linux-auditor.c
+-- 
+1.7.9
+
+
+From 54abef19f0b338d7c57c4629f6ca2cf441bcb553 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart at poettering.net>
+Date: Wed, 27 Jul 2011 01:30:09 +0200
+Subject: [PATCH 06/11] slave: pass seat id from product/simple slave to
+ worker, via the direct session
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Pass seat id from product and simple slave to the direct sessions
+created by it (along with the other display meta data we pass already).
+
+Pass seat id from session to worker (via D-Bus) along with the other
+display meta data.
+
+We need the seat information for the PAM conversation (later patch)
+hence we need to pass it from the slaves down to the workers.
+
+(Note that the seat ID has always been passed from the display to the
+slave, we just need to pass it on the worker now, so that the chain is
+complete: display → slave → session → worker)
+---
+ daemon/gdm-product-slave.c   |    3 ++
+ daemon/gdm-session-direct.c  |   60 ++++++++++++++++++++++++++++++++++++++++++
+ daemon/gdm-session-direct.h  |    2 +
+ daemon/gdm-session-worker.c  |   12 +++++++-
+ daemon/gdm-simple-slave.c    |    3 ++
+ daemon/gdm-welcome-session.c |    1 +
+ daemon/test-session.c        |    1 +
+ 7 files changed, 81 insertions(+), 1 deletions(-)
+
+diff --git a/daemon/gdm-product-slave.c b/daemon/gdm-product-slave.c
+index d56a74b..629c6e7 100644
+--- a/daemon/gdm-product-slave.c
++++ b/daemon/gdm-product-slave.c
+@@ -998,6 +998,7 @@ create_new_session (GdmProductSlave *slave)
+         char          *display_name;
+         char          *display_hostname;
+         char          *display_device;
++        char          *display_seat_id;
+         char          *display_x11_authority_file;
+ 
+         g_debug ("GdmProductSlave: Creating new session");
+@@ -1008,6 +1009,7 @@ create_new_session (GdmProductSlave *slave)
+                       "display-hostname", &display_hostname,
+                       "display-is-local", &display_is_local,
+                       "display-x11-authority-file", &display_x11_authority_file,
++                      "display-seat-id", &display_seat_id,
+                       NULL);
+ 
+         /* FIXME: we don't yet have a display device! */
+@@ -1017,6 +1019,7 @@ create_new_session (GdmProductSlave *slave)
+                                                        display_name,
+                                                        display_hostname,
+                                                        display_device,
++                                                       display_seat_id,
+                                                        display_x11_authority_file,
+                                                        display_is_local);
+         g_free (display_id);
+diff --git a/daemon/gdm-session-direct.c b/daemon/gdm-session-direct.c
+index bb2bff8..9f750f2 100644
+--- a/daemon/gdm-session-direct.c
++++ b/daemon/gdm-session-direct.c
+@@ -103,6 +103,7 @@ struct _GdmSessionDirectPrivate
+         char                *display_name;
+         char                *display_hostname;
+         char                *display_device;
++        char                *display_seat_id;
+         char                *display_x11_authority_file;
+         gboolean             display_is_local;
+ 
+@@ -121,6 +122,7 @@ enum {
+         PROP_DISPLAY_HOSTNAME,
+         PROP_DISPLAY_IS_LOCAL,
+         PROP_DISPLAY_DEVICE,
++        PROP_DISPLAY_SEAT_ID,
+         PROP_DISPLAY_X11_AUTHORITY_FILE,
+         PROP_USER_X11_AUTHORITY_FILE,
+ };
+@@ -1389,6 +1391,7 @@ do_introspect (DBusConnection *connection,
+                                "      <arg name=\"service_name\" type=\"s\"/>\n"
+                                "      <arg name=\"x11_display_name\" type=\"s\"/>\n"
+                                "      <arg name=\"display_device\" type=\"s\"/>\n"
++                               "      <arg name=\"display_seat\" type=\"s\"/>\n"
+                                "      <arg name=\"hostname\" type=\"s\"/>\n"
+                                "      <arg name=\"x11_authority_file\" type=\"s\"/>\n"
+                                "    </signal>\n"
+@@ -1396,6 +1399,7 @@ do_introspect (DBusConnection *connection,
+                                "      <arg name=\"service_name\" type=\"s\"/>\n"
+                                "      <arg name=\"x11_display_name\" type=\"s\"/>\n"
+                                "      <arg name=\"display_device\" type=\"s\"/>\n"
++                               "      <arg name=\"display_seat\" type=\"s\"/>\n"
+                                "      <arg name=\"hostname\" type=\"s\"/>\n"
+                                "      <arg name=\"x11_authority_file\" type=\"s\"/>\n"
+                                "      <arg name=\"username\" type=\"s\"/>\n"
+@@ -1404,6 +1408,7 @@ do_introspect (DBusConnection *connection,
+                                "      <arg name=\"service_name\" type=\"s\"/>\n"
+                                "      <arg name=\"x11_display_name\" type=\"s\"/>\n"
+                                "      <arg name=\"display_device\" type=\"s\"/>\n"
++                               "      <arg name=\"display_seat\" type=\"s\"/>\n"
+                                "      <arg name=\"hostname\" type=\"s\"/>\n"
+                                "      <arg name=\"x11_authority_file\" type=\"s\"/>\n"
+                                "      <arg name=\"log_file\" type=\"s\"/>\n"
+@@ -1975,6 +1980,7 @@ send_setup (GdmSessionDirect *session,
+         DBusMessageIter iter;
+         const char     *display_name;
+         const char     *display_device;
++        const char     *display_seat_id;
+         const char     *display_hostname;
+         const char     *display_x11_authority_file;
+         GdmSessionConversation *conversation;
+@@ -1996,6 +2002,11 @@ send_setup (GdmSessionDirect *session,
+         } else {
+                 display_device = "";
+         }
++        if (session->priv->display_seat_id != NULL) {
++                display_seat_id = session->priv->display_seat_id;
++        } else {
++                display_seat_id = "";
++        }
+         if (session->priv->display_x11_authority_file != NULL) {
+                 display_x11_authority_file = session->priv->display_x11_authority_file;
+         } else {
+@@ -2012,6 +2023,7 @@ send_setup (GdmSessionDirect *session,
+         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &service_name);
+         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_name);
+         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_device);
++        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_seat_id);
+         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_hostname);
+         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_x11_authority_file);
+ 
+@@ -2031,6 +2043,7 @@ send_setup_for_user (GdmSessionDirect *session,
+         DBusMessageIter iter;
+         const char     *display_name;
+         const char     *display_device;
++        const char     *display_seat_id;
+         const char     *display_hostname;
+         const char     *display_x11_authority_file;
+         const char     *selected_user;
+@@ -2053,6 +2066,11 @@ send_setup_for_user (GdmSessionDirect *session,
+         } else {
+                 display_device = "";
+         }
++        if (session->priv->display_seat_id != NULL) {
++                display_seat_id = session->priv->display_seat_id;
++        } else {
++                display_seat_id = "";
++        }
+         if (session->priv->display_x11_authority_file != NULL) {
+                 display_x11_authority_file = session->priv->display_x11_authority_file;
+         } else {
+@@ -2074,6 +2092,7 @@ send_setup_for_user (GdmSessionDirect *session,
+         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &service_name);
+         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_name);
+         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_device);
++        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_seat_id);
+         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_hostname);
+         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_x11_authority_file);
+         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &selected_user);
+@@ -2095,6 +2114,7 @@ send_setup_for_program (GdmSessionDirect *session,
+         DBusMessageIter iter;
+         const char     *display_name;
+         const char     *display_device;
++        const char     *display_seat_id;
+         const char     *display_hostname;
+         const char     *display_x11_authority_file;
+         GdmSessionConversation *conversation;
+@@ -2116,6 +2136,11 @@ send_setup_for_program (GdmSessionDirect *session,
+         } else {
+                 display_device = "";
+         }
++        if (session->priv->display_seat_id != NULL) {
++                display_seat_id = session->priv->display_seat_id;
++        } else {
++                display_seat_id = "";
++        }
+         if (session->priv->display_x11_authority_file != NULL) {
+                 display_x11_authority_file = session->priv->display_x11_authority_file;
+         } else {
+@@ -2132,6 +2157,7 @@ send_setup_for_program (GdmSessionDirect *session,
+         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &service_name);
+         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_name);
+         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_device);
++        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_seat_id);
+         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_hostname);
+         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_x11_authority_file);
+         dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &log_file);
+@@ -2587,6 +2613,14 @@ gdm_session_direct_get_display_device (GdmSessionDirect *session)
+         return g_strdup (session->priv->display_device);
+ }
+ 
++char *
++gdm_session_direct_get_display_seat_id (GdmSessionDirect *session)
++{
++        g_return_val_if_fail (session != NULL, NULL);
++
++        return g_strdup (session->priv->display_seat_id);
++}
++
+ gboolean
+ gdm_session_direct_bypasses_xsession (GdmSessionDirect *session_direct)
+ {
+@@ -2754,6 +2788,14 @@ _gdm_session_direct_set_display_device (GdmSessionDirect *session,
+ }
+ 
+ static void
++_gdm_session_direct_set_display_seat_id (GdmSessionDirect *session,
++                                         const char       *name)
++{
++        g_free (session->priv->display_seat_id);
++        session->priv->display_seat_id = g_strdup (name);
++}
++
++static void
+ _gdm_session_direct_set_user_x11_authority_file (GdmSessionDirect *session,
+                                                  const char       *name)
+ {
+@@ -2799,6 +2841,9 @@ gdm_session_direct_set_property (GObject      *object,
+         case PROP_DISPLAY_DEVICE:
+                 _gdm_session_direct_set_display_device (self, g_value_get_string (value));
+                 break;
++        case PROP_DISPLAY_SEAT_ID:
++                _gdm_session_direct_set_display_seat_id (self, g_value_get_string (value));
++                break;
+         case PROP_USER_X11_AUTHORITY_FILE:
+                 _gdm_session_direct_set_user_x11_authority_file (self, g_value_get_string (value));
+                 break;
+@@ -2837,6 +2882,9 @@ gdm_session_direct_get_property (GObject    *object,
+         case PROP_DISPLAY_DEVICE:
+                 g_value_set_string (value, self->priv->display_device);
+                 break;
++        case PROP_DISPLAY_SEAT_ID:
++                g_value_set_string (value, self->priv->display_seat_id);
++                break;
+         case PROP_USER_X11_AUTHORITY_FILE:
+                 g_value_set_string (value, self->priv->user_x11_authority_file);
+                 break;
+@@ -2875,6 +2923,9 @@ gdm_session_direct_dispose (GObject *object)
+         g_free (session->priv->display_device);
+         session->priv->display_device = NULL;
+ 
++        g_free (session->priv->display_seat_id);
++        session->priv->display_seat_id = NULL;
++
+         g_free (session->priv->display_x11_authority_file);
+         session->priv->display_x11_authority_file = NULL;
+ 
+@@ -3063,6 +3114,13 @@ gdm_session_direct_class_init (GdmSessionDirectClass *session_class)
+                                                               NULL,
+                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ 
++        g_object_class_install_property (object_class,
++                                         PROP_DISPLAY_SEAT_ID,
++                                         g_param_spec_string ("display-seat-id",
++                                                              "display seat id",
++                                                              "display seat id",
++                                                              NULL,
++                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ 
+         dbus_g_object_type_install_info (GDM_TYPE_SESSION_DIRECT, &dbus_glib_gdm_session_direct_object_info);
+ }
+@@ -3072,6 +3130,7 @@ gdm_session_direct_new (const char *display_id,
+                         const char *display_name,
+                         const char *display_hostname,
+                         const char *display_device,
++                        const char *display_seat_id,
+                         const char *display_x11_authority_file,
+                         gboolean    display_is_local)
+ {
+@@ -3082,6 +3141,7 @@ gdm_session_direct_new (const char *display_id,
+                                 "display-name", display_name,
+                                 "display-hostname", display_hostname,
+                                 "display-device", display_device,
++                                "display-seat-id", display_seat_id,
+                                 "display-x11-authority-file", display_x11_authority_file,
+                                 "display-is-local", display_is_local,
+                                 NULL);
+diff --git a/daemon/gdm-session-direct.h b/daemon/gdm-session-direct.h
+index 8023bf9..e35fa35 100644
+--- a/daemon/gdm-session-direct.h
++++ b/daemon/gdm-session-direct.h
+@@ -52,11 +52,13 @@ GdmSessionDirect * gdm_session_direct_new                      (const char *disp
+                                                                 const char *display_name,
+                                                                 const char *display_hostname,
+                                                                 const char *display_device,
++                                                                const char *display_seat_id,
+                                                                 const char *display_x11_authority_file,
+                                                                 gboolean    display_is_local) G_GNUC_MALLOC;
+ 
+ char             * gdm_session_direct_get_username             (GdmSessionDirect     *session_direct);
+ char             * gdm_session_direct_get_display_device       (GdmSessionDirect     *session_direct);
++char             * gdm_session_direct_get_display_seat_id      (GdmSessionDirect     *session_direct);
+ gboolean           gdm_session_direct_bypasses_xsession        (GdmSessionDirect     *session_direct);
+ 
+ /* Exported methods */
+diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
+index c402e6c..1fe0aaf 100644
+--- a/daemon/gdm-session-worker.c
++++ b/daemon/gdm-session-worker.c
+@@ -118,6 +118,7 @@ struct GdmSessionWorkerPrivate
+         char             *x11_display_name;
+         char             *x11_authority_file;
+         char             *display_device;
++        char             *display_seat_id;
+         char             *hostname;
+         char             *username;
+         char             *log_file;
+@@ -2494,6 +2495,7 @@ on_setup (GdmSessionWorker *worker,
+         const char *x11_display_name;
+         const char *x11_authority_file;
+         const char *console;
++        const char *seat_id;
+         const char *hostname;
+         dbus_bool_t res;
+ 
+@@ -2508,6 +2510,7 @@ on_setup (GdmSessionWorker *worker,
+                                      DBUS_TYPE_STRING, &service,
+                                      DBUS_TYPE_STRING, &x11_display_name,
+                                      DBUS_TYPE_STRING, &console,
++                                     DBUS_TYPE_STRING, &seat_id,
+                                      DBUS_TYPE_STRING, &hostname,
+                                      DBUS_TYPE_STRING, &x11_authority_file,
+                                      DBUS_TYPE_INVALID);
+@@ -2516,6 +2519,7 @@ on_setup (GdmSessionWorker *worker,
+                 worker->priv->x11_display_name = g_strdup (x11_display_name);
+                 worker->priv->x11_authority_file = g_strdup (x11_authority_file);
+                 worker->priv->display_device = g_strdup (console);
++                worker->priv->display_seat_id = g_strdup (seat_id);
+                 worker->priv->hostname = g_strdup (hostname);
+                 worker->priv->username = NULL;
+ 
+@@ -2536,6 +2540,7 @@ on_setup_for_user (GdmSessionWorker *worker,
+         const char *x11_display_name;
+         const char *x11_authority_file;
+         const char *console;
++        const char *seat_id;
+         const char *hostname;
+         const char *username;
+         dbus_bool_t res;
+@@ -2551,6 +2556,7 @@ on_setup_for_user (GdmSessionWorker *worker,
+                                      DBUS_TYPE_STRING, &service,
+                                      DBUS_TYPE_STRING, &x11_display_name,
+                                      DBUS_TYPE_STRING, &console,
++                                     DBUS_TYPE_STRING, &seat_id,
+                                      DBUS_TYPE_STRING, &hostname,
+                                      DBUS_TYPE_STRING, &x11_authority_file,
+                                      DBUS_TYPE_STRING, &username,
+@@ -2560,6 +2566,7 @@ on_setup_for_user (GdmSessionWorker *worker,
+                 worker->priv->x11_display_name = g_strdup (x11_display_name);
+                 worker->priv->x11_authority_file = g_strdup (x11_authority_file);
+                 worker->priv->display_device = g_strdup (console);
++                worker->priv->display_seat_id = g_strdup (seat_id);
+                 worker->priv->hostname = g_strdup (hostname);
+                 worker->priv->username = g_strdup (username);
+ 
+@@ -2598,6 +2605,7 @@ on_setup_for_program (GdmSessionWorker *worker,
+         char *service;
+         char *x11_display_name;
+         char *console;
++        char *seat_id;
+         char *hostname;
+         char *x11_authority_file;
+         char *log_file;
+@@ -2614,6 +2622,7 @@ on_setup_for_program (GdmSessionWorker *worker,
+                                      DBUS_TYPE_STRING, &service,
+                                      DBUS_TYPE_STRING, &x11_display_name,
+                                      DBUS_TYPE_STRING, &console,
++                                     DBUS_TYPE_STRING, &seat_id,
+                                      DBUS_TYPE_STRING, &hostname,
+                                      DBUS_TYPE_STRING, &x11_authority_file,
+                                      DBUS_TYPE_STRING, &log_file,
+@@ -2627,6 +2636,7 @@ on_setup_for_program (GdmSessionWorker *worker,
+                 worker->priv->x11_display_name = g_strdup (x11_display_name);
+                 worker->priv->hostname = g_strdup (hostname);
+                 worker->priv->display_device = g_strdup (console);
++                worker->priv->display_seat_id = g_strdup (seat_id);
+                 worker->priv->x11_authority_file = g_strdup (x11_authority_file);
+                 worker->priv->log_file = g_strdup (log_file);
+                 worker->priv->is_program_session = TRUE;
+@@ -2945,6 +2955,7 @@ gdm_session_worker_finalize (GObject *object)
+         g_free (worker->priv->x11_display_name);
+         g_free (worker->priv->x11_authority_file);
+         g_free (worker->priv->display_device);
++        g_free (worker->priv->display_seat_id);
+         g_free (worker->priv->hostname);
+         g_free (worker->priv->username);
+         g_free (worker->priv->server_address);
+@@ -2964,4 +2975,3 @@ gdm_session_worker_new (const char *address)
+ 
+         return GDM_SESSION_WORKER (object);
+ }
+-
+diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c
+index b9165fd..873b7f9 100644
+--- a/daemon/gdm-simple-slave.c
++++ b/daemon/gdm-simple-slave.c
+@@ -750,6 +750,7 @@ create_new_session (GdmSimpleSlave *slave)
+         char          *display_name;
+         char          *display_hostname;
+         char          *display_device;
++        char          *display_seat_id;
+         char          *display_x11_authority_file;
+ 
+         g_debug ("GdmSimpleSlave: Creating new session");
+@@ -760,6 +761,7 @@ create_new_session (GdmSimpleSlave *slave)
+                       "display-hostname", &display_hostname,
+                       "display-is-local", &display_is_local,
+                       "display-x11-authority-file", &display_x11_authority_file,
++                      "display-seat-id", &display_seat_id,
+                       NULL);
+ 
+         display_device = NULL;
+@@ -771,6 +773,7 @@ create_new_session (GdmSimpleSlave *slave)
+                                                        display_name,
+                                                        display_hostname,
+                                                        display_device,
++                                                       display_seat_id,
+                                                        display_x11_authority_file,
+                                                        display_is_local);
+         g_free (display_id);
+diff --git a/daemon/gdm-welcome-session.c b/daemon/gdm-welcome-session.c
+index 8721fe7..26af552 100644
+--- a/daemon/gdm-welcome-session.c
++++ b/daemon/gdm-welcome-session.c
+@@ -849,6 +849,7 @@ gdm_welcome_session_start (GdmWelcomeSession *welcome_session)
+                                                                               welcome_session->priv->x11_display_name,
+                                                                               welcome_session->priv->x11_display_hostname,
+                                                                               welcome_session->priv->x11_display_device,
++                                                                              welcome_session->priv->x11_display_seat_id,
+                                                                               welcome_session->priv->x11_authority_file,
+                                                                               welcome_session->priv->x11_display_is_local));
+ 
+diff --git a/daemon/test-session.c b/daemon/test-session.c
+index fe78230..f75d5ed 100644
+--- a/daemon/test-session.c
++++ b/daemon/test-session.c
+@@ -268,6 +268,7 @@ main (int   argc,
+                                                   ":0",
+                                                   g_get_host_name (),
+                                                   ttyname (STDIN_FILENO),
++                                                  "",
+                                                   getenv("XAUTHORITY"),
+                                                   TRUE);
+                 g_debug ("GdmSessionDirect object created successfully");
+-- 
+1.7.9
+
+
+From 69a8b09c993669e324c785be463136313be2cdb4 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart at poettering.net>
+Date: Wed, 27 Jul 2011 01:31:16 +0200
+Subject: [PATCH 07/11] pam: pass XDG_SEAT env var into PAM to inform PAM
+ modules about seat id
+
+This optionally replaces the current CK session registration logic with
+support for passing seat information to pam_systemd (and hence rely on
+pam_systemd's session registration).
+
+With this patch applied we can register sessions in systemd and in CK
+with the same binary.
+---
+ daemon/Makefile.am          |    1 +
+ daemon/gdm-session-worker.c |   34 ++++++++++++++++++++++++++++++++++
+ 2 files changed, 35 insertions(+), 0 deletions(-)
+
+diff --git a/daemon/Makefile.am b/daemon/Makefile.am
+index b228fea..8f8eedf 100644
+--- a/daemon/Makefile.am
++++ b/daemon/Makefile.am
+@@ -296,6 +296,7 @@ gdm_session_worker_LDFLAGS =			\
+ gdm_session_worker_LDADD = 			\
+ 	$(top_builddir)/common/libgdmcommon.la	\
+ 	$(DAEMON_LIBS)				\
++	$(SYSTEMD_LIBS) 			\
+ 	$(NULL)
+ 
+ sbin_PROGRAMS = 			\
+diff --git a/daemon/gdm-session-worker.c b/daemon/gdm-session-worker.c
+index 1fe0aaf..acf820c 100644
+--- a/daemon/gdm-session-worker.c
++++ b/daemon/gdm-session-worker.c
+@@ -46,7 +46,13 @@
+ 
+ #include <X11/Xauth.h>
+ 
++#ifdef WITH_SYSTEMD
++#include <systemd/sd-daemon.h>
++#endif
++
++#ifdef WITH_CONSOLE_KIT
+ #include "ck-connector.h"
++#endif
+ 
+ #include "gdm-common.h"
+ #include "gdm-log.h"
+@@ -107,7 +113,9 @@ struct GdmSessionWorkerPrivate
+ 
+         int               exit_code;
+ 
++#ifdef WITH_CONSOLE_KIT
+         CkConnector      *ckc;
++#endif
+         pam_handle_t     *pam_handle;
+ 
+         GPid              child_pid;
+@@ -151,8 +159,13 @@ static void     gdm_session_worker_class_init   (GdmSessionWorkerClass *klass);
+ static void     gdm_session_worker_init         (GdmSessionWorker      *session_worker);
+ static void     gdm_session_worker_finalize     (GObject               *object);
+ 
++static void     gdm_session_worker_set_environment_variable (GdmSessionWorker *worker,
++                                                             const char       *key,
++                                                             const char       *value);
++
+ static void     queue_state_change              (GdmSessionWorker      *worker);
+ 
++
+ typedef int (* GdmSessionWorkerPamNewMessagesFunc) (int,
+                                                     const struct pam_message **,
+                                                     struct pam_response **,
+@@ -171,6 +184,7 @@ gdm_session_worker_error_quark (void)
+         return error_quark;
+ }
+ 
++#ifdef WITH_CONSOLE_KIT
+ static gboolean
+ open_ck_session (GdmSessionWorker  *worker)
+ {
+@@ -257,6 +271,7 @@ open_ck_session (GdmSessionWorker  *worker)
+  out:
+         return ret;
+ }
++#endif
+ 
+ /* adapted from glib script_execute */
+ static void
+@@ -1057,6 +1072,7 @@ gdm_session_worker_initialize_pam (GdmSessionWorker *worker,
+                                    const char       *x11_display_name,
+                                    const char       *x11_authority_file,
+                                    const char       *display_device,
++                                   const char       *seat_id,
+                                    GError          **error)
+ {
+         struct pam_conv        pam_conversation;
+@@ -1138,6 +1154,13 @@ gdm_session_worker_initialize_pam (GdmSessionWorker *worker,
+                 goto out;
+         }
+ 
++#ifdef WITH_SYSTEMD
++        /* set seat ID */
++        if (seat_id != NULL && seat_id[0] != '\0' && sd_booted() > 0) {
++                gdm_session_worker_set_environment_variable (worker, "XDG_SEAT", seat_id);
++        }
++#endif
++
+ #ifdef PAM_XDISPLAY
+         /* set XDISPLAY */
+         error_code = pam_set_item (worker->priv->pam_handle, PAM_XDISPLAY, x11_display_name);
+@@ -1571,6 +1594,13 @@ register_ck_session (GdmSessionWorker *worker)
+         const char *session_cookie;
+         gboolean    res;
+ 
++#ifdef WITH_SYSTEMD
++        if (sd_booted() > 0) {
++                return;
++        }
++#endif
++
++#ifdef WITH_CONSOLE_KIT
+         session_cookie = NULL;
+         res = open_ck_session (worker);
+         if (res) {
+@@ -1581,6 +1611,7 @@ register_ck_session (GdmSessionWorker *worker)
+                                                              "XDG_SESSION_COOKIE",
+                                                              session_cookie);
+         }
++#endif
+ }
+ 
+ static void
+@@ -1611,11 +1642,13 @@ session_worker_child_watch (GPid              pid,
+                                       num);
+         }
+ 
++#ifdef WITH_CONSOLE_KIT
+         if (worker->priv->ckc != NULL) {
+                 ck_connector_close_session (worker->priv->ckc, NULL);
+                 ck_connector_unref (worker->priv->ckc);
+                 worker->priv->ckc = NULL;
+         }
++#endif
+ 
+         gdm_session_worker_uninitialize_pam (worker, PAM_SUCCESS);
+ 
+@@ -2140,6 +2173,7 @@ do_setup (GdmSessionWorker *worker)
+                                                  worker->priv->x11_display_name,
+                                                  worker->priv->x11_authority_file,
+                                                  worker->priv->display_device,
++                                                 worker->priv->display_seat_id,
+                                                  &error);
+         if (! res) {
+                 if (g_error_matches (error,
+-- 
+1.7.9
+
+
+From 6e9fb3fb4df7d05c803cc01fe638eb9cf88c4beb Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart at poettering.net>
+Date: Wed, 27 Jul 2011 01:32:54 +0200
+Subject: [PATCH 08/11] local-display-factory: subscribe to new seats being
+ created and removed
+
+logind will notify us when ever a new seat becomes available in the
+system, or an existing seat is removed. We simply create a new display
+for each seat showing up and remove a display when a seat goes away.
+---
+ daemon/Makefile.am                 |    1 +
+ daemon/gdm-local-display-factory.c |  239 +++++++++++++++++++++++++++++++++---
+ 2 files changed, 224 insertions(+), 16 deletions(-)
+
+diff --git a/daemon/Makefile.am b/daemon/Makefile.am
+index 8f8eedf..ffbaf9b 100644
+--- a/daemon/Makefile.am
++++ b/daemon/Makefile.am
+@@ -363,6 +363,7 @@ gdm_binary_LDADD = \
+ 	$(DAEMON_LIBS)				\
+ 	$(XDMCP_LIBS)                           \
+ 	$(LIBWRAP_LIBS)                         \
++	$(SYSTEMD_LIBS)				\
+ 	$(NULL)
+ 
+ if WITH_CONSOLE_KIT
+diff --git a/daemon/gdm-local-display-factory.c b/daemon/gdm-local-display-factory.c
+index 349c7b2..988b2ff 100644
+--- a/daemon/gdm-local-display-factory.c
++++ b/daemon/gdm-local-display-factory.c
+@@ -27,6 +27,13 @@
+ #include <glib/gi18n.h>
+ #include <glib-object.h>
+ 
++#include <dbus/dbus.h>
++#include <dbus/dbus-glib-lowlevel.h>
++
++#ifdef WITH_SYSTEMD
++#include <systemd/sd-daemon.h>
++#endif
++
+ #include "gdm-display-factory.h"
+ #include "gdm-local-display-factory.h"
+ #include "gdm-local-display-factory-glue.h"
+@@ -64,7 +71,8 @@ static void     gdm_local_display_factory_class_init    (GdmLocalDisplayFactoryC
+ static void     gdm_local_display_factory_init          (GdmLocalDisplayFactory      *factory);
+ static void     gdm_local_display_factory_finalize      (GObject                     *object);
+ 
+-static GdmDisplay *create_display                       (GdmLocalDisplayFactory      *factory);
++static GdmDisplay *create_display                       (GdmLocalDisplayFactory      *factory,
++                                                         const char                  *seat_id);
+ 
+ static gpointer local_display_factory_object = NULL;
+ 
+@@ -282,6 +290,7 @@ on_static_display_status_changed (GdmDisplay             *display,
+         int              status;
+         GdmDisplayStore *store;
+         int              num;
++        char            *seat_id = NULL;
+ 
+         num = -1;
+         gdm_display_get_x11_display_number (display, &num, NULL);
+@@ -289,6 +298,8 @@ on_static_display_status_changed (GdmDisplay             *display,
+ 
+         store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
+ 
++        g_object_get (display, "seat-id", &seat_id, NULL);
++
+         status = gdm_display_get_status (display);
+ 
+         g_debug ("GdmLocalDisplayFactory: static display status changed: %d", status);
+@@ -300,7 +311,7 @@ on_static_display_status_changed (GdmDisplay             *display,
+                 gdm_display_store_remove (store, display);
+                 /* reset num failures */
+                 factory->priv->num_failures = 0;
+-                create_display (factory);
++                create_display (factory, seat_id);
+                 break;
+         case GDM_DISPLAY_FAILED:
+                 /* leave the display number in factory->priv->displays
+@@ -313,7 +324,7 @@ on_static_display_status_changed (GdmDisplay             *display,
+                         /* FIXME: should monitor hardware changes to
+                            try again when seats change */
+                 } else {
+-                        create_display (factory);
++                        create_display (factory, seat_id);
+                 }
+                 break;
+         case GDM_DISPLAY_UNMANAGED:
+@@ -326,13 +337,44 @@ on_static_display_status_changed (GdmDisplay             *display,
+                 g_assert_not_reached ();
+                 break;
+         }
++
++        g_free (seat_id);
++}
++
++static gboolean
++lookup_by_seat_id (const char *id,
++                   GdmDisplay *display,
++                   gpointer    user_data)
++{
++        const char *looking_for = user_data;
++        char *current;
++        gboolean res;
++
++        g_object_get (G_OBJECT (display), "seat-id", &current, NULL);
++
++        res = g_strcmp0 (current, looking_for) == 0;
++
++        g_free(current);
++
++        return res;
+ }
+ 
+ static GdmDisplay *
+-create_display (GdmLocalDisplayFactory *factory)
++create_display (GdmLocalDisplayFactory *factory,
++                const char             *seat_id)
+ {
+-        GdmDisplay *display;
+-        guint32     num;
++        GdmDisplayStore *store;
++        GdmDisplay      *display;
++        guint32          num;
++
++        /* Ensure we don't create the same display more than once */
++        store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
++        display = gdm_display_store_find (store, lookup_by_seat_id, (gpointer) seat_id);
++        if (display != NULL) {
++                return NULL;
++        }
++
++        g_debug ("GdmLocalDisplayFactory: Adding display on seat %s", seat_id);
+ 
+         num = take_next_display_number (factory);
+ 
+@@ -342,8 +384,7 @@ create_display (GdmLocalDisplayFactory *factory)
+         display = gdm_static_display_new (num);
+ #endif
+ 
+-        /* FIXME: don't hardcode seat1? */
+-        g_object_set (display, "seat-id", CK_SEAT1_PATH, NULL);
++        g_object_set (display, "seat-id", seat_id, NULL);
+ 
+         g_signal_connect (display,
+                           "notify::status",
+@@ -362,24 +403,182 @@ create_display (GdmLocalDisplayFactory *factory)
+         return display;
+ }
+ 
++#ifdef WITH_SYSTEMD
++
++static void
++delete_display (GdmLocalDisplayFactory *factory,
++                const char             *seat_id) {
++
++        GdmDisplayStore *store;
++
++        g_debug ("GdmLocalDisplayFactory: Removing displays on seat %s", seat_id);
++
++        store = gdm_display_factory_get_display_store (GDM_DISPLAY_FACTORY (factory));
++        gdm_display_store_foreach_remove (store, lookup_by_seat_id, (gpointer) seat_id);
++}
++
++static gboolean gdm_local_display_factory_sync_seats (GdmLocalDisplayFactory *factory)
++{
++        DBusError error;
++        DBusMessage *message, *reply;
++        DBusMessageIter iter, sub, sub2;
++
++        dbus_error_init (&error);
++
++        message = dbus_message_new_method_call (
++                        "org.freedesktop.login1",
++                        "/org/freedesktop/login1",
++                        "org.freedesktop.login1.Manager",
++                        "ListSeats");
++        if (message == NULL) {
++                g_warning ("GdmLocalDisplayFactory: Failed to allocate message");
++                return FALSE;
++        }
++
++        reply = dbus_connection_send_with_reply_and_block (dbus_g_connection_get_connection (factory->priv->connection), message, -1, &error);
++        dbus_message_unref (message);
++
++        if (reply == NULL) {
++                g_warning ("GdmLocalDisplayFactory: Failed to issue method call: %s", error.message);
++                dbus_error_free (&error);
++                return FALSE;
++        }
++
++        if (!dbus_message_iter_init (reply, &iter) ||
++            dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY ||
++            dbus_message_iter_get_element_type (&iter) != DBUS_TYPE_STRUCT)  {
++                g_warning ("GdmLocalDisplayFactory: Failed to parse reply.");
++                dbus_message_unref (reply);
++                return FALSE;
++        }
++
++        dbus_message_iter_recurse (&iter, &sub);
++
++        while (dbus_message_iter_get_arg_type (&sub) != DBUS_TYPE_INVALID) {
++                const char *seat;
++
++                if (dbus_message_iter_get_arg_type (&sub) != DBUS_TYPE_STRUCT) {
++                        g_warning ("GdmLocalDisplayFactory: Failed to parse reply.");
++                        dbus_message_unref (reply);
++                        return FALSE;
++                }
++
++                dbus_message_iter_recurse (&sub, &sub2);
++
++                if (dbus_message_iter_get_arg_type (&sub2) != DBUS_TYPE_STRING) {
++                        g_warning ("GdmLocalDisplayFactory: Failed to parse reply.");
++                        dbus_message_unref (reply);
++                        return FALSE;
++                }
++
++                dbus_message_iter_get_basic (&sub2, &seat);
++                create_display (factory, seat);
++
++                dbus_message_iter_next (&sub);
++        }
++
++        dbus_message_unref (reply);
++        return TRUE;
++}
++
++static DBusHandlerResult
++on_seat_signal (DBusConnection *connection,
++                DBusMessage    *message,
++                void           *user_data)
++{
++        GdmLocalDisplayFactory *factory = user_data;
++        DBusError error;
++
++        dbus_error_init (&error);
++
++        if (dbus_message_is_signal (message, "org.freedesktop.login1.Manager", "SeatNew") ||
++            dbus_message_is_signal (message, "org.freedesktop.login1.Manager", "SeatRemoved")) {
++                const char *seat;
++
++                dbus_message_get_args (message,
++                                       &error,
++                                       DBUS_TYPE_STRING, &seat,
++                                       DBUS_TYPE_INVALID);
++
++                if (dbus_error_is_set (&error)) {
++                        g_warning ("GdmLocalDisplayFactory: Failed to decode seat message: %s", error.message);
++                        dbus_error_free (&error);
++                } else {
++
++                        if (strcmp (dbus_message_get_member (message), "SeatNew") == 0) {
++                                create_display (factory, seat);
++                        } else {
++                                delete_display (factory, seat);
++                        }
++                }
++        }
++
++        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
++}
++
++static void
++gdm_local_display_factory_start_monitor (GdmLocalDisplayFactory *factory)
++{
++        DBusError error;
++
++        dbus_error_init (&error);
++
++        dbus_bus_add_match (dbus_g_connection_get_connection (factory->priv->connection),
++                            "type='signal',"
++                            "sender='org.freedesktop.login1',"
++                            "path='/org/freedesktop/login1',"
++                            "interface='org.freedesktop.login1.Manager',"
++                            "member='SeatNew'",
++                            &error);
++
++        if (dbus_error_is_set (&error)) {
++                g_warning ("GdmLocalDisplayFactory: Failed to add match for SeatNew: %s", error.message);
++                dbus_error_free (&error);
++        }
++
++        dbus_bus_add_match (dbus_g_connection_get_connection (factory->priv->connection),
++                            "type='signal',"
++                            "sender='org.freedesktop.login1',"
++                            "path='/org/freedesktop/login1',"
++                            "interface='org.freedesktop.login1.Manager',"
++                            "member='SeatRemoved'",
++                            &error);
++
++        if (dbus_error_is_set (&error)) {
++                g_warning ("GdmLocalDisplayFactory: Failed to add match for SeatNew: %s", error.message);
++                dbus_error_free (&error);
++        }
++
++        dbus_connection_add_filter (dbus_g_connection_get_connection (factory->priv->connection), on_seat_signal, factory, NULL);
++}
++
++static void
++gdm_local_display_factory_stop_monitor (GdmLocalDisplayFactory *factory)
++{
++        dbus_connection_remove_filter (dbus_g_connection_get_connection (factory->priv->connection), on_seat_signal, factory);
++}
++
++#endif
++
+ static gboolean
+ gdm_local_display_factory_start (GdmDisplayFactory *base_factory)
+ {
+-        gboolean                ret;
+         GdmLocalDisplayFactory *factory = GDM_LOCAL_DISPLAY_FACTORY (base_factory);
+         GdmDisplay             *display;
+ 
+         g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE);
+ 
+-        ret = TRUE;
+-
+-        /* FIXME: use seat configuration */
+-        display = create_display (factory);
+-        if (display == NULL) {
+-                ret = FALSE;
++#ifdef WITH_SYSTEMD
++        if (sd_booted () > 0) {
++                gdm_local_display_factory_start_monitor (factory);
++                return gdm_local_display_factory_sync_seats (factory);
+         }
++#endif
+ 
+-        return ret;
++        /* On ConsoleKit just create Seat1, and that's it. */
++        display = create_display (factory, CK_SEAT1_PATH);
++
++        return display != NULL;
+ }
+ 
+ static gboolean
+@@ -389,6 +588,10 @@ gdm_local_display_factory_stop (GdmDisplayFactory *base_factory)
+ 
+         g_return_val_if_fail (GDM_IS_LOCAL_DISPLAY_FACTORY (factory), FALSE);
+ 
++#ifdef WITH_SYSTEMD
++        gdm_local_display_factory_stop_monitor (factory);
++#endif
++
+         return TRUE;
+ }
+ 
+@@ -499,6 +702,10 @@ gdm_local_display_factory_finalize (GObject *object)
+ 
+         g_hash_table_destroy (factory->priv->displays);
+ 
++#ifdef WITH_SYSTEMD
++        gdm_local_display_factory_stop_monitor (factory);
++#endif
++
+         G_OBJECT_CLASS (gdm_local_display_factory_parent_class)->finalize (object);
+ }
+ 
+-- 
+1.7.9
+
+
+From 51a27a199e36fcb5e90e8332c1f025e8a282fbd5 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart at poettering.net>
+Date: Wed, 27 Jul 2011 04:06:10 +0200
+Subject: [PATCH 09/11] server: pass seat id to server
+
+When we spawn a new X server, let's pass the seat id to it via the
+"-seat" parameter, which has been available since a while in upstream
+Xorg.
+
+-seat causes the X server to only make use of hardware that is assigned
+to the seat specified, and leave all other hardware untouched.
+---
+ daemon/gdm-factory-slave.c |    4 +++-
+ daemon/gdm-product-slave.c |    4 +++-
+ daemon/gdm-server.c        |   37 ++++++++++++++++++++++++++++++++++++-
+ daemon/gdm-server.h        |    1 +
+ daemon/gdm-simple-slave.c  |    4 +++-
+ 5 files changed, 46 insertions(+), 4 deletions(-)
+
+diff --git a/daemon/gdm-factory-slave.c b/daemon/gdm-factory-slave.c
+index 6154cd3..3538627 100644
+--- a/daemon/gdm-factory-slave.c
++++ b/daemon/gdm-factory-slave.c
+@@ -674,12 +674,14 @@ static gboolean
+ gdm_factory_slave_run (GdmFactorySlave *slave)
+ {
+         char    *display_name;
++        char    *seat_id;
+         char    *auth_file;
+         gboolean display_is_local;
+ 
+         g_object_get (slave,
+                       "display-is-local", &display_is_local,
+                       "display-name", &display_name,
++                      "display-seat-id", &seat_id,
+                       "display-x11-authority-file", &auth_file,
+                       NULL);
+ 
+@@ -688,7 +690,7 @@ gdm_factory_slave_run (GdmFactorySlave *slave)
+         if (display_is_local) {
+                 gboolean res;
+ 
+-                slave->priv->server = gdm_server_new (display_name, auth_file);
++                slave->priv->server = gdm_server_new (display_name, seat_id, auth_file);
+                 g_signal_connect (slave->priv->server,
+                                   "exited",
+                                   G_CALLBACK (on_server_exited),
+diff --git a/daemon/gdm-product-slave.c b/daemon/gdm-product-slave.c
+index 629c6e7..844af48 100644
+--- a/daemon/gdm-product-slave.c
++++ b/daemon/gdm-product-slave.c
+@@ -479,11 +479,13 @@ gdm_product_slave_create_server (GdmProductSlave *slave)
+ {
+         char    *display_name;
+         char    *auth_file;
++        char    *seat_id;
+         gboolean display_is_local;
+ 
+         g_object_get (slave,
+                       "display-is-local", &display_is_local,
+                       "display-name", &display_name,
++                      "display-seat-id", &seat_id,
+                       "display-x11-authority-file", &auth_file,
+                       NULL);
+ 
+@@ -492,7 +494,7 @@ gdm_product_slave_create_server (GdmProductSlave *slave)
+         if (display_is_local) {
+                 gboolean res;
+ 
+-                slave->priv->server = gdm_server_new (display_name, auth_file);
++                slave->priv->server = gdm_server_new (display_name, seat_id, auth_file);
+                 g_signal_connect (slave->priv->server,
+                                   "exited",
+                                   G_CALLBACK (on_server_exited),
+diff --git a/daemon/gdm-server.c b/daemon/gdm-server.c
+index 62ffca1..9a11ba0 100644
+--- a/daemon/gdm-server.c
++++ b/daemon/gdm-server.c
+@@ -38,6 +38,10 @@
+ #include <sys/prctl.h>
+ #endif
+ 
++#ifdef WITH_SYSTEMD
++#include <systemd/sd-daemon.h>
++#endif
++
+ #include <glib.h>
+ #include <glib/gi18n.h>
+ #include <glib/gstdio.h>
+@@ -77,6 +81,7 @@ struct GdmServerPrivate
+         char    *log_dir;
+         char    *display_name;
+         char    *display_device;
++        char    *display_seat_id;
+         char    *auth_file;
+ 
+         gboolean is_parented;
+@@ -90,6 +95,7 @@ struct GdmServerPrivate
+ enum {
+         PROP_0,
+         PROP_DISPLAY_NAME,
++        PROP_DISPLAY_SEAT_ID,
+         PROP_DISPLAY_DEVICE,
+         PROP_AUTH_FILE,
+         PROP_IS_PARENTED,
+@@ -284,7 +290,7 @@ gdm_server_resolve_command_line (GdmServer  *server,
+                         query_in_arglist = TRUE;
+         }
+ 
+-        argv = g_renew (char *, argv, len + 10);
++        argv = g_renew (char *, argv, len + 12);
+         /* shift args down one */
+         for (i = len - 1; i >= 1; i--) {
+                 argv[i+1] = argv[i];
+@@ -299,6 +305,11 @@ gdm_server_resolve_command_line (GdmServer  *server,
+                 argv[len++] = g_strdup (server->priv->auth_file);
+         }
+ 
++        if (sd_booted () > 0 && server->priv->display_seat_id != NULL) {
++                argv[len++] = g_strdup ("-seat");
++                argv[len++] = g_strdup (server->priv->display_seat_id);
++        }
++
+         if (server->priv->chosen_hostname) {
+                 /* run just one session */
+                 argv[len++] = g_strdup ("-terminate");
+@@ -753,6 +764,14 @@ _gdm_server_set_display_name (GdmServer  *server,
+ }
+ 
+ static void
++_gdm_server_set_display_seat_id (GdmServer  *server,
++                                 const char *name)
++{
++        g_free (server->priv->display_seat_id);
++        server->priv->display_seat_id = g_strdup (name);
++}
++
++static void
+ _gdm_server_set_auth_file (GdmServer  *server,
+                            const char *auth_file)
+ {
+@@ -789,6 +808,9 @@ gdm_server_set_property (GObject      *object,
+         case PROP_DISPLAY_NAME:
+                 _gdm_server_set_display_name (self, g_value_get_string (value));
+                 break;
++        case PROP_DISPLAY_SEAT_ID:
++                _gdm_server_set_display_seat_id (self, g_value_get_string (value));
++                break;
+         case PROP_AUTH_FILE:
+                 _gdm_server_set_auth_file (self, g_value_get_string (value));
+                 break;
+@@ -818,6 +840,9 @@ gdm_server_get_property (GObject    *object,
+         case PROP_DISPLAY_NAME:
+                 g_value_set_string (value, self->priv->display_name);
+                 break;
++        case PROP_DISPLAY_SEAT_ID:
++                g_value_set_string (value, self->priv->display_seat_id);
++                break;
+         case PROP_DISPLAY_DEVICE:
+                 g_value_take_string (value,
+                                      gdm_server_get_display_device (self));
+@@ -889,6 +914,13 @@ gdm_server_class_init (GdmServerClass *klass)
+                                                               NULL,
+                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+         g_object_class_install_property (object_class,
++                                         PROP_DISPLAY_SEAT_ID,
++                                         g_param_spec_string ("display-seat-id",
++                                                              "Seat ID",
++                                                              "ID of the seat this display is running on",
++                                                              NULL,
++                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
++        g_object_class_install_property (object_class,
+                                          PROP_DISPLAY_DEVICE,
+                                          g_param_spec_string ("display-device",
+                                                               "Display Device",
+@@ -954,6 +986,7 @@ gdm_server_finalize (GObject *object)
+         g_free (server->priv->session_args);
+         g_free (server->priv->log_dir);
+         g_free (server->priv->display_name);
++        g_free (server->priv->display_seat_id);
+         g_free (server->priv->display_device);
+         g_free (server->priv->auth_file);
+         g_free (server->priv->parent_display_name);
+@@ -965,12 +998,14 @@ gdm_server_finalize (GObject *object)
+ 
+ GdmServer *
+ gdm_server_new (const char *display_name,
++                const char *seat_id,
+                 const char *auth_file)
+ {
+         GObject *object;
+ 
+         object = g_object_new (GDM_TYPE_SERVER,
+                                "display-name", display_name,
++                               "display-seat-id", seat_id,
+                                "auth-file", auth_file,
+                                NULL);
+ 
+diff --git a/daemon/gdm-server.h b/daemon/gdm-server.h
+index 535a69a..b53d68e 100644
+--- a/daemon/gdm-server.h
++++ b/daemon/gdm-server.h
+@@ -54,6 +54,7 @@ typedef struct
+ 
+ GType               gdm_server_get_type  (void);
+ GdmServer *         gdm_server_new       (const char *display_id,
++                                          const char *seat_id,
+                                           const char *auth_file);
+ gboolean            gdm_server_start     (GdmServer   *server);
+ gboolean            gdm_server_stop      (GdmServer   *server);
+diff --git a/daemon/gdm-simple-slave.c b/daemon/gdm-simple-slave.c
+index 873b7f9..9d1347a 100644
+--- a/daemon/gdm-simple-slave.c
++++ b/daemon/gdm-simple-slave.c
+@@ -1437,11 +1437,13 @@ gdm_simple_slave_run (GdmSimpleSlave *slave)
+ {
+         char    *display_name;
+         char    *auth_file;
++        char    *seat_id;
+         gboolean display_is_local;
+ 
+         g_object_get (slave,
+                       "display-is-local", &display_is_local,
+                       "display-name", &display_name,
++                      "display-seat-id", &seat_id,
+                       "display-x11-authority-file", &auth_file,
+                       NULL);
+ 
+@@ -1451,7 +1453,7 @@ gdm_simple_slave_run (GdmSimpleSlave *slave)
+                 gboolean res;
+                 gboolean disable_tcp;
+ 
+-                slave->priv->server = gdm_server_new (display_name, auth_file);
++                slave->priv->server = gdm_server_new (display_name, seat_id, auth_file);
+ 
+                 disable_tcp = TRUE;
+                 if (gdm_settings_client_get_boolean (GDM_KEY_DISALLOW_TCP,
+-- 
+1.7.9
+
+
+From 2b24451c3816ecea30fdbfff2c249a6ac527e1b6 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart at poettering.net>
+Date: Tue, 24 Jan 2012 00:03:10 +0100
+Subject: [PATCH 10/11] server: invoke X with the systemd multi seat X wrapper
+ if necessary
+
+systemd 39 and newer provide a small wrapper for X which works around
+the fact that XOrg upstream currently support multi-seat hotplug for
+displays. Let's make use of this as a stop-gap until this feature is
+added to XOrg upstream.
+
+This code tries to be as defensive as possible and makes use of the
+wrapper only if the system as actually booted with systemd, the wrapper
+is available and we actually use a seat != "seat0".
+---
+ configure.ac        |    6 +++++-
+ daemon/gdm-server.c |   50 +++++++++++++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 54 insertions(+), 2 deletions(-)
+
+diff --git a/configure.ac b/configure.ac
+index dec31a9..855948d 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -939,7 +939,7 @@ use_systemd=no
+ if test "x$with_systemd" != "xno" ; then
+         PKG_CHECK_MODULES(SYSTEMD,
+                 libsystemd-daemon
+-                libsystemd-login
++                libsystemd-login >= 39
+         )
+         AC_SUBST(SYSTEMD_CFLAGS)
+         AC_SUBST(SYSTEMD_LIBS)
+@@ -950,6 +950,10 @@ fi
+ AM_CONDITIONAL(WITH_SYSTEMD, test x$use_systemd = xyes)
+ AC_SUBST(WITH_SYSTEMD)
+ 
++AC_PATH_PROG(SYSTEMD_X_SERVER, systemd-multi-seat-x, [/lib/systemd/systemd-multi-seat-x], [/lib/systemd:/usr/lib/systemd:$PATH])
++AC_SUBST(SYSTEMD_X_SERVER)
++AC_DEFINE_UNQUOTED(SYSTEMD_X_SERVER,"$SYSTEMD_X_SERVER",[Path to systemd X server wrapper])
++
+ dnl ---------------------------------------------------------------------------
+ dnl - Check for D-Bus
+ dnl ---------------------------------------------------------------------------
+diff --git a/daemon/gdm-server.c b/daemon/gdm-server.c
+index 9a11ba0..54bf8b3 100644
+--- a/daemon/gdm-server.c
++++ b/daemon/gdm-server.c
+@@ -260,6 +260,52 @@ connect_to_parent (GdmServer *server)
+ }
+ #endif
+ 
++static void
++gdm_server_init_command (GdmServer *server)
++{
++
++        if (server->priv->command != NULL) {
++                return;
++        }
++
++#ifdef WITH_SYSTEMD
++
++        /* This is a temporary hack to work around the fact that XOrg
++         * currently lacks support for multi-seat hotplugging for
++         * display devices. This bit should be removed as soon as XOrg
++         * gains native support for automatically enumerating usb
++         * based graphics adapters at start-up via udev. */
++
++        /* systemd ships an X server wrapper tool which simply invokes
++         * the usual X but ensures it only uses the display devices of
++         * the seat. */
++
++        /* We do not rely on this wrapper server if, a) the machine
++         * wasn't booted using systemd, or b) the wrapper tool is
++         * missing, or c) we are running for the main seat 'seat0'. */
++
++        if (sd_booted () <= 0) {
++                goto fallback;
++        }
++
++        if (g_access (SYSTEMD_X_SERVER, X_OK) < 0) {
++                goto fallback;
++        }
++
++        if (server->priv->display_seat_id == NULL ||
++            strcmp (server->priv->display_seat_id, "seat0") == 0) {
++                goto fallback;
++        }
++
++        server->priv->command = g_strdup (SYSTEMD_X_SERVER " -br -verbose -logverbose 7");
++        return;
++
++fallback:
++#endif
++
++        server->priv->command = g_strdup (X_SERVER " -br -verbose -logverbose 7");
++}
++
+ static gboolean
+ gdm_server_resolve_command_line (GdmServer  *server,
+                                  const char *vtarg,
+@@ -273,6 +319,8 @@ gdm_server_resolve_command_line (GdmServer  *server,
+         gboolean gotvtarg = FALSE;
+         gboolean query_in_arglist = FALSE;
+ 
++        gdm_server_init_command (server);
++
+         g_shell_parse_argv (server->priv->command, &argc, &argv, NULL);
+ 
+         for (len = 0; argv != NULL && argv[len] != NULL; len++) {
+@@ -959,7 +1007,7 @@ gdm_server_init (GdmServer *server)
+         server->priv = GDM_SERVER_GET_PRIVATE (server);
+ 
+         server->priv->pid = -1;
+-        server->priv->command = g_strdup (X_SERVER " -br -verbose -logverbose 7");
++
+         server->priv->log_dir = g_strdup (LOGDIR);
+ 
+         add_ready_handler (server);
+-- 
+1.7.9
+
+
+From 28c7f9e6d875076bfe0c79cdee98fc6aefc29874 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering <lennart at poettering.net>
+Date: Tue, 7 Feb 2012 22:48:40 +0100
+Subject: [PATCH 11/11] gdmflexiserver: port gdmflexiserver to
+ libsystemd-logind
+
+Port over gdmflexiserver to use native systemd calls with a fallback on
+CK.
+---
+ utils/Makefile.am      |    3 +-
+ utils/gdmflexiserver.c |  256 ++++++++++++++++++++++++++++++++++++++++++++----
+ 2 files changed, 239 insertions(+), 20 deletions(-)
+
+diff --git a/utils/Makefile.am b/utils/Makefile.am
+index 379c3d5..1cda413 100644
+--- a/utils/Makefile.am
++++ b/utils/Makefile.am
+@@ -10,6 +10,7 @@ AM_CPPFLAGS = \
+ 	$(CANBERRA_GTK_CFLAGS)				\
+ 	$(GTK_CFLAGS)					\
+ 	$(XLIB_CFLAGS)					\
++	$(SYSTEMD_CFLAGS)				\
+ 	$(COMMON_CFLAGS)				\
+ 	$(NULL)
+ 
+@@ -31,6 +32,7 @@ gdmflexiserver_SOURCES =	\
+ gdmflexiserver_LDADD =		\
+ 	$(GTK_LIBS)		\
+ 	$(COMMON_LIBS)		\
++	$(SYSTEMD_LIBS)         \
+ 	$(NULL)
+ 
+ gdm_screenshot_SOURCES =	\
+@@ -49,4 +51,3 @@ CLEANFILES = 			\
+ 
+ DISTCLEANFILES = 		\
+ 	$(NULL)
+-
+diff --git a/utils/gdmflexiserver.c b/utils/gdmflexiserver.c
+index f7fac33..59bccd1 100644
+--- a/utils/gdmflexiserver.c
++++ b/utils/gdmflexiserver.c
+@@ -29,6 +29,11 @@
+ #include <glib/gi18n.h>
+ #include <gtk/gtk.h>
+ 
++#ifdef WITH_SYSTEMD
++#include <systemd/sd-daemon.h>
++#include <systemd/sd-login.h>
++#endif
++
+ #define DBUS_API_SUBJECT_TO_CHANGE
+ #include <dbus/dbus-glib.h>
+ #include <dbus/dbus-glib-lowlevel.h>
+@@ -37,6 +42,7 @@
+ #define GDM_DBUS_LOCAL_DISPLAY_FACTORY_PATH      "/org/gnome/DisplayManager/LocalDisplayFactory"
+ #define GDM_DBUS_LOCAL_DISPLAY_FACTORY_INTERFACE "org.gnome.DisplayManager.LocalDisplayFactory"
+ 
++#ifdef WITH_CONSOLE_KIT
+ #define CK_NAME      "org.freedesktop.ConsoleKit"
+ #define CK_PATH      "/org/freedesktop/ConsoleKit"
+ #define CK_INTERFACE "org.freedesktop.ConsoleKit"
+@@ -45,6 +51,7 @@
+ #define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager"
+ #define CK_SEAT_INTERFACE    "org.freedesktop.ConsoleKit.Seat"
+ #define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session"
++#endif
+ 
+ static const char *send_command     = NULL;
+ static gboolean    use_xnest        = FALSE;
+@@ -206,6 +213,8 @@ create_transient_display (DBusConnection *connection,
+         return ret;
+ }
+ 
++#ifdef WITH_CONSOLE_KIT
++
+ static gboolean
+ get_current_session_id (DBusConnection *connection,
+                         char          **session_id)
+@@ -335,9 +344,9 @@ get_current_seat_id (DBusConnection *connection)
+ }
+ 
+ static gboolean
+-activate_session_id (DBusConnection *connection,
+-                     const char     *seat_id,
+-                     const char     *session_id)
++activate_session_id_for_ck (DBusConnection *connection,
++                            const char     *seat_id,
++                            const char     *session_id)
+ {
+         DBusError    local_error;
+         DBusMessage *message;
+@@ -609,9 +618,9 @@ seat_get_sessions (DBusConnection *connection,
+ }
+ 
+ static gboolean
+-get_login_window_session_id (DBusConnection  *connection,
+-                             const char      *seat_id,
+-                             char           **session_id)
++get_login_window_session_id_for_ck (DBusConnection  *connection,
++                                    const char      *seat_id,
++                                    char           **session_id)
+ {
+         gboolean    can_activate_sessions;
+         char      **sessions;
+@@ -645,46 +654,225 @@ get_login_window_session_id (DBusConnection  *connection,
+ }
+ 
+ static gboolean
+-goto_login_session (GError **error)
++goto_login_session_for_ck (DBusConnection  *connection,
++                           GError         **error)
+ {
+         gboolean        ret;
+         gboolean        res;
+         char           *session_id;
+         char           *seat_id;
+-        DBusError       local_error;
+-        DBusConnection *connection;
+ 
+         ret = FALSE;
+ 
++        /* First look for any existing LoginWindow sessions on the seat.
++           If none are found, create a new one. */
++
++        seat_id = get_current_seat_id (connection);
++        if (seat_id == NULL || seat_id[0] == '\0') {
++                g_debug ("seat id is not set; can't switch sessions");
++                g_set_error (error, GDM_FLEXISERVER_ERROR, 0, _("Could not identify the current session."));
++
++                return FALSE;
++        }
++
++        res = get_login_window_session_id_for_ck (connection, seat_id, &session_id);
++        if (! res) {
++                g_set_error (error, GDM_FLEXISERVER_ERROR, 1, _("User unable to switch sessions."));
++                return FALSE;
++        }
++
++        if (session_id != NULL) {
++                res = activate_session_id_for_ck (connection, seat_id, session_id);
++                if (res) {
++                        ret = TRUE;
++                }
++        }
++
++        if (! ret) {
++                res = create_transient_display (connection, error);
++                if (res) {
++                        ret = TRUE;
++                }
++        }
++
++        return ret;
++}
++#endif
++
++#ifdef WITH_SYSTEMD
++
++static gboolean
++activate_session_id_for_systemd (DBusConnection *connection,
++                                 const char     *seat_id,
++                                 const char     *session_id)
++{
++        DBusError    local_error;
++        DBusMessage *message;
++        DBusMessage *reply;
++        gboolean     ret;
++
++        ret = FALSE;
++        reply = NULL;
++
++        g_debug ("Switching to session %s", session_id);
++
++        message = dbus_message_new_method_call ("org.freedesktop.login1",
++                                                "/org/freedesktop/login1",
++                                                "org.freedesktop.login1.Manager",
++                                                "ActivateSessionOnSeat");
++        if (message == NULL) {
++                goto out;
++        }
++
++        if (! dbus_message_append_args (message,
++                                        DBUS_TYPE_STRING, &session_id,
++                                        DBUS_TYPE_STRING, &seat_id,
++                                        DBUS_TYPE_INVALID)) {
++                goto out;
++        }
++
+         dbus_error_init (&local_error);
+-        connection = dbus_bus_get (DBUS_BUS_SYSTEM, &local_error);
+-        if (connection == NULL) {
+-                g_debug ("Failed to connect to the D-Bus daemon: %s", local_error.message);
+-                g_set_error (error, GDM_FLEXISERVER_ERROR, 0, "%s", local_error.message);
++        reply = dbus_connection_send_with_reply_and_block (connection,
++                                                           message,
++                                                           -1,
++                                                           &local_error);
++        if (dbus_error_is_set (&local_error)) {
++                g_warning ("Unable to activate session: %s", local_error.message);
+                 dbus_error_free (&local_error);
++                goto out;
++        }
++
++        ret = TRUE;
++out:
++        if (message != NULL) {
++                dbus_message_unref (message);
++        }
++        if (reply != NULL) {
++                dbus_message_unref (reply);
++        }
++
++        return ret;
++}
++
++static gboolean
++get_login_window_session_id_for_systemd (const char  *seat_id,
++                                         char       **session_id)
++{
++        gboolean   ret;
++        int        res, i;
++        char     **sessions;
++        char      *service_id;
++
++        res = sd_seat_get_sessions (seat_id, &sessions, NULL, NULL);
++        if (res < 0) {
++                g_debug ("Failed to determine sessions: %s", strerror (-res));
+                 return FALSE;
+         }
+ 
++        if (sessions == NULL || sessions[0] == NULL) {
++                *session_id = NULL;
++                ret = TRUE;
++                goto out;
++        }
++
++        for (i = 0; sessions[i]; i ++) {
++
++                res = sd_session_get_service (sessions[i], &service_id);
++                if (res < 0) {
++                        g_debug ("failed to determine service of session %s: %s", sessions[i], strerror (-res));
++                        ret = FALSE;
++                        goto out;
++                }
++
++                if (strcmp (service_id, "gdm-welcome") == 0) {
++                        *session_id = g_strdup (sessions[i]);
++                        ret = TRUE;
++
++                        free (service_id);
++                        goto out;
++                }
++
++                free (service_id);
++        }
++
++        *session_id = NULL;
++        ret = TRUE;
++
++out:
++        for (i = 0; sessions[i]; i ++) {
++                free (sessions[i]);
++        }
++
++        free (sessions);
++
++        return ret;
++}
++
++static gboolean
++goto_login_session_for_systemd (DBusConnection  *connection,
++                                GError         **error)
++{
++        gboolean        ret;
++        int             res;
++        char           *our_session;
++        char           *session_id;
++        char           *seat_id;
++
++        ret = FALSE;
++
+         /* First look for any existing LoginWindow sessions on the seat.
+            If none are found, create a new one. */
+ 
+-        seat_id = get_current_seat_id (connection);
+-        if (seat_id == NULL || seat_id[0] == '\0') {
+-                g_debug ("seat id is not set; can't switch sessions");
++        /* Note that we mostly use free () here, instead of g_free ()
++         * since the data allocated is from libsystemd-logind, which
++         * does not use GLib's g_malloc (). */
++
++        res = sd_pid_get_session (0, &our_session);
++        if (res < 0) {
++                g_debug ("failed to determine own session: %s", strerror (-res));
+                 g_set_error (error, GDM_FLEXISERVER_ERROR, 0, _("Could not identify the current session."));
+ 
+                 return FALSE;
+         }
+ 
+-        res = get_login_window_session_id (connection, seat_id, &session_id);
++        res = sd_session_get_seat (our_session, &seat_id);
++        free (our_session);
++        if (res < 0) {
++                g_debug ("failed to determine own seat: %s", strerror (-res));
++                g_set_error (error, GDM_FLEXISERVER_ERROR, 0, _("Could not identify the current seat."));
++
++                return FALSE;
++        }
++
++        res = sd_seat_can_multi_session (seat_id);
++        if (res < 0) {
++                free (seat_id);
++
++                g_debug ("failed to determine whether seat can do multi session: %s", strerror (-res));
++                g_set_error (error, GDM_FLEXISERVER_ERROR, 0, _("Could not identify multi session property."));
++
++                return FALSE;
++        }
++
++        if (res == 0) {
++                free (seat_id);
+ 
++                g_set_error (error, GDM_FLEXISERVER_ERROR, 0, _("Seat can't do multi session"));
++
++                return FALSE;
++        }
++
++        res = get_login_window_session_id_for_systemd (seat_id, &session_id);
+         if (! res) {
+-                g_set_error (error, GDM_FLEXISERVER_ERROR, 1, _("User unable to switch sessions."));
++                free (seat_id);
++
++                g_set_error (error, GDM_FLEXISERVER_ERROR, 1, _("User unable to determine login session."));
+                 return FALSE;
+         }
+ 
+         if (session_id != NULL) {
+-                res = activate_session_id (connection, seat_id, session_id);
++                res = activate_session_id_for_systemd (connection, seat_id, session_id);
++
+                 if (res) {
+                         ret = TRUE;
+                 }
+@@ -697,8 +885,38 @@ goto_login_session (GError **error)
+                 }
+         }
+ 
++        free (seat_id);
++        g_free (session_id);
++
+         return ret;
+ }
++#endif
++
++static gboolean
++goto_login_session (GError **error)
++{
++        DBusError       local_error;
++        DBusConnection *connection;
++
++        dbus_error_init (&local_error);
++        connection = dbus_bus_get (DBUS_BUS_SYSTEM, &local_error);
++        if (connection == NULL) {
++                g_debug ("Failed to connect to the D-Bus daemon: %s", local_error.message);
++                g_set_error (error, GDM_FLEXISERVER_ERROR, 0, "%s", local_error.message);
++                dbus_error_free (&local_error);
++                return FALSE;
++        }
++
++#ifdef WITH_SYSTEMD
++        if (sd_booted () > 0) {
++                return goto_login_session_for_systemd (connection, error);
++        }
++#endif
++
++#ifdef WITH_CONSOLE_KIT
++        return goto_login_session_for_ck (connection, error);
++#endif
++}
+ 
+ int
+ main (int argc, char *argv[])
+-- 
+1.7.9
+


More information about the scm-commits mailing list