diff -pruN 43.0-1/debian/changelog 43.0-1ubuntu2/debian/changelog
--- 43.0-1/debian/changelog	2022-10-11 18:08:35.000000000 +0000
+++ 43.0-1ubuntu2/debian/changelog	2022-10-13 11:13:51.000000000 +0000
@@ -1,3 +1,60 @@
+gnome-session (43.0-1ubuntu2) kinetic; urgency=medium
+
+  * debian/gnome-session-bin.install: Don't install gnome-session-custom-session
+    (LP: #1992775)
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Thu, 13 Oct 2022 07:13:51 -0400
+
+gnome-session (43.0-1ubuntu1) kinetic; urgency=medium
+
+  * Merge with Debian. Remaining changes:
+    - debian/control.in:
+      + Recommend session-migration
+      + Move xwayland dependency to gnome-session and make gnome-session
+        Arch: any
+      + Split gnome-startup-applications to a separate binary package so
+        that it can be uninstalled without breaking the system
+      + Add unity-session
+    - debian/rules: Ensure pot file is generated to translate session files
+    - Split ubuntu-session out of gnome-session.
+    - debian/data: Add old-style systemd user session used by Unity
+    - debian/gnome-session-bin.postinst, debian/gnome-session-bin.prerm:
+       Moved registering gnome-session binary as a session manager to
+       gnome-session-bin package
+    - don't install gnome-mimeapps.list (installed by desktop-file-utils in
+      Ubuntu):
+      debian/gnome-session-common.dirs, gnome-session-common.install,
+      gnome-session-common.maintscript, gnome-session-common.postinst
+    - debian/patches/ubuntu/support_autostart_delay.patch:
+      + Bugzilla patch to support adding a delay to autostart apps, using
+        a "X-GNOME-Autostart-Delay" key in the desktop file
+    - debian/patches/ubuntu/ubuntu_sessions.patch:
+      + Add ubuntu sessions
+    - debian/patches/ubuntu/remove_session_saving_from_gui.patch:
+      + Add GNOME_SESSION_SAVE environment variable for people wanting to
+        use the save session still, knowing that it can break your system
+        if used unwisely
+    - debian/patches/ubuntu/add_sessionmigration.patch:
+      + launch session-migration if present at the start of the session.
+        This sync tool runns different session migration scripts that can be
+        provided in various desktop packages.
+    - debian/patches/ubuntu/dbus_request_shutdown.patch:
+      + Add "RequestShutdown" and "RequestReboot" DBus methods to allow
+        other applications to shutdown or reboot the machine via the session
+        manager.
+    - debian/patches/ubuntu/ignore_gsettings_region.patch:
+      + Ignore the "region" gsettings value - users' setting of LC_*
+        variables saved in ~/.pam_environment.
+    - debian/patches/revert_remove_gnome_session_properties.patch:
+      + Don't merge translations into gnome-session-properties.desktop
+    - debian/ubuntu-settings-migrate-to-defaults.18.10.1.py:
+      + Migrate users using old default ubuntu-settings to current ones
+    - debian/xdg_dirs_desktop_session.sh: Install a new script into
+      /etc/profile.d to prepend a $DESKTOP_SESSION related directory to
+      $XDG_{CONFIG,DATA}_DIRS.
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Tue, 11 Oct 2022 14:32:03 -0400
+
 gnome-session (43.0-1) unstable; urgency=medium
 
   [ Nathan Pratta Teodosio ]
@@ -10,12 +67,136 @@ gnome-session (43.0-1) unstable; urgency
 
  -- Jeremy Bicha <jbicha@ubuntu.com>  Tue, 11 Oct 2022 14:08:35 -0400
 
+gnome-session (42.0-1ubuntu3) kinetic; urgency=medium
+
+  * debian/gnome-session-common.install: Don't install gnome-mimeapps.list
+    (installed by desktop-file-utils in Ubuntu) (LP: #1970248)
+  * Have gnome-session and ubuntu-session depend on
+    xdg-desktop-portal-gnome | xdg-desktop-portal-backend (LP: #1970424)
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Sun, 01 May 2022 11:35:12 -0400
+
+gnome-session (42.0-1ubuntu2) jammy; urgency=medium
+
+  * No change rebuild to trigger a new translation import from launchpad,
+    the gettext domain changed this cycle but was set wrongly on the server
+    so we currently have no translation in the language packs.
+
+ -- Sebastien Bacher <seb128@ubuntu.com>  Thu, 07 Apr 2022 21:07:53 +0200
+
+gnome-session (42.0-1ubuntu1) jammy; urgency=medium
+
+  * Merge with Debian. Remaining changes:
+    - debian/control.in:
+      + Recommend session-migration
+      + Move xwayland dependency to gnome-session and make gnome-session
+        Arch: any
+      + Split gnome-startup-applications to a separate binary package so
+        that it can be uninstalled without breaking the system
+      + Add unity-session
+    - debian/rules: Ensure pot file is generated to translate session files
+    - Split ubuntu-session out of gnome-session.
+    - debian/data: Add old-style systemd user session used by Unity
+    - debian/gnome-session-bin.postinst, debian/gnome-session-bin.prerm:
+       Moved registering gnome-session binary as a session manager to
+       gnome-session-bin package
+    - don't install gnome-mimeapps.list (installed by desktop-file-utils in
+      Ubuntu):
+      debian/gnome-session-common.dirs, gnome-session-common.install,
+      gnome-session-common.maintscript, gnome-session-common.postinst
+    - debian/patches/ubuntu/support_autostart_delay.patch:
+      + Bugzilla patch to support adding a delay to autostart apps, using
+        a "X-GNOME-Autostart-Delay" key in the desktop file
+    - debian/patches/ubuntu/ubuntu_sessions.patch:
+      + Add ubuntu sessions
+    - debian/patches/ubuntu/remove_session_saving_from_gui.patch:
+      + Add GNOME_SESSION_SAVE environment variable for people wanting to
+        use the save session still, knowing that it can break your system
+        if used unwisely
+    - debian/patches/ubuntu/add_sessionmigration.patch:
+      + launch session-migration if present at the start of the session.
+        This sync tool runns different session migration scripts that can be
+        provided in various desktop packages.
+    - debian/patches/ubuntu/dbus_request_shutdown.patch:
+      + Add "RequestShutdown" and "RequestReboot" DBus methods to allow
+        other applications to shutdown or reboot the machine via the session
+        manager.
+    - debian/patches/ubuntu/ignore_gsettings_region.patch:
+      + Ignore the "region" gsettings value - users' setting of LC_*
+        variables saved in ~/.pam_environment.
+    - debian/patches/revert_remove_gnome_session_properties.patch:
+      + Don't merge translations into gnome-session-properties.desktop
+    - debian/ubuntu-settings-migrate-to-defaults.18.10.1.py:
+      + Migrate users using old default ubuntu-settings to current ones
+    - debian/xdg_dirs_desktop_session.sh: Install a new script into
+      /etc/profile.d to prepend a $DESKTOP_SESSION related directory to
+      $XDG_{CONFIG,DATA}_DIRS.
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Tue, 22 Mar 2022 08:45:09 -0400
+
 gnome-session (42.0-1) unstable; urgency=medium
 
   * New upstream release
 
  -- Jeremy Bicha <jbicha@ubuntu.com>  Tue, 22 Mar 2022 08:40:00 -0400
 
+gnome-session (41.3-1ubuntu1) jammy; urgency=medium
+
+  * Merge with debian:
+    - Ensure that systemd is preferred on startup (LP: #1959596)
+  * debian/rules: Automatically compute the pot name using $DEB_UPSTREAM_VERSION
+  * debian/rules: Keep gnome-session domain in sync with major version
+  * debian/patches: Remove applied upstream
+  * debian/patches: Refresh patches as per upstream changes
+  * debian: Remove communitheme-snap session
+  * Remaining changes with debian:
+    - debian/control.in:
+      + Recommend session-migration
+      + Move xwayland dependency to gnome-session and make gnome-session
+        Arch: any
+      + Split gnome-startup-applications to a separate binary package so
+        that it can be uninstalled without breaking the system
+      + Add unity-session
+    - debian/rules: Ensure pot file is generated to translate session files
+    - Split ubuntu-session out of gnome-session.
+    - debian/data: Add old-style systemd user session used by Unity
+    - debian/gnome-session-bin.postinst, debian/gnome-session-bin.prerm:
+       Moved registering gnome-session binary as a session manager to
+       gnome-session-bin package
+    - don't install gnome-mimeapps.list (installed by desktop-file-utils in
+      Ubuntu):
+      debian/gnome-session-common.dirs, gnome-session-common.install,
+      gnome-session-common.maintscript, gnome-session-common.postinst
+    - debian/patches/ubuntu/support_autostart_delay.patch:
+      + Bugzilla patch to support adding a delay to autostart apps, using
+        a "X-GNOME-Autostart-Delay" key in the desktop file
+    - debian/patches/ubuntu/ubuntu_sessions.patch:
+      + Add ubuntu sessions
+    - debian/patches/ubuntu/remove_session_saving_from_gui.patch:
+      + Add GNOME_SESSION_SAVE environment variable for people wanting to
+        use the save session still, knowing that it can break your system
+        if used unwisely
+    - debian/patches/ubuntu/add_sessionmigration.patch:
+      + launch session-migration if present at the start of the session.
+        This sync tool runns different session migration scripts that can be
+        provided in various desktop packages.
+    - debian/patches/ubuntu/dbus_request_shutdown.patch:
+      + Add "RequestShutdown" and "RequestReboot" DBus methods to allow
+        other applications to shutdown or reboot the machine via the session
+        manager.
+    - debian/patches/ubuntu/ignore_gsettings_region.patch:
+      + Ignore the "region" gsettings value - users' setting of LC_*
+        variables saved in ~/.pam_environment.
+    - debian/patches/revert_remove_gnome_session_properties.patch:
+      + Don't merge translations into gnome-session-properties.desktop
+    - debian/ubuntu-settings-migrate-to-defaults.18.10.1.py:
+      + Migrate users using old default ubuntu-settings to current ones
+    - debian/xdg_dirs_desktop_session.sh: Install a new script into
+      /etc/profile.d to prepend a $DESKTOP_SESSION related directory to
+      $XDG_{CONFIG,DATA}_DIRS.
+
+ -- Marco Trevisan (Treviño) <marco@ubuntu.com>  Tue, 01 Mar 2022 13:19:24 +0100
+
 gnome-session (41.3-1) unstable; urgency=medium
 
   * Team upload
@@ -44,6 +225,56 @@ gnome-session (41.3-1) unstable; urgency
 
  -- Simon McVittie <smcv@debian.org>  Sat, 29 Jan 2022 14:42:02 +0000
 
+gnome-session (40.1.1-3ubuntu1) jammy; urgency=medium
+
+  * Merge with debian, remaining changes:
+    - debian/control.in:
+      + Recommend session-migration
+      + Move xwayland dependency to gnome-session and make gnome-session
+        Arch: any
+      + Split gnome-startup-applications to a separate binary package so
+        that it can be uninstalled without breaking the system
+      + Add unity-session
+    - debian/rules: Ensure pot file is generated to translate session files
+    - Split ubuntu-session out of gnome-session.
+    - debian/data: Add old-style systemd user session used by Unity
+    - debian/gnome-session-bin.postinst, debian/gnome-session-bin.prerm:
+       Moved registering gnome-session binary as a session manager to
+       gnome-session-bin package
+    - don't install gnome-mimeapps.list (installed by desktop-file-utils in
+      Ubuntu):
+      debian/gnome-session-common.dirs, gnome-session-common.install,
+      gnome-session-common.maintscript, gnome-session-common.postinst
+    - debian/patches/ubuntu/support_autostart_delay.patch:
+      + Bugzilla patch to support adding a delay to autostart apps, using
+        a "X-GNOME-Autostart-Delay" key in the desktop file
+    - debian/patches/ubuntu/ubuntu_sessions.patch:
+      + Add ubuntu sessions
+    - debian/patches/ubuntu/remove_session_saving_from_gui.patch:
+      + Add GNOME_SESSION_SAVE environment variable for people wanting to
+        use the save session still, knowing that it can break your system
+        if used unwisely
+    - debian/patches/ubuntu/add_sessionmigration.patch:
+      + launch session-migration if present at the start of the session.
+        This sync tool runns different session migration scripts that can be
+        provided in various desktop packages.
+    - debian/patches/ubuntu/dbus_request_shutdown.patch:
+      + Add "RequestShutdown" and "RequestReboot" DBus methods to allow
+        other applications to shutdown or reboot the machine via the session
+        manager.
+    - debian/patches/ubuntu/ignore_gsettings_region.patch:
+      + Ignore the "region" gsettings value - users' setting of LC_*
+        variables saved in ~/.pam_environment.
+    - debian/patches/revert_remove_gnome_session_properties.patch:
+      + Don't merge translations into gnome-session-properties.desktop
+    - debian/ubuntu-settings-migrate-to-defaults.18.10.1.py:
+      + Migrate users using old default ubuntu-settings to current ones
+    - debian/xdg_dirs_desktop_session.sh: Install a new script into
+      /etc/profile.d to prepend a $DESKTOP_SESSION related directory to
+      $XDG_{CONFIG,DATA}_DIRS.
+
+ -- Marco Trevisan (Treviño) <marco@ubuntu.com>  Fri, 19 Nov 2021 03:28:07 +0100
+
 gnome-session (40.1.1-3) unstable; urgency=medium
 
   * Team upload
@@ -106,6 +337,67 @@ gnome-session (40.1.1-2) unstable; urgen
 
  -- Simon McVittie <smcv@debian.org>  Sun, 10 Oct 2021 19:21:16 +0100
 
+gnome-session (40.1.1-1ubuntu1) impish; urgency=medium
+
+  * Merge with debian, containing latest stable release:
+    We already included most of the patches.
+  * debian/patches: Install again gnome-wayland so that can be used from X11 gdm
+    (LP: #1944223)
+  * d/p/ubuntu-sessions.patch: Add ubuntu-wayland session to support gdm on X11
+    (LP: #1944223, required for LP: #1942911)
+  * d/p/ubuntu-sessions.patch: Skip ubuntu-xorg.desktop.in from translations.
+    The .in.in file is already translated.
+  * gnome-session.install: Include gnome-wayland session
+  * ubuntu-session.install: Include ubuntu-wayland session
+  * debian/rules: Update pot file name to be generated
+  * Remaining changes with debian:
+    - debian/control.in:
+      + Recommend session-migration
+      + Move xwayland dependency to gnome-session and make gnome-session
+        Arch: any
+      + Split gnome-startup-applications to a separate binary package so
+        that it can be uninstalled without breaking the system
+      + Add unity-session
+    - debian/rules: Ensure pot file is generated to translate session files
+    - Split ubuntu-session out of gnome-session.
+    - debian/data: Add old-style systemd user session used by Unity
+    - debian/gnome-session-bin.postinst, debian/gnome-session-bin.prerm:
+       Moved registering gnome-session binary as a session manager to
+       gnome-session-bin package
+    - don't install gnome-mimeapps.list (installed by desktop-file-utils in
+      Ubuntu):
+      debian/gnome-session-common.dirs, gnome-session-common.install,
+      gnome-session-common.maintscript, gnome-session-common.postinst
+    - debian/patches/ubuntu/support_autostart_delay.patch:
+      + Bugzilla patch to support adding a delay to autostart apps, using
+        a "X-GNOME-Autostart-Delay" key in the desktop file
+    - debian/patches/ubuntu/ubuntu_sessions.patch:
+      + Add ubuntu sessions
+    - debian/patches/ubuntu/remove_session_saving_from_gui.patch:
+      + Add GNOME_SESSION_SAVE environment variable for people wanting to
+        use the save session still, knowing that it can break your system
+        if used unwisely
+    - debian/patches/ubuntu/add_sessionmigration.patch:
+      + launch session-migration if present at the start of the session.
+        This sync tool runns different session migration scripts that can be
+        provided in various desktop packages.
+    - debian/patches/ubuntu/dbus_request_shutdown.patch:
+      + Add "RequestShutdown" and "RequestReboot" DBus methods to allow
+        other applications to shutdown or reboot the machine via the session
+        manager.
+    - debian/patches/ubuntu/ignore_gsettings_region.patch:
+      + Ignore the "region" gsettings value - users' setting of LC_*
+        variables saved in ~/.pam_environment.
+    - debian/patches/revert_remove_gnome_session_properties.patch:
+      + Don't merge translations into gnome-session-properties.desktop
+    - debian/ubuntu-settings-migrate-to-defaults.18.10.1.py:
+      + Migrate users using old default ubuntu-settings to current ones
+    - debian/xdg_dirs_desktop_session.sh: Install a new script into
+      /etc/profile.d to prepend a $DESKTOP_SESSION related directory to
+      $XDG_{CONFIG,DATA}_DIRS.
+
+ -- Marco Trevisan (Treviño) <marco@ubuntu.com>  Mon, 20 Sep 2021 20:34:00 +0200
+
 gnome-session (40.1.1-1) unstable; urgency=medium
 
   * New upstream release
@@ -148,6 +440,73 @@ gnome-session (3.38.0-4) unstable; urgen
 
  -- Simon McVittie <smcv@debian.org>  Mon, 29 Mar 2021 14:21:00 +0100
 
+gnome-session (3.38.0-3ubuntu2) hirsute; urgency=medium
+
+  * debian/control: Remove ubuntu-desktop Breaks on g-s-d common (again)
+  * debian/changelog: add back changes for release 3.38.0-1ubuntu1
+
+ -- Marco Trevisan (Treviño) <marco@ubuntu.com>  Wed, 10 Feb 2021 20:38:37 +0100
+
+gnome-session (3.38.0-3ubuntu1) hirsute; urgency=medium
+
+  * Merge with debian
+  * ubuntu-sessions: Use Wayland by default
+  * debian/patches:
+    - Drop applied patches (and refresh others)
+    - Drop patch to select gnome-session mode
+    - Cherry-pick upstream patch fixing a crash when using fish
+  * debian/data: Drop support for Upstart
+  * d/p/ubuntu/add_sessionmigration.patch: Don't check for upstart
+  * debian/gnome-session.links: Drop it, we handle this in meson now
+  * debian/gnome-session.preinst: Remove deprecated file, served us till bionic
+  * debian/control: Remove gnome-session-wayland, deprecated since zesty
+  * Remaining changes with debian:
+    - debian/control.in:
+      + Recommend session-migration
+      + Move xwayland dependency to gnome-session and make gnome-session
+        Arch: any
+      + Split gnome-startup-applications to a separate binary package so
+        that it can be uninstalled without breaking the system
+      + Add unity-session
+    - Split ubuntu-session out of gnome-session.
+    - debian/data: Add old-style systemd user session used by Unity
+    - debian/gnome-session-bin.postinst, debian/gnome-session-bin.prerm:
+       Moved registering gnome-session binary as a session manager to
+       gnome-session-bin package
+    - don't install gnome-mimeapps.list (installed by desktop-file-utils in
+      Ubuntu):
+      debian/gnome-session-common.dirs, gnome-session-common.install,
+      gnome-session-common.maintscript, gnome-session-common.postinst
+    - debian/patches/ubuntu/support_autostart_delay.patch:
+      + Bugzilla patch to support adding a delay to autostart apps, using
+        a "X-GNOME-Autostart-Delay" key in the desktop file
+    - debian/patches/ubuntu/ubuntu_sessions.patch:
+      + Add ubuntu sessions
+    - debian/patches/ubuntu/remove_session_saving_from_gui.patch:
+      + Add GNOME_SESSION_SAVE environment variable for people wanting to
+        use the save session still, knowing that it can break your system
+        if used unwisely
+    - debian/patches/ubuntu/add_sessionmigration.patch:
+      + launch session-migration if present at the start of the session.
+        This sync tool runns different session migration scripts that can be
+        provided in various desktop packages.
+    - debian/patches/ubuntu/dbus_request_shutdown.patch:
+      + Add "RequestShutdown" and "RequestReboot" DBus methods to allow
+        other applications to shutdown or reboot the machine via the session
+        manager.
+    - debian/patches/ubuntu/ignore_gsettings_region.patch:
+      + Ignore the "region" gsettings value - users' setting of LC_*
+        variables saved in ~/.pam_environment.
+    - debian/patches/revert_remove_gnome_session_properties.patch:
+      + Don't merge translations into gnome-session-properties.desktop
+    - debian/ubuntu-settings-migrate-to-defaults.18.10.1.py:
+      + Migrate users using old default ubuntu-settings to current ones
+    - debian/xdg_dirs_desktop_session.sh: Install a new script into
+      /etc/profile.d to prepend a $DESKTOP_SESSION related directory to
+      $XDG_{CONFIG,DATA}_DIRS.
+
+ -- Marco Trevisan (Treviño) <marco@ubuntu.com>  Wed, 10 Feb 2021 20:08:41 +0100
+
 gnome-session (3.38.0-3) unstable; urgency=medium
 
   * Team upload
@@ -171,6 +530,62 @@ gnome-session (3.38.0-2) unstable; urgen
 
  -- Simon McVittie <smcv@debian.org>  Fri, 25 Sep 2020 10:30:03 +0100
 
+gnome-session (3.38.0-1ubuntu1) groovy; urgency=medium
+
+  * Merge with debian, containing new upstream release.
+  * debian/control:
+    - Update ubuntu-session breaks to match gnome ones (where it makes sense)
+  * d/p/meson-Require-meson-0.53.patch,
+    d/p/data-Leave-to-meson-the-duty-of-keeping-the-lists-in-sync.patch,
+    d/p/meson-Generate-.session.conf-for-all-the-sessions-with-re.patch:
+    - Drop, applied upstream
+  * Remaining changes with debian:
+    - debian/control.in:
+      + Recommend session-migration
+      + Move xwayland dependency to gnome-session and make gnome-session
+        Arch: any
+      + Split gnome-startup-applications to a separate binary package so
+        that it can be uninstalled without breaking the system
+      + Add unity-session
+    - Split ubuntu-session out of gnome-session.
+    - debian/data: Add old-style systemd user session used by Unity
+    - debian/gnome-session-bin.postinst, debian/gnome-session-bin.prerm:
+       Moved registering gnome-session binary as a session manager to
+       gnome-session-bin package
+    - Add gnome-session-wayland transitional package
+    - don't install gnome-mimeapps.list (installed by desktop-file-utils in
+      Ubuntu):
+      debian/gnome-session-common.dirs, gnome-session-common.install,
+      gnome-session-common.maintscript, gnome-session-common.postinst
+    - debian/patches/ubuntu/kill_the_fail_whale.patch:
+      + Kill the Fail Whale as it tends to be more annoying than helpful
+    - debian/patches/ubuntu/support_autostart_delay.patch:
+      + Bugzilla patch to support adding a delay to autostart apps, using
+        a "X-GNOME-Autostart-Delay" key in the desktop file
+    - debian/patches/ubuntu/ubuntu_sessions.patch:
+      + Add ubuntu session tweaks
+    - debian/patches/ubuntu/remove_session_saving_from_gui.patch:
+      + Add GNOME_SESSION_SAVE environment variable for people wanting to
+        use the save session still, knowing that it can break your system
+        if used unwisely
+    - debian/patches/ubuntu/add_sessionmigration.patch:
+      + launch session-migration if present at the start of the session.
+        This sync tool runns different session migration scripts that can be
+        provided in various desktop packages.
+    - debian/patches/ubuntu/dbus_request_shutdown.patch:
+      + Add "RequestShutdown" and "RequestReboot" DBus methods to allow
+        other applications to shutdown or reboot the machine via the session
+        manager.
+    - debian/patches/ubuntu/ignore_gsettings_region.patch:
+      + Ignore the "region" gsettings value - users' setting of LC_*
+        ariables saved in ~/.pam_environment.
+    - debian/patches/revert_remove_gnome_session_properties.patch:
+      + Don't merge translations into gnome-session-properties.desktop
+    - debian/ubuntu-settings-migrate-to-defaults.18.10.1.py:
+      + Migrate users using old default ubuntu-settings to current ones
+
+ -- Marco Trevisan (Treviño) <marco@ubuntu.com>  Thu, 17 Sep 2020 13:23:35 +0200
+
 gnome-session (3.38.0-1) experimental; urgency=medium
 
   * Team upload
@@ -179,6 +594,98 @@ gnome-session (3.38.0-1) experimental; u
 
  -- Simon McVittie <smcv@debian.org>  Mon, 14 Sep 2020 11:38:01 +0100
 
+gnome-session (3.37.0-2ubuntu1) groovy; urgency=medium
+
+  [ Marco Trevisan (Treviño) ]
+  * Merge with debian, containing new upstream release.
+  * debian/patches: Refreshed as per upstream source changes
+  * debian/control:
+    - Bump ubuntu-session dependencies to match gnome ones
+    - Set ubuntu-session breaks on shell and g-s-d (as gnome-session does)
+    - Bump dependency to meson 0.53 as per upstream patches
+    - Add Breaks/Replaces to unity-session on gnome-session-bin
+  * debian/gnome-session-bin.install,
+    debian/gnome-session-common.install,
+    debian/gnome-session.install,
+    debian/ubuntu-session.install:
+    - Install gnome-session common systemd unit files to gnome-session-common
+      while the ubuntu and gnome configuration drop-ins {ubuntu,gnome}-session.
+      Add executable bit and use dh-exec to enable [linux-any] there.
+  * debian/unity-session.install,
+    debian/gnome-session-bin.install:
+    - Move gnome-session.service to unity-session (it's unity specific)
+  * d/p/ubuntu/ubuntu/kill_the_fail_whale.patch:
+    - Dropped. The fail whale is still used as triggered by systemd, the bugs
+      that the patch was addressing are 5 years old now and there's no point to
+      carry this patch even more when upstream believes that the dialog should
+      be shown. Also from an Ubuntu POV it's a better user experience than just
+      going back to gdm.
+  * d/p/meson-Require-meson-0.53.patch,
+    d/p/data-Leave-to-meson-the-duty-of-keeping-the-lists-in-sync.patch,
+    d/p/meson-Generate-.session.conf-for-all-the-sessions-with-re.patch:
+    - Cherry pick upstream patches that allow to generate session files from
+      meson, so that we can reuse the same codepath and reduce duplication for
+      ubuntu session files.
+  * d/p/ubuntu/ubuntu-sessions.patch:
+    - Refresh as per upstream meson changes, make it generate ubuntu systemd
+      configuration drop-in.
+    - Don't pass --systemd anymore, this is the default
+  * Remaining changes with debian:
+    - debian/control.in:
+      + Recommend session-migration
+      + Move xwayland dependency to gnome-session and make gnome-session
+        Arch: any
+      + Split gnome-startup-applications to a separate binary package so
+        that it can be uninstalled without breaking the system
+      + Add unity-session
+    - Split ubuntu-session out of gnome-session.
+    - debian/data: Add old-style systemd user session used by Unity
+    - debian/gnome-session-bin.postinst, debian/gnome-session-bin.prerm:
+       Moved registering gnome-session binary as a session manager to
+       gnome-session-bin package
+    - Add gnome-session-wayland transitional package
+    - don't install gnome-mimeapps.list (installed by desktop-file-utils in
+      Ubuntu):
+      debian/gnome-session-common.dirs, gnome-session-common.install,
+      gnome-session-common.maintscript, gnome-session-common.postinst
+    - debian/patches/ubuntu/kill_the_fail_whale.patch:
+      + Kill the Fail Whale as it tends to be more annoying than helpful
+    - debian/patches/ubuntu/support_autostart_delay.patch:
+      + Bugzilla patch to support adding a delay to autostart apps, using
+        a "X-GNOME-Autostart-Delay" key in the desktop file
+    - debian/patches/ubuntu/ubuntu_sessions.patch:
+      + Add ubuntu session tweaks
+    - debian/patches/ubuntu/remove_session_saving_from_gui.patch:
+      + Add GNOME_SESSION_SAVE environment variable for people wanting to
+        use the save session still, knowing that it can break your system
+        if used unwisely
+    - debian/patches/ubuntu/add_sessionmigration.patch:
+      + launch session-migration if present at the start of the session.
+        This sync tool runns different session migration scripts that can be
+        provided in various desktop packages.
+    - debian/patches/ubuntu/dbus_request_shutdown.patch:
+      + Add "RequestShutdown" and "RequestReboot" DBus methods to allow
+        other applications to shutdown or reboot the machine via the session
+        manager.
+    - debian/patches/ubuntu/ignore_gsettings_region.patch:
+      + Ignore the "region" gsettings value - users' setting of LC_*
+        variables saved in ~/.pam_environment.
+    - debian/patches/revert_remove_gnome_session_properties.patch:
+      + Don't merge translations into gnome-session-properties.desktop
+    - debian/ubuntu-settings-migrate-to-defaults.18.10.1.py:
+      + Migrate users using old default ubuntu-settings to current ones
+
+  [ Iain Lane ]
+  * control: Switch from Breaks old gnome-shell to Depends new one.  I think
+    this more correctly expresses what we want here. Our systemd session
+    definitions refer to org.gnome.Shell.target which was introduced in
+    3.37.91. We should ensure that this is on the system. Similarly for the
+    various org.gnome.SettingsDaemon units which were renamed in 3.37.0.
+  * debian/control: Apply relationship changes from gnome-session to
+    ubuntu-session
+
+ -- Iain Lane <iain.lane@canonical.com>  Wed, 02 Sep 2020 17:44:42 +0100
+
 gnome-session (3.37.0-2) experimental; urgency=medium
 
   [ Simon McVittie ]
@@ -222,6 +729,56 @@ gnome-session (3.37.0-1) experimental; u
 
  -- Marco Trevisan (Treviño) <marco@ubuntu.com>  Fri, 28 Aug 2020 22:12:37 +0200
 
+gnome-session (3.36.0-2ubuntu1) focal; urgency=medium
+
+  * Merge with Debian, remaining changes:
+    - debian/control.in:
+      + Recommend session-migration
+      + Move xwayland dependency to gnome-session and make gnome-session
+        Arch: any
+      + Split gnome-startup-applications to a separate binary package so
+        that it can be uninstalled without breaking the system
+      + Add unity-session
+    - Split ubuntu-session out of gnome-session.
+    - debian/data: Add old-style systemd user session used by Unity
+    - debian/gnome-session-bin.postinst, debian/gnome-session-bin.prerm:
+       Moved registering gnome-session binary as a session manager to
+       gnome-session-bin package
+    - Add gnome-session-wayland transitional package
+    - don't install gnome-mimeapps.list (installed by desktop-file-utils in
+      Ubuntu):
+      debian/gnome-session-common.dirs, gnome-session-common.install,
+      gnome-session-common.maintscript, gnome-session-common.postinst
+    - debian/patches/ubuntu/kill_the_fail_whale.patch:
+      + Kill the Fail Whale as it tends to be more annoying than helpful
+    - debian/patches/ubuntu/support_autostart_delay.patch:
+      + Bugzilla patch to support adding a delay to autostart apps, using
+        a "X-GNOME-Autostart-Delay" key in the desktop file
+    - debian/patches/ubuntu/ubuntu_sessions.patch:
+      + Add ubuntu session tweaks
+    - debian/patches/ubuntu/remove_session_saving_from_gui.patch:
+      + Add GNOME_SESSION_SAVE environment variable for people wanting to
+        use the save session still, knowing that it can break your system
+        if used unwisely
+    - debian/patches/ubuntu/add_sessionmigration.patch:
+      + launch session-migration if present at the start of the session.
+        This sync tool runns different session migration scripts that can be
+        provided in various desktop packages.
+    - debian/patches/ubuntu/dbus_request_shutdown.patch:
+      + Add "RequestShutdown" and "RequestReboot" DBus methods to allow
+        other applications to shutdown or reboot the machine via the session
+        manager.
+    - debian/patches/ubuntu/ignore_gsettings_region.patch:
+      + Ignore the "region" gsettings value - users' setting of LC_*
+        variables saved in ~/.pam_environment.
+    - debian/patches/revert_remove_gnome_session_properties.patch:
+      + Don't merge translations into gnome-session-properties.desktop
+    - debian/ubuntu-settings-migrate-to-defaults.18.10.1.py:
+      + Migrate users using old default ubuntu-settings to current ones
+  * Drop old upstart integration - upstart is long gone
+
+ -- Iain Lane <iain.lane@canonical.com>  Thu, 26 Mar 2020 12:22:56 +0000
+
 gnome-session (3.36.0-2) unstable; urgency=medium
 
   * debian/gnome-mimeapps.list: eog and evolution have renamed their .desktop
@@ -236,6 +793,87 @@ gnome-session (3.36.0-1) unstable; urgen
 
  -- Laurent Bigonville <bigon@debian.org>  Thu, 12 Mar 2020 17:29:11 +0100
 
+gnome-session (3.35.3-1ubuntu4) focal; urgency=medium
+
+  * debian/control*:
+    - update VCS information to point to ubuntu salsa branch
+    - Bump dependencies for ubuntu-session:
+      + gnome-shell (>= 3.36.0-2ubuntu1)
+      + yaru-theme-gnome-shell (>= 20.04.3)
+  * d/gnome-session.{preinst,postinst,prerm}:
+    - Don't install gdm3.css anymore (it's now provided as gresource
+      by gnome-shell).
+
+ -- Marco Trevisan (Treviño) <marco@ubuntu.com>  Fri, 20 Mar 2020 17:11:53 +0000
+
+gnome-session (3.35.3-1ubuntu3) focal; urgency=medium
+
+  * No-change rebuild against libgnome-desktop-3-19
+
+ -- Steve Langasek <steve.langasek@ubuntu.com>  Fri, 28 Feb 2020 04:33:32 +0000
+
+gnome-session (3.35.3-1ubuntu2) focal; urgency=medium
+
+  * No-change rebuild with fixed binutils on arm64.
+
+ -- Matthias Klose <doko@ubuntu.com>  Sat, 08 Feb 2020 11:02:25 +0000
+
+gnome-session (3.35.3-1ubuntu1) focal; urgency=medium
+
+  * Merge with Debian, remaining changes:
+    - debian/control.in:
+      + Recommend session-migration
+      + Move xwayland dependency to gnome-session and make gnome-session
+        Arch: any
+      + Split gnome-startup-applications to a separate binary package so
+        that it can be uninstalled without breaking the system
+      + Add unity-session
+    - Split ubuntu-session out of gnome-session.
+    - Add upstart user session and systemd user session:
+      debian/data, debian/gnome-session-bin.user-session.upstart
+    - debian/gnome-session-bin.postinst, debian/gnome-session-bin.prerm:
+       Moved registering gnome-session binary as a session manager to
+       gnome-session-bin package
+    - Add gnome-session-wayland transitional package
+    - don't install gnome-mimeapps.list (installed by desktop-file-utils in
+      Ubuntu):
+      debian/gnome-session-common.dirs, gnome-session-common.install,
+      gnome-session-common.maintscript, gnome-session-common.postinst
+    - debian/patches/103_kill_the_fail_whale.patch:
+      + Kill the Fail Whale as it tends to be more annoying than helpful
+    - debian/patches/22_support_autostart_delay.patch:
+      + Bugzilla patch to support adding a delay to autostart apps, using
+        a "X-GNOME-Autostart-Delay" key in the desktop file
+    - debian/patches/50_ubuntu_sessions.patch:
+      + Add ubuntu session tweaks
+    - debian/patches/51_remove_session_saving_from_gui.patch:
+      + Add GNOME_SESSION_SAVE environment variable for people wanting to
+        use the save session still, knowing that it can break your system
+        if used unwisely
+    - debian/patches/53_add_sessionmigration.patch:
+      + launch session-migration if present at the start of the session.
+        This sync tool runns different session migration scripts that can be
+        provided in various desktop packages.
+    - debian/patches/95_dbus_request_shutdown.patch:
+      + Add "RequestShutdown" and "RequestReboot" DBus methods to allow
+        other applications to shutdown or reboot the machine via the session
+        manager.
+    - debian/patches/ignore_gsettings_region.patch:
+      + Ignore the "region" gsettings value - users' setting of LC_*
+        variables saved in ~/.pam_environment.
+    - debian/patches/revert_remove_gnome_session_properties.patch:
+      + Don't merge translations into gnome-session-properties.desktop
+    - debian/ubuntu-settings-migrate-to-defaults.18.10.1.py:
+      + Migrate users using old default ubuntu-settings to current ones
+  * Update for run-systemd-session in /usr/libexec
+  * Rebase patches through gbp-pq add_sessionmigration.patch and
+    remove_session_saving_from_gui.patch required manual resolution.
+  * gnome-session-bin.links: Create a symlink for run-systemd-session for the
+    old location. Just in case anything is using it. If and when it's
+    verified that nothing is, this can be dropped.
+
+ -- Iain Lane <iain.lane@canonical.com>  Thu, 09 Jan 2020 13:54:41 +0000
+
 gnome-session (3.35.3-1) experimental; urgency=medium
 
   * New upstream release
@@ -263,6 +901,68 @@ gnome-session (3.34.2-1) unstable; urgen
 
  -- Simon McVittie <smcv@debian.org>  Mon, 30 Dec 2019 17:09:56 +0000
 
+gnome-session (3.34.1-1ubuntu2) eoan; urgency=medium
+
+  * debian/data/gnome-session.service:
+    - Pass --builtin to gnome-session to fix broken login for Unity
+      after the Debian change in version 3.34.0-3.
+      Discussion at https://discourse.ubuntu.com/t/10690/127
+      Thanks to Iain Lane for the solution!
+
+ -- Gunnar Hjalmarsson <gunnarhj@ubuntu.com>  Thu, 10 Oct 2019 15:29:00 +0200
+
+gnome-session (3.34.1-1ubuntu1) eoan; urgency=medium
+
+  * debian/*: Run wrap-and-sort -a.
+    We just did this in Debian: hopefully should make future merges easier.
+  * Merge with Debian, remaining changes:
+    - debian/control.in:
+      + Recommend session-migration
+      + Move xwayland dependency to gnome-session and make gnome-session
+        Arch: any
+      + Split gnome-startup-applications to a separate binary package so
+        that it can be uninstalled without breaking the system
+      + Add unity-session
+    - Split ubuntu-session out of gnome-session.
+    - Add upstart user session and systemd user session:
+      debian/data, debian/gnome-session-bin.user-session.upstart
+    - debian/gnome-session-bin.postinst, debian/gnome-session-bin.prerm:
+       Moved registering gnome-session binary as a session manager to
+       gnome-session-bin package
+    - Add gnome-session-wayland transitional package
+    - don't install gnome-mimeapps.list (installed by desktop-file-utils in
+      Ubuntu):
+      debian/gnome-session-common.dirs, gnome-session-common.install,
+      gnome-session-common.maintscript, gnome-session-common.postinst
+    - debian/patches/103_kill_the_fail_whale.patch:
+      + Kill the Fail Whale as it tends to be more annoying than helpful
+    - debian/patches/22_support_autostart_delay.patch:
+      + Bugzilla patch to support adding a delay to autostart apps, using
+        a "X-GNOME-Autostart-Delay" key in the desktop file
+    - debian/patches/50_ubuntu_sessions.patch:
+      + Add ubuntu session tweaks
+    - debian/patches/51_remove_session_saving_from_gui.patch:
+      + Add GNOME_SESSION_SAVE environment variable for people wanting to
+        use the save session still, knowing that it can break your system
+        if used unwisely
+    - debian/patches/53_add_sessionmigration.patch:
+      + launch session-migration if present at the start of the session.
+        This sync tool runns different session migration scripts that can be
+        provided in various desktop packages.
+    - debian/patches/95_dbus_request_shutdown.patch:
+      + Add "RequestShutdown" and "RequestReboot" DBus methods to allow
+        other applications to shutdown or reboot the machine via the session
+        manager.
+    - debian/patches/ignore_gsettings_region.patch:
+      + Ignore the "region" gsettings value - users' setting of LC_*
+        variables saved in ~/.pam_environment.
+    - debian/patches/revert_remove_gnome_session_properties.patch:
+      + Don't merge translations into gnome-session-properties.desktop
+    - debian/ubuntu-settings-migrate-to-defaults.18.10.1.py:
+      + Migrate users using old default ubuntu-settings to current ones
+
+ -- Iain Lane <iain.lane@canonical.com>  Mon, 07 Oct 2019 12:38:07 +0100
+
 gnome-session (3.34.1-1) unstable; urgency=medium
 
   * New upstream release
@@ -302,6 +1002,60 @@ gnome-session (3.34.0-1) experimental; u
 
  -- Simon McVittie <smcv@debian.org>  Mon, 16 Sep 2019 08:54:12 +0100
 
+gnome-session (3.33.92-1ubuntu1) eoan; urgency=medium
+
+  * Merge with Debian, remaining changes:
+    - debian/control.in:
+      + Recommend session-migration
+      + Move xwayland dependency to gnome-session and make gnome-session
+        Arch: any
+      + Split gnome-startup-applications to a separate binary package so
+        that it can be uninstalled without breaking the system
+      + Add unity-session
+    - Split ubuntu-session out of gnome-session.
+    - Add upstart user session and systemd user session:
+      debian/data, debian/gnome-session-bin.user-session.upstart
+    - debian/gnome-session-bin.postinst, debian/gnome-session-bin.prerm:
+       Moved registering gnome-session binary as a session manager to
+       gnome-session-bin package
+    - Add gnome-session-wayland transitional package
+    - don't install gnome-mimeapps.list (installed by desktop-file-utils in
+      Ubuntu):
+      debian/gnome-session-common.dirs, gnome-session-common.install,
+      gnome-session-common.maintscript, gnome-session-common.postinst
+    - debian/patches/103_kill_the_fail_whale.patch:
+      + Kill the Fail Whale as it tends to be more annoying than helpful
+    - debian/patches/22_support_autostart_delay.patch:
+      + Bugzilla patch to support adding a delay to autostart apps, using
+        a "X-GNOME-Autostart-Delay" key in the desktop file
+    - debian/patches/50_ubuntu_sessions.patch:
+      + Add ubuntu session tweaks
+    - debian/patches/51_remove_session_saving_from_gui.patch:
+      + Add GNOME_SESSION_SAVE environment variable for people wanting to
+        use the save session still, knowing that it can break your system
+        if used unwisely
+    - debian/patches/53_add_sessionmigration.patch:
+      + launch session-migration if present at the start of the session.
+        This sync tool runns different session migration scripts that can be
+        provided in various desktop packages.
+    - debian/patches/95_dbus_request_shutdown.patch:
+      + Add "RequestShutdown" and "RequestReboot" DBus methods to allow
+        other applications to shutdown or reboot the machine via the session
+        manager.
+    - debian/patches/ignore_gsettings_region.patch:
+      + Ignore the "region" gsettings value - users' setting of LC_*
+        variables saved in ~/.pam_environment.
+    - debian/patches/revert_remove_gnome_session_properties.patch:
+      + Don't merge translations into gnome-session-properties.desktop
+    - debian/ubuntu-settings-migrate-to-defaults.18.10.1.py:
+      + Migrate users using old default ubuntu-settings to current ones
+  * Take change from debian/master:
+    + d/p/d/gnome-.desktop.in.in-Pass-systemd.patch: Use gnome-session-systemd
+      too. I'd patched TryExec before, by mistake.
+  * Refresh patches
+
+ -- Iain Lane <iain.lane@canonical.com>  Fri, 06 Sep 2019 18:11:39 +0100
+
 gnome-session (3.33.92-1) experimental; urgency=medium
 
   * d/control, d/gnome-session-bin.install: Only install user units on Linux
@@ -322,6 +1076,64 @@ gnome-session (3.33.90-3) experimental;
 
  -- Iain Lane <laney@debian.org>  Thu, 05 Sep 2019 17:23:10 +0100
 
+gnome-session (3.33.90-2ubuntu2) eoan; urgency=medium
+
+  * Bring back gnome-session.service as Unity still needs it.
+  * Alter description of gnome-session.service to make clear it is for Unity.
+
+ -- Iain Lane <iain.lane@canonical.com>  Thu, 29 Aug 2019 10:39:12 +0100
+
+gnome-session (3.33.90-2ubuntu1) eoan; urgency=medium
+
+  * Merge with Debian, remaining changes:
+    - debian/control.in:
+      + Recommend session-migration
+      + Move xwayland dependency to gnome-session and make gnome-session
+        Arch: any
+      + Split gnome-startup-applications to a separate binary package so
+        that it can be uninstalled without breaking the system
+      + Add unity-session
+    - Split ubuntu-session out of gnome-session.
+    - Add upstart user session and systemd user session:
+      debian/data, debian/gnome-session-bin.user-session.upstart
+    - debian/gnome-session-bin.postinst, debian/gnome-session-bin.prerm:
+       Moved registering gnome-session binary as a session manager to
+       gnome-session-bin package
+    - Add gnome-session-wayland transitional package
+    - don't install gnome-mimeapps.list (installed by desktop-file-utils in
+      Ubuntu):
+      debian/gnome-session-common.dirs, gnome-session-common.install,
+      gnome-session-common.maintscript, gnome-session-common.postinst
+    - debian/patches/103_kill_the_fail_whale.patch:
+      + Kill the Fail Whale as it tends to be more annoying than helpful
+    - debian/patches/22_support_autostart_delay.patch:
+      + Bugzilla patch to support adding a delay to autostart apps, using
+        a "X-GNOME-Autostart-Delay" key in the desktop file
+    - debian/patches/50_ubuntu_sessions.patch:
+      + Add ubuntu session tweaks
+    - debian/patches/51_remove_session_saving_from_gui.patch:
+      + Add GNOME_SESSION_SAVE environment variable for people wanting to
+        use the save session still, knowing that it can break your system
+        if used unwisely
+    - debian/patches/53_add_sessionmigration.patch:
+      + launch session-migration if present at the start of the session.
+        This sync tool runns different session migration scripts that can be
+        provided in various desktop packages.
+    - debian/patches/95_dbus_request_shutdown.patch:
+      + Add "RequestShutdown" and "RequestReboot" DBus methods to allow
+        other applications to shutdown or reboot the machine via the session
+        manager.
+    - debian/patches/ignore_gsettings_region.patch:
+      + Ignore the "region" gsettings value - users' setting of LC_*
+        variables saved in ~/.pam_environment.
+    - debian/patches/revert_remove_gnome_session_properties.patch:
+      + Don't merge translations into gnome-session-properties.desktop
+    - debian/ubuntu-settings-migrate-to-defaults.18.10.1.py:
+      + Migrate users using old default ubuntu-settings to current ones
+  * ubuntu-sessions.patch: Refresh
+
+ -- Iain Lane <iain.lane@canonical.com>  Sat, 24 Aug 2019 08:55:06 +0100
+
 gnome-session (3.33.90-2) experimental; urgency=medium
 
   * rules, gnome-.desktop.in.in-Pass-systemd.patch: Build with
@@ -331,6 +1143,63 @@ gnome-session (3.33.90-2) experimental;
 
  -- Iain Lane <laney@debian.org>  Sat, 24 Aug 2019 08:18:53 +0100
 
+gnome-session (3.33.90-1ubuntu1) eoan; urgency=medium
+
+  * Merge with Debian, remaining changes:
+    - debian/control.in:
+      + Recommend session-migration
+      + Move xwayland dependency to gnome-session and make gnome-session
+        Arch: any
+      + Split gnome-startup-applications to a separate binary package so
+        that it can be uninstalled without breaking the system
+      + Add unity-session
+    - Split ubuntu-session out of gnome-session.
+    - Add upstart user session and systemd user session:
+      debian/data, debian/gnome-session-bin.user-session.upstart
+    - debian/gnome-session-bin.postinst, debian/gnome-session-bin.prerm:
+       Moved registering gnome-session binary as a session manager to
+       gnome-session-bin package
+    - Add gnome-session-wayland transitional package
+    - don't install gnome-mimeapps.list (installed by desktop-file-utils in
+      Ubuntu):
+      debian/gnome-session-common.dirs, gnome-session-common.install,
+      gnome-session-common.maintscript, gnome-session-common.postinst
+    - debian/patches/103_kill_the_fail_whale.patch:
+      + Kill the Fail Whale as it tends to be more annoying than helpful
+    - debian/patches/22_support_autostart_delay.patch:
+      + Bugzilla patch to support adding a delay to autostart apps, using
+        a "X-GNOME-Autostart-Delay" key in the desktop file
+    - debian/patches/50_ubuntu_sessions.patch:
+      + Add ubuntu session tweaks
+    - debian/patches/51_remove_session_saving_from_gui.patch:
+      + Add GNOME_SESSION_SAVE environment variable for people wanting to
+        use the save session still, knowing that it can break your system
+        if used unwisely
+    - debian/patches/53_add_sessionmigration.patch:
+      + launch session-migration if present at the start of the session.
+        This sync tool runns different session migration scripts that can be
+        provided in various desktop packages.
+    - debian/patches/95_dbus_request_shutdown.patch:
+      + Add "RequestShutdown" and "RequestReboot" DBus methods to allow
+        other applications to shutdown or reboot the machine via the session
+        manager.
+    - debian/patches/ignore_gsettings_region.patch:
+      + Ignore the "region" gsettings value - users' setting of LC_*
+        variables saved in ~/.pam_environment.
+    - debian/patches/revert_remove_gnome_session_properties.patch:
+      + Don't merge translations into gnome-session-properties.desktop
+    - debian/ubuntu-settings-migrate-to-defaults.18.10.1.py:
+      + Migrate users using old default ubuntu-settings to current ones
+  * ubuntu-sessions.patch: Add X-GDM-SessionRegisters=true to our.desktop
+    files. Following a change from upstream we need to register with GDM when
+    logging in, so that it knows when to shut itself down. (LP: #1798790)
+  * debian/patches/*: Rebase. Adjust the Ubuntu session to account for dropped
+    components
+  * Drop our downstream gnome-session upstart override and service. We have
+    this upstream now (and upstart is gone)
+
+ -- Iain Lane <laney@debian.org>  Fri, 16 Aug 2019 16:56:49 +0100
+
 gnome-session (3.33.90-1) experimental; urgency=medium
 
   * New upstream release
@@ -372,6 +1241,70 @@ gnome-session (3.32.0-1) experimental; u
 
  -- Jeremy Bicha <jbicha@debian.org>  Sun, 17 Mar 2019 15:54:16 -0400
 
+gnome-session (3.30.1-2ubuntu2) disco; urgency=medium
+
+  [ Khurshid Alam ]
+  * Add nemo autostart and other action files to unity session.
+    (LP: #1814506)
+
+  [ Alberts Muktupāvels ]
+  * gnome-session.service: Don't spam logs with dbus-send usage
+    If UPSTART_SESSION is not set log files are spammed with dbus-send
+    usage. Fix this by checking if UPSTART_SESSION is set to non-empty
+    string.
+
+ -- Didier Roche <didrocks@ubuntu.com>  Tue, 19 Feb 2019 11:17:40 +0100
+
+gnome-session (3.30.1-2ubuntu1) disco; urgency=medium
+
+  * Merge with Debian, remaining changes:
+    - debian/control.in:
+      + Recommend session-migration
+      + Move xwayland dependency to gnome-session and make gnome-session
+        Arch: any
+      + Split gnome-startup-applications to a separate binary package so
+        that it can be uninstalled without breaking the system
+      + Add unity-session
+    - Split ubuntu-session out of gnome-session.
+    - Add upstart user session and systemd user session:
+      debian/data, debian/gnome-session-bin.user-session.upstart
+    - debian/gnome-session-bin.postinst, debian/gnome-session-bin.prerm:
+       Moved registering gnome-session binary as a session manager to
+       gnome-session-bin package
+    - Add gnome-session-wayland transitional package
+    - don't install gnome-mimeapps.list (installed by desktop-file-utils in
+      Ubuntu):
+      debian/gnome-session-common.dirs, gnome-session-common.install,
+      gnome-session-common.maintscript, gnome-session-common.postinst
+    - debian/patches/103_kill_the_fail_whale.patch:
+      + Kill the Fail Whale as it tends to be more annoying than helpful
+    - debian/patches/22_support_autostart_delay.patch:
+      + Bugzilla patch to support adding a delay to autostart apps, using
+        a "X-GNOME-Autostart-Delay" key in the desktop file
+    - debian/patches/50_ubuntu_sessions.patch:
+      + Add ubuntu session tweaks
+    - debian/patches/51_remove_session_saving_from_gui.patch:
+      + Add GNOME_SESSION_SAVE environment variable for people wanting to
+        use the save session still, knowing that it can break your system
+        if used unwisely
+    - debian/patches/53_add_sessionmigration.patch:
+      + launch session-migration if present at the start of the session.
+        This sync tool runns different session migration scripts that can be
+        provided in various desktop packages.
+    - debian/patches/95_dbus_request_shutdown.patch:
+      + Add "RequestShutdown" and "RequestReboot" DBus methods to allow
+        other applications to shutdown or reboot the machine via the session
+        manager.
+    - debian/patches/ignore_gsettings_region.patch:
+      + Ignore the "region" gsettings value - users' setting of LC_*
+        variables saved in ~/.pam_environment.
+    - debian/patches/revert_remove_gnome_session_properties.patch:
+      + Don't merge translations into gnome-session-properties.desktop
+    - debian/ubuntu-settings-migrate-to-defaults.18.10.1.py:
+      + Migrate users using old default ubuntu-settings to current ones
+
+ -- Iain Lane <iain.lane@canonical.com>  Fri, 18 Jan 2019 17:45:00 +0000
+
 gnome-session (3.30.1-2) unstable; urgency=medium
 
   [ Laurent Bigonville ]
@@ -384,6 +1317,63 @@ gnome-session (3.30.1-2) unstable; urgen
 
  -- Jeremy Bicha <jbicha@debian.org>  Tue, 25 Dec 2018 09:52:38 -0500
 
+gnome-session (3.30.1-1ubuntu1) disco; urgency=medium
+
+  [ Iain Lane ]
+  * Merge with Debian, remaining changes:
+    - debian/control.in:
+      + Recommend session-migration
+      + Move xwayland dependency to gnome-session and make gnome-session
+        Arch: any
+      + Split gnome-startup-applications to a separate binary package so
+        that it can be uninstalled without breaking the system
+      + Add unity-session
+    - Split ubuntu-session out of gnome-session.
+    - Add upstart user session and systemd user session:
+      debian/data, debian/gnome-session-bin.user-session.upstart
+    - debian/gnome-session-bin.postinst, debian/gnome-session-bin.prerm:
+       Moved registering gnome-session binary as a session manager to
+       gnome-session-bin package
+    - Add gnome-session-wayland transitional package
+    - don't install gnome-mimeapps.list (installed by desktop-file-utils in
+      Ubuntu):
+      debian/gnome-session-common.dirs, gnome-session-common.install,
+      gnome-session-common.maintscript, gnome-session-common.postinst
+    - debian/patches/103_kill_the_fail_whale.patch:
+      + Kill the Fail Whale as it tends to be more annoying than helpful
+    - debian/patches/22_support_autostart_delay.patch:
+      + Bugzilla patch to support adding a delay to autostart apps, using
+        a "X-GNOME-Autostart-Delay" key in the desktop file
+    - debian/patches/50_ubuntu_sessions.patch:
+      + Add ubuntu session tweaks
+    - debian/patches/51_remove_session_saving_from_gui.patch:
+      + Add GNOME_SESSION_SAVE environment variable for people wanting to
+        use the save session still, knowing that it can break your system
+        if used unwisely
+    - debian/patches/53_add_sessionmigration.patch:
+      + launch session-migration if present at the start of the session.
+        This sync tool runns different session migration scripts that can be
+        provided in various desktop packages.
+    - debian/patches/95_dbus_request_shutdown.patch:
+      + Add "RequestShutdown" and "RequestReboot" DBus methods to allow
+        other applications to shutdown or reboot the machine via the session
+        manager.
+    - debian/patches/ignore_gsettings_region.patch:
+      + Ignore the "region" gsettings value - users' setting of LC_*
+        variables saved in ~/.pam_environment.
+    - debian/patches/revert_remove_gnome_session_properties.patch:
+      + Don't merge translations into gnome-session-properties.desktop
+  * debian/patches/50_ubuntu_sessions.patch:
+    - moved to debian/patches/ubuntu/ubuntu-sessions.patch (using gbp topic)
+  * ubuntu/ignore_gsettings_region.patch: Refresh
+
+  [ Marco Trevisan (Treviño) ]
+  * debian/ubuntu-settings-migrate-to-defaults.18.10.0.py:
+    - renamed to ubuntu-settings-migrate-to-defaults.18.10.1.py
+      + Also run in ubuntu-wayland desktop session (LP: #1799205)
+
+ -- Iain Lane <iain.lane@canonical.com>  Fri, 30 Nov 2018 16:32:53 +0000
+
 gnome-session (3.30.1-1) unstable; urgency=medium
 
   * Team upload
@@ -423,6 +1413,153 @@ gnome-session (3.30.0-1) experimental; u
 
  -- Simon McVittie <smcv@debian.org>  Wed, 19 Sep 2018 14:04:21 +0100
 
+gnome-session (3.30.0-0ubuntu4) cosmic; urgency=medium
+
+  * Make {ubuntu,gnome}-session Arch: all and remove qualification on xwayland
+    dep. In Ubuntu we only have architectures which match [linux-any] anyway.
+    Making these -session packages Arch: all means that it's not a problem
+    that gjs isn't built on s390x at the minute.
+
+ -- Iain Lane <laney@debian.org>  Fri, 05 Oct 2018 13:40:07 +0100
+
+gnome-session (3.30.0-0ubuntu3) cosmic; urgency=medium
+
+  * Introduce a communitheme-snap-session for people who want to test
+    the communitheme snap in cosmic and over. Moving them out of the
+    ubuntu-session package.
+    This split enables us to transition communitheme snap users to default
+    ubuntu session after upgrading from bionic to cosmic or next LTS.
+    (LP: #1794024)
+
+ -- Didier Roche <didrocks@ubuntu.com>  Mon, 24 Sep 2018 09:30:46 +0200
+
+gnome-session (3.30.0-0ubuntu2) cosmic; urgency=medium
+
+  * debian/ubuntu-settings-migrate-to-defaults.18.10.0.py:
+    - use getenv instead of environ[], as the session env key is
+      missing for instance under gdm. (LP: #1790532)
+    - add missing sys import (LP: #1791100)
+
+ -- Didier Roche <didrocks@ubuntu.com>  Fri, 07 Sep 2018 08:58:23 +0200
+
+gnome-session (3.30.0-0ubuntu1) cosmic; urgency=medium
+
+  * New upstream release:
+    - Fix NEWS file
+    - Translation updates
+    - Add new RebootToFirmwareSetup API
+    - Crash fix when running with nested wayland compositors
+    - use full path to binaries in desktop files
+  * debian/patches/ubuntu/ubuntu-sessions.patch:
+    - refresh to latest upstream (now that @bindir@ is required)
+    - change .in ubuntu desktop files to .in.in, including translations
+      and skipping generated files, so that we include @bindir@ for our
+      sessino files as well.
+    - adapt the build system to those, minimializing the diff with upstream
+  * d/p/revert_remove_gnome_session_properties.patch,
+    d/p/ubuntu/dbus_request_shutdown.patch,
+    d/p/ubuntu/post_install-install-gnome.desktop-session-in-wayland-ses.patch,
+    d/p/ubuntu/support_autostart_delay.patch:
+    - adapt to above changes and refresh
+
+ -- Didier Roche <didrocks@ubuntu.com>  Wed, 05 Sep 2018 11:08:25 +0200
+
+gnome-session (3.29.90-1ubuntu3) cosmic; urgency=medium
+
+  * debian/ubuntu-settings-migrate-to-defaults.18.10.0.py:
+    - Migrate users using old default ubuntu-settings to current ones
+
+ -- Marco Trevisan (Treviño) <marco@ubuntu.com>  Tue, 21 Aug 2018 21:50:02 +0200
+
+gnome-session (3.29.90-1ubuntu2) cosmic; urgency=medium
+
+  * debian/gnome-session.install:
+    - Revert change that was wrongly merged from debian, causing
+      gnome-session and ubuntu-session to have the same files (LP: #1787748)
+  * debian/control:
+    - Set Breaks/Replaces on gnome-shell <=> ubuntu-settings for versions
+      <= 3.29.90-1ubuntu1 (LP: #1787748)
+    - Build-depends on meson (>= 0.47.0) as per dict usage
+  * debian/gnome-session.install:
+    - install all gnome-provided *.session files
+  * d/p/ubuntu/post_install-install-gnome.desktop-session-in-wayland-ses.patch:
+    - Do not install gnome.session in xsessions (as defaults to wayland) 
+  * d/p/ubuntu/ubuntu-sessions.patch:
+    - Install session X and wayland .desktop files only in the relative-type
+      directories, and cleanup the meson code using a dict.
+  * debian/rules:
+    - Use dh_missing --fail-missing
+  * d/p/53_add_sessionmigration.patch:
+    - Use Gbp-Pq topic, moved to d/p/ubuntu/add_sessionmigration.patch
+  * d/p/95_dbus_request_shutdown.patch:
+    - Use Gbp-Pq topic, moved to d/p/ubuntu/dbus_request_shutdown.patch
+  * d/p/ignore_gsettings_region.patch:
+    - Use Gbp-Pq topic, moved to d/p/ubuntu/ignore_gsettings_region.patch
+  * d/p/103_kill_the_fail_whale.patch:
+    - Use Gbp-Pq topic, moved to d/p/ubuntu/kill_the_fail_whale.patch
+  * d/p/51_remove_session_saving_from_gui.patch:
+    - Use Gbp-Pq topic, moved to d/p/ubuntu/remove_session_saving_from_gui.patch
+  * d/p/22_support_autostart_delay.patch:
+    - Use Gbp-Pq topic, moved to d/p/ubuntu/support_autostart_delay.patch
+
+ -- Marco Trevisan (Treviño) <marco@ubuntu.com>  Tue, 21 Aug 2018 11:07:21 -0500
+
+gnome-session (3.29.90-1ubuntu1) cosmic; urgency=medium
+
+  * Merge with debian, remaining changes:
+    - debian/control.in:
+      + Recommend session-migration
+      + Move xwayland dependency to gnome-session and make gnome-session
+        Arch: any
+      + Split gnome-startup-applications to a separate binary package so
+        that it can be uninstalled without breaking the system
+      + Add unity-session
+    - Split ubuntu-session out of gnome-session.
+    - Add upstart user session and systemd user session:
+      debian/data, debian/gnome-session-bin.user-session.upstart
+    - debian/gnome-session-bin.postinst, debian/gnome-session-bin.prerm:
+       Moved registering gnome-session binary as a session manager to
+       gnome-session-bin package
+    - Add gnome-session-wayland transitional package
+    - don't install gnome-mimeapps.list (installed by desktop-file-utils in
+      Ubuntu):
+      debian/gnome-session-common.dirs, gnome-session-common.install,
+      gnome-session-common.maintscript, gnome-session-common.postinst
+    - debian/patches/103_kill_the_fail_whale.patch:
+      + Kill the Fail Whale as it tends to be more annoying than helpful
+    - debian/patches/22_support_autostart_delay.patch:
+      + Bugzilla patch to support adding a delay to autostart apps, using
+        a "X-GNOME-Autostart-Delay" key in the desktop file
+    - debian/patches/50_ubuntu_sessions.patch:
+      + Add ubuntu session tweaks
+    - debian/patches/51_remove_session_saving_from_gui.patch:
+      + Add GNOME_SESSION_SAVE environment variable for people wanting to
+        use the save session still, knowing that it can break your system
+        if used unwisely
+    - debian/patches/53_add_sessionmigration.patch:
+      + launch session-migration if present at the start of the session.
+        This sync tool runns different session migration scripts that can be
+        provided in various desktop packages.
+    - debian/patches/95_dbus_request_shutdown.patch:
+      + Add "RequestShutdown" and "RequestReboot" DBus methods to allow
+        other applications to shutdown or reboot the machine via the session
+        manager.
+    - debian/patches/ignore_gsettings_region.patch:
+      + Ignore the "region" gsettings value - users' setting of LC_*
+        variables saved in ~/.pam_environment.
+    - debian/patches/revert_remove_gnome_session_properties.patch:
+      + Don't merge translations into gnome-session-properties.desktop
+  * debian/patches/50_ubuntu_sessions.patch:
+    - moved to debian/patches/ubuntu/ubuntu-sessions.patch (using gbp topic)
+
+  [ Didier Roche ]
+  * Remove gnome-themes-extra and gtk2-engines-pixbuf Recommends.
+    Those are pulled by the themes as needed.
+  * ubuntu-session now depends on yaru-theme-gnome-shell, as the mod
+    refers to it. (LP: #1783571)
+
+ -- Marco Trevisan (Treviño) <marco@ubuntu.com>  Fri, 17 Aug 2018 03:12:08 +0200
+
 gnome-session (3.29.90-1) experimental; urgency=medium
 
   * New upstream revision
@@ -439,6 +1576,55 @@ gnome-session (3.28.1-1) unstable; urgen
 
  -- Tim Lunn <tim@feathertop.org>  Sat, 14 Apr 2018 12:57:24 +1000
 
+gnome-session (3.28.1-0ubuntu3) bionic; urgency=medium
+
+  * Prevent debian/unity-gnome-shell-migration.17.10.py script migration
+    crash when no Ubuntu Dock or Dash to Dock installed after upgrade
+    (LP: #1720310)
+
+ -- Didier Roche <didrocks@ubuntu.com>  Wed, 02 May 2018 09:40:42 +0200
+
+gnome-session (3.28.1-0ubuntu2) bionic; urgency=medium
+
+  * debian/xdg_dirs_desktop_session.sh, debian/55gnome-session_gnomerc:
+    - protect against multiple additions of the same paths to
+      XDG_CONFIG_DIRS and XDG_DATA_DIRS, resulting to duplication on
+      consecutive logout/logins due to older session hanging in and env
+      being reused.
+      Some consequences is that electron application crashes (LP: #1764355)
+
+ -- Didier Roche <didrocks@ubuntu.com>  Thu, 19 Apr 2018 16:43:50 +0200
+
+gnome-session (3.28.1-0ubuntu1) bionic; urgency=medium
+
+  * New upstream release
+    - Don't create ~/.config as world-readable. (LP: #1735929)
+  * Drop xsmp-don-t-check-for-HAVE_XTRANS.patch: Applied in new release
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Tue, 10 Apr 2018 10:09:40 -0400
+
+gnome-session (3.28.0-0ubuntu4) bionic; urgency=medium
+
+  * Split gnome-startup-applications to a separate binary package so
+    that it can be uninstalled without breaking the system (LP: #1756788)
+  * Have gnome-session-bin recommend gnome-startup-applications
+    to try to make this change less disruptive at this late point in the
+    Ubuntu release cycle
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Mon, 09 Apr 2018 11:42:46 -0400
+
+gnome-session (3.28.0-0ubuntu3) bionic; urgency=medium
+
+  * Cherry-pick Debian change
+
+  [Simon McVittie]
+  * d/p/xsmp-don-t-check-for-HAVE_XTRANS.patch:
+    Add patch from upstream making xtrans support work again, so that
+    gnome-session doesn't fall back to TCP sockets for session management
+    (Closes: #894351)
+
+ -- Tim Lunn <tim@feathertop.org>  Sun, 01 Apr 2018 11:53:22 +1000
+
 gnome-session (3.28.0-2) unstable; urgency=medium
 
   * Team upload
@@ -457,6 +1643,27 @@ gnome-session (3.28.0-1) unstable; urgen
 
  -- Tim Lunn <tim@feathertop.org>  Sun, 18 Mar 2018 18:06:26 +1100
 
+gnome-session (3.28.0-0ubuntu2) bionic; urgency=medium
+
+  * Add new communitheme session to the ubuntu session package. This
+    session only appears if the communitheme snap is installed. (LP: #1760049)
+    - debian/patches/50_ubuntu_sessions.patch, debian/ubuntu-session.install:
+      generate and install session file.
+    - add Recommends on gtk adwaita and pixbuf theme engine.
+    - debian/rules: enable communitheme to override the default ubuntu-dock
+      stylesheet from the snap.
+    - debian/rules: workaround for Xorg to pick up communitheme cursor theme
+      from the snap.
+  * Refresh debian/patches/revert_remove_gnome_session_properties.patch
+
+ -- Didier Roche <didrocks@ubuntu.com>  Fri, 30 Mar 2018 11:03:17 +0200
+
+gnome-session (3.28.0-0ubuntu1) bionic; urgency=medium
+
+  * New upstream release.
+
+ -- Tim Lunn <tim@feathertop.org>  Sun, 18 Mar 2018 19:00:24 +1100
+
 gnome-session (3.27.92-1) unstable; urgency=medium
 
   * New upstream release candidate
@@ -464,6 +1671,59 @@ gnome-session (3.27.92-1) unstable; urge
 
  -- Jeremy Bicha <jbicha@debian.org>  Sat, 10 Mar 2018 21:11:30 -0500
 
+gnome-session (3.27.91-0ubuntu4) bionic; urgency=medium
+
+  * debian/rules: Simplify code for adding X-Ubuntu-Gettext-Domain
+    (LP: #1754904, LP: #1754491).
+
+ -- Gunnar Hjalmarsson <gunnarhj@ubuntu.com>  Mon, 12 Mar 2018 15:51:00 +0100
+
+gnome-session (3.27.91-0ubuntu3) bionic; urgency=medium
+
+  * debian/rules:
+    - Add X-Ubuntu-Gettext-Domain to .desktop files (LP: #1754904).
+    - Build gnome-session-3.0.pot.
+  * debian/patches/revert_remove_gnome_session_properties.patch:
+    - Don't merge translations into gnome-session-properties.desktop.
+
+ -- Gunnar Hjalmarsson <gunnarhj@ubuntu.com>  Mon, 12 Mar 2018 03:25:00 +0100
+
+gnome-session (3.27.91-0ubuntu2) bionic; urgency=medium
+
+  * Fix dh_install rule after switching to dh_missing (LP: #1753403)
+  * Fix accidental +x permission for debian/gnome-session-bin.install
+
+ -- Jeremy Bicha <jbicha@debian.org>  Mon, 05 Mar 2018 08:06:39 -0500
+
+gnome-session (3.27.91-0ubuntu1) bionic; urgency=medium
+
+  [ Tim Lunn ]
+  * New upstream release (LP: #1752928)
+  * debian/patches:
+    - revert_remove_gnome_session_properties.patch merge with
+      revert_remove_gnome_session_properties2.patch and port to meson
+    - 13_display_session_properties.patch: Merged into the above revert
+    - 51_remove_session_saving_from_gui.patch: Merged UI part into revert
+    - export_env_to_upstart.patch: Dropped, upstart is no longer in
+      the archives
+  * debian/gnome-wayland.desktop: Drop, this was leftover from when
+    we overrode wayland being defaulta
+  * debian/control.in: Recommend gnome-theme-extra instead of
+    gnome-themes-standard
+  * debian/gnome-session-bin.user-session.upstart: Dropped, upstart is no
+    longer in the archives
+  * debian/rules: use dh-missing for future dh 12 compat
+  * Fix Lintian errors:
+    - Move gnome-session-wayland to oldlibs/optional
+    - gnome-session-bin.install: dh_exec features are not used
+    - debian/control.in: fix not-binnmuable-any-depends-all errors
+
+  [ Jeremy Bica ]
+  * Build with meson
+  * Refresh patches
+
+ -- Tim Lunn <tim@feathertop.org>  Mon, 05 Mar 2018 17:55:42 +1100
+
 gnome-session (3.27.90.1-1) experimental; urgency=medium
 
   * New upstream development release
@@ -488,12 +1748,126 @@ gnome-session (3.26.1-1) unstable; urgen
 
  -- Simon McVittie <smcv@debian.org>  Fri, 06 Oct 2017 10:52:04 +0100
 
+gnome-session (3.26.1-0ubuntu10) bionic; urgency=medium
+
+  * No-change rebuild against latest gnome-desktop3
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Thu, 15 Feb 2018 21:06:22 -0500
+
+gnome-session (3.26.1-0ubuntu9) bionic; urgency=medium
+
+  * debian/ubuntu-session.links, debian/patches/50_ubuntu_sessions.patch,
+    debian/ubuntu-session.install:
+    - Change ubuntu session to be running on Xorg by default. Added
+      an optional ubuntu-wayland one.
+
+ -- Didier Roche <didrocks@ubuntu.com>  Tue, 06 Feb 2018 10:57:16 +0100
+
+gnome-session (3.26.1-0ubuntu8) bionic; urgency=medium
+
+  * Have unity-session recommend gtk3-nocsd. (LP: #1738338)
+
+ -- Khurshid Alam <khurshid.alam@linuxmail.org>  Fri, 15 Dec 2017 11:46:26 +0530
+
+gnome-session (3.26.1-0ubuntu7) bionic; urgency=medium
+
+  * Allow building on s390x
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Thu, 02 Nov 2017 19:36:36 -0400
+
+gnome-session (3.26.1-0ubuntu6) artful; urgency=medium
+
+  * Add symlinks in /usr/share/xsessions/:
+    - gnome.desktop -> gnome-xorg.desktop
+    - ubuntu.desktop -> ubuntu-xorg.desktop
+    In combination with a gdm3 patch, this ensures a proper fallback session
+    is selected by gdm when wayland is not enabled (LP: #1718446).
+
+ -- Olivier Tilloy <olivier.tilloy@canonical.com>  Fri, 13 Oct 2017 13:33:27 +0200
+
+gnome-session (3.26.1-0ubuntu5) artful; urgency=medium
+
+  * debian/unity-gnome-shell-migration.17.10.py:
+    - Only reset rhythmbox keys if installed (LP: #1723365)
+
+ -- Didier Roche <didrocks@ubuntu.com>  Fri, 13 Oct 2017 11:56:41 +0200
+
+gnome-session (3.26.1-0ubuntu4) artful; urgency=medium
+
+  * Make sure ubuntu-xorg.desktop can be translated (as it's "Ubuntu on Xorg")
+    (LP: #1715822)
+
+ -- Didier Roche <didrocks@ubuntu.com>  Wed, 11 Oct 2017 17:30:38 +0200
+
+gnome-session (3.26.1-0ubuntu3) artful; urgency=medium
+
+  [ Gunnar Hjalmarsson ]
+  * debian/patches/ignore_gsettings_region.patch:
+    - Ignore the "region" gsettings value - users' setting of LC_*
+      variables saved in ~/.pam_environment (LP: #1722002).
+  * debian/control, debian/control.in:
+    - Suggest gnome-user-docs instead of gnome-user-guide
+      (LP: #1691867).
+
+ -- Gunnar Hjalmarsson <gunnarhj@ubuntu.com>  Mon, 09 Oct 2017 20:01:00 +0200
+
+gnome-session (3.26.1-0ubuntu2) artful; urgency=medium
+
+  * debian/patches/revert_remove_gnome_session_properties.patch: Fix to work
+    with multiple components in XDG_CURRENT_DESKTOP. (LP: #1718553)
+
+ -- Iain Lane <iain@orangesquash.org.uk>  Mon, 09 Oct 2017 22:52:22 +0100
+
+gnome-session (3.26.1-0ubuntu1) artful; urgency=medium
+
+  [ Marco Trevisan ]
+  * Remove scale factor reset in migration script as now handled in the unity
+    settings package and only impact people migrating with unity installed
+    (LP: #1721082)
+
+  [ Didier Roche ]
+  * New upstream release
+  * debian/unity-gnome-shell-migration.17.10.py:
+    - reset the rhythmbox plugins key and rename the migration script for
+      people who installed pre-alpha getting the glib fix where some
+      applications weren't supporting the per session override.
+      (LP: #1720754)
+    - rename it so that can applies to upgraders (the script is idempotent)
+
+ -- Didier Roche <didrocks@ubuntu.com>  Mon, 09 Oct 2017 12:23:49 +0200
+
 gnome-session (3.26.0-1) unstable; urgency=medium
 
   * New upstream release
 
  -- Jeremy Bicha <jbicha@debian.org>  Thu, 14 Sep 2017 19:11:33 -0400
 
+gnome-session (3.26.0-0ubuntu2) artful; urgency=medium
+
+  [ Jeremy Bicha ]
+  * Have gnome-session recommend gnome-themes-standard (Adwaita for GTK+ 2)
+
+  [ ventrical ]
+  * unity-session: Recommend zeitgeist-datahub
+
+ -- ventrical <dale_f_beaudoin@hotmail.com>  Mon, 02 Oct 2017 19:56:50 -0400
+
+gnome-session (3.26.0-0ubuntu1) artful; urgency=medium
+
+  [ Didier Roche ]
+  * Add a versioned dependency on GNOME Shell for alternative selection
+    so that we ensure the upstream css is on disk. This allow to remove
+    the || true in postinst.
+
+  [ Iain Lane ]
+  * debian/xdg_dirs_desktop_session.sh: Install a new script into
+    /etc/profile.d to prepend a $DESKTOP_SESSION related directory to
+    $XDG_{CONFIG,DATA}_DIRS. This fixes GNOME Software back to "Ubuntu
+    Software", with the corresponding icon, in the Ubuntu session.
+  * New upstream release.
+
+ -- Iain Lane <iain.lane@canonical.com>  Thu, 14 Sep 2017 17:32:12 +0100
+
 gnome-session (3.25.90-1) unstable; urgency=medium
 
   * New upstream release
@@ -502,6 +1876,38 @@ gnome-session (3.25.90-1) unstable; urge
 
  -- Jeremy Bicha <jbicha@debian.org>  Wed, 06 Sep 2017 22:21:26 -0400
 
+gnome-session (3.25.90-0ubuntu4) artful; urgency=medium
+
+  * Add a || true until GNOME Shell migrates to release pocket. We will
+    then use a versioned dep.
+
+ -- Didier Roche <didrocks@ubuntu.com>  Mon, 11 Sep 2017 12:46:42 +0200
+
+gnome-session (3.25.90-0ubuntu3) artful; urgency=medium
+
+  * Add an alternative to choose gdm upstream GNOME Shell theme. (LP: #1715722)
+
+ -- Didier Roche <didrocks@ubuntu.com>  Mon, 11 Sep 2017 11:54:47 +0200
+
+gnome-session (3.25.90-0ubuntu2) artful; urgency=medium
+
+  * Stop building gnome-session & ubuntu-session for s390x because
+    they depend on uninstallable gnome-shell/gjs (LP: #1712083)
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Sat, 26 Aug 2017 16:08:10 -0400
+
+gnome-session (3.25.90-0ubuntu1) artful; urgency=medium
+
+  * New upstream release
+  * Drop these patches, fixed a different way in new release:
+    - 0001-manager-add-bus-daemon-dbus-api-xml-file.patch
+    - 0002-system-add-api-for-detecting-if-this-is-the-last-ses.patch
+    - 0003-manager-kill-off-bus-clients-at-log-out.patch
+  * Update 50_ubuntu_sessions.patch to follow dropping orientation
+    and xrandr plugins from gnome-settings-daemon 3.25.4
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Mon, 21 Aug 2017 18:23:52 -0400
+
 gnome-session (3.24.1-2) unstable; urgency=medium
 
   * Upload to unstable (Closes: #869947)
@@ -525,12 +1931,312 @@ gnome-session (3.24.1-1) experimental; u
 
  -- Laurent Bigonville <bigon@debian.org>  Thu, 06 Jul 2017 00:25:20 +0200
 
+gnome-session (3.24.1-0ubuntu22) artful; urgency=medium
+
+  * Switch to wayland by default for both ubuntu and GNOME session:
+    - debian/rules: revert removal and renaming of GNOME sessions.
+    - debian/gnome-session.install: ship the GNOME sessions.
+    - debian/patches/50_ubuntu_sessions.patch, debian/ubuntu-session.install:
+      Swap the ubuntu session to wayland. Should fallback ex ubuntu-wayland
+      session users to "ubuntu" as well.
+
+ -- Didier Roche <didrocks@ubuntu.com>  Mon, 21 Aug 2017 14:06:21 +0200
+
+gnome-session (3.24.1-0ubuntu21) artful; urgency=medium
+
+  * Get GNOME Shell session migration handling ubuntu dock keys transition
+    from Unity.
+  * Rename migration script to include months for existing artful users.
+
+ -- Didier Roche <didrocks@ubuntu.com>  Thu, 17 Aug 2017 09:41:05 +0200
+
+gnome-session (3.24.1-0ubuntu20) artful; urgency=medium
+
+  * Add adwaita-icon-theme-full to the gnome session, as more icons like
+    nautilus ones are only located within it.
+
+ -- Didier Roche <didrocks@ubuntu.com>  Tue, 15 Aug 2017 08:58:50 +0200
+
+gnome-session (3.24.1-0ubuntu19) artful; urgency=medium
+
+  * debian/patches/50_ubuntu_sessions.patch:
+    - prepend "ubuntu" to DesktopNames. This will enable us to have per
+      session default experiences and session override.
+    - append "ubuntu" for unity session. Indeed, Unity overrides will be
+      higher in the hierarchy (like button positions) than ubuntu override
+      defaults.
+
+ -- Didier Roche <didrocks@ubuntu.com>  Tue, 15 Aug 2017 08:13:10 +0200
+
+gnome-session (3.24.1-0ubuntu18) artful; urgency=medium
+
+  * Change main ubuntu session to use the ubuntu gnome-shell mode:
+    - enable the mode on logging via env variable so that shell restart
+      reload the mode. This avoid an additional script though contrary
+      to classic.
+    - depends on latest GNOME Shell which provides the mode itself.
+  * Bump Standard-Version to latest
+  * debian/control*:
+    - Fix some lintian warnings
+    - gnome-session recommends fonts-cantarell as default font under
+      the vanilla GNOME Shell experience.
+
+ -- Didier Roche <didrocks@ubuntu.com>  Mon, 14 Aug 2017 09:00:30 +0200
+
+gnome-session (3.24.1-0ubuntu17) artful; urgency=medium
+
+  * debian/unity-gnome-shell-migration.py:
+    Don't migrate to new amazon desktop file, we are using the old
+    one for now for consistency with other desktop renames.
+
+ -- Didier Roche <didrocks@ubuntu.com>  Thu, 20 Jul 2017 09:51:37 +0200
+
+gnome-session (3.24.1-0ubuntu16) artful; urgency=medium
+
+  * Add rhythmbox-plugin-zeitgeist as recommends on *unity-session*
+    it won't be pulled (contrary to zg-core or indicator-application
+    by any other component on unity desktop.
+
+ -- Didier Roche <didrocks@ubuntu.com>  Wed, 19 Jul 2017 14:02:58 +0200
+
+gnome-session (3.24.1-0ubuntu15) artful; urgency=medium
+
+  * Add really the recommends to unity-session and not ubuntu-session,
+    then refill coffee.
+
+ -- Didier Roche <didrocks@ubuntu.com>  Wed, 12 Jul 2017 12:18:30 +0200
+
+gnome-session (3.24.1-0ubuntu14) artful; urgency=medium
+
+  * Actually adding it to recommends. Thanks ricotz for spotting.
+
+ -- Didier Roche <didrocks@ubuntu.com>  Wed, 12 Jul 2017 11:23:39 +0200
+
+gnome-session (3.24.1-0ubuntu13) artful; urgency=medium
+
+  * Add thunderbird-gnome-support recommends to unity-session as now
+    not part of the ubuntu desktop image (mostly unity specific)
+
+ -- Didier Roche <didrocks@ubuntu.com>  Wed, 12 Jul 2017 09:18:17 +0200
+
+gnome-session (3.24.1-0ubuntu12) artful; urgency=medium
+
+  * -debian/ubuntu-session.postinst
+    - Dropped transition script for lightdm->gdm3, it's now handled in gdm3
+
+ -- Ken VanDine <ken.vandine@canonical.com>  Mon, 10 Jul 2017 11:54:50 -0400
+
+gnome-session (3.24.1-0ubuntu11) artful; urgency=medium
+
+  * debian/ubuntu-session.postinst
+    - Check for user's sessions that are set to "ubuntu" and set gdm3
+      as the default display manager as recommended.  This just changes
+      the default in /etc/X11/default-display-manager, it still requires
+      configure from gdm3 to run after configure from ubuntu-session to
+      complete setting the proper default without prompting the user.
+
+ -- Ken VanDine <ken.vandine@canonical.com>  Mon, 03 Jul 2017 14:20:28 -0400
+
+gnome-session (3.24.1-0ubuntu10) artful; urgency=medium
+
+  * debian/unity-gnome-shell-migration.py:
+    u-c-c was actually unity-control-center, not ubuntu-control-center.
+    Changing the key for migration.
+
+ -- Didier Roche <didrocks@ubuntu.com>  Thu, 06 Jul 2017 15:15:14 +0200
+
+gnome-session (3.24.1-0ubuntu9) artful; urgency=medium
+
+  * debian/unity-gnome-shell-migration.py:
+    - migrate launcher icon from ubuntu-control-center to gnome-control-center
+      under GNOME Shell (LP: #1702091)
+
+ -- Didier Roche <didrocks@ubuntu.com>  Mon, 03 Jul 2017 15:23:03 +0200
+
+gnome-session (3.24.1-0ubuntu8) artful; urgency=medium
+
+  * Change ubuntu-session to Arch: any for new xwayland dependency
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Sat, 01 Jul 2017 14:35:17 -0400
+
+gnome-session (3.24.1-0ubuntu7) artful; urgency=medium
+
+  * debian/control.in:
+    - Have ubuntu-session depend on xwayland like gnome-session does
+      Thanks corrado for the report! (LP: #1701822)
+    - Have ubuntu-session and gnome-session depend on gnome-shell.
+      Now that gnome-shell recommends instead of depends on gnome-session |
+      ubuntu-session, there is no circular dependency so let's not diverge
+      from Debian.
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Sat, 01 Jul 2017 13:29:41 -0400
+
+gnome-session (3.24.1-0ubuntu6) artful; urgency=medium
+
+  * Add unity to gnome-shell migration script to ubuntu-session:
+    - Add unity-gnome-shell-migration.py migrating (if g-s has the default):
+      + launcher icons to the dash
+      + amazon to new amazon launcher name migration
+      + reset scale factor for new incoming scale factor algorithm
+    - Use dh-migration to install it.
+
+ -- Didier Roche <didrocks@ubuntu.com>  Wed, 28 Jun 2017 09:19:27 +0200
+
+gnome-session (3.24.1-0ubuntu5) artful; urgency=medium
+
+  * Backport patches from 3.25.3 to kill D-Bus clients on log out.
+    This works around GNOME Online Accounts not working correctly
+    after logging out (LP: #1610944)
+    - 0001-manager-add-bus-daemon-dbus-api-xml-file.patch
+    - 0002-system-add-api-for-detecting-if-this-is-the-last-ses.patch
+    - 0003-manager-kill-off-bus-clients-at-log-out.patch
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Wed, 21 Jun 2017 18:57:12 -0400
+
+gnome-session (3.24.1-0ubuntu4) artful; urgency=medium
+
+  * Add back ubuntu-session, being the default ubuntu experience on
+    GNOME shell:
+    - debian/patches/50_ubuntu_sessions.patch adapt the patch with new session
+      content (right now, similar than vanilla GNOME shell).
+    - debian/ubuntu-session.install, debian/control*: ensure smooth transition
+      for people with ubuntu-session == unity and add the new binary.
+    - debian/data/50-ubuntu.conf: add lightdm conf as long lightdm is the
+      default.
+  * Add a wayland ubuntu session as well alongside the Xorg one:
+    - Ensure we only ship the gnome-wayland session in gnome-session
+      (debian/gnome-session.install)
+    - Add to the patch and install the new session.
+
+ -- Didier Roche <didrocks@ubuntu.com>  Tue, 20 Jun 2017 09:04:29 +0200
+
+gnome-session (3.24.1-0ubuntu3) artful; urgency=medium
+
+  * Rename ubuntu-session into unity-session:
+    - debian/control.in, debian/*install: rename to new binary package name.
+    - modify debian/patches/50_ubuntu_sessions.patch to reference the new
+      session.
+    - debian/data/50-unity.conf: lightdm unity session seat
+    - debian/data/ubuntu-session.target -> debian/data/unity-session.target
+      change systemd user target to start required and wanted components.
+    - add breaks for systemd user session change against other packages,
+      changing targets as well.
+  * Add a new dep from unity-session to unity, otherwise, it wouldn't
+    be installed. It was previously removed for a circular dependency
+    reason.
+
+ -- Didier Roche <didrocks@ubuntu.com>  Mon, 19 Jun 2017 09:45:29 +0200
+
+gnome-session (3.24.1-0ubuntu2) artful; urgency=medium
+
+  * Fix revert_remove_gnome_session_properties.patch
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Sat, 22 Apr 2017 11:38:35 -0400
+
+gnome-session (3.24.1-0ubuntu1) artful; urgency=medium
+
+  * New upstream release (LP: #1685515)
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Sat, 22 Apr 2017 10:16:47 -0400
+
+gnome-session (3.24.0-0ubuntu1) zesty; urgency=medium
+
+  * New upstream release
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Mon, 20 Mar 2017 19:43:33 -0400
+
+gnome-session (3.23.92-0ubuntu1) zesty; urgency=medium
+
+  * New upstream translation release
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Mon, 13 Mar 2017 20:09:34 -0400
+
+gnome-session (3.23.91-0ubuntu1) zesty; urgency=medium
+
+  * New upstream release
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Tue, 28 Feb 2017 20:16:08 -0500
+
+gnome-session (3.23.4.1-0ubuntu2) zesty; urgency=medium
+
+  * debian/patches/50_ubuntu_sessions.patch: Let's have another go at setting
+    XDG_CURRENT_DESKTOP to Unity:Unity7.
+
+ -- Iain Lane <iain.lane@canonical.com>  Thu, 16 Feb 2017 17:48:14 +0000
+
+gnome-session (3.23.4.1-0ubuntu1) zesty; urgency=medium
+
+  * New upstream release
+  * debian/control.in:
+    - Bump minimum gnome-settings-daemon to 3.23.3
+  * Refreshed export_env_to_upstart.patch
+  * Dropped git_wayland_login_shell.patch, applied in new release
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Tue, 07 Feb 2017 18:24:14 -0500
+
 gnome-session (3.22.3-1) unstable; urgency=medium
 
   * New upstream release.
 
  -- Michael Biebl <biebl@debian.org>  Thu, 09 Mar 2017 06:47:00 +0100
 
+gnome-session (3.22.2-2ubuntu1) zesty; urgency=medium
+
+  * Merge with Debian unstable. Remaining changes:
+    - debian/control.in:
+      + Recommend session-migration
+      + Remove gnome-shell circular dependency to ease upgrades
+      + Don't suggest desktop-base
+      + Move xwayland dependency to gnome-session and
+        make gnome-session Arch: any
+    - Split ubuntu-session out of gnome-session.
+    - Add upstart user session and systemd user session:
+      debian/data, debian/gnome-session-bin.user-session.upstart
+    - debian/gnome-session-bin.postinst, debian/gnome-session-bin.prerm:
+       Moved registering gnome-session binary as a session manager to
+       gnome-session-bin package
+    - Add gnome-session-wayland transitional package
+    - don't install gnome-mimeapps.list (installed by desktop-file-utils in
+      Ubuntu):
+      debian/gnome-session-common.dirs, gnome-session-common.install,
+      gnome-session-common.maintscript, gnome-session-common.postinst
+    - debian/patches/revert_remove_gnome_session_properties.patch,
+      debian/patches/revert_remove_gnome_session_properties2.patch:
+      + Keep the session-properties applet for ubuntu sessions
+    - debian/patches/13_display_session_properties.patch: Display
+      session-properties as the Startup Applications capplet was removed from
+      gnome-control-center, which makes it hard to discover the
+      gnome-session-properties tool. (Closes: #683814)
+    - debian/patches/22_support_autostart_delay.patch:
+      Bugzilla patch to support adding a delay to autostart apps, using
+      a "X-GNOME-Autostart-Delay" key in the desktop file
+    - debian/patches/50_ubuntu_sessions.patch, debian/gnome-wayland.desktop:
+      + Add Ubuntu session
+      + Add --session=gnome to GNOME sessions now that the "ubuntu" session
+        is the default. Use TryExec to test if gnome-shell is installed.
+    - debian/patches/51_remove_session_saving_from_gui.patch:
+      add GNOME_SESSION_SAVE environment variable for people wanting to
+      use the save session still, knowing that it can break your system
+      if used unwisely
+    - debian/patches/53_add_sessionmigration.patch:
+      launch session-migration if present at the start of the session. This
+      sync tool runns different session migration scripts that can be
+      provided in various desktop packages.
+    - debian/patches/95_dbus_request_shutdown.patch: Add "RequestShutdown" and
+      "RequestReboot" DBus methods to allow other applications to shutdown or
+      reboot the machine via the session manager.
+    - debian/patches/103_kill_the_fail_whale.patch: Kill the Fail Whale as it
+      tends to be more annoying than helpful
+    - debian/patches/export_env_to_upstart.patch: Update the Upstart environment
+      before the plain D-Bus one. This is to work around a bug where Upstart
+      brokenly forwards variables which contain an "=" to the D-Bus environment,
+      resulting in invalid environment variables in the session (see bug
+      #1630090).
+  * Dropped patch applied in new version:
+    - git_fix_gpu_cache_info.patch
+
+ -- Jeremy Bicha <jbicha@ubuntu.com>  Wed, 01 Feb 2017 05:02:59 -0500
+
 gnome-session (3.22.2-2) unstable; urgency=medium
 
   * Team upload
@@ -601,6 +2307,138 @@ gnome-session (3.21.90-1) experimental;
 
  -- Andreas Henriksson <andreas@fatal.se>  Tue, 23 Aug 2016 12:19:33 +0200
 
+gnome-session (3.20.2-1ubuntu7) yakkety; urgency=medium
+
+  [ Iain Lane ]
+  * debian/patches/export_env_to_upstart.patch: Update the Upstart environment
+    before the plain D-Bus one. This is to work around a bug where Upstart
+    brokenly forwards variables which contain an "=" to the D-Bus environment,
+    resulting in invalid environment variables in the session (see bug
+    #1630090).
+
+  [ Martin Pitt ]
+  * debian/data/ubuntu-session.target: Pull in graphical-session-pre.target,
+    as we do not implicitly do it in run-systemd-session any more.
+
+ -- Martin Pitt <martin.pitt@ubuntu.com>  Tue, 04 Oct 2016 13:16:09 +0200
+
+gnome-session (3.20.2-1ubuntu6) yakkety; urgency=medium
+
+  * Set DesktopNames back to Unity. There are many buggy components that don't
+    know how to deal with XDG_CURRENT_DESKTOP having multiple values, and it's
+    too close to the release to fix them all.
+
+ -- Iain Lane <iain.lane@canonical.com>  Mon, 03 Oct 2016 17:37:57 +0100
+
+gnome-session (3.20.2-1ubuntu5) yakkety; urgency=medium
+
+  * debian/data/run-systemd-session: Drop the polling loops at the start and
+    end of the session and replace them with dynamically generated
+    "After=graphical-session-pre.target". Stopping that target then provides
+    the same waiting using systemd's transactions instead of polling. This is
+    still a workaround until this can be done declaratively, but a much better
+    one.
+  * debian/data/run-systemd-session: Use the new "systemctl start --wait"
+    instead of a polling loop. Bump systemd dependency accordingly.
+
+ -- Martin Pitt <martin.pitt@ubuntu.com>  Sun, 02 Oct 2016 11:38:37 +0200
+
+gnome-session (3.20.2-1ubuntu4) yakkety; urgency=medium
+
+  * debian/data/run-systemd-session: Stop any lingering active units when
+    logging in. (LP: #1618886)
+  * debian/data/gnome-session.service: Save the XDG SESSION we were started
+    with, and only use that one to end the session. Otherwise, if we are
+    stopped by the above codepath, we risk stopping the session that we are
+    logging into and not the previous (crashed) one.
+  * debian/patches/50_ubuntu_sessions.patch: Set the desktop names to
+    Unity:Unity7. "Unity" is shared between Unity 7 and Unity 8, but
+    applications should be able to Only/NotShowIn either one of these if they
+    want.
+
+ -- Iain Lane <iain.lane@canonical.com>  Wed, 28 Sep 2016 12:09:16 +0100
+
+gnome-session (3.20.2-1ubuntu3) yakkety; urgency=medium
+
+  [ Dmitry Shachnev ]
+  * Backport upstream patch to allow users to override $QT_QPA_PLATFORMTHEME
+    (allow_overriding_qt_platformtheme.patch).
+
+  [ Martin Pitt ]
+  * debian/data/run-systemd-session: Add missing $unit to systemctl show call,
+    so that the cleanup of failed units actually works. (LP: #1618886)
+
+ -- Martin Pitt <martin.pitt@ubuntu.com>  Fri, 16 Sep 2016 15:27:56 +0200
+
+gnome-session (3.20.2-1ubuntu2) yakkety; urgency=medium
+
+  * debian/patches/dont_override_IM_variables.patch:
+    - Honor values set by e.g. im-config, and with that give users
+      the option to use fcitx or other framework (LP: #1594681).
+
+ -- Gunnar Hjalmarsson <gunnarhj@ubuntu.com>  Sun, 14 Aug 2016 02:04:00 +0200
+
+gnome-session (3.20.2-1ubuntu1) yakkety; urgency=medium
+
+  [ Tim Lunn ]
+  * Merge from Debian unstable.  Remaining changes (LP: #1512914):
+    - debian/control.in:
+      + Recommend session-migration
+      + Remove gnome-shell circular dep to ease uprades
+    - Split ubuntu-session out of gnome-session.
+    - Split wayland session into gnome-session-wayland
+      + control.in: add gnome-session-wayland package and depend on xwayland
+      + gnome-session-wayland.install: install wayland session
+    - Add upstart user session
+    - debian/gnome-session-bin.postinst, debian/gnome-session-bin.prerm:
+       Moved registering gnome-session binary as a session manager to
+       gnome-session-bin package
+    - don't install defaults.list (installed by desktop-file-utils in ubuntu):
+      debian/gnome-session-common.dirs and gnome-session-common.install
+    - debian/patches/13_display_session_properties.patch: Display
+      session-properties as the Startup Applications capplet was removed from
+      gnome-control-center, which makes it hard to discover the
+      gnome-session-properties tool. (Closes: #683814)
+    - debian/patches/22_support_autostart_delay.patch:
+       Bugzilla patch to support adding a delay to autostart apps, using
+       a "X-GNOME-Autostart-Delay" key in the desktop file
+    - debian/patches/50_ubuntu_sessions.patch:
+       + Add Ubuntu session
+       + gnome-shell.desktop adds --session=gnome now that the "ubuntu" session
+         is the default. Use TryExec to test if gnome-shell is installed.
+    - debian/patches/51_remove_session_saving_from_gui.patch:
+       add GNOME_SESSION_SAVE environment variable for people wanting to
+       use the save session still, knowing that it can break your system
+       if used unwisely
+    - debian/patches/53_add_sessionmigration.patch, debian/control:
+      recommends and launch the session-migration if present at the start of
+      the session. This sync tool is running different session migration
+      scripts that can be provided in various desktop packages.
+    - debian/patches/95_dbus_request_shutdown.patch: Add "RequestShutdown" and
+      "RequestReboot" DBus methods to allow other applications to shutdown or
+      reboot the machine via the session manager.
+    - debian/patches/103_kill_the_fail_whale.patch: Kill the Fail Whale as it
+      tends to be more annoying than helpful
+    - debian/patches/revert_remove_gnome_session_properties.patch: Keep the
+      session-properties applet for ubuntu sessions
+    - debian/patches/Revert-switch-to-Xorg-by-default.patch: Disabled for now,
+      we will keep Xorg as default for the time being
+  * Refresh Patches as Required
+
+  [ Iain Lane ]
+  * Update the merge on top of 3.20.2-1 and 3.18.1.2-1ubuntu5
+    - Add systemd user session support
+  * Adapt our packaging for debhelper instead of cdbs
+  * Move debian/55gnome-session_gnomerc back, to reduce delta with Debian (a
+    previous upload had put it in debian/data).
+  * The previous merge forgot some maintainer script changes (gnome-sesion ->
+    gnome-session-bin) - restore those.
+  * Update patches to add .desktop.in files to POTFILES.skip, which is
+    required now that we run make check by default, which errors on this being
+    missing.
+
+ -- Iain Lane <iain.lane@canonical.com>  Wed, 03 Aug 2016 14:54:08 +0100
+
 gnome-session (3.20.2-1) unstable; urgency=medium
 
   * New upstream release.
@@ -684,6 +2522,89 @@ gnome-session (3.19.92-1) experimental;
 
  -- Andreas Henriksson <andreas@fatal.se>  Tue, 15 Mar 2016 21:05:23 +0100
 
+gnome-session (3.18.1.2-1ubuntu5) yakkety; urgency=medium
+
+  * 50_ubuntu_sessions.patch: Go back to a systemd-ified Exec= line and add a
+    Breaks: for the upstart versions that don't yet have the necessary
+    Xsession.d fixes yet.
+  * debian/data/run-systemd-session: Robustify session startup and shutdown.
+  * debian/data/ubuntu-session.target: Fix description.
+  * ubuntu-session: Depend on dbus-user-session and the systemd version that
+    provides graphical-session.target.
+  * debian/data/gnome-session.override: Don't completely disable this yet,
+    only disable "exec" script. The upstart job still needs to run as a stub
+    to start dependencies until the conversion of unity units lands.
+
+ -- Martin Pitt <martin.pitt@ubuntu.com>  Sun, 31 Jul 2016 11:22:57 +0200
+
+gnome-session (3.18.1.2-1ubuntu4) yakkety; urgency=medium
+
+  * 50_ubuntu_sessions.patch: Revert to directly running gnome-session again.
+    Something seems to actually look at the value of Exec= even with upstart
+    which breaks starting the session.
+
+ -- Martin Pitt <martin.pitt@ubuntu.com>  Tue, 19 Jul 2016 08:46:10 +0200
+
+gnome-session (3.18.1.2-1ubuntu3) yakkety; urgency=medium
+
+  * Move 50-ubuntu.conf and 55gnome-session_gnomerc into debian/data/.
+  * Add systemd units for gnome-session-bin and a systemd user
+    ubuntu-session.target.
+
+ -- Martin Pitt <martin.pitt@ubuntu.com>  Mon, 18 Jul 2016 17:41:31 +0200
+
+gnome-session (3.18.1.2-1ubuntu2) yakkety; urgency=medium
+
+  * debian/patches/export_env_to_upstart.patch:
+    - Export environment variables to upstart as well, if available (LP: #1433013)
+
+ -- Marco Trevisan (Treviño) <marco@ubuntu.com>  Thu, 12 May 2016 14:44:19 +0100
+
+gnome-session (3.18.1.2-1ubuntu1) xenial; urgency=medium
+
+  * Merge from Debian unstable.  Remaining changes (LP: #1512914):
+    - debian/control.in:
+      + Recommend session-migration
+      + Remove gnome-shell circular dep to ease uprades
+    - Split ubuntu-session out of gnome-session.
+    - Split wayland session into gnome-session-wayland
+      + control.in: add gnome-session-wayland package and depend on xwayland
+      + gnome-session-wayland.install: install wayland session
+    - Add upstart user session
+    - debian/gnome-session-bin.postinst, debian/gnome-session-bin.prerm:
+       Moved registering gnome-session binary as a session manager to
+       gnome-session-bin package
+    - don't install defaults.list (installed by desktop-file-utils in ubuntu):
+      debian/gnome-session-common.dirs and gnome-session-common.install
+    - debian/patches/13_display_session_properties.patch: Display
+      session-properties as the Startup Applications capplet was removed from
+      gnome-control-center, which makes it hard to discover the
+      gnome-session-properties tool. (Closes: #683814)
+    - debian/patches/22_support_autostart_delay.patch:
+       Bugzilla patch to support adding a delay to autostart apps, using
+       a "X-GNOME-Autostart-Delay" key in the desktop file
+    - debian/patches/50_ubuntu_sessions.patch:
+       + Add Ubuntu session
+       + gnome-shell.desktop adds --session=gnome now that the "ubuntu" session
+         is the default. Use TryExec to test if gnome-shell is installed.
+    - debian/patches/51_remove_session_saving_from_gui.patch:
+       add GNOME_SESSION_SAVE environment variable for people wanting to
+       use the save session still, knowing that it can break your system
+       if used unwisely
+    - debian/patches/53_add_sessionmigration.patch, debian/control:
+      recommends and launch the session-migration if present at the start of
+      the session. This sync tool is running different session migration
+      scripts that can be provided in various desktop packages.
+    - debian/patches/95_dbus_request_shutdown.patch: Add "RequestShutdown" and
+      "RequestReboot" DBus methods to allow other applications to shutdown or
+      reboot the machine via the session manager.
+    - debian/patches/103_kill_the_fail_whale.patch: Kill the Fail Whale as it
+      tends to be more annoying than helpful
+    - debian/patches/revert_remove_gnome_session_properties.patch: Keep the
+      session-properties applet for ubuntu sessions
+
+ -- Tim Lunn <tim@feathertop.org>  Thu, 12 Nov 2015 10:32:51 +1100
+
 gnome-session (3.18.1.2-1) unstable; urgency=medium
 
   * New upstream release.
diff -pruN 43.0-1/debian/control 43.0-1ubuntu2/debian/control
--- 43.0-1/debian/control	2022-10-11 18:08:35.000000000 +0000
+++ 43.0-1ubuntu2/debian/control	2022-10-13 11:13:51.000000000 +0000
@@ -5,10 +5,12 @@
 Source: gnome-session
 Section: gnome
 Priority: optional
-Maintainer: Debian GNOME Maintainers <pkg-gnome-maintainers@lists.alioth.debian.org>
+Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
+XSBC-Original-Maintainer: Debian GNOME Maintainers <pkg-gnome-maintainers@lists.alioth.debian.org>
 Uploaders: Iain Lane <laney@debian.org>, Jeremy Bicha <jbicha@ubuntu.com>, Laurent Bigonville <bigon@debian.org>
 Build-Depends: debhelper-compat (= 13),
                dh-exec,
+               dh-migrations,
                dh-sequence-gnome,
                libdbus-1-dev,
                libgl-dev,
@@ -34,8 +36,10 @@ Build-Depends: debhelper-compat (= 13),
                xtrans-dev
 Rules-Requires-Root: no
 Standards-Version: 4.6.0
-Vcs-Browser: https://salsa.debian.org/gnome-team/gnome-session
-Vcs-Git: https://salsa.debian.org/gnome-team/gnome-session.git
+XS-Debian-Vcs-Git: https://salsa.debian.org/gnome-team/gnome-session.git
+XS-Debian-Vcs-Browser: https://salsa.debian.org/gnome-team/gnome-session
+Vcs-Git: https://salsa.debian.org/gnome-team/gnome-session.git -b ubuntu/master
+Vcs-Browser: https://salsa.debian.org/gnome-team/gnome-session/tree/ubuntu/master
 
 Package: gnome-session
 Architecture: all
@@ -45,12 +49,15 @@ Depends: gnome-session-bin (<< ${gnome:N
          gnome-settings-daemon (>= 3.37.0),
          gnome-shell (>= 3.37.91),
          xdg-desktop-portal-gnome | xdg-desktop-portal-backend,
+         xwayland,
          ${misc:Depends}
 Suggests: desktop-base,
           gnome-keyring
 Breaks: gnome-initial-setup (<< 3.37.90),
-        gnome-session-bin (<< 3.37.0-2~)
-Replaces: gnome-session-bin (<< 3.37.0-2~)
+        gnome-session-bin (<< 3.37.0-2~),
+        ubuntu-session (<= 3.29.90-1ubuntu1)
+Replaces: gnome-session-bin (<< 3.37.0-2~),
+          ubuntu-session (<= 3.29.90-1ubuntu1)
 Provides: x-session-manager
 Description: GNOME Session Manager - GNOME 3 session
  The GNOME Session Manager is in charge of starting the core components
@@ -62,15 +69,81 @@ Description: GNOME Session Manager - GNO
  session, based on the GNOME Shell. It can be started from a display
  manager such as GDM, and requires 3D acceleration to work properly.
 
+Package: gnome-startup-applications
+Architecture: any
+Depends: gnome-session-bin (>= ${binary:Version}),
+         gnome-session-common (>= ${source:Version}),
+         ${misc:Depends}
+Breaks: gnome-session-bin (<< 3.28.0-0ubuntu4~),
+        gnome-session-common (<< 3.28.0-0ubuntu4~)
+Replaces: gnome-session-bin (<< 3.28.0-0ubuntu4~),
+          gnome-session-common (<< 3.28.0-0ubuntu4~)
+Description: Startup Applications manager for GNOME
+ The Startup Applications Preferences app allows configuring
+ applications to run automatically when logging in to your desktop.
+ This app complies with the FreeDesktop.org Desktop Application Autostart
+ Specification so it will work even if your chosen desktop is not GNOME.
+
+Package: ubuntu-session
+Architecture: all
+Depends: gnome-session-bin (<< ${gnome:NextVersion}),
+         gnome-session-bin (>= ${binary:Version}),
+         gnome-session-common (= ${binary:Version}),
+         gnome-settings-daemon (>= 3.37.0),
+         gnome-shell (>= 3.37.91),
+         xdg-desktop-portal-gnome | xdg-desktop-portal-backend,
+         xwayland,
+         yaru-theme-gnome-shell (>= 20.04.3~),
+         ${misc:Depends}
+Recommends: python3,
+            session-migration
+Breaks: gnome-session (<= 3.29.90-1ubuntu1),
+        hud (<< 14.10+17.10.20170619),
+        unity (<< 7.5.0+17.10.20170619),
+        unity-gtk-module (<< 0.0.0+17.04.20170918),
+        unity-settings-daemon (<< 15.04.1+17.04.20170619)
+Replaces: gnome-session (<= 3.29.90-1ubuntu1)
+Provides: x-session-manager
+Description: Ubuntu session with GNOME Shell
+ This package contains the required components for running a GNOME 3 session
+ with default Ubuntu configuration, based on the GNOME Shell.
+
+Package: unity-session
+Architecture: all
+Depends: dbus-user-session,
+         gnome-session-bin (<< ${gnome:NextVersion}),
+         gnome-session-bin (>= ${binary:Version}),
+         gnome-session-common (= ${binary:Version}),
+         systemd (>= 231-9git1~),
+         unity,
+         unity-settings-daemon,
+         ${misc:Depends}
+Recommends: gtk3-nocsd,
+            rhythmbox-plugin-zeitgeist,
+            session-migration,
+            thunderbird-gnome-support,
+            zeitgeist-datahub
+Provides: x-session-manager
+Breaks: hud (<< 14.10+17.10.20170619),
+        unity (<< 7.5.0+17.10.20170619),
+        unity-gtk-module (<< 0.0.0+17.04.20170918),
+        unity-settings-daemon (<< 15.04.1+17.04.20170619),
+        gnome-session-bin (<< 3.37.0-2ubuntu1~)
+Replaces: ubuntu-session (<< 3.24.1-0ubuntu2),
+          gnome-session-bin (<< 3.37.0-2ubuntu1~)
+Description: Unity session, previous ubuntu default experience.
+ This package contains the required components for the Unity session.
+ It can be started from a display manager such as LightDM.
+
 Package: gnome-session-bin
 Architecture: any
 Depends: default-dbus-session-bus | dbus-session-bus,
          gsettings-desktop-schemas,
          upower (>= 0.9.0),
-         xwayland [linux-any],
          ${misc:Depends},
          ${shlibs:Depends}
-Recommends: default-logind [linux-any] | logind [linux-any]
+Recommends: gnome-startup-applications,
+            default-logind [linux-any] | logind [linux-any]
 Breaks: gdm3 (<< 3.37.90)
 Description: GNOME Session Manager - Minimal runtime
  The GNOME Session Manager is in charge of starting the core components
diff -pruN 43.0-1/debian/control.in 43.0-1ubuntu2/debian/control.in
--- 43.0-1/debian/control.in	2022-10-11 18:08:35.000000000 +0000
+++ 43.0-1ubuntu2/debian/control.in	2022-10-13 11:13:51.000000000 +0000
@@ -1,10 +1,12 @@
 Source: gnome-session
 Section: gnome
 Priority: optional
-Maintainer: Debian GNOME Maintainers <pkg-gnome-maintainers@lists.alioth.debian.org>
+Maintainer: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
+XSBC-Original-Maintainer: Debian GNOME Maintainers <pkg-gnome-maintainers@lists.alioth.debian.org>
 Uploaders: @GNOME_TEAM@
 Build-Depends: debhelper-compat (= 13),
                dh-exec,
+               dh-migrations,
                dh-sequence-gnome,
                libdbus-1-dev,
                libgl-dev,
@@ -30,8 +32,10 @@ Build-Depends: debhelper-compat (= 13),
                xtrans-dev
 Rules-Requires-Root: no
 Standards-Version: 4.6.0
-Vcs-Browser: https://salsa.debian.org/gnome-team/gnome-session
-Vcs-Git: https://salsa.debian.org/gnome-team/gnome-session.git
+XS-Debian-Vcs-Git: https://salsa.debian.org/gnome-team/gnome-session.git
+XS-Debian-Vcs-Browser: https://salsa.debian.org/gnome-team/gnome-session
+Vcs-Git: https://salsa.debian.org/gnome-team/gnome-session.git -b ubuntu/master
+Vcs-Browser: https://salsa.debian.org/gnome-team/gnome-session/tree/ubuntu/master
 
 Package: gnome-session
 Architecture: all
@@ -41,12 +45,15 @@ Depends: gnome-session-bin (<< ${gnome:N
          gnome-settings-daemon (>= 3.37.0),
          gnome-shell (>= 3.37.91),
          xdg-desktop-portal-gnome | xdg-desktop-portal-backend,
+         xwayland,
          ${misc:Depends}
 Suggests: desktop-base,
           gnome-keyring
 Breaks: gnome-initial-setup (<< 3.37.90),
-        gnome-session-bin (<< 3.37.0-2~)
-Replaces: gnome-session-bin (<< 3.37.0-2~)
+        gnome-session-bin (<< 3.37.0-2~),
+        ubuntu-session (<= 3.29.90-1ubuntu1)
+Replaces: gnome-session-bin (<< 3.37.0-2~),
+          ubuntu-session (<= 3.29.90-1ubuntu1)
 Provides: x-session-manager
 Description: GNOME Session Manager - GNOME 3 session
  The GNOME Session Manager is in charge of starting the core components
@@ -58,15 +65,81 @@ Description: GNOME Session Manager - GNO
  session, based on the GNOME Shell. It can be started from a display
  manager such as GDM, and requires 3D acceleration to work properly.
 
+Package: gnome-startup-applications
+Architecture: any
+Depends: gnome-session-bin (>= ${binary:Version}),
+         gnome-session-common (>= ${source:Version}),
+         ${misc:Depends}
+Breaks: gnome-session-bin (<< 3.28.0-0ubuntu4~),
+        gnome-session-common (<< 3.28.0-0ubuntu4~)
+Replaces: gnome-session-bin (<< 3.28.0-0ubuntu4~),
+          gnome-session-common (<< 3.28.0-0ubuntu4~)
+Description: Startup Applications manager for GNOME
+ The Startup Applications Preferences app allows configuring
+ applications to run automatically when logging in to your desktop.
+ This app complies with the FreeDesktop.org Desktop Application Autostart
+ Specification so it will work even if your chosen desktop is not GNOME.
+
+Package: ubuntu-session
+Architecture: all
+Depends: gnome-session-bin (<< ${gnome:NextVersion}),
+         gnome-session-bin (>= ${binary:Version}),
+         gnome-session-common (= ${binary:Version}),
+         gnome-settings-daemon (>= 3.37.0),
+         gnome-shell (>= 3.37.91),
+         xdg-desktop-portal-gnome | xdg-desktop-portal-backend,
+         xwayland,
+         yaru-theme-gnome-shell (>= 20.04.3~),
+         ${misc:Depends}
+Recommends: python3,
+            session-migration
+Breaks: gnome-session (<= 3.29.90-1ubuntu1),
+        hud (<< 14.10+17.10.20170619),
+        unity (<< 7.5.0+17.10.20170619),
+        unity-gtk-module (<< 0.0.0+17.04.20170918),
+        unity-settings-daemon (<< 15.04.1+17.04.20170619)
+Replaces: gnome-session (<= 3.29.90-1ubuntu1)
+Provides: x-session-manager
+Description: Ubuntu session with GNOME Shell
+ This package contains the required components for running a GNOME 3 session
+ with default Ubuntu configuration, based on the GNOME Shell.
+
+Package: unity-session
+Architecture: all
+Depends: dbus-user-session,
+         gnome-session-bin (<< ${gnome:NextVersion}),
+         gnome-session-bin (>= ${binary:Version}),
+         gnome-session-common (= ${binary:Version}),
+         systemd (>= 231-9git1~),
+         unity,
+         unity-settings-daemon,
+         ${misc:Depends}
+Recommends: gtk3-nocsd,
+            rhythmbox-plugin-zeitgeist,
+            session-migration,
+            thunderbird-gnome-support,
+            zeitgeist-datahub
+Provides: x-session-manager
+Breaks: hud (<< 14.10+17.10.20170619),
+        unity (<< 7.5.0+17.10.20170619),
+        unity-gtk-module (<< 0.0.0+17.04.20170918),
+        unity-settings-daemon (<< 15.04.1+17.04.20170619),
+        gnome-session-bin (<< 3.37.0-2ubuntu1~)
+Replaces: ubuntu-session (<< 3.24.1-0ubuntu2),
+          gnome-session-bin (<< 3.37.0-2ubuntu1~)
+Description: Unity session, previous ubuntu default experience.
+ This package contains the required components for the Unity session.
+ It can be started from a display manager such as LightDM.
+
 Package: gnome-session-bin
 Architecture: any
 Depends: default-dbus-session-bus | dbus-session-bus,
          gsettings-desktop-schemas,
          upower (>= 0.9.0),
-         xwayland [linux-any],
          ${misc:Depends},
          ${shlibs:Depends}
-Recommends: default-logind [linux-any] | logind [linux-any]
+Recommends: gnome-startup-applications,
+            default-logind [linux-any] | logind [linux-any]
 Breaks: gdm3 (<< 3.37.90)
 Description: GNOME Session Manager - Minimal runtime
  The GNOME Session Manager is in charge of starting the core components
diff -pruN 43.0-1/debian/data/50-ubuntu.conf 43.0-1ubuntu2/debian/data/50-ubuntu.conf
--- 43.0-1/debian/data/50-ubuntu.conf	1970-01-01 00:00:00.000000000 +0000
+++ 43.0-1ubuntu2/debian/data/50-ubuntu.conf	2022-10-13 11:13:51.000000000 +0000
@@ -0,0 +1,2 @@
+[Seat:*]
+user-session=ubuntu
diff -pruN 43.0-1/debian/data/50-unity.conf 43.0-1ubuntu2/debian/data/50-unity.conf
--- 43.0-1/debian/data/50-unity.conf	1970-01-01 00:00:00.000000000 +0000
+++ 43.0-1ubuntu2/debian/data/50-unity.conf	2022-10-13 11:13:51.000000000 +0000
@@ -0,0 +1,2 @@
+[Seat:*]
+user-session=unity
diff -pruN 43.0-1/debian/data/change-background-unity.nemo_action 43.0-1ubuntu2/debian/data/change-background-unity.nemo_action
--- 43.0-1/debian/data/change-background-unity.nemo_action	1970-01-01 00:00:00.000000000 +0000
+++ 43.0-1ubuntu2/debian/data/change-background-unity.nemo_action	2022-10-13 11:13:51.000000000 +0000
@@ -0,0 +1,82 @@
+[Nemo Action]
+
+Name=Change Desktop _Background
+
+Comment=Change the Unity desktop background
+
+Exec=unity-control-center appearance
+
+Selection=None
+
+Icon-Name=cs-backgrounds-symbolic
+
+Extensions=any;
+
+
+Conditions=desktop;dbus com.canonical.Unity
+
+Name[jv]=Ganti Gambar _Buri Desktop
+Name[pt_BR]=Alterar _plano de fundo
+Name[ia]=Cambiar le fundo (_Background) del scriptorio
+Name[ko]=바탕화면 배경 바꾸기(_B)
+Name[kk]=Ф_он суретін ауыстыру
+Name[af]=Verander Werkskerm Agtergrond
+Name[el]=Αλλαγή _εικόνας επιφάνειας εργασίας
+Name[fr_CA]=Modifier l’arrière-plan du _bureau
+Name[ro]=Schim_bă imaginea de fundal
+Name[da]=Skift skrive_bordsbaggrund
+Name[gl]=Cambiar o _fondo do escritorio
+Name[vi]=Đổi Ảnh _nền Màn hình
+Name[ca]=Canvia el _fons de l'escriptori
+Name[de]=_Hintergrund des Schreibtisches ändern
+Name[sr@latin]=Iz_meni pozadinu
+Name[he]=שנה את _רקע שולחן העבודה
+Name[fr]=Modifier l'arrière-plan du _bureau
+Name[ga]=Athraigh Cúlra_na Deisce
+Name[bs]=Promijeni _pozadinu desktopa
+Name[id]=Ubah Latar _Belakang Desktop
+Name[sl]=Spremeni _ozadje namizja
+Name[sv]=Byt skrivbordsbak_grund
+Name[tg]=Тағйир додани пасзаминаи _мизи корӣ
+Name[sq]=Ndrysho _sfondin e desktopit
+Name[hu]=Asztal _hátterének módosítása
+Name[fi]=Muuta työpöydän _taustaa
+Name[ar]=تغيير خلفية _سطح المكتب
+Name[en_AU]=Change Desktop _Background
+Name[th]=_เปลี่ยนพื้นหลังของพื้นโต๊ะ
+Name[ku]=Zemîna Sermaseyê Biguherîne
+Name[ru]=Изменить _фон рабочего стола
+Name[bg]=Промяна на _фона
+Name[is]=Breyta _bakgrunni skjáborðs
+Name[oc]=Modificar lo _rèire plan del burèu
+Name[ur]=ڈیسک ٹاپ کا _پس منظر بدلیں
+Name[gd]=Atharraich _cùlaibh an desktop
+Name[sk]=Zmeniť _pozadie plochy
+Name[zh_TW]=變更桌面背景(_B)
+Name[zh_HK]=變更桌面背景(_B)
+Name[be]=Змяніць _фон працоўнага стала
+Name[en_GB]=Change Desktop _Background
+Name[et]=Vaheta töölaua _taust
+Name[hr]=Promijeni pozadinu _radne površine
+Name[cy]=Newid Cefndir y _Bwrdd Gwaith
+Name[ta]=(_B)பணிமேடை பின்னனியை மாற்று
+Name[eu]=Aldatu _mahaigainaren atzeko planoa
+Name[lt]=Keisti darbalaukio _foną
+Name[uk]=Змінити ф_он стільниці
+Name[ja]=背景を変更 (_B)
+Name[ast]=Camudar el fon_du d'escritoriu
+Name[ml]=ഡെസ്ക്ടോപ്പിന്റെ _പശ്ചാത്തലം മാറ്റുക
+Name[bn]=ডেস্কটপের পটভূমি পরিবর্তন করুন (_B)
+Name[sr]=Из_мени позадину
+Name[zh_CN]=更改桌面背景(_B)
+Name[it]=Ca_mbia sfondo desktop
+Name[ms]=Tukar Latar _Belakang Desktop
+Name[tr]=Masaüstü _Arkaplanını Değiştir
+Name[pt]=Alterar _fundo da área de trabalho
+Name[es]=Cambiar el _fondo del escritorio
+Name[pl]=Zmień _tło pulpitu
+Name[am]=የዴስክቶፕ _መደብ መቀየሪያ
+Name[nb]=Endre skrivebords_bakgrunn
+Name[cs]=Změnit _pozadí plochy
+Name[nl]=Werk_bladachtergrond wijzigen
+Name[nds]=Desktop_Hintergrund ändern
diff -pruN 43.0-1/debian/data/gnome-session.service 43.0-1ubuntu2/debian/data/gnome-session.service
--- 43.0-1/debian/data/gnome-session.service	1970-01-01 00:00:00.000000000 +0000
+++ 43.0-1ubuntu2/debian/data/gnome-session.service	2022-10-13 11:13:51.000000000 +0000
@@ -0,0 +1,10 @@
+[Unit]
+Description=GNOME Session Manager (Ubuntu downstream version for Unity support)
+PartOf=graphical-session.target
+
+[Service]
+ExecStart=/bin/sh -exc '[ "$DESKTOP_SESSION" != "gnome-classic" ] || export GNOME_SHELL_SESSION_MODE=classic; \
+    export GNOME_SESSION_XDG_SESSION_PATH=${XDG_SESSION_PATH}; \
+    [ "$DESKTOP_SESSION" = gnome-flashback-metacity ] && \
+        exec gnome-session --builtin --session=$DESKTOP_SESSION --disable-acceleration-check || \
+        exec gnome-session --builtin --session=$DESKTOP_SESSION'
diff -pruN 43.0-1/debian/data/nemo-unity-autostart.desktop 43.0-1ubuntu2/debian/data/nemo-unity-autostart.desktop
--- 43.0-1/debian/data/nemo-unity-autostart.desktop	1970-01-01 00:00:00.000000000 +0000
+++ 43.0-1ubuntu2/debian/data/nemo-unity-autostart.desktop	2022-10-13 11:13:51.000000000 +0000
@@ -0,0 +1,10 @@
+[Desktop Entry]
+Type=Application
+Name=Nemo
+Comment=Start Nemo desktop at log in
+Exec=nemo-desktop
+OnlyShowIn=Unity;
+AutostartCondition=GSettings org.nemo.desktop show-desktop-icons
+X-GNOME-AutoRestart=true
+X-GNOME-Autostart-Delay=2
+NoDisplay=false
diff -pruN 43.0-1/debian/data/run-systemd-session 43.0-1ubuntu2/debian/data/run-systemd-session
--- 43.0-1/debian/data/run-systemd-session	1970-01-01 00:00:00.000000000 +0000
+++ 43.0-1ubuntu2/debian/data/run-systemd-session	2022-10-13 11:13:51.000000000 +0000
@@ -0,0 +1,37 @@
+#!/bin/sh
+set -e
+
+# some old Qt programs still check this long-deprecated env var
+dbus-update-activation-environment --systemd GNOME_DESKTOP_SESSION_ID=this-is-deprecated
+
+# stop any lingering active units from a previous session
+systemctl --user stop graphical-session.target graphical-session-pre.target
+
+# robustness: if the previous graphical session left some failed units,
+# reset them so that they don't break this startup
+for unit in $(systemctl --user --no-legend --state=failed list-units | cut -f1 -d' '); do
+    if [ "$(systemctl --user show -p PartOf --value $unit)" = "graphical-session.target" ]; then
+        systemctl --user reset-failed $unit
+    fi
+done
+
+# FIXME: synthesize After=graphical-session-pre.target dependencies until this
+# can be done declaratively (https://github.com/systemd/systemd/issues/3750)
+# This could be a generator, but we don't want to penalize non-graphical logins
+# with this.
+systemctl --user list-unit-files --no-legend | while read unit status _; do
+    [ "${unit%.service}" != "$unit" ] || continue
+    [ "$status" != "$disabled" ] || continue
+    if [ "$(systemctl --user show -p PartOf --value $unit)" = "graphical-session.target" ]; then
+        mkdir -p "$XDG_RUNTIME_DIR/systemd/user/${unit}.d"
+        printf '[Unit]\nAfter=graphical-session-pre.target\n' > "$XDG_RUNTIME_DIR/systemd/user/${unit}.d/graphical-session-pre.conf"
+    fi
+done
+systemctl --user daemon-reload
+
+systemctl --user start --wait "$1"
+
+dbus-update-activation-environment --systemd GNOME_DESKTOP_SESSION_ID=
+
+# Delay killing the X server until all graphical units stopped
+systemctl --user stop graphical-session-pre.target
diff -pruN 43.0-1/debian/data/set-as-background-unity.nemo_action 43.0-1ubuntu2/debian/data/set-as-background-unity.nemo_action
--- 43.0-1/debian/data/set-as-background-unity.nemo_action	1970-01-01 00:00:00.000000000 +0000
+++ 43.0-1ubuntu2/debian/data/set-as-background-unity.nemo_action	2022-10-13 11:13:51.000000000 +0000
@@ -0,0 +1,68 @@
+[Nemo Action]
+
+Name=Set as Wallpaper...
+
+Comment=Set the selected image as your Unity desktop wallpaper
+
+Exec=gsettings set org.gnome.desktop.background picture-uri "%U"
+
+Selection=s
+
+Mimetypes=image/*;
+
+Conditions=dbus com.canonical.Unity;
+Name[pt_BR]=Definir como plano de fundo...
+Name[ia]=Fixar como tapete de papiro...
+Name[ko]=배경화면으로 설정하기...
+Name[el]=Ορισμός ως Ταπετσαρίας...
+Name[fr_CA]=Définir en tant que fond d’écran...
+Name[ro]=Setează ca imagine de fundal...
+Name[da]=Anvend som baggrund …
+Name[gl]=Estabelecer como fondo de pantalla
+Name[vi]=Đặt làm Hình nền...
+Name[ca]=Estableix com a fons de pantalla...
+Name[de]=Als Hintergrund festlegen …
+Name[sr@latin]=Postavi kao pozadinu...
+Name[he]=הגדרה כרקע...
+Name[fr]=Définir en tant que fond d'écran...
+Name[ga]=Socraigh mar Cúlra na Deisce
+Name[bs]=Postavi kao pozadinu...
+Name[id]=Pasang sebagai Wallpaper...
+Name[sl]=Nastavi kot sliko ozadja ...
+Name[sv]=Ange som skrivbordsbakgrund...
+Name[tg]=Танзим кардан ҳамчун тасвири экран...
+Name[hu]=Beállítás háttérképként…
+Name[fi]=Aseta taustakuvaksi...
+Name[ar]=تعيين كخلفية...
+Name[th]=ตั้งเป็นภาพพื้นหลัง...
+Name[ru]=Сделать фоном...
+Name[bg]=Задаване като тапет...
+Name[is]=Gera að veggfóðri...
+Name[ur]=بطور وال پیپر سیٹ کریں...
+Name[gd]=Suidhich mar phàipear-balla...
+Name[sk]=Nastaviť ako pozadie...
+Name[zh_TW]=設為桌布...
+Name[zh_HK]=設為桌布...
+Name[be]=Ўсталяваць у якасці фонавага малюнка...
+Name[en_GB]=Set as Wallpaper...
+Name[et]=Määra taustapildiks...
+Name[hr]=Postavi kao pozadinu...
+Name[cy]=Gosod fel Papur Wal...
+Name[eu]=Ezarri atzeko plano gisa...
+Name[lt]=Nustatyti kaip darbalaukio foną
+Name[uk]=Встановити як фон...
+Name[ja]=壁紙に設定...
+Name[ast]=Afitar como fondu pantalla...
+Name[ml]=പശ്ചാത്തലചിത്രമായി സജ്ജീകരിക്കുക...
+Name[sr]=Постави као позадину...
+Name[zh_CN]=设置为壁纸...
+Name[it]=Imposta come sfondo...
+Name[ms]=Tetapkan sebagai Kertas Dinding...
+Name[tr]=Duvarkağıdı olarak ayarla...
+Name[pt]=Definir como fundo do Ambiente de Trabalho
+Name[es]=Establecer como fondo...
+Name[pl]=Ustaw jako tło pulpitu...
+Name[am]=እንደ ግድግዳ ወረቀት ማሰናጃ...
+Name[nb]=Sett som bakgrunn...
+Name[cs]=Nastavit jako pozadí plochy…
+Name[nl]=Gebruik als bureaubladachtergrond...
diff -pruN 43.0-1/debian/data/unity-session.target 43.0-1ubuntu2/debian/data/unity-session.target
--- 43.0-1/debian/data/unity-session.target	1970-01-01 00:00:00.000000000 +0000
+++ 43.0-1ubuntu2/debian/data/unity-session.target	2022-10-13 11:13:51.000000000 +0000
@@ -0,0 +1,7 @@
+[Unit]
+Description=User systemd services for the Unity graphical session
+Requires=graphical-session-pre.target
+# start/tear down graphical-session.target along with the ubuntu session
+BindsTo=graphical-session.target
+# session leader -- if this dies, die along with it
+BindsTo=gnome-session.service
diff -pruN 43.0-1/debian/gbp.conf 43.0-1ubuntu2/debian/gbp.conf
--- 43.0-1/debian/gbp.conf	2022-10-11 18:08:35.000000000 +0000
+++ 43.0-1ubuntu2/debian/gbp.conf	2022-10-13 11:13:51.000000000 +0000
@@ -1,7 +1,9 @@
 [DEFAULT]
 pristine-tar = True
-debian-branch = debian/master
+debian-branch=ubuntu/master
 upstream-branch = upstream/latest
+debian-tag=ubuntu/%(version)s
+upstream-vcs-tag = %(version)s
 
 [buildpackage]
 sign-tags = True
diff -pruN 43.0-1/debian/gnome-session-bin.install 43.0-1ubuntu2/debian/gnome-session-bin.install
--- 43.0-1/debian/gnome-session-bin.install	2022-10-11 18:08:35.000000000 +0000
+++ 43.0-1ubuntu2/debian/gnome-session-bin.install	2022-10-13 11:13:51.000000000 +0000
@@ -1,6 +1,11 @@
-usr/bin/gnome-session*
+usr/bin/gnome-session
+usr/bin/gnome-session-inhibit
+usr/bin/gnome-session-quit
 usr/libexec
 usr/share/gnome-session/hardware-compatibility
-usr/share/man/man1
+usr/share/man/man1/gnome-session.1*
+usr/share/man/man1/gnome-session-inhibit*
+usr/share/man/man1/gnome-session-quit*
 usr/share/glib-2.0/schemas
 usr/share/GConf/gsettings
+debian/data/run-systemd-session usr/libexec/
diff -pruN 43.0-1/debian/gnome-session-bin.links 43.0-1ubuntu2/debian/gnome-session-bin.links
--- 43.0-1/debian/gnome-session-bin.links	1970-01-01 00:00:00.000000000 +0000
+++ 43.0-1ubuntu2/debian/gnome-session-bin.links	2022-10-13 11:13:51.000000000 +0000
@@ -0,0 +1 @@
+/usr/libexec/run-systemd-session /usr/lib/gnome-session/run-systemd-session
diff -pruN 43.0-1/debian/gnome-session-bin.postinst 43.0-1ubuntu2/debian/gnome-session-bin.postinst
--- 43.0-1/debian/gnome-session-bin.postinst	1970-01-01 00:00:00.000000000 +0000
+++ 43.0-1ubuntu2/debian/gnome-session-bin.postinst	2022-10-13 11:13:51.000000000 +0000
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+set -e
+
+if [ "$1" = configure ]; then
+  update-alternatives --install /usr/bin/x-session-manager \
+    x-session-manager /usr/bin/gnome-session 50 \
+    --slave /usr/share/man/man1/x-session-manager.1.gz \
+    x-session-manager.1.gz /usr/share/man/man1/gnome-session.1.gz
+fi
+
+#DEBHELPER#
diff -pruN 43.0-1/debian/gnome-session-bin.prerm 43.0-1ubuntu2/debian/gnome-session-bin.prerm
--- 43.0-1/debian/gnome-session-bin.prerm	1970-01-01 00:00:00.000000000 +0000
+++ 43.0-1ubuntu2/debian/gnome-session-bin.prerm	2022-10-13 11:13:51.000000000 +0000
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+set -e
+
+if [ "$1" = "remove" ]; then
+  update-alternatives --remove x-session-manager /usr/bin/gnome-session
+fi
+
+#DEBHELPER#
diff -pruN 43.0-1/debian/gnome-session-common.install 43.0-1ubuntu2/debian/gnome-session-common.install
--- 43.0-1/debian/gnome-session-common.install	2022-10-11 18:08:35.000000000 +0000
+++ 43.0-1ubuntu2/debian/gnome-session-common.install	2022-10-13 11:13:51.000000000 +0000
@@ -1,7 +1,9 @@
 #!/usr/bin/dh-exec
 debian/55gnome-session_gnomerc etc/X11/Xsession.d
+# Handled by desktop-file-utils in Ubuntu
+# debian/gnome-mimeapps.list usr/share/applications/
+debian/xdg_dirs_desktop_session.sh etc/profile.d
 debian/gnome-session_gnomerc.sh etc/profile.d/
-debian/gnome-mimeapps.list usr/share/applications/
 [linux-any] usr/lib/systemd/user/gnome-launched-*
 [linux-any] usr/lib/systemd/user/gnome-session*.service
 [linux-any] usr/lib/systemd/user/gnome-session*.target
diff -pruN 43.0-1/debian/gnome-session-common.maintscript 43.0-1ubuntu2/debian/gnome-session-common.maintscript
--- 43.0-1/debian/gnome-session-common.maintscript	2022-10-11 18:08:35.000000000 +0000
+++ 43.0-1ubuntu2/debian/gnome-session-common.maintscript	1970-01-01 00:00:00.000000000 +0000
@@ -1 +0,0 @@
-rm_conffile /etc/gnome/defaults.list 3.20.1-2~
diff -pruN 43.0-1/debian/gnome-session-common.postinst 43.0-1ubuntu2/debian/gnome-session-common.postinst
--- 43.0-1/debian/gnome-session-common.postinst	2022-10-11 18:08:35.000000000 +0000
+++ 43.0-1ubuntu2/debian/gnome-session-common.postinst	1970-01-01 00:00:00.000000000 +0000
@@ -1,16 +0,0 @@
-#!/bin/sh
-
-set -e
-
-# Abuse dpkg-maintscript-helper to move/remove /etc/gnome/defaults.list
-if [ "$1" = "configure" ] && dpkg --compare-versions "$2" le-nl "3.20.1-2~"; then
-  if [ -f "/etc/gnome/defaults.list.dpkg-backup" ]; then
-    echo "Obsolete conffile /etc/gnome/defaults.list has been modified by you."
-    echo "Moving the file to /etc/xdg/gnome-mimeapps.list ..."
-    mv -f "/etc/gnome/defaults.list.dpkg-backup" "/etc/xdg/gnome-mimeapps.list"
-  fi
-fi
-
-#DEBHELPER#
-
-exit 0
diff -pruN 43.0-1/debian/gnome-session.install 43.0-1ubuntu2/debian/gnome-session.install
--- 43.0-1/debian/gnome-session.install	2022-10-11 18:08:35.000000000 +0000
+++ 43.0-1ubuntu2/debian/gnome-session.install	2022-10-13 11:13:51.000000000 +0000
@@ -1,6 +1,8 @@
 #!/usr/bin/dh-exec
 [linux-any] usr/lib/systemd/user/gnome-session@gnome.target.d/*
 usr/share/doc
-usr/share/gnome-session/sessions/*.session
-usr/share/wayland-sessions/*.desktop
-usr/share/xsessions/*.desktop
+usr/share/gnome-session/sessions/gnome*.session
+usr/share/wayland-sessions/gnome.desktop
+usr/share/wayland-sessions/gnome-wayland.desktop
+usr/share/xsessions/gnome-xorg.desktop
+usr/share/xsessions/gnome.desktop
diff -pruN 43.0-1/debian/gnome-session.postinst 43.0-1ubuntu2/debian/gnome-session.postinst
--- 43.0-1/debian/gnome-session.postinst	2022-10-11 18:08:35.000000000 +0000
+++ 43.0-1ubuntu2/debian/gnome-session.postinst	1970-01-01 00:00:00.000000000 +0000
@@ -1,12 +0,0 @@
-#!/bin/sh
-
-set -e
-
-if [ "$1" = configure ]; then
-  update-alternatives --install /usr/bin/x-session-manager \
-    x-session-manager /usr/bin/gnome-session 50 \
-    --slave /usr/share/man/man1/x-session-manager.1.gz \
-    x-session-manager.1.gz /usr/share/man/man1/gnome-session.1.gz
-fi
-
-#DEBHELPER#
diff -pruN 43.0-1/debian/gnome-session.prerm 43.0-1ubuntu2/debian/gnome-session.prerm
--- 43.0-1/debian/gnome-session.prerm	2022-10-11 18:08:35.000000000 +0000
+++ 43.0-1ubuntu2/debian/gnome-session.prerm	1970-01-01 00:00:00.000000000 +0000
@@ -1,9 +0,0 @@
-#!/bin/sh
-
-set -e
-
-if [ "$1" = "remove" ]; then
-  update-alternatives --remove x-session-manager /usr/bin/gnome-session
-fi
-
-#DEBHELPER#
diff -pruN 43.0-1/debian/gnome-startup-applications.install 43.0-1ubuntu2/debian/gnome-startup-applications.install
--- 43.0-1/debian/gnome-startup-applications.install	1970-01-01 00:00:00.000000000 +0000
+++ 43.0-1ubuntu2/debian/gnome-startup-applications.install	2022-10-13 11:13:51.000000000 +0000
@@ -0,0 +1,5 @@
+usr/bin/gnome-session-properties
+usr/share/applications
+usr/share/gnome-session/*.ui
+usr/share/icons
+usr/share/man/man1/gnome-session-properties*
diff -pruN 43.0-1/debian/patches/revert_remove_gnome_session_properties.patch 43.0-1ubuntu2/debian/patches/revert_remove_gnome_session_properties.patch
--- 43.0-1/debian/patches/revert_remove_gnome_session_properties.patch	1970-01-01 00:00:00.000000000 +0000
+++ 43.0-1ubuntu2/debian/patches/revert_remove_gnome_session_properties.patch	2022-10-13 11:13:51.000000000 +0000
@@ -0,0 +1,6267 @@
+From: Tim Lunn <tim@feathertop.org>
+Date: Sat, 3 Mar 2018 00:15:04 +0100
+Subject: [PATCH] Revert "Remove gnome-session-properties"
+
+This reverts commits ea285af9 and 0c6fe6ca and ports the build to meson.
+
+https://bugzilla.gnome.org/show_bug.cgi?id=708923
+https://bugzilla.gnome.org/show_bug.cgi?id=766836
+
+Ubuntu note: .png icons were also removed but they aren't as important
+as svg icons. .png icons don't fit in a quilt patch.
+---
+ capplet/gsm-app-dialog.c                           |  540 ++++++++++
+ capplet/gsm-app-dialog.h                           |   66 ++
+ capplet/gsm-properties-dialog.c                    |  774 ++++++++++++++
+ capplet/gsm-properties-dialog.h                    |   57 +
+ capplet/gsp-app-manager.c                          |  593 ++++++++++
+ capplet/gsp-app-manager.h                          |   81 ++
+ capplet/gsp-app.c                                  | 1129 ++++++++++++++++++++
+ capplet/gsp-app.h                                  |  108 ++
+ capplet/gsp-keyfile.c                              |  207 ++++
+ capplet/gsp-keyfile.h                              |   65 ++
+ capplet/main.c                                     |  108 ++
+ capplet/meson.build                                |   36 +
+ data/gnome-session-properties.desktop.in           |   14 +
+ data/icons/16x16/session-properties.svg            |  394 +++++++
+ data/icons/22x22/session-properties.svg            |  440 ++++++++
+ data/icons/32x32/session-properties.svg            |  490 +++++++++
+ data/icons/scalable/session-properties.svg         |  515 +++++++++
+ .../icons/symbolic/session-properties-symbolic.svg |   28 +
+ data/meson.build                                   |   23 +
+ data/session-properties.ui                         |  303 ++++++
+ doc/man/gnome-session-properties.1                 |   24 +
+ doc/man/gnome-session.1                            |    2 +
+ doc/man/meson.build                                |    3 +-
+ meson.build                                        |    1 +
+ po/POTFILES.in                                     |    6 +
+ po/POTFILES.skip                                   |    1 +
+ 26 files changed, 6007 insertions(+), 1 deletion(-)
+ create mode 100644 capplet/gsm-app-dialog.c
+ create mode 100644 capplet/gsm-app-dialog.h
+ create mode 100644 capplet/gsm-properties-dialog.c
+ create mode 100644 capplet/gsm-properties-dialog.h
+ create mode 100644 capplet/gsp-app-manager.c
+ create mode 100644 capplet/gsp-app-manager.h
+ create mode 100644 capplet/gsp-app.c
+ create mode 100644 capplet/gsp-app.h
+ create mode 100644 capplet/gsp-keyfile.c
+ create mode 100644 capplet/gsp-keyfile.h
+ create mode 100644 capplet/main.c
+ create mode 100644 capplet/meson.build
+ create mode 100644 data/gnome-session-properties.desktop.in
+ create mode 100644 data/icons/16x16/session-properties.svg
+ create mode 100644 data/icons/22x22/session-properties.svg
+ create mode 100644 data/icons/32x32/session-properties.svg
+ create mode 100644 data/icons/scalable/session-properties.svg
+ create mode 100644 data/icons/symbolic/session-properties-symbolic.svg
+ create mode 100644 data/session-properties.ui
+ create mode 100644 doc/man/gnome-session-properties.1
+
+diff --git a/capplet/gsm-app-dialog.c b/capplet/gsm-app-dialog.c
+new file mode 100644
+index 0000000..e7369dd
+--- /dev/null
++++ b/capplet/gsm-app-dialog.c
+@@ -0,0 +1,540 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
++ *
++ * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ */
++
++#include "config.h"
++
++#include <glib.h>
++#include <glib/gi18n.h>
++#include <gtk/gtk.h>
++
++#include "gsm-util.h"
++
++#include "gsm-app-dialog.h"
++
++#define GTKBUILDER_FILE "session-properties.ui"
++
++#define CAPPLET_NAME_ENTRY_WIDGET_NAME    "session_properties_name_entry"
++#define CAPPLET_COMMAND_ENTRY_WIDGET_NAME "session_properties_command_entry"
++#define CAPPLET_COMMENT_ENTRY_WIDGET_NAME "session_properties_comment_entry"
++#define CAPPLET_BROWSE_WIDGET_NAME        "session_properties_browse_button"
++
++
++#define GSM_APP_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSM_TYPE_APP_DIALOG, GsmAppDialogPrivate))
++
++struct GsmAppDialogPrivate
++{
++        GtkWidget *name_entry;
++        GtkWidget *command_entry;
++        GtkWidget *comment_entry;
++        GtkWidget *browse_button;
++        char      *name;
++        char      *command;
++        char      *comment;
++};
++
++static void     gsm_app_dialog_class_init  (GsmAppDialogClass *klass);
++static void     gsm_app_dialog_init        (GsmAppDialog      *app_dialog);
++static void     gsm_app_dialog_finalize    (GObject           *object);
++
++enum {
++        PROP_0,
++        PROP_NAME,
++        PROP_COMMAND,
++        PROP_COMMENT
++};
++
++G_DEFINE_TYPE (GsmAppDialog, gsm_app_dialog, GTK_TYPE_DIALOG)
++
++static char *
++make_exec_uri (const char *exec)
++{
++        GString    *str;
++        const char *c;
++
++        if (exec == NULL) {
++                return g_strdup ("");
++        }
++
++        if (strchr (exec, ' ') == NULL) {
++                return g_strdup (exec);
++        }
++
++        str = g_string_new_len (NULL, strlen (exec));
++
++        str = g_string_append_c (str, '"');
++        for (c = exec; *c != '\0'; c++) {
++                /* FIXME: GKeyFile will add an additional backslach so we'll
++                 * end up with toto\\" instead of toto\"
++                 * We could use g_key_file_set_value(), but then we don't
++                 * benefit from the other escaping that glib is doing...
++                 */
++                if (*c == '"') {
++                        str = g_string_append (str, "\\\"");
++                } else {
++                        str = g_string_append_c (str, *c);
++                }
++        }
++        str = g_string_append_c (str, '"');
++
++        return g_string_free (str, FALSE);
++}
++
++static void
++on_browse_button_clicked (GtkWidget    *widget,
++                          GsmAppDialog *dialog)
++{
++        GtkWidget *chooser;
++        int        response;
++
++        chooser = gtk_file_chooser_dialog_new ("",
++                                               GTK_WINDOW (dialog),
++                                               GTK_FILE_CHOOSER_ACTION_OPEN,
++                                               GTK_STOCK_CANCEL,
++                                               GTK_RESPONSE_CANCEL,
++                                               GTK_STOCK_OPEN,
++                                               GTK_RESPONSE_ACCEPT,
++                                               NULL);
++
++        gtk_window_set_transient_for (GTK_WINDOW (chooser),
++                                      GTK_WINDOW (dialog));
++
++        gtk_window_set_destroy_with_parent (GTK_WINDOW (chooser), TRUE);
++
++        gtk_window_set_title (GTK_WINDOW (chooser), _("Select Command"));
++
++        gtk_widget_show (chooser);
++
++        response = gtk_dialog_run (GTK_DIALOG (chooser));
++
++        if (response == GTK_RESPONSE_ACCEPT) {
++                char *text;
++                char *uri;
++
++                text = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (chooser));
++
++                uri = make_exec_uri (text);
++
++                g_free (text);
++
++                gtk_entry_set_text (GTK_ENTRY (dialog->priv->command_entry), uri);
++
++                g_free (uri);
++        }
++
++        gtk_widget_destroy (chooser);
++}
++
++static void
++on_entry_activate (GtkEntry     *entry,
++                   GsmAppDialog *dialog)
++{
++        gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
++}
++
++static void
++setup_dialog (GsmAppDialog *dialog)
++{
++        GtkWidget  *content_area;
++        GtkWidget  *widget;
++        GtkBuilder *xml;
++        GError     *error;
++
++        xml = gtk_builder_new ();
++        gtk_builder_set_translation_domain (xml, GETTEXT_PACKAGE);
++
++        error = NULL;
++        if (!gtk_builder_add_from_file (xml,
++                                        GTKBUILDER_DIR "/" GTKBUILDER_FILE,
++                                        &error)) {
++                if (error) {
++                        g_warning ("Could not load capplet UI file: %s",
++                                   error->message);
++                        g_error_free (error);
++                } else {
++                        g_warning ("Could not load capplet UI file.");
++                }
++        }
++
++        content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
++        widget = GTK_WIDGET (gtk_builder_get_object (xml, "main-table"));
++        gtk_container_add (GTK_CONTAINER (content_area), widget);
++
++        gtk_container_set_border_width (GTK_CONTAINER (dialog), 6);
++        gtk_window_set_icon_name (GTK_WINDOW (dialog), "session-properties");
++
++        g_object_set (dialog,
++                      "allow-shrink", FALSE,
++                      "allow-grow", FALSE,
++                      NULL);
++
++        gtk_dialog_add_button (GTK_DIALOG (dialog),
++                               GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL);
++
++        if (dialog->priv->name == NULL
++            && dialog->priv->command == NULL
++            && dialog->priv->comment == NULL) {
++                gtk_window_set_title (GTK_WINDOW (dialog), _("Add Startup Program"));
++                gtk_dialog_add_button (GTK_DIALOG (dialog),
++                                       GTK_STOCK_ADD, GTK_RESPONSE_OK);
++        } else {
++                gtk_window_set_title (GTK_WINDOW (dialog), _("Edit Startup Program"));
++                gtk_dialog_add_button (GTK_DIALOG (dialog),
++                                       GTK_STOCK_SAVE, GTK_RESPONSE_OK);
++        }
++
++        dialog->priv->name_entry = GTK_WIDGET (gtk_builder_get_object (xml, CAPPLET_NAME_ENTRY_WIDGET_NAME));
++        g_signal_connect (dialog->priv->name_entry,
++                          "activate",
++                          G_CALLBACK (on_entry_activate),
++                          dialog);
++        if (dialog->priv->name != NULL) {
++                gtk_entry_set_text (GTK_ENTRY (dialog->priv->name_entry), dialog->priv->name);
++        }
++
++        dialog->priv->browse_button = GTK_WIDGET (gtk_builder_get_object (xml, CAPPLET_BROWSE_WIDGET_NAME));
++        g_signal_connect (dialog->priv->browse_button,
++                          "clicked",
++                          G_CALLBACK (on_browse_button_clicked),
++                          dialog);
++
++        dialog->priv->command_entry = GTK_WIDGET (gtk_builder_get_object (xml, CAPPLET_COMMAND_ENTRY_WIDGET_NAME));
++        g_signal_connect (dialog->priv->command_entry,
++                          "activate",
++                          G_CALLBACK (on_entry_activate),
++                          dialog);
++        if (dialog->priv->command != NULL) {
++                gtk_entry_set_text (GTK_ENTRY (dialog->priv->command_entry), dialog->priv->command);
++        }
++
++        dialog->priv->comment_entry = GTK_WIDGET (gtk_builder_get_object (xml, CAPPLET_COMMENT_ENTRY_WIDGET_NAME));
++        g_signal_connect (dialog->priv->comment_entry,
++                          "activate",
++                          G_CALLBACK (on_entry_activate),
++                          dialog);
++        if (dialog->priv->comment != NULL) {
++                gtk_entry_set_text (GTK_ENTRY (dialog->priv->comment_entry), dialog->priv->comment);
++        }
++
++        if (xml != NULL) {
++                g_object_unref (xml);
++        }
++}
++
++static GObject *
++gsm_app_dialog_constructor (GType                  type,
++                            guint                  n_construct_app,
++                            GObjectConstructParam *construct_app)
++{
++        GsmAppDialog *dialog;
++
++        dialog = GSM_APP_DIALOG (G_OBJECT_CLASS (gsm_app_dialog_parent_class)->constructor (type,
++                                                                                                                  n_construct_app,
++                                                                                                                  construct_app));
++
++        setup_dialog (dialog);
++
++        gtk_widget_show_all (GTK_WIDGET (dialog));
++
++        return G_OBJECT (dialog);
++}
++
++static void
++gsm_app_dialog_dispose (GObject *object)
++{
++        GsmAppDialog *dialog;
++
++        g_return_if_fail (object != NULL);
++        g_return_if_fail (GSM_IS_APP_DIALOG (object));
++
++        dialog = GSM_APP_DIALOG (object);
++
++        g_free (dialog->priv->name);
++        dialog->priv->name = NULL;
++        g_free (dialog->priv->command);
++        dialog->priv->command = NULL;
++        g_free (dialog->priv->comment);
++        dialog->priv->comment = NULL;
++
++        G_OBJECT_CLASS (gsm_app_dialog_parent_class)->dispose (object);
++}
++
++static void
++gsm_app_dialog_set_name (GsmAppDialog *dialog,
++                         const char   *name)
++{
++        g_return_if_fail (GSM_IS_APP_DIALOG (dialog));
++
++        g_free (dialog->priv->name);
++
++        dialog->priv->name = g_strdup (name);
++        g_object_notify (G_OBJECT (dialog), "name");
++}
++
++static void
++gsm_app_dialog_set_command (GsmAppDialog *dialog,
++                            const char   *name)
++{
++        g_return_if_fail (GSM_IS_APP_DIALOG (dialog));
++
++        g_free (dialog->priv->command);
++
++        dialog->priv->command = g_strdup (name);
++        g_object_notify (G_OBJECT (dialog), "command");
++}
++
++static void
++gsm_app_dialog_set_comment (GsmAppDialog *dialog,
++                            const char   *name)
++{
++        g_return_if_fail (GSM_IS_APP_DIALOG (dialog));
++
++        g_free (dialog->priv->comment);
++
++        dialog->priv->comment = g_strdup (name);
++        g_object_notify (G_OBJECT (dialog), "comment");
++}
++
++const char *
++gsm_app_dialog_get_name (GsmAppDialog *dialog)
++{
++        g_return_val_if_fail (GSM_IS_APP_DIALOG (dialog), NULL);
++        return gtk_entry_get_text (GTK_ENTRY (dialog->priv->name_entry));
++}
++
++const char *
++gsm_app_dialog_get_command (GsmAppDialog *dialog)
++{
++        g_return_val_if_fail (GSM_IS_APP_DIALOG (dialog), NULL);
++        return gtk_entry_get_text (GTK_ENTRY (dialog->priv->command_entry));
++}
++
++const char *
++gsm_app_dialog_get_comment (GsmAppDialog *dialog)
++{
++        g_return_val_if_fail (GSM_IS_APP_DIALOG (dialog), NULL);
++        return gtk_entry_get_text (GTK_ENTRY (dialog->priv->comment_entry));
++}
++
++static void
++gsm_app_dialog_set_property (GObject        *object,
++                             guint           prop_id,
++                             const GValue   *value,
++                             GParamSpec     *pspec)
++{
++        GsmAppDialog *dialog = GSM_APP_DIALOG (object);
++
++        switch (prop_id) {
++        case PROP_NAME:
++                gsm_app_dialog_set_name (dialog, g_value_get_string (value));
++                break;
++        case PROP_COMMAND:
++                gsm_app_dialog_set_command (dialog, g_value_get_string (value));
++                break;
++        case PROP_COMMENT:
++                gsm_app_dialog_set_comment (dialog, g_value_get_string (value));
++                break;
++        default:
++                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
++                break;
++        }
++}
++
++static void
++gsm_app_dialog_get_property (GObject        *object,
++                             guint           prop_id,
++                             GValue         *value,
++                             GParamSpec     *pspec)
++{
++        GsmAppDialog *dialog = GSM_APP_DIALOG (object);
++
++        switch (prop_id) {
++        case PROP_NAME:
++                g_value_set_string (value, dialog->priv->name);
++                break;
++        case PROP_COMMAND:
++                g_value_set_string (value, dialog->priv->command);
++                break;
++        case PROP_COMMENT:
++                g_value_set_string (value, dialog->priv->comment);
++                break;
++        default:
++                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
++                break;
++        }
++}
++
++static void
++gsm_app_dialog_class_init (GsmAppDialogClass *klass)
++{
++        GObjectClass   *object_class = G_OBJECT_CLASS (klass);
++
++        object_class->get_property = gsm_app_dialog_get_property;
++        object_class->set_property = gsm_app_dialog_set_property;
++        object_class->constructor = gsm_app_dialog_constructor;
++        object_class->dispose = gsm_app_dialog_dispose;
++        object_class->finalize = gsm_app_dialog_finalize;
++
++        g_object_class_install_property (object_class,
++                                         PROP_NAME,
++                                         g_param_spec_string ("name",
++                                                              "name",
++                                                              "name",
++                                                              NULL,
++                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
++        g_object_class_install_property (object_class,
++                                         PROP_COMMAND,
++                                         g_param_spec_string ("command",
++                                                              "command",
++                                                              "command",
++                                                              NULL,
++                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
++        g_object_class_install_property (object_class,
++                                         PROP_COMMENT,
++                                         g_param_spec_string ("comment",
++                                                              "comment",
++                                                              "comment",
++                                                              NULL,
++                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
++
++        g_type_class_add_private (klass, sizeof (GsmAppDialogPrivate));
++}
++
++static void
++gsm_app_dialog_init (GsmAppDialog *dialog)
++{
++
++        dialog->priv = GSM_APP_DIALOG_GET_PRIVATE (dialog);
++}
++
++static void
++gsm_app_dialog_finalize (GObject *object)
++{
++        GsmAppDialog *dialog;
++
++        g_return_if_fail (object != NULL);
++        g_return_if_fail (GSM_IS_APP_DIALOG (object));
++
++        dialog = GSM_APP_DIALOG (object);
++
++        g_return_if_fail (dialog->priv != NULL);
++
++        G_OBJECT_CLASS (gsm_app_dialog_parent_class)->finalize (object);
++}
++
++GtkWidget *
++gsm_app_dialog_new (const char *name,
++                    const char *command,
++                    const char *comment)
++{
++        GObject *object;
++
++        object = g_object_new (GSM_TYPE_APP_DIALOG,
++                               "name", name,
++                               "command", command,
++                               "comment", comment,
++                               NULL);
++
++        return GTK_WIDGET (object);
++}
++
++gboolean
++gsm_app_dialog_run (GsmAppDialog  *dialog,
++                    char         **name_p,
++                    char         **command_p,
++                    char         **comment_p)
++{
++        gboolean retval;
++
++        retval = FALSE;
++
++        while (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
++                const char *name;
++                const char *exec;
++                const char *comment;
++                const char *error_msg;
++                GError     *error;
++                char      **argv;
++                int         argc;
++
++                name = gsm_app_dialog_get_name (GSM_APP_DIALOG (dialog));
++                exec = gsm_app_dialog_get_command (GSM_APP_DIALOG (dialog));
++                comment = gsm_app_dialog_get_comment (GSM_APP_DIALOG (dialog));
++
++                error = NULL;
++                error_msg = NULL;
++
++                if (gsm_util_text_is_blank (exec)) {
++                        error_msg = _("The startup command cannot be empty");
++                } else {
++                        if (!g_shell_parse_argv (exec, &argc, &argv, &error)) {
++                                if (error != NULL) {
++                                        error_msg = error->message;
++                                } else {
++                                        error_msg = _("The startup command is not valid");
++                                }
++                        }
++                }
++
++                if (error_msg != NULL) {
++                        GtkWidget *msgbox;
++
++                        msgbox = gtk_message_dialog_new (GTK_WINDOW (dialog),
++                                                         GTK_DIALOG_MODAL,
++                                                         GTK_MESSAGE_ERROR,
++                                                         GTK_BUTTONS_CLOSE,
++                                                         "%s", error_msg);
++
++                        if (error != NULL) {
++                                g_error_free (error);
++                        }
++
++                        gtk_dialog_run (GTK_DIALOG (msgbox));
++
++                        gtk_widget_destroy (msgbox);
++
++                        continue;
++                }
++
++                if (gsm_util_text_is_blank (name)) {
++                        name = argv[0];
++                }
++
++                if (name_p) {
++                        *name_p = g_strdup (name);
++                }
++
++                g_strfreev (argv);
++
++                if (command_p) {
++                        *command_p = g_strdup (exec);
++                }
++
++                if (comment_p) {
++                        *comment_p = g_strdup (comment);
++                }
++
++                retval = TRUE;
++                break;
++        }
++
++        gtk_widget_destroy (GTK_WIDGET (dialog));
++
++        return retval;
++}
+diff --git a/capplet/gsm-app-dialog.h b/capplet/gsm-app-dialog.h
+new file mode 100644
+index 0000000..ced0628
+--- /dev/null
++++ b/capplet/gsm-app-dialog.h
+@@ -0,0 +1,66 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
++ *
++ * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ */
++
++#ifndef __GSM_APP_DIALOG_H
++#define __GSM_APP_DIALOG_H
++
++#include <glib-object.h>
++#include <gtk/gtk.h>
++
++G_BEGIN_DECLS
++
++#define GSM_TYPE_APP_DIALOG         (gsm_app_dialog_get_type ())
++#define GSM_APP_DIALOG(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GSM_TYPE_APP_DIALOG, GsmAppDialog))
++#define GSM_APP_DIALOG_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), GSM_TYPE_APP_DIALOG, GsmAppDialogClass))
++#define GSM_IS_APP_DIALOG(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSM_TYPE_APP_DIALOG))
++#define GSM_IS_APP_DIALOG_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), GSM_TYPE_APP_DIALOG))
++#define GSM_APP_DIALOG_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSM_TYPE_APP_DIALOG, GsmAppDialogClass))
++
++typedef struct GsmAppDialogPrivate GsmAppDialogPrivate;
++
++typedef struct
++{
++        GtkDialog            parent;
++        GsmAppDialogPrivate *priv;
++} GsmAppDialog;
++
++typedef struct
++{
++        GtkDialogClass   parent_class;
++} GsmAppDialogClass;
++
++GType                  gsm_app_dialog_get_type           (void);
++
++GtkWidget            * gsm_app_dialog_new                (const char   *name,
++                                                          const char   *command,
++                                                          const char   *comment);
++
++gboolean               gsm_app_dialog_run               (GsmAppDialog  *dialog,
++                                                         char         **name_p,
++                                                         char         **command_p,
++                                                         char         **comment_p);
++
++const char *           gsm_app_dialog_get_name           (GsmAppDialog *dialog);
++const char *           gsm_app_dialog_get_command        (GsmAppDialog *dialog);
++const char *           gsm_app_dialog_get_comment        (GsmAppDialog *dialog);
++
++G_END_DECLS
++
++#endif /* __GSM_APP_DIALOG_H */
+diff --git a/capplet/gsm-properties-dialog.c b/capplet/gsm-properties-dialog.c
+new file mode 100644
+index 0000000..33812b8
+--- /dev/null
++++ b/capplet/gsm-properties-dialog.c
+@@ -0,0 +1,774 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
++ *
++ * Copyright (C) 1999 Free Software Foundation, Inc.
++ * Copyright (C) 2007 Vincent Untz.
++ * Copyright (C) 2008 Lucas Rocha.
++ * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ */
++
++#include "config.h"
++
++#include <glib.h>
++#include <glib/gi18n.h>
++#include <gtk/gtk.h>
++
++#include "gsm-properties-dialog.h"
++#include "gsm-app-dialog.h"
++#include "gsm-util.h"
++#include "gsp-app.h"
++#include "gsp-app-manager.h"
++
++#define GSM_PROPERTIES_DIALOG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSM_TYPE_PROPERTIES_DIALOG, GsmPropertiesDialogPrivate))
++
++#define GTKBUILDER_FILE "session-properties.ui"
++
++#define CAPPLET_TREEVIEW_WIDGET_NAME      "session_properties_treeview"
++#define CAPPLET_ADD_WIDGET_NAME           "session_properties_add_button"
++#define CAPPLET_DELETE_WIDGET_NAME        "session_properties_delete_button"
++#define CAPPLET_EDIT_WIDGET_NAME          "session_properties_edit_button"
++#define CAPPLET_SAVE_WIDGET_NAME          "session_properties_save_button"
++#define CAPPLET_REMEMBER_WIDGET_NAME      "session_properties_remember_toggle"
++
++#define STARTUP_APP_ICON     "system-run"
++
++#define SPC_SETTINGS_SCHEMA          "org.gnome.SessionManager"
++#define SPC_SETTINGS_AUTOSAVE_KEY    "auto-save-session"
++
++struct GsmPropertiesDialogPrivate
++{
++        GtkBuilder        *xml;
++        GtkListStore      *list_store;
++        GtkTreeModel      *tree_filter;
++
++        GtkTreeView       *treeview;
++        GtkWidget         *add_button;
++        GtkWidget         *delete_button;
++        GtkWidget         *edit_button;
++
++        GSettings         *settings;
++
++        GspAppManager     *manager;
++};
++
++enum {
++        STORE_COL_VISIBLE = 0,
++        STORE_COL_ENABLED,
++        STORE_COL_GICON,
++        STORE_COL_DESCRIPTION,
++        STORE_COL_APP,
++        STORE_COL_SEARCH,
++        NUMBER_OF_COLUMNS
++};
++
++static void     gsm_properties_dialog_class_init  (GsmPropertiesDialogClass *klass);
++static void     gsm_properties_dialog_init        (GsmPropertiesDialog      *properties_dialog);
++static void     gsm_properties_dialog_finalize    (GObject                  *object);
++
++G_DEFINE_TYPE (GsmPropertiesDialog, gsm_properties_dialog, GTK_TYPE_DIALOG)
++
++static gboolean
++find_by_app (GtkTreeModel *model,
++             GtkTreeIter  *iter,
++             GspApp       *app)
++{
++        GspApp *iter_app = NULL;
++
++        if (!gtk_tree_model_get_iter_first (model, iter)) {
++                return FALSE;
++        }
++
++        do {
++                gtk_tree_model_get (model, iter,
++                                    STORE_COL_APP, &iter_app,
++                                    -1);
++
++                if (iter_app == app) {
++                        g_object_unref (iter_app);
++                        return TRUE;
++                }
++        } while (gtk_tree_model_iter_next (model, iter));
++
++        return FALSE;
++}
++
++static void
++_fill_iter_from_app (GtkListStore *list_store,
++                     GtkTreeIter  *iter,
++                     GspApp       *app)
++{
++        gboolean    hidden;
++        gboolean    display;
++        gboolean    enabled;
++        gboolean    shown;
++        GIcon      *icon;
++        const char *description;
++        const char *app_name;
++
++        hidden      = gsp_app_get_hidden (app);
++        display     = gsp_app_get_display (app);
++        enabled     = gsp_app_get_enabled (app);
++        shown       = gsp_app_get_shown (app);
++        icon        = gsp_app_get_icon (app);
++        description = gsp_app_get_description (app);
++        app_name    = gsp_app_get_name (app);
++
++        if (G_IS_THEMED_ICON (icon)) {
++                GtkIconTheme       *theme;
++                const char * const *icon_names;
++
++                theme = gtk_icon_theme_get_default ();
++                icon_names = g_themed_icon_get_names (G_THEMED_ICON (icon));
++                if (icon_names[0] == NULL ||
++                    !gtk_icon_theme_has_icon (theme, icon_names[0])) {
++                        g_object_unref (icon);
++                        icon = NULL;
++                }
++        } else if (G_IS_FILE_ICON (icon)) {
++                GFile *iconfile;
++
++                iconfile = g_file_icon_get_file (G_FILE_ICON (icon));
++                if (!g_file_query_exists (iconfile, NULL)) {
++                        g_object_unref (icon);
++                        icon = NULL;
++                }
++        }
++
++        if (icon == NULL) {
++                icon = g_themed_icon_new (STARTUP_APP_ICON);
++        }
++
++        gtk_list_store_set (list_store, iter,
++                            STORE_COL_VISIBLE, !hidden && shown && display,
++                            STORE_COL_ENABLED, enabled,
++                            STORE_COL_GICON, icon,
++                            STORE_COL_DESCRIPTION, description,
++                            STORE_COL_APP, app,
++                            STORE_COL_SEARCH, app_name,
++                            -1);
++        g_object_unref (icon);
++}
++
++static void
++_app_changed (GsmPropertiesDialog *dialog,
++              GspApp              *app)
++{
++        GtkTreeIter iter;
++
++        if (!find_by_app (GTK_TREE_MODEL (dialog->priv->list_store),
++                          &iter, app)) {
++                return;
++        }
++
++        _fill_iter_from_app (dialog->priv->list_store, &iter, app);
++}
++
++static void
++append_app (GsmPropertiesDialog *dialog,
++            GspApp              *app)
++{
++        GtkTreeIter   iter;
++
++        gtk_list_store_append (dialog->priv->list_store, &iter);
++        _fill_iter_from_app (dialog->priv->list_store, &iter, app);
++
++        g_signal_connect_swapped (app, "changed",
++                                  G_CALLBACK (_app_changed), dialog);
++}
++
++static void
++_app_added (GsmPropertiesDialog *dialog,
++            GspApp              *app,
++            GspAppManager       *manager)
++{
++        append_app (dialog, app);
++}
++
++static void
++_app_removed (GsmPropertiesDialog *dialog,
++              GspApp              *app,
++              GspAppManager       *manager)
++{
++        GtkTreeIter iter;
++
++        if (!find_by_app (GTK_TREE_MODEL (dialog->priv->list_store),
++                          &iter, app)) {
++                return;
++        }
++
++        g_signal_handlers_disconnect_by_func (app,
++                                              _app_changed,
++                                              dialog);
++        gtk_list_store_remove (dialog->priv->list_store, &iter);
++}
++
++static void
++populate_model (GsmPropertiesDialog *dialog)
++{
++        GSList *apps;
++        GSList *l;
++
++        apps = gsp_app_manager_get_apps (dialog->priv->manager);
++        for (l = apps; l != NULL; l = l->next) {
++                append_app (dialog, GSP_APP (l->data));
++        }
++        g_slist_free (apps);
++}
++
++static void
++on_selection_changed (GtkTreeSelection    *selection,
++                      GsmPropertiesDialog *dialog)
++{
++        gboolean sel;
++
++        sel = gtk_tree_selection_get_selected (selection, NULL, NULL);
++
++        gtk_widget_set_sensitive (dialog->priv->edit_button, sel);
++        gtk_widget_set_sensitive (dialog->priv->delete_button, sel);
++}
++
++static void
++on_startup_enabled_toggled (GtkCellRendererToggle *cell_renderer,
++                            char                  *path,
++                            GsmPropertiesDialog   *dialog)
++{
++        GtkTreeIter iter;
++        GspApp     *app;
++        gboolean    active;
++
++        if (!gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (dialog->priv->tree_filter),
++                                                  &iter, path)) {
++                return;
++        }
++
++        app = NULL;
++        gtk_tree_model_get (GTK_TREE_MODEL (dialog->priv->tree_filter),
++                            &iter,
++                            STORE_COL_APP, &app,
++                            -1);
++
++        active = gtk_cell_renderer_toggle_get_active (cell_renderer);
++        active = !active;
++
++        if (app) {
++                gsp_app_set_enabled (app, active);
++                g_object_unref (app);
++        }
++}
++
++static void
++on_drag_data_received (GtkWidget           *widget,
++                       GdkDragContext      *drag_context,
++                       gint                 x,
++                       gint                 y,
++                       GtkSelectionData    *data,
++                       guint                info,
++                       guint                time,
++                       GsmPropertiesDialog *dialog)
++{
++        gboolean dnd_success;
++
++        dnd_success = FALSE;
++
++        if (data != NULL) {
++                char **filenames;
++                int    i;
++
++                filenames = gtk_selection_data_get_uris (data);
++
++                for (i = 0; filenames[i] && filenames[i][0]; i++) {
++                        /* Return success if at least one file succeeded */
++                        gboolean file_success;
++                        file_success = gsp_app_copy_desktop_file (filenames[i]);
++                        dnd_success = dnd_success || file_success;
++                }
++
++                g_strfreev (filenames);
++        }
++
++        gtk_drag_finish (drag_context, dnd_success, FALSE, time);
++        g_signal_stop_emission_by_name (widget, "drag_data_received");
++}
++
++static void
++on_drag_begin (GtkWidget           *widget,
++               GdkDragContext      *context,
++               GsmPropertiesDialog *dialog)
++{
++        GtkTreePath *path;
++        GtkTreeIter  iter;
++        GspApp      *app;
++
++        gtk_tree_view_get_cursor (GTK_TREE_VIEW (widget), &path, NULL);
++        gtk_tree_model_get_iter (GTK_TREE_MODEL (dialog->priv->tree_filter),
++                                 &iter, path);
++        gtk_tree_path_free (path);
++
++        gtk_tree_model_get (GTK_TREE_MODEL (dialog->priv->tree_filter),
++                            &iter,
++                            STORE_COL_APP, &app,
++                            -1);
++
++        if (app) {
++                g_object_set_data_full (G_OBJECT (context), "gsp-app",
++                                        g_object_ref (app), g_object_unref);
++                g_object_unref (app);
++        }
++
++}
++
++static void
++on_drag_data_get (GtkWidget           *widget,
++                  GdkDragContext      *context,
++                  GtkSelectionData    *selection_data,
++                  guint                info,
++                  guint                time,
++                  GsmPropertiesDialog *dialog)
++{
++        GspApp *app;
++
++        app = g_object_get_data (G_OBJECT (context), "gsp-app");
++        if (app) {
++                const char *uris[2];
++                char       *uri;
++
++                uri = g_filename_to_uri (gsp_app_get_path (app), NULL, NULL);
++
++                uris[0] = uri;
++                uris[1] = NULL;
++                gtk_selection_data_set_uris (selection_data, (char **) uris);
++
++                g_free (uri);
++        }
++}
++
++static void
++on_add_app_clicked (GtkWidget           *widget,
++                    GsmPropertiesDialog *dialog)
++{
++        GtkWidget  *add_dialog;
++        char       *name;
++        char       *exec;
++        char       *comment;
++
++        add_dialog = gsm_app_dialog_new (NULL, NULL, NULL);
++        gtk_window_set_transient_for (GTK_WINDOW (add_dialog),
++                                      GTK_WINDOW (dialog));
++
++        if (gsm_app_dialog_run (GSM_APP_DIALOG (add_dialog),
++                                &name, &exec, &comment)) {
++                gsp_app_create (name, comment, exec);
++                g_free (name);
++                g_free (exec);
++                g_free (comment);
++        }
++}
++
++static void
++on_delete_app_clicked (GtkWidget           *widget,
++                       GsmPropertiesDialog *dialog)
++{
++        GtkTreeSelection *selection;
++        GtkTreeIter       iter;
++        GspApp           *app;
++
++        selection = gtk_tree_view_get_selection (dialog->priv->treeview);
++
++        if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) {
++                return;
++        }
++
++        app = NULL;
++        gtk_tree_model_get (GTK_TREE_MODEL (dialog->priv->tree_filter),
++                            &iter,
++                            STORE_COL_APP, &app,
++                            -1);
++
++        if (app) {
++                gsp_app_delete (app);
++                g_object_unref (app);
++        }
++}
++
++static void
++on_edit_app_clicked (GtkWidget           *widget,
++                     GsmPropertiesDialog *dialog)
++{
++        GtkTreeSelection *selection;
++        GtkTreeIter       iter;
++        GspApp           *app;
++
++        selection = gtk_tree_view_get_selection (dialog->priv->treeview);
++
++        if (!gtk_tree_selection_get_selected (selection, NULL, &iter)) {
++                return;
++        }
++
++        app = NULL;
++        gtk_tree_model_get (GTK_TREE_MODEL (dialog->priv->tree_filter),
++                            &iter,
++                            STORE_COL_APP, &app,
++                            -1);
++
++        if (app) {
++                GtkWidget  *edit_dialog;
++                char       *name;
++                char       *exec;
++                char       *comment;
++
++                edit_dialog = gsm_app_dialog_new (gsp_app_get_name (app),
++                                                  gsp_app_get_exec (app),
++                                                  gsp_app_get_comment (app));
++                gtk_window_set_transient_for (GTK_WINDOW (edit_dialog),
++                                              GTK_WINDOW (dialog));
++
++                if (gsm_app_dialog_run (GSM_APP_DIALOG (edit_dialog),
++                                        &name, &exec, &comment)) {
++                        gsp_app_update (app, name, comment, exec);
++                        g_free (name);
++                        g_free (exec);
++                        g_free (comment);
++                }
++
++                g_object_unref (app);
++        }
++}
++
++static void
++on_row_activated (GtkTreeView         *tree_view,
++                  GtkTreePath         *path,
++                  GtkTreeViewColumn   *column,
++                  GsmPropertiesDialog *dialog)
++{
++        on_edit_app_clicked (NULL, dialog);
++}
++
++static void
++on_save_session_clicked (GtkWidget           *widget,
++                         GsmPropertiesDialog *dialog)
++{
++        g_debug ("Session saving is not implemented yet!");
++}
++
++static void
++setup_dialog (GsmPropertiesDialog *dialog)
++{
++        GtkTreeView       *treeview;
++        GtkWidget         *button;
++        GtkTreeModel      *tree_filter;
++        GtkTreeViewColumn *column;
++        GtkCellRenderer   *renderer;
++        GtkTreeSelection  *selection;
++        GtkTargetList     *targetlist;
++
++        gtk_dialog_add_buttons (GTK_DIALOG (dialog),
++                                GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
++                                NULL);
++
++        dialog->priv->list_store = gtk_list_store_new (NUMBER_OF_COLUMNS,
++                                                       G_TYPE_BOOLEAN,
++                                                       G_TYPE_BOOLEAN,
++                                                       G_TYPE_ICON,
++                                                       G_TYPE_STRING,
++                                                       G_TYPE_OBJECT,
++                                                       G_TYPE_STRING);
++        tree_filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (dialog->priv->list_store),
++                                                 NULL);
++        g_object_unref (dialog->priv->list_store);
++        dialog->priv->tree_filter = tree_filter;
++
++        gtk_tree_model_filter_set_visible_column (GTK_TREE_MODEL_FILTER (tree_filter),
++                                                  STORE_COL_VISIBLE);
++
++        treeview = GTK_TREE_VIEW (gtk_builder_get_object (dialog->priv->xml,
++                                                          CAPPLET_TREEVIEW_WIDGET_NAME));
++        dialog->priv->treeview = treeview;
++
++        gtk_tree_view_set_model (treeview, tree_filter);
++        g_object_unref (tree_filter);
++
++        gtk_tree_view_set_headers_visible (treeview, FALSE);
++        g_signal_connect (treeview,
++                          "row-activated",
++                          G_CALLBACK (on_row_activated),
++                          dialog);
++
++        selection = gtk_tree_view_get_selection (treeview);
++        gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
++        g_signal_connect (selection,
++                          "changed",
++                          G_CALLBACK (on_selection_changed),
++                          dialog);
++
++        /* CHECKBOX COLUMN */
++        renderer = gtk_cell_renderer_toggle_new ();
++        column = gtk_tree_view_column_new_with_attributes (_("Enabled"),
++                                                           renderer,
++                                                           "active", STORE_COL_ENABLED,
++                                                           NULL);
++        gtk_tree_view_append_column (treeview, column);
++        g_signal_connect (renderer,
++                          "toggled",
++                          G_CALLBACK (on_startup_enabled_toggled),
++                          dialog);
++
++        /* ICON COLUMN */
++        renderer = gtk_cell_renderer_pixbuf_new ();
++        column = gtk_tree_view_column_new_with_attributes (_("Icon"),
++                                                           renderer,
++                                                           "gicon", STORE_COL_GICON,
++                                                           "sensitive", STORE_COL_ENABLED,
++                                                           NULL);
++        g_object_set (renderer,
++                      "stock-size", GSM_PROPERTIES_ICON_SIZE,
++                      NULL);
++        gtk_tree_view_append_column (treeview, column);
++
++        /* NAME COLUMN */
++        renderer = gtk_cell_renderer_text_new ();
++        column = gtk_tree_view_column_new_with_attributes (_("Program"),
++                                                           renderer,
++                                                           "markup", STORE_COL_DESCRIPTION,
++                                                           "sensitive", STORE_COL_ENABLED,
++                                                           NULL);
++        g_object_set (renderer,
++                      "ellipsize", PANGO_ELLIPSIZE_END,
++                      NULL);
++        gtk_tree_view_append_column (treeview, column);
++
++
++        gtk_tree_view_column_set_sort_column_id (column, STORE_COL_DESCRIPTION);
++        gtk_tree_view_set_search_column (treeview, STORE_COL_SEARCH);
++        gtk_tree_view_set_rules_hint (treeview, TRUE);
++
++        gtk_tree_view_enable_model_drag_source (treeview,
++                                                GDK_BUTTON1_MASK|GDK_BUTTON2_MASK,
++                                                NULL, 0,
++                                                GDK_ACTION_COPY);
++        gtk_drag_source_add_uri_targets (GTK_WIDGET (treeview));
++
++        gtk_drag_dest_set (GTK_WIDGET (treeview),
++                           GTK_DEST_DEFAULT_ALL,
++                           NULL, 0,
++                           GDK_ACTION_COPY);
++
++        gtk_drag_dest_add_uri_targets (GTK_WIDGET (treeview));
++        /* we don't want to accept drags coming from this widget */
++        targetlist = gtk_drag_dest_get_target_list (GTK_WIDGET (treeview));
++        if (targetlist != NULL) {
++                GtkTargetEntry *targets;
++                gint n_targets;
++                gint i;
++
++                targets = gtk_target_table_new_from_list (targetlist, &n_targets);
++                for (i = 0; i < n_targets; i++)
++                        targets[i].flags = GTK_TARGET_OTHER_WIDGET;
++
++                targetlist = gtk_target_list_new (targets, n_targets);
++                gtk_drag_dest_set_target_list (GTK_WIDGET (treeview), targetlist);
++                gtk_target_list_unref (targetlist);
++
++                gtk_target_table_free (targets, n_targets);
++        }
++
++        g_signal_connect (treeview, "drag_begin",
++                          G_CALLBACK (on_drag_begin),
++                          dialog);
++        g_signal_connect (treeview, "drag_data_get",
++                          G_CALLBACK (on_drag_data_get),
++                          dialog);
++        g_signal_connect (treeview, "drag_data_received",
++                          G_CALLBACK (on_drag_data_received),
++                          dialog);
++
++        gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (dialog->priv->list_store),
++                                              STORE_COL_DESCRIPTION,
++                                              GTK_SORT_ASCENDING);
++
++
++        button = GTK_WIDGET (gtk_builder_get_object (dialog->priv->xml,
++                                                     CAPPLET_ADD_WIDGET_NAME));
++        dialog->priv->add_button = button;
++        g_signal_connect (button,
++                          "clicked",
++                          G_CALLBACK (on_add_app_clicked),
++                          dialog);
++
++        button = GTK_WIDGET (gtk_builder_get_object (dialog->priv->xml,
++                                                     CAPPLET_DELETE_WIDGET_NAME));
++        dialog->priv->delete_button = button;
++        g_signal_connect (button,
++                          "clicked",
++                          G_CALLBACK (on_delete_app_clicked),
++                          dialog);
++
++        button = GTK_WIDGET (gtk_builder_get_object (dialog->priv->xml,
++                                                     CAPPLET_EDIT_WIDGET_NAME));
++        dialog->priv->edit_button = button;
++        g_signal_connect (button,
++                          "clicked",
++                          G_CALLBACK (on_edit_app_clicked),
++                          dialog);
++
++        button = GTK_WIDGET (gtk_builder_get_object (dialog->priv->xml,
++                                                     CAPPLET_REMEMBER_WIDGET_NAME));
++        g_settings_bind (dialog->priv->settings, SPC_SETTINGS_AUTOSAVE_KEY,
++                         button, "active", G_SETTINGS_BIND_DEFAULT);
++
++        button = GTK_WIDGET (gtk_builder_get_object (dialog->priv->xml,
++                                                     CAPPLET_SAVE_WIDGET_NAME));
++        g_signal_connect (button,
++                          "clicked",
++                          G_CALLBACK (on_save_session_clicked),
++                          dialog);
++
++        dialog->priv->manager = gsp_app_manager_get ();
++        gsp_app_manager_fill (dialog->priv->manager);
++        g_signal_connect_swapped (dialog->priv->manager, "added",
++                                  G_CALLBACK (_app_added), dialog);
++        g_signal_connect_swapped (dialog->priv->manager, "removed",
++                                  G_CALLBACK (_app_removed), dialog);
++
++        populate_model (dialog);
++}
++
++static GObject *
++gsm_properties_dialog_constructor (GType                  type,
++                                guint                  n_construct_properties,
++                                GObjectConstructParam *construct_properties)
++{
++        GsmPropertiesDialog *dialog;
++
++        dialog = GSM_PROPERTIES_DIALOG (G_OBJECT_CLASS (gsm_properties_dialog_parent_class)->constructor (type,
++                                                                                                                  n_construct_properties,
++                                                                                                                  construct_properties));
++
++        setup_dialog (dialog);
++
++        gtk_widget_show (GTK_WIDGET (dialog));
++
++        return G_OBJECT (dialog);
++}
++
++static void
++gsm_properties_dialog_dispose (GObject *object)
++{
++        GsmPropertiesDialog *dialog;
++
++        g_return_if_fail (object != NULL);
++        g_return_if_fail (GSM_IS_PROPERTIES_DIALOG (object));
++
++        dialog = GSM_PROPERTIES_DIALOG (object);
++
++        if (dialog->priv->xml != NULL) {
++                g_object_unref (dialog->priv->xml);
++                dialog->priv->xml = NULL;
++        }
++
++        if (dialog->priv->settings != NULL) {
++                g_object_unref (dialog->priv->settings);
++                dialog->priv->settings = NULL;
++        }
++
++        G_OBJECT_CLASS (gsm_properties_dialog_parent_class)->dispose (object);
++
++        /* it's important to do this after chaining to the parent dispose
++         * method because we want to make sure the treeview has been disposed
++         * and removed all its references to GspApp objects */
++        if (dialog->priv->manager != NULL) {
++                g_object_unref (dialog->priv->manager);
++                dialog->priv->manager = NULL;
++        }
++}
++
++static void
++gsm_properties_dialog_class_init (GsmPropertiesDialogClass *klass)
++{
++        GObjectClass   *object_class = G_OBJECT_CLASS (klass);
++
++        object_class->constructor = gsm_properties_dialog_constructor;
++        object_class->dispose = gsm_properties_dialog_dispose;
++        object_class->finalize = gsm_properties_dialog_finalize;
++
++        g_type_class_add_private (klass, sizeof (GsmPropertiesDialogPrivate));
++}
++
++static void
++gsm_properties_dialog_init (GsmPropertiesDialog *dialog)
++{
++        GtkWidget   *content_area;
++        GtkWidget   *widget;
++        GError      *error;
++
++        dialog->priv = GSM_PROPERTIES_DIALOG_GET_PRIVATE (dialog);
++
++        dialog->priv->settings = g_settings_new (SPC_SETTINGS_SCHEMA);
++
++        dialog->priv->xml = gtk_builder_new ();
++        gtk_builder_set_translation_domain (dialog->priv->xml, GETTEXT_PACKAGE);
++
++        error = NULL;
++        if (!gtk_builder_add_from_file (dialog->priv->xml,
++                                        GTKBUILDER_DIR "/" GTKBUILDER_FILE,
++                                        &error)) {
++                if (error) {
++                        g_warning ("Could not load capplet UI file: %s",
++                                   error->message);
++                        g_error_free (error);
++                } else {
++                        g_warning ("Could not load capplet UI file.");
++                }
++        }
++
++        content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
++        widget = GTK_WIDGET (gtk_builder_get_object (dialog->priv->xml,
++                                                     "main-notebook"));
++        gtk_box_pack_start (GTK_BOX (content_area), widget, TRUE, TRUE, 0);
++
++        gtk_window_set_default_size (GTK_WINDOW (dialog), 600, 450);
++        gtk_window_set_resizable (GTK_WINDOW (dialog), TRUE);
++        gtk_container_set_border_width (GTK_CONTAINER (dialog), 6);
++        gtk_box_set_spacing (GTK_BOX (content_area), 2);
++        gtk_window_set_icon_name (GTK_WINDOW (dialog), "session-properties");
++        gtk_window_set_title (GTK_WINDOW (dialog), _("Startup Applications Preferences"));
++}
++
++static void
++gsm_properties_dialog_finalize (GObject *object)
++{
++        GsmPropertiesDialog *dialog;
++
++        g_return_if_fail (object != NULL);
++        g_return_if_fail (GSM_IS_PROPERTIES_DIALOG (object));
++
++        dialog = GSM_PROPERTIES_DIALOG (object);
++
++        g_return_if_fail (dialog->priv != NULL);
++
++        G_OBJECT_CLASS (gsm_properties_dialog_parent_class)->finalize (object);
++}
++
++GtkWidget *
++gsm_properties_dialog_new (void)
++{
++        GObject *object;
++
++        object = g_object_new (GSM_TYPE_PROPERTIES_DIALOG,
++                               NULL);
++
++        return GTK_WIDGET (object);
++}
+diff --git a/capplet/gsm-properties-dialog.h b/capplet/gsm-properties-dialog.h
+new file mode 100644
+index 0000000..df4915e
+--- /dev/null
++++ b/capplet/gsm-properties-dialog.h
+@@ -0,0 +1,57 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
++ *
++ * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ */
++
++#ifndef __GSM_PROPERTIES_DIALOG_H
++#define __GSM_PROPERTIES_DIALOG_H
++
++#include <glib-object.h>
++#include <gtk/gtk.h>
++
++G_BEGIN_DECLS
++
++#define GSM_TYPE_PROPERTIES_DIALOG         (gsm_properties_dialog_get_type ())
++#define GSM_PROPERTIES_DIALOG(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), GSM_TYPE_PROPERTIES_DIALOG, GsmPropertiesDialog))
++#define GSM_PROPERTIES_DIALOG_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), GSM_TYPE_PROPERTIES_DIALOG, GsmPropertiesDialogClass))
++#define GSM_IS_PROPERTIES_DIALOG(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSM_TYPE_PROPERTIES_DIALOG))
++#define GSM_IS_PROPERTIES_DIALOG_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), GSM_TYPE_PROPERTIES_DIALOG))
++#define GSM_PROPERTIES_DIALOG_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSM_TYPE_PROPERTIES_DIALOG, GsmPropertiesDialogClass))
++
++typedef struct GsmPropertiesDialogPrivate GsmPropertiesDialogPrivate;
++
++typedef struct
++{
++        GtkDialog                   parent;
++        GsmPropertiesDialogPrivate *priv;
++} GsmPropertiesDialog;
++
++typedef struct
++{
++        GtkDialogClass   parent_class;
++} GsmPropertiesDialogClass;
++
++GType                  gsm_properties_dialog_get_type           (void);
++
++GtkWidget            * gsm_properties_dialog_new                (void);
++
++#define GSM_PROPERTIES_ICON_SIZE GTK_ICON_SIZE_LARGE_TOOLBAR
++
++G_END_DECLS
++
++#endif /* __GSM_PROPERTIES_DIALOG_H */
+diff --git a/capplet/gsp-app-manager.c b/capplet/gsp-app-manager.c
+new file mode 100644
+index 0000000..bcd6d40
+--- /dev/null
++++ b/capplet/gsp-app-manager.c
+@@ -0,0 +1,593 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
++ *
++ * Copyright (C) 1999 Free Software Foundation, Inc.
++ * Copyright (C) 2007, 2009 Vincent Untz.
++ * Copyright (C) 2008 Lucas Rocha.
++ * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ */
++
++#include <string.h>
++
++#include "gsm-util.h"
++#include "gsp-app.h"
++
++#include "gsp-app-manager.h"
++
++static GspAppManager *manager = NULL;
++
++typedef struct {
++        char         *dir;
++        int           index;
++        GFileMonitor *monitor;
++} GspXdgDir;
++
++struct _GspAppManagerPrivate {
++        GSList *apps;
++        GSList *dirs;
++};
++
++#define GSP_APP_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSP_TYPE_APP_MANAGER, GspAppManagerPrivate))
++
++
++enum {
++        ADDED,
++        REMOVED,
++        LAST_SIGNAL
++};
++
++static guint gsp_app_manager_signals[LAST_SIGNAL] = { 0 };
++
++
++G_DEFINE_TYPE (GspAppManager, gsp_app_manager, G_TYPE_OBJECT)
++
++static void     gsp_app_manager_dispose      (GObject       *object);
++static void     gsp_app_manager_finalize     (GObject       *object);
++static void     _gsp_app_manager_app_unref   (GspApp        *app,
++                                              GspAppManager *manager);
++static void     _gsp_app_manager_app_removed (GspAppManager *manager,
++                                              GspApp        *app);
++
++static GspXdgDir *
++_gsp_xdg_dir_new (const char *dir,
++                  int         index)
++{
++        GspXdgDir *xdgdir;
++
++        xdgdir = g_slice_new (GspXdgDir);
++
++        xdgdir->dir = g_strdup (dir);
++        xdgdir->index = index;
++        xdgdir->monitor = NULL;
++
++        return xdgdir;
++}
++
++static void
++_gsp_xdg_dir_free (GspXdgDir *xdgdir)
++{
++        if (xdgdir->dir) {
++                g_free (xdgdir->dir);
++                xdgdir->dir = NULL;
++        }
++
++        if (xdgdir->monitor) {
++                g_file_monitor_cancel (xdgdir->monitor);
++                g_object_unref (xdgdir->monitor);
++                xdgdir->monitor = NULL;
++        }
++
++        g_slice_free (GspXdgDir, xdgdir);
++}
++
++static void
++gsp_app_manager_class_init (GspAppManagerClass *class)
++{
++        GObjectClass *gobject_class = G_OBJECT_CLASS (class);
++
++        gobject_class->dispose  = gsp_app_manager_dispose;
++        gobject_class->finalize = gsp_app_manager_finalize;
++
++        gsp_app_manager_signals[ADDED] =
++                g_signal_new ("added",
++                              G_TYPE_FROM_CLASS (gobject_class),
++                              G_SIGNAL_RUN_LAST,
++                              G_STRUCT_OFFSET (GspAppManagerClass,
++                                               added),
++                              NULL,
++                              NULL,
++                              g_cclosure_marshal_VOID__OBJECT,
++                              G_TYPE_NONE, 1, G_TYPE_OBJECT);
++
++        gsp_app_manager_signals[REMOVED] =
++                g_signal_new ("removed",
++                              G_TYPE_FROM_CLASS (gobject_class),
++                              G_SIGNAL_RUN_LAST,
++                              G_STRUCT_OFFSET (GspAppManagerClass,
++                                               removed),
++                              NULL,
++                              NULL,
++                              g_cclosure_marshal_VOID__OBJECT,
++                              G_TYPE_NONE, 1, G_TYPE_OBJECT);
++
++        g_type_class_add_private (class, sizeof (GspAppManagerPrivate));
++}
++
++static void
++gsp_app_manager_init (GspAppManager *manager)
++{
++        manager->priv = GSP_APP_MANAGER_GET_PRIVATE (manager);
++
++        memset (manager->priv, 0, sizeof (GspAppManagerPrivate));
++}
++
++static void
++gsp_app_manager_dispose (GObject *object)
++{
++        GspAppManager *manager;
++
++        g_return_if_fail (object != NULL);
++        g_return_if_fail (GSP_IS_APP_MANAGER (object));
++
++        manager = GSP_APP_MANAGER (object);
++
++        /* we unref GspApp objects in dispose since they might need to
++         * reference us during their dispose/finalize */
++        g_slist_foreach (manager->priv->apps,
++                         (GFunc) _gsp_app_manager_app_unref, manager);
++        g_slist_free (manager->priv->apps);
++        manager->priv->apps = NULL;
++
++        G_OBJECT_CLASS (gsp_app_manager_parent_class)->dispose (object);
++}
++
++static void
++gsp_app_manager_finalize (GObject *object)
++{
++        GspAppManager *manager;
++
++        g_return_if_fail (object != NULL);
++        g_return_if_fail (GSP_IS_APP_MANAGER (object));
++
++        manager = GSP_APP_MANAGER (object);
++
++        g_slist_foreach (manager->priv->dirs,
++                         (GFunc) _gsp_xdg_dir_free, NULL);
++        g_slist_free (manager->priv->dirs);
++        manager->priv->dirs = NULL;
++
++        G_OBJECT_CLASS (gsp_app_manager_parent_class)->finalize (object);
++
++        manager = NULL;
++}
++
++static void
++_gsp_app_manager_emit_added (GspAppManager *manager,
++                             GspApp        *app)
++{
++        g_signal_emit (G_OBJECT (manager), gsp_app_manager_signals[ADDED],
++                       0, app);
++}
++
++static void
++_gsp_app_manager_emit_removed (GspAppManager *manager,
++                               GspApp        *app)
++{
++        g_signal_emit (G_OBJECT (manager), gsp_app_manager_signals[REMOVED],
++                       0, app);
++}
++
++/*
++ * Directories
++ */
++
++static int
++gsp_app_manager_get_dir_index (GspAppManager *manager,
++                               const char    *dir)
++{
++        GSList    *l;
++        GspXdgDir *xdgdir;
++
++        g_return_val_if_fail (GSP_IS_APP_MANAGER (manager), -1);
++        g_return_val_if_fail (dir != NULL, -1);
++
++        for (l = manager->priv->dirs; l != NULL; l = l->next) {
++                xdgdir = l->data;
++                if (strcmp (dir, xdgdir->dir) == 0) {
++                        return xdgdir->index;
++                }
++        }
++
++        return -1;
++}
++
++const char *
++gsp_app_manager_get_dir (GspAppManager *manager,
++                         unsigned int   index)
++{
++        GSList    *l;
++        GspXdgDir *xdgdir;
++
++        g_return_val_if_fail (GSP_IS_APP_MANAGER (manager), NULL);
++
++        for (l = manager->priv->dirs; l != NULL; l = l->next) {
++                xdgdir = l->data;
++                if (index == xdgdir->index) {
++                        return xdgdir->dir;
++                }
++        }
++
++        return NULL;
++}
++
++static int
++_gsp_app_manager_find_dir_with_basename (GspAppManager *manager,
++                                         const char    *basename,
++                                         int            minimum_index)
++{
++        GSList    *l;
++        GspXdgDir *xdgdir;
++        char      *path;
++        GKeyFile  *keyfile;
++        int        result = -1;
++
++        path = NULL;
++        keyfile = g_key_file_new ();
++
++        for (l = manager->priv->dirs; l != NULL; l = l->next) {
++                xdgdir = l->data;
++
++                if (xdgdir->index <= minimum_index) {
++                        continue;
++                }
++
++                g_free (path);
++                path = g_build_filename (xdgdir->dir, basename, NULL);
++                if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
++                        continue;
++                }
++
++                if (!g_key_file_load_from_file (keyfile, path,
++                                                G_KEY_FILE_NONE, NULL)) {
++                        continue;
++                }
++
++                /* the file exists and is readable */
++                if (result == -1) {
++                        result = xdgdir->index;
++                } else {
++                        result = MIN (result, xdgdir->index);
++                }
++        }
++
++        g_key_file_free (keyfile);
++        g_free (path);
++
++        return result;
++}
++
++static void
++_gsp_app_manager_handle_delete (GspAppManager *manager,
++                                GspApp        *app,
++                                const char    *basename,
++                                int            index)
++{
++        unsigned int position;
++        unsigned int system_position;
++
++        position = gsp_app_get_xdg_position (app);
++        system_position = gsp_app_get_xdg_system_position (app);
++
++        if (system_position < index) {
++                /* it got deleted, but we don't even care about it */
++                return;
++        }
++
++        if (index < position) {
++                /* it got deleted, but in a position earlier than the current
++                 * one. This happens when the user file was changed and became
++                 * identical to the system file; in this case, the user file is
++                 * simply removed. */
++                 g_assert (index == 0);
++                 return;
++        }
++
++        if (position == index &&
++            (system_position == index || system_position == G_MAXUINT)) {
++                /* the file used by the user was deleted, and there's no other
++                 * file in system directories. So it really got deleted. */
++                _gsp_app_manager_app_removed (manager, app);
++                return;
++        }
++
++        if (system_position == index) {
++                /* then we know that position != index; we just hae to tell
++                 * GspApp if there's still a system directory containing this
++                 * basename */
++                int new_system;
++
++                new_system = _gsp_app_manager_find_dir_with_basename (manager,
++                                                                      basename,
++                                                                      index);
++                if (new_system < 0) {
++                        gsp_app_set_xdg_system_position (app, G_MAXUINT);
++                } else {
++                        gsp_app_set_xdg_system_position (app, new_system);
++                }
++
++                return;
++        }
++
++        if (position == index) {
++                /* then we know that system_position != G_MAXUINT; we need to
++                 * tell GspApp to change position to system_position */
++                const char *dir;
++
++                dir = gsp_app_manager_get_dir (manager, system_position);
++                if (dir) {
++                        char *path;
++
++                        path = g_build_filename (dir, basename, NULL);
++                        gsp_app_reload_at (app, path,
++                                           (unsigned int) system_position);
++                        g_free (path);
++                } else {
++                        _gsp_app_manager_app_removed (manager, app);
++                }
++
++                return;
++        }
++
++        g_assert_not_reached ();
++}
++
++static gboolean
++gsp_app_manager_xdg_dir_monitor (GFileMonitor      *monitor,
++                                 GFile             *child,
++                                 GFile             *other_file,
++                                 GFileMonitorEvent  flags,
++                                 gpointer           data)
++{
++        GspAppManager *manager;
++        GspApp        *old_app;
++        GspApp        *app;
++        GFile         *parent;
++        char          *basename;
++        char          *dir;
++        char          *path;
++        int            index;
++
++        manager = GSP_APP_MANAGER (data);
++
++        basename = g_file_get_basename (child);
++        if (!g_str_has_suffix (basename, ".desktop")) {
++                /* not a desktop file, we can ignore */
++                g_free (basename);
++                return TRUE;
++        }
++        old_app = gsp_app_manager_find_app_with_basename (manager, basename);
++
++        parent = g_file_get_parent (child);
++        dir = g_file_get_path (parent);
++        g_object_unref (parent);
++
++        index = gsp_app_manager_get_dir_index (manager, dir);
++        if (index < 0) {
++                /* not a directory we know; should never happen, though */
++                g_free (dir);
++                return TRUE;
++        }
++
++        path = g_file_get_path (child);
++
++        switch (flags) {
++        case G_FILE_MONITOR_EVENT_CHANGED:
++        case G_FILE_MONITOR_EVENT_CREATED:
++                /* we just do as if it was a new file: GspApp is clever enough
++                 * to do the right thing */
++                app = gsp_app_new (path, (unsigned int) index);
++
++                /* we didn't have this app before, so add it */
++                if (old_app == NULL && app != NULL) {
++                        gsp_app_manager_add (manager, app);
++                        g_object_unref (app);
++                }
++                /* else: it was just updated, GspApp took care of
++                 * sending the event */
++                break;
++        case G_FILE_MONITOR_EVENT_DELETED:
++                if (!old_app) {
++                        /* it got deleted, but we don't know about it, so
++                         * nothing to do */
++                        break;
++                }
++
++                _gsp_app_manager_handle_delete (manager, old_app,
++                                                basename, index);
++                break;
++        default:
++                break;
++        }
++
++        g_free (path);
++        g_free (dir);
++        g_free (basename);
++
++        return TRUE;
++}
++
++/*
++ * Initialization
++ */
++
++static void
++_gsp_app_manager_fill_from_dir (GspAppManager *manager,
++                                GspXdgDir     *xdgdir)
++{
++        GFile      *file;
++        GDir       *dir;
++        const char *name;
++
++        file = g_file_new_for_path (xdgdir->dir);
++        xdgdir->monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE,
++                                                    NULL, NULL);
++        g_object_unref (file);
++
++        if (xdgdir->monitor) {
++                g_signal_connect (xdgdir->monitor, "changed",
++                                  G_CALLBACK (gsp_app_manager_xdg_dir_monitor),
++                                  manager);
++        }
++
++        dir = g_dir_open (xdgdir->dir, 0, NULL);
++        if (!dir) {
++                return;
++        }
++
++        while ((name = g_dir_read_name (dir))) {
++                GspApp *app;
++                char   *desktop_file_path;
++
++                if (!g_str_has_suffix (name, ".desktop")) {
++                        continue;
++                }
++
++                desktop_file_path = g_build_filename (xdgdir->dir, name, NULL);
++                app = gsp_app_new (desktop_file_path, xdgdir->index);
++
++                if (app != NULL) {
++                        gsp_app_manager_add (manager, app);
++                        g_object_unref (app);
++                }
++
++                g_free (desktop_file_path);
++        }
++
++        g_dir_close (dir);
++}
++
++void
++gsp_app_manager_fill (GspAppManager *manager)
++{
++        char **autostart_dirs;
++        int    i;
++
++        if (manager->priv->apps != NULL)
++                return;
++
++        autostart_dirs = gsm_util_get_autostart_dirs ();
++        /* we always assume that the first directory is the user one */
++        g_assert (g_str_has_prefix (autostart_dirs[0],
++                                    g_get_user_config_dir ()));
++
++        for (i = 0; autostart_dirs[i] != NULL; i++) {
++                GspXdgDir *xdgdir;
++
++                if (gsp_app_manager_get_dir_index (manager,
++                                                   autostart_dirs[i]) >= 0) {
++                        continue;
++                }
++
++                xdgdir = _gsp_xdg_dir_new (autostart_dirs[i], i);
++                manager->priv->dirs = g_slist_prepend (manager->priv->dirs,
++                                                       xdgdir);
++
++                _gsp_app_manager_fill_from_dir (manager, xdgdir);
++        }
++
++        g_strfreev (autostart_dirs);
++}
++
++/*
++ * App handling
++ */
++
++static void
++_gsp_app_manager_app_unref (GspApp        *app,
++                            GspAppManager *manager)
++{
++        g_signal_handlers_disconnect_by_func (app,
++                                              _gsp_app_manager_app_removed,
++                                              manager);
++        g_object_unref (app);
++}
++
++static void
++_gsp_app_manager_app_removed (GspAppManager *manager,
++                              GspApp        *app)
++{
++        _gsp_app_manager_emit_removed (manager, app);
++        manager->priv->apps = g_slist_remove (manager->priv->apps, app);
++        _gsp_app_manager_app_unref (app, manager);
++}
++
++void
++gsp_app_manager_add (GspAppManager *manager,
++                     GspApp        *app)
++{
++        g_return_if_fail (GSP_IS_APP_MANAGER (manager));
++        g_return_if_fail (GSP_IS_APP (app));
++
++        manager->priv->apps = g_slist_prepend (manager->priv->apps,
++                                               g_object_ref (app));
++        g_signal_connect_swapped (app, "removed",
++                                  G_CALLBACK (_gsp_app_manager_app_removed),
++                                  manager);
++        _gsp_app_manager_emit_added (manager, app);
++}
++
++GspApp *
++gsp_app_manager_find_app_with_basename (GspAppManager *manager,
++                                        const char    *basename)
++{
++        GSList *l;
++        GspApp *app;
++
++        g_return_val_if_fail (GSP_IS_APP_MANAGER (manager), NULL);
++        g_return_val_if_fail (basename != NULL, NULL);
++
++        for (l = manager->priv->apps; l != NULL; l = l->next) {
++                app = GSP_APP (l->data);
++                if (strcmp (basename, gsp_app_get_basename (app)) == 0)
++                        return app;
++        }
++
++        return NULL;
++}
++
++/*
++ * Singleton
++ */
++
++GspAppManager *
++gsp_app_manager_get (void)
++{
++        if (manager == NULL) {
++                manager = g_object_new (GSP_TYPE_APP_MANAGER, NULL);
++                return manager;
++        } else {
++                return g_object_ref (manager);
++        }
++}
++
++GSList *
++gsp_app_manager_get_apps (GspAppManager *manager)
++{
++        g_return_val_if_fail (GSP_IS_APP_MANAGER (manager), NULL);
++
++        return g_slist_copy (manager->priv->apps);
++}
+diff --git a/capplet/gsp-app-manager.h b/capplet/gsp-app-manager.h
+new file mode 100644
+index 0000000..777f8d6
+--- /dev/null
++++ b/capplet/gsp-app-manager.h
+@@ -0,0 +1,81 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
++ *
++ * Copyright (C) 1999 Free Software Foundation, Inc.
++ * Copyright (C) 2007, 2009 Vincent Untz.
++ * Copyright (C) 2008 Lucas Rocha.
++ * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ */
++
++#ifndef __GSP_APP_MANAGER_H
++#define __GSP_APP_MANAGER_H
++
++#include <glib-object.h>
++
++#include <gsp-app.h>
++
++G_BEGIN_DECLS
++
++#define GSP_TYPE_APP_MANAGER            (gsp_app_manager_get_type ())
++#define GSP_APP_MANAGER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSP_TYPE_APP_MANAGER, GspAppManager))
++#define GSP_APP_MANAGER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GSP_TYPE_APP_MANAGER, GspAppManagerClass))
++#define GSP_IS_APP_MANAGER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSP_TYPE_APP_MANAGER))
++#define GSP_IS_APP_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSP_TYPE_APP_MANAGER))
++#define GSP_APP_MANAGER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GSP_TYPE_APP_MANAGER, GspAppManagerClass))
++
++typedef struct _GspAppManager        GspAppManager;
++typedef struct _GspAppManagerClass   GspAppManagerClass;
++
++typedef struct _GspAppManagerPrivate GspAppManagerPrivate;
++
++struct _GspAppManagerClass
++{
++        GObjectClass parent_class;
++
++        void (* added)   (GspAppManager *manager,
++                          GspApp        *app);
++        void (* removed) (GspAppManager *manager,
++                          GspApp        *app);
++};
++
++struct _GspAppManager
++{
++        GObject parent_instance;
++
++        GspAppManagerPrivate *priv;
++};
++
++GType           gsp_app_manager_get_type               (void);
++
++GspAppManager  *gsp_app_manager_get                    (void);
++
++void            gsp_app_manager_fill                   (GspAppManager *manager);
++
++GSList         *gsp_app_manager_get_apps               (GspAppManager *manager);
++
++GspApp         *gsp_app_manager_find_app_with_basename (GspAppManager *manager,
++                                                        const char    *basename);
++
++const char     *gsp_app_manager_get_dir                (GspAppManager *manager,
++                                                        unsigned int   index);
++
++void            gsp_app_manager_add                    (GspAppManager *manager,
++                                                        GspApp        *app);
++
++G_END_DECLS
++
++#endif /* __GSP_APP_MANAGER_H */
+diff --git a/capplet/gsp-app.c b/capplet/gsp-app.c
+new file mode 100644
+index 0000000..1fa5496
+--- /dev/null
++++ b/capplet/gsp-app.c
+@@ -0,0 +1,1129 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
++ *
++ * Copyright (C) 1999 Free Software Foundation, Inc.
++ * Copyright (C) 2007, 2009 Vincent Untz.
++ * Copyright (C) 2008 Lucas Rocha.
++ * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
++
++#include <string.h>
++#include <sys/stat.h>
++
++#include <glib/gi18n.h>
++#include <glib/gstdio.h>
++
++#include "gsm-app-dialog.h"
++#include "gsm-properties-dialog.h"
++#include "gsm-util.h"
++#include "gsp-app-manager.h"
++#include "gsp-keyfile.h"
++
++#include "gsp-app.h"
++
++#define GSP_APP_SAVE_DELAY 2
++
++#define GSP_ASP_SAVE_MASK_HIDDEN     0x0001
++#define GSP_ASP_SAVE_MASK_ENABLED    0x0002
++#define GSP_ASP_SAVE_MASK_NAME       0x0004
++#define GSP_ASP_SAVE_MASK_EXEC       0x0008
++#define GSP_ASP_SAVE_MASK_COMMENT    0x0010
++#define GSP_ASP_SAVE_MASK_NO_DISPLAY 0x0020
++#define GSP_ASP_SAVE_MASK_ALL        0xffff
++
++struct _GspAppPrivate {
++        char         *basename;
++        char         *path;
++
++        gboolean      hidden;
++        gboolean      no_display;
++        gboolean      enabled;
++        gboolean      shown;
++
++        char         *name;
++        char         *exec;
++        char         *comment;
++        char         *icon;
++
++        GIcon        *gicon;
++        char         *description;
++
++        /* position of the directory in the XDG environment variable */
++        unsigned int  xdg_position;
++        /* position of the first system directory in the XDG env var containing
++         * this autostart app too (G_MAXUINT means none) */
++        unsigned int  xdg_system_position;
++
++        unsigned int  save_timeout;
++        /* mask of what has changed */
++        unsigned int  save_mask;
++        /* path that contains the original file that needs to be saved */
++        char         *old_system_path;
++        /* after writing to file, we skip the next file monitor event of type
++         * CHANGED */
++        gboolean      skip_next_monitor_event;
++};
++
++#define GSP_APP_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSP_TYPE_APP, GspAppPrivate))
++
++
++enum {
++        CHANGED,
++        REMOVED,
++        LAST_SIGNAL
++};
++
++static guint gsp_app_signals[LAST_SIGNAL] = { 0 };
++
++
++G_DEFINE_TYPE (GspApp, gsp_app, G_TYPE_OBJECT)
++
++static void     gsp_app_dispose  (GObject *object);
++static void     gsp_app_finalize (GObject *object);
++static gboolean _gsp_app_save    (gpointer data);
++
++
++static gboolean
++_gsp_str_equal (const char *a,
++                const char *b)
++{
++        if (g_strcmp0 (a, b) == 0) {
++                return TRUE;
++        }
++
++        if (a && !b && a[0] == '\0') {
++                return TRUE;
++        }
++
++        if (b && !a && b[0] == '\0') {
++                return TRUE;
++        }
++
++        return FALSE;
++}
++
++
++static void
++gsp_app_class_init (GspAppClass *class)
++{
++        GObjectClass *gobject_class = G_OBJECT_CLASS (class);
++
++        gobject_class->dispose  = gsp_app_dispose;
++        gobject_class->finalize = gsp_app_finalize;
++
++        gsp_app_signals[CHANGED] =
++                g_signal_new ("changed",
++                              G_TYPE_FROM_CLASS (gobject_class),
++                              G_SIGNAL_RUN_LAST,
++                              G_STRUCT_OFFSET (GspAppClass,
++                                               changed),
++                              NULL,
++                              NULL,
++                              g_cclosure_marshal_VOID__VOID,
++                              G_TYPE_NONE, 0);
++
++        gsp_app_signals[REMOVED] =
++                g_signal_new ("removed",
++                              G_TYPE_FROM_CLASS (gobject_class),
++                              G_SIGNAL_RUN_LAST,
++                              G_STRUCT_OFFSET (GspAppClass,
++                                               removed),
++                              NULL,
++                              NULL,
++                              g_cclosure_marshal_VOID__VOID,
++                              G_TYPE_NONE, 0);
++
++        g_type_class_add_private (class, sizeof (GspAppPrivate));
++}
++
++static void
++gsp_app_init (GspApp *app)
++{
++        app->priv = GSP_APP_GET_PRIVATE (app);
++
++        memset (app->priv, 0, sizeof (GspAppPrivate));
++        app->priv->xdg_position        = G_MAXUINT;
++        app->priv->xdg_system_position = G_MAXUINT;
++}
++
++static void
++_gsp_app_free_reusable_data (GspApp *app)
++{
++        if (app->priv->path) {
++                g_free (app->priv->path);
++                app->priv->path = NULL;
++        }
++
++        if (app->priv->name) {
++                g_free (app->priv->name);
++                app->priv->name = NULL;
++        }
++
++        if (app->priv->exec) {
++                g_free (app->priv->exec);
++                app->priv->exec = NULL;
++        }
++
++        if (app->priv->comment) {
++                g_free (app->priv->comment);
++                app->priv->comment = NULL;
++        }
++
++        if (app->priv->icon) {
++                g_free (app->priv->icon);
++                app->priv->icon = NULL;
++        }
++
++        if (app->priv->gicon) {
++                g_object_unref (app->priv->gicon);
++                app->priv->gicon = NULL;
++        }
++
++        if (app->priv->description) {
++                g_free (app->priv->description);
++                app->priv->description = NULL;
++        }
++
++        if (app->priv->old_system_path) {
++                g_free (app->priv->old_system_path);
++                app->priv->old_system_path = NULL;
++        }
++}
++
++static void
++gsp_app_dispose (GObject *object)
++{
++        GspApp *app;
++
++        g_return_if_fail (object != NULL);
++        g_return_if_fail (GSP_IS_APP (object));
++
++        app = GSP_APP (object);
++
++        /* we save in dispose since we might need to reference GspAppManager */
++        if (app->priv->save_timeout) {
++                g_source_remove (app->priv->save_timeout);
++                app->priv->save_timeout = 0;
++
++                /* save now */
++                _gsp_app_save (app);
++        }
++
++        G_OBJECT_CLASS (gsp_app_parent_class)->dispose (object);
++}
++
++static void
++gsp_app_finalize (GObject *object)
++{
++        GspApp *app;
++
++        g_return_if_fail (object != NULL);
++        g_return_if_fail (GSP_IS_APP (object));
++
++        app = GSP_APP (object);
++
++        if (app->priv->basename) {
++                g_free (app->priv->basename);
++                app->priv->basename = NULL;
++        }
++
++        _gsp_app_free_reusable_data (app);
++
++        G_OBJECT_CLASS (gsp_app_parent_class)->finalize (object);
++}
++
++static void
++_gsp_app_emit_changed (GspApp *app)
++{
++        g_signal_emit (G_OBJECT (app), gsp_app_signals[CHANGED], 0);
++}
++
++static void
++_gsp_app_emit_removed (GspApp *app)
++{
++        g_signal_emit (G_OBJECT (app), gsp_app_signals[REMOVED], 0);
++}
++
++static void
++_gsp_app_update_description (GspApp *app)
++{
++        const char *primary;
++        const char *secondary;
++
++        if (!gsm_util_text_is_blank (app->priv->name)) {
++                primary = app->priv->name;
++        } else if (!gsm_util_text_is_blank (app->priv->exec)) {
++                primary = app->priv->exec;
++        } else {
++                primary = _("No name");
++        }
++
++        if (!gsm_util_text_is_blank (app->priv->comment)) {
++                secondary = app->priv->comment;
++        } else {
++                secondary = _("No description");
++        }
++
++        g_free (app->priv->description);
++        app->priv->description = g_markup_printf_escaped ("<b>%s</b>\n%s",
++                                                          primary,
++                                                          secondary);
++}
++
++/*
++ * Saving
++ */
++
++static void
++_gsp_ensure_user_autostart_dir (void)
++{
++        char *dir;
++
++        dir = g_build_filename (g_get_user_config_dir (), "autostart", NULL);
++        g_mkdir_with_parents (dir, S_IRWXU);
++
++        g_free (dir);
++}
++
++static char *
++_gsp_get_current_desktop ()
++{
++        static char *current_desktop = NULL;
++
++        /* Support XDG_CURRENT_DESKTOP environment variable; this can be used
++         * to abuse gnome-session in non-GNOME desktops. */
++        if (!current_desktop) {
++               const char *desktop;
++
++                desktop = g_getenv ("XDG_CURRENT_DESKTOP");
++
++                /* Note: if XDG_CURRENT_DESKTOP is set but empty, do as if it
++                 * was not set */
++                if (!desktop || desktop[0] == '\0')
++                        current_desktop = g_strdup ("GNOME");
++                else
++                        current_desktop = g_strdup (desktop);
++        }
++
++        /* Using "*" means skipping desktop-related checks */
++        if (g_strcmp0 (current_desktop, "*") == 0)
++                return NULL;
++
++        return current_desktop;
++}
++
++static gboolean
++_gsp_app_user_equal_system (GspApp  *app,
++                            char   **system_path)
++{
++        GspAppManager *manager;
++        const char    *system_dir;
++        char          *path;
++        char          *str;
++        GKeyFile      *keyfile;
++
++        manager = gsp_app_manager_get ();
++        system_dir = gsp_app_manager_get_dir (manager,
++                                              app->priv->xdg_system_position);
++        g_object_unref (manager);
++        if (!system_dir) {
++                return FALSE;
++        }
++
++        path = g_build_filename (system_dir, app->priv->basename, NULL);
++
++        keyfile = g_key_file_new ();
++        if (!g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, NULL)) {
++                g_free (path);
++                g_key_file_free (keyfile);
++                return FALSE;
++        }
++
++        if (gsp_key_file_get_boolean (keyfile,
++                                      G_KEY_FILE_DESKTOP_KEY_HIDDEN,
++                                      FALSE) != app->priv->hidden ||
++            gsp_key_file_get_boolean (keyfile,
++                                      GSP_KEY_FILE_DESKTOP_KEY_AUTOSTART_ENABLED,
++                                      TRUE) != app->priv->enabled ||
++            gsp_key_file_get_shown (keyfile,
++                                    _gsp_get_current_desktop ()) != app->priv->shown) {
++                g_free (path);
++                g_key_file_free (keyfile);
++                return FALSE;
++        }
++
++        if (gsp_key_file_get_boolean (keyfile,
++                                      G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY,
++                                      FALSE) != app->priv->no_display) {
++                g_free (path);
++                g_key_file_free (keyfile);
++                return FALSE;
++        }
++
++        str = gsp_key_file_get_locale_string (keyfile,
++                                              G_KEY_FILE_DESKTOP_KEY_NAME);
++        if (!_gsp_str_equal (str, app->priv->name)) {
++                g_free (str);
++                g_free (path);
++                g_key_file_free (keyfile);
++                return FALSE;
++        }
++        g_free (str);
++
++        str = gsp_key_file_get_locale_string (keyfile,
++                                              G_KEY_FILE_DESKTOP_KEY_COMMENT);
++        if (!_gsp_str_equal (str, app->priv->comment)) {
++                g_free (str);
++                g_free (path);
++                g_key_file_free (keyfile);
++                return FALSE;
++        }
++        g_free (str);
++
++        str = gsp_key_file_get_string (keyfile,
++                                       G_KEY_FILE_DESKTOP_KEY_EXEC);
++        if (!_gsp_str_equal (str, app->priv->exec)) {
++                g_free (str);
++                g_free (path);
++                g_key_file_free (keyfile);
++                return FALSE;
++        }
++        g_free (str);
++
++        str = gsp_key_file_get_locale_string (keyfile,
++                                              G_KEY_FILE_DESKTOP_KEY_ICON);
++        if (!_gsp_str_equal (str, app->priv->icon)) {
++                g_free (str);
++                g_free (path);
++                g_key_file_free (keyfile);
++                return FALSE;
++        }
++        g_free (str);
++
++        g_key_file_free (keyfile);
++
++        *system_path = path;
++
++        return TRUE;
++}
++
++static inline void
++_gsp_app_save_done_success (GspApp *app)
++{
++        app->priv->save_mask = 0;
++
++        if (app->priv->old_system_path) {
++                g_free (app->priv->old_system_path);
++                app->priv->old_system_path = NULL;
++        }
++}
++
++static gboolean
++_gsp_app_save (gpointer data)
++{
++        GspApp   *app;
++        char     *use_path;
++        GKeyFile *keyfile;
++        GError   *error;
++
++        app = GSP_APP (data);
++
++        /* first check if removing the data from the user dir and using the
++         * data from the system dir is enough -- this helps us keep clean the
++         * user config dir by removing unneeded files */
++        if (_gsp_app_user_equal_system (app, &use_path)) {
++                if (g_file_test (app->priv->path, G_FILE_TEST_EXISTS)) {
++                        g_remove (app->priv->path);
++                }
++
++                g_free (app->priv->path);
++                app->priv->path = use_path;
++
++                app->priv->xdg_position = app->priv->xdg_system_position;
++
++                _gsp_app_save_done_success (app);
++                return FALSE;
++        }
++
++        if (app->priv->old_system_path)
++                use_path = app->priv->old_system_path;
++        else
++                use_path = app->priv->path;
++
++        keyfile = g_key_file_new ();
++
++        error = NULL;
++        g_key_file_load_from_file (keyfile, use_path,
++                                   G_KEY_FILE_KEEP_COMMENTS|G_KEY_FILE_KEEP_TRANSLATIONS,
++                                   &error);
++
++        if (error) {
++                g_error_free (error);
++                gsp_key_file_populate (keyfile);
++        }
++
++        if (app->priv->save_mask & GSP_ASP_SAVE_MASK_HIDDEN) {
++                gsp_key_file_set_boolean (keyfile,
++                                          G_KEY_FILE_DESKTOP_KEY_HIDDEN,
++                                          app->priv->hidden);
++        }
++
++        if (app->priv->save_mask & GSP_ASP_SAVE_MASK_NO_DISPLAY) {
++                gsp_key_file_set_boolean (keyfile,
++                                          G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY,
++                                          app->priv->no_display);
++        }
++
++        if (app->priv->save_mask & GSP_ASP_SAVE_MASK_ENABLED) {
++                gsp_key_file_set_boolean (keyfile,
++                                          GSP_KEY_FILE_DESKTOP_KEY_AUTOSTART_ENABLED,
++                                          app->priv->enabled);
++        }
++
++        if (app->priv->save_mask & GSP_ASP_SAVE_MASK_NAME) {
++                gsp_key_file_set_locale_string (keyfile,
++                                                G_KEY_FILE_DESKTOP_KEY_NAME,
++                                                app->priv->name);
++                gsp_key_file_ensure_C_key (keyfile, G_KEY_FILE_DESKTOP_KEY_NAME);
++        }
++
++        if (app->priv->save_mask & GSP_ASP_SAVE_MASK_COMMENT) {
++                gsp_key_file_set_locale_string (keyfile,
++                                                G_KEY_FILE_DESKTOP_KEY_COMMENT,
++                                                app->priv->comment);
++                gsp_key_file_ensure_C_key (keyfile, G_KEY_FILE_DESKTOP_KEY_COMMENT);
++        }
++
++        if (app->priv->save_mask & GSP_ASP_SAVE_MASK_EXEC) {
++                gsp_key_file_set_string (keyfile,
++                                         G_KEY_FILE_DESKTOP_KEY_EXEC,
++                                         app->priv->exec);
++        }
++
++        _gsp_ensure_user_autostart_dir ();
++        if (gsp_key_file_to_file (keyfile, app->priv->path, NULL)) {
++                app->priv->skip_next_monitor_event = TRUE;
++                _gsp_app_save_done_success (app);
++        } else {
++                g_warning ("Could not save %s file", app->priv->path);
++        }
++
++        g_key_file_free (keyfile);
++
++        app->priv->save_timeout = 0;
++        return FALSE;
++}
++
++static void
++_gsp_app_queue_save (GspApp *app)
++{
++        if (app->priv->save_timeout) {
++                g_source_remove (app->priv->save_timeout);
++                app->priv->save_timeout = 0;
++        }
++
++        /* if the file was not in the user directory, then we'll create a copy
++         * there */
++        if (app->priv->xdg_position != 0) {
++                app->priv->xdg_position = 0;
++
++                if (app->priv->old_system_path == NULL) {
++                        app->priv->old_system_path = app->priv->path;
++                        /* if old_system_path was not NULL, then it means we
++                         * tried to save and we failed; in that case, we want
++                         * to try again and use the old file as a basis again */
++                }
++
++                app->priv->path = g_build_filename (g_get_user_config_dir (),
++                                                    "autostart",
++                                                    app->priv->basename, NULL);
++        }
++
++        app->priv->save_timeout = g_timeout_add_seconds (GSP_APP_SAVE_DELAY,
++                                                         _gsp_app_save,
++                                                         app);
++}
++
++/*
++ * Accessors
++ */
++
++const char *
++gsp_app_get_basename (GspApp *app)
++{
++        g_return_val_if_fail (GSP_IS_APP (app), NULL);
++
++        return app->priv->basename;
++}
++
++const char *
++gsp_app_get_path (GspApp *app)
++{
++        g_return_val_if_fail (GSP_IS_APP (app), NULL);
++
++        return app->priv->path;
++}
++
++gboolean
++gsp_app_get_hidden (GspApp *app)
++{
++        g_return_val_if_fail (GSP_IS_APP (app), FALSE);
++
++        return app->priv->hidden;
++}
++
++gboolean
++gsp_app_get_display (GspApp *app)
++{
++        g_return_val_if_fail (GSP_IS_APP (app), FALSE);
++
++        return !app->priv->no_display;
++}
++
++gboolean
++gsp_app_get_enabled (GspApp *app)
++{
++        g_return_val_if_fail (GSP_IS_APP (app), FALSE);
++
++        return app->priv->enabled;
++}
++
++void
++gsp_app_set_enabled (GspApp   *app,
++                     gboolean  enabled)
++{
++        g_return_if_fail (GSP_IS_APP (app));
++
++        if (enabled == app->priv->enabled) {
++                return;
++        }
++
++        app->priv->enabled = enabled;
++        app->priv->save_mask |= GSP_ASP_SAVE_MASK_ENABLED;
++
++        _gsp_app_queue_save (app);
++        _gsp_app_emit_changed (app);
++}
++
++gboolean
++gsp_app_get_shown (GspApp *app)
++{
++        g_return_val_if_fail (GSP_IS_APP (app), FALSE);
++
++        return app->priv->shown;
++}
++
++const char *
++gsp_app_get_name (GspApp *app)
++{
++        g_return_val_if_fail (GSP_IS_APP (app), NULL);
++
++        return app->priv->name;
++}
++
++const char *
++gsp_app_get_exec (GspApp *app)
++{
++        g_return_val_if_fail (GSP_IS_APP (app), NULL);
++
++        return app->priv->exec;
++}
++
++const char *
++gsp_app_get_comment (GspApp *app)
++{
++        g_return_val_if_fail (GSP_IS_APP (app), NULL);
++
++        return app->priv->comment;
++}
++
++GIcon *
++gsp_app_get_icon (GspApp *app)
++{
++        g_return_val_if_fail (GSP_IS_APP (app), NULL);
++
++        if (app->priv->gicon) {
++                return g_object_ref (app->priv->gicon);
++        } else {
++                return NULL;
++        }
++}
++
++unsigned int
++gsp_app_get_xdg_position (GspApp *app)
++{
++        g_return_val_if_fail (GSP_IS_APP (app), G_MAXUINT);
++
++        return app->priv->xdg_position;
++}
++
++unsigned int
++gsp_app_get_xdg_system_position (GspApp *app)
++{
++        g_return_val_if_fail (GSP_IS_APP (app), G_MAXUINT);
++
++        return app->priv->xdg_system_position;
++}
++
++void
++gsp_app_set_xdg_system_position (GspApp       *app,
++                                 unsigned int  position)
++{
++        g_return_if_fail (GSP_IS_APP (app));
++
++        app->priv->xdg_system_position = position;
++}
++
++const char *
++gsp_app_get_description (GspApp *app)
++{
++        g_return_val_if_fail (GSP_IS_APP (app), NULL);
++
++        return app->priv->description;
++}
++
++/*
++ * High-level edition
++ */
++
++void
++gsp_app_update (GspApp     *app,
++                const char *name,
++                const char *comment,
++                const char *exec)
++{
++        gboolean    changed;
++
++        g_return_if_fail (GSP_IS_APP (app));
++
++        changed = FALSE;
++
++        if (!_gsp_str_equal (name, app->priv->name)) {
++                changed = TRUE;
++                g_free (app->priv->name);
++                app->priv->name = g_strdup (name);
++                app->priv->save_mask |= GSP_ASP_SAVE_MASK_NAME;
++        }
++
++        if (!_gsp_str_equal (comment, app->priv->comment)) {
++                changed = TRUE;
++                g_free (app->priv->comment);
++                app->priv->comment = g_strdup (comment);
++                app->priv->save_mask |= GSP_ASP_SAVE_MASK_COMMENT;
++        }
++
++        if (changed) {
++                _gsp_app_update_description (app);
++        }
++
++        if (!_gsp_str_equal (exec, app->priv->exec)) {
++                changed = TRUE;
++                g_free (app->priv->exec);
++                app->priv->exec = g_strdup (exec);
++                app->priv->save_mask |= GSP_ASP_SAVE_MASK_EXEC;
++        }
++
++        if (changed) {
++                _gsp_app_queue_save (app);
++                _gsp_app_emit_changed (app);
++        }
++}
++
++void
++gsp_app_delete (GspApp *app)
++{
++        g_return_if_fail (GSP_IS_APP (app));
++
++        if (app->priv->xdg_position == 0 &&
++            app->priv->xdg_system_position == G_MAXUINT) {
++                /* exists in user directory only */
++                if (app->priv->save_timeout) {
++                        g_source_remove (app->priv->save_timeout);
++                        app->priv->save_timeout = 0;
++                }
++
++                if (g_file_test (app->priv->path, G_FILE_TEST_EXISTS)) {
++                        g_remove (app->priv->path);
++                }
++
++                /* for extra safety */
++                app->priv->hidden = TRUE;
++                app->priv->save_mask |= GSP_ASP_SAVE_MASK_HIDDEN;
++
++                _gsp_app_emit_removed (app);
++        } else {
++                /* also exists in system directory, so we have to keep a file
++                 * in the user directory */
++                app->priv->hidden = TRUE;
++                app->priv->save_mask |= GSP_ASP_SAVE_MASK_HIDDEN;
++
++                _gsp_app_queue_save (app);
++                _gsp_app_emit_changed (app);
++        }
++}
++
++/*
++ * New autostart app
++ */
++
++void
++gsp_app_reload_at (GspApp       *app,
++                   const char   *path,
++                   unsigned int  xdg_position)
++{
++        g_return_if_fail (GSP_IS_APP (app));
++
++        app->priv->xdg_position = G_MAXUINT;
++        gsp_app_new (path, xdg_position);
++}
++
++GspApp *
++gsp_app_new (const char   *path,
++             unsigned int  xdg_position)
++{
++        GspAppManager *manager;
++        GspApp        *app;
++        GKeyFile      *keyfile;
++        char          *basename;
++        gboolean       new;
++
++        basename = g_path_get_basename (path);
++
++        manager = gsp_app_manager_get ();
++        app = gsp_app_manager_find_app_with_basename (manager, basename);
++        g_object_unref (manager);
++
++        new = (app == NULL);
++
++        if (!new) {
++                if (app->priv->xdg_position == xdg_position) {
++                        if (app->priv->skip_next_monitor_event) {
++                                app->priv->skip_next_monitor_event = FALSE;
++                                return NULL;
++                        }
++                        /* else: the file got changed but not by us, we'll
++                         * update our data from disk */
++                }
++
++                if (app->priv->xdg_position < xdg_position ||
++                    app->priv->save_timeout != 0) {
++                        /* we don't really care about this file, since we
++                         * already have something with a higher priority, or
++                         * we're going to write something in the user config
++                         * anyway.
++                         * Note: xdg_position >= 1 so it's a system dir */
++                        app->priv->xdg_system_position = MIN (xdg_position,
++                                                              app->priv->xdg_system_position);
++                        return NULL;
++                }
++        }
++
++        keyfile = g_key_file_new ();
++        if (!g_key_file_load_from_file (keyfile, path, G_KEY_FILE_NONE, NULL)) {
++                g_key_file_free (keyfile);
++                g_free (basename);
++                return NULL;
++        }
++
++        if (new) {
++                app = g_object_new (GSP_TYPE_APP, NULL);
++                app->priv->basename = basename;
++        } else {
++                g_free (basename);
++                _gsp_app_free_reusable_data (app);
++        }
++
++        app->priv->path = g_strdup (path);
++
++        app->priv->hidden = gsp_key_file_get_boolean (keyfile,
++                                                      G_KEY_FILE_DESKTOP_KEY_HIDDEN,
++                                                      FALSE);
++        app->priv->no_display = gsp_key_file_get_boolean (keyfile,
++                                                          G_KEY_FILE_DESKTOP_KEY_NO_DISPLAY,
++                                                          FALSE);
++        app->priv->enabled = gsp_key_file_get_boolean (keyfile,
++                                                       GSP_KEY_FILE_DESKTOP_KEY_AUTOSTART_ENABLED,
++                                                       TRUE);
++        app->priv->shown = gsp_key_file_get_shown (keyfile,
++                                                   _gsp_get_current_desktop ());
++
++        app->priv->name = gsp_key_file_get_locale_string (keyfile,
++                                                          G_KEY_FILE_DESKTOP_KEY_NAME);
++        app->priv->exec = gsp_key_file_get_string (keyfile,
++                                                   G_KEY_FILE_DESKTOP_KEY_EXEC);
++        app->priv->comment = gsp_key_file_get_locale_string (keyfile,
++                                                             G_KEY_FILE_DESKTOP_KEY_COMMENT);
++
++        if (gsm_util_text_is_blank (app->priv->name)) {
++                g_free (app->priv->name);
++                app->priv->name = g_strdup (app->priv->exec);
++        }
++
++        app->priv->icon = gsp_key_file_get_locale_string (keyfile,
++                                                          G_KEY_FILE_DESKTOP_KEY_ICON);
++
++        if (app->priv->icon) {
++                /* look at icon and see if it's a themed icon or not */
++                if (g_path_is_absolute (app->priv->icon)) {
++                        GFile *iconfile;
++
++                        iconfile = g_file_new_for_path (app->priv->icon);
++                        app->priv->gicon = g_file_icon_new (iconfile);
++                        g_object_unref (iconfile);
++                } else {
++                        app->priv->gicon = g_themed_icon_new (app->priv->icon);
++                }
++        } else {
++                app->priv->gicon = NULL;
++        }
++
++        g_key_file_free (keyfile);
++
++        _gsp_app_update_description (app);
++
++        if (xdg_position > 0) {
++                g_assert (xdg_position <= app->priv->xdg_system_position);
++                app->priv->xdg_system_position = xdg_position;
++        }
++        /* else we keep the old value (which is G_MAXUINT if it wasn't set) */
++        app->priv->xdg_position = xdg_position;
++
++        g_assert (!new || app->priv->save_timeout == 0);
++        app->priv->save_timeout = 0;
++        app->priv->old_system_path = NULL;
++        app->priv->skip_next_monitor_event = FALSE;
++
++        if (!new) {
++                _gsp_app_emit_changed (app);
++        }
++
++        return app;
++}
++
++static char *
++_gsp_find_free_basename (const char *suggested_basename)
++{
++        GspAppManager *manager;
++        char          *base_path;
++        char          *filename;
++        char          *basename;
++        int            i;
++
++        if (g_str_has_suffix (suggested_basename, ".desktop")) {
++                char *basename_no_ext;
++
++                basename_no_ext = g_strndup (suggested_basename,
++                                             strlen (suggested_basename) - strlen (".desktop"));
++                base_path = g_build_filename (g_get_user_config_dir (),
++                                              "autostart",
++                                              basename_no_ext, NULL);
++                g_free (basename_no_ext);
++        } else {
++                base_path = g_build_filename (g_get_user_config_dir (),
++                                              "autostart",
++                                              suggested_basename, NULL);
++        }
++
++        filename = g_strdup_printf ("%s.desktop", base_path);
++        basename = g_path_get_basename (filename);
++
++        manager = gsp_app_manager_get ();
++
++        i = 1;
++#define _GSP_FIND_MAX_TRY 10000
++        while (gsp_app_manager_find_app_with_basename (manager,
++                                                       basename) != NULL &&
++               g_file_test (filename, G_FILE_TEST_EXISTS) &&
++               i < _GSP_FIND_MAX_TRY) {
++                g_free (filename);
++                g_free (basename);
++
++                filename = g_strdup_printf ("%s-%d.desktop", base_path, i);
++                basename = g_path_get_basename (filename);
++
++                i++;
++        }
++
++        g_object_unref (manager);
++
++        g_free (base_path);
++        g_free (filename);
++
++        if (i == _GSP_FIND_MAX_TRY) {
++                g_free (basename);
++                return NULL;
++        }
++
++        return basename;
++}
++
++void
++gsp_app_create (const char *name,
++                const char *comment,
++                const char *exec)
++{
++        GspAppManager  *manager;
++        GspApp         *app;
++        char           *basename;
++        char          **argv;
++        int             argc;
++
++        g_return_if_fail (!gsm_util_text_is_blank (exec));
++
++        if (!g_shell_parse_argv (exec, &argc, &argv, NULL)) {
++                return;
++        }
++
++        basename = _gsp_find_free_basename (argv[0]);
++        g_strfreev (argv);
++        if (basename == NULL) {
++                return;
++        }
++
++        app = g_object_new (GSP_TYPE_APP, NULL);
++
++        app->priv->basename = basename;
++        app->priv->path = g_build_filename (g_get_user_config_dir (),
++                                            "autostart",
++                                            app->priv->basename, NULL);
++
++        app->priv->hidden = FALSE;
++        app->priv->no_display = FALSE;
++        app->priv->enabled = TRUE;
++        app->priv->shown = TRUE;
++
++        if (!gsm_util_text_is_blank (name)) {
++                app->priv->name = g_strdup (name);
++        } else {
++                app->priv->name = g_strdup (exec);
++        }
++        app->priv->exec = g_strdup (exec);
++        app->priv->comment = g_strdup (comment);
++        app->priv->icon = NULL;
++
++        app->priv->gicon = NULL;
++        _gsp_app_update_description (app);
++
++        /* by definition */
++        app->priv->xdg_position = 0;
++        app->priv->xdg_system_position = G_MAXUINT;
++
++        app->priv->save_timeout = 0;
++        app->priv->save_mask |= GSP_ASP_SAVE_MASK_ALL;
++        app->priv->old_system_path = NULL;
++        app->priv->skip_next_monitor_event = FALSE;
++
++        _gsp_app_queue_save (app);
++
++        manager = gsp_app_manager_get ();
++        gsp_app_manager_add (manager, app);
++        g_object_unref (app);
++        g_object_unref (manager);
++}
++
++gboolean
++gsp_app_copy_desktop_file (const char *uri)
++{
++        GspAppManager *manager;
++        GspApp        *app;
++        GFile         *src_file;
++        char          *src_basename;
++        char          *dst_basename;
++        char          *dst_path;
++        GFile         *dst_file;
++        gboolean       changed;
++
++        g_return_val_if_fail (uri != NULL, FALSE);
++
++        src_file = g_file_new_for_uri (uri);
++        src_basename = g_file_get_basename (src_file);
++
++        if (src_basename == NULL) {
++                g_object_unref (src_file);
++                return FALSE;
++        }
++
++        dst_basename = _gsp_find_free_basename (src_basename);
++        g_free (src_basename);
++
++        if (dst_basename == NULL) {
++                g_object_unref (src_file);
++                return FALSE;
++        }
++
++        dst_path = g_build_filename (g_get_user_config_dir (),
++                                     "autostart",
++                                     dst_basename, NULL);
++        g_free (dst_basename);
++
++        dst_file = g_file_new_for_path (dst_path);
++
++        _gsp_ensure_user_autostart_dir ();
++        if (!g_file_copy (src_file, dst_file, G_FILE_COPY_NONE,
++                          NULL, NULL, NULL, NULL)) {
++                g_object_unref (src_file);
++                g_object_unref (dst_file);
++                g_free (dst_path);
++                return FALSE;
++        }
++
++        g_object_unref (src_file);
++        g_object_unref (dst_file);
++
++        app = gsp_app_new (dst_path, 0);
++        if (!app) {
++                g_remove (dst_path);
++                g_free (dst_path);
++                return FALSE;
++        }
++
++        g_free (dst_path);
++
++        changed = FALSE;
++        if (app->priv->hidden) {
++                changed = TRUE;
++                app->priv->hidden = FALSE;
++                app->priv->save_mask |= GSP_ASP_SAVE_MASK_HIDDEN;
++        }
++
++        if (app->priv->no_display) {
++                changed = TRUE;
++                app->priv->no_display = FALSE;
++                app->priv->save_mask |= GSP_ASP_SAVE_MASK_NO_DISPLAY;
++        }
++
++        if (!app->priv->enabled) {
++                changed = TRUE;
++                app->priv->enabled = TRUE;
++                app->priv->save_mask |= GSP_ASP_SAVE_MASK_ENABLED;
++        }
++
++        if (changed) {
++                _gsp_app_queue_save (app);
++        }
++
++        manager = gsp_app_manager_get ();
++        gsp_app_manager_add (manager, app);
++        g_object_unref (app);
++        g_object_unref (manager);
++
++        return TRUE;
++}
+diff --git a/capplet/gsp-app.h b/capplet/gsp-app.h
+new file mode 100644
+index 0000000..a199795
+--- /dev/null
++++ b/capplet/gsp-app.h
+@@ -0,0 +1,108 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
++ *
++ * Copyright (C) 1999 Free Software Foundation, Inc.
++ * Copyright (C) 2007, 2009 Vincent Untz.
++ * Copyright (C) 2008 Lucas Rocha.
++ * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ */
++
++#ifndef __GSP_APP_H
++#define __GSP_APP_H
++
++#include <glib-object.h>
++#include <gio/gio.h>
++
++G_BEGIN_DECLS
++
++#define GSP_TYPE_APP            (gsp_app_get_type ())
++#define GSP_APP(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSP_TYPE_APP, GspApp))
++#define GSP_APP_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GSP_TYPE_APP, GspAppClass))
++#define GSP_IS_APP(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSP_TYPE_APP))
++#define GSP_IS_APP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSP_TYPE_APP))
++#define GSP_APP_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GSP_TYPE_APP, GspAppClass))
++
++typedef struct _GspApp        GspApp;
++typedef struct _GspAppClass   GspAppClass;
++
++typedef struct _GspAppPrivate GspAppPrivate;
++
++struct _GspAppClass
++{
++        GObjectClass parent_class;
++
++        void (* changed) (GspApp *app);
++        void (* removed) (GspApp *app);
++};
++
++struct _GspApp
++{
++        GObject parent_instance;
++
++        GspAppPrivate *priv;
++};
++
++GType            gsp_app_get_type          (void);
++
++void             gsp_app_create            (const char   *name,
++                                            const char   *comment,
++                                            const char   *exec);
++void             gsp_app_update            (GspApp       *app,
++                                            const char   *name,
++                                            const char   *comment,
++                                            const char   *exec);
++
++gboolean         gsp_app_copy_desktop_file (const char   *uri);
++
++void             gsp_app_delete            (GspApp       *app);
++
++const char      *gsp_app_get_basename      (GspApp       *app);
++const char      *gsp_app_get_path          (GspApp       *app);
++
++gboolean         gsp_app_get_hidden        (GspApp       *app);
++gboolean         gsp_app_get_display       (GspApp       *app);
++
++gboolean         gsp_app_get_enabled       (GspApp       *app);
++void             gsp_app_set_enabled       (GspApp       *app,
++                                            gboolean      enabled);
++
++gboolean         gsp_app_get_shown         (GspApp       *app);
++
++const char      *gsp_app_get_name          (GspApp       *app);
++const char      *gsp_app_get_exec          (GspApp       *app);
++const char      *gsp_app_get_comment       (GspApp       *app);
++
++const char      *gsp_app_get_description   (GspApp       *app);
++GIcon           *gsp_app_get_icon          (GspApp       *app);
++
++/* private interface for GspAppManager only */
++
++GspApp          *gsp_app_new                      (const char   *path,
++                                                   unsigned int  xdg_position);
++
++void             gsp_app_reload_at                (GspApp       *app,
++                                                   const char   *path,
++                                                   unsigned int  xdg_position);
++
++unsigned int     gsp_app_get_xdg_position         (GspApp       *app);
++unsigned int     gsp_app_get_xdg_system_position  (GspApp       *app);
++void             gsp_app_set_xdg_system_position  (GspApp       *app,
++                                                   unsigned int  position);
++
++G_END_DECLS
++
++#endif /* __GSP_APP_H */
+diff --git a/capplet/gsp-keyfile.c b/capplet/gsp-keyfile.c
+new file mode 100644
+index 0000000..48c8e31
+--- /dev/null
++++ b/capplet/gsp-keyfile.c
+@@ -0,0 +1,207 @@
++/*
++ * gsp-keyfile.c: GKeyFile extensions
++ *
++ * Copyright (C) 2008, 2009 Novell, Inc.
++ *
++ * Based on code from panel-keyfile.c (from gnome-panel)
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
++ * 02111-1307, USA.
++ *
++ * Authors:
++ *        Vincent Untz <vuntz@gnome.org>
++ */
++
++#include <string.h>
++
++#include <glib.h>
++
++#include "gsp-keyfile.h"
++
++void
++gsp_key_file_populate (GKeyFile *keyfile)
++{
++        gsp_key_file_set_string (keyfile,
++                                 G_KEY_FILE_DESKTOP_KEY_TYPE,
++                                 "Application");
++
++        gsp_key_file_set_string (keyfile,
++                                 G_KEY_FILE_DESKTOP_KEY_EXEC,
++                                 "/bin/false");
++}
++
++//FIXME: kill this when bug #309224 is fixed
++gboolean
++gsp_key_file_to_file (GKeyFile     *keyfile,
++                      const gchar  *path,
++                      GError      **error)
++{
++        GError  *write_error;
++        gchar   *data;
++        gsize    length;
++        gboolean res;
++
++        g_return_val_if_fail (keyfile != NULL, FALSE);
++        g_return_val_if_fail (path != NULL, FALSE);
++
++        write_error = NULL;
++        data = g_key_file_to_data (keyfile, &length, &write_error);
++
++        if (write_error) {
++                g_propagate_error (error, write_error);
++                return FALSE;
++        }
++
++        res = g_file_set_contents (path, data, length, &write_error);
++        g_free (data);
++
++        if (write_error) {
++                g_propagate_error (error, write_error);
++                return FALSE;
++        }
++
++        return res;
++}
++
++gboolean
++gsp_key_file_get_boolean (GKeyFile    *keyfile,
++                          const gchar *key,
++                          gboolean     default_value)
++{
++        GError   *error;
++        gboolean  retval;
++
++        error = NULL;
++        retval = g_key_file_get_boolean (keyfile, G_KEY_FILE_DESKTOP_GROUP,
++                                         key, &error);
++        if (error != NULL) {
++                retval = default_value;
++                g_error_free (error);
++        }
++
++        return retval;
++}
++
++gboolean
++gsp_key_file_get_shown (GKeyFile   *keyfile,
++                        const char *current_desktop)
++{
++        char     **only_show_in, **not_show_in;
++        gchar    **current_desktops = { NULL };
++        gboolean   found;
++        int        i;
++
++        if (!current_desktop)
++                return TRUE;
++
++        only_show_in = g_key_file_get_string_list (keyfile, G_KEY_FILE_DESKTOP_GROUP,
++                                                   G_KEY_FILE_DESKTOP_KEY_ONLY_SHOW_IN,
++                                                   NULL, NULL);
++
++        if (current_desktop && current_desktop[0] != '\0')
++                current_desktops = g_strsplit (current_desktop, ":", 0);
++
++        if (only_show_in) {
++                found = FALSE;
++                for (i = 0; only_show_in[i] != NULL; i++) {
++                        if (g_strv_contains ((const gchar * const *) current_desktops, only_show_in[i])) {
++                                found = TRUE;
++                                break;
++                        }
++                }
++
++                g_strfreev (only_show_in);
++
++                if (!found)
++                        return FALSE;
++        }
++
++        not_show_in = g_key_file_get_string_list (keyfile, G_KEY_FILE_DESKTOP_GROUP,
++                                                  G_KEY_FILE_DESKTOP_KEY_NOT_SHOW_IN,
++                                                  NULL, NULL);
++
++        if (not_show_in) {
++                found = FALSE;
++                for (i = 0; not_show_in[i] != NULL; i++) {
++                        if (g_strv_contains ((const gchar * const *) current_desktops, not_show_in[i])) {
++                                found = TRUE;
++                                break;
++                        }
++                }
++
++                g_strfreev (not_show_in);
++
++                if (found)
++                        return FALSE;
++        }
++
++        g_strfreev (current_desktops);
++
++        return TRUE;
++}
++
++void
++gsp_key_file_set_locale_string (GKeyFile    *keyfile,
++                                const gchar *key,
++                                const gchar *value)
++{
++        const char         *locale;
++        const char * const *langs_pointer;
++        int                 i;
++
++        if (value == NULL) {
++                value = "";
++        }
++
++        locale = NULL;
++        langs_pointer = g_get_language_names ();
++        for (i = 0; langs_pointer[i] != NULL; i++) {
++                /* find first without encoding  */
++                if (strchr (langs_pointer[i], '.') == NULL) {
++                        locale = langs_pointer[i];
++                        break;
++                }
++        }
++
++        if (locale != NULL) {
++                g_key_file_set_locale_string (keyfile, G_KEY_FILE_DESKTOP_GROUP,
++                                              key, locale, value);
++        } else {
++                g_key_file_set_string (keyfile, G_KEY_FILE_DESKTOP_GROUP,
++                                       key, value);
++        }
++}
++
++void
++gsp_key_file_ensure_C_key (GKeyFile   *keyfile,
++                           const char *key)
++{
++        char *C_value;
++        char *buffer;
++
++        /* Make sure we set the "C" locale strings to the terms we set here.
++         * This is so that if the user logs into another locale they get their
++         * own description there rather then empty. It is not the C locale
++         * however, but the user created this entry herself so it's OK */
++        C_value = gsp_key_file_get_string (keyfile, key);
++        if (C_value == NULL || C_value [0] == '\0') {
++                buffer = gsp_key_file_get_locale_string (keyfile, key);
++                if (buffer) {
++                        gsp_key_file_set_string (keyfile, key, buffer);
++                        g_free (buffer);
++                }
++        }
++        g_free (C_value);
++}
+diff --git a/capplet/gsp-keyfile.h b/capplet/gsp-keyfile.h
+new file mode 100644
+index 0000000..d94f667
+--- /dev/null
++++ b/capplet/gsp-keyfile.h
+@@ -0,0 +1,65 @@
++/*
++ * gsp-keyfile.h: GKeyFile extensions
++ *
++ * Copyright (C) 2008, 2009 Novell, Inc.
++ *
++ * Based on code from panel-keyfile.h (from gnome-panel)
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
++ * 02111-1307, USA.
++ *
++ * Authors:
++ *        Vincent Untz <vuntz@gnome.org>
++ */
++
++#ifndef GSP_KEYFILE_H
++#define GSP_KEYFILE_H
++
++#include "glib.h"
++
++G_BEGIN_DECLS
++
++#define GSP_KEY_FILE_DESKTOP_KEY_AUTOSTART_ENABLED "X-GNOME-Autostart-enabled"
++
++void      gsp_key_file_populate        (GKeyFile *keyfile);
++
++gboolean  gsp_key_file_to_file         (GKeyFile       *keyfile,
++                                        const gchar    *path,
++                                        GError        **error);
++
++gboolean gsp_key_file_get_boolean      (GKeyFile       *keyfile,
++                                        const gchar    *key,
++                                        gboolean        default_value);
++gboolean gsp_key_file_get_shown        (GKeyFile       *keyfile,
++                                        const char     *current_desktop);
++#define gsp_key_file_get_string(key_file, key) \
++         g_key_file_get_string (key_file, G_KEY_FILE_DESKTOP_GROUP, key, NULL)
++#define gsp_key_file_get_locale_string(key_file, key) \
++         g_key_file_get_locale_string(key_file, G_KEY_FILE_DESKTOP_GROUP, key, NULL, NULL)
++
++#define gsp_key_file_set_boolean(key_file, key, value) \
++         g_key_file_set_boolean (key_file, G_KEY_FILE_DESKTOP_GROUP, key, value)
++#define gsp_key_file_set_string(key_file, key, value) \
++         g_key_file_set_string (key_file, G_KEY_FILE_DESKTOP_GROUP, key, value)
++void    gsp_key_file_set_locale_string (GKeyFile    *keyfile,
++                                        const gchar *key,
++                                        const gchar *value);
++
++void gsp_key_file_ensure_C_key         (GKeyFile   *keyfile,
++                                        const char *key);
++
++G_END_DECLS
++
++#endif /* GSP_KEYFILE_H */
+diff --git a/capplet/main.c b/capplet/main.c
+new file mode 100644
+index 0000000..3c7177b
+--- /dev/null
++++ b/capplet/main.c
+@@ -0,0 +1,108 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
++ * main.c
++ * Copyright (C) 1999 Free Software Foundation, Inc.
++ * Copyright (C) 2008 Lucas Rocha.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
++ * 02111-1307, USA.
++ */
++
++#include <config.h>
++
++#include <unistd.h>
++#include <stdlib.h>
++
++#include <glib/gi18n.h>
++#include <gtk/gtk.h>
++
++#include "gsm-properties-dialog.h"
++
++static gboolean    show_version     = FALSE;
++
++static GOptionEntry options[] = {
++        { "version", 0, 0, G_OPTION_ARG_NONE, &show_version, N_("Version of this application"), NULL },
++        { NULL, 0, 0, 0, NULL, NULL, NULL }
++};
++
++static void
++dialog_response (GsmPropertiesDialog *dialog,
++                 guint                response_id,
++                 gpointer             data)
++{
++        GdkScreen *screen;
++        GError    *error;
++
++        if (response_id == GTK_RESPONSE_HELP) {
++                screen = gtk_widget_get_screen (GTK_WIDGET (dialog));
++
++                error = NULL;
++                gtk_show_uri (screen, "ghelp:user-guide?gosstartsession-2",
++                              gtk_get_current_event_time (), &error);
++
++                if (error != NULL) {
++                        GtkWidget *d;
++                        d = gtk_message_dialog_new (GTK_WINDOW (dialog),
++                                                    GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
++                                                    GTK_MESSAGE_ERROR,
++                                                    GTK_BUTTONS_CLOSE,
++                                                    "%s",
++                                                    _("Could not display help document"));
++                        gtk_message_dialog_format_secondary_text (
++                                                GTK_MESSAGE_DIALOG (d),
++                                                "%s", error->message);
++                        g_error_free (error);
++
++                        gtk_dialog_run (GTK_DIALOG (d));
++                        gtk_widget_destroy (d);
++                }
++        } else {
++                gtk_widget_destroy (GTK_WIDGET (dialog));
++                gtk_main_quit ();
++        }
++}
++
++int
++main (int argc, char *argv[])
++{
++        GError    *error;
++        GtkWidget *dialog;
++
++        bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR);
++        bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
++        textdomain (GETTEXT_PACKAGE);
++
++        error = NULL;
++        if (! gtk_init_with_args (&argc, &argv, " - GNOME Session Properties", options, GETTEXT_PACKAGE, &error)) {
++                g_warning ("Unable to start: %s", error->message);
++                g_error_free (error);
++                return 1;
++        }
++
++        if (show_version) {
++                g_print ("%s %s\n", argv [0], VERSION);
++                return 0;
++        }
++
++        dialog = gsm_properties_dialog_new ();
++        g_signal_connect (dialog,
++                          "response",
++                          G_CALLBACK (dialog_response),
++                          NULL);
++        gtk_widget_show (dialog);
++
++        gtk_main ();
++
++        return 0;
++}
+diff --git a/capplet/meson.build b/capplet/meson.build
+new file mode 100644
+index 0000000..8bc9f58
+--- /dev/null
++++ b/capplet/meson.build
+@@ -0,0 +1,36 @@
++
++cflags = [
++	'-DLOCALE_DIR="@0@"'.format(session_localedir),
++	'-DGTKBUILDER_DIR="@0@"'.format(session_pkgdatadir)
++]
++
++deps = [
++	gio_dep,
++	glib_dep,
++	gtk_dep
++]
++
++sources = files(
++	'main.c',
++	'gsm-properties-dialog.c',
++	'gsm-app-dialog.c',
++	'gsp-app.c',
++	'gsp-app-manager.c',
++	'gsp-keyfile.c',
++)
++
++includes = [
++	top_inc,
++	include_directories('../gnome-session')
++]
++
++executable(
++	'gnome-session-properties',
++	sources,
++	include_directories: includes,
++	dependencies: deps,
++	c_args: cflags,
++	link_with: libgsmutil,
++	install: true,
++	install_dir: session_bindir
++)
+diff --git a/data/gnome-session-properties.desktop.in b/data/gnome-session-properties.desktop.in
+new file mode 100644
+index 0000000..a0b2c6b
+--- /dev/null
++++ b/data/gnome-session-properties.desktop.in
+@@ -0,0 +1,14 @@
++[Desktop Entry]
++Name=Startup Applications
++Comment=Choose what applications to start when you log in
++Exec=gnome-session-properties
++Icon=session-properties
++Terminal=false
++Type=Application
++StartupNotify=true
++Categories=GTK;GNOME;Settings;X-GNOME-PersonalSettings;
++OnlyShowIn=GNOME;Unity;
++X-GNOME-Bugzilla-Bugzilla=GNOME
++X-GNOME-Bugzilla-Product=gnome-session
++X-GNOME-Bugzilla-Component=gnome-session-properties
++X-GNOME-Bugzilla-Version=@VERSION@
+diff --git a/data/icons/16x16/session-properties.svg b/data/icons/16x16/session-properties.svg
+new file mode 100644
+index 0000000..4f7c37f
+--- /dev/null
++++ b/data/icons/16x16/session-properties.svg
+@@ -0,0 +1,394 @@
++<?xml version="1.0" encoding="UTF-8" standalone="no"?>
++<!-- Created with Inkscape (http://www.inkscape.org/) -->
++<svg
++   xmlns:dc="http://purl.org/dc/elements/1.1/"
++   xmlns:cc="http://web.resource.org/cc/"
++   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
++   xmlns:svg="http://www.w3.org/2000/svg"
++   xmlns="http://www.w3.org/2000/svg"
++   xmlns:xlink="http://www.w3.org/1999/xlink"
++   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
++   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
++   width="16"
++   height="16"
++   id="svg7854"
++   sodipodi:version="0.32"
++   inkscape:version="0.44+devel"
++   version="1.0"
++   sodipodi:docname="session-properties.svg"
++   sodipodi:docbase="/home/jimmac/gfx/ximian/art/icons/control-center/22x22"
++   inkscape:output_extension="org.inkscape.output.svg.inkscape"
++   sodipodi:modified="true">
++  <defs
++     id="defs7856">
++    <linearGradient
++       inkscape:collect="always"
++       id="linearGradient5650">
++      <stop
++         style="stop-color:#d3d7cf;stop-opacity:1;"
++         offset="0"
++         id="stop5652" />
++      <stop
++         style="stop-color:#9ea795;stop-opacity:1"
++         offset="1"
++         id="stop5654" />
++    </linearGradient>
++    <linearGradient
++       inkscape:collect="always"
++       id="linearGradient5642">
++      <stop
++         style="stop-color:#eeeeec;stop-opacity:1;"
++         offset="0"
++         id="stop5644" />
++      <stop
++         style="stop-color:#c3c3bc;stop-opacity:1"
++         offset="1"
++         id="stop5646" />
++    </linearGradient>
++    <linearGradient
++       inkscape:collect="always"
++       id="linearGradient5634">
++      <stop
++         style="stop-color:#ffffff;stop-opacity:1;"
++         offset="0"
++         id="stop5636" />
++      <stop
++         style="stop-color:#ffffff;stop-opacity:0;"
++         offset="1"
++         id="stop5638" />
++    </linearGradient>
++    <linearGradient
++       inkscape:collect="always"
++       id="linearGradient5598">
++      <stop
++         style="stop-color:#ffffff;stop-opacity:1;"
++         offset="0"
++         id="stop5600" />
++      <stop
++         style="stop-color:#ffffff;stop-opacity:0;"
++         offset="1"
++         id="stop5602" />
++    </linearGradient>
++    <linearGradient
++       inkscape:collect="always"
++       id="linearGradient5716">
++      <stop
++         style="stop-color:#ffffff;stop-opacity:1;"
++         offset="0"
++         id="stop5718" />
++      <stop
++         style="stop-color:#ffffff;stop-opacity:0;"
++         offset="1"
++         id="stop5720" />
++    </linearGradient>
++    <linearGradient
++       inkscape:collect="always"
++       id="linearGradient5700">
++      <stop
++         style="stop-color:#e4e4e4;stop-opacity:1;"
++         offset="0"
++         id="stop5702" />
++      <stop
++         id="stop5708"
++         offset="0.639386"
++         style="stop-color:#fefefe;stop-opacity:1" />
++      <stop
++         style="stop-color:#ffffff;stop-opacity:1"
++         offset="0.79632628"
++         id="stop5710" />
++      <stop
++         style="stop-color:#949494;stop-opacity:1"
++         offset="1"
++         id="stop5704" />
++    </linearGradient>
++    <linearGradient
++       id="linearGradient3832">
++      <stop
++         id="stop3834"
++         offset="0.0000000"
++         style="stop-color:#ffffff;stop-opacity:1.0000000" />
++      <stop
++         id="stop3836"
++         offset="1.0000000"
++         style="stop-color:#e0e0e0;stop-opacity:1.0000000" />
++    </linearGradient>
++    <linearGradient
++       id="linearGradient4816">
++      <stop
++         id="stop4818"
++         offset="0.0000000"
++         style="stop-color:#204a87;stop-opacity:1.0000000" />
++      <stop
++         id="stop4820"
++         offset="1.0000000"
++         style="stop-color:#204a87;stop-opacity:0.0000000" />
++    </linearGradient>
++    <linearGradient
++       id="linearGradient5048">
++      <stop
++         id="stop5050"
++         offset="0"
++         style="stop-color:black;stop-opacity:0;" />
++      <stop
++         style="stop-color:black;stop-opacity:1;"
++         offset="0.5"
++         id="stop5056" />
++      <stop
++         id="stop5052"
++         offset="1"
++         style="stop-color:black;stop-opacity:0;" />
++    </linearGradient>
++    <linearGradient
++       id="linearGradient5060"
++       inkscape:collect="always">
++      <stop
++         id="stop5062"
++         offset="0"
++         style="stop-color:black;stop-opacity:1;" />
++      <stop
++         id="stop5064"
++         offset="1"
++         style="stop-color:black;stop-opacity:0;" />
++    </linearGradient>
++    <radialGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5060"
++       id="radialGradient5664"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(-6.6526975e-2,0,0,3.5014969e-2,47.812816,25.161837)"
++       cx="605.71429"
++       cy="486.64789"
++       fx="605.71429"
++       fy="486.64789"
++       r="117.14286" />
++    <radialGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5060"
++       id="radialGradient5667"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(6.6526975e-2,0,0,3.5014969e-2,-0.2505064,25.161837)"
++       cx="605.71429"
++       cy="486.64789"
++       fx="605.71429"
++       fy="486.64789"
++       r="117.14286" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5048"
++       id="linearGradient5670"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(6.6526975e-2,0,0,3.5014969e-2,-0.2635996,25.161837)"
++       x1="302.85715"
++       y1="366.64789"
++       x2="302.85715"
++       y2="609.50507" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient3832"
++       id="linearGradient5682"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(1.451927,0,0,1.3372801,-45.830775,7.6961475)"
++       x1="17.88068"
++       y1="11.072588"
++       x2="17.88068"
++       y2="21.767578" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient4816"
++       id="linearGradient5684"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(1.4668451,0,0,1.8750592,-45.628571,3.9919211)"
++       x1="13.050564"
++       y1="11.353518"
++       x2="13.050564"
++       y2="5.6173568" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5700"
++       id="linearGradient5728"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="translate(0.5,0)"
++       x1="24"
++       y1="23"
++       x2="45.505005"
++       y2="23" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5716"
++       id="linearGradient5730"
++       gradientUnits="userSpaceOnUse"
++       x1="40.745819"
++       y1="23"
++       x2="44.005268"
++       y2="23" />
++    <filter
++       inkscape:collect="always"
++       id="filter5786">
++      <feGaussianBlur
++         inkscape:collect="always"
++         stdDeviation="0.62861987"
++         id="feGaussianBlur5788" />
++    </filter>
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5598"
++       id="linearGradient5604"
++       x1="25.627417"
++       y1="8"
++       x2="25.627417"
++       y2="4.7617435"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(0.3170731,0,0,0.1513709,0.3902442,0.3687103)" />
++    <filter
++       inkscape:collect="always"
++       x="-0.019480519"
++       width="1.0389611"
++       y="-0.14285713"
++       height="1.2857143"
++       id="filter5628">
++      <feGaussianBlur
++         inkscape:collect="always"
++         stdDeviation="0.42857143"
++         id="feGaussianBlur5630" />
++    </filter>
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5634"
++       id="linearGradient5640"
++       x1="25.313259"
++       y1="42.656792"
++       x2="25.313261"
++       y2="10.129107"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(0.3182502,0,0,0.3589572,0.3378627,-0.7556826)" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5642"
++       id="linearGradient5648"
++       x1="26.29347"
++       y1="7.3125"
++       x2="26.232994"
++       y2="3.5357027"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(0.3500965,0,0,0.4000001,-0.3752413,-0.8999998)" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5650"
++       id="linearGradient5656"
++       x1="26.29347"
++       y1="7.3125"
++       x2="26.232994"
++       y2="3.5357027"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(0.3500965,0,0,0.4000001,-0.3752413,-0.8999998)" />
++  </defs>
++  <sodipodi:namedview
++     id="base"
++     pagecolor="#ffffff"
++     bordercolor="#e0e0e0"
++     borderopacity="1"
++     gridtolerance="10000"
++     guidetolerance="10"
++     objecttolerance="10"
++     inkscape:pageopacity="0.0"
++     inkscape:pageshadow="2"
++     inkscape:zoom="1"
++     inkscape:cx="13.920386"
++     inkscape:cy="2.77771"
++     inkscape:document-units="px"
++     inkscape:current-layer="layer1"
++     width="16px"
++     height="16px"
++     inkscape:showpageshadow="false"
++     inkscape:window-width="1102"
++     inkscape:window-height="958"
++     inkscape:window-x="2117"
++     inkscape:window-y="82"
++     showgrid="false"
++     borderlayer="true" />
++  <metadata
++     id="metadata7859">
++    <rdf:RDF>
++      <cc:Work
++         rdf:about="">
++        <dc:format>image/svg+xml</dc:format>
++        <dc:type
++           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
++        <dc:creator>
++          <cc:Agent>
++            <dc:title>Jakub Steiner</dc:title>
++          </cc:Agent>
++        </dc:creator>
++        <dc:source>http://jimmac.musichall.cz</dc:source>
++        <cc:license
++           rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
++        <dc:title>Gnome Session Properties</dc:title>
++      </cc:Work>
++      <cc:License
++         rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
++        <cc:permits
++           rdf:resource="http://web.resource.org/cc/Reproduction" />
++        <cc:permits
++           rdf:resource="http://web.resource.org/cc/Distribution" />
++        <cc:requires
++           rdf:resource="http://web.resource.org/cc/Notice" />
++        <cc:permits
++           rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
++        <cc:requires
++           rdf:resource="http://web.resource.org/cc/ShareAlike" />
++        <cc:requires
++           rdf:resource="http://web.resource.org/cc/SourceCode" />
++      </cc:License>
++    </rdf:RDF>
++  </metadata>
++  <g
++     inkscape:label="Layer 1"
++     inkscape:groupmode="layer"
++     id="layer1">
++    <rect
++       style="opacity:1;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:evenodd;stroke:#3465a4;stroke-width:1.00000012;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
++       id="rect4585"
++       width="15.054147"
++       height="14.931664"
++       x="0.50000006"
++       y="0.56833637"
++       rx="0.80243546"
++       ry="0.85151595" />
++    <rect
++       style="opacity:1;color:#000000;fill:url(#linearGradient5648);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient5656);stroke-width:1.00000012;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
++       id="rect5556"
++       width="15.054147"
++       height="1.9999999"
++       x="0.5"
++       y="0.50000006"
++       rx="0.80249435"
++       ry="0.91688365" />
++    <rect
++       ry="0"
++       rx="0"
++       y="0.90594715"
++       x="1.5"
++       height="13.594053"
++       width="12.999999"
++       id="rect5632"
++       style="opacity:0.52571429;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient5640);stroke-width:1.00000012;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
++    <g
++       id="g5724"
++       transform="matrix(0.4041599,0,0,0.4075968,-2.9205921,-0.7107676)">
++      <path
++         sodipodi:nodetypes="cccccccccc"
++         id="path5698"
++         d="M 11.121851,22.804198 L 23.199467,12.216748 L 23.199467,17.747078 L 36.633956,17.747078 C 44.741684,17.747078 45.5,23.213443 45.5,23.213443 L 45.5,36.603439 C 45.5,36.603439 43.628297,27.513864 36.758956,27.513864 L 23.199467,27.513864 L 23.199467,33 L 11.121851,22.804198 z "
++         style="fill:url(#linearGradient5728);fill-opacity:1;fill-rule:evenodd;stroke:#555753;stroke-width:2.46381474px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
++    </g>
++    <rect
++       ry="0.17072184"
++       rx="0.35760722"
++       y="1.0498793"
++       x="1.5"
++       height="0.45411268"
++       width="13"
++       id="rect4627"
++       style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient5604);stroke-width:0.99999982;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
++  </g>
++</svg>
+diff --git a/data/icons/22x22/session-properties.svg b/data/icons/22x22/session-properties.svg
+new file mode 100644
+index 0000000..1d0afda
+--- /dev/null
++++ b/data/icons/22x22/session-properties.svg
+@@ -0,0 +1,440 @@
++<?xml version="1.0" encoding="UTF-8" standalone="no"?>
++<!-- Created with Inkscape (http://www.inkscape.org/) -->
++<svg
++   xmlns:dc="http://purl.org/dc/elements/1.1/"
++   xmlns:cc="http://web.resource.org/cc/"
++   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
++   xmlns:svg="http://www.w3.org/2000/svg"
++   xmlns="http://www.w3.org/2000/svg"
++   xmlns:xlink="http://www.w3.org/1999/xlink"
++   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
++   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
++   width="22"
++   height="22"
++   id="svg7854"
++   sodipodi:version="0.32"
++   inkscape:version="0.44+devel"
++   version="1.0"
++   sodipodi:docname="session-properties.svg"
++   sodipodi:docbase="/home/jimmac/gfx/ximian/art/icons/control-center/32x32"
++   inkscape:output_extension="org.inkscape.output.svg.inkscape"
++   sodipodi:modified="true">
++  <defs
++     id="defs7856">
++    <linearGradient
++       inkscape:collect="always"
++       id="linearGradient5650">
++      <stop
++         style="stop-color:#d3d7cf;stop-opacity:1;"
++         offset="0"
++         id="stop5652" />
++      <stop
++         style="stop-color:#9ea795;stop-opacity:1"
++         offset="1"
++         id="stop5654" />
++    </linearGradient>
++    <linearGradient
++       inkscape:collect="always"
++       id="linearGradient5642">
++      <stop
++         style="stop-color:#eeeeec;stop-opacity:1;"
++         offset="0"
++         id="stop5644" />
++      <stop
++         style="stop-color:#c3c3bc;stop-opacity:1"
++         offset="1"
++         id="stop5646" />
++    </linearGradient>
++    <linearGradient
++       inkscape:collect="always"
++       id="linearGradient5634">
++      <stop
++         style="stop-color:#ffffff;stop-opacity:1;"
++         offset="0"
++         id="stop5636" />
++      <stop
++         style="stop-color:#ffffff;stop-opacity:0;"
++         offset="1"
++         id="stop5638" />
++    </linearGradient>
++    <linearGradient
++       inkscape:collect="always"
++       id="linearGradient5598">
++      <stop
++         style="stop-color:#ffffff;stop-opacity:1;"
++         offset="0"
++         id="stop5600" />
++      <stop
++         style="stop-color:#ffffff;stop-opacity:0;"
++         offset="1"
++         id="stop5602" />
++    </linearGradient>
++    <linearGradient
++       inkscape:collect="always"
++       id="linearGradient5716">
++      <stop
++         style="stop-color:#ffffff;stop-opacity:1;"
++         offset="0"
++         id="stop5718" />
++      <stop
++         style="stop-color:#ffffff;stop-opacity:0;"
++         offset="1"
++         id="stop5720" />
++    </linearGradient>
++    <linearGradient
++       inkscape:collect="always"
++       id="linearGradient5700">
++      <stop
++         style="stop-color:#e4e4e4;stop-opacity:1;"
++         offset="0"
++         id="stop5702" />
++      <stop
++         id="stop5708"
++         offset="0.639386"
++         style="stop-color:#fefefe;stop-opacity:1" />
++      <stop
++         style="stop-color:#ffffff;stop-opacity:1"
++         offset="0.79632628"
++         id="stop5710" />
++      <stop
++         style="stop-color:#949494;stop-opacity:1"
++         offset="1"
++         id="stop5704" />
++    </linearGradient>
++    <linearGradient
++       id="linearGradient3832">
++      <stop
++         id="stop3834"
++         offset="0.0000000"
++         style="stop-color:#ffffff;stop-opacity:1.0000000" />
++      <stop
++         id="stop3836"
++         offset="1.0000000"
++         style="stop-color:#e0e0e0;stop-opacity:1.0000000" />
++    </linearGradient>
++    <linearGradient
++       id="linearGradient4816">
++      <stop
++         id="stop4818"
++         offset="0.0000000"
++         style="stop-color:#204a87;stop-opacity:1.0000000" />
++      <stop
++         id="stop4820"
++         offset="1.0000000"
++         style="stop-color:#204a87;stop-opacity:0.0000000" />
++    </linearGradient>
++    <linearGradient
++       id="linearGradient5048">
++      <stop
++         id="stop5050"
++         offset="0"
++         style="stop-color:black;stop-opacity:0;" />
++      <stop
++         style="stop-color:black;stop-opacity:1;"
++         offset="0.5"
++         id="stop5056" />
++      <stop
++         id="stop5052"
++         offset="1"
++         style="stop-color:black;stop-opacity:0;" />
++    </linearGradient>
++    <linearGradient
++       id="linearGradient5060"
++       inkscape:collect="always">
++      <stop
++         id="stop5062"
++         offset="0"
++         style="stop-color:black;stop-opacity:1;" />
++      <stop
++         id="stop5064"
++         offset="1"
++         style="stop-color:black;stop-opacity:0;" />
++    </linearGradient>
++    <radialGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5060"
++       id="radialGradient5664"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(-6.6526975e-2,0,0,3.5014969e-2,47.812816,25.161837)"
++       cx="605.71429"
++       cy="486.64789"
++       fx="605.71429"
++       fy="486.64789"
++       r="117.14286" />
++    <radialGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5060"
++       id="radialGradient5667"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(6.6526975e-2,0,0,3.5014969e-2,-0.2505064,25.161837)"
++       cx="605.71429"
++       cy="486.64789"
++       fx="605.71429"
++       fy="486.64789"
++       r="117.14286" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5048"
++       id="linearGradient5670"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(6.6526975e-2,0,0,3.5014969e-2,-0.2635996,25.161837)"
++       x1="302.85715"
++       y1="366.64789"
++       x2="302.85715"
++       y2="609.50507" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient3832"
++       id="linearGradient5682"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(1.451927,0,0,1.3372801,-45.830775,7.6961475)"
++       x1="17.88068"
++       y1="11.072588"
++       x2="17.88068"
++       y2="21.767578" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient4816"
++       id="linearGradient5684"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(1.4668451,0,0,1.8750592,-45.628571,3.9919211)"
++       x1="13.050564"
++       y1="11.353518"
++       x2="13.050564"
++       y2="5.6173568" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5700"
++       id="linearGradient5728"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="translate(0.5,0)"
++       x1="24"
++       y1="23"
++       x2="45.505005"
++       y2="23" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5716"
++       id="linearGradient5730"
++       gradientUnits="userSpaceOnUse"
++       x1="40.745819"
++       y1="23"
++       x2="44.005268"
++       y2="23" />
++    <filter
++       inkscape:collect="always"
++       id="filter5786">
++      <feGaussianBlur
++         inkscape:collect="always"
++         stdDeviation="0.62861987"
++         id="feGaussianBlur5788" />
++    </filter>
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5598"
++       id="linearGradient5604"
++       x1="25.627417"
++       y1="8"
++       x2="25.627417"
++       y2="4.7617435"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(0.4311139,0,0,0.1911915,0.6155053,1.0660639)" />
++    <filter
++       inkscape:collect="always"
++       x="-0.019480519"
++       width="1.0389611"
++       y="-0.14285713"
++       height="1.2857143"
++       id="filter5628">
++      <feGaussianBlur
++         inkscape:collect="always"
++         stdDeviation="0.42857143"
++         id="feGaussianBlur5630" />
++    </filter>
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5634"
++       id="linearGradient5640"
++       x1="25.313259"
++       y1="42.656792"
++       x2="25.313261"
++       y2="10.129107"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(0.4161734,0,0,0.4097743,0.9802818,8.45901e-2)" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5642"
++       id="linearGradient5648"
++       x1="26.29347"
++       y1="7.3125"
++       x2="26.232994"
++       y2="3.5357027"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(0.4415111,0,0,0.3917361,0.3659716,0.1289237)" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5650"
++       id="linearGradient5656"
++       x1="26.29347"
++       y1="7.3125"
++       x2="26.232994"
++       y2="3.5357027"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(0.4415111,0,0,0.3917361,0.3659716,0.1289237)" />
++  </defs>
++  <sodipodi:namedview
++     id="base"
++     pagecolor="#ffffff"
++     bordercolor="#e0e0e0"
++     borderopacity="1"
++     gridtolerance="10000"
++     guidetolerance="10"
++     objecttolerance="10"
++     inkscape:pageopacity="0.0"
++     inkscape:pageshadow="2"
++     inkscape:zoom="1"
++     inkscape:cx="21.888246"
++     inkscape:cy="13.442716"
++     inkscape:document-units="px"
++     inkscape:current-layer="layer1"
++     width="22px"
++     height="22px"
++     inkscape:showpageshadow="false"
++     inkscape:window-width="1102"
++     inkscape:window-height="958"
++     inkscape:window-x="2117"
++     inkscape:window-y="82"
++     showgrid="false"
++     borderlayer="true" />
++  <metadata
++     id="metadata7859">
++    <rdf:RDF>
++      <cc:Work
++         rdf:about="">
++        <dc:format>image/svg+xml</dc:format>
++        <dc:type
++           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
++        <dc:creator>
++          <cc:Agent>
++            <dc:title>Jakub Steiner</dc:title>
++          </cc:Agent>
++        </dc:creator>
++        <dc:source>http://jimmac.musichall.cz</dc:source>
++        <cc:license
++           rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
++        <dc:title>Gnome Session Properties</dc:title>
++      </cc:Work>
++      <cc:License
++         rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
++        <cc:permits
++           rdf:resource="http://web.resource.org/cc/Reproduction" />
++        <cc:permits
++           rdf:resource="http://web.resource.org/cc/Distribution" />
++        <cc:requires
++           rdf:resource="http://web.resource.org/cc/Notice" />
++        <cc:permits
++           rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
++        <cc:requires
++           rdf:resource="http://web.resource.org/cc/ShareAlike" />
++        <cc:requires
++           rdf:resource="http://web.resource.org/cc/SourceCode" />
++      </cc:License>
++    </rdf:RDF>
++  </metadata>
++  <g
++     inkscape:label="Layer 1"
++     inkscape:groupmode="layer"
++     id="layer1">
++    <g
++       id="g5672"
++       style="opacity:0.53714288"
++       transform="matrix(0.4617581,0,0,0.6375656,-4.8917036e-2,-9.3215937)">
++      <rect
++         y="38"
++         x="7.7196383"
++         height="8.5036354"
++         width="32.123024"
++         id="rect4173"
++         style="opacity:1;color:#000000;fill:url(#linearGradient5670);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
++      <path
++         sodipodi:nodetypes="cccc"
++         id="path5058"
++         d="M 39.842663,38.000295 C 39.842663,38.000295 39.842663,46.503461 39.842663,46.503461 C 43.268636,46.519469 48.125002,44.598333 48.125,42.25133 C 48.125,39.904328 44.30187,38.000295 39.842663,38.000295 z "
++         style="opacity:1;color:#000000;fill:url(#radialGradient5667);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
++      <path
++         style="opacity:1;color:#000000;fill:url(#radialGradient5664);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
++         d="M 7.7196385,38.000295 C 7.7196385,38.000295 7.7196385,46.503461 7.7196385,46.503461 C 4.2936621,46.519469 -0.56270146,44.598333 -0.56270146,42.25133 C -0.56270146,39.904328 3.2604286,38.000295 7.7196385,38.000295 z "
++         id="path5018"
++         sodipodi:nodetypes="cccc" />
++    </g>
++    <rect
++       style="opacity:1;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:evenodd;stroke:#3465a4;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
++       id="rect4585"
++       width="18.984974"
++       height="16.920202"
++       x="1.4697493"
++       y="1.5550299"
++       rx="1.0119615"
++       ry="0.96491748" />
++    <rect
++       ry="2.2922091"
++       rx="2.2922091"
++       y="4.3838844"
++       x="2.5"
++       height="5"
++       width="43"
++       id="rect5606"
++       style="opacity:0.27999998;color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:2.34036613;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter5628);enable-background:accumulate"
++       transform="matrix(0.4281431,0,0,0.4264257,0.8323174,7.5101245e-3)" />
++    <rect
++       style="opacity:1;color:#000000;fill:url(#linearGradient5648);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient5656);stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
++       id="rect5556"
++       width="18.984974"
++       height="1.9586804"
++       x="1.4697493"
++       y="1.5"
++       rx="1.0120357"
++       ry="0.89794111" />
++    <rect
++       ry="0.32291412"
++       rx="0.31787637"
++       y="1.9814546"
++       x="2.5"
++       height="15.518545"
++       width="16.999998"
++       id="rect5632"
++       style="opacity:0.52571429;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient5640);stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
++    <g
++       id="g5724"
++       transform="matrix(0.4754857,0,0,0.4735784,-1.225003,-0.5239366)">
++      <path
++         style="opacity:0.3142857;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter5786)"
++         d="M 10.5,25.474874 L 20.5,15.474874 L 20.5,21.005204 L 40.5,21.005204 C 44.35508,21.005204 45.58678,20.95144 45.5,23 L 45.5,33 C 45.5,33 43.070425,29.988738 40.625,29.988738 L 20.5,29.988738 L 20.5,35.474874 L 10.5,25.474874 z "
++         id="path5738"
++         sodipodi:nodetypes="cccccccccc" />
++      <path
++         sodipodi:nodetypes="cccccccccc"
++         id="path5698"
++         d="M 10.5,23.279959 L 20.5,13.559918 L 20.5,19.090248 L 40.5,19.090248 C 44.35508,19.090248 45.58678,21.511358 45.5,23.559918 L 45.5,33 C 45.5,33 45.096959,27.513864 40.625,27.513864 L 20.5,27.513864 L 20.5,33 L 10.5,23.279959 z "
++         style="fill:url(#linearGradient5728);fill-opacity:1;fill-rule:evenodd;stroke:#555753;stroke-width:2.10734344px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
++      <path
++         d="M 18.125,18.8125 L 13.9375,23 L 18.09375,27.15625 C 18.269985,25.965284 19.296092,25.085764 20.5,25.09375 L 40.625,25.09375 C 41.541275,25.09375 42.352276,25.289567 43.09375,25.59375 L 43.09375,23 C 43.093144,22.968753 43.093144,22.937497 43.09375,22.90625 C 43.114981,22.405075 42.966583,21.933517 42.6875,21.625 C 42.408417,21.316483 41.921956,20.9375 40.5,20.9375 L 20.5,20.9375 C 19.287205,20.925631 18.271136,20.016516 18.125,18.8125 z "
++         inkscape:href="#path5698"
++         id="path5712"
++         style="opacity:0.62857145;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient5730);stroke-width:2.10734344px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
++         xlink:href="#path5698"
++         inkscape:original="M 20.5 13.5625 L 10.5 23.28125 L 20.5 33 L 20.5 27.5 L 40.625 27.5 C 45.096959 27.5 45.5 33 45.5 33 L 45.5 23.5625 C 45.58678 21.51394 44.35508 19.09375 40.5 19.09375 L 20.5 19.09375 L 20.5 13.5625 z "
++         inkscape:radius="-2.4160075"
++         sodipodi:type="inkscape:offset" />
++    </g>
++    <rect
++       ry="0.21563303"
++       rx="0.48622662"
++       y="1.9264256"
++       x="2.1244035"
++       height="0.57357448"
++       width="17.675669"
++       id="rect4627"
++       style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient5604);stroke-width:0.99999988;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
++  </g>
++</svg>
+diff --git a/data/icons/32x32/session-properties.svg b/data/icons/32x32/session-properties.svg
+new file mode 100644
+index 0000000..5bb1455
+--- /dev/null
++++ b/data/icons/32x32/session-properties.svg
+@@ -0,0 +1,490 @@
++<?xml version="1.0" encoding="UTF-8" standalone="no"?>
++<!-- Created with Inkscape (http://www.inkscape.org/) -->
++<svg
++   xmlns:dc="http://purl.org/dc/elements/1.1/"
++   xmlns:cc="http://web.resource.org/cc/"
++   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
++   xmlns:svg="http://www.w3.org/2000/svg"
++   xmlns="http://www.w3.org/2000/svg"
++   xmlns:xlink="http://www.w3.org/1999/xlink"
++   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
++   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
++   width="32"
++   height="32"
++   id="svg7854"
++   sodipodi:version="0.32"
++   inkscape:version="0.44+devel"
++   version="1.0"
++   sodipodi:docname="session-properties.svg"
++   sodipodi:docbase="/home/jimmac/gfx/ximian/art/icons/control-center/scalable"
++   inkscape:output_extension="org.inkscape.output.svg.inkscape"
++   sodipodi:modified="true">
++  <defs
++     id="defs7856">
++    <linearGradient
++       inkscape:collect="always"
++       id="linearGradient5650">
++      <stop
++         style="stop-color:#d3d7cf;stop-opacity:1;"
++         offset="0"
++         id="stop5652" />
++      <stop
++         style="stop-color:#9ea795;stop-opacity:1"
++         offset="1"
++         id="stop5654" />
++    </linearGradient>
++    <linearGradient
++       inkscape:collect="always"
++       id="linearGradient5642">
++      <stop
++         style="stop-color:#eeeeec;stop-opacity:1;"
++         offset="0"
++         id="stop5644" />
++      <stop
++         style="stop-color:#c3c3bc;stop-opacity:1"
++         offset="1"
++         id="stop5646" />
++    </linearGradient>
++    <linearGradient
++       inkscape:collect="always"
++       id="linearGradient5634">
++      <stop
++         style="stop-color:#ffffff;stop-opacity:1;"
++         offset="0"
++         id="stop5636" />
++      <stop
++         style="stop-color:#ffffff;stop-opacity:0;"
++         offset="1"
++         id="stop5638" />
++    </linearGradient>
++    <linearGradient
++       inkscape:collect="always"
++       id="linearGradient5598">
++      <stop
++         style="stop-color:#ffffff;stop-opacity:1;"
++         offset="0"
++         id="stop5600" />
++      <stop
++         style="stop-color:#ffffff;stop-opacity:0;"
++         offset="1"
++         id="stop5602" />
++    </linearGradient>
++    <linearGradient
++       inkscape:collect="always"
++       id="linearGradient5716">
++      <stop
++         style="stop-color:#ffffff;stop-opacity:1;"
++         offset="0"
++         id="stop5718" />
++      <stop
++         style="stop-color:#ffffff;stop-opacity:0;"
++         offset="1"
++         id="stop5720" />
++    </linearGradient>
++    <linearGradient
++       inkscape:collect="always"
++       id="linearGradient5700">
++      <stop
++         style="stop-color:#e4e4e4;stop-opacity:1;"
++         offset="0"
++         id="stop5702" />
++      <stop
++         id="stop5708"
++         offset="0.639386"
++         style="stop-color:#fefefe;stop-opacity:1" />
++      <stop
++         style="stop-color:#ffffff;stop-opacity:1"
++         offset="0.79632628"
++         id="stop5710" />
++      <stop
++         style="stop-color:#949494;stop-opacity:1"
++         offset="1"
++         id="stop5704" />
++    </linearGradient>
++    <linearGradient
++       id="linearGradient3832">
++      <stop
++         id="stop3834"
++         offset="0.0000000"
++         style="stop-color:#ffffff;stop-opacity:1.0000000" />
++      <stop
++         id="stop3836"
++         offset="1.0000000"
++         style="stop-color:#e0e0e0;stop-opacity:1.0000000" />
++    </linearGradient>
++    <linearGradient
++       id="linearGradient4816">
++      <stop
++         id="stop4818"
++         offset="0.0000000"
++         style="stop-color:#204a87;stop-opacity:1.0000000" />
++      <stop
++         id="stop4820"
++         offset="1.0000000"
++         style="stop-color:#204a87;stop-opacity:0.0000000" />
++    </linearGradient>
++    <linearGradient
++       id="linearGradient5048">
++      <stop
++         id="stop5050"
++         offset="0"
++         style="stop-color:black;stop-opacity:0;" />
++      <stop
++         style="stop-color:black;stop-opacity:1;"
++         offset="0.5"
++         id="stop5056" />
++      <stop
++         id="stop5052"
++         offset="1"
++         style="stop-color:black;stop-opacity:0;" />
++    </linearGradient>
++    <linearGradient
++       id="linearGradient5060"
++       inkscape:collect="always">
++      <stop
++         id="stop5062"
++         offset="0"
++         style="stop-color:black;stop-opacity:1;" />
++      <stop
++         id="stop5064"
++         offset="1"
++         style="stop-color:black;stop-opacity:0;" />
++    </linearGradient>
++    <radialGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5060"
++       id="radialGradient5664"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(-6.6526975e-2,0,0,3.5014969e-2,47.812816,25.161837)"
++       cx="605.71429"
++       cy="486.64789"
++       fx="605.71429"
++       fy="486.64789"
++       r="117.14286" />
++    <radialGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5060"
++       id="radialGradient5667"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(6.6526975e-2,0,0,3.5014969e-2,-0.2505064,25.161837)"
++       cx="605.71429"
++       cy="486.64789"
++       fx="605.71429"
++       fy="486.64789"
++       r="117.14286" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5048"
++       id="linearGradient5670"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(6.6526975e-2,0,0,3.5014969e-2,-0.2635996,25.161837)"
++       x1="302.85715"
++       y1="366.64789"
++       x2="302.85715"
++       y2="609.50507" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient3832"
++       id="linearGradient5682"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(1.4257653,0,0,1.3494809,-45.841705,7.4048427)"
++       x1="17.88068"
++       y1="11.072588"
++       x2="17.88068"
++       y2="21.767578" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient4816"
++       id="linearGradient5684"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(1.2803684,0,0,1.2242141,-43.519693,10.324658)"
++       x1="13.050564"
++       y1="11.353518"
++       x2="13.050564"
++       y2="5.6173568" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient3832"
++       id="linearGradient5694"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(1.367592,0,0,1.259127,-45.521751,9.5621318)"
++       x1="17.88068"
++       y1="11.072588"
++       x2="17.88068"
++       y2="21.767578" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient4816"
++       id="linearGradient5696"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(1.325819,0,0,1.19936,-44.590631,11.169522)"
++       x1="13.050564"
++       y1="11.353518"
++       x2="13.050564"
++       y2="5.6173568" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5700"
++       id="linearGradient5728"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="translate(0.5,0)"
++       x1="24"
++       y1="23"
++       x2="45.505005"
++       y2="23" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5716"
++       id="linearGradient5730"
++       gradientUnits="userSpaceOnUse"
++       x1="40.745819"
++       y1="23"
++       x2="44.005268"
++       y2="23" />
++    <filter
++       inkscape:collect="always"
++       id="filter5786">
++      <feGaussianBlur
++         inkscape:collect="always"
++         stdDeviation="0.62861987"
++         id="feGaussianBlur5788" />
++    </filter>
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5598"
++       id="linearGradient5604"
++       x1="25.627417"
++       y1="8"
++       x2="25.627417"
++       y2="4.7617435"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(0.6585366,0,0,0.448956,0.195122,1.1328299)" />
++    <filter
++       inkscape:collect="always"
++       x="-0.019480519"
++       width="1.0389611"
++       y="-0.14285713"
++       height="1.2857143"
++       id="filter5628">
++      <feGaussianBlur
++         inkscape:collect="always"
++         stdDeviation="0.42857143"
++         id="feGaussianBlur5630" />
++    </filter>
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5634"
++       id="linearGradient5640"
++       x1="25.313259"
++       y1="42.656792"
++       x2="25.313261"
++       y2="10.129107"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(0.6609814,0,0,0.6406647,8.63294e-2,0.2717499)" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5642"
++       id="linearGradient5648"
++       x1="26.29347"
++       y1="7.3125"
++       x2="26.232994"
++       y2="3.5357027"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(0.6744186,0,0,0.6,-0.1860466,0.4000001)" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5650"
++       id="linearGradient5656"
++       x1="26.29347"
++       y1="7.3125"
++       x2="26.232994"
++       y2="3.5357027"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(0.6744186,0,0,0.6,-0.1860466,0.4000001)" />
++  </defs>
++  <sodipodi:namedview
++     id="base"
++     pagecolor="#ffffff"
++     bordercolor="#e0e0e0"
++     borderopacity="1"
++     gridtolerance="10000"
++     guidetolerance="10"
++     objecttolerance="10"
++     inkscape:pageopacity="0.0"
++     inkscape:pageshadow="2"
++     inkscape:zoom="1"
++     inkscape:cx="31.400129"
++     inkscape:cy="-4.050017"
++     inkscape:document-units="px"
++     inkscape:current-layer="layer1"
++     width="32px"
++     height="32px"
++     inkscape:showpageshadow="false"
++     inkscape:window-width="1102"
++     inkscape:window-height="958"
++     inkscape:window-x="2117"
++     inkscape:window-y="82"
++     showgrid="false" />
++  <metadata
++     id="metadata7859">
++    <rdf:RDF>
++      <cc:Work
++         rdf:about="">
++        <dc:format>image/svg+xml</dc:format>
++        <dc:type
++           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
++        <dc:creator>
++          <cc:Agent>
++            <dc:title>Jakub Steiner</dc:title>
++          </cc:Agent>
++        </dc:creator>
++        <dc:source>http://jimmac.musichall.cz</dc:source>
++        <cc:license
++           rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
++        <dc:title>Gnome Session Properties</dc:title>
++      </cc:Work>
++      <cc:License
++         rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
++        <cc:permits
++           rdf:resource="http://web.resource.org/cc/Reproduction" />
++        <cc:permits
++           rdf:resource="http://web.resource.org/cc/Distribution" />
++        <cc:requires
++           rdf:resource="http://web.resource.org/cc/Notice" />
++        <cc:permits
++           rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
++        <cc:requires
++           rdf:resource="http://web.resource.org/cc/ShareAlike" />
++        <cc:requires
++           rdf:resource="http://web.resource.org/cc/SourceCode" />
++      </cc:License>
++    </rdf:RDF>
++  </metadata>
++  <g
++     inkscape:label="Layer 1"
++     inkscape:groupmode="layer"
++     id="layer1">
++    <g
++       id="g5672"
++       style="opacity:0.53714288"
++       transform="matrix(0.7053465,0,0,0.9765232,-0.8197989,-14.074824)">
++      <rect
++         y="38"
++         x="7.7196383"
++         height="8.5036354"
++         width="32.123024"
++         id="rect4173"
++         style="opacity:1;color:#000000;fill:url(#linearGradient5670);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
++      <path
++         sodipodi:nodetypes="cccc"
++         id="path5058"
++         d="M 39.842663,38.000295 C 39.842663,38.000295 39.842663,46.503461 39.842663,46.503461 C 43.268636,46.519469 48.125002,44.598333 48.125,42.25133 C 48.125,39.904328 44.30187,38.000295 39.842663,38.000295 z "
++         style="opacity:1;color:#000000;fill:url(#radialGradient5667);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
++      <path
++         style="opacity:1;color:#000000;fill:url(#radialGradient5664);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
++         d="M 7.7196385,38.000295 C 7.7196385,38.000295 7.7196385,46.503461 7.7196385,46.503461 C 4.2936621,46.519469 -0.56270146,44.598333 -0.56270146,42.25133 C -0.56270146,39.904328 3.2604286,38.000295 7.7196385,38.000295 z "
++         id="path5018"
++         sodipodi:nodetypes="cccc" />
++    </g>
++    <rect
++       style="opacity:1;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:evenodd;stroke:#3465a4;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
++       id="rect4585"
++       width="29"
++       height="25.915714"
++       x="1.5"
++       y="2.5842862"
++       rx="1.5457952"
++       ry="1.4779093" />
++    <rect
++       ry="2.2922091"
++       rx="2.2922091"
++       y="4.3838844"
++       x="2.5"
++       height="5"
++       width="43"
++       id="rect5606"
++       style="opacity:0.27999998;color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.53006899;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;filter:url(#filter5628);enable-background:accumulate"
++       transform="matrix(0.6539988,0,0,0.6531321,0.5263077,0.2140377)" />
++    <rect
++       style="opacity:1;color:#000000;fill:url(#linearGradient5648);fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient5656);stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
++       id="rect5556"
++       width="29"
++       height="3"
++       x="1.5"
++       y="2.5"
++       rx="1.5459085"
++       ry="1.3753254" />
++    <rect
++       ry="0.50486249"
++       rx="0.50486249"
++       y="3.2374167"
++       x="2.5"
++       height="24.262585"
++       width="27.000004"
++       id="rect5632"
++       style="opacity:0.52571429;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient5640);stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
++    <g
++       id="g5677"
++       transform="matrix(0.6539988,0,0,0.6531321,29.351952,-3.3803525)">
++      <rect
++         id="rect3818"
++         style="color:#000000;fill:url(#linearGradient5682);fill-opacity:1;fill-rule:evenodd;stroke:#8d8d8d;stroke-width:1.5300703;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
++         y="18.189814"
++         x="-37.999996"
++         ry="0.57820499"
++         rx="0.56373626"
++         height="21.435171"
++         width="22.935822" />
++      <rect
++         id="rect3820"
++         style="color:#000000;fill:url(#linearGradient5684);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
++         y="20.486441"
++         x="-35.706413"
++         ry="0.097232968"
++         rx="0.09710411"
++         height="3.0621684"
++         width="18.348656" />
++      <rect
++         id="rect4962"
++         style="color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.53007114;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.47878789;visibility:visible;display:inline;overflow:visible"
++         y="19.7209"
++         x="-36.47094"
++         ry="0.16788077"
++         rx="0.18690105"
++         height="18.373005"
++         width="19.877708" />
++    </g>
++    <g
++       id="g5724"
++       transform="matrix(0.6539988,0,0,0.6531321,0.5263077,5.4390943)">
++      <path
++         style="opacity:0.3142857;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;filter:url(#filter5786)"
++         d="M 10.5,25.474874 L 20.5,15.474874 L 20.5,21.005204 L 40.5,21.005204 C 44.35508,21.005204 45.58678,20.95144 45.5,23 L 45.5,33 C 45.5,33 43.070425,29.988738 40.625,29.988738 L 20.5,29.988738 L 20.5,35.474874 L 10.5,25.474874 z "
++         id="path5738"
++         sodipodi:nodetypes="cccccccccc" />
++      <path
++         sodipodi:nodetypes="cccccccccc"
++         id="path5698"
++         d="M 10.5,23 L 20.5,13 L 20.5,18.53033 L 40.5,18.53033 C 44.35508,18.53033 45.58678,20.95144 45.5,23 L 45.5,33 C 45.5,33 45.096959,27.513864 40.625,27.513864 L 20.5,27.513864 L 20.5,33 L 10.5,23 z "
++         style="fill:url(#linearGradient5728);fill-opacity:1;fill-rule:evenodd;stroke:#555753;stroke-width:1.53006899px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
++      <path
++         d="M 19.1875,16.1875 L 12.375,23 L 19.1875,29.8125 L 19.1875,27.5 C 19.191541,26.776807 19.776807,26.191541 20.5,26.1875 L 40.625,26.1875 C 42.124779,26.1875 43.279176,26.742626 44.1875,27.5 L 44.1875,23 C 44.187007,22.97917 44.187007,22.95833 44.1875,22.9375 C 44.218785,22.19897 44.005899,21.434255 43.5,20.875 C 42.994101,20.315745 42.151361,19.84375 40.5,19.84375 L 20.5,19.84375 C 19.776807,19.839709 19.191541,19.254443 19.1875,18.53125 L 19.1875,16.1875 z "
++         inkscape:href="#path5698"
++         id="path5712"
++         style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient5730);stroke-width:1.53006899px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
++         xlink:href="#path5698"
++         inkscape:original="M 20.5 13 L 10.5 23 L 20.5 33 L 20.5 27.5 L 40.625 27.5 C 45.096959 27.5 45.5 33 45.5 33 L 45.5 23 C 45.58678 20.95144 44.35508 18.531249 40.5 18.53125 L 20.5 18.53125 L 20.5 13 z "
++         inkscape:radius="-1.3197637"
++         sodipodi:type="inkscape:offset" />
++    </g>
++    <rect
++       ry="0.50634968"
++       rx="0.74272269"
++       y="3.153132"
++       x="2.5"
++       height="1.346868"
++       width="27.000002"
++       id="rect4627"
++       style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient5604);stroke-width:0.99999994;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
++  </g>
++</svg>
+diff --git a/data/icons/scalable/session-properties.svg b/data/icons/scalable/session-properties.svg
+new file mode 100644
+index 0000000..cec2c39
+--- /dev/null
++++ b/data/icons/scalable/session-properties.svg
+@@ -0,0 +1,515 @@
++<?xml version="1.0" encoding="UTF-8" standalone="no"?>
++<!-- Created with Inkscape (http://www.inkscape.org/) -->
++<svg
++   xmlns:dc="http://purl.org/dc/elements/1.1/"
++   xmlns:cc="http://web.resource.org/cc/"
++   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
++   xmlns:svg="http://www.w3.org/2000/svg"
++   xmlns="http://www.w3.org/2000/svg"
++   xmlns:xlink="http://www.w3.org/1999/xlink"
++   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
++   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
++   width="48"
++   height="48"
++   id="svg7854"
++   sodipodi:version="0.32"
++   inkscape:version="0.44+devel"
++   version="1.0"
++   sodipodi:docname="session-properties.svg"
++   sodipodi:docbase="/home/jimmac/gfx/ximian/art/icons/control-center/scalable"
++   inkscape:output_extension="org.inkscape.output.svg.inkscape"
++   sodipodi:modified="true">
++  <defs
++     id="defs7856">
++    <linearGradient
++       inkscape:collect="always"
++       id="linearGradient5650">
++      <stop
++         style="stop-color:#d3d7cf;stop-opacity:1;"
++         offset="0"
++         id="stop5652" />
++      <stop
++         style="stop-color:#9ea795;stop-opacity:1"
++         offset="1"
++         id="stop5654" />
++    </linearGradient>
++    <linearGradient
++       inkscape:collect="always"
++       id="linearGradient5642">
++      <stop
++         style="stop-color:#eeeeec;stop-opacity:1;"
++         offset="0"
++         id="stop5644" />
++      <stop
++         style="stop-color:#c3c3bc;stop-opacity:1"
++         offset="1"
++         id="stop5646" />
++    </linearGradient>
++    <linearGradient
++       inkscape:collect="always"
++       id="linearGradient5634">
++      <stop
++         style="stop-color:#ffffff;stop-opacity:1;"
++         offset="0"
++         id="stop5636" />
++      <stop
++         style="stop-color:#ffffff;stop-opacity:0;"
++         offset="1"
++         id="stop5638" />
++    </linearGradient>
++    <linearGradient
++       inkscape:collect="always"
++       id="linearGradient5598">
++      <stop
++         style="stop-color:#ffffff;stop-opacity:1;"
++         offset="0"
++         id="stop5600" />
++      <stop
++         style="stop-color:#ffffff;stop-opacity:0;"
++         offset="1"
++         id="stop5602" />
++    </linearGradient>
++    <linearGradient
++       inkscape:collect="always"
++       id="linearGradient5716">
++      <stop
++         style="stop-color:#ffffff;stop-opacity:1;"
++         offset="0"
++         id="stop5718" />
++      <stop
++         style="stop-color:#ffffff;stop-opacity:0;"
++         offset="1"
++         id="stop5720" />
++    </linearGradient>
++    <linearGradient
++       inkscape:collect="always"
++       id="linearGradient5700">
++      <stop
++         style="stop-color:#e4e4e4;stop-opacity:1;"
++         offset="0"
++         id="stop5702" />
++      <stop
++         id="stop5708"
++         offset="0.639386"
++         style="stop-color:#fefefe;stop-opacity:1" />
++      <stop
++         style="stop-color:#ffffff;stop-opacity:1"
++         offset="0.79632628"
++         id="stop5710" />
++      <stop
++         style="stop-color:#949494;stop-opacity:1"
++         offset="1"
++         id="stop5704" />
++    </linearGradient>
++    <linearGradient
++       id="linearGradient3832">
++      <stop
++         id="stop3834"
++         offset="0.0000000"
++         style="stop-color:#ffffff;stop-opacity:1.0000000" />
++      <stop
++         id="stop3836"
++         offset="1.0000000"
++         style="stop-color:#e0e0e0;stop-opacity:1.0000000" />
++    </linearGradient>
++    <linearGradient
++       id="linearGradient4816">
++      <stop
++         id="stop4818"
++         offset="0.0000000"
++         style="stop-color:#204a87;stop-opacity:1.0000000" />
++      <stop
++         id="stop4820"
++         offset="1.0000000"
++         style="stop-color:#204a87;stop-opacity:0.0000000" />
++    </linearGradient>
++    <linearGradient
++       id="linearGradient5048">
++      <stop
++         id="stop5050"
++         offset="0"
++         style="stop-color:black;stop-opacity:0;" />
++      <stop
++         style="stop-color:black;stop-opacity:1;"
++         offset="0.5"
++         id="stop5056" />
++      <stop
++         id="stop5052"
++         offset="1"
++         style="stop-color:black;stop-opacity:0;" />
++    </linearGradient>
++    <linearGradient
++       id="linearGradient5060"
++       inkscape:collect="always">
++      <stop
++         id="stop5062"
++         offset="0"
++         style="stop-color:black;stop-opacity:1;" />
++      <stop
++         id="stop5064"
++         offset="1"
++         style="stop-color:black;stop-opacity:0;" />
++    </linearGradient>
++    <radialGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5060"
++       id="radialGradient5664"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(-6.6526975e-2,0,0,3.5014969e-2,47.812816,25.161837)"
++       cx="605.71429"
++       cy="486.64789"
++       fx="605.71429"
++       fy="486.64789"
++       r="117.14286" />
++    <radialGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5060"
++       id="radialGradient5667"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(6.6526975e-2,0,0,3.5014969e-2,-0.2505064,25.161837)"
++       cx="605.71429"
++       cy="486.64789"
++       fx="605.71429"
++       fy="486.64789"
++       r="117.14286" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5048"
++       id="linearGradient5670"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(6.6526975e-2,0,0,3.5014969e-2,-0.2635996,25.161837)"
++       x1="302.85715"
++       y1="366.64789"
++       x2="302.85715"
++       y2="609.50507" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient3832"
++       id="linearGradient5682"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(1.367592,0,0,1.259127,-45.521751,9.5621318)"
++       x1="17.880680"
++       y1="11.072588"
++       x2="17.880680"
++       y2="21.767578" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient4816"
++       id="linearGradient5684"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(1.325819,0,0,1.19936,-44.590631,11.169522)"
++       x1="13.050564"
++       y1="11.353518"
++       x2="13.050564"
++       y2="5.6173568" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient3832"
++       id="linearGradient5694"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(1.367592,0,0,1.259127,-45.521751,9.5621318)"
++       x1="17.880680"
++       y1="11.072588"
++       x2="17.880680"
++       y2="21.767578" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient4816"
++       id="linearGradient5696"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="matrix(1.325819,0,0,1.19936,-44.590631,11.169522)"
++       x1="13.050564"
++       y1="11.353518"
++       x2="13.050564"
++       y2="5.6173568" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5700"
++       id="linearGradient5728"
++       gradientUnits="userSpaceOnUse"
++       gradientTransform="translate(0.5,0)"
++       x1="24"
++       y1="23"
++       x2="45.505004"
++       y2="23" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5716"
++       id="linearGradient5730"
++       gradientUnits="userSpaceOnUse"
++       x1="40.745819"
++       y1="23"
++       x2="44.005268"
++       y2="23" />
++    <filter
++       inkscape:collect="always"
++       id="filter5786">
++      <feGaussianBlur
++         inkscape:collect="always"
++         stdDeviation="0.62861987"
++         id="feGaussianBlur5788" />
++    </filter>
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5598"
++       id="linearGradient5604"
++       x1="25.627417"
++       y1="8"
++       x2="25.627417"
++       y2="4.7617435"
++       gradientUnits="userSpaceOnUse" />
++    <filter
++       inkscape:collect="always"
++       x="-0.019480519"
++       width="1.038961"
++       y="-0.14285714"
++       height="1.2857143"
++       id="filter5628">
++      <feGaussianBlur
++         inkscape:collect="always"
++         stdDeviation="0.42857143"
++         id="feGaussianBlur5630" />
++    </filter>
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5634"
++       id="linearGradient5640"
++       x1="25.313259"
++       y1="42.656792"
++       x2="25.313261"
++       y2="10.129107"
++       gradientUnits="userSpaceOnUse" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5642"
++       id="linearGradient5648"
++       x1="26.29347"
++       y1="7.3125"
++       x2="26.232994"
++       y2="3.5357027"
++       gradientUnits="userSpaceOnUse" />
++    <linearGradient
++       inkscape:collect="always"
++       xlink:href="#linearGradient5650"
++       id="linearGradient5656"
++       x1="26.29347"
++       y1="7.3125"
++       x2="26.232994"
++       y2="3.5357027"
++       gradientUnits="userSpaceOnUse" />
++  </defs>
++  <sodipodi:namedview
++     id="base"
++     pagecolor="#ffffff"
++     bordercolor="#e0e0e0"
++     borderopacity="1"
++     gridtolerance="10000"
++     guidetolerance="10"
++     objecttolerance="10"
++     inkscape:pageopacity="0.0"
++     inkscape:pageshadow="2"
++     inkscape:zoom="4"
++     inkscape:cx="20.372005"
++     inkscape:cy="14.768475"
++     inkscape:document-units="px"
++     inkscape:current-layer="layer1"
++     width="48px"
++     height="48px"
++     inkscape:showpageshadow="false"
++     inkscape:window-width="1102"
++     inkscape:window-height="958"
++     inkscape:window-x="2117"
++     inkscape:window-y="82"
++     showgrid="false" />
++  <metadata
++     id="metadata7859">
++    <rdf:RDF>
++      <cc:Work
++         rdf:about="">
++        <dc:format>image/svg+xml</dc:format>
++        <dc:type
++           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
++        <dc:creator>
++          <cc:Agent>
++            <dc:title>Jakub Steiner</dc:title>
++          </cc:Agent>
++        </dc:creator>
++        <dc:source>http://jimmac.musichall.cz</dc:source>
++        <cc:license
++           rdf:resource="http://creativecommons.org/licenses/GPL/2.0/" />
++        <dc:title>Gnome Session Properties</dc:title>
++      </cc:Work>
++      <cc:License
++         rdf:about="http://creativecommons.org/licenses/GPL/2.0/">
++        <cc:permits
++           rdf:resource="http://web.resource.org/cc/Reproduction" />
++        <cc:permits
++           rdf:resource="http://web.resource.org/cc/Distribution" />
++        <cc:requires
++           rdf:resource="http://web.resource.org/cc/Notice" />
++        <cc:permits
++           rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
++        <cc:requires
++           rdf:resource="http://web.resource.org/cc/ShareAlike" />
++        <cc:requires
++           rdf:resource="http://web.resource.org/cc/SourceCode" />
++      </cc:License>
++    </rdf:RDF>
++  </metadata>
++  <g
++     inkscape:label="Layer 1"
++     inkscape:groupmode="layer"
++     id="layer1">
++    <g
++       id="g5672"
++       style="opacity:0.53714286">
++      <rect
++         y="38"
++         x="7.7196383"
++         height="8.5036354"
++         width="32.123024"
++         id="rect4173"
++         style="opacity:1;color:#000000;fill:url(#linearGradient5670);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
++      <path
++         sodipodi:nodetypes="cccc"
++         id="path5058"
++         d="M 39.842663,38.000295 C 39.842663,38.000295 39.842663,46.503461 39.842663,46.503461 C 43.268636,46.519469 48.125002,44.598333 48.125,42.25133 C 48.125,39.904328 44.30187,38.000295 39.842663,38.000295 z "
++         style="opacity:1;color:#000000;fill:url(#radialGradient5667);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" />
++      <path
++         style="opacity:1;color:#000000;fill:url(#radialGradient5664);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
++         d="M 7.7196385,38.000295 C 7.7196385,38.000295 7.7196385,46.503461 7.7196385,46.503461 C 4.2936621,46.519469 -0.56270146,44.598333 -0.56270146,42.25133 C -0.56270146,39.904328 3.2604286,38.000295 7.7196385,38.000295 z "
++         id="path5018"
++         sodipodi:nodetypes="cccc" />
++    </g>
++    <rect
++       style="opacity:1;color:#000000;fill:#729fcf;fill-opacity:1;fill-rule:evenodd;stroke:#3465a4;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
++       id="rect4585"
++       width="42.848347"
++       height="39.870949"
++       x="2.6516504"
++       y="3.6290491"
++       rx="2.2839575"
++       ry="2.273742" />
++    <rect
++       ry="2.2922091"
++       rx="2.2922091"
++       y="4.3838844"
++       x="2.5"
++       height="5"
++       width="43"
++       id="rect5606"
++       style="opacity:0.28;color:#000000;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate;filter:url(#filter5628)" />
++    <rect
++       style="opacity:1;color:#000000;fill:url(#linearGradient5648);fill-opacity:1.0;fill-rule:evenodd;stroke:url(#linearGradient5656);stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
++       id="rect5556"
++       width="43"
++       height="5"
++       x="2.5"
++       y="3.5"
++       rx="2.2922091"
++       ry="2.2922091" />
++    <rect
++       ry="1.2758038"
++       rx="1.2758038"
++       y="4.6290464"
++       x="3.6516466"
++       height="37.870953"
++       width="40.848354"
++       id="rect5632"
++       style="opacity:0.52571429;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient5640);stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
++    <g
++       id="g5677"
++       transform="translate(43.499997,-2.124989)">
++      <rect
++         id="rect3818"
++         style="color:#000000;fill:url(#linearGradient5682);fill-opacity:1;fill-rule:evenodd;stroke:#8d8d8d;stroke-width:1.00000095;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
++         y="19.625"
++         x="-37.999996"
++         ry="0.53949153"
++         rx="0.54073501"
++         height="19.999989"
++         width="22.000008" />
++      <rect
++         id="rect3820"
++         style="color:#000000;fill:url(#linearGradient5684);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
++         y="21.125"
++         x="-36.499996"
++         ry="0.095258936"
++         rx="0.10055112"
++         height="3"
++         width="19" />
++      <rect
++         id="rect4962"
++         style="color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.00000143;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.47878789;visibility:visible;display:inline;overflow:visible"
++         y="20.624994"
++         x="-37"
++         ry="0.16447251"
++         rx="0.188051"
++         height="18.000002"
++         width="20.000011" />
++    </g>
++    <g
++       transform="translate(53.499997,-7.124989)"
++       id="g5686">
++      <rect
++         width="22.000008"
++         height="19.999989"
++         rx="0.54073501"
++         ry="0.53949153"
++         x="-37.999996"
++         y="19.625"
++         style="color:#000000;fill:url(#linearGradient5694);fill-opacity:1;fill-rule:evenodd;stroke:#8d8d8d;stroke-width:1.00000095;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
++         id="rect5688" />
++      <rect
++         width="19"
++         height="3"
++         rx="0.10055112"
++         ry="0.095258936"
++         x="-36.499996"
++         y="21.125"
++         style="color:#000000;fill:url(#linearGradient5696);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
++         id="rect5690" />
++      <rect
++         width="20.000011"
++         height="18.000002"
++         rx="0.188051"
++         ry="0.16447251"
++         x="-37"
++         y="20.624994"
++         style="color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:1.00000143;stroke-linecap:butt;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.47878789;visibility:visible;display:inline;overflow:visible"
++         id="rect5692" />
++    </g>
++    <g
++       id="g5724"
++       transform="translate(0,8)">
++      <path
++         style="fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;opacity:0.31428571;filter:url(#filter5786)"
++         d="M 10.5,25.474874 L 20.5,15.474874 L 20.5,21.005204 L 40.5,21.005204 C 44.35508,21.005204 45.58678,20.95144 45.5,23 L 45.5,33 C 45.5,33 43.070425,29.988738 40.625,29.988738 L 20.5,29.988738 L 20.5,35.474874 L 10.5,25.474874 z "
++         id="path5738"
++         sodipodi:nodetypes="cccccccccc" />
++      <path
++         sodipodi:nodetypes="cccccccccc"
++         id="path5698"
++         d="M 10.5,23 L 20.5,13 L 20.5,18.53033 L 40.5,18.53033 C 44.35508,18.53033 45.58678,20.95144 45.5,23 L 45.5,33 C 45.5,33 45.096959,27.513864 40.625,27.513864 L 20.5,27.513864 L 20.5,33 L 10.5,23 z "
++         style="fill:url(#linearGradient5728);fill-opacity:1;fill-rule:evenodd;stroke:#555753;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
++      <path
++         d="M 19.5625,15.25 L 11.8125,23 L 19.5625,30.75 L 19.5625,27.5 C 19.55998,27.250596 19.657943,27.010672 19.834307,26.834307 C 20.010672,26.657943 20.250596,26.55998 20.5,26.5625 L 40.625,26.5625 C 42.489029,26.5625 43.674657,27.497362 44.5625,28.5625 L 44.5625,23 C 44.562325,22.989584 44.562325,22.979166 44.5625,22.96875 C 44.597378,22.145414 44.36819,21.273844 43.78125,20.625 C 43.19431,19.976156 42.233327,19.46875 40.5,19.46875 L 20.5,19.46875 C 20.250596,19.47127 20.010672,19.373307 19.834307,19.196943 C 19.657943,19.020578 19.55998,18.780654 19.5625,18.53125 L 19.5625,15.25 z "
++         inkscape:href="#path5698"
++         id="path5712"
++         style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient5730);stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
++         xlink:href="#path5698"
++         inkscape:original="M 20.5 13 L 10.5 23 L 20.5 33 L 20.5 27.5 L 40.625 27.5 C 45.096959 27.5 45.5 33 45.5 33 L 45.5 23 C 45.58678 20.95144 44.35508 18.531249 40.5 18.53125 L 20.5 18.53125 L 20.5 13 z "
++         inkscape:radius="-0.92807764"
++         sodipodi:type="inkscape:offset" />
++    </g>
++    <rect
++       ry="1.1278381"
++       rx="1.1278381"
++       y="4.5"
++       x="3.5"
++       height="3"
++       width="41"
++       id="rect4627"
++       style="opacity:1;color:#000000;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient5604);stroke-width:1;stroke-linecap:square;stroke-linejoin:round;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
++  </g>
++</svg>
+diff --git a/data/icons/symbolic/session-properties-symbolic.svg b/data/icons/symbolic/session-properties-symbolic.svg
+new file mode 100644
+index 0000000..497fb9d
+--- /dev/null
++++ b/data/icons/symbolic/session-properties-symbolic.svg
+@@ -0,0 +1,28 @@
++<?xml version='1.0' encoding='UTF-8' standalone='no'?>
++<!-- Created with Inkscape (http://www.inkscape.org/) -->
++
++<svg xmlns:cc='http://creativecommons.org/ns#' xmlns:dc='http://purl.org/dc/elements/1.1/' sodipodi:docname='gnome-session-properties-symbolic.svg' height='16.000015' id='svg7384' xmlns:inkscape='http://www.inkscape.org/namespaces/inkscape' xmlns:osb='http://www.openswatchbook.org/uri/2009/osb' xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns:sodipodi='http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd' xmlns:svg='http://www.w3.org/2000/svg' version='1.1' inkscape:version='0.91 r13725' width='16.000013' xmlns='http://www.w3.org/2000/svg'>
++  <metadata id='metadata90'>
++    <rdf:RDF>
++      <cc:Work rdf:about=''>
++        <dc:format>image/svg+xml</dc:format>
++        <dc:type rdf:resource='http://purl.org/dc/dcmitype/StillImage'/>
++        <dc:title>Gnome Symbolic Icon Theme</dc:title>
++      </cc:Work>
++    </rdf:RDF>
++  </metadata>
++  <sodipodi:namedview inkscape:bbox-paths='true' bordercolor='#666666' borderopacity='1' inkscape:current-layer='layer9' inkscape:cx='16.984015' inkscape:cy='3.9235845' gridtolerance='10' inkscape:guide-bbox='true' guidetolerance='10' id='namedview88' inkscape:object-nodes='false' inkscape:object-paths='false' objecttolerance='10' pagecolor='#555753' inkscape:pageopacity='1' inkscape:pageshadow='2' showborder='false' showgrid='false' showguides='true' inkscape:snap-bbox='true' inkscape:snap-bbox-midpoints='false' inkscape:snap-global='true' inkscape:snap-grids='true' inkscape:snap-nodes='true' inkscape:snap-others='false' inkscape:snap-to-guides='true' inkscape:window-height='1376' inkscape:window-maximized='1' inkscape:window-width='2560' inkscape:window-x='0' inkscape:window-y='27' inkscape:zoom='1'>
++    <inkscape:grid empspacing='2' enabled='true' id='grid4866' originx='-22' originy='-341.99999' snapvisiblegridlinesonly='true' spacingx='1px' spacingy='1px' type='xygrid' visible='true'/>
++  </sodipodi:namedview>
++  <title id='title9167'>Gnome Symbolic Icon Theme</title>
++  <defs id='defs7386'>
++    <linearGradient id='linearGradient7212' osb:paint='solid'>
++      <stop id='stop7214' offset='0' style='stop-color:#000000;stop-opacity:1;'/>
++    </linearGradient>
++  </defs>
++  <g inkscape:groupmode='layer' id='layer9' inkscape:label='apps' style='display:inline' transform='translate(-263.0002,125)'>
++    <path inkscape:connector-curvature='0' d='m 264.03145,-125 c -0.56312,0 -1.03125,0.43688 -1.03125,1 l 0,2 16,0 0,-2 c 0,-0.56312 -0.43688,-1 -1,-1 z' id='rect10231' sodipodi:nodetypes='ssccsss' style='color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#bebebe;fill-opacity:0.36470588;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate'/>
++    <path inkscape:connector-curvature='0' d='m 263.0002,-120.96865 0,10.9061 c 0,0.5631 0.46813,1.0314 1.03125,1.0314 l 13.96875,0 c 0.56312,0 1,-0.4683 1,-1.0314 l 0,-10.9061 z m 6,0.9686 9,0 0,7 -9,0 z m 1,2 0,4 7,0 0,-4 z m -5,1 3,0 0,2 -2,0 0,4 7,0 0,-0.9686 1,0 0,1.9686 -9,0 z' id='rect10231-3' sodipodi:nodetypes='cssssccccccccccccccccccccccc' style='color:#000000;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;fill:#bebebe;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate'/>
++
++  </g>
++</svg>
+diff --git a/data/meson.build b/data/meson.build
+index 07fe12a..5f72bd0 100644
+--- a/data/meson.build
++++ b/data/meson.build
+@@ -232,7 +232,30 @@ if enable_session_selector
+   data += files('session-selector.ui')
+ endif
+ 
++desktop = configure_file(
++  input: 'gnome-session-properties.desktop.in',
++  output: 'gnome-session-properties.desktop',
++  configuration: desktop_conf
++)
++
++install_data(
++  desktop,
++  install_dir : join_paths(session_datadir, 'applications')
++)
++
++data += files('session-properties.ui')
++
+ install_data(
+   data,
+   install_dir: session_pkgdatadir
+ )
++
++icondir = join_paths(get_option('datadir'), 'icons/hicolor')
++foreach size: ['16x16', '22x22', '32x32', 'symbolic']
++  install_subdir('icons/' + size, install_dir: icondir)
++endforeach
++
++install_data(
++  'icons/scalable/session-properties.svg',
++  install_dir: icondir + '/scalable/apps'
++)
+diff --git a/data/session-properties.ui b/data/session-properties.ui
+new file mode 100644
+index 0000000..6526154
+--- /dev/null
++++ b/data/session-properties.ui
+@@ -0,0 +1,303 @@
++<?xml version="1.0"?>
++<interface>
++  <requires lib="gtk+" version="2.16"/>
++  <!-- interface-naming-policy toplevel-contextual -->
++  <object class="GtkVBox" id="main-notebook">
++    <property name="visible">True</property>
++    <property name="border_width">6</property>
++    <child>
++      <object class="GtkVBox" id="vbox1">
++        <property name="visible">True</property>
++        <property name="border_width">12</property>
++        <property name="orientation">vertical</property>
++        <property name="spacing">3</property>
++        <child>
++          <object class="GtkLabel" id="label6">
++            <property name="visible">True</property>
++            <property name="xalign">0</property>
++            <property name="xpad">3</property>
++            <property name="ypad">3</property>
++            <property name="label" translatable="yes">Additional startup _programs:</property>
++            <property name="use_underline">True</property>
++            <property name="mnemonic_widget">session_properties_treeview</property>
++          </object>
++          <packing>
++            <property name="expand">False</property>
++            <property name="position">0</property>
++          </packing>
++        </child>
++        <child>
++          <object class="GtkHBox" id="hbox1">
++            <property name="visible">True</property>
++            <property name="spacing">6</property>
++            <child>
++              <object class="GtkScrolledWindow" id="scrolledwindow1">
++                <property name="visible">True</property>
++                <property name="can_focus">True</property>
++                <property name="hscrollbar_policy">never</property>
++                <property name="vscrollbar_policy">automatic</property>
++                <property name="shadow_type">etched-in</property>
++                <child>
++                  <object class="GtkTreeView" id="session_properties_treeview">
++                    <property name="height_request">210</property>
++                    <property name="visible">True</property>
++                    <property name="can_focus">True</property>
++                  </object>
++                </child>
++              </object>
++              <packing>
++                <property name="position">0</property>
++              </packing>
++            </child>
++            <child>
++              <object class="GtkVButtonBox" id="vbuttonbox1">
++                <property name="visible">True</property>
++                <property name="spacing">6</property>
++                <property name="layout_style">start</property>
++                <child>
++                  <object class="GtkButton" id="session_properties_add_button">
++                    <property name="label">gtk-add</property>
++                    <property name="visible">True</property>
++                    <property name="can_focus">True</property>
++                    <property name="receives_default">True</property>
++                    <property name="use_stock">True</property>
++                  </object>
++                  <packing>
++                    <property name="expand">False</property>
++                    <property name="fill">False</property>
++                    <property name="position">0</property>
++                  </packing>
++                </child>
++                <child>
++                  <object class="GtkButton" id="session_properties_delete_button">
++                    <property name="label">gtk-remove</property>
++                    <property name="visible">True</property>
++                    <property name="sensitive">False</property>
++                    <property name="can_focus">True</property>
++                    <property name="receives_default">True</property>
++                    <property name="use_stock">True</property>
++                  </object>
++                  <packing>
++                    <property name="expand">False</property>
++                    <property name="fill">False</property>
++                    <property name="position">1</property>
++                  </packing>
++                </child>
++                <child>
++                  <object class="GtkButton" id="session_properties_edit_button">
++                    <property name="label">gtk-edit</property>
++                    <property name="visible">True</property>
++                    <property name="sensitive">False</property>
++                    <property name="can_focus">True</property>
++                    <property name="receives_default">True</property>
++                    <property name="use_stock">True</property>
++                  </object>
++                  <packing>
++                    <property name="expand">False</property>
++                    <property name="fill">False</property>
++                    <property name="position">2</property>
++                  </packing>
++                </child>
++              </object>
++              <packing>
++                <property name="expand">False</property>
++                <property name="fill">False</property>
++                <property name="position">1</property>
++              </packing>
++            </child>
++          </object>
++          <packing>
++            <property name="position">1</property>
++          </packing>
++        </child>
++      </object>
++    </child>
++    <child>
++      <object class="GtkVBox" id="vbox3">
++        <property name="visible">False</property>
++        <property name="border_width">12</property>
++        <property name="orientation">vertical</property>
++        <property name="spacing">6</property>
++        <child>
++          <object class="GtkCheckButton" id="session_properties_remember_toggle">
++            <property name="label" translatable="yes">_Automatically remember running applications when logging out</property>
++            <property name="visible">True</property>
++            <property name="can_focus">True</property>
++            <property name="receives_default">False</property>
++            <property name="use_underline">True</property>
++            <property name="draw_indicator">True</property>
++          </object>
++          <packing>
++            <property name="expand">False</property>
++            <property name="fill">False</property>
++            <property name="position">0</property>
++          </packing>
++        </child>
++        <child>
++          <object class="GtkHButtonBox" id="hbuttonbox1">
++            <property name="visible">True</property>
++            <child>
++              <object class="GtkButton" id="session_properties_save_button">
++                <property name="can_focus">True</property>
++                <property name="receives_default">True</property>
++                <child>
++                  <object class="GtkHBox" id="hbox2">
++                    <property name="visible">True</property>
++                    <property name="spacing">4</property>
++                    <child>
++                      <object class="GtkImage" id="image1">
++                        <property name="visible">True</property>
++                        <property name="stock">gtk-save</property>
++                      </object>
++                      <packing>
++                        <property name="expand">False</property>
++                        <property name="fill">False</property>
++                        <property name="position">0</property>
++                      </packing>
++                    </child>
++                    <child>
++                      <object class="GtkLabel" id="label7">
++                        <property name="visible">True</property>
++                        <property name="label" translatable="yes">_Remember Currently Running Applications</property>
++                        <property name="use_underline">True</property>
++                      </object>
++                      <packing>
++                        <property name="position">1</property>
++                      </packing>
++                    </child>
++                  </object>
++                </child>
++              </object>
++              <packing>
++                <property name="expand">False</property>
++                <property name="fill">False</property>
++                <property name="position">0</property>
++              </packing>
++            </child>
++          </object>
++          <packing>
++            <property name="expand">False</property>
++            <property name="fill">False</property>
++            <property name="position">1</property>
++          </packing>
++        </child>
++      </object>
++      <packing>
++        <property name="position">1</property>
++      </packing>
++    </child>
++  </object>
++  <object class="GtkTable" id="main-table">
++    <property name="visible">True</property>
++    <property name="border_width">6</property>
++    <property name="n_rows">3</property>
++    <property name="n_columns">2</property>
++    <property name="column_spacing">12</property>
++    <property name="row_spacing">6</property>
++    <child>
++      <object class="GtkHBox" id="hbox3">
++        <property name="visible">True</property>
++        <property name="spacing">12</property>
++        <child>
++          <object class="GtkEntry" id="session_properties_command_entry">
++            <property name="visible">True</property>
++            <property name="can_focus">True</property>
++            <property name="invisible_char">&#x25CF;</property>
++          </object>
++          <packing>
++            <property name="position">0</property>
++          </packing>
++        </child>
++        <child>
++          <object class="GtkButton" id="session_properties_browse_button">
++            <property name="label" translatable="yes">Browse…</property>
++            <property name="visible">True</property>
++            <property name="can_focus">True</property>
++            <property name="receives_default">True</property>
++          </object>
++          <packing>
++            <property name="expand">False</property>
++            <property name="fill">False</property>
++            <property name="position">1</property>
++          </packing>
++        </child>
++      </object>
++      <packing>
++        <property name="left_attach">1</property>
++        <property name="right_attach">2</property>
++        <property name="top_attach">1</property>
++        <property name="bottom_attach">2</property>
++        <property name="y_options">GTK_FILL</property>
++      </packing>
++    </child>
++    <child>
++      <object class="GtkEntry" id="session_properties_comment_entry">
++        <property name="visible">True</property>
++        <property name="can_focus">True</property>
++        <property name="invisible_char">&#x25CF;</property>
++      </object>
++      <packing>
++        <property name="left_attach">1</property>
++        <property name="right_attach">2</property>
++        <property name="top_attach">2</property>
++        <property name="bottom_attach">3</property>
++        <property name="y_options">GTK_FILL</property>
++      </packing>
++    </child>
++    <child>
++      <object class="GtkEntry" id="session_properties_name_entry">
++        <property name="visible">True</property>
++        <property name="can_focus">True</property>
++        <property name="invisible_char">&#x25CF;</property>
++      </object>
++      <packing>
++        <property name="left_attach">1</property>
++        <property name="right_attach">2</property>
++        <property name="y_options">GTK_FILL</property>
++      </packing>
++    </child>
++    <child>
++      <object class="GtkLabel" id="label3">
++        <property name="visible">True</property>
++        <property name="xalign">0</property>
++        <property name="label" translatable="yes">Comm_ent:</property>
++        <property name="use_underline">True</property>
++        <property name="mnemonic_widget">label2</property>
++      </object>
++      <packing>
++        <property name="top_attach">2</property>
++        <property name="bottom_attach">3</property>
++        <property name="x_options">GTK_FILL</property>
++        <property name="y_options">GTK_FILL</property>
++      </packing>
++    </child>
++    <child>
++      <object class="GtkLabel" id="label2">
++        <property name="visible">True</property>
++        <property name="xalign">0</property>
++        <property name="label" translatable="yes">Co_mmand:</property>
++        <property name="use_underline">True</property>
++        <property name="mnemonic_widget">session_properties_command_entry</property>
++      </object>
++      <packing>
++        <property name="top_attach">1</property>
++        <property name="bottom_attach">2</property>
++        <property name="x_options">GTK_FILL</property>
++        <property name="y_options">GTK_FILL</property>
++      </packing>
++    </child>
++    <child>
++      <object class="GtkLabel" id="label1">
++        <property name="visible">True</property>
++        <property name="xalign">0</property>
++        <property name="label" translatable="yes">_Name:</property>
++        <property name="use_underline">True</property>
++        <property name="mnemonic_widget">session_properties_name_entry</property>
++      </object>
++      <packing>
++        <property name="x_options">GTK_FILL</property>
++        <property name="y_options">GTK_FILL</property>
++      </packing>
++    </child>
++  </object>
++</interface>
+diff --git a/doc/man/gnome-session-properties.1 b/doc/man/gnome-session-properties.1
+new file mode 100644
+index 0000000..c7ef1af
+--- /dev/null
++++ b/doc/man/gnome-session-properties.1
+@@ -0,0 +1,24 @@
++.\"
++.\" gnome-session-properties manual page.
++.\" (C) 2009-2010 Vincent Untz (vuntz@gnome.org)
++.\"
++.TH GNOME-SESSION-PROPERTIES 1 "GNOME"
++.SH NAME
++gnome-session-properties \- Configure applications to start on login
++.SH SYNOPSIS
++.B gnome-session-properties
++.SH DESCRIPTION
++.PP
++The \fIgnome-session-properties\fP program enables the users to
++configure what applications should be started on login, in addition to
++the default startup applications configured on the system.
++.PP
++It also proposes an interface to save a snapshot of the currently
++running applications so that they can automatically be restored to
++their current state on your next GNOME session.
++.SH BUGS
++If you find bugs in the \fIgnome-session-properties\fP program, please report
++these on https://bugzilla.gnome.org.
++.SH SEE ALSO
++.BR gnome-session(1)
++.BR gnome-session-quit(1)
+diff --git a/doc/man/gnome-session.1 b/doc/man/gnome-session.1
+index 7f6f360..8b309ec 100644
+--- a/doc/man/gnome-session.1
++++ b/doc/man/gnome-session.1
+@@ -166,6 +166,7 @@ files. This variable overrides all directories specified via the
+ .B /usr/share/gnome/autostart
+ .IP
+ Applications defined via .desktop files in those directories will be started on login.
++\fIgnome-session-properties(1)\fP can be used to easily configure them.
+ .PP
+ .B $XDG_CONFIG_HOME/gnome-session/sessions
+ .B $XDG_CONFIG_DIRS/gnome-session/sessions
+@@ -181,4 +182,5 @@ This directory contains the list of applications of the saved session.
+ If you find bugs in the \fIgnome-session\fP program, please report
+ these on https://gitlab.gnome.org/GNOME/gnome-session/issues.
+ .SH SEE ALSO
++.BR gnome-session-properties(1)
+ .BR gnome-session-quit(1)
+diff --git a/doc/man/meson.build b/doc/man/meson.build
+index 4a389bc..9d9cc2d 100644
+--- a/doc/man/meson.build
++++ b/doc/man/meson.build
+@@ -34,7 +34,8 @@ endforeach
+ 
+ man_data = files(
+   'gnome-session.1',
+-  'gnome-session-quit.1'
++  'gnome-session-quit.1',
++  'gnome-session-properties.1'
+ )
+ 
+ install_data(
+diff --git a/meson.build b/meson.build
+index 88110f7..7181335 100644
+--- a/meson.build
++++ b/meson.build
+@@ -187,6 +187,7 @@ top_inc = include_directories('.')
+ subdir('gnome-session')
+ subdir('tools')
+ subdir('data')
++subdir('capplet')
+ 
+ enable_docbook = get_option('docbook')
+ enable_man = get_option('man')
+diff --git a/po/POTFILES.in b/po/POTFILES.in
+index 2483de2..68c0699 100644
+--- a/po/POTFILES.in
++++ b/po/POTFILES.in
+@@ -1,5 +1,9 @@
+ # List of source files containing translatable strings.
+ # Please keep this file sorted alphabetically.
++capplet/gsm-app-dialog.c
++capplet/gsm-properties-dialog.c
++capplet/gsp-app.c
++capplet/main.c
+ data/gnome-custom-session.desktop.in.in
+ data/gnome.desktop.in.in
+ data/gnome-dummy.session.desktop.in.in
+@@ -7,7 +11,9 @@ data/gnome.session.desktop.in.in
+ data/gnome-wayland.desktop.in.in
+ data/gnome-xorg.desktop.in.in
+ data/org.gnome.SessionManager.gschema.xml.in
++data/gnome-session-properties.desktop.in
+ data/session-selector.ui
++data/session-properties.ui
+ data/ubuntu.desktop.in.in
+ data/ubuntu-wayland.desktop.in.in
+ data/ubuntu-xorg.desktop.in.in
+diff --git a/po/POTFILES.skip b/po/POTFILES.skip
+index 4d20abb..c9ed3ae 100644
+--- a/po/POTFILES.skip
++++ b/po/POTFILES.skip
+@@ -7,6 +7,7 @@ data/gnome-dummy.session.desktop.in
+ data/gnome.session.desktop.in
+ data/gnome-wayland.desktop.in
+ data/gnome-xorg.desktop.in
++data/gnome-session-properties.desktop
+ data/ubuntu.desktop.in
+ data/ubuntu-wayland.desktop.in
+ data/ubuntu-xorg.desktop.in
diff -pruN 43.0-1/debian/patches/series 43.0-1ubuntu2/debian/patches/series
--- 43.0-1/debian/patches/series	2022-10-11 18:08:35.000000000 +0000
+++ 43.0-1ubuntu2/debian/patches/series	2022-10-13 11:13:51.000000000 +0000
@@ -1 +1,8 @@
 debian/Revert-main-Remove-GNOME_DESKTOP_SESSION_ID-envvar.patch
+ubuntu/support_autostart_delay.patch
+ubuntu/ubuntu-sessions.patch
+ubuntu/remove_session_saving_from_gui.patch
+ubuntu/add_sessionmigration.patch
+ubuntu/dbus_request_shutdown.patch
+ubuntu/ignore_gsettings_region.patch
+revert_remove_gnome_session_properties.patch
diff -pruN 43.0-1/debian/patches/ubuntu/add_sessionmigration.patch 43.0-1ubuntu2/debian/patches/ubuntu/add_sessionmigration.patch
--- 43.0-1/debian/patches/ubuntu/add_sessionmigration.patch	1970-01-01 00:00:00.000000000 +0000
+++ 43.0-1ubuntu2/debian/patches/ubuntu/add_sessionmigration.patch	2022-10-13 11:13:51.000000000 +0000
@@ -0,0 +1,27 @@
+From: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
+Date: Wed, 15 Aug 2018 17:13:26 +0200
+Subject: gsm-session-fill: Launch session migration
+
+===================================================================
+---
+ gnome-session/gsm-session-fill.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/gnome-session/gsm-session-fill.c b/gnome-session/gsm-session-fill.c
+index 191b6ce..4494176 100644
+--- a/gnome-session/gsm-session-fill.c
++++ b/gnome-session/gsm-session-fill.c
+@@ -134,6 +134,13 @@ load_standard_apps (GsmManager *manager,
+ {
+         /* Note that saving/restoring sessions is not really possible on systemd, as
+          * XSMP clients cannot be reliably mapped to .desktop files. */
++        g_autoptr(GError) error = NULL;
++
++        g_debug ("fill: *** Executing user migration");
++        if (!g_spawn_command_line_sync ("session-migration", NULL, NULL, NULL, &error)) {
++                g_warning ("Error while executing session-migration: %s", error->message);
++        }
++
+         g_debug ("fill: *** Adding required components");
+         handle_required_components (keyfile,
+                                     !gsm_manager_get_failsafe (manager) && !gsm_manager_get_systemd_managed (manager),
diff -pruN 43.0-1/debian/patches/ubuntu/dbus_request_shutdown.patch 43.0-1ubuntu2/debian/patches/ubuntu/dbus_request_shutdown.patch
--- 43.0-1/debian/patches/ubuntu/dbus_request_shutdown.patch	1970-01-01 00:00:00.000000000 +0000
+++ 43.0-1ubuntu2/debian/patches/ubuntu/dbus_request_shutdown.patch	2022-10-13 11:13:51.000000000 +0000
@@ -0,0 +1,111 @@
+From: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
+Date: Wed, 15 Aug 2018 17:13:26 +0200
+Subject: Add "RequestShutdown" and "RequestReboot" DBus methods to allow
+
+other applications to shutdown or reboot the machine via the session manager
+Author: Chris Coulson <chrisccoulson@ubuntu.com>
+---
+ gnome-session/gsm-manager.c                | 45 ++++++++++++++++++++++++++++++
+ gnome-session/gsm-manager.h                |  4 +++
+ gnome-session/org.gnome.SessionManager.xml | 17 +++++++++++
+ 3 files changed, 66 insertions(+)
+
+diff --git a/gnome-session/gsm-manager.c b/gnome-session/gsm-manager.c
+index 8c95d9b..a832f8e 100644
+--- a/gnome-session/gsm-manager.c
++++ b/gnome-session/gsm-manager.c
+@@ -2654,6 +2654,51 @@ request_logout (GsmManager           *manager,
+         end_phase (manager);
+ }
+ 
++gboolean
++gsm_manager_request_shutdown (GsmManager *manager,
++                              GError    **error)
++{
++        GsmManagerPrivate *priv = gsm_manager_get_instance_private (manager);
++
++        g_debug ("GsmManager: RequestShutdown called");
++
++        g_return_val_if_fail (GSM_IS_MANAGER (manager), FALSE);
++
++        if (priv->phase != GSM_MANAGER_PHASE_RUNNING) {
++                g_set_error (error,
++                             GSM_MANAGER_ERROR,
++                             GSM_MANAGER_ERROR_NOT_IN_RUNNING,
++                             "RequestShutdown interface is only available during the Running phase");
++                return FALSE;
++        }
++
++        request_shutdown (manager);
++
++        return TRUE;
++}
++
++gboolean
++gsm_manager_request_reboot (GsmManager *manager,
++                            GError    **error)
++{
++        GsmManagerPrivate *priv = gsm_manager_get_instance_private (manager);
++
++        g_debug ("GsmManager: RequestReboot called");
++
++        g_return_val_if_fail (GSM_IS_MANAGER (manager), FALSE);
++
++        if (priv->phase != GSM_MANAGER_PHASE_RUNNING) {
++                g_set_error (error,
++                             GSM_MANAGER_ERROR,
++                            GSM_MANAGER_ERROR_NOT_IN_RUNNING,
++                             "RequestReboot interface is only available during the Running phase");
++                return FALSE;
++        }
++        request_reboot (manager);
++
++        return TRUE;
++}
++
+ static gboolean
+ gsm_manager_shutdown (GsmExportedManager    *skeleton,
+                       GDBusMethodInvocation *invocation,
+diff --git a/gnome-session/gsm-manager.h b/gnome-session/gsm-manager.h
+index 7cd5cc4..025c58c 100644
+--- a/gnome-session/gsm-manager.h
++++ b/gnome-session/gsm-manager.h
+@@ -112,6 +112,10 @@ void                _gsm_manager_set_renderer                  (GsmManager     *
+ gboolean            gsm_manager_logout                         (GsmManager     *manager,
+                                                                 guint           logout_mode,
+                                                                 GError        **error);
++gboolean            gsm_manager_request_shutdown               (GsmManager     *manager,
++                                                                GError        **error);
++gboolean            gsm_manager_request_reboot                 (GsmManager     *manager,
++                                                                GError        **error);
+ 
+ gboolean            gsm_manager_set_phase                      (GsmManager     *manager,
+                                                                 GsmManagerPhase phase);
+diff --git a/gnome-session/org.gnome.SessionManager.xml b/gnome-session/org.gnome.SessionManager.xml
+index ce4b8c0..be7e70d 100644
+--- a/gnome-session/org.gnome.SessionManager.xml
++++ b/gnome-session/org.gnome.SessionManager.xml
+@@ -377,6 +377,23 @@
+       </doc:doc>
+     </method>
+ 
++	<method name="RequestShutdown">
++      <doc:doc>
++        <doc:description>
++          <doc:para>Request a shutdown with no dialog</doc:para>
++        </doc:description>
++      </doc:doc>
++	</method>
++
++	<method name="RequestReboot">
++      <doc:doc>
++        <doc:description>
++          <doc:para>Request a reboot with no dialog</doc:para>
++        </doc:description>
++      </doc:doc>
++	</method>
++	
++
+     <!-- Signals -->
+ 
+     <signal name="ClientAdded">
diff -pruN 43.0-1/debian/patches/ubuntu/ignore_gsettings_region.patch 43.0-1ubuntu2/debian/patches/ubuntu/ignore_gsettings_region.patch
--- 43.0-1/debian/patches/ubuntu/ignore_gsettings_region.patch	1970-01-01 00:00:00.000000000 +0000
+++ 43.0-1ubuntu2/debian/patches/ubuntu/ignore_gsettings_region.patch	2022-10-13 11:13:51.000000000 +0000
@@ -0,0 +1,28 @@
+From: Gunnar Hjalmarsson <gunnarhj@ubuntu.com>
+Date: Wed, 15 Aug 2018 17:13:26 +0200
+Subject: Ignore the "region" gsettings value
+
+We rely on ~/.pam_environment for the users' setting of LC_* variables.
+Bug-Ubuntu: https://launchpad.net/bugs/1722002
+Forwarded: not-needed
+---
+ gnome-session/gnome-session.in | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/gnome-session/gnome-session.in b/gnome-session/gnome-session.in
+index b4b1f8f..872005e 100755
+--- a/gnome-session/gnome-session.in
++++ b/gnome-session/gnome-session.in
+@@ -10,9 +10,9 @@ if [ "x$XDG_SESSION_TYPE" = "xwayland" ] &&
+   fi
+ fi
+ 
+-SETTING=$(G_MESSAGES_DEBUG='' gsettings get org.gnome.system.locale region)
+-REGION=${SETTING#\'}
+-REGION=${REGION%\'}
++#SETTING=$(G_MESSAGES_DEBUG='' gsettings get org.gnome.system.locale region)
++#REGION=${SETTING#\'}
++#REGION=${REGION%\'}
+ 
+ if [ -n "$REGION" ]; then
+   unset LC_TIME LC_NUMERIC LC_MONETARY LC_MEASUREMENT LC_PAPER
diff -pruN 43.0-1/debian/patches/ubuntu/remove_session_saving_from_gui.patch 43.0-1ubuntu2/debian/patches/ubuntu/remove_session_saving_from_gui.patch
--- 43.0-1/debian/patches/ubuntu/remove_session_saving_from_gui.patch	1970-01-01 00:00:00.000000000 +0000
+++ 43.0-1ubuntu2/debian/patches/ubuntu/remove_session_saving_from_gui.patch	2022-10-13 11:13:51.000000000 +0000
@@ -0,0 +1,23 @@
+From: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
+Date: Wed, 15 Aug 2018 17:13:26 +0200
+Subject: Remove session saving from gui
+
+===================================================================
+---
+ gnome-session/gsm-session-fill.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/gnome-session/gsm-session-fill.c b/gnome-session/gsm-session-fill.c
+index 93a6dbc..191b6ce 100644
+--- a/gnome-session/gsm-session-fill.c
++++ b/gnome-session/gsm-session-fill.c
+@@ -146,7 +146,8 @@ load_standard_apps (GsmManager *manager,
+ 
+                 autostart_dirs = gsm_util_get_autostart_dirs ();
+ 
+-                if (!gsm_manager_get_systemd_managed (manager))
++                if (!gsm_manager_get_systemd_managed (manager) &&
++                    g_getenv ("GNOME_SESSION_SAVE") != NULL)
+                         maybe_load_saved_session_apps (manager);
+ 
+                 for (i = 0; autostart_dirs[i]; i++) {
diff -pruN 43.0-1/debian/patches/ubuntu/support_autostart_delay.patch 43.0-1ubuntu2/debian/patches/ubuntu/support_autostart_delay.patch
--- 43.0-1/debian/patches/ubuntu/support_autostart_delay.patch	1970-01-01 00:00:00.000000000 +0000
+++ 43.0-1ubuntu2/debian/patches/ubuntu/support_autostart_delay.patch	2022-10-13 11:13:51.000000000 +0000
@@ -0,0 +1,242 @@
+From: Chris Coulson <chrisccoulson@ubuntu.com>
+Date: Wed, 15 Aug 2018 17:13:26 +0200
+Subject: Add support for autostarting applications after a delay
+
+Make it possible to delay autostarting an application for a time
+period defined by the "X-GNOME-Autostart-Delay" key in the applications
+desktop file
+Bug: https://bugzilla.gnome.org/show_bug.cgi?id=608402
+---
+ gnome-session/gsm-app.c           | 18 +++++++++++++++-
+ gnome-session/gsm-app.h           |  2 ++
+ gnome-session/gsm-autostart-app.c | 27 +++++++++++++++++++++++
+ gnome-session/gsm-autostart-app.h |  1 +
+ gnome-session/gsm-manager.c       | 45 ++++++++++++++++++++++++++++++++++++---
+ 5 files changed, 89 insertions(+), 4 deletions(-)
+
+diff --git a/gnome-session/gsm-app.c b/gnome-session/gsm-app.c
+index 8da7bd1..7241376 100644
+--- a/gnome-session/gsm-app.c
++++ b/gnome-session/gsm-app.c
+@@ -327,6 +327,7 @@ gsm_app_class_init (GsmAppClass *klass)
+         klass->impl_provides = NULL;
+         klass->impl_get_provides = NULL;
+         klass->impl_is_running = NULL;
++        klass->impl_peek_autostart_delay = NULL;
+ 
+         g_object_class_install_property (object_class,
+                                          PROP_PHASE,
+@@ -536,7 +537,22 @@ gboolean
+ gsm_app_stop (GsmApp  *app,
+               GError **error)
+ {
+-        return GSM_APP_GET_CLASS (app)->impl_stop (app, error);
++        if (gsm_app_is_running (app))
++                return GSM_APP_GET_CLASS (app)->impl_stop (app, error);
++
++        return TRUE;
++}
++
++int
++gsm_app_peek_autostart_delay (GsmApp *app)
++{
++        g_return_val_if_fail (GSM_IS_APP (app), FALSE);
++
++        if (GSM_APP_GET_CLASS (app)->impl_peek_autostart_delay) {
++                return GSM_APP_GET_CLASS (app)->impl_peek_autostart_delay (app);
++        } else {
++                return 0;
++        }
+ }
+ 
+ void
+diff --git a/gnome-session/gsm-app.h b/gnome-session/gsm-app.h
+index 2808a21..72f03c9 100644
+--- a/gnome-session/gsm-app.h
++++ b/gnome-session/gsm-app.h
+@@ -49,6 +49,7 @@ struct _GsmAppClass
+                                                        GError    **error);
+         gboolean    (*impl_stop)                      (GsmApp     *app,
+                                                        GError    **error);
++        int         (*impl_peek_autostart_delay)      (GsmApp     *app);
+         gboolean    (*impl_provides)                  (GsmApp     *app,
+                                                        const char *service);
+         char **     (*impl_get_provides)              (GsmApp     *app);
+@@ -109,6 +110,7 @@ gboolean         gsm_app_has_autostart_condition        (GsmApp     *app,
+ gboolean         gsm_app_get_registered                 (GsmApp     *app);
+ void             gsm_app_set_registered                 (GsmApp     *app,
+                                                          gboolean  registered);
++int              gsm_app_peek_autostart_delay           (GsmApp     *app);
+ 
+ gboolean         gsm_app_save_to_keyfile                (GsmApp    *app,
+                                                          GKeyFile  *keyfile,
+diff --git a/gnome-session/gsm-autostart-app.c b/gnome-session/gsm-autostart-app.c
+index 8204d4f..de7e3ad 100644
+--- a/gnome-session/gsm-autostart-app.c
++++ b/gnome-session/gsm-autostart-app.c
+@@ -20,6 +20,7 @@
+ #include <config.h>
+ 
+ #include <ctype.h>
++#include <stdlib.h>
+ #include <string.h>
+ #include <sys/wait.h>
+ #include <errno.h>
+@@ -73,6 +74,7 @@ typedef struct
+         char                 *condition_string;
+         gboolean              condition;
+         gboolean              autorestart;
++        int                   autostart_delay;
+ 
+         GFileMonitor         *condition_monitor;
+         guint                 condition_notify_id;
+@@ -111,6 +113,7 @@ gsm_autostart_app_init (GsmAutostartApp *app)
+         priv->pid = -1;
+         priv->condition_monitor = NULL;
+         priv->condition = FALSE;
++        priv->autostart_delay = -1;
+ }
+ 
+ static gboolean
+@@ -617,6 +620,21 @@ load_desktop_file (GsmAutostartApp  *app)
+                                                                    "AutostartCondition");
+         setup_condition_monitor (app);
+ 
++        const char *delay;
++        delay = g_desktop_app_info_get_string (priv->app_info,
++                                               GSM_AUTOSTART_APP_DELAY_KEY);
++
++        if (delay != NULL) {
++                priv->autostart_delay = strtol (delay, NULL, 10);
++
++                if (priv->autostart_delay < 0) {
++                        g_warning ("Invalid autostart delay of %d for %s",
++                                   priv->autostart_delay,
++                                   gsm_app_peek_id (GSM_APP (app)));
++                        priv->autostart_delay = -1;
++                }
++        }
++
+         g_object_set (app,
+                       "phase", phase,
+                       "startup-id", startup_id,
+@@ -1352,6 +1370,14 @@ gsm_autostart_app_get_app_id (GsmApp *app)
+         return g_app_info_get_id (G_APP_INFO (priv->app_info));
+ }
+ 
++static int
++gsm_autostart_app_peek_autostart_delay (GsmApp *app)
++{
++        GsmAutostartAppPrivate *priv = gsm_autostart_app_get_instance_private (GSM_AUTOSTART_APP (app));
++
++        return priv->autostart_delay;
++}
++
+ static gboolean
+ gsm_autostart_app_initable_init (GInitable *initable,
+                                  GCancellable *cancellable,
+@@ -1470,6 +1496,7 @@ gsm_autostart_app_class_init (GsmAutostartAppClass *klass)
+         app_class->impl_has_autostart_condition = gsm_autostart_app_has_autostart_condition;
+         app_class->impl_get_app_id = gsm_autostart_app_get_app_id;
+         app_class->impl_get_autorestart = gsm_autostart_app_get_autorestart;
++        app_class->impl_peek_autostart_delay = gsm_autostart_app_peek_autostart_delay;
+         app_class->impl_save_to_keyfile = gsm_autostart_app_save_to_keyfile;
+ 
+         props[PROP_DESKTOP_FILENAME] =
+diff --git a/gnome-session/gsm-autostart-app.h b/gnome-session/gsm-autostart-app.h
+index a7a5c28..5192865 100644
+--- a/gnome-session/gsm-autostart-app.h
++++ b/gnome-session/gsm-autostart-app.h
+@@ -55,6 +55,7 @@ void    gsm_autostart_app_add_provides       (GsmAutostartApp *aapp,
+ #define GSM_AUTOSTART_APP_DBUS_PATH_KEY   "X-GNOME-DBus-Path"
+ #define GSM_AUTOSTART_APP_DBUS_ARGS_KEY   "X-GNOME-DBus-Start-Arguments"
+ #define GSM_AUTOSTART_APP_DISCARD_KEY     "X-GNOME-Autostart-discard-exec"
++#define GSM_AUTOSTART_APP_DELAY_KEY       "X-GNOME-Autostart-Delay"
+ 
+ G_END_DECLS
+ 
+diff --git a/gnome-session/gsm-manager.c b/gnome-session/gsm-manager.c
+index 1b88b26..8c95d9b 100644
+--- a/gnome-session/gsm-manager.c
++++ b/gnome-session/gsm-manager.c
+@@ -415,7 +415,8 @@ app_condition_changed (GsmApp     *app,
+                 } else {
+                         g_debug ("GsmManager: stopping app %s", gsm_app_peek_id (app));
+ 
+-                        /* If we don't have a client then we should try to kill the app */
++                        /* If we don't have a client then we should try to kill the app ,
++                         * if it is running */
+                         error = NULL;
+                         res = gsm_app_stop (app, &error);
+                         if (! res) {
+@@ -755,11 +756,36 @@ on_phase_timeout (GsmManager *manager)
+         return FALSE;
+ }
+ 
++static gboolean
++_autostart_delay_timeout (GsmApp *app)
++{
++        GError *error = NULL;
++        gboolean res;
++
++        if (!gsm_app_peek_is_disabled (app)
++            && !gsm_app_peek_is_conditionally_disabled (app)) {
++                res = gsm_app_start (app, &error);
++                if (!res) {
++                        if (error != NULL) {
++                                g_warning ("Could not launch application '%s': %s",
++                                           gsm_app_peek_app_id (app),
++                                           error->message);
++                                g_error_free (error);
++                        }
++                }
++        }
++
++        g_object_unref (app);
++
++        return FALSE;
++}
++
+ static gboolean
+ _start_app (const char *id,
+             GsmApp     *app,
+             GsmManager *manager)
+ {
++        int delay;
+         GsmManagerPrivate *priv = gsm_manager_get_instance_private (manager);
+ 
+         if (gsm_app_peek_phase (app) != priv->phase) {
+@@ -779,6 +805,18 @@ _start_app (const char *id,
+                 goto out;
+         }
+ 
++        /* Only accept an autostart delay for the application phase */
++        if (priv->phase == GSM_MANAGER_PHASE_APPLICATION) {
++                delay = gsm_app_peek_autostart_delay (app);
++                if (delay > 0) {
++                        g_timeout_add_seconds (delay,
++                                               (GSourceFunc)_autostart_delay_timeout,
++                                               g_object_ref (app));
++                        g_debug ("GsmManager: %s is scheduled to start in %d seconds", id, delay);
++                        goto out;
++                }
++        }
++
+         if (!start_app_or_warn (manager, app))
+                 goto out;
+ 
+@@ -1464,11 +1502,12 @@ _debug_app_for_phase (const char *id,
+                 return FALSE;
+         }
+ 
+-        g_debug ("GsmManager:\tID: %s\tapp-id:%s\tis-disabled:%d\tis-conditionally-disabled:%d",
++        g_debug ("GsmManager:\tID: %s\tapp-id:%s\tis-disabled:%d\tis-conditionally-disabled:%d\tis-delayed:%d",
+                  gsm_app_peek_id (app),
+                  gsm_app_peek_app_id (app),
+                  gsm_app_peek_is_disabled (app),
+-                 gsm_app_peek_is_conditionally_disabled (app));
++                 gsm_app_peek_is_conditionally_disabled (app),
++                 (gsm_app_peek_autostart_delay (app) > 0));
+ 
+         return FALSE;
+ }
diff -pruN 43.0-1/debian/patches/ubuntu/ubuntu-sessions.patch 43.0-1ubuntu2/debian/patches/ubuntu/ubuntu-sessions.patch
--- 43.0-1/debian/patches/ubuntu/ubuntu-sessions.patch	1970-01-01 00:00:00.000000000 +0000
+++ 43.0-1ubuntu2/debian/patches/ubuntu/ubuntu-sessions.patch	2022-10-13 11:13:51.000000000 +0000
@@ -0,0 +1,305 @@
+From: Ubuntu Developers <ubuntu-devel-discuss@lists.ubuntu.com>
+Date: Wed, 15 Aug 2018 17:13:26 +0200
+Subject: sessions: Tweak the system to make it for ubuntu
+
+The session contains:
+ - ubuntu (gnome-shell with ubuntu tweaks) in ubuntu-session package
+ - unity in unity-session package
+ - gnome-shell in the main gnome-session package.
+
+Forwarded: Not needed
+---
+ data/gnome-wayland.desktop.in.in  |  2 +-
+ data/gnome-xorg.desktop.in.in     |  2 +-
+ data/gnome.desktop.in.in          |  2 +-
+ data/meson.build                  | 43 ++++++++++++++++++++++++++++++++++++++-
+ data/ubuntu-wayland.desktop.in.in |  8 ++++++++
+ data/ubuntu-xorg.desktop.in.in    |  8 ++++++++
+ data/ubuntu.desktop.in.in         |  8 ++++++++
+ data/ubuntu.session.conf.in       |  5 +++++
+ data/ubuntu.session.desktop.in.in |  4 ++++
+ data/unity.desktop.in.in          |  7 +++++++
+ data/unity.session.desktop.in.in  |  4 ++++
+ data/wayland-sessions/meson.build |  1 +
+ meson_post_install.py             |  6 +++---
+ po/POTFILES.in                    |  6 ++++++
+ po/POTFILES.skip                  |  6 ++++++
+ 15 files changed, 105 insertions(+), 7 deletions(-)
+ create mode 100644 data/ubuntu-wayland.desktop.in.in
+ create mode 100644 data/ubuntu-xorg.desktop.in.in
+ create mode 100644 data/ubuntu.desktop.in.in
+ create mode 100644 data/ubuntu.session.conf.in
+ create mode 100644 data/ubuntu.session.desktop.in.in
+ create mode 100644 data/unity.desktop.in.in
+ create mode 100644 data/unity.session.desktop.in.in
+ create mode 100644 data/wayland-sessions/meson.build
+
+diff --git a/data/gnome-wayland.desktop.in.in b/data/gnome-wayland.desktop.in.in
+index b48eecd..5e6ffa6 100644
+--- a/data/gnome-wayland.desktop.in.in
++++ b/data/gnome-wayland.desktop.in.in
+@@ -1,7 +1,7 @@
+ [Desktop Entry]
+ Name=GNOME on Wayland
+ Comment=This session logs you into GNOME
+-Exec=@bindir@/gnome-session
++Exec=@bindir@/gnome-session --session=gnome
+ TryExec=@bindir@/gnome-session
+ Type=Application
+ DesktopNames=GNOME
+diff --git a/data/gnome-xorg.desktop.in.in b/data/gnome-xorg.desktop.in.in
+index 9a76fac..3ee3181 100644
+--- a/data/gnome-xorg.desktop.in.in
++++ b/data/gnome-xorg.desktop.in.in
+@@ -1,7 +1,7 @@
+ [Desktop Entry]
+ Name=GNOME on Xorg
+ Comment=This session logs you into GNOME
+-Exec=@bindir@/gnome-session
++Exec=@bindir@/gnome-session --session=gnome
+ TryExec=@bindir@/gnome-session
+ Type=Application
+ DesktopNames=GNOME
+diff --git a/data/gnome.desktop.in.in b/data/gnome.desktop.in.in
+index 7eec1de..d240f57 100644
+--- a/data/gnome.desktop.in.in
++++ b/data/gnome.desktop.in.in
+@@ -1,7 +1,7 @@
+ [Desktop Entry]
+ Name=GNOME
+ Comment=This session logs you into GNOME
+-Exec=@bindir@/gnome-session
++Exec=@bindir@/gnome-session --session=gnome
+ TryExec=@bindir@/gnome-session
+ Type=Application
+ DesktopNames=GNOME
+diff --git a/data/meson.build b/data/meson.build
+index f6d264f..07fe12a 100644
+--- a/data/meson.build
++++ b/data/meson.build
+@@ -4,6 +4,14 @@ desktops = [
+   desktop_plain,
+   'gnome-xorg',
+   'gnome-wayland',
++  'ubuntu',
++  'ubuntu-wayland',
++  'ubuntu-xorg',
++  'unity',
++]
++
++non_wayland_desktops = [
++  'unity',
+ ]
+ 
+ shell_component = {
+@@ -31,6 +39,25 @@ required_components = {
+   ],
+ }
+ 
++shell_component += {
++  'ubuntu': shell_component[desktop_plain],
++}
++
++ubuntu_required_components = []
++ubuntu_excluded_components = [
++  'org.gnome.SettingsDaemon.UsbProtection',
++]
++
++foreach component: required_components[desktop_plain]
++  if component not in ubuntu_excluded_components
++    ubuntu_required_components += component
++  endif
++endforeach
++
++required_components += {
++  'ubuntu': ubuntu_required_components
++}
++
+ if enable_session_selector
+   desktops += 'gnome-custom-session'
+ endif
+@@ -47,6 +74,7 @@ foreach name: desktops
+     configuration: desktop_conf
+   )
+ 
++  all_sessions_desktop = false
+   if name.endswith('-xorg')
+     install_dir = session_datadir / 'xsessions'
+   elif name.endswith('-wayland')
+@@ -61,6 +89,7 @@ foreach name: desktops
+     #  join_paths(session_datadir, 'xsessions'),
+     #  join_paths(session_datadir, 'wayland-sessions')
+     #]
++    all_sessions_desktop = name not in non_wayland_desktops
+   endif
+ 
+   desktop_target = i18n.merge_file(
+@@ -71,11 +100,23 @@ foreach name: desktops
+     install: true,
+     install_dir: install_dir
+   )
++
++  if all_sessions_desktop
++    custom_target(desktop + '-wayland',
++      command: [ 'cat', desktop_target ],
++      capture: true,
++      output: desktop + '.tmp-session',
++      install: true,
++      install_dir: session_datadir / 'wayland-sessions',
++    )
++  endif
+ endforeach
+ 
+ sessions = [
+   'gnome',
+-  'gnome-dummy'
++  'gnome-dummy',
++  'ubuntu',
++  'unity',
+ ]
+ 
+ foreach session: sessions
+diff --git a/data/ubuntu-wayland.desktop.in.in b/data/ubuntu-wayland.desktop.in.in
+new file mode 100644
+index 0000000..958d171
+--- /dev/null
++++ b/data/ubuntu-wayland.desktop.in.in
+@@ -0,0 +1,8 @@
++[Desktop Entry]
++Name=Ubuntu on Wayland
++Comment=This session logs you into Ubuntu
++Exec=env GNOME_SHELL_SESSION_MODE=ubuntu @bindir@/gnome-session --session=ubuntu
++TryExec=@bindir@/gnome-shell
++Type=Application
++DesktopNames=ubuntu:GNOME
++X-GDM-SessionRegisters=true
+diff --git a/data/ubuntu-xorg.desktop.in.in b/data/ubuntu-xorg.desktop.in.in
+new file mode 100644
+index 0000000..071ebad
+--- /dev/null
++++ b/data/ubuntu-xorg.desktop.in.in
+@@ -0,0 +1,8 @@
++[Desktop Entry]
++Name=Ubuntu on Xorg
++Comment=This session logs you into Ubuntu
++Exec=env GNOME_SHELL_SESSION_MODE=ubuntu @bindir@/gnome-session --session=ubuntu
++TryExec=@bindir@/gnome-shell
++Type=Application
++DesktopNames=ubuntu:GNOME
++X-GDM-SessionRegisters=true
+diff --git a/data/ubuntu.desktop.in.in b/data/ubuntu.desktop.in.in
+new file mode 100644
+index 0000000..bc6a697
+--- /dev/null
++++ b/data/ubuntu.desktop.in.in
+@@ -0,0 +1,8 @@
++[Desktop Entry]
++Name=Ubuntu
++Comment=This session logs you into Ubuntu
++Exec=env GNOME_SHELL_SESSION_MODE=ubuntu @bindir@/gnome-session --session=ubuntu
++TryExec=@bindir@/gnome-shell
++Type=Application
++DesktopNames=ubuntu:GNOME
++X-GDM-SessionRegisters=true
+diff --git a/data/ubuntu.session.conf.in b/data/ubuntu.session.conf.in
+new file mode 100644
+index 0000000..8373d82
+--- /dev/null
++++ b/data/ubuntu.session.conf.in
+@@ -0,0 +1,5 @@
++[Unit]
++# Must be in sync with ubuntu.session
++@wants_required_components@
++
++Requires=@requires_component@.target
+diff --git a/data/ubuntu.session.desktop.in.in b/data/ubuntu.session.desktop.in.in
+new file mode 100644
+index 0000000..4ace628
+--- /dev/null
++++ b/data/ubuntu.session.desktop.in.in
+@@ -0,0 +1,4 @@
++[GNOME Session]
++Name=Ubuntu
++# Must be in sync with gnome-session@ubuntu.target.d/ubuntu.session.conf drop-in
++RequiredComponents=@required_components@;
+diff --git a/data/unity.desktop.in.in b/data/unity.desktop.in.in
+new file mode 100644
+index 0000000..2a489dc
+--- /dev/null
++++ b/data/unity.desktop.in.in
+@@ -0,0 +1,7 @@
++[Desktop Entry]
++Name=Unity
++Comment=This session logs you into Unity
++Exec=/usr/libexec/run-systemd-session unity-session.target
++TryExec=@bindir@/unity
++Type=Application
++DesktopNames=Unity:Unity7:ubuntu
+diff --git a/data/unity.session.desktop.in.in b/data/unity.session.desktop.in.in
+new file mode 100644
+index 0000000..615b492
+--- /dev/null
++++ b/data/unity.session.desktop.in.in
+@@ -0,0 +1,4 @@
++[GNOME Session]
++Name=Unity
++RequiredComponents=unity-settings-daemon;
++DesktopName=Unity:Unity7:ubuntu
+diff --git a/data/wayland-sessions/meson.build b/data/wayland-sessions/meson.build
+new file mode 100644
+index 0000000..8b13789
+--- /dev/null
++++ b/data/wayland-sessions/meson.build
+@@ -0,0 +1 @@
++
+diff --git a/meson_post_install.py b/meson_post_install.py
+index 27017f6..b77bedc 100644
+--- a/meson_post_install.py
++++ b/meson_post_install.py
+@@ -1,5 +1,6 @@
+ #!/usr/bin/env python3
+ 
++import glob
+ import os
+ import shutil
+ import subprocess
+@@ -21,6 +22,5 @@ dst_dir = os.path.join(install_root, 'wayland-sessions')
+ if not os.path.exists(dst_dir):
+   os.makedirs(dst_dir)
+ 
+-src = os.path.join(install_root, 'xsessions', 'gnome.desktop')
+-dst = os.path.join(dst_dir, 'gnome.desktop')
+-shutil.copyfile(src, dst)
++for i in glob.glob(os.path.join(dst_dir, '*.tmp-session')):
++  os.rename(i, i[:-len('.tmp-session')])
+diff --git a/po/POTFILES.in b/po/POTFILES.in
+index a1401e4..2483de2 100644
+--- a/po/POTFILES.in
++++ b/po/POTFILES.in
+@@ -8,6 +8,12 @@ data/gnome-wayland.desktop.in.in
+ data/gnome-xorg.desktop.in.in
+ data/org.gnome.SessionManager.gschema.xml.in
+ data/session-selector.ui
++data/ubuntu.desktop.in.in
++data/ubuntu-wayland.desktop.in.in
++data/ubuntu-xorg.desktop.in.in
++data/ubuntu.session.desktop.in.in
++data/unity.desktop.in.in
++data/unity.session.desktop.in.in
+ gnome-session/gsm-fail-whale-dialog.c
+ gnome-session/gsm-manager.c
+ gnome-session/gsm-process-helper.c
+diff --git a/po/POTFILES.skip b/po/POTFILES.skip
+index d59455a..4d20abb 100644
+--- a/po/POTFILES.skip
++++ b/po/POTFILES.skip
+@@ -7,3 +7,9 @@ data/gnome-dummy.session.desktop.in
+ data/gnome.session.desktop.in
+ data/gnome-wayland.desktop.in
+ data/gnome-xorg.desktop.in
++data/ubuntu.desktop.in
++data/ubuntu-wayland.desktop.in
++data/ubuntu-xorg.desktop.in
++data/ubuntu.session.desktop.in
++data/unity.desktop.in
++data/unity.session.desktop.in
diff -pruN 43.0-1/debian/rules 43.0-1ubuntu2/debian/rules
--- 43.0-1/debian/rules	2022-10-11 18:08:35.000000000 +0000
+++ 43.0-1ubuntu2/debian/rules	2022-10-13 11:13:51.000000000 +0000
@@ -1,8 +1,12 @@
 #!/usr/bin/make -f
 
+include /usr/share/dpkg/default.mk
+
 export DEB_BUILD_MAINT_OPTIONS = hardening=+all
 export DEB_LDFLAGS_MAINT_APPEND = -Wl,-O1 -Wl,-z,defs
 
+GS_MAJOR_VERSION = $(shell echo $(DEB_VERSION_UPSTREAM) | sed 's/[~.].*//')
+
 %:
 	dh $@
 
@@ -16,3 +20,20 @@ override_dh_auto_configure:
 	dh_auto_configure -- \
 		-Dman=true \
 		$(CONFFLAGS)
+
+override_dh_install:
+	cd debian/tmp/usr/share; \
+	for f in wayland-sessions/*.desktop xsessions/*.desktop applications/*.desktop; do \
+		echo X-Ubuntu-Gettext-Domain=gnome-session-$(GS_MAJOR_VERSION) >> "$$f"; \
+	done
+	dh_install
+	dh_migrations
+
+override_dh_auto_build:
+	dh_auto_build
+	ninja -C obj-$(DEB_HOST_GNU_TYPE) gnome-session-$(GS_MAJOR_VERSION)-pot
+
+override_dh_auto_clean:
+	dh_auto_clean
+	rm -f po/gnome-session-$(GS_MAJOR_VERSION).pot
+
diff -pruN 43.0-1/debian/ubuntu-session.install 43.0-1ubuntu2/debian/ubuntu-session.install
--- 43.0-1/debian/ubuntu-session.install	1970-01-01 00:00:00.000000000 +0000
+++ 43.0-1ubuntu2/debian/ubuntu-session.install	2022-10-13 11:13:51.000000000 +0000
@@ -0,0 +1,8 @@
+#!/usr/bin/dh-exec
+debian/data/50-ubuntu.conf /usr/share/lightdm/lightdm.conf.d
+[linux-any] usr/lib/systemd/user/gnome-session@ubuntu.target.d/*
+usr/share/gnome-session/sessions/ubuntu.session
+usr/share/wayland-sessions/ubuntu.desktop
+usr/share/wayland-sessions/ubuntu-wayland.desktop
+usr/share/xsessions/ubuntu.desktop
+usr/share/xsessions/ubuntu-xorg.desktop
diff -pruN 43.0-1/debian/ubuntu-session.migrations 43.0-1ubuntu2/debian/ubuntu-session.migrations
--- 43.0-1/debian/ubuntu-session.migrations	1970-01-01 00:00:00.000000000 +0000
+++ 43.0-1ubuntu2/debian/ubuntu-session.migrations	2022-10-13 11:13:51.000000000 +0000
@@ -0,0 +1,2 @@
+debian/unity-gnome-shell-migration.*.py
+debian/ubuntu-settings-migrate-to-defaults.*.py
diff -pruN 43.0-1/debian/ubuntu-settings-migrate-to-defaults.18.10.1.py 43.0-1ubuntu2/debian/ubuntu-settings-migrate-to-defaults.18.10.1.py
--- 43.0-1/debian/ubuntu-settings-migrate-to-defaults.18.10.1.py	1970-01-01 00:00:00.000000000 +0000
+++ 43.0-1ubuntu2/debian/ubuntu-settings-migrate-to-defaults.18.10.1.py	2022-10-13 11:13:51.000000000 +0000
@@ -0,0 +1,58 @@
+#!/usr/bin/python3
+# -*- coding: utf-8 -*-
+# Copyright (C) 2018 Canonical
+#
+# Authors:
+#  Marco Trevisan <marco.trevisan@canonical.com>
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; version 3.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUTa
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+from gi.repository import Gio
+import os
+import sys
+
+OLD_DEFAULTS = {
+    "org.gnome.desktop.sound": {
+        "theme-name": ["ubuntu"],
+    },
+    "org.gnome.desktop.interface": {
+        "gtk-theme": ["Ambiance", "Radiance"],
+        "icon-theme": ["ubuntu-mono-dark"],
+        "cursor-theme": ["DMZ-White"],
+    }
+}
+
+if os.getenv('DESKTOP_SESSION') not in ['ubuntu', 'ubuntu-wayland']:
+    sys.exit(0)
+
+any_changed = False
+
+for schema in OLD_DEFAULTS.keys():
+    settings = Gio.Settings.new(schema)
+    old_settings = OLD_DEFAULTS[schema]
+
+    for key in old_settings.keys():
+        user_value = settings.get_user_value(key)
+
+        if user_value and user_value.unpack() in old_settings[key]:
+            print('{}.{} is using old ubuntu setting ("{}"), replacing it with '
+                'the latest default ("{}")'.format(schema, key,
+                    user_value.unpack(),
+                    settings.get_default_value(key).unpack()))
+            settings.reset(key)
+            any_changed = True
+
+if any_changed:
+    Gio.Settings.sync()
+
diff -pruN 43.0-1/debian/unity-gnome-shell-migration.17.10.py 43.0-1ubuntu2/debian/unity-gnome-shell-migration.17.10.py
--- 43.0-1/debian/unity-gnome-shell-migration.17.10.py	1970-01-01 00:00:00.000000000 +0000
+++ 43.0-1ubuntu2/debian/unity-gnome-shell-migration.17.10.py	2022-10-13 11:13:51.000000000 +0000
@@ -0,0 +1,120 @@
+#!/usr/bin/python3
+
+from gi.repository import Gio
+import os
+import sys
+
+
+UNITY_LAUNCHER_SETTINGS = "com.canonical.Unity.Launcher"
+UNITY_LAUNCHER_FAVORITE_KEY = "favorites"
+UNITY_APP_PREFIX = "application://"
+
+GNOME_DASH_SETTINGS = "org.gnome.shell"
+GNOME_DASH_FAVORITE_KEY = "favorite-apps"
+
+UNITY_COMPIZ_LAUNCHER_SETTINGS = "org.compiz.unityshell"
+UNITY_COMPIZ_LAUNCHER_SETTINGS_PATH = "/org/compiz/profiles/unity/plugins/unityshell/"
+
+DOCK_SETTINGS = "org.gnome.shell.extensions.dash-to-dock"
+
+def get_default_gnome_shell_favorites():
+    settings = Gio.Settings.new(GNOME_DASH_SETTINGS)
+    settings.delay()
+    settings.reset(GNOME_DASH_FAVORITE_KEY)
+    return settings.get_strv(GNOME_DASH_FAVORITE_KEY)
+
+
+def get_default_launcher_property(property):
+    settings = Gio.Settings.new_with_path(UNITY_COMPIZ_LAUNCHER_SETTINGS, UNITY_COMPIZ_LAUNCHER_SETTINGS_PATH)
+    settings.delay()
+    settings.reset(property)
+    return settings.get_int(property)
+
+
+def migrate_unity_launchers():
+
+    gs_settings = Gio.Settings.new(GNOME_DASH_SETTINGS)
+    if not gs_settings.is_writable(GNOME_DASH_FAVORITE_KEY):
+        print("Can't migrate unity keys to GNOME Shell as they are not writable")
+        return
+    gs_favorites = gs_settings.get_strv(GNOME_DASH_FAVORITE_KEY)
+
+    if gs_favorites != get_default_gnome_shell_favorites():
+        print("Migration prevented as GNOME Shell launchers are modified from defaults")
+        return
+
+    unity_settings = Gio.Settings.new(UNITY_LAUNCHER_SETTINGS)
+    unity_favorites = unity_settings.get_strv(UNITY_LAUNCHER_FAVORITE_KEY)
+
+    new_favorites = []
+    for fav in unity_favorites:
+        if not fav.startswith(UNITY_APP_PREFIX):
+            continue
+        # change from u-c-c
+        if fav == UNITY_APP_PREFIX + "unity-control-center.desktop":
+            fav = UNITY_APP_PREFIX + "gnome-control-center.desktop"
+        new_favorites.append(fav[len(UNITY_APP_PREFIX):])
+    
+    # we replace with unity existing keys
+    gs_settings.set_strv(GNOME_DASH_FAVORITE_KEY, new_favorites)
+    gs_settings.sync() # force sync to avoid race
+
+
+def migrate_launcher_properties():
+    source = Gio.SettingsSchemaSource.get_default()
+    if source.lookup(DOCK_SETTINGS, True) is None:
+        print("Don't migrate launcher properties as Ubuntu Docker not installed")
+        return
+
+    unity_settings = Gio.Settings.new_with_path(UNITY_COMPIZ_LAUNCHER_SETTINGS, UNITY_COMPIZ_LAUNCHER_SETTINGS_PATH)
+    dock_settings = Gio.Settings.new(DOCK_SETTINGS)
+
+    intellihide = unity_settings.get_int("launcher-hide-mode")
+    if intellihide == 1 and intellihide != get_default_launcher_property("launcher-hide-mode"):
+        dock_settings.set_boolean("dock-fixed", False)
+
+    icon_size = unity_settings.get_int("icon-size")
+    if icon_size != get_default_launcher_property("icon-size"):
+        dock_settings.set_int("dash-max-icon-size", icon_size)
+    
+    launcher_placement = unity_settings.get_int("num-launchers")
+    if launcher_placement != get_default_launcher_property("num-launchers"):
+        if launcher_placement == 0:
+            dock_settings.set_boolean("multi-monitor", "True")
+        else:
+            dock_settings.set_int("preferred-monitor", launcher_placement - 1)
+    dock_settings.sync() # force sync to avoid race
+
+
+def reset_rhythmbox_plugins():
+    '''We had a glib bug for list plugins, people installing 17.10 beta or before
+    were reset to default non override defaults, if this is the case, reset them
+    again.
+    '''
+    source = Gio.SettingsSchemaSource.get_default()
+    if (source.lookup("org.gnome.rhythmbox.plugins", True) is None):
+        print("Don't reset Rhythmbox key as not installed")
+        return
+    rh_settings = Gio.Settings.new("org.gnome.rhythmbox.plugins")
+    if not rh_settings.is_writable("active-plugins"):
+        print("Can't reset Rhythmbox key as not writable")
+        return
+    # only migrate if default system values were set
+    if rh_settings.get_strv("active-plugins") != ['power-manager', 'generic-player', 'android', 'audiocd', 'iradio', 'mmkeys']:
+        return
+    rh_settings.reset("active-plugins")
+    rh_settings.sync()
+
+
+if __name__ == "__main__":
+    source = Gio.SettingsSchemaSource.get_default()
+    # Unity or GS not installed
+    if (source.lookup(UNITY_LAUNCHER_SETTINGS, True) is None or
+        source.lookup(UNITY_COMPIZ_LAUNCHER_SETTINGS, True) is None or
+        source.lookup(GNOME_DASH_SETTINGS, True) is None):
+        print("Unity or GNOME Shell not installed: no migration needed")
+        sys.exit(0)
+
+    migrate_unity_launchers()
+    migrate_launcher_properties()
+    reset_rhythmbox_plugins()
diff -pruN 43.0-1/debian/unity-session.install 43.0-1ubuntu2/debian/unity-session.install
--- 43.0-1/debian/unity-session.install	1970-01-01 00:00:00.000000000 +0000
+++ 43.0-1ubuntu2/debian/unity-session.install	2022-10-13 11:13:51.000000000 +0000
@@ -0,0 +1,7 @@
+debian/data/*.nemo_action /usr/share/nemo/actions/
+debian/data/50-unity.conf /usr/share/lightdm/lightdm.conf.d
+debian/data/nemo-unity-autostart.desktop /etc/xdg/autostart/
+debian/data/unity-session.target usr/lib/systemd/user/
+debian/data/gnome-session.service usr/lib/systemd/user/
+usr/share/gnome-session/sessions/unity.session
+usr/share/xsessions/unity.desktop
diff -pruN 43.0-1/debian/xdg_dirs_desktop_session.sh 43.0-1ubuntu2/debian/xdg_dirs_desktop_session.sh
--- 43.0-1/debian/xdg_dirs_desktop_session.sh	1970-01-01 00:00:00.000000000 +0000
+++ 43.0-1ubuntu2/debian/xdg_dirs_desktop_session.sh	2022-10-13 11:13:51.000000000 +0000
@@ -0,0 +1,25 @@
+# /etc/profile.d/desktop_session_xdg_dirs.sh - Prepend a $DESKTOP_SESSION-named directory to $XDG_CONFIG_DIRS and $XDG_DATA_DIRS
+
+DEFAULT_XDG_CONFIG_DIRS='/etc/xdg'
+DEFAULT_XDG_DATA_DIRS='/usr/local/share/:/usr/share/'
+
+if [ -n "$DESKTOP_SESSION" ]; then
+  # readd default if was empty
+  if [ -z "$XDG_CONFIG_DIRS" ]; then
+    XDG_CONFIG_DIRS="$DEFAULT_XDG_CONFIG_DIRS"
+  fi
+  if [ -n "${XDG_CONFIG_DIRS##*$DEFAULT_XDG_CONFIG_DIRS/xdg-$DESKTOP_SESSION*}" ]; then
+    XDG_CONFIG_DIRS="$DEFAULT_XDG_CONFIG_DIRS"/xdg-"$DESKTOP_SESSION":"$XDG_CONFIG_DIRS"
+  fi
+  export XDG_CONFIG_DIRS
+  # gnome is already added if gnome-session installed
+  if [ "$DESKTOP_SESSION" != "gnome" ]; then
+     if [ -z "$XDG_DATA_DIRS" ]; then
+       XDG_DATA_DIRS="$DEFAULT_XDG_DATA_DIRS"
+     fi
+     if [ -n "${XDG_DATA_DIRS##*/usr/share/$DESKTOP_SESSION*}" ]; then
+       XDG_DATA_DIRS=/usr/share/"$DESKTOP_SESSION":"$XDG_DATA_DIRS"
+     fi
+     export XDG_DATA_DIRS
+  fi
+fi
