From 5d36d8be078082007f55b8b14838ef7f642a0a73 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Aug 01 2017 03:22:57 +0000 Subject: import gnome-session-3.22.3-4.el7 --- diff --git a/.gitignore b/.gitignore index 69067b6..7e9dd9c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/gnome-session-3.14.0.tar.xz +SOURCES/gnome-session-3.22.3.tar.xz diff --git a/.gnome-session.metadata b/.gnome-session.metadata index d647b10..6796fde 100644 --- a/.gnome-session.metadata +++ b/.gnome-session.metadata @@ -1 +1 @@ -0df66062c4ff7286bcf951517a7a8728133f6469 SOURCES/gnome-session-3.14.0.tar.xz +84daef055a4aad831950341e83c5b34091479006 SOURCES/gnome-session-3.22.3.tar.xz diff --git a/SOURCES/0001-Revert-Remove-all-references-to-gnome-session-proper.patch b/SOURCES/0001-Revert-Remove-all-references-to-gnome-session-proper.patch new file mode 100644 index 0000000..5c9491b --- /dev/null +++ b/SOURCES/0001-Revert-Remove-all-references-to-gnome-session-proper.patch @@ -0,0 +1,2851 @@ +From 5d77ba7a2ce0bedfc65a991bd232e518418ce950 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 8 Mar 2017 14:08:09 -0500 +Subject: [PATCH 01/19] Revert "Remove all references to + gnome-session-properties" + +This reverts commit 0c6fe6ca14b65cdfc1cd039a5cc9cb83ea346d6b. +--- + configure.ac | 8 + + data/Makefile.am | 5 +- + data/icons/16x16/Makefile.am | 28 ++ + data/icons/16x16/session-properties.png | Bin 0 -> 595 bytes + data/icons/16x16/session-properties.svg | 394 ++++++++++++++++ + data/icons/22x22/Makefile.am | 27 ++ + data/icons/22x22/session-properties.png | Bin 0 -> 754 bytes + data/icons/22x22/session-properties.svg | 440 ++++++++++++++++++ + data/icons/24x24/Makefile.am | 25 + + data/icons/24x24/session-properties.png | Bin 0 -> 784 bytes + data/icons/32x32/Makefile.am | 27 ++ + data/icons/32x32/session-properties.png | Bin 0 -> 1109 bytes + data/icons/32x32/session-properties.svg | 490 ++++++++++++++++++++ + data/icons/48x48/Makefile.am | 25 + + data/icons/48x48/session-properties.png | Bin 0 -> 1839 bytes + data/icons/Makefile.am | 3 + + data/icons/scalable/Makefile.am | 25 + + data/icons/scalable/session-properties.svg | 515 +++++++++++++++++++++ + data/icons/symbolic/Makefile.am | 25 + + .../icons/symbolic/session-properties-symbolic.svg | 28 ++ + data/session-properties.ui | 323 +++++++++++++ + doc/man/gnome-session.1 | 2 + + po/POTFILES.in | 1 + + 23 files changed, 2390 insertions(+), 1 deletion(-) + create mode 100644 data/icons/16x16/Makefile.am + create mode 100644 data/icons/16x16/session-properties.png + create mode 100644 data/icons/16x16/session-properties.svg + create mode 100644 data/icons/22x22/Makefile.am + create mode 100644 data/icons/22x22/session-properties.png + create mode 100644 data/icons/22x22/session-properties.svg + create mode 100644 data/icons/24x24/Makefile.am + create mode 100644 data/icons/24x24/session-properties.png + create mode 100644 data/icons/32x32/Makefile.am + create mode 100644 data/icons/32x32/session-properties.png + create mode 100644 data/icons/32x32/session-properties.svg + create mode 100644 data/icons/48x48/Makefile.am + create mode 100644 data/icons/48x48/session-properties.png + create mode 100644 data/icons/Makefile.am + create mode 100644 data/icons/scalable/Makefile.am + create mode 100644 data/icons/scalable/session-properties.svg + create mode 100644 data/icons/symbolic/Makefile.am + create mode 100644 data/icons/symbolic/session-properties-symbolic.svg + create mode 100644 data/session-properties.ui + +diff --git a/configure.ac b/configure.ac +index c6facb35..776c8208 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -343,60 +343,68 @@ if test $enable_ipv6 = yes; then + dnl ================================================================= + dnl Now we would check for specific function like getaddrinfo. + dnl ================================================================= + have_getaddrinfo=no + if test $have_ipv6=yes; then + AC_CHECK_FUNC(getaddrinfo, have_getaddrinfo=yes) + if test $have_getaddrinfo != yes; then + # getaddrinfo is not in the default libraries. See if it's in some other. + for lib in bsd socket inet; do + AC_CHECK_LIB($lib, getaddrinfo, [LIBS="$LIBS -l$lib";have_getaddrinfo=yes; break]) + done + fi + if test $have_getaddrinfo=yes; then + AC_DEFINE(ENABLE_IPV6, 1, [Define if IPV6 is supported]) + have_full_ipv6=yes + fi + fi + fi + dnl ============================================================================== + dnl End of IPv6 checks + dnl ============================================================================== + + AC_CONFIG_FILES([ + Makefile + doc/Makefile + doc/dbus/Makefile + doc/dbus/gnome-session.xml + doc/man/Makefile + data/Makefile + data/org.gnome.SessionManager.gschema.xml ++data/icons/Makefile ++data/icons/16x16/Makefile ++data/icons/22x22/Makefile ++data/icons/24x24/Makefile ++data/icons/32x32/Makefile ++data/icons/48x48/Makefile ++data/icons/scalable/Makefile ++data/icons/symbolic/Makefile + gnome-session/Makefile + tools/Makefile + po/Makefile.in + ]) + AC_OUTPUT + + dnl --------------------------------------------------------------------------- + dnl - Show summary + dnl --------------------------------------------------------------------------- + + echo " + gnome-session $VERSION + `echo gnome-session $VERSION | sed "s/./=/g"` + + prefix: ${prefix} + exec_prefix: ${exec_prefix} + libdir: ${libdir} + bindir: ${bindir} + sbindir: ${sbindir} + sysconfdir: ${sysconfdir} + localstatedir: ${localstatedir} + datadir: ${datadir} + source code location: ${srcdir} + compiler: ${CC} + cflags: ${CFLAGS} + Maintainer mode: ${USE_MAINTAINER_MODE} + Use *_DISABLE_DEPRECATED: ${enable_deprecation_flags} + + GConf support: ${enable_gconf} + Session tracking: ${session_tracking} +diff --git a/data/Makefile.am b/data/Makefile.am +index ae08730d..a171dfcb 100644 +--- a/data/Makefile.am ++++ b/data/Makefile.am +@@ -1,32 +1,35 @@ ++SUBDIRS = icons ++ + uidir = $(pkgdatadir) +-ui_DATA = ++ui_DATA = \ ++ session-properties.ui + + if BUILD_SESSION_SELECTOR + ui_DATA += session-selector.ui + endif + + hwcompatdir = $(pkgdatadir) + hwcompat_DATA = hardware-compatibility + + xsessiondir = $(datadir)/xsessions + xsession_in_files = gnome.desktop.in gnome-xorg.desktop.in + + if BUILD_SESSION_SELECTOR + xsession_in_files += gnome-custom-session.desktop.in + endif + + xsession_DATA = $(xsession_in_files:.desktop.in=.desktop) + + wayland_sessiondir = $(datadir)/wayland-sessions + wayland_session_in_files = gnome.desktop.in + wayland_session_DATA = $(wayland_session_in_files:.desktop.in=.desktop) + + sessiondir = $(datadir)/gnome-session/sessions + session_in_in_files = gnome.session.desktop.in.in gnome-dummy.session.desktop.in.in + session_in_files = $(session_in_in_files:.session.desktop.in.in=.session.desktop.in) + session_DATA = $(session_in_files:.session.desktop.in=.session) + + %.session.desktop.in: %.session.desktop.in.in Makefile + $(AM_V_GEN)sed \ + -e "s|\@LIBEXECDIR\@|$(libexecdir)|" \ + $< > $@ +diff --git a/data/icons/16x16/Makefile.am b/data/icons/16x16/Makefile.am +new file mode 100644 +index 00000000..d338f4c3 +--- /dev/null ++++ b/data/icons/16x16/Makefile.am +@@ -0,0 +1,28 @@ ++size = 16x16 ++ ++themedir = $(datadir)/icons/hicolor ++iconsdir = $(themedir)/$(size)/apps ++ ++icons_DATA = session-properties.png ++icons_SOURCE = session-properties.svg ++ ++gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor ++ ++install-data-hook: ++ @-if test -z "$(DESTDIR)"; then \ ++ echo "Updating Gtk icon cache."; \ ++ $(gtk_update_icon_cache); \ ++ else \ ++ echo "*** Icon cache not updated. After install, run this:"; \ ++ echo "*** $(gtk_update_icon_cache)"; \ ++ fi ++ ++uninstall-hook: ++ @rm -f $(DESTDIR)$(themedir)/icon-theme.cache ++ ++ ++EXTRA_DIST = \ ++ $(icons_DATA) \ ++ $(icons_SOURCE) ++ ++-include $(top_srcdir)/git.mk +diff --git a/data/icons/16x16/session-properties.png b/data/icons/16x16/session-properties.png +new file mode 100644 +index 0000000000000000000000000000000000000000..1367c20ae73a8b5e73d98f5dbcb6341cd0dc9ebe +GIT binary patch +literal 595 +zcmV-Z0<8UsP)5liy2|Q5eTR&-=cox8c~2 +zT2`*8E+SB&p~E)2@g|62&LHY4vde`2fUqAIbrnQ(5fMsI5DdE5O+<8)3nGl7Xd(&* +zq1IM`>7Zrq{n5poPS>=at8;js&-a|~^PD4B?+lHE1HU`?hY%420RcqF7tApudZ4MJ +zE8c~s=~abwC6-r?>+t&Bt7c<7Zxa4AL0x8@n8=B3Jba!bXKlr@-Brn-Gw*5G6{!mw +zx-k6mv!wxSGPJ6c%lz0AW=9{ddwPY@08FFo-*qhJvS~b}{D#-BFh)hqDJ?Mn;Sqax +z1UY%4pUYP+GX3;gE$H#$@o&f6A6pS{7YqD&bD!wJR(gAqhzK`t+(Oedlu{Umfl>;k +z6vbkZ$&Zr^-W$Se?b9@IZQiD@6K)K0JlTuXpCJG~pO5yocFvyeBealJnkzc71Mt88Ig(;l`&`*@Z~@%7txx)TWoE?xL5*x>ck8IN-~-nr5P)6mg9 +zK7!FRjAql!4BiEV-A4y%1ngf0M#hJkno0pnV_cr8VG@X(V$SseZVe2edwlqtk5MQt +z;yTunfU0^(A_Q7`2)1_DZ-59bhmMpjh+r#S^hDdv)kSOfYppnq%x;cY66;Uhwo3Ln +haR2i^x#&uN@CTAjj`{aKg8l#i002ovPDHLkV1gZB6^{S_ + +literal 0 +HcmV?d00001 + +diff --git a/data/icons/16x16/session-properties.svg b/data/icons/16x16/session-properties.svg +new file mode 100644 +index 00000000..4f7c37f2 +--- /dev/null ++++ b/data/icons/16x16/session-properties.svg +@@ -0,0 +1,394 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ image/svg+xml ++ ++ ++ ++ Jakub Steiner ++ ++ ++ http://jimmac.musichall.cz ++ ++ Gnome Session Properties ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/data/icons/22x22/Makefile.am b/data/icons/22x22/Makefile.am +new file mode 100644 +index 00000000..ae4931c2 +--- /dev/null ++++ b/data/icons/22x22/Makefile.am +@@ -0,0 +1,27 @@ ++size = 22x22 ++ ++themedir = $(datadir)/icons/hicolor ++iconsdir = $(themedir)/$(size)/apps ++ ++icons_DATA = session-properties.png ++icons_SOURCE = session-properties.svg ++ ++gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor ++ ++install-data-hook: ++ @-if test -z "$(DESTDIR)"; then \ ++ echo "Updating Gtk icon cache."; \ ++ $(gtk_update_icon_cache); \ ++ else \ ++ echo "*** Icon cache not updated. After install, run this:"; \ ++ echo "*** $(gtk_update_icon_cache)"; \ ++ fi ++ ++uninstall-hook: ++ @rm -f $(DESTDIR)$(themedir)/icon-theme.cache ++ ++EXTRA_DIST = \ ++ $(icons_DATA) \ ++ $(icons_SOURCE) ++ ++-include $(top_srcdir)/git.mk +diff --git a/data/icons/22x22/session-properties.png b/data/icons/22x22/session-properties.png +new file mode 100644 +index 0000000000000000000000000000000000000000..12225ee3c2abb7f1a4be7bb77743514cde5d08fe +GIT binary patch +literal 754 +zcmV*lgmp~Q5?rV=iJ8}9cNN| +z*^7v%7U@C>t-#cZ78aG(u1!U>>3?Wdi-=qVy&!035MdZp6cK`;6=)9%L}*o1+QXS< +zrhDh!x%ag2IgaI2wCD>54nNNCbAIQ0en0p}5&)+zUwyJH?$rySe=k`GKp@08Dn#(^ +zvwipEi6gtkmW~@G9owqD*VWWd-ZLw?sM;o^8GQX*Z?0{SrZk|A?`$gdTK +zaDO0~126$@_KpOjxkYBE3$4&W4q=!@f;D|lKLr4CGH98FJQi}5Oa^mqgu~>{)EJidMMJYuj62Y=848xeJ +z7{D+L1iH`)Q^hH(Zs*Q}TLfW9+rIrAJ$4v9M}N;&M3t~^?Yf_TUfIGGi0XFkJ?vs^ +zYz(b6)`qru!Jd<3_)R}Lm(2&;GX^ADxg2T^@_4WdfT}ec=LG{SSQ+D0UpJ69dHDkp +zt*9bia{#F-ih=@c+|kzyj@OzrDW#WF~*C6j%({ +kfc1x54{(9eiT!`39~bB4p9yeF3;+NC07*qoM6N<$f(k-YiU0rr + +literal 0 +HcmV?d00001 + +diff --git a/data/icons/22x22/session-properties.svg b/data/icons/22x22/session-properties.svg +new file mode 100644 +index 00000000..1d0afda2 +--- /dev/null ++++ b/data/icons/22x22/session-properties.svg +@@ -0,0 +1,440 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ image/svg+xml ++ ++ ++ ++ Jakub Steiner ++ ++ ++ http://jimmac.musichall.cz ++ ++ Gnome Session Properties ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/data/icons/24x24/Makefile.am b/data/icons/24x24/Makefile.am +new file mode 100644 +index 00000000..8c28888a +--- /dev/null ++++ b/data/icons/24x24/Makefile.am +@@ -0,0 +1,25 @@ ++size = 24x24 ++ ++themedir = $(datadir)/icons/hicolor ++iconsdir = $(themedir)/$(size)/apps ++ ++icons_DATA = session-properties.png ++ ++gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor ++ ++install-data-hook: ++ @-if test -z "$(DESTDIR)"; then \ ++ echo "Updating Gtk icon cache."; \ ++ $(gtk_update_icon_cache); \ ++ else \ ++ echo "*** Icon cache not updated. After install, run this:"; \ ++ echo "*** $(gtk_update_icon_cache)"; \ ++ fi ++ ++uninstall-hook: ++ @rm -f $(DESTDIR)$(themedir)/icon-theme.cache ++ ++EXTRA_DIST = \ ++ $(icons_DATA) ++ ++-include $(top_srcdir)/git.mk +diff --git a/data/icons/24x24/session-properties.png b/data/icons/24x24/session-properties.png +new file mode 100644 +index 0000000000000000000000000000000000000000..ac81c7ad3b604a056ed02c86bcb2db97c78f4aed +GIT binary patch +literal 784 +zcmV+r1MmEaP)KPZr(RZ;%TnP#T<=Dm6Ew$M?>9B0Z^(18c%aCzU)J?GqWFZ}B! +zvd+01w_dJ}IQ2rPKNAoF5C}0P=Og$s9(Z*2%!z|DfSs4`mR#Ob^|P+FelBy4NYVQQ +z6oVh$s2$rHGyns@86wbI>11TdkWpA{ar1q6G7!&XVmBh%Gb;>V{azyFWe~bi +zBtX&kYRt>V+T2Cc5DSRAjJ&vAbOxr8Bbf^b%v)3$huG^oxQUUX0fEH;ral|`u1##P +zlg5T^f7An0&#i*7P!%&3;P2j#V`BrK2a2i-_1 +ziAJMDA`!yjFyU~RP$-0yl3*~1X`1M|K9d1}uImU?{t_87LTODq51)47`95u}M>u)v +zI7$`1LV~h{>P^*!n_RklEuyBK$ItFFIXQ_^3Ufm23ZXCU1ygSN$Jd)cYW_>H3|I*Svg!SWIe-m}PW%6@u>Ar9X6B0{qPS!L +O0000jOCUOrWQ}?uexLlr3kGN|uWD_;#<|u5RK) +zY+`Mgak=WxnI0e^pt9nCR9kxlwNy<@njb{gPyyI%>YIck8xnvI;QB91>{F*GDcX}0 +z$O=7X^4Y)wNdc3yI{oAS4tWAH_omhWkdh{;@Y3f^@8I$|jizODC^81o)xt8D1ehy5 +zUbp}NqN_AFHy6a;+uIAJ+5J2P_+$w%lN)C)4`SPPPQ*e8&b;$_&O#Gh=>i<8Y};ny +z!CYPfa`jE;N*#fmGFq0!x7}~;nj{{NqbQ0iCRaGQcC3JDn(Txdzuv&MEgD~KO4`yp +z=5BCuB@e@wRsqvAJ;$xvx9Gcmjg^%Zmpz{f_`E70OR0-tSr&$2WCRZ19VQgI%iAYU +zp=p}SN0xJMWKJ&6Mznnd&T;3?ZAM0h>FoG``e*Ais+7+q+~GIOJc4b6LL-cgkJ8%G +zj;`yht*`ULkKgn2;6Tzx2$86Wc$mq!l{y|Xk<<#-kH3~Fz^Te9V01LZ#JvexTiVey +zjc7DV@NkeTmp*rM2;rL3*N~{}`1lx~T>2D6ys~=*48ve_EX3q*leC_0L(?>LT?b%! +zdD)d%k|bnV_8i-LLI{Kq)YR1Sazg{l!w=E~I4*{5+pL6F=>O_V`oH*^SS*$#|EDkv +zgFs+EMV6Kj?^OYS;Nc)APn@Eovkgg-C@syQ$>)f~lPz&+Gwy(0RL0e-R{@AbA}lN{ +z(%IF{xw9VvpzAv2<>js}=t<(ym~7joxVYG5%MdW{Z%FNygZktuQ}>5x@9Nk9> +z%JlRU-4`z)$qo_1HF-i&6l!bh2>AE81SH;OvUg~SKfuA~nwYsiL`PRA7ccZsRu&*E +zsxXTW?n38{#fOW?+6X9R0Kx}Ug1bBIBx3saA>M0wpQgq}Dr=774`zRSIAIzwRv*t3 +z|6`t*t^rg?fFE|QfKx>E^G(cXDt&#|Fr$&Y$N^+u5#`l&)EzyxZSwm7NnnTP9DXP(4sABZyPdr@{r2fTh{@!?W=uHM@4}{@6;R807W=7gCe`9}SA(iEpq7oiO +z;O1aK0wgSLd3LN7*c3o9Pyqx06|jLP3d)=vn_F`P2m^mP4_*aI00qbIxyOhD2C(4} +b^WWlc-6EIuR>CZG00000NkvXXu0mjfn7$9& + +literal 0 +HcmV?d00001 + +diff --git a/data/icons/32x32/session-properties.svg b/data/icons/32x32/session-properties.svg +new file mode 100644 +index 00000000..5bb14559 +--- /dev/null ++++ b/data/icons/32x32/session-properties.svg +@@ -0,0 +1,490 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ image/svg+xml ++ ++ ++ ++ Jakub Steiner ++ ++ ++ http://jimmac.musichall.cz ++ ++ Gnome Session Properties ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/data/icons/48x48/Makefile.am b/data/icons/48x48/Makefile.am +new file mode 100644 +index 00000000..13b0cf36 +--- /dev/null ++++ b/data/icons/48x48/Makefile.am +@@ -0,0 +1,25 @@ ++size = 48x48 ++ ++themedir = $(datadir)/icons/hicolor ++iconsdir = $(themedir)/$(size)/apps ++ ++icons_DATA = session-properties.png ++ ++gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor ++ ++install-data-hook: ++ @-if test -z "$(DESTDIR)"; then \ ++ echo "Updating Gtk icon cache."; \ ++ $(gtk_update_icon_cache); \ ++ else \ ++ echo "*** Icon cache not updated. After install, run this:"; \ ++ echo "*** $(gtk_update_icon_cache)"; \ ++ fi ++ ++uninstall-hook: ++ @rm -f $(DESTDIR)$(themedir)/icon-theme.cache ++ ++EXTRA_DIST = \ ++ $(icons_DATA) ++ ++-include $(top_srcdir)/git.mk +diff --git a/data/icons/48x48/session-properties.png b/data/icons/48x48/session-properties.png +new file mode 100644 +index 0000000000000000000000000000000000000000..32c2358ca45a07e86fbb03d75ec4742e8203091a +GIT binary patch +literal 1839 +zcmV+~2hjM5P)o(6r8k8?YI(DKwnU$ +zscQXx?!c!0iv$|d3jp#tKO3Mop|HfdwiG^%(Bv{YDXBhor03QDNj@<7u-QR}Ec +zVmpa1^{zMG*>esLv%B8Q?96WL#>pp*>^W!7Io~(`|9394!WhG?47u3^){9$SfL;3M +z;O`G6Kbf~)=uVkOY^kjqNkSk%G`=sEP%uKzEQ;faSmfJ3{?2z7p+dmQlJnw@ZOKQr +zboJpxqVWlr$ygr&M18@s@xn<$<*n9uUyaL=`79fO>e|+r^U%h+#PIN(` +zwf+>yR5$Xm?ILu%@)` +zg-9uhwY8C)y(IAbTNYs6I=^u3t{u6y{{F2p;AU7h32cP;`LSo46HJUh3X +zZvRKyeM6UVA~)ycly^06ou6a!>?~9YFvjRFfA4pNv(t*do?n2p}$TPH<;fLe87u(KE0yLT^AZk*}0*6iQE9~ua-f+8S=muIbb +zKuXDzN8a3!v=hKjAG<$fyz2Y<2(*wwB~1TszO@GHKyV5P(ej%##xQ+xo{czG2;ub? +zgg_HZ0h-p#X^i33rygsKX-I!Tu)<8NP4nj5w{IWDn2OEc`Vlr}pa(1|D5$lL!p!O5 +zy)mU!xlAdAWnKSX%70_GhCmMpArNAXa+o>qh*K2-r4)yreTE-A{-c&iS0Xfp!aPvf +zQJ6XJ*s&%+DaCV#pXKd$-d; +zc<331hITPJGFl!ypU)GCL;~9e^%;cPX|yH+Ysbd02)M4x^o5TY92{hHWRxpcu9OGg +zv> +zGm9Vj@rlC>4i1&yeCfI60Gw@=7%GY&M(a-23O4IPyFnW-kDJ4Fm{LmqNAV +zCw@C#&iP960GUjNOeW(?Qc4+k`8`uYJRWEJz;=H4{l|Iw(92OLZN^Vf-l|sMS2S#Ac~=D$^%L%j=bXszk(?L(*xc--Ck6e>=n +zl^#$^h0YE)3XbD|R#5yxR+B>h3z-mtN5An+&YV5NYsX)ur>AFK8@7!^{a&bniF3Ie +zU-*O4LoGjaFjEap>&qEQ*){>O~|H2~w$43tzIEeYwy^1YvkR4T>KfB6J6GnYciHVfOf8Q6X&0|TF9;P%hf*H_+DuF^^=(&=>7 +z!|8OIbUIBknIw@&aO%`wszeAOn3=i6gAa_<4WzYZYHEu4)Noy0Fbr2N`t)hvwsyxhoJgWY +z`UXs#LLtpU_5vr~II&h$E1-1RnTzd&*v^1n4Q}T(Ru|^T&d+dc@&q9G+QScf^>;st +zW!3LSEug=yG#FYd3hpY`vPh9&^)K~^yN(mwIwh+PwqRX?>FTU}&-d}zFft|5?ZtrNRV`B{Y)vYWpTt#pXUA=wS +z_Vt~}f{@9%96$4cTFERP1EN6G#`_qjKAd{$6)Au6nUDT^`CA&RtM%>;Mk|cgNISxY +zrcn_By^>qJ^rw$cjZXjtU{x4n5JE(NE}*@5C4e@-#S_@tI4yr3ZU_ye0R`lNERX?~ +zfLUXVCjcnzuiNkhwBdzF7aMLSl0_aao`5A_#T1DPzio0+j07;oY}#(E$iu>ms5U-i +deFfY~_&?#hc%)mzygmQ`002ovPDHLkV1i5*a;5+P + +literal 0 +HcmV?d00001 + +diff --git a/data/icons/Makefile.am b/data/icons/Makefile.am +new file mode 100644 +index 00000000..8b6c5491 +--- /dev/null ++++ b/data/icons/Makefile.am +@@ -0,0 +1,3 @@ ++SUBDIRS = 16x16 22x22 24x24 32x32 48x48 scalable symbolic ++ ++-include $(top_srcdir)/git.mk +diff --git a/data/icons/scalable/Makefile.am b/data/icons/scalable/Makefile.am +new file mode 100644 +index 00000000..4ff67b7b +--- /dev/null ++++ b/data/icons/scalable/Makefile.am +@@ -0,0 +1,25 @@ ++size = scalable ++ ++themedir = $(datadir)/icons/hicolor ++iconsdir = $(themedir)/$(size)/apps ++ ++icons_DATA = session-properties.svg ++ ++gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor ++ ++install-data-hook: ++ @-if test -z "$(DESTDIR)"; then \ ++ echo "Updating Gtk icon cache."; \ ++ $(gtk_update_icon_cache); \ ++ else \ ++ echo "*** Icon cache not updated. After install, run this:"; \ ++ echo "*** $(gtk_update_icon_cache)"; \ ++ fi ++ ++uninstall-hook: ++ @rm -f $(DESTDIR)$(themedir)/icon-theme.cache ++ ++EXTRA_DIST = \ ++ $(icons_DATA) ++ ++-include $(top_srcdir)/git.mk +diff --git a/data/icons/scalable/session-properties.svg b/data/icons/scalable/session-properties.svg +new file mode 100644 +index 00000000..cec2c39e +--- /dev/null ++++ b/data/icons/scalable/session-properties.svg +@@ -0,0 +1,515 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ image/svg+xml ++ ++ ++ ++ Jakub Steiner ++ ++ ++ http://jimmac.musichall.cz ++ ++ Gnome Session Properties ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/data/icons/symbolic/Makefile.am b/data/icons/symbolic/Makefile.am +new file mode 100644 +index 00000000..670d0a5a +--- /dev/null ++++ b/data/icons/symbolic/Makefile.am +@@ -0,0 +1,25 @@ ++size = symbolic ++ ++themedir = $(datadir)/icons/hicolor ++iconsdir = $(themedir)/$(size)/apps ++ ++icons_DATA = session-properties-symbolic.svg ++ ++gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor ++ ++install-data-hook: ++ @-if test -z "$(DESTDIR)"; then \ ++ echo "Updating Gtk icon cache."; \ ++ $(gtk_update_icon_cache); \ ++ else \ ++ echo "*** Icon cache not updated. After install, run this:"; \ ++ echo "*** $(gtk_update_icon_cache)"; \ ++ fi ++ ++uninstall-hook: ++ @rm -f $(DESTDIR)$(themedir)/icon-theme.cache ++ ++EXTRA_DIST = \ ++ $(icons_DATA) ++ ++-include $(top_srcdir)/git.mk +diff --git a/data/icons/symbolic/session-properties-symbolic.svg b/data/icons/symbolic/session-properties-symbolic.svg +new file mode 100644 +index 00000000..e628ecd1 +--- /dev/null ++++ b/data/icons/symbolic/session-properties-symbolic.svg +@@ -0,0 +1,28 @@ ++ ++ ++ ++ ++ ++ ++ ++ image/svg+xml ++ ++ Gnome Symbolic Icon Theme ++ ++ ++ ++ ++ ++ ++ Gnome Symbolic Icon Theme ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/data/session-properties.ui b/data/session-properties.ui +new file mode 100644 +index 00000000..1f0cb9a5 +--- /dev/null ++++ b/data/session-properties.ui +@@ -0,0 +1,323 @@ ++ ++ ++ ++ ++ ++ True ++ True ++ 6 ++ ++ ++ True ++ 12 ++ vertical ++ 3 ++ ++ ++ True ++ 0 ++ 3 ++ 3 ++ Additional startup _programs: ++ True ++ session_properties_treeview ++ ++ ++ False ++ 0 ++ ++ ++ ++ ++ True ++ 6 ++ ++ ++ True ++ True ++ never ++ automatic ++ etched-in ++ ++ ++ 210 ++ True ++ True ++ ++ ++ ++ ++ 0 ++ ++ ++ ++ ++ True ++ 6 ++ start ++ ++ ++ gtk-add ++ True ++ True ++ True ++ True ++ ++ ++ False ++ False ++ 0 ++ ++ ++ ++ ++ gtk-remove ++ True ++ False ++ True ++ True ++ True ++ ++ ++ False ++ False ++ 1 ++ ++ ++ ++ ++ gtk-edit ++ True ++ False ++ True ++ True ++ True ++ ++ ++ False ++ False ++ 2 ++ ++ ++ ++ ++ False ++ False ++ 1 ++ ++ ++ ++ ++ 1 ++ ++ ++ ++ ++ ++ ++ True ++ Startup Programs ++ ++ ++ False ++ ++ ++ ++ ++ True ++ 12 ++ vertical ++ 6 ++ ++ ++ _Automatically remember running applications when logging out ++ True ++ True ++ False ++ True ++ True ++ ++ ++ False ++ False ++ 0 ++ ++ ++ ++ ++ True ++ ++ ++ True ++ True ++ ++ ++ True ++ 4 ++ ++ ++ True ++ gtk-save ++ ++ ++ False ++ False ++ 0 ++ ++ ++ ++ ++ True ++ _Remember Currently Running Applications ++ True ++ ++ ++ 1 ++ ++ ++ ++ ++ ++ ++ False ++ False ++ 0 ++ ++ ++ ++ ++ False ++ False ++ 1 ++ ++ ++ ++ ++ 1 ++ ++ ++ ++ ++ True ++ Options ++ ++ ++ 1 ++ False ++ ++ ++ ++ ++ True ++ 6 ++ 3 ++ 2 ++ 12 ++ 6 ++ ++ ++ True ++ 12 ++ ++ ++ True ++ True ++ ++ ++ ++ 0 ++ ++ ++ ++ ++ Browse… ++ True ++ True ++ True ++ ++ ++ False ++ False ++ 1 ++ ++ ++ ++ ++ 1 ++ 2 ++ 1 ++ 2 ++ GTK_FILL ++ ++ ++ ++ ++ True ++ True ++ ++ ++ ++ 1 ++ 2 ++ 2 ++ 3 ++ GTK_FILL ++ ++ ++ ++ ++ True ++ True ++ ++ ++ ++ 1 ++ 2 ++ GTK_FILL ++ ++ ++ ++ ++ True ++ 0 ++ Comm_ent: ++ True ++ label2 ++ ++ ++ 2 ++ 3 ++ GTK_FILL ++ GTK_FILL ++ ++ ++ ++ ++ True ++ 0 ++ Co_mmand: ++ True ++ session_properties_command_entry ++ ++ ++ 1 ++ 2 ++ GTK_FILL ++ GTK_FILL ++ ++ ++ ++ ++ True ++ 0 ++ _Name: ++ True ++ session_properties_name_entry ++ ++ ++ GTK_FILL ++ GTK_FILL ++ ++ ++ ++ +diff --git a/doc/man/gnome-session.1 b/doc/man/gnome-session.1 +index bf9cf808..35c062c5 100644 +--- a/doc/man/gnome-session.1 ++++ b/doc/man/gnome-session.1 +@@ -67,46 +67,48 @@ Name=GNOME + RequiredComponents=gnome-shell;gnome-settings-daemon; + .in + .fi + .PP + The \fB.session\fP files are looked for in + \fB$XDG_CONFIG_HOME/gnome-session/sessions\fP, + \fB$XDG_CONFIG_DIRS/gnome-session/sessions\fP and + \fB$XDG_DATA_DIRS/gnome-session/sessions\fP. + .SH ENVIRONMENT + \fIgnome-session\fP sets several environment variables for the use of + its child processes: + .PP + .B SESSION_MANAGER + .IP + This variable is used by session-manager aware clients to contact + gnome-session. + .PP + .B DISPLAY + .IP + This variable is set to the X display being used by + \fIgnome-session\fP. Note that if the \fI--display\fP option is used + this might be different from the setting of the environment variable + when gnome-session is invoked. + .SH FILES + .PP + .B $XDG_CONFIG_HOME/config/autostart + .B $XDG_CONFIG_DIRS/config/autostart + .B /usr/share/gnome/autostart + .IP + The applications defined 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 + .B $XDG_DATA_DIRS/gnome-session/sessions + .IP + These directories contain the \fB.session\fP files that can be used + with the \fI--session\fP option. + .PP + .B $XDG_CONFIG_HOME/gnome-session/saved-session + .IP + This directory contains the list of applications of the saved session. + .SH BUGS + If you find bugs in the \fIgnome-session\fP program, please report + these on https://bugzilla.gnome.org. + .SH SEE ALSO ++.BR gnome-session-properties(1) + .BR gnome-session-quit(1) +diff --git a/po/POTFILES.in b/po/POTFILES.in +index cc1170aa..76882645 100644 +--- a/po/POTFILES.in ++++ b/po/POTFILES.in +@@ -1,18 +1,19 @@ + # List of source files containing translatable strings. + # Please keep this file sorted alphabetically. + data/gnome-custom-session.desktop.in + data/gnome.desktop.in + data/gnome-xorg.desktop.in + data/gnome-dummy.session.desktop.in.in + data/gnome.session.desktop.in.in + [type: gettext/glade]data/session-selector.ui ++[type: gettext/glade]data/session-properties.ui + gnome-session/gsm-fail-whale-dialog.c + gnome-session/gsm-manager.c + gnome-session/gsm-process-helper.c + gnome-session/gsm-util.c + gnome-session/gsm-xsmp-client.c + gnome-session/gsm-xsmp-server.c + gnome-session/main.c + tools/gnome-session-inhibit.c + tools/gnome-session-selector.c + tools/gnome-session-quit.c +-- +2.12.0 + diff --git a/SOURCES/0001-fail-whale-handle-X-server-dying-before-startup.patch b/SOURCES/0001-fail-whale-handle-X-server-dying-before-startup.patch new file mode 100644 index 0000000..5390164 --- /dev/null +++ b/SOURCES/0001-fail-whale-handle-X-server-dying-before-startup.patch @@ -0,0 +1,89 @@ +From ec58cbbc612992e2de70cbbb858bbbb25cac6aff Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 30 May 2017 12:46:19 -0400 +Subject: [PATCH] fail-whale: handle X server dying before startup + +This commit deals with gtk_init_with_args failing, +without setting an error (which it does if it can't +connect to the X server). +--- + gnome-session/gsm-fail-whale-dialog.c | 21 ++++++++++++++------- + 1 file changed, 14 insertions(+), 7 deletions(-) + +diff --git a/gnome-session/gsm-fail-whale-dialog.c b/gnome-session/gsm-fail-whale-dialog.c +index f53ce417..c5889efc 100644 +--- a/gnome-session/gsm-fail-whale-dialog.c ++++ b/gnome-session/gsm-fail-whale-dialog.c +@@ -344,55 +344,62 @@ setup_window (GsmFailWhaleDialog *fail_dialog) + G_CALLBACK (on_logout_clicked), fail_dialog); + } + } + + static void + gsm_fail_whale_dialog_init (GsmFailWhaleDialog *fail_dialog) + { + fail_dialog->priv = GSM_FAIL_WHALE_DIALOG_GET_PRIVATE (fail_dialog); + } + + static gboolean debug_mode = FALSE; + static gboolean allow_logout = FALSE; + static gboolean extensions = FALSE; + + int main (int argc, char *argv[]) + { + GOptionEntry entries[] = { + { "debug", 0, 0, G_OPTION_ARG_NONE, &debug_mode, N_("Enable debugging code"), NULL }, + { "allow-logout", 0, 0, G_OPTION_ARG_NONE, &allow_logout, N_("Allow logout"), NULL }, + { "extensions", 0, 0, G_OPTION_ARG_NONE, &extensions, N_("Show extension warning"), NULL }, + { NULL, 0, 0, 0, NULL, NULL, NULL } + }; + + GsmFailWhaleDialog *fail_dialog; + GError *error = NULL; + + bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR); + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); + textdomain (GETTEXT_PACKAGE); + +- gtk_init_with_args (&argc, &argv, " - fail whale", +- entries, GETTEXT_PACKAGE, +- &error); +- if (error != NULL) { +- g_warning ("%s", error->message); +- exit (1); +- } ++ if (!gtk_init_with_args (&argc, &argv, " - fail whale", ++ entries, GETTEXT_PACKAGE, ++ &error)) { ++ if (error != NULL) { ++ g_warning ("%s", error->message); ++ exit (1); ++ } ++ ++ /* display server probably went away. Could be for legitimate reasons, could be for ++ * unexpected reasons. If it went away unexpectantly, that's logged elsewhere, so ++ * let's not add noise by logging here. ++ */ ++ return 0; ++ } + + fail_dialog = g_object_new (GSM_TYPE_FAIL_WHALE_DIALOG, NULL); + fail_dialog->priv->debug_mode = debug_mode; + fail_dialog->priv->allow_logout = allow_logout; + fail_dialog->priv->extensions = extensions; + + setup_window (fail_dialog); + + g_signal_connect (fail_dialog, "destroy", + G_CALLBACK (gtk_main_quit), NULL); + + gtk_widget_show (GTK_WIDGET (fail_dialog)); + + gtk_main (); + + return 0; + } + +-- +2.13.0 + diff --git a/SOURCES/0001-main-Set-XDG_MENU_PREFIX.patch b/SOURCES/0001-main-Set-XDG_MENU_PREFIX.patch deleted file mode 100644 index 3e74dcd..0000000 --- a/SOURCES/0001-main-Set-XDG_MENU_PREFIX.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 6bda8ba424d2dbd2441d9a7e6553608dceaa8454 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Thu, 18 Oct 2012 16:53:12 +0200 -Subject: [PATCH] main: Set XDG_MENU_PREFIX - ---- - gnome-session/main.c | 5 +++++ - 1 file changed, 5 insertions(+) - -diff --git a/gnome-session/main.c b/gnome-session/main.c -index 1903381..147daec 100644 ---- a/gnome-session/main.c -+++ b/gnome-session/main.c -@@ -347,6 +347,11 @@ main (int argc, char **argv) - */ - gsm_util_setenv ("GNOME_DESKTOP_SESSION_ID", "this-is-deprecated"); - -+ /* We want to use the GNOME menus which has the designed categories, -+ * not the legacy redhat-menus. -+ */ -+ gsm_util_setenv ("XDG_MENU_PREFIX", "gnome-"); -+ - client_store = gsm_store_new (); - - xsmp_server = gsm_xsmp_server_new (client_store); --- -1.7.12.1 - diff --git a/SOURCES/0002-Revert-Remove-gnome-session-properties.patch b/SOURCES/0002-Revert-Remove-gnome-session-properties.patch new file mode 100644 index 0000000..781c171 --- /dev/null +++ b/SOURCES/0002-Revert-Remove-gnome-session-properties.patch @@ -0,0 +1,4147 @@ +From a4d8ac3f6c392416b2569b4617ab6ef4a64d53b7 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 8 May 2015 16:24:59 -0400 +Subject: [PATCH 02/19] Revert "Remove gnome-session-properties" + +This reverts commit ea285af9962313ee2675fff27d3a852bb61e936a. +--- + Makefile.am | 1 + + capplet/Makefile.am | 31 + + 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 | 1102 +++++++++++++++++++++++++++ + capplet/gsp-app.h | 108 +++ + capplet/gsp-keyfile.c | 201 +++++ + capplet/gsp-keyfile.h | 65 ++ + capplet/main.c | 108 +++ + configure.ac | 2 + + data/Makefile.am | 6 + + data/gnome-session-properties.desktop.in.in | 15 + + doc/man/Makefile.am | 1 + + doc/man/gnome-session-properties.1 | 24 + + po/POTFILES.in | 5 + + 19 files changed, 3780 insertions(+) + create mode 100644 capplet/Makefile.am + 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 data/gnome-session-properties.desktop.in.in + create mode 100644 doc/man/gnome-session-properties.1 + +diff --git a/Makefile.am b/Makefile.am +index 6560a4ec..6b6a47bf 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -1,32 +1,33 @@ + SUBDIRS = \ + gnome-session \ ++ capplet \ + tools \ + data \ + doc \ + po + + ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} + + EXTRA_DIST = \ + HACKING \ + MAINTAINERS + + MAINTAINERCLEANFILES = \ + $(srcdir)/INSTALL \ + $(srcdir)/aclocal.m4 \ + $(srcdir)/config.guess \ + $(srcdir)/config.h.in \ + $(srcdir)/config.sub \ + $(srcdir)/depcomp \ + $(srcdir)/install-sh \ + $(srcdir)/ltmain.sh \ + $(srcdir)/missing \ + $(srcdir)/mkinstalldirs \ + $(srcdir)/configure \ + $(srcdir)/m4/intltool.m4 \ + `find "$(srcdir)" -type f -name Makefile.in -print` + + CHANGELOG_GIT_RANGE = GNOME_SESSION_2_26_1.. + dist-hook: + $(AM_V_GEN)if test -d "$(srcdir)/.git"; then \ + ( echo '# Generated by Makefile. Do not edit.'; echo; \ +diff --git a/capplet/Makefile.am b/capplet/Makefile.am +new file mode 100644 +index 00000000..c2e563cf +--- /dev/null ++++ b/capplet/Makefile.am +@@ -0,0 +1,31 @@ ++bin_PROGRAMS = gnome-session-properties ++ ++AM_CPPFLAGS = \ ++ $(SESSION_PROPERTIES_CFLAGS) \ ++ $(GCONF_CFLAGS) \ ++ -I$(top_srcdir)/gnome-session \ ++ -DLOCALE_DIR=\""$(datadir)/locale"\" \ ++ -DGTKBUILDER_DIR=\""$(pkgdatadir)"\" \ ++ $(DISABLE_DEPRECATED_CFLAGS) ++ ++AM_CFLAGS = $(WARN_CFLAGS) ++ ++gnome_session_properties_SOURCES = \ ++ main.c \ ++ gsm-properties-dialog.h \ ++ gsm-properties-dialog.c \ ++ gsm-app-dialog.h \ ++ gsm-app-dialog.c \ ++ gsp-app.h \ ++ gsp-app.c \ ++ gsp-app-manager.h \ ++ gsp-app-manager.c \ ++ gsp-keyfile.h \ ++ gsp-keyfile.c ++ ++gnome_session_properties_LDADD = \ ++ $(SESSION_PROPERTIES_LIBS) \ ++ $(top_builddir)/gnome-session/libgsmutil.la \ ++ $(GCONF_LIBS) ++ ++-include $(top_srcdir)/git.mk +diff --git a/capplet/gsm-app-dialog.c b/capplet/gsm-app-dialog.c +new file mode 100644 +index 00000000..e7369dda +--- /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 ++ * ++ * 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 ++#include ++#include ++ ++#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 00000000..ced0628c +--- /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 ++ * ++ * 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 ++#include ++ ++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 00000000..33812b8b +--- /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 ++ * ++ * 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 ++#include ++#include ++ ++#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 00000000..df4915ea +--- /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 ++ * ++ * 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 ++#include ++ ++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 00000000..bcd6d402 +--- /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 ++ * ++ * 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 ++ ++#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 00000000..777f8d6c +--- /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 ++ * ++ * 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 ++ ++#include ++ ++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 00000000..c92b8dad +--- /dev/null ++++ b/capplet/gsp-app.c +@@ -0,0 +1,1102 @@ ++/* -*- 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 ++ * ++ * 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 ++#endif ++ ++#include ++#include ++ ++#include ++#include ++ ++#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 ("%s\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 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, ++ gsm_util_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, ++ gsm_util_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 00000000..a1997955 +--- /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 ++ * ++ * 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 ++#include ++ ++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 00000000..de9fac0e +--- /dev/null ++++ b/capplet/gsp-keyfile.c +@@ -0,0 +1,201 @@ ++/* ++ * 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 ++ */ ++ ++#include ++ ++#include ++ ++#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; ++ 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 (only_show_in) { ++ found = FALSE; ++ for (i = 0; only_show_in[i] != NULL; i++) { ++ if (g_strcmp0 (current_desktop, only_show_in[i]) == 0) { ++ 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_strcmp0 (current_desktop, not_show_in[i]) == 0) { ++ found = TRUE; ++ break; ++ } ++ } ++ ++ g_strfreev (not_show_in); ++ ++ if (found) ++ return FALSE; ++ } ++ ++ 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 00000000..d94f6672 +--- /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 ++ */ ++ ++#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 00000000..3c7177bc +--- /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 ++ ++#include ++#include ++ ++#include ++#include ++ ++#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/configure.ac b/configure.ac +index 776c8208..47caf9c8 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -337,65 +337,67 @@ if test $enable_ipv6 = yes; then + ]])], + [have_ipv6=yes], + [have_ipv6=no] + ) + AC_MSG_RESULT($have_ipv6) + + dnl ================================================================= + dnl Now we would check for specific function like getaddrinfo. + dnl ================================================================= + have_getaddrinfo=no + if test $have_ipv6=yes; then + AC_CHECK_FUNC(getaddrinfo, have_getaddrinfo=yes) + if test $have_getaddrinfo != yes; then + # getaddrinfo is not in the default libraries. See if it's in some other. + for lib in bsd socket inet; do + AC_CHECK_LIB($lib, getaddrinfo, [LIBS="$LIBS -l$lib";have_getaddrinfo=yes; break]) + done + fi + if test $have_getaddrinfo=yes; then + AC_DEFINE(ENABLE_IPV6, 1, [Define if IPV6 is supported]) + have_full_ipv6=yes + fi + fi + fi + dnl ============================================================================== + dnl End of IPv6 checks + dnl ============================================================================== + + AC_CONFIG_FILES([ + Makefile ++capplet/Makefile + doc/Makefile + doc/dbus/Makefile + doc/dbus/gnome-session.xml + doc/man/Makefile + data/Makefile ++data/gnome-session-properties.desktop.in + data/org.gnome.SessionManager.gschema.xml + data/icons/Makefile + data/icons/16x16/Makefile + data/icons/22x22/Makefile + data/icons/24x24/Makefile + data/icons/32x32/Makefile + data/icons/48x48/Makefile + data/icons/scalable/Makefile + data/icons/symbolic/Makefile + gnome-session/Makefile + tools/Makefile + po/Makefile.in + ]) + AC_OUTPUT + + dnl --------------------------------------------------------------------------- + dnl - Show summary + dnl --------------------------------------------------------------------------- + + echo " + gnome-session $VERSION + `echo gnome-session $VERSION | sed "s/./=/g"` + + prefix: ${prefix} + exec_prefix: ${exec_prefix} + libdir: ${libdir} + bindir: ${bindir} + sbindir: ${sbindir} + sysconfdir: ${sysconfdir} + localstatedir: ${localstatedir} +diff --git a/data/Makefile.am b/data/Makefile.am +index a171dfcb..6167d10f 100644 +--- a/data/Makefile.am ++++ b/data/Makefile.am +@@ -1,68 +1,74 @@ + SUBDIRS = icons + + uidir = $(pkgdatadir) + ui_DATA = \ + session-properties.ui + + if BUILD_SESSION_SELECTOR + ui_DATA += session-selector.ui + endif + + hwcompatdir = $(pkgdatadir) + hwcompat_DATA = hardware-compatibility + + xsessiondir = $(datadir)/xsessions + xsession_in_files = gnome.desktop.in gnome-xorg.desktop.in + + if BUILD_SESSION_SELECTOR + xsession_in_files += gnome-custom-session.desktop.in + endif + + xsession_DATA = $(xsession_in_files:.desktop.in=.desktop) + + wayland_sessiondir = $(datadir)/wayland-sessions + wayland_session_in_files = gnome.desktop.in + wayland_session_DATA = $(wayland_session_in_files:.desktop.in=.desktop) + ++desktopdir = $(datadir)/applications ++desktop_in_files = gnome-session-properties.desktop.in ++desktop_DATA = $(desktop_in_files:.desktop.in=.desktop) ++ + sessiondir = $(datadir)/gnome-session/sessions + session_in_in_files = gnome.session.desktop.in.in gnome-dummy.session.desktop.in.in + session_in_files = $(session_in_in_files:.session.desktop.in.in=.session.desktop.in) + session_DATA = $(session_in_files:.session.desktop.in=.session) + + %.session.desktop.in: %.session.desktop.in.in Makefile + $(AM_V_GEN)sed \ + -e "s|\@LIBEXECDIR\@|$(libexecdir)|" \ + $< > $@ + + %.session: %.session.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@ + + @INTLTOOL_DESKTOP_RULE@ + @INTLTOOL_XML_NOMERGE_RULE@ + + gsettings_SCHEMAS = org.gnome.SessionManager.gschema.xml + @GSETTINGS_RULES@ + + migrationdir = $(datadir)/GConf/gsettings + dist_migration_DATA = gnome-session.convert + + EXTRA_DIST = \ + $(xsession_in_files) \ + $(session_in_in_files) \ + $(wayland_session_in_files) \ + $(gsettings_SCHEMAS:.xml=.xml.in) \ + session-selector.ui \ + gnome-custom-session.desktop.in \ + $(ui_DATA) \ + $(hwcompat_DATA) + + CLEANFILES = \ + $(gsettings_SCHEMAS) \ + $(xsession_DATA) \ + $(wayland_session_DATA) \ ++ $(desktop_DATA) \ + $(session_DATA) + + DISTCLEANFILES = \ + $(gsettings_SCHEMAS) \ ++ $(desktop_in_files) \ + $(wayland_session_in_files) + + -include $(top_srcdir)/git.mk +diff --git a/data/gnome-session-properties.desktop.in.in b/data/gnome-session-properties.desktop.in.in +new file mode 100644 +index 00000000..3dc7b033 +--- /dev/null ++++ b/data/gnome-session-properties.desktop.in.in +@@ -0,0 +1,15 @@ ++[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; ++NoDisplay=true ++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/doc/man/Makefile.am b/doc/man/Makefile.am +index 02e5c62a..28794233 100644 +--- a/doc/man/Makefile.am ++++ b/doc/man/Makefile.am +@@ -1,29 +1,30 @@ + XSLTPROC_FLAGS = \ + --nonet \ + --stringparam man.output.quietly 1 \ + --stringparam funcsynopsis.style ansi \ + --stringparam man.th.extra1.suppress 1 \ + --stringparam man.authors.section.enabled 0 \ + --stringparam man.copyright.section.enabled 0 + + .xml.1: + $(AM_V_GEN) $(XSLTPROC) $(XSLTPROC_FLAGS) http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $< + + man_MANS = \ + gnome-session.1 \ ++ gnome-session-properties.1 \ + gnome-session-quit.1 \ + gnome-session-inhibit.1 + + if BUILD_SESSION_SELECTOR + man_MANS += gnome-session-selector.1 + endif + + EXTRA_DIST = \ + gnome-session-inhibit.xml \ + gnome-session-selector.xml \ + $(man_MANS) + + CLEANFILES = \ + gnome-session-inhibit.1 + + -include $(top_srcdir)/git.mk +diff --git a/doc/man/gnome-session-properties.1 b/doc/man/gnome-session-properties.1 +new file mode 100644 +index 00000000..c7ef1af3 +--- /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/po/POTFILES.in b/po/POTFILES.in +index 76882645..5cb5123d 100644 +--- a/po/POTFILES.in ++++ b/po/POTFILES.in +@@ -1,19 +1,24 @@ + # 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 + data/gnome.desktop.in + data/gnome-xorg.desktop.in + data/gnome-dummy.session.desktop.in.in + data/gnome.session.desktop.in.in ++data/gnome-session-properties.desktop.in.in + [type: gettext/glade]data/session-selector.ui + [type: gettext/glade]data/session-properties.ui + gnome-session/gsm-fail-whale-dialog.c + gnome-session/gsm-manager.c + gnome-session/gsm-process-helper.c + gnome-session/gsm-util.c + gnome-session/gsm-xsmp-client.c + gnome-session/gsm-xsmp-server.c + gnome-session/main.c + tools/gnome-session-inhibit.c + tools/gnome-session-selector.c + tools/gnome-session-quit.c +-- +2.12.0 + diff --git a/SOURCES/0003-Revert-Rename-the-desktop-file-to-gnome-session-prop.patch b/SOURCES/0003-Revert-Rename-the-desktop-file-to-gnome-session-prop.patch new file mode 100644 index 0000000..51b9a1e --- /dev/null +++ b/SOURCES/0003-Revert-Rename-the-desktop-file-to-gnome-session-prop.patch @@ -0,0 +1,195 @@ +From 99d31512307576e9c06a201728eaa023718d3db7 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 8 May 2015 16:27:15 -0400 +Subject: [PATCH 03/19] Revert "Rename the desktop file to + gnome-session-properties.desktop" + +This reverts commit ac9fd0dc97a17674cb082f80df0b1fcc45bc92bf. +--- + configure.ac | 2 +- + data/Makefile.am | 2 +- + ...ession-properties.desktop.in.in => session-properties.desktop.in.in} | 0 + po/POTFILES.in | 1 + + po/POTFILES.skip | 1 + + 5 files changed, 4 insertions(+), 2 deletions(-) + rename data/{gnome-session-properties.desktop.in.in => session-properties.desktop.in.in} (100%) + +diff --git a/configure.ac b/configure.ac +index 47caf9c8..cc554a8a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -343,61 +343,61 @@ if test $enable_ipv6 = yes; then + dnl ================================================================= + dnl Now we would check for specific function like getaddrinfo. + dnl ================================================================= + have_getaddrinfo=no + if test $have_ipv6=yes; then + AC_CHECK_FUNC(getaddrinfo, have_getaddrinfo=yes) + if test $have_getaddrinfo != yes; then + # getaddrinfo is not in the default libraries. See if it's in some other. + for lib in bsd socket inet; do + AC_CHECK_LIB($lib, getaddrinfo, [LIBS="$LIBS -l$lib";have_getaddrinfo=yes; break]) + done + fi + if test $have_getaddrinfo=yes; then + AC_DEFINE(ENABLE_IPV6, 1, [Define if IPV6 is supported]) + have_full_ipv6=yes + fi + fi + fi + dnl ============================================================================== + dnl End of IPv6 checks + dnl ============================================================================== + + AC_CONFIG_FILES([ + Makefile + capplet/Makefile + doc/Makefile + doc/dbus/Makefile + doc/dbus/gnome-session.xml + doc/man/Makefile + data/Makefile +-data/gnome-session-properties.desktop.in ++data/session-properties.desktop.in + data/org.gnome.SessionManager.gschema.xml + data/icons/Makefile + data/icons/16x16/Makefile + data/icons/22x22/Makefile + data/icons/24x24/Makefile + data/icons/32x32/Makefile + data/icons/48x48/Makefile + data/icons/scalable/Makefile + data/icons/symbolic/Makefile + gnome-session/Makefile + tools/Makefile + po/Makefile.in + ]) + AC_OUTPUT + + dnl --------------------------------------------------------------------------- + dnl - Show summary + dnl --------------------------------------------------------------------------- + + echo " + gnome-session $VERSION + `echo gnome-session $VERSION | sed "s/./=/g"` + + prefix: ${prefix} + exec_prefix: ${exec_prefix} + libdir: ${libdir} + bindir: ${bindir} + sbindir: ${sbindir} + sysconfdir: ${sysconfdir} + localstatedir: ${localstatedir} +diff --git a/data/Makefile.am b/data/Makefile.am +index 6167d10f..e8a0e05e 100644 +--- a/data/Makefile.am ++++ b/data/Makefile.am +@@ -1,58 +1,58 @@ + SUBDIRS = icons + + uidir = $(pkgdatadir) + ui_DATA = \ + session-properties.ui + + if BUILD_SESSION_SELECTOR + ui_DATA += session-selector.ui + endif + + hwcompatdir = $(pkgdatadir) + hwcompat_DATA = hardware-compatibility + + xsessiondir = $(datadir)/xsessions + xsession_in_files = gnome.desktop.in gnome-xorg.desktop.in + + if BUILD_SESSION_SELECTOR + xsession_in_files += gnome-custom-session.desktop.in + endif + + xsession_DATA = $(xsession_in_files:.desktop.in=.desktop) + + wayland_sessiondir = $(datadir)/wayland-sessions + wayland_session_in_files = gnome.desktop.in + wayland_session_DATA = $(wayland_session_in_files:.desktop.in=.desktop) + + desktopdir = $(datadir)/applications +-desktop_in_files = gnome-session-properties.desktop.in ++desktop_in_files = session-properties.desktop.in + desktop_DATA = $(desktop_in_files:.desktop.in=.desktop) + + sessiondir = $(datadir)/gnome-session/sessions + session_in_in_files = gnome.session.desktop.in.in gnome-dummy.session.desktop.in.in + session_in_files = $(session_in_in_files:.session.desktop.in.in=.session.desktop.in) + session_DATA = $(session_in_files:.session.desktop.in=.session) + + %.session.desktop.in: %.session.desktop.in.in Makefile + $(AM_V_GEN)sed \ + -e "s|\@LIBEXECDIR\@|$(libexecdir)|" \ + $< > $@ + + %.session: %.session.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@ + + @INTLTOOL_DESKTOP_RULE@ + @INTLTOOL_XML_NOMERGE_RULE@ + + gsettings_SCHEMAS = org.gnome.SessionManager.gschema.xml + @GSETTINGS_RULES@ + + migrationdir = $(datadir)/GConf/gsettings + dist_migration_DATA = gnome-session.convert + + EXTRA_DIST = \ + $(xsession_in_files) \ + $(session_in_in_files) \ + $(wayland_session_in_files) \ + $(gsettings_SCHEMAS:.xml=.xml.in) \ + session-selector.ui \ + gnome-custom-session.desktop.in \ +diff --git a/data/gnome-session-properties.desktop.in.in b/data/session-properties.desktop.in.in +similarity index 100% +rename from data/gnome-session-properties.desktop.in.in +rename to data/session-properties.desktop.in.in +diff --git a/po/POTFILES.in b/po/POTFILES.in +index 5cb5123d..08d2eb06 100644 +--- a/po/POTFILES.in ++++ b/po/POTFILES.in +@@ -1,24 +1,25 @@ + # 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 + data/gnome.desktop.in + data/gnome-xorg.desktop.in + data/gnome-dummy.session.desktop.in.in + data/gnome.session.desktop.in.in + data/gnome-session-properties.desktop.in.in + [type: gettext/glade]data/session-selector.ui ++data/session-properties.desktop.in.in + [type: gettext/glade]data/session-properties.ui + gnome-session/gsm-fail-whale-dialog.c + gnome-session/gsm-manager.c + gnome-session/gsm-process-helper.c + gnome-session/gsm-util.c + gnome-session/gsm-xsmp-client.c + gnome-session/gsm-xsmp-server.c + gnome-session/main.c + tools/gnome-session-inhibit.c + tools/gnome-session-selector.c + tools/gnome-session-quit.c +diff --git a/po/POTFILES.skip b/po/POTFILES.skip +index 91b41569..e6470914 100644 +--- a/po/POTFILES.skip ++++ b/po/POTFILES.skip +@@ -1,5 +1,6 @@ + # List of source files containing translatable strings that should not be + # translated. + # Please keep this file sorted alphabetically. + data/gnome-dummy.session.desktop.in + data/gnome.session.desktop.in ++data/session-properties.desktop.in +-- +2.12.0 + diff --git a/SOURCES/0004-stop-using-gsm_util_get_current_desktop.patch b/SOURCES/0004-stop-using-gsm_util_get_current_desktop.patch new file mode 100644 index 0000000..748a4dc --- /dev/null +++ b/SOURCES/0004-stop-using-gsm_util_get_current_desktop.patch @@ -0,0 +1,441 @@ +From 5732c282f1cb2f485bd1d3a7b0ce391ab7709d81 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 13 May 2015 10:56:09 -0400 +Subject: [PATCH 04/19] stop using gsm_util_get_current_desktop + +It no longer exists. +--- + capplet/gsp-app.c | 111 +++++++++++++++++++++++++++++------------------------- + 1 file changed, 60 insertions(+), 51 deletions(-) + +diff --git a/capplet/gsp-app.c b/capplet/gsp-app.c +index c92b8dad..123ab217 100644 +--- a/capplet/gsp-app.c ++++ b/capplet/gsp-app.c +@@ -3,60 +3,61 @@ + * Copyright (C) 1999 Free Software Foundation, Inc. + * Copyright (C) 2007, 2009 Vincent Untz. + * Copyright (C) 2008 Lucas Rocha. + * Copyright (C) 2008 William Jon McCann + * + * 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 + #endif + + #include + #include + + #include + #include ++#include + + #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; +@@ -281,148 +282,145 @@ _gsp_app_update_description (GspApp *app) + } else { + secondary = _("No description"); + } + + g_free (app->priv->description); + app->priv->description = g_markup_printf_escaped ("%s\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 gboolean + _gsp_app_user_equal_system (GspApp *app, + char **system_path) + { + GspAppManager *manager; +- const char *system_dir; +- char *path; +- char *str; +- GKeyFile *keyfile; ++ gboolean return_value = FALSE; ++ const char *system_dir = NULL; ++ char *path = NULL; ++ char *str = NULL; ++ GKeyFile *keyfile = NULL; ++ GDesktopAppInfo *app_info = NULL; + + 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; ++ goto out; + } + + 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; ++ goto out; + } + +- 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, +- gsm_util_get_current_desktop ()) != app->priv->shown) { +- g_free (path); +- g_key_file_free (keyfile); +- return FALSE; ++ app_info = g_desktop_app_info_new_from_keyfile (keyfile); ++ ++ if (!app_info) { ++ goto out; + } + +- 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; ++ if (g_desktop_app_info_get_is_hidden (app_info)) { ++ goto out; ++ } ++ ++ if (g_desktop_app_info_has_key (app_info, ++ GSP_KEY_FILE_DESKTOP_KEY_AUTOSTART_ENABLED) && ++ !g_desktop_app_info_get_boolean (app_info, ++ GSP_KEY_FILE_DESKTOP_KEY_AUTOSTART_ENABLED)) { ++ goto out; ++ } ++ ++ if (!g_desktop_app_info_get_show_in (app_info, NULL)) { ++ goto out; ++ } ++ ++ if (g_desktop_app_info_get_nodisplay (app_info)) { ++ goto out; + } + + 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; ++ goto out; + } +- g_free (str); ++ g_clear_pointer (&str, g_free); + + 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; ++ goto out; + } +- g_free (str); ++ g_clear_pointer (&str, g_free); + + 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; ++ goto out; + } +- g_free (str); ++ g_clear_pointer (&str, g_free); + + 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; ++ goto out; + } +- g_free (str); +- +- g_key_file_free (keyfile); ++ g_clear_pointer (&str, g_free); + + *system_path = path; +- +- return TRUE; ++ path = NULL; ++ return_value = TRUE; ++out: ++ g_clear_pointer (&path, g_free); ++ g_clear_pointer (&str, g_free); ++ g_clear_object (&app_info); ++ g_clear_pointer (&keyfile, g_key_file_free); ++ ++ return return_value; + } + + 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); + } +@@ -748,153 +746,164 @@ gsp_app_delete (GspApp *app) + 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; ++ GDesktopAppInfo *app_info; + 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; + } + ++ app_info = g_desktop_app_info_new_from_keyfile (keyfile); ++ ++ if (!app_info) { ++ g_object_unref (app_info); ++ 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, +- gsm_util_get_current_desktop ()); ++ app->priv->shown = g_desktop_app_info_get_show_in (app_info, NULL); + + 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_object_unref (app_info); + 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; +-- +2.12.0 + diff --git a/SOURCES/0005-session-properties-get-out-of-Other.patch b/SOURCES/0005-session-properties-get-out-of-Other.patch new file mode 100644 index 0000000..f63298c --- /dev/null +++ b/SOURCES/0005-session-properties-get-out-of-Other.patch @@ -0,0 +1,34 @@ +From d53180ebccd678fae1da76d1defb05a9c73e92fe Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 20 Dec 2013 15:07:35 -0500 +Subject: [PATCH 05/19] session-properties: get out of Other + +Put it in the menus next to Settings and Software +--- + data/session-properties.desktop.in.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/data/session-properties.desktop.in.in b/data/session-properties.desktop.in.in +index 3dc7b033..dcfe2f84 100644 +--- a/data/session-properties.desktop.in.in ++++ b/data/session-properties.desktop.in.in +@@ -1,15 +1,15 @@ + [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; ++Categories=GNOME;GTK;System; + OnlyShowIn=GNOME;Unity; + NoDisplay=true + X-GNOME-Bugzilla-Bugzilla=GNOME + X-GNOME-Bugzilla-Product=gnome-session + X-GNOME-Bugzilla-Component=gnome-session-properties + X-GNOME-Bugzilla-Version=@VERSION@ +-- +2.12.0 + diff --git a/SOURCES/0006-session-properties-refresh-from-recent-glade.patch b/SOURCES/0006-session-properties-refresh-from-recent-glade.patch new file mode 100644 index 0000000..29a8281 --- /dev/null +++ b/SOURCES/0006-session-properties-refresh-from-recent-glade.patch @@ -0,0 +1,377 @@ +From faf13c2b486153683337064824712a440b158424 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 20 Dec 2013 10:53:33 -0500 +Subject: [PATCH 06/19] session-properties: refresh from recent glade + +The ui file is rather old. This commit just opens it up in a recent +glade and resaves it, so we have a fresh starting point to make +changes. +--- + data/session-properties.ui | 43 ++++++++++++++++++++++++++++++++++--------- + 1 file changed, 34 insertions(+), 9 deletions(-) + +diff --git a/data/session-properties.ui b/data/session-properties.ui +index 1f0cb9a5..47a30f78 100644 +--- a/data/session-properties.ui ++++ b/data/session-properties.ui +@@ -1,323 +1,348 @@ +- ++ + +- +- ++ + + True + True + 6 + + + True ++ False + 12 +- vertical + 3 + + + True ++ False + 0 + 3 + 3 + Additional startup _programs: + True + session_properties_treeview + + + False ++ True + 0 + + + + + True ++ False + 6 + + + True + True + never +- automatic + etched-in + + + 210 + True + True ++ ++ ++ + + + + ++ True ++ True + 0 + + + + + True ++ False + 6 + start + + + gtk-add + True + True + True + True + + + False + False + 0 + + + + + gtk-remove + True + False + True + True + True + + + False + False + 1 + + + + + gtk-edit + True + False + True + True + True + + + False + False + 2 + + + + + False + False + 1 + + + + ++ True ++ True + 1 + + + + + + + True ++ False + Startup Programs + + + False + + + + + True ++ False + 12 +- vertical + 6 + + + _Automatically remember running applications when logging out + True + True + False + True ++ 0.5 + True + + + False + False + 0 + + + + + True ++ False + + + True + True + + + True ++ False + 4 + + + True ++ False + gtk-save + + + False + False + 0 + + + + + True ++ False + _Remember Currently Running Applications + True + + ++ True ++ True + 1 + + + + + + + False + False + 0 + + + + + False + False + 1 + + + + + 1 + + + + + True ++ False + Options + + + 1 + False + + + + + True ++ False + 6 + 3 + 2 + 12 + 6 + + + True ++ False + 12 + + + True + True +- ++ + + ++ True ++ True + 0 + + + + + Browse… + True + True + True + + + False + False + 1 + + + + + 1 + 2 + 1 + 2 + GTK_FILL + + + + + True + True +- ++ + + + 1 + 2 + 2 + 3 + GTK_FILL + + + + + True + True +- ++ + + + 1 + 2 + GTK_FILL + + + + + True ++ False + 0 + Comm_ent: + True + label2 + + + 2 + 3 + GTK_FILL + GTK_FILL + + + + + True ++ False + 0 + Co_mmand: + True + session_properties_command_entry + + + 1 + 2 + GTK_FILL + GTK_FILL + + + + + True ++ False + 0 + _Name: + True + session_properties_name_entry + + + GTK_FILL + GTK_FILL + + + + +-- +2.12.0 + diff --git a/SOURCES/0007-manager-Don-t-clear-saved-session-if-autosaving-is-d.patch b/SOURCES/0007-manager-Don-t-clear-saved-session-if-autosaving-is-d.patch new file mode 100644 index 0000000..8147c53 --- /dev/null +++ b/SOURCES/0007-manager-Don-t-clear-saved-session-if-autosaving-is-d.patch @@ -0,0 +1,81 @@ +From b8e1b19177e1bbe866ed5561880eaaa7852d31dd Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 20 Dec 2013 16:14:16 -0500 +Subject: [PATCH 07/19] manager: Don't clear saved session if autosaving is + disabled + +Now that we support on-demand saving again, we need to make sure +we don't wipe that away at log out. +--- + gnome-session/gsm-manager.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/gnome-session/gsm-manager.c b/gnome-session/gsm-manager.c +index 012f3d3f..ce2ffbcf 100644 +--- a/gnome-session/gsm-manager.c ++++ b/gnome-session/gsm-manager.c +@@ -1790,61 +1790,60 @@ on_xsmp_client_register_confirmed (GsmXSMPClient *client, + app = find_app_for_startup_id (manager, id); + + if (app != NULL) { + gsm_app_set_registered (app, TRUE); + } + } + + static gboolean + auto_save_is_enabled (GsmManager *manager) + { + return g_settings_get_boolean (manager->priv->settings, KEY_AUTOSAVE_ONE_SHOT) + || g_settings_get_boolean (manager->priv->settings, KEY_AUTOSAVE); + } + + static void + maybe_save_session (GsmManager *manager) + { + GError *error; + + if (gsm_system_is_login_session (manager->priv->system)) + return; + + /* We only allow session saving when session is running or when + * logging out */ + if (manager->priv->phase != GSM_MANAGER_PHASE_RUNNING && + manager->priv->phase != GSM_MANAGER_PHASE_END_SESSION) { + return; + } + + if (!auto_save_is_enabled (manager)) { +- gsm_session_save_clear (); + return; + } + + error = NULL; + gsm_session_save (manager->priv->clients, &error); + + if (error) { + g_warning ("Error saving session: %s", error->message); + g_error_free (error); + } + } + + static void + _handle_client_end_session_response (GsmManager *manager, + GsmClient *client, + gboolean is_ok, + gboolean do_last, + gboolean cancel, + const char *reason) + { + /* just ignore if received outside of shutdown */ + if (manager->priv->phase < GSM_MANAGER_PHASE_QUERY_END_SESSION) { + return; + } + + g_debug ("GsmManager: Response from end session request: is-ok=%d do-last=%d cancel=%d reason=%s", is_ok, do_last, cancel, reason ? reason :""); + + if (cancel) { + cancel_end_session (manager); + return; +-- +2.12.0 + diff --git a/SOURCES/0008-Add-Remember-Currently-Running-Applications-button.patch b/SOURCES/0008-Add-Remember-Currently-Running-Applications-button.patch new file mode 100644 index 0000000..6e38896 --- /dev/null +++ b/SOURCES/0008-Add-Remember-Currently-Running-Applications-button.patch @@ -0,0 +1,1722 @@ +From 0399cc2e36daaec2ea70c0f32866fb37f08ad4b2 Mon Sep 17 00:00:00 2001 +From: Josselin Mouette +Date: Mon, 21 Jun 2010 15:22:23 -0400 +Subject: [PATCH 08/19] Add "Remember Currently Running Applications" button + +This adds back session saving that's not at logout. +--- + capplet/gsm-properties-dialog.c | 63 +++++++++++- + configure.ac | 1 + + data/session-properties.ui | 12 +++ + gnome-session/gsm-client.c | 10 ++ + gnome-session/gsm-client.h | 6 ++ + gnome-session/gsm-dbus-client.c | 14 +++ + gnome-session/gsm-manager.c | 150 ++++++++++++++++++++++++++++- + gnome-session/gsm-manager.h | 3 + + gnome-session/gsm-xsmp-client.c | 37 +++++++ + gnome-session/gsm-xsmp-client.h | 3 +- + gnome-session/org.gnome.SessionManager.xml | 8 ++ + 11 files changed, 303 insertions(+), 4 deletions(-) + +diff --git a/capplet/gsm-properties-dialog.c b/capplet/gsm-properties-dialog.c +index 33812b8b..d2be778b 100644 +--- a/capplet/gsm-properties-dialog.c ++++ b/capplet/gsm-properties-dialog.c +@@ -5,70 +5,77 @@ + * Copyright (C) 2008 Lucas Rocha. + * Copyright (C) 2008 William Jon McCann + * + * 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 + #include + #include + + #include "gsm-properties-dialog.h" + #include "gsm-app-dialog.h" + #include "gsm-util.h" + #include "gsp-app.h" + #include "gsp-app-manager.h" ++#include ++#include ++ ++#define GSM_SERVICE_DBUS "org.gnome.SessionManager" ++#define GSM_PATH_DBUS "/org/gnome/SessionManager" ++#define GSM_INTERFACE_DBUS "org.gnome.SessionManager" + + #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_SESSION_SAVED_WIDGET_NAME "session_properties_session_saved_label" + #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, +@@ -431,64 +438,118 @@ on_edit_app_clicked (GtkWidget *widget, + 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 ++session_saved_message (GsmPropertiesDialog *dialog, ++ const char *msg, ++ gboolean is_error) ++{ ++ GtkLabel *label; ++ gchar *markup; ++ label = GTK_LABEL (gtk_builder_get_object (dialog->priv->xml, CAPPLET_SESSION_SAVED_WIDGET_NAME)); ++ if (is_error) ++ markup = g_markup_printf_escaped ("%s", msg); ++ else ++ markup = g_markup_escape_text (msg, -1); ++ gtk_label_set_markup (label, markup); ++ g_free (markup); ++} ++ ++static void ++session_saved_cb (DBusGProxy *proxy, ++ DBusGProxyCall *call_id, ++ void *user_data) ++{ ++ gboolean res; ++ GsmPropertiesDialog *dialog = user_data; ++ ++ res = dbus_g_proxy_end_call (proxy, call_id, NULL, G_TYPE_INVALID); ++ if (res) ++ session_saved_message (dialog, _("Your session has been saved."), FALSE); ++ else ++ session_saved_message (dialog, _("Failed to save session"), TRUE); ++ ++ g_object_unref (proxy); ++} ++ ++static void + on_save_session_clicked (GtkWidget *widget, + GsmPropertiesDialog *dialog) + { +- g_debug ("Session saving is not implemented yet!"); ++ DBusGConnection *conn; ++ DBusGProxy *proxy; ++ DBusGProxyCall *call; ++ ++ conn = dbus_g_bus_get (DBUS_BUS_SESSION, NULL); ++ if (conn == NULL) { ++ session_saved_message (dialog, _("Could not connect to the session bus"), TRUE); ++ return; ++ } ++ ++ proxy = dbus_g_proxy_new_for_name (conn, GSM_SERVICE_DBUS, GSM_PATH_DBUS, GSM_INTERFACE_DBUS); ++ if (proxy == NULL) { ++ session_saved_message (dialog, _("Could not connect to the session manager"), TRUE); ++ return; ++ } ++ ++ call = dbus_g_proxy_begin_call (proxy, "SaveSession", session_saved_cb, dialog, NULL, G_TYPE_INVALID); ++ if (call == NULL) { ++ session_saved_message (dialog, _("Failed to save session"), TRUE); ++ g_object_unref (proxy); ++ return; ++ } + } + + 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), +diff --git a/configure.ac b/configure.ac +index cc554a8a..04a25fc8 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -51,60 +51,61 @@ if test "$enable_session_selector" = yes; then + PKG_CHECK_MODULES(SESSION_SELECTOR, gtk+-3.0 gio-2.0) + fi + + dnl ==================================================================== + dnl Dependency Checks + dnl ==================================================================== + + dnl Standard vertical stacks + PKG_CHECK_MODULES(GIO, gio-2.0) + PKG_CHECK_MODULES(GIOUNIX, gio-unix-2.0 >= $GLIB_REQUIRED) + PKG_CHECK_MODULES(GTK3, gtk+-3.0 >= $GTK3_REQUIRED) + + PKG_CHECK_MODULES(GNOME_SESSION, + glib-2.0 >= $GLIB_REQUIRED + gio-2.0 >= $GLIB_REQUIRED + json-glib-1.0 >= $JSON_GLIB_REQUIRED + gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED + ) + + dnl We can only support old upower + dnl https://bugzilla.gnome.org/show_bug.cgi?id=710383 + PKG_CHECK_MODULES(UPOWER, upower-glib < 0.99.0, have_old_upower=yes, have_old_upower=no) + AS_IF([test x$have_old_upower = xyes], [ + AC_DEFINE([HAVE_OLD_UPOWER], [1], [Define if we have an older upower]) + ]) + AM_CONDITIONAL(HAVE_OLD_UPOWER, test x$have_old_upower = xyes) + + PKG_CHECK_MODULES(SESSION_PROPERTIES, + glib-2.0 >= $GLIB_REQUIRED + gtk+-3.0 >= $GTK3_REQUIRED ++ dbus-glib-1 >= $DBUS_GLIB_REQUIRED + ) + + PKG_CHECK_MODULES(X11, x11) + PKG_CHECK_MODULES(SM, sm) + PKG_CHECK_MODULES(ICE, ice) + PKG_CHECK_MODULES(XEXT, xext xau) + + PKG_CHECK_MODULES(GL_TEST, xcomposite gl glib-2.0 epoxy) + PKG_CHECK_MODULES(GLES_TEST, egl glesv2) + + dnl ==================================================================== + dnl Check for gconf + dnl ==================================================================== + AC_ARG_ENABLE([gconf], + AS_HELP_STRING([--enable-gconf], [Support gconf-based autostart]), + [enable_gconf=$enableval], + [enable_gconf=auto]) + + PKG_CHECK_MODULES(GCONF, gconf-2.0, [have_gconf=yes], [have_gconf=no]) + + if test x$enable_gconf = xauto ; then + enable_gconf=$have_gconf + elif test x$enable_gconf = xyes -a x$have_gconf = xno ; then + AC_MSG_ERROR([GConf support explicitly required, but gconf not found]) + fi + + if test x$enable_gconf = xyes ; then + AC_DEFINE([HAVE_GCONF], [1], [Define if we support gconf-based autostart]) + fi + +diff --git a/data/session-properties.ui b/data/session-properties.ui +index 47a30f78..b43759ff 100644 +--- a/data/session-properties.ui ++++ b/data/session-properties.ui +@@ -133,108 +133,120 @@ + + + + + True + False + 12 + 6 + + + _Automatically remember running applications when logging out + True + True + False + True + 0.5 + True + + + False + False + 0 + + + + + True + False + + ++ True + True + True + + + True + False + 4 + + + True + False + gtk-save + + + False + False + 0 + + + + + True + False + _Remember Currently Running Applications + True + + + True + True + 1 + + + + + + + False + False + 0 + + + + + False + False + 1 + + ++ ++ ++ True ++ True ++ ++ ++ False ++ False ++ 2 ++ ++ + + + 1 + + + + + True + False + Options + + + 1 + False + + + + + True + False + 6 + 3 + 2 + 12 + 6 + + + True + False + 12 +diff --git a/gnome-session/gsm-client.c b/gnome-session/gsm-client.c +index 75edbbff..7b78d9e1 100644 +--- a/gnome-session/gsm-client.c ++++ b/gnome-session/gsm-client.c +@@ -514,49 +514,59 @@ gsm_client_query_end_session (GsmClient *client, + g_return_val_if_fail (GSM_IS_CLIENT (client), FALSE); + + return GSM_CLIENT_GET_CLASS (client)->impl_query_end_session (client, flags, error); + } + + gboolean + gsm_client_end_session (GsmClient *client, + GsmClientEndSessionFlag flags, + GError **error) + { + g_return_val_if_fail (GSM_IS_CLIENT (client), FALSE); + + return GSM_CLIENT_GET_CLASS (client)->impl_end_session (client, flags, error); + } + + gboolean + gsm_client_stop (GsmClient *client, + GError **error) + { + g_return_val_if_fail (GSM_IS_CLIENT (client), FALSE); + + return GSM_CLIENT_GET_CLASS (client)->impl_stop (client, error); + } + + void + gsm_client_disconnected (GsmClient *client) + { + g_signal_emit (client, signals[DISCONNECTED], 0); + } + ++gboolean ++gsm_client_request_save (GsmClient *client, ++ guint flags, ++ GError **error) ++{ ++ g_return_val_if_fail (GSM_IS_CLIENT (client), FALSE); ++ ++ return GSM_CLIENT_GET_CLASS (client)->impl_request_save (client, flags, error); ++} ++ + GKeyFile * + gsm_client_save (GsmClient *client, + GError **error) + { + g_return_val_if_fail (GSM_IS_CLIENT (client), FALSE); + + return GSM_CLIENT_GET_CLASS (client)->impl_save (client, error); + } + + void + gsm_client_end_session_response (GsmClient *client, + gboolean is_ok, + gboolean do_last, + gboolean cancel, + const char *reason) + { + g_signal_emit (client, signals[END_SESSION_RESPONSE], 0, + is_ok, do_last, cancel, reason); + } +diff --git a/gnome-session/gsm-client.h b/gnome-session/gsm-client.h +index cd7c06d8..f79896b3 100644 +--- a/gnome-session/gsm-client.h ++++ b/gnome-session/gsm-client.h +@@ -63,89 +63,95 @@ struct _GsmClient + GObject parent; + GsmClientPrivate *priv; + }; + + struct _GsmClientClass + { + GObjectClass parent_class; + + /* signals */ + void (*disconnected) (GsmClient *client); + void (*end_session_response) (GsmClient *client, + gboolean ok, + gboolean do_last, + gboolean cancel, + const char *reason); + + /* virtual methods */ + char * (*impl_get_app_name) (GsmClient *client); + GsmClientRestartStyle (*impl_get_restart_style_hint) (GsmClient *client); + guint (*impl_get_unix_process_id) (GsmClient *client); + gboolean (*impl_query_end_session) (GsmClient *client, + GsmClientEndSessionFlag flags, + GError **error); + gboolean (*impl_end_session) (GsmClient *client, + GsmClientEndSessionFlag flags, + GError **error); + gboolean (*impl_cancel_end_session) (GsmClient *client, + GError **error); + gboolean (*impl_stop) (GsmClient *client, + GError **error); ++ gboolean (*impl_request_save) (GsmClient *client, ++ guint flags, ++ GError **error); + GKeyFile * (*impl_save) (GsmClient *client, + GError **error); + }; + + typedef enum + { + GSM_CLIENT_ERROR_GENERAL = 0, + GSM_CLIENT_ERROR_NOT_REGISTERED, + GSM_CLIENT_NUM_ERRORS + } GsmClientError; + + #define GSM_CLIENT_ERROR gsm_client_error_quark () + GQuark gsm_client_error_quark (void); + + GType gsm_client_get_type (void) G_GNUC_CONST; + + const char *gsm_client_peek_id (GsmClient *client); + + + const char * gsm_client_peek_startup_id (GsmClient *client); + const char * gsm_client_peek_app_id (GsmClient *client); + guint gsm_client_peek_restart_style_hint (GsmClient *client); + guint gsm_client_peek_status (GsmClient *client); + + + char *gsm_client_get_app_name (GsmClient *client); + void gsm_client_set_app_id (GsmClient *client, + const char *app_id); + void gsm_client_set_status (GsmClient *client, + guint status); + + gboolean gsm_client_end_session (GsmClient *client, + guint flags, + GError **error); + gboolean gsm_client_query_end_session (GsmClient *client, + guint flags, + GError **error); + gboolean gsm_client_cancel_end_session (GsmClient *client, + GError **error); + + void gsm_client_disconnected (GsmClient *client); + ++gboolean gsm_client_request_save (GsmClient *client, ++ guint flags, ++ GError **error); + GKeyFile *gsm_client_save (GsmClient *client, + GError **error); + + gboolean gsm_client_stop (GsmClient *client, + GError **error); + + /* private */ + + void gsm_client_end_session_response (GsmClient *client, + gboolean is_ok, + gboolean do_last, + gboolean cancel, + const char *reason); + + G_END_DECLS + + #endif /* __GSM_CLIENT_H__ */ +diff --git a/gnome-session/gsm-dbus-client.c b/gnome-session/gsm-dbus-client.c +index 6f5099f9..3c5f7504 100644 +--- a/gnome-session/gsm-dbus-client.c ++++ b/gnome-session/gsm-dbus-client.c +@@ -299,60 +299,73 @@ gsm_dbus_client_get_property (GObject *object, + case PROP_BUS_NAME: + g_value_set_string (value, self->priv->bus_name); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + } + + static void + gsm_dbus_client_finalize (GObject *object) + { + GsmDBusClient *client = (GsmDBusClient *) object; + + g_free (client->priv->bus_name); + + if (client->priv->skeleton != NULL) { + g_dbus_interface_skeleton_unexport_from_connection (G_DBUS_INTERFACE_SKELETON (client->priv->skeleton), + client->priv->connection); + g_clear_object (&client->priv->skeleton); + } + + g_clear_object (&client->priv->connection); + + if (client->priv->watch_id != 0) + g_bus_unwatch_name (client->priv->watch_id); + + G_OBJECT_CLASS (gsm_dbus_client_parent_class)->finalize (object); + } + ++static gboolean ++dbus_client_request_save (GsmClient *client, ++ guint flags, ++ GError **error) ++{ ++ g_debug ("GsmDBusClient: sending save request to client with id %s", ++ gsm_client_peek_id (client)); ++ ++ /* FIXME: The protocol does not support this */ ++ ++ return FALSE; ++} ++ + static GKeyFile * + dbus_client_save (GsmClient *client, + GError **error) + { + g_debug ("GsmDBusClient: saving client with id %s", + gsm_client_peek_id (client)); + + /* FIXME: We still don't support client saving for D-Bus + * session clients */ + + return NULL; + } + + static gboolean + dbus_client_stop (GsmClient *client, + GError **error) + { + GsmDBusClient *dbus_client = (GsmDBusClient *) client; + gsm_exported_client_private_emit_stop (dbus_client->priv->skeleton); + return TRUE; + } + + static char * + dbus_client_get_app_name (GsmClient *client) + { + /* Always use app-id instead */ + return NULL; + } + + static GsmClientRestartStyle +@@ -392,60 +405,61 @@ static gboolean + dbus_client_end_session (GsmClient *client, + GsmClientEndSessionFlag flags, + GError **error) + { + GsmDBusClient *dbus_client = (GsmDBusClient *) client; + + gsm_exported_client_private_emit_end_session (dbus_client->priv->skeleton, flags); + return TRUE; + } + + static gboolean + dbus_client_cancel_end_session (GsmClient *client, + GError **error) + { + GsmDBusClient *dbus_client = (GsmDBusClient *) client; + gsm_exported_client_private_emit_cancel_end_session (dbus_client->priv->skeleton); + return TRUE; + } + + static void + gsm_dbus_client_class_init (GsmDBusClientClass *klass) + { + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GsmClientClass *client_class = GSM_CLIENT_CLASS (klass); + + object_class->finalize = gsm_dbus_client_finalize; + object_class->constructor = gsm_dbus_client_constructor; + object_class->get_property = gsm_dbus_client_get_property; + object_class->set_property = gsm_dbus_client_set_property; + ++ client_class->impl_request_save = dbus_client_request_save; + client_class->impl_save = dbus_client_save; + client_class->impl_stop = dbus_client_stop; + client_class->impl_query_end_session = dbus_client_query_end_session; + client_class->impl_end_session = dbus_client_end_session; + client_class->impl_cancel_end_session = dbus_client_cancel_end_session; + client_class->impl_get_app_name = dbus_client_get_app_name; + client_class->impl_get_restart_style_hint = dbus_client_get_restart_style_hint; + client_class->impl_get_unix_process_id = dbus_client_get_unix_process_id; + + g_object_class_install_property (object_class, + PROP_BUS_NAME, + g_param_spec_string ("bus-name", + "bus-name", + "bus-name", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_type_class_add_private (klass, sizeof (GsmDBusClientPrivate)); + } + + GsmClient * + gsm_dbus_client_new (const char *startup_id, + const char *bus_name) + { + GsmDBusClient *client; + + client = g_object_new (GSM_TYPE_DBUS_CLIENT, + "startup-id", startup_id, + "bus-name", bus_name, + NULL); +diff --git a/gnome-session/gsm-manager.c b/gnome-session/gsm-manager.c +index ce2ffbcf..711961d6 100644 +--- a/gnome-session/gsm-manager.c ++++ b/gnome-session/gsm-manager.c +@@ -54,60 +54,61 @@ + #include "gsm-dbus-client.h" + + #include "gsm-autostart-app.h" + + #include "gsm-util.h" + #include "gsm-icon-names.h" + #include "gsm-system.h" + #include "gsm-session-save.h" + #include "gsm-shell-extensions.h" + #include "gsm-fail-whale.h" + + #define GSM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSM_TYPE_MANAGER, GsmManagerPrivate)) + + /* UUIDs for log messages */ + #define GSM_MANAGER_STARTUP_SUCCEEDED_MSGID "0ce153587afa4095832d233c17a88001" + #define GSM_MANAGER_UNRECOVERABLE_FAILURE_MSGID "10dd2dc188b54a5e98970f56499d1f73" + + #define GSM_MANAGER_DBUS_PATH "/org/gnome/SessionManager" + #define GSM_MANAGER_DBUS_NAME "org.gnome.SessionManager" + #define GSM_MANAGER_DBUS_IFACE "org.gnome.SessionManager" + + /* Probably about the longest amount of time someone could reasonably + * want to wait, at least for something happening more than once. + * We can get deployed on very slow media though like CDROM devices, + * often with complex stacking/compressing filesystems on top, which + * is not a recipie for speed. Particularly now that we throw up + * a fail whale if required components don't show up quickly enough, + * let's make this fairly long. + */ + #define GSM_MANAGER_PHASE_TIMEOUT 90 /* seconds */ ++#define GSM_MANAGER_SAVE_SESSION_TIMEOUT 2 + + #define GDM_FLEXISERVER_COMMAND "gdmflexiserver" + #define GDM_FLEXISERVER_ARGS "--startnew Standard" + + #define SESSION_SCHEMA "org.gnome.desktop.session" + #define KEY_IDLE_DELAY "idle-delay" + #define KEY_SESSION_NAME "session-name" + + #define GSM_MANAGER_SCHEMA "org.gnome.SessionManager" + #define KEY_AUTOSAVE "auto-save-session" + #define KEY_AUTOSAVE_ONE_SHOT "auto-save-session-one-shot" + #define KEY_LOGOUT_PROMPT "logout-prompt" + #define KEY_SHOW_FALLBACK_WARNING "show-fallback-warning" + + #define SCREENSAVER_SCHEMA "org.gnome.desktop.screensaver" + #define KEY_SLEEP_LOCK "lock-enabled" + + #define LOCKDOWN_SCHEMA "org.gnome.desktop.lockdown" + #define KEY_DISABLE_LOG_OUT "disable-log-out" + #define KEY_DISABLE_USER_SWITCHING "disable-user-switching" + + static void app_registered (GsmApp *app, GParamSpec *spec, GsmManager *manager); + + typedef enum + { + GSM_MANAGER_LOGOUT_NONE, + GSM_MANAGER_LOGOUT_LOGOUT, + GSM_MANAGER_LOGOUT_REBOOT, + GSM_MANAGER_LOGOUT_REBOOT_INTERACT, + GSM_MANAGER_LOGOUT_SHUTDOWN, +@@ -1134,60 +1135,123 @@ end_session_or_show_shell_dialog (GsmManager *manager) + end_phase (manager); + } + break; + + case GSM_MANAGER_LOGOUT_MODE_FORCE: + end_phase (manager); + break; + default: + g_assert_not_reached (); + break; + } + + } + + static void + query_end_session_complete (GsmManager *manager) + { + + g_debug ("GsmManager: query end session complete"); + + /* Remove the timeout since this can be called from outside the timer + * and we don't want to have it called twice */ + if (manager->priv->query_timeout_id > 0) { + g_source_remove (manager->priv->query_timeout_id); + manager->priv->query_timeout_id = 0; + } + + end_session_or_show_shell_dialog (manager); + } + ++static gboolean ++_client_request_save (GsmClient *client, ++ ClientEndSessionData *data) ++{ ++ gboolean ret; ++ GError *error; ++ ++ error = NULL; ++ ret = gsm_client_request_save (client, data->flags, &error); ++ if (ret) { ++ g_debug ("GsmManager: adding client to query clients: %s", gsm_client_peek_id (client)); ++ data->manager->priv->query_clients = g_slist_prepend (data->manager->priv->query_clients, ++ client); ++ } else if (error) { ++ g_debug ("GsmManager: unable to query client: %s", error->message); ++ g_error_free (error); ++ } ++ ++ return FALSE; ++} ++ ++static gboolean ++_client_request_save_helper (const char *id, ++ GsmClient *client, ++ ClientEndSessionData *data) ++{ ++ return _client_request_save (client, data); ++} ++ ++static void ++query_save_session_complete (GsmManager *manager) ++{ ++ GError *error = NULL; ++ ++ if (g_slist_length (manager->priv->next_query_clients) > 0) { ++ ClientEndSessionData data; ++ ++ data.manager = manager; ++ data.flags = GSM_CLIENT_END_SESSION_FLAG_LAST; ++ ++ g_slist_foreach (manager->priv->next_query_clients, ++ (GFunc)_client_request_save, ++ &data); ++ ++ g_slist_free (manager->priv->next_query_clients); ++ manager->priv->next_query_clients = NULL; ++ ++ return; ++ } ++ ++ if (manager->priv->query_timeout_id > 0) { ++ g_source_remove (manager->priv->query_timeout_id); ++ manager->priv->query_timeout_id = 0; ++ } ++ ++ gsm_session_save (manager->priv->clients, &error); ++ ++ if (error) { ++ g_warning ("Error saving session: %s", error->message); ++ g_error_free (error); ++ } ++} ++ + static guint32 + generate_cookie (void) + { + guint32 cookie; + + cookie = (guint32)g_random_int_range (1, G_MAXINT32); + + return cookie; + } + + static guint32 + _generate_unique_cookie (GsmManager *manager) + { + guint32 cookie; + + do { + cookie = generate_cookie (); + } while (gsm_store_find (manager->priv->inhibitors, (GsmStoreFunc)_find_by_cookie, &cookie) != NULL); + + return cookie; + } + + static gboolean + _on_query_end_session_timeout (GsmManager *manager) + { + GSList *l; + + manager->priv->query_timeout_id = 0; + + g_debug ("GsmManager: query end session timed out"); +@@ -1214,60 +1278,75 @@ _on_query_end_session_timeout (GsmManager *manager) + bus_name = NULL; + } + + app_id = g_strdup (gsm_client_peek_app_id (l->data)); + if (IS_STRING_EMPTY (app_id)) { + /* XSMP clients don't give us an app id unless we start them */ + g_free (app_id); + app_id = gsm_client_get_app_name (l->data); + } + + cookie = _generate_unique_cookie (manager); + inhibitor = gsm_inhibitor_new_for_client (gsm_client_peek_id (l->data), + app_id, + GSM_INHIBITOR_FLAG_LOGOUT, + _("Not responding"), + bus_name, + cookie); + g_free (app_id); + gsm_store_add (manager->priv->inhibitors, gsm_inhibitor_peek_id (inhibitor), G_OBJECT (inhibitor)); + g_object_unref (inhibitor); + } + + g_slist_free (manager->priv->query_clients); + manager->priv->query_clients = NULL; + + query_end_session_complete (manager); + + return FALSE; + } + ++static gboolean ++_on_query_save_session_timeout (GsmManager *manager) ++{ ++ manager->priv->query_timeout_id = 0; ++ ++ g_debug ("GsmManager: query to save session timed out"); ++ ++ g_slist_free (manager->priv->query_clients); ++ manager->priv->query_clients = NULL; ++ ++ query_save_session_complete (manager); ++ ++ return FALSE; ++} ++ + static void + do_phase_query_end_session (GsmManager *manager) + { + ClientEndSessionData data; + + data.manager = manager; + data.flags = 0; + + if (manager->priv->logout_mode == GSM_MANAGER_LOGOUT_MODE_FORCE) { + data.flags |= GSM_CLIENT_END_SESSION_FLAG_FORCEFUL; + } + /* We only query if an app is ready to log out, so we don't use + * GSM_CLIENT_END_SESSION_FLAG_SAVE here. + */ + + debug_clients (manager); + g_debug ("GsmManager: sending query-end-session to clients (logout mode: %s)", + manager->priv->logout_mode == GSM_MANAGER_LOGOUT_MODE_NORMAL? "normal" : + manager->priv->logout_mode == GSM_MANAGER_LOGOUT_MODE_FORCE? "forceful": + "no confirmation"); + gsm_store_foreach (manager->priv->clients, + (GsmStoreFunc)_client_query_end_session, + &data); + + /* This phase doesn't time out unless logout is forced. Typically, this + * separate timer is only used to show UI. */ + manager->priv->query_timeout_id = g_timeout_add_seconds (1, (GSourceFunc)_on_query_end_session_timeout, manager); + } + + static void +@@ -1810,67 +1889,86 @@ maybe_save_session (GsmManager *manager) + return; + + /* We only allow session saving when session is running or when + * logging out */ + if (manager->priv->phase != GSM_MANAGER_PHASE_RUNNING && + manager->priv->phase != GSM_MANAGER_PHASE_END_SESSION) { + return; + } + + if (!auto_save_is_enabled (manager)) { + return; + } + + error = NULL; + gsm_session_save (manager->priv->clients, &error); + + if (error) { + g_warning ("Error saving session: %s", error->message); + g_error_free (error); + } + } + + static void + _handle_client_end_session_response (GsmManager *manager, + GsmClient *client, + gboolean is_ok, + gboolean do_last, + gboolean cancel, + const char *reason) + { +- /* just ignore if received outside of shutdown */ +- if (manager->priv->phase < GSM_MANAGER_PHASE_QUERY_END_SESSION) { ++ /* just ignore if we are not yet running */ ++ if (manager->priv->phase < GSM_MANAGER_PHASE_RUNNING) { + return; + } + + g_debug ("GsmManager: Response from end session request: is-ok=%d do-last=%d cancel=%d reason=%s", is_ok, do_last, cancel, reason ? reason :""); + ++ if (manager->priv->phase == GSM_MANAGER_PHASE_RUNNING) { ++ /* Ignore responses when no requests were sent */ ++ if (manager->priv->query_clients == NULL) { ++ return; ++ } ++ ++ manager->priv->query_clients = g_slist_remove (manager->priv->query_clients, client); ++ ++ if (do_last) { ++ manager->priv->next_query_clients = g_slist_prepend (manager->priv->next_query_clients, ++ client); ++ } ++ ++ if (manager->priv->query_clients == NULL) { ++ query_save_session_complete (manager); ++ } ++ return; ++ } ++ + if (cancel) { + cancel_end_session (manager); + return; + } + + manager->priv->query_clients = g_slist_remove (manager->priv->query_clients, client); + + if (! is_ok && manager->priv->logout_mode != GSM_MANAGER_LOGOUT_MODE_FORCE) { + guint cookie; + GsmInhibitor *inhibitor; + char *app_id; + const char *bus_name; + + /* FIXME: do we support updating the reason? */ + + /* Create JIT inhibit */ + if (GSM_IS_DBUS_CLIENT (client)) { + bus_name = gsm_dbus_client_get_bus_name (GSM_DBUS_CLIENT (client)); + } else { + bus_name = NULL; + } + + app_id = g_strdup (gsm_client_peek_app_id (client)); + if (IS_STRING_EMPTY (app_id)) { + /* XSMP clients don't give us an app id unless we start them */ + g_free (app_id); + app_id = gsm_client_get_app_name (client); + } + + cookie = _generate_unique_cookie (manager); +@@ -1931,84 +2029,97 @@ on_client_end_session_response (GsmClient *client, + client, + is_ok, + do_last, + cancel, + reason); + } + + static void + on_xsmp_client_logout_request (GsmXSMPClient *client, + gboolean show_dialog, + GsmManager *manager) + { + GError *error; + int logout_mode; + + if (show_dialog) { + logout_mode = GSM_MANAGER_LOGOUT_MODE_NORMAL; + } else { + logout_mode = GSM_MANAGER_LOGOUT_MODE_NO_CONFIRMATION; + } + + error = NULL; + gsm_manager_logout (manager, logout_mode, &error); + if (error != NULL) { + g_warning ("Unable to logout: %s", error->message); + g_error_free (error); + } + } + + static void ++on_xsmp_client_save_request (GsmXSMPClient *client, ++ gboolean show_dialog, ++ GsmManager *manager) ++{ ++ g_debug ("GsmManager: save_request"); ++ gsm_manager_save_session (manager, NULL); ++} ++ ++static void + on_store_client_added (GsmStore *store, + const char *id, + GsmManager *manager) + { + GsmClient *client; + + g_debug ("GsmManager: Client added: %s", id); + + client = (GsmClient *)gsm_store_lookup (store, id); + + /* a bit hacky */ + if (GSM_IS_XSMP_CLIENT (client)) { + g_signal_connect (client, + "register-request", + G_CALLBACK (on_xsmp_client_register_request), + manager); + g_signal_connect (client, + "register-confirmed", + G_CALLBACK (on_xsmp_client_register_confirmed), + manager); + g_signal_connect (client, + "logout-request", + G_CALLBACK (on_xsmp_client_logout_request), + manager); ++ g_signal_connect (client, ++ "save-request", ++ G_CALLBACK (on_xsmp_client_save_request), ++ manager); + } + + g_signal_connect (client, + "end-session-response", + G_CALLBACK (on_client_end_session_response), + manager); + + gsm_exported_manager_emit_client_added (manager->priv->skeleton, id); + /* FIXME: disconnect signal handler */ + } + + static void + on_store_client_removed (GsmStore *store, + const char *id, + GsmManager *manager) + { + g_debug ("GsmManager: Client removed: %s", id); + + gsm_exported_manager_emit_client_removed (manager->priv->skeleton, id); + } + + static void + gsm_manager_set_client_store (GsmManager *manager, + GsmStore *store) + { + g_return_if_fail (GSM_IS_MANAGER (manager)); + + if (store != NULL) { + g_object_ref (store); + } +@@ -2588,60 +2699,95 @@ gsm_manager_initialization_error (GsmExportedManager *skeleton, + GsmManager *manager) + { + if (manager->priv->phase != GSM_MANAGER_PHASE_INITIALIZATION) { + g_dbus_method_invocation_return_error (invocation, + GSM_MANAGER_ERROR, + GSM_MANAGER_ERROR_NOT_IN_INITIALIZATION, + "InitializationError interface is only available during the Initialization phase"); + return TRUE; + } + + gsm_util_init_error (fatal, "%s", message); + gsm_exported_manager_complete_initialization_error (skeleton, invocation); + + return TRUE; + } + + static void + user_logout (GsmManager *manager, + GsmManagerLogoutMode mode) + { + if (manager->priv->phase >= GSM_MANAGER_PHASE_QUERY_END_SESSION) { + manager->priv->logout_mode = mode; + end_session_or_show_shell_dialog (manager); + return; + } + + request_logout (manager, mode); + } + + gboolean ++gsm_manager_save_session (GsmManager *manager, ++ GError **error) ++{ ++ ClientEndSessionData data; ++ ++ g_debug ("GsmManager: SaveSession called"); ++ ++ g_return_val_if_fail (GSM_IS_MANAGER (manager), FALSE); ++ ++ if (manager->priv->phase != GSM_MANAGER_PHASE_RUNNING) { ++ g_set_error (error, ++ GSM_MANAGER_ERROR, ++ GSM_MANAGER_ERROR_NOT_IN_RUNNING, ++ "SaveSession interface is only available during the Running phase"); ++ return FALSE; ++ } ++ ++ data.manager = manager; ++ data.flags = 0; ++ gsm_store_foreach (manager->priv->clients, ++ (GsmStoreFunc)_client_request_save_helper, ++ &data); ++ ++ if (manager->priv->query_clients) { ++ manager->priv->query_timeout_id = g_timeout_add_seconds (GSM_MANAGER_SAVE_SESSION_TIMEOUT, ++ (GSourceFunc)_on_query_save_session_timeout, ++ manager); ++ return TRUE; ++ } else { ++ g_debug ("GsmManager: Nothing to save"); ++ return FALSE; ++ } ++} ++ ++gboolean + gsm_manager_logout (GsmManager *manager, + guint logout_mode, + GError **error) + { + if (manager->priv->phase < GSM_MANAGER_PHASE_RUNNING) { + g_set_error (error, + GSM_MANAGER_ERROR, + GSM_MANAGER_ERROR_NOT_IN_RUNNING, + "Logout interface is only available after the Running phase starts"); + return FALSE; + } + + if (_log_out_is_locked_down (manager)) { + g_set_error (error, + GSM_MANAGER_ERROR, + GSM_MANAGER_ERROR_LOCKED_DOWN, + "Logout has been locked down"); + return FALSE; + } + + switch (logout_mode) { + case GSM_MANAGER_LOGOUT_MODE_NORMAL: + case GSM_MANAGER_LOGOUT_MODE_NO_CONFIRMATION: + case GSM_MANAGER_LOGOUT_MODE_FORCE: + user_logout (manager, logout_mode); + break; + + default: + g_debug ("Unknown logout mode option"); + +diff --git a/gnome-session/gsm-manager.h b/gnome-session/gsm-manager.h +index bc440cb0..4d14aa34 100644 +--- a/gnome-session/gsm-manager.h ++++ b/gnome-session/gsm-manager.h +@@ -96,40 +96,43 @@ GQuark gsm_manager_error_quark (void); + GType gsm_manager_get_type (void); + + GsmManager * gsm_manager_new (GsmStore *client_store, + gboolean failsafe); + GsmManager * gsm_manager_get (void); + + gboolean gsm_manager_get_failsafe (GsmManager *manager); + + gboolean gsm_manager_add_autostart_app (GsmManager *manager, + const char *path, + const char *provides); + gboolean gsm_manager_add_required_app (GsmManager *manager, + const char *path, + const char *provides); + gboolean gsm_manager_add_autostart_apps_from_dir (GsmManager *manager, + const char *path); + gboolean gsm_manager_add_legacy_session_apps (GsmManager *manager, + const char *path); + + void gsm_manager_start (GsmManager *manager); + + const char * _gsm_manager_get_default_session (GsmManager *manager); + + void _gsm_manager_set_active_session (GsmManager *manager, + const char *session_name, + gboolean is_fallback); + + void _gsm_manager_set_renderer (GsmManager *manager, + const char *renderer); + ++gboolean gsm_manager_save_session (GsmManager *manager, ++ GError **error); ++ + gboolean gsm_manager_logout (GsmManager *manager, + guint logout_mode, + GError **error); + + gboolean gsm_manager_set_phase (GsmManager *manager, + GsmManagerPhase phase); + + G_END_DECLS + + #endif /* __GSM_MANAGER_H */ +diff --git a/gnome-session/gsm-xsmp-client.c b/gnome-session/gsm-xsmp-client.c +index 9358f94c..2846d9b3 100644 +--- a/gnome-session/gsm-xsmp-client.c ++++ b/gnome-session/gsm-xsmp-client.c +@@ -39,60 +39,61 @@ + #define GsmDesktopFile "_GSM_DesktopFile" + + #define GSM_XSMP_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSM_TYPE_XSMP_CLIENT, GsmXSMPClientPrivate)) + + struct GsmXSMPClientPrivate + { + + SmsConn conn; + IceConn ice_connection; + + guint watch_id; + + char *description; + GPtrArray *props; + + /* SaveYourself state */ + int current_save_yourself; + int next_save_yourself; + guint next_save_yourself_allow_interact : 1; + }; + + enum { + PROP_0, + PROP_ICE_CONNECTION + }; + + enum { + REGISTER_REQUEST, + REGISTER_CONFIRMED, + LOGOUT_REQUEST, ++ SAVE_REQUEST, + LAST_SIGNAL + }; + + static guint signals[LAST_SIGNAL] = { 0 }; + + G_DEFINE_TYPE (GsmXSMPClient, gsm_xsmp_client, GSM_TYPE_CLIENT) + + static gboolean + client_iochannel_watch (GIOChannel *channel, + GIOCondition condition, + GsmXSMPClient *client) + { + gboolean keep_going; + + g_object_ref (client); + switch (IceProcessMessages (client->priv->ice_connection, NULL, NULL)) { + case IceProcessMessagesSuccess: + keep_going = TRUE; + break; + + case IceProcessMessagesIOError: + g_debug ("GsmXSMPClient: IceProcessMessagesIOError on '%s'", client->priv->description); + gsm_client_set_status (GSM_CLIENT (client), GSM_CLIENT_FAILED); + /* Emitting "disconnected" will eventually cause + * IceCloseConnection() to be called. + */ + gsm_client_disconnected (GSM_CLIENT (client)); + keep_going = FALSE; + break; + +@@ -472,60 +473,84 @@ xsmp_interact (GsmClient *client) + + SmsInteract (xsmp->priv->conn); + } + + static gboolean + xsmp_cancel_end_session (GsmClient *client, + GError **error) + { + GsmXSMPClient *xsmp = (GsmXSMPClient *) client; + + g_debug ("GsmXSMPClient: xsmp_cancel_end_session ('%s')", xsmp->priv->description); + + if (xsmp->priv->conn == NULL) { + g_set_error (error, + GSM_CLIENT_ERROR, + GSM_CLIENT_ERROR_NOT_REGISTERED, + "Client is not registered"); + return FALSE; + } + + SmsShutdownCancelled (xsmp->priv->conn); + + /* reset the state */ + xsmp->priv->current_save_yourself = -1; + xsmp->priv->next_save_yourself = -1; + xsmp->priv->next_save_yourself_allow_interact = FALSE; + + return TRUE; + } + ++static gboolean ++xsmp_request_save (GsmClient *client, ++ guint flags, ++ GError **error) ++{ ++ GsmXSMPClient *xsmp = (GsmXSMPClient *) client; ++ ++ g_debug ("GsmXSMPClient: xsmp_request_save ('%s')", xsmp->priv->description); ++ ++ if (xsmp->priv->conn == NULL) { ++ g_set_error (error, ++ GSM_CLIENT_ERROR, ++ GSM_CLIENT_ERROR_NOT_REGISTERED, ++ "Client is not registered"); ++ return FALSE; ++ } ++ ++ if (flags & GSM_CLIENT_END_SESSION_FLAG_LAST) ++ xsmp_save_yourself_phase2 (client); ++ else ++ do_save_yourself (xsmp, SmSaveLocal, FALSE); ++ ++ return TRUE; ++} + static char * + get_desktop_file_path (GsmXSMPClient *client) + { + SmProp *prop; + char *desktop_file_path = NULL; + const char *program_name; + + /* XSMP clients using eggsmclient defines a special property + * pointing to their respective desktop entry file */ + prop = find_property (client, GsmDesktopFile, NULL); + + if (prop) { + GFile *file = g_file_new_for_uri (prop->vals[0].value); + desktop_file_path = g_file_get_path (file); + g_object_unref (file); + goto out; + } + + /* If we can't get desktop file from GsmDesktopFile then we + * try to find the desktop file from its program name */ + prop = find_property (client, SmProgram, NULL); + + if (!prop) { + goto out; + } + + program_name = prop->vals[0].value; + desktop_file_path = + gsm_util_find_desktop_file_for_app_name (program_name, + TRUE, FALSE); +@@ -955,100 +980,112 @@ xsmp_get_unix_process_id (GsmClient *client) + gboolean res; + + g_debug ("GsmXSMPClient: getting pid"); + + prop = find_property (GSM_XSMP_CLIENT (client), SmProcessID, NULL); + + if (!prop || strcmp (prop->type, SmARRAY8) != 0) { + return 0; + } + + pid = 0; + res = _parse_value_as_uint ((char *)prop->vals[0].value, &pid); + if (! res) { + pid = 0; + } + + return pid; + } + + static void + gsm_xsmp_client_class_init (GsmXSMPClientClass *klass) + { + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GsmClientClass *client_class = GSM_CLIENT_CLASS (klass); + + object_class->finalize = gsm_xsmp_client_finalize; + object_class->constructor = gsm_xsmp_client_constructor; + object_class->get_property = gsm_xsmp_client_get_property; + object_class->set_property = gsm_xsmp_client_set_property; + ++ client_class->impl_request_save = xsmp_request_save; + client_class->impl_save = xsmp_save; + client_class->impl_stop = xsmp_stop; + client_class->impl_query_end_session = xsmp_query_end_session; + client_class->impl_end_session = xsmp_end_session; + client_class->impl_cancel_end_session = xsmp_cancel_end_session; + client_class->impl_get_app_name = xsmp_get_app_name; + client_class->impl_get_restart_style_hint = xsmp_get_restart_style_hint; + client_class->impl_get_unix_process_id = xsmp_get_unix_process_id; + + signals[REGISTER_REQUEST] = + g_signal_new ("register-request", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GsmXSMPClientClass, register_request), + _boolean_handled_accumulator, + NULL, + NULL, + G_TYPE_BOOLEAN, + 1, G_TYPE_POINTER); + signals[REGISTER_CONFIRMED] = + g_signal_new ("register-confirmed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GsmXSMPClientClass, register_confirmed), + NULL, + NULL, + NULL, + G_TYPE_NONE, + 1, G_TYPE_POINTER); + signals[LOGOUT_REQUEST] = + g_signal_new ("logout-request", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GsmXSMPClientClass, logout_request), + NULL, + NULL, + NULL, + G_TYPE_NONE, + 1, G_TYPE_BOOLEAN); + ++ signals[SAVE_REQUEST] = ++ g_signal_new ("save-request", ++ G_OBJECT_CLASS_TYPE (object_class), ++ G_SIGNAL_RUN_LAST, ++ G_STRUCT_OFFSET (GsmXSMPClientClass, save_request), ++ NULL, ++ NULL, ++ g_cclosure_marshal_VOID__BOOLEAN, ++ G_TYPE_NONE, ++ 1, G_TYPE_BOOLEAN); ++ + g_object_class_install_property (object_class, + PROP_ICE_CONNECTION, + g_param_spec_pointer ("ice-connection", + "ice-connection", + "ice-connection", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_type_class_add_private (klass, sizeof (GsmXSMPClientPrivate)); + } + + GsmClient * + gsm_xsmp_client_new (IceConn ice_conn) + { + GsmXSMPClient *xsmp; + + xsmp = g_object_new (GSM_TYPE_XSMP_CLIENT, + "ice-connection", ice_conn, + NULL); + + return GSM_CLIENT (xsmp); + } + + static Status + register_client_callback (SmsConn conn, + SmPointer manager_data, + char *previous_id) + { + GsmXSMPClient *client = manager_data; + gboolean handled; + char *id; +diff --git a/gnome-session/gsm-xsmp-client.h b/gnome-session/gsm-xsmp-client.h +index 1bb27975..6b95c51b 100644 +--- a/gnome-session/gsm-xsmp-client.h ++++ b/gnome-session/gsm-xsmp-client.h +@@ -27,61 +27,62 @@ G_BEGIN_DECLS + + #define GSM_TYPE_XSMP_CLIENT (gsm_xsmp_client_get_type ()) + #define GSM_XSMP_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSM_TYPE_XSMP_CLIENT, GsmXSMPClient)) + #define GSM_XSMP_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSM_TYPE_XSMP_CLIENT, GsmXSMPClientClass)) + #define GSM_IS_XSMP_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSM_TYPE_XSMP_CLIENT)) + #define GSM_IS_XSMP_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSM_TYPE_XSMP_CLIENT)) + #define GSM_XSMP_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSM_TYPE_XSMP_CLIENT, GsmXSMPClientClass)) + + typedef struct _GsmXSMPClient GsmXSMPClient; + typedef struct _GsmXSMPClientClass GsmXSMPClientClass; + + typedef struct GsmXSMPClientPrivate GsmXSMPClientPrivate; + + struct _GsmXSMPClient + { + GsmClient parent; + GsmXSMPClientPrivate *priv; + }; + + struct _GsmXSMPClientClass + { + GsmClientClass parent_class; + + /* signals */ + gboolean (*register_request) (GsmXSMPClient *client, + char **client_id); + void (*register_confirmed) (GsmXSMPClient *client, + const char *client_id); + gboolean (*logout_request) (GsmXSMPClient *client, + gboolean prompt); +- ++ gboolean (*save_request) (GsmXSMPClient *client, ++ gboolean prompt); + + void (*saved_state) (GsmXSMPClient *client); + + void (*request_phase2) (GsmXSMPClient *client); + + void (*request_interaction) (GsmXSMPClient *client); + void (*interaction_done) (GsmXSMPClient *client, + gboolean cancel_shutdown); + + void (*save_yourself_done) (GsmXSMPClient *client); + + }; + + GType gsm_xsmp_client_get_type (void) G_GNUC_CONST; + + GsmClient *gsm_xsmp_client_new (IceConn ice_conn); + + void gsm_xsmp_client_connect (GsmXSMPClient *client, + SmsConn conn, + unsigned long *mask_ret, + SmsCallbacks *callbacks_ret); + + void gsm_xsmp_client_save_state (GsmXSMPClient *client); + void gsm_xsmp_client_save_yourself (GsmXSMPClient *client, + gboolean save_state); + void gsm_xsmp_client_save_yourself_phase2 (GsmXSMPClient *client); + void gsm_xsmp_client_interact (GsmXSMPClient *client); + void gsm_xsmp_client_shutdown_cancelled (GsmXSMPClient *client); + + G_END_DECLS +diff --git a/gnome-session/org.gnome.SessionManager.xml b/gnome-session/org.gnome.SessionManager.xml +index 580ec356..29eb0990 100644 +--- a/gnome-session/org.gnome.SessionManager.xml ++++ b/gnome-session/org.gnome.SessionManager.xml +@@ -255,60 +255,68 @@ + + + + True if condition is handled, false otherwise + + + + + Allows the caller to determine whether the session manager is + handling changes to the specified autostart condition. + + + + + + + + Request a shutdown dialog. + + + + + + + + Request a reboot dialog. + + + + ++ ++ ++ ++ Request to save session ++ ++ ++ ++ + + + + True if shutdown is available to the user, false otherwise + + + + + Allows the caller to determine whether or not it's okay to show + a shutdown option in the UI + + + + + + + + The type of logout that is being requested + + + + + Request a logout dialog + + Allowed values for the mode parameter are: + + + 0 + Normal. + +-- +2.12.0 + diff --git a/SOURCES/0009-Revert-Allow-saved-session-to-be-a-symlink.patch b/SOURCES/0009-Revert-Allow-saved-session-to-be-a-symlink.patch new file mode 100644 index 0000000..72da3d4 --- /dev/null +++ b/SOURCES/0009-Revert-Allow-saved-session-to-be-a-symlink.patch @@ -0,0 +1,272 @@ +From 43ef133022ec1c25d1626a58fd8c3c8349d5d041 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 20 Dec 2013 11:22:07 -0500 +Subject: [PATCH 09/19] Revert "Allow saved-session to be a symlink" + +This reverts commit b733c2ee519b65c3c4eab0d0e93056412f995f3f. +--- + gnome-session/gsm-session-save.c | 32 ++++++++++++++++++++++++++++---- + gnome-session/gsm-util.c | 6 ++++++ + 2 files changed, 34 insertions(+), 4 deletions(-) + +diff --git a/gnome-session/gsm-session-save.c b/gnome-session/gsm-session-save.c +index d6000e09..eebc5ff1 100644 +--- a/gnome-session/gsm-session-save.c ++++ b/gnome-session/gsm-session-save.c +@@ -9,61 +9,61 @@ + * + * 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, see . + */ + + #include + + #include + #include + #include + + #include "gsm-util.h" + #include "gsm-autostart-app.h" + #include "gsm-client.h" + + #include "gsm-session-save.h" + + #define GSM_MANAGER_SCHEMA "org.gnome.SessionManager" + #define KEY_AUTOSAVE_ONE_SHOT "auto-save-session-one-shot" + + + static gboolean gsm_session_clear_saved_session (const char *directory, + GHashTable *discard_hash); + + typedef struct { +- const char *dir; ++ char *dir; + GHashTable *discard_hash; + GError **error; + } SessionSaveData; + + static gboolean + save_one_client (char *id, + GObject *object, + SessionSaveData *data) + { + GsmClient *client; + GKeyFile *keyfile; + const char *app_id; + char *path = NULL; + char *filename = NULL; + char *contents = NULL; + gsize length = 0; + char *discard_exec; + GError *local_error; + + client = GSM_CLIENT (object); + + local_error = NULL; + + keyfile = gsm_client_save (client, &local_error); + + if (keyfile == NULL || local_error) { + goto out; + } + + contents = g_key_file_to_data (keyfile, &length, &local_error); +@@ -112,89 +112,113 @@ save_one_client (char *id, + } + + g_debug ("GsmSessionSave: saved client %s to %s", id, filename); + + out: + if (keyfile != NULL) { + g_key_file_free (keyfile); + } + + g_free (contents); + g_free (filename); + g_free (path); + + /* in case of any error, stop saving session */ + if (local_error) { + g_propagate_error (data->error, local_error); + g_error_free (local_error); + + return TRUE; + } + + return FALSE; + } + + void + gsm_session_save (GsmStore *client_store, + GError **error) + { + GSettings *settings; + const char *save_dir; ++ char *tmp_dir; + SessionSaveData data; + + g_debug ("GsmSessionSave: Saving session"); + + /* Clear one shot key autosave in the event its set (so that it's actually + * one shot only) + */ + settings = g_settings_new (GSM_MANAGER_SCHEMA); + g_settings_set_boolean (settings, KEY_AUTOSAVE_ONE_SHOT, FALSE); + g_object_unref (settings); + + save_dir = gsm_util_get_saved_session_dir (); + if (save_dir == NULL) { + g_warning ("GsmSessionSave: cannot create saved session directory"); + return; + } + +- data.dir = save_dir; ++ tmp_dir = gsm_util_get_empty_tmp_session_dir (); ++ if (tmp_dir == NULL) { ++ g_warning ("GsmSessionSave: cannot create new saved session directory"); ++ return; ++ } ++ ++ /* save the session in a temp directory, and remember the discard ++ * commands */ ++ data.dir = tmp_dir; + data.discard_hash = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, NULL); +- /* remove old saved session */ +- gsm_session_clear_saved_session (save_dir, data.discard_hash); + data.error = error; + + gsm_store_foreach (client_store, + (GsmStoreFunc) save_one_client, + &data); + ++ if (!*error) { ++ /* remove the old saved session */ ++ gsm_session_clear_saved_session (save_dir, data.discard_hash); ++ ++ /* rename the temp session dir */ ++ if (g_file_test (save_dir, G_FILE_TEST_IS_DIR)) ++ g_rmdir (save_dir); ++ g_rename (tmp_dir, save_dir); ++ } else { ++ g_warning ("GsmSessionSave: error saving session: %s", (*error)->message); ++ /* FIXME: we should create a hash table filled with the discard ++ * commands that are in desktop files from save_dir. */ ++ gsm_session_clear_saved_session (tmp_dir, NULL); ++ g_rmdir (tmp_dir); ++ } ++ + g_hash_table_destroy (data.discard_hash); ++ g_free (tmp_dir); + } + + static gboolean + gsm_session_clear_one_client (const char *filename, + GHashTable *discard_hash) + { + gboolean result = TRUE; + GKeyFile *key_file; + char *discard_exec = NULL; + char **envp; + + g_debug ("GsmSessionSave: removing '%s' from saved session", filename); + + envp = (char **) gsm_util_listenv (); + key_file = g_key_file_new (); + if (g_key_file_load_from_file (key_file, filename, + G_KEY_FILE_NONE, NULL)) { + char **argv; + int argc; + + discard_exec = g_key_file_get_string (key_file, + G_KEY_FILE_DESKTOP_GROUP, + GSM_AUTOSTART_APP_DISCARD_KEY, + NULL); + if (!discard_exec) + goto out; + + if (discard_hash && g_hash_table_lookup (discard_hash, discard_exec)) + goto out; + +diff --git a/gnome-session/gsm-util.c b/gnome-session/gsm-util.c +index e30cf912..13f674cb 100644 +--- a/gnome-session/gsm-util.c ++++ b/gnome-session/gsm-util.c +@@ -71,63 +71,69 @@ gsm_util_find_desktop_file_for_app_name (const char *name, + g_debug ("GsmUtil: found in XDG dirs: '%s'", app_path); + } + + /* look for gnome vendor prefix */ + if (app_path == NULL) { + g_free (desktop_file); + desktop_file = g_strdup_printf ("gnome-%s.desktop", name); + + g_key_file_load_from_dirs (key_file, + desktop_file, + (const char **) app_dirs, + &app_path, + G_KEY_FILE_NONE, + NULL); + if (app_path != NULL) { + g_debug ("GsmUtil: found in XDG dirs: '%s'", app_path); + } + } + + g_free (desktop_file); + g_key_file_free (key_file); + + g_strfreev (app_dirs); + + return app_path; + } + + static gboolean + ensure_dir_exists (const char *dir) + { ++ if (g_file_test (dir, G_FILE_TEST_IS_DIR)) ++ return TRUE; ++ + if (g_mkdir_with_parents (dir, 0755) == 0) + return TRUE; + ++ if (errno == EEXIST) ++ return g_file_test (dir, G_FILE_TEST_IS_DIR); ++ + g_warning ("GsmSessionSave: Failed to create directory %s: %s", dir, strerror (errno)); + + return FALSE; + } + + gchar * + gsm_util_get_empty_tmp_session_dir (void) + { + char *tmp; + gboolean exists; + + tmp = g_build_filename (g_get_user_config_dir (), + "gnome-session", + "saved-session.new", + NULL); + + exists = ensure_dir_exists (tmp); + + if (G_UNLIKELY (!exists)) { + g_warning ("GsmSessionSave: could not create directory for saved session: %s", tmp); + g_free (tmp); + return NULL; + } else { + /* make sure it's empty */ + GDir *dir; + const char *filename; + + dir = g_dir_open (tmp, 0, NULL); + if (dir) { + while ((filename = g_dir_read_name (dir))) { +-- +2.12.0 + diff --git a/SOURCES/0010-Allow-saved-session-directory-to-be-a-symlink.patch b/SOURCES/0010-Allow-saved-session-directory-to-be-a-symlink.patch new file mode 100644 index 0000000..67457e9 --- /dev/null +++ b/SOURCES/0010-Allow-saved-session-directory-to-be-a-symlink.patch @@ -0,0 +1,191 @@ +From 6a7054d12d1177184ed20f1d2263eef476d25b8f Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 20 Dec 2013 11:22:53 -0500 +Subject: [PATCH 10/19] Allow saved-session directory to be a symlink + +This gives us the option of adding a rudimentary session +chooser later. +--- + gnome-session/gsm-session-save.c | 36 ++++++++++++++++++++++++++++++------ + gnome-session/gsm-util.c | 6 ------ + 2 files changed, 30 insertions(+), 12 deletions(-) + +diff --git a/gnome-session/gsm-session-save.c b/gnome-session/gsm-session-save.c +index eebc5ff1..66914b57 100644 +--- a/gnome-session/gsm-session-save.c ++++ b/gnome-session/gsm-session-save.c +@@ -148,67 +148,91 @@ gsm_session_save (GsmStore *client_store, + * one shot only) + */ + settings = g_settings_new (GSM_MANAGER_SCHEMA); + g_settings_set_boolean (settings, KEY_AUTOSAVE_ONE_SHOT, FALSE); + g_object_unref (settings); + + save_dir = gsm_util_get_saved_session_dir (); + if (save_dir == NULL) { + g_warning ("GsmSessionSave: cannot create saved session directory"); + return; + } + + tmp_dir = gsm_util_get_empty_tmp_session_dir (); + if (tmp_dir == NULL) { + g_warning ("GsmSessionSave: cannot create new saved session directory"); + return; + } + + /* save the session in a temp directory, and remember the discard + * commands */ + data.dir = tmp_dir; + data.discard_hash = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, NULL); + data.error = error; + + gsm_store_foreach (client_store, + (GsmStoreFunc) save_one_client, + &data); + + if (!*error) { +- /* remove the old saved session */ +- gsm_session_clear_saved_session (save_dir, data.discard_hash); ++ char *session_dir; + +- /* rename the temp session dir */ +- if (g_file_test (save_dir, G_FILE_TEST_IS_DIR)) +- g_rmdir (save_dir); +- g_rename (tmp_dir, save_dir); ++ if (g_file_test (save_dir, G_FILE_TEST_IS_SYMLINK)) ++ session_dir = g_file_read_link (save_dir, error); ++ else ++ session_dir = g_strdup (save_dir); ++ ++ if (session_dir != NULL) { ++ ++ char *absolute_session_dir; ++ ++ if (g_path_is_absolute (session_dir)) { ++ absolute_session_dir = g_strdup (session_dir); ++ } else { ++ char *parent_dir; ++ ++ parent_dir = g_path_get_dirname (save_dir); ++ absolute_session_dir = g_build_filename (parent_dir, session_dir, NULL); ++ g_free (parent_dir); ++ } ++ g_free (session_dir); ++ ++ /* remove the old saved session */ ++ gsm_session_clear_saved_session (absolute_session_dir, data.discard_hash); ++ ++ if (g_file_test (absolute_session_dir, G_FILE_TEST_IS_DIR)) ++ g_rmdir (absolute_session_dir); ++ g_rename (tmp_dir, absolute_session_dir); ++ ++ g_free (absolute_session_dir); ++ } + } else { + g_warning ("GsmSessionSave: error saving session: %s", (*error)->message); + /* FIXME: we should create a hash table filled with the discard + * commands that are in desktop files from save_dir. */ + gsm_session_clear_saved_session (tmp_dir, NULL); + g_rmdir (tmp_dir); + } + + g_hash_table_destroy (data.discard_hash); + g_free (tmp_dir); + } + + static gboolean + gsm_session_clear_one_client (const char *filename, + GHashTable *discard_hash) + { + gboolean result = TRUE; + GKeyFile *key_file; + char *discard_exec = NULL; + char **envp; + + g_debug ("GsmSessionSave: removing '%s' from saved session", filename); + + envp = (char **) gsm_util_listenv (); + key_file = g_key_file_new (); + if (g_key_file_load_from_file (key_file, filename, + G_KEY_FILE_NONE, NULL)) { + char **argv; + int argc; + +diff --git a/gnome-session/gsm-util.c b/gnome-session/gsm-util.c +index 13f674cb..e30cf912 100644 +--- a/gnome-session/gsm-util.c ++++ b/gnome-session/gsm-util.c +@@ -71,69 +71,63 @@ gsm_util_find_desktop_file_for_app_name (const char *name, + g_debug ("GsmUtil: found in XDG dirs: '%s'", app_path); + } + + /* look for gnome vendor prefix */ + if (app_path == NULL) { + g_free (desktop_file); + desktop_file = g_strdup_printf ("gnome-%s.desktop", name); + + g_key_file_load_from_dirs (key_file, + desktop_file, + (const char **) app_dirs, + &app_path, + G_KEY_FILE_NONE, + NULL); + if (app_path != NULL) { + g_debug ("GsmUtil: found in XDG dirs: '%s'", app_path); + } + } + + g_free (desktop_file); + g_key_file_free (key_file); + + g_strfreev (app_dirs); + + return app_path; + } + + static gboolean + ensure_dir_exists (const char *dir) + { +- if (g_file_test (dir, G_FILE_TEST_IS_DIR)) +- return TRUE; +- + if (g_mkdir_with_parents (dir, 0755) == 0) + return TRUE; + +- if (errno == EEXIST) +- return g_file_test (dir, G_FILE_TEST_IS_DIR); +- + g_warning ("GsmSessionSave: Failed to create directory %s: %s", dir, strerror (errno)); + + return FALSE; + } + + gchar * + gsm_util_get_empty_tmp_session_dir (void) + { + char *tmp; + gboolean exists; + + tmp = g_build_filename (g_get_user_config_dir (), + "gnome-session", + "saved-session.new", + NULL); + + exists = ensure_dir_exists (tmp); + + if (G_UNLIKELY (!exists)) { + g_warning ("GsmSessionSave: could not create directory for saved session: %s", tmp); + g_free (tmp); + return NULL; + } else { + /* make sure it's empty */ + GDir *dir; + const char *filename; + + dir = g_dir_open (tmp, 0, NULL); + if (dir) { + while ((filename = g_dir_read_name (dir))) { +-- +2.12.0 + diff --git a/SOURCES/0011-Tie-session-selector-to-properties-dialog.patch b/SOURCES/0011-Tie-session-selector-to-properties-dialog.patch new file mode 100644 index 0000000..bfa64ca --- /dev/null +++ b/SOURCES/0011-Tie-session-selector-to-properties-dialog.patch @@ -0,0 +1,1162 @@ +From 9b75d5137aea0a54d8e04f55e31d63e5fa250fc8 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 20 Dec 2013 11:28:53 -0500 +Subject: [PATCH 11/19] Tie session selector to properties dialog + +--- + capplet/gsm-properties-dialog.c | 30 +++++- + configure.ac | 3 +- + data/session-selector.ui | 2 +- + tools/Makefile.am | 1 + + tools/gnome-session-selector.c | 211 ++++++++++++++++++++++++++++++++-------- + 5 files changed, 200 insertions(+), 47 deletions(-) + +diff --git a/capplet/gsm-properties-dialog.c b/capplet/gsm-properties-dialog.c +index d2be778b..51fa5106 100644 +--- a/capplet/gsm-properties-dialog.c ++++ b/capplet/gsm-properties-dialog.c +@@ -471,88 +471,114 @@ session_saved_message (GsmPropertiesDialog *dialog, + { + GtkLabel *label; + gchar *markup; + label = GTK_LABEL (gtk_builder_get_object (dialog->priv->xml, CAPPLET_SESSION_SAVED_WIDGET_NAME)); + if (is_error) + markup = g_markup_printf_escaped ("%s", msg); + else + markup = g_markup_escape_text (msg, -1); + gtk_label_set_markup (label, markup); + g_free (markup); + } + + static void + session_saved_cb (DBusGProxy *proxy, + DBusGProxyCall *call_id, + void *user_data) + { + gboolean res; + GsmPropertiesDialog *dialog = user_data; + + res = dbus_g_proxy_end_call (proxy, call_id, NULL, G_TYPE_INVALID); + if (res) + session_saved_message (dialog, _("Your session has been saved."), FALSE); + else + session_saved_message (dialog, _("Failed to save session"), TRUE); + + g_object_unref (proxy); + } + + static void +-on_save_session_clicked (GtkWidget *widget, +- GsmPropertiesDialog *dialog) ++save_session_directly (GsmPropertiesDialog *dialog) + { + DBusGConnection *conn; + DBusGProxy *proxy; + DBusGProxyCall *call; + + conn = dbus_g_bus_get (DBUS_BUS_SESSION, NULL); + if (conn == NULL) { + session_saved_message (dialog, _("Could not connect to the session bus"), TRUE); + return; + } + + proxy = dbus_g_proxy_new_for_name (conn, GSM_SERVICE_DBUS, GSM_PATH_DBUS, GSM_INTERFACE_DBUS); + if (proxy == NULL) { + session_saved_message (dialog, _("Could not connect to the session manager"), TRUE); + return; + } + + call = dbus_g_proxy_begin_call (proxy, "SaveSession", session_saved_cb, dialog, NULL, G_TYPE_INVALID); + if (call == NULL) { + session_saved_message (dialog, _("Failed to save session"), TRUE); + g_object_unref (proxy); + return; + } + } + + static void ++save_session_from_selector (GsmPropertiesDialog *dialog, ++ const char *program_path) ++{ ++ char *command_line = g_strdup_printf ("%s --action save", program_path); ++ ++ g_spawn_command_line_sync (command_line, NULL, NULL, NULL, NULL); ++ ++ g_free (command_line); ++} ++ ++static void ++on_save_session_clicked (GtkWidget *widget, ++ GsmPropertiesDialog *dialog) ++{ ++ char *program_path; ++ ++ program_path = g_find_program_in_path ("gnome-session-selector"); ++ ++ if (program_path != NULL) { ++ save_session_from_selector (dialog, program_path); ++ g_free (program_path); ++ } else { ++ save_session_directly (dialog); ++ } ++} ++ ++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, +diff --git a/configure.ac b/configure.ac +index 04a25fc8..ccbbf970 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -21,91 +21,90 @@ LT_PREREQ([2.2.6]) + LT_INIT([dlopen disable-static]) + + GNOME_MAINTAINER_MODE_DEFINES + GNOME_COMPILE_WARNINGS([maximum]) + + AC_ARG_ENABLE(deprecation_flags, + [AS_HELP_STRING([--enable-deprecation-flags], + [use *_DISABLE_DEPRECATED flags @<:@default=no@:>@])],, + [enable_deprecation_flags=no]) + + if test "x$enable_deprecation_flags" = "xyes"; then + DISABLE_DEPRECATED_CFLAGS=$DISABLE_DEPRECATED + AC_SUBST([DISABLE_DEPRECATED_CFLAGS]) + fi + + GLIB_REQUIRED=2.46.0 + GTK3_REQUIRED=3.18.0 + DBUS_GLIB_REQUIRED=0.76 + UPOWER_REQUIRED=0.9.0 + JSON_GLIB_REQUIRED=0.10 + GNOME_DESKTOP_REQUIRED=3.18.0 + + AC_ARG_ENABLE(session-selector, AS_HELP_STRING([--enable-session-selector], + [enable building a custom session selector dialog]), + enable_session_selector=$enableval,enable_session_selector=no) + + AM_CONDITIONAL(BUILD_SESSION_SELECTOR, + [test "$enable_session_selector" = yes]) + + if test "$enable_session_selector" = yes; then +- PKG_CHECK_MODULES(SESSION_SELECTOR, gtk+-3.0 gio-2.0) ++ PKG_CHECK_MODULES(SESSION_SELECTOR, gtk+-3.0 gio-2.0 dbus-glib-1 >= $DBUS_GLIB_REQUIRED) + fi + + dnl ==================================================================== + dnl Dependency Checks + dnl ==================================================================== + + dnl Standard vertical stacks + PKG_CHECK_MODULES(GIO, gio-2.0) + PKG_CHECK_MODULES(GIOUNIX, gio-unix-2.0 >= $GLIB_REQUIRED) + PKG_CHECK_MODULES(GTK3, gtk+-3.0 >= $GTK3_REQUIRED) + + PKG_CHECK_MODULES(GNOME_SESSION, + glib-2.0 >= $GLIB_REQUIRED + gio-2.0 >= $GLIB_REQUIRED + json-glib-1.0 >= $JSON_GLIB_REQUIRED + gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED + ) + + dnl We can only support old upower + dnl https://bugzilla.gnome.org/show_bug.cgi?id=710383 + PKG_CHECK_MODULES(UPOWER, upower-glib < 0.99.0, have_old_upower=yes, have_old_upower=no) + AS_IF([test x$have_old_upower = xyes], [ + AC_DEFINE([HAVE_OLD_UPOWER], [1], [Define if we have an older upower]) + ]) + AM_CONDITIONAL(HAVE_OLD_UPOWER, test x$have_old_upower = xyes) + + PKG_CHECK_MODULES(SESSION_PROPERTIES, + glib-2.0 >= $GLIB_REQUIRED + gtk+-3.0 >= $GTK3_REQUIRED +- dbus-glib-1 >= $DBUS_GLIB_REQUIRED + ) + + PKG_CHECK_MODULES(X11, x11) + PKG_CHECK_MODULES(SM, sm) + PKG_CHECK_MODULES(ICE, ice) + PKG_CHECK_MODULES(XEXT, xext xau) + + PKG_CHECK_MODULES(GL_TEST, xcomposite gl glib-2.0 epoxy) + PKG_CHECK_MODULES(GLES_TEST, egl glesv2) + + dnl ==================================================================== + dnl Check for gconf + dnl ==================================================================== + AC_ARG_ENABLE([gconf], + AS_HELP_STRING([--enable-gconf], [Support gconf-based autostart]), + [enable_gconf=$enableval], + [enable_gconf=auto]) + + PKG_CHECK_MODULES(GCONF, gconf-2.0, [have_gconf=yes], [have_gconf=no]) + + if test x$enable_gconf = xauto ; then + enable_gconf=$have_gconf + elif test x$enable_gconf = xyes -a x$have_gconf = xno ; then + AC_MSG_ERROR([GConf support explicitly required, but gconf not found]) + fi + + if test x$enable_gconf = xyes ; then + AC_DEFINE([HAVE_GCONF], [1], [Define if we support gconf-based autostart]) + fi + +diff --git a/data/session-selector.ui b/data/session-selector.ui +index 1c55712d..1534a746 100644 +--- a/data/session-selector.ui ++++ b/data/session-selector.ui +@@ -20,61 +20,61 @@ + + + True + 0.5 + out + + + True + 12 + + + True + vertical + 6 + + + + True + other + + + + True + vertical + 0 + + + True + 0.0 + 0.5 +- Please select a custom session to run ++ Please select a custom session to use + + + True + True + 0 + + + + + + + False + True + 0 + + + + + True + vertical + 12 + + + True + 12 + + + True + True + never +diff --git a/tools/Makefile.am b/tools/Makefile.am +index d3b8bf3f..d6784d1b 100644 +--- a/tools/Makefile.am ++++ b/tools/Makefile.am +@@ -68,37 +68,38 @@ gnome_session_check_accelerated_gl_helper_CPPFLAGS = \ + + gnome_session_check_accelerated_gl_helper_LDADD = \ + $(GL_TEST_LIBS) \ + $(X11_LIBS) + + gnome_session_check_accelerated_SOURCES = \ + gnome-session-check-accelerated-common.h \ + gnome-session-check-accelerated.c + + gnome_session_check_accelerated_CPPFLAGS = \ + -DLIBEXECDIR=\""$(libexecdir)"\" \ + $(AM_CPPFLAGS) \ + $(GTK3_CFLAGS) \ + $(GL_TEST_CFLAGS) + + gnome_session_check_accelerated_LDADD = \ + $(GTK3_LIBS) \ + $(X11_LIBS) \ + $(GL_TEST_LIBS) + + if BUILD_SESSION_SELECTOR + gnome_session_selector_CPPFLAGS = \ + $(AM_CPPFLAGS) \ + $(GNOME_SESSION_CFLAGS) \ + $(DBUS_GLIB_CFLAGS) \ + -DGTKBUILDER_DIR=\""$(pkgdatadir)"\" \ + -DLOCALE_DIR=\""$(datadir)/locale"\" \ + $(DISABLE_DEPRECATED_CFLAGS) + + gnome_session_selector_LDADD = \ ++ $(DBUS_GLIB_CFLAGS) \ + $(SESSION_SELECTOR_LIBS) + + gnome_session_selector_SOURCES = \ + gnome-session-selector.c + endif + + -include $(top_srcdir)/git.mk +diff --git a/tools/gnome-session-selector.c b/tools/gnome-session-selector.c +index d7584ffb..8f37eca4 100644 +--- a/tools/gnome-session-selector.c ++++ b/tools/gnome-session-selector.c +@@ -7,126 +7,133 @@ + * 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, see . + * + * Written by: Matthias Clasen + */ + + #include "config.h" + + #include + #include + #include + #include + #include + #include + + #include + #include + #include + + #include + #include + ++#include ++#include ++ ++#define GSM_SERVICE_DBUS "org.gnome.SessionManager" ++#define GSM_PATH_DBUS "/org/gnome/SessionManager" ++#define GSM_INTERFACE_DBUS "org.gnome.SessionManager" ++ + #define GSM_MANAGER_SCHEMA "org.gnome.SessionManager" + #define KEY_AUTOSAVE_ONE_SHOT "auto-save-session-one-shot" + + static GtkBuilder *builder; + static GtkWidget *session_list; + static GtkListStore *store; + static GtkTreeModelSort *sort_model; ++static char *info_text; + + static void select_session (const char *name); ++static gboolean make_session_current (const char *name); + + static char * + get_session_path (const char *name) + { + return g_build_filename (g_get_user_config_dir (), "gnome-session", name, NULL); + } + + static char * + find_new_session_name (void) + { + char *name; + char *path; + int i; + + for (i = 1; i < 20; i++) { + name = g_strdup_printf (_("Session %d"), i); + path = get_session_path (name); + if (!g_file_test (path, G_FILE_TEST_EXISTS)) { + g_free (path); + return name; + } + g_free (path); + g_free (name); + } + + return NULL; + } + + static gboolean + is_valid_session_name (const char *name) + { + GtkTreeIter iter; + char *n; +- const char *info_text; + char *warning_text; + gboolean user_tried_dot; + gboolean user_tried_slash; + GtkWidget *info_bar; + GtkWidget *label; + + if (name[0] == 0) { + return FALSE; + } + + if (name[0] == '.') { + user_tried_dot = TRUE; + } else { + user_tried_dot = FALSE; + } + + if (strchr (name, '/') != NULL) { + user_tried_slash = TRUE; + } else { + user_tried_slash = FALSE; + } + +- info_text = _("Please select a custom session to run"); + warning_text = NULL; + if (user_tried_dot && user_tried_slash) { + warning_text = g_strdup_printf ("%s\nNote: %s", + info_text, + _("Session names are not allowed to start with ‘.’ or contain ‘/’ characters")); + } else if (user_tried_dot) { + warning_text = g_strdup_printf ("%s\nNote: %s", + info_text, + _("Session names are not allowed to start with ‘.’")); + } else if (user_tried_slash) { + warning_text = g_strdup_printf ("%s\nNote: %s", + info_text, + _("Session names are not allowed to contain ‘/’ characters")); + } + + gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter); + do { + gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, 0, &n, -1); + if (strcmp (n, name) == 0) { + char *message; + message = g_strdup_printf (_("A session named ‘%s’ already exists"), name); + warning_text = g_strdup_printf ("%s\nNote: %s", info_text, message); + g_free (message); + g_free (n); + break; + } + g_free (n); + } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter)); + + info_bar = (GtkWidget *) gtk_builder_get_object (builder, "info-bar"); +@@ -182,517 +189,637 @@ populate_session_list (GtkWidget *session_list) + default_name = NULL; + if (readlink (saved_session, last_session, PATH_MAX - 1) > 0) { + default_name = g_path_get_basename (last_session); + } + + while ((name = g_dir_read_name (dir)) != NULL) { + if (strcmp (name, "saved-session") == 0) + continue; + + gtk_list_store_insert_with_values (store, &iter, 100, 0, name, -1); + + if (g_strcmp0 (default_name, name) == 0) { + GtkTreeSelection *selection; + GtkTreeIter child_iter; + + gtk_tree_model_sort_convert_child_iter_to_iter (GTK_TREE_MODEL_SORT (sort_model), &child_iter, &iter); + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (session_list)); + gtk_tree_selection_select_iter (selection, &child_iter); + } + } + + g_free (default_name); + g_dir_close (dir); + + out: + g_free (saved_session); + g_free (path); + } + + static char * ++get_last_session (void) ++{ ++ char *saved_session; ++ char last_session[PATH_MAX] = ""; ++ char *name = NULL; ++ ++ saved_session = get_session_path ("saved-session"); ++ ++ if (readlink (saved_session, last_session, PATH_MAX - 1) > 0) { ++ name = g_path_get_basename (last_session); ++ } ++ ++ g_free (saved_session); ++ ++ return name; ++} ++ ++static char * + get_selected_session (void) + { + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkTreeIter iter; + gchar *name; + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (session_list)); + if (gtk_tree_selection_get_selected (selection, &model, &iter)) { + gtk_tree_model_get (model, &iter, 0, &name, -1); + return name; + } + + return NULL; + } + + static void + remove_session (const char *name) + { + char *path1, *path2; + char *n, *path; + const char *d; + GDir *dir; + GError *error; + + path1 = get_session_path ("saved-session"); + path2 = get_session_path (name); + + error = NULL; + n = g_file_read_link (path1, &error); + if (n == NULL) { + g_warning ("Failed to read link: %s", error->message); + g_error_free (error); + } + else if (strcmp (n, name) == 0) { + unlink (path1); + } + g_free (n); + + dir = g_dir_open (path2, 0, NULL); + while ((d = g_dir_read_name (dir)) != NULL) { + path = g_build_filename (path2, d, NULL); + unlink (path); + g_free (path); + } + g_dir_close (dir); + + remove (path2); + + g_free (path1); + g_free (path2); + } + ++static gboolean ++make_session_current (const char *name) ++{ ++ char *path1; ++ gboolean ret = TRUE; ++ ++ path1 = g_build_filename (g_get_user_config_dir (), "gnome-session", "saved-session", NULL); ++ ++ unlink (path1); ++ if (symlink (name, path1) < 0) { ++ g_warning ("Failed to make session '%s' current", name); ++ ret = FALSE; ++ } ++ ++ g_free (path1); ++ ++ return ret; ++} ++ + static void + on_remove_session_clicked (GtkButton *button, + gpointer data) + { + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkTreeIter iter; + char *name; + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (session_list)); + if (gtk_tree_selection_get_selected (selection, &model, &iter)) { + GtkTreeIter child_iter; + gtk_tree_model_get (model, &iter, 0, &name, -1); + remove_session (name); + g_free (name); + + gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (model), &child_iter, &iter); + gtk_list_store_remove (GTK_LIST_STORE (store), &child_iter); + + if (!gtk_tree_selection_get_selected (selection, NULL, NULL)) { + gtk_tree_model_get_iter_first (model, &iter); + gtk_tree_model_get (model, &iter, 0, &name, -1); + select_session (name); ++ make_session_current (name); + g_free (name); + } + } + } + + static void + begin_rename (void) + { + GtkTreePath *path; + GtkTreeViewColumn *column; + GList *cells; + + gtk_widget_grab_focus (session_list); + + gtk_tree_view_get_cursor (GTK_TREE_VIEW (session_list), + &path, &column); + + cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column)); + + if (cells != NULL) { + GtkCellRenderer *cell; + + cell = (GtkCellRenderer *) cells->data; + g_list_free (cells); + + g_object_set (cell, "editable", TRUE, NULL); + gtk_tree_view_set_cursor_on_cell (GTK_TREE_VIEW (session_list), path, + column, cell, TRUE); + } + gtk_tree_path_free (path); + } + + static void + on_rename_session_clicked (GtkButton *button, + gpointer data) + { + begin_rename (); + } + + static void + on_continue_clicked (GtkButton *button, + gpointer data) + { + char *name; + + name = get_selected_session (); + g_free (name); + + gtk_main_quit (); + } + + static void + create_session (const char *name) + { + char *path; + GtkTreeIter iter; + + path = get_session_path (name); + +- if (mkdir (path, 0755) < 0) { ++ if (g_mkdir_with_parents (path, 0755) < 0) { + g_warning ("Failed to create directory %s", path); + } + else { + char *marker; + + gtk_list_store_insert_with_values (store, &iter, 100, 0, name, -1); + + marker = g_build_filename (path, ".new-session", NULL); + creat (marker, 0600); + g_free (marker); + } + + g_free (path); + } + + static gboolean + rename_session (const char *old_name, + const char *new_name) + { + char *old_path, *new_path; + int result; + + if (g_strcmp0 (old_name, new_name) == 0) { + return TRUE; + } + + if (!is_valid_session_name (new_name)) { + return FALSE; + } + + old_path = get_session_path (old_name); + new_path = get_session_path (new_name); + + result = g_rename (old_path, new_path); + + if (result < 0) { + g_warning ("Failed to rename session from '%s' to '%s': %m", old_name, new_name); ++ } else { ++ char *last_session; ++ last_session = get_last_session (); ++ if (g_strcmp0 (old_name, last_session) == 0) { ++ make_session_current (new_name); ++ } ++ g_free (last_session); + } + + g_free (old_path); + g_free (new_path); +- + return result == 0; + } + + static gboolean +-make_session_current (const char *name) +-{ +- char *path1; +- gboolean ret = TRUE; +- +- path1 = g_build_filename (g_get_user_config_dir (), "gnome-session", "saved-session", NULL); +- +- unlink (path1); +- if (symlink (name, path1) < 0) { +- g_warning ("Failed to make session '%s' current", name); +- ret = FALSE; +- } +- +- g_free (path1); +- +- return ret; +-} +- +-static gboolean + create_and_select_session (const char *name) + { + gchar *path; + + if (name[0] == 0 || name[0] == '.' || strchr (name, '/')) { + g_warning ("Invalid session name"); + return FALSE; + } + + path = g_build_filename (g_get_user_config_dir (), "gnome-session", name, NULL); + if (!g_file_test (path, G_FILE_TEST_IS_DIR)) { +- if (mkdir (path, 0755) < 0) { ++ if (g_mkdir_with_parents (path, 0755) < 0) { + g_warning ("Failed to create directory %s", path); + g_free (path); + return FALSE; + } + } + + g_free (path); + + return make_session_current (name); + } + + static void + select_session (const char *name) + { + GtkTreeIter iter; + char *n; + +- make_session_current (name); +- + /* now select it in the list */ + gtk_tree_model_get_iter_first (GTK_TREE_MODEL (sort_model), &iter); + do { + gtk_tree_model_get (GTK_TREE_MODEL (sort_model), &iter, 0, &n, -1); + if (strcmp (n, name) == 0) { + GtkTreePath *path; + + path = gtk_tree_model_get_path (GTK_TREE_MODEL (sort_model), &iter); + gtk_tree_view_set_cursor (GTK_TREE_VIEW (session_list), path, NULL, FALSE); + gtk_tree_path_free (path); + g_free (n); + break; + } + g_free (n); + } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (sort_model), &iter)); + } + + static void +-on_new_session_clicked (GtkButton *button, +- gpointer data) ++create_session_and_begin_rename (void) + { + gchar *name; + + name = find_new_session_name (); + create_session (name); + select_session (name); + + begin_rename (); + } + + static void ++on_new_session_clicked (GtkButton *button, ++ gpointer data) ++{ ++ create_session_and_begin_rename (); ++} ++ ++static void + on_selection_changed (GtkTreeSelection *selection, + gpointer data) + { + char *name; + + name = get_selected_session (); + + if (name == NULL) { + return; + } + +- make_session_current (name); +- + g_free (name); + } + + static void + update_remove_button (void) + { + GtkWidget *button; + + button = (GtkWidget *)gtk_builder_get_object (builder, "remove-session"); + if (gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), NULL) > 1) { + gtk_widget_set_sensitive (button, TRUE); + } else { + gtk_widget_set_sensitive (button, FALSE); + } + } + + static void + on_row_edited (GtkCellRendererText *cell, + const char *path_string, + const char *new_name, + gpointer data) + { + GtkTreePath *path; + GtkTreeIter sort_iter, items_iter; + char *old_name; + gboolean was_renamed; + + path = gtk_tree_path_new_from_string (path_string); + gtk_tree_model_get_iter (GTK_TREE_MODEL (sort_model), &sort_iter, path); + + gtk_tree_model_get (GTK_TREE_MODEL (sort_model), &sort_iter, 0, &old_name, -1); + + was_renamed = rename_session (old_name, new_name); + + if (was_renamed) { + gtk_tree_model_sort_convert_iter_to_child_iter (sort_model, &items_iter, &sort_iter); + + gtk_list_store_set (store, &items_iter, 0, g_strdup (new_name), -1); + g_free (old_name); +- make_session_current (new_name); + } else { + begin_rename (); + } + + gtk_tree_path_free (path); + + g_object_set (cell, "editable", FALSE, NULL); + } + + static void + on_row_deleted (GtkTreeModel *model, + GtkTreePath *path, + gpointer data) + { + update_remove_button (); + } + + static void + on_row_inserted (GtkTreeModel *model, + GtkTreePath *path, + GtkTreeIter *iter, + gpointer data) + { + update_remove_button (); + } + + static void + on_row_activated (GtkTreeView *tree_view, + GtkTreePath *path, + GtkTreeViewColumn *column, + gpointer data) + { +- char *name; +- +- name = get_selected_session (); +- g_free (name); +- + gtk_main_quit (); + } + + static void + auto_save_next_session (void) + { + GSettings *settings; + + settings = g_settings_new (GSM_MANAGER_SCHEMA); + g_settings_set_boolean (settings, KEY_AUTOSAVE_ONE_SHOT, TRUE); + g_object_unref (settings); + } + + static void + auto_save_next_session_if_needed (void) + { + char *marker; + + marker = g_build_filename (g_get_user_config_dir (), + "gnome-session", "saved-session", + ".new-session", NULL); + + if (g_file_test (marker, G_FILE_TEST_EXISTS)) { + auto_save_next_session (); + unlink (marker); + } + g_free (marker); + } + ++static void ++save_session (void) ++{ ++ DBusGConnection *conn; ++ DBusGProxy *proxy; ++ GError *error; ++ ++ conn = dbus_g_bus_get (DBUS_BUS_SESSION, NULL); ++ if (conn == NULL) { ++ g_warning ("Could not connect to the session bus"); ++ return; ++ } ++ ++ proxy = dbus_g_proxy_new_for_name (conn, GSM_SERVICE_DBUS, GSM_PATH_DBUS, GSM_INTERFACE_DBUS); ++ if (proxy == NULL) { ++ g_warning ("Could not connect to the session manager"); ++ return; ++ } ++ ++ error = NULL; ++ if (!dbus_g_proxy_call (proxy, "SaveSession", &error, G_TYPE_INVALID, G_TYPE_INVALID)) { ++ g_warning ("Failed to save session: %s", error->message); ++ g_error_free (error); ++ return; ++ } ++ ++ g_object_unref (proxy); ++} ++ + static int + compare_sessions (GtkTreeModel *model, + GtkTreeIter *a, + GtkTreeIter *b, + gpointer data) + { + char *name_a, *name_b; + int result; + + gtk_tree_model_get (model, a, 0, &name_a, -1); + gtk_tree_model_get (model, b, 0, &name_b, -1); + + result = g_utf8_collate (name_a, name_b); + + g_free (name_a); + g_free (name_b); + + return result; + } + + static void + on_map (GtkWidget *widget, + gpointer data) + { + gdk_window_focus (gtk_widget_get_window (widget), GDK_CURRENT_TIME); + } + + int + main (int argc, char *argv[]) + { + GtkWidget *window; + GtkWidget *widget; ++ GtkWidget *label; + GtkCellRenderer *cell; + GtkTreeViewColumn *column; + GtkTreeSelection *selection; + GError *error; ++ char *selected_session; ++ ++ static char *action = NULL; ++ static char **remaining_args = NULL; ++ static GOptionEntry entries[] = { ++ {"action", '\0', 0, G_OPTION_ARG_STRING, &action, N_("What to do with session selection (save|load|print)"), NULL}, ++{ G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &remaining_args, N_("[session-name]"), NULL} ++ }; ++ ++ if (action == NULL) { ++ if (getenv ("SESSION_MANAGER") != NULL) ++ action = "print"; ++ else ++ action = "load"; ++ } + +- if (getenv ("SESSION_MANAGER") != NULL) ++ if (getenv ("SESSION_MANAGER") != NULL && strcmp (action, "load") == 0) { ++ g_warning ("Cannot load new session when session currently loaded"); + return 1; ++ } ++ ++ if (getenv ("SESSION_MANAGER") == NULL && strcmp (action, "save") == 0) { ++ g_warning ("Can only save session when session loaded"); ++ return 1; ++ } ++ ++ if (strcmp (action, "load") != 0 && strcmp (action, "save") != 0 && strcmp (action, "print") != 0) { ++ g_warning ("'%s' is not a supported action. Supported actions are load, save, and print.\n", action); ++ return 1; ++ } + +- gtk_init (&argc, &argv); +- if (argc > 1) { +- g_print ("create and select session\n"); +- if (!create_and_select_session (argv[1])) ++ error = NULL; ++ gtk_init_with_args (&argc, &argv, ++ NULL, entries, GETTEXT_PACKAGE, &error); ++ ++ if (remaining_args != NULL) { ++ if (g_strv_length (remaining_args) > 1) { ++ g_warning ("gnome-session-selector takes at most one session argument"); ++ return 1; ++ } ++ ++ if (!create_and_select_session (remaining_args[0])) + return 1; + else + return 0; + } + + builder = gtk_builder_new (); + gtk_builder_set_translation_domain (builder, GETTEXT_PACKAGE); + + error = NULL; + if (!gtk_builder_add_from_file (builder, GTKBUILDER_DIR "/" "session-selector.ui", &error)) { + g_warning ("Could not load file 'session-selector.ui': %s", error->message); + exit (1); + } + + window = (GtkWidget *) gtk_builder_get_object (builder, "main-window"); + + store = (GtkListStore *) gtk_builder_get_object (builder, "session-store"); + sort_model = (GtkTreeModelSort *) gtk_builder_get_object (builder, "sort-model"); + + gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (sort_model), + 0, compare_sessions, NULL, NULL); + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model), + 0, GTK_SORT_ASCENDING); + g_signal_connect (store, "row-deleted", G_CALLBACK (on_row_deleted), NULL); + g_signal_connect (store, "row-inserted", G_CALLBACK (on_row_inserted), NULL); + session_list = (GtkWidget *) gtk_builder_get_object (builder, "session-list"); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (session_list)); + gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); + + populate_session_list (session_list); + + cell = gtk_cell_renderer_text_new (); + g_signal_connect (cell, "edited", G_CALLBACK (on_row_edited), NULL); + + column = gtk_tree_view_column_new_with_attributes ("", cell, "text", 0, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (session_list), GTK_TREE_VIEW_COLUMN (column)); + + g_signal_connect (session_list, "row-activated", G_CALLBACK (on_row_activated), NULL); + + g_signal_connect (selection, "changed", + G_CALLBACK (on_selection_changed), NULL); + + widget = (GtkWidget *) gtk_builder_get_object (builder, "new-session"); + g_signal_connect (widget, "clicked", G_CALLBACK (on_new_session_clicked), NULL); + widget = (GtkWidget *) gtk_builder_get_object (builder, "remove-session"); + g_signal_connect (widget, "clicked", G_CALLBACK (on_remove_session_clicked), NULL); + widget = (GtkWidget *) gtk_builder_get_object (builder, "rename-session"); + g_signal_connect (widget, "clicked", G_CALLBACK (on_rename_session_clicked), NULL); + widget = (GtkWidget *) gtk_builder_get_object (builder, "continue-button"); + g_signal_connect (widget, "clicked", G_CALLBACK (on_continue_clicked), NULL); + + g_signal_connect (window, "map", G_CALLBACK (on_map), NULL); + gtk_widget_show (window); + ++ if (g_strcmp0 (action, "load") == 0) { ++ info_text = _("Please select a custom session to run"); ++ } else if (g_strcmp0 (action, "print") == 0) { ++ info_text = _("Please select a session to use"); ++ } else if (g_strcmp0 (action, "save") == 0) { ++ info_text = _("Please select a session to save to"); ++ } ++ ++ label = (GtkWidget*) gtk_builder_get_object (builder, "info-label"); ++ gtk_label_set_markup (GTK_LABEL (label), info_text); ++ ++ selected_session = get_selected_session (); ++ ++ if (selected_session == NULL) { ++ create_session_and_begin_rename (); ++ } else { ++ g_free (selected_session); ++ } ++ + gtk_main (); + +- auto_save_next_session_if_needed (); ++ selected_session = get_selected_session (); ++ ++ if (g_strcmp0 (action, "load") == 0) { ++ make_session_current (selected_session); ++ auto_save_next_session_if_needed (); ++ } else if (g_strcmp0 (action, "save") == 0) { ++ char *last_session; ++ ++ last_session = get_last_session (); ++ make_session_current (selected_session); ++ save_session (); ++ if (last_session != NULL) ++ make_session_current (last_session); ++ } else if (g_strcmp0 (action, "print") == 0) { ++ g_print ("%s\n", selected_session); ++ } ++ g_free (selected_session); + + return 0; + } +-- +2.12.0 + diff --git a/SOURCES/0012-make-save-session-stall-until-it-finishes.patch b/SOURCES/0012-make-save-session-stall-until-it-finishes.patch new file mode 100644 index 0000000..06680c0 --- /dev/null +++ b/SOURCES/0012-make-save-session-stall-until-it-finishes.patch @@ -0,0 +1,428 @@ +From 92c8574d86c70e8a595dfbfdab461c7b990d2fe1 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 20 Dec 2013 11:32:52 -0500 +Subject: [PATCH 12/19] make save-session stall until it finishes + +--- + gnome-session/gsm-manager.c | 58 ++++++++++++++++++++++++++---- + gnome-session/gsm-manager.h | 2 +- + gnome-session/org.gnome.SessionManager.xml | 1 + + 3 files changed, 53 insertions(+), 8 deletions(-) + +diff --git a/gnome-session/gsm-manager.c b/gnome-session/gsm-manager.c +index 711961d6..3c6bb7f4 100644 +--- a/gnome-session/gsm-manager.c ++++ b/gnome-session/gsm-manager.c +@@ -113,60 +113,61 @@ typedef enum + GSM_MANAGER_LOGOUT_REBOOT_INTERACT, + GSM_MANAGER_LOGOUT_SHUTDOWN, + GSM_MANAGER_LOGOUT_SHUTDOWN_INTERACT, + } GsmManagerLogoutType; + + struct GsmManagerPrivate + { + gboolean failsafe; + GsmStore *clients; + GsmStore *inhibitors; + GsmInhibitorFlag inhibited_actions; + GsmStore *apps; + GsmPresence *presence; + GsmXsmpServer *xsmp_server; + + char *session_name; + gboolean is_fallback_session : 1; + + /* Current status */ + GsmManagerPhase phase; + guint phase_timeout_id; + GSList *required_apps; + GSList *pending_apps; + GsmManagerLogoutMode logout_mode; + GSList *query_clients; + guint query_timeout_id; + /* This is used for GSM_MANAGER_PHASE_END_SESSION only at the moment, + * since it uses a sublist of all running client that replied in a + * specific way */ + GSList *next_query_clients; ++ GSList *pending_save_invocations; + /* This is the action that will be done just before we exit */ + GsmManagerLogoutType logout_type; + + /* List of clients which were disconnected due to disabled condition + * and shouldn't be automatically restarted */ + GSList *condition_clients; + + GSList *pending_end_session_tasks; + GCancellable *end_session_cancellable; + + GSettings *settings; + GSettings *session_settings; + GSettings *screensaver_settings; + GSettings *lockdown_settings; + + GsmSystem *system; + GDBusConnection *connection; + GsmExportedManager *skeleton; + gboolean dbus_disconnected : 1; + + GsmShell *shell; + guint shell_end_session_dialog_canceled_id; + guint shell_end_session_dialog_open_failed_id; + guint shell_end_session_dialog_confirmed_logout_id; + guint shell_end_session_dialog_confirmed_shutdown_id; + guint shell_end_session_dialog_confirmed_reboot_id; + }; + + enum { + PROP_0, +@@ -1165,90 +1166,124 @@ query_end_session_complete (GsmManager *manager) + static gboolean + _client_request_save (GsmClient *client, + ClientEndSessionData *data) + { + gboolean ret; + GError *error; + + error = NULL; + ret = gsm_client_request_save (client, data->flags, &error); + if (ret) { + g_debug ("GsmManager: adding client to query clients: %s", gsm_client_peek_id (client)); + data->manager->priv->query_clients = g_slist_prepend (data->manager->priv->query_clients, + client); + } else if (error) { + g_debug ("GsmManager: unable to query client: %s", error->message); + g_error_free (error); + } + + return FALSE; + } + + static gboolean + _client_request_save_helper (const char *id, + GsmClient *client, + ClientEndSessionData *data) + { + return _client_request_save (client, data); + } + + static void ++fail_pending_save_invocations (GsmManager *manager, ++ GError *error) ++{ ++ GSList *l; ++ ++ for (l = manager->priv->pending_save_invocations; l != NULL; l = l->next) { ++ DBusGMethodInvocation *context = l->data; ++ ++ dbus_g_method_return_error (context, error); ++ } ++ ++ g_slist_free (manager->priv->pending_save_invocations); ++ manager->priv->pending_save_invocations = NULL; ++} ++ ++static void ++finish_pending_save_invocations (GsmManager *manager) ++{ ++ GSList *l; ++ ++ for (l = manager->priv->pending_save_invocations; l != NULL; l = l->next) { ++ DBusGMethodInvocation *context = l->data; ++ ++ dbus_g_method_return (context); ++ } ++ ++ g_slist_free (manager->priv->pending_save_invocations); ++ manager->priv->pending_save_invocations = NULL; ++} ++ ++static void + query_save_session_complete (GsmManager *manager) + { + GError *error = NULL; + + if (g_slist_length (manager->priv->next_query_clients) > 0) { + ClientEndSessionData data; + + data.manager = manager; + data.flags = GSM_CLIENT_END_SESSION_FLAG_LAST; + + g_slist_foreach (manager->priv->next_query_clients, + (GFunc)_client_request_save, + &data); + + g_slist_free (manager->priv->next_query_clients); + manager->priv->next_query_clients = NULL; + + return; + } + + if (manager->priv->query_timeout_id > 0) { + g_source_remove (manager->priv->query_timeout_id); + manager->priv->query_timeout_id = 0; + } + + gsm_session_save (manager->priv->clients, &error); + + if (error) { + g_warning ("Error saving session: %s", error->message); ++ fail_pending_save_invocations (manager, error); + g_error_free (error); ++ } else { ++ finish_pending_save_invocations (manager); + } + } + + static guint32 + generate_cookie (void) + { + guint32 cookie; + + cookie = (guint32)g_random_int_range (1, G_MAXINT32); + + return cookie; + } + + static guint32 + _generate_unique_cookie (GsmManager *manager) + { + guint32 cookie; + + do { + cookie = generate_cookie (); + } while (gsm_store_find (manager->priv->inhibitors, (GsmStoreFunc)_find_by_cookie, &cookie) != NULL); + + return cookie; + } + + static gboolean + _on_query_end_session_timeout (GsmManager *manager) + { + GSList *l; + +@@ -2699,92 +2734,101 @@ gsm_manager_initialization_error (GsmExportedManager *skeleton, + GsmManager *manager) + { + if (manager->priv->phase != GSM_MANAGER_PHASE_INITIALIZATION) { + g_dbus_method_invocation_return_error (invocation, + GSM_MANAGER_ERROR, + GSM_MANAGER_ERROR_NOT_IN_INITIALIZATION, + "InitializationError interface is only available during the Initialization phase"); + return TRUE; + } + + gsm_util_init_error (fatal, "%s", message); + gsm_exported_manager_complete_initialization_error (skeleton, invocation); + + return TRUE; + } + + static void + user_logout (GsmManager *manager, + GsmManagerLogoutMode mode) + { + if (manager->priv->phase >= GSM_MANAGER_PHASE_QUERY_END_SESSION) { + manager->priv->logout_mode = mode; + end_session_or_show_shell_dialog (manager); + return; + } + + request_logout (manager, mode); + } + + gboolean +-gsm_manager_save_session (GsmManager *manager, +- GError **error) ++gsm_manager_save_session (GsmManager *manager, ++ DBusGMethodInvocation *context) + { + ClientEndSessionData data; ++ GError *error; + + g_debug ("GsmManager: SaveSession called"); + + g_return_val_if_fail (GSM_IS_MANAGER (manager), FALSE); + + if (manager->priv->phase != GSM_MANAGER_PHASE_RUNNING) { +- g_set_error (error, +- GSM_MANAGER_ERROR, +- GSM_MANAGER_ERROR_NOT_IN_RUNNING, +- "SaveSession interface is only available during the Running phase"); ++ error = g_error_new (GSM_MANAGER_ERROR, ++ GSM_MANAGER_ERROR_NOT_IN_RUNNING, ++ "SaveSession interface is only available during the Running phase"); ++ dbus_g_method_return_error (context, error); ++ g_error_free (error); + return FALSE; + } + + data.manager = manager; + data.flags = 0; + gsm_store_foreach (manager->priv->clients, + (GsmStoreFunc)_client_request_save_helper, + &data); + + if (manager->priv->query_clients) { + manager->priv->query_timeout_id = g_timeout_add_seconds (GSM_MANAGER_SAVE_SESSION_TIMEOUT, + (GSourceFunc)_on_query_save_session_timeout, + manager); ++ ++ manager->priv->pending_save_invocations = g_slist_prepend (manager->priv->pending_save_invocations, ++ context); ++ + return TRUE; + } else { + g_debug ("GsmManager: Nothing to save"); +- return FALSE; ++ dbus_g_method_return (context); ++ return TRUE; + } ++ ++ return TRUE; + } + + gboolean + gsm_manager_logout (GsmManager *manager, + guint logout_mode, + GError **error) + { + if (manager->priv->phase < GSM_MANAGER_PHASE_RUNNING) { + g_set_error (error, + GSM_MANAGER_ERROR, + GSM_MANAGER_ERROR_NOT_IN_RUNNING, + "Logout interface is only available after the Running phase starts"); + return FALSE; + } + + if (_log_out_is_locked_down (manager)) { + g_set_error (error, + GSM_MANAGER_ERROR, + GSM_MANAGER_ERROR_LOCKED_DOWN, + "Logout has been locked down"); + return FALSE; + } + + switch (logout_mode) { + case GSM_MANAGER_LOGOUT_MODE_NORMAL: + case GSM_MANAGER_LOGOUT_MODE_NO_CONFIRMATION: + case GSM_MANAGER_LOGOUT_MODE_FORCE: + user_logout (manager, logout_mode); + break; + +diff --git a/gnome-session/gsm-manager.h b/gnome-session/gsm-manager.h +index 4d14aa34..a8de58de 100644 +--- a/gnome-session/gsm-manager.h ++++ b/gnome-session/gsm-manager.h +@@ -97,42 +97,42 @@ GType gsm_manager_get_type (void); + + GsmManager * gsm_manager_new (GsmStore *client_store, + gboolean failsafe); + GsmManager * gsm_manager_get (void); + + gboolean gsm_manager_get_failsafe (GsmManager *manager); + + gboolean gsm_manager_add_autostart_app (GsmManager *manager, + const char *path, + const char *provides); + gboolean gsm_manager_add_required_app (GsmManager *manager, + const char *path, + const char *provides); + gboolean gsm_manager_add_autostart_apps_from_dir (GsmManager *manager, + const char *path); + gboolean gsm_manager_add_legacy_session_apps (GsmManager *manager, + const char *path); + + void gsm_manager_start (GsmManager *manager); + + const char * _gsm_manager_get_default_session (GsmManager *manager); + + void _gsm_manager_set_active_session (GsmManager *manager, + const char *session_name, + gboolean is_fallback); + + void _gsm_manager_set_renderer (GsmManager *manager, + const char *renderer); + + gboolean gsm_manager_save_session (GsmManager *manager, +- GError **error); ++ DBusGMethodInvocation *context); + + gboolean gsm_manager_logout (GsmManager *manager, + guint logout_mode, + GError **error); + + gboolean gsm_manager_set_phase (GsmManager *manager, + GsmManagerPhase phase); + + G_END_DECLS + + #endif /* __GSM_MANAGER_H */ +diff --git a/gnome-session/org.gnome.SessionManager.xml b/gnome-session/org.gnome.SessionManager.xml +index 29eb0990..ac73adc9 100644 +--- a/gnome-session/org.gnome.SessionManager.xml ++++ b/gnome-session/org.gnome.SessionManager.xml +@@ -256,60 +256,61 @@ + + + True if condition is handled, false otherwise + + + + + Allows the caller to determine whether the session manager is + handling changes to the specified autostart condition. + + + + + + + + Request a shutdown dialog. + + + + + + + + Request a reboot dialog. + + + + + ++ + + + Request to save session + + + + + + + + True if shutdown is available to the user, false otherwise + + + + + Allows the caller to determine whether or not it's okay to show + a shutdown option in the UI + + + + + + + + The type of logout that is being requested + + + + + Request a logout dialog +-- +2.12.0 + diff --git a/SOURCES/0013-manager-save-session-type-in-session-dir.patch b/SOURCES/0013-manager-save-session-type-in-session-dir.patch new file mode 100644 index 0000000..a28b2f4 --- /dev/null +++ b/SOURCES/0013-manager-save-session-type-in-session-dir.patch @@ -0,0 +1,662 @@ +From c5ad3fc27895f07f871d94aea69fc4713b258a82 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 20 Dec 2013 15:32:04 -0500 +Subject: [PATCH 13/19] manager: save session type in session dir + +If a user saved their session when in classic mode, make sure we +record that information so subsequent calls to gnome-session will +restore classic mode. +--- + gnome-session/gsm-manager.c | 21 ++++++++++++++++++-- + gnome-session/gsm-manager.h | 1 + + gnome-session/gsm-session-save.c | 41 +++++++++++++++++++++++++++++++++++++--- + gnome-session/gsm-session-save.h | 5 +++-- + gnome-session/main.c | 11 ++++++++++- + 5 files changed, 71 insertions(+), 8 deletions(-) + +diff --git a/gnome-session/gsm-manager.c b/gnome-session/gsm-manager.c +index 3c6bb7f4..4377fe9b 100644 +--- a/gnome-session/gsm-manager.c ++++ b/gnome-session/gsm-manager.c +@@ -1222,61 +1222,61 @@ finish_pending_save_invocations (GsmManager *manager) + g_slist_free (manager->priv->pending_save_invocations); + manager->priv->pending_save_invocations = NULL; + } + + static void + query_save_session_complete (GsmManager *manager) + { + GError *error = NULL; + + if (g_slist_length (manager->priv->next_query_clients) > 0) { + ClientEndSessionData data; + + data.manager = manager; + data.flags = GSM_CLIENT_END_SESSION_FLAG_LAST; + + g_slist_foreach (manager->priv->next_query_clients, + (GFunc)_client_request_save, + &data); + + g_slist_free (manager->priv->next_query_clients); + manager->priv->next_query_clients = NULL; + + return; + } + + if (manager->priv->query_timeout_id > 0) { + g_source_remove (manager->priv->query_timeout_id); + manager->priv->query_timeout_id = 0; + } + +- gsm_session_save (manager->priv->clients, &error); ++ gsm_session_save (manager->priv->clients, manager->priv->session_name, &error); + + if (error) { + g_warning ("Error saving session: %s", error->message); + fail_pending_save_invocations (manager, error); + g_error_free (error); + } else { + finish_pending_save_invocations (manager); + } + } + + static guint32 + generate_cookie (void) + { + guint32 cookie; + + cookie = (guint32)g_random_int_range (1, G_MAXINT32); + + return cookie; + } + + static guint32 + _generate_unique_cookie (GsmManager *manager) + { + guint32 cookie; + + do { + cookie = generate_cookie (); + } while (gsm_store_find (manager->priv->inhibitors, (GsmStoreFunc)_find_by_cookie, &cookie) != NULL); + + return cookie; +@@ -1490,60 +1490,77 @@ debug_app_summary (GsmManager *manager) + + g_debug ("GsmManager: App startup summary"); + for (phase = GSM_MANAGER_PHASE_EARLY_INITIALIZATION; phase < GSM_MANAGER_PHASE_RUNNING; phase++) { + g_debug ("GsmManager: Phase %s", phase_num_to_name (phase)); + gsm_store_foreach (manager->priv->apps, + (GsmStoreFunc)_debug_app_for_phase, + GUINT_TO_POINTER (phase)); + } + } + + void + gsm_manager_start (GsmManager *manager) + { + g_debug ("GsmManager: GSM starting to manage"); + + g_return_if_fail (GSM_IS_MANAGER (manager)); + + gsm_xsmp_server_start (manager->priv->xsmp_server); + gsm_manager_set_phase (manager, GSM_MANAGER_PHASE_EARLY_INITIALIZATION); + debug_app_summary (manager); + start_phase (manager); + } + + const char * + _gsm_manager_get_default_session (GsmManager *manager) + { + return g_settings_get_string (manager->priv->session_settings, + KEY_SESSION_NAME); + } + ++char * ++_gsm_manager_get_saved_session (GsmManager *manager) ++{ ++ char *file; ++ char *type; ++ gboolean loaded; ++ ++ file = g_build_filename (gsm_util_get_saved_session_dir (), "type", NULL); ++ loaded = g_file_get_contents (file, &type, NULL, NULL); ++ g_free (file); ++ ++ if (!loaded) ++ return NULL; ++ ++ return type; ++} ++ + void + _gsm_manager_set_active_session (GsmManager *manager, + const char *session_name, + gboolean is_fallback) + { + g_free (manager->priv->session_name); + manager->priv->session_name = g_strdup (session_name); + manager->priv->is_fallback_session = is_fallback; + + gsm_exported_manager_set_session_name (manager->priv->skeleton, session_name); + } + + void + _gsm_manager_set_renderer (GsmManager *manager, + const char *renderer) + { + gsm_exported_manager_set_renderer (manager->priv->skeleton, renderer); + } + + static gboolean + _app_has_app_id (const char *id, + GsmApp *app, + const char *app_id_a) + { + const char *app_id_b; + + app_id_b = gsm_app_peek_app_id (app); + return (app_id_b != NULL && strcmp (app_id_a, app_id_b) == 0); + } + +@@ -1908,61 +1925,61 @@ on_xsmp_client_register_confirmed (GsmXSMPClient *client, + } + } + + static gboolean + auto_save_is_enabled (GsmManager *manager) + { + return g_settings_get_boolean (manager->priv->settings, KEY_AUTOSAVE_ONE_SHOT) + || g_settings_get_boolean (manager->priv->settings, KEY_AUTOSAVE); + } + + static void + maybe_save_session (GsmManager *manager) + { + GError *error; + + if (gsm_system_is_login_session (manager->priv->system)) + return; + + /* We only allow session saving when session is running or when + * logging out */ + if (manager->priv->phase != GSM_MANAGER_PHASE_RUNNING && + manager->priv->phase != GSM_MANAGER_PHASE_END_SESSION) { + return; + } + + if (!auto_save_is_enabled (manager)) { + return; + } + + error = NULL; +- gsm_session_save (manager->priv->clients, &error); ++ gsm_session_save (manager->priv->clients, manager->priv->session_name, &error); + + if (error) { + g_warning ("Error saving session: %s", error->message); + g_error_free (error); + } + } + + static void + _handle_client_end_session_response (GsmManager *manager, + GsmClient *client, + gboolean is_ok, + gboolean do_last, + gboolean cancel, + const char *reason) + { + /* just ignore if we are not yet running */ + if (manager->priv->phase < GSM_MANAGER_PHASE_RUNNING) { + return; + } + + g_debug ("GsmManager: Response from end session request: is-ok=%d do-last=%d cancel=%d reason=%s", is_ok, do_last, cancel, reason ? reason :""); + + if (manager->priv->phase == GSM_MANAGER_PHASE_RUNNING) { + /* Ignore responses when no requests were sent */ + if (manager->priv->query_clients == NULL) { + return; + } + + manager->priv->query_clients = g_slist_remove (manager->priv->query_clients, client); + +diff --git a/gnome-session/gsm-manager.h b/gnome-session/gsm-manager.h +index a8de58de..fcf36019 100644 +--- a/gnome-session/gsm-manager.h ++++ b/gnome-session/gsm-manager.h +@@ -88,51 +88,52 @@ typedef enum + GSM_MANAGER_ERROR_INVALID_OPTION, + GSM_MANAGER_ERROR_LOCKED_DOWN, + GSM_MANAGER_NUM_ERRORS + } GsmManagerError; + + #define GSM_MANAGER_ERROR gsm_manager_error_quark () + GQuark gsm_manager_error_quark (void); + + GType gsm_manager_get_type (void); + + GsmManager * gsm_manager_new (GsmStore *client_store, + gboolean failsafe); + GsmManager * gsm_manager_get (void); + + gboolean gsm_manager_get_failsafe (GsmManager *manager); + + gboolean gsm_manager_add_autostart_app (GsmManager *manager, + const char *path, + const char *provides); + gboolean gsm_manager_add_required_app (GsmManager *manager, + const char *path, + const char *provides); + gboolean gsm_manager_add_autostart_apps_from_dir (GsmManager *manager, + const char *path); + gboolean gsm_manager_add_legacy_session_apps (GsmManager *manager, + const char *path); + + void gsm_manager_start (GsmManager *manager); + + const char * _gsm_manager_get_default_session (GsmManager *manager); ++char * _gsm_manager_get_saved_session (GsmManager *manager); + + void _gsm_manager_set_active_session (GsmManager *manager, + const char *session_name, + gboolean is_fallback); + + void _gsm_manager_set_renderer (GsmManager *manager, + const char *renderer); + + gboolean gsm_manager_save_session (GsmManager *manager, + DBusGMethodInvocation *context); + + gboolean gsm_manager_logout (GsmManager *manager, + guint logout_mode, + GError **error); + + gboolean gsm_manager_set_phase (GsmManager *manager, + GsmManagerPhase phase); + + G_END_DECLS + + #endif /* __GSM_MANAGER_H */ +diff --git a/gnome-session/gsm-session-save.c b/gnome-session/gsm-session-save.c +index 66914b57..78b64197 100644 +--- a/gnome-session/gsm-session-save.c ++++ b/gnome-session/gsm-session-save.c +@@ -1,73 +1,105 @@ + /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * gsm-session-save.c + * 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, see . + */ + + #include + ++#include ++ + #include + #include + #include + + #include "gsm-util.h" + #include "gsm-autostart-app.h" + #include "gsm-client.h" + + #include "gsm-session-save.h" + + #define GSM_MANAGER_SCHEMA "org.gnome.SessionManager" + #define KEY_AUTOSAVE_ONE_SHOT "auto-save-session-one-shot" + + + static gboolean gsm_session_clear_saved_session (const char *directory, + GHashTable *discard_hash); + + typedef struct { + char *dir; + GHashTable *discard_hash; + GError **error; + } SessionSaveData; + ++static void ++clear_session_type (const char *save_dir) ++{ ++ char *file; ++ ++ file = g_build_filename (save_dir, "type", NULL); ++ ++ g_unlink (file); ++ ++ g_free (file); ++} ++ ++static void ++set_session_type (const char *save_dir, ++ const char *type) ++{ ++ char *file; ++ GError *error; ++ ++ file = g_build_filename (save_dir, "type", NULL); ++ ++ error = NULL; ++ g_file_set_contents (file, type, strlen (type), &error); ++ if (error != NULL) ++ g_warning ("couldn't save session type to %s: %s", ++ type, error->message); ++ ++ g_free (file); ++} ++ + static gboolean + save_one_client (char *id, + GObject *object, + SessionSaveData *data) + { + GsmClient *client; + GKeyFile *keyfile; + const char *app_id; + char *path = NULL; + char *filename = NULL; + char *contents = NULL; + gsize length = 0; + char *discard_exec; + GError *local_error; + + client = GSM_CLIENT (object); + + local_error = NULL; + + keyfile = gsm_client_save (client, &local_error); + + if (keyfile == NULL || local_error) { + goto out; + } + + contents = g_key_file_to_data (keyfile, &length, &local_error); + + if (local_error) { + goto out; + } +@@ -107,112 +139,114 @@ save_one_client (char *id, + GSM_AUTOSTART_APP_DISCARD_KEY, + NULL); + if (discard_exec) { + g_hash_table_insert (data->discard_hash, + discard_exec, discard_exec); + } + + g_debug ("GsmSessionSave: saved client %s to %s", id, filename); + + out: + if (keyfile != NULL) { + g_key_file_free (keyfile); + } + + g_free (contents); + g_free (filename); + g_free (path); + + /* in case of any error, stop saving session */ + if (local_error) { + g_propagate_error (data->error, local_error); + g_error_free (local_error); + + return TRUE; + } + + return FALSE; + } + + void +-gsm_session_save (GsmStore *client_store, +- GError **error) ++gsm_session_save (GsmStore *client_store, ++ const char *type, ++ GError **error) + { + GSettings *settings; + const char *save_dir; + char *tmp_dir; + SessionSaveData data; + + g_debug ("GsmSessionSave: Saving session"); + + /* Clear one shot key autosave in the event its set (so that it's actually + * one shot only) + */ + settings = g_settings_new (GSM_MANAGER_SCHEMA); + g_settings_set_boolean (settings, KEY_AUTOSAVE_ONE_SHOT, FALSE); + g_object_unref (settings); + + save_dir = gsm_util_get_saved_session_dir (); + if (save_dir == NULL) { + g_warning ("GsmSessionSave: cannot create saved session directory"); + return; + } + + tmp_dir = gsm_util_get_empty_tmp_session_dir (); + if (tmp_dir == NULL) { + g_warning ("GsmSessionSave: cannot create new saved session directory"); + return; + } + + /* save the session in a temp directory, and remember the discard + * commands */ + data.dir = tmp_dir; + data.discard_hash = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, NULL); + data.error = error; + + gsm_store_foreach (client_store, + (GsmStoreFunc) save_one_client, + &data); + + if (!*error) { + char *session_dir; + + if (g_file_test (save_dir, G_FILE_TEST_IS_SYMLINK)) + session_dir = g_file_read_link (save_dir, error); + else + session_dir = g_strdup (save_dir); + + if (session_dir != NULL) { +- + char *absolute_session_dir; + ++ set_session_type (tmp_dir, type); ++ + if (g_path_is_absolute (session_dir)) { + absolute_session_dir = g_strdup (session_dir); + } else { + char *parent_dir; + + parent_dir = g_path_get_dirname (save_dir); + absolute_session_dir = g_build_filename (parent_dir, session_dir, NULL); + g_free (parent_dir); + } + g_free (session_dir); + + /* remove the old saved session */ + gsm_session_clear_saved_session (absolute_session_dir, data.discard_hash); + + if (g_file_test (absolute_session_dir, G_FILE_TEST_IS_DIR)) + g_rmdir (absolute_session_dir); + g_rename (tmp_dir, absolute_session_dir); + + g_free (absolute_session_dir); + } + } else { + g_warning ("GsmSessionSave: error saving session: %s", (*error)->message); + /* FIXME: we should create a hash table filled with the discard + * commands that are in desktop files from save_dir. */ + gsm_session_clear_saved_session (tmp_dir, NULL); + g_rmdir (tmp_dir); + } + + g_hash_table_destroy (data.discard_hash); + g_free (tmp_dir); +@@ -294,31 +328,32 @@ gsm_session_clear_saved_session (const char *directory, + + while ((filename = g_dir_read_name (dir))) { + char *path = g_build_filename (directory, + filename, NULL); + + result = gsm_session_clear_one_client (path, discard_hash) + && result; + + g_free (path); + } + + g_dir_close (dir); + + return result; + } + + void + gsm_session_save_clear (void) + { + const char *save_dir; + + g_debug ("GsmSessionSave: Clearing saved session"); + + save_dir = gsm_util_get_saved_session_dir (); + if (save_dir == NULL) { + g_warning ("GsmSessionSave: cannot create saved session directory"); + return; + } + + gsm_session_clear_saved_session (save_dir, NULL); ++ clear_session_type (save_dir); + } +diff --git a/gnome-session/gsm-session-save.h b/gnome-session/gsm-session-save.h +index e623260f..c91b5615 100644 +--- a/gnome-session/gsm-session-save.h ++++ b/gnome-session/gsm-session-save.h +@@ -1,33 +1,34 @@ + /* gsm-session-save.h + * 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, see . + */ + + #ifndef __GSM_SESSION_SAVE_H__ + #define __GSM_SESSION_SAVE_H__ + + #include + + #include "gsm-store.h" + + G_BEGIN_DECLS + +-void gsm_session_save (GsmStore *client_store, +- GError **error); ++void gsm_session_save (GsmStore *client_store, ++ const char *type, ++ GError **error); + void gsm_session_save_clear (void); + + G_END_DECLS + + #endif /* __GSM_SESSION_SAVE_H__ */ +diff --git a/gnome-session/main.c b/gnome-session/main.c +index 614c3427..7a4c855b 100644 +--- a/gnome-session/main.c ++++ b/gnome-session/main.c +@@ -113,61 +113,70 @@ term_or_int_signal_cb (gpointer data) + + static gboolean + sigusr2_cb (gpointer data) + { + g_debug ("-------- MARK --------"); + return TRUE; + } + + static gboolean + sigusr1_cb (gpointer data) + { + gdm_log_toggle_debug (); + return TRUE; + } + + static void + create_manager (void) + { + GsmStore *client_store; + + client_store = gsm_store_new (); + manager = gsm_manager_new (client_store, failsafe); + g_object_unref (client_store); + + g_unix_signal_add (SIGTERM, term_or_int_signal_cb, manager); + g_unix_signal_add (SIGINT, term_or_int_signal_cb, manager); + g_unix_signal_add (SIGUSR1, sigusr1_cb, manager); + g_unix_signal_add (SIGUSR2, sigusr2_cb, manager); + + if (IS_STRING_EMPTY (session_name)) { +- session_name = _gsm_manager_get_default_session (manager); ++ char *saved_session_name; ++ ++ saved_session_name = _gsm_manager_get_saved_session (manager); ++ ++ if (IS_STRING_EMPTY (saved_session_name)) ++ session_name = _gsm_manager_get_default_session (manager); ++ else ++ session_name = g_steal_pointer (&saved_session_name); ++ ++ g_free (saved_session_name); + } + + if (!gsm_session_fill (manager, session_name)) { + gsm_fail_whale_dialog_we_failed (FALSE, TRUE, NULL); + } + + _gsm_manager_set_renderer (manager, gl_renderer); + gsm_manager_start (manager); + } + + static void + on_bus_acquired (GDBusConnection *connection, + const char *name, + gpointer data) + { + create_manager (); + } + + static guint + acquire_name (void) + { + return g_bus_own_name (G_BUS_TYPE_SESSION, + GSM_DBUS_NAME, + G_BUS_NAME_OWNER_FLAGS_NONE, + on_bus_acquired, + NULL, + on_name_lost, + NULL, NULL); + } + +-- +2.12.0 + diff --git a/SOURCES/0014-session-selector-restore-saved-session-mode.patch b/SOURCES/0014-session-selector-restore-saved-session-mode.patch new file mode 100644 index 0000000..4ec53d8 --- /dev/null +++ b/SOURCES/0014-session-selector-restore-saved-session-mode.patch @@ -0,0 +1,42 @@ +From b6c78c97a1eac2c4c1711cd86ed740cd9d25c9fc Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 7 Jan 2014 21:16:23 -0500 +Subject: [PATCH 14/19] session-selector: restore saved session mode + +When using the custom session selector, we need to know +whether to use classic mode or not. + +This commit makes us use whatever mode was saved with the +session. +--- + tools/gnome-session-custom-session | 17 ++++++++++++++++- + 1 file changed, 16 insertions(+), 1 deletion(-) + +diff --git a/tools/gnome-session-custom-session b/tools/gnome-session-custom-session +index 07fdb0cc..358aee01 100644 +--- a/tools/gnome-session-custom-session ++++ b/tools/gnome-session-custom-session +@@ -1,4 +1,19 @@ + #! /bin/sh + + gnome-session-selector +-exec gnome-session ++ ++type_file="${XDG_CONFIG_HOME:-$HOME/.config}/gnome-session/saved-session/type" ++ ++session_type="" ++if [ -e "$type_file" ]; then ++ read session_type < "$type_file" ++fi ++ ++session_type_argument="" ++[ -n "$session_type" ] && session_type_argument="--session=$session_type" ++ ++if [ "$session_type" = "gnome-classic" ]; then ++ export GNOME_SHELL_SESSION_MODE="classic" ++fi ++ ++exec gnome-session "$session_type_argument" +-- +2.12.0 + diff --git a/SOURCES/0015-session-selector-refresh-from-recent-glade.patch b/SOURCES/0015-session-selector-refresh-from-recent-glade.patch new file mode 100644 index 0000000..d15c654 --- /dev/null +++ b/SOURCES/0015-session-selector-refresh-from-recent-glade.patch @@ -0,0 +1,269 @@ +From 813c3f933584b9a11f88ab3bd26fc266ffac28c8 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Fri, 20 Dec 2013 10:53:33 -0500 +Subject: [PATCH 15/19] session-selector: refresh from recent glade + +The ui file is rather old. This commit just opens it up in a recent +glade and resaves it, so we have a fresh starting point to make +changes. +--- + data/session-selector.ui | 80 ++++++++++++++++++++++++++++++++---------------- + 1 file changed, 54 insertions(+), 26 deletions(-) + +diff --git a/data/session-selector.ui b/data/session-selector.ui +index 1534a746..4d1e3009 100644 +--- a/data/session-selector.ui ++++ b/data/session-selector.ui +@@ -1,195 +1,223 @@ +- ++ + +- +- +- +- +- +- +- +- +- +- session-store +- ++ + ++ False + Custom Session + center + 500 + 310 + False + + + True ++ False + 0.5 + out + + + True ++ False + 12 + + + True +- vertical ++ False + 6 +- + + + True +- other +- ++ False ++ other + +- ++ + True ++ False + vertical +- 0 + + + True +- 0.0 +- 0.5 ++ False ++ 0 + Please select a custom session to use + + +- True +- True ++ False ++ False + 0 + + + ++ ++ False ++ False ++ 0 ++ ++ ++ ++ ++ False ++ ++ ++ False ++ True ++ 1 ++ + + + + False + True + 0 + + + + + True +- vertical ++ False + 12 + + + True ++ False + 12 + + + True + True + never +- automatic + in + + + True + True ++ sort-model + False + 0 +- sort-model ++ ++ ++ + + + + ++ True ++ True + 0 + + + + + True +- vertical ++ False + 6 + start + + + _New Session + True + True + True + True + + + False + False + 0 + + + + + _Remove Session + True + True + True + True + + + False + False + 1 + + + + + Rena_me Session + True + True + True + True + + + False + False + 2 + + + + + False ++ True + 1 + + + + ++ True ++ True + 1 + + + + ++ True ++ True + 1 + + + + + True ++ False + 6 + end + + + _Continue + True + True + True + True + True + True + + + False + False + 0 + + + + + False ++ True + 2 + + + + + + + + + ++ ++ ++ ++ ++ ++ ++ ++ session-store ++ + +-- +2.12.0 + diff --git a/SOURCES/0016-session-selector-add-toggle-for-classic-normal-selec.patch b/SOURCES/0016-session-selector-add-toggle-for-classic-normal-selec.patch new file mode 100644 index 0000000..d1674d9 --- /dev/null +++ b/SOURCES/0016-session-selector-add-toggle-for-classic-normal-selec.patch @@ -0,0 +1,604 @@ +From a5a64308ef552d7a1ef4210db9d848c9fd7b3740 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 7 Jan 2014 21:02:02 -0500 +Subject: [PATCH 16/19] session-selector: add toggle for classic/normal + selection + +Since we offer both classic mode and regular mode when +not using the session selector, we should also offer it +when using the session selector. +--- + data/session-selector.ui | 39 ++++++++++++++- + tools/gnome-session-selector.c | 106 +++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 143 insertions(+), 2 deletions(-) + +diff --git a/data/session-selector.ui b/data/session-selector.ui +index 4d1e3009..beab73a1 100644 +--- a/data/session-selector.ui ++++ b/data/session-selector.ui +@@ -153,71 +153,106 @@ + False + 2 + + + + + False + True + 1 + + + + + True + True + 1 + + + + + True + True + 1 + + + + + True + False + 6 +- end ++ ++ ++ True ++ False ++ 6 ++ ++ ++ True ++ False ++ Classic Experience ++ ++ ++ False ++ True ++ 0 ++ ++ ++ ++ ++ True ++ True ++ ++ ++ False ++ True ++ 1 ++ ++ ++ ++ ++ False ++ True ++ 0 ++ ++ + + + _Continue + True + True + True + True + True + True + + + False + False +- 0 ++ 1 ++ True + + + + + False + True + 2 + + + + + + + + + + + + + + + + + session-store + + +diff --git a/tools/gnome-session-selector.c b/tools/gnome-session-selector.c +index 8f37eca4..f7f12e7b 100644 +--- a/tools/gnome-session-selector.c ++++ b/tools/gnome-session-selector.c +@@ -16,60 +16,61 @@ + * along with this program; if not, see . + * + * Written by: Matthias Clasen + */ + + #include "config.h" + + #include + #include + #include + #include + #include + #include + + #include + #include + #include + + #include + #include + + #include + #include + + #define GSM_SERVICE_DBUS "org.gnome.SessionManager" + #define GSM_PATH_DBUS "/org/gnome/SessionManager" + #define GSM_INTERFACE_DBUS "org.gnome.SessionManager" + + #define GSM_MANAGER_SCHEMA "org.gnome.SessionManager" + #define KEY_AUTOSAVE_ONE_SHOT "auto-save-session-one-shot" ++#define DEFAULT_SESSION_NAME "gnome" + + static GtkBuilder *builder; + static GtkWidget *session_list; + static GtkListStore *store; + static GtkTreeModelSort *sort_model; + static char *info_text; + + static void select_session (const char *name); + static gboolean make_session_current (const char *name); + + static char * + get_session_path (const char *name) + { + return g_build_filename (g_get_user_config_dir (), "gnome-session", name, NULL); + } + + static char * + find_new_session_name (void) + { + char *name; + char *path; + int i; + + for (i = 1; i < 20; i++) { + name = g_strdup_printf (_("Session %d"), i); + path = get_session_path (name); + if (!g_file_test (path, G_FILE_TEST_EXISTS)) { + g_free (path); + return name; + } +@@ -125,104 +126,126 @@ is_valid_session_name (const char *name) + gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter); + do { + gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, 0, &n, -1); + if (strcmp (n, name) == 0) { + char *message; + message = g_strdup_printf (_("A session named ‘%s’ already exists"), name); + warning_text = g_strdup_printf ("%s\nNote: %s", info_text, message); + g_free (message); + g_free (n); + break; + } + g_free (n); + } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter)); + + info_bar = (GtkWidget *) gtk_builder_get_object (builder, "info-bar"); + label = (GtkWidget*) gtk_builder_get_object (builder, "info-label"); + + if (warning_text != NULL) { + gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar), GTK_MESSAGE_WARNING); + gtk_label_set_markup (GTK_LABEL (label), warning_text); + g_free (warning_text); + return FALSE; + } + + gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar), GTK_MESSAGE_OTHER); + gtk_label_set_markup (GTK_LABEL (label), info_text); + + return TRUE; + } + ++static char * ++get_session_type_from_file (const char *name) ++{ ++ char *file; ++ char *type; ++ gboolean loaded; ++ ++ file = g_build_filename (g_get_user_config_dir (), "gnome-session", name, "type", NULL); ++ loaded = g_file_get_contents (file, &type, NULL, NULL); ++ g_free (file); ++ ++ if (!loaded) ++ return g_strdup (DEFAULT_SESSION_NAME); ++ ++ return type; ++} ++ + static void + populate_session_list (GtkWidget *session_list) + { + GtkTreeIter iter; + char *path; + const char *name; + GDir *dir; + GError *error; + char *saved_session; + char *default_session; + char *default_name; + char last_session[PATH_MAX] = ""; + + saved_session = get_session_path ("saved-session"); + + if (!g_file_test (saved_session, G_FILE_TEST_IS_SYMLINK)) { + default_name = find_new_session_name (); + default_session = get_session_path (default_name); + rename (saved_session, default_session); + if (symlink (default_name, saved_session) < 0) + g_warning ("Failed to convert saved-session to symlink"); + g_free (default_name); + g_free (default_session); + } + + path = g_build_filename (g_get_user_config_dir (), "gnome-session", NULL); + error = NULL; + dir = g_dir_open (path, 0, &error); + if (dir == NULL) { + g_warning ("Failed to open %s: %s", path, error->message); + g_error_free (error); + goto out; + } + + default_name = NULL; + if (readlink (saved_session, last_session, PATH_MAX - 1) > 0) { + default_name = g_path_get_basename (last_session); + } + + while ((name = g_dir_read_name (dir)) != NULL) { ++ char *session_type; ++ + if (strcmp (name, "saved-session") == 0) + continue; + ++ session_type = get_session_type_from_file (name); ++ + gtk_list_store_insert_with_values (store, &iter, 100, 0, name, -1); ++ g_free (session_type); + + if (g_strcmp0 (default_name, name) == 0) { + GtkTreeSelection *selection; + GtkTreeIter child_iter; + + gtk_tree_model_sort_convert_child_iter_to_iter (GTK_TREE_MODEL_SORT (sort_model), &child_iter, &iter); + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (session_list)); + gtk_tree_selection_select_iter (selection, &child_iter); + } + } + + g_free (default_name); + g_dir_close (dir); + + out: + g_free (saved_session); + g_free (path); + } + + static char * + get_last_session (void) + { + char *saved_session; + char last_session[PATH_MAX] = ""; + char *name = NULL; + + saved_session = get_session_path ("saved-session"); + + if (readlink (saved_session, last_session, PATH_MAX - 1) > 0) { + name = g_path_get_basename (last_session); +@@ -260,60 +283,136 @@ remove_session (const char *name) + GError *error; + + path1 = get_session_path ("saved-session"); + path2 = get_session_path (name); + + error = NULL; + n = g_file_read_link (path1, &error); + if (n == NULL) { + g_warning ("Failed to read link: %s", error->message); + g_error_free (error); + } + else if (strcmp (n, name) == 0) { + unlink (path1); + } + g_free (n); + + dir = g_dir_open (path2, 0, NULL); + while ((d = g_dir_read_name (dir)) != NULL) { + path = g_build_filename (path2, d, NULL); + unlink (path); + g_free (path); + } + g_dir_close (dir); + + remove (path2); + + g_free (path1); + g_free (path2); + } + ++static const char * ++get_session_type_from_switch (void) ++{ ++ GtkWidget *mode_switch; ++ gboolean is_classic_mode; ++ ++ mode_switch = (GtkWidget *)gtk_builder_get_object (builder, "classic-mode-switch"); ++ ++ is_classic_mode = gtk_switch_get_active (GTK_SWITCH (mode_switch)); ++ ++ if (is_classic_mode) { ++ return "gnome-classic"; ++ } else { ++ return "gnome"; ++ } ++} ++ ++static void ++set_mode_switch_from_session_type_file (const char *name) ++{ ++ GtkWidget *mode_switch; ++ gboolean is_classic_mode = FALSE; ++ char *type; ++ ++ mode_switch = (GtkWidget *)gtk_builder_get_object (builder, "classic-mode-switch"); ++ ++ type = get_session_type_from_file (name); ++ is_classic_mode = strcmp (type, "gnome-classic") == 0; ++ g_free (type); ++ ++ gtk_switch_set_active (GTK_SWITCH (mode_switch), is_classic_mode); ++} ++ ++static void ++save_session_type (const char *save_dir, ++ const char *type) ++{ ++ char *file; ++ GError *error; ++ ++ file = g_build_filename (save_dir, "type", NULL); ++ ++ error = NULL; ++ g_file_set_contents (file, type, strlen (type), &error); ++ if (error != NULL) ++ g_warning ("couldn't save session type to %s: %s", ++ type, error->message); ++ ++ g_free (file); ++} ++ ++static void ++save_session_type_from_switch (void) ++{ ++ char *name, *path; ++ const char *session_type; ++ ++ name = get_selected_session (); ++ ++ if (name == NULL) { ++ return; ++ } ++ ++ path = get_session_path (name); ++ g_free (name); ++ ++ session_type = get_session_type_from_switch (); ++ save_session_type (path, session_type); ++} ++ ++static void ++on_mode_switched (GtkSwitch *mode_switch) ++{ ++ save_session_type_from_switch (); ++} ++ + static gboolean + make_session_current (const char *name) + { + char *path1; + gboolean ret = TRUE; + + path1 = g_build_filename (g_get_user_config_dir (), "gnome-session", "saved-session", NULL); + + unlink (path1); + if (symlink (name, path1) < 0) { + g_warning ("Failed to make session '%s' current", name); + ret = FALSE; + } + + g_free (path1); + + return ret; + } + + static void + on_remove_session_clicked (GtkButton *button, + gpointer data) + { + GtkTreeSelection *selection; + GtkTreeModel *model; + GtkTreeIter iter; + char *name; + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (session_list)); + if (gtk_tree_selection_get_selected (selection, &model, &iter)) { +@@ -492,60 +591,62 @@ static void + create_session_and_begin_rename (void) + { + gchar *name; + + name = find_new_session_name (); + create_session (name); + select_session (name); + + begin_rename (); + } + + static void + on_new_session_clicked (GtkButton *button, + gpointer data) + { + create_session_and_begin_rename (); + } + + static void + on_selection_changed (GtkTreeSelection *selection, + gpointer data) + { + char *name; + + name = get_selected_session (); + + if (name == NULL) { + return; + } + ++ set_mode_switch_from_session_type_file (name); ++ + g_free (name); + } + + static void + update_remove_button (void) + { + GtkWidget *button; + + button = (GtkWidget *)gtk_builder_get_object (builder, "remove-session"); + if (gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), NULL) > 1) { + gtk_widget_set_sensitive (button, TRUE); + } else { + gtk_widget_set_sensitive (button, FALSE); + } + } + + static void + on_row_edited (GtkCellRendererText *cell, + const char *path_string, + const char *new_name, + gpointer data) + { + GtkTreePath *path; + GtkTreeIter sort_iter, items_iter; + char *old_name; + gboolean was_renamed; + + path = gtk_tree_path_new_from_string (path_string); + gtk_tree_model_get_iter (GTK_TREE_MODEL (sort_model), &sort_iter, path); + +@@ -751,75 +852,80 @@ main (int argc, char *argv[]) + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model), + 0, GTK_SORT_ASCENDING); + g_signal_connect (store, "row-deleted", G_CALLBACK (on_row_deleted), NULL); + g_signal_connect (store, "row-inserted", G_CALLBACK (on_row_inserted), NULL); + session_list = (GtkWidget *) gtk_builder_get_object (builder, "session-list"); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (session_list)); + gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); + + populate_session_list (session_list); + + cell = gtk_cell_renderer_text_new (); + g_signal_connect (cell, "edited", G_CALLBACK (on_row_edited), NULL); + + column = gtk_tree_view_column_new_with_attributes ("", cell, "text", 0, NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (session_list), GTK_TREE_VIEW_COLUMN (column)); + + g_signal_connect (session_list, "row-activated", G_CALLBACK (on_row_activated), NULL); + + g_signal_connect (selection, "changed", + G_CALLBACK (on_selection_changed), NULL); + + widget = (GtkWidget *) gtk_builder_get_object (builder, "new-session"); + g_signal_connect (widget, "clicked", G_CALLBACK (on_new_session_clicked), NULL); + widget = (GtkWidget *) gtk_builder_get_object (builder, "remove-session"); + g_signal_connect (widget, "clicked", G_CALLBACK (on_remove_session_clicked), NULL); + widget = (GtkWidget *) gtk_builder_get_object (builder, "rename-session"); + g_signal_connect (widget, "clicked", G_CALLBACK (on_rename_session_clicked), NULL); + widget = (GtkWidget *) gtk_builder_get_object (builder, "continue-button"); + g_signal_connect (widget, "clicked", G_CALLBACK (on_continue_clicked), NULL); ++ widget = (GtkWidget *) gtk_builder_get_object (builder, "classic-mode-switch"); ++ g_signal_connect (widget, "notify::active", G_CALLBACK (on_mode_switched), NULL); + + g_signal_connect (window, "map", G_CALLBACK (on_map), NULL); + gtk_widget_show (window); + + if (g_strcmp0 (action, "load") == 0) { + info_text = _("Please select a custom session to run"); + } else if (g_strcmp0 (action, "print") == 0) { + info_text = _("Please select a session to use"); + } else if (g_strcmp0 (action, "save") == 0) { + info_text = _("Please select a session to save to"); + } + + label = (GtkWidget*) gtk_builder_get_object (builder, "info-label"); + gtk_label_set_markup (GTK_LABEL (label), info_text); + + selected_session = get_selected_session (); + + if (selected_session == NULL) { + create_session_and_begin_rename (); + } else { ++ set_mode_switch_from_session_type_file (selected_session); + g_free (selected_session); + } + + gtk_main (); + + selected_session = get_selected_session (); + + if (g_strcmp0 (action, "load") == 0) { + make_session_current (selected_session); ++ save_session_type_from_switch (); + auto_save_next_session_if_needed (); + } else if (g_strcmp0 (action, "save") == 0) { + char *last_session; + + last_session = get_last_session (); + make_session_current (selected_session); + save_session (); ++ save_session_type_from_switch (); + if (last_session != NULL) + make_session_current (last_session); + } else if (g_strcmp0 (action, "print") == 0) { + g_print ("%s\n", selected_session); + } + g_free (selected_session); + + return 0; + } +-- +2.12.0 + diff --git a/SOURCES/0017-session-selector-use-classic-mode-by-default.patch b/SOURCES/0017-session-selector-use-classic-mode-by-default.patch new file mode 100644 index 0000000..d777036 --- /dev/null +++ b/SOURCES/0017-session-selector-use-classic-mode-by-default.patch @@ -0,0 +1,79 @@ +From 8df9a4f1bb272d982d7b63fb2f4c7db92ff55a10 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 8 Jan 2014 10:15:29 -0500 +Subject: [PATCH 17/19] session-selector: use classic mode by default + +--- + tools/gnome-session-selector.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tools/gnome-session-selector.c b/tools/gnome-session-selector.c +index f7f12e7b..1068dbba 100644 +--- a/tools/gnome-session-selector.c ++++ b/tools/gnome-session-selector.c +@@ -16,61 +16,61 @@ + * along with this program; if not, see . + * + * Written by: Matthias Clasen + */ + + #include "config.h" + + #include + #include + #include + #include + #include + #include + + #include + #include + #include + + #include + #include + + #include + #include + + #define GSM_SERVICE_DBUS "org.gnome.SessionManager" + #define GSM_PATH_DBUS "/org/gnome/SessionManager" + #define GSM_INTERFACE_DBUS "org.gnome.SessionManager" + + #define GSM_MANAGER_SCHEMA "org.gnome.SessionManager" + #define KEY_AUTOSAVE_ONE_SHOT "auto-save-session-one-shot" +-#define DEFAULT_SESSION_NAME "gnome" ++#define DEFAULT_SESSION_NAME "gnome-classic" + + static GtkBuilder *builder; + static GtkWidget *session_list; + static GtkListStore *store; + static GtkTreeModelSort *sort_model; + static char *info_text; + + static void select_session (const char *name); + static gboolean make_session_current (const char *name); + + static char * + get_session_path (const char *name) + { + return g_build_filename (g_get_user_config_dir (), "gnome-session", name, NULL); + } + + static char * + find_new_session_name (void) + { + char *name; + char *path; + int i; + + for (i = 1; i < 20; i++) { + name = g_strdup_printf (_("Session %d"), i); + path = get_session_path (name); + if (!g_file_test (path, G_FILE_TEST_EXISTS)) { + g_free (path); + return name; + } +-- +2.12.0 + diff --git a/SOURCES/0018-manager-port-away-from-dbus-glib-to-GDBus.patch b/SOURCES/0018-manager-port-away-from-dbus-glib-to-GDBus.patch new file mode 100644 index 0000000..a90150b --- /dev/null +++ b/SOURCES/0018-manager-port-away-from-dbus-glib-to-GDBus.patch @@ -0,0 +1,756 @@ +From d8f3c88186a22984b79d5f9f78d6007451ab4e02 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 8 Mar 2017 16:36:44 -0500 +Subject: [PATCH 18/19] manager: port away from dbus-glib to GDBus + +--- + capplet/gsm-properties-dialog.c | 52 +++++++++++++++++++++-------------------- + configure.ac | 2 +- + gnome-session/gsm-manager.c | 16 ++++++------- + gnome-session/gsm-manager.h | 3 ++- + tools/gnome-session-selector.c | 48 ++++++++++++++++++++----------------- + 5 files changed, 64 insertions(+), 57 deletions(-) + +diff --git a/capplet/gsm-properties-dialog.c b/capplet/gsm-properties-dialog.c +index 51fa5106..04452c1a 100644 +--- a/capplet/gsm-properties-dialog.c ++++ b/capplet/gsm-properties-dialog.c +@@ -1,66 +1,66 @@ + /* -*- 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 + * + * 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 + #include + #include + ++#include ++ + #include "gsm-properties-dialog.h" + #include "gsm-app-dialog.h" + #include "gsm-util.h" + #include "gsp-app.h" + #include "gsp-app-manager.h" +-#include +-#include + + #define GSM_SERVICE_DBUS "org.gnome.SessionManager" + #define GSM_PATH_DBUS "/org/gnome/SessionManager" + #define GSM_INTERFACE_DBUS "org.gnome.SessionManager" + + #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_SESSION_SAVED_WIDGET_NAME "session_properties_session_saved_label" + #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; +@@ -454,101 +454,103 @@ on_edit_app_clicked (GtkWidget *widget, + 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 + session_saved_message (GsmPropertiesDialog *dialog, + const char *msg, + gboolean is_error) + { + GtkLabel *label; + gchar *markup; + label = GTK_LABEL (gtk_builder_get_object (dialog->priv->xml, CAPPLET_SESSION_SAVED_WIDGET_NAME)); + if (is_error) + markup = g_markup_printf_escaped ("%s", msg); + else + markup = g_markup_escape_text (msg, -1); + gtk_label_set_markup (label, markup); + g_free (markup); + } + + static void +-session_saved_cb (DBusGProxy *proxy, +- DBusGProxyCall *call_id, +- void *user_data) ++session_saved_cb (GDBusConnection *conn, ++ GAsyncResult *result, ++ gpointer user_data) + { +- gboolean res; ++ GVariant *reply; + GsmPropertiesDialog *dialog = user_data; ++ GError *error = NULL; + +- res = dbus_g_proxy_end_call (proxy, call_id, NULL, G_TYPE_INVALID); +- if (res) ++ reply = g_dbus_connection_call_finish (conn, result, &error); ++ if (error == NULL) + session_saved_message (dialog, _("Your session has been saved."), FALSE); + else + session_saved_message (dialog, _("Failed to save session"), TRUE); + +- g_object_unref (proxy); ++ g_clear_error (&error); ++ ++ g_variant_unref (reply); + } + + static void + save_session_directly (GsmPropertiesDialog *dialog) + { +- DBusGConnection *conn; +- DBusGProxy *proxy; +- DBusGProxyCall *call; ++ GDBusConnection *conn; + +- conn = dbus_g_bus_get (DBUS_BUS_SESSION, NULL); ++ conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); + if (conn == NULL) { + session_saved_message (dialog, _("Could not connect to the session bus"), TRUE); + return; + } + +- proxy = dbus_g_proxy_new_for_name (conn, GSM_SERVICE_DBUS, GSM_PATH_DBUS, GSM_INTERFACE_DBUS); +- if (proxy == NULL) { +- session_saved_message (dialog, _("Could not connect to the session manager"), TRUE); +- return; +- } +- +- call = dbus_g_proxy_begin_call (proxy, "SaveSession", session_saved_cb, dialog, NULL, G_TYPE_INVALID); +- if (call == NULL) { +- session_saved_message (dialog, _("Failed to save session"), TRUE); +- g_object_unref (proxy); +- return; +- } ++ g_dbus_connection_call (conn, ++ GSM_SERVICE_DBUS, ++ GSM_PATH_DBUS, ++ GSM_INTERFACE_DBUS, ++ "SaveSession", ++ NULL, ++ NULL, ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, ++ NULL, ++ (GAsyncReadyCallback) ++ session_saved_cb, ++ dialog); + } + + static void + save_session_from_selector (GsmPropertiesDialog *dialog, + const char *program_path) + { + char *command_line = g_strdup_printf ("%s --action save", program_path); + + g_spawn_command_line_sync (command_line, NULL, NULL, NULL, NULL); + + g_free (command_line); + } + + static void + on_save_session_clicked (GtkWidget *widget, + GsmPropertiesDialog *dialog) + { + char *program_path; + + program_path = g_find_program_in_path ("gnome-session-selector"); + + if (program_path != NULL) { + save_session_from_selector (dialog, program_path); + g_free (program_path); + } else { + save_session_directly (dialog); + } + } + + static void +diff --git a/configure.ac b/configure.ac +index ccbbf970..cc554a8a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -21,61 +21,61 @@ LT_PREREQ([2.2.6]) + LT_INIT([dlopen disable-static]) + + GNOME_MAINTAINER_MODE_DEFINES + GNOME_COMPILE_WARNINGS([maximum]) + + AC_ARG_ENABLE(deprecation_flags, + [AS_HELP_STRING([--enable-deprecation-flags], + [use *_DISABLE_DEPRECATED flags @<:@default=no@:>@])],, + [enable_deprecation_flags=no]) + + if test "x$enable_deprecation_flags" = "xyes"; then + DISABLE_DEPRECATED_CFLAGS=$DISABLE_DEPRECATED + AC_SUBST([DISABLE_DEPRECATED_CFLAGS]) + fi + + GLIB_REQUIRED=2.46.0 + GTK3_REQUIRED=3.18.0 + DBUS_GLIB_REQUIRED=0.76 + UPOWER_REQUIRED=0.9.0 + JSON_GLIB_REQUIRED=0.10 + GNOME_DESKTOP_REQUIRED=3.18.0 + + AC_ARG_ENABLE(session-selector, AS_HELP_STRING([--enable-session-selector], + [enable building a custom session selector dialog]), + enable_session_selector=$enableval,enable_session_selector=no) + + AM_CONDITIONAL(BUILD_SESSION_SELECTOR, + [test "$enable_session_selector" = yes]) + + if test "$enable_session_selector" = yes; then +- PKG_CHECK_MODULES(SESSION_SELECTOR, gtk+-3.0 gio-2.0 dbus-glib-1 >= $DBUS_GLIB_REQUIRED) ++ PKG_CHECK_MODULES(SESSION_SELECTOR, gtk+-3.0 gio-2.0) + fi + + dnl ==================================================================== + dnl Dependency Checks + dnl ==================================================================== + + dnl Standard vertical stacks + PKG_CHECK_MODULES(GIO, gio-2.0) + PKG_CHECK_MODULES(GIOUNIX, gio-unix-2.0 >= $GLIB_REQUIRED) + PKG_CHECK_MODULES(GTK3, gtk+-3.0 >= $GTK3_REQUIRED) + + PKG_CHECK_MODULES(GNOME_SESSION, + glib-2.0 >= $GLIB_REQUIRED + gio-2.0 >= $GLIB_REQUIRED + json-glib-1.0 >= $JSON_GLIB_REQUIRED + gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED + ) + + dnl We can only support old upower + dnl https://bugzilla.gnome.org/show_bug.cgi?id=710383 + PKG_CHECK_MODULES(UPOWER, upower-glib < 0.99.0, have_old_upower=yes, have_old_upower=no) + AS_IF([test x$have_old_upower = xyes], [ + AC_DEFINE([HAVE_OLD_UPOWER], [1], [Define if we have an older upower]) + ]) + AM_CONDITIONAL(HAVE_OLD_UPOWER, test x$have_old_upower = xyes) + + PKG_CHECK_MODULES(SESSION_PROPERTIES, + glib-2.0 >= $GLIB_REQUIRED + gtk+-3.0 >= $GTK3_REQUIRED + ) +diff --git a/gnome-session/gsm-manager.c b/gnome-session/gsm-manager.c +index 4377fe9b..7c0351a2 100644 +--- a/gnome-session/gsm-manager.c ++++ b/gnome-session/gsm-manager.c +@@ -1172,78 +1172,78 @@ _client_request_save (GsmClient *client, + + error = NULL; + ret = gsm_client_request_save (client, data->flags, &error); + if (ret) { + g_debug ("GsmManager: adding client to query clients: %s", gsm_client_peek_id (client)); + data->manager->priv->query_clients = g_slist_prepend (data->manager->priv->query_clients, + client); + } else if (error) { + g_debug ("GsmManager: unable to query client: %s", error->message); + g_error_free (error); + } + + return FALSE; + } + + static gboolean + _client_request_save_helper (const char *id, + GsmClient *client, + ClientEndSessionData *data) + { + return _client_request_save (client, data); + } + + static void + fail_pending_save_invocations (GsmManager *manager, + GError *error) + { + GSList *l; + + for (l = manager->priv->pending_save_invocations; l != NULL; l = l->next) { +- DBusGMethodInvocation *context = l->data; ++ GDBusMethodInvocation *invocation = l->data; + +- dbus_g_method_return_error (context, error); ++ g_dbus_method_invocation_return_gerror (invocation, error); + } + + g_slist_free (manager->priv->pending_save_invocations); + manager->priv->pending_save_invocations = NULL; + } + + static void + finish_pending_save_invocations (GsmManager *manager) + { + GSList *l; + + for (l = manager->priv->pending_save_invocations; l != NULL; l = l->next) { +- DBusGMethodInvocation *context = l->data; ++ GDBusMethodInvocation *invocation = l->data; + +- dbus_g_method_return (context); ++ g_dbus_method_invocation_return_value (invocation, NULL); + } + + g_slist_free (manager->priv->pending_save_invocations); + manager->priv->pending_save_invocations = NULL; + } + + static void + query_save_session_complete (GsmManager *manager) + { + GError *error = NULL; + + if (g_slist_length (manager->priv->next_query_clients) > 0) { + ClientEndSessionData data; + + data.manager = manager; + data.flags = GSM_CLIENT_END_SESSION_FLAG_LAST; + + g_slist_foreach (manager->priv->next_query_clients, + (GFunc)_client_request_save, + &data); + + g_slist_free (manager->priv->next_query_clients); + manager->priv->next_query_clients = NULL; + + return; + } + + if (manager->priv->query_timeout_id > 0) { + g_source_remove (manager->priv->query_timeout_id); + manager->priv->query_timeout_id = 0; +@@ -2752,96 +2752,96 @@ gsm_manager_initialization_error (GsmExportedManager *skeleton, + { + if (manager->priv->phase != GSM_MANAGER_PHASE_INITIALIZATION) { + g_dbus_method_invocation_return_error (invocation, + GSM_MANAGER_ERROR, + GSM_MANAGER_ERROR_NOT_IN_INITIALIZATION, + "InitializationError interface is only available during the Initialization phase"); + return TRUE; + } + + gsm_util_init_error (fatal, "%s", message); + gsm_exported_manager_complete_initialization_error (skeleton, invocation); + + return TRUE; + } + + static void + user_logout (GsmManager *manager, + GsmManagerLogoutMode mode) + { + if (manager->priv->phase >= GSM_MANAGER_PHASE_QUERY_END_SESSION) { + manager->priv->logout_mode = mode; + end_session_or_show_shell_dialog (manager); + return; + } + + request_logout (manager, mode); + } + + gboolean + gsm_manager_save_session (GsmManager *manager, +- DBusGMethodInvocation *context) ++ GDBusMethodInvocation *invocation) + { + ClientEndSessionData data; + GError *error; + + g_debug ("GsmManager: SaveSession called"); + + g_return_val_if_fail (GSM_IS_MANAGER (manager), FALSE); + + if (manager->priv->phase != GSM_MANAGER_PHASE_RUNNING) { + error = g_error_new (GSM_MANAGER_ERROR, + GSM_MANAGER_ERROR_NOT_IN_RUNNING, + "SaveSession interface is only available during the Running phase"); +- dbus_g_method_return_error (context, error); ++ g_dbus_method_invocation_return_gerror (invocation, error); + g_error_free (error); + return FALSE; + } + + data.manager = manager; + data.flags = 0; + gsm_store_foreach (manager->priv->clients, + (GsmStoreFunc)_client_request_save_helper, + &data); + + if (manager->priv->query_clients) { + manager->priv->query_timeout_id = g_timeout_add_seconds (GSM_MANAGER_SAVE_SESSION_TIMEOUT, + (GSourceFunc)_on_query_save_session_timeout, + manager); + + manager->priv->pending_save_invocations = g_slist_prepend (manager->priv->pending_save_invocations, +- context); ++ invocation); + + return TRUE; + } else { + g_debug ("GsmManager: Nothing to save"); +- dbus_g_method_return (context); ++ g_dbus_method_invocation_return_value (invocation, NULL); + return TRUE; + } + + return TRUE; + } + + gboolean + gsm_manager_logout (GsmManager *manager, + guint logout_mode, + GError **error) + { + if (manager->priv->phase < GSM_MANAGER_PHASE_RUNNING) { + g_set_error (error, + GSM_MANAGER_ERROR, + GSM_MANAGER_ERROR_NOT_IN_RUNNING, + "Logout interface is only available after the Running phase starts"); + return FALSE; + } + + if (_log_out_is_locked_down (manager)) { + g_set_error (error, + GSM_MANAGER_ERROR, + GSM_MANAGER_ERROR_LOCKED_DOWN, + "Logout has been locked down"); + return FALSE; + } + + switch (logout_mode) { + case GSM_MANAGER_LOGOUT_MODE_NORMAL: + case GSM_MANAGER_LOGOUT_MODE_NO_CONFIRMATION: +diff --git a/gnome-session/gsm-manager.h b/gnome-session/gsm-manager.h +index fcf36019..88a88ccc 100644 +--- a/gnome-session/gsm-manager.h ++++ b/gnome-session/gsm-manager.h +@@ -1,54 +1,55 @@ + /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2008 William Jon McCann + * + * 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, see . + * + */ + + + #ifndef __GSM_MANAGER_H + #define __GSM_MANAGER_H + + #include ++#include + + #include "gsm-store.h" + #include "gsm-manager-logout-mode.h" + + G_BEGIN_DECLS + + #define GSM_TYPE_MANAGER (gsm_manager_get_type ()) + #define GSM_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GSM_TYPE_MANAGER, GsmManager)) + #define GSM_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GSM_TYPE_MANAGER, GsmManagerClass)) + #define GSM_IS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GSM_TYPE_MANAGER)) + #define GSM_IS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GSM_TYPE_MANAGER)) + #define GSM_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GSM_TYPE_MANAGER, GsmManagerClass)) + + typedef struct GsmManagerPrivate GsmManagerPrivate; + + typedef struct + { + GObject parent; + GsmManagerPrivate *priv; + } GsmManager; + + typedef struct + { + GObjectClass parent_class; + + void (* phase_changed) (GsmManager *manager, + const char *phase); + } GsmManagerClass; + + typedef enum { +@@ -98,42 +99,42 @@ GType gsm_manager_get_type (void); + GsmManager * gsm_manager_new (GsmStore *client_store, + gboolean failsafe); + GsmManager * gsm_manager_get (void); + + gboolean gsm_manager_get_failsafe (GsmManager *manager); + + gboolean gsm_manager_add_autostart_app (GsmManager *manager, + const char *path, + const char *provides); + gboolean gsm_manager_add_required_app (GsmManager *manager, + const char *path, + const char *provides); + gboolean gsm_manager_add_autostart_apps_from_dir (GsmManager *manager, + const char *path); + gboolean gsm_manager_add_legacy_session_apps (GsmManager *manager, + const char *path); + + void gsm_manager_start (GsmManager *manager); + + const char * _gsm_manager_get_default_session (GsmManager *manager); + char * _gsm_manager_get_saved_session (GsmManager *manager); + + void _gsm_manager_set_active_session (GsmManager *manager, + const char *session_name, + gboolean is_fallback); + + void _gsm_manager_set_renderer (GsmManager *manager, + const char *renderer); + + gboolean gsm_manager_save_session (GsmManager *manager, +- DBusGMethodInvocation *context); ++ GDBusMethodInvocation *context); + + gboolean gsm_manager_logout (GsmManager *manager, + guint logout_mode, + GError **error); + + gboolean gsm_manager_set_phase (GsmManager *manager, + GsmManagerPhase phase); + + G_END_DECLS + + #endif /* __GSM_MANAGER_H */ +diff --git a/tools/gnome-session-selector.c b/tools/gnome-session-selector.c +index 1068dbba..08503a9b 100644 +--- a/tools/gnome-session-selector.c ++++ b/tools/gnome-session-selector.c +@@ -7,63 +7,60 @@ + * 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, see . + * + * Written by: Matthias Clasen + */ + + #include "config.h" + + #include + #include + #include + #include + #include + #include + + #include + #include + #include + + #include + #include + +-#include +-#include +- + #define GSM_SERVICE_DBUS "org.gnome.SessionManager" + #define GSM_PATH_DBUS "/org/gnome/SessionManager" + #define GSM_INTERFACE_DBUS "org.gnome.SessionManager" + + #define GSM_MANAGER_SCHEMA "org.gnome.SessionManager" + #define KEY_AUTOSAVE_ONE_SHOT "auto-save-session-one-shot" + #define DEFAULT_SESSION_NAME "gnome-classic" + + static GtkBuilder *builder; + static GtkWidget *session_list; + static GtkListStore *store; + static GtkTreeModelSort *sort_model; + static char *info_text; + + static void select_session (const char *name); + static gboolean make_session_current (const char *name); + + static char * + get_session_path (const char *name) + { + return g_build_filename (g_get_user_config_dir (), "gnome-session", name, NULL); + } + + static char * + find_new_session_name (void) + { + char *name; + char *path; + int i; + +@@ -694,86 +691,93 @@ on_row_activated (GtkTreeView *tree_view, + gtk_main_quit (); + } + + static void + auto_save_next_session (void) + { + GSettings *settings; + + settings = g_settings_new (GSM_MANAGER_SCHEMA); + g_settings_set_boolean (settings, KEY_AUTOSAVE_ONE_SHOT, TRUE); + g_object_unref (settings); + } + + static void + auto_save_next_session_if_needed (void) + { + char *marker; + + marker = g_build_filename (g_get_user_config_dir (), + "gnome-session", "saved-session", + ".new-session", NULL); + + if (g_file_test (marker, G_FILE_TEST_EXISTS)) { + auto_save_next_session (); + unlink (marker); + } + g_free (marker); + } + + static void +-save_session (void) ++session_saved_cb (GDBusConnection *conn, ++ GAsyncResult *result) + { +- DBusGConnection *conn; +- DBusGProxy *proxy; +- GError *error; ++ GVariant *reply; + +- conn = dbus_g_bus_get (DBUS_BUS_SESSION, NULL); +- if (conn == NULL) { +- g_warning ("Could not connect to the session bus"); +- return; +- } ++ reply = g_dbus_connection_call_finish (conn, result, NULL); + +- proxy = dbus_g_proxy_new_for_name (conn, GSM_SERVICE_DBUS, GSM_PATH_DBUS, GSM_INTERFACE_DBUS); +- if (proxy == NULL) { +- g_warning ("Could not connect to the session manager"); +- return; +- } ++ g_variant_unref (reply); ++} + +- error = NULL; +- if (!dbus_g_proxy_call (proxy, "SaveSession", &error, G_TYPE_INVALID, G_TYPE_INVALID)) { +- g_warning ("Failed to save session: %s", error->message); +- g_error_free (error); ++static void ++save_session (void) ++{ ++ GDBusConnection *conn; ++ ++ conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); ++ if (conn == NULL) { + return; + } + +- g_object_unref (proxy); ++ g_dbus_connection_call (conn, ++ GSM_SERVICE_DBUS, ++ GSM_PATH_DBUS, ++ GSM_INTERFACE_DBUS, ++ "SaveSession", ++ NULL, ++ NULL, ++ G_DBUS_CALL_FLAGS_NONE, ++ -1, ++ NULL, ++ (GAsyncReadyCallback) ++ session_saved_cb, ++ NULL); + } + + static int + compare_sessions (GtkTreeModel *model, + GtkTreeIter *a, + GtkTreeIter *b, + gpointer data) + { + char *name_a, *name_b; + int result; + + gtk_tree_model_get (model, a, 0, &name_a, -1); + gtk_tree_model_get (model, b, 0, &name_b, -1); + + result = g_utf8_collate (name_a, name_b); + + g_free (name_a); + g_free (name_b); + + return result; + } + + static void + on_map (GtkWidget *widget, + gpointer data) + { + gdk_window_focus (gtk_widget_get_window (widget), GDK_CURRENT_TIME); + } + + int +-- +2.12.0 + diff --git a/SOURCES/0019-capplet-fix-disable-check-items.patch b/SOURCES/0019-capplet-fix-disable-check-items.patch new file mode 100644 index 0000000..98cc56b --- /dev/null +++ b/SOURCES/0019-capplet-fix-disable-check-items.patch @@ -0,0 +1,91 @@ +From b502391322b2660f1bbb4fa9abcecc6cb0680a6e Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 27 Mar 2017 15:34:51 -0400 +Subject: [PATCH 19/19] capplet: fix disable check items + +An optimzation that tries to prevent transient desktop files from +accumulating in the user's homedirectory inadvertently broke the +ability for a user to disable startup applications. + +This commit restores the broken functionality. +--- + capplet/gsp-app.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/capplet/gsp-app.c b/capplet/gsp-app.c +index 123ab217..1a0580e6 100644 +--- a/capplet/gsp-app.c ++++ b/capplet/gsp-app.c +@@ -315,64 +315,65 @@ _gsp_app_user_equal_system (GspApp *app, + char *str = NULL; + GKeyFile *keyfile = NULL; + GDesktopAppInfo *app_info = NULL; + + 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) { + goto out; + } + + 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)) { + goto out; + } + + app_info = g_desktop_app_info_new_from_keyfile (keyfile); + + if (!app_info) { + goto out; + } + + if (g_desktop_app_info_get_is_hidden (app_info)) { + goto out; + } + + if (g_desktop_app_info_has_key (app_info, +- GSP_KEY_FILE_DESKTOP_KEY_AUTOSTART_ENABLED) && +- !g_desktop_app_info_get_boolean (app_info, +- GSP_KEY_FILE_DESKTOP_KEY_AUTOSTART_ENABLED)) { +- goto out; ++ GSP_KEY_FILE_DESKTOP_KEY_AUTOSTART_ENABLED)) { ++ if (app->priv->enabled != g_desktop_app_info_get_boolean (app_info, GSP_KEY_FILE_DESKTOP_KEY_AUTOSTART_ENABLED)) ++ goto out; ++ } else if (!app->priv->enabled) { ++ goto out; + } + + if (!g_desktop_app_info_get_show_in (app_info, NULL)) { + goto out; + } + + if (g_desktop_app_info_get_nodisplay (app_info)) { + goto out; + } + + str = gsp_key_file_get_locale_string (keyfile, + G_KEY_FILE_DESKTOP_KEY_NAME); + if (!_gsp_str_equal (str, app->priv->name)) { + goto out; + } + g_clear_pointer (&str, g_free); + + str = gsp_key_file_get_locale_string (keyfile, + G_KEY_FILE_DESKTOP_KEY_COMMENT); + if (!_gsp_str_equal (str, app->priv->comment)) { + goto out; + } + g_clear_pointer (&str, g_free); + + str = gsp_key_file_get_string (keyfile, + G_KEY_FILE_DESKTOP_KEY_EXEC); + if (!_gsp_str_equal (str, app->priv->exec)) { + goto out; + } + g_clear_pointer (&str, g_free); +-- +2.12.0 + diff --git a/SOURCES/custom-sessions.patch b/SOURCES/custom-sessions.patch deleted file mode 100644 index adc625b..0000000 --- a/SOURCES/custom-sessions.patch +++ /dev/null @@ -1,10921 +0,0 @@ -From 8d967c46fe8debcd3eedbb0bbf43a6545429b243 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 8 May 2015 16:24:59 -0400 -Subject: [PATCH 01/17] Revert "Remove gnome-session-properties" - -This reverts commit ea285af9962313ee2675fff27d3a852bb61e936a. ---- - Makefile.am | 1 + - capplet/Makefile.am | 31 + - 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 | 1102 +++++++++++++++++++++++++++ - capplet/gsp-app.h | 108 +++ - capplet/gsp-keyfile.c | 201 +++++ - capplet/gsp-keyfile.h | 65 ++ - capplet/main.c | 108 +++ - configure.ac | 2 + - data/Makefile.am | 6 + - data/gnome-session-properties.desktop.in.in | 15 + - doc/man/Makefile.am | 1 + - doc/man/gnome-session-properties.1 | 24 + - po/POTFILES.in | 5 + - 19 files changed, 3780 insertions(+) - create mode 100644 capplet/Makefile.am - 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 data/gnome-session-properties.desktop.in.in - create mode 100644 doc/man/gnome-session-properties.1 - -diff --git a/Makefile.am b/Makefile.am -index 6560a4e..6b6a47b 100644 ---- a/Makefile.am -+++ b/Makefile.am -@@ -1,32 +1,33 @@ - SUBDIRS = \ - gnome-session \ -+ capplet \ - tools \ - data \ - doc \ - po - - ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} - - EXTRA_DIST = \ - HACKING \ - MAINTAINERS - - MAINTAINERCLEANFILES = \ - $(srcdir)/INSTALL \ - $(srcdir)/aclocal.m4 \ - $(srcdir)/config.guess \ - $(srcdir)/config.h.in \ - $(srcdir)/config.sub \ - $(srcdir)/depcomp \ - $(srcdir)/install-sh \ - $(srcdir)/ltmain.sh \ - $(srcdir)/missing \ - $(srcdir)/mkinstalldirs \ - $(srcdir)/configure \ - $(srcdir)/m4/intltool.m4 \ - `find "$(srcdir)" -type f -name Makefile.in -print` - - CHANGELOG_GIT_RANGE = GNOME_SESSION_2_26_1.. - dist-hook: - $(AM_V_GEN)if test -d "$(srcdir)/.git"; then \ - ( echo '# Generated by Makefile. Do not edit.'; echo; \ -diff --git a/capplet/Makefile.am b/capplet/Makefile.am -new file mode 100644 -index 0000000..c2e563c ---- /dev/null -+++ b/capplet/Makefile.am -@@ -0,0 +1,31 @@ -+bin_PROGRAMS = gnome-session-properties -+ -+AM_CPPFLAGS = \ -+ $(SESSION_PROPERTIES_CFLAGS) \ -+ $(GCONF_CFLAGS) \ -+ -I$(top_srcdir)/gnome-session \ -+ -DLOCALE_DIR=\""$(datadir)/locale"\" \ -+ -DGTKBUILDER_DIR=\""$(pkgdatadir)"\" \ -+ $(DISABLE_DEPRECATED_CFLAGS) -+ -+AM_CFLAGS = $(WARN_CFLAGS) -+ -+gnome_session_properties_SOURCES = \ -+ main.c \ -+ gsm-properties-dialog.h \ -+ gsm-properties-dialog.c \ -+ gsm-app-dialog.h \ -+ gsm-app-dialog.c \ -+ gsp-app.h \ -+ gsp-app.c \ -+ gsp-app-manager.h \ -+ gsp-app-manager.c \ -+ gsp-keyfile.h \ -+ gsp-keyfile.c -+ -+gnome_session_properties_LDADD = \ -+ $(SESSION_PROPERTIES_LIBS) \ -+ $(top_builddir)/gnome-session/libgsmutil.la \ -+ $(GCONF_LIBS) -+ -+-include $(top_srcdir)/git.mk -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 -+ * -+ * 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 -+#include -+#include -+ -+#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 -+ * -+ * 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 -+#include -+ -+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 -+ * -+ * 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 -+#include -+#include -+ -+#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 -+ * -+ * 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 -+#include -+ -+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 -+ * -+ * 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 -+ -+#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 -+ * -+ * 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 -+ -+#include -+ -+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..c92b8da ---- /dev/null -+++ b/capplet/gsp-app.c -@@ -0,0 +1,1102 @@ -+/* -*- 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 -+ * -+ * 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 -+#endif -+ -+#include -+#include -+ -+#include -+#include -+ -+#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 ("%s\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 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, -+ gsm_util_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, -+ gsm_util_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 -+ * -+ * 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 -+#include -+ -+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..de9fac0 ---- /dev/null -+++ b/capplet/gsp-keyfile.c -@@ -0,0 +1,201 @@ -+/* -+ * 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 -+ */ -+ -+#include -+ -+#include -+ -+#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; -+ 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 (only_show_in) { -+ found = FALSE; -+ for (i = 0; only_show_in[i] != NULL; i++) { -+ if (g_strcmp0 (current_desktop, only_show_in[i]) == 0) { -+ 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_strcmp0 (current_desktop, not_show_in[i]) == 0) { -+ found = TRUE; -+ break; -+ } -+ } -+ -+ g_strfreev (not_show_in); -+ -+ if (found) -+ return FALSE; -+ } -+ -+ 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 -+ */ -+ -+#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 -+ -+#include -+#include -+ -+#include -+#include -+ -+#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/configure.ac b/configure.ac -index 6485d57..b67c0e6 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -301,65 +301,67 @@ if test $enable_ipv6 = yes; then - ]])], - [have_ipv6=yes], - [have_ipv6=no] - ) - AC_MSG_RESULT($have_ipv6) - - dnl ================================================================= - dnl Now we would check for specific function like getaddrinfo. - dnl ================================================================= - have_getaddrinfo=no - if test $have_ipv6=yes; then - AC_CHECK_FUNC(getaddrinfo, have_getaddrinfo=yes) - if test $have_getaddrinfo != yes; then - # getaddrinfo is not in the default libraries. See if it's in some other. - for lib in bsd socket inet; do - AC_CHECK_LIB($lib, getaddrinfo, [LIBS="$LIBS -l$lib";have_getaddrinfo=yes; break]) - done - fi - if test $have_getaddrinfo=yes; then - AC_DEFINE(ENABLE_IPV6, 1, [Define if IPV6 is supported]) - have_full_ipv6=yes - fi - fi - fi - dnl ============================================================================== - dnl End of IPv6 checks - dnl ============================================================================== - - AC_CONFIG_FILES([ - Makefile -+capplet/Makefile - doc/Makefile - doc/dbus/Makefile - doc/dbus/gnome-session.xml - doc/man/Makefile - data/Makefile -+data/gnome-session-properties.desktop.in - data/org.gnome.SessionManager.gschema.xml - data/icons/Makefile - data/icons/16x16/Makefile - data/icons/22x22/Makefile - data/icons/24x24/Makefile - data/icons/32x32/Makefile - data/icons/48x48/Makefile - data/icons/scalable/Makefile - gnome-session/Makefile - tools/Makefile - po/Makefile.in - ]) - AC_OUTPUT - - dnl --------------------------------------------------------------------------- - dnl - Show summary - dnl --------------------------------------------------------------------------- - - echo " - gnome-session $VERSION - `echo gnome-session $VERSION | sed "s/./=/g"` - - prefix: ${prefix} - exec_prefix: ${exec_prefix} - libdir: ${libdir} - bindir: ${bindir} - sbindir: ${sbindir} - sysconfdir: ${sysconfdir} - localstatedir: ${localstatedir} - datadir: ${datadir} -diff --git a/data/Makefile.am b/data/Makefile.am -index d1d8d25..524cc6e 100644 ---- a/data/Makefile.am -+++ b/data/Makefile.am -@@ -1,68 +1,74 @@ - SUBDIRS = icons - - uidir = $(pkgdatadir) - ui_DATA = \ - session-properties.ui - - if BUILD_SESSION_SELECTOR - ui_DATA += session-selector.ui - endif - - hwcompatdir = $(pkgdatadir) - hwcompat_DATA = hardware-compatibility - - xsessiondir = $(datadir)/xsessions - xsession_in_files = gnome.desktop.in - - if BUILD_SESSION_SELECTOR - xsession_in_files += gnome-custom-session.desktop.in - endif - - xsession_DATA = $(xsession_in_files:.desktop.in=.desktop) - - wayland_sessiondir = $(datadir)/wayland-sessions - wayland_session_in_files = gnome-wayland.desktop.in - wayland_session_DATA = $(wayland_session_in_files:.desktop.in=.desktop) - -+desktopdir = $(datadir)/applications -+desktop_in_files = gnome-session-properties.desktop.in -+desktop_DATA = $(desktop_in_files:.desktop.in=.desktop) -+ - sessiondir = $(datadir)/gnome-session/sessions - session_in_in_files = gnome.session.desktop.in.in gnome-dummy.session.desktop.in.in gnome-wayland.session.desktop.in.in - session_in_files = $(session_in_in_files:.session.desktop.in.in=.session.desktop.in) - session_DATA = $(session_in_files:.session.desktop.in=.session) - - %.session.desktop.in: %.session.desktop.in.in Makefile - $(AM_V_GEN)sed \ - -e "s|\@LIBEXECDIR\@|$(libexecdir)|" \ - $< > $@ - - %.session: %.session.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@ - - @INTLTOOL_DESKTOP_RULE@ - @INTLTOOL_XML_NOMERGE_RULE@ - - gsettings_SCHEMAS = org.gnome.SessionManager.gschema.xml - @GSETTINGS_RULES@ - - migrationdir = $(datadir)/GConf/gsettings - dist_migration_DATA = gnome-session.convert - - EXTRA_DIST = \ - $(xsession_in_files) \ - $(session_in_in_files) \ - $(wayland_session_in_files) \ - $(gsettings_SCHEMAS:.xml=.xml.in) \ - session-selector.ui \ - gnome-custom-session.desktop.in \ - $(ui_DATA) \ - $(hwcompat_DATA) - - CLEANFILES = \ - $(gsettings_SCHEMAS) \ - $(xsession_DATA) \ - $(wayland_session_DATA) \ -+ $(desktop_DATA) \ - $(session_DATA) - - DISTCLEANFILES = \ - $(gsettings_SCHEMAS) \ -+ $(desktop_in_files) \ - $(wayland_session_in_files) - - -include $(top_srcdir)/git.mk -diff --git a/data/gnome-session-properties.desktop.in.in b/data/gnome-session-properties.desktop.in.in -new file mode 100644 -index 0000000..3dc7b03 ---- /dev/null -+++ b/data/gnome-session-properties.desktop.in.in -@@ -0,0 +1,15 @@ -+[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; -+NoDisplay=true -+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/doc/man/Makefile.am b/doc/man/Makefile.am -index 02e5c62..2879423 100644 ---- a/doc/man/Makefile.am -+++ b/doc/man/Makefile.am -@@ -1,29 +1,30 @@ - XSLTPROC_FLAGS = \ - --nonet \ - --stringparam man.output.quietly 1 \ - --stringparam funcsynopsis.style ansi \ - --stringparam man.th.extra1.suppress 1 \ - --stringparam man.authors.section.enabled 0 \ - --stringparam man.copyright.section.enabled 0 - - .xml.1: - $(AM_V_GEN) $(XSLTPROC) $(XSLTPROC_FLAGS) http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl $< - - man_MANS = \ - gnome-session.1 \ -+ gnome-session-properties.1 \ - gnome-session-quit.1 \ - gnome-session-inhibit.1 - - if BUILD_SESSION_SELECTOR - man_MANS += gnome-session-selector.1 - endif - - EXTRA_DIST = \ - gnome-session-inhibit.xml \ - gnome-session-selector.xml \ - $(man_MANS) - - CLEANFILES = \ - gnome-session-inhibit.1 - - -include $(top_srcdir)/git.mk -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/po/POTFILES.in b/po/POTFILES.in -index 5a887ec..9221412 100644 ---- a/po/POTFILES.in -+++ b/po/POTFILES.in -@@ -1,20 +1,25 @@ - # 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 - data/gnome.desktop.in - data/gnome-dummy.session.desktop.in.in - data/gnome.session.desktop.in.in -+data/gnome-session-properties.desktop.in.in - data/gnome-wayland.desktop.in - data/gnome-wayland.session.desktop.in.in - [type: gettext/glade]data/session-selector.ui - [type: gettext/glade]data/session-properties.ui - gnome-session/gsm-fail-whale-dialog.c - gnome-session/gsm-manager.c - gnome-session/gsm-process-helper.c - gnome-session/gsm-util.c - gnome-session/gsm-xsmp-client.c - gnome-session/gsm-xsmp-server.c - gnome-session/main.c - tools/gnome-session-inhibit.c - tools/gnome-session-selector.c - tools/gnome-session-quit.c --- -2.3.7 - - -From 36694037511ac9d61270c7194118cb3fbb438ab7 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 8 May 2015 16:27:15 -0400 -Subject: [PATCH 02/17] Revert "Rename the desktop file to - gnome-session-properties.desktop" - -This reverts commit ac9fd0dc97a17674cb082f80df0b1fcc45bc92bf. ---- - configure.ac | 2 +- - data/Makefile.am | 2 +- - data/gnome-session-properties.desktop.in.in | 15 --------------- - data/session-properties.desktop.in.in | 15 +++++++++++++++ - po/POTFILES.in | 1 + - po/POTFILES.skip | 3 ++- - 6 files changed, 20 insertions(+), 18 deletions(-) - delete mode 100644 data/gnome-session-properties.desktop.in.in - create mode 100644 data/session-properties.desktop.in.in - -diff --git a/configure.ac b/configure.ac -index b67c0e6..0990e70 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -307,61 +307,61 @@ if test $enable_ipv6 = yes; then - dnl ================================================================= - dnl Now we would check for specific function like getaddrinfo. - dnl ================================================================= - have_getaddrinfo=no - if test $have_ipv6=yes; then - AC_CHECK_FUNC(getaddrinfo, have_getaddrinfo=yes) - if test $have_getaddrinfo != yes; then - # getaddrinfo is not in the default libraries. See if it's in some other. - for lib in bsd socket inet; do - AC_CHECK_LIB($lib, getaddrinfo, [LIBS="$LIBS -l$lib";have_getaddrinfo=yes; break]) - done - fi - if test $have_getaddrinfo=yes; then - AC_DEFINE(ENABLE_IPV6, 1, [Define if IPV6 is supported]) - have_full_ipv6=yes - fi - fi - fi - dnl ============================================================================== - dnl End of IPv6 checks - dnl ============================================================================== - - AC_CONFIG_FILES([ - Makefile - capplet/Makefile - doc/Makefile - doc/dbus/Makefile - doc/dbus/gnome-session.xml - doc/man/Makefile - data/Makefile --data/gnome-session-properties.desktop.in -+data/session-properties.desktop.in - data/org.gnome.SessionManager.gschema.xml - data/icons/Makefile - data/icons/16x16/Makefile - data/icons/22x22/Makefile - data/icons/24x24/Makefile - data/icons/32x32/Makefile - data/icons/48x48/Makefile - data/icons/scalable/Makefile - gnome-session/Makefile - tools/Makefile - po/Makefile.in - ]) - AC_OUTPUT - - dnl --------------------------------------------------------------------------- - dnl - Show summary - dnl --------------------------------------------------------------------------- - - echo " - gnome-session $VERSION - `echo gnome-session $VERSION | sed "s/./=/g"` - - prefix: ${prefix} - exec_prefix: ${exec_prefix} - libdir: ${libdir} - bindir: ${bindir} - sbindir: ${sbindir} - sysconfdir: ${sysconfdir} - localstatedir: ${localstatedir} - datadir: ${datadir} -diff --git a/data/Makefile.am b/data/Makefile.am -index 524cc6e..8834fcb 100644 ---- a/data/Makefile.am -+++ b/data/Makefile.am -@@ -1,58 +1,58 @@ - SUBDIRS = icons - - uidir = $(pkgdatadir) - ui_DATA = \ - session-properties.ui - - if BUILD_SESSION_SELECTOR - ui_DATA += session-selector.ui - endif - - hwcompatdir = $(pkgdatadir) - hwcompat_DATA = hardware-compatibility - - xsessiondir = $(datadir)/xsessions - xsession_in_files = gnome.desktop.in - - if BUILD_SESSION_SELECTOR - xsession_in_files += gnome-custom-session.desktop.in - endif - - xsession_DATA = $(xsession_in_files:.desktop.in=.desktop) - - wayland_sessiondir = $(datadir)/wayland-sessions - wayland_session_in_files = gnome-wayland.desktop.in - wayland_session_DATA = $(wayland_session_in_files:.desktop.in=.desktop) - - desktopdir = $(datadir)/applications --desktop_in_files = gnome-session-properties.desktop.in -+desktop_in_files = session-properties.desktop.in - desktop_DATA = $(desktop_in_files:.desktop.in=.desktop) - - sessiondir = $(datadir)/gnome-session/sessions - session_in_in_files = gnome.session.desktop.in.in gnome-dummy.session.desktop.in.in gnome-wayland.session.desktop.in.in - session_in_files = $(session_in_in_files:.session.desktop.in.in=.session.desktop.in) - session_DATA = $(session_in_files:.session.desktop.in=.session) - - %.session.desktop.in: %.session.desktop.in.in Makefile - $(AM_V_GEN)sed \ - -e "s|\@LIBEXECDIR\@|$(libexecdir)|" \ - $< > $@ - - %.session: %.session.desktop.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@ - - @INTLTOOL_DESKTOP_RULE@ - @INTLTOOL_XML_NOMERGE_RULE@ - - gsettings_SCHEMAS = org.gnome.SessionManager.gschema.xml - @GSETTINGS_RULES@ - - migrationdir = $(datadir)/GConf/gsettings - dist_migration_DATA = gnome-session.convert - - EXTRA_DIST = \ - $(xsession_in_files) \ - $(session_in_in_files) \ - $(wayland_session_in_files) \ - $(gsettings_SCHEMAS:.xml=.xml.in) \ - session-selector.ui \ - gnome-custom-session.desktop.in \ -diff --git a/data/gnome-session-properties.desktop.in.in b/data/gnome-session-properties.desktop.in.in -deleted file mode 100644 -index 3dc7b03..0000000 ---- a/data/gnome-session-properties.desktop.in.in -+++ /dev/null -@@ -1,15 +0,0 @@ --[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; --NoDisplay=true --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/session-properties.desktop.in.in b/data/session-properties.desktop.in.in -new file mode 100644 -index 0000000..3dc7b03 ---- /dev/null -+++ b/data/session-properties.desktop.in.in -@@ -0,0 +1,15 @@ -+[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; -+NoDisplay=true -+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/po/POTFILES.in b/po/POTFILES.in -index 9221412..b18fcab 100644 ---- a/po/POTFILES.in -+++ b/po/POTFILES.in -@@ -1,25 +1,26 @@ - # 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 - data/gnome.desktop.in - data/gnome-dummy.session.desktop.in.in - data/gnome.session.desktop.in.in - data/gnome-session-properties.desktop.in.in - data/gnome-wayland.desktop.in - data/gnome-wayland.session.desktop.in.in - [type: gettext/glade]data/session-selector.ui -+data/session-properties.desktop.in.in - [type: gettext/glade]data/session-properties.ui - gnome-session/gsm-fail-whale-dialog.c - gnome-session/gsm-manager.c - gnome-session/gsm-process-helper.c - gnome-session/gsm-util.c - gnome-session/gsm-xsmp-client.c - gnome-session/gsm-xsmp-server.c - gnome-session/main.c - tools/gnome-session-inhibit.c - tools/gnome-session-selector.c - tools/gnome-session-quit.c -diff --git a/po/POTFILES.skip b/po/POTFILES.skip -index c5d4ac9..6f57edc 100644 ---- a/po/POTFILES.skip -+++ b/po/POTFILES.skip -@@ -1,9 +1,10 @@ - # List of source files containing translatable strings that should not be - # translated. - # Please keep this file sorted alphabetically. - data/gnome-dummy.session.desktop.in - data/gnome.session.desktop.in --data/gnome-session-properties.desktop.in -+data/session-properties.desktop.in. - data/gnome-session.schemas.in - data/gnome-wayland.session.desktop.in - data/gnome-wm.desktop.in -+data/session-properties.desktop.in --- -2.3.7 - - -From 2ed0c1357a3fc729b2f5a86662fb15609c1d81a5 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Wed, 13 May 2015 10:56:09 -0400 -Subject: [PATCH 03/17] stop using gsm_util_get_current_desktop - -It no longer exists. ---- - capplet/gsp-app.c | 111 +++++++++++++++++++++++++++++------------------------- - 1 file changed, 60 insertions(+), 51 deletions(-) - -diff --git a/capplet/gsp-app.c b/capplet/gsp-app.c -index c92b8da..123ab21 100644 ---- a/capplet/gsp-app.c -+++ b/capplet/gsp-app.c -@@ -3,60 +3,61 @@ - * Copyright (C) 1999 Free Software Foundation, Inc. - * Copyright (C) 2007, 2009 Vincent Untz. - * Copyright (C) 2008 Lucas Rocha. - * Copyright (C) 2008 William Jon McCann - * - * 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 - #endif - - #include - #include - - #include - #include -+#include - - #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; -@@ -281,148 +282,145 @@ _gsp_app_update_description (GspApp *app) - } else { - secondary = _("No description"); - } - - g_free (app->priv->description); - app->priv->description = g_markup_printf_escaped ("%s\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 gboolean - _gsp_app_user_equal_system (GspApp *app, - char **system_path) - { - GspAppManager *manager; -- const char *system_dir; -- char *path; -- char *str; -- GKeyFile *keyfile; -+ gboolean return_value = FALSE; -+ const char *system_dir = NULL; -+ char *path = NULL; -+ char *str = NULL; -+ GKeyFile *keyfile = NULL; -+ GDesktopAppInfo *app_info = NULL; - - 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; -+ goto out; - } - - 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; -+ goto out; - } - -- 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, -- gsm_util_get_current_desktop ()) != app->priv->shown) { -- g_free (path); -- g_key_file_free (keyfile); -- return FALSE; -+ app_info = g_desktop_app_info_new_from_keyfile (keyfile); -+ -+ if (!app_info) { -+ goto out; - } - -- 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; -+ if (g_desktop_app_info_get_is_hidden (app_info)) { -+ goto out; -+ } -+ -+ if (g_desktop_app_info_has_key (app_info, -+ GSP_KEY_FILE_DESKTOP_KEY_AUTOSTART_ENABLED) && -+ !g_desktop_app_info_get_boolean (app_info, -+ GSP_KEY_FILE_DESKTOP_KEY_AUTOSTART_ENABLED)) { -+ goto out; -+ } -+ -+ if (!g_desktop_app_info_get_show_in (app_info, NULL)) { -+ goto out; -+ } -+ -+ if (g_desktop_app_info_get_nodisplay (app_info)) { -+ goto out; - } - - 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; -+ goto out; - } -- g_free (str); -+ g_clear_pointer (&str, g_free); - - 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; -+ goto out; - } -- g_free (str); -+ g_clear_pointer (&str, g_free); - - 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; -+ goto out; - } -- g_free (str); -+ g_clear_pointer (&str, g_free); - - 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; -+ goto out; - } -- g_free (str); -- -- g_key_file_free (keyfile); -+ g_clear_pointer (&str, g_free); - - *system_path = path; -- -- return TRUE; -+ path = NULL; -+ return_value = TRUE; -+out: -+ g_clear_pointer (&path, g_free); -+ g_clear_pointer (&str, g_free); -+ g_clear_object (&app_info); -+ g_clear_pointer (&keyfile, g_key_file_free); -+ -+ return return_value; - } - - 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); - } -@@ -748,153 +746,164 @@ gsp_app_delete (GspApp *app) - 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; -+ GDesktopAppInfo *app_info; - 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; - } - -+ app_info = g_desktop_app_info_new_from_keyfile (keyfile); -+ -+ if (!app_info) { -+ g_object_unref (app_info); -+ 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, -- gsm_util_get_current_desktop ()); -+ app->priv->shown = g_desktop_app_info_get_show_in (app_info, NULL); - - 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_object_unref (app_info); - 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; --- -2.3.7 - - -From 6b24a33c89913eec63a1547d5e372833e5c25a30 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 20 Dec 2013 10:48:03 -0500 -Subject: [PATCH 04/17] session-properties: show it in the menus again - -It provides functionality for adjusting the session which -customers rely on, so make it show up in the menus again. ---- - data/session-properties.desktop.in.in | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/data/session-properties.desktop.in.in b/data/session-properties.desktop.in.in -index 3dc7b03..1a506d9 100644 ---- a/data/session-properties.desktop.in.in -+++ b/data/session-properties.desktop.in.in -@@ -1,15 +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; --NoDisplay=true - X-GNOME-Bugzilla-Bugzilla=GNOME - X-GNOME-Bugzilla-Product=gnome-session - X-GNOME-Bugzilla-Component=gnome-session-properties - X-GNOME-Bugzilla-Version=@VERSION@ --- -2.3.7 - - -From 9fe478de117315c714d63a73b6c143b50a57912e Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 20 Dec 2013 15:07:35 -0500 -Subject: [PATCH 05/17] session-properties: get out of Other - -Put it in the menus next to Settings and Software ---- - data/session-properties.desktop.in.in | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/data/session-properties.desktop.in.in b/data/session-properties.desktop.in.in -index 1a506d9..e615d5c 100644 ---- a/data/session-properties.desktop.in.in -+++ b/data/session-properties.desktop.in.in -@@ -1,14 +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; -+Categories=GNOME;GTK;System; - 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@ --- -2.3.7 - - -From 0e2261200550ebe0a0e455b550b227d12c47ac50 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 20 Dec 2013 10:53:33 -0500 -Subject: [PATCH 06/17] session-properties: refresh from recent glade - -The ui file is rather old. This commit just opens it up in a recent -glade and resaves it, so we have a fresh starting point to make -changes. ---- - data/session-properties.ui | 43 ++++++++++++++++++++++++++++++++++--------- - 1 file changed, 34 insertions(+), 9 deletions(-) - -diff --git a/data/session-properties.ui b/data/session-properties.ui -index 1f0cb9a..47a30f7 100644 ---- a/data/session-properties.ui -+++ b/data/session-properties.ui -@@ -1,323 +1,348 @@ -- -+ - -- -- -+ - - True - True - 6 - - - True -+ False - 12 -- vertical - 3 - - - True -+ False - 0 - 3 - 3 - Additional startup _programs: - True - session_properties_treeview - - - False -+ True - 0 - - - - - True -+ False - 6 - - - True - True - never -- automatic - etched-in - - - 210 - True - True -+ -+ -+ - - - - -+ True -+ True - 0 - - - - - True -+ False - 6 - start - - - gtk-add - True - True - True - True - - - False - False - 0 - - - - - gtk-remove - True - False - True - True - True - - - False - False - 1 - - - - - gtk-edit - True - False - True - True - True - - - False - False - 2 - - - - - False - False - 1 - - - - -+ True -+ True - 1 - - - - - - - True -+ False - Startup Programs - - - False - - - - - True -+ False - 12 -- vertical - 6 - - - _Automatically remember running applications when logging out - True - True - False - True -+ 0.5 - True - - - False - False - 0 - - - - - True -+ False - - - True - True - - - True -+ False - 4 - - - True -+ False - gtk-save - - - False - False - 0 - - - - - True -+ False - _Remember Currently Running Applications - True - - -+ True -+ True - 1 - - - - - - - False - False - 0 - - - - - False - False - 1 - - - - - 1 - - - - - True -+ False - Options - - - 1 - False - - - - - True -+ False - 6 - 3 - 2 - 12 - 6 - - - True -+ False - 12 - - - True - True -- -+ - - -+ True -+ True - 0 - - - - - Browse… - True - True - True - - - False - False - 1 - - - - - 1 - 2 - 1 - 2 - GTK_FILL - - - - - True - True -- -+ - - - 1 - 2 - 2 - 3 - GTK_FILL - - - - - True - True -- -+ - - - 1 - 2 - GTK_FILL - - - - - True -+ False - 0 - Comm_ent: - True - label2 - - - 2 - 3 - GTK_FILL - GTK_FILL - - - - - True -+ False - 0 - Co_mmand: - True - session_properties_command_entry - - - 1 - 2 - GTK_FILL - GTK_FILL - - - - - True -+ False - 0 - _Name: - True - session_properties_name_entry - - - GTK_FILL - GTK_FILL - - - - --- -2.3.7 - - -From 70e758b03d9b4a018c196cf58d4147709ae1eb5e Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 20 Dec 2013 16:14:16 -0500 -Subject: [PATCH 07/17] manager: Don't clear saved session if autosaving is - disabled - -Now that we support on-demand saving again, we need to make sure -we don't wipe that away at log out. ---- - gnome-session/gsm-manager.c | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/gnome-session/gsm-manager.c b/gnome-session/gsm-manager.c -index 596db92..c32bbe4 100644 ---- a/gnome-session/gsm-manager.c -+++ b/gnome-session/gsm-manager.c -@@ -1952,61 +1952,60 @@ on_xsmp_client_register_confirmed (GsmXSMPClient *client, - app = find_app_for_startup_id (manager, id); - - if (app != NULL) { - gsm_app_registered (app); - } - } - - static gboolean - auto_save_is_enabled (GsmManager *manager) - { - return g_settings_get_boolean (manager->priv->settings, KEY_AUTOSAVE_ONE_SHOT) - || g_settings_get_boolean (manager->priv->settings, KEY_AUTOSAVE); - } - - static void - maybe_save_session (GsmManager *manager) - { - GError *error; - - if (gsm_system_is_login_session (manager->priv->system)) - return; - - /* We only allow session saving when session is running or when - * logging out */ - if (manager->priv->phase != GSM_MANAGER_PHASE_RUNNING && - manager->priv->phase != GSM_MANAGER_PHASE_END_SESSION) { - return; - } - - if (!auto_save_is_enabled (manager)) { -- gsm_session_save_clear (); - return; - } - - error = NULL; - gsm_session_save (manager->priv->clients, &error); - - if (error) { - g_warning ("Error saving session: %s", error->message); - g_error_free (error); - } - } - - static void - _handle_client_end_session_response (GsmManager *manager, - GsmClient *client, - gboolean is_ok, - gboolean do_last, - gboolean cancel, - const char *reason) - { - /* just ignore if received outside of shutdown */ - if (manager->priv->phase < GSM_MANAGER_PHASE_QUERY_END_SESSION) { - return; - } - - g_debug ("GsmManager: Response from end session request: is-ok=%d do-last=%d cancel=%d reason=%s", is_ok, do_last, cancel, reason ? reason :""); - - if (cancel) { - cancel_end_session (manager); - return; --- -2.3.7 - - -From 4d41334693ccf1617f242326d1c5a9e367a54169 Mon Sep 17 00:00:00 2001 -From: Josselin Mouette -Date: Mon, 21 Jun 2010 15:22:23 -0400 -Subject: [PATCH 08/17] Add "Remember Currently Running Applications" button - -This adds back session saving that's not at logout. ---- - capplet/gsm-properties-dialog.c | 63 +++++++++++- - configure.ac | 1 + - data/session-properties.ui | 12 +++ - gnome-session/gsm-client.c | 10 ++ - gnome-session/gsm-client.h | 6 ++ - gnome-session/gsm-dbus-client.c | 14 +++ - gnome-session/gsm-manager.c | 150 ++++++++++++++++++++++++++++- - gnome-session/gsm-manager.h | 3 + - gnome-session/gsm-xsmp-client.c | 37 +++++++ - gnome-session/gsm-xsmp-client.h | 3 +- - gnome-session/org.gnome.SessionManager.xml | 8 ++ - 11 files changed, 303 insertions(+), 4 deletions(-) - -diff --git a/capplet/gsm-properties-dialog.c b/capplet/gsm-properties-dialog.c -index 33812b8..d2be778 100644 ---- a/capplet/gsm-properties-dialog.c -+++ b/capplet/gsm-properties-dialog.c -@@ -5,70 +5,77 @@ - * Copyright (C) 2008 Lucas Rocha. - * Copyright (C) 2008 William Jon McCann - * - * 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 - #include - #include - - #include "gsm-properties-dialog.h" - #include "gsm-app-dialog.h" - #include "gsm-util.h" - #include "gsp-app.h" - #include "gsp-app-manager.h" -+#include -+#include -+ -+#define GSM_SERVICE_DBUS "org.gnome.SessionManager" -+#define GSM_PATH_DBUS "/org/gnome/SessionManager" -+#define GSM_INTERFACE_DBUS "org.gnome.SessionManager" - - #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_SESSION_SAVED_WIDGET_NAME "session_properties_session_saved_label" - #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, -@@ -431,64 +438,118 @@ on_edit_app_clicked (GtkWidget *widget, - 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 -+session_saved_message (GsmPropertiesDialog *dialog, -+ const char *msg, -+ gboolean is_error) -+{ -+ GtkLabel *label; -+ gchar *markup; -+ label = GTK_LABEL (gtk_builder_get_object (dialog->priv->xml, CAPPLET_SESSION_SAVED_WIDGET_NAME)); -+ if (is_error) -+ markup = g_markup_printf_escaped ("%s", msg); -+ else -+ markup = g_markup_escape_text (msg, -1); -+ gtk_label_set_markup (label, markup); -+ g_free (markup); -+} -+ -+static void -+session_saved_cb (DBusGProxy *proxy, -+ DBusGProxyCall *call_id, -+ void *user_data) -+{ -+ gboolean res; -+ GsmPropertiesDialog *dialog = user_data; -+ -+ res = dbus_g_proxy_end_call (proxy, call_id, NULL, G_TYPE_INVALID); -+ if (res) -+ session_saved_message (dialog, _("Your session has been saved."), FALSE); -+ else -+ session_saved_message (dialog, _("Failed to save session"), TRUE); -+ -+ g_object_unref (proxy); -+} -+ -+static void - on_save_session_clicked (GtkWidget *widget, - GsmPropertiesDialog *dialog) - { -- g_debug ("Session saving is not implemented yet!"); -+ DBusGConnection *conn; -+ DBusGProxy *proxy; -+ DBusGProxyCall *call; -+ -+ conn = dbus_g_bus_get (DBUS_BUS_SESSION, NULL); -+ if (conn == NULL) { -+ session_saved_message (dialog, _("Could not connect to the session bus"), TRUE); -+ return; -+ } -+ -+ proxy = dbus_g_proxy_new_for_name (conn, GSM_SERVICE_DBUS, GSM_PATH_DBUS, GSM_INTERFACE_DBUS); -+ if (proxy == NULL) { -+ session_saved_message (dialog, _("Could not connect to the session manager"), TRUE); -+ return; -+ } -+ -+ call = dbus_g_proxy_begin_call (proxy, "SaveSession", session_saved_cb, dialog, NULL, G_TYPE_INVALID); -+ if (call == NULL) { -+ session_saved_message (dialog, _("Failed to save session"), TRUE); -+ g_object_unref (proxy); -+ return; -+ } - } - - 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), -diff --git a/configure.ac b/configure.ac -index 0990e70..505292c 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -52,60 +52,61 @@ if test "$enable_session_selector" = yes; then - fi - - dnl ==================================================================== - dnl Dependency Checks - dnl ==================================================================== - - dnl Standard vertical stacks - PKG_CHECK_MODULES(GIO, gio-2.0) - PKG_CHECK_MODULES(GIOUNIX, gio-unix-2.0 >= $GLIB_REQUIRED) - PKG_CHECK_MODULES(GTK3, gtk+-3.0 >= $GTK3_REQUIRED) - - PKG_CHECK_MODULES(GNOME_SESSION, - glib-2.0 >= $GLIB_REQUIRED - gio-2.0 >= $GLIB_REQUIRED - dbus-glib-1 >= $DBUS_GLIB_REQUIRED - json-glib-1.0 >= $JSON_GLIB_REQUIRED - gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED - ) - - dnl We can only support old upower - dnl https://bugzilla.gnome.org/show_bug.cgi?id=710383 - PKG_CHECK_MODULES(UPOWER, upower-glib < 0.99.0, have_old_upower=yes, have_old_upower=no) - AS_IF([test x$have_old_upower = xyes], [ - AC_DEFINE([HAVE_OLD_UPOWER], [1], [Define if we have an older upower]) - ]) - AM_CONDITIONAL(HAVE_OLD_UPOWER, test x$have_old_upower = xyes) - - PKG_CHECK_MODULES(SESSION_PROPERTIES, - glib-2.0 >= $GLIB_REQUIRED - gtk+-3.0 >= $GTK3_REQUIRED -+ dbus-glib-1 >= $DBUS_GLIB_REQUIRED - ) - - PKG_CHECK_MODULES(X11, x11) - PKG_CHECK_MODULES(SM, sm) - PKG_CHECK_MODULES(ICE, ice) - PKG_CHECK_MODULES(XEXT, xext xau) - - PKG_CHECK_MODULES(DBUS_GLIB, dbus-glib-1 >= $DBUS_GLIB_REQUIRED) - - PKG_CHECK_MODULES(EGG_SMCLIENT, gtk+-3.0) - - PKG_CHECK_MODULES(GL_TEST, xcomposite gl glib-2.0) - - dnl ==================================================================== - dnl Check for gconf - dnl ==================================================================== - AC_ARG_ENABLE([gconf], - AS_HELP_STRING([--enable-gconf], [Support gconf-based autostart]), - [enable_gconf=$enableval], - [enable_gconf=auto]) - - PKG_CHECK_MODULES(GCONF, gconf-2.0, [have_gconf=yes], [have_gconf=no]) - - if test x$enable_gconf = xauto ; then - enable_gconf=$have_gconf - elif test x$enable_gconf = xyes -a x$have_gconf = xno ; then - AC_MSG_ERROR([GConf support explicitly required, but gconf not found]) - fi - - if test x$enable_gconf = xyes ; then -diff --git a/data/session-properties.ui b/data/session-properties.ui -index 47a30f7..b43759f 100644 ---- a/data/session-properties.ui -+++ b/data/session-properties.ui -@@ -133,108 +133,120 @@ - - - - - True - False - 12 - 6 - - - _Automatically remember running applications when logging out - True - True - False - True - 0.5 - True - - - False - False - 0 - - - - - True - False - - -+ True - True - True - - - True - False - 4 - - - True - False - gtk-save - - - False - False - 0 - - - - - True - False - _Remember Currently Running Applications - True - - - True - True - 1 - - - - - - - False - False - 0 - - - - - False - False - 1 - - -+ -+ -+ True -+ True -+ -+ -+ False -+ False -+ 2 -+ -+ - - - 1 - - - - - True - False - Options - - - 1 - False - - - - - True - False - 6 - 3 - 2 - 12 - 6 - - - True - False - 12 -diff --git a/gnome-session/gsm-client.c b/gnome-session/gsm-client.c -index 543d7ef..23f0f56 100644 ---- a/gnome-session/gsm-client.c -+++ b/gnome-session/gsm-client.c -@@ -493,49 +493,59 @@ gsm_client_query_end_session (GsmClient *client, - g_return_val_if_fail (GSM_IS_CLIENT (client), FALSE); - - return GSM_CLIENT_GET_CLASS (client)->impl_query_end_session (client, flags, error); - } - - gboolean - gsm_client_end_session (GsmClient *client, - GsmClientEndSessionFlag flags, - GError **error) - { - g_return_val_if_fail (GSM_IS_CLIENT (client), FALSE); - - return GSM_CLIENT_GET_CLASS (client)->impl_end_session (client, flags, error); - } - - gboolean - gsm_client_stop (GsmClient *client, - GError **error) - { - g_return_val_if_fail (GSM_IS_CLIENT (client), FALSE); - - return GSM_CLIENT_GET_CLASS (client)->impl_stop (client, error); - } - - void - gsm_client_disconnected (GsmClient *client) - { - g_signal_emit (client, signals[DISCONNECTED], 0); - } - -+gboolean -+gsm_client_request_save (GsmClient *client, -+ guint flags, -+ GError **error) -+{ -+ g_return_val_if_fail (GSM_IS_CLIENT (client), FALSE); -+ -+ return GSM_CLIENT_GET_CLASS (client)->impl_request_save (client, flags, error); -+} -+ - GKeyFile * - gsm_client_save (GsmClient *client, - GError **error) - { - g_return_val_if_fail (GSM_IS_CLIENT (client), FALSE); - - return GSM_CLIENT_GET_CLASS (client)->impl_save (client, error); - } - - void - gsm_client_end_session_response (GsmClient *client, - gboolean is_ok, - gboolean do_last, - gboolean cancel, - const char *reason) - { - g_signal_emit (client, signals[END_SESSION_RESPONSE], 0, - is_ok, do_last, cancel, reason); - } -diff --git a/gnome-session/gsm-client.h b/gnome-session/gsm-client.h -index 4ef5dc9..46c913a 100644 ---- a/gnome-session/gsm-client.h -+++ b/gnome-session/gsm-client.h -@@ -63,105 +63,111 @@ struct _GsmClient - GObject parent; - GsmClientPrivate *priv; - }; - - struct _GsmClientClass - { - GObjectClass parent_class; - - /* signals */ - void (*disconnected) (GsmClient *client); - void (*end_session_response) (GsmClient *client, - gboolean ok, - gboolean do_last, - gboolean cancel, - const char *reason); - - /* virtual methods */ - char * (*impl_get_app_name) (GsmClient *client); - GsmClientRestartStyle (*impl_get_restart_style_hint) (GsmClient *client); - guint (*impl_get_unix_process_id) (GsmClient *client); - gboolean (*impl_query_end_session) (GsmClient *client, - GsmClientEndSessionFlag flags, - GError **error); - gboolean (*impl_end_session) (GsmClient *client, - GsmClientEndSessionFlag flags, - GError **error); - gboolean (*impl_cancel_end_session) (GsmClient *client, - GError **error); - gboolean (*impl_stop) (GsmClient *client, - GError **error); -+ gboolean (*impl_request_save) (GsmClient *client, -+ guint flags, -+ GError **error); - GKeyFile * (*impl_save) (GsmClient *client, - GError **error); - }; - - typedef enum - { - GSM_CLIENT_ERROR_GENERAL = 0, - GSM_CLIENT_ERROR_NOT_REGISTERED, - GSM_CLIENT_NUM_ERRORS - } GsmClientError; - - #define GSM_CLIENT_ERROR gsm_client_error_quark () - #define GSM_CLIENT_TYPE_ERROR (gsm_client_error_get_type ()) - - GType gsm_client_error_get_type (void); - GQuark gsm_client_error_quark (void); - - GType gsm_client_get_type (void) G_GNUC_CONST; - - const char *gsm_client_peek_id (GsmClient *client); - - - const char * gsm_client_peek_startup_id (GsmClient *client); - const char * gsm_client_peek_app_id (GsmClient *client); - guint gsm_client_peek_restart_style_hint (GsmClient *client); - guint gsm_client_peek_status (GsmClient *client); - - - char *gsm_client_get_app_name (GsmClient *client); - void gsm_client_set_app_id (GsmClient *client, - const char *app_id); - void gsm_client_set_status (GsmClient *client, - guint status); - - gboolean gsm_client_end_session (GsmClient *client, - guint flags, - GError **error); - gboolean gsm_client_query_end_session (GsmClient *client, - guint flags, - GError **error); - gboolean gsm_client_cancel_end_session (GsmClient *client, - GError **error); - - void gsm_client_disconnected (GsmClient *client); - -+gboolean gsm_client_request_save (GsmClient *client, -+ guint flags, -+ GError **error); - GKeyFile *gsm_client_save (GsmClient *client, - GError **error); - /* exported to bus */ - gboolean gsm_client_stop (GsmClient *client, - GError **error); - gboolean gsm_client_get_startup_id (GsmClient *client, - char **startup_id, - GError **error); - gboolean gsm_client_get_app_id (GsmClient *client, - char **app_id, - GError **error); - gboolean gsm_client_get_restart_style_hint (GsmClient *client, - guint *hint, - GError **error); - gboolean gsm_client_get_status (GsmClient *client, - guint *status, - GError **error); - gboolean gsm_client_get_unix_process_id (GsmClient *client, - guint *pid, - GError **error); - - /* private */ - - void gsm_client_end_session_response (GsmClient *client, - gboolean is_ok, - gboolean do_last, - gboolean cancel, - const char *reason); - - G_END_DECLS -diff --git a/gnome-session/gsm-dbus-client.c b/gnome-session/gsm-dbus-client.c -index fdd43d2..16c3df0 100644 ---- a/gnome-session/gsm-dbus-client.c -+++ b/gnome-session/gsm-dbus-client.c -@@ -388,60 +388,73 @@ gsm_dbus_client_set_property (GObject *object, - static void - gsm_dbus_client_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) - { - GsmDBusClient *self; - - self = GSM_DBUS_CLIENT (object); - - switch (prop_id) { - case PROP_BUS_NAME: - g_value_set_string (value, self->priv->bus_name); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } - } - - static void - gsm_dbus_client_finalize (GObject *object) - { - GsmDBusClient *client = (GsmDBusClient *) object; - - g_free (client->priv->bus_name); - - G_OBJECT_CLASS (gsm_dbus_client_parent_class)->finalize (object); - } - -+static gboolean -+dbus_client_request_save (GsmClient *client, -+ guint flags, -+ GError **error) -+{ -+ g_debug ("GsmDBusClient: sending save request to client with id %s", -+ gsm_client_peek_id (client)); -+ -+ /* FIXME: The protocol does not support this */ -+ -+ return FALSE; -+} -+ - static GKeyFile * - dbus_client_save (GsmClient *client, - GError **error) - { - g_debug ("GsmDBusClient: saving client with id %s", - gsm_client_peek_id (client)); - - /* FIXME: We still don't support client saving for D-Bus - * session clients */ - - return NULL; - } - - static gboolean - dbus_client_stop (GsmClient *client, - GError **error) - { - GsmDBusClient *dbus_client = (GsmDBusClient *) client; - DBusMessage *message; - gboolean ret; - - ret = FALSE; - - /* unicast the signal to only the registered bus name */ - message = dbus_message_new_signal (gsm_client_peek_id (client), - SM_DBUS_CLIENT_PRIVATE_INTERFACE, - "Stop"); - if (message == NULL) { - goto out; - } -@@ -640,60 +653,61 @@ dbus_client_cancel_end_session (GsmClient *client, - return ret; - } - - static void - gsm_dbus_client_dispose (GObject *object) - { - GsmDBusClient *client; - - g_return_if_fail (object != NULL); - g_return_if_fail (GSM_IS_DBUS_CLIENT (object)); - - client = GSM_DBUS_CLIENT (object); - - dbus_connection_remove_filter (client->priv->connection, client_dbus_filter_function, client); - - G_OBJECT_CLASS (gsm_dbus_client_parent_class)->dispose (object); - } - - static void - gsm_dbus_client_class_init (GsmDBusClientClass *klass) - { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GsmClientClass *client_class = GSM_CLIENT_CLASS (klass); - - object_class->finalize = gsm_dbus_client_finalize; - object_class->constructor = gsm_dbus_client_constructor; - object_class->get_property = gsm_dbus_client_get_property; - object_class->set_property = gsm_dbus_client_set_property; - object_class->dispose = gsm_dbus_client_dispose; - -+ client_class->impl_request_save = dbus_client_request_save; - client_class->impl_save = dbus_client_save; - client_class->impl_stop = dbus_client_stop; - client_class->impl_query_end_session = dbus_client_query_end_session; - client_class->impl_end_session = dbus_client_end_session; - client_class->impl_cancel_end_session = dbus_client_cancel_end_session; - client_class->impl_get_app_name = dbus_client_get_app_name; - client_class->impl_get_restart_style_hint = dbus_client_get_restart_style_hint; - client_class->impl_get_unix_process_id = dbus_client_get_unix_process_id; - - g_object_class_install_property (object_class, - PROP_BUS_NAME, - g_param_spec_string ("bus-name", - "bus-name", - "bus-name", - NULL, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - g_type_class_add_private (klass, sizeof (GsmDBusClientPrivate)); - } - - GsmClient * - gsm_dbus_client_new (const char *startup_id, - const char *bus_name) - { - GsmDBusClient *client; - - client = g_object_new (GSM_TYPE_DBUS_CLIENT, - "startup-id", startup_id, - "bus-name", bus_name, - NULL); -diff --git a/gnome-session/gsm-manager.c b/gnome-session/gsm-manager.c -index c32bbe4..67e0c82 100644 ---- a/gnome-session/gsm-manager.c -+++ b/gnome-session/gsm-manager.c -@@ -55,60 +55,61 @@ - #include "gsm-xsmp-client.h" - #include "gsm-dbus-client.h" - - #include "gsm-autostart-app.h" - - #include "gsm-util.h" - #include "gsm-icon-names.h" - #include "gsm-system.h" - #include "gsm-session-save.h" - #include "gsm-shell-extensions.h" - #include "gsm-fail-whale.h" - - #define GSM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSM_TYPE_MANAGER, GsmManagerPrivate)) - - /* UUIDs for log messages */ - #define GSM_MANAGER_STARTUP_SUCCEEDED_MSGID "0ce153587afa4095832d233c17a88001" - #define GSM_MANAGER_UNRECOVERABLE_FAILURE_MSGID "10dd2dc188b54a5e98970f56499d1f73" - - #define GSM_MANAGER_DBUS_PATH "/org/gnome/SessionManager" - #define GSM_MANAGER_DBUS_NAME "org.gnome.SessionManager" - - /* Probably about the longest amount of time someone could reasonably - * want to wait, at least for something happening more than once. - * We can get deployed on very slow media though like CDROM devices, - * often with complex stacking/compressing filesystems on top, which - * is not a recipie for speed. Particularly now that we throw up - * a fail whale if required components don't show up quickly enough, - * let's make this fairly long. - */ - #define GSM_MANAGER_PHASE_TIMEOUT 90 /* seconds */ -+#define GSM_MANAGER_SAVE_SESSION_TIMEOUT 2 - - #define GDM_FLEXISERVER_COMMAND "gdmflexiserver" - #define GDM_FLEXISERVER_ARGS "--startnew Standard" - - #define SESSION_SCHEMA "org.gnome.desktop.session" - #define KEY_IDLE_DELAY "idle-delay" - #define KEY_SESSION_NAME "session-name" - - #define GSM_MANAGER_SCHEMA "org.gnome.SessionManager" - #define KEY_AUTOSAVE "auto-save-session" - #define KEY_AUTOSAVE_ONE_SHOT "auto-save-session-one-shot" - #define KEY_LOGOUT_PROMPT "logout-prompt" - #define KEY_SHOW_FALLBACK_WARNING "show-fallback-warning" - - #define SCREENSAVER_SCHEMA "org.gnome.desktop.screensaver" - #define KEY_SLEEP_LOCK "lock-enabled" - - #define LOCKDOWN_SCHEMA "org.gnome.desktop.lockdown" - #define KEY_DISABLE_LOG_OUT "disable-log-out" - #define KEY_DISABLE_USER_SWITCHING "disable-user-switching" - - static void app_registered (GsmApp *app, GsmManager *manager); - - typedef enum - { - GSM_MANAGER_LOGOUT_NONE, - GSM_MANAGER_LOGOUT_LOGOUT, - GSM_MANAGER_LOGOUT_REBOOT, - GSM_MANAGER_LOGOUT_REBOOT_INTERACT, - GSM_MANAGER_LOGOUT_SHUTDOWN, -@@ -1177,60 +1178,123 @@ end_session_or_show_shell_dialog (GsmManager *manager) - end_phase (manager); - } - break; - - case GSM_MANAGER_LOGOUT_MODE_FORCE: - end_phase (manager); - break; - default: - g_assert_not_reached (); - break; - } - - } - - static void - query_end_session_complete (GsmManager *manager) - { - - g_debug ("GsmManager: query end session complete"); - - /* Remove the timeout since this can be called from outside the timer - * and we don't want to have it called twice */ - if (manager->priv->query_timeout_id > 0) { - g_source_remove (manager->priv->query_timeout_id); - manager->priv->query_timeout_id = 0; - } - - end_session_or_show_shell_dialog (manager); - } - -+static gboolean -+_client_request_save (GsmClient *client, -+ ClientEndSessionData *data) -+{ -+ gboolean ret; -+ GError *error; -+ -+ error = NULL; -+ ret = gsm_client_request_save (client, data->flags, &error); -+ if (ret) { -+ g_debug ("GsmManager: adding client to query clients: %s", gsm_client_peek_id (client)); -+ data->manager->priv->query_clients = g_slist_prepend (data->manager->priv->query_clients, -+ client); -+ } else if (error) { -+ g_debug ("GsmManager: unable to query client: %s", error->message); -+ g_error_free (error); -+ } -+ -+ return FALSE; -+} -+ -+static gboolean -+_client_request_save_helper (const char *id, -+ GsmClient *client, -+ ClientEndSessionData *data) -+{ -+ return _client_request_save (client, data); -+} -+ -+static void -+query_save_session_complete (GsmManager *manager) -+{ -+ GError *error = NULL; -+ -+ if (g_slist_length (manager->priv->next_query_clients) > 0) { -+ ClientEndSessionData data; -+ -+ data.manager = manager; -+ data.flags = GSM_CLIENT_END_SESSION_FLAG_LAST; -+ -+ g_slist_foreach (manager->priv->next_query_clients, -+ (GFunc)_client_request_save, -+ &data); -+ -+ g_slist_free (manager->priv->next_query_clients); -+ manager->priv->next_query_clients = NULL; -+ -+ return; -+ } -+ -+ if (manager->priv->query_timeout_id > 0) { -+ g_source_remove (manager->priv->query_timeout_id); -+ manager->priv->query_timeout_id = 0; -+ } -+ -+ gsm_session_save (manager->priv->clients, &error); -+ -+ if (error) { -+ g_warning ("Error saving session: %s", error->message); -+ g_error_free (error); -+ } -+} -+ - static guint32 - generate_cookie (void) - { - guint32 cookie; - - cookie = (guint32)g_random_int_range (1, G_MAXINT32); - - return cookie; - } - - static guint32 - _generate_unique_cookie (GsmManager *manager) - { - guint32 cookie; - - do { - cookie = generate_cookie (); - } while (gsm_store_find (manager->priv->inhibitors, (GsmStoreFunc)_find_by_cookie, &cookie) != NULL); - - return cookie; - } - - static gboolean - _on_query_end_session_timeout (GsmManager *manager) - { - GSList *l; - - manager->priv->query_timeout_id = 0; - - g_debug ("GsmManager: query end session timed out"); -@@ -1257,60 +1321,75 @@ _on_query_end_session_timeout (GsmManager *manager) - bus_name = NULL; - } - - app_id = g_strdup (gsm_client_peek_app_id (l->data)); - if (IS_STRING_EMPTY (app_id)) { - /* XSMP clients don't give us an app id unless we start them */ - g_free (app_id); - app_id = gsm_client_get_app_name (l->data); - } - - cookie = _generate_unique_cookie (manager); - inhibitor = gsm_inhibitor_new_for_client (gsm_client_peek_id (l->data), - app_id, - GSM_INHIBITOR_FLAG_LOGOUT, - _("Not responding"), - bus_name, - cookie); - g_free (app_id); - gsm_store_add (manager->priv->inhibitors, gsm_inhibitor_peek_id (inhibitor), G_OBJECT (inhibitor)); - g_object_unref (inhibitor); - } - - g_slist_free (manager->priv->query_clients); - manager->priv->query_clients = NULL; - - query_end_session_complete (manager); - - return FALSE; - } - -+static gboolean -+_on_query_save_session_timeout (GsmManager *manager) -+{ -+ manager->priv->query_timeout_id = 0; -+ -+ g_debug ("GsmManager: query to save session timed out"); -+ -+ g_slist_free (manager->priv->query_clients); -+ manager->priv->query_clients = NULL; -+ -+ query_save_session_complete (manager); -+ -+ return FALSE; -+} -+ - static void - do_phase_query_end_session (GsmManager *manager) - { - ClientEndSessionData data; - - data.manager = manager; - data.flags = 0; - - if (manager->priv->logout_mode == GSM_MANAGER_LOGOUT_MODE_FORCE) { - data.flags |= GSM_CLIENT_END_SESSION_FLAG_FORCEFUL; - } - /* We only query if an app is ready to log out, so we don't use - * GSM_CLIENT_END_SESSION_FLAG_SAVE here. - */ - - debug_clients (manager); - g_debug ("GsmManager: sending query-end-session to clients (logout mode: %s)", - manager->priv->logout_mode == GSM_MANAGER_LOGOUT_MODE_NORMAL? "normal" : - manager->priv->logout_mode == GSM_MANAGER_LOGOUT_MODE_FORCE? "forceful": - "no confirmation"); - gsm_store_foreach (manager->priv->clients, - (GsmStoreFunc)_client_query_end_session, - &data); - - /* This phase doesn't time out unless logout is forced. Typically, this - * separate timer is only used to show UI. */ - manager->priv->query_timeout_id = g_timeout_add_seconds (1, (GSourceFunc)_on_query_end_session_timeout, manager); - } - - static void -@@ -1972,67 +2051,86 @@ maybe_save_session (GsmManager *manager) - return; - - /* We only allow session saving when session is running or when - * logging out */ - if (manager->priv->phase != GSM_MANAGER_PHASE_RUNNING && - manager->priv->phase != GSM_MANAGER_PHASE_END_SESSION) { - return; - } - - if (!auto_save_is_enabled (manager)) { - return; - } - - error = NULL; - gsm_session_save (manager->priv->clients, &error); - - if (error) { - g_warning ("Error saving session: %s", error->message); - g_error_free (error); - } - } - - static void - _handle_client_end_session_response (GsmManager *manager, - GsmClient *client, - gboolean is_ok, - gboolean do_last, - gboolean cancel, - const char *reason) - { -- /* just ignore if received outside of shutdown */ -- if (manager->priv->phase < GSM_MANAGER_PHASE_QUERY_END_SESSION) { -+ /* just ignore if we are not yet running */ -+ if (manager->priv->phase < GSM_MANAGER_PHASE_RUNNING) { - return; - } - - g_debug ("GsmManager: Response from end session request: is-ok=%d do-last=%d cancel=%d reason=%s", is_ok, do_last, cancel, reason ? reason :""); - -+ if (manager->priv->phase == GSM_MANAGER_PHASE_RUNNING) { -+ /* Ignore responses when no requests were sent */ -+ if (manager->priv->query_clients == NULL) { -+ return; -+ } -+ -+ manager->priv->query_clients = g_slist_remove (manager->priv->query_clients, client); -+ -+ if (do_last) { -+ manager->priv->next_query_clients = g_slist_prepend (manager->priv->next_query_clients, -+ client); -+ } -+ -+ if (manager->priv->query_clients == NULL) { -+ query_save_session_complete (manager); -+ } -+ return; -+ } -+ - if (cancel) { - cancel_end_session (manager); - return; - } - - manager->priv->query_clients = g_slist_remove (manager->priv->query_clients, client); - - if (! is_ok && manager->priv->logout_mode != GSM_MANAGER_LOGOUT_MODE_FORCE) { - guint cookie; - GsmInhibitor *inhibitor; - char *app_id; - const char *bus_name; - - /* FIXME: do we support updating the reason? */ - - /* Create JIT inhibit */ - if (GSM_IS_DBUS_CLIENT (client)) { - bus_name = gsm_dbus_client_get_bus_name (GSM_DBUS_CLIENT (client)); - } else { - bus_name = NULL; - } - - app_id = g_strdup (gsm_client_peek_app_id (client)); - if (IS_STRING_EMPTY (app_id)) { - /* XSMP clients don't give us an app id unless we start them */ - g_free (app_id); - app_id = gsm_client_get_app_name (client); - } - - cookie = _generate_unique_cookie (manager); -@@ -2093,84 +2191,97 @@ on_client_end_session_response (GsmClient *client, - client, - is_ok, - do_last, - cancel, - reason); - } - - static void - on_xsmp_client_logout_request (GsmXSMPClient *client, - gboolean show_dialog, - GsmManager *manager) - { - GError *error; - int logout_mode; - - if (show_dialog) { - logout_mode = GSM_MANAGER_LOGOUT_MODE_NORMAL; - } else { - logout_mode = GSM_MANAGER_LOGOUT_MODE_NO_CONFIRMATION; - } - - error = NULL; - gsm_manager_logout (manager, logout_mode, &error); - if (error != NULL) { - g_warning ("Unable to logout: %s", error->message); - g_error_free (error); - } - } - - static void -+on_xsmp_client_save_request (GsmXSMPClient *client, -+ gboolean show_dialog, -+ GsmManager *manager) -+{ -+ g_debug ("GsmManager: save_request"); -+ gsm_manager_save_session (manager, NULL); -+} -+ -+static void - on_store_client_added (GsmStore *store, - const char *id, - GsmManager *manager) - { - GsmClient *client; - - g_debug ("GsmManager: Client added: %s", id); - - client = (GsmClient *)gsm_store_lookup (store, id); - - /* a bit hacky */ - if (GSM_IS_XSMP_CLIENT (client)) { - g_signal_connect (client, - "register-request", - G_CALLBACK (on_xsmp_client_register_request), - manager); - g_signal_connect (client, - "register-confirmed", - G_CALLBACK (on_xsmp_client_register_confirmed), - manager); - g_signal_connect (client, - "logout-request", - G_CALLBACK (on_xsmp_client_logout_request), - manager); -+ g_signal_connect (client, -+ "save-request", -+ G_CALLBACK (on_xsmp_client_save_request), -+ manager); - } - - g_signal_connect (client, - "end-session-response", - G_CALLBACK (on_client_end_session_response), - manager); - - g_signal_emit (manager, signals [CLIENT_ADDED], 0, id); - /* FIXME: disconnect signal handler */ - } - - static void - on_store_client_removed (GsmStore *store, - const char *id, - GsmManager *manager) - { - g_debug ("GsmManager: Client removed: %s", id); - - g_signal_emit (manager, signals [CLIENT_REMOVED], 0, id); - } - - static void - gsm_manager_set_client_store (GsmManager *manager, - GsmStore *store) - { - g_return_if_fail (GSM_IS_MANAGER (manager)); - - if (store != NULL) { - g_object_ref (store); - } -@@ -3127,60 +3238,95 @@ gsm_manager_reboot (GsmManager *manager, - if (manager->priv->phase != GSM_MANAGER_PHASE_RUNNING) { - error = g_error_new (GSM_MANAGER_ERROR, - GSM_MANAGER_ERROR_NOT_IN_RUNNING, - "Reboot interface is only available during the Running phase"); - dbus_g_method_return_error (context, error); - g_error_free (error); - return FALSE; - } - - if (_log_out_is_locked_down (manager)) { - error = g_error_new (GSM_MANAGER_ERROR, - GSM_MANAGER_ERROR_LOCKED_DOWN, - "Logout has been locked down"); - dbus_g_method_return_error (context, error); - g_error_free (error); - return FALSE; - } - - task = g_task_new (manager, manager->priv->end_session_cancellable, (GAsyncReadyCallback) complete_end_session_task, context); - - manager->priv->pending_end_session_tasks = g_slist_prepend (manager->priv->pending_end_session_tasks, - task); - - request_reboot (manager); - - return TRUE; - } - - - gboolean -+gsm_manager_save_session (GsmManager *manager, -+ GError **error) -+{ -+ ClientEndSessionData data; -+ -+ g_debug ("GsmManager: SaveSession called"); -+ -+ g_return_val_if_fail (GSM_IS_MANAGER (manager), FALSE); -+ -+ if (manager->priv->phase != GSM_MANAGER_PHASE_RUNNING) { -+ g_set_error (error, -+ GSM_MANAGER_ERROR, -+ GSM_MANAGER_ERROR_NOT_IN_RUNNING, -+ "SaveSession interface is only available during the Running phase"); -+ return FALSE; -+ } -+ -+ data.manager = manager; -+ data.flags = 0; -+ gsm_store_foreach (manager->priv->clients, -+ (GsmStoreFunc)_client_request_save_helper, -+ &data); -+ -+ if (manager->priv->query_clients) { -+ manager->priv->query_timeout_id = g_timeout_add_seconds (GSM_MANAGER_SAVE_SESSION_TIMEOUT, -+ (GSourceFunc)_on_query_save_session_timeout, -+ manager); -+ return TRUE; -+ } else { -+ g_debug ("GsmManager: Nothing to save"); -+ return FALSE; -+ } -+} -+ -+gboolean - gsm_manager_can_shutdown (GsmManager *manager, - gboolean *shutdown_available, - GError **error) - { - g_debug ("GsmManager: CanShutdown called"); - - g_return_val_if_fail (GSM_IS_MANAGER (manager), FALSE); - - *shutdown_available = !_log_out_is_locked_down (manager) && - (gsm_system_can_stop (manager->priv->system) - || gsm_system_can_restart (manager->priv->system) - || gsm_system_can_suspend (manager->priv->system) - || gsm_system_can_hibernate (manager->priv->system)); - - return TRUE; - } - - gboolean - gsm_manager_logout (GsmManager *manager, - guint logout_mode, - GError **error) - { - g_debug ("GsmManager: Logout called"); - - g_return_val_if_fail (GSM_IS_MANAGER (manager), FALSE); - - if (manager->priv->phase != GSM_MANAGER_PHASE_RUNNING) { - g_set_error (error, - GSM_MANAGER_ERROR, - GSM_MANAGER_ERROR_NOT_IN_RUNNING, -diff --git a/gnome-session/gsm-manager.h b/gnome-session/gsm-manager.h -index a0030b9..bc16654 100644 ---- a/gnome-session/gsm-manager.h -+++ b/gnome-session/gsm-manager.h -@@ -137,60 +137,63 @@ void _gsm_manager_set_active_session (GsmManager * - - /* exported methods */ - - gboolean gsm_manager_register_client (GsmManager *manager, - const char *app_id, - const char *client_startup_id, - DBusGMethodInvocation *context); - gboolean gsm_manager_unregister_client (GsmManager *manager, - const char *session_client_id, - DBusGMethodInvocation *context); - - gboolean gsm_manager_inhibit (GsmManager *manager, - const char *app_id, - guint toplevel_xid, - const char *reason, - guint flags, - DBusGMethodInvocation *context); - gboolean gsm_manager_uninhibit (GsmManager *manager, - guint inhibit_cookie, - DBusGMethodInvocation *context); - gboolean gsm_manager_is_inhibited (GsmManager *manager, - guint flags, - gboolean *is_inhibited, - GError *error); - - gboolean gsm_manager_shutdown (GsmManager *manager, - DBusGMethodInvocation *context); - gboolean gsm_manager_reboot (GsmManager *manager, - DBusGMethodInvocation *context); - -+gboolean gsm_manager_save_session (GsmManager *manager, -+ GError **error); -+ - gboolean gsm_manager_can_shutdown (GsmManager *manager, - gboolean *shutdown_available, - GError **error); - gboolean gsm_manager_logout (GsmManager *manager, - guint logout_mode, - GError **error); - - gboolean gsm_manager_setenv (GsmManager *manager, - const char *variable, - const char *value, - GError **error); - gboolean gsm_manager_get_locale (GsmManager *manager, - int category, - const char **value, - GError **error); - gboolean gsm_manager_initialization_error (GsmManager *manager, - const char *message, - gboolean fatal, - GError **error); - - gboolean gsm_manager_get_clients (GsmManager *manager, - GPtrArray **clients, - GError **error); - gboolean gsm_manager_get_inhibitors (GsmManager *manager, - GPtrArray **inhibitors, - GError **error); - gboolean gsm_manager_is_autostart_condition_handled (GsmManager *manager, - const char *condition, - gboolean *handled, - GError **error); -diff --git a/gnome-session/gsm-xsmp-client.c b/gnome-session/gsm-xsmp-client.c -index c256acb..1cfb47f 100644 ---- a/gnome-session/gsm-xsmp-client.c -+++ b/gnome-session/gsm-xsmp-client.c -@@ -39,60 +39,61 @@ - #define GsmDesktopFile "_GSM_DesktopFile" - - #define GSM_XSMP_CLIENT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSM_TYPE_XSMP_CLIENT, GsmXSMPClientPrivate)) - - struct GsmXSMPClientPrivate - { - - SmsConn conn; - IceConn ice_connection; - - guint watch_id; - - char *description; - GPtrArray *props; - - /* SaveYourself state */ - int current_save_yourself; - int next_save_yourself; - guint next_save_yourself_allow_interact : 1; - }; - - enum { - PROP_0, - PROP_ICE_CONNECTION - }; - - enum { - REGISTER_REQUEST, - REGISTER_CONFIRMED, - LOGOUT_REQUEST, -+ SAVE_REQUEST, - LAST_SIGNAL - }; - - static guint signals[LAST_SIGNAL] = { 0 }; - - G_DEFINE_TYPE (GsmXSMPClient, gsm_xsmp_client, GSM_TYPE_CLIENT) - - static gboolean - client_iochannel_watch (GIOChannel *channel, - GIOCondition condition, - GsmXSMPClient *client) - { - gboolean keep_going; - - g_object_ref (client); - switch (IceProcessMessages (client->priv->ice_connection, NULL, NULL)) { - case IceProcessMessagesSuccess: - keep_going = TRUE; - break; - - case IceProcessMessagesIOError: - g_debug ("GsmXSMPClient: IceProcessMessagesIOError on '%s'", client->priv->description); - gsm_client_set_status (GSM_CLIENT (client), GSM_CLIENT_FAILED); - /* Emitting "disconnected" will eventually cause - * IceCloseConnection() to be called. - */ - gsm_client_disconnected (GSM_CLIENT (client)); - keep_going = FALSE; - break; - -@@ -472,60 +473,84 @@ xsmp_interact (GsmClient *client) - - SmsInteract (xsmp->priv->conn); - } - - static gboolean - xsmp_cancel_end_session (GsmClient *client, - GError **error) - { - GsmXSMPClient *xsmp = (GsmXSMPClient *) client; - - g_debug ("GsmXSMPClient: xsmp_cancel_end_session ('%s')", xsmp->priv->description); - - if (xsmp->priv->conn == NULL) { - g_set_error (error, - GSM_CLIENT_ERROR, - GSM_CLIENT_ERROR_NOT_REGISTERED, - "Client is not registered"); - return FALSE; - } - - SmsShutdownCancelled (xsmp->priv->conn); - - /* reset the state */ - xsmp->priv->current_save_yourself = -1; - xsmp->priv->next_save_yourself = -1; - xsmp->priv->next_save_yourself_allow_interact = FALSE; - - return TRUE; - } - -+static gboolean -+xsmp_request_save (GsmClient *client, -+ guint flags, -+ GError **error) -+{ -+ GsmXSMPClient *xsmp = (GsmXSMPClient *) client; -+ -+ g_debug ("GsmXSMPClient: xsmp_request_save ('%s')", xsmp->priv->description); -+ -+ if (xsmp->priv->conn == NULL) { -+ g_set_error (error, -+ GSM_CLIENT_ERROR, -+ GSM_CLIENT_ERROR_NOT_REGISTERED, -+ "Client is not registered"); -+ return FALSE; -+ } -+ -+ if (flags & GSM_CLIENT_END_SESSION_FLAG_LAST) -+ xsmp_save_yourself_phase2 (client); -+ else -+ do_save_yourself (xsmp, SmSaveLocal, FALSE); -+ -+ return TRUE; -+} - static char * - get_desktop_file_path (GsmXSMPClient *client) - { - SmProp *prop; - char *desktop_file_path = NULL; - const char *program_name; - - /* XSMP clients using eggsmclient defines a special property - * pointing to their respective desktop entry file */ - prop = find_property (client, GsmDesktopFile, NULL); - - if (prop) { - GFile *file = g_file_new_for_uri (prop->vals[0].value); - desktop_file_path = g_file_get_path (file); - g_object_unref (file); - goto out; - } - - /* If we can't get desktop file from GsmDesktopFile then we - * try to find the desktop file from its program name */ - prop = find_property (client, SmProgram, NULL); - - if (!prop) { - goto out; - } - - program_name = prop->vals[0].value; - desktop_file_path = - gsm_util_find_desktop_file_for_app_name (program_name, - TRUE, FALSE); -@@ -955,100 +980,112 @@ xsmp_get_unix_process_id (GsmClient *client) - gboolean res; - - g_debug ("GsmXSMPClient: getting pid"); - - prop = find_property (GSM_XSMP_CLIENT (client), SmProcessID, NULL); - - if (!prop || strcmp (prop->type, SmARRAY8) != 0) { - return 0; - } - - pid = 0; - res = _parse_value_as_uint ((char *)prop->vals[0].value, &pid); - if (! res) { - pid = 0; - } - - return pid; - } - - static void - gsm_xsmp_client_class_init (GsmXSMPClientClass *klass) - { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GsmClientClass *client_class = GSM_CLIENT_CLASS (klass); - - object_class->finalize = gsm_xsmp_client_finalize; - object_class->constructor = gsm_xsmp_client_constructor; - object_class->get_property = gsm_xsmp_client_get_property; - object_class->set_property = gsm_xsmp_client_set_property; - -+ client_class->impl_request_save = xsmp_request_save; - client_class->impl_save = xsmp_save; - client_class->impl_stop = xsmp_stop; - client_class->impl_query_end_session = xsmp_query_end_session; - client_class->impl_end_session = xsmp_end_session; - client_class->impl_cancel_end_session = xsmp_cancel_end_session; - client_class->impl_get_app_name = xsmp_get_app_name; - client_class->impl_get_restart_style_hint = xsmp_get_restart_style_hint; - client_class->impl_get_unix_process_id = xsmp_get_unix_process_id; - - signals[REGISTER_REQUEST] = - g_signal_new ("register-request", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GsmXSMPClientClass, register_request), - _boolean_handled_accumulator, - NULL, - NULL, - G_TYPE_BOOLEAN, - 1, G_TYPE_POINTER); - signals[REGISTER_CONFIRMED] = - g_signal_new ("register-confirmed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GsmXSMPClientClass, register_confirmed), - NULL, - NULL, - NULL, - G_TYPE_NONE, - 1, G_TYPE_POINTER); - signals[LOGOUT_REQUEST] = - g_signal_new ("logout-request", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GsmXSMPClientClass, logout_request), - NULL, - NULL, - NULL, - G_TYPE_NONE, - 1, G_TYPE_BOOLEAN); - -+ signals[SAVE_REQUEST] = -+ g_signal_new ("save-request", -+ G_OBJECT_CLASS_TYPE (object_class), -+ G_SIGNAL_RUN_LAST, -+ G_STRUCT_OFFSET (GsmXSMPClientClass, save_request), -+ NULL, -+ NULL, -+ g_cclosure_marshal_VOID__BOOLEAN, -+ G_TYPE_NONE, -+ 1, G_TYPE_BOOLEAN); -+ - g_object_class_install_property (object_class, - PROP_ICE_CONNECTION, - g_param_spec_pointer ("ice-connection", - "ice-connection", - "ice-connection", - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_type_class_add_private (klass, sizeof (GsmXSMPClientPrivate)); - } - - GsmClient * - gsm_xsmp_client_new (IceConn ice_conn) - { - GsmXSMPClient *xsmp; - - xsmp = g_object_new (GSM_TYPE_XSMP_CLIENT, - "ice-connection", ice_conn, - NULL); - - return GSM_CLIENT (xsmp); - } - - static Status - register_client_callback (SmsConn conn, - SmPointer manager_data, - char *previous_id) - { - GsmXSMPClient *client = manager_data; - gboolean handled; - char *id; -diff --git a/gnome-session/gsm-xsmp-client.h b/gnome-session/gsm-xsmp-client.h -index 1bb2797..6b95c51 100644 ---- a/gnome-session/gsm-xsmp-client.h -+++ b/gnome-session/gsm-xsmp-client.h -@@ -27,61 +27,62 @@ G_BEGIN_DECLS - - #define GSM_TYPE_XSMP_CLIENT (gsm_xsmp_client_get_type ()) - #define GSM_XSMP_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSM_TYPE_XSMP_CLIENT, GsmXSMPClient)) - #define GSM_XSMP_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSM_TYPE_XSMP_CLIENT, GsmXSMPClientClass)) - #define GSM_IS_XSMP_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSM_TYPE_XSMP_CLIENT)) - #define GSM_IS_XSMP_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSM_TYPE_XSMP_CLIENT)) - #define GSM_XSMP_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSM_TYPE_XSMP_CLIENT, GsmXSMPClientClass)) - - typedef struct _GsmXSMPClient GsmXSMPClient; - typedef struct _GsmXSMPClientClass GsmXSMPClientClass; - - typedef struct GsmXSMPClientPrivate GsmXSMPClientPrivate; - - struct _GsmXSMPClient - { - GsmClient parent; - GsmXSMPClientPrivate *priv; - }; - - struct _GsmXSMPClientClass - { - GsmClientClass parent_class; - - /* signals */ - gboolean (*register_request) (GsmXSMPClient *client, - char **client_id); - void (*register_confirmed) (GsmXSMPClient *client, - const char *client_id); - gboolean (*logout_request) (GsmXSMPClient *client, - gboolean prompt); -- -+ gboolean (*save_request) (GsmXSMPClient *client, -+ gboolean prompt); - - void (*saved_state) (GsmXSMPClient *client); - - void (*request_phase2) (GsmXSMPClient *client); - - void (*request_interaction) (GsmXSMPClient *client); - void (*interaction_done) (GsmXSMPClient *client, - gboolean cancel_shutdown); - - void (*save_yourself_done) (GsmXSMPClient *client); - - }; - - GType gsm_xsmp_client_get_type (void) G_GNUC_CONST; - - GsmClient *gsm_xsmp_client_new (IceConn ice_conn); - - void gsm_xsmp_client_connect (GsmXSMPClient *client, - SmsConn conn, - unsigned long *mask_ret, - SmsCallbacks *callbacks_ret); - - void gsm_xsmp_client_save_state (GsmXSMPClient *client); - void gsm_xsmp_client_save_yourself (GsmXSMPClient *client, - gboolean save_state); - void gsm_xsmp_client_save_yourself_phase2 (GsmXSMPClient *client); - void gsm_xsmp_client_interact (GsmXSMPClient *client); - void gsm_xsmp_client_shutdown_cancelled (GsmXSMPClient *client); - - G_END_DECLS -diff --git a/gnome-session/org.gnome.SessionManager.xml b/gnome-session/org.gnome.SessionManager.xml -index 8c31694..eacac4b 100644 ---- a/gnome-session/org.gnome.SessionManager.xml -+++ b/gnome-session/org.gnome.SessionManager.xml -@@ -261,60 +261,68 @@ - - True if condition is handled, false otherwise - - - - - Allows the caller to determine whether the session manager is - handling changes to the specified autostart condition. - - - - - - - - - Request a shutdown dialog. - - - - - - - - - Request a reboot dialog. - - - - -+ -+ -+ -+ Request to save session -+ -+ -+ -+ - - - - True if shutdown is available to the user, false otherwise - - - - - Allows the caller to determine whether or not it's okay to show - a shutdown option in the UI - - - - - - - - The type of logout that is being requested - - - - - Request a logout dialog - - Allowed values for the mode parameter are: - - - 0 - Normal. - --- -2.3.7 - - -From 7b1c1782ef895a536f95d83e0d6596dd076ee32f Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 20 Dec 2013 11:22:07 -0500 -Subject: [PATCH 09/17] Revert "Allow saved-session to be a symlink" - -This reverts commit b733c2ee519b65c3c4eab0d0e93056412f995f3f. ---- - gnome-session/gsm-session-save.c | 32 ++++++++++++++++++++++++++++---- - gnome-session/gsm-util.c | 6 ++++++ - 2 files changed, 34 insertions(+), 4 deletions(-) - -diff --git a/gnome-session/gsm-session-save.c b/gnome-session/gsm-session-save.c -index 025eeea..131a58b 100644 ---- a/gnome-session/gsm-session-save.c -+++ b/gnome-session/gsm-session-save.c -@@ -9,61 +9,61 @@ - * - * 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, see . - */ - - #include - - #include - #include - #include - - #include "gsm-util.h" - #include "gsm-autostart-app.h" - #include "gsm-client.h" - - #include "gsm-session-save.h" - - #define GSM_MANAGER_SCHEMA "org.gnome.SessionManager" - #define KEY_AUTOSAVE_ONE_SHOT "auto-save-session-one-shot" - - - static gboolean gsm_session_clear_saved_session (const char *directory, - GHashTable *discard_hash); - - typedef struct { -- const char *dir; -+ char *dir; - GHashTable *discard_hash; - GError **error; - } SessionSaveData; - - static gboolean - save_one_client (char *id, - GObject *object, - SessionSaveData *data) - { - GsmClient *client; - GKeyFile *keyfile; - const char *app_id; - char *path = NULL; - char *filename = NULL; - char *contents = NULL; - gsize length = 0; - char *discard_exec; - GError *local_error; - - client = GSM_CLIENT (object); - - local_error = NULL; - - keyfile = gsm_client_save (client, &local_error); - - if (keyfile == NULL || local_error) { - goto out; - } - - contents = g_key_file_to_data (keyfile, &length, &local_error); -@@ -112,89 +112,113 @@ save_one_client (char *id, - } - - g_debug ("GsmSessionSave: saved client %s to %s", id, filename); - - out: - if (keyfile != NULL) { - g_key_file_free (keyfile); - } - - g_free (contents); - g_free (filename); - g_free (path); - - /* in case of any error, stop saving session */ - if (local_error) { - g_propagate_error (data->error, local_error); - g_error_free (local_error); - - return TRUE; - } - - return FALSE; - } - - void - gsm_session_save (GsmStore *client_store, - GError **error) - { - GSettings *settings; - const char *save_dir; -+ char *tmp_dir; - SessionSaveData data; - - g_debug ("GsmSessionSave: Saving session"); - - /* Clear one shot key autosave in the event its set (so that it's actually - * one shot only) - */ - settings = g_settings_new (GSM_MANAGER_SCHEMA); - g_settings_set_boolean (settings, KEY_AUTOSAVE_ONE_SHOT, FALSE); - g_object_unref (settings); - - save_dir = gsm_util_get_saved_session_dir (); - if (save_dir == NULL) { - g_warning ("GsmSessionSave: cannot create saved session directory"); - return; - } - -- data.dir = save_dir; -+ tmp_dir = gsm_util_get_empty_tmp_session_dir (); -+ if (tmp_dir == NULL) { -+ g_warning ("GsmSessionSave: cannot create new saved session directory"); -+ return; -+ } -+ -+ /* save the session in a temp directory, and remember the discard -+ * commands */ -+ data.dir = tmp_dir; - data.discard_hash = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, NULL); -- /* remove old saved session */ -- gsm_session_clear_saved_session (save_dir, data.discard_hash); - data.error = error; - - gsm_store_foreach (client_store, - (GsmStoreFunc) save_one_client, - &data); - -+ if (!*error) { -+ /* remove the old saved session */ -+ gsm_session_clear_saved_session (save_dir, data.discard_hash); -+ -+ /* rename the temp session dir */ -+ if (g_file_test (save_dir, G_FILE_TEST_IS_DIR)) -+ g_rmdir (save_dir); -+ g_rename (tmp_dir, save_dir); -+ } else { -+ g_warning ("GsmSessionSave: error saving session: %s", (*error)->message); -+ /* FIXME: we should create a hash table filled with the discard -+ * commands that are in desktop files from save_dir. */ -+ gsm_session_clear_saved_session (tmp_dir, NULL); -+ g_rmdir (tmp_dir); -+ } -+ - g_hash_table_destroy (data.discard_hash); -+ g_free (tmp_dir); - } - - static gboolean - gsm_session_clear_one_client (const char *filename, - GHashTable *discard_hash) - { - gboolean result = TRUE; - GKeyFile *key_file; - char *discard_exec = NULL; - - g_debug ("GsmSessionSave: removing '%s' from saved session", filename); - - key_file = g_key_file_new (); - if (g_key_file_load_from_file (key_file, filename, - G_KEY_FILE_NONE, NULL)) { - char **argv; - int argc; - - discard_exec = g_key_file_get_string (key_file, - G_KEY_FILE_DESKTOP_GROUP, - GSM_AUTOSTART_APP_DISCARD_KEY, - NULL); - if (!discard_exec) - goto out; - - if (discard_hash && g_hash_table_lookup (discard_hash, discard_exec)) - goto out; - - if (!g_shell_parse_argv (discard_exec, &argc, &argv, NULL)) - goto out; -diff --git a/gnome-session/gsm-util.c b/gnome-session/gsm-util.c -index ff6484c..bf24830 100644 ---- a/gnome-session/gsm-util.c -+++ b/gnome-session/gsm-util.c -@@ -71,63 +71,69 @@ gsm_util_find_desktop_file_for_app_name (const char *name, - g_debug ("GsmUtil: found in XDG dirs: '%s'", app_path); - } - - /* look for gnome vendor prefix */ - if (app_path == NULL) { - g_free (desktop_file); - desktop_file = g_strdup_printf ("gnome-%s.desktop", name); - - g_key_file_load_from_dirs (key_file, - desktop_file, - (const char **) app_dirs, - &app_path, - G_KEY_FILE_NONE, - NULL); - if (app_path != NULL) { - g_debug ("GsmUtil: found in XDG dirs: '%s'", app_path); - } - } - - g_free (desktop_file); - g_key_file_free (key_file); - - g_strfreev (app_dirs); - - return app_path; - } - - static gboolean - ensure_dir_exists (const char *dir) - { -+ if (g_file_test (dir, G_FILE_TEST_IS_DIR)) -+ return TRUE; -+ - if (g_mkdir_with_parents (dir, 0755) == 0) - return TRUE; - -+ if (errno == EEXIST) -+ return g_file_test (dir, G_FILE_TEST_IS_DIR); -+ - g_warning ("GsmSessionSave: Failed to create directory %s: %s", dir, strerror (errno)); - - return FALSE; - } - - gchar * - gsm_util_get_empty_tmp_session_dir (void) - { - char *tmp; - gboolean exists; - - tmp = g_build_filename (g_get_user_config_dir (), - "gnome-session", - "saved-session.new", - NULL); - - exists = ensure_dir_exists (tmp); - - if (G_UNLIKELY (!exists)) { - g_warning ("GsmSessionSave: could not create directory for saved session: %s", tmp); - g_free (tmp); - return NULL; - } else { - /* make sure it's empty */ - GDir *dir; - const char *filename; - - dir = g_dir_open (tmp, 0, NULL); - if (dir) { - while ((filename = g_dir_read_name (dir))) { --- -2.3.7 - - -From efdb8db827399dadd3b8638b201e7da81f6e9592 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 20 Dec 2013 11:22:53 -0500 -Subject: [PATCH 10/17] Allow saved-session directory to be a symlink - -This gives us the option of adding a rudimentary session -chooser later. ---- - gnome-session/gsm-session-save.c | 36 ++++++++++++++++++++++++++++++------ - gnome-session/gsm-util.c | 6 ------ - 2 files changed, 30 insertions(+), 12 deletions(-) - -diff --git a/gnome-session/gsm-session-save.c b/gnome-session/gsm-session-save.c -index 131a58b..ea23be5 100644 ---- a/gnome-session/gsm-session-save.c -+++ b/gnome-session/gsm-session-save.c -@@ -148,67 +148,91 @@ gsm_session_save (GsmStore *client_store, - * one shot only) - */ - settings = g_settings_new (GSM_MANAGER_SCHEMA); - g_settings_set_boolean (settings, KEY_AUTOSAVE_ONE_SHOT, FALSE); - g_object_unref (settings); - - save_dir = gsm_util_get_saved_session_dir (); - if (save_dir == NULL) { - g_warning ("GsmSessionSave: cannot create saved session directory"); - return; - } - - tmp_dir = gsm_util_get_empty_tmp_session_dir (); - if (tmp_dir == NULL) { - g_warning ("GsmSessionSave: cannot create new saved session directory"); - return; - } - - /* save the session in a temp directory, and remember the discard - * commands */ - data.dir = tmp_dir; - data.discard_hash = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, NULL); - data.error = error; - - gsm_store_foreach (client_store, - (GsmStoreFunc) save_one_client, - &data); - - if (!*error) { -- /* remove the old saved session */ -- gsm_session_clear_saved_session (save_dir, data.discard_hash); -+ char *session_dir; - -- /* rename the temp session dir */ -- if (g_file_test (save_dir, G_FILE_TEST_IS_DIR)) -- g_rmdir (save_dir); -- g_rename (tmp_dir, save_dir); -+ if (g_file_test (save_dir, G_FILE_TEST_IS_SYMLINK)) -+ session_dir = g_file_read_link (save_dir, error); -+ else -+ session_dir = g_strdup (save_dir); -+ -+ if (session_dir != NULL) { -+ -+ char *absolute_session_dir; -+ -+ if (g_path_is_absolute (session_dir)) { -+ absolute_session_dir = g_strdup (session_dir); -+ } else { -+ char *parent_dir; -+ -+ parent_dir = g_path_get_dirname (save_dir); -+ absolute_session_dir = g_build_filename (parent_dir, session_dir, NULL); -+ g_free (parent_dir); -+ } -+ g_free (session_dir); -+ -+ /* remove the old saved session */ -+ gsm_session_clear_saved_session (absolute_session_dir, data.discard_hash); -+ -+ if (g_file_test (absolute_session_dir, G_FILE_TEST_IS_DIR)) -+ g_rmdir (absolute_session_dir); -+ g_rename (tmp_dir, absolute_session_dir); -+ -+ g_free (absolute_session_dir); -+ } - } else { - g_warning ("GsmSessionSave: error saving session: %s", (*error)->message); - /* FIXME: we should create a hash table filled with the discard - * commands that are in desktop files from save_dir. */ - gsm_session_clear_saved_session (tmp_dir, NULL); - g_rmdir (tmp_dir); - } - - g_hash_table_destroy (data.discard_hash); - g_free (tmp_dir); - } - - static gboolean - gsm_session_clear_one_client (const char *filename, - GHashTable *discard_hash) - { - gboolean result = TRUE; - GKeyFile *key_file; - char *discard_exec = NULL; - - g_debug ("GsmSessionSave: removing '%s' from saved session", filename); - - key_file = g_key_file_new (); - if (g_key_file_load_from_file (key_file, filename, - G_KEY_FILE_NONE, NULL)) { - char **argv; - int argc; - - discard_exec = g_key_file_get_string (key_file, - G_KEY_FILE_DESKTOP_GROUP, -diff --git a/gnome-session/gsm-util.c b/gnome-session/gsm-util.c -index bf24830..ff6484c 100644 ---- a/gnome-session/gsm-util.c -+++ b/gnome-session/gsm-util.c -@@ -71,69 +71,63 @@ gsm_util_find_desktop_file_for_app_name (const char *name, - g_debug ("GsmUtil: found in XDG dirs: '%s'", app_path); - } - - /* look for gnome vendor prefix */ - if (app_path == NULL) { - g_free (desktop_file); - desktop_file = g_strdup_printf ("gnome-%s.desktop", name); - - g_key_file_load_from_dirs (key_file, - desktop_file, - (const char **) app_dirs, - &app_path, - G_KEY_FILE_NONE, - NULL); - if (app_path != NULL) { - g_debug ("GsmUtil: found in XDG dirs: '%s'", app_path); - } - } - - g_free (desktop_file); - g_key_file_free (key_file); - - g_strfreev (app_dirs); - - return app_path; - } - - static gboolean - ensure_dir_exists (const char *dir) - { -- if (g_file_test (dir, G_FILE_TEST_IS_DIR)) -- return TRUE; -- - if (g_mkdir_with_parents (dir, 0755) == 0) - return TRUE; - -- if (errno == EEXIST) -- return g_file_test (dir, G_FILE_TEST_IS_DIR); -- - g_warning ("GsmSessionSave: Failed to create directory %s: %s", dir, strerror (errno)); - - return FALSE; - } - - gchar * - gsm_util_get_empty_tmp_session_dir (void) - { - char *tmp; - gboolean exists; - - tmp = g_build_filename (g_get_user_config_dir (), - "gnome-session", - "saved-session.new", - NULL); - - exists = ensure_dir_exists (tmp); - - if (G_UNLIKELY (!exists)) { - g_warning ("GsmSessionSave: could not create directory for saved session: %s", tmp); - g_free (tmp); - return NULL; - } else { - /* make sure it's empty */ - GDir *dir; - const char *filename; - - dir = g_dir_open (tmp, 0, NULL); - if (dir) { - while ((filename = g_dir_read_name (dir))) { --- -2.3.7 - - -From fdc43e0cc51bf0d16bb9173bd3a23cf27c1ed2b3 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 20 Dec 2013 11:28:53 -0500 -Subject: [PATCH 11/17] Tie session selector to properties dialog - ---- - capplet/gsm-properties-dialog.c | 30 +++++- - configure.ac | 3 +- - data/session-selector.ui | 2 +- - tools/Makefile.am | 1 + - tools/gnome-session-selector.c | 211 ++++++++++++++++++++++++++++++++-------- - 5 files changed, 200 insertions(+), 47 deletions(-) - -diff --git a/capplet/gsm-properties-dialog.c b/capplet/gsm-properties-dialog.c -index d2be778..51fa510 100644 ---- a/capplet/gsm-properties-dialog.c -+++ b/capplet/gsm-properties-dialog.c -@@ -471,88 +471,114 @@ session_saved_message (GsmPropertiesDialog *dialog, - { - GtkLabel *label; - gchar *markup; - label = GTK_LABEL (gtk_builder_get_object (dialog->priv->xml, CAPPLET_SESSION_SAVED_WIDGET_NAME)); - if (is_error) - markup = g_markup_printf_escaped ("%s", msg); - else - markup = g_markup_escape_text (msg, -1); - gtk_label_set_markup (label, markup); - g_free (markup); - } - - static void - session_saved_cb (DBusGProxy *proxy, - DBusGProxyCall *call_id, - void *user_data) - { - gboolean res; - GsmPropertiesDialog *dialog = user_data; - - res = dbus_g_proxy_end_call (proxy, call_id, NULL, G_TYPE_INVALID); - if (res) - session_saved_message (dialog, _("Your session has been saved."), FALSE); - else - session_saved_message (dialog, _("Failed to save session"), TRUE); - - g_object_unref (proxy); - } - - static void --on_save_session_clicked (GtkWidget *widget, -- GsmPropertiesDialog *dialog) -+save_session_directly (GsmPropertiesDialog *dialog) - { - DBusGConnection *conn; - DBusGProxy *proxy; - DBusGProxyCall *call; - - conn = dbus_g_bus_get (DBUS_BUS_SESSION, NULL); - if (conn == NULL) { - session_saved_message (dialog, _("Could not connect to the session bus"), TRUE); - return; - } - - proxy = dbus_g_proxy_new_for_name (conn, GSM_SERVICE_DBUS, GSM_PATH_DBUS, GSM_INTERFACE_DBUS); - if (proxy == NULL) { - session_saved_message (dialog, _("Could not connect to the session manager"), TRUE); - return; - } - - call = dbus_g_proxy_begin_call (proxy, "SaveSession", session_saved_cb, dialog, NULL, G_TYPE_INVALID); - if (call == NULL) { - session_saved_message (dialog, _("Failed to save session"), TRUE); - g_object_unref (proxy); - return; - } - } - - static void -+save_session_from_selector (GsmPropertiesDialog *dialog, -+ const char *program_path) -+{ -+ char *command_line = g_strdup_printf ("%s --action save", program_path); -+ -+ g_spawn_command_line_sync (command_line, NULL, NULL, NULL, NULL); -+ -+ g_free (command_line); -+} -+ -+static void -+on_save_session_clicked (GtkWidget *widget, -+ GsmPropertiesDialog *dialog) -+{ -+ char *program_path; -+ -+ program_path = g_find_program_in_path ("gnome-session-selector"); -+ -+ if (program_path != NULL) { -+ save_session_from_selector (dialog, program_path); -+ g_free (program_path); -+ } else { -+ save_session_directly (dialog); -+ } -+} -+ -+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, -diff --git a/configure.ac b/configure.ac -index 505292c..9b97c15 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -21,92 +21,91 @@ LT_PREREQ([2.2.6]) - LT_INIT([dlopen disable-static]) - - GNOME_MAINTAINER_MODE_DEFINES - GNOME_COMPILE_WARNINGS([maximum]) - - AC_ARG_ENABLE(deprecation_flags, - [AS_HELP_STRING([--enable-deprecation-flags], - [use *_DISABLE_DEPRECATED flags @<:@default=no@:>@])],, - [enable_deprecation_flags=no]) - - if test "x$enable_deprecation_flags" = "xyes"; then - DISABLE_DEPRECATED_CFLAGS=$DISABLE_DEPRECATED - AC_SUBST([DISABLE_DEPRECATED_CFLAGS]) - fi - - GLIB_REQUIRED=2.35.0 - GTK3_REQUIRED=2.90.7 - DBUS_GLIB_REQUIRED=0.76 - UPOWER_REQUIRED=0.9.0 - JSON_GLIB_REQUIRED=0.10 - GNOME_DESKTOP_REQUIRED=3.9.91 - - AC_ARG_ENABLE(session-selector, AS_HELP_STRING([--enable-session-selector], - [enable building a custom session selector dialog]), - enable_session_selector=$enableval,enable_session_selector=no) - - AM_CONDITIONAL(BUILD_SESSION_SELECTOR, - [test "$enable_session_selector" = yes]) - - if test "$enable_session_selector" = yes; then -- PKG_CHECK_MODULES(SESSION_SELECTOR, gtk+-3.0 gio-2.0) -+ PKG_CHECK_MODULES(SESSION_SELECTOR, gtk+-3.0 gio-2.0 dbus-glib-1 >= $DBUS_GLIB_REQUIRED) - fi - - dnl ==================================================================== - dnl Dependency Checks - dnl ==================================================================== - - dnl Standard vertical stacks - PKG_CHECK_MODULES(GIO, gio-2.0) - PKG_CHECK_MODULES(GIOUNIX, gio-unix-2.0 >= $GLIB_REQUIRED) - PKG_CHECK_MODULES(GTK3, gtk+-3.0 >= $GTK3_REQUIRED) - - PKG_CHECK_MODULES(GNOME_SESSION, - glib-2.0 >= $GLIB_REQUIRED - gio-2.0 >= $GLIB_REQUIRED - dbus-glib-1 >= $DBUS_GLIB_REQUIRED - json-glib-1.0 >= $JSON_GLIB_REQUIRED - gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED - ) - - dnl We can only support old upower - dnl https://bugzilla.gnome.org/show_bug.cgi?id=710383 - PKG_CHECK_MODULES(UPOWER, upower-glib < 0.99.0, have_old_upower=yes, have_old_upower=no) - AS_IF([test x$have_old_upower = xyes], [ - AC_DEFINE([HAVE_OLD_UPOWER], [1], [Define if we have an older upower]) - ]) - AM_CONDITIONAL(HAVE_OLD_UPOWER, test x$have_old_upower = xyes) - - PKG_CHECK_MODULES(SESSION_PROPERTIES, - glib-2.0 >= $GLIB_REQUIRED - gtk+-3.0 >= $GTK3_REQUIRED -- dbus-glib-1 >= $DBUS_GLIB_REQUIRED - ) - - PKG_CHECK_MODULES(X11, x11) - PKG_CHECK_MODULES(SM, sm) - PKG_CHECK_MODULES(ICE, ice) - PKG_CHECK_MODULES(XEXT, xext xau) - - PKG_CHECK_MODULES(DBUS_GLIB, dbus-glib-1 >= $DBUS_GLIB_REQUIRED) - - PKG_CHECK_MODULES(EGG_SMCLIENT, gtk+-3.0) - - PKG_CHECK_MODULES(GL_TEST, xcomposite gl glib-2.0) - - dnl ==================================================================== - dnl Check for gconf - dnl ==================================================================== - AC_ARG_ENABLE([gconf], - AS_HELP_STRING([--enable-gconf], [Support gconf-based autostart]), - [enable_gconf=$enableval], - [enable_gconf=auto]) - - PKG_CHECK_MODULES(GCONF, gconf-2.0, [have_gconf=yes], [have_gconf=no]) - - if test x$enable_gconf = xauto ; then - enable_gconf=$have_gconf - elif test x$enable_gconf = xyes -a x$have_gconf = xno ; then - AC_MSG_ERROR([GConf support explicitly required, but gconf not found]) - fi - - if test x$enable_gconf = xyes ; then -diff --git a/data/session-selector.ui b/data/session-selector.ui -index 1c55712..1534a74 100644 ---- a/data/session-selector.ui -+++ b/data/session-selector.ui -@@ -20,61 +20,61 @@ - - - True - 0.5 - out - - - True - 12 - - - True - vertical - 6 - - - - True - other - - - - True - vertical - 0 - - - True - 0.0 - 0.5 -- Please select a custom session to run -+ Please select a custom session to use - - - True - True - 0 - - - - - - - False - True - 0 - - - - - True - vertical - 12 - - - True - 12 - - - True - True - never -diff --git a/tools/Makefile.am b/tools/Makefile.am -index 57b82c7..715affe 100644 ---- a/tools/Makefile.am -+++ b/tools/Makefile.am -@@ -49,37 +49,38 @@ gnome_session_check_accelerated_helper_CPPFLAGS = \ - -DPKGDATADIR=\""$(pkgdatadir)"\" \ - $(GL_TEST_CFLAGS) - - gnome_session_check_accelerated_helper_LDADD = \ - $(GL_TEST_LIBS) \ - $(X11_LIBS) - - gnome_session_check_accelerated_SOURCES = \ - gnome-session-check-accelerated-common.h \ - gnome-session-check-accelerated.c - - gnome_session_check_accelerated_CPPFLAGS = \ - -DLIBEXECDIR=\""$(libexecdir)"\" \ - $(AM_CPPFLAGS) \ - $(GTK3_CFLAGS) - - gnome_session_check_accelerated_LDADD = \ - $(GTK3_LIBS) \ - $(X11_LIBS) - - if BUILD_SESSION_SELECTOR - gnome_session_selector_CPPFLAGS = \ - $(AM_CPPFLAGS) \ - $(GNOME_SESSION_CFLAGS) \ - $(DBUS_GLIB_CFLAGS) \ - -DGTKBUILDER_DIR=\""$(pkgdatadir)"\" \ - -DLOCALE_DIR=\""$(datadir)/locale"\" \ - $(DISABLE_DEPRECATED_CFLAGS) - - gnome_session_selector_LDADD = \ -+ $(DBUS_GLIB_CFLAGS) \ - $(SESSION_SELECTOR_LIBS) - - gnome_session_selector_SOURCES = \ - gnome-session-selector.c - endif - - -include $(top_srcdir)/git.mk -diff --git a/tools/gnome-session-selector.c b/tools/gnome-session-selector.c -index d7584ff..8f37eca 100644 ---- a/tools/gnome-session-selector.c -+++ b/tools/gnome-session-selector.c -@@ -7,126 +7,133 @@ - * 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, see . - * - * Written by: Matthias Clasen - */ - - #include "config.h" - - #include - #include - #include - #include - #include - #include - - #include - #include - #include - - #include - #include - -+#include -+#include -+ -+#define GSM_SERVICE_DBUS "org.gnome.SessionManager" -+#define GSM_PATH_DBUS "/org/gnome/SessionManager" -+#define GSM_INTERFACE_DBUS "org.gnome.SessionManager" -+ - #define GSM_MANAGER_SCHEMA "org.gnome.SessionManager" - #define KEY_AUTOSAVE_ONE_SHOT "auto-save-session-one-shot" - - static GtkBuilder *builder; - static GtkWidget *session_list; - static GtkListStore *store; - static GtkTreeModelSort *sort_model; -+static char *info_text; - - static void select_session (const char *name); -+static gboolean make_session_current (const char *name); - - static char * - get_session_path (const char *name) - { - return g_build_filename (g_get_user_config_dir (), "gnome-session", name, NULL); - } - - static char * - find_new_session_name (void) - { - char *name; - char *path; - int i; - - for (i = 1; i < 20; i++) { - name = g_strdup_printf (_("Session %d"), i); - path = get_session_path (name); - if (!g_file_test (path, G_FILE_TEST_EXISTS)) { - g_free (path); - return name; - } - g_free (path); - g_free (name); - } - - return NULL; - } - - static gboolean - is_valid_session_name (const char *name) - { - GtkTreeIter iter; - char *n; -- const char *info_text; - char *warning_text; - gboolean user_tried_dot; - gboolean user_tried_slash; - GtkWidget *info_bar; - GtkWidget *label; - - if (name[0] == 0) { - return FALSE; - } - - if (name[0] == '.') { - user_tried_dot = TRUE; - } else { - user_tried_dot = FALSE; - } - - if (strchr (name, '/') != NULL) { - user_tried_slash = TRUE; - } else { - user_tried_slash = FALSE; - } - -- info_text = _("Please select a custom session to run"); - warning_text = NULL; - if (user_tried_dot && user_tried_slash) { - warning_text = g_strdup_printf ("%s\nNote: %s", - info_text, - _("Session names are not allowed to start with ‘.’ or contain ‘/’ characters")); - } else if (user_tried_dot) { - warning_text = g_strdup_printf ("%s\nNote: %s", - info_text, - _("Session names are not allowed to start with ‘.’")); - } else if (user_tried_slash) { - warning_text = g_strdup_printf ("%s\nNote: %s", - info_text, - _("Session names are not allowed to contain ‘/’ characters")); - } - - gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter); - do { - gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, 0, &n, -1); - if (strcmp (n, name) == 0) { - char *message; - message = g_strdup_printf (_("A session named ‘%s’ already exists"), name); - warning_text = g_strdup_printf ("%s\nNote: %s", info_text, message); - g_free (message); - g_free (n); - break; - } - g_free (n); - } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter)); - - info_bar = (GtkWidget *) gtk_builder_get_object (builder, "info-bar"); -@@ -182,517 +189,637 @@ populate_session_list (GtkWidget *session_list) - default_name = NULL; - if (readlink (saved_session, last_session, PATH_MAX - 1) > 0) { - default_name = g_path_get_basename (last_session); - } - - while ((name = g_dir_read_name (dir)) != NULL) { - if (strcmp (name, "saved-session") == 0) - continue; - - gtk_list_store_insert_with_values (store, &iter, 100, 0, name, -1); - - if (g_strcmp0 (default_name, name) == 0) { - GtkTreeSelection *selection; - GtkTreeIter child_iter; - - gtk_tree_model_sort_convert_child_iter_to_iter (GTK_TREE_MODEL_SORT (sort_model), &child_iter, &iter); - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (session_list)); - gtk_tree_selection_select_iter (selection, &child_iter); - } - } - - g_free (default_name); - g_dir_close (dir); - - out: - g_free (saved_session); - g_free (path); - } - - static char * -+get_last_session (void) -+{ -+ char *saved_session; -+ char last_session[PATH_MAX] = ""; -+ char *name = NULL; -+ -+ saved_session = get_session_path ("saved-session"); -+ -+ if (readlink (saved_session, last_session, PATH_MAX - 1) > 0) { -+ name = g_path_get_basename (last_session); -+ } -+ -+ g_free (saved_session); -+ -+ return name; -+} -+ -+static char * - get_selected_session (void) - { - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; - gchar *name; - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (session_list)); - if (gtk_tree_selection_get_selected (selection, &model, &iter)) { - gtk_tree_model_get (model, &iter, 0, &name, -1); - return name; - } - - return NULL; - } - - static void - remove_session (const char *name) - { - char *path1, *path2; - char *n, *path; - const char *d; - GDir *dir; - GError *error; - - path1 = get_session_path ("saved-session"); - path2 = get_session_path (name); - - error = NULL; - n = g_file_read_link (path1, &error); - if (n == NULL) { - g_warning ("Failed to read link: %s", error->message); - g_error_free (error); - } - else if (strcmp (n, name) == 0) { - unlink (path1); - } - g_free (n); - - dir = g_dir_open (path2, 0, NULL); - while ((d = g_dir_read_name (dir)) != NULL) { - path = g_build_filename (path2, d, NULL); - unlink (path); - g_free (path); - } - g_dir_close (dir); - - remove (path2); - - g_free (path1); - g_free (path2); - } - -+static gboolean -+make_session_current (const char *name) -+{ -+ char *path1; -+ gboolean ret = TRUE; -+ -+ path1 = g_build_filename (g_get_user_config_dir (), "gnome-session", "saved-session", NULL); -+ -+ unlink (path1); -+ if (symlink (name, path1) < 0) { -+ g_warning ("Failed to make session '%s' current", name); -+ ret = FALSE; -+ } -+ -+ g_free (path1); -+ -+ return ret; -+} -+ - static void - on_remove_session_clicked (GtkButton *button, - gpointer data) - { - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; - char *name; - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (session_list)); - if (gtk_tree_selection_get_selected (selection, &model, &iter)) { - GtkTreeIter child_iter; - gtk_tree_model_get (model, &iter, 0, &name, -1); - remove_session (name); - g_free (name); - - gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (model), &child_iter, &iter); - gtk_list_store_remove (GTK_LIST_STORE (store), &child_iter); - - if (!gtk_tree_selection_get_selected (selection, NULL, NULL)) { - gtk_tree_model_get_iter_first (model, &iter); - gtk_tree_model_get (model, &iter, 0, &name, -1); - select_session (name); -+ make_session_current (name); - g_free (name); - } - } - } - - static void - begin_rename (void) - { - GtkTreePath *path; - GtkTreeViewColumn *column; - GList *cells; - - gtk_widget_grab_focus (session_list); - - gtk_tree_view_get_cursor (GTK_TREE_VIEW (session_list), - &path, &column); - - cells = gtk_cell_layout_get_cells (GTK_CELL_LAYOUT (column)); - - if (cells != NULL) { - GtkCellRenderer *cell; - - cell = (GtkCellRenderer *) cells->data; - g_list_free (cells); - - g_object_set (cell, "editable", TRUE, NULL); - gtk_tree_view_set_cursor_on_cell (GTK_TREE_VIEW (session_list), path, - column, cell, TRUE); - } - gtk_tree_path_free (path); - } - - static void - on_rename_session_clicked (GtkButton *button, - gpointer data) - { - begin_rename (); - } - - static void - on_continue_clicked (GtkButton *button, - gpointer data) - { - char *name; - - name = get_selected_session (); - g_free (name); - - gtk_main_quit (); - } - - static void - create_session (const char *name) - { - char *path; - GtkTreeIter iter; - - path = get_session_path (name); - -- if (mkdir (path, 0755) < 0) { -+ if (g_mkdir_with_parents (path, 0755) < 0) { - g_warning ("Failed to create directory %s", path); - } - else { - char *marker; - - gtk_list_store_insert_with_values (store, &iter, 100, 0, name, -1); - - marker = g_build_filename (path, ".new-session", NULL); - creat (marker, 0600); - g_free (marker); - } - - g_free (path); - } - - static gboolean - rename_session (const char *old_name, - const char *new_name) - { - char *old_path, *new_path; - int result; - - if (g_strcmp0 (old_name, new_name) == 0) { - return TRUE; - } - - if (!is_valid_session_name (new_name)) { - return FALSE; - } - - old_path = get_session_path (old_name); - new_path = get_session_path (new_name); - - result = g_rename (old_path, new_path); - - if (result < 0) { - g_warning ("Failed to rename session from '%s' to '%s': %m", old_name, new_name); -+ } else { -+ char *last_session; -+ last_session = get_last_session (); -+ if (g_strcmp0 (old_name, last_session) == 0) { -+ make_session_current (new_name); -+ } -+ g_free (last_session); - } - - g_free (old_path); - g_free (new_path); -- - return result == 0; - } - - static gboolean --make_session_current (const char *name) --{ -- char *path1; -- gboolean ret = TRUE; -- -- path1 = g_build_filename (g_get_user_config_dir (), "gnome-session", "saved-session", NULL); -- -- unlink (path1); -- if (symlink (name, path1) < 0) { -- g_warning ("Failed to make session '%s' current", name); -- ret = FALSE; -- } -- -- g_free (path1); -- -- return ret; --} -- --static gboolean - create_and_select_session (const char *name) - { - gchar *path; - - if (name[0] == 0 || name[0] == '.' || strchr (name, '/')) { - g_warning ("Invalid session name"); - return FALSE; - } - - path = g_build_filename (g_get_user_config_dir (), "gnome-session", name, NULL); - if (!g_file_test (path, G_FILE_TEST_IS_DIR)) { -- if (mkdir (path, 0755) < 0) { -+ if (g_mkdir_with_parents (path, 0755) < 0) { - g_warning ("Failed to create directory %s", path); - g_free (path); - return FALSE; - } - } - - g_free (path); - - return make_session_current (name); - } - - static void - select_session (const char *name) - { - GtkTreeIter iter; - char *n; - -- make_session_current (name); -- - /* now select it in the list */ - gtk_tree_model_get_iter_first (GTK_TREE_MODEL (sort_model), &iter); - do { - gtk_tree_model_get (GTK_TREE_MODEL (sort_model), &iter, 0, &n, -1); - if (strcmp (n, name) == 0) { - GtkTreePath *path; - - path = gtk_tree_model_get_path (GTK_TREE_MODEL (sort_model), &iter); - gtk_tree_view_set_cursor (GTK_TREE_VIEW (session_list), path, NULL, FALSE); - gtk_tree_path_free (path); - g_free (n); - break; - } - g_free (n); - } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (sort_model), &iter)); - } - - static void --on_new_session_clicked (GtkButton *button, -- gpointer data) -+create_session_and_begin_rename (void) - { - gchar *name; - - name = find_new_session_name (); - create_session (name); - select_session (name); - - begin_rename (); - } - - static void -+on_new_session_clicked (GtkButton *button, -+ gpointer data) -+{ -+ create_session_and_begin_rename (); -+} -+ -+static void - on_selection_changed (GtkTreeSelection *selection, - gpointer data) - { - char *name; - - name = get_selected_session (); - - if (name == NULL) { - return; - } - -- make_session_current (name); -- - g_free (name); - } - - static void - update_remove_button (void) - { - GtkWidget *button; - - button = (GtkWidget *)gtk_builder_get_object (builder, "remove-session"); - if (gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), NULL) > 1) { - gtk_widget_set_sensitive (button, TRUE); - } else { - gtk_widget_set_sensitive (button, FALSE); - } - } - - static void - on_row_edited (GtkCellRendererText *cell, - const char *path_string, - const char *new_name, - gpointer data) - { - GtkTreePath *path; - GtkTreeIter sort_iter, items_iter; - char *old_name; - gboolean was_renamed; - - path = gtk_tree_path_new_from_string (path_string); - gtk_tree_model_get_iter (GTK_TREE_MODEL (sort_model), &sort_iter, path); - - gtk_tree_model_get (GTK_TREE_MODEL (sort_model), &sort_iter, 0, &old_name, -1); - - was_renamed = rename_session (old_name, new_name); - - if (was_renamed) { - gtk_tree_model_sort_convert_iter_to_child_iter (sort_model, &items_iter, &sort_iter); - - gtk_list_store_set (store, &items_iter, 0, g_strdup (new_name), -1); - g_free (old_name); -- make_session_current (new_name); - } else { - begin_rename (); - } - - gtk_tree_path_free (path); - - g_object_set (cell, "editable", FALSE, NULL); - } - - static void - on_row_deleted (GtkTreeModel *model, - GtkTreePath *path, - gpointer data) - { - update_remove_button (); - } - - static void - on_row_inserted (GtkTreeModel *model, - GtkTreePath *path, - GtkTreeIter *iter, - gpointer data) - { - update_remove_button (); - } - - static void - on_row_activated (GtkTreeView *tree_view, - GtkTreePath *path, - GtkTreeViewColumn *column, - gpointer data) - { -- char *name; -- -- name = get_selected_session (); -- g_free (name); -- - gtk_main_quit (); - } - - static void - auto_save_next_session (void) - { - GSettings *settings; - - settings = g_settings_new (GSM_MANAGER_SCHEMA); - g_settings_set_boolean (settings, KEY_AUTOSAVE_ONE_SHOT, TRUE); - g_object_unref (settings); - } - - static void - auto_save_next_session_if_needed (void) - { - char *marker; - - marker = g_build_filename (g_get_user_config_dir (), - "gnome-session", "saved-session", - ".new-session", NULL); - - if (g_file_test (marker, G_FILE_TEST_EXISTS)) { - auto_save_next_session (); - unlink (marker); - } - g_free (marker); - } - -+static void -+save_session (void) -+{ -+ DBusGConnection *conn; -+ DBusGProxy *proxy; -+ GError *error; -+ -+ conn = dbus_g_bus_get (DBUS_BUS_SESSION, NULL); -+ if (conn == NULL) { -+ g_warning ("Could not connect to the session bus"); -+ return; -+ } -+ -+ proxy = dbus_g_proxy_new_for_name (conn, GSM_SERVICE_DBUS, GSM_PATH_DBUS, GSM_INTERFACE_DBUS); -+ if (proxy == NULL) { -+ g_warning ("Could not connect to the session manager"); -+ return; -+ } -+ -+ error = NULL; -+ if (!dbus_g_proxy_call (proxy, "SaveSession", &error, G_TYPE_INVALID, G_TYPE_INVALID)) { -+ g_warning ("Failed to save session: %s", error->message); -+ g_error_free (error); -+ return; -+ } -+ -+ g_object_unref (proxy); -+} -+ - static int - compare_sessions (GtkTreeModel *model, - GtkTreeIter *a, - GtkTreeIter *b, - gpointer data) - { - char *name_a, *name_b; - int result; - - gtk_tree_model_get (model, a, 0, &name_a, -1); - gtk_tree_model_get (model, b, 0, &name_b, -1); - - result = g_utf8_collate (name_a, name_b); - - g_free (name_a); - g_free (name_b); - - return result; - } - - static void - on_map (GtkWidget *widget, - gpointer data) - { - gdk_window_focus (gtk_widget_get_window (widget), GDK_CURRENT_TIME); - } - - int - main (int argc, char *argv[]) - { - GtkWidget *window; - GtkWidget *widget; -+ GtkWidget *label; - GtkCellRenderer *cell; - GtkTreeViewColumn *column; - GtkTreeSelection *selection; - GError *error; -+ char *selected_session; -+ -+ static char *action = NULL; -+ static char **remaining_args = NULL; -+ static GOptionEntry entries[] = { -+ {"action", '\0', 0, G_OPTION_ARG_STRING, &action, N_("What to do with session selection (save|load|print)"), NULL}, -+{ G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &remaining_args, N_("[session-name]"), NULL} -+ }; -+ -+ if (action == NULL) { -+ if (getenv ("SESSION_MANAGER") != NULL) -+ action = "print"; -+ else -+ action = "load"; -+ } - -- if (getenv ("SESSION_MANAGER") != NULL) -+ if (getenv ("SESSION_MANAGER") != NULL && strcmp (action, "load") == 0) { -+ g_warning ("Cannot load new session when session currently loaded"); - return 1; -+ } -+ -+ if (getenv ("SESSION_MANAGER") == NULL && strcmp (action, "save") == 0) { -+ g_warning ("Can only save session when session loaded"); -+ return 1; -+ } -+ -+ if (strcmp (action, "load") != 0 && strcmp (action, "save") != 0 && strcmp (action, "print") != 0) { -+ g_warning ("'%s' is not a supported action. Supported actions are load, save, and print.\n", action); -+ return 1; -+ } - -- gtk_init (&argc, &argv); -- if (argc > 1) { -- g_print ("create and select session\n"); -- if (!create_and_select_session (argv[1])) -+ error = NULL; -+ gtk_init_with_args (&argc, &argv, -+ NULL, entries, GETTEXT_PACKAGE, &error); -+ -+ if (remaining_args != NULL) { -+ if (g_strv_length (remaining_args) > 1) { -+ g_warning ("gnome-session-selector takes at most one session argument"); -+ return 1; -+ } -+ -+ if (!create_and_select_session (remaining_args[0])) - return 1; - else - return 0; - } - - builder = gtk_builder_new (); - gtk_builder_set_translation_domain (builder, GETTEXT_PACKAGE); - - error = NULL; - if (!gtk_builder_add_from_file (builder, GTKBUILDER_DIR "/" "session-selector.ui", &error)) { - g_warning ("Could not load file 'session-selector.ui': %s", error->message); - exit (1); - } - - window = (GtkWidget *) gtk_builder_get_object (builder, "main-window"); - - store = (GtkListStore *) gtk_builder_get_object (builder, "session-store"); - sort_model = (GtkTreeModelSort *) gtk_builder_get_object (builder, "sort-model"); - - gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (sort_model), - 0, compare_sessions, NULL, NULL); - gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model), - 0, GTK_SORT_ASCENDING); - g_signal_connect (store, "row-deleted", G_CALLBACK (on_row_deleted), NULL); - g_signal_connect (store, "row-inserted", G_CALLBACK (on_row_inserted), NULL); - session_list = (GtkWidget *) gtk_builder_get_object (builder, "session-list"); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (session_list)); - gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); - - populate_session_list (session_list); - - cell = gtk_cell_renderer_text_new (); - g_signal_connect (cell, "edited", G_CALLBACK (on_row_edited), NULL); - - column = gtk_tree_view_column_new_with_attributes ("", cell, "text", 0, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (session_list), GTK_TREE_VIEW_COLUMN (column)); - - g_signal_connect (session_list, "row-activated", G_CALLBACK (on_row_activated), NULL); - - g_signal_connect (selection, "changed", - G_CALLBACK (on_selection_changed), NULL); - - widget = (GtkWidget *) gtk_builder_get_object (builder, "new-session"); - g_signal_connect (widget, "clicked", G_CALLBACK (on_new_session_clicked), NULL); - widget = (GtkWidget *) gtk_builder_get_object (builder, "remove-session"); - g_signal_connect (widget, "clicked", G_CALLBACK (on_remove_session_clicked), NULL); - widget = (GtkWidget *) gtk_builder_get_object (builder, "rename-session"); - g_signal_connect (widget, "clicked", G_CALLBACK (on_rename_session_clicked), NULL); - widget = (GtkWidget *) gtk_builder_get_object (builder, "continue-button"); - g_signal_connect (widget, "clicked", G_CALLBACK (on_continue_clicked), NULL); - - g_signal_connect (window, "map", G_CALLBACK (on_map), NULL); - gtk_widget_show (window); - -+ if (g_strcmp0 (action, "load") == 0) { -+ info_text = _("Please select a custom session to run"); -+ } else if (g_strcmp0 (action, "print") == 0) { -+ info_text = _("Please select a session to use"); -+ } else if (g_strcmp0 (action, "save") == 0) { -+ info_text = _("Please select a session to save to"); -+ } -+ -+ label = (GtkWidget*) gtk_builder_get_object (builder, "info-label"); -+ gtk_label_set_markup (GTK_LABEL (label), info_text); -+ -+ selected_session = get_selected_session (); -+ -+ if (selected_session == NULL) { -+ create_session_and_begin_rename (); -+ } else { -+ g_free (selected_session); -+ } -+ - gtk_main (); - -- auto_save_next_session_if_needed (); -+ selected_session = get_selected_session (); -+ -+ if (g_strcmp0 (action, "load") == 0) { -+ make_session_current (selected_session); -+ auto_save_next_session_if_needed (); -+ } else if (g_strcmp0 (action, "save") == 0) { -+ char *last_session; -+ -+ last_session = get_last_session (); -+ make_session_current (selected_session); -+ save_session (); -+ if (last_session != NULL) -+ make_session_current (last_session); -+ } else if (g_strcmp0 (action, "print") == 0) { -+ g_print ("%s\n", selected_session); -+ } -+ g_free (selected_session); - - return 0; - } --- -2.3.7 - - -From ebf36d525604940d33f23732ddeb6c8ab306a7b0 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 20 Dec 2013 11:32:52 -0500 -Subject: [PATCH 12/17] make save-session stall until it finishes - ---- - gnome-session/gsm-manager.c | 58 ++++++++++++++++++++++++++---- - gnome-session/gsm-manager.h | 2 +- - gnome-session/org.gnome.SessionManager.xml | 1 + - 3 files changed, 53 insertions(+), 8 deletions(-) - -diff --git a/gnome-session/gsm-manager.c b/gnome-session/gsm-manager.c -index 67e0c82..2af3358 100644 ---- a/gnome-session/gsm-manager.c -+++ b/gnome-session/gsm-manager.c -@@ -114,60 +114,61 @@ typedef enum - GSM_MANAGER_LOGOUT_REBOOT_INTERACT, - GSM_MANAGER_LOGOUT_SHUTDOWN, - GSM_MANAGER_LOGOUT_SHUTDOWN_INTERACT, - } GsmManagerLogoutType; - - struct GsmManagerPrivate - { - gboolean failsafe; - GsmStore *clients; - GsmStore *inhibitors; - GsmInhibitorFlag inhibited_actions; - GsmStore *apps; - GsmPresence *presence; - GsmXsmpServer *xsmp_server; - - char *session_name; - gboolean is_fallback_session : 1; - - /* Current status */ - GsmManagerPhase phase; - guint phase_timeout_id; - GSList *required_apps; - GSList *pending_apps; - GsmManagerLogoutMode logout_mode; - GSList *query_clients; - guint query_timeout_id; - /* This is used for GSM_MANAGER_PHASE_END_SESSION only at the moment, - * since it uses a sublist of all running client that replied in a - * specific way */ - GSList *next_query_clients; -+ GSList *pending_save_invocations; - /* This is the action that will be done just before we exit */ - GsmManagerLogoutType logout_type; - - /* List of clients which were disconnected due to disabled condition - * and shouldn't be automatically restarted */ - GSList *condition_clients; - - GSList *pending_end_session_tasks; - GCancellable *end_session_cancellable; - - GSettings *settings; - GSettings *session_settings; - GSettings *screensaver_settings; - GSettings *lockdown_settings; - - GsmSystem *system; - DBusGProxy *bus_proxy; - DBusGConnection *connection; - gboolean dbus_disconnected : 1; - - GsmShell *shell; - guint shell_end_session_dialog_canceled_id; - guint shell_end_session_dialog_open_failed_id; - guint shell_end_session_dialog_confirmed_logout_id; - guint shell_end_session_dialog_confirmed_shutdown_id; - guint shell_end_session_dialog_confirmed_reboot_id; - }; - - enum { - PROP_0, -@@ -1208,90 +1209,124 @@ query_end_session_complete (GsmManager *manager) - static gboolean - _client_request_save (GsmClient *client, - ClientEndSessionData *data) - { - gboolean ret; - GError *error; - - error = NULL; - ret = gsm_client_request_save (client, data->flags, &error); - if (ret) { - g_debug ("GsmManager: adding client to query clients: %s", gsm_client_peek_id (client)); - data->manager->priv->query_clients = g_slist_prepend (data->manager->priv->query_clients, - client); - } else if (error) { - g_debug ("GsmManager: unable to query client: %s", error->message); - g_error_free (error); - } - - return FALSE; - } - - static gboolean - _client_request_save_helper (const char *id, - GsmClient *client, - ClientEndSessionData *data) - { - return _client_request_save (client, data); - } - - static void -+fail_pending_save_invocations (GsmManager *manager, -+ GError *error) -+{ -+ GSList *l; -+ -+ for (l = manager->priv->pending_save_invocations; l != NULL; l = l->next) { -+ DBusGMethodInvocation *context = l->data; -+ -+ dbus_g_method_return_error (context, error); -+ } -+ -+ g_slist_free (manager->priv->pending_save_invocations); -+ manager->priv->pending_save_invocations = NULL; -+} -+ -+static void -+finish_pending_save_invocations (GsmManager *manager) -+{ -+ GSList *l; -+ -+ for (l = manager->priv->pending_save_invocations; l != NULL; l = l->next) { -+ DBusGMethodInvocation *context = l->data; -+ -+ dbus_g_method_return (context); -+ } -+ -+ g_slist_free (manager->priv->pending_save_invocations); -+ manager->priv->pending_save_invocations = NULL; -+} -+ -+static void - query_save_session_complete (GsmManager *manager) - { - GError *error = NULL; - - if (g_slist_length (manager->priv->next_query_clients) > 0) { - ClientEndSessionData data; - - data.manager = manager; - data.flags = GSM_CLIENT_END_SESSION_FLAG_LAST; - - g_slist_foreach (manager->priv->next_query_clients, - (GFunc)_client_request_save, - &data); - - g_slist_free (manager->priv->next_query_clients); - manager->priv->next_query_clients = NULL; - - return; - } - - if (manager->priv->query_timeout_id > 0) { - g_source_remove (manager->priv->query_timeout_id); - manager->priv->query_timeout_id = 0; - } - - gsm_session_save (manager->priv->clients, &error); - - if (error) { - g_warning ("Error saving session: %s", error->message); -+ fail_pending_save_invocations (manager, error); - g_error_free (error); -+ } else { -+ finish_pending_save_invocations (manager); - } - } - - static guint32 - generate_cookie (void) - { - guint32 cookie; - - cookie = (guint32)g_random_int_range (1, G_MAXINT32); - - return cookie; - } - - static guint32 - _generate_unique_cookie (GsmManager *manager) - { - guint32 cookie; - - do { - cookie = generate_cookie (); - } while (gsm_store_find (manager->priv->inhibitors, (GsmStoreFunc)_find_by_cookie, &cookie) != NULL); - - return cookie; - } - - static gboolean - _on_query_end_session_timeout (GsmManager *manager) - { - GSList *l; - -@@ -3238,92 +3273,101 @@ gsm_manager_reboot (GsmManager *manager, - if (manager->priv->phase != GSM_MANAGER_PHASE_RUNNING) { - error = g_error_new (GSM_MANAGER_ERROR, - GSM_MANAGER_ERROR_NOT_IN_RUNNING, - "Reboot interface is only available during the Running phase"); - dbus_g_method_return_error (context, error); - g_error_free (error); - return FALSE; - } - - if (_log_out_is_locked_down (manager)) { - error = g_error_new (GSM_MANAGER_ERROR, - GSM_MANAGER_ERROR_LOCKED_DOWN, - "Logout has been locked down"); - dbus_g_method_return_error (context, error); - g_error_free (error); - return FALSE; - } - - task = g_task_new (manager, manager->priv->end_session_cancellable, (GAsyncReadyCallback) complete_end_session_task, context); - - manager->priv->pending_end_session_tasks = g_slist_prepend (manager->priv->pending_end_session_tasks, - task); - - request_reboot (manager); - - return TRUE; - } - - - gboolean --gsm_manager_save_session (GsmManager *manager, -- GError **error) -+gsm_manager_save_session (GsmManager *manager, -+ DBusGMethodInvocation *context) - { - ClientEndSessionData data; -+ GError *error; - - g_debug ("GsmManager: SaveSession called"); - - g_return_val_if_fail (GSM_IS_MANAGER (manager), FALSE); - - if (manager->priv->phase != GSM_MANAGER_PHASE_RUNNING) { -- g_set_error (error, -- GSM_MANAGER_ERROR, -- GSM_MANAGER_ERROR_NOT_IN_RUNNING, -- "SaveSession interface is only available during the Running phase"); -+ error = g_error_new (GSM_MANAGER_ERROR, -+ GSM_MANAGER_ERROR_NOT_IN_RUNNING, -+ "SaveSession interface is only available during the Running phase"); -+ dbus_g_method_return_error (context, error); -+ g_error_free (error); - return FALSE; - } - - data.manager = manager; - data.flags = 0; - gsm_store_foreach (manager->priv->clients, - (GsmStoreFunc)_client_request_save_helper, - &data); - - if (manager->priv->query_clients) { - manager->priv->query_timeout_id = g_timeout_add_seconds (GSM_MANAGER_SAVE_SESSION_TIMEOUT, - (GSourceFunc)_on_query_save_session_timeout, - manager); -+ -+ manager->priv->pending_save_invocations = g_slist_prepend (manager->priv->pending_save_invocations, -+ context); -+ - return TRUE; - } else { - g_debug ("GsmManager: Nothing to save"); -- return FALSE; -+ dbus_g_method_return (context); -+ return TRUE; - } -+ -+ return TRUE; - } - - gboolean - gsm_manager_can_shutdown (GsmManager *manager, - gboolean *shutdown_available, - GError **error) - { - g_debug ("GsmManager: CanShutdown called"); - - g_return_val_if_fail (GSM_IS_MANAGER (manager), FALSE); - - *shutdown_available = !_log_out_is_locked_down (manager) && - (gsm_system_can_stop (manager->priv->system) - || gsm_system_can_restart (manager->priv->system) - || gsm_system_can_suspend (manager->priv->system) - || gsm_system_can_hibernate (manager->priv->system)); - - return TRUE; - } - - gboolean - gsm_manager_logout (GsmManager *manager, - guint logout_mode, - GError **error) - { - g_debug ("GsmManager: Logout called"); - - g_return_val_if_fail (GSM_IS_MANAGER (manager), FALSE); - - if (manager->priv->phase != GSM_MANAGER_PHASE_RUNNING) { -diff --git a/gnome-session/gsm-manager.h b/gnome-session/gsm-manager.h -index bc16654..c365596 100644 ---- a/gnome-session/gsm-manager.h -+++ b/gnome-session/gsm-manager.h -@@ -138,61 +138,61 @@ void _gsm_manager_set_active_session (GsmManager * - /* exported methods */ - - gboolean gsm_manager_register_client (GsmManager *manager, - const char *app_id, - const char *client_startup_id, - DBusGMethodInvocation *context); - gboolean gsm_manager_unregister_client (GsmManager *manager, - const char *session_client_id, - DBusGMethodInvocation *context); - - gboolean gsm_manager_inhibit (GsmManager *manager, - const char *app_id, - guint toplevel_xid, - const char *reason, - guint flags, - DBusGMethodInvocation *context); - gboolean gsm_manager_uninhibit (GsmManager *manager, - guint inhibit_cookie, - DBusGMethodInvocation *context); - gboolean gsm_manager_is_inhibited (GsmManager *manager, - guint flags, - gboolean *is_inhibited, - GError *error); - - gboolean gsm_manager_shutdown (GsmManager *manager, - DBusGMethodInvocation *context); - gboolean gsm_manager_reboot (GsmManager *manager, - DBusGMethodInvocation *context); - - gboolean gsm_manager_save_session (GsmManager *manager, -- GError **error); -+ DBusGMethodInvocation *context); - - gboolean gsm_manager_can_shutdown (GsmManager *manager, - gboolean *shutdown_available, - GError **error); - gboolean gsm_manager_logout (GsmManager *manager, - guint logout_mode, - GError **error); - - gboolean gsm_manager_setenv (GsmManager *manager, - const char *variable, - const char *value, - GError **error); - gboolean gsm_manager_get_locale (GsmManager *manager, - int category, - const char **value, - GError **error); - gboolean gsm_manager_initialization_error (GsmManager *manager, - const char *message, - gboolean fatal, - GError **error); - - gboolean gsm_manager_get_clients (GsmManager *manager, - GPtrArray **clients, - GError **error); - gboolean gsm_manager_get_inhibitors (GsmManager *manager, - GPtrArray **inhibitors, - GError **error); - gboolean gsm_manager_is_autostart_condition_handled (GsmManager *manager, - const char *condition, - gboolean *handled, -diff --git a/gnome-session/org.gnome.SessionManager.xml b/gnome-session/org.gnome.SessionManager.xml -index eacac4b..81d3da1 100644 ---- a/gnome-session/org.gnome.SessionManager.xml -+++ b/gnome-session/org.gnome.SessionManager.xml -@@ -262,60 +262,61 @@ - True if condition is handled, false otherwise - - - - - Allows the caller to determine whether the session manager is - handling changes to the specified autostart condition. - - - - - - - - - Request a shutdown dialog. - - - - - - - - - Request a reboot dialog. - - - - - -+ - - - Request to save session - - - - - - - - True if shutdown is available to the user, false otherwise - - - - - Allows the caller to determine whether or not it's okay to show - a shutdown option in the UI - - - - - - - - The type of logout that is being requested - - - - - Request a logout dialog --- -2.3.7 - - -From b7ed1a7fd45a0dac66353f8ec5b8f30a5f0207a8 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 20 Dec 2013 15:32:04 -0500 -Subject: [PATCH 13/17] manager: save session type in session dir - -If a user saved their session when in classic mode, make sure we -record that information so subsequent calls to gnome-session will -restore classic mode. ---- - gnome-session/gsm-manager.c | 21 ++++++++++++++++++-- - gnome-session/gsm-manager.h | 1 + - gnome-session/gsm-session-save.c | 41 +++++++++++++++++++++++++++++++++++++--- - gnome-session/gsm-session-save.h | 5 +++-- - gnome-session/main.c | 14 +++++++++++--- - 5 files changed, 72 insertions(+), 10 deletions(-) - -diff --git a/gnome-session/gsm-manager.c b/gnome-session/gsm-manager.c -index 2af3358..8a8943d 100644 ---- a/gnome-session/gsm-manager.c -+++ b/gnome-session/gsm-manager.c -@@ -1265,61 +1265,61 @@ finish_pending_save_invocations (GsmManager *manager) - g_slist_free (manager->priv->pending_save_invocations); - manager->priv->pending_save_invocations = NULL; - } - - static void - query_save_session_complete (GsmManager *manager) - { - GError *error = NULL; - - if (g_slist_length (manager->priv->next_query_clients) > 0) { - ClientEndSessionData data; - - data.manager = manager; - data.flags = GSM_CLIENT_END_SESSION_FLAG_LAST; - - g_slist_foreach (manager->priv->next_query_clients, - (GFunc)_client_request_save, - &data); - - g_slist_free (manager->priv->next_query_clients); - manager->priv->next_query_clients = NULL; - - return; - } - - if (manager->priv->query_timeout_id > 0) { - g_source_remove (manager->priv->query_timeout_id); - manager->priv->query_timeout_id = 0; - } - -- gsm_session_save (manager->priv->clients, &error); -+ gsm_session_save (manager->priv->clients, manager->priv->session_name, &error); - - if (error) { - g_warning ("Error saving session: %s", error->message); - fail_pending_save_invocations (manager, error); - g_error_free (error); - } else { - finish_pending_save_invocations (manager); - } - } - - static guint32 - generate_cookie (void) - { - guint32 cookie; - - cookie = (guint32)g_random_int_range (1, G_MAXINT32); - - return cookie; - } - - static guint32 - _generate_unique_cookie (GsmManager *manager) - { - guint32 cookie; - - do { - cookie = generate_cookie (); - } while (gsm_store_find (manager->priv->inhibitors, (GsmStoreFunc)_find_by_cookie, &cookie) != NULL); - - return cookie; -@@ -1532,60 +1532,77 @@ debug_app_summary (GsmManager *manager) - - g_debug ("GsmManager: App startup summary"); - for (phase = GSM_MANAGER_PHASE_EARLY_INITIALIZATION; phase < GSM_MANAGER_PHASE_RUNNING; phase++) { - g_debug ("GsmManager: Phase %s", phase_num_to_name (phase)); - gsm_store_foreach (manager->priv->apps, - (GsmStoreFunc)_debug_app_for_phase, - GUINT_TO_POINTER (phase)); - } - } - - void - gsm_manager_start (GsmManager *manager) - { - g_debug ("GsmManager: GSM starting to manage"); - - g_return_if_fail (GSM_IS_MANAGER (manager)); - - gsm_xsmp_server_start (manager->priv->xsmp_server); - gsm_manager_set_phase (manager, GSM_MANAGER_PHASE_EARLY_INITIALIZATION); - debug_app_summary (manager); - start_phase (manager); - } - - const char * - _gsm_manager_get_default_session (GsmManager *manager) - { - return g_settings_get_string (manager->priv->session_settings, - KEY_SESSION_NAME); - } - -+char * -+_gsm_manager_get_saved_session (GsmManager *manager) -+{ -+ char *file; -+ char *type; -+ gboolean loaded; -+ -+ file = g_build_filename (gsm_util_get_saved_session_dir (), "type", NULL); -+ loaded = g_file_get_contents (file, &type, NULL, NULL); -+ g_free (file); -+ -+ if (!loaded) -+ return NULL; -+ -+ return type; -+} -+ - void - _gsm_manager_set_active_session (GsmManager *manager, - const char *session_name, - gboolean is_fallback) - { - g_free (manager->priv->session_name); - manager->priv->session_name = g_strdup (session_name); - manager->priv->is_fallback_session = is_fallback; - } - - static gboolean - _app_has_app_id (const char *id, - GsmApp *app, - const char *app_id_a) - { - const char *app_id_b; - - app_id_b = gsm_app_peek_app_id (app); - return (app_id_b != NULL && strcmp (app_id_a, app_id_b) == 0); - } - - static GsmApp * - find_app_for_app_id (GsmManager *manager, - const char *app_id) - { - GsmApp *app; - app = (GsmApp *)gsm_store_find (manager->priv->apps, - (GsmStoreFunc)_app_has_app_id, - (char *)app_id); - return app; -@@ -2070,61 +2087,61 @@ on_xsmp_client_register_confirmed (GsmXSMPClient *client, - } - } - - static gboolean - auto_save_is_enabled (GsmManager *manager) - { - return g_settings_get_boolean (manager->priv->settings, KEY_AUTOSAVE_ONE_SHOT) - || g_settings_get_boolean (manager->priv->settings, KEY_AUTOSAVE); - } - - static void - maybe_save_session (GsmManager *manager) - { - GError *error; - - if (gsm_system_is_login_session (manager->priv->system)) - return; - - /* We only allow session saving when session is running or when - * logging out */ - if (manager->priv->phase != GSM_MANAGER_PHASE_RUNNING && - manager->priv->phase != GSM_MANAGER_PHASE_END_SESSION) { - return; - } - - if (!auto_save_is_enabled (manager)) { - return; - } - - error = NULL; -- gsm_session_save (manager->priv->clients, &error); -+ gsm_session_save (manager->priv->clients, manager->priv->session_name, &error); - - if (error) { - g_warning ("Error saving session: %s", error->message); - g_error_free (error); - } - } - - static void - _handle_client_end_session_response (GsmManager *manager, - GsmClient *client, - gboolean is_ok, - gboolean do_last, - gboolean cancel, - const char *reason) - { - /* just ignore if we are not yet running */ - if (manager->priv->phase < GSM_MANAGER_PHASE_RUNNING) { - return; - } - - g_debug ("GsmManager: Response from end session request: is-ok=%d do-last=%d cancel=%d reason=%s", is_ok, do_last, cancel, reason ? reason :""); - - if (manager->priv->phase == GSM_MANAGER_PHASE_RUNNING) { - /* Ignore responses when no requests were sent */ - if (manager->priv->query_clients == NULL) { - return; - } - - manager->priv->query_clients = g_slist_remove (manager->priv->query_clients, client); - -diff --git a/gnome-session/gsm-manager.h b/gnome-session/gsm-manager.h -index c365596..d10879b 100644 ---- a/gnome-session/gsm-manager.h -+++ b/gnome-session/gsm-manager.h -@@ -103,60 +103,61 @@ typedef enum - } GsmManagerError; - - #define GSM_MANAGER_ERROR gsm_manager_error_quark () - - GType gsm_manager_error_get_type (void); - #define GSM_MANAGER_TYPE_ERROR (gsm_manager_error_get_type ()) - - GQuark gsm_manager_error_quark (void); - GType gsm_manager_get_type (void); - - GsmManager * gsm_manager_new (GsmStore *client_store, - gboolean failsafe); - GsmManager * gsm_manager_get (void); - - gboolean gsm_manager_get_failsafe (GsmManager *manager); - - gboolean gsm_manager_add_autostart_app (GsmManager *manager, - const char *path, - const char *provides); - gboolean gsm_manager_add_required_app (GsmManager *manager, - const char *path, - const char *provides); - gboolean gsm_manager_add_autostart_apps_from_dir (GsmManager *manager, - const char *path); - gboolean gsm_manager_add_legacy_session_apps (GsmManager *manager, - const char *path); - - void gsm_manager_start (GsmManager *manager); - - const char * _gsm_manager_get_default_session (GsmManager *manager); -+char * _gsm_manager_get_saved_session (GsmManager *manager); - - void _gsm_manager_set_active_session (GsmManager *manager, - const char *session_name, - gboolean is_fallback); - - /* exported methods */ - - gboolean gsm_manager_register_client (GsmManager *manager, - const char *app_id, - const char *client_startup_id, - DBusGMethodInvocation *context); - gboolean gsm_manager_unregister_client (GsmManager *manager, - const char *session_client_id, - DBusGMethodInvocation *context); - - gboolean gsm_manager_inhibit (GsmManager *manager, - const char *app_id, - guint toplevel_xid, - const char *reason, - guint flags, - DBusGMethodInvocation *context); - gboolean gsm_manager_uninhibit (GsmManager *manager, - guint inhibit_cookie, - DBusGMethodInvocation *context); - gboolean gsm_manager_is_inhibited (GsmManager *manager, - guint flags, - gboolean *is_inhibited, - GError *error); - - gboolean gsm_manager_shutdown (GsmManager *manager, -diff --git a/gnome-session/gsm-session-save.c b/gnome-session/gsm-session-save.c -index ea23be5..06eeeb1 100644 ---- a/gnome-session/gsm-session-save.c -+++ b/gnome-session/gsm-session-save.c -@@ -1,73 +1,105 @@ - /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- - * gsm-session-save.c - * 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, see . - */ - - #include - -+#include -+ - #include - #include - #include - - #include "gsm-util.h" - #include "gsm-autostart-app.h" - #include "gsm-client.h" - - #include "gsm-session-save.h" - - #define GSM_MANAGER_SCHEMA "org.gnome.SessionManager" - #define KEY_AUTOSAVE_ONE_SHOT "auto-save-session-one-shot" - - - static gboolean gsm_session_clear_saved_session (const char *directory, - GHashTable *discard_hash); - - typedef struct { - char *dir; - GHashTable *discard_hash; - GError **error; - } SessionSaveData; - -+static void -+clear_session_type (const char *save_dir) -+{ -+ char *file; -+ -+ file = g_build_filename (save_dir, "type", NULL); -+ -+ g_unlink (file); -+ -+ g_free (file); -+} -+ -+static void -+set_session_type (const char *save_dir, -+ const char *type) -+{ -+ char *file; -+ GError *error; -+ -+ file = g_build_filename (save_dir, "type", NULL); -+ -+ error = NULL; -+ g_file_set_contents (file, type, strlen (type), &error); -+ if (error != NULL) -+ g_warning ("couldn't save session type to %s: %s", -+ type, error->message); -+ -+ g_free (file); -+} -+ - static gboolean - save_one_client (char *id, - GObject *object, - SessionSaveData *data) - { - GsmClient *client; - GKeyFile *keyfile; - const char *app_id; - char *path = NULL; - char *filename = NULL; - char *contents = NULL; - gsize length = 0; - char *discard_exec; - GError *local_error; - - client = GSM_CLIENT (object); - - local_error = NULL; - - keyfile = gsm_client_save (client, &local_error); - - if (keyfile == NULL || local_error) { - goto out; - } - - contents = g_key_file_to_data (keyfile, &length, &local_error); - - if (local_error) { - goto out; - } -@@ -107,112 +139,114 @@ save_one_client (char *id, - GSM_AUTOSTART_APP_DISCARD_KEY, - NULL); - if (discard_exec) { - g_hash_table_insert (data->discard_hash, - discard_exec, discard_exec); - } - - g_debug ("GsmSessionSave: saved client %s to %s", id, filename); - - out: - if (keyfile != NULL) { - g_key_file_free (keyfile); - } - - g_free (contents); - g_free (filename); - g_free (path); - - /* in case of any error, stop saving session */ - if (local_error) { - g_propagate_error (data->error, local_error); - g_error_free (local_error); - - return TRUE; - } - - return FALSE; - } - - void --gsm_session_save (GsmStore *client_store, -- GError **error) -+gsm_session_save (GsmStore *client_store, -+ const char *type, -+ GError **error) - { - GSettings *settings; - const char *save_dir; - char *tmp_dir; - SessionSaveData data; - - g_debug ("GsmSessionSave: Saving session"); - - /* Clear one shot key autosave in the event its set (so that it's actually - * one shot only) - */ - settings = g_settings_new (GSM_MANAGER_SCHEMA); - g_settings_set_boolean (settings, KEY_AUTOSAVE_ONE_SHOT, FALSE); - g_object_unref (settings); - - save_dir = gsm_util_get_saved_session_dir (); - if (save_dir == NULL) { - g_warning ("GsmSessionSave: cannot create saved session directory"); - return; - } - - tmp_dir = gsm_util_get_empty_tmp_session_dir (); - if (tmp_dir == NULL) { - g_warning ("GsmSessionSave: cannot create new saved session directory"); - return; - } - - /* save the session in a temp directory, and remember the discard - * commands */ - data.dir = tmp_dir; - data.discard_hash = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, NULL); - data.error = error; - - gsm_store_foreach (client_store, - (GsmStoreFunc) save_one_client, - &data); - - if (!*error) { - char *session_dir; - - if (g_file_test (save_dir, G_FILE_TEST_IS_SYMLINK)) - session_dir = g_file_read_link (save_dir, error); - else - session_dir = g_strdup (save_dir); - - if (session_dir != NULL) { -- - char *absolute_session_dir; - -+ set_session_type (tmp_dir, type); -+ - if (g_path_is_absolute (session_dir)) { - absolute_session_dir = g_strdup (session_dir); - } else { - char *parent_dir; - - parent_dir = g_path_get_dirname (save_dir); - absolute_session_dir = g_build_filename (parent_dir, session_dir, NULL); - g_free (parent_dir); - } - g_free (session_dir); - - /* remove the old saved session */ - gsm_session_clear_saved_session (absolute_session_dir, data.discard_hash); - - if (g_file_test (absolute_session_dir, G_FILE_TEST_IS_DIR)) - g_rmdir (absolute_session_dir); - g_rename (tmp_dir, absolute_session_dir); - - g_free (absolute_session_dir); - } - } else { - g_warning ("GsmSessionSave: error saving session: %s", (*error)->message); - /* FIXME: we should create a hash table filled with the discard - * commands that are in desktop files from save_dir. */ - gsm_session_clear_saved_session (tmp_dir, NULL); - g_rmdir (tmp_dir); - } - - g_hash_table_destroy (data.discard_hash); - g_free (tmp_dir); -@@ -292,31 +326,32 @@ gsm_session_clear_saved_session (const char *directory, - - while ((filename = g_dir_read_name (dir))) { - char *path = g_build_filename (directory, - filename, NULL); - - result = gsm_session_clear_one_client (path, discard_hash) - && result; - - g_free (path); - } - - g_dir_close (dir); - - return result; - } - - void - gsm_session_save_clear (void) - { - const char *save_dir; - - g_debug ("GsmSessionSave: Clearing saved session"); - - save_dir = gsm_util_get_saved_session_dir (); - if (save_dir == NULL) { - g_warning ("GsmSessionSave: cannot create saved session directory"); - return; - } - - gsm_session_clear_saved_session (save_dir, NULL); -+ clear_session_type (save_dir); - } -diff --git a/gnome-session/gsm-session-save.h b/gnome-session/gsm-session-save.h -index e623260..c91b561 100644 ---- a/gnome-session/gsm-session-save.h -+++ b/gnome-session/gsm-session-save.h -@@ -1,33 +1,34 @@ - /* gsm-session-save.h - * 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, see . - */ - - #ifndef __GSM_SESSION_SAVE_H__ - #define __GSM_SESSION_SAVE_H__ - - #include - - #include "gsm-store.h" - - G_BEGIN_DECLS - --void gsm_session_save (GsmStore *client_store, -- GError **error); -+void gsm_session_save (GsmStore *client_store, -+ const char *type, -+ GError **error); - void gsm_session_save_clear (void); - - G_END_DECLS - - #endif /* __GSM_SESSION_SAVE_H__ */ -diff --git a/gnome-session/main.c b/gnome-session/main.c -index fce5e86..52d2aaa 100644 ---- a/gnome-session/main.c -+++ b/gnome-session/main.c -@@ -270,60 +270,61 @@ require_dbus_session (int argc, - } - - static gboolean - check_gl (GError **error) - { - int status; - char *argv[] = { LIBEXECDIR "/gnome-session-check-accelerated", NULL }; - - if (getenv ("DISPLAY") == NULL) { - /* Not connected to X11, someone else will take care of checking GL */ - return TRUE; - } - - if (!g_spawn_sync (NULL, (char **) argv, NULL, 0, NULL, NULL, NULL, NULL, - &status, error)) { - return FALSE; - } - - return g_spawn_check_exit_status (status, error); - } - - int - main (int argc, char **argv) - { - GError *error = NULL; - GsmManager *manager; - GsmStore *client_store; - static char **override_autostart_dirs = NULL; - static char *opt_session_name = NULL; - const char *session_name; -+ char *saved_session_name = NULL; - gboolean gl_failed = FALSE; - GOptionContext *options; - static GOptionEntry entries[] = { - { "autostart", 'a', 0, G_OPTION_ARG_STRING_ARRAY, &override_autostart_dirs, N_("Override standard autostart directories"), N_("AUTOSTART_DIR") }, - { "session", 0, 0, G_OPTION_ARG_STRING, &opt_session_name, N_("Session to use"), N_("SESSION_NAME") }, - { "debug", 0, 0, G_OPTION_ARG_NONE, &debug, N_("Enable debugging code"), NULL }, - { "failsafe", 'f', 0, G_OPTION_ARG_NONE, &failsafe, N_("Do not load user-specified applications"), NULL }, - { "version", 0, 0, G_OPTION_ARG_NONE, &show_version, N_("Version of this application"), NULL }, - /* Translators: the 'fail whale' is the black dialog we show when something goes seriously wrong */ - { "whale", 0, 0, G_OPTION_ARG_NONE, &please_fail, N_("Show the fail whale dialog for testing"), NULL }, - { NULL, 0, 0, 0, NULL, NULL, NULL } - }; - - /* Make sure that we have a session bus */ - if (!require_dbus_session (argc, argv, &error)) { - gsm_util_init_error (TRUE, "%s", error->message); - } - - /* Check GL, if it doesn't work out then force software fallback */ - if (!check_gl (&error)) { - gl_failed = TRUE; - - g_debug ("hardware acceleration check failed: %s", - error? error->message : ""); - g_clear_error (&error); - if (g_getenv ("LIBGL_ALWAYS_SOFTWARE") == NULL) { - g_setenv ("LIBGL_ALWAYS_SOFTWARE", "1", TRUE); - if (!check_gl (&error)) { - g_warning ("software acceleration check failed: %s", - error? error->message : ""); -@@ -402,53 +403,60 @@ main (int argc, char **argv) - gsm_util_setenv ("XDG_MENU_PREFIX", "gnome-"); - - client_store = gsm_store_new (); - - /* Talk to logind before acquiring a name, since it does synchronous - * calls at initialization time that invoke a main loop and if we - * already owned a name, then we would service too early during - * that main loop. - */ - g_object_unref (gsm_get_system ()); - - if (!acquire_name ()) { - gsm_fail_whale_dialog_we_failed (TRUE, TRUE, NULL); - gsm_main (); - exit (1); - } - - manager = gsm_manager_new (client_store, failsafe); - - g_signal_connect_object (bus_proxy, - "destroy", - G_CALLBACK (shutdown_cb), - manager, - G_CONNECT_SWAPPED); - - g_unix_signal_add (SIGTERM, term_or_int_signal_cb, manager); - g_unix_signal_add (SIGINT, term_or_int_signal_cb, manager); - g_unix_signal_add (SIGUSR1, sigusr1_cb, manager); - g_unix_signal_add (SIGUSR2, sigusr2_cb, manager); - -- if (IS_STRING_EMPTY (opt_session_name)) -- session_name = _gsm_manager_get_default_session (manager); -- else -+ if (IS_STRING_EMPTY (opt_session_name)) { -+ saved_session_name = _gsm_manager_get_saved_session (manager); -+ -+ if (IS_STRING_EMPTY (saved_session_name)) -+ session_name = _gsm_manager_get_default_session (manager); -+ else -+ session_name = saved_session_name; -+ } else { - session_name = opt_session_name; -+ } - - gsm_util_set_autostart_dirs (override_autostart_dirs); - - if (!gsm_session_fill (manager, session_name)) { - gsm_fail_whale_dialog_we_failed (FALSE, TRUE, NULL); - } - - gsm_manager_start (manager); - - gsm_main (); - - g_clear_object (&manager); - g_clear_object (&client_store); - g_clear_object (&bus_proxy); -+ g_free (saved_session_name); - - gdm_log_shutdown (); - - return 0; - } --- -2.3.7 - - -From c9c7daa61e77f86a4b3cd53ae55af3ad93e8b406 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Tue, 7 Jan 2014 21:16:23 -0500 -Subject: [PATCH 14/17] session-selector: restore saved session mode - -When using the custom session selector, we need to know -whether to use classic mode or not. - -This commit makes us use whatever mode was saved with the -session. ---- - tools/gnome-session-custom-session | 17 ++++++++++++++++- - 1 file changed, 16 insertions(+), 1 deletion(-) - -diff --git a/tools/gnome-session-custom-session b/tools/gnome-session-custom-session -index 07fdb0c..358aee0 100644 ---- a/tools/gnome-session-custom-session -+++ b/tools/gnome-session-custom-session -@@ -1,4 +1,19 @@ - #! /bin/sh - - gnome-session-selector --exec gnome-session -+ -+type_file="${XDG_CONFIG_HOME:-$HOME/.config}/gnome-session/saved-session/type" -+ -+session_type="" -+if [ -e "$type_file" ]; then -+ read session_type < "$type_file" -+fi -+ -+session_type_argument="" -+[ -n "$session_type" ] && session_type_argument="--session=$session_type" -+ -+if [ "$session_type" = "gnome-classic" ]; then -+ export GNOME_SHELL_SESSION_MODE="classic" -+fi -+ -+exec gnome-session "$session_type_argument" --- -2.3.7 - - -From ded037a059a781042d61e3bc7ef1ced0c9ee706f Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Fri, 20 Dec 2013 10:53:33 -0500 -Subject: [PATCH 15/17] session-selector: refresh from recent glade - -The ui file is rather old. This commit just opens it up in a recent -glade and resaves it, so we have a fresh starting point to make -changes. ---- - data/session-selector.ui | 80 ++++++++++++++++++++++++++++++++---------------- - 1 file changed, 54 insertions(+), 26 deletions(-) - -diff --git a/data/session-selector.ui b/data/session-selector.ui -index 1534a74..4d1e300 100644 ---- a/data/session-selector.ui -+++ b/data/session-selector.ui -@@ -1,195 +1,223 @@ -- -+ - -- -- -- -- -- -- -- -- -- -- session-store -- -+ - -+ False - Custom Session - center - 500 - 310 - False - - - True -+ False - 0.5 - out - - - True -+ False - 12 - - - True -- vertical -+ False - 6 -- - - - True -- other -- -+ False -+ other - -- -+ - True -+ False - vertical -- 0 - - - True -- 0.0 -- 0.5 -+ False -+ 0 - Please select a custom session to use - - -- True -- True -+ False -+ False - 0 - - - -+ -+ False -+ False -+ 0 -+ -+ -+ -+ -+ False -+ -+ -+ False -+ True -+ 1 -+ - - - - False - True - 0 - - - - - True -- vertical -+ False - 12 - - - True -+ False - 12 - - - True - True - never -- automatic - in - - - True - True -+ sort-model - False - 0 -- sort-model -+ -+ -+ - - - - -+ True -+ True - 0 - - - - - True -- vertical -+ False - 6 - start - - - _New Session - True - True - True - True - - - False - False - 0 - - - - - _Remove Session - True - True - True - True - - - False - False - 1 - - - - - Rena_me Session - True - True - True - True - - - False - False - 2 - - - - - False -+ True - 1 - - - - -+ True -+ True - 1 - - - - -+ True -+ True - 1 - - - - - True -+ False - 6 - end - - - _Continue - True - True - True - True - True - True - - - False - False - 0 - - - - - False -+ True - 2 - - - - - - - - - -+ -+ -+ -+ -+ -+ -+ -+ session-store -+ - --- -2.3.7 - - -From 34d666e847c142545c3de244df08705f6a19b933 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Tue, 7 Jan 2014 21:02:02 -0500 -Subject: [PATCH 16/17] session-selector: add toggle for classic/normal - selection - -Since we offer both classic mode and regular mode when -not using the session selector, we should also offer it -when using the session selector. ---- - data/session-selector.ui | 39 ++++++++++++++- - tools/gnome-session-selector.c | 105 +++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 142 insertions(+), 2 deletions(-) - -diff --git a/data/session-selector.ui b/data/session-selector.ui -index 4d1e300..beab73a 100644 ---- a/data/session-selector.ui -+++ b/data/session-selector.ui -@@ -153,71 +153,106 @@ - False - 2 - - - - - False - True - 1 - - - - - True - True - 1 - - - - - True - True - 1 - - - - - True - False - 6 -- end -+ -+ -+ True -+ False -+ 6 -+ -+ -+ True -+ False -+ Classic Experience -+ -+ -+ False -+ True -+ 0 -+ -+ -+ -+ -+ True -+ True -+ -+ -+ False -+ True -+ 1 -+ -+ -+ -+ -+ False -+ True -+ 0 -+ -+ - - - _Continue - True - True - True - True - True - True - - - False - False -- 0 -+ 1 -+ True - - - - - False - True - 2 - - - - - - - - - - - - - - - - - session-store - - -diff --git a/tools/gnome-session-selector.c b/tools/gnome-session-selector.c -index 8f37eca..dbe3bda 100644 ---- a/tools/gnome-session-selector.c -+++ b/tools/gnome-session-selector.c -@@ -16,60 +16,61 @@ - * along with this program; if not, see . - * - * Written by: Matthias Clasen - */ - - #include "config.h" - - #include - #include - #include - #include - #include - #include - - #include - #include - #include - - #include - #include - - #include - #include - - #define GSM_SERVICE_DBUS "org.gnome.SessionManager" - #define GSM_PATH_DBUS "/org/gnome/SessionManager" - #define GSM_INTERFACE_DBUS "org.gnome.SessionManager" - - #define GSM_MANAGER_SCHEMA "org.gnome.SessionManager" - #define KEY_AUTOSAVE_ONE_SHOT "auto-save-session-one-shot" -+#define DEFAULT_SESSION_NAME "gnome" - - static GtkBuilder *builder; - static GtkWidget *session_list; - static GtkListStore *store; - static GtkTreeModelSort *sort_model; - static char *info_text; - - static void select_session (const char *name); - static gboolean make_session_current (const char *name); - - static char * - get_session_path (const char *name) - { - return g_build_filename (g_get_user_config_dir (), "gnome-session", name, NULL); - } - - static char * - find_new_session_name (void) - { - char *name; - char *path; - int i; - - for (i = 1; i < 20; i++) { - name = g_strdup_printf (_("Session %d"), i); - path = get_session_path (name); - if (!g_file_test (path, G_FILE_TEST_EXISTS)) { - g_free (path); - return name; - } -@@ -125,104 +126,126 @@ is_valid_session_name (const char *name) - gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter); - do { - gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, 0, &n, -1); - if (strcmp (n, name) == 0) { - char *message; - message = g_strdup_printf (_("A session named ‘%s’ already exists"), name); - warning_text = g_strdup_printf ("%s\nNote: %s", info_text, message); - g_free (message); - g_free (n); - break; - } - g_free (n); - } while (gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter)); - - info_bar = (GtkWidget *) gtk_builder_get_object (builder, "info-bar"); - label = (GtkWidget*) gtk_builder_get_object (builder, "info-label"); - - if (warning_text != NULL) { - gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar), GTK_MESSAGE_WARNING); - gtk_label_set_markup (GTK_LABEL (label), warning_text); - g_free (warning_text); - return FALSE; - } - - gtk_info_bar_set_message_type (GTK_INFO_BAR (info_bar), GTK_MESSAGE_OTHER); - gtk_label_set_markup (GTK_LABEL (label), info_text); - - return TRUE; - } - -+static char * -+get_session_type_from_file (const char *name) -+{ -+ char *file; -+ char *type; -+ gboolean loaded; -+ -+ file = g_build_filename (g_get_user_config_dir (), "gnome-session", name, "type", NULL); -+ loaded = g_file_get_contents (file, &type, NULL, NULL); -+ g_free (file); -+ -+ if (!loaded) -+ return g_strdup (DEFAULT_SESSION_NAME); -+ -+ return type; -+} -+ - static void - populate_session_list (GtkWidget *session_list) - { - GtkTreeIter iter; - char *path; - const char *name; - GDir *dir; - GError *error; - char *saved_session; - char *default_session; - char *default_name; - char last_session[PATH_MAX] = ""; - - saved_session = get_session_path ("saved-session"); - - if (!g_file_test (saved_session, G_FILE_TEST_IS_SYMLINK)) { - default_name = find_new_session_name (); - default_session = get_session_path (default_name); - rename (saved_session, default_session); - if (symlink (default_name, saved_session) < 0) - g_warning ("Failed to convert saved-session to symlink"); - g_free (default_name); - g_free (default_session); - } - - path = g_build_filename (g_get_user_config_dir (), "gnome-session", NULL); - error = NULL; - dir = g_dir_open (path, 0, &error); - if (dir == NULL) { - g_warning ("Failed to open %s: %s", path, error->message); - g_error_free (error); - goto out; - } - - default_name = NULL; - if (readlink (saved_session, last_session, PATH_MAX - 1) > 0) { - default_name = g_path_get_basename (last_session); - } - - while ((name = g_dir_read_name (dir)) != NULL) { -+ char *session_type; -+ - if (strcmp (name, "saved-session") == 0) - continue; - -+ session_type = get_session_type_from_file (name); -+ - gtk_list_store_insert_with_values (store, &iter, 100, 0, name, -1); -+ g_free (session_type); - - if (g_strcmp0 (default_name, name) == 0) { - GtkTreeSelection *selection; - GtkTreeIter child_iter; - - gtk_tree_model_sort_convert_child_iter_to_iter (GTK_TREE_MODEL_SORT (sort_model), &child_iter, &iter); - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (session_list)); - gtk_tree_selection_select_iter (selection, &child_iter); - } - } - - g_free (default_name); - g_dir_close (dir); - - out: - g_free (saved_session); - g_free (path); - } - - static char * - get_last_session (void) - { - char *saved_session; - char last_session[PATH_MAX] = ""; - char *name = NULL; - - saved_session = get_session_path ("saved-session"); - - if (readlink (saved_session, last_session, PATH_MAX - 1) > 0) { - name = g_path_get_basename (last_session); -@@ -260,60 +283,136 @@ remove_session (const char *name) - GError *error; - - path1 = get_session_path ("saved-session"); - path2 = get_session_path (name); - - error = NULL; - n = g_file_read_link (path1, &error); - if (n == NULL) { - g_warning ("Failed to read link: %s", error->message); - g_error_free (error); - } - else if (strcmp (n, name) == 0) { - unlink (path1); - } - g_free (n); - - dir = g_dir_open (path2, 0, NULL); - while ((d = g_dir_read_name (dir)) != NULL) { - path = g_build_filename (path2, d, NULL); - unlink (path); - g_free (path); - } - g_dir_close (dir); - - remove (path2); - - g_free (path1); - g_free (path2); - } - -+static const char * -+get_session_type_from_switch (void) -+{ -+ GtkWidget *mode_switch; -+ gboolean is_classic_mode; -+ -+ mode_switch = (GtkWidget *)gtk_builder_get_object (builder, "classic-mode-switch"); -+ -+ is_classic_mode = gtk_switch_get_active (GTK_SWITCH (mode_switch)); -+ -+ if (is_classic_mode) { -+ return "gnome-classic"; -+ } else { -+ return "gnome"; -+ } -+} -+ -+static void -+set_mode_switch_from_session_type_file (const char *name) -+{ -+ GtkWidget *mode_switch; -+ gboolean is_classic_mode = FALSE; -+ char *type; -+ -+ mode_switch = (GtkWidget *)gtk_builder_get_object (builder, "classic-mode-switch"); -+ -+ type = get_session_type_from_file (name); -+ is_classic_mode = strcmp (type, "gnome-classic") == 0; -+ g_free (type); -+ -+ gtk_switch_set_active (GTK_SWITCH (mode_switch), is_classic_mode); -+} -+ -+static void -+save_session_type (const char *save_dir, -+ const char *type) -+{ -+ char *file; -+ GError *error; -+ -+ file = g_build_filename (save_dir, "type", NULL); -+ -+ error = NULL; -+ g_file_set_contents (file, type, strlen (type), &error); -+ if (error != NULL) -+ g_warning ("couldn't save session type to %s: %s", -+ type, error->message); -+ -+ g_free (file); -+} -+ -+static void -+save_session_type_from_switch (void) -+{ -+ char *name, *path; -+ const char *session_type; -+ -+ name = get_selected_session (); -+ -+ if (name == NULL) { -+ return; -+ } -+ -+ path = get_session_path (name); -+ g_free (name); -+ -+ session_type = get_session_type_from_switch (); -+ save_session_type (path, session_type); -+} -+ -+static void -+on_mode_switched (GtkSwitch *mode_switch) -+{ -+ save_session_type_from_switch (); -+} -+ - static gboolean - make_session_current (const char *name) - { - char *path1; - gboolean ret = TRUE; - - path1 = g_build_filename (g_get_user_config_dir (), "gnome-session", "saved-session", NULL); - - unlink (path1); - if (symlink (name, path1) < 0) { - g_warning ("Failed to make session '%s' current", name); - ret = FALSE; - } - - g_free (path1); - - return ret; - } - - static void - on_remove_session_clicked (GtkButton *button, - gpointer data) - { - GtkTreeSelection *selection; - GtkTreeModel *model; - GtkTreeIter iter; - char *name; - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (session_list)); - if (gtk_tree_selection_get_selected (selection, &model, &iter)) { -@@ -492,60 +591,62 @@ static void - create_session_and_begin_rename (void) - { - gchar *name; - - name = find_new_session_name (); - create_session (name); - select_session (name); - - begin_rename (); - } - - static void - on_new_session_clicked (GtkButton *button, - gpointer data) - { - create_session_and_begin_rename (); - } - - static void - on_selection_changed (GtkTreeSelection *selection, - gpointer data) - { - char *name; - - name = get_selected_session (); - - if (name == NULL) { - return; - } - -+ set_mode_switch_from_session_type_file (name); -+ - g_free (name); - } - - static void - update_remove_button (void) - { - GtkWidget *button; - - button = (GtkWidget *)gtk_builder_get_object (builder, "remove-session"); - if (gtk_tree_model_iter_n_children (GTK_TREE_MODEL (store), NULL) > 1) { - gtk_widget_set_sensitive (button, TRUE); - } else { - gtk_widget_set_sensitive (button, FALSE); - } - } - - static void - on_row_edited (GtkCellRendererText *cell, - const char *path_string, - const char *new_name, - gpointer data) - { - GtkTreePath *path; - GtkTreeIter sort_iter, items_iter; - char *old_name; - gboolean was_renamed; - - path = gtk_tree_path_new_from_string (path_string); - gtk_tree_model_get_iter (GTK_TREE_MODEL (sort_model), &sort_iter, path); - -@@ -751,75 +852,80 @@ main (int argc, char *argv[]) - gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (sort_model), - 0, GTK_SORT_ASCENDING); - g_signal_connect (store, "row-deleted", G_CALLBACK (on_row_deleted), NULL); - g_signal_connect (store, "row-inserted", G_CALLBACK (on_row_inserted), NULL); - session_list = (GtkWidget *) gtk_builder_get_object (builder, "session-list"); - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (session_list)); - gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); - - populate_session_list (session_list); - - cell = gtk_cell_renderer_text_new (); - g_signal_connect (cell, "edited", G_CALLBACK (on_row_edited), NULL); - - column = gtk_tree_view_column_new_with_attributes ("", cell, "text", 0, NULL); - gtk_tree_view_append_column (GTK_TREE_VIEW (session_list), GTK_TREE_VIEW_COLUMN (column)); - - g_signal_connect (session_list, "row-activated", G_CALLBACK (on_row_activated), NULL); - - g_signal_connect (selection, "changed", - G_CALLBACK (on_selection_changed), NULL); - - widget = (GtkWidget *) gtk_builder_get_object (builder, "new-session"); - g_signal_connect (widget, "clicked", G_CALLBACK (on_new_session_clicked), NULL); - widget = (GtkWidget *) gtk_builder_get_object (builder, "remove-session"); - g_signal_connect (widget, "clicked", G_CALLBACK (on_remove_session_clicked), NULL); - widget = (GtkWidget *) gtk_builder_get_object (builder, "rename-session"); - g_signal_connect (widget, "clicked", G_CALLBACK (on_rename_session_clicked), NULL); - widget = (GtkWidget *) gtk_builder_get_object (builder, "continue-button"); - g_signal_connect (widget, "clicked", G_CALLBACK (on_continue_clicked), NULL); -+ widget = (GtkWidget *) gtk_builder_get_object (builder, "classic-mode-switch"); -+ g_signal_connect (widget, "notify::active", G_CALLBACK (on_mode_switched), NULL); - - g_signal_connect (window, "map", G_CALLBACK (on_map), NULL); - gtk_widget_show (window); - - if (g_strcmp0 (action, "load") == 0) { - info_text = _("Please select a custom session to run"); - } else if (g_strcmp0 (action, "print") == 0) { - info_text = _("Please select a session to use"); - } else if (g_strcmp0 (action, "save") == 0) { - info_text = _("Please select a session to save to"); - } - - label = (GtkWidget*) gtk_builder_get_object (builder, "info-label"); - gtk_label_set_markup (GTK_LABEL (label), info_text); - - selected_session = get_selected_session (); - - if (selected_session == NULL) { - create_session_and_begin_rename (); - } else { -+ set_mode_switch_from_session_type_file (selected_session); - g_free (selected_session); - } - - gtk_main (); - - selected_session = get_selected_session (); - - if (g_strcmp0 (action, "load") == 0) { - make_session_current (selected_session); -+ save_session_type_from_switch (); - auto_save_next_session_if_needed (); - } else if (g_strcmp0 (action, "save") == 0) { - char *last_session; - - last_session = get_last_session (); - make_session_current (selected_session); - save_session (); -+ save_session_type_from_switch (); - if (last_session != NULL) - make_session_current (last_session); - } else if (g_strcmp0 (action, "print") == 0) { - g_print ("%s\n", selected_session); - } - g_free (selected_session); - - return 0; - } --- -2.3.7 - - -From c056d368938c75b1d6227e84f3daba40e8d39d71 Mon Sep 17 00:00:00 2001 -From: Ray Strode -Date: Wed, 8 Jan 2014 10:15:29 -0500 -Subject: [PATCH 17/17] session-selector: use classic mode by default - ---- - tools/gnome-session-selector.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/tools/gnome-session-selector.c b/tools/gnome-session-selector.c -index dbe3bda..3e0b32e 100644 ---- a/tools/gnome-session-selector.c -+++ b/tools/gnome-session-selector.c -@@ -16,61 +16,61 @@ - * along with this program; if not, see . - * - * Written by: Matthias Clasen - */ - - #include "config.h" - - #include - #include - #include - #include - #include - #include - - #include - #include - #include - - #include - #include - - #include - #include - - #define GSM_SERVICE_DBUS "org.gnome.SessionManager" - #define GSM_PATH_DBUS "/org/gnome/SessionManager" - #define GSM_INTERFACE_DBUS "org.gnome.SessionManager" - - #define GSM_MANAGER_SCHEMA "org.gnome.SessionManager" - #define KEY_AUTOSAVE_ONE_SHOT "auto-save-session-one-shot" --#define DEFAULT_SESSION_NAME "gnome" -+#define DEFAULT_SESSION_NAME "gnome-classic" - - static GtkBuilder *builder; - static GtkWidget *session_list; - static GtkListStore *store; - static GtkTreeModelSort *sort_model; - static char *info_text; - - static void select_session (const char *name); - static gboolean make_session_current (const char *name); - - static char * - get_session_path (const char *name) - { - return g_build_filename (g_get_user_config_dir (), "gnome-session", name, NULL); - } - - static char * - find_new_session_name (void) - { - char *name; - char *path; - int i; - - for (i = 1; i < 20; i++) { - name = g_strdup_printf (_("Session %d"), i); - path = get_session_path (name); - if (!g_file_test (path, G_FILE_TEST_EXISTS)) { - g_free (path); - return name; - } --- -2.3.7 - diff --git a/SOURCES/gnome-session-3.14.0-EL7.3_translations.patch b/SOURCES/gnome-session-3.14.0-EL7.3_translations.patch deleted file mode 100644 index cf67bb3..0000000 --- a/SOURCES/gnome-session-3.14.0-EL7.3_translations.patch +++ /dev/null @@ -1,5660 +0,0 @@ -diff -urN gnome-session-3.14.0/po/de.po gnome-session-3.14.0_localized/po/de.po ---- gnome-session-3.14.0/po/de.po 2014-06-25 23:36:33.000000000 +0530 -+++ gnome-session-3.14.0_localized/po/de.po 2016-03-14 19:41:08.892245236 +0530 -@@ -16,21 +16,22 @@ - # Tobias Endrigkeit , 2012. - # Andre Jonas , 2013. - # Christian Kirbach , 2009, 2010, 2011, 2012, 2013. --# -+# lstemmle , 2016. #zanata -+# pnemade , 2016. #zanata - msgid "" - msgstr "" - "Project-Id-Version: gnome-session master\n" --"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" --"session&keywords=I18N+L10N&component=general\n" --"POT-Creation-Date: 2013-09-09 23:10+0000\n" --"PO-Revision-Date: 2013-09-13 19:26+0100\n" --"Last-Translator: Benjamin Steinwender \n" --"Language-Team: Deutsch \n" -+"Report-Msgid-Bugs-To: \n" -+"POT-Creation-Date: 2016-02-26 10:16+0530\n" - "MIME-Version: 1.0\n" - "Content-Type: text/plain; charset=UTF-8\n" - "Content-Transfer-Encoding: 8bit\n" -+"PO-Revision-Date: 2016-03-07 04:39+0000\n" -+"Last-Translator: lstemmle \n" -+"Language-Team: Deutsch \n" -+"Language: de\n" - "Plural-Forms: nplurals=2; plural=(n != 1);\n" --"X-Generator: Poedit 1.5.7\n" -+"X-Generator: Zanata 3.8.2\n" - - #: ../capplet/gsm-app-dialog.c:120 - msgid "Select Command" -@@ -52,31 +53,49 @@ - msgid "The startup command is not valid" - msgstr "Der Startbefehl ist ungültig" - --#: ../capplet/gsm-properties-dialog.c:519 -+#: ../capplet/gsm-properties-dialog.c:493 -+msgid "Your session has been saved." -+msgstr "Ihre Sitzung wurde gespeichert." -+ -+#: ../capplet/gsm-properties-dialog.c:495 -+#: ../capplet/gsm-properties-dialog.c:521 -+msgid "Failed to save session" -+msgstr "Speichern der Sitzung fehlgeschlagen" -+ -+#: ../capplet/gsm-properties-dialog.c:509 -+msgid "Could not connect to the session bus" -+msgstr "Verbindung zum Sitzungs-Bus konnte nicht hergestellt werden" -+ -+#: ../capplet/gsm-properties-dialog.c:515 ../tools/gnome-session-quit.c:89 -+#: ../tools/gnome-session-quit.c:99 -+msgid "Could not connect to the session manager" -+msgstr "Sitzungsverwaltung konnte nicht kontaktiert werden" -+ -+#: ../capplet/gsm-properties-dialog.c:606 - msgid "Enabled" - msgstr "Aktiviert" - --#: ../capplet/gsm-properties-dialog.c:531 -+#: ../capplet/gsm-properties-dialog.c:618 - msgid "Icon" - msgstr "Symbol" - --#: ../capplet/gsm-properties-dialog.c:543 -+#: ../capplet/gsm-properties-dialog.c:630 - msgid "Program" - msgstr "Programm" - --#: ../capplet/gsm-properties-dialog.c:747 -+#: ../capplet/gsm-properties-dialog.c:834 - msgid "Startup Applications Preferences" - msgstr "Startprogrammeinstellungen" - --#: ../capplet/gsp-app.c:276 -+#: ../capplet/gsp-app.c:277 - msgid "No name" - msgstr "Namenlos" - --#: ../capplet/gsp-app.c:282 -+#: ../capplet/gsp-app.c:283 - msgid "No description" - msgstr "Keine Beschreibung" - --#: ../capplet/main.c:35 ../gnome-session/main.c:309 -+#: ../capplet/main.c:35 ../gnome-session/main.c:308 - msgid "Version of this application" - msgstr "Version dieser Anwendung" - -@@ -106,11 +125,11 @@ - msgid "GNOME dummy" - msgstr "GNOME Platzhalter" - --#: ../data/gnome-session-properties.desktop.in.in.h:1 -+#: ../data/session-properties.desktop.in.in.h:1 - msgid "Startup Applications" - msgstr "Startprogramme" - --#: ../data/gnome-session-properties.desktop.in.in.h:2 -+#: ../data/session-properties.desktop.in.in.h:2 - msgid "Choose what applications to start when you log in" - msgstr "" - "Wählen Sie, welche Anwendungen gestartet werden, wenn Sie sich anmelden" -@@ -122,7 +141,6 @@ - msgstr "GNOME unter Wayland" - - #: ../data/gnome-wayland.desktop.in.h:2 --#| msgid "This session logs you into GNOME" - msgid "This session logs you into GNOME, using Wayland" - msgstr "Diese Sitzung meldet Sie bei GNOME unter Wayland an" - -@@ -130,10 +148,10 @@ - msgid "Custom Session" - msgstr "Benutzerdefinierte Sitzung" - --#: ../data/session-selector.ui.h:2 ../tools/gnome-session-selector.c:103 --msgid "Please select a custom session to run" -+#: ../data/session-selector.ui.h:2 -+msgid "Please select a custom session to use" - msgstr "" --"Bitte wählen Sie eine benutzerdefinierte Sitzung, die ausgeführt werden soll" -+"Bitte wählen Sie eine benutzerdefinierte Sitzung, die verwendet werden soll" - - #: ../data/session-selector.ui.h:3 - msgid "_New Session" -@@ -148,6 +166,10 @@ - msgstr "Sitzung _umbenennen" - - #: ../data/session-selector.ui.h:6 -+msgid "Classic Experience" -+msgstr "Classic-Erfahrung" -+ -+#: ../data/session-selector.ui.h:7 - msgid "_Continue" - msgstr "_Fortfahren" - -@@ -187,79 +209,11 @@ - msgid "_Name:" - msgstr "_Name:" - --#: ../egg/eggdesktopfile.c:165 --#, c-format --msgid "File is not a valid .desktop file" --msgstr "Diese Datei ist keine gültige .desktop-Datei" -- --#. translators: 'Version' is from a desktop file, and --#. * should not be translated. '%s' would probably be a --#. * version number. --#: ../egg/eggdesktopfile.c:191 --#, c-format --msgid "Unrecognized desktop file Version '%s'" --msgstr "Version der Desktop-Datei »%s« wurde nicht erkannt" -- --#: ../egg/eggdesktopfile.c:974 --#, c-format --msgid "Starting %s" --msgstr "Startet %s" -- --#: ../egg/eggdesktopfile.c:1116 --#, c-format --msgid "Application does not accept documents on command line" --msgstr "Anwendung akzeptiert keine Befehlszeilenargumente" -- --#: ../egg/eggdesktopfile.c:1184 --#, c-format --msgid "Unrecognized launch option: %d" --msgstr "Nicht erkannte Startoption: %d" -- --#. translators: The 'Type=Link' string is found in a --#. * desktop file, and should not be translated. --#: ../egg/eggdesktopfile.c:1391 --#, c-format --msgid "Can't pass document URIs to a 'Type=Link' desktop entry" --msgstr "URI konnte auf Desktop-Datei 'Type=Link' nicht angewendet werden" -- --#: ../egg/eggdesktopfile.c:1412 --#, c-format --msgid "Not a launchable item" --msgstr "Kein ausführbares Objekt" -- --#: ../egg/eggsmclient.c:226 --msgid "Disable connection to session manager" --msgstr "Verbindung zur Sitzungsverwaltung deaktivieren" -- --#: ../egg/eggsmclient.c:229 --msgid "Specify file containing saved configuration" --msgstr "Datei zum Speichern der Konfiguration auswählen" -- --#: ../egg/eggsmclient.c:229 --msgid "FILE" --msgstr "DATEI" -- --#: ../egg/eggsmclient.c:232 --msgid "Specify session management ID" --msgstr "Geben Sie die zu ladende Sitzungskennung an" -- --#: ../egg/eggsmclient.c:232 --msgid "ID" --msgstr "Kennung" -- --#: ../egg/eggsmclient.c:253 --msgid "Session management options:" --msgstr "Sitzungsoptionen:" -- --#: ../egg/eggsmclient.c:254 --msgid "Show session management options" --msgstr "Sitzungsoptionen anzeigen" -- --#: ../gnome-session/gsm-fail-whale-dialog.c:295 -+#: ../gnome-session/gsm-fail-whale-dialog.c:321 - msgid "Oh no! Something has gone wrong." - msgstr "Leider ist ein Problem aufgetreten." - --#: ../gnome-session/gsm-fail-whale-dialog.c:302 -+#: ../gnome-session/gsm-fail-whale-dialog.c:328 - msgid "" - "A problem has occurred and the system can't recover. Please contact a system " - "administrator" -@@ -267,7 +221,7 @@ - "Ein Problem ist aufgetreten, welches vom System nicht behoben werden kann. " - "Bitte kontaktieren Sie den Systemverwalter." - --#: ../gnome-session/gsm-fail-whale-dialog.c:304 -+#: ../gnome-session/gsm-fail-whale-dialog.c:330 - msgid "" - "A problem has occurred and the system can't recover. All extensions have " - "been disabled as a precaution." -@@ -275,7 +229,7 @@ - "Ein Problem ist aufgetreten, welches vom System nicht behoben werden kann. " - "Als Vorsichtsmaßnahme sind alle Erweiterungen deaktiviert worden." - --#: ../gnome-session/gsm-fail-whale-dialog.c:306 -+#: ../gnome-session/gsm-fail-whale-dialog.c:332 - msgid "" - "A problem has occurred and the system can't recover.\n" - "Please log out and try again." -@@ -283,43 +237,43 @@ - "Ein Problem ist aufgetreten, welches vom System nicht behoben werden kann.\n" - "Bitte melden Sie sich ab und versuchen Sie es erneut." - --#: ../gnome-session/gsm-fail-whale-dialog.c:321 -+#: ../gnome-session/gsm-fail-whale-dialog.c:347 - msgid "_Log Out" - msgstr "Benutzer ab_melden" - --#: ../gnome-session/gsm-fail-whale-dialog.c:343 ../gnome-session/main.c:307 -+#: ../gnome-session/gsm-fail-whale-dialog.c:369 ../gnome-session/main.c:306 - msgid "Enable debugging code" - msgstr "Debugging-Code aktivieren" - --#: ../gnome-session/gsm-fail-whale-dialog.c:344 -+#: ../gnome-session/gsm-fail-whale-dialog.c:370 - msgid "Allow logout" - msgstr "Abmelden erlauben" - --#: ../gnome-session/gsm-fail-whale-dialog.c:345 -+#: ../gnome-session/gsm-fail-whale-dialog.c:371 - msgid "Show extension warning" - msgstr "Warnung der Erweiterung anzeigen" - --#: ../gnome-session/gsm-manager.c:1271 ../gnome-session/gsm-manager.c:2043 -+#: ../gnome-session/gsm-manager.c:1370 ../gnome-session/gsm-manager.c:2192 - msgid "Not responding" - msgstr "Keine Antwort" - --#: ../gnome-session/gsm-util.c:411 -+#: ../gnome-session/gsm-util.c:382 - msgid "_Log out" - msgstr "_Abmelden" - - #. It'd be really surprising to reach this code: if we're here, - #. * then the XSMP client already has set several XSMP - #. * properties. But it could still be that SmProgram is not set. --#. --#: ../gnome-session/gsm-xsmp-client.c:559 -+#. -+#: ../gnome-session/gsm-xsmp-client.c:582 - msgid "Remembered Application" - msgstr "Gemerkte Anwendung" - --#: ../gnome-session/gsm-xsmp-client.c:1209 -+#: ../gnome-session/gsm-xsmp-client.c:1244 - msgid "This program is blocking logout." - msgstr "Dieses Programm blockiert die Abmeldung." - --#: ../gnome-session/gsm-xsmp-server.c:341 -+#: ../gnome-session/gsm-xsmp-server.c:340 - msgid "" - "Refusing new client connection because the session is currently being shut " - "down\n" -@@ -327,42 +281,42 @@ - "Neue Client-Verbindung wurde abgelehnt, weil die aktuelle Sitzung " - "gegenwärtig beendet wird\n" - --#: ../gnome-session/gsm-xsmp-server.c:610 -+#: ../gnome-session/gsm-xsmp-server.c:609 - #, c-format - msgid "Could not create ICE listening socket: %s" - msgstr "ICE-Listening-Socket konnte nicht erzeugt werden: %s" - --#: ../gnome-session/main.c:305 -+#: ../gnome-session/main.c:304 - msgid "Override standard autostart directories" - msgstr "Vorgegebene Autostart-Ordner außer Kraft setzen" - --#: ../gnome-session/main.c:305 -+#: ../gnome-session/main.c:304 - msgid "AUTOSTART_DIR" - msgstr "AUTOSTARTORDNER" - --#: ../gnome-session/main.c:306 -+#: ../gnome-session/main.c:305 - msgid "Session to use" - msgstr "Zu verwendende Sitzung" - --#: ../gnome-session/main.c:306 -+#: ../gnome-session/main.c:305 - msgid "SESSION_NAME" - msgstr "SITZUNGSNAME" - --#: ../gnome-session/main.c:308 -+#: ../gnome-session/main.c:307 - msgid "Do not load user-specified applications" - msgstr "Keine benutzerspezifischen Anwendungen laden" - - # Der Kommentar im Quelltext lautet: »/* Translators: the 'fail whale' is the black dialog we show when something goes seriously wrong */« - #. Translators: the 'fail whale' is the black dialog we show when something goes seriously wrong --#: ../gnome-session/main.c:311 -+#: ../gnome-session/main.c:310 - msgid "Show the fail whale dialog for testing" - msgstr "Den Dialog zum Fehlschlag für Prüfungszwecke anzeigen" - --#: ../gnome-session/main.c:344 -+#: ../gnome-session/main.c:343 - msgid " - the GNOME session manager" - msgstr " - Die GNOME-Sitzung verwalten" - --#: ../tools/gnome-session-inhibit.c:110 -+#: ../tools/gnome-session-inhibit.c:108 - #, c-format - msgid "" - "%s [OPTION...] COMMAND\n" -@@ -396,285 +350,81 @@ - "\n" - "Wenn keine --inhibit-Option angegeben wird, wird »idle« angenommen.\n" - --#: ../tools/gnome-session-inhibit.c:148 -+#: ../tools/gnome-session-inhibit.c:146 - #, c-format - msgid "Failed to execute %s\n" - msgstr "Fehler beim Ausführen von %s\n" - --#: ../tools/gnome-session-inhibit.c:208 ../tools/gnome-session-inhibit.c:218 --#: ../tools/gnome-session-inhibit.c:228 -+#: ../tools/gnome-session-inhibit.c:206 ../tools/gnome-session-inhibit.c:216 -+#: ../tools/gnome-session-inhibit.c:226 - #, c-format - msgid "%s requires an argument\n" - msgstr "%s benötigt ein Argument\n" - --#: ../tools/gnome-session-selector.c:62 -+#: ../tools/gnome-session-selector.c:71 - #, c-format - msgid "Session %d" - msgstr "Sitzung %d" - --#: ../tools/gnome-session-selector.c:108 -+#: ../tools/gnome-session-selector.c:115 - msgid "" - "Session names are not allowed to start with ‘.’ or contain ‘/’ characters" - msgstr "Sitzungsnamen dürfen nicht mit einem ».« anfangen oder »/« enthalten" - --#: ../tools/gnome-session-selector.c:112 -+#: ../tools/gnome-session-selector.c:119 - msgid "Session names are not allowed to start with ‘.’" - msgstr "Sitzungsnamen dürfen nicht mit einem ».« anfangen" - --#: ../tools/gnome-session-selector.c:116 -+#: ../tools/gnome-session-selector.c:123 - msgid "Session names are not allowed to contain ‘/’ characters" - msgstr "Sitzungsnamen dürfen keine »/«-Zeichen enthalten" - --#: ../tools/gnome-session-selector.c:124 -+#: ../tools/gnome-session-selector.c:131 - #, c-format - msgid "A session named ‘%s’ already exists" - msgstr "Eine Sitzung mit Namen »%s« existiert bereits" - --#: ../tools/gnome-session-quit.c:53 -+#: ../tools/gnome-session-selector.c:794 -+msgid "What to do with session selection (save|load|print)" -+msgstr "Weiteres Verfahren mit der Sitzungsauswahl (speichern|laden|drucken)" -+ -+#: ../tools/gnome-session-selector.c:795 -+msgid "[session-name]" -+msgstr "[Sitzungs-Name]" -+ -+#: ../tools/gnome-session-selector.c:889 -+msgid "Please select a custom session to run" -+msgstr "" -+"Bitte wählen Sie eine benutzerdefinierte Sitzung, die ausgeführt werden soll" -+ -+#: ../tools/gnome-session-selector.c:891 -+msgid "Please select a session to use" -+msgstr "Bitte wählen Sie eine Sitzung, die verwendet werden soll" -+ -+#: ../tools/gnome-session-selector.c:893 -+msgid "Please select a session to save to" -+msgstr "Bitte wählen Sie eine Sitzung zum Speichern aus" -+ -+#: ../tools/gnome-session-quit.c:51 - msgid "Log out" - msgstr "Abmelden" - --#: ../tools/gnome-session-quit.c:54 -+#: ../tools/gnome-session-quit.c:52 - msgid "Power off" - msgstr "Ausschalten" - --#: ../tools/gnome-session-quit.c:55 -+#: ../tools/gnome-session-quit.c:53 - msgid "Reboot" - msgstr "Neustart" - --#: ../tools/gnome-session-quit.c:56 -+#: ../tools/gnome-session-quit.c:54 - msgid "Ignoring any existing inhibitors" - msgstr "Bestehende Unterdrückungen ignorieren" - --#: ../tools/gnome-session-quit.c:57 -+#: ../tools/gnome-session-quit.c:55 - msgid "Don't prompt for user confirmation" - msgstr "Keine Bestätigung abfragen" - --#: ../tools/gnome-session-quit.c:91 ../tools/gnome-session-quit.c:101 --msgid "Could not connect to the session manager" --msgstr "Sitzungsverwaltung konnte nicht kontaktiert werden" -- --#: ../tools/gnome-session-quit.c:203 -+#: ../tools/gnome-session-quit.c:201 - msgid "Program called with conflicting options" - msgstr "Programm wurde mit Optionen aufgerufen, die zu einem Konflikt führen" -- --#~ msgid "Some programs are still running:" --#~ msgstr "Einige Anwendungen laufen noch:" -- --#~ msgid "Unknown" --#~ msgstr "Unbekannt" -- --#~ msgid "A program is still running:" --#~ msgstr "Eine Anwendung läuft noch:" -- --#~ msgid "" --#~ "Waiting for the program to finish. Interrupting the program may cause you " --#~ "to lose work." --#~ msgstr "" --#~ "Warten auf das Beenden der Anwendung. Durch Abbruch der Anwendung könnten " --#~ "Änderungen verloren gehen." -- --#~ msgid "" --#~ "Waiting for programs to finish. Interrupting these programs may cause you " --#~ "to lose work." --#~ msgstr "" --#~ "Warten auf das Beenden der Anwendungen. Durch Abbruch der Anwendungen " --#~ "könnten Änderungen verloren gehen." -- --#~ msgid "Switch User Anyway" --#~ msgstr "Trotzdem Benutzer wechseln" -- --#~ msgid "Log Out Anyway" --#~ msgstr "Trotzdem abmelden" -- --#~ msgid "Suspend Anyway" --#~ msgstr "Trotzdem in Bereitschaftsmodus gehen" -- --#~ msgid "Hibernate Anyway" --#~ msgstr "Trotzdem in Ruhezustand gehen" -- --#~ msgid "Shut Down Anyway" --#~ msgstr "Trotzdem ausschalten" -- --#~ msgid "Restart Anyway" --#~ msgstr "Trotzdem neu starten" -- --#~ msgid "Lock Screen" --#~ msgstr "Bildschirm sperren" -- --#~ msgid "Cancel" --#~ msgstr "Abbrechen" -- --#~ msgid "You will be automatically logged out in %d second." --#~ msgid_plural "You will be automatically logged out in %d seconds." --#~ msgstr[0] "Sie werden in %d Sekunde automatisch abgemeldet." --#~ msgstr[1] "Sie werden in %d Sekunden automatisch abgemeldet." -- --#~ msgid "This system will be automatically shut down in %d second." --#~ msgid_plural "This system will be automatically shut down in %d seconds." --#~ msgstr[0] "Der Rechner wird in %d Sekunde automatisch ausgeschaltet." --#~ msgstr[1] "Der Rechner wird in %d Sekunden automatisch ausgeschaltet." -- --#~ msgid "This system will be automatically restarted in %d second." --#~ msgid_plural "This system will be automatically restarted in %d seconds." --#~ msgstr[0] "Der Rechner wird in %d Sekunde automatisch neu gestartet." --#~ msgstr[1] "Der Rechner wird in %d Sekunden automatisch neu gestartet." -- --#~ msgid "You are currently logged in as \"%s\"." --#~ msgstr "Sie sind zurzeit als »%s« angemeldet." -- --#~ msgid "Log out of this system now?" --#~ msgstr "Jetzt vom System abmelden?" -- --#~ msgid "_Switch User" --#~ msgstr "Benutzer _wechseln" -- --#~ msgid "Shut down this system now?" --#~ msgstr "Möchten Sie den Rechner jetzt ausschalten?" -- --#~ msgid "S_uspend" --#~ msgstr "_Bereitschaft" -- --#~ msgid "_Hibernate" --#~ msgstr "_Ruhezustand" -- --#~ msgid "_Restart" --#~ msgstr "_Neu starten" -- --#~ msgid "_Shut Down" --#~ msgstr "Rechner a_usschalten" -- --#~ msgid "Restart this system now?" --#~ msgstr "Möchten Sie den Rechner jetzt neustarten?" -- --#~ msgid "%d hour" --#~ msgid_plural "%d hours" --#~ msgstr[0] "%d Stunde" --#~ msgstr[1] "%d Stunden" -- --#~ msgid "%d minute" --#~ msgid_plural "%d minutes" --#~ msgstr[0] "%d Minute" --#~ msgstr[1] "%d Minuten" -- --#~ msgid "%d second" --#~ msgid_plural "%d seconds" --#~ msgstr[0] "%d Sekunde" --#~ msgstr[1] "%d Sekunden" -- --#~ msgid "0 seconds" --#~ msgstr "0 Sekunden" -- --#~ msgid "Automatic logout in %s" --#~ msgstr "Automatisches Abmelden in %s" -- --#~ msgid "" --#~ "This session is configured to automatically log out after a period of " --#~ "inactivity." --#~ msgstr "" --#~ "Diese Sitzung wurde so konfiguriert, dass sie automatisch abgemeldet " --#~ "wird, wenn sie eine Zeit lang nicht benutzt wird." -- --#~ msgid "Icon '%s' not found" --#~ msgstr "Symbol »%s« konnte nicht gefunden werden" -- --#~ msgid "GNOME 3 Failed to Load" --#~ msgstr "Das Laden von GNOME 3 schlug fehl" -- --#~ msgid "" --#~ "Unfortunately GNOME 3 failed to start properly and started in the " --#~ "fallback mode.\n" --#~ "\n" --#~ "This most likely means your system (graphics hardware or driver) is not " --#~ "capable of delivering the full GNOME 3 experience." --#~ msgstr "" --#~ "Leider schlug das richtige Laden von GNOME 3 fehl und es wurde im " --#~ "Ausweichmodus gestartet.\n" --#~ "\n" --#~ "Das bedeutet sehr wahrscheinlich, dass Ihre Grafik-Hardware nicht für die " --#~ "vollständige GNOME-3-Umgebung geeignet ist." -- --#~ msgid "Learn more about GNOME 3" --#~ msgstr "Erfahren Sie mehr über GNOME 3" -- --#~ msgid "" --#~ "Unable to start login session (and unable to connect to the X server)" --#~ msgstr "" --#~ "Anmeldesitzung konnte nicht gestartet werden (keine Verbindung zum X-" --#~ "Server)" -- --#~ msgid "Exited with code %d" --#~ msgstr "Abbruch mit Code %d" -- --#~ msgid "Killed by signal %d" --#~ msgstr "Abgewürgt durch Signal %d" -- --#~ msgid "Stopped by signal %d" --#~ msgstr "Gestoppt durch Signal %d" -- --#~ msgid "Some programs are still running:" --#~ msgstr "Einige Anwendungen laufen noch:" -- --#~ msgid "" --#~ "A problem has occurred and the system can't recover. Some of the " --#~ "extensions below may have caused this.\n" --#~ "Please try disabling some of these, and then log out and try again." --#~ msgstr "" --#~ "Ein Problem ist aufgetreten, welches vom System nicht behoben werden " --#~ "kann. Einige der unten aufgelisteten Erweiterungen könnten dies " --#~ "verursacht haben.\n" --#~ "Bitte versuchen Sie einige davon zu deaktivieren. Melden Sie sich danach " --#~ "ab und erneut an." -- --#~ msgid "" --#~ "There is a problem with the configuration server.\n" --#~ "(%s exited with status %d)" --#~ msgstr "" --#~ "Es gibt ein Problem mit dem Konfigurationsserver.\n" --#~ "(%s beendet mit Status %d)" -- --#~ msgid "File Manager" --#~ msgstr "Dateimanager" -- --#~ msgid "" --#~ "If enabled, gnome-session will prompt the user before ending a session." --#~ msgstr "" --#~ "Soll gnome-session den Benutzer vor dem Beenden einer Sitzung fragen?" -- --#~ msgid "If enabled, gnome-session will save the session automatically." --#~ msgstr "Falls aktiviert, speichert gnome-session die Sitzung automatisch." -- --#~ msgid "List of applications that are part of the default session." --#~ msgstr "Liste der Anwendungen, die Teil der Standardsitzung sind." -- --#~ msgid "" --#~ "List of components that are required as part of the session. (Each " --#~ "element names a key under \"/desktop/gnome/session/required_components" --#~ "\"). The Startup Applications preferences tool will not normally allow " --#~ "users to remove a required component from the session, and the session " --#~ "manager will automatically add the required components back to the " --#~ "session at login time if they do get removed." --#~ msgstr "" --#~ "Liste der Komponenten, die als Teil der Sitzung erforderlich sind. (Jedes " --#~ "Element bezeichnet einen Schlüssel unter »/desktop/gnome/session/" --#~ "required_components«). Das Programm zur Verwaltung der " --#~ "Startprogrammeinstellungen erlaubt gewöhnlichen Benutzern nicht, " --#~ "benötigte Komponenten aus der Sitzung zu entfernen. Diese werden bei " --#~ "Anmeldung wieder automatisch zur Sitzung hinzugefügt, falls sie entfernt " --#~ "wurden." -- --#~ msgid "Logout prompt" --#~ msgstr "Abmeldedialog" -- --#~ msgid "Panel" --#~ msgstr "Das Panel" -- --#~ msgid "Required session components" --#~ msgstr "Benötigte Sitzungskomponenten" -- --#~ msgid "" --#~ "The file manager provides the desktop icons and allows you to interact " --#~ "with your saved files." --#~ msgstr "" --#~ "Der Dateimanager stellt die Desktop-Symbole bereit und erlaubt Ihnen, " --#~ "gespeicherte Dateien zu verwalten." -diff -urN gnome-session-3.14.0/po/es.po gnome-session-3.14.0_localized/po/es.po ---- gnome-session-3.14.0/po/es.po 2014-07-19 02:20:42.000000000 +0530 -+++ gnome-session-3.14.0_localized/po/es.po 2016-03-14 19:41:08.904245225 +0530 -@@ -1,36 +1,106 @@ --# translation of gnome-session.master.po to Español --# gnome-session Spanish translation. --# Copyright © 1998-2003, 2006, 2007, 2008 the Free Software Foundation, Inc. --# Pablo Saratxaga 1999-2000 --# Javier Gómez 2000 --# Juanjo Alvarez 2000 --# Ismael Olea 2000 --# Manuel de Vega Barreiro 2000 --# Juan Manuel García Molina 2001-2002. --# --# Miguel de Icaza,computo,622-4680 1998. --# Francisco Javier F. Serrador , 2003. --# Francisco Javier F. Serrador , 2005, 2006. --# --# Jorge González , 2007, 2009, 2010, 2011. , 2011. --# Daniel Mustieles , 2011. , 2012, 2013. --# -+# translation of gnome-session.master.po to Español -+# gnome-session Spanish translation. -+# Copyright © 1998-2003, 2006, 2007, 2008 the Free Software Foundation, Inc. -+# Pablo Saratxaga 1999-2000 -+# Javier Gómez 2000 -+# Juanjo Alvarez 2000 -+# Ismael Olea 2000 -+# Manuel de Vega Barreiro 2000 -+# Juan Manuel García Molina 2001-2002. -+# -+# Miguel de Icaza,computo,622-4680 1998. -+# Francisco Javier F. Serrador , 2003. -+# Francisco Javier F. Serrador , 2005, 2006. -+# -+# Jorge González , 2007, 2009, 2010, 2011, 2011. -+# Daniel Mustieles , 2011, 2012, 2013. -+# gguerrer , 2016. #zanata -+# pnemade , 2016. #zanata - msgid "" - msgstr "" - "Project-Id-Version: gnome-session.master\n" --"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" --"session&keywords=I18N+L10N&component=general\n" --"POT-Creation-Date: 2014-04-15 08:11+0000\n" --"PO-Revision-Date: 2013-09-10 14:25+0200\n" --"Last-Translator: Daniel Mustieles \n" --"Language-Team: Español \n" --"Language: \n" -+"Report-Msgid-Bugs-To: \n" -+"POT-Creation-Date: 2016-02-26 10:16+0530\n" - "MIME-Version: 1.0\n" - "Content-Type: text/plain; charset=UTF-8\n" - "Content-Transfer-Encoding: 8bit\n" --"X-Generator: Gtranslator 2.91.5\n" -+"PO-Revision-Date: 2016-03-09 06:28+0000\n" -+"Last-Translator: gguerrer \n" -+"Language-Team: Español \n" -+"Language: es\n" -+"X-Generator: Zanata 3.8.2\n" - "Plural-Forms: nplurals=2; plural=(n!=1);\n" - -+#: ../capplet/gsm-app-dialog.c:120 -+msgid "Select Command" -+msgstr "Seleccionar comando" -+ -+#: ../capplet/gsm-app-dialog.c:193 -+msgid "Add Startup Program" -+msgstr "Añadir programa al inicio" -+ -+#: ../capplet/gsm-app-dialog.c:197 -+msgid "Edit Startup Program" -+msgstr "Editar programa al inicio" -+ -+#: ../capplet/gsm-app-dialog.c:484 -+msgid "The startup command cannot be empty" -+msgstr "El comando de inicio no puede estar vacío" -+ -+#: ../capplet/gsm-app-dialog.c:490 -+msgid "The startup command is not valid" -+msgstr "El comando de inicio no es válido" -+ -+#: ../capplet/gsm-properties-dialog.c:493 -+msgid "Your session has been saved." -+msgstr "Su sesión ha sido guardada" -+ -+#: ../capplet/gsm-properties-dialog.c:495 -+#: ../capplet/gsm-properties-dialog.c:521 -+msgid "Failed to save session" -+msgstr "Falló al guardar sesión" -+ -+#: ../capplet/gsm-properties-dialog.c:509 -+msgid "Could not connect to the session bus" -+msgstr "No se pudo conectar con el bus de sesiones" -+ -+#: ../capplet/gsm-properties-dialog.c:515 ../tools/gnome-session-quit.c:89 -+#: ../tools/gnome-session-quit.c:99 -+msgid "Could not connect to the session manager" -+msgstr "No se pudo conectar con el gestor de sesiones" -+ -+#: ../capplet/gsm-properties-dialog.c:606 -+msgid "Enabled" -+msgstr "Activado" -+ -+#: ../capplet/gsm-properties-dialog.c:618 -+msgid "Icon" -+msgstr "Icono" -+ -+#: ../capplet/gsm-properties-dialog.c:630 -+msgid "Program" -+msgstr "Programa" -+ -+#: ../capplet/gsm-properties-dialog.c:834 -+msgid "Startup Applications Preferences" -+msgstr "Preferencias de las aplicaciones al inicio" -+ -+#: ../capplet/gsp-app.c:277 -+msgid "No name" -+msgstr "Sin nombre" -+ -+#: ../capplet/gsp-app.c:283 -+msgid "No description" -+msgstr "Sin descripción" -+ -+#: ../capplet/main.c:35 ../gnome-session/main.c:308 -+msgid "Version of this application" -+msgstr "Versión de esta aplicación" -+ -+#: ../capplet/main.c:61 -+msgid "Could not display help document" -+msgstr "No se pudo mostrar el documento de ayuda" -+ - #: ../data/gnome-custom-session.desktop.in.h:1 - msgid "Custom" - msgstr "Personalizada" -@@ -51,6 +121,14 @@ - msgid "GNOME dummy" - msgstr "GNOME «dummy»" - -+#: ../data/session-properties.desktop.in.in.h:1 -+msgid "Startup Applications" -+msgstr "Aplicaciones al inicio" -+ -+#: ../data/session-properties.desktop.in.in.h:2 -+msgid "Choose what applications to start when you log in" -+msgstr "Elija qué aplicaciones iniciar al iniciar la sesión" -+ - #: ../data/gnome-wayland.desktop.in.h:1 - #: ../data/gnome-wayland.session.desktop.in.in.h:1 - msgid "GNOME on Wayland" -@@ -64,9 +142,9 @@ - msgid "Custom Session" - msgstr "Sesión personalizada" - --#: ../data/session-selector.ui.h:2 ../tools/gnome-session-selector.c:102 --msgid "Please select a custom session to run" --msgstr "Seleccione una sesión personalizada que ejecutar" -+#: ../data/session-selector.ui.h:2 -+msgid "Please select a custom session to use" -+msgstr "Seleccione una sesión personalizada a usar" - - #: ../data/session-selector.ui.h:3 - msgid "_New Session" -@@ -81,6 +159,10 @@ - msgstr "Reno_mbrar sesión" - - #: ../data/session-selector.ui.h:6 -+msgid "Classic Experience" -+msgstr "Experiencia clásica" -+ -+#: ../data/session-selector.ui.h:7 - msgid "_Continue" - msgstr "_Continuar" - -@@ -95,7 +177,8 @@ - #: ../data/session-properties.ui.h:3 - msgid "_Automatically remember running applications when logging out" - msgstr "" --"Recordar _automáticamente las aplicaciones en ejecución al salir de la sesión" -+"Recordar _automáticamente las aplicaciones en ejecución al salir de la " -+"sesión" - - #: ../data/session-properties.ui.h:4 - msgid "_Remember Currently Running Applications" -@@ -153,7 +236,7 @@ - msgid "_Log Out" - msgstr "Ce_rrar la sesión" - --#: ../gnome-session/gsm-fail-whale-dialog.c:369 ../gnome-session/main.c:305 -+#: ../gnome-session/gsm-fail-whale-dialog.c:369 ../gnome-session/main.c:306 - msgid "Enable debugging code" - msgstr "Activar el código de depuración" - -@@ -165,23 +248,23 @@ - msgid "Show extension warning" - msgstr "Mostrar advertencias de las extensiones" - --#: ../gnome-session/gsm-manager.c:1271 ../gnome-session/gsm-manager.c:2043 -+#: ../gnome-session/gsm-manager.c:1370 ../gnome-session/gsm-manager.c:2192 - msgid "Not responding" - msgstr "No responde" - --#: ../gnome-session/gsm-util.c:409 -+#: ../gnome-session/gsm-util.c:382 - msgid "_Log out" - msgstr "_Cerrar la sesión" - - #. It'd be really surprising to reach this code: if we're here, - #. * then the XSMP client already has set several XSMP - #. * properties. But it could still be that SmProgram is not set. --#. --#: ../gnome-session/gsm-xsmp-client.c:557 -+#. -+#: ../gnome-session/gsm-xsmp-client.c:582 - msgid "Remembered Application" - msgstr "Aplicación recordada" - --#: ../gnome-session/gsm-xsmp-client.c:1207 -+#: ../gnome-session/gsm-xsmp-client.c:1244 - msgid "This program is blocking logout." - msgstr "Este programa está bloqueando el cierre de sesión." - -@@ -198,36 +281,32 @@ - msgid "Could not create ICE listening socket: %s" - msgstr "No se pudo crear el socket de escucha ICE: %s" - --#: ../gnome-session/main.c:303 -+#: ../gnome-session/main.c:304 - msgid "Override standard autostart directories" - msgstr "Sobrescribir las carpetas de inicio automático estándar" - --#: ../gnome-session/main.c:303 -+#: ../gnome-session/main.c:304 - msgid "AUTOSTART_DIR" - msgstr "CARPETA_DE_AUTOINICIO" - --#: ../gnome-session/main.c:304 -+#: ../gnome-session/main.c:305 - msgid "Session to use" - msgstr "Sesión que usar" - --#: ../gnome-session/main.c:304 -+#: ../gnome-session/main.c:305 - msgid "SESSION_NAME" - msgstr "NOMBRE_DE_LA_SESIÓN" - --#: ../gnome-session/main.c:306 -+#: ../gnome-session/main.c:307 - msgid "Do not load user-specified applications" - msgstr "No cargar las aplicaciones especificadas por el usuario" - --#: ../gnome-session/main.c:307 --msgid "Version of this application" --msgstr "Versión de esta aplicación" -- - #. Translators: the 'fail whale' is the black dialog we show when something goes seriously wrong --#: ../gnome-session/main.c:309 -+#: ../gnome-session/main.c:310 - msgid "Show the fail whale dialog for testing" - msgstr "Mostrar el diálogo de la ballena de pruebas" - --#: ../gnome-session/main.c:342 -+#: ../gnome-session/main.c:343 - msgid " - the GNOME session manager" - msgstr " - El gestor de sesiones de GNOME" - -@@ -276,31 +355,51 @@ - msgid "%s requires an argument\n" - msgstr "%s requiere un argumento\n" - --#: ../tools/gnome-session-selector.c:61 -+#: ../tools/gnome-session-selector.c:71 - #, c-format - msgid "Session %d" - msgstr "Sesión %d" - --#: ../tools/gnome-session-selector.c:107 -+#: ../tools/gnome-session-selector.c:115 - msgid "" - "Session names are not allowed to start with ‘.’ or contain ‘/’ characters" - msgstr "" - "No se permite que los nombres de las sesiones empiecen por «.» ni que " - "contengan el caracter «/»" - --#: ../tools/gnome-session-selector.c:111 -+#: ../tools/gnome-session-selector.c:119 - msgid "Session names are not allowed to start with ‘.’" - msgstr "No se permite que los nombres de las sesiones empiecen por «.»" - --#: ../tools/gnome-session-selector.c:115 -+#: ../tools/gnome-session-selector.c:123 - msgid "Session names are not allowed to contain ‘/’ characters" - msgstr "No se permite que los nombres de las sesiones contengan «/»" - --#: ../tools/gnome-session-selector.c:123 -+#: ../tools/gnome-session-selector.c:131 - #, c-format - msgid "A session named ‘%s’ already exists" - msgstr "Ya existe una sesión llamada «%s»" - -+#: ../tools/gnome-session-selector.c:794 -+msgid "What to do with session selection (save|load|print)" -+msgstr "Qué hacer con la selección de sesiones (guardar|cargar|imprimir)" -+ -+#: ../tools/gnome-session-selector.c:795 -+msgid "[session-name]" -+msgstr "[session-name]" -+ -+#: ../tools/gnome-session-selector.c:889 -+msgid "Please select a custom session to run" -+msgstr "Seleccione una sesión personalizada que ejecutar" -+ -+#: ../tools/gnome-session-selector.c:891 -+msgid "Please select a session to use" -+msgstr "Seleccione una sesión a usar" -+ -+#: ../tools/gnome-session-selector.c:893 -+msgid "Please select a session to save to" -+msgstr "Seleccione una sesión para guardar " -+ - #: ../tools/gnome-session-quit.c:51 - msgid "Log out" - msgstr "Cerrar la sesión" -@@ -321,488 +420,6 @@ - msgid "Don't prompt for user confirmation" - msgstr "No requerir confirmación del usuario" - --#: ../tools/gnome-session-quit.c:89 ../tools/gnome-session-quit.c:99 --msgid "Could not connect to the session manager" --msgstr "No se pudo conectar con el gestor de sesiones" -- - #: ../tools/gnome-session-quit.c:201 - msgid "Program called with conflicting options" - msgstr "Se llamó al programa con opciones en conflicto" -- --#~ msgid "Select Command" --#~ msgstr "Seleccionar comando" -- --#~ msgid "Add Startup Program" --#~ msgstr "Añadir programa al inicio" -- --#~ msgid "Edit Startup Program" --#~ msgstr "Editar programa al inicio" -- --#~ msgid "The startup command cannot be empty" --#~ msgstr "El comando de inicio no puede estar vacío" -- --#~ msgid "The startup command is not valid" --#~ msgstr "El comando de inicio no es válido" -- --#~ msgid "Enabled" --#~ msgstr "Activado" -- --#~ msgid "Icon" --#~ msgstr "Icono" -- --#~ msgid "Program" --#~ msgstr "Programa" -- --#~ msgid "Startup Applications Preferences" --#~ msgstr "Preferencias de las aplicaciones al inicio" -- --#~ msgid "No name" --#~ msgstr "Sin nombre" -- --#~ msgid "No description" --#~ msgstr "Sin descripción" -- --#~ msgid "Could not display help document" --#~ msgstr "No se pudo mostrar el documento de ayuda" -- --#~ msgid "Startup Applications" --#~ msgstr "Aplicaciones al inicio" -- --#~ msgid "Choose what applications to start when you log in" --#~ msgstr "Elija qué aplicaciones iniciar al iniciar la sesión" -- --#~ msgid "File is not a valid .desktop file" --#~ msgstr "El archivo no es un archivo .desktop válido" -- --#~ msgid "Unrecognized desktop file Version '%s'" --#~ msgstr "No se reconoce la versión «%s» del archivo desktop" -- --#~ msgid "Starting %s" --#~ msgstr "Iniciando %s" -- --#~ msgid "Application does not accept documents on command line" --#~ msgstr "La aplicación no acepta documentos en la línea de comandos" -- --#~ msgid "Unrecognized launch option: %d" --#~ msgstr "Opción de lanzamiento no reconocida: %d" -- --#~ msgid "Can't pass document URIs to a 'Type=Link' desktop entry" --#~ msgstr "" --#~ "No se pueden pasar los URI de documentos a entradas de escritorio " --#~ "Type=Link" -- --#~ msgid "Not a launchable item" --#~ msgstr "No es un elemento lanzable" -- --#~ msgid "Disable connection to session manager" --#~ msgstr "Desactivar la conexión con el gestor de sesiones" -- --#~ msgid "Specify file containing saved configuration" --#~ msgstr "Especifique el archivo que contiene la configuración guardada" -- --#~ msgid "FILE" --#~ msgstr "ARCHIVO" -- --#~ msgid "Specify session management ID" --#~ msgstr "Especifique el ID de gestión de la sesión" -- --#~ msgid "ID" --#~ msgstr "ID" -- --#~ msgid "Session management options:" --#~ msgstr "Opciones de gestión de sesión:" -- --#~ msgid "Show session management options" --#~ msgstr "Mostrar opciones de gestión de sesión" -- --#~ msgid "Some programs are still running:" --#~ msgstr "Aún se están ejecutando algunos programas:" -- --#~ msgid "Unknown" --#~ msgstr "Desconocido" -- --#~ msgid "A program is still running:" --#~ msgstr "Aún se está ejecutando un programa:" -- --#~ msgid "" --#~ "Waiting for the program to finish. Interrupting the program may cause you " --#~ "to lose work." --#~ msgstr "" --#~ "Esperando a que los programas finalicen. Interrumpir estos programas " --#~ "puede causar la pérdida de su trabajo." -- --#~ msgid "" --#~ "Waiting for programs to finish. Interrupting these programs may cause you " --#~ "to lose work." --#~ msgstr "" --#~ "Esperando a que los programas finalicen. Interrumpir estos programas " --#~ "puede causar la pérdida de su trabajo." -- --#~ msgid "Switch User Anyway" --#~ msgstr "Cambiar usuario de todas formas" -- --#~ msgid "Log Out Anyway" --#~ msgstr "Salir de todas formas" -- --#~ msgid "Suspend Anyway" --#~ msgstr "Suspender de todas formas" -- --#~ msgid "Hibernate Anyway" --#~ msgstr "Hibernar de todas formas" -- --#~ msgid "Shut Down Anyway" --#~ msgstr "Apagar de todas formas" -- --#~ msgid "Restart Anyway" --#~ msgstr "Reiniciar de todas formas" -- --#~ msgid "Lock Screen" --#~ msgstr "Bloquear pantalla" -- --#~ msgid "Cancel" --#~ msgstr "Cancelar" -- --#~ msgid "You will be automatically logged out in %d second." --#~ msgid_plural "You will be automatically logged out in %d seconds." --#~ msgstr[0] "Saldrá automáticamente de la sesión en %d segundo." --#~ msgstr[1] "Saldrá automáticamente de la sesión en %d segundos." -- --#~ msgid "This system will be automatically shut down in %d second." --#~ msgid_plural "This system will be automatically shut down in %d seconds." --#~ msgstr[0] "El sistema se apagará automáticamente en %d segundo." --#~ msgstr[1] "El sistema se apagará automáticamente en %d segundos." -- --#~ msgid "This system will be automatically restarted in %d second." --#~ msgid_plural "This system will be automatically restarted in %d seconds." --#~ msgstr[0] "El sistema se reiniciará automáticamente en %d segundo." --#~ msgstr[1] "El sistema se reiniciará automáticamente en %d segundos." -- --#~ msgid "You are currently logged in as \"%s\"." --#~ msgstr "Ha iniciado sesión como «%s»." -- --#~ msgid "Log out of this system now?" --#~ msgstr "¿Cerrar la sesión en este sistema ahora?" -- --#~ msgid "_Switch User" --#~ msgstr "Ca_mbiar usuario" -- --#~ msgid "Shut down this system now?" --#~ msgstr "¿Apagar ahora este sistema?" -- --#~ msgid "S_uspend" --#~ msgstr "_Suspender" -- --#~ msgid "_Hibernate" --#~ msgstr "_Hibernar" -- --#~ msgid "_Restart" --#~ msgstr "_Reiniciar" -- --#~ msgid "_Shut Down" --#~ msgstr "_Apagar" -- --#~ msgid "Restart this system now?" --#~ msgstr "¿Reiniciar este sistema ahora?" -- --#~ msgid "%d hour" --#~ msgid_plural "%d hours" --#~ msgstr[0] "%d hora" --#~ msgstr[1] "%d horas" -- --#~ msgid "%d minute" --#~ msgid_plural "%d minutes" --#~ msgstr[0] "%d minuto" --#~ msgstr[1] "%d minutos" -- --#~ msgid "%d second" --#~ msgid_plural "%d seconds" --#~ msgstr[0] "%d segundo" --#~ msgstr[1] "%d segundos" -- --#~ msgid "0 seconds" --#~ msgstr "0 segundos" -- --#~ msgid "Automatic logout in %s" --#~ msgstr "Cierre de sesión automático en %s" -- --#~ msgid "" --#~ "This session is configured to automatically log out after a period of " --#~ "inactivity." --#~ msgstr "" --#~ "Esta sesión está configurada para cerrarse automáticamente después de un " --#~ "período de inactividad." -- --#~ msgid "Icon '%s' not found" --#~ msgstr "No se encontró el icono «%s»" -- --#~ msgid "GNOME 3 Failed to Load" --#~ msgstr "GNOME 3 falló al cargar" -- --#~ msgid "" --#~ "Unfortunately GNOME 3 failed to start properly and started in the " --#~ "fallback mode.\n" --#~ "\n" --#~ "This most likely means your system (graphics hardware or driver) is not " --#~ "capable of delivering the full GNOME 3 experience." --#~ msgstr "" --#~ "Desafortunadamente GNOME 3 falló al iniciar y se inició en el modo " --#~ "alternativo.\n" --#~ "\n" --#~ "Probablemente significa que su sistema (hardware gráfico o controlador) " --#~ "no es capaz de ejecutar la experiencia GNOME 3 completa." -- --#~ msgid "Learn more about GNOME 3" --#~ msgstr "Aprenda más acerca de GNOME 3" -- --#~ msgid "" --#~ "Unable to start login session (and unable to connect to the X server)" --#~ msgstr "" --#~ "No se pudo iniciar el inicio de sesión (y fue imposible conectar con el " --#~ "servidor X)" -- --#~ msgid "Exited with code %d" --#~ msgstr "Salió con el código %d" -- --#~ msgid "Killed by signal %d" --#~ msgstr "Matado por la señal %d" -- --#~ msgid "Stopped by signal %d" --#~ msgstr "Detenido por la señal %d" -- --#~ msgid "Some programs are still running:" --#~ msgstr "Algunos programas aún se están ejecutando:" -- --#~ msgid "" --#~ "A problem has occurred and the system can't recover. Some of the " --#~ "extensions below may have caused this.\n" --#~ "Please try disabling some of these, and then log out and try again." --#~ msgstr "" --#~ "Ocurrió un problema y el sistema no se puede recuperar. Algunas de las " --#~ "extensiones de abajo pueden haber causado el problema.\n" --#~ "Desactive algunas de ellas y después cierre la sesión e inténtelo de " --#~ "nuevo." -- --#~ msgid "" --#~ "There is a problem with the configuration server.\n" --#~ "(%s exited with status %d)" --#~ msgstr "" --#~ "Hay un problema con la configuración del servidor.\n" --#~ "(%s salió con el estado %d)" -- --#~ msgid "Try _Recovery" --#~ msgstr "Intentar _recuperar" -- --#~ msgid "A system error has occurred: %s" --#~ msgstr "Ocurrió un error del sistema: %s" -- --#~ msgid "A fatal system error has occurred: %s" --#~ msgstr "Ocurrió un error fatal del sistema: %s" -- --#~ msgid "Component '%s': %s" --#~ msgstr "Componente «%s»: %s" -- --#~ msgid "Killed by signal" --#~ msgstr "Matado por una señal" -- --#~ msgid "Timed out" --#~ msgstr "Tiempo de espera agotado" -- --#~ msgid "Show shutdown dialog" --#~ msgstr "Mostrar el diálogo de apagado" -- --#~ msgid "Use dialog boxes for errors" --#~ msgstr "Usar cajas de diálogo para los errores" -- --#~ msgid "Set the current session name" --#~ msgstr "Establecer el nombre de la sesión actual" -- --#~ msgid "NAME" --#~ msgstr "NOMBRE" -- --#~ msgid "Kill session" --#~ msgstr "Terminar la sesión" -- --#~ msgid "Window Manager" --#~ msgstr "Gestor de ventanas" -- --#~ msgid "Classic GNOME" --#~ msgstr "GNOME clásico" -- --#~ msgid "File Manager" --#~ msgstr "Gestor de archivos" -- --#~ msgid "" --#~ "If enabled, gnome-session will prompt the user before ending a session." --#~ msgstr "" --#~ "Si está activado, gnome-session preguntará al usuario antes de cerrar una " --#~ "sesión." -- --#~ msgid "If enabled, gnome-session will save the session automatically." --#~ msgstr "Si está activado, gnome-session guardará la sesión automáticamente." -- --#~ msgid "List of applications that are part of the default session." --#~ msgstr "Lista de aplicaciones que son parte de la sesión predeterminada." -- --#~ msgid "" --#~ "List of components that are required as part of the session. (Each " --#~ "element names a key under \"/desktop/gnome/session/required_components" --#~ "\"). The Startup Applications preferences tool will not normally allow " --#~ "users to remove a required component from the session, and the session " --#~ "manager will automatically add the required components back to the " --#~ "session at login time if they do get removed." --#~ msgstr "" --#~ "Lista de componentes necesarios como partes de la sesión. (Cada elemento " --#~ "tiene una clave bajo \"/desktop/gnome/session/required_components\".) " --#~ "Generalmente la miniaplicación de la sesión no permitirá que los usuarios " --#~ "eliminen componentes necesarios para la sesión, y el gestor de sesiones " --#~ "añadirá automáticamente los componentes necesarios a la sesión, si se " --#~ "eliminaron." -- --#~ msgid "Logout prompt" --#~ msgstr "Diálogo de salida" -- --#~ msgid "Panel" --#~ msgstr "El panel" -- --#~ msgid "Required session components" --#~ msgstr "Componentes de sesión requeridos" -- --#~ msgid "" --#~ "The file manager provides the desktop icons and allows you to interact " --#~ "with your saved files." --#~ msgstr "" --#~ "El gestor de archivos proporciona los iconos de escritorio y le permite " --#~ "interactuar con sus archivos guardados." -- --#~ msgid "" --#~ "The number of minutes of inactivity before the session is considered idle." --#~ msgstr "" --#~ "El número de minutos de inactividad antes de considerar la sesión " --#~ "inactiva." -- --#~ msgid "" --#~ "The panel provides the bar at the top or bottom of the screen containing " --#~ "menus, the window list, status icons, the clock, etc." --#~ msgstr "" --#~ "El panel proporciona la barra en la parte superior y/o inferior de la " --#~ "pantalla y que contiene los menús, la lista de ventanas, los iconos de " --#~ "estado, el reloj, etc." -- --#~ msgid "" --#~ "The window manager is the program that draws the title bar and borders " --#~ "around windows, and allows you to move and resize windows." --#~ msgstr "" --#~ "El gestor de ventanas es el programa que dibuja las barras de título y " --#~ "los bordes alrededor de las ventanas, y le permite mover y redimensionar " --#~ "ventanas." -- --#~ msgid "Time before session is considered idle" --#~ msgstr "Tiempo antes de que la sesión se considere inactiva" -- --#~| msgid "GConf key used to lookup default session" --#~ msgid "GConf key used to look up default session" --#~ msgstr "Clave de GConf usada para buscar la sesión predeterminada" -- --#~ msgid "Preferred Image to use for login splash screen" --#~ msgstr "La imagen preferida para mostrar como pantalla de bienvenida" -- --#~ msgid "Show the splash screen" --#~ msgstr "Mostrar la pantalla de bienvenida" -- --#~ msgid "Show the splash screen when the session starts up" --#~ msgstr "Muestra la pantalla de bienvenida cuando se inicia la sesión" -- --#~| msgid "" --#~| "This is a relative path value based off the $datadir/pixmaps/ directory. " --#~| "Sub-directories and image names are valid values. Changing this value " --#~| "will effect the next session login." --#~ msgid "" --#~ "This is a relative path value based off the $datadir/pixmaps/ directory. " --#~ "Sub-directories and image names are valid values. Changing this value " --#~ "will affect the next session login." --#~ msgstr "" --#~ "Esta es una ruta relativa basada en el directorio $datadir/pixmaps/. Los " --#~ "subdirectorios y los nombres de imágenes son valores válidos. El cambio " --#~ "de este valor afectará al siguiente inicio de sesión." -- --#~ msgid "" --#~ "Waiting for program to finish. Interrupting program may cause you to " --#~ "lose work." --#~ msgstr "" --#~ "Esperando a que finalice el programa. Interrumpir el programa puede " --#~ "causar pérdidas de datos." -- --#~ msgid "- GNOME Splash Screen" --#~ msgstr "- Pantalla de bienvenida de GNOME" -- --#~ msgid "GNOME Splash Screen" --#~ msgstr "Pantalla de bienvenida de GNOME" -- --#~ msgid "" --#~ "Assistive technology support has been requested for this session, but the " --#~ "accessibility registry was not found. Please ensure that the AT-SPI " --#~ "package is installed. Your session has been started without assistive " --#~ "technology support." --#~ msgstr "" --#~ "Se ha solicitado soporte de tecnologías de asistencia para esta sesión, " --#~ "pero no se ha encontrado el registro para accesibilidad. Asegúrese de que " --#~ "el paquete AT-SPI está instalado. Su sesión se ha iniciado sin soporte de " --#~ "tecnologías de asistencia." -- --#~ msgid "AT SPI Registry Wrapper" --#~ msgstr "Envolvente de registro AT SPI" -- --#~ msgid "GNOME Settings Daemon Helper" --#~ msgstr "Ayudante del demonio de preferencias de GNOME" -- --#~ msgid "" --#~ "If enabled, gnome-session will save the session automatically. Otherwise, " --#~ "the logout dialog will have an option to save the session." --#~ msgstr "" --#~ "Si está activado, gnome-session guardará la sesión automáticamente. En " --#~ "caso contrario, el diálogo de salida presentará la opción de guardar la " --#~ "sesión." -- --#~ msgid "The name of the startup program cannot be empty" --#~ msgstr "El nombre del programa de inicio no puede estar vacío" -- --#~ msgid "Sessions Preferences" --#~ msgstr "Preferencias de la sesión" -- --#~ msgid "Selected option in the log out dialog" --#~ msgstr "Opción seleccionada en el diálogo de cierre de sesión" -- --#~ msgid "" --#~ "This is the option that will be selected in the logout dialog, valid " --#~ "values are \"logout\" for logging out, \"shutdown\" for halting the " --#~ "system and \"restart\" for restarting the system." --#~ msgstr "" --#~ "Esta es la opción que estará seleccionado en el diálogo de cierre de " --#~ "sesión, los valores válidos son \"logout\" para cerrar la sesión, " --#~ "\"shutdown\" para apagar el sistema y \"restart\" para reiniciar el " --#~ "sistema." -- --#~ msgid "Configure your sessions" --#~ msgstr "Configure sus sesiones" -- --#~ msgid "GNOME Keyring Daemon Wrapper" --#~ msgstr "Envolvente del demonio del Depósito de claves de GNOME" -- --#~ msgid "Session management" --#~ msgstr "Gestión de sesiones" -- --#~ msgid "GNOME GUI Library + EggSMClient" --#~ msgstr "Biblioteca IGU de GNOME + EggSMClient" -- --#~ msgid "" --#~ "The Window manager that gnome-session will start. Valid values are " --#~ "\"metacity\" and \"compiz\"." --#~ msgstr "" --#~ "El Gestor de ventanas que gnome-session iniciará. Los valores válidos son " --#~ "«metacity» y «compiz»." -- --#~ msgid "Window Manager to start" --#~ msgstr "Gestor de ventanas que iniciar" -- --#~ msgid "gtk-cancel" --#~ msgstr "gtk-cancel" -diff -urN gnome-session-3.14.0/po/fr.po gnome-session-3.14.0_localized/po/fr.po ---- gnome-session-3.14.0/po/fr.po 2014-06-25 23:36:33.000000000 +0530 -+++ gnome-session-3.14.0_localized/po/fr.po 2016-03-14 19:41:08.914245216 +0530 -@@ -1,6 +1,6 @@ - # French translation of gnome-session. - # Copyright (C) 1998-2012 Free Software Foundation, Inc. --# -+# - # Vincent Renardias , 1998-2000. - # Joaquim Fellmann , 2000. - # Christophe Merlet , 2000-2006. -@@ -14,21 +14,22 @@ - # Frédéric Péters , 2008. - # Bruno Brouard , 2009,2011-2012 - # Nicolas Repentin , 2011 --# -+# Sam Friedmann , 2016. #zanata -+# pnemade , 2016. #zanata - msgid "" - msgstr "" - "Project-Id-Version: gnome-session.HEAD\n" --"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" --"session&keywords=I18N+L10N&component=general\n" --"POT-Creation-Date: 2013-09-09 23:10+0000\n" --"PO-Revision-Date: 2013-09-12 18:08+0200\n" --"Last-Translator: Bruno Brouard \n" --"Language-Team: GNOME French Team \n" --"Language: \n" -+"Report-Msgid-Bugs-To: \n" -+"POT-Creation-Date: 2016-02-26 10:16+0530\n" - "MIME-Version: 1.0\n" - "Content-Type: text/plain; charset=UTF-8\n" - "Content-Transfer-Encoding: 8bit\n" -+"PO-Revision-Date: 2016-03-02 10:22+0000\n" -+"Last-Translator: Sam Friedmann \n" -+"Language-Team: GNOME French Team \n" -+"Language: fr\n" - "Plural-Forms: nplurals=2; plural=n>1;\n" -+"X-Generator: Zanata 3.8.2\n" - - #: ../capplet/gsm-app-dialog.c:120 - msgid "Select Command" -@@ -50,31 +51,49 @@ - msgid "The startup command is not valid" - msgstr "La commande de démarrage n'est pas valide" - --#: ../capplet/gsm-properties-dialog.c:519 -+#: ../capplet/gsm-properties-dialog.c:493 -+msgid "Your session has been saved." -+msgstr "Votre session a été enregistrée" -+ -+#: ../capplet/gsm-properties-dialog.c:495 -+#: ../capplet/gsm-properties-dialog.c:521 -+msgid "Failed to save session" -+msgstr "Impossible d'enregistrer la session" -+ -+#: ../capplet/gsm-properties-dialog.c:509 -+msgid "Could not connect to the session bus" -+msgstr "Impossible de se connecter au bus de session" -+ -+#: ../capplet/gsm-properties-dialog.c:515 ../tools/gnome-session-quit.c:89 -+#: ../tools/gnome-session-quit.c:99 -+msgid "Could not connect to the session manager" -+msgstr "Impossible de se connecter au gestionnaire de sessions" -+ -+#: ../capplet/gsm-properties-dialog.c:606 - msgid "Enabled" - msgstr "Activé" - --#: ../capplet/gsm-properties-dialog.c:531 -+#: ../capplet/gsm-properties-dialog.c:618 - msgid "Icon" - msgstr "Icône" - --#: ../capplet/gsm-properties-dialog.c:543 -+#: ../capplet/gsm-properties-dialog.c:630 - msgid "Program" - msgstr "Programme" - --#: ../capplet/gsm-properties-dialog.c:747 -+#: ../capplet/gsm-properties-dialog.c:834 - msgid "Startup Applications Preferences" - msgstr "Préférences des applications au démarrage" - --#: ../capplet/gsp-app.c:276 -+#: ../capplet/gsp-app.c:277 - msgid "No name" - msgstr "Pas de nom" - --#: ../capplet/gsp-app.c:282 -+#: ../capplet/gsp-app.c:283 - msgid "No description" - msgstr "Pas de description" - --#: ../capplet/main.c:35 ../gnome-session/main.c:309 -+#: ../capplet/main.c:35 ../gnome-session/main.c:308 - msgid "Version of this application" - msgstr "Version de cette application" - -@@ -102,11 +121,11 @@ - msgid "GNOME dummy" - msgstr "GNOME factice" - --#: ../data/gnome-session-properties.desktop.in.in.h:1 -+#: ../data/session-properties.desktop.in.in.h:1 - msgid "Startup Applications" - msgstr "Applications au démarrage" - --#: ../data/gnome-session-properties.desktop.in.in.h:2 -+#: ../data/session-properties.desktop.in.in.h:2 - msgid "Choose what applications to start when you log in" - msgstr "Choisir les applications à lancer à la connexion" - -@@ -123,9 +142,9 @@ - msgid "Custom Session" - msgstr "Session personnalisée" - --#: ../data/session-selector.ui.h:2 ../tools/gnome-session-selector.c:103 --msgid "Please select a custom session to run" --msgstr "Veuillez choisir une session personnalisée à lancer" -+#: ../data/session-selector.ui.h:2 -+msgid "Please select a custom session to use" -+msgstr "Veuillez sélectionner une session personnalisée à utiliser" - - #: ../data/session-selector.ui.h:3 - msgid "_New Session" -@@ -140,6 +159,10 @@ - msgstr "Reno_mmer la session" - - #: ../data/session-selector.ui.h:6 -+msgid "Classic Experience" -+msgstr "Expérience classique" -+ -+#: ../data/session-selector.ui.h:7 - msgid "_Continue" - msgstr "_Continuer" - -@@ -181,81 +204,11 @@ - msgid "_Name:" - msgstr "_Nom :" - --#: ../egg/eggdesktopfile.c:165 --#, c-format --msgid "File is not a valid .desktop file" --msgstr "Le fichier n'est pas un fichier .desktop valide" -- --#. translators: 'Version' is from a desktop file, and --#. * should not be translated. '%s' would probably be a --#. * version number. --#: ../egg/eggdesktopfile.c:191 --#, c-format --msgid "Unrecognized desktop file Version '%s'" --msgstr "La version « %s » du fichier .desktop n'est pas reconnue" -- --#: ../egg/eggdesktopfile.c:974 --#, c-format --msgid "Starting %s" --msgstr "Démarrage de %s" -- --#: ../egg/eggdesktopfile.c:1116 --#, c-format --msgid "Application does not accept documents on command line" --msgstr "L'application n'accepte pas de documents en ligne de commande" -- --#: ../egg/eggdesktopfile.c:1184 --#, c-format --msgid "Unrecognized launch option: %d" --msgstr "Option de démarrage non reconnue : %d" -- --#. translators: The 'Type=Link' string is found in a --#. * desktop file, and should not be translated. --#: ../egg/eggdesktopfile.c:1391 --#, c-format --msgid "Can't pass document URIs to a 'Type=Link' desktop entry" --msgstr "" --"Impossible de passer des URI de document à un fichier de bureau avec " --"« Type=Link »" -- --#: ../egg/eggdesktopfile.c:1412 --#, c-format --msgid "Not a launchable item" --msgstr "Cet élément ne peut être lancé" -- --#: ../egg/eggsmclient.c:226 --msgid "Disable connection to session manager" --msgstr "Désactive la connexion au gestionnaire de sessions" -- --#: ../egg/eggsmclient.c:229 --msgid "Specify file containing saved configuration" --msgstr "Indique le fichier contenant la configuration enregistrée" -- --#: ../egg/eggsmclient.c:229 --msgid "FILE" --msgstr "FICHIER" -- --#: ../egg/eggsmclient.c:232 --msgid "Specify session management ID" --msgstr "Indique l'identificateur de la gestion de sessions" -- --#: ../egg/eggsmclient.c:232 --msgid "ID" --msgstr "ID" -- --#: ../egg/eggsmclient.c:253 --msgid "Session management options:" --msgstr "Options de la gestion de sessions :" -- --#: ../egg/eggsmclient.c:254 --msgid "Show session management options" --msgstr "Affiche les options de la gestion de sessions" -- --#: ../gnome-session/gsm-fail-whale-dialog.c:295 -+#: ../gnome-session/gsm-fail-whale-dialog.c:321 - msgid "Oh no! Something has gone wrong." - msgstr "Oh mince ! Quelque chose s'est mal passé." - --#: ../gnome-session/gsm-fail-whale-dialog.c:302 -+#: ../gnome-session/gsm-fail-whale-dialog.c:328 - msgid "" - "A problem has occurred and the system can't recover. Please contact a system " - "administrator" -@@ -263,7 +216,7 @@ - "Un problème est survenu et le système ne peut pas se récupérer. Contactez un " - "administrateur système" - --#: ../gnome-session/gsm-fail-whale-dialog.c:304 -+#: ../gnome-session/gsm-fail-whale-dialog.c:330 - msgid "" - "A problem has occurred and the system can't recover. All extensions have " - "been disabled as a precaution." -@@ -271,7 +224,7 @@ - "Un problème est survenu et le système ne peut pas se récupérer. Toutes les " - "extensions ont été désactivées par mesure de précaution." - --#: ../gnome-session/gsm-fail-whale-dialog.c:306 -+#: ../gnome-session/gsm-fail-whale-dialog.c:332 - msgid "" - "A problem has occurred and the system can't recover.\n" - "Please log out and try again." -@@ -279,43 +232,43 @@ - "Un problème est survenu et le système ne peut pas se récupérer.\n" - "Déconnectez-vous et essayez à nouveau." - --#: ../gnome-session/gsm-fail-whale-dialog.c:321 -+#: ../gnome-session/gsm-fail-whale-dialog.c:347 - msgid "_Log Out" - msgstr "_Fermer la session" - --#: ../gnome-session/gsm-fail-whale-dialog.c:343 ../gnome-session/main.c:307 -+#: ../gnome-session/gsm-fail-whale-dialog.c:369 ../gnome-session/main.c:306 - msgid "Enable debugging code" - msgstr "Active le code de débogage" - --#: ../gnome-session/gsm-fail-whale-dialog.c:344 -+#: ../gnome-session/gsm-fail-whale-dialog.c:370 - msgid "Allow logout" - msgstr "Autoriser la déconnexion" - --#: ../gnome-session/gsm-fail-whale-dialog.c:345 -+#: ../gnome-session/gsm-fail-whale-dialog.c:371 - msgid "Show extension warning" - msgstr "Afficher l'avertissement pour les extensions" - --#: ../gnome-session/gsm-manager.c:1271 ../gnome-session/gsm-manager.c:2043 -+#: ../gnome-session/gsm-manager.c:1370 ../gnome-session/gsm-manager.c:2192 - msgid "Not responding" - msgstr "Absence de réponse" - --#: ../gnome-session/gsm-util.c:411 -+#: ../gnome-session/gsm-util.c:382 - msgid "_Log out" - msgstr "_Se déconnecter" - - #. It'd be really surprising to reach this code: if we're here, - #. * then the XSMP client already has set several XSMP - #. * properties. But it could still be that SmProgram is not set. --#. --#: ../gnome-session/gsm-xsmp-client.c:559 -+#. -+#: ../gnome-session/gsm-xsmp-client.c:582 - msgid "Remembered Application" - msgstr "Applications mémorisées" - --#: ../gnome-session/gsm-xsmp-client.c:1209 -+#: ../gnome-session/gsm-xsmp-client.c:1244 - msgid "This program is blocking logout." - msgstr "Ce programme bloque la déconnexion." - --#: ../gnome-session/gsm-xsmp-server.c:341 -+#: ../gnome-session/gsm-xsmp-server.c:340 - msgid "" - "Refusing new client connection because the session is currently being shut " - "down\n" -@@ -323,41 +276,41 @@ - "Refus de la connexion d'un nouveau client car la session est actuellement en " - "cours de fermeture\n" - --#: ../gnome-session/gsm-xsmp-server.c:610 -+#: ../gnome-session/gsm-xsmp-server.c:609 - #, c-format - msgid "Could not create ICE listening socket: %s" - msgstr "Impossible de créer le connecteur d'écoute ICE : %s" - --#: ../gnome-session/main.c:305 -+#: ../gnome-session/main.c:304 - msgid "Override standard autostart directories" - msgstr "Remplace les répertoires autostart standards" - --#: ../gnome-session/main.c:305 -+#: ../gnome-session/main.c:304 - msgid "AUTOSTART_DIR" - msgstr "RÉP_AUTOSTART" - --#: ../gnome-session/main.c:306 -+#: ../gnome-session/main.c:305 - msgid "Session to use" - msgstr "Session à utiliser" - --#: ../gnome-session/main.c:306 -+#: ../gnome-session/main.c:305 - msgid "SESSION_NAME" - msgstr "NOM_SESSION" - --#: ../gnome-session/main.c:308 -+#: ../gnome-session/main.c:307 - msgid "Do not load user-specified applications" - msgstr "Ne charge pas les applications demandées par l'utilisateur" - - #. Translators: the 'fail whale' is the black dialog we show when something goes seriously wrong --#: ../gnome-session/main.c:311 -+#: ../gnome-session/main.c:310 - msgid "Show the fail whale dialog for testing" - msgstr "Afficher le dialogue d'erreur pour le tester" - --#: ../gnome-session/main.c:344 -+#: ../gnome-session/main.c:343 - msgid " - the GNOME session manager" - msgstr "- le gestionnaire de sessions de GNOME" - --#: ../tools/gnome-session-inhibit.c:110 -+#: ../tools/gnome-session-inhibit.c:108 - #, c-format - msgid "" - "%s [OPTION...] COMMAND\n" -@@ -392,191 +345,82 @@ - "\n" - "Si aucune option --inhibit n'est précisée, « idle » est supposé.\n" - --#: ../tools/gnome-session-inhibit.c:148 -+#: ../tools/gnome-session-inhibit.c:146 - #, c-format - msgid "Failed to execute %s\n" - msgstr "Impossible d'exécuter %s\n" - --#: ../tools/gnome-session-inhibit.c:208 ../tools/gnome-session-inhibit.c:218 --#: ../tools/gnome-session-inhibit.c:228 -+#: ../tools/gnome-session-inhibit.c:206 ../tools/gnome-session-inhibit.c:216 -+#: ../tools/gnome-session-inhibit.c:226 - #, c-format - msgid "%s requires an argument\n" - msgstr "%s nécessite un paramètre\n" - --#: ../tools/gnome-session-selector.c:62 -+#: ../tools/gnome-session-selector.c:71 - #, c-format - msgid "Session %d" - msgstr "Session %d" - --#: ../tools/gnome-session-selector.c:108 -+#: ../tools/gnome-session-selector.c:115 - msgid "" - "Session names are not allowed to start with ‘.’ or contain ‘/’ characters" - msgstr "" - "Les noms de sessions ne peuvent pas commencer par « . » ou contenir le " - "caractère « / »" - --#: ../tools/gnome-session-selector.c:112 -+#: ../tools/gnome-session-selector.c:119 - msgid "Session names are not allowed to start with ‘.’" - msgstr "Les noms de sessions ne peuvent pas commencer par « . »" - --#: ../tools/gnome-session-selector.c:116 -+#: ../tools/gnome-session-selector.c:123 - msgid "Session names are not allowed to contain ‘/’ characters" - msgstr "Les noms de sessions ne peuvent pas contenir le caractère « / »" - --#: ../tools/gnome-session-selector.c:124 -+#: ../tools/gnome-session-selector.c:131 - #, c-format - msgid "A session named ‘%s’ already exists" - msgstr "Une session nommée « %s » existe déjà" - --#: ../tools/gnome-session-quit.c:53 -+#: ../tools/gnome-session-selector.c:794 -+msgid "What to do with session selection (save|load|print)" -+msgstr "Que faire avec la sélection de session (enregistrer|charger|imprimer)" -+ -+#: ../tools/gnome-session-selector.c:795 -+msgid "[session-name]" -+msgstr "[session-name]" -+ -+#: ../tools/gnome-session-selector.c:889 -+msgid "Please select a custom session to run" -+msgstr "Veuillez choisir une session personnalisée à lancer" -+ -+#: ../tools/gnome-session-selector.c:891 -+msgid "Please select a session to use" -+msgstr "Veuillez sélectionner une session à utiliser" -+ -+#: ../tools/gnome-session-selector.c:893 -+msgid "Please select a session to save to" -+msgstr "Veuillez sélectionner une session sur laquelle enregistrer" -+ -+#: ../tools/gnome-session-quit.c:51 - msgid "Log out" - msgstr "Se déconnecte" - --#: ../tools/gnome-session-quit.c:54 -+#: ../tools/gnome-session-quit.c:52 - msgid "Power off" - msgstr "S'éteint" - --#: ../tools/gnome-session-quit.c:55 -+#: ../tools/gnome-session-quit.c:53 - msgid "Reboot" - msgstr "Redémarrer" - --#: ../tools/gnome-session-quit.c:56 -+#: ../tools/gnome-session-quit.c:54 - msgid "Ignoring any existing inhibitors" - msgstr "Ignorer tout inhibiteur existant" - --#: ../tools/gnome-session-quit.c:57 -+#: ../tools/gnome-session-quit.c:55 - msgid "Don't prompt for user confirmation" - msgstr "Ne demande pas de confirmation" - --#: ../tools/gnome-session-quit.c:91 ../tools/gnome-session-quit.c:101 --msgid "Could not connect to the session manager" --msgstr "Impossible de se connecter au gestionnaire de sessions" -- --#: ../tools/gnome-session-quit.c:203 -+#: ../tools/gnome-session-quit.c:201 - msgid "Program called with conflicting options" - msgstr "Programme appelé avec des options conflictuelles" -- --#~ msgid "Some programs are still running:" --#~ msgstr "Des programmes sont toujours en cours d'exécution :" -- --#~ msgid "Unknown" --#~ msgstr "Inconnu" -- --#~ msgid "A program is still running:" --#~ msgstr "Un programme est toujours en cours d'exécution :" -- --#~ msgid "" --#~ "Waiting for the program to finish. Interrupting the program may cause you " --#~ "to lose work." --#~ msgstr "" --#~ "Attente de la fin du programme. L'interruption du programme risquerait de " --#~ "vous faire perdre certaines données." -- --#~ msgid "" --#~ "Waiting for programs to finish. Interrupting these programs may cause you " --#~ "to lose work." --#~ msgstr "" --#~ "Attente de la fin des programmes. L'interruption de ces programmes " --#~ "risquerait de vous faire perdre certaines données." -- --#~ msgid "Switch User Anyway" --#~ msgstr "Changer d'utilisateur malgré tout" -- --#~ msgid "Log Out Anyway" --#~ msgstr "Se déconnecter malgré tout" -- --#~ msgid "Suspend Anyway" --#~ msgstr "Mettre en veille malgré tout" -- --#~ msgid "Hibernate Anyway" --#~ msgstr "Hiberner malgré tout" -- --#~ msgid "Shut Down Anyway" --#~ msgstr "Éteindre malgré tout" -- --#~ msgid "Restart Anyway" --#~ msgstr "Redémarrer malgré tout" -- --#~ msgid "Lock Screen" --#~ msgstr "Verrouiller l'écran" -- --#~ msgid "Cancel" --#~ msgstr "Annuler" -- --#~ msgid "You will be automatically logged out in %d second." --#~ msgid_plural "You will be automatically logged out in %d seconds." --#~ msgstr[0] "Vous serez automatiquement déconnecté dans %d seconde." --#~ msgstr[1] "Vous serez automatiquement déconnecté dans %d secondes." -- --#~ msgid "This system will be automatically shut down in %d second." --#~ msgid_plural "This system will be automatically shut down in %d seconds." --#~ msgstr[0] "Cet ordinateur va s'éteindre automatiquement dans %d seconde." --#~ msgstr[1] "Cet ordinateur va s'éteindre automatiquement dans %d secondes." -- --#~ msgid "This system will be automatically restarted in %d second." --#~ msgid_plural "This system will be automatically restarted in %d seconds." --#~ msgstr[0] "Cet ordinateur va redémarrer automatiquement dans %d seconde." --#~ msgstr[1] "Cet ordinateur va redémarrer automatiquement dans %d secondes." -- --#~ msgid "You are currently logged in as \"%s\"." --#~ msgstr "Vous êtes actuellement connecté en tant que « %s »." -- --#~ msgid "Log out of this system now?" --#~ msgstr "Se déconnecter du système maintenant ?" -- --#~ msgid "_Switch User" --#~ msgstr "Changer d'_utilisateur" -- --#~ msgid "Shut down this system now?" --#~ msgstr "Éteindre cet ordinateur maintenant ?" -- --#~ msgid "S_uspend" --#~ msgstr "_Mettre en veille" -- --#~ msgid "_Hibernate" --#~ msgstr "_Hiberner" -- --#~ msgid "_Restart" --#~ msgstr "_Redémarrer" -- --#~ msgid "_Shut Down" --#~ msgstr "Ét_eindre" -- --#~ msgid "Restart this system now?" --#~ msgstr "Redémarrer cet ordinateur maintenant ?" -- --#~ msgid "Icon '%s' not found" --#~ msgstr "Icône « %s » non trouvée" -- --#~ msgid "GNOME 3 Failed to Load" --#~ msgstr "Échec du chargement de GNOME 3" -- --#~ msgid "" --#~ "Unfortunately GNOME 3 failed to start properly and started in the " --#~ "fallback mode.\n" --#~ "\n" --#~ "This most likely means your system (graphics hardware or driver) is not " --#~ "capable of delivering the full GNOME 3 experience." --#~ msgstr "" --#~ "GNOME 3 n'a malheureusement pas réussi à démarrer correctement et a " --#~ "démarré en mode restreint.\n" --#~ "\n" --#~ "Cela signifie probablement que votre système (la carte graphique ou son " --#~ "pilote) n'est pas assez puissant pour prendre en charge tous les éléments " --#~ "du bureau GNOME 3." -- --#~ msgid "Learn more about GNOME 3" --#~ msgstr "En apprendre plus sur GNOME 3" -- --#~ msgid "" --#~ "Unable to start login session (and unable to connect to the X server)" --#~ msgstr "Impossible de démarrer la session (et de se connecter au serveur X)" -- --#~ msgid "Exited with code %d" --#~ msgstr "Quitté avec le code %d" -- --#~ msgid "Killed by signal %d" --#~ msgstr "Tué par le signal %d" -- --#~ msgid "Stopped by signal %d" --#~ msgstr "Interrompu par le signal %d" -diff -urN gnome-session-3.14.0/po/it.po gnome-session-3.14.0_localized/po/it.po ---- gnome-session-3.14.0/po/it.po 2014-06-25 23:36:34.000000000 +0530 -+++ gnome-session-3.14.0_localized/po/it.po 2016-03-14 19:41:08.922245209 +0530 -@@ -4,21 +4,21 @@ - # Christopher R. Gabriel , 1997, 1998, 1999, 2000, 2001, 2002. - # Milo Casagrande , 2012. - # Luca Ferretti , 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013. --# -+# pnemade , 2016. #zanata - msgid "" - msgstr "" - "Project-Id-Version: gnome-session 3.7.x\n" - "Report-Msgid-Bugs-To: \n" --"POT-Creation-Date: 2013-09-16 14:24+0200\n" --"PO-Revision-Date: 2013-09-15 18:45+0200\n" --"Last-Translator: Luca Ferretti \n" --"Language-Team: Italiano \n" --"Language: \n" -+"POT-Creation-Date: 2016-02-26 10:16+0530\n" - "MIME-Version: 1.0\n" - "Content-Type: text/plain; charset=UTF-8\n" - "Content-Transfer-Encoding: 8bit\n" -+"PO-Revision-Date: 2013-09-15 04:45+0000\n" -+"Last-Translator: Luca Ferretti \n" -+"Language-Team: Italiano \n" -+"Language: it\n" - "Plural-Forms: nplurals=2; plural=(n != 1);\n" --"X-Generator: Gtranslator 2.91.6\n" -+"X-Generator: Zanata 3.8.2\n" - - #: ../capplet/gsm-app-dialog.c:120 - msgid "Select Command" -@@ -40,31 +40,51 @@ - msgid "The startup command is not valid" - msgstr "Il comando di avvio non è valido" - --#: ../capplet/gsm-properties-dialog.c:519 -+#: ../capplet/gsm-properties-dialog.c:493 -+msgid "Your session has been saved." -+msgstr "" -+ -+#: ../capplet/gsm-properties-dialog.c:495 -+#: ../capplet/gsm-properties-dialog.c:521 -+#, fuzzy -+msgid "Failed to save session" -+msgstr "Esecuzione di %s non riuscita\n" -+ -+#: ../capplet/gsm-properties-dialog.c:509 -+#, fuzzy -+msgid "Could not connect to the session bus" -+msgstr "Impossibile connettersi al gestore di sessione" -+ -+#: ../capplet/gsm-properties-dialog.c:515 ../tools/gnome-session-quit.c:89 -+#: ../tools/gnome-session-quit.c:99 -+msgid "Could not connect to the session manager" -+msgstr "Impossibile connettersi al gestore di sessione" -+ -+#: ../capplet/gsm-properties-dialog.c:606 - msgid "Enabled" - msgstr "Abilitato" - --#: ../capplet/gsm-properties-dialog.c:531 -+#: ../capplet/gsm-properties-dialog.c:618 - msgid "Icon" - msgstr "Icona" - --#: ../capplet/gsm-properties-dialog.c:543 -+#: ../capplet/gsm-properties-dialog.c:630 - msgid "Program" - msgstr "Programma" - --#: ../capplet/gsm-properties-dialog.c:747 -+#: ../capplet/gsm-properties-dialog.c:834 - msgid "Startup Applications Preferences" - msgstr "Preferenze delle applicazioni d'avvio" - --#: ../capplet/gsp-app.c:276 -+#: ../capplet/gsp-app.c:277 - msgid "No name" - msgstr "Nessun nome" - --#: ../capplet/gsp-app.c:282 -+#: ../capplet/gsp-app.c:283 - msgid "No description" - msgstr "Nessuna descrizione" - --#: ../capplet/main.c:35 ../gnome-session/main.c:309 -+#: ../capplet/main.c:35 ../gnome-session/main.c:308 - msgid "Version of this application" - msgstr "Versione di questa applicazione" - -@@ -92,11 +112,11 @@ - msgid "GNOME dummy" - msgstr "GNOME dummy" - --#: ../data/gnome-session-properties.desktop.in.in.h:1 -+#: ../data/session-properties.desktop.in.in.h:1 - msgid "Startup Applications" - msgstr "Applicazioni d'avvio" - --#: ../data/gnome-session-properties.desktop.in.in.h:2 -+#: ../data/session-properties.desktop.in.in.h:2 - msgid "Choose what applications to start when you log in" - msgstr "Sceglie quali applicazioni avviare quando si esegue l'accesso" - -@@ -113,8 +133,9 @@ - msgid "Custom Session" - msgstr "Sessione personalizzata" - --#: ../data/session-selector.ui.h:2 ../tools/gnome-session-selector.c:103 --msgid "Please select a custom session to run" -+#: ../data/session-selector.ui.h:2 -+#, fuzzy -+msgid "Please select a custom session to use" - msgstr "Selezionare una sessione personalizzata da lanciare" - - #: ../data/session-selector.ui.h:3 -@@ -130,6 +151,10 @@ - msgstr "Rino_mina sessione" - - #: ../data/session-selector.ui.h:6 -+msgid "Classic Experience" -+msgstr "" -+ -+#: ../data/session-selector.ui.h:7 - msgid "_Continue" - msgstr "_Continua" - -@@ -172,83 +197,11 @@ - msgid "_Name:" - msgstr "N_ome:" - --#: ../egg/eggdesktopfile.c:165 --#, c-format --msgid "File is not a valid .desktop file" --msgstr "Il file non è un file .desktop valido" -- --#. translators: 'Version' is from a desktop file, and --#. * should not be translated. '%s' would probably be a --#. * version number. --#: ../egg/eggdesktopfile.c:191 --#, c-format --msgid "Unrecognized desktop file Version '%s'" --msgstr "Versione «%s» del file desktop non riconosciuta" -- --#: ../egg/eggdesktopfile.c:974 --#, c-format --msgid "Starting %s" --msgstr "Avvio di «%s»" -- --#: ../egg/eggdesktopfile.c:1116 --#, c-format --msgid "Application does not accept documents on command line" --msgstr "L'applicazione non accetta documenti sulla riga di comando" -- --#: ../egg/eggdesktopfile.c:1184 --#, c-format --msgid "Unrecognized launch option: %d" --msgstr "Opzione di lancio non riconosciuta: %d" -- --#. translators: The 'Type=Link' string is found in a --#. * desktop file, and should not be translated. --#: ../egg/eggdesktopfile.c:1391 --#, c-format --msgid "Can't pass document URIs to a 'Type=Link' desktop entry" --msgstr "" --"Impossibile passare URI di documenti a una desktop entry con \"Type=Link\"" -- --#: ../egg/eggdesktopfile.c:1412 --#, c-format --msgid "Not a launchable item" --msgstr "Non è un oggetto lanciabile" -- --# spiegazione opzione riga comando --#: ../egg/eggsmclient.c:226 --msgid "Disable connection to session manager" --msgstr "Disabilita la connessione al gestore di sessione" -- --# spiegazione opzione riga comando --#: ../egg/eggsmclient.c:229 --msgid "Specify file containing saved configuration" --msgstr "Specifica il file contenente la configurazione salvata" -- --#: ../egg/eggsmclient.c:229 --msgid "FILE" --msgstr "FILE" -- --# spiegazione opzione riga comando --#: ../egg/eggsmclient.c:232 --msgid "Specify session management ID" --msgstr "Specifica l'ID di gestione sessione" -- --#: ../egg/eggsmclient.c:232 --msgid "ID" --msgstr "ID" -- --#: ../egg/eggsmclient.c:253 --msgid "Session management options:" --msgstr "Opzioni di gestione sessione:" -- --#: ../egg/eggsmclient.c:254 --msgid "Show session management options" --msgstr "Mostra le opzioni di gestione sessione" -- --#: ../gnome-session/gsm-fail-whale-dialog.c:295 -+#: ../gnome-session/gsm-fail-whale-dialog.c:321 - msgid "Oh no! Something has gone wrong." - msgstr "Oh no! Qualcosa è andato storto." - --#: ../gnome-session/gsm-fail-whale-dialog.c:302 -+#: ../gnome-session/gsm-fail-whale-dialog.c:328 - msgid "" - "A problem has occurred and the system can't recover. Please contact a system " - "administrator" -@@ -256,7 +209,7 @@ - "Si è verificato un problema impossibile da recuperare. Contattare " - "l'amministratore di sistema" - --#: ../gnome-session/gsm-fail-whale-dialog.c:304 -+#: ../gnome-session/gsm-fail-whale-dialog.c:330 - msgid "" - "A problem has occurred and the system can't recover. All extensions have " - "been disabled as a precaution." -@@ -264,7 +217,7 @@ - "Si è verificato un problema impossibile da recuperare. Per precauzione, " - "tutte le estensioni sono state disabilitate." - --#: ../gnome-session/gsm-fail-whale-dialog.c:306 -+#: ../gnome-session/gsm-fail-whale-dialog.c:332 - msgid "" - "A problem has occurred and the system can't recover.\n" - "Please log out and try again." -@@ -272,86 +225,86 @@ - "Si è verificato un problema impossibile da recuperare.\n" - "Terminare la sessione e provare di nuovo." - --#: ../gnome-session/gsm-fail-whale-dialog.c:321 -+#: ../gnome-session/gsm-fail-whale-dialog.c:347 - msgid "_Log Out" - msgstr "_Termina sessione" - --#: ../gnome-session/gsm-fail-whale-dialog.c:343 ../gnome-session/main.c:307 -+#: ../gnome-session/gsm-fail-whale-dialog.c:369 ../gnome-session/main.c:306 - msgid "Enable debugging code" - msgstr "Abilita codice di debug" - --#: ../gnome-session/gsm-fail-whale-dialog.c:344 -+#: ../gnome-session/gsm-fail-whale-dialog.c:370 - msgid "Allow logout" - msgstr "Consente di terminare la sessione" - --#: ../gnome-session/gsm-fail-whale-dialog.c:345 -+#: ../gnome-session/gsm-fail-whale-dialog.c:371 - msgid "Show extension warning" - msgstr "Mostra gli avvisi delle estensioni" - - # non so se la forma è corretta, non ho provato - # a inibire il termine sessione --#: ../gnome-session/gsm-manager.c:1271 ../gnome-session/gsm-manager.c:2043 -+#: ../gnome-session/gsm-manager.c:1370 ../gnome-session/gsm-manager.c:2192 - msgid "Not responding" - msgstr "Non risponde" - --#: ../gnome-session/gsm-util.c:411 -+#: ../gnome-session/gsm-util.c:382 - msgid "_Log out" - msgstr "_Termina la sessione" - - #. It'd be really surprising to reach this code: if we're here, - #. * then the XSMP client already has set several XSMP - #. * properties. But it could still be that SmProgram is not set. --#. --#: ../gnome-session/gsm-xsmp-client.c:559 -+#. -+#: ../gnome-session/gsm-xsmp-client.c:582 - msgid "Remembered Application" - msgstr "Applicazioni memorizzate" - --#: ../gnome-session/gsm-xsmp-client.c:1209 -+#: ../gnome-session/gsm-xsmp-client.c:1244 - msgid "This program is blocking logout." - msgstr "Questo programma sta bloccando la terminazione della sessione." - --#: ../gnome-session/gsm-xsmp-server.c:341 -+#: ../gnome-session/gsm-xsmp-server.c:340 - msgid "" - "Refusing new client connection because the session is currently being shut " - "down\n" - msgstr "" - "Rifiutate nuove connessioni client perché la sessione è in via di arresto\n" - --#: ../gnome-session/gsm-xsmp-server.c:610 -+#: ../gnome-session/gsm-xsmp-server.c:609 - #, c-format - msgid "Could not create ICE listening socket: %s" - msgstr "Impossibile creare il socket di ascolto ICE: %s" - --#: ../gnome-session/main.c:305 -+#: ../gnome-session/main.c:304 - msgid "Override standard autostart directories" - msgstr "Non tiene conto delle directory standard di avvio automatico" - --#: ../gnome-session/main.c:305 -+#: ../gnome-session/main.c:304 - msgid "AUTOSTART_DIR" - msgstr "DIR_AUTOSTART" - --#: ../gnome-session/main.c:306 -+#: ../gnome-session/main.c:305 - msgid "Session to use" - msgstr "Sessione da usare" - --#: ../gnome-session/main.c:306 -+#: ../gnome-session/main.c:305 - msgid "SESSION_NAME" - msgstr "NOME_SESSIONE" - --#: ../gnome-session/main.c:308 -+#: ../gnome-session/main.c:307 - msgid "Do not load user-specified applications" - msgstr "Non carica le applicazioni specificate dall'utente" - - #. Translators: the 'fail whale' is the black dialog we show when something goes seriously wrong --#: ../gnome-session/main.c:311 -+#: ../gnome-session/main.c:310 - msgid "Show the fail whale dialog for testing" - msgstr "Mostra il dialogo \"fail whale\" per test" - --#: ../gnome-session/main.c:344 -+#: ../gnome-session/main.c:343 - msgid " - the GNOME session manager" - msgstr "- il gestore di sessioni di GNOME" - --#: ../tools/gnome-session-inhibit.c:110 -+#: ../tools/gnome-session-inhibit.c:108 - #, c-format - msgid "" - "%s [OPTION...] COMMAND\n" -@@ -384,69 +337,87 @@ - "\n" - "Se non è specificata alcuna opzine per --inhibit, viene usato idle.\n" - --#: ../tools/gnome-session-inhibit.c:148 -+#: ../tools/gnome-session-inhibit.c:146 - #, c-format - msgid "Failed to execute %s\n" - msgstr "Esecuzione di %s non riuscita\n" - --#: ../tools/gnome-session-inhibit.c:208 ../tools/gnome-session-inhibit.c:218 --#: ../tools/gnome-session-inhibit.c:228 -+#: ../tools/gnome-session-inhibit.c:206 ../tools/gnome-session-inhibit.c:216 -+#: ../tools/gnome-session-inhibit.c:226 - #, c-format - msgid "%s requires an argument\n" - msgstr "%s richiede un parametro\n" - --#: ../tools/gnome-session-selector.c:62 -+#: ../tools/gnome-session-selector.c:71 - #, c-format - msgid "Session %d" - msgstr "Sessione %d" - --#: ../tools/gnome-session-selector.c:108 -+#: ../tools/gnome-session-selector.c:115 - msgid "" - "Session names are not allowed to start with ‘.’ or contain ‘/’ characters" - msgstr "" - "I nomi delle sessioni non possono iniziare con «.» o contenere caratteri «/»" - --#: ../tools/gnome-session-selector.c:112 -+#: ../tools/gnome-session-selector.c:119 - msgid "Session names are not allowed to start with ‘.’" - msgstr "I nomi delle sessioni non possono iniziare con «.»" - --#: ../tools/gnome-session-selector.c:116 -+#: ../tools/gnome-session-selector.c:123 - msgid "Session names are not allowed to contain ‘/’ characters" - msgstr "I nomi delle sessioni non contenere caratteri «/»" - --#: ../tools/gnome-session-selector.c:124 -+#: ../tools/gnome-session-selector.c:131 - #, c-format - msgid "A session named ‘%s’ already exists" - msgstr "Un sessione chiamata «%s» esiste già" - -+#: ../tools/gnome-session-selector.c:794 -+msgid "What to do with session selection (save|load|print)" -+msgstr "" -+ -+#: ../tools/gnome-session-selector.c:795 -+msgid "[session-name]" -+msgstr "" -+ -+#: ../tools/gnome-session-selector.c:889 -+msgid "Please select a custom session to run" -+msgstr "Selezionare una sessione personalizzata da lanciare" -+ -+#: ../tools/gnome-session-selector.c:891 -+#, fuzzy -+msgid "Please select a session to use" -+msgstr "Selezionare una sessione personalizzata da lanciare" -+ -+#: ../tools/gnome-session-selector.c:893 -+#, fuzzy -+msgid "Please select a session to save to" -+msgstr "Selezionare una sessione personalizzata da lanciare" -+ - # commento opzioni riga comando --#: ../tools/gnome-session-quit.c:53 -+#: ../tools/gnome-session-quit.c:51 - msgid "Log out" - msgstr "Termina la sessione" - --#: ../tools/gnome-session-quit.c:54 -+#: ../tools/gnome-session-quit.c:52 - msgid "Power off" - msgstr "Spegni" - --#: ../tools/gnome-session-quit.c:55 -+#: ../tools/gnome-session-quit.c:53 - msgid "Reboot" - msgstr "Riavvia" - - # commento opzioni riga comando - # (ingorando non avrebbe senso in italiano - NdT) --#: ../tools/gnome-session-quit.c:56 -+#: ../tools/gnome-session-quit.c:54 - msgid "Ignoring any existing inhibitors" - msgstr "Ignora ogni inibitore esistente" - - # commento opzioni riga comando --#: ../tools/gnome-session-quit.c:57 -+#: ../tools/gnome-session-quit.c:55 - msgid "Don't prompt for user confirmation" - msgstr "Non richiede conferma all'utente" - --#: ../tools/gnome-session-quit.c:91 ../tools/gnome-session-quit.c:101 --msgid "Could not connect to the session manager" --msgstr "Impossibile connettersi al gestore di sessione" -- --#: ../tools/gnome-session-quit.c:203 -+#: ../tools/gnome-session-quit.c:201 - msgid "Program called with conflicting options" - msgstr "Programma chiamato con opzioni in conflitto" -diff -urN gnome-session-3.14.0/po/ja.po gnome-session-3.14.0_localized/po/ja.po ---- gnome-session-3.14.0/po/ja.po 2014-06-25 23:36:34.000000000 +0530 -+++ gnome-session-3.14.0_localized/po/ja.po 2016-03-14 19:41:08.929245203 +0530 -@@ -14,20 +14,22 @@ - # Jiro Matsuzawa , 2011, 2012, 2013. - # Hideki Yamane , 2011, 2012. - # Noriko Mizumoto , 2012. --# -+# kmoriguc , 2016. #zanata -+# pnemade , 2016. #zanata - msgid "" - msgstr "" - "Project-Id-Version: gnome-session master\n" --"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-session&keywords=I18N+L10N&component=general\n" --"POT-Creation-Date: 2013-09-09 23:10+0000\n" --"PO-Revision-Date: 2013-09-15 21:58+0900\n" --"Last-Translator: Jiro Matsuzawa \n" --"Language-Team: Japanese \n" --"Language: ja\n" -+"Report-Msgid-Bugs-To: \n" -+"POT-Creation-Date: 2016-02-26 10:16+0530\n" - "MIME-Version: 1.0\n" - "Content-Type: text/plain; charset=UTF-8\n" - "Content-Transfer-Encoding: 8bit\n" -+"PO-Revision-Date: 2016-03-14 01:18+0000\n" -+"Last-Translator: kmoriguc \n" -+"Language-Team: Japanese \n" -+"Language: ja\n" - "Plural-Forms: nplurals=1; plural=0;\n" -+"X-Generator: Zanata 3.8.2\n" - - #: ../capplet/gsm-app-dialog.c:120 - msgid "Select Command" -@@ -49,31 +51,49 @@ - msgid "The startup command is not valid" - msgstr "コマンド名が間違っています" - --#: ../capplet/gsm-properties-dialog.c:519 -+#: ../capplet/gsm-properties-dialog.c:493 -+msgid "Your session has been saved." -+msgstr "セッションが保存されました。" -+ -+#: ../capplet/gsm-properties-dialog.c:495 -+#: ../capplet/gsm-properties-dialog.c:521 -+msgid "Failed to save session" -+msgstr "セッションの保存に失敗しました" -+ -+#: ../capplet/gsm-properties-dialog.c:509 -+msgid "Could not connect to the session bus" -+msgstr "セッションバスに接続できませんでした" -+ -+#: ../capplet/gsm-properties-dialog.c:515 ../tools/gnome-session-quit.c:89 -+#: ../tools/gnome-session-quit.c:99 -+msgid "Could not connect to the session manager" -+msgstr "セッションマネージャーに接続できませんでした" -+ -+#: ../capplet/gsm-properties-dialog.c:606 - msgid "Enabled" - msgstr "有効" - --#: ../capplet/gsm-properties-dialog.c:531 -+#: ../capplet/gsm-properties-dialog.c:618 - msgid "Icon" - msgstr "アイコン" - --#: ../capplet/gsm-properties-dialog.c:543 -+#: ../capplet/gsm-properties-dialog.c:630 - msgid "Program" - msgstr "プログラム" - --#: ../capplet/gsm-properties-dialog.c:747 -+#: ../capplet/gsm-properties-dialog.c:834 - msgid "Startup Applications Preferences" - msgstr "自動起動するアプリケーションの設定" - --#: ../capplet/gsp-app.c:276 -+#: ../capplet/gsp-app.c:277 - msgid "No name" - msgstr "名前なし" - --#: ../capplet/gsp-app.c:282 -+#: ../capplet/gsp-app.c:283 - msgid "No description" - msgstr "(説明なし)" - --#: ../capplet/main.c:35 ../gnome-session/main.c:309 -+#: ../capplet/main.c:35 ../gnome-session/main.c:308 - msgid "Version of this application" - msgstr "このアプリケーションのバージョンを表示する" - -@@ -101,11 +121,11 @@ - msgid "GNOME dummy" - msgstr "GNOME ダミー" - --#: ../data/gnome-session-properties.desktop.in.in.h:1 -+#: ../data/session-properties.desktop.in.in.h:1 - msgid "Startup Applications" - msgstr "自動起動するアプリケーション" - --#: ../data/gnome-session-properties.desktop.in.in.h:2 -+#: ../data/session-properties.desktop.in.in.h:2 - msgid "Choose what applications to start when you log in" - msgstr "ログインした後に起動するアプリケーションを選択します" - -@@ -122,9 +142,9 @@ - msgid "Custom Session" - msgstr "カスタムセッション" - --#: ../data/session-selector.ui.h:2 ../tools/gnome-session-selector.c:103 --msgid "Please select a custom session to run" --msgstr "起動するカスタムセッションを選択してください" -+#: ../data/session-selector.ui.h:2 -+msgid "Please select a custom session to use" -+msgstr "使用するカスタムセッションを選択してください" - - #: ../data/session-selector.ui.h:3 - msgid "_New Session" -@@ -139,6 +159,10 @@ - msgstr "セッション名を変更(_M)" - - #: ../data/session-selector.ui.h:6 -+msgid "Classic Experience" -+msgstr "クラッシックエクスペリエンス" -+ -+#: ../data/session-selector.ui.h:7 - msgid "_Continue" - msgstr "続行(_C)" - -@@ -178,169 +202,106 @@ - msgid "_Name:" - msgstr "名前(_N):" - --#: ../egg/eggdesktopfile.c:165 --#, c-format --msgid "File is not a valid .desktop file" --msgstr "有効な .desktop ファイルではありません" -- --#. translators: 'Version' is from a desktop file, and --#. * should not be translated. '%s' would probably be a --#. * version number. --#: ../egg/eggdesktopfile.c:191 --#, c-format --msgid "Unrecognized desktop file Version '%s'" --msgstr "バージョン '%s' の .desktop ファイルはサポートしていません" -- --#: ../egg/eggdesktopfile.c:974 --#, c-format --msgid "Starting %s" --msgstr "%sの起動中です" -- --#: ../egg/eggdesktopfile.c:1116 --#, c-format --msgid "Application does not accept documents on command line" --msgstr "コマンドラインからドキュメントにはアクセスできません" -- --#: ../egg/eggdesktopfile.c:1184 --#, c-format --msgid "Unrecognized launch option: %d" --msgstr "不明な起動オプションです: %d" -- --#. translators: The 'Type=Link' string is found in a --#. * desktop file, and should not be translated. --#: ../egg/eggdesktopfile.c:1391 --#, c-format --msgid "Can't pass document URIs to a 'Type=Link' desktop entry" --msgstr "ドキュメントの URI を 'Type=Link' な .desktop エントリには渡せません" -- --#: ../egg/eggdesktopfile.c:1412 --#, c-format --msgid "Not a launchable item" --msgstr "起動可能なアイテムではありません" -- --#: ../egg/eggsmclient.c:226 --msgid "Disable connection to session manager" --msgstr "セッションマネージャーに接続しない" -- --#: ../egg/eggsmclient.c:229 --msgid "Specify file containing saved configuration" --msgstr "設定を保存したファイルを指定する" -- --#: ../egg/eggsmclient.c:229 --msgid "FILE" --msgstr "FILE" -- --#: ../egg/eggsmclient.c:232 --msgid "Specify session management ID" --msgstr "セッション管理の ID を指定する" -- --#: ../egg/eggsmclient.c:232 --msgid "ID" --msgstr "ID" -- --#: ../egg/eggsmclient.c:253 --msgid "Session management options:" --msgstr "セッション管理のオプション:" -- --#: ../egg/eggsmclient.c:254 --msgid "Show session management options" --msgstr "セッション管理のオプションを表示する" -- --#: ../gnome-session/gsm-fail-whale-dialog.c:295 -+#: ../gnome-session/gsm-fail-whale-dialog.c:321 - msgid "Oh no! Something has gone wrong." - msgstr "あれっ! 何かおかしいです。" - --#: ../gnome-session/gsm-fail-whale-dialog.c:302 --msgid "A problem has occurred and the system can't recover. Please contact a system administrator" -+#: ../gnome-session/gsm-fail-whale-dialog.c:328 -+msgid "" -+"A problem has occurred and the system can't recover. Please contact a system " -+"administrator" - msgstr "問題が発生して、システムの復帰ができません。システム管理者に連絡してください" - --#: ../gnome-session/gsm-fail-whale-dialog.c:304 --msgid "A problem has occurred and the system can't recover. All extensions have been disabled as a precaution." -+#: ../gnome-session/gsm-fail-whale-dialog.c:330 -+msgid "" -+"A problem has occurred and the system can't recover. All extensions have " -+"been disabled as a precaution." - msgstr "問題が発生して、システムの復帰ができません。念のため、すべての拡張を無効にしました。" - --#: ../gnome-session/gsm-fail-whale-dialog.c:306 -+#: ../gnome-session/gsm-fail-whale-dialog.c:332 - msgid "" - "A problem has occurred and the system can't recover.\n" - "Please log out and try again." --msgstr "" --"問題が発生して、システムの復帰ができません。\n" -+msgstr "問題が発生して、システムの復帰ができません。\n" - "ログアウトして再度試してください。" - --#: ../gnome-session/gsm-fail-whale-dialog.c:321 -+#: ../gnome-session/gsm-fail-whale-dialog.c:347 - msgid "_Log Out" - msgstr "ログアウト(_L)" - --#: ../gnome-session/gsm-fail-whale-dialog.c:343 ../gnome-session/main.c:307 -+#: ../gnome-session/gsm-fail-whale-dialog.c:369 ../gnome-session/main.c:306 - msgid "Enable debugging code" - msgstr "デバッグモードにする" - --#: ../gnome-session/gsm-fail-whale-dialog.c:344 -+#: ../gnome-session/gsm-fail-whale-dialog.c:370 - msgid "Allow logout" - msgstr "ログアウトを許可する" - --#: ../gnome-session/gsm-fail-whale-dialog.c:345 -+#: ../gnome-session/gsm-fail-whale-dialog.c:371 - msgid "Show extension warning" - msgstr "拡張機能に関する警告を表示する" - --#: ../gnome-session/gsm-manager.c:1271 ../gnome-session/gsm-manager.c:2043 -+#: ../gnome-session/gsm-manager.c:1370 ../gnome-session/gsm-manager.c:2192 - msgid "Not responding" - msgstr "応答なし" - --#: ../gnome-session/gsm-util.c:411 -+#: ../gnome-session/gsm-util.c:382 - msgid "_Log out" - msgstr "ログアウト(_L)" - - #. It'd be really surprising to reach this code: if we're here, - #. * then the XSMP client already has set several XSMP - #. * properties. But it could still be that SmProgram is not set. --#. --#: ../gnome-session/gsm-xsmp-client.c:559 -+#. -+#: ../gnome-session/gsm-xsmp-client.c:582 - msgid "Remembered Application" - msgstr "実行していたアプリケーション" - --#: ../gnome-session/gsm-xsmp-client.c:1209 -+#: ../gnome-session/gsm-xsmp-client.c:1244 - msgid "This program is blocking logout." - msgstr "このプログラムがログアウトできないようにしています。" - --#: ../gnome-session/gsm-xsmp-server.c:341 --msgid "Refusing new client connection because the session is currently being shut down\n" -+#: ../gnome-session/gsm-xsmp-server.c:340 -+msgid "" -+"Refusing new client connection because the session is currently being shut " -+"down\n" - msgstr "セッションがシャットダウンを実行しているため、新しいクライアントとの接続を拒否しました。\n" - --#: ../gnome-session/gsm-xsmp-server.c:610 -+#: ../gnome-session/gsm-xsmp-server.c:609 - #, c-format - msgid "Could not create ICE listening socket: %s" - msgstr "ICE の監視ソケットを生成できませんでした: %s" - --#: ../gnome-session/main.c:305 -+#: ../gnome-session/main.c:304 - msgid "Override standard autostart directories" - msgstr "標準の自動起動フォルダーをオーバーライドする" - --#: ../gnome-session/main.c:305 -+#: ../gnome-session/main.c:304 - msgid "AUTOSTART_DIR" - msgstr "AUTOSTART_DIR" - --#: ../gnome-session/main.c:306 -+#: ../gnome-session/main.c:305 - msgid "Session to use" - msgstr "使用するセッション" - --#: ../gnome-session/main.c:306 -+#: ../gnome-session/main.c:305 - msgid "SESSION_NAME" - msgstr "SESSION_NAME" - --#: ../gnome-session/main.c:308 -+#: ../gnome-session/main.c:307 - msgid "Do not load user-specified applications" - msgstr "ユーザーが指定したアプリケーションを起動しない" - - #. Translators: the 'fail whale' is the black dialog we show when something goes seriously wrong --#: ../gnome-session/main.c:311 -+#: ../gnome-session/main.c:310 - msgid "Show the fail whale dialog for testing" - msgstr "テスト用にエラー画面を表示する" - --#: ../gnome-session/main.c:344 -+#: ../gnome-session/main.c:343 - msgid " - the GNOME session manager" - msgstr "- GNOME セッションマネージャー" - --#: ../tools/gnome-session-inhibit.c:110 -+#: ../tools/gnome-session-inhibit.c:108 - #, c-format - msgid "" - "%s [OPTION...] COMMAND\n" -@@ -372,181 +333,80 @@ - "\n" - "--inhibit オプションが無指定の場合 idle を指定したものと扱います。\n" - --#: ../tools/gnome-session-inhibit.c:148 -+#: ../tools/gnome-session-inhibit.c:146 - #, c-format - msgid "Failed to execute %s\n" - msgstr "%s を起動できませんでした。\n" - --#: ../tools/gnome-session-inhibit.c:208 ../tools/gnome-session-inhibit.c:218 --#: ../tools/gnome-session-inhibit.c:228 -+#: ../tools/gnome-session-inhibit.c:206 ../tools/gnome-session-inhibit.c:216 -+#: ../tools/gnome-session-inhibit.c:226 - #, c-format - msgid "%s requires an argument\n" - msgstr "%s には引数が1つ必要です。\n" - --#: ../tools/gnome-session-selector.c:62 -+#: ../tools/gnome-session-selector.c:71 - #, c-format - msgid "Session %d" - msgstr "セッション %d" - --#: ../tools/gnome-session-selector.c:108 --msgid "Session names are not allowed to start with ‘.’ or contain ‘/’ characters" -+#: ../tools/gnome-session-selector.c:115 -+msgid "" -+"Session names are not allowed to start with ‘.’ or contain ‘/’ characters" - msgstr "セッション名は‘.’から始めたり、‘/’を含めることはできません。" - --#: ../tools/gnome-session-selector.c:112 -+#: ../tools/gnome-session-selector.c:119 - msgid "Session names are not allowed to start with ‘.’" - msgstr "‘.’はセッション名の先頭には使用できません。" - --#: ../tools/gnome-session-selector.c:116 -+#: ../tools/gnome-session-selector.c:123 - msgid "Session names are not allowed to contain ‘/’ characters" - msgstr "‘/’はセッション名に含めることができません。" - --#: ../tools/gnome-session-selector.c:124 -+#: ../tools/gnome-session-selector.c:131 - #, c-format - msgid "A session named ‘%s’ already exists" - msgstr "セッション‘%s’は既に存在します。" - --#: ../tools/gnome-session-quit.c:53 -+#: ../tools/gnome-session-selector.c:794 -+msgid "What to do with session selection (save|load|print)" -+msgstr "セッション選択での実行内容 (save|load|print)" -+ -+#: ../tools/gnome-session-selector.c:795 -+msgid "[session-name]" -+msgstr "[session-name]" -+ -+#: ../tools/gnome-session-selector.c:889 -+msgid "Please select a custom session to run" -+msgstr "起動するカスタムセッションを選択してください" -+ -+#: ../tools/gnome-session-selector.c:891 -+msgid "Please select a session to use" -+msgstr "使用するセッションを選択してください" -+ -+#: ../tools/gnome-session-selector.c:893 -+msgid "Please select a session to save to" -+msgstr "保存するセッションを選択してください" -+ -+#: ../tools/gnome-session-quit.c:51 - msgid "Log out" - msgstr "ログアウトする" - --#: ../tools/gnome-session-quit.c:54 -+#: ../tools/gnome-session-quit.c:52 - msgid "Power off" - msgstr "電源オフ" - --#: ../tools/gnome-session-quit.c:55 -+#: ../tools/gnome-session-quit.c:53 - msgid "Reboot" - msgstr "再起動" - --#: ../tools/gnome-session-quit.c:56 -+#: ../tools/gnome-session-quit.c:54 - msgid "Ignoring any existing inhibitors" - msgstr "阻害するプロセスを無視する" - --#: ../tools/gnome-session-quit.c:57 -+#: ../tools/gnome-session-quit.c:55 - msgid "Don't prompt for user confirmation" - msgstr "ユーザーに確認をしない" - --#: ../tools/gnome-session-quit.c:91 ../tools/gnome-session-quit.c:101 --msgid "Could not connect to the session manager" --msgstr "セッションマネージャーに接続できませんでした" -- --#: ../tools/gnome-session-quit.c:203 -+#: ../tools/gnome-session-quit.c:201 - msgid "Program called with conflicting options" - msgstr "同時には適用できないオプションを指定しました" -- --#~ msgid "Some programs are still running:" --#~ msgstr "いくつかのプログラムが未だ実行中です:" -- --#~ msgid "Unknown" --#~ msgstr "不明" -- --#~ msgid "A program is still running:" --#~ msgstr "プログラムが未だ実行中です:" -- --#~ msgid "Waiting for the program to finish. Interrupting the program may cause you to lose work." --#~ msgstr "プログラムが終了するのを待っています。プログラムの実行を強制的に中断すると、作業内容を失うことになるかもしれません。" -- --#~ msgid "Waiting for programs to finish. Interrupting these programs may cause you to lose work." --#~ msgstr "プログラムが終了するのを待っています。実行中のプログラムを途中で強制終了させてしまうと、これまでの処理結果を失ってしまう可能性があります。" -- --#~ msgid "Switch User Anyway" --#~ msgstr "とにかくユーザーを切り替える" -- --#~ msgid "Log Out Anyway" --#~ msgstr "とにかくログアウトする" -- --#~ msgid "Suspend Anyway" --#~ msgstr "とにかくサスペンドにする" -- --#~ msgid "Hibernate Anyway" --#~ msgstr "とにかく休止状態にする" -- --#~ msgid "Shut Down Anyway" --#~ msgstr "とにかくシャットダウンする" -- --#~ msgid "Restart Anyway" --#~ msgstr "とにかく再起動する" -- --#~ msgid "Lock Screen" --#~ msgstr "画面をロックする" -- --#~ msgid "Cancel" --#~ msgstr "キャンセル" -- --#~ msgid "You will be automatically logged out in %d second." --#~ msgid_plural "You will be automatically logged out in %d seconds." --#~ msgstr[0] "残り %d 秒で自動的にログアウトします。" -- --#~ msgid "This system will be automatically shut down in %d second." --#~ msgid_plural "This system will be automatically shut down in %d seconds." --#~ msgstr[0] "このシステムは残り %d 秒で自動的にシャットダウンします。" -- --#~ msgid "This system will be automatically restarted in %d second." --#~ msgid_plural "This system will be automatically restarted in %d seconds." --#~ msgstr[0] "このシステムは残り %d 秒で自動的に再起動します。" -- --#~ msgid "You are currently logged in as \"%s\"." --#~ msgstr "あなたは現在 \"%s\" としてログインしています。" -- --#~ msgid "Log out of this system now?" --#~ msgstr "このシステムから今すぐログアウトしますか?" -- --#~ msgid "_Switch User" --#~ msgstr "ユーザーを切り替える(_S)" -- --#~ msgid "Shut down this system now?" --#~ msgstr "このシステムを今すぐシャットダウンしますか?" -- --#~ msgid "S_uspend" --#~ msgstr "サスペンド(_U)" -- --#~ msgid "_Hibernate" --#~ msgstr "休止状態(_H)" -- --#~ msgid "_Restart" --#~ msgstr "再起動(_R)" -- --#~ msgid "_Shut Down" --#~ msgstr "シャットダウン(_S)" -- --#~ msgid "Restart this system now?" --#~ msgstr "このシステムを今すぐ再起動しますか?" -- --#~ msgid "Icon '%s' not found" --#~ msgstr "'%s' というアイコンが見つかりませんでした" -- --#~ msgid "GNOME 3 Failed to Load" --#~ msgstr "GNOME 3 を読み込むのに失敗しました" -- --#~ msgid "" --#~ "Unfortunately GNOME 3 failed to start properly and started in the fallback mode.\n" --#~ "\n" --#~ "This most likely means your system (graphics hardware or driver) is not capable of delivering the full GNOME 3 experience." --#~ msgstr "" --#~ "残念ながら GNOME 3 が正しく起動せず、フォールバックモード で起動しました。\n" --#~ "\n" --#~ "おそらく、このシステム (グラフィックのハードウェアやドライバー) は GNOME 3 を満足に動かすことができないようです。" -- --#~ msgid "Learn more about GNOME 3" --#~ msgstr "GNOME 3 について詳しく知る" -- --#~ msgid "Unable to start login session (and unable to connect to the X server)" --#~ msgstr "ログインセッションを起動できません (X サーバーにも接続できません)" -- --#~ msgid "Some programs are still running:" --#~ msgstr "いくつかのプログラムが未だ実行中です:" -- --#~ msgid "Exited with code %d" --#~ msgstr "コード %d で終了しました" -- --#~ msgid "Killed by signal %d" --#~ msgstr "シグナル %d で終了させられました" -- --#~ msgid "Stopped by signal %d" --#~ msgstr "シグナル %d で停止させられました" -- --#~ msgid "" --#~ "A problem has occurred and the system can't recover. Some of the extensions below may have caused this.\n" --#~ "Please try disabling some of these, and then log out and try again." --#~ msgstr "" --#~ "問題が発生して、システムの復帰ができません。これは以下の拡張のどれかが引き起こした可能性があります。\n" --#~ "これらのどれかを無効にして、ログアウトして再度試してください。" -diff -urN gnome-session-3.14.0/po/ko.po gnome-session-3.14.0_localized/po/ko.po ---- gnome-session-3.14.0/po/ko.po 2014-06-25 23:36:34.000000000 +0530 -+++ gnome-session-3.14.0_localized/po/ko.po 2016-03-14 19:41:08.936245196 +0530 -@@ -1,29 +1,29 @@ - # gnome-session Korean message translation - # This file is distributed under the same license as the gnome-session package. --# -+# - # Updated by Sung-Hyun Nam , 2000 - # Updated by Young-Ho Cha , 2000,2001,2006,2007 - # Changwoo Ryu , 1998, 2002-2013. --# --# -+# -+# - # 용어: --# -+# - # - Wayland - 웨일랜드 --# -+# pnemade , 2016. #zanata - msgid "" - msgstr "" - "Project-Id-Version: gnome-session\n" --"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" --"session&keywords=I18N+L10N&component=general\n" --"POT-Creation-Date: 2013-09-09 23:10+0000\n" --"PO-Revision-Date: 2013-09-14 04:16+0900\n" --"Last-Translator: Changwoo Ryu \n" --"Language-Team: GNOME Korea \n" --"Language: ko\n" -+"Report-Msgid-Bugs-To: \n" -+"POT-Creation-Date: 2016-02-26 10:16+0530\n" - "MIME-Version: 1.0\n" - "Content-Type: text/plain; charset=UTF-8\n" - "Content-Transfer-Encoding: 8bit\n" -+"PO-Revision-Date: 2013-09-13 07:16+0000\n" -+"Last-Translator: Changwoo Ryu \n" -+"Language-Team: GNOME Korea \n" -+"Language: ko\n" - "Plural-Forms: nplurals=1; plural=0;\n" -+"X-Generator: Zanata 3.8.2\n" - - #: ../capplet/gsm-app-dialog.c:120 - msgid "Select Command" -@@ -45,31 +45,51 @@ - msgid "The startup command is not valid" - msgstr "시작 프로그램이 올바르지 않습니다" - --#: ../capplet/gsm-properties-dialog.c:519 -+#: ../capplet/gsm-properties-dialog.c:493 -+msgid "Your session has been saved." -+msgstr "" -+ -+#: ../capplet/gsm-properties-dialog.c:495 -+#: ../capplet/gsm-properties-dialog.c:521 -+#, fuzzy -+msgid "Failed to save session" -+msgstr "%s 실행 실패\n" -+ -+#: ../capplet/gsm-properties-dialog.c:509 -+#, fuzzy -+msgid "Could not connect to the session bus" -+msgstr "세션 관리자에 연결할 수 없습니다" -+ -+#: ../capplet/gsm-properties-dialog.c:515 ../tools/gnome-session-quit.c:89 -+#: ../tools/gnome-session-quit.c:99 -+msgid "Could not connect to the session manager" -+msgstr "세션 관리자에 연결할 수 없습니다" -+ -+#: ../capplet/gsm-properties-dialog.c:606 - msgid "Enabled" - msgstr "사용하기" - --#: ../capplet/gsm-properties-dialog.c:531 -+#: ../capplet/gsm-properties-dialog.c:618 - msgid "Icon" - msgstr "아이콘" - --#: ../capplet/gsm-properties-dialog.c:543 -+#: ../capplet/gsm-properties-dialog.c:630 - msgid "Program" - msgstr "프로그램" - --#: ../capplet/gsm-properties-dialog.c:747 -+#: ../capplet/gsm-properties-dialog.c:834 - msgid "Startup Applications Preferences" - msgstr "시작 프로그램 기본 설정" - --#: ../capplet/gsp-app.c:276 -+#: ../capplet/gsp-app.c:277 - msgid "No name" - msgstr "이름 없음" - --#: ../capplet/gsp-app.c:282 -+#: ../capplet/gsp-app.c:283 - msgid "No description" - msgstr "설명 없음" - --#: ../capplet/main.c:35 ../gnome-session/main.c:309 -+#: ../capplet/main.c:35 ../gnome-session/main.c:308 - msgid "Version of this application" - msgstr "이 프로그램의 버전" - -@@ -97,11 +117,11 @@ - msgid "GNOME dummy" - msgstr "그놈 더미" - --#: ../data/gnome-session-properties.desktop.in.in.h:1 -+#: ../data/session-properties.desktop.in.in.h:1 - msgid "Startup Applications" - msgstr " 시작 프로그램" - --#: ../data/gnome-session-properties.desktop.in.in.h:2 -+#: ../data/session-properties.desktop.in.in.h:2 - msgid "Choose what applications to start when you log in" - msgstr "로그인할 때 어떤 프로그램을 시작할 지 고릅니다" - -@@ -118,8 +138,9 @@ - msgid "Custom Session" - msgstr "사용자 지정 세션" - --#: ../data/session-selector.ui.h:2 ../tools/gnome-session-selector.c:103 --msgid "Please select a custom session to run" -+#: ../data/session-selector.ui.h:2 -+#, fuzzy -+msgid "Please select a custom session to use" - msgstr "실행할 세션을 직접 지정하십시오" - - #: ../data/session-selector.ui.h:3 -@@ -135,6 +156,10 @@ - msgstr "세션 이름 바꾸기(_M)" - - #: ../data/session-selector.ui.h:6 -+msgid "Classic Experience" -+msgstr "" -+ -+#: ../data/session-selector.ui.h:7 - msgid "_Continue" - msgstr "계속(_C)" - -@@ -174,177 +199,106 @@ - msgid "_Name:" - msgstr "이름(_N):" - --#: ../egg/eggdesktopfile.c:165 --#, c-format --msgid "File is not a valid .desktop file" --msgstr "올바른 .desktop 파일이 아닙니다" -- --#. translators: 'Version' is from a desktop file, and --#. * should not be translated. '%s' would probably be a --#. * version number. --#: ../egg/eggdesktopfile.c:191 --#, c-format --msgid "Unrecognized desktop file Version '%s'" --msgstr "desktop 파일 버전을 ('%s') 인식할 수 없습니다" -- --#: ../egg/eggdesktopfile.c:974 --#, c-format --msgid "Starting %s" --msgstr "%s 시작" -- --#: ../egg/eggdesktopfile.c:1116 --#, c-format --msgid "Application does not accept documents on command line" --msgstr "명령행에서 문서를 지정할 수 없는 프로그램입니다" -- --#: ../egg/eggdesktopfile.c:1184 --#, c-format --msgid "Unrecognized launch option: %d" --msgstr "알 수 없는 실행 옵션: %d" -- --#. translators: The 'Type=Link' string is found in a --#. * desktop file, and should not be translated. --#: ../egg/eggdesktopfile.c:1391 --#, c-format --msgid "Can't pass document URIs to a 'Type=Link' desktop entry" --msgstr "문서 URI는 'Type=Link' desktop 항목에 넘길 수 없습니다" -- --#: ../egg/eggdesktopfile.c:1412 --#, c-format --msgid "Not a launchable item" --msgstr "실행할 수 있는 항목이 없습니다" -- --#: ../egg/eggsmclient.c:226 --msgid "Disable connection to session manager" --msgstr "세션 관리자에 연결하지 않습니다" -- --#: ../egg/eggsmclient.c:229 --msgid "Specify file containing saved configuration" --msgstr "설정을 저장할 파일을 지정합니다" -- --#: ../egg/eggsmclient.c:229 --msgid "FILE" --msgstr "<파일>" -- --#: ../egg/eggsmclient.c:232 --msgid "Specify session management ID" --msgstr "세션 관리 ID를 지정합니다" -- --#: ../egg/eggsmclient.c:232 --msgid "ID" --msgstr "" -- --#: ../egg/eggsmclient.c:253 --msgid "Session management options:" --msgstr "세션 관리 옵션:" -- --#: ../egg/eggsmclient.c:254 --msgid "Show session management options" --msgstr "세션 관리 옵션을 표시합니다" -- --#: ../gnome-session/gsm-fail-whale-dialog.c:295 -+#: ../gnome-session/gsm-fail-whale-dialog.c:321 - msgid "Oh no! Something has gone wrong." - msgstr "아, 뭔가 문제가 생겼습니다." - --#: ../gnome-session/gsm-fail-whale-dialog.c:302 -+#: ../gnome-session/gsm-fail-whale-dialog.c:328 - msgid "" - "A problem has occurred and the system can't recover. Please contact a system " - "administrator" - msgstr "문제가 발생했지만 복구하지 못했습니다. 시스템 관리자에게 문의하십시오" - --#: ../gnome-session/gsm-fail-whale-dialog.c:304 -+#: ../gnome-session/gsm-fail-whale-dialog.c:330 - msgid "" - "A problem has occurred and the system can't recover. All extensions have " - "been disabled as a precaution." --msgstr "" --"문제가 발생했지만 복구하지 못했습니다. 안전을 위해 모든 확장 기능을 사용하지 " --"않도록 만듭니다." -+msgstr "문제가 발생했지만 복구하지 못했습니다. 안전을 위해 모든 확장 기능을 사용하지 않도록 만듭니다." - --#: ../gnome-session/gsm-fail-whale-dialog.c:306 -+#: ../gnome-session/gsm-fail-whale-dialog.c:332 - msgid "" - "A problem has occurred and the system can't recover.\n" - "Please log out and try again." --msgstr "" --"문제가 발생했지만 복구하지 못했습니다.\n" -+msgstr "문제가 발생했지만 복구하지 못했습니다.\n" - "로그아웃하고 다시 시도하십시오." - --#: ../gnome-session/gsm-fail-whale-dialog.c:321 -+#: ../gnome-session/gsm-fail-whale-dialog.c:347 - msgid "_Log Out" - msgstr "로그아웃(_L)" - --#: ../gnome-session/gsm-fail-whale-dialog.c:343 ../gnome-session/main.c:307 -+#: ../gnome-session/gsm-fail-whale-dialog.c:369 ../gnome-session/main.c:306 - msgid "Enable debugging code" - msgstr "디버깅 코드를 사용합니다" - --#: ../gnome-session/gsm-fail-whale-dialog.c:344 -+#: ../gnome-session/gsm-fail-whale-dialog.c:370 - msgid "Allow logout" - msgstr "로그아웃 허용" - --#: ../gnome-session/gsm-fail-whale-dialog.c:345 -+#: ../gnome-session/gsm-fail-whale-dialog.c:371 - msgid "Show extension warning" - msgstr "확장 경고 표시" - --#: ../gnome-session/gsm-manager.c:1271 ../gnome-session/gsm-manager.c:2043 -+#: ../gnome-session/gsm-manager.c:1370 ../gnome-session/gsm-manager.c:2192 - msgid "Not responding" - msgstr "응답 없음" - --#: ../gnome-session/gsm-util.c:411 -+#: ../gnome-session/gsm-util.c:382 - msgid "_Log out" - msgstr "로그아웃(_L)" - - #. It'd be really surprising to reach this code: if we're here, - #. * then the XSMP client already has set several XSMP - #. * properties. But it could still be that SmProgram is not set. --#. --#: ../gnome-session/gsm-xsmp-client.c:559 -+#. -+#: ../gnome-session/gsm-xsmp-client.c:582 - msgid "Remembered Application" - msgstr "기억한 프로그램" - --#: ../gnome-session/gsm-xsmp-client.c:1209 -+#: ../gnome-session/gsm-xsmp-client.c:1244 - msgid "This program is blocking logout." - msgstr "이 프로그램이 로그아웃을 막고 있습니다." - --#: ../gnome-session/gsm-xsmp-server.c:341 -+#: ../gnome-session/gsm-xsmp-server.c:340 - msgid "" - "Refusing new client connection because the session is currently being shut " - "down\n" - msgstr "지금 세션을 끝내는 중이므로 새 클라이언트 연결을 거부합니다.\n" - --#: ../gnome-session/gsm-xsmp-server.c:610 -+#: ../gnome-session/gsm-xsmp-server.c:609 - #, c-format - msgid "Could not create ICE listening socket: %s" - msgstr "ICE 리스닝 소켓을 만들 수 없습니다: %s" - --#: ../gnome-session/main.c:305 -+#: ../gnome-session/main.c:304 - msgid "Override standard autostart directories" - msgstr "기본 자동 시작 디렉토리 대신 사용합니다" - --#: ../gnome-session/main.c:305 -+#: ../gnome-session/main.c:304 - msgid "AUTOSTART_DIR" - msgstr "<자동시작_폴더>" - --#: ../gnome-session/main.c:306 -+#: ../gnome-session/main.c:305 - msgid "Session to use" - msgstr "사용할 세션" - --#: ../gnome-session/main.c:306 -+#: ../gnome-session/main.c:305 - msgid "SESSION_NAME" - msgstr "<세션_이름>" - --#: ../gnome-session/main.c:308 -+#: ../gnome-session/main.c:307 - msgid "Do not load user-specified applications" - msgstr "사용자가 지정한 프로그램을 읽어들이지 않습니다" - - #. Translators: the 'fail whale' is the black dialog we show when something goes seriously wrong --#: ../gnome-session/main.c:311 -+#: ../gnome-session/main.c:310 - msgid "Show the fail whale dialog for testing" - msgstr "테스트 용도로 고래 표시" - --#: ../gnome-session/main.c:344 -+#: ../gnome-session/main.c:343 - msgid " - the GNOME session manager" - msgstr "- 그놈 세션 관리자" - --#: ../tools/gnome-session-inhibit.c:110 -+#: ../tools/gnome-session-inhibit.c:108 - #, c-format - msgid "" - "%s [OPTION...] COMMAND\n" -@@ -376,64 +330,82 @@ - "\n" - "--inhibit 옵션을 지정하지 않았다면, 입력 없음 기능만 금지합니다.\n" - --#: ../tools/gnome-session-inhibit.c:148 -+#: ../tools/gnome-session-inhibit.c:146 - #, c-format - msgid "Failed to execute %s\n" - msgstr "%s 실행 실패\n" - --#: ../tools/gnome-session-inhibit.c:208 ../tools/gnome-session-inhibit.c:218 --#: ../tools/gnome-session-inhibit.c:228 -+#: ../tools/gnome-session-inhibit.c:206 ../tools/gnome-session-inhibit.c:216 -+#: ../tools/gnome-session-inhibit.c:226 - #, c-format - msgid "%s requires an argument\n" - msgstr "%s requires an argument\n" - --#: ../tools/gnome-session-selector.c:62 -+#: ../tools/gnome-session-selector.c:71 - #, c-format - msgid "Session %d" - msgstr "세션 %d" - --#: ../tools/gnome-session-selector.c:108 -+#: ../tools/gnome-session-selector.c:115 - msgid "" - "Session names are not allowed to start with ‘.’ or contain ‘/’ characters" - msgstr "'.'으로 시작하거나 '/'가 들어간 세션 이름은 허용하지 않습니다" - --#: ../tools/gnome-session-selector.c:112 -+#: ../tools/gnome-session-selector.c:119 - msgid "Session names are not allowed to start with ‘.’" - msgstr "'.'으로 시작하는 세션 이름은 허용하지 않습니다" - --#: ../tools/gnome-session-selector.c:116 -+#: ../tools/gnome-session-selector.c:123 - msgid "Session names are not allowed to contain ‘/’ characters" - msgstr "'/'가 들어간 세션 이름은 허용하지 않습니다" - --#: ../tools/gnome-session-selector.c:124 -+#: ../tools/gnome-session-selector.c:131 - #, c-format - msgid "A session named ‘%s’ already exists" - msgstr "이름이 '%s'인 세션이 이미 있습니다" - --#: ../tools/gnome-session-quit.c:53 -+#: ../tools/gnome-session-selector.c:794 -+msgid "What to do with session selection (save|load|print)" -+msgstr "" -+ -+#: ../tools/gnome-session-selector.c:795 -+msgid "[session-name]" -+msgstr "" -+ -+#: ../tools/gnome-session-selector.c:889 -+msgid "Please select a custom session to run" -+msgstr "실행할 세션을 직접 지정하십시오" -+ -+#: ../tools/gnome-session-selector.c:891 -+#, fuzzy -+msgid "Please select a session to use" -+msgstr "실행할 세션을 직접 지정하십시오" -+ -+#: ../tools/gnome-session-selector.c:893 -+#, fuzzy -+msgid "Please select a session to save to" -+msgstr "실행할 세션을 직접 지정하십시오" -+ -+#: ../tools/gnome-session-quit.c:51 - msgid "Log out" - msgstr "로그아웃" - --#: ../tools/gnome-session-quit.c:54 -+#: ../tools/gnome-session-quit.c:52 - msgid "Power off" - msgstr "전원 끄기" - --#: ../tools/gnome-session-quit.c:55 -+#: ../tools/gnome-session-quit.c:53 - msgid "Reboot" - msgstr "다시 시작" - --#: ../tools/gnome-session-quit.c:56 -+#: ../tools/gnome-session-quit.c:54 - msgid "Ignoring any existing inhibitors" - msgstr "금지하는 프로그램이 있어도 무시" - --#: ../tools/gnome-session-quit.c:57 -+#: ../tools/gnome-session-quit.c:55 - msgid "Don't prompt for user confirmation" - msgstr "사용자 확인 질문을 하지 않기" - --#: ../tools/gnome-session-quit.c:91 ../tools/gnome-session-quit.c:101 --msgid "Could not connect to the session manager" --msgstr "세션 관리자에 연결할 수 없습니다" -- --#: ../tools/gnome-session-quit.c:203 -+#: ../tools/gnome-session-quit.c:201 - msgid "Program called with conflicting options" - msgstr "함께 사용할 수 없는 옵션을 같이 사용했습니다" -diff -urN gnome-session-3.14.0/po/pt_BR.po gnome-session-3.14.0_localized/po/pt_BR.po ---- gnome-session-3.14.0/po/pt_BR.po 2014-06-25 23:36:34.000000000 +0530 -+++ gnome-session-3.14.0_localized/po/pt_BR.po 2016-03-14 19:41:08.944245189 +0530 -@@ -14,22 +14,22 @@ - # André Gondim , 2009. - # Flamarion Jorge , 2011. - # Enrico Nicoletto , 2013. --# -+# msuppesd , 2016. #zanata -+# pnemade , 2016. #zanata - msgid "" - msgstr "" - "Project-Id-Version: gnome-session\n" --"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" --"session&keywords=I18N+L10N&component=general\n" --"POT-Creation-Date: 2013-09-18 14:27+0000\n" --"PO-Revision-Date: 2013-09-18 15:27-0300\n" --"Last-Translator: Antonio Fernandes C. Neto \n" --"Language-Team: Brazilian Portuguese \n" --"Language: pt_BR\n" -+"Report-Msgid-Bugs-To: \n" -+"POT-Creation-Date: 2016-02-26 10:16+0530\n" - "MIME-Version: 1.0\n" - "Content-Type: text/plain; charset=UTF-8\n" - "Content-Transfer-Encoding: 8bit\n" -+"PO-Revision-Date: 2016-03-09 08:53+0000\n" -+"Last-Translator: msuppesd \n" -+"Language-Team: Brazilian Portuguese \n" -+"Language: pt-BR\n" - "Plural-Forms: nplurals=2; plural=(n > 1);\n" --"X-Generator: Poedit 1.5.7\n" -+"X-Generator: Zanata 3.8.2\n" - "X-Project-Style: gnome\n" - - #: ../capplet/gsm-app-dialog.c:120 -@@ -52,31 +52,49 @@ - msgid "The startup command is not valid" - msgstr "O comando inicial não é válido" - --#: ../capplet/gsm-properties-dialog.c:519 -+#: ../capplet/gsm-properties-dialog.c:493 -+msgid "Your session has been saved." -+msgstr "Sua sessão foi salva." -+ -+#: ../capplet/gsm-properties-dialog.c:495 -+#: ../capplet/gsm-properties-dialog.c:521 -+msgid "Failed to save session" -+msgstr "Falha ao salvar a sessão" -+ -+#: ../capplet/gsm-properties-dialog.c:509 -+msgid "Could not connect to the session bus" -+msgstr "Não foi possível conectar ao barramento de sessão" -+ -+#: ../capplet/gsm-properties-dialog.c:515 ../tools/gnome-session-quit.c:89 -+#: ../tools/gnome-session-quit.c:99 -+msgid "Could not connect to the session manager" -+msgstr "Não foi possível conectar ao gerenciador de sessões" -+ -+#: ../capplet/gsm-properties-dialog.c:606 - msgid "Enabled" - msgstr "Habilitado" - --#: ../capplet/gsm-properties-dialog.c:531 -+#: ../capplet/gsm-properties-dialog.c:618 - msgid "Icon" - msgstr "Ícone" - --#: ../capplet/gsm-properties-dialog.c:543 -+#: ../capplet/gsm-properties-dialog.c:630 - msgid "Program" - msgstr "Programa" - --#: ../capplet/gsm-properties-dialog.c:747 -+#: ../capplet/gsm-properties-dialog.c:834 - msgid "Startup Applications Preferences" - msgstr "Preferências dos aplicativos iniciais de sessão" - --#: ../capplet/gsp-app.c:276 -+#: ../capplet/gsp-app.c:277 - msgid "No name" - msgstr "Sem nome" - --#: ../capplet/gsp-app.c:282 -+#: ../capplet/gsp-app.c:283 - msgid "No description" - msgstr "Nenhuma descrição" - --#: ../capplet/main.c:35 ../gnome-session/main.c:309 -+#: ../capplet/main.c:35 ../gnome-session/main.c:308 - msgid "Version of this application" - msgstr "Versão deste aplicativo" - -@@ -106,11 +124,11 @@ - msgid "GNOME dummy" - msgstr "GNOME experimental" - --#: ../data/gnome-session-properties.desktop.in.in.h:1 -+#: ../data/session-properties.desktop.in.in.h:1 - msgid "Startup Applications" - msgstr "Aplicativos iniciais de sessão" - --#: ../data/gnome-session-properties.desktop.in.in.h:2 -+#: ../data/session-properties.desktop.in.in.h:2 - msgid "Choose what applications to start when you log in" - msgstr "" - "Escolha quais os aplicativos que irão iniciar quando sua sessão iniciar" -@@ -129,9 +147,9 @@ - msgid "Custom Session" - msgstr "Sessão personalizada" - --#: ../data/session-selector.ui.h:2 ../tools/gnome-session-selector.c:103 --msgid "Please select a custom session to run" --msgstr "Por gentileza selecione uma sessão personalizada a ser executada" -+#: ../data/session-selector.ui.h:2 -+msgid "Please select a custom session to use" -+msgstr "Por favor, selecione uma sessão personalizada para ser usada" - - #: ../data/session-selector.ui.h:3 - msgid "_New Session" -@@ -146,6 +164,10 @@ - msgstr "Reno_mear sessão" - - #: ../data/session-selector.ui.h:6 -+msgid "Classic Experience" -+msgstr "Experiência Clássica" -+ -+#: ../data/session-selector.ui.h:7 - msgid "_Continue" - msgstr "_Continuar" - -@@ -186,81 +208,11 @@ - msgid "_Name:" - msgstr "_Nome:" - --#: ../egg/eggdesktopfile.c:165 --#, c-format --msgid "File is not a valid .desktop file" --msgstr "O arquivo não é um arquivo .desktop válido" -- --#. translators: 'Version' is from a desktop file, and --#. * should not be translated. '%s' would probably be a --#. * version number. --#: ../egg/eggdesktopfile.c:191 --#, c-format --msgid "Unrecognized desktop file Version '%s'" --msgstr "Versão do arquivo da área de trabalho \"%s\" não reconhecida" -- --#: ../egg/eggdesktopfile.c:974 --#, c-format --msgid "Starting %s" --msgstr "Iniciando %s" -- --#: ../egg/eggdesktopfile.c:1116 --#, c-format --msgid "Application does not accept documents on command line" --msgstr "O aplicativo não aceita documentos na linha de comando" -- --#: ../egg/eggdesktopfile.c:1184 --#, c-format --msgid "Unrecognized launch option: %d" --msgstr "Opção de lançamento não reconhecida: %d" -- --#. translators: The 'Type=Link' string is found in a --#. * desktop file, and should not be translated. --#: ../egg/eggdesktopfile.c:1391 --#, c-format --msgid "Can't pass document URIs to a 'Type=Link' desktop entry" --msgstr "" --"Não foi possível passar as URIs dos documentos para uma entrada de área de " --"trabalho 'Type=Link'" -- --#: ../egg/eggdesktopfile.c:1412 --#, c-format --msgid "Not a launchable item" --msgstr "Não é um item lançável" -- --#: ../egg/eggsmclient.c:226 --msgid "Disable connection to session manager" --msgstr "Desabilitar conexão para o gerenciador de sessões" -- --#: ../egg/eggsmclient.c:229 --msgid "Specify file containing saved configuration" --msgstr "Especificar o arquivo que contém a configuração salva" -- --#: ../egg/eggsmclient.c:229 --msgid "FILE" --msgstr "ARQUIVO" -- --#: ../egg/eggsmclient.c:232 --msgid "Specify session management ID" --msgstr "Especificar o ID de gerenciamento de sessão" -- --#: ../egg/eggsmclient.c:232 --msgid "ID" --msgstr "ID" -- --#: ../egg/eggsmclient.c:253 --msgid "Session management options:" --msgstr "Opções de gerenciamento de sessão:" -- --#: ../egg/eggsmclient.c:254 --msgid "Show session management options" --msgstr "Mostra as opções de gerenciamento de sessão" -- --#: ../gnome-session/gsm-fail-whale-dialog.c:295 -+#: ../gnome-session/gsm-fail-whale-dialog.c:321 - msgid "Oh no! Something has gone wrong." - msgstr "Oh não! Alguma coisa está errada." - --#: ../gnome-session/gsm-fail-whale-dialog.c:302 -+#: ../gnome-session/gsm-fail-whale-dialog.c:328 - msgid "" - "A problem has occurred and the system can't recover. Please contact a system " - "administrator" -@@ -268,7 +220,7 @@ - "Ocorreu um problema e o sistema não pôde ser recuperado. Por favor, entre em " - "contato com um administrador de sistemas" - --#: ../gnome-session/gsm-fail-whale-dialog.c:304 -+#: ../gnome-session/gsm-fail-whale-dialog.c:330 - msgid "" - "A problem has occurred and the system can't recover. All extensions have " - "been disabled as a precaution." -@@ -276,7 +228,7 @@ - "Ocorreu um problema e o sistema não pôde ser recuperado. Todas as extensões " - "foram desativadas por precaução." - --#: ../gnome-session/gsm-fail-whale-dialog.c:306 -+#: ../gnome-session/gsm-fail-whale-dialog.c:332 - msgid "" - "A problem has occurred and the system can't recover.\n" - "Please log out and try again." -@@ -284,43 +236,43 @@ - "Ocorreu um problema e o sistema não pôde ser recuperado.\n" - "Por favor encerre a sessão e tente novamente." - --#: ../gnome-session/gsm-fail-whale-dialog.c:321 -+#: ../gnome-session/gsm-fail-whale-dialog.c:347 - msgid "_Log Out" - msgstr "_Encerrar sessão" - --#: ../gnome-session/gsm-fail-whale-dialog.c:343 ../gnome-session/main.c:307 -+#: ../gnome-session/gsm-fail-whale-dialog.c:369 ../gnome-session/main.c:306 - msgid "Enable debugging code" - msgstr "Habilitar código de depuração" - --#: ../gnome-session/gsm-fail-whale-dialog.c:344 -+#: ../gnome-session/gsm-fail-whale-dialog.c:370 - msgid "Allow logout" - msgstr "Permitir encerramento de sessão" - --#: ../gnome-session/gsm-fail-whale-dialog.c:345 -+#: ../gnome-session/gsm-fail-whale-dialog.c:371 - msgid "Show extension warning" - msgstr "Mostrar alerta de extensão" - --#: ../gnome-session/gsm-manager.c:1271 ../gnome-session/gsm-manager.c:2043 -+#: ../gnome-session/gsm-manager.c:1370 ../gnome-session/gsm-manager.c:2192 - msgid "Not responding" - msgstr "Não respondendo" - --#: ../gnome-session/gsm-util.c:411 -+#: ../gnome-session/gsm-util.c:382 - msgid "_Log out" - msgstr "_Encerrar sessão" - - #. It'd be really surprising to reach this code: if we're here, - #. * then the XSMP client already has set several XSMP - #. * properties. But it could still be that SmProgram is not set. --#. --#: ../gnome-session/gsm-xsmp-client.c:559 -+#. -+#: ../gnome-session/gsm-xsmp-client.c:582 - msgid "Remembered Application" - msgstr "Lembrar dos aplicativos" - --#: ../gnome-session/gsm-xsmp-client.c:1209 -+#: ../gnome-session/gsm-xsmp-client.c:1244 - msgid "This program is blocking logout." - msgstr "Este programa está bloqueando o encerramento da sessão." - --#: ../gnome-session/gsm-xsmp-server.c:341 -+#: ../gnome-session/gsm-xsmp-server.c:340 - msgid "" - "Refusing new client connection because the session is currently being shut " - "down\n" -@@ -328,42 +280,42 @@ - "Recusando a nova conexão do cliente porque a sessão está sendo desligada " - "neste momento\n" - --#: ../gnome-session/gsm-xsmp-server.c:610 -+#: ../gnome-session/gsm-xsmp-server.c:609 - #, c-format - msgid "Could not create ICE listening socket: %s" - msgstr "Não foi possível criar o soquete de escuta ICE: %s" - --#: ../gnome-session/main.c:305 -+#: ../gnome-session/main.c:304 - msgid "Override standard autostart directories" - msgstr "Substituir os diretórios padrões de início automático" - --#: ../gnome-session/main.c:305 -+#: ../gnome-session/main.c:304 - msgid "AUTOSTART_DIR" - msgstr "AUTOSTART_DIR" - --#: ../gnome-session/main.c:306 -+#: ../gnome-session/main.c:305 - msgid "Session to use" - msgstr "Sessões para usar" - --#: ../gnome-session/main.c:306 -+#: ../gnome-session/main.c:305 - msgid "SESSION_NAME" - msgstr "SESSION_NAME" - --#: ../gnome-session/main.c:308 -+#: ../gnome-session/main.c:307 - msgid "Do not load user-specified applications" - msgstr "Não carregar aplicativos especificados pelo usuário" - - # Translators: the 'fail whale' is the black dialog we show when something goes seriously wrong. http://is.gd/Q4XOeq - #. Translators: the 'fail whale' is the black dialog we show when something goes seriously wrong --#: ../gnome-session/main.c:311 -+#: ../gnome-session/main.c:310 - msgid "Show the fail whale dialog for testing" - msgstr "Mostrar o diálogo da \"falha da baleia\" para teste" - --#: ../gnome-session/main.c:344 -+#: ../gnome-session/main.c:343 - msgid " - the GNOME session manager" - msgstr " - gerenciador de sessões do GNOME" - --#: ../tools/gnome-session-inhibit.c:110 -+#: ../tools/gnome-session-inhibit.c:108 - #, c-format - msgid "" - "%s [OPTION...] COMMAND\n" -@@ -397,195 +349,82 @@ - "\n" - "Se nenhuma opção --inhibit for especificada, assume-se como ocioso (idle).\n" - --#: ../tools/gnome-session-inhibit.c:148 -+#: ../tools/gnome-session-inhibit.c:146 - #, c-format - msgid "Failed to execute %s\n" - msgstr "Ocorreu falha ao executar %s\n" - --#: ../tools/gnome-session-inhibit.c:208 ../tools/gnome-session-inhibit.c:218 --#: ../tools/gnome-session-inhibit.c:228 -+#: ../tools/gnome-session-inhibit.c:206 ../tools/gnome-session-inhibit.c:216 -+#: ../tools/gnome-session-inhibit.c:226 - #, c-format - msgid "%s requires an argument\n" - msgstr "%s requer um argumento\n" - --#: ../tools/gnome-session-selector.c:62 -+#: ../tools/gnome-session-selector.c:71 - #, c-format - msgid "Session %d" - msgstr "Sessão %d" - --#: ../tools/gnome-session-selector.c:108 -+#: ../tools/gnome-session-selector.c:115 - msgid "" - "Session names are not allowed to start with ‘.’ or contain ‘/’ characters" - msgstr "" - "Não são permitidos a nomes de sessões iniciarem com \".\" ou conterem " - "caracteres \"/\"" - --#: ../tools/gnome-session-selector.c:112 -+#: ../tools/gnome-session-selector.c:119 - msgid "Session names are not allowed to start with ‘.’" - msgstr "Não são permitidos a nomes de sessões iniciarem com \".\"" - --#: ../tools/gnome-session-selector.c:116 -+#: ../tools/gnome-session-selector.c:123 - msgid "Session names are not allowed to contain ‘/’ characters" - msgstr "Não são permitidos a nomes de sessões conterem caracteres \"/\"" - --#: ../tools/gnome-session-selector.c:124 -+#: ../tools/gnome-session-selector.c:131 - #, c-format - msgid "A session named ‘%s’ already exists" - msgstr "Uma sessão com nome \"%s\" já existe" - --#: ../tools/gnome-session-quit.c:53 -+#: ../tools/gnome-session-selector.c:794 -+msgid "What to do with session selection (save|load|print)" -+msgstr "O que fazer com a seleção de seções (salvar|carregar|imprimir)" -+ -+#: ../tools/gnome-session-selector.c:795 -+msgid "[session-name]" -+msgstr "[session-name]" -+ -+#: ../tools/gnome-session-selector.c:889 -+msgid "Please select a custom session to run" -+msgstr "Por gentileza selecione uma sessão personalizada a ser executada" -+ -+#: ../tools/gnome-session-selector.c:891 -+msgid "Please select a session to use" -+msgstr "Por favor, selecione uma sessão para ser usada" -+ -+#: ../tools/gnome-session-selector.c:893 -+msgid "Please select a session to save to" -+msgstr "Por favor, selecione uma sessão a ser salva " -+ -+#: ../tools/gnome-session-quit.c:51 - msgid "Log out" - msgstr "Encerrar sessão" - --#: ../tools/gnome-session-quit.c:54 -+#: ../tools/gnome-session-quit.c:52 - msgid "Power off" - msgstr "Desligar" - --#: ../tools/gnome-session-quit.c:55 -+#: ../tools/gnome-session-quit.c:53 - msgid "Reboot" - msgstr "Reiniciar" - --#: ../tools/gnome-session-quit.c:56 -+#: ../tools/gnome-session-quit.c:54 - msgid "Ignoring any existing inhibitors" - msgstr "Ignorar qualquer um inibidor existente" - --#: ../tools/gnome-session-quit.c:57 -+#: ../tools/gnome-session-quit.c:55 - msgid "Don't prompt for user confirmation" - msgstr "Não pedir configuração do usuário" - --#: ../tools/gnome-session-quit.c:91 ../tools/gnome-session-quit.c:101 --msgid "Could not connect to the session manager" --msgstr "Não foi possível conectar ao gerenciador de sessões" -- --#: ../tools/gnome-session-quit.c:203 -+#: ../tools/gnome-session-quit.c:201 - msgid "Program called with conflicting options" - msgstr "Programa chamado com opções conflitantes" -- --#~ msgid "Some programs are still running:" --#~ msgstr "Alguns programas ainda estão em execução:" -- --#~ msgid "Unknown" --#~ msgstr "Desconhecido" -- --#~ msgid "A program is still running:" --#~ msgstr "Um programa ainda está em execução:" -- --#~ msgid "" --#~ "Waiting for the program to finish. Interrupting the program may cause you " --#~ "to lose work." --#~ msgstr "" --#~ "Aguardando o programa para finalizar. Interromper este programa pode " --#~ "ocasionar em perda de trabalho." -- --#~ msgid "" --#~ "Waiting for programs to finish. Interrupting these programs may cause you " --#~ "to lose work." --#~ msgstr "" --#~ "Aguardando os programas para finalizar. Interromper estes programas pode " --#~ "ocasionar em perda de trabalho." -- --#~ msgid "Switch User Anyway" --#~ msgstr "Trocar usuário mesmo assim" -- --#~ msgid "Log Out Anyway" --#~ msgstr "Encerrar mesmo assim" -- --#~ msgid "Suspend Anyway" --#~ msgstr "Suspender mesmo assim" -- --#~ msgid "Hibernate Anyway" --#~ msgstr "Hibernar mesmo assim" -- --#~ msgid "Shut Down Anyway" --#~ msgstr "Desligar mesmo assim" -- --#~ msgid "Restart Anyway" --#~ msgstr "Reiniciar mesmo assim" -- --#~ msgid "Lock Screen" --#~ msgstr "Bloquear tela" -- --#~ msgid "Cancel" --#~ msgstr "Cancelar" -- --#~ msgid "You will be automatically logged out in %d second." --#~ msgid_plural "You will be automatically logged out in %d seconds." --#~ msgstr[0] "Essa sessão será encerrada automaticamente em %d segundo." --#~ msgstr[1] "Essa sessão será encerrada automaticamente em %d segundos." -- --#~ msgid "This system will be automatically shut down in %d second." --#~ msgid_plural "This system will be automatically shut down in %d seconds." --#~ msgstr[0] "Este sistema será automaticamente desligado em %d segundo." --#~ msgstr[1] "Este sistema será automaticamente desligado em %d segundos." -- --#~ msgid "This system will be automatically restarted in %d second." --#~ msgid_plural "This system will be automatically restarted in %d seconds." --#~ msgstr[0] "Este sistema será automaticamente reiniciado em %d segundo." --#~ msgstr[1] "Este sistema será automaticamente reiniciado em %d segundos." -- --#~ msgid "You are currently logged in as \"%s\"." --#~ msgstr "Você está logado atualmente como \"%s\"." -- --#~ msgid "Log out of this system now?" --#~ msgstr "Encerrar a sessão deste sistema agora?" -- --#~ msgid "_Switch User" --#~ msgstr "_Trocar usuário" -- --#~ msgid "Shut down this system now?" --#~ msgstr "Desligar este sistema agora?" -- --#~ msgid "S_uspend" --#~ msgstr "S_uspender" -- --#~ msgid "_Hibernate" --#~ msgstr "_Hibernar" -- --#~ msgid "_Restart" --#~ msgstr "_Reiniciar" -- --#~ msgid "_Shut Down" --#~ msgstr "_Desligar" -- --#~ msgid "Restart this system now?" --#~ msgstr "Reiniciar este sistema agora?" -- --#~ msgid "Icon '%s' not found" --#~ msgstr "Ícone \"%s\" não localizado" -- --#~ msgid "GNOME 3 Failed to Load" --#~ msgstr "Falha ao carregar o GNOME 3" -- --#~ msgid "" --#~ "Unfortunately GNOME 3 failed to start properly and started in the " --#~ "fallback mode.\n" --#~ "\n" --#~ "This most likely means your system (graphics hardware or driver) is not " --#~ "capable of delivering the full GNOME 3 experience." --#~ msgstr "" --#~ "Infelizmente o GNOME 3 falhou ao inicializar corretamente e inicializou " --#~ "em modo reserva.\n" --#~ "\n" --#~ "Isto provavelmente significa que o seu sistema (hardware de gráficos ou " --#~ "driver) não é capaz de obter a experiência completa do GNOME 3." -- --#~ msgid "Learn more about GNOME 3" --#~ msgstr "Aprender mais sobre o GNOME 3" -- --#~ msgid "" --#~ "Unable to start login session (and unable to connect to the X server)" --#~ msgstr "" --#~ "Não foi possível iniciar a sessão de login (e não foi possível conectar " --#~ "ao servidor X)" -- --#~ msgid "Exited with code %d" --#~ msgstr "Saiu com o código %d" -- --#~ msgid "Killed by signal %d" --#~ msgstr "Morto pelo sinal %d" -- --#~ msgid "Stopped by signal %d" --#~ msgstr "Parado pelo sinal %d" -- --#~ msgid "Some programs are still running:" --#~ msgstr "Alguns programas ainda estão em execução:" -diff -urN gnome-session-3.14.0/po/ru.po gnome-session-3.14.0_localized/po/ru.po ---- gnome-session-3.14.0/po/ru.po 2014-06-25 23:36:34.000000000 +0530 -+++ gnome-session-3.14.0_localized/po/ru.po 2016-03-14 19:41:08.950245184 +0530 -@@ -1,6 +1,6 @@ - # translation of gnome-session to Russian - # Copyright (C) 1998-2002, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. --# -+# - # Max Valianskiy , 1998-1999. - # Sergey Panov , 1999. - # Valek Filippov , 2000-2002. -@@ -8,23 +8,23 @@ - # Leonid Kanter , 2004, 2005, 2006, 2007, 2008. - # Anisimov Victor , 2009. - # Yuri Myasoedov , 2013. --# -+# pnemade , 2016. #zanata -+# ypoyarko , 2016. #zanata - msgid "" - msgstr "" - "Project-Id-Version: ru\n" --"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" --"session&keywords=I18N+L10N&component=general\n" --"POT-Creation-Date: 2013-09-10 13:37+0000\n" --"PO-Revision-Date: 2013-09-10 20:09+0600\n" --"Last-Translator: Dmitriy S. Seregin \n" --"Language-Team: русский \n" --"Language: ru\n" -+"Report-Msgid-Bugs-To: \n" -+"POT-Creation-Date: 2016-02-26 10:16+0530\n" - "MIME-Version: 1.0\n" - "Content-Type: text/plain; charset=UTF-8\n" - "Content-Transfer-Encoding: 8bit\n" --"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" --"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" --"X-Generator: Poedit 1.5.7\n" -+"PO-Revision-Date: 2016-03-07 06:37+0000\n" -+"Last-Translator: ypoyarko \n" -+"Language-Team: русский \n" -+"Language: ru\n" -+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && " -+"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -+"X-Generator: Zanata 3.8.2\n" - - #: ../capplet/gsm-app-dialog.c:120 - msgid "Select Command" -@@ -46,31 +46,49 @@ - msgid "The startup command is not valid" - msgstr "Некорректная команда запуска" - --#: ../capplet/gsm-properties-dialog.c:519 -+#: ../capplet/gsm-properties-dialog.c:493 -+msgid "Your session has been saved." -+msgstr "Ваш сеанс был сохранен." -+ -+#: ../capplet/gsm-properties-dialog.c:495 -+#: ../capplet/gsm-properties-dialog.c:521 -+msgid "Failed to save session" -+msgstr "Не удалось сохранить сеанс" -+ -+#: ../capplet/gsm-properties-dialog.c:509 -+msgid "Could not connect to the session bus" -+msgstr "Не удалось подключиться к шине сеансов" -+ -+#: ../capplet/gsm-properties-dialog.c:515 ../tools/gnome-session-quit.c:89 -+#: ../tools/gnome-session-quit.c:99 -+msgid "Could not connect to the session manager" -+msgstr "Не удалось соединиться с менеджером сеансов" -+ -+#: ../capplet/gsm-properties-dialog.c:606 - msgid "Enabled" - msgstr "Включено" - --#: ../capplet/gsm-properties-dialog.c:531 -+#: ../capplet/gsm-properties-dialog.c:618 - msgid "Icon" - msgstr "Значок" - --#: ../capplet/gsm-properties-dialog.c:543 -+#: ../capplet/gsm-properties-dialog.c:630 - msgid "Program" - msgstr "Программа" - --#: ../capplet/gsm-properties-dialog.c:747 -+#: ../capplet/gsm-properties-dialog.c:834 - msgid "Startup Applications Preferences" - msgstr "Настройки запуска приложений" - --#: ../capplet/gsp-app.c:276 -+#: ../capplet/gsp-app.c:277 - msgid "No name" - msgstr "Нет имени" - --#: ../capplet/gsp-app.c:282 -+#: ../capplet/gsp-app.c:283 - msgid "No description" - msgstr "Нет описания" - --#: ../capplet/main.c:35 ../gnome-session/main.c:309 -+#: ../capplet/main.c:35 ../gnome-session/main.c:308 - msgid "Version of this application" - msgstr "Версия этого приложения" - -@@ -98,11 +116,11 @@ - msgid "GNOME dummy" - msgstr "Фиктивный сеанс GNOME" - --#: ../data/gnome-session-properties.desktop.in.in.h:1 -+#: ../data/session-properties.desktop.in.in.h:1 - msgid "Startup Applications" - msgstr "Запускаемые приложения" - --#: ../data/gnome-session-properties.desktop.in.in.h:2 -+#: ../data/session-properties.desktop.in.in.h:2 - msgid "Choose what applications to start when you log in" - msgstr "Выберите приложения, запускаемые при входе в систему" - -@@ -119,9 +137,9 @@ - msgid "Custom Session" - msgstr "Другой сеанс" - --#: ../data/session-selector.ui.h:2 ../tools/gnome-session-selector.c:103 --msgid "Please select a custom session to run" --msgstr "Выберите сеанс для запуска" -+#: ../data/session-selector.ui.h:2 -+msgid "Please select a custom session to use" -+msgstr "Выберите сеанс" - - #: ../data/session-selector.ui.h:3 - msgid "_New Session" -@@ -136,6 +154,10 @@ - msgstr "П_ереименовать сеанс" - - #: ../data/session-selector.ui.h:6 -+msgid "Classic Experience" -+msgstr "Классический" -+ -+#: ../data/session-selector.ui.h:7 - msgid "_Continue" - msgstr "_Продолжить" - -@@ -175,79 +197,11 @@ - msgid "_Name:" - msgstr "_Имя:" - --#: ../egg/eggdesktopfile.c:165 --#, c-format --msgid "File is not a valid .desktop file" --msgstr "Файл не является правильным desktop-файлом" -- --#. translators: 'Version' is from a desktop file, and --#. * should not be translated. '%s' would probably be a --#. * version number. --#: ../egg/eggdesktopfile.c:191 --#, c-format --msgid "Unrecognized desktop file Version '%s'" --msgstr "Нераспознанная версия desktop-файла «%s»" -- --#: ../egg/eggdesktopfile.c:974 --#, c-format --msgid "Starting %s" --msgstr "Запускается «%s»" -- --#: ../egg/eggdesktopfile.c:1116 --#, c-format --msgid "Application does not accept documents on command line" --msgstr "Приложение не принимает документы, указанные в командной строке" -- --#: ../egg/eggdesktopfile.c:1184 --#, c-format --msgid "Unrecognized launch option: %d" --msgstr "Нераспознанный параметр запуска: %d" -- --#. translators: The 'Type=Link' string is found in a --#. * desktop file, and should not be translated. --#: ../egg/eggdesktopfile.c:1391 --#, c-format --msgid "Can't pass document URIs to a 'Type=Link' desktop entry" --msgstr "Не удалось передать URI документа элементу рабочего стола 'Type=Link'" -- --#: ../egg/eggdesktopfile.c:1412 --#, c-format --msgid "Not a launchable item" --msgstr "Не является запускаемым элементом" -- --#: ../egg/eggsmclient.c:226 --msgid "Disable connection to session manager" --msgstr "Отключить соединение с менеджером сеансов" -- --#: ../egg/eggsmclient.c:229 --msgid "Specify file containing saved configuration" --msgstr "Указать файл, содержащий сохранённую конфигурацию" -- --#: ../egg/eggsmclient.c:229 --msgid "FILE" --msgstr "ФАЙЛ" -- --#: ../egg/eggsmclient.c:232 --msgid "Specify session management ID" --msgstr "Указать идентификатор управления сеансом" -- --#: ../egg/eggsmclient.c:232 --msgid "ID" --msgstr "ID" -- --#: ../egg/eggsmclient.c:253 --msgid "Session management options:" --msgstr "Параметры управления сеансами:" -- --#: ../egg/eggsmclient.c:254 --msgid "Show session management options" --msgstr "Отобразить параметры управления сеансами:" -- --#: ../gnome-session/gsm-fail-whale-dialog.c:295 -+#: ../gnome-session/gsm-fail-whale-dialog.c:321 - msgid "Oh no! Something has gone wrong." - msgstr "О, нет! Что-то пошло не так." - --#: ../gnome-session/gsm-fail-whale-dialog.c:302 -+#: ../gnome-session/gsm-fail-whale-dialog.c:328 - msgid "" - "A problem has occurred and the system can't recover. Please contact a system " - "administrator" -@@ -255,7 +209,7 @@ - "Произошла ошибка, и системе не удалось восстановиться. Обратитесь к " - "системному администратору." - --#: ../gnome-session/gsm-fail-whale-dialog.c:304 -+#: ../gnome-session/gsm-fail-whale-dialog.c:330 - msgid "" - "A problem has occurred and the system can't recover. All extensions have " - "been disabled as a precaution." -@@ -263,7 +217,7 @@ - "Произошла ошибка, и системе не удалось восстановиться. Все расширения были " - "отключены в целях безопасности." - --#: ../gnome-session/gsm-fail-whale-dialog.c:306 -+#: ../gnome-session/gsm-fail-whale-dialog.c:332 - msgid "" - "A problem has occurred and the system can't recover.\n" - "Please log out and try again." -@@ -271,83 +225,83 @@ - "Произошла ошибка, и системе не удалось восстановиться.\n" - "Нужно завершить сеанс и войти снова." - --#: ../gnome-session/gsm-fail-whale-dialog.c:321 -+#: ../gnome-session/gsm-fail-whale-dialog.c:347 - msgid "_Log Out" - msgstr "_Завершить сеанс" - --#: ../gnome-session/gsm-fail-whale-dialog.c:343 ../gnome-session/main.c:307 -+#: ../gnome-session/gsm-fail-whale-dialog.c:369 ../gnome-session/main.c:306 - msgid "Enable debugging code" - msgstr "Включить отладочный код" - --#: ../gnome-session/gsm-fail-whale-dialog.c:344 -+#: ../gnome-session/gsm-fail-whale-dialog.c:370 - msgid "Allow logout" - msgstr "Разрешить завершение сеанса" - --#: ../gnome-session/gsm-fail-whale-dialog.c:345 -+#: ../gnome-session/gsm-fail-whale-dialog.c:371 - msgid "Show extension warning" - msgstr "Показывать предупреждения от расширений" - --#: ../gnome-session/gsm-manager.c:1271 ../gnome-session/gsm-manager.c:2043 -+#: ../gnome-session/gsm-manager.c:1370 ../gnome-session/gsm-manager.c:2192 - msgid "Not responding" - msgstr "Не отвечает" - --#: ../gnome-session/gsm-util.c:411 -+#: ../gnome-session/gsm-util.c:382 - msgid "_Log out" - msgstr "_Завершить сеанс" - - #. It'd be really surprising to reach this code: if we're here, - #. * then the XSMP client already has set several XSMP - #. * properties. But it could still be that SmProgram is not set. --#. --#: ../gnome-session/gsm-xsmp-client.c:559 -+#. -+#: ../gnome-session/gsm-xsmp-client.c:582 - msgid "Remembered Application" - msgstr "Запомненное приложение" - --#: ../gnome-session/gsm-xsmp-client.c:1209 -+#: ../gnome-session/gsm-xsmp-client.c:1244 - msgid "This program is blocking logout." - msgstr "Эта программа блокирует выход из системы." - --#: ../gnome-session/gsm-xsmp-server.c:341 -+#: ../gnome-session/gsm-xsmp-server.c:340 - msgid "" - "Refusing new client connection because the session is currently being shut " - "down\n" - msgstr "Новые клиентские подключения отклоняются, т. к. сеанс завершается\n" - --#: ../gnome-session/gsm-xsmp-server.c:610 -+#: ../gnome-session/gsm-xsmp-server.c:609 - #, c-format - msgid "Could not create ICE listening socket: %s" - msgstr "Не удалось создать сокет, слушающий ICE: %s" - --#: ../gnome-session/main.c:305 -+#: ../gnome-session/main.c:304 - msgid "Override standard autostart directories" - msgstr "Заместить стандартные каталоги автозапуска" - --#: ../gnome-session/main.c:305 -+#: ../gnome-session/main.c:304 - msgid "AUTOSTART_DIR" - msgstr "КАТАЛОГ_АВТОЗАПУСКА" - --#: ../gnome-session/main.c:306 -+#: ../gnome-session/main.c:305 - msgid "Session to use" - msgstr "Использовать сеанс" - --#: ../gnome-session/main.c:306 -+#: ../gnome-session/main.c:305 - msgid "SESSION_NAME" - msgstr "НАЗВАНИЕ_СЕАНСА" - --#: ../gnome-session/main.c:308 -+#: ../gnome-session/main.c:307 - msgid "Do not load user-specified applications" - msgstr "Не загружать указанные пользователем приложения" - - #. Translators: the 'fail whale' is the black dialog we show when something goes seriously wrong --#: ../gnome-session/main.c:311 -+#: ../gnome-session/main.c:310 - msgid "Show the fail whale dialog for testing" - msgstr "Показать для отладки диалог с сообщением об ошибке" - --#: ../gnome-session/main.c:344 -+#: ../gnome-session/main.c:343 - msgid " - the GNOME session manager" - msgstr "— менеджер сеансов GNOME" - --#: ../tools/gnome-session-inhibit.c:110 -+#: ../tools/gnome-session-inhibit.c:108 - #, c-format - msgid "" - "%s [OPTION...] COMMAND\n" -@@ -380,65 +334,81 @@ - "\n" - "При использовании параметра --inhibit включается ожидание.\n" - --#: ../tools/gnome-session-inhibit.c:148 -+#: ../tools/gnome-session-inhibit.c:146 - #, c-format - msgid "Failed to execute %s\n" - msgstr "Не удалось запустить %s\n" - --#: ../tools/gnome-session-inhibit.c:208 ../tools/gnome-session-inhibit.c:218 --#: ../tools/gnome-session-inhibit.c:228 -+#: ../tools/gnome-session-inhibit.c:206 ../tools/gnome-session-inhibit.c:216 -+#: ../tools/gnome-session-inhibit.c:226 - #, c-format - msgid "%s requires an argument\n" - msgstr "%s требуется аргумент\n" - --#: ../tools/gnome-session-selector.c:62 -+#: ../tools/gnome-session-selector.c:71 - #, c-format - msgid "Session %d" - msgstr "Сеанс %d" - --#: ../tools/gnome-session-selector.c:108 -+#: ../tools/gnome-session-selector.c:115 - msgid "" - "Session names are not allowed to start with ‘.’ or contain ‘/’ characters" - msgstr "" - "Имена сеансов не могут начинаться с символа «.» или содержать символы «/»" - --#: ../tools/gnome-session-selector.c:112 -+#: ../tools/gnome-session-selector.c:119 - msgid "Session names are not allowed to start with ‘.’" - msgstr "Имена сеансов не могут начинаться с символа «.»" - --#: ../tools/gnome-session-selector.c:116 -+#: ../tools/gnome-session-selector.c:123 - msgid "Session names are not allowed to contain ‘/’ characters" - msgstr "Имена сеансов не могут содержать символы «/»" - --#: ../tools/gnome-session-selector.c:124 -+#: ../tools/gnome-session-selector.c:131 - #, c-format - msgid "A session named ‘%s’ already exists" - msgstr "Сеанс с именем «%s» уже существует" - --#: ../tools/gnome-session-quit.c:53 -+#: ../tools/gnome-session-selector.c:794 -+msgid "What to do with session selection (save|load|print)" -+msgstr "Действие над выбранным сеансом (save|load|print)" -+ -+#: ../tools/gnome-session-selector.c:795 -+msgid "[session-name]" -+msgstr "[имя-сеанса]" -+ -+#: ../tools/gnome-session-selector.c:889 -+msgid "Please select a custom session to run" -+msgstr "Выберите сеанс для запуска" -+ -+#: ../tools/gnome-session-selector.c:891 -+msgid "Please select a session to use" -+msgstr "Выберите сеанс" -+ -+#: ../tools/gnome-session-selector.c:893 -+msgid "Please select a session to save to" -+msgstr "Выберите сеанс для сохранения" -+ -+#: ../tools/gnome-session-quit.c:51 - msgid "Log out" - msgstr "Завершить сеанс" - --#: ../tools/gnome-session-quit.c:54 -+#: ../tools/gnome-session-quit.c:52 - msgid "Power off" - msgstr "Выключить" - --#: ../tools/gnome-session-quit.c:55 -+#: ../tools/gnome-session-quit.c:53 - msgid "Reboot" - msgstr "Перезагрузить" - --#: ../tools/gnome-session-quit.c:56 -+#: ../tools/gnome-session-quit.c:54 - msgid "Ignoring any existing inhibitors" - msgstr "Игнорирование любых существующих препятствий" - --#: ../tools/gnome-session-quit.c:57 -+#: ../tools/gnome-session-quit.c:55 - msgid "Don't prompt for user confirmation" - msgstr "Не требовать подтверждения от пользователя" - --#: ../tools/gnome-session-quit.c:91 ../tools/gnome-session-quit.c:101 --msgid "Could not connect to the session manager" --msgstr "Не удалось соединиться с менеджером сеансов" -- --#: ../tools/gnome-session-quit.c:203 -+#: ../tools/gnome-session-quit.c:201 - msgid "Program called with conflicting options" - msgstr "Программа вызвана с конфликтующими параметрами" -diff -urN gnome-session-3.14.0/po/zh_CN.po gnome-session-3.14.0_localized/po/zh_CN.po ---- gnome-session-3.14.0/po/zh_CN.po 2014-06-25 23:36:34.000000000 +0530 -+++ gnome-session-3.14.0_localized/po/zh_CN.po 2016-03-14 19:41:08.959245176 +0530 -@@ -13,22 +13,97 @@ - # tuhaihe <1132321739qq@gmail.com>, 2012. - # nhm <572348382@qq.com>, 2013. - # Wylmer Wang , 2013. --# -+# Leah Liu , 2016. #zanata -+# pnemade , 2016. #zanata - msgid "" - msgstr "" - "Project-Id-Version: gnome-session master\n" --"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-" --"session&keywords=I18N+L10N&component=general\n" --"POT-Creation-Date: 2013-10-23 19:36+0000\n" --"PO-Revision-Date: 2013-11-01 23:04+0800\n" --"Last-Translator: nhm <572348382@qq.com>\n" --"Language-Team: Chinese/Simplified \n" --"Language: \n" -+"Report-Msgid-Bugs-To: \n" -+"POT-Creation-Date: 2016-02-26 10:16+0530\n" - "MIME-Version: 1.0\n" - "Content-Type: text/plain; charset=UTF-8\n" - "Content-Transfer-Encoding: 8bit\n" -+"PO-Revision-Date: 2016-03-07 03:58+0000\n" -+"Last-Translator: Leah Liu \n" -+"Language-Team: Chinese/Simplified \n" -+"Language: zh-CN\n" - "Plural-Forms: nplurals=1; plural=0;\n" --"X-Generator: Poedit 1.5.5\n" -+"X-Generator: Zanata 3.8.2\n" -+ -+# help-browser/toc-man.c:19 help-browser/toc2-man.c:21 -+#: ../capplet/gsm-app-dialog.c:120 -+msgid "Select Command" -+msgstr "选择命令" -+ -+#: ../capplet/gsm-app-dialog.c:193 -+msgid "Add Startup Program" -+msgstr "添加启动程序" -+ -+#: ../capplet/gsm-app-dialog.c:197 -+msgid "Edit Startup Program" -+msgstr "编辑启动程序" -+ -+#: ../capplet/gsm-app-dialog.c:484 -+msgid "The startup command cannot be empty" -+msgstr "启动命令不能为空" -+ -+#: ../capplet/gsm-app-dialog.c:490 -+msgid "The startup command is not valid" -+msgstr "启动命令无效" -+ -+#: ../capplet/gsm-properties-dialog.c:493 -+msgid "Your session has been saved." -+msgstr "已保存您的会话。" -+ -+#: ../capplet/gsm-properties-dialog.c:495 -+#: ../capplet/gsm-properties-dialog.c:521 -+msgid "Failed to save session" -+msgstr "保存会话失败" -+ -+# gsm/save-session.c:86 -+#: ../capplet/gsm-properties-dialog.c:509 -+msgid "Could not connect to the session bus" -+msgstr "无法连接到会话总线" -+ -+# gsm/save-session.c:86 -+#: ../capplet/gsm-properties-dialog.c:515 ../tools/gnome-session-quit.c:89 -+#: ../tools/gnome-session-quit.c:99 -+msgid "Could not connect to the session manager" -+msgstr "无法连接到会话管理器" -+ -+#: ../capplet/gsm-properties-dialog.c:606 -+msgid "Enabled" -+msgstr "启用" -+ -+# gsm/logout.c:240 -+#: ../capplet/gsm-properties-dialog.c:618 -+msgid "Icon" -+msgstr "图标" -+ -+# applets/gkb/gkb.c:262 -+#: ../capplet/gsm-properties-dialog.c:630 -+msgid "Program" -+msgstr "程序" -+ -+#: ../capplet/gsm-properties-dialog.c:834 -+msgid "Startup Applications Preferences" -+msgstr "启动应用程序首选项" -+ -+#: ../capplet/gsp-app.c:277 -+msgid "No name" -+msgstr "无名称" -+ -+#: ../capplet/gsp-app.c:283 -+msgid "No description" -+msgstr "无描述" -+ -+#: ../capplet/main.c:35 ../gnome-session/main.c:308 -+msgid "Version of this application" -+msgstr "此应用程序的版本" -+ -+#: ../capplet/main.c:61 -+msgid "Could not display help document" -+msgstr "不能显示帮助文档" - - #: ../data/gnome-custom-session.desktop.in.h:1 - msgid "Custom" -@@ -50,14 +125,20 @@ - msgid "GNOME dummy" - msgstr "GNOME dummy" - -+#: ../data/session-properties.desktop.in.in.h:1 -+msgid "Startup Applications" -+msgstr "启动应用程序" -+ -+#: ../data/session-properties.desktop.in.in.h:2 -+msgid "Choose what applications to start when you log in" -+msgstr "选择登录时要启动的应用程序" -+ - #: ../data/gnome-wayland.desktop.in.h:1 - #: ../data/gnome-wayland.session.desktop.in.in.h:1 --#| msgid "GNOME fallback" - msgid "GNOME on Wayland" - msgstr "基于 Wayland 的 GNOME" - - #: ../data/gnome-wayland.desktop.in.h:2 --#| msgid "This session logs you into GNOME" - msgid "This session logs you into GNOME, using Wayland" - msgstr "此会话将您登录到使用 Wayland 的 GNOME" - -@@ -65,9 +146,9 @@ - msgid "Custom Session" - msgstr "自定义会话" - --#: ../data/session-selector.ui.h:2 ../tools/gnome-session-selector.c:103 --msgid "Please select a custom session to run" --msgstr "请选择一个要运行的自定义会话" -+#: ../data/session-selector.ui.h:2 -+msgid "Please select a custom session to use" -+msgstr "请选择要运行的自定义会话" - - #: ../data/session-selector.ui.h:3 - msgid "_New Session" -@@ -82,6 +163,10 @@ - msgstr "重命名会话(_M)" - - #: ../data/session-selector.ui.h:6 -+msgid "Classic Experience" -+msgstr "典型体验" -+ -+#: ../data/session-selector.ui.h:7 - msgid "_Continue" - msgstr "继续(_C)" - -@@ -126,111 +211,107 @@ - msgid "_Name:" - msgstr "名称(_N):" - --#: ../gnome-session/gsm-fail-whale-dialog.c:295 -+#: ../gnome-session/gsm-fail-whale-dialog.c:321 - msgid "Oh no! Something has gone wrong." - msgstr "糟糕!出错啦!" - --#: ../gnome-session/gsm-fail-whale-dialog.c:302 -+#: ../gnome-session/gsm-fail-whale-dialog.c:328 - msgid "" - "A problem has occurred and the system can't recover. Please contact a system " - "administrator" - msgstr "系统出错且无法恢复。请联系系统管理员。" - --#: ../gnome-session/gsm-fail-whale-dialog.c:304 -+#: ../gnome-session/gsm-fail-whale-dialog.c:330 - msgid "" - "A problem has occurred and the system can't recover. All extensions have " - "been disabled as a precaution." - msgstr "系统出错且无法恢复。为预防起见,已禁用了所有扩展。" - --#: ../gnome-session/gsm-fail-whale-dialog.c:306 -+#: ../gnome-session/gsm-fail-whale-dialog.c:332 - msgid "" - "A problem has occurred and the system can't recover.\n" - "Please log out and try again." - msgstr "系统出错并无法恢复,请尝试注销并重新登录。" - - # gsm/logout.c:248 --#: ../gnome-session/gsm-fail-whale-dialog.c:321 -+#: ../gnome-session/gsm-fail-whale-dialog.c:347 - msgid "_Log Out" - msgstr "注销(_L)" - --#: ../gnome-session/gsm-fail-whale-dialog.c:343 ../gnome-session/main.c:307 -+#: ../gnome-session/gsm-fail-whale-dialog.c:369 ../gnome-session/main.c:306 - msgid "Enable debugging code" - msgstr "启用调试代码" - --#: ../gnome-session/gsm-fail-whale-dialog.c:344 -+#: ../gnome-session/gsm-fail-whale-dialog.c:370 - msgid "Allow logout" - msgstr "允许注销" - --#: ../gnome-session/gsm-fail-whale-dialog.c:345 -+#: ../gnome-session/gsm-fail-whale-dialog.c:371 - msgid "Show extension warning" - msgstr "显示扩展警告" - --#: ../gnome-session/gsm-manager.c:1272 ../gnome-session/gsm-manager.c:2044 -+#: ../gnome-session/gsm-manager.c:1370 ../gnome-session/gsm-manager.c:2192 - msgid "Not responding" - msgstr "无响应" - - # gsm/logout.c:248 --#: ../gnome-session/gsm-util.c:411 -+#: ../gnome-session/gsm-util.c:382 - msgid "_Log out" - msgstr "注销(_L)" - - #. It'd be really surprising to reach this code: if we're here, - #. * then the XSMP client already has set several XSMP - #. * properties. But it could still be that SmProgram is not set. --#. --#: ../gnome-session/gsm-xsmp-client.c:559 -+#. -+#: ../gnome-session/gsm-xsmp-client.c:582 - msgid "Remembered Application" - msgstr "记住的应用程序" - --#: ../gnome-session/gsm-xsmp-client.c:1209 -+#: ../gnome-session/gsm-xsmp-client.c:1244 - msgid "This program is blocking logout." - msgstr "此程序正在阻止注销。" - --#: ../gnome-session/gsm-xsmp-server.c:341 -+#: ../gnome-session/gsm-xsmp-server.c:340 - msgid "" - "Refusing new client connection because the session is currently being shut " - "down\n" - msgstr "拒绝新客户连接,原因是会话正在关闭\n" - --#: ../gnome-session/gsm-xsmp-server.c:610 -+#: ../gnome-session/gsm-xsmp-server.c:609 - #, c-format - msgid "Could not create ICE listening socket: %s" - msgstr "无法创建 ICE 监听套接字:%s" - --#: ../gnome-session/main.c:305 -+#: ../gnome-session/main.c:304 - msgid "Override standard autostart directories" - msgstr "取代默认的自动启动目录" - --#: ../gnome-session/main.c:305 -+#: ../gnome-session/main.c:304 - msgid "AUTOSTART_DIR" - msgstr "自动启动目录" - --#: ../gnome-session/main.c:306 -+#: ../gnome-session/main.c:305 - msgid "Session to use" - msgstr "要使用的会话" - --#: ../gnome-session/main.c:306 -+#: ../gnome-session/main.c:305 - msgid "SESSION_NAME" - msgstr "会话名称" - --#: ../gnome-session/main.c:308 -+#: ../gnome-session/main.c:307 - msgid "Do not load user-specified applications" - msgstr "不装入用户指定的应用程序" - --#: ../gnome-session/main.c:309 --msgid "Version of this application" --msgstr "此应用程序的版本" -- - #. Translators: the 'fail whale' is the black dialog we show when something goes seriously wrong --#: ../gnome-session/main.c:311 -+#: ../gnome-session/main.c:310 - msgid "Show the fail whale dialog for testing" - msgstr "显示用于测试的鲸鱼失败对话框" - --#: ../gnome-session/main.c:344 -+#: ../gnome-session/main.c:343 - msgid " - the GNOME session manager" - msgstr "- GNOME 会话管理器" - --#: ../tools/gnome-session-inhibit.c:110 -+#: ../tools/gnome-session-inhibit.c:108 - #, c-format - msgid "" - "%s [OPTION...] COMMAND\n" -@@ -262,291 +343,81 @@ - "\n" - "若未指定 --inhibit 参数,将假设为 idle\n" - --#: ../tools/gnome-session-inhibit.c:148 -+#: ../tools/gnome-session-inhibit.c:146 - #, c-format - msgid "Failed to execute %s\n" - msgstr "执行 %s 失败\n" - --#: ../tools/gnome-session-inhibit.c:208 ../tools/gnome-session-inhibit.c:218 --#: ../tools/gnome-session-inhibit.c:228 -+#: ../tools/gnome-session-inhibit.c:206 ../tools/gnome-session-inhibit.c:216 -+#: ../tools/gnome-session-inhibit.c:226 - #, c-format - msgid "%s requires an argument\n" - msgstr "%s 需要一个参数\n" - --#: ../tools/gnome-session-selector.c:62 -+#: ../tools/gnome-session-selector.c:71 - #, c-format - msgid "Session %d" - msgstr "会话 %d" - --#: ../tools/gnome-session-selector.c:108 -+#: ../tools/gnome-session-selector.c:115 - msgid "" - "Session names are not allowed to start with ‘.’ or contain ‘/’ characters" - msgstr "会话名称不允许以“.”开头或包含“/”字符" - --#: ../tools/gnome-session-selector.c:112 -+#: ../tools/gnome-session-selector.c:119 - msgid "Session names are not allowed to start with ‘.’" - msgstr "会话名称不允许以“.”开头" - --#: ../tools/gnome-session-selector.c:116 -+#: ../tools/gnome-session-selector.c:123 - msgid "Session names are not allowed to contain ‘/’ characters" - msgstr "会话名称不允许包含“/”字符" - --#: ../tools/gnome-session-selector.c:124 -+#: ../tools/gnome-session-selector.c:131 - #, c-format - msgid "A session named ‘%s’ already exists" - msgstr "名为“%s”的会话已存在" - -+#: ../tools/gnome-session-selector.c:794 -+msgid "What to do with session selection (save|load|print)" -+msgstr "要为所选会话进行什么操作(save|load|print)" -+ -+#: ../tools/gnome-session-selector.c:795 -+msgid "[session-name]" -+msgstr "[session-name]" -+ -+#: ../tools/gnome-session-selector.c:889 -+msgid "Please select a custom session to run" -+msgstr "请选择一个要运行的自定义会话" -+ -+#: ../tools/gnome-session-selector.c:891 -+msgid "Please select a session to use" -+msgstr "请选择要运行的会话" -+ -+#: ../tools/gnome-session-selector.c:893 -+msgid "Please select a session to save to" -+msgstr "请选择要保存的会话" -+ - # gsm/logout.c:248 --#: ../tools/gnome-session-quit.c:53 -+#: ../tools/gnome-session-quit.c:51 - msgid "Log out" - msgstr "注销" - --#: ../tools/gnome-session-quit.c:54 -+#: ../tools/gnome-session-quit.c:52 - msgid "Power off" - msgstr "关机" - --#: ../tools/gnome-session-quit.c:55 -+#: ../tools/gnome-session-quit.c:53 - msgid "Reboot" - msgstr "重启" - --#: ../tools/gnome-session-quit.c:56 -+#: ../tools/gnome-session-quit.c:54 - msgid "Ignoring any existing inhibitors" - msgstr "忽略现有限制因素" - --#: ../tools/gnome-session-quit.c:57 -+#: ../tools/gnome-session-quit.c:55 - msgid "Don't prompt for user confirmation" - msgstr "不提示用户确认" - --# gsm/save-session.c:86 --#: ../tools/gnome-session-quit.c:91 ../tools/gnome-session-quit.c:101 --msgid "Could not connect to the session manager" --msgstr "无法连接到会话管理器" -- --#: ../tools/gnome-session-quit.c:203 -+#: ../tools/gnome-session-quit.c:201 - msgid "Program called with conflicting options" - msgstr "调用程序的选项互相冲突" -- --# help-browser/toc-man.c:19 help-browser/toc2-man.c:21 --#~ msgid "Select Command" --#~ msgstr "选择命令" -- --#~ msgid "Add Startup Program" --#~ msgstr "添加启动程序" -- --#~ msgid "Edit Startup Program" --#~ msgstr "编辑启动程序" -- --#~ msgid "The startup command cannot be empty" --#~ msgstr "启动命令不能为空" -- --#~ msgid "The startup command is not valid" --#~ msgstr "启动命令无效" -- --#~ msgid "Enabled" --#~ msgstr "启用" -- --# gsm/logout.c:240 --#~ msgid "Icon" --#~ msgstr "图标" -- --# applets/gkb/gkb.c:262 --#~ msgid "Program" --#~ msgstr "程序" -- --#~ msgid "Startup Applications Preferences" --#~ msgstr "启动应用程序首选项" -- --#~ msgid "No name" --#~ msgstr "无名称" -- --#~ msgid "No description" --#~ msgstr "无描述" -- --#~ msgid "Could not display help document" --#~ msgstr "不能显示帮助文档" -- --#~ msgid "Some programs are still running:" --#~ msgstr "有些程序仍在运行中:" -- --#~ msgid "Startup Applications" --#~ msgstr "启动应用程序" -- --#~ msgid "Choose what applications to start when you log in" --#~ msgstr "选择登录时要启动的应用程序" -- --#~ msgid "File is not a valid .desktop file" --#~ msgstr "文件不是有效的 .desktop 文件" -- --#~ msgid "Unrecognized desktop file Version '%s'" --#~ msgstr "不识别的桌面文件版本“%s”" -- --# gnome-terminal/gnome-terminal.c:1590 --#~ msgid "Starting %s" --#~ msgstr "正在启动 %s" -- --#~ msgid "Application does not accept documents on command line" --#~ msgstr "应用程序在命令行上不接受文档" -- --#~ msgid "Unrecognized launch option: %d" --#~ msgstr "无法识别的调用选项:%d" -- --#~ msgid "Can't pass document URIs to a 'Type=Link' desktop entry" --#~ msgstr "无法将文档 URI 传送给“Type=Link”桌面项" -- --#~ msgid "Not a launchable item" --#~ msgstr "不是可调用项" -- --# gsm/save-session.c:86 --#~ msgid "Disable connection to session manager" --#~ msgstr "禁止连接到会话管理器" -- --#~ msgid "Specify file containing saved configuration" --#~ msgstr "指定包含已保存配置的文件" -- --#~ msgid "FILE" --#~ msgstr "文件" -- --#~ msgid "Specify session management ID" --#~ msgstr "指定会话管理 ID" -- --#~ msgid "ID" --#~ msgstr "ID" -- --# panel/menu.c:3509 --#~ msgid "Session management options:" --#~ msgstr "会话管理选项:" -- --# panel/menu.c:3509 --#~ msgid "Show session management options" --#~ msgstr "显示会话管理选项" -- --#~ msgid "Unknown" --#~ msgstr "未知" -- --#~ msgid "A program is still running:" --#~ msgstr "有程序仍在运行中:" -- --#~ msgid "" --#~ "Waiting for the program to finish. Interrupting the program may cause you " --#~ "to lose work." --#~ msgstr "正在等候程序结束。中断程序可能导致您的工作成果丢失。" -- --#~ msgid "" --#~ "Waiting for programs to finish. Interrupting these programs may cause you " --#~ "to lose work." --#~ msgstr "正在等候程序结束。中断程序可能导致您的工作成果丢失。" -- --#~ msgid "Switch User Anyway" --#~ msgstr "强制切换用户" -- --#~ msgid "Log Out Anyway" --#~ msgstr "强制注销" -- --#~ msgid "Suspend Anyway" --#~ msgstr "强制挂起" -- --#~ msgid "Hibernate Anyway" --#~ msgstr "强制休眠" -- --#~ msgid "Shut Down Anyway" --#~ msgstr "强制关机" -- --#~ msgid "Restart Anyway" --#~ msgstr "强制重新启动" -- --#~ msgid "Lock Screen" --#~ msgstr "锁定屏幕" -- --#~ msgid "Cancel" --#~ msgstr "取消" -- --#~ msgid "You will be automatically logged out in %d second." --#~ msgid_plural "You will be automatically logged out in %d seconds." --#~ msgstr[0] "您即将在 %d 秒后自动注销。" -- --#~ msgid "This system will be automatically shut down in %d second." --#~ msgid_plural "This system will be automatically shut down in %d seconds." --#~ msgstr[0] "系统即将在 %d 秒后自动关闭。" -- --#~ msgid "This system will be automatically restarted in %d second." --#~ msgid_plural "This system will be automatically restarted in %d seconds." --#~ msgstr[0] "系统将在 %d 秒后自动重启。" -- --#~ msgid "You are currently logged in as \"%s\"." --#~ msgstr "您目前以“%s”身份登录。" -- --#~ msgid "Log out of this system now?" --#~ msgstr "现在注销系统吗?" -- --#~ msgid "_Switch User" --#~ msgstr "切换用户(_S)" -- --#~ msgid "Shut down this system now?" --#~ msgstr "现在关闭此系统吗?" -- --#~ msgid "S_uspend" --#~ msgstr "挂起(_U)" -- --#~ msgid "_Hibernate" --#~ msgstr "休眠(_H)" -- --# gmenu/edit.c:336 gsm/session-properties.c:167 --#~ msgid "_Restart" --#~ msgstr "重启(_R)" -- --#~ msgid "_Shut Down" --#~ msgstr "关机(_S)" -- --#~ msgid "Restart this system now?" --#~ msgstr "现在重启该系统吗?" -- --#~ msgid "Icon '%s' not found" --#~ msgstr "图标“%s”未找到" -- --#~ msgid "GNOME 3 Failed to Load" --#~ msgstr "GNOME 3 加载失败" -- --#~ msgid "" --#~ "Unfortunately GNOME 3 failed to start properly and started in the " --#~ "fallback mode.\n" --#~ "\n" --#~ "This most likely means your system (graphics hardware or driver) is not " --#~ "capable of delivering the full GNOME 3 experience." --#~ msgstr "" --#~ "很遗憾 GNOME 3 无法正常启动,并已启动到后备模式。\n" --#~ "\n" --#~ "这可能是因为您的显卡硬件或驱动不足以完全运行 GNOME 3。" -- --#~ msgid "Learn more about GNOME 3" --#~ msgstr "进一步了解 GNOME 3" -- --#~ msgid "" --#~ "Unable to start login session (and unable to connect to the X server)" --#~ msgstr "无法启动登录会话(并且无法连接到 X 服务器)" -- --#~ msgid "Some programs are still running:" --#~ msgstr "某些程序仍在运行中:" -- --#~ msgid "Exited with code %d" --#~ msgstr "以代码 %d 退出" -- --#~ msgid "Killed by signal %d" --#~ msgstr "被信号 %d 杀死" -- --#~ msgid "Stopped by signal %d" --#~ msgstr "被信号 %d 停止" -- --#~ msgid "" --#~ "A problem has occurred and the system can't recover. Some of the " --#~ "extensions below may have caused this.\n" --#~ "Please try disabling some of these, and then log out and try again." --#~ msgstr "" --#~ "系统出错并无法恢复。这可能是下面的一些扩展导致的。\n" --#~ "请尝试禁用一些,并注销重试。" -- --#~ msgid "" --#~ "There is a problem with the configuration server.\n" --#~ "(%s exited with status %d)" --#~ msgstr "" --#~ "配置服务器有错。\n" --#~ "(%s 的退出状态为 %d)" -diff -urN gnome-session-3.14.0/po/zh_TW.po gnome-session-3.14.0_localized/po/zh_TW.po ---- gnome-session-3.14.0/po/zh_TW.po 2014-06-25 23:36:34.000000000 +0530 -+++ gnome-session-3.14.0_localized/po/zh_TW.po 2016-03-14 19:41:08.964245171 +0530 -@@ -10,21 +10,22 @@ - # Woodman Tuen , 2005-006. - # Chao-Hsiung Liao , 2008, 2010. - # Wei-Lun Chao , 2010. --# -+# ccheng , 2016. #zanata -+# pnemade , 2016. #zanata - msgid "" - msgstr "" - "Project-Id-Version: gnome-session 3.1.92\n" - "Report-Msgid-Bugs-To: \n" --"POT-Creation-Date: 2013-09-17 19:40+0800\n" --"PO-Revision-Date: 2013-09-13 09:22+0800\n" --"Last-Translator: Chao-Hsiung Liao \n" --"Language-Team: Chinese (Taiwan) \n" --"Language: \n" -+"POT-Creation-Date: 2016-02-26 10:16+0530\n" - "MIME-Version: 1.0\n" - "Content-Type: text/plain; charset=UTF-8\n" - "Content-Transfer-Encoding: 8bit\n" -+"PO-Revision-Date: 2016-03-04 06:34+0000\n" -+"Last-Translator: ccheng \n" -+"Language-Team: Chinese (Taiwan) \n" -+"Language: zh-TW\n" - "Plural-Forms: nplurals=1; plural=0;\n" --"X-Generator: Poedit 1.5.5\n" -+"X-Generator: Zanata 3.8.2\n" - - #: ../capplet/gsm-app-dialog.c:120 - msgid "Select Command" -@@ -46,31 +47,49 @@ - msgid "The startup command is not valid" - msgstr "初始啟動指令無效" - --#: ../capplet/gsm-properties-dialog.c:519 -+#: ../capplet/gsm-properties-dialog.c:493 -+msgid "Your session has been saved." -+msgstr "您的 session 已儲存。" -+ -+#: ../capplet/gsm-properties-dialog.c:495 -+#: ../capplet/gsm-properties-dialog.c:521 -+msgid "Failed to save session" -+msgstr "儲存 session 失敗" -+ -+#: ../capplet/gsm-properties-dialog.c:509 -+msgid "Could not connect to the session bus" -+msgstr "無法連接至 session 匯流排" -+ -+#: ../capplet/gsm-properties-dialog.c:515 ../tools/gnome-session-quit.c:89 -+#: ../tools/gnome-session-quit.c:99 -+msgid "Could not connect to the session manager" -+msgstr "無法連接作業階段總管" -+ -+#: ../capplet/gsm-properties-dialog.c:606 - msgid "Enabled" - msgstr "已啟用" - --#: ../capplet/gsm-properties-dialog.c:531 -+#: ../capplet/gsm-properties-dialog.c:618 - msgid "Icon" - msgstr "圖示" - --#: ../capplet/gsm-properties-dialog.c:543 -+#: ../capplet/gsm-properties-dialog.c:630 - msgid "Program" - msgstr "程式" - --#: ../capplet/gsm-properties-dialog.c:747 -+#: ../capplet/gsm-properties-dialog.c:834 - msgid "Startup Applications Preferences" - msgstr "初始啟動程式偏好設定" - --#: ../capplet/gsp-app.c:276 -+#: ../capplet/gsp-app.c:277 - msgid "No name" - msgstr "沒有名稱" - --#: ../capplet/gsp-app.c:282 -+#: ../capplet/gsp-app.c:283 - msgid "No description" - msgstr "沒有描述" - --#: ../capplet/main.c:35 ../gnome-session/main.c:309 -+#: ../capplet/main.c:35 ../gnome-session/main.c:308 - msgid "Version of this application" - msgstr "這個程式的版本" - -@@ -98,11 +117,11 @@ - msgid "GNOME dummy" - msgstr "GNOME dummy" - --#: ../data/gnome-session-properties.desktop.in.in.h:1 -+#: ../data/session-properties.desktop.in.in.h:1 - msgid "Startup Applications" - msgstr "初始啟動程式" - --#: ../data/gnome-session-properties.desktop.in.in.h:2 -+#: ../data/session-properties.desktop.in.in.h:2 - msgid "Choose what applications to start when you log in" - msgstr "選擇在您登入時要啟動哪些應用程式" - -@@ -119,9 +138,9 @@ - msgid "Custom Session" - msgstr "自訂作業階段" - --#: ../data/session-selector.ui.h:2 ../tools/gnome-session-selector.c:103 --msgid "Please select a custom session to run" --msgstr "請選擇要執行的自訂作業階段" -+#: ../data/session-selector.ui.h:2 -+msgid "Please select a custom session to use" -+msgstr "請選擇要使用的自訂 session" - - #: ../data/session-selector.ui.h:3 - msgid "_New Session" -@@ -136,6 +155,10 @@ - msgstr "重新命名作業階段(_M)" - - #: ../data/session-selector.ui.h:6 -+msgid "Classic Experience" -+msgstr "經點體驗" -+ -+#: ../data/session-selector.ui.h:7 - msgid "_Continue" - msgstr "繼續(_C)" - -@@ -175,175 +198,106 @@ - msgid "_Name:" - msgstr "名稱(_N):" - --#: ../egg/eggdesktopfile.c:165 --#, c-format --msgid "File is not a valid .desktop file" --msgstr "檔案不是有效的 .desktop 檔案" -- --#. translators: 'Version' is from a desktop file, and --#. * should not be translated. '%s' would probably be a --#. * version number. --#: ../egg/eggdesktopfile.c:191 --#, c-format --msgid "Unrecognized desktop file Version '%s'" --msgstr "無法辨識的桌面檔案版本「%s」" -- --#: ../egg/eggdesktopfile.c:974 --#, c-format --msgid "Starting %s" --msgstr "準備啟動 %s" -- --#: ../egg/eggdesktopfile.c:1116 --#, c-format --msgid "Application does not accept documents on command line" --msgstr "應用程式不接受以命令列開啟文件" -- --#: ../egg/eggdesktopfile.c:1184 --#, c-format --msgid "Unrecognized launch option: %d" --msgstr "無法辨識的啟動選項:%d" -- --#. translators: The 'Type=Link' string is found in a --#. * desktop file, and should not be translated. --#: ../egg/eggdesktopfile.c:1391 --#, c-format --msgid "Can't pass document URIs to a 'Type=Link' desktop entry" --msgstr "不能傳送文件 URI 至「Type=Link」桌面項目" -- --#: ../egg/eggdesktopfile.c:1412 --#, c-format --msgid "Not a launchable item" --msgstr "不是可以啟動的項目" -- --#: ../egg/eggsmclient.c:226 --msgid "Disable connection to session manager" --msgstr "停用到作業階段管理程式的連線" -- --#: ../egg/eggsmclient.c:229 --msgid "Specify file containing saved configuration" --msgstr "指定含有已儲存組態的檔案" -- --#: ../egg/eggsmclient.c:229 --msgid "FILE" --msgstr "檔案" -- --#: ../egg/eggsmclient.c:232 --msgid "Specify session management ID" --msgstr "指定作業階段管理 ID" -- --#: ../egg/eggsmclient.c:232 --msgid "ID" --msgstr "ID" -- --#: ../egg/eggsmclient.c:253 --msgid "Session management options:" --msgstr "作業階段管理選項:" -- --#: ../egg/eggsmclient.c:254 --msgid "Show session management options" --msgstr "顯示作業階段管理選項" -- --#: ../gnome-session/gsm-fail-whale-dialog.c:295 -+#: ../gnome-session/gsm-fail-whale-dialog.c:321 - msgid "Oh no! Something has gone wrong." - msgstr "糟糕!有些地方出問題了。" - --#: ../gnome-session/gsm-fail-whale-dialog.c:302 -+#: ../gnome-session/gsm-fail-whale-dialog.c:328 - msgid "" - "A problem has occurred and the system can't recover. Please contact a system " - "administrator" - msgstr "有問題產生且系統不能恢復。請連絡系統管理者" - --#: ../gnome-session/gsm-fail-whale-dialog.c:304 -+#: ../gnome-session/gsm-fail-whale-dialog.c:330 - msgid "" - "A problem has occurred and the system can't recover. All extensions have " - "been disabled as a precaution." - msgstr "有問題產生且系統不能恢復。為了預防已先停用所有的擴充功能。" - --#: ../gnome-session/gsm-fail-whale-dialog.c:306 -+#: ../gnome-session/gsm-fail-whale-dialog.c:332 - msgid "" - "A problem has occurred and the system can't recover.\n" - "Please log out and try again." --msgstr "" --"有問題產生且系統不能恢復。\n" -+msgstr "有問題產生且系統不能恢復。\n" - "請登出後再試一次。" - --#: ../gnome-session/gsm-fail-whale-dialog.c:321 -+#: ../gnome-session/gsm-fail-whale-dialog.c:347 - msgid "_Log Out" - msgstr "登出(_L)" - --#: ../gnome-session/gsm-fail-whale-dialog.c:343 ../gnome-session/main.c:307 -+#: ../gnome-session/gsm-fail-whale-dialog.c:369 ../gnome-session/main.c:306 - msgid "Enable debugging code" - msgstr "啟用除錯碼" - --#: ../gnome-session/gsm-fail-whale-dialog.c:344 -+#: ../gnome-session/gsm-fail-whale-dialog.c:370 - msgid "Allow logout" - msgstr "允許登出" - --#: ../gnome-session/gsm-fail-whale-dialog.c:345 -+#: ../gnome-session/gsm-fail-whale-dialog.c:371 - msgid "Show extension warning" - msgstr "顯示擴充功能警告" - --#: ../gnome-session/gsm-manager.c:1271 ../gnome-session/gsm-manager.c:2043 -+#: ../gnome-session/gsm-manager.c:1370 ../gnome-session/gsm-manager.c:2192 - msgid "Not responding" - msgstr "沒有回應" - --#: ../gnome-session/gsm-util.c:411 -+#: ../gnome-session/gsm-util.c:382 - msgid "_Log out" - msgstr "登出(_L)" - - #. It'd be really surprising to reach this code: if we're here, - #. * then the XSMP client already has set several XSMP - #. * properties. But it could still be that SmProgram is not set. --#. --#: ../gnome-session/gsm-xsmp-client.c:559 -+#. -+#: ../gnome-session/gsm-xsmp-client.c:582 - msgid "Remembered Application" - msgstr "記住的應用程式" - --#: ../gnome-session/gsm-xsmp-client.c:1209 -+#: ../gnome-session/gsm-xsmp-client.c:1244 - msgid "This program is blocking logout." - msgstr "這個程式正在阻擋登出。" - --#: ../gnome-session/gsm-xsmp-server.c:341 -+#: ../gnome-session/gsm-xsmp-server.c:340 - msgid "" - "Refusing new client connection because the session is currently being shut " - "down\n" - msgstr "因為目前此作業階段即將關閉電腦,拒絕新的客戶端連線\n" - --#: ../gnome-session/gsm-xsmp-server.c:610 -+#: ../gnome-session/gsm-xsmp-server.c:609 - #, c-format - msgid "Could not create ICE listening socket: %s" - msgstr "無法建立 ICE 監聽插槽:%s" - --#: ../gnome-session/main.c:305 -+#: ../gnome-session/main.c:304 - msgid "Override standard autostart directories" - msgstr "覆蓋標準的自動啟動目錄" - --#: ../gnome-session/main.c:305 -+#: ../gnome-session/main.c:304 - msgid "AUTOSTART_DIR" - msgstr "AUTOSTART_DIR" - --#: ../gnome-session/main.c:306 -+#: ../gnome-session/main.c:305 - msgid "Session to use" - msgstr "要使用的作業階段" - --#: ../gnome-session/main.c:306 -+#: ../gnome-session/main.c:305 - msgid "SESSION_NAME" - msgstr "SESSION_NAME" - --#: ../gnome-session/main.c:308 -+#: ../gnome-session/main.c:307 - msgid "Do not load user-specified applications" - msgstr "不要載入使用者指定的應用程式" - - #. Translators: the 'fail whale' is the black dialog we show when something goes seriously wrong --#: ../gnome-session/main.c:311 -+#: ../gnome-session/main.c:310 - msgid "Show the fail whale dialog for testing" - msgstr "顯示嚴重錯誤對話盒以供測試" - --#: ../gnome-session/main.c:344 -+#: ../gnome-session/main.c:343 - msgid " - the GNOME session manager" - msgstr " - GNOME 作業階段管理員" - --#: ../tools/gnome-session-inhibit.c:110 -+#: ../tools/gnome-session-inhibit.c:108 - #, c-format - msgid "" - "%s [OPTION...] COMMAND\n" -@@ -376,182 +330,80 @@ - "\n" - "如果沒有指定 --inhibit 選項,預設為 idle。\n" - --#: ../tools/gnome-session-inhibit.c:148 -+#: ../tools/gnome-session-inhibit.c:146 - #, c-format - msgid "Failed to execute %s\n" - msgstr "無法執行 %s\n" - --#: ../tools/gnome-session-inhibit.c:208 ../tools/gnome-session-inhibit.c:218 --#: ../tools/gnome-session-inhibit.c:228 -+#: ../tools/gnome-session-inhibit.c:206 ../tools/gnome-session-inhibit.c:216 -+#: ../tools/gnome-session-inhibit.c:226 - #, c-format - msgid "%s requires an argument\n" - msgstr "%s 需要引數\n" - --#: ../tools/gnome-session-selector.c:62 -+#: ../tools/gnome-session-selector.c:71 - #, c-format - msgid "Session %d" - msgstr "作業階段 %d" - --#: ../tools/gnome-session-selector.c:108 -+#: ../tools/gnome-session-selector.c:115 - msgid "" - "Session names are not allowed to start with ‘.’ or contain ‘/’ characters" - msgstr "作業階段名稱不允許以 ‘.’ 開頭或包含 ‘/’字元" - --#: ../tools/gnome-session-selector.c:112 -+#: ../tools/gnome-session-selector.c:119 - msgid "Session names are not allowed to start with ‘.’" - msgstr "作業階段名稱不允許以 ‘.’ 開頭" - --#: ../tools/gnome-session-selector.c:116 -+#: ../tools/gnome-session-selector.c:123 - msgid "Session names are not allowed to contain ‘/’ characters" - msgstr "作業階段名稱不允許包含 ‘/’字元" - --#: ../tools/gnome-session-selector.c:124 -+#: ../tools/gnome-session-selector.c:131 - #, c-format - msgid "A session named ‘%s’ already exists" - msgstr "已存在名為「%s」的作業階段" - --#: ../tools/gnome-session-quit.c:53 -+#: ../tools/gnome-session-selector.c:794 -+msgid "What to do with session selection (save|load|print)" -+msgstr "針對所選的 session 要進行什麼動作(save|load|print)" -+ -+#: ../tools/gnome-session-selector.c:795 -+msgid "[session-name]" -+msgstr "[session-name]" -+ -+#: ../tools/gnome-session-selector.c:889 -+msgid "Please select a custom session to run" -+msgstr "請選擇要執行的自訂作業階段" -+ -+#: ../tools/gnome-session-selector.c:891 -+msgid "Please select a session to use" -+msgstr "請選擇要使用的 session" -+ -+#: ../tools/gnome-session-selector.c:893 -+msgid "Please select a session to save to" -+msgstr "請選擇要儲存至的 session" -+ -+#: ../tools/gnome-session-quit.c:51 - msgid "Log out" - msgstr "登出" - --#: ../tools/gnome-session-quit.c:54 -+#: ../tools/gnome-session-quit.c:52 - msgid "Power off" - msgstr "關閉電源" - --#: ../tools/gnome-session-quit.c:55 -+#: ../tools/gnome-session-quit.c:53 - msgid "Reboot" - msgstr "重新開機" - --#: ../tools/gnome-session-quit.c:56 -+#: ../tools/gnome-session-quit.c:54 - msgid "Ignoring any existing inhibitors" - msgstr "忽略任何現有的限制因素" - --#: ../tools/gnome-session-quit.c:57 -+#: ../tools/gnome-session-quit.c:55 - msgid "Don't prompt for user confirmation" - msgstr "無需使用者確認" - --#: ../tools/gnome-session-quit.c:91 ../tools/gnome-session-quit.c:101 --msgid "Could not connect to the session manager" --msgstr "無法連接作業階段總管" -- --#: ../tools/gnome-session-quit.c:203 -+#: ../tools/gnome-session-quit.c:201 - msgid "Program called with conflicting options" - msgstr "以相衝突的選項呼叫程式" -- --#~ msgid "Some programs are still running:" --#~ msgstr "有些程式仍在執行中:" -- --#~ msgid "Unknown" --#~ msgstr "不明" -- --#~ msgid "A program is still running:" --#~ msgstr "一個程式仍在執行中:" -- --#~ msgid "" --#~ "Waiting for the program to finish. Interrupting the program may cause you " --#~ "to lose work." --#~ msgstr "正在等待程式結束。中斷這個程式可能造成您的工作遺失。" -- --#~ msgid "" --#~ "Waiting for programs to finish. Interrupting these programs may cause you " --#~ "to lose work." --#~ msgstr "正在等待程式結束。中斷這些程式可能造成您進行中的工作遺失。" -- --#~ msgid "Switch User Anyway" --#~ msgstr "強制切換使用者" -- --#~ msgid "Log Out Anyway" --#~ msgstr "強制登出" -- --#~ msgid "Suspend Anyway" --#~ msgstr "強制暫停" -- --#~ msgid "Hibernate Anyway" --#~ msgstr "強制休眠" -- --#~ msgid "Shut Down Anyway" --#~ msgstr "強制關閉電腦" -- --#~ msgid "Restart Anyway" --#~ msgstr "強制重新啟動" -- --#~ msgid "Lock Screen" --#~ msgstr "鎖定螢幕" -- --#~ msgid "Cancel" --#~ msgstr "取消" -- --#~ msgid "You will be automatically logged out in %d second." --#~ msgid_plural "You will be automatically logged out in %d seconds." --#~ msgstr[0] "您會在 %d 秒後自動登出。" -- --#~ msgid "This system will be automatically shut down in %d second." --#~ msgid_plural "This system will be automatically shut down in %d seconds." --#~ msgstr[0] "本系統會在 %d 秒後自動關閉。" -- --#~ msgid "This system will be automatically restarted in %d second." --#~ msgid_plural "This system will be automatically restarted in %d seconds." --#~ msgstr[0] "本系統會在 %d 秒後自動重新啟動。" -- --#~ msgid "You are currently logged in as \"%s\"." --#~ msgstr "您目前以「%s」的身分登入。" -- --#~ msgid "Log out of this system now?" --#~ msgstr "是否立刻登出系統?" -- --#~ msgid "_Switch User" --#~ msgstr "切換使用者(_S)" -- --#~ msgid "Shut down this system now?" --#~ msgstr "是否立刻關閉這個系統?" -- --#~ msgid "S_uspend" --#~ msgstr "暫停(_U)" -- --#~ msgid "_Hibernate" --#~ msgstr "休眠(_H)" -- --#~ msgid "_Restart" --#~ msgstr "重新啟動(_R)" -- --#~ msgid "_Shut Down" --#~ msgstr "關閉電腦(_S)" -- --#~ msgid "Restart this system now?" --#~ msgstr "是否立刻重新啟動系統?" -- --#~ msgid "Icon '%s' not found" --#~ msgstr "找不到圖示「%s」" -- --#~ msgid "GNOME 3 Failed to Load" --#~ msgstr "GNOME 3 無法載入" -- --#~ msgid "" --#~ "Unfortunately GNOME 3 failed to start properly and started in the " --#~ "fallback mode.\n" --#~ "\n" --#~ "This most likely means your system (graphics hardware or driver) is not " --#~ "capable of delivering the full GNOME 3 experience." --#~ msgstr "" --#~ "很不幸的 GNOME 3 無法正常啟動而必須以後備模式啟動。\n" --#~ "\n" --#~ "這通常代表您的系統 (圖形硬體或驅動程式) 無法完整呈現 GNOME 3 的體驗。" -- --#~ msgid "Learn more about GNOME 3" --#~ msgstr "獲取更多有關 GNOME 3 的資訊" -- --#~ msgid "" --#~ "Unable to start login session (and unable to connect to the X server)" --#~ msgstr "無法啟動登入作業階段(並且無法連線至 X 伺服器)" -- --#~ msgid "Exited with code %d" --#~ msgstr "程式以代碼 %d 結束" -- --#~ msgid "Killed by signal %d" --#~ msgstr "以訊號 %d 終止" -- --#~ msgid "Stopped by signal %d" --#~ msgstr "以訊號 %d 停止" -- --#~ msgid "Some programs are still running:" --#~ msgstr "某些程式仍在執行:" diff --git a/SPECS/gnome-session.spec b/SPECS/gnome-session.spec index 599facc..363075b 100644 --- a/SPECS/gnome-session.spec +++ b/SPECS/gnome-session.spec @@ -1,26 +1,42 @@ %global _changelog_trimtime %(date +%s -d "1 year ago") %define po_package gnome-session-3.0 -%define _default_patch_fuzz 2 Summary: GNOME session manager Name: gnome-session -Version: 3.14.0 -Release: 5%{?dist} +Version: 3.22.3 +Release: 4%{?dist} URL: http://www.gnome.org #VCS: git:git://git.gnome.org/gnome-session -Source0: http://download.gnome.org/sources/gnome-session/3.14/%{name}-%{version}.tar.xz +Source0: http://download.gnome.org/sources/gnome-session/3.22/%{name}-%{version}.tar.xz # Blacklist NV30: https://bugzilla.redhat.com/show_bug.cgi?id=745202 -Patch1: gnome-session-3.3.92-nv30.patch -Patch2: 0001-main-Set-XDG_MENU_PREFIX.patch -Patch3: gnome-session-3.6.2-swrast.patch +Patch00:gnome-session-3.3.92-nv30.patch +Patch01: gnome-session-3.6.2-swrast.patch # https://bugzilla.redhat.com/show_bug.cgi?id=1031182 # https://bugzilla.redhat.com/show_bug.cgi?id=1031188 -Patch7: custom-sessions.patch - -Patch8: gnome-session-3.14.0-EL7.3_translations.patch +Patch02: 0001-Revert-Remove-all-references-to-gnome-session-proper.patch +Patch03: 0002-Revert-Remove-gnome-session-properties.patch +Patch04: 0003-Revert-Rename-the-desktop-file-to-gnome-session-prop.patch +Patch05: 0004-stop-using-gsm_util_get_current_desktop.patch +Patch06: 0005-session-properties-get-out-of-Other.patch +Patch07: 0006-session-properties-refresh-from-recent-glade.patch +Patch08: 0007-manager-Don-t-clear-saved-session-if-autosaving-is-d.patch +Patch09: 0008-Add-Remember-Currently-Running-Applications-button.patch +Patch10: 0009-Revert-Allow-saved-session-to-be-a-symlink.patch +Patch11: 0010-Allow-saved-session-directory-to-be-a-symlink.patch +Patch12: 0011-Tie-session-selector-to-properties-dialog.patch +Patch13: 0012-make-save-session-stall-until-it-finishes.patch +Patch14: 0013-manager-save-session-type-in-session-dir.patch +Patch15: 0014-session-selector-restore-saved-session-mode.patch +Patch16: 0015-session-selector-refresh-from-recent-glade.patch +Patch17: 0016-session-selector-add-toggle-for-classic-normal-selec.patch +Patch18: 0017-session-selector-use-classic-mode-by-default.patch +Patch19: 0018-manager-port-away-from-dbus-glib-to-GDBus.patch +Patch20: 0019-capplet-fix-disable-check-items.patch + +Patch30: 0001-fail-whale-handle-X-server-dying-before-startup.patch License: GPLv2+ Group: User Interface/Desktops @@ -37,20 +53,28 @@ Requires: dbus-x11 # https://bugzilla.redhat.com/show_bug.cgi?id=1072801 Requires: mesa-dri-drivers -BuildRequires: gtk3-devel >= 2.99.0 -BuildRequires: dbus-glib-devel -BuildRequires: gnome-desktop3-devel -BuildRequires: libnotify-devel >= 0.7.0 +BuildRequires: pkgconfig(egl) +BuildRequires: pkgconfig(epoxy) +BuildRequires: pkgconfig(gl) +BuildRequires: pkgconfig(glesv2) +BuildRequires: pkgconfig(gnome-desktop-3.0) +BuildRequires: pkgconfig(gtk+-3.0) +BuildRequires: pkgconfig(libsystemd) +BuildRequires: pkgconfig(ice) +BuildRequires: pkgconfig(json-glib-1.0) +BuildRequires: pkgconfig(sm) +BuildRequires: pkgconfig(x11) +BuildRequires: pkgconfig(xau) +BuildRequires: pkgconfig(xcomposite) +BuildRequires: pkgconfig(xext) +BuildRequires: pkgconfig(xrender) +BuildRequires: pkgconfig(xtrans) +BuildRequires: pkgconfig(xtst) BuildRequires: GConf2-devel BuildRequires: pango-devel -BuildRequires: gnome-settings-daemon-devel BuildRequires: desktop-file-utils -BuildRequires: libXau-devel BuildRequires: libXrandr-devel -BuildRequires: xorg-x11-xtrans-devel -BuildRequires: mesa-libGL-devel BuildRequires: librsvg2-devel -BuildRequires: json-glib-devel # this is so the configure checks find /usr/bin/halt etc. BuildRequires: usermode @@ -65,6 +89,7 @@ BuildRequires: upower-devel BuildRequires: gnome-common BuildRequires: systemd-devel BuildRequires: polkit-devel +BuildRequires: git # an artificial requires to make sure we get dconf, for now Requires: dconf @@ -84,19 +109,14 @@ Desktop file to add GNOME to display manager session menu. %package custom-session Summary: A facility to select and store saved sessions Group: User Interface/Desktop -Requires: gnome-session = %{version}-%{release} +Requires: %{name}%{?_isa} = %{version}-%{release} %description custom-session Installs a 'Custom' entry in the display manager session menu that lets the user manage multiple saved sessions. %prep -%setup -q -%patch1 -p1 -b .nv30 -%patch2 -p1 -b .set-xdg-menu-prefix -%patch3 -p1 -b .swrast -%patch7 -p1 -b .custom-sessions -%patch8 -p1 -b .translations +%autosetup -S git echo "ACLOCAL_AMFLAGS = -I m4" >> Makefile.am @@ -109,14 +129,11 @@ autoreconf -i -f make %{?_smp_mflags} V=1 %install -make install DESTDIR=$RPM_BUILD_ROOT INSTALL="install -p" -desktop-file-install --vendor gnome --delete-original \ - --dir $RPM_BUILD_ROOT%{_datadir}/applications \ - --add-only-show-in GNOME \ - $RPM_BUILD_ROOT%{_datadir}/applications/* +%make_install rm -rf $RPM_BUILD_ROOT%{_datadir}/wayland-sessions +rm -rf $RPM_BUILD_ROOT%{_datadir}/xsessions/gnome-xorg.desktop %find_lang %{po_package} @@ -150,18 +167,41 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &>/dev/null || : %doc AUTHORS COPYING NEWS README %doc %{_mandir}/man*/* %{_bindir}/* +%{_libexecdir}/gnome-session-binary %{_libexecdir}/gnome-session-check-accelerated -%{_libexecdir}/gnome-session-check-accelerated-helper +%{_libexecdir}/gnome-session-check-accelerated-gl-helper +%{_libexecdir}/gnome-session-check-accelerated-gles-helper %{_libexecdir}/gnome-session-failed -%{_datadir}/applications/gnome-session-properties.desktop +%{_datadir}/applications/session-properties.desktop %{_datadir}/gnome-session/ %{_datadir}/doc/gnome-session/dbus/gnome-session.html %{_datadir}/icons/hicolor/*/apps/session-properties.png +%{_datadir}/icons/hicolor/symbolic/apps/session-properties-symbolic.svg %{_datadir}/icons/hicolor/scalable/apps/session-properties.svg %{_datadir}/GConf/gsettings/gnome-session.convert %{_datadir}/glib-2.0/schemas/org.gnome.SessionManager.gschema.xml %changelog +* Tue May 30 2017 Ray Strode - 3.22.3-4 +- fix crash in fail whale + Resolves: #1392970 + +* Mon Mar 27 2017 Ray Strode - 3.22.3-3 +- Fix the ability to disable a service from session properties + Resolves: #1310975 + +* Thu Mar 16 2017 Ray Strode - 3.22.3-2 +- Drop gnome-xorg.desktop + Related: #1386957 + +* Wed Mar 08 2017 Ray Strode - 3.22.3-1 +- Rebase to 3.22.3 + Resolves: #1386957 + +* Mon Jun 27 2016 Ray Strode - 3.14.0-6 +- update ko and it translations + Related: #1272374 + * Mon Apr 4 2016 Matthias Clasen 3.14.0-5 - Update translations Resolves: #1272374