diff options
48 files changed, 3030 insertions, 5762 deletions
diff --git a/Makefile.am b/Makefile.am index d63dac8..8fb5d77 100644 --- a/Makefile.am +++ b/Makefile.am @@ -4,6 +4,12 @@ SUBDIRS = \ data \ po +if BUILD_TESTS +SUBDIRS += tests +# build src first +tests: src +endif + EXTRA_DIST = autogen.sh DISTCHECK_CONFIGURE_FLAGS = --enable-localinstall @@ -34,41 +40,4 @@ dist-hook: echo Failed to generate AUTHORS: not a branch >&2; \ fi -TESTS = \ - test-ellipsis \ - test-space-ellipsis \ - test-ascii-quotes - -##### -# Tests for there being proper ellipsis instead of three periods in a row -##### -test-ellipsis: po - @echo "#!/bin/bash" > $@ - @echo "(cd po && make $(GETTEXT_PACKAGE).pot)" >> $@ - @echo "grep -c -e \"^msgid.*\.\.\.\\\"\" po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"Ellipsis found in user visible strings\" >&2 && exit 1" >> $@ - @echo "exit 0" >> $@ - @chmod +x $@ - -##### -# Tests for there being a space before an ellipsis -##### -test-space-ellipsis: po - @echo "#!/bin/bash" > $@ - @echo "(cd po && make $(GETTEXT_PACKAGE).pot)" >> $@ - @echo "grep -c -e \"^msgid.* …\\\"\" po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"Space before ellipsis found in user visible strings\" >&2 && exit 1" >> $@ - @echo "exit 0" >> $@ - @chmod +x $@ - -##### -# Tests for ASCII quote types -##### -test-ascii-quotes: po - @echo "#!/bin/bash" > $@ - @echo "(cd po && make $(GETTEXT_PACKAGE).pot)" >> $@ - @echo "grep -c -e \"^msgid \\\".*'.*\\\"\" po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"ASCII apostrophy found in user visible strings\" >&2 && exit 1" >> $@ - @echo "grep -c -e \"^msgid \\\".*\\\".*\\\"\" po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"ASCII quote found in user visible strings\" >&2 && exit 1" >> $@ - @echo "grep -c -e \"^msgid \\\".*\\\`.*\\\"\" po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"ASCII backtick found in user visible strings\" >&2 && exit 1" >> $@ - @echo "exit 0" >> $@ - @chmod +x $@ - -CLEANFILES = $(TESTS) +include $(top_srcdir)/Makefile.am.coverage diff --git a/Makefile.am.coverage b/Makefile.am.coverage new file mode 100644 index 0000000..fb97747 --- /dev/null +++ b/Makefile.am.coverage @@ -0,0 +1,48 @@ + +# Coverage targets + +.PHONY: clean-gcno clean-gcda \ + coverage-html generate-coverage-html clean-coverage-html \ + coverage-gcovr generate-coverage-gcovr clean-coverage-gcovr + +clean-local: clean-gcno clean-coverage-html clean-coverage-gcovr + +if HAVE_GCOV + +clean-gcno: + @echo Removing old coverage instrumentation + -find -name '*.gcno' -print | xargs -r rm + +clean-gcda: + @echo Removing old coverage results + -find -name '*.gcda' -print | xargs -r rm + +coverage-html: clean-gcda + -$(MAKE) $(AM_MAKEFLAGS) -k check + $(MAKE) $(AM_MAKEFLAGS) generate-coverage-html + +generate-coverage-html: + @echo Collecting coverage data + $(LCOV) --directory $(top_builddir) --capture --output-file coverage.info --no-checksum --compat-libtool + LANG=C $(GENHTML) --prefix $(top_builddir) --output-directory coveragereport --title "Code Coverage" --legend --show-details coverage.info + +clean-coverage-html: clean-gcda + -$(LCOV) --directory $(top_builddir) -z + -rm -rf coverage.info coveragereport + +if HAVE_GCOVR + +coverage-gcovr: clean-gcda + -$(MAKE) $(AM_MAKEFLAGS) -k check + $(MAKE) $(AM_MAKEFLAGS) generate-coverage-gcovr + +generate-coverage-gcovr: + @echo Generating coverage GCOVR report + $(GCOVR) -x -r $(top_builddir) -o $(top_builddir)/coverage.xml + +clean-coverage-gcovr: clean-gcda + -rm -rf $(top_builddir)/coverage.xml + +endif # HAVE_GCOVR + +endif # HAVE_GCOV diff --git a/configure.ac b/configure.ac index ab12f12..5968927 100644 --- a/configure.ac +++ b/configure.ac @@ -4,7 +4,7 @@ AC_INIT(src/indicator-session.c) AC_PREREQ(2.53) AM_CONFIG_HEADER(config.h) -AM_INIT_AUTOMAKE(indicator-session, 0.3.92) +AM_INIT_AUTOMAKE(indicator-session, 12.10.0) AM_MAINTAINER_MODE @@ -14,6 +14,7 @@ IT_PROG_INTLTOOL([0.35.0]) AC_ISC_POSIX AC_PROG_CC +AC_PROG_CXX AM_PROG_CC_C_O AC_STDC_HEADERS AC_PROG_LIBTOOL @@ -27,66 +28,36 @@ m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) # Dependencies ########################### -GTK_REQUIRED_VERSION=2.12 -GTK3_REQUIRED_VERSION=3.0 +GLIB_REQUIRED_VERSION=2.33 +GTK_REQUIRED_VERSION=3.0 INDICATOR_REQUIRED_VERSION=0.3.19 DBUSMENUGTK_REQUIRED_VERSION=0.5.90 POLKIT_REQUIRED_VERSION=0.92 +DBUSTEST_REQUIRED_VERSION=0.0.5 +DBUSMENUGLIB_REQUIRED_VERSION=0.1.1 -AC_ARG_WITH([gtk], - [AS_HELP_STRING([--with-gtk], - [Which version of gtk to use for the indicator @<:@default=3@:>@])], - [], - [with_gtk=3]) - -AS_IF([test "x$with_gtk" = x3], - [PKG_CHECK_MODULES(APPLET, gtk+-3.0 >= $GTK3_REQUIRED_VERSION - indicator3-0.4 >= $INDICATOR_REQUIRED_VERSION - dbusmenu-gtk3-0.4 >= $DBUSMENUGTK_REQUIRED_VERSION) - ], - [test "x$with_gtk" = x2], - [PKG_CHECK_MODULES(APPLET, gtk+-2.0 >= $GTK_REQUIRED_VERSION - indicator-0.4 >= $INDICATOR_REQUIRED_VERSION - dbusmenu-gtk-0.4 >= $DBUSMENUGTK_REQUIRED_VERSION) - ], - [AC_MSG_FAILURE([Value for --with-indicator-gtk was neither 2 nor 3])] -) +PKG_CHECK_MODULES(APPLET, glib-2.0 >= $GLIB_REQUIRED_VERSION + gtk+-3.0 >= $GTK_REQUIRED_VERSION + indicator3-0.4 >= $INDICATOR_REQUIRED_VERSION + dbusmenu-gtk3-0.4 >= $DBUSMENUGTK_REQUIRED_VERSION) AC_SUBST(APPLET_CFLAGS) AC_SUBST(APPLET_LIBS) -DBUSMENUGLIB_REQUIRED_VERSION=0.1.1 - -AS_IF([test "x$with_gtk" = x3], - [PKG_CHECK_MODULES(SESSIONSERVICE, dbusmenu-glib-0.4 >= $DBUSMENUGLIB_REQUIRED_VERSION - dbusmenu-gtk3-0.4 >= $DBUSMENUGTK_REQUIRED_VERSION - dbus-glib-1 - gio-unix-2.0 - indicator3-0.4 >= $INDICATOR_REQUIRED_VERSION - packagekit-glib2) - ], - [test "x$with_gtk" = x2], - [PKG_CHECK_MODULES(SESSIONSERVICE, dbusmenu-glib-0.4 >= $DBUSMENUGLIB_REQUIRED_VERSION - dbusmenu-gtk-0.4 >= $DBUSMENUGTK_REQUIRED_VERSION - dbus-glib-1 - gio-unix-2.0 - indicator-0.4 >= $INDICATOR_REQUIRED_VERSION - packagekit-glib2) - ] -) +PKG_CHECK_MODULES(SESSIONSERVICE, glib-2.0 >= $GLIB_REQUIRED_VERSION + dbusmenu-glib-0.4 >= $DBUSMENUGLIB_REQUIRED_VERSION + dbusmenu-gtk3-0.4 >= $DBUSMENUGTK_REQUIRED_VERSION + dbus-glib-1 + gio-unix-2.0 + indicator3-0.4 >= $INDICATOR_REQUIRED_VERSION + packagekit-glib2) AC_SUBST(SESSIONERVICE_CFLAGS) AC_SUBST(SESSIONERVICE_LIBS) -PKG_CHECK_MODULES(GUDEV, gudev-1.0, has_gudev=true, has_gudev=false) AC_SUBST(GUDEV_CFLAGS) AC_SUBST(GUDEV_LIBS) -AM_CONDITIONAL([USE_GTK3], [test "x$with_gtk" = "x3"]) -AS_IF([test "x$with_gtk" = x3], [ - AC_DEFINE(HAVE_GTK3, 1, [whether gtk3 is available]) - ]) - ########################### # GTK Logout Helper ########################### @@ -96,19 +67,10 @@ AC_ARG_ENABLE([gtklogouthelper], enable_gtklogouthelper=auto) if test x"$enable_gtklogouthelper" != x"no" ; then - AS_IF([test "x$with_gtk" = x3], - [PKG_CHECK_MODULES(GTKLOGOUTHELPER, gtk+-3.0 >= $GTK3_REQUIRED_VERSION - polkit-gobject-1 >= $POLKIT_REQUIRED_VERSION, - [have_gtklogouthelper=yes], - [have_gtklogouthelper=no]) - ], - [test "x$with_gtk" = x2], - [PKG_CHECK_MODULES(GTKLOGOUTHELPER, gtk+-2.0 >= $GTK_REQUIRED_VERSION - polkit-gobject-1 >= $POLKIT_REQUIRED_VERSION, - [have_gtklogouthelper=yes], - [have_gtklogouthelper=no]) - ] - ) + PKG_CHECK_MODULES(GTKLOGOUTHELPER, gtk+-3.0 >= $GTK_REQUIRED_VERSION + polkit-gobject-1 >= $POLKIT_REQUIRED_VERSION, + [have_gtklogouthelper=yes], + [have_gtklogouthelper=no]) if test x${have_gtklogouthelper} = xyes; then AC_DEFINE(HAVE_GTKLOGOUTHELPER, 1, [Define to 1 to enable GTK Logout Helper]) fi @@ -124,18 +86,6 @@ AC_SUBST(GTKLOGOUTHELPER_CFLAGS) AC_SUBST(GTKLOGOUTHELPER_LIBS) ########################### -# APT support -########################### -AC_ARG_ENABLE([apt], - AC_HELP_STRING([--disable-apt], [disable APT support]),, - [enable_apt=yes]) -AM_CONDITIONAL([BUILD_APT], [test "x$enable_apt" != "xno"]) - -if test "x$enable_apt" != "xno"; then - AC_DEFINE(HAVE_APT, 1, [Define to 1 to enable APT support]) -fi - -########################### # Check to see if we're local ########################### @@ -170,6 +120,35 @@ else fi AC_SUBST(DBUSSERVICEDIR) +########################### +# Google Test framework +########################### + +AC_ARG_ENABLE([tests], + [AS_HELP_STRING([--disable-tests], [Disable test scripts and tools (default=auto)])], + [enable_tests=${enableval}], + [enable_tests=auto]) +if test "x$enable_tests" != "xno"; then + m4_include([m4/gtest.m4]) + CHECK_GTEST + CHECK_XORG_GTEST + if test "x$enable_tests" = "xauto"; then + enable_tests=${have_gtest} + elif test "x$enable_tests" = "xyes" && test "x$have_gtest" != "xyes"; then + AC_MSG_ERROR([tests were requested but gtest is not installed.]) + fi + if test "x$enable_tests" = "xyes"; then + PKG_CHECK_MODULES([TEST_SERVICE],[indicator3-0.4 >= $INDICATOR_REQUIRED_VERSION + dbustest-1 >= $DBUSTEST_REQUIRED_VERSION + dbusmenu-glib-0.4 >= $DBUSMENUGLIB_REQUIRED_VERSION], + [enable_tests="yes"], + [enable_tests="no"]) + fi +fi +AM_CONDITIONAL([BUILD_TESTS],[test "x$enable_tests" = "xyes"]) +AC_SUBST([TEST_SERVICE_CFLAGS]) +AC_SUBST([TEST_SERVICE_LDFLAGS]) + ############################## # Custom Junk ############################## @@ -198,10 +177,20 @@ AC_DEFINE_PATH(GNOMELOCALEDIR, "${datadir}/locale", [locale directory]) AM_GLIB_GNU_GETTEXT ########################### -# Files +# gcov coverage reporting ########################### -AM_CONDITIONAL([HAS_GUDEV], [test "x$has_gudev" = "xtrue"]) +m4_include([m4/gcov.m4]) +AC_TDD_GCOV +AM_CONDITIONAL([HAVE_GCOV], [test "x$ac_cv_check_gcov" = xyes]) +AM_CONDITIONAL([HAVE_LCOV], [test "x$ac_cv_check_lcov" = xyes]) +AM_CONDITIONAL([HAVE_GCOVR], [test "x$ac_cv_check_gcovr" = xyes]) +AC_SUBST(COVERAGE_CFLAGS) +AC_SUBST(COVERAGE_LDFLAGS) + +########################### +# Files +########################### AC_CONFIG_FILES([ Makefile @@ -224,6 +213,7 @@ data/icons/scalable/Makefile data/icons/scalable/actions/Makefile data/icons/scalable/status/Makefile data/extra-sessions/Makefile +tests/Makefile po/Makefile.in ]) @@ -237,9 +227,9 @@ AC_MSG_NOTICE([ SUS Indicator Configuration: - Prefix: $prefix - Indicator Dir: $INDICATORDIR - Indicator GTK: $with_gtk - Logout Helper: $have_gtklogouthelper - APT support: $enable_apt + Prefix: $prefix + Indicator Dir: $INDICATORDIR + Logout Helper: $have_gtklogouthelper + Unit Tests: $enable_tests + Coverage reporting: $use_gcov ]) diff --git a/data/Makefile.am b/data/Makefile.am index 3b8de1f..27b5ea2 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -25,30 +25,3 @@ EXTRA_DIST = \ CLEANFILES = \ $(dbus_services_DATA) \ $(gsettings_SCHEMAS) - -if BUILD_GTKLOGOUTHELPER -@INTLTOOL_DESKTOP_RULE@ - -%.desktop.in: %.desktop.in.in - sed \ - -e "s|\@libexecdir\@|$(libexecdir)|" \ - -e "s|\@bindir\@|$(bindir)|" \ - $< > $@ - -logout_helper_desktop_in_in_files = \ - indicator-session-lock-screen.desktop.in.in \ - indicator-session-logout.desktop.in.in \ - indicator-session-restart.desktop.in.in \ - indicator-session-shutdown.desktop.in.in - -logout_helperdir = $(datadir)/applications -logout_helper_desktop_files = \ - $(logout_helper_desktop_in_in_files:.desktop.in.in=.desktop) -logout_helper_DATA = $(logout_helper_desktop_files) - -EXTRA_DIST += \ - $(logout_helper_desktop_in_in_files) - -CLEANFILES += \ - $(logout_helper_desktop_files) -endif diff --git a/data/com.canonical.indicator.session.gschema.xml.in b/data/com.canonical.indicator.session.gschema.xml.in index 0ef3d00..6010b3f 100644 --- a/data/com.canonical.indicator.session.gschema.xml.in +++ b/data/com.canonical.indicator.session.gschema.xml.in @@ -21,21 +21,10 @@ <_description>Makes it so that the shutdown button doesn’t show in the session menu.</_description> </key> <key type="b" name="show-real-name-on-panel"> - <default>true</default> + <default>false</default> <summary>Determine the visibility of the User's real name on the panel</summary> <description>Allow for the Removal of the users name from the panel</description> </key> - <key type="b" name="user-show-menu"> - <default>true</default> - <summary>Determine the visibility of the User Menu</summary> - <description>Allow for the user menu to be hidden by the user.</description> - </key> - <key type="b" name="use-username-in-switch-item"> - <default>false</default> - <summary>Determine what string to use for the user's name in the switch menuitem.</summary> - <description>The switch menuitem as part of the user menu should be default have the label 'Switch User Account'. - This settings gives the user the potential to have the label read 'Switch from $username'</description> - </key> </schema> diff --git a/data/indicator-session-lock-screen.desktop.in.in b/data/indicator-session-lock-screen.desktop.in.in deleted file mode 100644 index c414402..0000000 --- a/data/indicator-session-lock-screen.desktop.in.in +++ /dev/null @@ -1,10 +0,0 @@ -[Desktop Entry] -_Name=Lock Screen -TryExec=@bindir@/xdg-screensaver -Exec=@bindir@/xdg-screensaver lock -Icon=system-lock-screen -Terminal=false -Type=Application -OnlyShowIn=Unity; -Categories=System; -Version=1.0 diff --git a/data/indicator-session-logout.desktop.in.in b/data/indicator-session-logout.desktop.in.in deleted file mode 100644 index 800324e..0000000 --- a/data/indicator-session-logout.desktop.in.in +++ /dev/null @@ -1,10 +0,0 @@ -[Desktop Entry] -_Name=Log Out -TryExec=@libexecdir@/gtk-logout-helper -Exec=@libexecdir@/gtk-logout-helper --logout -Icon=system-log-out -Terminal=false -Type=Application -OnlyShowIn=Unity; -Categories=System; -Version=1.0 diff --git a/data/indicator-session-restart.desktop.in.in b/data/indicator-session-restart.desktop.in.in deleted file mode 100644 index 51acded..0000000 --- a/data/indicator-session-restart.desktop.in.in +++ /dev/null @@ -1,10 +0,0 @@ -[Desktop Entry] -_Name=Restart -TryExec=@libexecdir@/gtk-logout-helper -Exec=@libexecdir@/gtk-logout-helper --restart -Icon=system-restart -Terminal=false -Type=Application -OnlyShowIn=Unity; -Categories=System; -Version=1.0 diff --git a/data/indicator-session-shutdown.desktop.in.in b/data/indicator-session-shutdown.desktop.in.in deleted file mode 100644 index 4603fd1..0000000 --- a/data/indicator-session-shutdown.desktop.in.in +++ /dev/null @@ -1,10 +0,0 @@ -[Desktop Entry] -_Name=Shut Down -TryExec=@libexecdir@/gtk-logout-helper -Exec=@libexecdir@/gtk-logout-helper --shutdown -Icon=system-shutdown -Terminal=false -Type=Application -OnlyShowIn=Unity; -Categories=System; -Version=1.0 diff --git a/m4/gcov.m4 b/m4/gcov.m4 new file mode 100644 index 0000000..3163584 --- /dev/null +++ b/m4/gcov.m4 @@ -0,0 +1,86 @@ +# Checks for existence of coverage tools: +# * gcov +# * lcov +# * genhtml +# * gcovr +# +# Sets ac_cv_check_gcov to yes if tooling is present +# and reports the executables to the variables LCOV, GCOVR and GENHTML. +AC_DEFUN([AC_TDD_GCOV], +[ + AC_ARG_ENABLE(gcov, + AS_HELP_STRING([--enable-gcov], + [enable coverage testing with gcov]), + [use_gcov=$enableval], [use_gcov=no]) + + if test "x$use_gcov" = "xyes"; then + # we need gcc: + if test "$GCC" != "yes"; then + AC_MSG_ERROR([GCC is required for --enable-gcov]) + fi + + # Check if ccache is being used + AC_CHECK_PROG(SHTOOL, shtool, shtool) + case `$SHTOOL path $CC` in + *ccache*[)] gcc_ccache=yes;; + *[)] gcc_ccache=no;; + esac + + if test "$gcc_ccache" = "yes" && (test -z "$CCACHE_DISABLE" || test "$CCACHE_DISABLE" != "1"); then + AC_MSG_ERROR([ccache must be disabled when --enable-gcov option is used. You can disable ccache by setting environment variable CCACHE_DISABLE=1.]) + fi + + lcov_version_list="1.6 1.7 1.8 1.9" + AC_CHECK_PROG(LCOV, lcov, lcov) + AC_CHECK_PROG(GENHTML, genhtml, genhtml) + + if test "$LCOV"; then + AC_CACHE_CHECK([for lcov version], glib_cv_lcov_version, [ + glib_cv_lcov_version=invalid + lcov_version=`$LCOV -v 2>/dev/null | $SED -e 's/^.* //'` + for lcov_check_version in $lcov_version_list; do + if test "$lcov_version" = "$lcov_check_version"; then + glib_cv_lcov_version="$lcov_check_version (ok)" + fi + done + ]) + else + lcov_msg="To enable code coverage reporting you must have one of the following lcov versions installed: $lcov_version_list" + AC_MSG_ERROR([$lcov_msg]) + fi + + case $glib_cv_lcov_version in + ""|invalid[)] + lcov_msg="You must have one of the following versions of lcov: $lcov_version_list (found: $lcov_version)." + AC_MSG_ERROR([$lcov_msg]) + LCOV="exit 0;" + ;; + esac + + if test -z "$GENHTML"; then + AC_MSG_ERROR([Could not find genhtml from the lcov package]) + fi + + ac_cv_check_gcov=yes + ac_cv_check_lcov=yes + + # Remove all optimization flags from CFLAGS + changequote({,}) + CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9]*//g'` + changequote([,]) + + # Add the special gcc flags + COVERAGE_CFLAGS="-O0 -fprofile-arcs -ftest-coverage" + COVERAGE_CXXFLAGS="-O0 -fprofile-arcs -ftest-coverage" + COVERAGE_LDFLAGS="-lgcov" + + # Check availability of gcovr + AC_CHECK_PROG(GCOVR, gcovr, gcovr) + if test -z "$GCOVR"; then + ac_cv_check_gcovr=no + else + ac_cv_check_gcovr=yes + fi + +fi +]) # AC_TDD_GCOV diff --git a/m4/gtest.m4 b/m4/gtest.m4 new file mode 100644 index 0000000..2de334c --- /dev/null +++ b/m4/gtest.m4 @@ -0,0 +1,63 @@ +# Copyright (C) 2012 Canonical, Ltd. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# Checks whether the gtest source is available on the system. Allows for +# adjusting the include and source path. Sets have_gtest=yes if the source is +# present. Sets GTEST_CPPFLAGS and GTEST_SOURCE to the preprocessor flags and +# source location respectively. +AC_DEFUN([CHECK_GTEST], +[ + AC_ARG_WITH([gtest-include-path], + [AS_HELP_STRING([--with-gtest-include-path], + [location of the Google test headers])], + [GTEST_CPPFLAGS="-I$withval"]) + + AC_ARG_WITH([gtest-source-path], + [AS_HELP_STRING([--with-gtest-source-path], + [location of the Google test sources, defaults to /usr/src/gtest])], + [GTEST_SOURCE="$withval"], + [GTEST_SOURCE="/usr/src/gtest"]) + + GTEST_CPPFLAGS="$GTEST_CPPFLAGS -I$GTEST_SOURCE" + + AC_LANG_PUSH([C++]) + + tmp_CPPFLAGS="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $GTEST_CPPFLAGS" + + AC_CHECK_HEADER([gtest/gtest.h]) + + CPPFLAGS="$tmp_CPPFLAGS" + + AC_LANG_POP + + AC_CHECK_FILES([$GTEST_SOURCE/src/gtest-all.cc] + [$GTEST_SOURCE/src/gtest_main.cc], + [have_gtest_source=yes], + [have_gtest_source=no]) + + AS_IF([test "x$ac_cv_header_gtest_gtest_h" = xyes -a \ + "x$have_gtest_source" = xyes], + [have_gtest=yes] + [AC_SUBST(GTEST_CPPFLAGS)] + [AC_SUBST(GTEST_SOURCE)], + [have_gtest=no]) +]) # CHECK_GTEST diff --git a/po/POTFILES.in b/po/POTFILES.in index 18b5d9b..6392590 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,17 +1,13 @@ [encoding: UTF-8] data/com.canonical.indicator.session.gschema.xml.in data/extra-sessions/classic-desktop.desktop.in.in -data/indicator-session-lock-screen.desktop.in.in -data/indicator-session-shutdown.desktop.in.in -data/indicator-session-logout.desktop.in.in -data/indicator-session-restart.desktop.in.in -src/settings-helper.c -src/lock-helper.c -src/gtk-logout-helper.c src/dialog.c +src/gen-session-dbus.xml.c +src/gtk-logout-helper.c src/indicator-session.c +src/session-dbus.c +src/session-menu-mgr.c src/session-service.c -src/apt-watcher.c -src/device-menu-mgr.c -src/user-menu-mgr.c -src/udev-mgr.c +src/users-service-dbus.c +src/user-widget.c + diff --git a/src/Makefile.am b/src/Makefile.am index 2201da0..b28ca4a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,4 @@ - +CLEANFILES = EXTRA_DIST = libexec_PROGRAMS = \ @@ -13,72 +13,96 @@ endif # Indicator Stuff ################### +CLEANFILES += .libs/*.gcda .libs/*.gcno *.gcda *.gcno + sessionlibdir = $(INDICATORDIR) sessionlib_LTLIBRARIES = libsession.la libsession_la_SOURCES = \ indicator-session.c \ gen-session-dbus.xml.h \ - dbus-shared-names.h \ - dbusmenu-shared.h \ + shared-names.h \ user-widget.c \ - user-widget.h \ - accounts-service-client.h \ - accounts-service-user-client.h + user-widget.h libsession_la_CFLAGS = \ $(APPLET_CFLAGS) \ - -Wall -Werror \ + $(COVERAGE_CFLAGS) \ + -Wall -Wunused \ -DG_LOG_DOMAIN=\"Indicator-Session\" libsession_la_LIBADD = $(APPLET_LIBS) -libsession_la_LDFLAGS = -module -avoid-version - -consolekit-manager-client.h: $(srcdir)/org.freedesktop.ConsoleKit.Manager.xml - dbus-binding-tool \ - --prefix=_consolekit_manager_client \ - --mode=glib-client \ - --output=consolekit-manager-client.h \ - $(srcdir)/org.freedesktop.ConsoleKit.Manager.xml - -consolekit-seat-client.h: $(srcdir)/org.freedesktop.ConsoleKit.Seat.xml - dbus-binding-tool \ - --prefix=_consolekit_seat_client \ - --mode=glib-client \ - --output=consolekit-seat-client.h \ - $(srcdir)/org.freedesktop.ConsoleKit.Seat.xml - -consolekit-session-client.h: $(srcdir)/org.freedesktop.ConsoleKit.Session.xml - dbus-binding-tool \ - --prefix=_consolekit_session_client \ - --mode=glib-client \ - --output=consolekit-session-client.h \ - $(srcdir)/org.freedesktop.ConsoleKit.Session.xml - -display-manager-client.h: $(srcdir)/display-manager.xml - dbus-binding-tool \ - --prefix=_gdm_local_display_factory_client \ - --mode=glib-client \ - --output=display-manager-client.h \ - $(srcdir)/display-manager.xml - -accounts-service-client.h: $(srcdir)/accounts-service.xml - dbus-binding-tool \ - --prefix=_accounts_service_client \ - --mode=glib-client \ - --output=accounts-service-client.h \ - $(srcdir)/accounts-service.xml - -accounts-service-user-client.h: $(srcdir)/accounts-service-user.xml - dbus-binding-tool \ - --prefix=_accounts_service_user_client \ - --mode=glib-client \ - --output=accounts-service-user-client.h \ - $(srcdir)/accounts-service-user.xml - -upower-client.h: $(srcdir)/upower.xml - dbus-binding-tool \ - --prefix=_upower_client \ - --mode=glib-client \ - --output=upower-client.h \ - $(srcdir)/upower.xml +libsession_la_LDFLAGS = \ + $(COVERAGE_LDFLAGS) \ + -module -avoid-version + +dbus_display_manager_sources = \ + dbus-display-manager.c \ + dbus-display-manager.h + +$(dbus_display_manager_sources): display-manager.xml + gdbus-codegen \ + --interface-prefix org.freedesktop \ + --generate-c-code dbus-display-manager \ + $^ + +dbus_consolekit_manager_sources = \ + dbus-consolekit-manager.c \ + dbus-consolekit-manager.h + +$(dbus_consolekit_manager_sources): org.freedesktop.ConsoleKit.Manager.xml + gdbus-codegen \ + --interface-prefix org.freedesktop \ + --generate-c-code dbus-consolekit-manager \ + $^ + +dbus_consolekit_seat_sources = \ + dbus-consolekit-seat.c \ + dbus-consolekit-seat.h + +$(dbus_consolekit_seat_sources): org.freedesktop.ConsoleKit.Seat.xml + gdbus-codegen \ + --interface-prefix org.freedesktop \ + --generate-c-code dbus-consolekit-seat \ + $^ + +dbus_consolekit_session_sources = \ + dbus-consolekit-session.c \ + dbus-consolekit-session.h + +$(dbus_consolekit_session_sources): org.freedesktop.ConsoleKit.Session.xml + gdbus-codegen \ + --interface-prefix org.freedesktop \ + --generate-c-code dbus-consolekit-session \ + $^ + +dbus_accounts_sources = \ + dbus-accounts.c \ + dbus-accounts.h + +$(dbus_accounts_sources): org.freedesktop.Accounts.xml + gdbus-codegen \ + --interface-prefix org.freedesktop \ + --generate-c-code dbus-accounts \ + $^ + +dbus_user_sources = \ + dbus-user.c \ + dbus-user.h + +$(dbus_user_sources): org.freedesktop.Accounts.User.xml + gdbus-codegen \ + --interface-prefix org.freedesktop \ + --generate-c-code dbus-user \ + $^ + +dbus_upower_sources = \ + dbus-upower.c \ + dbus-upower.h + +$(dbus_upower_sources): upower.xml + gdbus-codegen \ + --interface-prefix org.freedesktop \ + --generate-c-code dbus-upower \ + --c-namespace DBus \ + $^ gen-%.xml.c: %.xml @echo "Building $@ from $<" @@ -95,55 +119,36 @@ gen-%.xml.h: %.xml ################# indicator_session_service_SOURCES = \ - lock-helper.c \ - lock-helper.h \ + $(dbus_accounts_sources) \ + $(dbus_consolekit_manager_sources) \ + $(dbus_consolekit_seat_sources) \ + $(dbus_consolekit_session_sources) \ + $(dbus_display_manager_sources) \ + $(dbus_upower_sources) \ + $(dbus_user_sources) \ session-service.c \ session-dbus.c \ session-dbus.h \ gen-session-dbus.xml.c \ - dbusmenu-shared.h \ - settings-helper.c \ users-service-dbus.h \ users-service-dbus.c \ - user-menu-mgr.h \ - user-menu-mgr.c \ - device-menu-mgr.h \ - device-menu-mgr.c \ - sane-rules.h \ + session-menu-mgr.h \ + session-menu-mgr.c \ webcredentials-mgr.c \ webcredentials-mgr.h -if BUILD_APT -indicator_session_service_SOURCES += \ - apt-watcher.h \ - apt-watcher.c -else -EXTRA_DIST += \ - apt-watcher.h \ - apt-watcher.c -endif - -if HAS_GUDEV -indicator_session_service_SOURCES += \ - udev-mgr.h \ - udev-mgr.c -else -EXTRA_DIST += \ - udev-mgr.h \ - udev-mgr.c -endif - indicator_session_service_CFLAGS = \ $(SESSIONSERVICE_CFLAGS) \ $(GCONF_CFLAGS) \ -DLIBEXECDIR=\"$(libexecdir)\" \ - -Wall -Werror \ + -Wall \ -DG_LOG_DOMAIN=\"Indicator-Session\" \ - $(GUDEV_CFLAGS) + $(COVERAGE_CFLAGS) indicator_session_service_LDADD = \ $(SESSIONSERVICE_LIBS) \ - $(GCONF_LIBS) \ - $(GUDEV_LIBS) + $(GCONF_LIBS) +indicator_session_service_LDFLAGS = \ + $(COVERAGE_LDFLAGS) ################# # GTK Logout Stuff @@ -151,9 +156,8 @@ indicator_session_service_LDADD = \ if BUILD_GTKLOGOUTHELPER gtk_logout_helper_SOURCES = \ + $(dbus_consolekit_manager_sources) \ gtk-logout-helper.c \ - settings-helper.c \ - settings-helper.h \ dialog.c \ dialog.h @@ -161,13 +165,17 @@ gtk_logout_helper_CFLAGS = \ $(SESSIONSERVICE_CFLAGS) \ $(GTKLOGOUTHELPER_CFLAGS) \ $(GCONF_CFLAGS) \ - -Wall -Werror \ + $(COVERAGE_CFLAGS) \ + -Wall \ -DINDICATOR_ICONS_DIR="\"$(INDICATORICONSDIR)\"" gtk_logout_helper_LDADD = \ $(SESSIONSERVICE_LIBS) \ $(GTKLOGOUTHELPER_LIBS) \ $(GCONF_LIBS) + +gtk_logout_helper_LDFLAGS = \ + $(COVERAGE_LDFLAGS) endif @@ -176,25 +184,24 @@ endif ############### BUILT_SOURCES = \ - consolekit-manager-client.h \ - consolekit-seat-client.h \ - consolekit-session-client.h \ - display-manager-client.h \ + $(dbus_accounts_sources) \ + $(dbus_consolekit_manager_sources) \ + $(dbus_consolekit_seat_sources) \ + $(dbus_consolekit_session_sources) \ + $(dbus_display_manager_sources) \ + $(dbus_upower_sources) \ + $(dbus_user_sources) \ gen-session-dbus.xml.c \ - gen-session-dbus.xml.h \ - upower-client.h \ - accounts-service-client.h \ - accounts-service-user-client.h + gen-session-dbus.xml.h EXTRA_DIST += \ + display-manager.xml \ + org.freedesktop.Accounts.User.xml \ + org.freedesktop.Accounts.xml \ org.freedesktop.ConsoleKit.Manager.xml \ org.freedesktop.ConsoleKit.Seat.xml \ org.freedesktop.ConsoleKit.Session.xml \ - display-manager.xml \ session-dbus.xml \ - upower.xml \ - accounts-service.xml \ - accounts-service-user.xml + upower.xml -CLEANFILES = \ - $(BUILT_SOURCES) +CLEANFILES += $(BUILT_SOURCES) diff --git a/src/apt-watcher.c b/src/apt-watcher.c deleted file mode 100644 index c638a93..0000000 --- a/src/apt-watcher.c +++ /dev/null @@ -1,282 +0,0 @@ -/* -Copyright 2011 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>. -*/ - -// Conor - 6/2/2012 -// Please pull in packagekit's client lib -// using apt-get install --no-install-recommends libpackagekit-glib2-dev -// make sure you don't install package-kit -#define I_KNOW_THE_PACKAGEKIT_GLIB2_API_IS_SUBJECT_TO_CHANGE - -#include <glib/gi18n.h> -#include <packagekit-glib2/packagekit.h> -#include "apt-watcher.h" -#include "dbus-shared-names.h" - -static guint watcher_id; - -struct _AptWatcher -{ - GObject parent_instance; - SessionDbus* session_dbus_interface; - DbusmenuMenuitem* apt_item; - AptState current_state; - GCancellable * proxy_cancel; - GDBusProxy * proxy; -}; - -G_DEFINE_TYPE (AptWatcher, apt_watcher, G_TYPE_OBJECT); - - -static void -get_updates_complete (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - g_return_if_fail (APT_IS_WATCHER (user_data)); - AptWatcher* self = APT_WATCHER (user_data); - - PkResults *results; - GError *error = NULL; - results = pk_client_generic_finish (PK_CLIENT(source_object), res, &error); - - if (error != NULL){ - g_warning ("Unable to query for updates - error - %s", error->message); - return; - } - - GPtrArray *packages; - packages = pk_results_get_package_array (results); - - const gchar* disposition; - disposition = dbusmenu_menuitem_property_get (self->apt_item, - DBUSMENU_MENUITEM_PROP_DISPOSITION); - gboolean do_update; - do_update = g_strcmp0 (disposition, DBUSMENU_MENUITEM_DISPOSITION_ALERT) != 0; - - if (packages->len > 0){ - g_print ("Apparently we have updates available - change dbmitem %i", do_update); - if (do_update) - dbusmenu_menuitem_property_set (self->apt_item, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Updates Available…")); - } - else{ - g_print ("No updates available - change dbmitem - %i", do_update); - if (do_update) - dbusmenu_menuitem_property_set (self->apt_item, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Software Up to Date")); - } - g_ptr_array_unref (packages); - g_object_unref (results); - g_object_unref (source_object); -} - -static void -apt_watcher_check_for_updates (AptWatcher* self) -{ - PkClient* client; - client = pk_client_new (); - - pk_client_get_updates_async (client, - PK_FILTER_ENUM_NONE, - NULL, NULL, NULL, - (GAsyncReadyCallback)get_updates_complete, - self); -} - -static void apt_watcher_signal_cb ( GDBusProxy* proxy, - gchar* sender_name, - gchar* signal_name, - GVariant* parameters, - gpointer user_data) -{ - g_return_if_fail (APT_IS_WATCHER (user_data)); - AptWatcher* self = APT_WATCHER (user_data); - - g_debug ("apt-watcher-signal cb signal name - %s", signal_name); - if (g_strcmp0(signal_name, "UpdatesChanged") == 0){ - g_debug ("updates changed signal received"); - apt_watcher_check_for_updates (self); - } - else if (g_strcmp0(signal_name, "RestartSchedule") == 0) { - g_debug ("RestartScheduled signal received"); - dbusmenu_menuitem_property_set (self->apt_item, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Restart to Complete Updates…")); - dbusmenu_menuitem_property_set (self->apt_item, - DBUSMENU_MENUITEM_PROP_DISPOSITION, - DBUSMENU_MENUITEM_DISPOSITION_ALERT); - session_dbus_restart_required (self->session_dbus_interface); - } -} - -static void -apt_watcher_on_name_appeared (GDBusConnection *connection, - const gchar *name, - const gchar *name_owner, - gpointer user_data) -{ - g_return_if_fail (APT_IS_WATCHER (user_data)); - // AptWatcher* watcher = APT_WATCHER (user_data); - - g_print ("Name %s on %s is owned by %s\n", - name, - "the system bus", - name_owner); -} - - -static void -apt_watcher_on_name_vanished (GDBusConnection *connection, - const gchar *name, - gpointer user_data) -{ - g_debug ("Name %s does not exist or has just vanished", - name); - g_return_if_fail (APT_IS_WATCHER (user_data)); -} - -static void -fetch_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data) -{ - GError * error = NULL; - - AptWatcher* self = APT_WATCHER(user_data); - g_return_if_fail(self != NULL); - - GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish (res, &error); - - if (self->proxy_cancel != NULL) { - g_object_unref (self->proxy_cancel); - self->proxy_cancel = NULL; - } - - if (error != NULL) { - g_warning("Could not grab DBus proxy for %s: %s", - "org.debian.apt", error->message); - g_error_free(error); - return; - } - - self->proxy = proxy; - // Set up the watch. - watcher_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM, - "org.freedesktop.PackageKit", - G_BUS_NAME_WATCHER_FLAGS_NONE, - apt_watcher_on_name_appeared, - apt_watcher_on_name_vanished, - self, - NULL); - g_signal_connect (self->proxy, - "g-signal", - G_CALLBACK(apt_watcher_signal_cb), - self); -} - -static gboolean -apt_watcher_start_apt_interaction (gpointer data) -{ - g_return_val_if_fail (APT_IS_WATCHER (data), FALSE); - AptWatcher* self = APT_WATCHER (data); - g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, - G_DBUS_PROXY_FLAGS_NONE, - NULL, - "org.freedesktop.PackageKit", - "/org/freedesktop/PackageKit", - "org.freedesktop.PackageKit", - self->proxy_cancel, - fetch_proxy_cb, - self); - apt_watcher_check_for_updates (self); - return FALSE; -} - - -static void -apt_watcher_show_apt_dialog (DbusmenuMenuitem * mi, - guint timestamp, - gpointer userdata) -{ - GError * error = NULL; - g_return_if_fail (APT_IS_WATCHER (userdata)); - AptWatcher* self = APT_WATCHER (userdata); - const gchar* disposition = NULL; - disposition = dbusmenu_menuitem_property_get (self->apt_item, - DBUSMENU_MENUITEM_PROP_DISPOSITION); - - if (g_strcmp0 (disposition, DBUSMENU_MENUITEM_DISPOSITION_ALERT) == 0){ - gchar * helper = g_build_filename (LIBEXECDIR, "gtk-logout-helper", NULL); - gchar * dialog_line = g_strdup_printf ("%s --%s", helper, "restart"); - g_free(helper); - if (!g_spawn_command_line_async(dialog_line, &error)) { - g_warning("Unable to show dialog: %s", error->message); - g_error_free(error); - } - g_free(dialog_line); - } - else{ - if (!g_spawn_command_line_async("update-manager", &error)) - { - g_warning("Unable to show update-manager: %s", error->message); - g_error_free(error); - } - } -} - -static void -apt_watcher_init (AptWatcher *self) -{ - self->current_state = UP_TO_DATE; - g_timeout_add_seconds (60, - apt_watcher_start_apt_interaction, - self); -} - -static void -apt_watcher_finalize (GObject *object) -{ - g_bus_unwatch_name (watcher_id); - AptWatcher* self = APT_WATCHER (object); - - if (self->proxy != NULL) - g_object_unref (self->proxy); - - G_OBJECT_CLASS (apt_watcher_parent_class)->finalize (object); -} - -static void -apt_watcher_class_init (AptWatcherClass *klass) -{ - GObjectClass* object_class = G_OBJECT_CLASS (klass); - object_class->finalize = apt_watcher_finalize; -} - -AptWatcher* apt_watcher_new (SessionDbus* session_dbus, - DbusmenuMenuitem* item) -{ - AptWatcher* watcher = g_object_new (APT_TYPE_WATCHER, NULL); - watcher->session_dbus_interface = session_dbus; - watcher->apt_item = item; - g_signal_connect (G_OBJECT(watcher->apt_item), - DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK(apt_watcher_show_apt_dialog), watcher); - return watcher; -} - diff --git a/src/apt-watcher.h b/src/apt-watcher.h deleted file mode 100644 index c571502..0000000 --- a/src/apt-watcher.h +++ /dev/null @@ -1,55 +0,0 @@ -/* -Copyright 2011 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>. -*/ - -#ifndef _APT_WATCHER_H_ -#define _APT_WATCHER_H_ - -#include <glib-object.h> - -#include <libdbusmenu-glib/client.h> - -#include <gtk/gtk.h> -#include <libdbusmenu-gtk/menuitem.h> - -#include "session-dbus.h" - -G_BEGIN_DECLS - -#define APT_TYPE_WATCHER (apt_watcher_get_type ()) -#define APT_WATCHER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), APT_TYPE_WATCHER, AptWatcher)) -#define APT_WATCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), APT_TYPE_WATCHER, AptWatcherClass)) -#define APT_IS_WATCHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), APT_TYPE_WATCHER)) -#define APT_IS_WATCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), APT_TYPE_WATCHER)) -#define APT_WATCHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), APT_TYPE_WATCHER, AptWatcherClass)) - -typedef struct _AptWatcherClass AptWatcherClass; -typedef struct _AptWatcher AptWatcher; - -struct _AptWatcherClass -{ - GObjectClass parent_class; -}; - -GType apt_watcher_get_type (void) G_GNUC_CONST; - -AptWatcher* apt_watcher_new (SessionDbus* session_dbus, - DbusmenuMenuitem* apt_item); -G_END_DECLS - -#endif /* _APT_WATCHER_H_ */ diff --git a/src/dbusmenu-shared.h b/src/dbusmenu-shared.h deleted file mode 100644 index 1ef179b..0000000 --- a/src/dbusmenu-shared.h +++ /dev/null @@ -1,4 +0,0 @@ - -#define MENU_SWITCH_TYPE "x-canonical-switch-from" -#define MENU_SWITCH_USER "x-canonical-switch-username" - diff --git a/src/device-menu-mgr.c b/src/device-menu-mgr.c deleted file mode 100644 index cfdb55d..0000000 --- a/src/device-menu-mgr.c +++ /dev/null @@ -1,794 +0,0 @@ -/* -Copyright 2011 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>. -*/ - -#include <config.h> -#include <libdbusmenu-glib/client.h> - -#include "device-menu-mgr.h" -#include "settings-helper.h" -#include "dbus-shared-names.h" -#include "dbusmenu-shared.h" -#include "lock-helper.h" -#include "upower-client.h" - -#ifdef HAVE_APT -#include "apt-watcher.h" -#endif /* HAVE_APT */ - -#ifdef HAS_GUDEV -#include "udev-mgr.h" -#endif /* HAS_GUDEV */ - -#define UP_ADDRESS "org.freedesktop.UPower" -#define UP_OBJECT "/org/freedesktop/UPower" -#define UP_INTERFACE "org.freedesktop.UPower" - -#define EXTRA_LAUNCHER_DIR "/usr/share/indicators/session/applications" - -struct _DeviceMenuMgr -{ - GObject parent_instance; - DbusmenuMenuitem* root_item; - SessionDbus* session_dbus_interface; -#ifdef HAVE_APT - AptWatcher* apt_watcher; -#endif /* HAVE_APT */ -#ifdef HAS_GUDEV - UdevMgr* udev_mgr; -#endif /* HAS_GUDEV */ -}; - -static GSettings *lockdown_settings = NULL; -static GSettings *keybinding_settings = NULL; -static DbusmenuMenuitem *lock_menuitem = NULL; -static DbusmenuMenuitem *system_settings_menuitem = NULL; -static DbusmenuMenuitem *display_settings_menuitem = NULL; -static DbusmenuMenuitem *login_settings_menuitem = NULL; -#ifdef HAVE_APT -static DbusmenuMenuitem *software_updates_menuitem = NULL; -#endif /* HAVE_APT */ -static DbusmenuMenuitem *printers_menuitem = NULL; -static DbusmenuMenuitem *scanners_menuitem = NULL; -static DbusmenuMenuitem *webcam_menuitem = NULL; - -static DBusGProxyCall * suspend_call = NULL; -static DBusGProxyCall * hibernate_call = NULL; - -static DbusmenuMenuitem * hibernate_mi = NULL; -static DbusmenuMenuitem * suspend_mi = NULL; -static DbusmenuMenuitem * logout_mi = NULL; -static DbusmenuMenuitem * shutdown_mi = NULL; - -static gboolean can_hibernate = TRUE; -static gboolean can_suspend = TRUE; -static gboolean allow_hibernate = TRUE; -static gboolean allow_suspend = TRUE; - -static DBusGProxy * up_main_proxy = NULL; -static DBusGProxy * up_prop_proxy = NULL; - -static void device_menu_mgr_ensure_settings_client (DeviceMenuMgr* self); -static void setup_up (DeviceMenuMgr* self); -static void device_menu_mgr_rebuild_items (DeviceMenuMgr *self); -static void machine_sleep_with_context (DeviceMenuMgr* self, - gchar* type); -static void show_system_settings_with_context (DbusmenuMenuitem * mi, - guint timestamp, - gchar * type); - -static void device_menu_mgr_show_simple_scan (DbusmenuMenuitem * mi, - guint timestamp, - gchar * type); -static void device_menu_mgr_show_cheese (DbusmenuMenuitem * mi, - guint timestamp, - gchar * type); - -static void -machine_sleep_from_hibernate (DbusmenuMenuitem * mi, - guint timestamp, - gpointer userdata); -static void -machine_sleep_from_suspend (DbusmenuMenuitem * mi, - guint timestamp, - gpointer userdata); - -G_DEFINE_TYPE (DeviceMenuMgr, device_menu_mgr, G_TYPE_OBJECT); - -static void -device_menu_mgr_init (DeviceMenuMgr *self) -{ -#ifdef HAVE_APT - self->apt_watcher = NULL; -#endif /* HAVE_APT */ - self->root_item = dbusmenu_menuitem_new (); - setup_up(self); - g_idle_add(lock_screen_setup, NULL); -} - -static void -device_menu_mgr_finalize (GObject *object) -{ - G_OBJECT_CLASS (device_menu_mgr_parent_class)->finalize (object); -} - -// TODO refactor into one helper method for both menu mgrs. -static void -device_menu_mgr_class_init (DeviceMenuMgrClass *klass) -{ - GObjectClass* object_class = G_OBJECT_CLASS (klass); - object_class->finalize = device_menu_mgr_finalize; -} - -// TODO -// Is this needed anymore -static void -lockdown_changed (GSettings * settings, - const gchar * key, - gpointer user_data) -{ - DeviceMenuMgr* self = DEVICE_MENU_MGR (user_data); - - if (key == NULL) { - return; - } - - if (g_strcmp0 (key, LOCKDOWN_KEY_USER) == 0 || - g_strcmp0 (key, LOCKDOWN_KEY_SCREENSAVER) == 0) { - device_menu_mgr_rebuild_items(self); - } - - return; -} - -static void -keybinding_changed (GSettings *settings, - const gchar *key, - gpointer user_data) -{ - if (key == NULL) { - return; - } - - if (g_strcmp0 (key, KEY_LOCK_SCREEN) == 0) { - g_debug("Keybinding changed to: %s", g_settings_get_string(settings, key)); - if (lock_menuitem != NULL) { - dbusmenu_menuitem_property_set_shortcut_string (lock_menuitem, - g_settings_get_string(settings, key)); - } - } - return; -} - -static void -machine_sleep_from_suspend (DbusmenuMenuitem * mi, - guint timestamp, - gpointer userdata) -{ - DeviceMenuMgr* self = DEVICE_MENU_MGR (userdata); - machine_sleep_with_context (self, "Suspend"); -} - -static void -machine_sleep_from_hibernate (DbusmenuMenuitem * mi, - guint timestamp, - gpointer userdata) -{ - DeviceMenuMgr* self = DEVICE_MENU_MGR (userdata); - machine_sleep_with_context (self, "Hibernate"); -} - -/* Let's put this machine to sleep, with some info on how - it should sleep. */ -static void -machine_sleep_with_context (DeviceMenuMgr* self, gchar* type) -{ - if (up_main_proxy == NULL) { - g_warning("Can not %s as no upower proxy", type); - } - - dbus_g_proxy_begin_call(up_main_proxy, - type, - NULL, - NULL, - NULL, - G_TYPE_INVALID); - - return; -} - -/* A response to getting the suspend property */ -static void -suspend_prop_cb (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata) -{ - suspend_call = NULL; - DeviceMenuMgr* self = DEVICE_MENU_MGR (userdata); - - GValue candoit = {0}; - GError * error = NULL; - dbus_g_proxy_end_call(proxy, call, &error, G_TYPE_VALUE, &candoit, G_TYPE_INVALID); - if (error != NULL) { - g_warning("Unable to check suspend: %s", error->message); - g_error_free(error); - return; - } - g_debug("Got Suspend: %s", g_value_get_boolean(&candoit) ? "true" : "false"); - - gboolean local_can_suspend = g_value_get_boolean(&candoit); - if (local_can_suspend != can_suspend) { - can_suspend = local_can_suspend; - // TODO figure out what needs updating on the menu - // And add or remove it but just don't rebuild the whole menu - // a waste - device_menu_mgr_rebuild_items(self); - } - return; -} - -/* Response to getting the hibernate property */ -static void -hibernate_prop_cb (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata) -{ - hibernate_call = NULL; - DeviceMenuMgr* self = DEVICE_MENU_MGR (userdata); - - GValue candoit = {0}; - GError * error = NULL; - dbus_g_proxy_end_call(proxy, call, &error, G_TYPE_VALUE, &candoit, G_TYPE_INVALID); - if (error != NULL) { - g_warning("Unable to check hibernate: %s", error->message); - g_error_free(error); - return; - } - g_debug("Got Hibernate: %s", g_value_get_boolean(&candoit) ? "true" : "false"); - - gboolean local_can_hibernate = g_value_get_boolean(&candoit); - if (local_can_hibernate != can_hibernate) { - can_hibernate = local_can_hibernate; - device_menu_mgr_rebuild_items(self); - } -} - -/* A signal that we need to recheck to ensure we can still - hibernate and/or suspend */ -static void -up_changed_cb (DBusGProxy * proxy, gpointer user_data) -{ - /* Start Async call to see if we can hibernate */ - if (suspend_call == NULL) { - suspend_call = dbus_g_proxy_begin_call(up_prop_proxy, - "Get", - suspend_prop_cb, - user_data, - NULL, - G_TYPE_STRING, - UP_INTERFACE, - G_TYPE_STRING, - "CanSuspend", - G_TYPE_INVALID, - G_TYPE_VALUE, - G_TYPE_INVALID); - } - - /* Start Async call to see if we can suspend */ - if (hibernate_call == NULL) { - hibernate_call = dbus_g_proxy_begin_call(up_prop_proxy, - "Get", - hibernate_prop_cb, - user_data, - NULL, - G_TYPE_STRING, - UP_INTERFACE, - G_TYPE_STRING, - "CanHibernate", - G_TYPE_INVALID, - G_TYPE_VALUE, - G_TYPE_INVALID); - } -} -/* Handle the callback from the allow functions to check and - see if we're changing the value, and if so, rebuilding the - menus based on that info. */ -static void -allowed_suspend_cb (DBusGProxy *proxy, - gboolean OUT_allowed, - GError *error, - gpointer userdata) -{ - if (error != NULL) { - g_warning("Unable to get information on what is allowed from UPower: %s", - error->message); - return; - } - - if (OUT_allowed != allow_suspend) { - allow_suspend = OUT_allowed; - device_menu_mgr_rebuild_items(DEVICE_MENU_MGR (userdata)); - } -} - -/* Handle the callback from the allow functions to check and - see if we're changing the value, and if so, rebuilding the - menus based on that info. */ -static void -allowed_hibernate_cb (DBusGProxy *proxy, - gboolean OUT_allowed, - GError *error, - gpointer userdata) -{ - if (error != NULL) { - g_warning("Unable to get information on what is allowed from UPower: %s", - error->message); - return; - } - - if (OUT_allowed != allow_hibernate) { - allow_hibernate = OUT_allowed; - device_menu_mgr_rebuild_items(DEVICE_MENU_MGR (userdata)); - } -} - -/* This function goes through and sets up what we need for - DKp checking. We're even setting up the calls for the props - we need */ -static void -setup_up (DeviceMenuMgr* self) { - DBusGConnection * bus = dbus_g_bus_get(DBUS_BUS_SYSTEM, NULL); - g_return_if_fail(bus != NULL); - - if (up_main_proxy == NULL) { - up_main_proxy = dbus_g_proxy_new_for_name(bus, - UP_ADDRESS, - UP_OBJECT, - UP_INTERFACE); - } - g_return_if_fail(up_main_proxy != NULL); - - if (up_prop_proxy == NULL) { - up_prop_proxy = dbus_g_proxy_new_for_name(bus, - UP_ADDRESS, - UP_OBJECT, - DBUS_INTERFACE_PROPERTIES); - /* Connect to changed signal */ - dbus_g_proxy_add_signal(up_main_proxy, - "Changed", - G_TYPE_INVALID); - - dbus_g_proxy_connect_signal(up_main_proxy, - "Changed", - G_CALLBACK(up_changed_cb), - self, - NULL); - } - g_return_if_fail(up_prop_proxy != NULL); - - - /* Force an original "changed" event */ - up_changed_cb(up_main_proxy, self); - - /* Check to see if these are getting blocked by PolicyKit */ - org_freedesktop_UPower_suspend_allowed_async(up_main_proxy, - allowed_suspend_cb, - self); - org_freedesktop_UPower_hibernate_allowed_async(up_main_proxy, - allowed_hibernate_cb, - self); - - return; -} - -/* This is the function to show a dialog on actions that - can destroy data. Currently it just calls the GTK version - but it seems that in the future it should figure out - what's going on and something better. */ -static void -show_dialog (DbusmenuMenuitem * mi, guint timestamp, gchar * type) -{ - -#ifdef HAVE_GTKLOGOUTHELPER - gchar * helper = g_build_filename(LIBEXECDIR, "gtk-logout-helper", NULL); -#else - gchar * helper = g_build_filename("gnome-session-quit", NULL); -#endif /* HAVE_GTKLOGOUTHELPER */ - gchar * dialog_line = g_strdup_printf("%s --%s", helper, type); - g_free(helper); - - g_debug("Showing dialog '%s'", dialog_line); - - GError * error = NULL; - if (!g_spawn_command_line_async(dialog_line, &error)) { - g_warning("Unable to show dialog: %s", error->message); - g_error_free(error); - } - g_free(dialog_line); -} - -static void -show_session_properties (DbusmenuMenuitem * mi, - guint timestamp, - gchar * type) -{ - GError * error = NULL; - if (!g_spawn_command_line_async("gnome-session-properties", &error)) - { - g_warning("Unable to show dialog: %s", error->message); - g_error_free(error); - } -} - -static void -show_printer_properties (DbusmenuMenuitem * mi, - guint timestamp, - gchar * type) -{ - GError * error = NULL; - if (!g_spawn_command_line_async("system-config-printer", &error)) - { - g_warning("Unable to show dialog: %s", error->message); - g_error_free(error); - } -} - -static void -show_system_settings_with_context (DbusmenuMenuitem * mi, - guint timestamp, - gchar * type) -{ - gchar * control_centre_command = g_strdup_printf("%s %s", - "gnome-control-center", - type); - - g_debug("Command centre exec call '%s'", control_centre_command); - - GError * error = NULL; - if (!g_spawn_command_line_async(control_centre_command, &error)) - { - g_warning("Unable to show dialog: %s", error->message); - g_error_free(error); - } - g_free(control_centre_command); -} - -// TODO: refactor both of these down to the one method. -static void device_menu_mgr_show_simple_scan (DbusmenuMenuitem * mi, - guint timestamp, - gchar * type) -{ - GError * error = NULL; - if (!g_spawn_command_line_async("simple-scan", &error)) - { - g_warning("Unable to launch simple-scan: %s", error->message); - g_error_free(error); -#ifdef HAVE_APT - if (!g_spawn_command_line_async("software-center simple-scan", &error)) - { - g_warning ("Unable to launch software-centre simple-scan: %s", - error->message); - g_error_free(error); - } -#endif /* HAVE_APT */ - } -} - -static void device_menu_mgr_show_cheese (DbusmenuMenuitem * mi, - guint timestamp, - gchar * type) -{ - GError * error = NULL; - if (!g_spawn_command_line_async("cheese", &error)) - { - g_warning("Unable to launch cheese: %s", error->message); - g_error_free(error); -#ifdef HAVE_APT - if (!g_spawn_command_line_async("software-center cheese", &error)) - { - g_warning ("Unable to launch software-centre cheese: %s", - error->message); - g_error_free(error); - } -#endif /* HAVE_APT */ - } -} - -static void -device_menu_mgr_build_settings_items (DeviceMenuMgr* self) -{ - system_settings_menuitem = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (system_settings_menuitem, - DBUSMENU_MENUITEM_PROP_LABEL, - _("System Settings…")); - g_signal_connect (G_OBJECT(system_settings_menuitem), - DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK(show_system_settings_with_context), ""); - dbusmenu_menuitem_child_add_position(self->root_item, - system_settings_menuitem, - 0); - - display_settings_menuitem = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (display_settings_menuitem, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Displays…")); - g_signal_connect (G_OBJECT(display_settings_menuitem), - DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK(show_system_settings_with_context), "display"); - dbusmenu_menuitem_child_add_position(self->root_item, - display_settings_menuitem, - 1); - login_settings_menuitem = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (login_settings_menuitem, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Startup Applications…")); - g_signal_connect (G_OBJECT(login_settings_menuitem), - DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK(show_session_properties), - "login"); - dbusmenu_menuitem_child_add_position(self->root_item, - login_settings_menuitem, - 2); -#ifdef HAVE_APT - software_updates_menuitem = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (software_updates_menuitem, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Software Up to Date")); - dbusmenu_menuitem_child_add_position(self->root_item, - software_updates_menuitem, - 3); -#endif /* HAVE_APT */ - - DbusmenuMenuitem * separator1 = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (separator1, - DBUSMENU_MENUITEM_PROP_TYPE, - DBUSMENU_CLIENT_TYPES_SEPARATOR); - dbusmenu_menuitem_child_add_position (self->root_item, separator1, 4); -} - -static void -device_menu_mgr_build_devices_items (DeviceMenuMgr* self) -{ - DbusmenuMenuitem * device_heading = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (device_heading, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Attached Devices")); - dbusmenu_menuitem_property_set_bool (device_heading, - DBUSMENU_MENUITEM_PROP_ENABLED, - FALSE); - dbusmenu_menuitem_child_add_position (self->root_item, - device_heading, - 5); - - printers_menuitem = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (printers_menuitem, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Printers")); - g_signal_connect (G_OBJECT(printers_menuitem), - DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK(show_printer_properties), - "printers"); - dbusmenu_menuitem_child_add_position(self->root_item, - printers_menuitem, - 6); - scanners_menuitem = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (scanners_menuitem, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Scanners")); - g_signal_connect (G_OBJECT(scanners_menuitem), - DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK(device_menu_mgr_show_simple_scan), - NULL); - dbusmenu_menuitem_child_add_position (self->root_item, - scanners_menuitem, - 7); - dbusmenu_menuitem_property_set_bool (scanners_menuitem, - DBUSMENU_MENUITEM_PROP_VISIBLE, - FALSE); - - webcam_menuitem = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (webcam_menuitem, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Webcam")); - g_signal_connect (G_OBJECT(webcam_menuitem), - DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK(device_menu_mgr_show_cheese), - NULL); - dbusmenu_menuitem_child_add_position (self->root_item, - webcam_menuitem, - 8); - dbusmenu_menuitem_property_set_bool (webcam_menuitem, - DBUSMENU_MENUITEM_PROP_VISIBLE, - FALSE); - - DbusmenuMenuitem * separator3 = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (separator3, - DBUSMENU_MENUITEM_PROP_TYPE, - DBUSMENU_CLIENT_TYPES_SEPARATOR); - dbusmenu_menuitem_child_add_position (self->root_item, separator3, 9); -} - -static void -device_menu_mgr_build_static_items (DeviceMenuMgr* self, gboolean greeter_mode) -{ - // Static Setting items - if (!greeter_mode) { - device_menu_mgr_build_settings_items (self); - } - - // Devices control - if (!greeter_mode) { - device_menu_mgr_build_devices_items (self); - } - - // Session control - if (!greeter_mode) { - gboolean can_lockscreen; - - /* Make sure we have a valid GConf client, and build one - if needed */ - device_menu_mgr_ensure_settings_client (self); - can_lockscreen = !g_settings_get_boolean (lockdown_settings, - LOCKDOWN_KEY_SCREENSAVER); - /* Lock screen item */ - if (can_lockscreen) { - lock_menuitem = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (lock_menuitem, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Lock Screen")); - - gchar * shortcut = g_settings_get_string(keybinding_settings, KEY_LOCK_SCREEN); - if (shortcut != NULL) { - g_debug("Lock screen shortcut: %s", shortcut); - dbusmenu_menuitem_property_set_shortcut_string(lock_menuitem, shortcut); - g_free(shortcut); - } - else { - g_debug("Unable to get lock screen shortcut."); - } - - g_signal_connect (G_OBJECT(lock_menuitem), - DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK(lock_screen), NULL); - dbusmenu_menuitem_child_append(self->root_item, lock_menuitem); - } - - logout_mi = dbusmenu_menuitem_new(); - - if (supress_confirmations()) { - dbusmenu_menuitem_property_set (logout_mi, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Log Out")); - } - else { - dbusmenu_menuitem_property_set (logout_mi, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Log Out\342\200\246")); - } - dbusmenu_menuitem_property_set_bool (logout_mi, - DBUSMENU_MENUITEM_PROP_VISIBLE, - show_logout()); - dbusmenu_menuitem_child_append(self->root_item, logout_mi); - g_signal_connect( G_OBJECT(logout_mi), - DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK(show_dialog), "logout"); - } - - if (can_suspend && allow_suspend) { - suspend_mi = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (suspend_mi, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Suspend")); - dbusmenu_menuitem_child_append (self->root_item, suspend_mi); - g_signal_connect( G_OBJECT(suspend_mi), - DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK(machine_sleep_from_suspend), - self); - } - - if (can_hibernate && allow_hibernate) { - hibernate_mi = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (hibernate_mi, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Hibernate")); - dbusmenu_menuitem_child_append(self->root_item, hibernate_mi); - g_signal_connect (G_OBJECT(hibernate_mi), - DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK(machine_sleep_from_hibernate), self); - } - - shutdown_mi = dbusmenu_menuitem_new(); - - if (supress_confirmations()) { - dbusmenu_menuitem_property_set (shutdown_mi, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Shut Down")); - } - else { - dbusmenu_menuitem_property_set (shutdown_mi, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Shut Down\342\200\246")); - } - dbusmenu_menuitem_property_set_bool (shutdown_mi, - DBUSMENU_MENUITEM_PROP_VISIBLE, - show_shutdown()); - dbusmenu_menuitem_child_append (self->root_item, shutdown_mi); - g_signal_connect (G_OBJECT(shutdown_mi), - DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, -#ifdef HAVE_GTKLOGOUTHELPER - G_CALLBACK(show_dialog), "shutdown"); -#else - G_CALLBACK(show_dialog), "power-off"); -#endif /* HAVE_GTKLOGOUTHELPER */ - - RestartShutdownLogoutMenuItems * restart_shutdown_logout_mi = g_new0 (RestartShutdownLogoutMenuItems, 1); - restart_shutdown_logout_mi->logout_mi = logout_mi; - restart_shutdown_logout_mi->shutdown_mi = shutdown_mi; - - update_menu_entries(restart_shutdown_logout_mi); -#ifdef HAS_GUDEV - // Time to create the udev mgr and hand it the static relevant items. - self->udev_mgr = udev_mgr_new (scanners_menuitem, webcam_menuitem); -#endif -} - -static void -device_menu_mgr_rebuild_items (DeviceMenuMgr* self) -{ - dbusmenu_menuitem_property_set_bool (hibernate_mi, - DBUSMENU_MENUITEM_PROP_VISIBLE, - can_hibernate && allow_hibernate); - dbusmenu_menuitem_property_set_bool (suspend_mi, - DBUSMENU_MENUITEM_PROP_VISIBLE, - can_suspend && allow_suspend); -} - -/* Ensures that we have a GConf client and if we build one - set up the signal handler. */ -static void -device_menu_mgr_ensure_settings_client (DeviceMenuMgr* self) -{ - if (!lockdown_settings) { - lockdown_settings = g_settings_new (LOCKDOWN_SCHEMA); - g_signal_connect(lockdown_settings, "changed", G_CALLBACK(lockdown_changed), self); - } - if (!keybinding_settings) { - keybinding_settings = g_settings_new (KEYBINDING_SCHEMA); - g_signal_connect(lockdown_settings, "changed::" KEY_LOCK_SCREEN, G_CALLBACK(keybinding_changed), self); - } - return; -} - -DbusmenuMenuitem* -device_mgr_get_root_item (DeviceMenuMgr* self) -{ - return self->root_item; -} - -/* - * Clean Entry Point - */ -DeviceMenuMgr* device_menu_mgr_new (SessionDbus* session_dbus, gboolean greeter_mode) -{ - DeviceMenuMgr* device_mgr = g_object_new (DEVICE_TYPE_MENU_MGR, NULL); - device_mgr->session_dbus_interface = session_dbus; - device_menu_mgr_build_static_items (device_mgr, greeter_mode); -#ifdef HAVE_APT - if (software_updates_menuitem != NULL) { - device_mgr->apt_watcher = apt_watcher_new (session_dbus, - software_updates_menuitem); - } -#endif /* HAVE_APT */ - return device_mgr; -} diff --git a/src/device-menu-mgr.h b/src/device-menu-mgr.h deleted file mode 100644 index d3c3a5a..0000000 --- a/src/device-menu-mgr.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -Copyright 2011 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>. -*/ - - -#ifndef _DEVICE_MENU_MGR_H_ -#define _DEVICE_MENU_MGR_H_ - -#include <glib-object.h> - -#include "session-dbus.h" - -G_BEGIN_DECLS - -#define DEVICE_TYPE_MENU_MGR (device_menu_mgr_get_type ()) -#define DEVICE_MENU_MGR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DEVICE_TYPE_MENU_MGR, DeviceMenuMgr)) -#define DEVICE_MENU_MGR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DEVICE_TYPE_MENU_MGR, DeviceMenuMgrClass)) -#define DEVICE_IS_MENU_MGR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DEVICE_TYPE_MENU_MGR)) -#define DEVICE_IS_MENU_MGR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DEVICE_TYPE_MENU_MGR)) -#define DEVICE_MENU_MGR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DEVICE_TYPE_MENU_MGR, DeviceMenuMgrClass)) - -typedef struct _DeviceMenuMgrClass DeviceMenuMgrClass; -typedef struct _DeviceMenuMgr DeviceMenuMgr; - -struct _DeviceMenuMgrClass -{ - GObjectClass parent_class; -}; - -GType device_menu_mgr_get_type (void) G_GNUC_CONST; - -DeviceMenuMgr* device_menu_mgr_new (SessionDbus* session_dbus, gboolean greeter_mode); - -DbusmenuMenuitem* device_mgr_get_root_item (DeviceMenuMgr* self); - -G_END_DECLS - -#endif /* _DEVICE_MENU_MGR_H_ */ diff --git a/src/dialog.c b/src/dialog.c index 4b139ca..c46ac80 100644 --- a/src/dialog.c +++ b/src/dialog.c @@ -7,16 +7,16 @@ Copyright 2010 Canonical Ltd. Authors: Ted Gould <ted@canonical.com> -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, 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 +You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -26,7 +26,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include <glib/gi18n.h> -#include "consolekit-manager-client.h" +#include "dbus-consolekit-manager.h" #include "dialog.h" /* Strings */ @@ -34,7 +34,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>. static const gchar * title_strings[LOGOUT_DIALOG_TYPE_CNT] = { /* LOGOUT_DIALOG_LOGOUT, */ NC_("title", "Log Out"), /* LOGOUT_DIALOG_RESTART, */ NC_("title", "Restart"), - /* LOGOUT_DIALOG_SHUTDOWN, */ NC_("title", "Shut Down") + /* LOGOUT_DIALOG_SHUTDOWN, */ NC_("title", "Switch Off") }; static const gchar * body_strings[LOGOUT_DIALOG_TYPE_CNT] = { @@ -46,7 +46,7 @@ static const gchar * body_strings[LOGOUT_DIALOG_TYPE_CNT] = { static const gchar * button_strings[LOGOUT_DIALOG_TYPE_CNT] = { /* LOGOUT_DIALOG_LOGOUT, */ NC_("button", "Log Out"), /* LOGOUT_DIALOG_RESTART, */ NC_("button", "Restart"), - /* LOGOUT_DIALOG_SHUTDOWN, */ NC_("button", "Shut Down") + /* LOGOUT_DIALOG_SHUTDOWN, */ NC_("button", "Switch Off") }; /* TRANSLATORS: These strings have an ellipsis so that the user knows @@ -54,7 +54,7 @@ static const gchar * button_strings[LOGOUT_DIALOG_TYPE_CNT] = { static const gchar * button_auth_strings[LOGOUT_DIALOG_TYPE_CNT] = { /* LOGOUT_DIALOG_LOGOUT, */ NC_("button auth", "Log Out"), /* LOGOUT_DIALOG_RESTART, */ NC_("button auth", "Restart…"), - /* LOGOUT_DIALOG_SHUTDOWN, */ NC_("button auth", "Shut Down…") + /* LOGOUT_DIALOG_SHUTDOWN, */ NC_("button auth", "Switch Off…") }; /* TRANSLATORS: This button appears on the logout dialog when @@ -137,30 +137,31 @@ check_restart_required (void) static gboolean ck_check_allowed (LogoutDialogType type) { - DBusGConnection * system_bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL); - g_return_val_if_fail(system_bus != NULL, TRUE); - - DBusGProxy * ck_proxy = dbus_g_proxy_new_for_name (system_bus, - "org.freedesktop.ConsoleKit", - "/org/freedesktop/ConsoleKit/Manager", - "org.freedesktop.ConsoleKit.Manager"); - g_return_val_if_fail(ck_proxy != NULL, TRUE); - - gboolean retval = TRUE; - switch (type) { - case LOGOUT_DIALOG_TYPE_RESTART: - org_freedesktop_ConsoleKit_Manager_can_restart(ck_proxy, &retval, NULL); - break; - case LOGOUT_DIALOG_TYPE_SHUTDOWN: - org_freedesktop_ConsoleKit_Manager_can_stop(ck_proxy, &retval, NULL); - break; - default: - break; - } + gboolean allowed = TRUE; + + ConsoleKitManager * ck_proxy = console_kit_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.ConsoleKit", + "/org/freedesktop/ConsoleKit/Manager", + NULL, + NULL); + if (ck_proxy != NULL) + { + switch (type) { + case LOGOUT_DIALOG_TYPE_RESTART: + console_kit_manager_call_can_restart_sync (ck_proxy, &allowed, NULL, NULL); + break; + case LOGOUT_DIALOG_TYPE_SHUTDOWN: + console_kit_manager_call_can_stop_sync (ck_proxy, &allowed, NULL, NULL); + break; + default: + break; + } - g_object_unref(ck_proxy); + g_object_unref(ck_proxy); + } - return retval; + return allowed; } LogoutDialog * @@ -225,17 +226,17 @@ logout_dialog_new (LogoutDialogType type) button_text, GTK_RESPONSE_OK, NULL); } - - if (type == LOGOUT_DIALOG_TYPE_SHUTDOWN){ - const gchar * restart_text; + + if (type == LOGOUT_DIALOG_TYPE_SHUTDOWN) { + const gchar * restart_text; restart_text = g_dpgettext2 (NULL, "button", button_strings[LOGOUT_DIALOG_TYPE_RESTART]); - gtk_dialog_add_button (GTK_DIALOG(dialog), restart_text, GTK_RESPONSE_HELP); - } + gtk_dialog_add_button (GTK_DIALOG(dialog), restart_text, GTK_RESPONSE_HELP); + } gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); - /* The following is a workaround to fix an issue in GtkMessageDialog - in which the user can tab through the text in addition to + /* The following is a workaround to fix an issue in GtkMessageDialog + in which the user can tab through the text in addition to the buttons. */ GtkWidget *message_area = gtk_message_dialog_get_message_area(GTK_MESSAGE_DIALOG(dialog)); GList *children = gtk_container_get_children(GTK_CONTAINER(message_area)); diff --git a/src/display-manager.xml b/src/display-manager.xml index 92f5e05..07b5f29 100644 --- a/src/display-manager.xml +++ b/src/display-manager.xml @@ -1,20 +1,30 @@ <!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"> + <node> <interface name="org.freedesktop.DisplayManager.Seat"> + <property name="CanSwitch" type="b" access="read"/> + + <property name="HasGuestAccount" type="b" access="read"/> + + <property name="Sessions" type="ao" access="read"/> + <!-- Show greeter to allow new login / switch users --> <method name="SwitchToGreeter"/> <!-- Switch to a user, starting a new display if required --> <method name="SwitchToUser"> <arg name="username" direction="in" type="s"/> - <arg name="session" direction="in" type="s"/> + <arg name="session_name" direction="in" type="s"/> </method> <!-- Switch to the guest user --> <method name="SwitchToGuest"> - <arg name="session" direction="in" type="s"/> + <arg name="session_name" direction="in" type="s"/> </method> + <method name='Lock'/> + </interface> + </node> diff --git a/src/gtk-logout-helper.c b/src/gtk-logout-helper.c index 1975121..7868978 100644 --- a/src/gtk-logout-helper.c +++ b/src/gtk-logout-helper.c @@ -8,25 +8,28 @@ Authors: Ted Gould <ted@canonical.com> Christoph Korn <c_korn@gmx.de> -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, 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 +You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <config.h> +#include "config.h" + +#include <locale.h> #include <glib.h> -#include <gtk/gtk.h> +#include <glib/gi18n.h> /* textdomain(), bindtextdomain() */ #include <dbus/dbus-glib.h> +#include <gtk/gtk.h> #include "dialog.h" -#include "settings-helper.h" +#include "shared-names.h" static void consolekit_fallback (LogoutDialogType action) @@ -89,7 +92,7 @@ session_action (LogoutDialogType action) GError * error = NULL; gboolean res = FALSE; - sbus = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); + sbus = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); if (sbus == NULL) { g_warning("Unable to get DBus session bus."); return; @@ -111,15 +114,15 @@ session_action (LogoutDialogType action) if (action == LOGOUT_DIALOG_TYPE_LOG_OUT) { g_debug("Asking Session manager to 'Logout'"); - res = dbus_g_proxy_call_with_timeout (sm_proxy, "Logout", INT_MAX, &error, + res = dbus_g_proxy_call_with_timeout (sm_proxy, "Logout", INT_MAX, &error, G_TYPE_UINT, 1, G_TYPE_INVALID, G_TYPE_INVALID); } else if (action == LOGOUT_DIALOG_TYPE_SHUTDOWN) { g_debug("Asking Session manager to 'RequestShutdown'"); - res = dbus_g_proxy_call_with_timeout (sm_proxy, "RequestShutdown", INT_MAX, &error, + res = dbus_g_proxy_call_with_timeout (sm_proxy, "RequestShutdown", INT_MAX, &error, G_TYPE_INVALID, G_TYPE_INVALID); } else if (action == LOGOUT_DIALOG_TYPE_RESTART) { g_debug("Asking Session manager to 'RequestReboot'"); - res = dbus_g_proxy_call_with_timeout (sm_proxy, "RequestReboot", INT_MAX, &error, + res = dbus_g_proxy_call_with_timeout (sm_proxy, "RequestReboot", INT_MAX, &error, G_TYPE_INVALID, G_TYPE_INVALID); } else { g_warning ("Unknown session action"); @@ -136,10 +139,7 @@ session_action (LogoutDialogType action) } g_object_unref(sm_proxy); - - if (error != NULL) { - g_error_free(error); - } + g_clear_error (&error); return; } @@ -178,6 +178,17 @@ static GOptionEntry options[] = { {NULL} }; +static gboolean +suppress_confirmations (void) +{ + GSettings * s = g_settings_new (SESSION_SCHEMA); + const gboolean suppress = g_settings_get_boolean (s, SUPPRESS_KEY); + g_clear_object (&s); + return suppress; +} + + + int main (int argc, char * argv[]) { @@ -206,7 +217,7 @@ main (int argc, char * argv[]) INDICATOR_ICONS_DIR); GtkWidget * dialog = NULL; - if (!supress_confirmations()) { + if (!suppress_confirmations()) { g_debug("Showing dialog to ask for user confirmation"); dialog = GTK_WIDGET(logout_dialog_new(type)); } diff --git a/src/indicator-session.c b/src/indicator-session.c index 5d894e8..53ff87e 100644 --- a/src/indicator-session.c +++ b/src/indicator-session.c @@ -1,23 +1,23 @@ /* A small wrapper utility to load indicators and put them as menu items -into the gnome-panel using it's applet interface. +into the gnome-panel using its applet interface. Copyright 2009 Canonical Ltd. Authors: Ted Gould <ted@canonical.com> Conor Curran <conor.curran@canonical.com> - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, 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 +You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -38,8 +38,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include <libindicator/indicator-service-manager.h> #include <libindicator/indicator-image-helper.h> -#include "dbus-shared-names.h" -#include "dbusmenu-shared.h" +#include "shared-names.h" #include "user-widget.h" #define INDICATOR_SESSION_TYPE (indicator_session_get_type ()) @@ -52,18 +51,19 @@ with this program. If not, see <http://www.gnu.org/licenses/>. typedef struct _IndicatorSession IndicatorSession; typedef struct _IndicatorSessionClass IndicatorSessionClass; -struct _IndicatorSessionClass { - IndicatorObjectClass parent_class; +struct _IndicatorSessionClass +{ + IndicatorObjectClass parent_class; }; -struct _IndicatorSession { - IndicatorObject parent; - IndicatorServiceManager * service; - IndicatorObjectEntry users; - IndicatorObjectEntry devices; - gboolean show_users_entry; - GCancellable * service_proxy_cancel; - GDBusProxy * service_proxy; +struct _IndicatorSession +{ + IndicatorObject parent; + IndicatorServiceManager * service; + IndicatorObjectEntry entry; + GCancellable * service_proxy_cancel; + GDBusProxy * service_proxy; + GSettings * settings; }; static gboolean greeter_mode; @@ -75,10 +75,6 @@ INDICATOR_SET_VERSION INDICATOR_SET_TYPE(INDICATOR_SESSION_TYPE) /* Prototypes */ -static gboolean build_menu_switch (DbusmenuMenuitem * newitem, - DbusmenuMenuitem * parent, - DbusmenuClient * client, - gpointer user_data); static gboolean new_user_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, @@ -93,7 +89,6 @@ static void service_connection_cb (IndicatorServiceManager * sm, gboolean connec static void receive_signal (GDBusProxy * proxy, gchar * sender_name, gchar * signal_name, GVariant * parameters, gpointer user_data); static void service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data); static void user_real_name_get_cb (GObject * obj, GAsyncResult * res, gpointer user_data); -static void user_menu_visibility_get_cb (GObject* obj, GAsyncResult* res, gpointer user_data); static void indicator_session_class_init (IndicatorSessionClass *klass); static void indicator_session_init (IndicatorSession *self); @@ -102,10 +97,10 @@ static void indicator_session_finalize (GObject *object); static GList* indicator_session_get_entries (IndicatorObject* obj); static guint indicator_session_get_location (IndicatorObject * io, IndicatorObjectEntry * entry); - + G_DEFINE_TYPE (IndicatorSession, indicator_session, INDICATOR_OBJECT_TYPE); -static void +static void indicator_session_class_init (IndicatorSessionClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); @@ -122,126 +117,64 @@ indicator_session_class_init (IndicatorSessionClass *klass) static void indicator_session_init (IndicatorSession *self) { - self->service = NULL; - self->service_proxy_cancel = NULL; - self->service_proxy = NULL; - self->show_users_entry = FALSE; - - /* Now let's fire these guys up. */ - self->service = indicator_service_manager_new_version(INDICATOR_SESSION_DBUS_NAME, + self->settings = g_settings_new ("com.canonical.indicator.session"); + + /* Now let's fire these guys up. */ + self->service = indicator_service_manager_new_version(INDICATOR_SESSION_DBUS_NAME, INDICATOR_SESSION_DBUS_VERSION); - g_signal_connect(G_OBJECT(self->service), - INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE, - G_CALLBACK(service_connection_cb), self); - - GtkWidget* avatar_icon = NULL; - // users - self->users.name_hint = PACKAGE"-users"; - self->users.menu = GTK_MENU (dbusmenu_gtkmenu_new (INDICATOR_USERS_DBUS_NAME, - INDICATOR_USERS_DBUS_OBJECT)); - // Set the image to the default avator image - GdkPixbuf* pixbuf = NULL; - GError* error = NULL; - pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), - "avatar-default", - 17, - GTK_ICON_LOOKUP_FORCE_SIZE, - &error); - - // I think the avatar image is available always but just in case have a fallback - if (error != NULL) { - g_warning ("Could not load the default avatar image for some reason"); - self->users.image = indicator_image_helper (USER_ITEM_ICON_DEFAULT); - } - else{ - avatar_icon = gtk_image_new (); - gtk_image_set_from_pixbuf (GTK_IMAGE (avatar_icon), pixbuf); - self->users.image = GTK_IMAGE (avatar_icon); - g_object_unref (pixbuf); - g_error_free (error); - } - - self->users.label = GTK_LABEL (gtk_label_new (NULL)); - self->users.accessible_desc = _("User Menu"); - - const gchar *greeter_var; - greeter_var = g_getenv("INDICATOR_GREETER_MODE"); - greeter_mode = g_strcmp0(greeter_var, "1") == 0; - - // devices - self->devices.name_hint = PACKAGE"-devices"; - self->devices.accessible_desc = _("Device Menu"); - self->devices.menu = GTK_MENU (dbusmenu_gtkmenu_new(INDICATOR_SESSION_DBUS_NAME, - INDICATOR_SESSION_DBUS_OBJECT)); - if (greeter_mode){ - self->devices.image = indicator_image_helper (GREETER_ICON_DEFAULT); - } - else{ - self->devices.image = indicator_image_helper (ICON_DEFAULT); - } - - gtk_widget_show (GTK_WIDGET(self->devices.menu)); - gtk_widget_show (GTK_WIDGET(self->devices.image)); - gtk_widget_show (GTK_WIDGET(self->users.image)); - gtk_widget_show (GTK_WIDGET(self->users.menu)); - - g_object_ref_sink (self->users.menu); - g_object_ref_sink (self->users.image); - g_object_ref_sink (self->devices.menu); - g_object_ref_sink (self->devices.image); - - // Setup the handlers for users - DbusmenuClient * users_client = DBUSMENU_CLIENT(dbusmenu_gtkmenu_get_client(DBUSMENU_GTKMENU(self->users.menu))); - dbusmenu_client_add_type_handler (users_client, + g_signal_connect (G_OBJECT(self->service), + INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE, + G_CALLBACK(service_connection_cb), self); + + greeter_mode = !g_strcmp0(g_getenv("INDICATOR_GREETER_MODE"), "1"); + + self->entry.name_hint = PACKAGE; + self->entry.accessible_desc = _("Session Menu"); + self->entry.label = GTK_LABEL (gtk_label_new ("User Name")); + self->entry.image = greeter_mode + ? indicator_image_helper (GREETER_ICON_DEFAULT) + : indicator_image_helper (ICON_DEFAULT); + self->entry.menu = GTK_MENU (dbusmenu_gtkmenu_new(INDICATOR_SESSION_DBUS_NAME, + INDICATOR_SESSION_DBUS_OBJECT)); + g_settings_bind (self->settings, "show-real-name-on-panel", + self->entry.label, "visible", + G_SETTINGS_BIND_GET); + + gtk_widget_show (GTK_WIDGET(self->entry.menu)); + gtk_widget_show (GTK_WIDGET(self->entry.image)); + g_object_ref_sink (self->entry.menu); + g_object_ref_sink (self->entry.image); + + // set up the handlers + DbusmenuClient * menu_client = DBUSMENU_CLIENT(dbusmenu_gtkmenu_get_client(DBUSMENU_GTKMENU(self->entry.menu))); + dbusmenu_client_add_type_handler (menu_client, USER_ITEM_TYPE, new_user_item); - dbusmenu_client_add_type_handler_full (users_client, - MENU_SWITCH_TYPE, - build_menu_switch, - self, NULL); - - // Setup the handlers for devices - DbusmenuClient * devices_client = DBUSMENU_CLIENT(dbusmenu_gtkmenu_get_client(DBUSMENU_GTKMENU(self->devices.menu))); - dbusmenu_client_add_type_handler (devices_client, + dbusmenu_client_add_type_handler (menu_client, RESTART_ITEM_TYPE, build_restart_item); - - GtkAccelGroup * agroup = gtk_accel_group_new(); - dbusmenu_gtkclient_set_accel_group(DBUSMENU_GTKCLIENT(devices_client), agroup); - return; + dbusmenu_gtkclient_set_accel_group (DBUSMENU_GTKCLIENT(menu_client), + gtk_accel_group_new()); } static void indicator_session_dispose (GObject *object) { - IndicatorSession * self = INDICATOR_SESSION(object); + IndicatorSession * self = INDICATOR_SESSION(object); - if (self->service != NULL) { - g_object_unref(G_OBJECT(self->service)); - self->service = NULL; - } + g_clear_object (&self->settings); + g_clear_object (&self->service); + g_clear_object (&self->service_proxy); - if (self->service_proxy != NULL) { - g_object_unref(self->service_proxy); - self->service_proxy = NULL; - } + if (self->service_proxy_cancel != NULL) + { + g_cancellable_cancel(self->service_proxy_cancel); + g_clear_object (&self->service_proxy_cancel); + } - if (self->service_proxy_cancel != NULL) { - g_cancellable_cancel(self->service_proxy_cancel); - g_object_unref(self->service_proxy_cancel); - self->service_proxy_cancel = NULL; - } - - if (self->users.menu != NULL) { - g_object_unref (self->users.menu); - } - - if (self->devices.menu != NULL) { - g_object_unref (self->devices.menu); - } + g_clear_object (&self->entry.menu); - G_OBJECT_CLASS (indicator_session_parent_class)->dispose (object); - return; + G_OBJECT_CLASS (indicator_session_parent_class)->dispose (object); } static void @@ -255,35 +188,16 @@ indicator_session_finalize (GObject *object) static GList* indicator_session_get_entries (IndicatorObject* obj) { - g_return_val_if_fail(IS_INDICATOR_SESSION(obj), NULL); - IndicatorSession* self = INDICATOR_SESSION (obj); - - g_debug ("get entries"); - GList * retval = NULL; - // Only show the users menu if we have more than one - if (self->show_users_entry == TRUE){ - retval = g_list_prepend (retval, &self->users); - } - retval = g_list_prepend (retval, &self->devices); + g_return_val_if_fail(IS_INDICATOR_SESSION(obj), NULL); - if (retval != NULL) { - retval = g_list_reverse(retval); - } - return retval; + IndicatorSession* self = INDICATOR_SESSION (obj); + return g_list_append (NULL, &self->entry); } static guint indicator_session_get_location (IndicatorObject * io, IndicatorObjectEntry * entry) -{ - IndicatorSession * self = INDICATOR_SESSION (io); - if (entry == &self->users){ - return 0; - } - else if (entry == &self->devices){ - return 1; - } - g_warning ("IOEntry handed to us to position but we don't own it!"); +{ return 0; } @@ -298,24 +212,16 @@ service_connection_cb (IndicatorServiceManager * sm, gboolean connected, gpointe // Its a reconnect ! // Fetch synchronisation data and return (proxy is still legit) g_dbus_proxy_call (self->service_proxy, - "GetUserMenuVisibility", - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - user_menu_visibility_get_cb, - user_data); - g_dbus_proxy_call (self->service_proxy, "GetUserRealName", NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, user_real_name_get_cb, - user_data); + user_data); return; } - + self->service_proxy_cancel = g_cancellable_new(); g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_NONE, @@ -326,7 +232,7 @@ service_connection_cb (IndicatorServiceManager * sm, gboolean connected, gpointe self->service_proxy_cancel, service_proxy_cb, self); - } + } return; } @@ -341,10 +247,7 @@ service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data) GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish(res, &error); - if (self->service_proxy_cancel != NULL) { - g_object_unref(self->service_proxy_cancel); - self->service_proxy_cancel = NULL; - } + g_clear_object (&self->service_proxy_cancel); if (error != NULL) { g_warning("Could not grab DBus proxy for %s: %s", INDICATOR_SESSION_DBUS_NAME, error->message); @@ -357,17 +260,7 @@ service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data) self->service_proxy = proxy; g_signal_connect(proxy, "g-signal", G_CALLBACK(receive_signal), self); - - // Figure out whether we should show the user menu at all. - g_dbus_proxy_call (self->service_proxy, - "GetUserMenuVisibility", - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - user_menu_visibility_get_cb, - user_data); - + // Fetch the user's real name for the user entry label g_dbus_proxy_call (self->service_proxy, "GetUserRealName", @@ -384,17 +277,13 @@ service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data) static gboolean new_user_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, - DbusmenuClient * client, - gpointer user_data) + DbusmenuClient * client, + gpointer user_data) { - - - GtkWidget* user_item = NULL; + g_return_val_if_fail (DBUSMENU_IS_MENUITEM(newitem), FALSE); + g_return_val_if_fail (DBUSMENU_IS_GTKCLIENT(client), FALSE); - g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE); - g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE); - - user_item = user_widget_new(newitem); + GtkWidget * user_item = user_widget_new (newitem); GtkMenuItem *user_widget = GTK_MENU_ITEM(user_item); @@ -415,191 +304,51 @@ new_user_item (DbusmenuMenuitem * newitem, static void user_real_name_get_cb (GObject * obj, GAsyncResult * res, gpointer user_data) { - IndicatorSession * self = INDICATOR_SESSION(user_data); - GError * error = NULL; - GVariant * result; - - result = g_dbus_proxy_call_finish(self->service_proxy, res, &error); + IndicatorSession * self = INDICATOR_SESSION(user_data); - if (error != NULL) { - g_warning ("unable to complete real name dbus query"); - g_error_free (error); - return; - } - - const gchar* username = NULL; - g_variant_get (result, "(s)", &username); - indicator_session_update_users_label (self, username); - return; -} - -static void -user_menu_visibility_get_cb (GObject* obj, GAsyncResult* res, gpointer user_data) -{ - IndicatorSession * self = INDICATOR_SESSION(user_data); - GError * error = NULL; - GVariant * result; + GError * error = NULL; + GVariant * result = g_dbus_proxy_call_finish(self->service_proxy, res, &error); - result = g_dbus_proxy_call_finish(self->service_proxy, res, &error); - - if (error != NULL) { - g_warning ("unable to complete real name dbus query"); - g_error_free (error); - return; - } - gboolean update; - g_variant_get (result, "(b)", &update); - - // If it is what we had before no need to do anything... - if (self->show_users_entry == update){ - return; - } - //Otherwise - self->show_users_entry = update; - - if (self->show_users_entry == TRUE){ - g_signal_emit_by_name ((gpointer)self, - "entry-added", - &self->users); - } - else{ - g_signal_emit_by_name ((gpointer)self, - "entry-removed", - &self->users); - } + if (error != NULL) + { + g_warning ("Unable to complete real name dbus query: %s", error->message); + g_clear_error (&error); + } + else + { + const gchar * username = NULL; + g_variant_get (result, "(&s)", &username); + indicator_session_update_users_label (self, username); + g_variant_unref (result); + } } /* Receives all signals from the service, routed to the appropriate functions */ static void receive_signal (GDBusProxy * proxy, - gchar * sender_name, - gchar * signal_name, - GVariant * parameters, - gpointer user_data) + gchar * sender_name, + gchar * signal_name, + GVariant * parameters, + gpointer user_data) { - IndicatorSession * self = INDICATOR_SESSION(user_data); + IndicatorSession * self = INDICATOR_SESSION(user_data); - if (g_strcmp0(signal_name, "UserRealNameUpdated") == 0) { - const gchar* username = NULL; - g_variant_get (parameters, "(s)", &username); - indicator_session_update_users_label (self, username); - } - else if (g_strcmp0(signal_name, "UserMenuIsVisible") == 0) { - gboolean update; - g_variant_get (parameters, "(b)", &update); - - // If it is what we had before no need to do anything... - if (self->show_users_entry == update){ - return; - } - - //Otherwise - self->show_users_entry = update; - - if (self->show_users_entry == TRUE){ - g_signal_emit_by_name ((gpointer)self, - "entry-added", - &self->users); - - } - else{ - g_signal_emit_by_name ((gpointer)self, - "entry-removed", - &self->users); - } - } - else if (g_strcmp0(signal_name, "RestartRequired") == 0) { - if (greeter_mode == TRUE){ - indicator_image_helper_update(self->devices.image, GREETER_ICON_RESTART); + if (!g_strcmp0(signal_name, "UserRealNameUpdated")) + { + const gchar * username = NULL; + g_variant_get (parameters, "(&s)", &username); + indicator_session_update_users_label (self, username); } - else{ - g_debug ("reboot required"); - indicator_image_helper_update(self->devices.image, ICON_RESTART); + else if (!g_strcmp0(signal_name, "RestartRequired")) + { + indicator_image_helper_update (self->entry.image, greeter_mode ? GREETER_ICON_RESTART : ICON_RESTART); + self->entry.accessible_desc = _("Device Menu (reboot required)"); + g_signal_emit (G_OBJECT(self), INDICATOR_OBJECT_SIGNAL_ACCESSIBLE_DESC_UPDATE_ID, 0, &self->entry); } - self->devices.accessible_desc = _("Device Menu (reboot required)"); - g_signal_emit(G_OBJECT(self), INDICATOR_OBJECT_SIGNAL_ACCESSIBLE_DESC_UPDATE_ID, 0, &(self->devices)); - } } -static void -switch_property_change (DbusmenuMenuitem * item, - const gchar * property, - GVariant * variant, - gpointer user_data) -{ - if (g_strcmp0 (property, MENU_SWITCH_USER) != 0) { - return; - } - - GtkMenuItem * gmi = dbusmenu_gtkclient_menuitem_get(DBUSMENU_GTKCLIENT(user_data), item); - gchar * finalstring = NULL; - gboolean set_ellipsize = FALSE; - gboolean no_name_in_lang = FALSE; - - const gchar * translate = C_("session_menu:switchfrom", "1"); - if (g_strcmp0(translate, "1") != 0) { - no_name_in_lang = TRUE; - } - - GSettings* settings = g_settings_new ("com.canonical.indicator.session"); - gboolean use_username = g_settings_get_boolean (settings, - "use-username-in-switch-item"); - g_object_unref (settings); - - if (variant == NULL || g_variant_get_string(variant, NULL) == NULL || - g_variant_get_string(variant, NULL)[0] == '\0' || no_name_in_lang - || use_username == FALSE) { - finalstring = _("Switch User Account…"); - set_ellipsize = FALSE; - } - - if (finalstring == NULL) { - const gchar * username = g_variant_get_string(variant, NULL); - GtkStyle * style = gtk_widget_get_style(GTK_WIDGET(gmi)); - - PangoLayout * layout = pango_layout_new(gtk_widget_get_pango_context(GTK_WIDGET(gmi))); - pango_layout_set_text (layout, username, -1); - pango_layout_set_font_description(layout, style->font_desc); - - gint width; - pango_layout_get_pixel_size(layout, &width, NULL); - g_object_unref(layout); - g_debug("Username width %dpx", width); - - gint point = pango_font_description_get_size(style->font_desc); - g_debug("Font size %f pt", (gfloat)point / PANGO_SCALE); - - gdouble dpi = gdk_screen_get_resolution(gdk_screen_get_default()); - g_debug("Screen DPI %f", dpi); - - gdouble pixels_per_em = ((point * dpi) / 72.0f) / PANGO_SCALE; - gdouble ems = width / pixels_per_em; - g_debug("Username width %fem", ems); - - finalstring = g_strdup_printf(_("Switch From %s…"), username); - if (ems >= 20.0f) { - set_ellipsize = TRUE; - } else { - set_ellipsize = FALSE; - } - - } - gtk_menu_item_set_label(gmi, finalstring); - - GtkLabel * label = GTK_LABEL(gtk_bin_get_child(GTK_BIN(gmi))); - if (label != NULL) { - if (set_ellipsize) { - gtk_label_set_ellipsize(label, PANGO_ELLIPSIZE_END); - } else { - gtk_label_set_ellipsize(label, PANGO_ELLIPSIZE_NONE); - } - } - return; -} - -static const gchar * dbusmenu_item_data = "dbusmenu-item"; static void restart_property_change (DbusmenuMenuitem * item, @@ -657,70 +406,8 @@ build_restart_item (DbusmenuMenuitem * newitem, } static void -switch_style_set (GtkWidget * widget, - GtkStyle * prev_style, - gpointer user_data) -{ - DbusmenuGtkClient * client = DBUSMENU_GTKCLIENT(user_data); - DbusmenuMenuitem * mi = DBUSMENU_MENUITEM(g_object_get_data(G_OBJECT(widget), - dbusmenu_item_data)); - - switch_property_change (mi, - MENU_SWITCH_USER, - dbusmenu_menuitem_property_get_variant(mi, MENU_SWITCH_USER), - client); - return; -} - -static gboolean -build_menu_switch (DbusmenuMenuitem * newitem, - DbusmenuMenuitem * parent, - DbusmenuClient * client, - gpointer user_data) +indicator_session_update_users_label (IndicatorSession * self, + const gchar * name) { - GtkMenuItem * gmi = GTK_MENU_ITEM(gtk_menu_item_new()); - if (gmi == NULL) { - return FALSE; - } - - g_object_set_data(G_OBJECT(gmi), dbusmenu_item_data, newitem); - - dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, gmi, parent); - - g_signal_connect (G_OBJECT(newitem), - DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, - G_CALLBACK(switch_property_change), - client); - g_signal_connect (G_OBJECT(gmi), - "style-set", - G_CALLBACK(switch_style_set), - client); - - switch_property_change (newitem, - MENU_SWITCH_USER, - dbusmenu_menuitem_property_get_variant(newitem, MENU_SWITCH_USER), client); - - return TRUE; -} - -static void -indicator_session_update_users_label (IndicatorSession* self, - const gchar* name) -{ - if (name == NULL){ - gtk_widget_hide(GTK_WIDGET(self->users.label)); - return; - } - - GSettings* settings = g_settings_new ("com.canonical.indicator.session"); - gboolean use_name = g_settings_get_boolean (settings, - "show-real-name-on-panel"); - g_object_unref (settings); - gtk_label_set_text (self->users.label, g_strdup(name)); - if (use_name){ - gtk_widget_show(GTK_WIDGET(self->users.label)); - } - else{ - gtk_widget_hide(GTK_WIDGET(self->users.label)); - } + gtk_label_set_text (self->entry.label, name ? name : ""); } diff --git a/src/lock-helper.c b/src/lock-helper.c deleted file mode 100644 index 8eae674..0000000 --- a/src/lock-helper.c +++ /dev/null @@ -1,157 +0,0 @@ -/* -A small helper for locking the screen. - -Copyright 2009 Canonical Ltd. - -Authors: - Ted Gould <ted@canonical.com> - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>. -*/ - -#include <glib/gi18n.h> -#include <gio/gio.h> -#include <dbus/dbus-glib.h> -#include "lock-helper.h" - -#define SCREENSAVER_SCHEMA "org.gnome.desktop.screensaver" -#define SCREENSAVER_LOCK_ENABLED_KEY "lock-enabled" - -static DBusGProxy * gss_proxy = NULL; -static GMainLoop * gss_mainloop = NULL; - -static gboolean is_guest = FALSE; - -static GSettings * settings = NULL; - -void build_gss_proxy (void); - -/* This is our logic on whether the screen should be locked - or not. It effects everything else. */ -gboolean -will_lock_screen (void) -{ - if (is_guest) { - return FALSE; - } - - if (settings == NULL) { - settings = g_settings_new (SCREENSAVER_SCHEMA); - } - - return g_settings_get_boolean (settings, SCREENSAVER_LOCK_ENABLED_KEY); -} - -/* When the screensave go active, if we've got a mainloop - running we should quit it. */ -static void -gss_active_changed (DBusGProxy * proxy, gboolean active, gpointer data) -{ - if (active && gss_mainloop != NULL) { - g_main_loop_quit(gss_mainloop); - } - - return; -} - -static gboolean -get_greeter_mode (void) -{ - const gchar *var; - var = g_getenv("INDICATOR_GREETER_MODE"); - return (g_strcmp0(var, "1") == 0); -} - -/* Build the gss proxy and set up it's signals */ -void -build_gss_proxy (void) -{ - if (gss_proxy == NULL) { - if (get_greeter_mode ()) - return; /* Don't start/lock the screensaver from the login screen */ - - DBusGConnection * session_bus = dbus_g_bus_get(DBUS_BUS_SESSION, NULL); - g_return_if_fail(session_bus != NULL); - - gss_proxy = dbus_g_proxy_new_for_name(session_bus, - "org.gnome.ScreenSaver", - "/", - "org.gnome.ScreenSaver"); - g_return_if_fail(gss_proxy != NULL); - - dbus_g_proxy_add_signal(gss_proxy, "ActiveChanged", G_TYPE_BOOLEAN, G_TYPE_INVALID); - dbus_g_proxy_connect_signal(gss_proxy, "ActiveChanged", G_CALLBACK(gss_active_changed), NULL, NULL); - } - - return; -} - -/* This is a timeout, we only want to wait for the screen to - lock for a little bit, but not forever. */ -static gboolean -activate_timeout (gpointer data) -{ - /* Clear the ID for the timeout */ - guint * address = (guint *)data; - *address = 0; - - /* Quit the mainloop */ - if (gss_mainloop != NULL) { - g_main_loop_quit(gss_mainloop); - } - - return FALSE; -} - -/* A fun little function to actually lock the screen. If, - that's what you want, let's do it! */ -void -lock_screen (DbusmenuMenuitem * mi, guint timestamp, gpointer data) -{ - g_debug("Lock Screen"); - - build_gss_proxy(); - g_return_if_fail(gss_proxy != NULL); - - dbus_g_proxy_call_no_reply(gss_proxy, - "Lock", - G_TYPE_INVALID, - G_TYPE_INVALID); - - if (gss_mainloop == NULL) { - gss_mainloop = g_main_loop_new(NULL, FALSE); - } - - guint timer = g_timeout_add_seconds(1, activate_timeout, &timer); - - g_main_loop_run(gss_mainloop); - - if (timer != 0) { - g_source_remove(timer); - } - - return; -} - -/* Do what it takes to make the lock screen function work - and be happy. */ -gboolean -lock_screen_setup (gpointer data) -{ - if (!g_strcmp0(g_get_user_name(), "guest")) { - is_guest = TRUE; - } - - return FALSE; -} - diff --git a/src/lock-helper.h b/src/lock-helper.h deleted file mode 100644 index e2d5106..0000000 --- a/src/lock-helper.h +++ /dev/null @@ -1,31 +0,0 @@ -/* -A small helper for locking the screen. - -Copyright 2009 Canonical Ltd. - -Authors: - Ted Gould <ted@canonical.com> - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>. -*/ - -#ifndef LOCK_HELPER_H__ -#define LOCK_HELPER_H__ - -#include <libdbusmenu-glib/menuitem.h> - -gboolean will_lock_screen (void); -void lock_screen (DbusmenuMenuitem * mi, guint timestamp, gpointer data); -gboolean lock_screen_setup (gpointer data); - -#endif /* LOCK_HELPER_H__ */ diff --git a/src/accounts-service-user.xml b/src/org.freedesktop.Accounts.User.xml index bd4cb21..53f54d4 100644 --- a/src/accounts-service-user.xml +++ b/src/org.freedesktop.Accounts.User.xml @@ -2,6 +2,7 @@ "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd" > <node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd"> + <interface name="org.freedesktop.Accounts.User"> <method name="SetUserName"> @@ -125,10 +126,10 @@ <doc:para> Sets the users language. </doc:para> - <doc:language> + <doc:para> The expectation is that display managers will start the users session with this locale. - </doc:language> + </doc:para> </doc:description> <doc:permission> The caller needs one of the following PolicyKit authorizations: @@ -150,6 +151,46 @@ </doc:doc> </method> + <method name="SetXSession"> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + <annotation name="org.freedesktop.DBus.GLib.CSymbol" value="user_set_x_session"/> + <arg name="x_session" direction="in" type="s"> + <doc:doc> + <doc:summary> + The new xsession to start (e.g. "gnome") + </doc:summary> + </doc:doc> + </arg> + <doc:doc> + <doc:description> + <doc:para> + Sets the users x session. + </doc:para> + <doc:para> + The expectation is that display managers will log the user in to this + specified session, if available. + </doc:para> + </doc:description> + <doc:permission> + The caller needs one of the following PolicyKit authorizations: + <doc:list> + <doc:item> + <doc:term>org.freedesktop.accounts.change-own-user-data</doc:term> + <doc:definition>To change his own language</doc:definition> + </doc:item> + <doc:item> + <doc:term>org.freedesktop.accounts.user-administration</doc:term> + <doc:definition>To change the language of another user</doc:definition> + </doc:item> + </doc:list> + </doc:permission> + <doc:errors> + <doc:error name="org.freedesktop.Accounts.Error.PermissionDenied">if the caller lacks the appropriate PolicyKit authorization</doc:error> + <doc:error name="org.freedesktop.Accounts.Error.Failed">if the operation failed</doc:error> + </doc:errors> + </doc:doc> + </method> + <method name="SetLocation"> <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> <arg name="location" direction="in" type="s"> @@ -340,10 +381,6 @@ <doc:term>1</doc:term> <doc:definition>Administrator</doc:definition> </doc:item> - <doc:item> - <doc:term>2</doc:term> - <doc:definition>Supervised user</doc:definition> - </doc:item> </doc:list> </doc:summary> </doc:doc> @@ -541,10 +578,6 @@ <doc:term>1</doc:term> <doc:definition>Administrator</doc:definition> </doc:item> - <doc:item> - <doc:term>2</doc:term> - <doc:definition>Supervised user</doc:definition> - </doc:item> </doc:list> </doc:para> </doc:description> @@ -591,6 +624,16 @@ </doc:doc> </property> + <property name="XSession" type="s" access="read"> + <doc:doc> + <doc:description> + <doc:para> + The users x session. + </doc:para> + </doc:description> + </doc:doc> + </property> + <property name="Location" type="s" access="read"> <doc:doc> <doc:description> @@ -675,6 +718,18 @@ </doc:doc> </property> + <property name="SystemAccount" type="b" access="read"> + <doc:doc> + <doc:description> + <doc:para> + Whether this is a 'system' account, like 'root' or 'nobody'. + System accounts should normally not appear in lists of + users, and ListCachedUsers will not include such accounts. + </doc:para> + </doc:description> + </doc:doc> + </property> + <signal name="Changed"> <doc:doc> <doc:description> diff --git a/src/accounts-service.xml b/src/org.freedesktop.Accounts.xml index 9c19761..9c19761 100644 --- a/src/accounts-service.xml +++ b/src/org.freedesktop.Accounts.xml diff --git a/src/org.freedesktop.ConsoleKit.Seat.xml b/src/org.freedesktop.ConsoleKit.Seat.xml index d95990b..58c2ce7 100644 --- a/src/org.freedesktop.ConsoleKit.Seat.xml +++ b/src/org.freedesktop.ConsoleKit.Seat.xml @@ -101,7 +101,7 @@ seat at a time.</doc:para> </method> <signal name="ActiveSessionChanged"> - <arg name="ssid" type="o"> + <arg name="ssid" type="s"> <doc:doc> <doc:summary>Session ID</doc:summary> </doc:doc> diff --git a/src/sane-rules.h b/src/sane-rules.h deleted file mode 100644 index 0b72e52..0000000 --- a/src/sane-rules.h +++ /dev/null @@ -1,778 +0,0 @@ -void populate_scsi_scanners (GHashTable* scanners) -{ - GList* epson = NULL; - epson = g_list_append (epson, g_strdup ("GT-9700")); - epson = g_list_append (epson, g_strdup ("GT-9800")); - epson = g_list_append (epson, g_strdup ("Perfection1200")); - epson = g_list_append (epson, g_strdup ("Perfection636")); - epson = g_list_append (epson, g_strdup ("SCANNER GT-7000")); - g_hash_table_insert (scanners, - g_strdup("EPSON"), - epson); - - - GList* hp = NULL; - hp = g_list_append (hp, g_strdup ("C1130A")); - hp = g_list_append (hp, g_strdup ("C1750A")); - hp = g_list_append (hp, g_strdup ("C1790A")); - hp = g_list_append (hp, g_strdup ("C2500A")); - hp = g_list_append (hp, g_strdup ("C2520A")); - hp = g_list_append (hp, g_strdup ("C5110A")); - hp = g_list_append (hp, g_strdup ("C6270A")); - hp = g_list_append (hp, g_strdup ("C7670A")); - g_hash_table_insert (scanners, - g_strdup("HP"), - hp); -} - - - -void populate_usb_scanners (GHashTable* scanners) -{ - GList* hp = NULL; - - hp = g_list_append (hp, g_strdup ("0101")); - hp = g_list_append (hp, g_strdup ("0105")); - hp = g_list_append (hp, g_strdup ("0201")); - hp = g_list_append (hp, g_strdup ("0205")); - hp = g_list_append (hp, g_strdup ("0305")); - hp = g_list_append (hp, g_strdup ("0401")); - hp = g_list_append (hp, g_strdup ("0405")); - hp = g_list_append (hp, g_strdup ("0505")); - hp = g_list_append (hp, g_strdup ("0601")); - hp = g_list_append (hp, g_strdup ("0605")); - hp = g_list_append (hp, g_strdup ("0701")); - hp = g_list_append (hp, g_strdup ("0705")); - hp = g_list_append (hp, g_strdup ("0801")); - hp = g_list_append (hp, g_strdup ("0805")); - hp = g_list_append (hp, g_strdup ("0901")); - hp = g_list_append (hp, g_strdup ("0a01")); - hp = g_list_append (hp, g_strdup ("0b01")); - hp = g_list_append (hp, g_strdup ("1005")); - hp = g_list_append (hp, g_strdup ("1105")); - hp = g_list_append (hp, g_strdup ("1205")); - hp = g_list_append (hp, g_strdup ("1305")); - hp = g_list_append (hp, g_strdup ("1405")); - hp = g_list_append (hp, g_strdup ("1705")); - hp = g_list_append (hp, g_strdup ("1805")); - hp = g_list_append (hp, g_strdup ("2005")); - hp = g_list_append (hp, g_strdup ("2205")); - hp = g_list_append (hp, g_strdup ("2305")); - hp = g_list_append (hp, g_strdup ("2405")); - hp = g_list_append (hp, g_strdup ("2605")); - hp = g_list_append (hp, g_strdup ("2805")); - hp = g_list_append (hp, g_strdup ("3805")); - hp = g_list_append (hp, g_strdup ("3905")); - hp = g_list_append (hp, g_strdup ("3B17")); - hp = g_list_append (hp, g_strdup ("4105")); - hp = g_list_append (hp, g_strdup ("4205")); - hp = g_list_append (hp, g_strdup ("4305")); - hp = g_list_append (hp, g_strdup ("4505")); - hp = g_list_append (hp, g_strdup ("4605")); - hp = g_list_append (hp, g_strdup ("5617")); - hp = g_list_append (hp, g_strdup ("5717")); - - g_hash_table_insert (scanners, - g_strdup("03f0"), - hp); - - GList* mustek_2 = NULL; - mustek_2 = g_list_append (mustek_2, g_strdup ("1000")); - mustek_2 = g_list_append (mustek_2, g_strdup ("1001")); - g_hash_table_insert (scanners, - g_strdup("0400"), - mustek_2); - - GList* kodak = NULL; - kodak = g_list_append (kodak, g_strdup ("6001")); - kodak = g_list_append (kodak, g_strdup ("6002")); - kodak = g_list_append (kodak, g_strdup ("6003")); - kodak = g_list_append (kodak, g_strdup ("6004")); - kodak = g_list_append (kodak, g_strdup ("6005")); - g_hash_table_insert (scanners, - g_strdup("040a"), - kodak); - - GList* creative = NULL; - - creative = g_list_append (creative, g_strdup ("4007")); - - g_hash_table_insert (scanners, - g_strdup("041e"), - creative); - - GList* lexmark = NULL; - - lexmark = g_list_append (lexmark, g_strdup("002d")); - lexmark = g_list_append (lexmark, g_strdup("0060")); - lexmark = g_list_append (lexmark, g_strdup("007c")); - lexmark = g_list_append (lexmark, g_strdup("007d")); - - g_hash_table_insert (scanners, - g_strdup("043d"), - lexmark); - - - GList* genius = NULL; - genius = g_list_append (genius, g_strdup("2004")); - genius = g_list_append (genius, g_strdup("2007")); - genius = g_list_append (genius, g_strdup("2008")); - genius = g_list_append (genius, g_strdup("2009")); - genius = g_list_append (genius, g_strdup("2011")); - genius = g_list_append (genius, g_strdup("2013")); - genius = g_list_append (genius, g_strdup("2014")); - genius = g_list_append (genius, g_strdup("2015")); - genius = g_list_append (genius, g_strdup("2016")); - genius = g_list_append (genius, g_strdup("2017")); - genius = g_list_append (genius, g_strdup("201a")); - genius = g_list_append (genius, g_strdup("201b")); - genius = g_list_append (genius, g_strdup("201d")); - genius = g_list_append (genius, g_strdup("201e")); - genius = g_list_append (genius, g_strdup("201f")); - genius = g_list_append (genius, g_strdup("20c1")); - g_hash_table_insert (scanners, - g_strdup("0458"), - genius); - - GList* medion = NULL; - medion = g_list_append (medion, g_strdup("0377")); - g_hash_table_insert (scanners, - g_strdup("0461"), - medion); - - GList* trust = NULL; - trust = g_list_append (trust, g_strdup("1000")); - trust = g_list_append (trust, g_strdup("1002")); - g_hash_table_insert (scanners, - g_strdup("047b"), - trust); - - GList* kyocera = NULL; - kyocera = g_list_append (kyocera, g_strdup("0335")); - g_hash_table_insert (scanners, - g_strdup("0482"), - kyocera); - - GList* compaq = NULL; - compaq = g_list_append (compaq, g_strdup("001a")); - g_hash_table_insert (scanners, - g_strdup("049f"), - compaq); - GList* benq = NULL; - benq = g_list_append (benq, g_strdup("1a20")); - benq = g_list_append (benq, g_strdup("1a2a")); - benq = g_list_append (benq, g_strdup("2022")); - benq = g_list_append (benq, g_strdup("2040")); - benq = g_list_append (benq, g_strdup("2060")); - benq = g_list_append (benq, g_strdup("207e")); - benq = g_list_append (benq, g_strdup("20b0")); - benq = g_list_append (benq, g_strdup("20be")); - benq = g_list_append (benq, g_strdup("20c0")); - benq = g_list_append (benq, g_strdup("20de")); - benq = g_list_append (benq, g_strdup("20f8")); - benq = g_list_append (benq, g_strdup("20fc")); - benq = g_list_append (benq, g_strdup("20fe")); - benq = g_list_append (benq, g_strdup("2137")); - benq = g_list_append (benq, g_strdup("2211")); - g_hash_table_insert (scanners, - g_strdup("04a5"), - benq); - - GList* visioneer = NULL; - visioneer = g_list_append (visioneer, g_strdup("0229")); - visioneer = g_list_append (visioneer, g_strdup("0390")); - visioneer = g_list_append (visioneer, g_strdup("0420")); - visioneer = g_list_append (visioneer, g_strdup("0421")); - visioneer = g_list_append (visioneer, g_strdup("0422")); - visioneer = g_list_append (visioneer, g_strdup("0423")); - visioneer = g_list_append (visioneer, g_strdup("0424")); - visioneer = g_list_append (visioneer, g_strdup("0426")); - visioneer = g_list_append (visioneer, g_strdup("0427")); - visioneer = g_list_append (visioneer, g_strdup("0444")); - visioneer = g_list_append (visioneer, g_strdup("0446")); - visioneer = g_list_append (visioneer, g_strdup("0447")); - visioneer = g_list_append (visioneer, g_strdup("0448")); - visioneer = g_list_append (visioneer, g_strdup("0449")); - visioneer = g_list_append (visioneer, g_strdup("044c")); - visioneer = g_list_append (visioneer, g_strdup("0474")); - visioneer = g_list_append (visioneer, g_strdup("0475")); - visioneer = g_list_append (visioneer, g_strdup("0477")); - visioneer = g_list_append (visioneer, g_strdup("0478")); - visioneer = g_list_append (visioneer, g_strdup("0479")); - visioneer = g_list_append (visioneer, g_strdup("047a")); - visioneer = g_list_append (visioneer, g_strdup("047b")); - visioneer = g_list_append (visioneer, g_strdup("047c")); - visioneer = g_list_append (visioneer, g_strdup("048c")); - visioneer = g_list_append (visioneer, g_strdup("048d")); - visioneer = g_list_append (visioneer, g_strdup("048e")); - visioneer = g_list_append (visioneer, g_strdup("048f")); - visioneer = g_list_append (visioneer, g_strdup("0490")); - visioneer = g_list_append (visioneer, g_strdup("0491")); - visioneer = g_list_append (visioneer, g_strdup("0492")); - visioneer = g_list_append (visioneer, g_strdup("0493")); - visioneer = g_list_append (visioneer, g_strdup("0494")); - visioneer = g_list_append (visioneer, g_strdup("0495")); - visioneer = g_list_append (visioneer, g_strdup("0497")); - visioneer = g_list_append (visioneer, g_strdup("0498")); - visioneer = g_list_append (visioneer, g_strdup("0499")); - visioneer = g_list_append (visioneer, g_strdup("049a")); - visioneer = g_list_append (visioneer, g_strdup("049b")); - visioneer = g_list_append (visioneer, g_strdup("049c")); - visioneer = g_list_append (visioneer, g_strdup("049d")); - visioneer = g_list_append (visioneer, g_strdup("04a7")); - visioneer = g_list_append (visioneer, g_strdup("04ac")); - g_hash_table_insert (scanners, - g_strdup("04a7"), - visioneer); - GList* canon = NULL; - canon = g_list_append (canon, g_strdup("1601")); - canon = g_list_append (canon, g_strdup("1602")); - canon = g_list_append (canon, g_strdup("1603")); - canon = g_list_append (canon, g_strdup("1604")); - canon = g_list_append (canon, g_strdup("1606")); - canon = g_list_append (canon, g_strdup("1607")); - canon = g_list_append (canon, g_strdup("1608")); - canon = g_list_append (canon, g_strdup("1609")); - canon = g_list_append (canon, g_strdup("160a")); - canon = g_list_append (canon, g_strdup("160b")); - canon = g_list_append (canon, g_strdup("1706")); - canon = g_list_append (canon, g_strdup("1707")); - canon = g_list_append (canon, g_strdup("1708")); - canon = g_list_append (canon, g_strdup("1709")); - canon = g_list_append (canon, g_strdup("170a")); - canon = g_list_append (canon, g_strdup("170b")); - canon = g_list_append (canon, g_strdup("170c")); - canon = g_list_append (canon, g_strdup("170d")); - canon = g_list_append (canon, g_strdup("170e")); - canon = g_list_append (canon, g_strdup("1712")); - canon = g_list_append (canon, g_strdup("1713")); - canon = g_list_append (canon, g_strdup("1714")); - canon = g_list_append (canon, g_strdup("1715")); - canon = g_list_append (canon, g_strdup("1716")); - canon = g_list_append (canon, g_strdup("1717")); - canon = g_list_append (canon, g_strdup("1718")); - canon = g_list_append (canon, g_strdup("1719")); - canon = g_list_append (canon, g_strdup("171a")); - canon = g_list_append (canon, g_strdup("171b")); - canon = g_list_append (canon, g_strdup("171c")); - canon = g_list_append (canon, g_strdup("1721")); - canon = g_list_append (canon, g_strdup("1722")); - canon = g_list_append (canon, g_strdup("1723")); - canon = g_list_append (canon, g_strdup("1724")); - canon = g_list_append (canon, g_strdup("1725")); - canon = g_list_append (canon, g_strdup("1726")); - canon = g_list_append (canon, g_strdup("1727")); - canon = g_list_append (canon, g_strdup("1728")); - canon = g_list_append (canon, g_strdup("1729")); - canon = g_list_append (canon, g_strdup("172b")); - canon = g_list_append (canon, g_strdup("172c")); - canon = g_list_append (canon, g_strdup("172d")); - canon = g_list_append (canon, g_strdup("172e")); - canon = g_list_append (canon, g_strdup("172f")); - canon = g_list_append (canon, g_strdup("1730")); - canon = g_list_append (canon, g_strdup("1731")); - canon = g_list_append (canon, g_strdup("1732")); - canon = g_list_append (canon, g_strdup("1733")); - canon = g_list_append (canon, g_strdup("1734")); - canon = g_list_append (canon, g_strdup("1735")); - canon = g_list_append (canon, g_strdup("1736")); - canon = g_list_append (canon, g_strdup("173a")); - canon = g_list_append (canon, g_strdup("173b")); - canon = g_list_append (canon, g_strdup("173c")); - canon = g_list_append (canon, g_strdup("173d")); - canon = g_list_append (canon, g_strdup("173e")); - canon = g_list_append (canon, g_strdup("173f")); - canon = g_list_append (canon, g_strdup("1740")); - canon = g_list_append (canon, g_strdup("1741")); - canon = g_list_append (canon, g_strdup("1742")); - canon = g_list_append (canon, g_strdup("1901")); - canon = g_list_append (canon, g_strdup("1904")); - canon = g_list_append (canon, g_strdup("1905")); - canon = g_list_append (canon, g_strdup("1909")); - canon = g_list_append (canon, g_strdup("190a")); - canon = g_list_append (canon, g_strdup("2204")); - canon = g_list_append (canon, g_strdup("2206")); - canon = g_list_append (canon, g_strdup("2207")); - canon = g_list_append (canon, g_strdup("2208")); - canon = g_list_append (canon, g_strdup("220d")); - canon = g_list_append (canon, g_strdup("220e")); - canon = g_list_append (canon, g_strdup("2213")); - canon = g_list_append (canon, g_strdup("221c")); - canon = g_list_append (canon, g_strdup("2220")); - canon = g_list_append (canon, g_strdup("2222")); - canon = g_list_append (canon, g_strdup("262f")); - canon = g_list_append (canon, g_strdup("2630")); - canon = g_list_append (canon, g_strdup("263c")); - canon = g_list_append (canon, g_strdup("263d")); - canon = g_list_append (canon, g_strdup("263e")); - canon = g_list_append (canon, g_strdup("263f")); - canon = g_list_append (canon, g_strdup("264c")); - canon = g_list_append (canon, g_strdup("264d")); - canon = g_list_append (canon, g_strdup("264e")); - canon = g_list_append (canon, g_strdup("264f")); - canon = g_list_append (canon, g_strdup("2659")); - canon = g_list_append (canon, g_strdup("265d")); - canon = g_list_append (canon, g_strdup("265e")); - canon = g_list_append (canon, g_strdup("265f")); - canon = g_list_append (canon, g_strdup("2660")); - canon = g_list_append (canon, g_strdup("2684")); - canon = g_list_append (canon, g_strdup("2686")); - canon = g_list_append (canon, g_strdup("26a3")); - canon = g_list_append (canon, g_strdup("26b0")); - canon = g_list_append (canon, g_strdup("26b4")); - canon = g_list_append (canon, g_strdup("26b5")); - canon = g_list_append (canon, g_strdup("26ec")); - canon = g_list_append (canon, g_strdup("26ed")); - canon = g_list_append (canon, g_strdup("26ee")); - g_hash_table_insert (scanners, - g_strdup("04a9"), - canon); - - GList* nikon = NULL; - nikon = g_list_append (nikon, g_strdup ("4000")); - nikon = g_list_append (nikon, g_strdup ("4001")); - nikon = g_list_append (nikon, g_strdup ("4002")); - g_hash_table_insert (scanners, - g_strdup("04b0"), - nikon); - - GList* epson = NULL; - - // for testing (its a printer not a scanner!) - //epson = g_list_append (epson, g_strdup ("0001")); - - epson = g_list_append (epson, g_strdup("0101")); - epson = g_list_append (epson, g_strdup("0103")); - epson = g_list_append (epson, g_strdup("0104")); - epson = g_list_append (epson, g_strdup("0105")); - epson = g_list_append (epson, g_strdup("0106")); - epson = g_list_append (epson, g_strdup("0107")); - epson = g_list_append (epson, g_strdup("0109")); - epson = g_list_append (epson, g_strdup("010a")); - epson = g_list_append (epson, g_strdup("010b")); - epson = g_list_append (epson, g_strdup("010c")); - epson = g_list_append (epson, g_strdup("010e")); - epson = g_list_append (epson, g_strdup("010f")); - epson = g_list_append (epson, g_strdup("0110")); - epson = g_list_append (epson, g_strdup("0112")); - epson = g_list_append (epson, g_strdup("0114")); - epson = g_list_append (epson, g_strdup("011b")); - epson = g_list_append (epson, g_strdup("011c")); - epson = g_list_append (epson, g_strdup("011d")); - epson = g_list_append (epson, g_strdup("011e")); - epson = g_list_append (epson, g_strdup("011f")); - epson = g_list_append (epson, g_strdup("0120")); - epson = g_list_append (epson, g_strdup("0121")); - epson = g_list_append (epson, g_strdup("0122")); - epson = g_list_append (epson, g_strdup("0126")); - epson = g_list_append (epson, g_strdup("0128")); - epson = g_list_append (epson, g_strdup("0129")); - epson = g_list_append (epson, g_strdup("012a")); - epson = g_list_append (epson, g_strdup("012b")); - epson = g_list_append (epson, g_strdup("012c")); - epson = g_list_append (epson, g_strdup("0135")); - epson = g_list_append (epson, g_strdup("0801")); - epson = g_list_append (epson, g_strdup("0802")); - epson = g_list_append (epson, g_strdup("0805")); - epson = g_list_append (epson, g_strdup("0806")); - epson = g_list_append (epson, g_strdup("0807")); - epson = g_list_append (epson, g_strdup("0808")); - epson = g_list_append (epson, g_strdup("080c")); - epson = g_list_append (epson, g_strdup("080d")); - epson = g_list_append (epson, g_strdup("080e")); - epson = g_list_append (epson, g_strdup("080f")); - epson = g_list_append (epson, g_strdup("0810")); - epson = g_list_append (epson, g_strdup("0811")); - epson = g_list_append (epson, g_strdup("0813")); - epson = g_list_append (epson, g_strdup("0814")); - epson = g_list_append (epson, g_strdup("0815")); - epson = g_list_append (epson, g_strdup("0817")); - epson = g_list_append (epson, g_strdup("0818")); - epson = g_list_append (epson, g_strdup("0819")); - epson = g_list_append (epson, g_strdup("081a")); - epson = g_list_append (epson, g_strdup("081c")); - epson = g_list_append (epson, g_strdup("081d")); - epson = g_list_append (epson, g_strdup("081f")); - epson = g_list_append (epson, g_strdup("0820")); - epson = g_list_append (epson, g_strdup("0827")); - epson = g_list_append (epson, g_strdup("0828")); - epson = g_list_append (epson, g_strdup("0829")); - epson = g_list_append (epson, g_strdup("082a")); - epson = g_list_append (epson, g_strdup("082b")); - epson = g_list_append (epson, g_strdup("082e")); - epson = g_list_append (epson, g_strdup("082f")); - epson = g_list_append (epson, g_strdup("0830")); - epson = g_list_append (epson, g_strdup("0833")); - epson = g_list_append (epson, g_strdup("0834")); - epson = g_list_append (epson, g_strdup("0835")); - epson = g_list_append (epson, g_strdup("0836")); - epson = g_list_append (epson, g_strdup("0837")); - epson = g_list_append (epson, g_strdup("0838")); - epson = g_list_append (epson, g_strdup("0839")); - epson = g_list_append (epson, g_strdup("083a")); - epson = g_list_append (epson, g_strdup("083c")); - epson = g_list_append (epson, g_strdup("0841")); - epson = g_list_append (epson, g_strdup("0843")); - epson = g_list_append (epson, g_strdup("0844")); - epson = g_list_append (epson, g_strdup("0846")); - epson = g_list_append (epson, g_strdup("0847")); - epson = g_list_append (epson, g_strdup("0848")); - epson = g_list_append (epson, g_strdup("0849")); - epson = g_list_append (epson, g_strdup("084a")); - epson = g_list_append (epson, g_strdup("084c")); - epson = g_list_append (epson, g_strdup("084d")); - epson = g_list_append (epson, g_strdup("084f")); - epson = g_list_append (epson, g_strdup("0851")); - epson = g_list_append (epson, g_strdup("0854")); - epson = g_list_append (epson, g_strdup("0856")); - g_hash_table_insert (scanners, - g_strdup("04b8"), - epson); - - GList* fujitsu = NULL; - fujitsu = g_list_append (fujitsu, g_strdup ("1029")); - fujitsu = g_list_append (fujitsu, g_strdup ("1041")); - fujitsu = g_list_append (fujitsu, g_strdup ("1042")); - fujitsu = g_list_append (fujitsu, g_strdup ("1078")); - fujitsu = g_list_append (fujitsu, g_strdup ("1095")); - fujitsu = g_list_append (fujitsu, g_strdup ("1096")); - fujitsu = g_list_append (fujitsu, g_strdup ("1097")); - fujitsu = g_list_append (fujitsu, g_strdup ("10ad")); - fujitsu = g_list_append (fujitsu, g_strdup ("10ae")); - fujitsu = g_list_append (fujitsu, g_strdup ("10af")); - fujitsu = g_list_append (fujitsu, g_strdup ("10c7")); - fujitsu = g_list_append (fujitsu, g_strdup ("10cf")); - fujitsu = g_list_append (fujitsu, g_strdup ("10e0")); - fujitsu = g_list_append (fujitsu, g_strdup ("10e1")); - fujitsu = g_list_append (fujitsu, g_strdup ("10e2")); - fujitsu = g_list_append (fujitsu, g_strdup ("10e6")); - fujitsu = g_list_append (fujitsu, g_strdup ("10e7")); - fujitsu = g_list_append (fujitsu, g_strdup ("10ef")); - fujitsu = g_list_append (fujitsu, g_strdup ("10f2")); - fujitsu = g_list_append (fujitsu, g_strdup ("10fe")); - fujitsu = g_list_append (fujitsu, g_strdup ("1135")); - fujitsu = g_list_append (fujitsu, g_strdup ("114a")); - fujitsu = g_list_append (fujitsu, g_strdup ("114d")); - fujitsu = g_list_append (fujitsu, g_strdup ("114e")); - fujitsu = g_list_append (fujitsu, g_strdup ("114f")); - fujitsu = g_list_append (fujitsu, g_strdup ("1150")); - fujitsu = g_list_append (fujitsu, g_strdup ("1155")); - fujitsu = g_list_append (fujitsu, g_strdup ("1156")); - fujitsu = g_list_append (fujitsu, g_strdup ("116f")); - fujitsu = g_list_append (fujitsu, g_strdup ("1174")); - fujitsu = g_list_append (fujitsu, g_strdup ("1175")); - fujitsu = g_list_append (fujitsu, g_strdup ("1176")); - fujitsu = g_list_append (fujitsu, g_strdup ("1177")); - fujitsu = g_list_append (fujitsu, g_strdup ("1178")); - fujitsu = g_list_append (fujitsu, g_strdup ("117f")); - fujitsu = g_list_append (fujitsu, g_strdup ("119d")); - fujitsu = g_list_append (fujitsu, g_strdup ("119e")); - fujitsu = g_list_append (fujitsu, g_strdup ("119f")); - fujitsu = g_list_append (fujitsu, g_strdup ("11a0")); - fujitsu = g_list_append (fujitsu, g_strdup ("11a2")); - fujitsu = g_list_append (fujitsu, g_strdup ("11ed")); - fujitsu = g_list_append (fujitsu, g_strdup ("11ee")); - fujitsu = g_list_append (fujitsu, g_strdup ("11ef")); - fujitsu = g_list_append (fujitsu, g_strdup ("11f1")); - fujitsu = g_list_append (fujitsu, g_strdup ("11f2")); - fujitsu = g_list_append (fujitsu, g_strdup ("11f3")); - fujitsu = g_list_append (fujitsu, g_strdup ("11f4")); - fujitsu = g_list_append (fujitsu, g_strdup ("11fc")); - g_hash_table_insert (scanners, - g_strdup("04c5"), - fujitsu); - GList* konica = NULL; - konica = g_list_append (konica, g_strdup ("0722")); - g_hash_table_insert (scanners, - g_strdup("04c8"), - konica); - GList* panasonic = NULL; - panasonic = g_list_append (panasonic, g_strdup ("1000")); - panasonic = g_list_append (panasonic, g_strdup ("1001")); - panasonic = g_list_append (panasonic, g_strdup ("1006")); - panasonic = g_list_append (panasonic, g_strdup ("1007")); - panasonic = g_list_append (panasonic, g_strdup ("1009")); - panasonic = g_list_append (panasonic, g_strdup ("100a")); - panasonic = g_list_append (panasonic, g_strdup ("100f")); - panasonic = g_list_append (panasonic, g_strdup ("1010")); - g_hash_table_insert (scanners, - g_strdup("04da"), - panasonic); - - GList* samsung = NULL; - - samsung = g_list_append (samsung, g_strdup ("341b")); - samsung = g_list_append (samsung, g_strdup ("341f")); - samsung = g_list_append (samsung, g_strdup ("3426")); - samsung = g_list_append (samsung, g_strdup ("342a")); - samsung = g_list_append (samsung, g_strdup ("342b")); - samsung = g_list_append (samsung, g_strdup ("342c")); - samsung = g_list_append (samsung, g_strdup ("3433")); - samsung = g_list_append (samsung, g_strdup ("3434")); - samsung = g_list_append (samsung, g_strdup ("343c")); - samsung = g_list_append (samsung, g_strdup ("3434")); - g_hash_table_insert (scanners, - g_strdup("04e8"), - samsung); - - GList* pentax = NULL; - pentax = g_list_append (pentax, g_strdup ("2038")); - g_hash_table_insert (scanners, - g_strdup("04f9"), - pentax); - - GList* apitek = NULL; - apitek = g_list_append (apitek, g_strdup ("0202")); - g_hash_table_insert (scanners, - g_strdup("0553"), - apitek); - - GList* mustek = NULL; - mustek = g_list_append (mustek, g_strdup ("0001")); - mustek = g_list_append (mustek, g_strdup ("0002")); - mustek = g_list_append (mustek, g_strdup ("0006")); - mustek = g_list_append (mustek, g_strdup ("0008")); - mustek = g_list_append (mustek, g_strdup ("0010")); - mustek = g_list_append (mustek, g_strdup ("0210")); - mustek = g_list_append (mustek, g_strdup ("0218")); - mustek = g_list_append (mustek, g_strdup ("0219")); - mustek = g_list_append (mustek, g_strdup ("021a")); - mustek = g_list_append (mustek, g_strdup ("021b")); - mustek = g_list_append (mustek, g_strdup ("021c")); - mustek = g_list_append (mustek, g_strdup ("021d")); - mustek = g_list_append (mustek, g_strdup ("021e")); - mustek = g_list_append (mustek, g_strdup ("021f")); - mustek = g_list_append (mustek, g_strdup ("0409")); - g_hash_table_insert (scanners, - g_strdup("055f"), - mustek); - GList* artec = NULL; - artec = g_list_append (artec, g_strdup ("4002")); - artec = g_list_append (artec, g_strdup ("4003")); - artec = g_list_append (artec, g_strdup ("4004")); - artec = g_list_append (artec, g_strdup ("4005")); - artec = g_list_append (artec, g_strdup ("4006")); - artec = g_list_append (artec, g_strdup ("4007")); - artec = g_list_append (artec, g_strdup ("4009")); - artec = g_list_append (artec, g_strdup ("4010")); - artec = g_list_append (artec, g_strdup ("4011")); - g_hash_table_insert (scanners, - g_strdup("05d8"), - artec); - - GList* microtek = NULL; - microtek = g_list_append (microtek, g_strdup ("0099")); - microtek = g_list_append (microtek, g_strdup ("009a")); - microtek = g_list_append (microtek, g_strdup ("00a3")); - microtek = g_list_append (microtek, g_strdup ("00b6")); - microtek = g_list_append (microtek, g_strdup ("30cf")); - microtek = g_list_append (microtek, g_strdup ("30d4")); - microtek = g_list_append (microtek, g_strdup ("40b3")); - microtek = g_list_append (microtek, g_strdup ("40b8")); - microtek = g_list_append (microtek, g_strdup ("40ca")); - microtek = g_list_append (microtek, g_strdup ("40cb")); - microtek = g_list_append (microtek, g_strdup ("40dd")); - microtek = g_list_append (microtek, g_strdup ("40ff")); - microtek = g_list_append (microtek, g_strdup ("80a3")); - g_hash_table_insert (scanners, - g_strdup("05da"), - microtek); - - GList* avision = NULL; - avision = g_list_append (avision, g_strdup ("0268")); - avision = g_list_append (avision, g_strdup ("026a")); - avision = g_list_append (avision, g_strdup ("0a13")); - avision = g_list_append (avision, g_strdup ("0a15")); - avision = g_list_append (avision, g_strdup ("0a16")); - avision = g_list_append (avision, g_strdup ("0a18")); - avision = g_list_append (avision, g_strdup ("0a19")); - avision = g_list_append (avision, g_strdup ("0a23")); - avision = g_list_append (avision, g_strdup ("0a24")); - avision = g_list_append (avision, g_strdup ("0a25")); - avision = g_list_append (avision, g_strdup ("0a27")); - avision = g_list_append (avision, g_strdup ("0a2a")); - avision = g_list_append (avision, g_strdup ("0a2b")); - avision = g_list_append (avision, g_strdup ("0a2c")); - avision = g_list_append (avision, g_strdup ("0a2d")); - avision = g_list_append (avision, g_strdup ("0a2e")); - avision = g_list_append (avision, g_strdup ("0a2f")); - avision = g_list_append (avision, g_strdup ("0a33")); - avision = g_list_append (avision, g_strdup ("0a3a")); - avision = g_list_append (avision, g_strdup ("0a3c")); - avision = g_list_append (avision, g_strdup ("0a40")); - avision = g_list_append (avision, g_strdup ("0a41")); - avision = g_list_append (avision, g_strdup ("0a45")); - avision = g_list_append (avision, g_strdup ("0a4d")); - avision = g_list_append (avision, g_strdup ("0a4e")); - avision = g_list_append (avision, g_strdup ("0a4f")); - avision = g_list_append (avision, g_strdup ("0a5e")); - avision = g_list_append (avision, g_strdup ("0a61")); - avision = g_list_append (avision, g_strdup ("0a65")); - avision = g_list_append (avision, g_strdup ("0a66")); - avision = g_list_append (avision, g_strdup ("0a68")); - avision = g_list_append (avision, g_strdup ("0a82")); - avision = g_list_append (avision, g_strdup ("0a84")); - avision = g_list_append (avision, g_strdup ("0a93")); - avision = g_list_append (avision, g_strdup ("0a94")); - avision = g_list_append (avision, g_strdup ("0aa1")); - avision = g_list_append (avision, g_strdup ("1a35")); - g_hash_table_insert (scanners, - g_strdup("0638"), - avision); - GList* minolta = NULL; - minolta = g_list_append (minolta, g_strdup ("4004")); - minolta = g_list_append (minolta, g_strdup ("400d")); - minolta = g_list_append (minolta, g_strdup ("400e")); - g_hash_table_insert (scanners, - g_strdup("0686"), - minolta); - - GList* agfa = NULL; - agfa = g_list_append (agfa, g_strdup ("0001")); - agfa = g_list_append (agfa, g_strdup ("0002")); - agfa = g_list_append (agfa, g_strdup ("0100")); - agfa = g_list_append (agfa, g_strdup ("2061")); - agfa = g_list_append (agfa, g_strdup ("208d")); - agfa = g_list_append (agfa, g_strdup ("208f")); - agfa = g_list_append (agfa, g_strdup ("2091")); - agfa = g_list_append (agfa, g_strdup ("2093")); - agfa = g_list_append (agfa, g_strdup ("2095")); - agfa = g_list_append (agfa, g_strdup ("2097")); - agfa = g_list_append (agfa, g_strdup ("20fd")); - agfa = g_list_append (agfa, g_strdup ("20ff")); - g_hash_table_insert (scanners, - g_strdup("06bd"), - minolta); - - GList* umax_2 = NULL; - umax_2 = g_list_append (umax_2, g_strdup ("0020")); - g_hash_table_insert (scanners, - g_strdup("06dc"), - umax_2); - - GList* plustek = NULL; - - plustek = g_list_append (plustek, g_strdup ("0001")); - plustek = g_list_append (plustek, g_strdup ("0010")); - plustek = g_list_append (plustek, g_strdup ("0011")); - plustek = g_list_append (plustek, g_strdup ("0013")); - plustek = g_list_append (plustek, g_strdup ("0015")); - plustek = g_list_append (plustek, g_strdup ("0017")); - plustek = g_list_append (plustek, g_strdup ("0400")); - plustek = g_list_append (plustek, g_strdup ("0401")); - plustek = g_list_append (plustek, g_strdup ("0402")); - plustek = g_list_append (plustek, g_strdup ("0403")); - plustek = g_list_append (plustek, g_strdup ("040b")); - plustek = g_list_append (plustek, g_strdup ("040e")); - plustek = g_list_append (plustek, g_strdup ("0412")); - plustek = g_list_append (plustek, g_strdup ("0413")); - plustek = g_list_append (plustek, g_strdup ("0422")); - plustek = g_list_append (plustek, g_strdup ("0454")); - plustek = g_list_append (plustek, g_strdup ("045f")); - plustek = g_list_append (plustek, g_strdup ("0462")); - plustek = g_list_append (plustek, g_strdup ("0900")); - g_hash_table_insert (scanners, - g_strdup("07b3"), - plustek); - - GList* corex = NULL; - corex = g_list_append (corex, g_strdup ("0002")); - corex = g_list_append (corex, g_strdup ("0005")); - g_hash_table_insert (scanners, - g_strdup("08f0"), - corex); - - GList* xerox = NULL; - xerox = g_list_append (xerox, g_strdup ("3d5d")); - xerox = g_list_append (xerox, g_strdup ("3da4")); - xerox = g_list_append (xerox, g_strdup ("420c")); - xerox = g_list_append (xerox, g_strdup ("4265")); - xerox = g_list_append (xerox, g_strdup ("4293")); - xerox = g_list_append (xerox, g_strdup ("4294")); - g_hash_table_insert (scanners, - g_strdup("0924"), - xerox); - - GList* pentax_2 = NULL; - pentax_2 = g_list_append (pentax_2, g_strdup ("3210")); - g_hash_table_insert (scanners, - g_strdup("0a17"), - pentax_2); - - GList* portable = NULL; - portable = g_list_append (portable, g_strdup ("1000")); - g_hash_table_insert (scanners, - g_strdup("0a53"), - portable); - - GList* syscan = NULL; - syscan = g_list_append (syscan, g_strdup ("4600")); - syscan = g_list_append (syscan, g_strdup ("4802")); - syscan = g_list_append (syscan, g_strdup ("4803")); - syscan = g_list_append (syscan, g_strdup ("480c")); - syscan = g_list_append (syscan, g_strdup ("4810")); - syscan = g_list_append (syscan, g_strdup ("6620")); - g_hash_table_insert (scanners, - g_strdup("0a82"), - syscan); - - GList* canon_2 = NULL; - canon_2 = g_list_append (canon_2, g_strdup ("160c")); - canon_2 = g_list_append (canon_2, g_strdup ("160f")); - canon_2 = g_list_append (canon_2, g_strdup ("1614")); - canon_2 = g_list_append (canon_2, g_strdup ("1617")); - canon_2 = g_list_append (canon_2, g_strdup ("1618")); - canon_2 = g_list_append (canon_2, g_strdup ("161a")); - canon_2 = g_list_append (canon_2, g_strdup ("161b")); - canon_2 = g_list_append (canon_2, g_strdup ("161d")); - canon_2 = g_list_append (canon_2, g_strdup ("1620")); - canon_2 = g_list_append (canon_2, g_strdup ("1622")); - canon_2 = g_list_append (canon_2, g_strdup ("1623")); - canon_2 = g_list_append (canon_2, g_strdup ("1624")); - canon_2 = g_list_append (canon_2, g_strdup ("1626")); - canon_2 = g_list_append (canon_2, g_strdup ("162b")); - canon_2 = g_list_append (canon_2, g_strdup ("1638")); - canon_2 = g_list_append (canon_2, g_strdup ("1639")); - g_hash_table_insert (scanners, - g_strdup("1083"), - canon_2); - - GList* digital = NULL; - digital = g_list_append (digital, g_strdup ("0001")); - g_hash_table_insert (scanners, - g_strdup("1183"), - digital); - - GList* konica_2 = NULL; - konica_2 = g_list_append (konica_2, g_strdup ("2089")); - g_hash_table_insert (scanners, - g_strdup("132b"), - konica_2); - - GList* umax = NULL; - umax = g_list_append (umax, g_strdup ("0010")); - umax = g_list_append (umax, g_strdup ("0030")); - umax = g_list_append (umax, g_strdup ("0050")); - umax = g_list_append (umax, g_strdup ("0060")); - umax = g_list_append (umax, g_strdup ("0070")); - umax = g_list_append (umax, g_strdup ("0130")); - umax = g_list_append (umax, g_strdup ("0160")); - umax = g_list_append (umax, g_strdup ("0230")); - g_hash_table_insert (scanners, - g_strdup("1606"), - umax); - - GList* docketport = NULL; - docketport = g_list_append (docketport, g_strdup ("4810")); - g_hash_table_insert (scanners, - g_strdup("1dcc"), - docketport); - - GList* dell = NULL; - dell = g_list_append (dell, g_strdup ("5105")); - dell = g_list_append (dell, g_strdup ("5124")); - dell = g_list_append (dell, g_strdup ("5250")); - g_hash_table_insert (scanners, - g_strdup("413c"), - dell); -} diff --git a/src/session-dbus.c b/src/session-dbus.c index 232e440..4ece444 100644 --- a/src/session-dbus.c +++ b/src/session-dbus.c @@ -7,16 +7,16 @@ Authors: Ted Gould <ted@canonical.com> Conor Curran <conor.curran@canonical.com> -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, 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 +You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -27,7 +27,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include <gio/gio.h> #include "session-dbus.h" -#include "dbus-shared-names.h" +#include "shared-names.h" static GVariant * get_users_real_name (SessionDbus * service); static void bus_get_cb (GObject * object, GAsyncResult * res, gpointer user_data); @@ -38,7 +38,6 @@ static void bus_method_call (GDBusConnection * connection, const gchar * sender, typedef struct _SessionDbusPrivate SessionDbusPrivate; struct _SessionDbusPrivate { gchar * name; - gboolean user_menu_is_visible; GDBusConnection * bus; GCancellable * bus_cancel; guint dbus_registration; @@ -104,7 +103,6 @@ session_dbus_init (SessionDbus *self) priv->bus = NULL; priv->bus_cancel = NULL; priv->dbus_registration = 0; - priv->user_menu_is_visible = FALSE; priv->bus_cancel = g_cancellable_new(); g_bus_get(G_BUS_TYPE_SESSION, @@ -164,16 +162,12 @@ bus_method_call (GDBusConnection * connection, const gchar * sender, GDBusMethodInvocation * invocation, gpointer user_data) { SessionDbus * service = SESSION_DBUS (user_data); - SessionDbusPrivate * priv = SESSION_DBUS_GET_PRIVATE (service); GVariant * retval = NULL; if (g_strcmp0(method, "GetUserRealName") == 0) { retval = get_users_real_name (service); } - else if (g_strcmp0 (method, "GetUserMenuVisibility") == 0){ - retval = g_variant_new ("(b)", priv->user_menu_is_visible); - } else { g_warning("Calling method '%s' on the indicator service and it's unknown", method); } @@ -212,10 +206,7 @@ session_dbus_finalize (GObject *object) { SessionDbusPrivate * priv = SESSION_DBUS_GET_PRIVATE(object); - if (priv->name != NULL) { - g_free(priv->name); - priv->name = NULL; - } + g_clear_pointer (&priv->name, g_free); G_OBJECT_CLASS (session_dbus_parent_class)->finalize (object); return; @@ -225,7 +216,7 @@ static GVariant * get_users_real_name (SessionDbus * service) { SessionDbusPrivate * priv = SESSION_DBUS_GET_PRIVATE(service); - return g_variant_new ("(s)", priv->name); + return g_variant_new ("(s)", priv->name ? priv->name : ""); } SessionDbus * @@ -244,11 +235,8 @@ session_dbus_set_users_real_name (SessionDbus * session, const gchar * name) { SessionDbusPrivate * priv = SESSION_DBUS_GET_PRIVATE(session); GError * error = NULL; - if (priv->name != NULL) { - g_free(priv->name); - priv->name = NULL; - } - + + g_free (priv->name); priv->name = g_strdup(name); if (priv->bus != NULL) { @@ -269,36 +257,11 @@ session_dbus_set_users_real_name (SessionDbus * session, const gchar * name) return; } -void -session_dbus_set_user_menu_visibility (SessionDbus* session, - gboolean visible) -{ - SessionDbusPrivate * priv = SESSION_DBUS_GET_PRIVATE(session); - GError * error = NULL; - - priv->user_menu_is_visible = visible; - - if (priv->bus != NULL) { - g_dbus_connection_emit_signal (priv->bus, - NULL, - INDICATOR_SESSION_SERVICE_DBUS_OBJECT, - INDICATOR_SESSION_SERVICE_DBUS_IFACE, - "UserMenuIsVisible", - g_variant_new ("(b)", priv->user_menu_is_visible), - &error); - - if (error != NULL) { - g_warning("Unable to send UserMenuIsVisible signal: %s", error->message); - g_error_free(error); - } - } -} - void session_dbus_restart_required (SessionDbus* session) { SessionDbusPrivate * priv = SESSION_DBUS_GET_PRIVATE(session); GError * error = NULL; - + if (priv->bus != NULL) { g_debug("About to send RebootRequired signal"); @@ -314,6 +277,6 @@ void session_dbus_restart_required (SessionDbus* session) g_warning("Unable to send reboot-required signal: %s", error->message); g_error_free(error); } - } - + } + } diff --git a/src/session-dbus.h b/src/session-dbus.h index 4dc340a..7520f06 100644 --- a/src/session-dbus.h +++ b/src/session-dbus.h @@ -50,7 +50,6 @@ GType session_dbus_get_type (void); SessionDbus * session_dbus_new (void); void session_dbus_set_name (SessionDbus * session, const gchar * name); void session_dbus_set_users_real_name (SessionDbus * session, const gchar * name); -void session_dbus_set_user_menu_visibility (SessionDbus* session, gboolean visible); void session_dbus_restart_required (SessionDbus* session); G_END_DECLS diff --git a/src/session-menu-mgr.c b/src/session-menu-mgr.c new file mode 100644 index 0000000..96fc2a0 --- /dev/null +++ b/src/session-menu-mgr.c @@ -0,0 +1,1172 @@ +/* +Copyright 2011 Canonical Ltd. + +Authors: + Charles Kerr <charles.kerr@canonical.com> + Conor Curran <conor.curran@canonical.com> + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published +by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>. +*/ + +#include "config.h" + +#include <sys/types.h> +#include <pwd.h> /* geteuid(), getpwuid() */ + +#include <glib.h> +#include <glib/gi18n.h> + +#include <libdbusmenu-glib/client.h> +#include <libdbusmenu-gtk/menuitem.h> + +#include "dbus-upower.h" +#include "session-menu-mgr.h" +#include "shared-names.h" +#include "users-service-dbus.h" + +#define DEBUG_SHOW_ALL FALSE + +#define UPOWER_ADDRESS "org.freedesktop.UPower" +#define UPOWER_PATH "/org/freedesktop/UPower" + +#define CMD_HELP "yelp" +#define CMD_INFO "gnome-control-center info" +#define CMD_SYSTEM_SETTINGS "gnome-control-center" +#ifdef HAVE_GTKLOGOUTHELPER + #define HAVE_RESTART_CMD TRUE + #define CMD_RESTART LIBEXECDIR"/gtk-logout-helper --restart" + #define CMD_LOGOUT LIBEXECDIR"/gtk-logout-helper --logout" + #define CMD_SHUTDOWN LIBEXECDIR"/gtk-logout-helper --shutdown" +#else + #define HAVE_RESTART_CMD FALSE /* hmm, no gnome-session-quit --restart? */ + #define CMD_RESTART "" + #define CMD_LOGOUT "gnome-session-quit --logout" + #define CMD_SHUTDOWN "gnome-session-quit --power-off" +#endif + +/** + * Which switch menuitem to show -- based on lockdown settings, + * greeter mode, number of users in the system, and so on. + * See get_switcher_mode() + */ +typedef enum +{ + SWITCHER_MODE_SCREENSAVER, + SWITCHER_MODE_LOCK, + SWITCHER_MODE_SWITCH, + SWITCHER_MODE_SWITCH_OR_LOCK +} +SwitcherMode; + +/** + * Creates and manages the menumodel and associated actions for the + * session menu described at <https://wiki.ubuntu.com/SystemMenu>. + * + * This is a pretty straightforward class: it creates the menumodel + * and listens for events that can affect the model's properties. + * + * Simple event sources, such as GSettings and a UPower DBus proxy, + * are handled here. More involved event sources are delegated to the + * UsersServiceDBus facade class. + */ +struct _SessionMenuMgr +{ + GObject parent_instance; + + DbusmenuMenuitem * top_mi; + DbusmenuMenuitem * screensaver_mi; + DbusmenuMenuitem * lock_mi; + DbusmenuMenuitem * lock_switch_mi; + DbusmenuMenuitem * guest_mi; + DbusmenuMenuitem * logout_mi; + DbusmenuMenuitem * suspend_mi; + DbusmenuMenuitem * hibernate_mi; + DbusmenuMenuitem * restart_mi; + DbusmenuMenuitem * shutdown_mi; + + GSList * user_menuitems; + gint user_menuitem_index; + + GSettings * lockdown_settings; + GSettings * indicator_settings; + GSettings * keybinding_settings; + + /* cached settings taken from the upower proxy */ + gboolean can_hibernate; + gboolean can_suspend; + gboolean allow_hibernate; + gboolean allow_suspend; + + gboolean greeter_mode; + + GCancellable * cancellable; + DBusUPower * upower_proxy; + SessionDbus * session_dbus; + UsersServiceDbus * users_dbus_facade; +}; + +static SwitcherMode get_switcher_mode (SessionMenuMgr *); + +static void init_upower_proxy (SessionMenuMgr *); + +static void update_screensaver_shortcut (SessionMenuMgr *); +static void update_user_menuitems (SessionMenuMgr *); +static void update_session_menuitems (SessionMenuMgr *); +static void update_confirmation_labels (SessionMenuMgr *); + +static void action_func_lock (SessionMenuMgr *); +static void action_func_suspend (SessionMenuMgr *); +static void action_func_hibernate (SessionMenuMgr *); +static void action_func_switch_to_lockscreen (SessionMenuMgr *); +static void action_func_switch_to_greeter (SessionMenuMgr *); +static void action_func_switch_to_guest (SessionMenuMgr *); +static void action_func_switch_to_user (AccountsUser *); +static void action_func_spawn_async (const char * cmd); + +static gboolean is_this_guest_session (void); +static gboolean is_this_live_session (void); + +static void on_guest_logged_in_changed (UsersServiceDbus *, + SessionMenuMgr *); + +static void on_user_logged_in_changed (UsersServiceDbus *, + AccountsUser *, + SessionMenuMgr *); + +/** +*** GObject init / dispose +**/ + +G_DEFINE_TYPE (SessionMenuMgr, session_menu_mgr, G_TYPE_OBJECT); + +static void +session_menu_mgr_init (SessionMenuMgr *mgr) +{ + mgr->top_mi = dbusmenu_menuitem_new (); + + /* Lockdown settings */ + GSettings * s = g_settings_new ("org.gnome.desktop.lockdown"); + g_signal_connect_swapped (s, "changed::disable-log-out", + G_CALLBACK(update_session_menuitems), mgr); + g_signal_connect_swapped (s, "changed::disable-lock-screen", + G_CALLBACK(update_user_menuitems), mgr); + g_signal_connect_swapped (s, "changed::disable-user-switching", + G_CALLBACK(update_user_menuitems), mgr); + mgr->lockdown_settings = s; + + /* Indicator settings */ + s = g_settings_new ("com.canonical.indicator.session"); + g_signal_connect_swapped (s, "changed::suppress-logout-restart-shutdown", + G_CALLBACK(update_confirmation_labels), mgr); + g_signal_connect_swapped (s, "changed::suppress-logout-menuitem", + G_CALLBACK(update_session_menuitems), mgr); + g_signal_connect_swapped (s, "changed::suppress-restart-menuitem", + G_CALLBACK(update_session_menuitems), mgr); + g_signal_connect_swapped (s, "changed::suppress-shutdown-menuitem", + G_CALLBACK(update_session_menuitems), mgr); + mgr->indicator_settings = s; + + /* Keybinding settings */ + s = g_settings_new ("org.gnome.settings-daemon.plugins.media-keys"); + g_signal_connect_swapped (s, "changed::screensaver", + G_CALLBACK(update_screensaver_shortcut), mgr); + mgr->keybinding_settings = s; + + /* listen for user events */ + mgr->users_dbus_facade = g_object_new (USERS_SERVICE_DBUS_TYPE, NULL); + g_signal_connect_swapped (mgr->users_dbus_facade, "user-list-changed", + G_CALLBACK (update_user_menuitems), mgr); + g_signal_connect (mgr->users_dbus_facade, "user-logged-in-changed", + G_CALLBACK(on_user_logged_in_changed), mgr); + g_signal_connect (mgr->users_dbus_facade, "guest-logged-in-changed", + G_CALLBACK(on_guest_logged_in_changed), mgr); + + init_upower_proxy (mgr); +} + +static void +session_menu_mgr_dispose (GObject *object) +{ + SessionMenuMgr * mgr = SESSION_MENU_MGR (object); + + if (mgr->cancellable != NULL) + { + g_cancellable_cancel (mgr->cancellable); + g_clear_object (&mgr->cancellable); + } + + g_clear_object (&mgr->indicator_settings); + g_clear_object (&mgr->lockdown_settings); + g_clear_object (&mgr->keybinding_settings); + g_clear_object (&mgr->upower_proxy); + g_clear_object (&mgr->users_dbus_facade); + g_clear_object (&mgr->top_mi); + g_clear_object (&mgr->session_dbus); + + g_slist_free (mgr->user_menuitems); + mgr->user_menuitems = NULL; + + G_OBJECT_CLASS (session_menu_mgr_parent_class)->dispose (object); +} + +static void +session_menu_mgr_class_init (SessionMenuMgrClass * klass) +{ + GObjectClass* object_class = G_OBJECT_CLASS (klass); + object_class->dispose = session_menu_mgr_dispose; +} + +/*** +**** UPower Proxy: +**** +**** 1. While bootstrapping, we invoke the AllowSuspend and AllowHibernate +**** methods to find out whether or not those features are allowed. +**** 2. While bootstrapping, we get the CanSuspend and CanHibernate properties +**** and also listen for property changes. +**** 3. These four values are used to set suspend and hibernate's visibility. +**** +***/ + +static void +on_upower_properties_changed (SessionMenuMgr * mgr) +{ + gboolean b; + gboolean need_refresh = FALSE; + + /* suspend */ + b = dbus_upower_get_can_suspend (mgr->upower_proxy); + if (mgr->can_suspend != b) + { + mgr->can_suspend = b; + need_refresh = TRUE; + } + + /* hibernate */ + b = dbus_upower_get_can_hibernate (mgr->upower_proxy); + if (mgr->can_hibernate != b) + { + mgr->can_hibernate = b; + need_refresh = TRUE; + } + + if (need_refresh) + { + update_session_menuitems (mgr); + } +} + +static void +init_upower_proxy (SessionMenuMgr * mgr) +{ + /* default values */ + mgr->can_suspend = TRUE; + mgr->can_hibernate = TRUE; + mgr->allow_suspend = TRUE; + mgr->allow_hibernate = TRUE; + + mgr->cancellable = g_cancellable_new (); + + GError * error = NULL; + mgr->upower_proxy = dbus_upower_proxy_new_for_bus_sync ( + G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + UPOWER_ADDRESS, + UPOWER_PATH, + NULL, + &error); + if (error != NULL) + { + g_warning ("Error creating upower proxy: %s", error->message); + g_clear_error (&error); + } + else + { + dbus_upower_call_suspend_allowed_sync (mgr->upower_proxy, + &mgr->allow_suspend, + NULL, + &error); + if (error != NULL) + { + g_warning ("%s: %s", G_STRFUNC, error->message); + g_clear_error (&error); + } + + dbus_upower_call_hibernate_allowed_sync (mgr->upower_proxy, + &mgr->allow_hibernate, + NULL, + &error); + if (error != NULL) + { + g_warning ("%s: %s", G_STRFUNC, error->message); + g_clear_error (&error); + } + + on_upower_properties_changed (mgr); + g_signal_connect_swapped (mgr->upower_proxy, "changed", + G_CALLBACK(on_upower_properties_changed), mgr); + } +} + +/*** +**** Menuitem Helpers +***/ + +static inline void +mi_set_label (DbusmenuMenuitem * mi, const char * str) +{ + dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_LABEL, str); +} + +static inline void +mi_set_type (DbusmenuMenuitem * mi, const char * str) +{ + dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_TYPE, str); +} + +static inline void +mi_set_visible (DbusmenuMenuitem * mi, gboolean b) +{ + dbusmenu_menuitem_property_set_bool (mi, DBUSMENU_MENUITEM_PROP_VISIBLE, + b || DEBUG_SHOW_ALL); +} + +static inline void +mi_set_logged_in (DbusmenuMenuitem * mi, gboolean b) +{ + dbusmenu_menuitem_property_set_bool (mi, USER_ITEM_PROP_LOGGED_IN, b); +} + +static DbusmenuMenuitem* +mi_new_separator (void) +{ + DbusmenuMenuitem * mi = dbusmenu_menuitem_new (); + mi_set_type (mi, DBUSMENU_CLIENT_TYPES_SEPARATOR); + return mi; +} + +static DbusmenuMenuitem* +mi_new (const char * label) +{ + DbusmenuMenuitem * mi = dbusmenu_menuitem_new (); + mi_set_label (mi, label); + return mi; +} + +/*** +**** Admin Menuitems +**** <https://wiki.ubuntu.com/SystemMenu#Admin_items> +***/ + +static void +build_admin_menuitems (SessionMenuMgr * mgr) +{ + if (!mgr->greeter_mode) + { + DbusmenuMenuitem * mi; + const gboolean show_settings = !mgr->greeter_mode; + + mi = mi_new (_("About This Computer")); + dbusmenu_menuitem_child_append (mgr->top_mi, mi); + g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK(action_func_spawn_async), CMD_INFO); + + mi = mi_new (_("Ubuntu Help")); + dbusmenu_menuitem_child_append (mgr->top_mi, mi); + g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK(action_func_spawn_async), CMD_HELP); + + mi = mi_new_separator (); + mi_set_visible (mi, show_settings); + dbusmenu_menuitem_child_append (mgr->top_mi, mi); + + mi = mi_new (_("System Settings\342\200\246")); + mi_set_visible (mi, show_settings); + dbusmenu_menuitem_child_append (mgr->top_mi, mi); + g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK(action_func_spawn_async), + CMD_SYSTEM_SETTINGS); + + mi = mi_new_separator (); + dbusmenu_menuitem_child_append (mgr->top_mi, mi); + } +} + +/*** +**** Session Menuitems +**** <https://wiki.ubuntu.com/SystemMenu#Session_items> +***/ + +static void +update_session_menuitems (SessionMenuMgr * mgr) +{ + gboolean v; + GSettings * s = mgr->indicator_settings; + + v = !mgr->greeter_mode + && !is_this_live_session() + && !g_settings_get_boolean (mgr->lockdown_settings, "disable-log-out") + && !g_settings_get_boolean (s, "suppress-logout-menuitem"); + mi_set_visible (mgr->logout_mi, v); + + v = mgr->can_suspend + && mgr->allow_suspend; + mi_set_visible (mgr->suspend_mi, v); + + v = mgr->can_hibernate + && mgr->allow_hibernate; + mi_set_visible (mgr->hibernate_mi, v); + + v = HAVE_RESTART_CMD + && !g_settings_get_boolean (s, "suppress-restart-menuitem"); + mi_set_visible (mgr->restart_mi, v); + + v = !g_settings_get_boolean (s, "suppress-shutdown-menuitem"); + mi_set_visible (mgr->shutdown_mi, v); +} + +/* Update the ellipses when the confirmation setting changes. + * + * <http://developer.gnome.org/hig-book/3.0/menus-design.html.en>: + * "Label the menu item with a trailing ellipsis ("...") only if the + * command requires further input from the user before it can be performed." + */ +static void +update_confirmation_labels (SessionMenuMgr * mgr) +{ + const gboolean confirm_needed = !g_settings_get_boolean ( + mgr->indicator_settings, + "suppress-logout-restart-shutdown"); + + mi_set_label (mgr->logout_mi, confirm_needed ? _("Log Out\342\200\246") + : _("Log Out")); + + mi_set_label (mgr->shutdown_mi, confirm_needed ? _("Switch Off\342\200\246") + : _("Switch Off")); + + dbusmenu_menuitem_property_set (mgr->restart_mi, RESTART_ITEM_LABEL, + confirm_needed ? _("Restart\342\200\246") + : _("Restart")); +} + +static void +build_session_menuitems (SessionMenuMgr* mgr) +{ + DbusmenuMenuitem * mi; + + mi = mgr->logout_mi = mi_new (_("Log Out\342\200\246")); + dbusmenu_menuitem_child_append (mgr->top_mi, mi); + g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK(action_func_spawn_async), CMD_LOGOUT); + + mi = mgr->suspend_mi = mi_new ("Suspend"); + dbusmenu_menuitem_child_append (mgr->top_mi, mi); + g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK(action_func_suspend), mgr); + + mi = mgr->hibernate_mi = mi_new (_("Hibernate")); + dbusmenu_menuitem_child_append (mgr->top_mi, mi); + g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK(action_func_hibernate), mgr); + + mi = mgr->restart_mi = dbusmenu_menuitem_new (); + mi_set_type (mi, RESTART_ITEM_TYPE); + dbusmenu_menuitem_property_set (mi, RESTART_ITEM_LABEL, _("Restart\342\200\246")); + dbusmenu_menuitem_child_append (mgr->top_mi, mi); + g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK(action_func_spawn_async), CMD_RESTART); + + mi = mgr->shutdown_mi = mi_new (_("Switch Off\342\200\246")); + dbusmenu_menuitem_child_append (mgr->top_mi, mi); + g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK(action_func_spawn_async), CMD_SHUTDOWN); + + update_confirmation_labels (mgr); + update_session_menuitems (mgr); +} + +/**** +***** User Menuitems +***** https://wiki.ubuntu.com/SystemMenu#Account-switching_items +****/ + +/* Local extensions to AccountsUser */ + +static GQuark +get_menuitem_quark (void) +{ + static GQuark q = 0; + + if (G_UNLIKELY(!q)) + { + q = g_quark_from_static_string ("menuitem"); + } + + return q; +} + +static DbusmenuMenuitem* +user_get_menuitem (AccountsUser * user) +{ + return g_object_get_qdata (G_OBJECT(user), get_menuitem_quark()); +} + +static void +user_clear_menuitem (AccountsUser * user) +{ + g_object_steal_qdata (G_OBJECT(user), get_menuitem_quark()); +} + +static void +user_set_menuitem (AccountsUser * user, DbusmenuMenuitem * mi) +{ + g_object_set_qdata (G_OBJECT(user), get_menuitem_quark(), mi); + + g_object_weak_ref (G_OBJECT(mi), (GWeakNotify)user_clear_menuitem, user); +} + +/***/ + +static GQuark +get_mgr_quark (void) +{ + static GQuark q = 0; + + if (G_UNLIKELY(!q)) + { + q = g_quark_from_static_string ("session-menu-mgr"); + } + + return q; +} + +static SessionMenuMgr* +user_get_mgr (AccountsUser * user) +{ + return g_object_get_qdata (G_OBJECT(user), get_mgr_quark()); +} + +static void +user_set_mgr (AccountsUser * user, SessionMenuMgr * mgr) +{ + g_object_set_qdata (G_OBJECT(user), get_mgr_quark(), mgr); +} + +/***/ + +static GQuark +get_collision_quark (void) +{ + static GQuark q = 0; + + if (G_UNLIKELY(!q)) + { + q = g_quark_from_static_string ("name-collision"); + } + + return q; +} + +static gboolean +user_has_name_collision (AccountsUser * u) +{ + return g_object_get_qdata (G_OBJECT(u), get_collision_quark()) != NULL; +} + +static void +user_set_name_collision (AccountsUser * u, gboolean b) +{ + g_object_set_qdata (G_OBJECT(u), get_collision_quark(), GINT_TO_POINTER(b)); +} + +/*** +**** +***/ + +static void +on_guest_logged_in_changed (UsersServiceDbus * usd, + SessionMenuMgr * mgr) +{ + if (mgr->guest_mi != NULL) + { + mi_set_logged_in (mgr->guest_mi, + users_service_dbus_is_guest_logged_in (usd)); + } +} + +/* When a user's login state changes, + update the corresponding menuitem's LOGGED_IN property */ +static void +on_user_logged_in_changed (UsersServiceDbus * usd, + AccountsUser * user, + SessionMenuMgr * mgr) +{ + DbusmenuMenuitem * mi = user_get_menuitem (user); + + if (mi != NULL) + { + mi_set_logged_in (mi, users_service_dbus_is_user_logged_in (usd, user)); + } +} + +static void +update_screensaver_shortcut (SessionMenuMgr * mgr) +{ + gchar * s = g_settings_get_string (mgr->keybinding_settings, "screensaver"); + g_debug ("%s Screensaver shortcut changed to: '%s'", G_STRLOC, s); + + if (mgr->lock_mi != NULL) + { + dbusmenu_menuitem_property_set_shortcut_string (mgr->lock_mi, s); + } + + if (mgr->lock_switch_mi != NULL) + { + dbusmenu_menuitem_property_set_shortcut_string (mgr->lock_switch_mi, s); + } + + if (mgr->screensaver_mi != NULL) + { + dbusmenu_menuitem_property_set_shortcut_string (mgr->screensaver_mi, s); + } + + g_free (s); +} + +static void +update_user_menuitem_icon (DbusmenuMenuitem * mi, AccountsUser * user) +{ + const gchar * str = accounts_user_get_icon_file (user); + + if (!str || !*str) + { + str = USER_ITEM_ICON_DEFAULT; + } + + dbusmenu_menuitem_property_set (mi, USER_ITEM_PROP_ICON, str); +} + +static void +update_user_menuitem_name (DbusmenuMenuitem * mi, AccountsUser * user) +{ + GString * gstr = g_string_new (accounts_user_get_real_name (user)); + + if (user_has_name_collision (user)) + { + g_string_append_printf (gstr, " (%s)", accounts_user_get_user_name(user)); + } + + dbusmenu_menuitem_property_set (mi, USER_ITEM_PROP_NAME, gstr->str); + g_string_free (gstr, TRUE); +} + +static void +on_user_property_changed (AccountsUser * user, + GParamSpec * pspec, + DbusmenuMenuitem * mi) +{ + static const char * interned_icon_file = NULL; + static const char * interned_real_name = NULL; + static const char * interned_user_name = NULL; + + if (G_UNLIKELY (interned_icon_file == NULL)) + { + interned_icon_file = g_intern_static_string ("icon-file"); + interned_user_name = g_intern_static_string ("user-name"); + interned_real_name = g_intern_static_string ("real-name"); + } + + if (pspec->name == interned_icon_file) + { + update_user_menuitem_icon (mi, user); + } + else if ((pspec->name == interned_real_name) + || (pspec->name == interned_user_name)) + { + /* name changing can affect other menuitems too by invalidating + the sort order or name collision flags... so let's rebuild */ + update_user_menuitems (user_get_mgr (user)); + } +} + +typedef struct +{ + gpointer instance; + gulong handler_id; +} +SignalHandlerData; + +/* when a user menuitem is destroyed, + it should stop listening for its UserAccount's property changes */ +static void +on_user_menuitem_destroyed (SignalHandlerData * data) +{ + g_signal_handler_disconnect (data->instance, data->handler_id); + g_free (data); +} + +static DbusmenuMenuitem* +user_menuitem_new (AccountsUser * user, SessionMenuMgr * mgr) +{ + DbusmenuMenuitem * mi = dbusmenu_menuitem_new (); + mi_set_type (mi, USER_ITEM_TYPE); + + /* set the name & icon and listen for property changes */ + update_user_menuitem_name (mi, user); + update_user_menuitem_icon (mi, user); + SignalHandlerData * hd = g_new0 (SignalHandlerData, 1); + hd->instance = user; + hd->handler_id = g_signal_connect (user, "notify", + G_CALLBACK(on_user_property_changed), mi); + g_object_weak_ref (G_OBJECT(mi), (GWeakNotify)on_user_menuitem_destroyed, hd); + + /* set the logged-in property */ + mi_set_logged_in (mi, + users_service_dbus_is_user_logged_in (mgr->users_dbus_facade, user)); + + /* set the is-current-user property */ + const gboolean is_current_user = + !g_strcmp0 (g_get_user_name(), accounts_user_get_user_name(user)); + dbusmenu_menuitem_property_set_bool (mi, + USER_ITEM_PROP_IS_CURRENT_USER, + is_current_user); + + /* set the switch-to-user action */ + g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK (action_func_switch_to_user), user); + + /* give this AccountsUser a hook back to this menuitem */ + user_set_menuitem (user, mi); + user_set_mgr (user, mgr); + + return mi; +} + +/* for sorting AccountsUsers from most to least frequently used */ +static gint +compare_users_by_login_frequency (gconstpointer a, gconstpointer b) +{ + const guint64 a_freq = accounts_user_get_login_frequency (ACCOUNTS_USER(a)); + const guint64 b_freq = accounts_user_get_login_frequency (ACCOUNTS_USER(b)); + if (a_freq > b_freq) return -1; + if (a_freq < b_freq) return 1; + return 0; +} + +/* for sorting AccountsUsers alphabetically */ +static gint +compare_users_by_username (gconstpointer ga, gconstpointer gb) +{ + AccountsUser * a = ACCOUNTS_USER(ga); + AccountsUser * b = ACCOUNTS_USER(gb); + + const int ret = g_strcmp0 (accounts_user_get_real_name (a), + accounts_user_get_real_name (b)); + + if (!ret) /* names are the same, so both have a name collision */ + { + user_set_name_collision (a, TRUE); + user_set_name_collision (b, TRUE); + } + + return ret; +} + +static gboolean +is_user_switching_allowed (SessionMenuMgr * mgr) +{ + /* maybe it's locked down */ + if (g_settings_get_boolean (mgr->lockdown_settings, "disable-user-switching")) + { + return FALSE; + } + + /* maybe the seat doesn't support activation */ + if (!users_service_dbus_can_activate_session (mgr->users_dbus_facade)) + { + return FALSE; + } + + return TRUE; +} + +static void +build_user_menuitems (SessionMenuMgr * mgr) +{ + g_return_if_fail (!mgr->greeter_mode); + + DbusmenuMenuitem * mi; + GSList * items = NULL; + gint pos = mgr->user_menuitem_index; + const char * current_real_name = NULL; + + /** + *** Start Screen Saver + *** Switch Account... + *** Lock + *** Lock / Switch Account... + **/ + + const SwitcherMode mode = get_switcher_mode (mgr); + + mi = mgr->screensaver_mi = mi_new (_("Start Screen Saver")); + mi_set_visible (mi, mode == SWITCHER_MODE_SCREENSAVER); + dbusmenu_menuitem_child_add_position (mgr->top_mi, mi, pos++); + items = g_slist_prepend (items, mi); + g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK (action_func_lock), mgr); + + mi = mi_new (_("Switch User Account\342\200\246")); + mi_set_visible (mi, mode == SWITCHER_MODE_SWITCH); + dbusmenu_menuitem_child_add_position (mgr->top_mi, mi, pos++); + items = g_slist_prepend (items, mi); + g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK (action_func_switch_to_greeter), mgr); + + mi = mgr->lock_mi = mi_new (_("Lock")); + mi_set_visible (mi, mode == SWITCHER_MODE_LOCK); + dbusmenu_menuitem_child_add_position (mgr->top_mi, mi, pos++); + items = g_slist_prepend (items, mi); + g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK (action_func_switch_to_lockscreen), mgr); + + mi = mgr->lock_switch_mi = mi_new (_("Lock/Switch Account\342\200\246")); + mi_set_visible (mi, mode == SWITCHER_MODE_SWITCH_OR_LOCK); + dbusmenu_menuitem_child_add_position (mgr->top_mi, mi, pos++); + items = g_slist_prepend (items, mi); + g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK (action_func_switch_to_lockscreen), mgr); + + const gboolean is_guest = is_this_guest_session (); + const gboolean guest_allowed = + users_service_dbus_guest_session_enabled (mgr->users_dbus_facade); + mi = mgr->guest_mi = dbusmenu_menuitem_new (); + mi_set_type (mi, USER_ITEM_TYPE); + mi_set_visible (mi, !is_guest && guest_allowed); + dbusmenu_menuitem_property_set (mi, USER_ITEM_PROP_NAME, _("Guest Session")); + dbusmenu_menuitem_child_add_position (mgr->top_mi, mi, pos++); + on_guest_logged_in_changed (mgr->users_dbus_facade, mgr); + items = g_slist_prepend (items, mi); + g_signal_connect_swapped (mi, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK (action_func_switch_to_guest), mgr); + + if (guest_allowed && is_guest) + { + current_real_name = _("Guest"); + } + + /*** + **** Users + ***/ + + /* if we can switch to another user account, show them here */ + const char * const username = g_get_user_name(); + GList * users = users_service_dbus_get_user_list (mgr->users_dbus_facade); + + /* since we're building (or rebuilding) from scratch, + clear the name collision flags */ + GList * u; + for (u=users; u!=NULL; u=u->next) + { + AccountsUser * user = ACCOUNTS_USER(u->data); + + user_set_name_collision (user, FALSE); + + if (!g_strcmp0 (username, accounts_user_get_user_name(user))) + { + current_real_name = accounts_user_get_real_name (user); + } + } + + if (is_user_switching_allowed (mgr)) + { + /* pick the most frequently used accounts */ + const int MAX_USERS = 12; /* this limit comes from the spec */ + if (g_list_length(users) > MAX_USERS) + { + users = g_list_sort (users, compare_users_by_login_frequency); + GList * last = g_list_nth (users, MAX_USERS-1); + GList * remainder = last->next; + last->next = NULL; + remainder->prev = NULL; + g_list_free (remainder); + } + + /* Sort the users by name for display */ + users = g_list_sort (users, compare_users_by_username); + + /* Create menuitems for them */ + int i; + for (i=0, u=users; i<MAX_USERS && u!=NULL; u=u->next, i++) + { + AccountsUser * user = u->data; + DbusmenuMenuitem * mi = user_menuitem_new (user, mgr); + dbusmenu_menuitem_child_add_position (mgr->top_mi, mi, pos++); + items = g_slist_prepend (items, mi); + } + } + + g_list_free (users); + + /* separator */ + mi = mi_new_separator (); + dbusmenu_menuitem_child_add_position (mgr->top_mi, mi, pos++); + items = g_slist_prepend (items, mi); + + if (current_real_name != NULL) + { + session_dbus_set_users_real_name (mgr->session_dbus, + current_real_name); + } + + update_screensaver_shortcut (mgr); + mgr->user_menuitems = items; +} + +static void +update_user_menuitems (SessionMenuMgr * mgr) +{ + /* remove any previous user menuitems */ + GSList * l; + for (l=mgr->user_menuitems; l!=NULL; l=l->next) + { + dbusmenu_menuitem_child_delete (mgr->top_mi, l->data); + } + g_slist_free (mgr->user_menuitems); + mgr->user_menuitems = NULL; + + /* add fresh user menuitems */ + if (!mgr->greeter_mode) + { + build_user_menuitems (mgr); + } +} + +/*** +**** Actions! +***/ + +static void +action_func_spawn_async (const char * cmd) +{ + GError * error = NULL; + + g_debug ("%s calling \"%s\"", G_STRFUNC, cmd); + g_spawn_command_line_async (cmd, &error); + + if (error != NULL) + { + g_warning ("Unable to execute \"%s\": %s", cmd, error->message); + g_clear_error (&error); + } +} + +/* Calling "Lock" locks the screen & goes to black. + Calling "SimulateUserActivity" afterwards shows the Lock Screen. */ +static void +lock_helper (SessionMenuMgr * mgr, gboolean show_lock_screen) +{ + if (!g_settings_get_boolean (mgr->lockdown_settings, "disable-lock-screen")) + { + GError * error = NULL; + GDBusProxy * proxy = g_dbus_proxy_new_for_bus_sync ( + G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + "org.gnome.ScreenSaver", + "/org/gnome/ScreenSaver", + "org.gnome.ScreenSaver", + NULL, + &error); + + if (error == NULL) + { + g_dbus_proxy_call_sync (proxy, "Lock", + NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, + &error); + } + + if ((error == NULL) && show_lock_screen) + { + g_dbus_proxy_call_sync (proxy, "SimulateUserActivity", + NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, + &error); + } + + if (error != NULL) + { + g_warning ("Error locking screen: %s", error->message); + } + + g_clear_object (&proxy); + g_clear_error (&error); + } +} + +static void +action_func_lock (SessionMenuMgr * mgr) +{ + lock_helper (mgr, FALSE); +} + +static void +action_func_switch_to_lockscreen (SessionMenuMgr * mgr) +{ + lock_helper (mgr, TRUE); +} + +static void +action_func_switch_to_greeter (SessionMenuMgr * mgr) +{ + action_func_lock (mgr); + users_service_dbus_show_greeter (mgr->users_dbus_facade); +} + +static void +action_func_switch_to_user (AccountsUser * user) +{ + SessionMenuMgr * mgr = user_get_mgr (user); + g_return_if_fail (mgr != NULL); + action_func_lock (mgr); + users_service_dbus_activate_user_session (mgr->users_dbus_facade, user); +} + +static void +action_func_switch_to_guest (SessionMenuMgr * mgr) +{ + action_func_lock (mgr); + users_service_dbus_activate_guest_session (mgr->users_dbus_facade); +} + +static void +action_func_suspend (SessionMenuMgr * mgr) +{ + GError * error = NULL; + + dbus_upower_call_suspend_sync (mgr->upower_proxy, + mgr->cancellable, + &error); + + if (error != NULL) + { + g_warning ("%s: %s", G_STRFUNC, error->message); + g_clear_error (&error); + } +} + +static void +action_func_hibernate (SessionMenuMgr * mgr) +{ + GError * error = NULL; + + dbus_upower_call_hibernate_sync (mgr->upower_proxy, + mgr->cancellable, + &error); + + if (error != NULL) + { + g_warning ("%s: %s", G_STRFUNC, error->message); + g_clear_error (&error); + } +} + +/*** +**** +***/ + +static gboolean +is_this_guest_session (void) +{ + /* FIXME: this test has been here awhile and seems to work, + but seems brittle to me */ + return geteuid() < 500; +} + +static gboolean +is_this_live_session (void) +{ + const struct passwd * const pw = getpwuid (geteuid()); + return (pw->pw_uid==999) && !g_strcmp0("ubuntu",pw->pw_name); +} + +static SwitcherMode +get_switcher_mode (SessionMenuMgr * mgr) +{ + SwitcherMode mode; + + const gboolean can_lock = !g_settings_get_boolean (mgr->lockdown_settings, + "disable-lock-screen"); + const gboolean can_switch = is_user_switching_allowed (mgr); + + if (!can_lock && !can_switch) /* hmm, quite an extreme lockdown */ + { + mode = SWITCHER_MODE_SCREENSAVER; + } + else if (is_this_live_session()) /* live sessions can't lock or switch */ + { + mode = SWITCHER_MODE_SCREENSAVER; + } + else if (!can_switch) /* switching's locked down */ + { + mode = SWITCHER_MODE_LOCK; + } + else if (is_this_guest_session ()) /* guest sessions can't lock */ + { + mode = SWITCHER_MODE_SWITCH; + } + else /* both locking & switching are allowed */ + { + GList * l = users_service_dbus_get_user_list (mgr->users_dbus_facade); + const size_t user_count = g_list_length (l); + g_list_free (l); + + /* only show switch mode if we have users to switch to */ + mode = user_count > (is_this_guest_session() ? 0 : 1) + ? SWITCHER_MODE_SWITCH_OR_LOCK + : SWITCHER_MODE_LOCK; + } + + return mode; +} + + +/*** +**** +***/ + +SessionMenuMgr* +session_menu_mgr_new (SessionDbus * session_dbus, + gboolean greeter_mode) +{ + SessionMenuMgr* mgr = g_object_new (SESSION_TYPE_MENU_MGR, NULL); + mgr->greeter_mode = greeter_mode; + mgr->session_dbus = g_object_ref (session_dbus); + build_admin_menuitems (mgr); + const guint n = g_list_length (dbusmenu_menuitem_get_children (mgr->top_mi)); + mgr->user_menuitem_index = n; + update_user_menuitems (mgr); + build_session_menuitems (mgr); + return mgr; +} + +/** + * session_menu_mgr_get_menu: + * + * Returns: (transfer none): the manager's menu. + */ +DbusmenuMenuitem * +session_menu_mgr_get_menu (SessionMenuMgr * mgr) +{ + g_return_val_if_fail (IS_SESSION_MENU_MGR(mgr), NULL); + + return mgr->top_mi; +} diff --git a/src/session-menu-mgr.h b/src/session-menu-mgr.h new file mode 100644 index 0000000..5a173e1 --- /dev/null +++ b/src/session-menu-mgr.h @@ -0,0 +1,55 @@ +/* +Copyright 2011 Canonical Ltd. + +Authors: + Conor Curran <conor.curran@canonical.com> + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published +by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>. +*/ + + +#ifndef _SESSION_MENU_MGR_H_ +#define _SESSION_MENU_MGR_H_ + +#include <glib-object.h> + +#include "session-dbus.h" + +G_BEGIN_DECLS + +#define SESSION_TYPE_MENU_MGR (session_menu_mgr_get_type ()) +#define SESSION_MENU_MGR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SESSION_TYPE_MENU_MGR, SessionMenuMgr)) +#define SESSION_MENU_MGR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SESSION_TYPE_MENU_MGR, SessionMenuMgrClass)) +#define IS_SESSION_MENU_MGR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SESSION_TYPE_MENU_MGR)) +#define IS_SESSION_MENU_MGR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SESSION_TYPE_MENU_MGR)) +#define SESSION_MENU_MGR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SESSION_TYPE_MENU_MGR, SessionMenuMgrClass)) + +typedef struct _SessionMenuMgrClass SessionMenuMgrClass; +typedef struct _SessionMenuMgr SessionMenuMgr; + +struct _SessionMenuMgrClass +{ + GObjectClass parent_class; +}; + +GType session_menu_mgr_get_type (void) G_GNUC_CONST; + +SessionMenuMgr* session_menu_mgr_new (SessionDbus * session_dbus, + gboolean greeter_mode); + +DbusmenuMenuitem* session_menu_mgr_get_menu (SessionMenuMgr * mgr); + + +G_END_DECLS + +#endif /* _SESSION_MENU_MGR_H_ */ diff --git a/src/session-service.c b/src/session-service.c index 76ec047..6d5a7f3 100644 --- a/src/session-service.c +++ b/src/session-service.c @@ -9,78 +9,62 @@ Authors: Christoph Korn <c_korn@gmx.de> Cody Russell <crussell@canonical.com> Conor Curran <conor.curran@canonical.com> + Charles Kerr <charles.kerr@canonical.com> -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, 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 +You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <config.h> +#include "config.h" #include <locale.h> #include <unistd.h> +#include <locale.h> #include <glib/gi18n.h> #include <gio/gio.h> #include <gio/gdesktopappinfo.h> -#include <dbus/dbus-glib.h> -#include <dbus/dbus-glib-bindings.h> - #include <libdbusmenu-glib/server.h> -#include <libdbusmenu-glib/menuitem.h> -#include <libdbusmenu-glib/client.h> #include <gtk/gtk.h> -#include <libdbusmenu-gtk/menuitem.h> #include <libindicator/indicator-service.h> -#include "dbus-shared-names.h" -#include "dbusmenu-shared.h" -#include "users-service-dbus.h" -#include "user-menu-mgr.h" -#include "device-menu-mgr.h" #include "session-dbus.h" +#include "session-menu-mgr.h" +#include "shared-names.h" +#include "users-service-dbus.h" -typedef struct _ActivateData ActivateData; -struct _ActivateData -{ - UsersServiceDbus *service; - UserData *user; -}; - -//static UsersServiceDbus *dbus_interface = NULL; -static SessionDbus *session_dbus = NULL; +static SessionDbus * session_dbus = NULL; static GMainLoop * mainloop = NULL; -/* When the service interface starts to shutdown, we - should follow it. */ +/* When the service interface starts to shutdown, + we should follow it. */ void service_shutdown (IndicatorService * service, gpointer user_data) { - if (mainloop != NULL) { - g_debug("Service shutdown"); - g_main_loop_quit(mainloop); - } - return; + if (mainloop != NULL) + { + g_debug ("Service shutdown"); + g_main_loop_quit (mainloop); + } } -static gboolean -get_greeter_mode (void) +static inline gboolean +is_greeter_mode (void) { - const gchar *var; - var = g_getenv("INDICATOR_GREETER_MODE"); - return (g_strcmp0(var, "1") == 0); + return !g_strcmp0 (g_getenv ("INDICATOR_GREETER_MODE"), "1"); } /* Main, is well, main. It brings everything up and throws @@ -88,41 +72,28 @@ get_greeter_mode (void) int main (int argc, char ** argv) { - gboolean greeter_mode; - g_type_init(); - /* Setting up i18n and gettext. Apparently, we need - all of these. */ - setlocale (LC_ALL, ""); - bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); - textdomain (GETTEXT_PACKAGE); + /* Setting up i18n and gettext. + Apparently we need all of these. */ + setlocale (LC_ALL, ""); + bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); + textdomain (GETTEXT_PACKAGE); - IndicatorService * service = indicator_service_new_version (INDICATOR_SESSION_DBUS_NAME, - INDICATOR_SESSION_DBUS_VERSION); - g_signal_connect (G_OBJECT(service), - INDICATOR_SERVICE_SIGNAL_SHUTDOWN, + IndicatorService * service = indicator_service_new_version (INDICATOR_SESSION_DBUS_NAME, + INDICATOR_SESSION_DBUS_VERSION); + g_signal_connect (G_OBJECT(service), INDICATOR_SERVICE_SIGNAL_SHUTDOWN, G_CALLBACK(service_shutdown), NULL); - session_dbus = session_dbus_new(); + session_dbus = session_dbus_new(); - greeter_mode = get_greeter_mode(); - - // Devices - DeviceMenuMgr* device_mgr = device_menu_mgr_new (session_dbus, greeter_mode); - DbusmenuServer * server = dbusmenu_server_new(INDICATOR_SESSION_DBUS_OBJECT); - dbusmenu_server_set_root(server, device_mgr_get_root_item (device_mgr)); - - if (!greeter_mode) { - // Users - UserMenuMgr* user_mgr = user_menu_mgr_new (session_dbus, greeter_mode); - DbusmenuServer* users_server = dbusmenu_server_new (INDICATOR_USERS_DBUS_OBJECT); - dbusmenu_server_set_root (users_server, user_mgr_get_root_item (user_mgr)); - } + SessionMenuMgr * menu_mgr = session_menu_mgr_new (session_dbus, is_greeter_mode()); + DbusmenuServer* server = dbusmenu_server_new (INDICATOR_SESSION_DBUS_OBJECT); + dbusmenu_server_set_root (server, session_menu_mgr_get_menu (menu_mgr)); mainloop = g_main_loop_new(NULL, FALSE); g_main_loop_run(mainloop); - + return 0; } diff --git a/src/settings-helper.c b/src/settings-helper.c deleted file mode 100644 index 007f83f..0000000 --- a/src/settings-helper.c +++ /dev/null @@ -1,167 +0,0 @@ -/* -A small wrapper utility for connecting to GSettings. - -Copyright 2009 Canonical Ltd. - -Authors: - Christoph Korn <c_korn@gmx.de> - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>. -*/ - -#include <gio/gio.h> -#include <glib/gi18n.h> - -#include <dbus/dbus-glib.h> -#include <dbus/dbus-glib-bindings.h> - -#include <libdbusmenu-glib/server.h> -#include <libdbusmenu-glib/menuitem.h> - -#include "dbus-shared-names.h" -#include "settings-helper.h" - -static GSettings* settings = NULL; - -static guint confirmation_notify = 0; -static guint logout_notify = 0; -static guint restart_notify = 0; -static guint shutdown_notify = 0; - -static gboolean -build_settings (void) { - if (settings == NULL) { - settings = g_settings_new (SESSION_SCHEMA); - } - if (settings == NULL) { - return FALSE; - } - return TRUE; -} - -gboolean -supress_confirmations (void) { - gboolean settings_built = build_settings(); - g_return_val_if_fail(settings_built, FALSE); - return g_settings_get_boolean (settings, SUPPRESS_KEY) ; -} - -gboolean -should_show_user_menu (void) { - gboolean settings_built = build_settings(); - g_return_val_if_fail(settings_built, TRUE); - return g_settings_get_boolean (settings, SHOW_USER_MENU) ; -} - -gboolean -show_logout (void) { - gboolean settings_built = build_settings(); - g_return_val_if_fail(settings_built, TRUE); - return !g_settings_get_boolean (settings, LOGOUT_KEY) ; -} - -gboolean -show_restart (void) { - gboolean settings_built = build_settings(); - g_return_val_if_fail(settings_built, TRUE); - return !g_settings_get_boolean (settings, RESTART_KEY) ; -} - -gboolean -show_shutdown (void) { - gboolean settings_built = build_settings(); - g_return_val_if_fail(settings_built, TRUE); - return !g_settings_get_boolean (settings, SHUTDOWN_KEY) ; -} - -static void update_menu_entries_callback (GSettings * settings, const gchar * key, gpointer data) { - RestartShutdownLogoutMenuItems * restart_shutdown_logout_mi = (RestartShutdownLogoutMenuItems*) data; - - if(g_strcmp0 (key, SUPPRESS_KEY) == 0) { - if (g_settings_get_boolean (settings, key)) { - dbusmenu_menuitem_property_set(restart_shutdown_logout_mi->logout_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Log Out")); - dbusmenu_menuitem_property_set(restart_shutdown_logout_mi->restart_mi, RESTART_ITEM_LABEL, _("Restart")); - dbusmenu_menuitem_property_set(restart_shutdown_logout_mi->shutdown_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Shut Down")); - } else { - dbusmenu_menuitem_property_set(restart_shutdown_logout_mi->logout_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Log Out…")); - dbusmenu_menuitem_property_set(restart_shutdown_logout_mi->restart_mi, RESTART_ITEM_LABEL, _("Restart…")); - dbusmenu_menuitem_property_set(restart_shutdown_logout_mi->shutdown_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Shut Down…")); - } - } -} - -static void -update_logout_callback (GSettings * settings, const gchar * key, gpointer data) { - DbusmenuMenuitem * mi = (DbusmenuMenuitem*) data; - - if(g_strcmp0 (key, LOGOUT_KEY) == 0) { - dbusmenu_menuitem_property_set_bool(mi, DBUSMENU_MENUITEM_PROP_VISIBLE, !g_settings_get_boolean(settings, key)); - } -} - -static void -update_restart_callback (GSettings * settings, const gchar * key, gpointer data) { - DbusmenuMenuitem * mi = (DbusmenuMenuitem*) data; - - if(g_strcmp0 (key, RESTART_KEY) == 0) { - dbusmenu_menuitem_property_set_bool(mi, DBUSMENU_MENUITEM_PROP_VISIBLE, !g_settings_get_boolean(settings, key)); - } -} - -static void -update_shutdown_callback (GSettings * settings, const gchar * key, gpointer data) { - DbusmenuMenuitem * mi = (DbusmenuMenuitem*) data; - - if(g_strcmp0 (key, SHUTDOWN_KEY) == 0) { - dbusmenu_menuitem_property_set_bool(mi, DBUSMENU_MENUITEM_PROP_VISIBLE, !g_settings_get_boolean(settings, key)); - } -} - -void -update_menu_entries(RestartShutdownLogoutMenuItems * restart_shutdown_logout_mi) { - /* If we don't have a client, build one. */ - gboolean settings_built = build_settings(); - g_return_if_fail(settings_built); - - if (confirmation_notify != 0) { - g_signal_handler_disconnect (settings, confirmation_notify); - confirmation_notify = 0; - } - - if (logout_notify != 0) { - g_signal_handler_disconnect (settings, logout_notify); - logout_notify = 0; - } - - if (restart_notify != 0) { - g_signal_handler_disconnect (settings, restart_notify); - restart_notify = 0; - } - - if (shutdown_notify != 0) { - g_signal_handler_disconnect (settings, shutdown_notify); - shutdown_notify = 0; - } - - confirmation_notify = g_signal_connect (settings, "changed::" SUPPRESS_KEY, - G_CALLBACK(update_menu_entries_callback), restart_shutdown_logout_mi); - logout_notify = g_signal_connect (settings, "changed::" LOGOUT_KEY, - G_CALLBACK(update_logout_callback), restart_shutdown_logout_mi->logout_mi); - restart_notify = g_signal_connect (settings, "changed::" RESTART_KEY, - G_CALLBACK(update_restart_callback), restart_shutdown_logout_mi->restart_mi); - shutdown_notify = g_signal_connect (settings, "changed::" SHUTDOWN_KEY, - G_CALLBACK(update_shutdown_callback), restart_shutdown_logout_mi->shutdown_mi); - - return; -} - diff --git a/src/settings-helper.h b/src/settings-helper.h deleted file mode 100644 index ea0c99f..0000000 --- a/src/settings-helper.h +++ /dev/null @@ -1,64 +0,0 @@ -/* -A small wrapper utility for connecting to GSettings. - -Copyright 2009 Canonical Ltd. - -Authors: - Christoph Korn <c_korn@gmx.de> - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>. -*/ - - -#ifndef __GCONF_HELPER_H__ -#define __GCONF_HELPER_H__ - -#include <glib/gi18n.h> - -#include <dbus/dbus-glib.h> -#include <dbus/dbus-glib-bindings.h> - -#include <libdbusmenu-glib/server.h> -#include <libdbusmenu-glib/menuitem.h> - -#define SESSION_SCHEMA "com.canonical.indicator.session" -#define SUPPRESS_KEY "suppress-logout-restart-shutdown" -#define LOGOUT_KEY "suppress-logout-menuitem" -#define RESTART_KEY "suppress-restart-menuitem" -#define SHUTDOWN_KEY "suppress-shutdown-menuitem" -#define SHOW_USER_MENU "user-show-menu" -#define USER_USERNAME_IN_SWITCH_ITEM "use-username-in-switch-item" - -#define LOCKDOWN_SCHEMA "org.gnome.desktop.lockdown" -#define LOCKDOWN_KEY_USER "disable-user-switching" -#define LOCKDOWN_KEY_SCREENSAVER "disable-lock-screen" -#define KEYBINDING_SCHEMA "org.gnome.settings-daemon.plugins.media-keys" -#define KEY_LOCK_SCREEN "screensaver" - -typedef struct _RestartShutdownLogoutMenuItems -{ - DbusmenuMenuitem * logout_mi; - DbusmenuMenuitem * restart_mi; - DbusmenuMenuitem * shutdown_mi; -} -RestartShutdownLogoutMenuItems; - -void update_menu_entries(RestartShutdownLogoutMenuItems*); -gboolean supress_confirmations (void); -gboolean show_logout (void); -gboolean show_restart (void); -gboolean show_shutdown (void); -gboolean should_show_user_menu (void); - - -#endif /* __GCONF_HELPER__ */ diff --git a/src/dbus-shared-names.h b/src/shared-names.h index 5f35903..dcda182 100644 --- a/src/dbus-shared-names.h +++ b/src/shared-names.h @@ -23,33 +23,12 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #ifndef __DBUS_SHARED_NAMES_H__ #define __DBUS_SHARED_NAMES_H__ -typedef enum { - UP_TO_DATE, - CHECKING_FOR_UPDATES, - UPDATES_AVAILABLE, - UPGRADE_IN_PROGRESS, - FINISHED, - RESTART_NEEDED, - DONT_KNOW -}AptState; - -typedef enum { - SIMULATION, - REAL -}TransactionType; - -#define INDICATOR_USERS_DBUS_NAME INDICATOR_SESSION_DBUS_NAME -#define INDICATOR_USERS_DBUS_OBJECT "/com/canonical/indicator/users/menu" -#define INDICATOR_USERS_SERVICE_DBUS_OBJECT "/org/gnome/DisplayManager/UserManager" -#define INDICATOR_USERS_SERVICE_DBUS_INTERFACE "org.gnome.DisplayManager.UserManager" - #define INDICATOR_SESSION_DBUS_NAME "com.canonical.indicator.session" #define INDICATOR_SESSION_DBUS_OBJECT "/com/canonical/indicator/session/menu" #define INDICATOR_SESSION_DBUS_VERSION 0 #define INDICATOR_SESSION_SERVICE_DBUS_OBJECT "/com/canonical/indicator/session/service" #define INDICATOR_SESSION_SERVICE_DBUS_IFACE "com.canonical.indicator.session.service" - #define USER_ITEM_TYPE "x-canonical-user-item" #define USER_ITEM_PROP_NAME "user-item-name" #define USER_ITEM_PROP_LOGGED_IN "user-item-logged-in" @@ -66,4 +45,13 @@ typedef enum { #define GREETER_ICON_DEFAULT "system-shutdown-panel" #define GREETER_ICON_RESTART "system-shutdown-panel-restart" +/* the session indicator's settings */ +#define SESSION_SCHEMA "com.canonical.indicator.session" +#define SUPPRESS_KEY "suppress-logout-restart-shutdown" +#define LOGOUT_KEY "suppress-logout-menuitem" +#define RESTART_KEY "suppress-restart-menuitem" +#define SHUTDOWN_KEY "suppress-shutdown-menuitem" +#define SHOW_USER_MENU "user-show-menu" + + #endif /* __DBUS_SHARED_NAMES_H__ */ diff --git a/src/udev-mgr.c b/src/udev-mgr.c deleted file mode 100644 index 5f197d6..0000000 --- a/src/udev-mgr.c +++ /dev/null @@ -1,546 +0,0 @@ -/* -Copyright 2011 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>. -*/ - -#include <gudev/gudev.h> - -#include <glib/gi18n.h> - -#include "udev-mgr.h" -#include "sane-rules.h" - -static void udevice_mgr_device_list_iterator (gpointer data, - gpointer userdata); -static void udev_mgr_uevent_cb (GUdevClient *client, - gchar *action, - GUdevDevice *device, - gpointer user_data); -static void udev_mgr_update_menuitems (UdevMgr* self); -static void udev_mgr_check_if_usb_device_is_supported (UdevMgr* self, - GUdevDevice *device, - UdevMgrDeviceAction action); -static void udev_mgr_handle_webcam (UdevMgr* self, - GUdevDevice* device, - UdevMgrDeviceAction action); -static void udev_mgr_handle_scsi_device (UdevMgr* self, - GUdevDevice* device, - UdevMgrDeviceAction action); - -static void udev_mgr_cleanup_lists(gpointer data, gpointer self); -static void udev_mgr_cleanup_entries(gpointer data, gpointer self); - - -static void debug_device (UdevMgr* self, - GUdevDevice* device, - UdevMgrDeviceAction action); - -static gchar* format_device_name (UdevMgr* self, - const gchar* brand, - const gchar* generic, - const gchar* branded) G_GNUC_WARN_UNUSED_RESULT; -struct _UdevMgr -{ - GObject parent_instance; - DbusmenuMenuitem* scanner_item; - DbusmenuMenuitem* webcam_item; - GUdevClient* client; - GHashTable* supported_usb_scanners; - GHashTable* supported_scsi_scanners; - GHashTable* scanners_present; - GHashTable* webcams_present; -}; - -const char *subsystems[3] = {"usb", "scsi", "video4linux"}; -const gchar* usb_subsystem = "usb"; -const gchar* scsi_subsystem = "scsi"; -const gchar* video4linux_subsystem = "video4linux"; - - -G_DEFINE_TYPE (UdevMgr, udev_mgr, G_TYPE_OBJECT); - -static void -udev_mgr_init (UdevMgr* self) -{ - self->client = NULL; - self->supported_usb_scanners = NULL; - self->scanners_present = NULL; - self->webcams_present = NULL; - self->client = g_udev_client_new (subsystems); - self->supported_usb_scanners = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - (GDestroyNotify)udev_mgr_cleanup_lists); - self->supported_scsi_scanners = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - (GDestroyNotify)udev_mgr_cleanup_lists); - self->scanners_present = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - g_free); - self->webcams_present = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - g_free); - - // load into memory all supported scanners ... - populate_usb_scanners (self->supported_usb_scanners); - populate_scsi_scanners (self->supported_scsi_scanners); - g_signal_connect (G_OBJECT (self->client), - "uevent", - G_CALLBACK (udev_mgr_uevent_cb), - self); -} - -static void -udev_mgr_cleanup_lists(gpointer data, gpointer self) -{ - GList* scanners = (GList*)data; - g_list_foreach (scanners, udev_mgr_cleanup_entries, NULL); - g_list_free(scanners); -} - -static void -udev_mgr_cleanup_entries(gpointer data, gpointer self) -{ - gchar* entry = (gchar*)data; - g_free(entry); -} - -static void -udev_mgr_finalize (GObject *object) -{ - UdevMgr* self = UDEV_MGR (object); - g_hash_table_destroy (self->supported_scsi_scanners); - g_hash_table_destroy (self->supported_usb_scanners); - g_hash_table_destroy (self->scanners_present); - g_hash_table_destroy (self->webcams_present); - G_OBJECT_CLASS (udev_mgr_parent_class)->finalize (object); -} - -static void -udev_mgr_class_init (UdevMgrClass *klass) -{ - GObjectClass* object_class = G_OBJECT_CLASS (klass); - object_class->finalize = udev_mgr_finalize; -} - -static void -udevice_mgr_device_list_iterator (gpointer data, gpointer userdata) -{ - g_return_if_fail (G_UDEV_IS_DEVICE (data)); - g_return_if_fail (UDEV_IS_MGR (userdata)); - - UdevMgr* self = UDEV_MGR (userdata); - - GUdevDevice* device = G_UDEV_DEVICE (data); - - const gchar* subsystem = NULL; - subsystem = g_udev_device_get_subsystem (device); - - if (g_strcmp0 (subsystem, "usb") == 0){ - udev_mgr_check_if_usb_device_is_supported (self, device, ADD); - } - else if (g_strcmp0 (subsystem, "video4linux") == 0){ - udev_mgr_handle_webcam (self, device, ADD); - } - else if (g_strcmp0 (subsystem, "scsi") == 0){ - udev_mgr_handle_scsi_device (self, device, ADD); - } - - g_object_unref (device); -} - - -static void udev_mgr_update_menuitems (UdevMgr* self) -{ - dbusmenu_menuitem_property_set_bool (self->scanner_item, - DBUSMENU_MENUITEM_PROP_VISIBLE, - g_hash_table_size (self->scanners_present) > 0); - - dbusmenu_menuitem_property_set_bool (self->webcam_item, - DBUSMENU_MENUITEM_PROP_VISIBLE, - g_hash_table_size (self->webcams_present) > 0); - -} - -static void udev_mgr_uevent_cb (GUdevClient *client, - gchar *action, - GUdevDevice *device, - gpointer user_data) -{ - g_return_if_fail (UDEV_IS_MGR (user_data)); - UdevMgr* self = UDEV_MGR (user_data); - g_return_if_fail (device != NULL); - - g_debug ("just received a UEVENT with an action : %s", action); - - UdevMgrDeviceAction udev_mgr_action = ADD; - - if (g_strcmp0 (action, "remove") == 0){ - udev_mgr_action = REMOVE; - } - - const gchar* subsystem = NULL; - subsystem = g_udev_device_get_subsystem (device); - - if (g_strcmp0 (subsystem, "usb") == 0){ - udev_mgr_check_if_usb_device_is_supported (self, - device, - udev_mgr_action); - } - else if (g_strcmp0 (subsystem, "video4linux") == 0){ - udev_mgr_handle_webcam (self, device, udev_mgr_action); - } - else if (g_strcmp0 (subsystem, "scsi") == 0){ - udev_mgr_handle_scsi_device (self, device, udev_mgr_action); - } -} - - -static void -udev_mgr_handle_webcam (UdevMgr* self, - GUdevDevice* device, - UdevMgrDeviceAction action) -{ - if (FALSE) - debug_device (self, device, action); - - const gchar* vendor; - const gchar* product; - - vendor = g_udev_device_get_property (device, "ID_VENDOR_ID"); - product = g_udev_device_get_property (device, "ID_MODEL_ID"); - - if (!vendor || !product) { - return; - } - - if (action == REMOVE){ - if (g_hash_table_lookup (self->webcams_present, product) == NULL){ - g_warning ("Got a remove event on a webcam device but we don't have that device in our webcam cache"); - return; - } - g_hash_table_remove (self->webcams_present, - product); - dbusmenu_menuitem_property_set (self->webcam_item, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Webcam")); - } - else { - if (g_hash_table_lookup (self->webcams_present, product) != NULL){ - g_warning ("Got an ADD event on a webcam device but we already have that device in our webcam cache"); - return; - } - - const gchar* manufacturer = NULL; - manufacturer = g_udev_device_get_property (device, "ID_VENDOR"); - - if (manufacturer != NULL){ - gchar * label = format_device_name(self, manufacturer, _("Webcam"), _("%s Webcam")); - dbusmenu_menuitem_property_set (self->webcam_item, - DBUSMENU_MENUITEM_PROP_LABEL, - label); - g_free(label); - } - - g_hash_table_insert (self->webcams_present, - g_strdup (product), - g_strdup (vendor)); - } - udev_mgr_update_menuitems (self); -} - -static void -debug_device (UdevMgr* self, - GUdevDevice* device, - UdevMgrDeviceAction action) -{ - const gchar* vendor; - const gchar* product; - const gchar* number; - const gchar* name; - const gchar* manufacturer; - - vendor = g_udev_device_get_property (device, "ID_VENDOR_ID"); - manufacturer = g_udev_device_get_property (device, "ID_VENDOR"); - product = g_udev_device_get_property (device, "ID_MODEL_ID"); - number = g_udev_device_get_number (device); - name = g_udev_device_get_name (device); - - g_debug ("%s device vendor id %s , product id of %s , number of %s and name of %s", - g_strdup(manufacturer), - g_strdup(vendor), - g_strdup(product), - g_strdup(number), - g_strdup(name)); - - /*const gchar *const *list; - const gchar *const *iter; - char propstr[500]; - guint32 namelen = 0, i; - - list = g_udev_device_get_property_keys(device); - - for (iter = list; iter && *iter; iter++) { - if (strlen(*iter) > namelen) - namelen = strlen(*iter); - } - namelen++; - - for (iter = list; iter && *iter; iter++) { - strcpy(propstr, *iter); - strcat(propstr, ":"); - for (i = 0; i < namelen - strlen(*iter); i++) - strcat(propstr, " "); - strcat(propstr, g_udev_device_get_property(device, *iter)); - g_debug("%s", propstr); - }*/ -} -// TODO SCSI is not dynamic right ? -// i.e. just need to handle startup scan. -static void udev_mgr_handle_scsi_device (UdevMgr* self, - GUdevDevice* device, - UdevMgrDeviceAction action) -{ - const gchar* type = NULL; - type = g_udev_device_get_property (device, "TYPE"); - - if (!type) { - return; - } - - // apparently anything thats type 6 and SCSI is a Scanner - if (g_strcmp0 (type, "6") == 0 && action == ADD){ - - const gchar* manufacturer = NULL; - manufacturer = g_udev_device_get_property (device, "ID_VENDOR"); - - if (manufacturer != NULL){ - gchar * label = format_device_name(self, manufacturer, _("Scanner"), _("%s Scanner")); - dbusmenu_menuitem_property_set (self->scanner_item, - DBUSMENU_MENUITEM_PROP_LABEL, - label); - g_free(label); - } - - gchar* random_scanner_name = g_strdup_printf("%p--scanner", self); - g_hash_table_insert (self->scanners_present, - random_scanner_name, - g_strdup("Scanner")); - udev_mgr_update_menuitems (self); - return; - } - - // We only care about type 3 for the special cases below - if (g_strcmp0 (type, "3") != 0){ - return; - } - - const gchar* vendor = NULL; - vendor = g_udev_device_get_property (device, "VENDOR"); - - if (vendor == NULL) - return; - - GList* vendor_list = NULL; - vendor_list = g_hash_table_lookup (self->supported_scsi_scanners, - (gpointer)vendor); - if (vendor_list == NULL) - return; - - const gchar* model_id = NULL; - model_id = g_udev_device_get_property (device, "MODEL"); - - if (model_id == NULL) - return; - - GList* model_entry = NULL; - model_entry = g_list_find_custom (vendor_list, - model_id, - (GCompareFunc)g_strcmp0); - - if (model_entry != NULL){ - if (action == REMOVE){ - if (g_hash_table_lookup (self->scanners_present, g_strdup(vendor)) == NULL){ - g_warning ("Got an REMOVE event on a scanner device but we dont have that device in our scanners cache"); - } - else{ - g_hash_table_remove (self->scanners_present, vendor); - dbusmenu_menuitem_property_set (self->scanner_item, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Scanner")); - - } - } - else{ - if (g_hash_table_lookup (self->scanners_present, g_strdup(vendor)) != NULL){ - g_warning ("Got an ADD event on a scanner device but we already have that device in our scanners cache"); - } - else{ - const gchar* manufacturer = NULL; - manufacturer = g_udev_device_get_property (device, "ID_VENDOR"); - - if (manufacturer != NULL){ - gchar * label = format_device_name(self, manufacturer, _("Scanner"), _("%s Scanner")); - dbusmenu_menuitem_property_set (self->scanner_item, - DBUSMENU_MENUITEM_PROP_LABEL, - label); - g_free(label); - } - g_hash_table_insert (self->scanners_present, - g_strdup(vendor), - g_strdup(model_id)); - } - } - udev_mgr_update_menuitems (self); - } -} - -static void -udev_mgr_check_if_usb_device_is_supported (UdevMgr* self, - GUdevDevice *device, - UdevMgrDeviceAction action) -{ - const gchar* vendor = NULL; - //debug_device (self, device, action); - - vendor = g_udev_device_get_property (device, "ID_VENDOR_ID"); - - if (vendor == NULL) - return; - - //g_debug ("vendor = %s", vendor); - - GList* vendor_list = NULL; - vendor_list = g_hash_table_lookup (self->supported_usb_scanners, - (gpointer)vendor); - if (vendor_list == NULL) - return; - - const gchar* model_id = NULL; - model_id = g_udev_device_get_property (device, "ID_MODEL_ID"); - - if (model_id == NULL) - return; - - GList* model_entry = NULL; - model_entry = g_list_find_custom(vendor_list, model_id, (GCompareFunc)g_strcmp0); - - if (model_entry != NULL){ - if (action == REMOVE){ - if (g_hash_table_lookup (self->scanners_present, g_strdup(vendor)) == NULL){ - g_warning ("Got an REMOVE event on a scanner device but we dont have that device in our scanners cache"); - } - else{ - g_hash_table_remove (self->scanners_present, vendor); - dbusmenu_menuitem_property_set (self->scanner_item, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Scanner")); - } - } - else{ - if (g_hash_table_lookup (self->scanners_present, g_strdup(vendor)) != NULL){ - g_warning ("Got an ADD event on a scanner device but we already have that device in our scanners cache"); - } - else{ - const gchar* manufacturer = NULL; - - manufacturer = g_udev_device_get_property (device, "ID_VENDOR"); - if (manufacturer != NULL){ - gchar * label = format_device_name(self, manufacturer, _("Scanner"), _("%s Scanner")); - dbusmenu_menuitem_property_set (self->scanner_item, - DBUSMENU_MENUITEM_PROP_LABEL, - label); - g_free(label); - } - - g_hash_table_insert (self->scanners_present, - g_strdup(vendor), - g_strdup(model_id)); - } - } - udev_mgr_update_menuitems (self); - } -} - -UdevMgr* udev_mgr_new (DbusmenuMenuitem* scanner, - DbusmenuMenuitem* webcam) -{ - UdevMgr* mgr = g_object_new (UDEV_TYPE_MGR, NULL); - mgr->scanner_item = scanner; - mgr->webcam_item = webcam; - - // Check for USB devices - GList* usb_devices_available = NULL; - usb_devices_available = g_udev_client_query_by_subsystem (mgr->client, - usb_subsystem); - if (usb_devices_available != NULL){ - g_list_foreach (usb_devices_available, - udevice_mgr_device_list_iterator, - mgr); - - g_list_free (usb_devices_available); - } - // Check for webcams - GList* video_devices_available = NULL; - video_devices_available = g_udev_client_query_by_subsystem (mgr->client, - video4linux_subsystem); - if (video_devices_available != NULL){ - g_list_foreach (video_devices_available, - udevice_mgr_device_list_iterator, - mgr); - - g_list_free (video_devices_available); - } - // Check for SCSI devices - GList* scsi_devices_available = NULL; - scsi_devices_available = g_udev_client_query_by_subsystem (mgr->client, - scsi_subsystem); - if (scsi_devices_available != NULL){ - g_list_foreach (scsi_devices_available, - udevice_mgr_device_list_iterator, - mgr); - g_list_free (scsi_devices_available); - } - return mgr; -} - -static gchar* format_device_name (UdevMgr* self, - const gchar* brand, - const gchar* generic, - const gchar* branded) -{ - // We don't want to accommodate long names - if (strlen(brand) > 7) - return g_strdup(generic); - - gint i = 0; - - // If it contains something other than an alphabetic entry ignore it. - for(i = 0; i < sizeof(brand); i++){ - if ( !g_ascii_isalpha (brand[i]) ) - return g_strdup(generic); - } - - gchar* lowered = g_ascii_strdown (brand, -1); - lowered[0] = g_ascii_toupper (lowered[0]); - gchar* label = g_strdup_printf(branded, lowered); - g_free (lowered); - return label; -} diff --git a/src/udev-mgr.h b/src/udev-mgr.h deleted file mode 100644 index 2e57cff..0000000 --- a/src/udev-mgr.h +++ /dev/null @@ -1,58 +0,0 @@ -/* -Copyright 2011 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>. -*/ - -#ifndef _UDEV_MGR_H_ -#define _UDEV_MGR_H_ - -#include <glib-object.h> -#include <libdbusmenu-glib/client.h> - -#include <gtk/gtk.h> -#include <libdbusmenu-gtk/menuitem.h> - -G_BEGIN_DECLS - -#define UDEV_TYPE_MGR (udev_mgr_get_type ()) -#define UDEV_MGR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UDEV_TYPE_MGR, UdevMgr)) -#define UDEV_MGR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UDEV_TYPE_MGR, UdevMgrClass)) -#define UDEV_IS_MGR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UDEV_TYPE_MGR)) -#define UDEV_IS_MGR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UDEV_TYPE_MGR)) -#define UDEV_MGR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UDEV_TYPE_MGR, UdevMgrClass)) - -typedef struct _UdevMgrClass UdevMgrClass; -typedef struct _UdevMgr UdevMgr; - -struct _UdevMgrClass -{ - GObjectClass parent_class; -}; - - -GType udev_mgr_get_type (void) G_GNUC_CONST; -UdevMgr* udev_mgr_new (DbusmenuMenuitem* scanner_item, - DbusmenuMenuitem* webcam_item); - -typedef enum { - ADD, - REMOVE -}UdevMgrDeviceAction; - -G_END_DECLS - -#endif /* _UDEV_MGR_H_ */ diff --git a/src/upower.xml b/src/upower.xml index a4066ff..18d5fbd 100644 --- a/src/upower.xml +++ b/src/upower.xml @@ -86,7 +86,7 @@ method return sender=:1.386 -> dest=:1.451 reply_serial=2 <!-- ************************************************************ --> <signal name="DeviceChanged"> - <arg name="device" type="o"> + <arg name="device" type="s"> <doc:doc><doc:summary>Object path of device that was changed.</doc:summary></doc:doc> </arg> diff --git a/src/user-menu-mgr.c b/src/user-menu-mgr.c deleted file mode 100644 index 5b2aefb..0000000 --- a/src/user-menu-mgr.c +++ /dev/null @@ -1,435 +0,0 @@ -/* -Copyright 2011 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>. -*/ - -#include <libdbusmenu-glib/client.h> -#include "user-menu-mgr.h" -#include "settings-helper.h" -#include "dbus-shared-names.h" -#include "dbusmenu-shared.h" -#include "lock-helper.h" -#include "users-service-dbus.h" -#include "webcredentials-mgr.h" - -static GSettings* settings = NULL; -static DbusmenuMenuitem *switch_menuitem = NULL; - -struct _UserMenuMgr -{ - GObject parent_instance; - UsersServiceDbus* users_dbus_interface; - WebcredentialsMgr *webcredentials_mgr; - DbusmenuMenuitem* root_item; - gint user_count; - SessionDbus* session_dbus_interface; -}; - -static void activate_new_session (DbusmenuMenuitem * mi, - guint timestamp, - gpointer user_data); -static void activate_user_session (DbusmenuMenuitem *mi, - guint timestamp, - gpointer user_data); -static void activate_user_accounts (DbusmenuMenuitem *mi, - guint timestamp, - gpointer user_data); -static gint compare_users_by_username (const gchar *a, - const gchar *b); -static void activate_user_accounts (DbusmenuMenuitem *mi, - guint timestamp, - gpointer user_data); -static void user_menu_mgr_rebuild_items (UserMenuMgr *self, - gboolean greeter_mode); -static gboolean check_new_session (); -static void user_change (UsersServiceDbus *service, - const gchar *user_id, - gpointer user_data); -static void ensure_settings_client (); -static gboolean is_this_guest_session (void); -static void activate_guest_session (DbusmenuMenuitem * mi, - guint timestamp, - gpointer user_data); - - -G_DEFINE_TYPE (UserMenuMgr, user_menu_mgr, G_TYPE_OBJECT); - - -static void -user_menu_mgr_init (UserMenuMgr *self) -{ - self->users_dbus_interface = g_object_new (USERS_SERVICE_DBUS_TYPE, NULL); - self->webcredentials_mgr = webcredentials_mgr_new (); - self->root_item = dbusmenu_menuitem_new (); - g_signal_connect (G_OBJECT (self->users_dbus_interface), - "user-added", - G_CALLBACK (user_change), - self); - g_signal_connect (G_OBJECT (self->users_dbus_interface), - "user-deleted", - G_CALLBACK (user_change), - self); -} - -static void -user_menu_mgr_finalize (GObject *object) -{ - /* TODO: Add deinitalization code here */ - G_OBJECT_CLASS (user_menu_mgr_parent_class)->finalize (object); -} - -static void -user_menu_mgr_class_init (UserMenuMgrClass *klass) -{ - GObjectClass* object_class = G_OBJECT_CLASS (klass); - object_class->finalize = user_menu_mgr_finalize; -} - -/* Builds up the menu for us */ -static void -user_menu_mgr_rebuild_items (UserMenuMgr *self, gboolean greeter_mode) -{ - DbusmenuMenuitem *mi = NULL; - DbusmenuMenuitem *guest_mi = NULL; - GList *u; - UserData *user; - gboolean can_activate; - GList *children; - - /* Make sure we have a valid GConf client, and build one - if needed */ - ensure_settings_client (); - - /* Check to see which menu items we're allowed to have */ - can_activate = users_service_dbus_can_activate_session (self->users_dbus_interface) && - !g_settings_get_boolean (settings, LOCKDOWN_KEY_USER); - - /* Remove the old menu items if that makes sense */ - children = dbusmenu_menuitem_take_children (self->root_item); - g_list_foreach (children, (GFunc)g_object_unref, NULL); - g_list_free (children); - - /* Set to NULL just incase we don't end up building one */ - users_service_dbus_set_guest_item(self->users_dbus_interface, NULL); - - /* Build all of the user switching items */ - if (can_activate == TRUE) - { - - gboolean guest_enabled = users_service_dbus_guest_session_enabled (self->users_dbus_interface); - GList * users = NULL; - users = users_service_dbus_get_user_list (self->users_dbus_interface); - self->user_count = g_list_length(users); - - gboolean gsettings_user_menu_is_visible = should_show_user_menu(); - - if (gsettings_user_menu_is_visible == FALSE || greeter_mode == TRUE){ - session_dbus_set_user_menu_visibility (self->session_dbus_interface, - FALSE); - } - else{ - // This needs to be updated once the ability to query guest session support is available - session_dbus_set_user_menu_visibility (self->session_dbus_interface, - guest_enabled || self->user_count > 1); - } - - // TODO we should really return here if the menu is not going to be shown. - - if (check_new_session ()){ - switch_menuitem = dbusmenu_menuitem_new (); - dbusmenu_menuitem_property_set (switch_menuitem, - DBUSMENU_MENUITEM_PROP_TYPE, - MENU_SWITCH_TYPE); - dbusmenu_menuitem_property_set (switch_menuitem, - MENU_SWITCH_USER, - g_get_user_name()); - dbusmenu_menuitem_child_append (self->root_item, switch_menuitem); - g_signal_connect (G_OBJECT (switch_menuitem), - DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK (activate_new_session), - self->users_dbus_interface); - } - - if ( !is_this_guest_session () && guest_enabled) - { - guest_mi = dbusmenu_menuitem_new (); - dbusmenu_menuitem_property_set (guest_mi, - DBUSMENU_MENUITEM_PROP_TYPE, - USER_ITEM_TYPE); - dbusmenu_menuitem_property_set (guest_mi, - USER_ITEM_PROP_NAME, - _("Guest Session")); - dbusmenu_menuitem_property_set_bool (guest_mi, - USER_ITEM_PROP_LOGGED_IN, - FALSE); - dbusmenu_menuitem_child_append (self->root_item, guest_mi); - g_signal_connect (G_OBJECT (guest_mi), - DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK (activate_guest_session), - self); - users_service_dbus_set_guest_item (self->users_dbus_interface, - guest_mi); - } - else{ - session_dbus_set_users_real_name (self->session_dbus_interface, - _("Guest")); - } - - - - if (self->user_count > MINIMUM_USERS) { - users = g_list_sort (users, (GCompareFunc)compare_users_by_username); - } - - for (u = users; u != NULL; u = g_list_next (u)) { - user = u->data; - g_debug ("%s: %s", user->user_name, user->real_name); - user->service = self->users_dbus_interface; - gboolean current_user = g_strcmp0 (user->user_name, g_get_user_name()) == 0; - if (current_user == TRUE){ - g_debug ("about to set the users real name to %s for user %s", - user->real_name, user->user_name); - session_dbus_set_users_real_name (self->session_dbus_interface, user->real_name); - } - - if (self->user_count > MINIMUM_USERS) { - mi = dbusmenu_menuitem_new (); - dbusmenu_menuitem_property_set (mi, - DBUSMENU_MENUITEM_PROP_TYPE, - USER_ITEM_TYPE); - if (user->real_name_conflict) { - gchar * conflictedname = g_strdup_printf("%s (%s)", user->real_name, user->user_name); - dbusmenu_menuitem_property_set (mi, USER_ITEM_PROP_NAME, conflictedname); - g_free(conflictedname); - } else { - //g_debug ("%p: %s", user, user->real_name); - dbusmenu_menuitem_property_set (mi, - USER_ITEM_PROP_NAME, - user->real_name); - } - dbusmenu_menuitem_property_set_bool (mi, - USER_ITEM_PROP_LOGGED_IN, - user->sessions != NULL); - if (user->icon_file != NULL && user->icon_file[0] != '\0') { - g_debug ("user %s has this icon : %s", - user->user_name, - user->icon_file); - dbusmenu_menuitem_property_set (mi, - USER_ITEM_PROP_ICON, - user->icon_file); - } else { - dbusmenu_menuitem_property_set (mi, - USER_ITEM_PROP_ICON, - USER_ITEM_ICON_DEFAULT); - } - - - /*g_debug ("user name = %s and g user name = %s", - user->user_name, - g_get_user_name());*/ - - dbusmenu_menuitem_property_set_bool (mi, - USER_ITEM_PROP_IS_CURRENT_USER, - current_user); - dbusmenu_menuitem_child_append (self->root_item, mi); - g_signal_connect (G_OBJECT (mi), - DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK (activate_user_session), - user); - user->menuitem = mi; - } - } - g_list_free(users); - } - // Add the user accounts and separator - DbusmenuMenuitem * separator1 = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (separator1, - DBUSMENU_MENUITEM_PROP_TYPE, - DBUSMENU_CLIENT_TYPES_SEPARATOR); - dbusmenu_menuitem_child_append (self->root_item, separator1); - - DbusmenuMenuitem *webcredentials_item = - webcredentials_mgr_get_menu_item (self->webcredentials_mgr); - dbusmenu_menuitem_child_append (self->root_item, webcredentials_item); - - DbusmenuMenuitem * user_accounts_item = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (user_accounts_item, - DBUSMENU_MENUITEM_PROP_TYPE, - DBUSMENU_CLIENT_TYPES_DEFAULT); - dbusmenu_menuitem_property_set (user_accounts_item, - DBUSMENU_MENUITEM_PROP_LABEL, - _("User Accounts…")); - - g_signal_connect (G_OBJECT (user_accounts_item), - DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK (activate_user_accounts), - NULL); - - dbusmenu_menuitem_child_append (self->root_item, user_accounts_item); - - -} - -/* Checks to see if we can create sessions */ -// TODO what is this ? -static gboolean -check_new_session () -{ - return TRUE; -} - -/* Check to see if the lockdown key is protecting from - locking the screen. If not, lock it. */ -static void -lock_if_possible (void) { - ensure_settings_client (); - - if (!g_settings_get_boolean (settings, LOCKDOWN_KEY_SCREENSAVER)) { - lock_screen(NULL, 0, NULL); - } - - return; -} - - -/* Starts a new generic session */ -static void -activate_new_session (DbusmenuMenuitem * mi, guint timestamp, gpointer user_data) -{ - lock_if_possible(); - - users_service_dbus_show_greeter (USERS_SERVICE_DBUS(user_data)); - - return; -} - -/* Activates a session for a particular user. */ -static void -activate_user_session (DbusmenuMenuitem *mi, guint timestamp, gpointer user_data) -{ - UserData *user = (UserData *)user_data; - UsersServiceDbus *service = user->service; - - lock_if_possible(); - - users_service_dbus_activate_user_session (service, user); -} - -/* Comparison function to look into the UserData struct - to compare by using the username value */ -static gint -compare_users_by_username (const gchar *a, - const gchar *b) -{ - UserData *user1 = (UserData *)a; - UserData *user2 = (UserData *)b; - - gint retval = g_strcmp0 (user1->real_name, user2->real_name); - - /* If they're the same, they're both in conflict. */ - if (retval == 0) { - user1->real_name_conflict = TRUE; - user2->real_name_conflict = TRUE; - } - - return retval; -} - -static void -activate_user_accounts (DbusmenuMenuitem *mi, - guint timestamp, - gpointer user_data) -{ - GError * error = NULL; - if (!g_spawn_command_line_async("gnome-control-center user-accounts", &error)) - { - g_warning("Unable to show control centre: %s", error->message); - g_error_free(error); - } -} - -/* Signal called when a user is added. It updates the count and - rebuilds the menu */ -static void -user_change (UsersServiceDbus *service, - const gchar *user_id, - gpointer user_data) -{ - g_return_if_fail (USER_IS_MENU_MGR (user_data)); - UserMenuMgr* user_mgr = USER_MENU_MGR(user_data); - user_menu_mgr_rebuild_items (user_mgr, FALSE); - return; -} - -/* Ensures that we have a GConf client and if we build one - set up the signal handler. */ -static void -ensure_settings_client () -{ - if(!settings) { - settings = g_settings_new (LOCKDOWN_SCHEMA); - } - return; -} - -DbusmenuMenuitem* -user_mgr_get_root_item (UserMenuMgr* self) -{ - return self->root_item; -} - -/* Checks to see if we should show the guest suession item */ -static gboolean -is_this_guest_session (void) -{ - if (geteuid() < 500) { - /* System users shouldn't have guest account shown. Mostly - this would be the case of the guest user itself. */ - return TRUE; - } - - return FALSE; -} - -/* Called when someone clicks on the guest session item. */ -static void -activate_guest_session (DbusmenuMenuitem * mi, guint timestamp, gpointer user_data) -{ - g_return_if_fail (USER_IS_MENU_MGR (user_data)); - UserMenuMgr* user_mgr = USER_MENU_MGR(user_data); - UsersServiceDbus *service = user_mgr->users_dbus_interface; - - lock_if_possible(); - - if (users_service_dbus_activate_guest_session(service)) { - return; - } -} - - -/* - * Clean Entry Point - */ -UserMenuMgr* user_menu_mgr_new (SessionDbus* session_dbus, gboolean greeter_mode) -{ - UserMenuMgr* user_mgr = g_object_new (USER_TYPE_MENU_MGR, NULL); - user_mgr->session_dbus_interface = session_dbus; - user_menu_mgr_rebuild_items (user_mgr, greeter_mode); - return user_mgr; -} - - diff --git a/src/user-menu-mgr.h b/src/user-menu-mgr.h deleted file mode 100644 index 40f7b18..0000000 --- a/src/user-menu-mgr.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -Copyright 2011 Canonical Ltd. - -Authors: - Conor Curran <conor.curran@canonical.com> - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published -by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>. -*/ - - -#ifndef _USER_MENU_MGR_H_ -#define _USER_MENU_MGR_H_ - - -#include <glib-object.h> -#include <libdbusmenu-gtk/menuitem.h> - -#include "session-dbus.h" - -G_BEGIN_DECLS - -#define USER_TYPE_MENU_MGR (user_menu_mgr_get_type ()) -#define USER_MENU_MGR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), USER_TYPE_MENU_MGR, UserMenuMgr)) -#define USER_MENU_MGR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), USER_TYPE_MENU_MGR, UserMenuMgrClass)) -#define USER_IS_MENU_MGR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), USER_TYPE_MENU_MGR)) -#define USER_IS_MENU_MGR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), USER_TYPE_MENU_MGR)) -#define USER_MENU_MGR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), USER_TYPE_MENU_MGR, UserMenuMgrClass)) - -typedef struct _UserMenuMgrClass UserMenuMgrClass; -typedef struct _UserMenuMgr UserMenuMgr; - -struct _UserMenuMgrClass -{ - GObjectClass parent_class; -}; - -GType user_menu_mgr_get_type (void) G_GNUC_CONST; -UserMenuMgr* user_menu_mgr_new (SessionDbus* session_dbus, - gboolean greeter_mode); - -DbusmenuMenuitem* user_mgr_get_root_item (UserMenuMgr* self); -G_END_DECLS - -#endif /* _USER_MENU_MGR_H_ */ diff --git a/src/user-widget.c b/src/user-widget.c index 33b9e40..b0d2dd4 100644 --- a/src/user-widget.c +++ b/src/user-widget.c @@ -4,31 +4,31 @@ Copyright 2011 Canonical Ltd. Authors: Conor Curran <conor.curran@canonical.com> Mirco Müller <mirco.mueller@canonical.com> - -This program is free software: you can redistribute it and/or modify it -under the terms of the GNU General Public License version 3, as published + Charles Kerr <charles.kerr@canonical.com> + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. -This program is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranties of -MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, 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 +You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <glib/gi18n.h> #include <gtk/gtk.h> -#include <glib.h> -#include <math.h> + #include <libindicator/indicator-image-helper.h> + +#include "shared-names.h" #include "user-widget.h" -#include "dbus-shared-names.h" typedef struct _UserWidgetPrivate UserWidgetPrivate; @@ -37,7 +37,6 @@ struct _UserWidgetPrivate { DbusmenuMenuitem* twin_item; GtkWidget* user_image; - gboolean using_personal_icon; GtkWidget* user_name; GtkWidget* container; GtkWidget* tick_icon; @@ -47,13 +46,6 @@ struct _UserWidgetPrivate #define USER_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), USER_WIDGET_TYPE, UserWidgetPrivate)) -typedef struct -{ - double r; - double g; - double b; -} CairoColorRGB; - /* Prototypes */ static void user_widget_class_init (UserWidgetClass *klass); static void user_widget_init (UserWidget *self); @@ -62,50 +54,18 @@ static void user_widget_finalize (GObject *object); static void user_widget_set_twin_item (UserWidget* self, DbusmenuMenuitem* twin_item); -// keyevent consumers -static gboolean user_widget_button_release_event (GtkWidget *menuitem, - GdkEventButton *event); -// Dbusmenuitem properties update callback -static void user_widget_property_update (DbusmenuMenuitem* item, - gchar* property, - GVariant* value, - gpointer userdata); - - -static void _color_shade (const CairoColorRGB *a, - float k, - CairoColorRGB *b); - -static void draw_album_border (GtkWidget *widget, gboolean selected); - -#if GTK_CHECK_VERSION(3, 0, 0) + static gboolean user_widget_primitive_draw_cb_gtk_3 (GtkWidget *image, cairo_t* cr, gpointer user_data); -static gboolean user_widget_draw_usericon_gtk_3 (GtkWidget *widget, - cairo_t* cr, - gpointer user_data); - -#else -static gboolean user_widget_primitive_draw_cb (GtkWidget *image, - GdkEventExpose *event, - gpointer user_data); -static gboolean user_widget_draw_usericon_gtk_2 (GtkWidget *widget, - GdkEventExpose *event, - gpointer user_data); - -#endif G_DEFINE_TYPE (UserWidget, user_widget, GTK_TYPE_MENU_ITEM); static void user_widget_class_init (UserWidgetClass *klass) { - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + GObjectClass * gobject_class = G_OBJECT_CLASS (klass); - widget_class->button_release_event = user_widget_button_release_event; - g_type_class_add_private (klass, sizeof (UserWidgetPrivate)); gobject_class->dispose = user_widget_dispose; @@ -115,79 +75,57 @@ user_widget_class_init (UserWidgetClass *klass) static void user_widget_init (UserWidget *self) { - UserWidgetPrivate * priv = USER_WIDGET_GET_PRIVATE(self); - - gint padding = 0; - gtk_widget_style_get (GTK_WIDGET(self), - "horizontal-padding", - &padding, - NULL); - + self->priv = USER_WIDGET_GET_PRIVATE(self); + + UserWidgetPrivate * priv = self->priv; + priv->user_image = NULL; priv->user_name = NULL; priv->logged_in = FALSE; priv->sessions_active = FALSE; priv->container = NULL; priv->tick_icon = NULL; - - // Create the UI elements. + + // Create the UI elements. priv->user_image = gtk_image_new (); - gtk_misc_set_alignment(GTK_MISC(priv->user_image), 0.0, 0.0); + gtk_misc_set_alignment(GTK_MISC(priv->user_image), 0.0, 0.0); gtk_misc_set_padding (GTK_MISC(priv->user_image),0, 4.0); - + priv->user_name = gtk_label_new (""); -#if HAVE_GTK3 - priv->container = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); -#else - priv->container = gtk_hbox_new (FALSE, 0); -#endif + priv->container = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 4); - priv->tick_icon = gtk_image_new_from_icon_name ("account-logged-in", + priv->tick_icon = gtk_image_new_from_icon_name ("account-logged-in", GTK_ICON_SIZE_MENU); - gtk_misc_set_alignment(GTK_MISC(priv->tick_icon), 1.0, 0.5); - + gtk_misc_set_alignment(GTK_MISC(priv->tick_icon), 1.0, 0.5); + // Pack it together gtk_box_pack_start (GTK_BOX (priv->container), priv->user_image, FALSE, FALSE, - 0); + 0); gtk_box_pack_start (GTK_BOX (priv->container), priv->user_name, FALSE, FALSE, - 3); - gtk_box_pack_start (GTK_BOX(priv->container), - priv->tick_icon, - FALSE, - FALSE, 5); - - gtk_widget_show_all (priv->container); - gtk_container_add (GTK_CONTAINER (self), priv->container); + 3); + gtk_box_pack_end (GTK_BOX(priv->container), + priv->tick_icon, + FALSE, + FALSE, 5); + + gtk_widget_show_all (priv->container); + gtk_container_add (GTK_CONTAINER (self), priv->container); gtk_widget_show_all (priv->tick_icon); gtk_widget_set_no_show_all (priv->tick_icon, TRUE); gtk_widget_hide (priv->tick_icon); - - + + // Fetch the drawing context. - #if GTK_CHECK_VERSION(3, 0, 0) - g_signal_connect_after (GTK_WIDGET(self), "draw", + g_signal_connect_after (GTK_WIDGET(self), "draw", G_CALLBACK(user_widget_primitive_draw_cb_gtk_3), GTK_WIDGET(self)); - - g_signal_connect_after (GTK_WIDGET(priv->user_image), "draw", - G_CALLBACK(user_widget_draw_usericon_gtk_3), - GTK_WIDGET(self)); - - #else - g_signal_connect_after (GTK_WIDGET(self), "expose-event", - G_CALLBACK(user_widget_primitive_draw_cb), - GTK_WIDGET(self)); - g_signal_connect_after (GTK_WIDGET(priv->user_image), "expose-event", - G_CALLBACK(user_widget_draw_usericon_gtk_2), - GTK_WIDGET(self)); - #endif } static void @@ -206,519 +144,145 @@ user_widget_finalize (GObject *object) /*****************************************************************/ -#if GTK_CHECK_VERSION(3, 0, 0) - // TODO handle drawing of green check mark static gboolean user_widget_primitive_draw_cb_gtk_3 (GtkWidget *widget, cairo_t* cr, gpointer user_data) { - g_return_val_if_fail(IS_USER_WIDGET(user_data), FALSE); UserWidget* meta = USER_WIDGET(user_data); - UserWidgetPrivate * priv = USER_WIDGET_GET_PRIVATE(meta); + UserWidgetPrivate * priv = USER_WIDGET_GET_PRIVATE(meta); // Draw dot only when user is the current user. - if (!dbusmenu_menuitem_property_get_bool (priv->twin_item, - USER_ITEM_PROP_IS_CURRENT_USER)){ - return FALSE; - } - - GtkStyle *style; - gdouble x, y; - style = gtk_widget_get_style (widget); - - GtkAllocation allocation; - gtk_widget_get_allocation (widget, &allocation); - x = allocation.x + 13; - y = allocation.height / 2; - - cairo_arc (cr, x, y, 3.0, 0.0, 2 * G_PI);; - - cairo_set_source_rgb (cr, style->fg[gtk_widget_get_state(widget)].red/65535.0, - style->fg[gtk_widget_get_state(widget)].green/65535.0, - style->fg[gtk_widget_get_state(widget)].blue/65535.0); - cairo_fill (cr); - - return FALSE; -} - -static gboolean -user_widget_draw_usericon_gtk_3 (GtkWidget *widget, - cairo_t* cr, - gpointer user_data) -{ - g_return_val_if_fail(IS_USER_WIDGET(user_data), FALSE); - UserWidget* meta = USER_WIDGET(user_data); - UserWidgetPrivate * priv = USER_WIDGET_GET_PRIVATE(meta); + if (dbusmenu_menuitem_property_get_bool (priv->twin_item, USER_ITEM_PROP_IS_CURRENT_USER)) + { + gdouble x, y; + GtkStyle * style = gtk_widget_get_style (widget); + + GtkAllocation allocation; + gtk_widget_get_allocation (widget, &allocation); + x = allocation.x + 13; + y = allocation.height / 2; + + cairo_arc (cr, x, y, 3.0, 0.0, 2 * G_PI); + + cairo_set_source_rgb (cr, style->fg[gtk_widget_get_state(widget)].red/65535.0, + style->fg[gtk_widget_get_state(widget)].green/65535.0, + style->fg[gtk_widget_get_state(widget)].blue/65535.0); + cairo_fill (cr); + } - if (priv->using_personal_icon == FALSE) - return FALSE; - - draw_album_border (widget, FALSE); return FALSE; } -/** - * TODO: - * Sort out gtk2 - */ -// GTK 2 Expose handler -#else -static gboolean -user_widget_draw_usericon_gtk_2 (GtkWidget *widget, - GdkEventExpose *event, - gpointer user_data) -{ - g_return_val_if_fail(IS_USER_WIDGET(user_data), FALSE); - UserWidget* meta = USER_WIDGET(user_data); - UserWidgetPrivate * priv = USER_WIDGET_GET_PRIVATE(meta); +/*** +**** +***/ - if (priv->using_personal_icon == FALSE) - return FALSE; - - draw_album_border (widget, FALSE); - return FALSE; -} +static const int ICON_SIZE = 24; -static gboolean -user_widget_primitive_draw_cb (GtkWidget *widget, - GdkEventExpose *event, - gpointer user_data) +static void +update_icon (UserWidget * self, DbusmenuMenuitem * mi) { - g_return_val_if_fail(IS_USER_WIDGET(user_data), FALSE); - UserWidget* meta = USER_WIDGET(user_data); - UserWidgetPrivate * priv = USER_WIDGET_GET_PRIVATE(meta); + GdkPixbuf * pixbuf = NULL; + + /* first, try the menuitem's icon property */ + const gchar * icon_name = dbusmenu_menuitem_property_get (mi, USER_ITEM_PROP_ICON); + if (icon_name) + { + GError* error = NULL; + pixbuf = gdk_pixbuf_new_from_file_at_size (icon_name, ICON_SIZE, ICON_SIZE, &error); + if (error != NULL) + { + g_warning ("Couldn't load the image \"%s\": %s", icon_name, error->message); + g_clear_error (&error); + } + } - // Draw dot only when user is the current user. - if (!dbusmenu_menuitem_property_get_bool (priv->twin_item, - USER_ITEM_PROP_IS_CURRENT_USER)){ - return FALSE; - } - - GtkStyle *style; - cairo_t *cr; - cr = (cairo_t*) gdk_cairo_create (gtk_widget_get_window (widget)); - - gdouble x, y; - style = gtk_widget_get_style (widget); - - GtkAllocation allocation; - - gtk_widget_get_allocation (widget, &allocation); - x = allocation.x + 13; - y = allocation.y + allocation.height/2; - - cairo_arc (cr, x, y, 3.0, 0.0, 2 * G_PI);; - - cairo_set_source_rgb (cr, style->fg[gtk_widget_get_state(widget)].red/65535.0, - style->fg[gtk_widget_get_state(widget)].green/65535.0, - style->fg[gtk_widget_get_state(widget)].blue/65535.0); - cairo_fill (cr); - cairo_destroy (cr); - - return FALSE; -} -#endif + /* as a fallback, try to use the default user icon */ + if (pixbuf == NULL) + { + pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), + USER_ITEM_ICON_DEFAULT, + ICON_SIZE, + GTK_ICON_LOOKUP_FORCE_SIZE, + NULL); + } + if (pixbuf != NULL) + { + gtk_image_set_from_pixbuf (GTK_IMAGE(self->priv->user_image), pixbuf); + g_object_unref (pixbuf); + } +} static void -draw_album_border(GtkWidget *widg, gboolean selected) +update_logged_in (UserWidget * self, DbusmenuMenuitem * mi) { - cairo_t *cr; - cr = gdk_cairo_create (gtk_widget_get_window (widg)); - #if GTK_CHECK_VERSION(3, 0, 0) - gtk_style_context_add_class (gtk_widget_get_style_context (widg), - "menu"); - #endif - - GtkStyle *style; - style = gtk_widget_get_style (widg); - - GtkAllocation alloc; - gtk_widget_get_allocation (widg, &alloc); - gint offset = 0; - gint v_offset = 4; - - alloc.width = alloc.width + (offset * 2); - alloc.height = alloc.height - v_offset - 2; - alloc.x = alloc.x - offset; - alloc.y = alloc.y + v_offset/2 +1; - - CairoColorRGB bg_normal, fg_normal; - - bg_normal.r = style->bg[0].red/65535.0; - bg_normal.g = style->bg[0].green/65535.0; - bg_normal.b = style->bg[0].blue/65535.0; - - gint state = selected ? 5 : 0; - - fg_normal.r = style->fg[state].red/65535.0; - fg_normal.g = style->fg[state].green/65535.0; - fg_normal.b = style->fg[state].blue/65535.0; - - CairoColorRGB dark_top_color; - CairoColorRGB light_bottom_color; - CairoColorRGB background_color; - - _color_shade ( &bg_normal, 0.93, &background_color ); - _color_shade ( &bg_normal, 0.23, &dark_top_color ); - _color_shade ( &fg_normal, 0.55, &light_bottom_color ); - - cairo_rectangle (cr, - alloc.x, alloc.y, - alloc.width, alloc.height); - - cairo_set_line_width (cr, 1.0); - - cairo_clip ( cr ); - - cairo_move_to (cr, alloc.x, alloc.y ); - cairo_line_to (cr, alloc.x + alloc.width, - alloc.y ); - cairo_line_to ( cr, alloc.x + alloc.width, - alloc.y + alloc.height ); - cairo_line_to ( cr, alloc.x, alloc.y + alloc.height ); - cairo_line_to ( cr, alloc.x, alloc.y); - cairo_close_path (cr); - - cairo_set_source_rgba ( cr, - background_color.r, - background_color.g, - background_color.b, - 1.0 ); - - cairo_stroke ( cr ); - - cairo_move_to (cr, alloc.x, alloc.y ); - cairo_line_to (cr, alloc.x + alloc.width, - alloc.y ); - - cairo_close_path (cr); - cairo_set_source_rgba ( cr, - dark_top_color.r, - dark_top_color.g, - dark_top_color.b, - 1.0 ); - - cairo_stroke ( cr ); - - cairo_move_to ( cr, alloc.x + alloc.width, - alloc.y + alloc.height ); - cairo_line_to ( cr, alloc.x, alloc.y + alloc.height ); - - cairo_close_path (cr); - cairo_set_source_rgba ( cr, - light_bottom_color.r, - light_bottom_color.g, - light_bottom_color.b, - 1.0); - - cairo_stroke ( cr ); - cairo_destroy (cr); + const gboolean b = dbusmenu_menuitem_property_get_bool (mi, USER_ITEM_PROP_LOGGED_IN); + + g_debug ("User \"%s\" %s active sessions", + dbusmenu_menuitem_property_get (mi, USER_ITEM_PROP_NAME), + b ? "has" : "doesn't have"); + + gtk_widget_set_visible (self->priv->tick_icon, b); } static void -_color_rgb_to_hls (gdouble *r, - gdouble *g, - gdouble *b) +update_name (UserWidget * self, DbusmenuMenuitem * mi) { - gdouble min; - gdouble max; - gdouble red; - gdouble green; - gdouble blue; - gdouble h = 0; - gdouble l; - gdouble s; - gdouble delta; - - red = *r; - green = *g; - blue = *b; - - if (red > green) - { - if (red > blue) - max = red; - else - max = blue; - - if (green < blue) - min = green; - else - min = blue; - } - else - { - if (green > blue) - max = green; - else - max = blue; - - if (red < blue) - min = red; - else - min = blue; - } - l = (max+min)/2; - if (fabs (max-min) < 0.0001) - { - h = 0; - s = 0; - } - else - { - if (l <= 0.5) - s = (max-min)/(max+min); - else - s = (max-min)/(2-max-min); - - delta = (max -min) != 0 ? (max -min) : 1; - - if(delta == 0) - delta = 1; - if (red == max) - h = (green-blue)/delta; - else if (green == max) - h = 2+(blue-red)/delta; - else if (blue == max) - h = 4+(red-green)/delta; - - h *= 60; - if (h < 0.0) - h += 360; - } - - *r = h; - *g = l; - *b = s; + gtk_label_set_label (GTK_LABEL(self->priv->user_name), + dbusmenu_menuitem_property_get (mi, USER_ITEM_PROP_NAME)); } static void -_color_hls_to_rgb (gdouble *h, - gdouble *l, - gdouble *s) +user_widget_property_update (DbusmenuMenuitem * mi, + const gchar * property, + GVariant * value, + UserWidget * self) { - gdouble hue; - gdouble lightness; - gdouble saturation; - gdouble m1, m2; - gdouble r, g, b; + g_return_if_fail (IS_USER_WIDGET (self)); - lightness = *l; - saturation = *s; - - if (lightness <= 0.5) - m2 = lightness*(1+saturation); - else - m2 = lightness+saturation-lightness*saturation; - - m1 = 2*lightness-m2; - - if (saturation == 0) - { - *h = lightness; - *l = lightness; - *s = lightness; - } + if (!g_strcmp0 (property, USER_ITEM_PROP_LOGGED_IN)) + { + update_logged_in (self, mi); + } + else if (!g_strcmp0 (property, USER_ITEM_PROP_ICON)) + { + update_icon (self, mi); + } + else if (!g_strcmp0 (property, USER_ITEM_PROP_NAME)) + { + update_name (self, mi); + } else - { - hue = *h+120; - while (hue > 360) - hue -= 360; - while (hue < 0) - hue += 360; - - if (hue < 60) - r = m1+(m2-m1)*hue/60; - else if (hue < 180) - r = m2; - else if (hue < 240) - r = m1+(m2-m1)*(240-hue)/60; - else - r = m1; - - hue = *h; - while (hue > 360) - hue -= 360; - while (hue < 0) - hue += 360; - - if (hue < 60) - g = m1+(m2-m1)*hue/60; - else if (hue < 180) - g = m2; - else if (hue < 240) - g = m1+(m2-m1)*(240-hue)/60; - else - g = m1; - - hue = *h-120; - while (hue > 360) - hue -= 360; - while (hue < 0) - hue += 360; - - if (hue < 60) - b = m1+(m2-m1)*hue/60; - else if (hue < 180) - b = m2; - else if (hue < 240) - b = m1+(m2-m1)*(240-hue)/60; - else - b = m1; - - *h = r; - *l = g; - *s = b; - } -} - -void -_color_shade (const CairoColorRGB *a, float k, CairoColorRGB *b) -{ - double red; - double green; - double blue; - - red = a->r; - green = a->g; - blue = a->b; - - if (k == 1.0) - { - b->r = red; - b->g = green; - b->b = blue; - return; - } - - _color_rgb_to_hls (&red, &green, &blue); - - green *= k; - if (green > 1.0) - green = 1.0; - else if (green < 0.0) - green = 0.0; - - blue *= k; - if (blue > 1.0) - blue = 1.0; - else if (blue < 0.0) - blue = 0.0; - - _color_hls_to_rgb (&red, &green, &blue); - - b->r = red; - b->g = green; - b->b = blue; -} - - -/*****************************************************************/ - -/* Suppress/consume keyevents */ -static gboolean -user_widget_button_release_event (GtkWidget *menuitem, - GdkEventButton *event) -{ - return FALSE; + { + g_debug ("%s FIXME: unhandled property change %s", G_STRFUNC, property); + } } - -/** - * TODO, be sensitive to UI updates - * */ -static void -user_widget_property_update (DbusmenuMenuitem* item, gchar* property, - GVariant* value, gpointer userdata) +static void +user_widget_set_twin_item (UserWidget * self, DbusmenuMenuitem * mi) { - g_return_if_fail (IS_USER_WIDGET (userdata)); - //gtk_widget_queue_redraw (GTK_WIDGET(userdata)); -} - + self->priv->twin_item = mi; + update_icon (self, mi); + update_name (self, mi); + update_logged_in (self, mi); - -static void -user_widget_set_twin_item (UserWidget* self, - DbusmenuMenuitem* twin_item) -{ - UserWidgetPrivate* priv = USER_WIDGET_GET_PRIVATE(self); - priv->twin_item = twin_item; - g_signal_connect( G_OBJECT(priv->twin_item), "property-changed", + g_signal_connect (G_OBJECT(mi), "property-changed", G_CALLBACK(user_widget_property_update), self); - - const gchar * icon_name = dbusmenu_menuitem_property_get (twin_item, - USER_ITEM_PROP_ICON); - gtk_label_set_label (GTK_LABEL (priv->user_name), - dbusmenu_menuitem_property_get (twin_item, USER_ITEM_PROP_NAME)); - - if (dbusmenu_menuitem_property_get_bool (twin_item, USER_ITEM_PROP_LOGGED_IN)) { - g_debug ("%s USER HAS ACTIVE SESSIONS", - dbusmenu_menuitem_property_get (twin_item, USER_ITEM_PROP_NAME)); - gtk_widget_show(priv->tick_icon); - } - else { - g_debug ("%s USER DOESN'T HAVE ACTIVE SESSIONS", - dbusmenu_menuitem_property_get (twin_item, USER_ITEM_PROP_NAME)); - gtk_widget_hide(priv->tick_icon); - } - - GdkPixbuf* pixbuf = NULL; - GError* error = NULL; - pixbuf = gdk_pixbuf_new_from_file_at_size(icon_name, 32, 32, NULL); - - if (pixbuf == NULL || error != NULL) { - g_warning ("Could not load the user image (%s) for some reason", - icon_name); - if (pixbuf != NULL){ - g_object_unref (pixbuf); - pixbuf = NULL; - } - if (error != NULL){ - g_error_free (error); - error = NULL; - } - - priv->using_personal_icon = FALSE; - - pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (), - USER_ITEM_ICON_DEFAULT, - 32, - GTK_ICON_LOOKUP_FORCE_SIZE, - &error); - } - else{ - priv->using_personal_icon = TRUE; - } - - if (pixbuf == NULL || error != NULL) { - g_warning ("Could not load the user image"); - if (error != NULL){ - g_error_free (error); - error = NULL; - } - } - else{ - gtk_image_set_from_pixbuf (GTK_IMAGE(priv->user_image), pixbuf); - } - if (pixbuf != NULL){ - g_object_unref (pixbuf); - pixbuf = NULL; - } } /** - * transport_new: - * @returns: a new #UserWidget. - **/ -GtkWidget* -user_widget_new(DbusmenuMenuitem *item) + * user_widget_new: + * @returns: a new #UserWidget. + **/ +GtkWidget* +user_widget_new (DbusmenuMenuitem *item) { GtkWidget* widget = g_object_new(USER_WIDGET_TYPE, NULL); user_widget_set_twin_item ( USER_WIDGET(widget), item ); - return widget; + return widget; } diff --git a/src/user-widget.h b/src/user-widget.h index 52a5e34..0953e6c 100644 --- a/src/user-widget.h +++ b/src/user-widget.h @@ -31,18 +31,23 @@ G_BEGIN_DECLS #define IS_USER_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), USER_WIDGET_TYPE)) #define USER_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), USER_WIDGET_TYPE, UserWidgetClass)) -typedef struct _UserWidget UserWidget; -typedef struct _UserWidgetClass UserWidgetClass; +typedef struct _UserWidget UserWidget; +typedef struct _UserWidgetClass UserWidgetClass; +typedef struct _UserWidgetPrivate UserWidgetPrivate; -struct _UserWidgetClass { +struct _UserWidgetClass +{ GtkMenuItemClass parent_class; }; -struct _UserWidget { +struct _UserWidget +{ + /*< private >*/ GtkMenuItem parent; + UserWidgetPrivate * priv; }; -GType user_widget_get_type (void); +GType user_widget_get_type (void) G_GNUC_CONST; GtkWidget* user_widget_new(DbusmenuMenuitem *twin_item); G_END_DECLS diff --git a/src/users-service-dbus.c b/src/users-service-dbus.c index 09f916d..fec17dc 100644 --- a/src/users-service-dbus.c +++ b/src/users-service-dbus.c @@ -4,6 +4,7 @@ * * Authors: * Cody Russell <crussell@canonical.com> + * Charles Kerr <charles.kerr@canonical.com> * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published @@ -19,101 +20,134 @@ */ #ifdef HAVE_CONFIG_H -#include "config.h" + #include "config.h" #endif -#include <string.h> +#include <glib.h> + #include <errno.h> -#include <pwd.h> -#include <dbus/dbus-glib.h> -#include <dbus/dbus-glib.h> -#include <dbus/dbus-glib-lowlevel.h> +#include <pwd.h> /* getpwuid() */ -#include "dbus-shared-names.h" -#include "display-manager-client.h" +#include "dbus-accounts.h" +#include "dbus-consolekit-manager.h" +#include "dbus-consolekit-seat.h" +#include "dbus-consolekit-session.h" +#include "dbus-display-manager.h" +#include "dbus-user.h" +#include "shared-names.h" #include "users-service-dbus.h" -#include "accounts-service-client.h" -#include "consolekit-manager-client.h" -#include "consolekit-session-client.h" -#include "consolekit-seat-client.h" #define CK_ADDR "org.freedesktop.ConsoleKit" #define CK_SESSION_IFACE "org.freedesktop.ConsoleKit.Session" +/** +*** +**/ + +static void update_user_list (UsersServiceDbus * self); + +static gchar* get_seat (UsersServiceDbus * service); + +static void on_user_added (Accounts * o, + const gchar * user_object_path, + UsersServiceDbus * service); + +static void on_user_deleted (Accounts * o, + const gchar * user_object_path, + UsersServiceDbus * service); -static void users_service_dbus_class_init (UsersServiceDbusClass *klass); -static void users_service_dbus_init (UsersServiceDbus *self); -static void users_service_dbus_dispose (GObject *object); -static void users_service_dbus_finalize (GObject *object); -static void create_display_manager_proxy (UsersServiceDbus *self); -static void create_accounts_service_proxy (UsersServiceDbus *self); -static void create_seat_proxy (UsersServiceDbus *self); -static void create_ck_proxy (UsersServiceDbus *self); -static void create_cksession_proxy (UsersServiceDbus *self); -static gchar *get_seat (UsersServiceDbus *service); -static void user_added (DBusGProxy *proxy, - const gchar *user_id, - gpointer user_data); -static void user_deleted (DBusGProxy *proxy, - const gchar *user_id, - gpointer user_data); -static void user_changed (DBusGProxy *proxy, - gpointer user_data); -static void seat_proxy_session_added (DBusGProxy *seat_proxy, - const gchar *session_id, - UsersServiceDbus *service); -static void seat_proxy_session_removed (DBusGProxy *seat_proxy, - const gchar *session_id, - UsersServiceDbus *service); -static void sync_users (UsersServiceDbus *self); -static gboolean do_add_session (UsersServiceDbus *service, - UserData *user, - const gchar *ssid); -static gchar * get_seat_internal (DBusGProxy *proxy); - -/* Private */ -typedef struct _UsersServiceDbusPrivate UsersServiceDbusPrivate; +static void on_session_added (ConsoleKitSeat * seat, + const gchar * ssid, + UsersServiceDbus * service); + +static void on_session_removed (ConsoleKitSeat * seat, + const gchar * ssid, + UsersServiceDbus * service); + +static void on_session_list (ConsoleKitSeat * seat, + GAsyncResult * result, + UsersServiceDbus * service); + +/*** +**** Priv Struct +***/ struct _UsersServiceDbusPrivate { - GHashTable *users; - gint count; - gchar *seat; - gchar *ssid; - - DBusGConnection *system_bus; + gchar * seat; + gchar * guest_ssid; - DBusGProxy *accounts_service_proxy; - DBusGProxy *display_manager_proxy; - DBusGProxy *display_manager_props_proxy; - DBusGProxy *ck_proxy; - DBusGProxy *seat_proxy; - DBusGProxy *session_proxy; + /* ssid -> AccountsUser lookup */ + GHashTable * sessions; - GHashTable *exclusions; - GHashTable *sessions; + /* user object path -> AccountsUser lookup */ + GHashTable * users; - DbusmenuMenuitem * guest_item; - gchar * guest_session_id; - gboolean guest_session_enabled; + GCancellable * cancellable; + ConsoleKitSeat * seat_proxy; + ConsoleKitManager * ck_manager_proxy; + Accounts * accounts_proxy; }; -#define USERS_SERVICE_DBUS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), USERS_SERVICE_DBUS_TYPE, UsersServiceDbusPrivate)) +/*** +**** GObject +***/ -/* Signals */ -enum { - USER_ADDED, - USER_DELETED, - LAST_SIGNAL +enum +{ + USER_LIST_CHANGED, + USER_LOGGED_IN_CHANGED, + GUEST_LOGGED_IN_CHANGED, + N_SIGNALS }; -static guint signals[LAST_SIGNAL] = { 0 }; +static guint signals[N_SIGNALS] = { 0 }; -/* GObject Boilerplate */ G_DEFINE_TYPE (UsersServiceDbus, users_service_dbus, G_TYPE_OBJECT); static void +users_service_dbus_dispose (GObject *object) +{ + UsersServiceDbusPrivate * priv = USERS_SERVICE_DBUS(object)->priv; + + g_clear_object (&priv->accounts_proxy); + g_clear_object (&priv->seat_proxy); + g_clear_object (&priv->ck_manager_proxy); + + if (priv->cancellable != NULL) + { + g_cancellable_cancel (priv->cancellable); + g_clear_object (&priv->cancellable); + } + + if (priv->users != NULL) + { + g_hash_table_destroy (priv->users); + priv->users = NULL; + } + + if (priv->sessions != NULL) + { + g_hash_table_destroy (priv->sessions); + priv->sessions = NULL; + } + + G_OBJECT_CLASS (users_service_dbus_parent_class)->dispose (object); +} + +static void +users_service_dbus_finalize (GObject *object) +{ + UsersServiceDbusPrivate * priv = USERS_SERVICE_DBUS(object)->priv; + + g_free (priv->guest_ssid); + g_free (priv->seat); + + G_OBJECT_CLASS (users_service_dbus_parent_class)->finalize (object); +} + +static void users_service_dbus_class_init (UsersServiceDbusClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); @@ -123,845 +157,866 @@ users_service_dbus_class_init (UsersServiceDbusClass *klass) object_class->dispose = users_service_dbus_dispose; object_class->finalize = users_service_dbus_finalize; - signals[USER_ADDED] = g_signal_new ("user-added", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (UsersServiceDbusClass, user_added), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); - - signals[USER_DELETED] = g_signal_new ("user-deleted", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (UsersServiceDbusClass, user_deleted), - NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); + signals[USER_LIST_CHANGED] = g_signal_new ( + "user-list-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (UsersServiceDbusClass, user_list_changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + signals[USER_LOGGED_IN_CHANGED] = g_signal_new ( + "user-logged-in-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (UsersServiceDbusClass, user_logged_in_changed), + NULL, NULL, + g_cclosure_marshal_VOID__OBJECT, + G_TYPE_NONE, 1, G_TYPE_OBJECT); + + signals[GUEST_LOGGED_IN_CHANGED] = g_signal_new ( + "guest-logged-in-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (UsersServiceDbusClass, guest_logged_in_changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); } static void users_service_dbus_init (UsersServiceDbus *self) { - GError *error = NULL; - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); + GError * error = NULL; - priv->users = NULL; - priv->count = 0; - priv->guest_item = NULL; - priv->guest_session_id = NULL; - - priv->guest_session_enabled = FALSE; + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + USERS_SERVICE_DBUS_TYPE, + UsersServiceDbusPrivate); - /* Get the system bus */ - priv->system_bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); + UsersServiceDbusPrivate * p = self->priv; + + p->cancellable = g_cancellable_new (); + + /* ssid -> AccountsUser */ + p->sessions = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + g_object_unref); + + /* user object path -> AccountsUser */ + p->users = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + g_object_unref); + + /** + *** create the consolekit manager proxy... + **/ + + p->ck_manager_proxy = console_kit_manager_proxy_new_for_bus_sync ( + G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.ConsoleKit", + "/org/freedesktop/ConsoleKit/Manager", + NULL, + &error); if (error != NULL) { - g_error ("Unable to get system bus"); - g_error_free(error); - - return; + g_warning ("%s: %s", G_STRLOC, error->message); + g_clear_error (&error); } - priv->sessions = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - g_free); + p->seat = get_seat (self); - priv->users = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - NULL); + /** + *** create the consolekit seat proxy... + **/ + + if (p->seat != NULL) + { + ConsoleKitSeat * proxy = console_kit_seat_proxy_new_for_bus_sync ( + G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.ConsoleKit", + p->seat, + NULL, + &error); - create_ck_proxy (self); - create_seat_proxy (self); - create_display_manager_proxy (self); - create_accounts_service_proxy (self); + if (error != NULL) + { + g_warning ("Failed to connect to the ConsoleKit seat: %s", error->message); + g_clear_error (&error); + } + else + { + g_signal_connect (proxy, "session-added", + G_CALLBACK (on_session_added), self); + g_signal_connect (proxy, "session-removed", + G_CALLBACK (on_session_removed), self); + console_kit_seat_call_get_sessions (proxy, p->cancellable, + (GAsyncReadyCallback)on_session_list, self); + p->seat_proxy = proxy; + } + } + + /** + *** create the accounts manager proxy... + **/ + + Accounts * proxy = accounts_proxy_new_for_bus_sync ( + G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.Accounts", + "/org/freedesktop/Accounts", + NULL, + &error); + if (error != NULL) + { + g_warning ("%s: %s", G_STRFUNC, error->message); + g_clear_error (&error); + } + else + { + g_signal_connect (proxy, "user-added", G_CALLBACK(on_user_added), self); + g_signal_connect (proxy, "user-deleted", G_CALLBACK(on_user_deleted), self); + p->accounts_proxy = proxy; + update_user_list (self); + } } +/*** +**** +***/ + static void -users_service_dbus_dispose (GObject *object) +emit_user_list_changed (UsersServiceDbus * self) { - G_OBJECT_CLASS (users_service_dbus_parent_class)->dispose (object); + g_signal_emit (self, signals[USER_LIST_CHANGED], 0); } static void -users_service_dbus_finalize (GObject *object) +emit_user_login_changed (UsersServiceDbus * self, AccountsUser * user) { - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (object); - - if (priv->guest_session_id != NULL) { - g_free(priv->guest_session_id); - priv->guest_session_id = NULL; - } - - G_OBJECT_CLASS (users_service_dbus_parent_class)->finalize (object); + g_signal_emit (self, signals[USER_LOGGED_IN_CHANGED], 0, user); } - static void -create_display_manager_proxy (UsersServiceDbus *self) -{ - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); - GError *error = NULL; - const gchar *seat = NULL; - - seat = g_getenv ("XDG_SEAT_PATH"); - g_debug ("CREATING DM PROXIES WITH %s", seat); - priv->display_manager_proxy = dbus_g_proxy_new_for_name (priv->system_bus, - "org.freedesktop.DisplayManager", - seat, - "org.freedesktop.DisplayManager.Seat"); - - priv->display_manager_props_proxy = dbus_g_proxy_new_for_name (priv->system_bus, - "org.freedesktop.DisplayManager", - seat, - "org.freedesktop.DBus.Properties"); - - - if (!priv->display_manager_proxy) - { - g_warning ("Failed to get DisplayManager seat proxy."); - return; - } - if (!priv->display_manager_props_proxy) - { - g_warning ("Failed to get DisplayManager Properties seat proxy."); - return; - } - - GValue has_guest_session = {0}; - g_value_init (&has_guest_session, G_TYPE_BOOLEAN); - if (!dbus_g_proxy_call (priv->display_manager_props_proxy, - "Get", - &error, - G_TYPE_STRING, - "org.freedesktop.DisplayManager.Seat", - G_TYPE_STRING, - "HasGuestAccount", - G_TYPE_INVALID, - G_TYPE_VALUE, - &has_guest_session, - G_TYPE_INVALID)) - { - g_warning ("Failed to get the HasGuestSession property from the DisplayManager Properties seat proxy. error: %s", error->message); - g_error_free (error); - return; - } - g_debug ("Does seat have a guest account = %i", g_value_get_boolean (&has_guest_session)); - priv->guest_session_enabled = g_value_get_boolean (&has_guest_session); +emit_guest_login_changed (UsersServiceDbus * self) +{ + g_signal_emit (self, signals[GUEST_LOGGED_IN_CHANGED], 0); } -static void -create_accounts_service_proxy (UsersServiceDbus *self) -{ - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); - GPtrArray *users = g_ptr_array_new (); - GError *error = NULL; - - priv->accounts_service_proxy = dbus_g_proxy_new_for_name (priv->system_bus, - "org.freedesktop.Accounts", - "/org/freedesktop/Accounts", - "org.freedesktop.Accounts"); - - dbus_g_proxy_add_signal (priv->accounts_service_proxy, - "UserAdded", - DBUS_TYPE_G_OBJECT_PATH, - G_TYPE_INVALID); - - dbus_g_proxy_add_signal (priv->accounts_service_proxy, - "UserChanged", - DBUS_TYPE_G_OBJECT_PATH, - G_TYPE_INVALID); - - dbus_g_proxy_add_signal (priv->accounts_service_proxy, - "UserDeleted", - DBUS_TYPE_G_OBJECT_PATH, - G_TYPE_INVALID); - - dbus_g_proxy_connect_signal (priv->accounts_service_proxy, - "UserAdded", - G_CALLBACK (user_added), - self, - NULL); - - dbus_g_proxy_connect_signal (priv->accounts_service_proxy, - "UserDeleted", - G_CALLBACK (user_deleted), - self, - NULL); - - if (!org_freedesktop_Accounts_list_cached_users (priv->accounts_service_proxy, - &users, - &error)) - { - g_warning ("failed to retrieve user count: %s", error->message); - g_error_free (error); +/*** +**** +***/ - return; +static ConsoleKitSession* +create_consolekit_session_proxy (const char * ssid) +{ + GError * error = NULL; + + ConsoleKitSession * p = console_kit_session_proxy_new_for_bus_sync ( + G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + CK_ADDR, + ssid, + NULL, + &error); + if (error != NULL) + { + g_warning ("%s: %s", G_STRLOC, error->message); + g_error_free (error); } - priv->count = users->len; - g_ptr_array_free (users, TRUE); - sync_users (self); + return p; } -static void -create_ck_proxy (UsersServiceDbus *self) +static gchar * +get_seat_from_session_proxy (ConsoleKitSession * session_proxy) { - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); + gchar * seat = NULL; - priv->ck_proxy = dbus_g_proxy_new_for_name (priv->system_bus, - "org.freedesktop.ConsoleKit", - "/org/freedesktop/ConsoleKit/Manager", - "org.freedesktop.ConsoleKit.Manager"); - - if (!priv->ck_proxy) + GError * error = NULL; + console_kit_session_call_get_seat_id_sync (session_proxy, + &seat, + NULL, + &error); + if (error != NULL) { - g_warning ("Failed to get ConsoleKit proxy."); - return; + g_debug ("%s: %s", G_STRLOC, error->message); + g_error_free (error); } + + return seat; } -/* Get the initial sessions when starting up */ -static void -get_cksessions_cb (DBusGProxy *proxy, GPtrArray * sessions, GError * error, gpointer userdata) +static gchar * +get_seat (UsersServiceDbus *service) { - if (error != NULL) { - g_warning("Unable to get initial sessions: %s", error->message); - return; - } + gchar * seat = NULL; + gchar * ssid = NULL; + GError * error = NULL; + UsersServiceDbusPrivate * priv = service->priv; - /* If there's no error we should at least get an - array of zero entries */ - g_return_if_fail(sessions != NULL); - g_debug("Got %d initial sessions", sessions->len); + console_kit_manager_call_get_current_session_sync (priv->ck_manager_proxy, + &ssid, + NULL, + &error); - int i; - for (i = 0; i < sessions->len; i++) { - seat_proxy_session_added(proxy, g_ptr_array_index(sessions, i), USERS_SERVICE_DBUS(userdata)); - } + if (error != NULL) + { + g_debug ("%s: %s", G_STRLOC, error->message); + g_error_free (error); + } + else + { + ConsoleKitSession * session = create_consolekit_session_proxy (ssid); + + if (session != NULL) + { + seat = get_seat_from_session_proxy (session); + g_object_unref (session); + } + } - return; + return seat; } -static void -create_seat_proxy (UsersServiceDbus *self) +/*** +**** AccountsUser add-ons for tracking sessions +***/ + +static GHashTable* +user_get_sessions_hashset (AccountsUser * user) { - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); - GError *error = NULL; + static GQuark q = 0; - priv->seat = get_seat (self); - if (priv->seat == NULL) + if (G_UNLIKELY(!q)) { - return; + q = g_quark_from_static_string ("sessions"); } - priv->seat_proxy = dbus_g_proxy_new_for_name_owner (priv->system_bus, - "org.freedesktop.ConsoleKit", - priv->seat, - "org.freedesktop.ConsoleKit.Seat", - &error); - - if (!priv->seat_proxy) + GObject * o = G_OBJECT (user); + GHashTable * h = g_object_get_qdata (o, q); + if (h == NULL) { - if (error != NULL) - { - g_warning ("Failed to connect to the ConsoleKit seat: %s", error->message); - g_error_free (error); - } - - return; + h = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + g_object_set_qdata_full (o, q, h, (GDestroyNotify)g_hash_table_destroy); } - dbus_g_proxy_add_signal (priv->seat_proxy, - "SessionAdded", - DBUS_TYPE_G_OBJECT_PATH, - G_TYPE_INVALID); - dbus_g_proxy_add_signal (priv->seat_proxy, - "SessionRemoved", - DBUS_TYPE_G_OBJECT_PATH, - G_TYPE_INVALID); + return h; +} - dbus_g_proxy_connect_signal (priv->seat_proxy, - "SessionAdded", - G_CALLBACK (seat_proxy_session_added), - self, - NULL); - dbus_g_proxy_connect_signal (priv->seat_proxy, - "SessionRemoved", - G_CALLBACK (seat_proxy_session_removed), - self, - NULL); +static void +user_add_session (AccountsUser * user, const char * ssid) +{ + g_hash_table_add (user_get_sessions_hashset(user), g_strdup(ssid)); +} - org_freedesktop_ConsoleKit_Seat_get_sessions_async (priv->seat_proxy, get_cksessions_cb, self); +static void +user_remove_session (AccountsUser * user, const char * ssid) +{ + g_hash_table_remove (user_get_sessions_hashset(user), ssid); +} - return; +static guint +user_count_sessions (AccountsUser * user) +{ + return g_hash_table_size (user_get_sessions_hashset(user)); } +/*** +**** Users +***/ + +/* adds this user session to the user's and service's session tables */ static void -create_cksession_proxy (UsersServiceDbus *service) +add_user_session (UsersServiceDbus * service, + AccountsUser * user, + const gchar * ssid) { - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); + ConsoleKitSession * session_proxy = create_consolekit_session_proxy (ssid); + if (session_proxy != NULL) + { + UsersServiceDbusPrivate * priv = service->priv; + gchar * seat = get_seat_from_session_proxy (session_proxy); - priv->session_proxy = dbus_g_proxy_new_for_name (priv->system_bus, - CK_ADDR, - priv->ssid, - CK_SESSION_IFACE); + /* is this session in our seat? */ + if (seat && priv->seat && !g_strcmp0 (seat, priv->seat)) + { + /* does this session have a display? */ + gchar * display = NULL; + console_kit_session_call_get_x11_display_sync (session_proxy, + &display, + NULL, NULL); + const gboolean has_display = display && *display; + g_free (display); + + if (has_display) + { + const gchar * username = accounts_user_get_user_name (user); + g_debug ("%s adding %s's session '%s' to our tables", + G_STRLOC, username, ssid); - if (!priv->session_proxy) - { - g_warning ("Failed to get ConsoleKit session proxy"); - return; + g_hash_table_insert (priv->sessions, + g_strdup (ssid), + g_object_ref (user)); + + user_add_session (user, ssid); + } + } + + g_free (seat); + g_object_unref (session_proxy); } } -static gchar * -get_seat (UsersServiceDbus *service) +/* calls add_user_session() for each of this user's sessions */ +static void +add_user_sessions (UsersServiceDbus *self, AccountsUser * user) { - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); - GError *error = NULL; - gchar *ssid = NULL; - gchar *seat; + const guint64 uid = accounts_user_get_uid (user); + const char * username = accounts_user_get_user_name (user); + g_debug ("%s adding %s (%i)", G_STRLOC, username, (int)uid); + + GError * error = NULL; + gchar ** sessions = NULL; + console_kit_manager_call_get_sessions_for_unix_user_sync ( + self->priv->ck_manager_proxy, + uid, + &sessions, + NULL, + &error); - if (!dbus_g_proxy_call (priv->ck_proxy, - "GetCurrentSession", - &error, - G_TYPE_INVALID, - DBUS_TYPE_G_OBJECT_PATH, - &ssid, - G_TYPE_INVALID)) + if (error != NULL) { - if (error) + g_debug ("%s: %s", G_STRLOC, error->message); + g_error_free (error); + } + else if (sessions != NULL) + { + int i; + + for (i=0; sessions[i]; i++) { - g_debug ("Failed to call GetCurrentSession: %s", error->message); - g_error_free (error); + const char * const ssid = sessions[i]; + g_debug ("%s adding %s's session %s", G_STRLOC, username, ssid); + add_user_session (self, user, ssid); } - if (ssid) - g_free (ssid); - - return NULL; + g_strfreev (sessions); } +} - priv->ssid = ssid; - create_cksession_proxy (service); - - seat = get_seat_internal (priv->session_proxy); - - return seat; +/* returns true if this property is one we use */ +static gboolean +is_interesting_user_property (const char * key) +{ + return !g_strcmp0 (key, "IconFile") + || !g_strcmp0 (key, "LoginFrequency") + || !g_strcmp0 (key, "RealName") + || !g_strcmp0 (key, "Uid") + || !g_strcmp0 (key, "UserName"); } -static gchar * -get_seat_internal (DBusGProxy *proxy) +static void +sync_user_properties (GDBusProxy * source, GDBusProxy * target) { - GError *error = NULL; - gchar *seat = NULL; + gchar ** keys = g_dbus_proxy_get_cached_property_names (source); - if (!org_freedesktop_ConsoleKit_Session_get_seat_id (proxy, &seat, &error)) + if (keys != NULL) { - if (error) + int i; + GVariantBuilder builder; + gboolean changed = FALSE; + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}")); + + for (i=0; keys[i]; i++) { - g_debug ("Failed to call GetSeatId: %s", error->message); + const gchar * const key = keys[i]; - return NULL; + if (is_interesting_user_property (key)) + { + GVariant * oldval = g_dbus_proxy_get_cached_property (target, key); + GVariant * newval = g_dbus_proxy_get_cached_property (source, key); + + /* all the properties we're interested in are + basic types safe for g_variant_compare()... */ + g_assert (g_variant_type_is_basic(g_variant_get_type(newval))); + + if (g_variant_compare (oldval, newval)) + { + changed = TRUE; + g_dbus_proxy_set_cached_property (target, key, newval); + g_variant_builder_add (&builder, "{sv}", key, newval); + } + + g_variant_unref (newval); + g_variant_unref (oldval); + } } - } - return seat; -} - -static gboolean -get_unix_user (UsersServiceDbus *service, - const gchar *session_id, - uid_t *uidp) -{ - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); - GError *error = NULL; - guint uid; - DBusGProxy *session_proxy; - - g_debug("Building session proxy for: %s", session_id); - session_proxy = dbus_g_proxy_new_for_name_owner(priv->system_bus, - CK_ADDR, - session_id, - CK_SESSION_IFACE, - &error); - - if (error != NULL) { - g_warning("Unable to get CK Session proxy: %s", error->message); - g_error_free(error); - return FALSE; - } - - if (!org_freedesktop_ConsoleKit_Session_get_unix_user(session_proxy, &uid, &error)) - { - if (error) + if (changed) { - g_warning ("Failed to call GetUnixUser: %s", error->message); - g_error_free (error); + g_signal_emit_by_name (target, "g-properties-changed", g_variant_builder_end(&builder), keys); } - g_object_unref(session_proxy); - return FALSE; + g_variant_builder_clear (&builder); + g_strfreev (keys); } +} - if (uidp != NULL) +/** + * The AccountsUserProxy's properties aren't being updated automatically + * for some reason... the only update we get is the 'changed' signal. + * This function is a workaround to update our User object's properties. + */ +static void +on_user_changed (AccountsUser * user, UsersServiceDbus * service) +{ + AccountsUser * tmp = accounts_user_proxy_new_for_bus_sync ( + G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.Accounts", + g_dbus_proxy_get_object_path (G_DBUS_PROXY(user)), + NULL, + NULL); + if (tmp != NULL) { - *uidp = (uid_t)uid; + sync_user_properties (G_DBUS_PROXY(tmp), G_DBUS_PROXY(user)); + g_object_unref (tmp); } - - g_object_unref(session_proxy); - return TRUE; } -static gboolean -do_add_session (UsersServiceDbus *service, - UserData *user, - const gchar *ssid) -{ - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); - GError *error = NULL; - gchar *seat = NULL; - gchar *xdisplay = NULL; - DBusGProxy * session_proxy; - GList *l; - - session_proxy = dbus_g_proxy_new_for_name_owner(priv->system_bus, - CK_ADDR, - ssid, - CK_SESSION_IFACE, - &error); - - if (error != NULL) { - g_warning("Unable to get CK Session proxy: %s", error->message); - g_error_free(error); - return FALSE; - } - - seat = get_seat_internal (session_proxy); - - if (!seat || !priv->seat || strcmp (seat, priv->seat) != 0) { - g_object_unref(session_proxy); - return FALSE; - } - - if (!org_freedesktop_ConsoleKit_Session_get_x11_display (session_proxy, &xdisplay, &error)) - { - if (error) - { - g_debug ("Failed to call GetX11Display: %s", error->message); - g_error_free (error); - } - - g_object_unref(session_proxy); - return FALSE; - } - - g_object_unref(session_proxy); - - if (!xdisplay || xdisplay[0] == '\0') - return FALSE; +static void +add_user_from_object_path (UsersServiceDbus * self, + const char * user_object_path) +{ + GError * error = NULL; - g_hash_table_insert (priv->sessions, - g_strdup (ssid), - g_strdup (user->user_name)); + AccountsUser * user = accounts_user_proxy_new_for_bus_sync ( + G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.Accounts", + user_object_path, + NULL, + &error); - l = g_list_find_custom (user->sessions, ssid, (GCompareFunc)g_strcmp0); - if (l == NULL) + if (error != NULL) { - g_debug ("Adding session %s", ssid); - - user->sessions = g_list_prepend (user->sessions, g_strdup (ssid)); - - if (user->menuitem != NULL) { - dbusmenu_menuitem_property_set_bool(user->menuitem, USER_ITEM_PROP_LOGGED_IN, TRUE); - } + g_warning ("%s: %s", G_STRLOC, error->message); + g_clear_error (&error); } else { - g_debug ("User %s already has session %s", user->user_name, ssid); - } + AccountsUser * prev = g_hash_table_lookup (self->priv->users, user_object_path); + + if (prev != NULL) /* we've already got this user... sync its properties */ + { + sync_user_properties (G_DBUS_PROXY(user), G_DBUS_PROXY(prev)); + g_object_unref (user); + user = prev; + } + else /* ooo, we got a new user */ + { + g_signal_connect (user, "changed", G_CALLBACK(on_user_changed), self); + g_hash_table_insert (self->priv->users, g_strdup(user_object_path), user); + } - return TRUE; + add_user_sessions (self, user); + } } + +/* asks org.freedesktop.Accounts for a list of users and + * calls add_user_from_object_path() on each of those users */ static void -add_sessions_for_user (UsersServiceDbus *self, - UserData *user) +update_user_list (UsersServiceDbus *self) { - g_return_if_fail (IS_USERS_SERVICE_DBUS(self)); + g_return_if_fail(IS_USERS_SERVICE_DBUS(self)); - g_debug ("!!!!!!!!!! - add_sessions_for_user %i %s", - (int)user->uid, user->user_name); + GError * error = NULL; + char ** object_paths = NULL; + UsersServiceDbusPrivate * priv = self->priv; - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); - GError *error; - GPtrArray *sessions; - int i; + accounts_call_list_cached_users_sync (priv->accounts_proxy, + &object_paths, + NULL, + &error); - error = NULL; - if (!org_freedesktop_ConsoleKit_Manager_get_sessions_for_unix_user(priv->ck_proxy, user->uid, &sessions, &error)) + if (error != NULL) { - g_debug ("Failed to call GetSessionsForUnixUser: %s", error->message); - g_error_free (error); - - return; + g_warning ("%s: %s", G_STRFUNC, error->message); + g_clear_error (&error); } - - for (i = 0; i < sessions->len; i++) + else if (object_paths != NULL) { - char *ssid; + gint i; - ssid = g_ptr_array_index (sessions, i); - do_add_session (self, user, ssid); + for (i=0; object_paths[i] != NULL; ++i) + { + add_user_from_object_path (self, object_paths[i]); + } + + emit_user_list_changed (self); + + g_strfreev (object_paths); } - g_ptr_array_foreach (sessions, (GFunc)g_free, NULL); - g_ptr_array_free (sessions, TRUE); + g_debug ("%s finished updating the user list", G_STRLOC); } +static void +on_user_added (Accounts * o G_GNUC_UNUSED, + const gchar * user_path G_GNUC_UNUSED, + UsersServiceDbus * service) +{ + /* We see a new user but we might not want to list it -- + for example, lightdm shows up when we switch to the greeter. + So instead of adding the user directly here, let's ask + org.freedesktop.Accounts for a fresh list of users + because it filters out special cases. */ + update_user_list (service); +} static void -seat_proxy_session_added (DBusGProxy *seat_proxy, - const gchar *session_id, - UsersServiceDbus *service) +on_user_deleted (Accounts * o G_GNUC_UNUSED, + const gchar * user_path, + UsersServiceDbus * service) { - g_return_if_fail(IS_USERS_SERVICE_DBUS(service)); - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); - uid_t uid; - struct passwd *pwent; - UserData *user; + AccountsUser * user = g_hash_table_lookup (service->priv->users, user_path); - if (!get_unix_user (service, session_id, &uid)) + if (user != NULL) { - g_warning ("Failed to lookup user for session"); - return; + GObject * o = g_object_ref (G_OBJECT(user)); + g_hash_table_remove (service->priv->users, user_path); + emit_user_list_changed (service); + g_object_unref (o); } +} - errno = 0; - pwent = getpwuid (uid); - if (!pwent) - { - g_warning ("Failed to lookup user id %d: %s", (int)uid, g_strerror (errno)); - return; - } +static AccountsUser * +find_user_from_username (UsersServiceDbus * self, + const gchar * username) +{ + AccountsUser * match = NULL; - /* We need to special case guest here because it doesn't - show up in the GDM user tables. */ - if (g_strcmp0("guest", pwent->pw_name) == 0) { - if (priv->guest_item != NULL) { - dbusmenu_menuitem_property_set_bool(priv->guest_item, USER_ITEM_PROP_LOGGED_IN, TRUE); - } - priv->guest_session_id = g_strdup(session_id); - g_debug("Found guest session: %s", priv->guest_session_id); - return; - } + g_return_val_if_fail (IS_USERS_SERVICE_DBUS(self), match); - user = users_service_dbus_get_user_by_username (service, pwent->pw_name); - if (!user) - return; + gpointer user; + GHashTableIter iter; + g_hash_table_iter_init (&iter, self->priv->users); + while (!match && g_hash_table_iter_next (&iter, NULL, &user)) + { + if (!g_strcmp0 (username, accounts_user_get_user_name (user))) + { + match = user; + } + } - do_add_session (service, user, session_id); + return match; } +/*** +**** Sessions +***/ + static void -seat_proxy_session_removed (DBusGProxy *seat_proxy, - const gchar *session_id, - UsersServiceDbus *service) -{ - g_return_if_fail(IS_USERS_SERVICE_DBUS(service)); - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); - UserData *user; - gchar *username; - GList *l; - - username = g_hash_table_lookup (priv->sessions, session_id); - if (!username) { - if (g_strcmp0(session_id, priv->guest_session_id) == 0) { - g_debug("Removing guest session: %s", priv->guest_session_id); - if (priv->guest_item != NULL) { - dbusmenu_menuitem_property_set_bool(priv->guest_item, USER_ITEM_PROP_LOGGED_IN, FALSE); - } - g_free(priv->guest_session_id); - priv->guest_session_id = NULL; - } - return; - } - - user = users_service_dbus_get_user_by_username (service, username); - if (!user) - return; - - l = g_list_find_custom (user->sessions, - session_id, - (GCompareFunc)g_strcmp0); - if (l) - { - g_debug ("Removing session %s", session_id); - - g_free (l->data); - user->sessions = g_list_delete_link (user->sessions, l); - if (user->menuitem != NULL && user->sessions == NULL) { - dbusmenu_menuitem_property_set_bool(user->menuitem, USER_ITEM_PROP_LOGGED_IN, FALSE); - } +on_session_removed (ConsoleKitSeat * seat_proxy, + const gchar * ssid, + UsersServiceDbus * service) +{ + g_return_if_fail (IS_USERS_SERVICE_DBUS (service)); + + UsersServiceDbusPrivate * priv = service->priv; + g_debug ("%s %s() session removed %s", G_STRLOC, G_STRFUNC, ssid); + + if (!g_strcmp0 (ssid, priv->guest_ssid)) + { + g_debug ("%s removing guest session %s", G_STRLOC, ssid); + g_clear_pointer (&priv->guest_ssid, g_free); + emit_guest_login_changed (service); } else { - g_debug ("Session not found: %s", session_id); + AccountsUser * user = g_hash_table_lookup (priv->sessions, ssid); + if (user == NULL) + { + g_debug ("%s we're not tracking ssid %s", G_STRLOC, ssid); + } + else + { + GObject * o = g_object_ref (G_OBJECT(user)); + g_hash_table_remove (service->priv->users, ssid); + user_remove_session (user, ssid); + emit_user_login_changed (service, user); + g_object_unref (o); + } } } -static void -sync_users (UsersServiceDbus *self) +static gchar* +get_unix_username_from_ssid (UsersServiceDbus * self, + const gchar * ssid) { - g_return_if_fail(IS_USERS_SERVICE_DBUS(self)); - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); + gchar * username = NULL; - if (priv->count > MINIMUM_USERS) + ConsoleKitSession * session_proxy = create_consolekit_session_proxy (ssid); + if (session_proxy != NULL) { - GPtrArray *users = NULL; - GError *error = NULL; - gint i; - - users = g_ptr_array_new (); - - if (!org_freedesktop_Accounts_list_cached_users (priv->accounts_service_proxy, - &users, - &error)) + guint uid = 0; + GError * error = NULL; + console_kit_session_call_get_unix_user_sync (session_proxy, + &uid, + NULL, &error); + if (error != NULL) { - g_warning ("failed to retrieve user list: %s", error->message); - g_error_free (error); - - return; + g_warning ("%s: %s", G_STRLOC, error->message); + g_clear_error (&error); } - - for (i = 0; i < users->len; i++) + else { - gchar *id; - DBusGProxy *proxy; - UserData *user; - GError *error = NULL; - - id = g_ptr_array_index (users, i); - - proxy = dbus_g_proxy_new_for_name (priv->system_bus, - "org.freedesktop.Accounts", - id, - "org.freedesktop.DBus.Properties"); - - GHashTable *properties; - if (!dbus_g_proxy_call (proxy, "GetAll", &error, - G_TYPE_STRING, "org.freedesktop.Accounts.User", G_TYPE_INVALID, - dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), &properties, G_TYPE_INVALID)) - { - g_warning ("unable to retrieve user info: %s", error->message); - g_error_free (error); - - continue; - } - - user = g_hash_table_lookup (priv->users, id); - // Double check we havent processed this user already - if (user != NULL) + errno = 0; + const struct passwd * pwent = getpwuid (uid); + if (pwent == NULL) { - g_free(user->user_name); - g_free(user->real_name); - g_free(user->icon_file); - user->real_name_conflict = FALSE; - //continue; + g_warning ("Failed to lookup user id %d: %s", (int)uid, g_strerror(errno)); } else - { - user = g_new0 (UserData, 1); + { + username = g_strdup (pwent->pw_name); } - // Can't subscribe to the Changed signal on each individual user path - // for some reason. - dbus_g_proxy_add_signal (proxy, - "Changed", - G_TYPE_INVALID); - - dbus_g_proxy_connect_signal (proxy, "Changed", - G_CALLBACK(user_changed), - self, - NULL); - user->uid = g_value_get_uint64 (g_hash_table_lookup (properties, "Uid")); - user->user_name = g_strdup (g_value_get_string (g_hash_table_lookup (properties, "UserName"))); - user->real_name = g_strdup (g_value_get_string (g_hash_table_lookup (properties, "RealName"))); - user->icon_file = g_strdup (g_value_get_string (g_hash_table_lookup (properties, "IconFile"))); - user->real_name_conflict = FALSE; - user->menuitem = NULL; - - g_hash_table_unref (properties); - - g_hash_table_insert (priv->users, - g_strdup (id), - user); - - add_sessions_for_user (self, user); } - g_ptr_array_free (users, TRUE); + g_object_unref (session_proxy); } + + return username; } -static void -user_changed (DBusGProxy *proxy, - gpointer user_data) +static gboolean +is_guest_username (const char * username) { - g_debug ("JUST RESYNCED THE USERS FROM A USER CHANGE"); - UsersServiceDbus *service = (UsersServiceDbus *)user_data; - sync_users (service); + if (!g_strcmp0 (username, "guest")) + return TRUE; + + if (username && g_str_has_prefix (username, "guest-")) + return TRUE; + + return FALSE; } +/* If the new session belongs to 'guest', update our guest_ssid. + Otherwise, call add_user_session() to update our session tables */ static void -user_added (DBusGProxy *proxy, - const gchar *user_id, - gpointer user_data) +on_session_added (ConsoleKitSeat * seat_proxy G_GNUC_UNUSED, + const gchar * ssid, + UsersServiceDbus * service) { - UsersServiceDbus *service = (UsersServiceDbus *)user_data; - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); - priv->count++; - sync_users (service); - g_signal_emit (service, - signals[USER_ADDED], - 0, - user_id); -} + g_return_if_fail (IS_USERS_SERVICE_DBUS(service)); -static void -user_deleted (DBusGProxy *proxy, - const gchar *user_id, - gpointer user_data) -{ - UsersServiceDbus *service = (UsersServiceDbus *)user_data; - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service); + gchar * username = get_unix_username_from_ssid (service, ssid); + g_debug ("%s %s() username %s has new session %s", G_STRLOC, G_STRFUNC, username, ssid); + + if (is_guest_username (username)) + { + /* handle guest as a special case -- it's not in the GDM + user tables and there isn't be an AccountsUser for it */ + g_debug("Found guest session: %s", ssid); + g_free (service->priv->guest_ssid); + service->priv->guest_ssid = g_strdup (ssid); + emit_guest_login_changed (service); + } + else + { + AccountsUser * user = find_user_from_username (service, username); - priv->count--; - g_hash_table_remove (priv->users, user_id); + if (user != NULL) + { + add_user_session (service, user, ssid); + emit_user_login_changed (service, user); + } + } - g_signal_emit (service, - signals[USER_DELETED], - 0, - user_id); - + g_free (username); } -UserData * -users_service_dbus_get_user_by_username (UsersServiceDbus *self, - const gchar *username) +/* Receives a list of sessions and calls on_session_added() for each of them */ +static void +on_session_list (ConsoleKitSeat * seat_proxy, + GAsyncResult * result, + UsersServiceDbus * self) { - GHashTableIter iter; - gpointer value; + GError * error = NULL; + gchar ** sessions = NULL; + g_debug ("%s bootstrapping the session list", G_STRLOC); - g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), NULL); + console_kit_seat_call_get_sessions_finish (seat_proxy, + &sessions, + result, + &error); + + if (error != NULL) + { + g_debug ("%s: %s", G_STRLOC, error->message); + g_error_free (error); + } + else if (sessions != NULL) + { + int i; + + for (i=0; sessions[i]; i++) + { + g_debug ("%s adding initial session '%s'", G_STRLOC, sessions[i]); + on_session_added (seat_proxy, sessions[i], self); + } + + g_strfreev (sessions); + } + + g_debug ("%s done bootstrapping the session list", G_STRLOC); +} - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); +static DisplayManagerSeat * +create_display_proxy (UsersServiceDbus * self) +{ + const gchar * const seat = g_getenv ("XDG_SEAT_PATH"); + g_debug ("%s creating a DisplayManager proxy for seat %s", G_STRLOC, seat); + + GError * error = NULL; + DisplayManagerSeat * p = display_manager_seat_proxy_new_for_bus_sync ( + G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + "org.freedesktop.DisplayManager", + seat, + NULL, + &error); - g_hash_table_iter_init (&iter, priv->users); - while (g_hash_table_iter_next (&iter, NULL, &value)) + if (error != NULL) { - UserData *user = value; - if (strcmp (user->user_name, username) == 0) - return user; + g_warning ("%s: %s", G_STRLOC, error->message); + g_error_free (error); } - return NULL; + return p; } +/*** +**** Public API +***/ + +/** + * users_service_dbus_get_user_list: + * + * Returns: (transfer container): a list of AccountsUser objects + */ GList * -users_service_dbus_get_user_list (UsersServiceDbus *self) +users_service_dbus_get_user_list (UsersServiceDbus * self) { g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), NULL); - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); + return g_hash_table_get_values (self->priv->users); +} + +/** + * users_service_dbus_show_greeter: + * + * Ask the Display Mnaager to switch to the greeter screen. + */ +void +users_service_dbus_show_greeter (UsersServiceDbus * self) +{ + g_return_if_fail (IS_USERS_SERVICE_DBUS(self)); - return g_hash_table_get_values (priv->users); + DisplayManagerSeat * dp = create_display_proxy (self); + display_manager_seat_call_switch_to_greeter_sync (dp, NULL, NULL); + g_clear_object (&dp); } -gboolean -users_service_dbus_show_greeter (UsersServiceDbus *self) +/** + * users_service_dbus_activate_guest_session: + * + * Activates the guest account. + */ +void +users_service_dbus_activate_guest_session (UsersServiceDbus * self) { - g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), FALSE); - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); - return org_freedesktop_DisplayManager_Seat_switch_to_greeter(priv->display_manager_proxy, NULL); + g_return_if_fail(IS_USERS_SERVICE_DBUS(self)); + + DisplayManagerSeat * dp = create_display_proxy (self); + display_manager_seat_call_switch_to_guest_sync (dp, "", NULL, NULL); + g_clear_object (&dp); } -/* Activates the guest account if it can. */ -gboolean -users_service_dbus_activate_guest_session (UsersServiceDbus *self) +/** + * users_service_dbus_activate_user_session: + * + * Activates a specific user. + */ +void +users_service_dbus_activate_user_session (UsersServiceDbus * self, + AccountsUser * user) { - g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), FALSE); - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); - return org_freedesktop_DisplayManager_Seat_switch_to_guest(priv->display_manager_proxy, "", NULL); + g_return_if_fail (IS_USERS_SERVICE_DBUS(self)); + + const char * const username = accounts_user_get_user_name (user); + DisplayManagerSeat * dp = create_display_proxy (self); + display_manager_seat_call_switch_to_user_sync (dp, username, "", NULL, NULL); + g_clear_object (&dp); } -/* Activates a specific user */ +/** + * users_service_dbus_guest_session_enabled: + * + * Tells whether or not guest sessions are allowed. + */ gboolean -users_service_dbus_activate_user_session (UsersServiceDbus *self, - UserData *user) +users_service_dbus_guest_session_enabled (UsersServiceDbus * self) { - g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), FALSE); - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); - return org_freedesktop_DisplayManager_Seat_switch_to_user(priv->display_manager_proxy, user->user_name, "", NULL); + g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), FALSE); + + DisplayManagerSeat * dp = create_display_proxy (self); + const gboolean enabled = display_manager_seat_get_has_guest_account (dp); + g_clear_object (&dp); + return enabled; } gboolean -users_service_dbus_can_activate_session (UsersServiceDbus *self) +users_service_dbus_can_activate_session (UsersServiceDbus * self) { - g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), FALSE); - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); gboolean can_activate = FALSE; - GError *error = NULL; - if (!priv->seat_proxy) - { - create_seat_proxy (self); - } - - if (!priv->seat || priv->seat[0] == '\0') - { - return FALSE; - } + g_return_val_if_fail (IS_USERS_SERVICE_DBUS(self), can_activate); - if (!dbus_g_proxy_call (priv->seat_proxy, - "CanActivateSessions", - &error, - G_TYPE_INVALID, - G_TYPE_BOOLEAN, &can_activate, - G_TYPE_INVALID)) + GError * error = NULL; + console_kit_seat_call_can_activate_sessions_sync (self->priv->seat_proxy, + &can_activate, + NULL, + &error); + if (error != NULL) { - if (error != NULL){ - g_warning ("Failed to determine if seat can activate sessions: %s", - error->message); - g_error_free (error); - } - return FALSE; + g_warning ("%s: %s", G_STRLOC, error->message); + g_error_free (error); } return can_activate; } -/* Sets the menu item that represents the guest account */ -void -users_service_dbus_set_guest_item (UsersServiceDbus * self, DbusmenuMenuitem * mi) +gboolean +users_service_dbus_is_guest_logged_in (UsersServiceDbus * self) { - g_return_if_fail(IS_USERS_SERVICE_DBUS(self)); - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); - priv->guest_item = mi; + g_return_val_if_fail (IS_USERS_SERVICE_DBUS(self), FALSE); - if (priv->guest_session_id != NULL) { - dbusmenu_menuitem_property_set_bool(priv->guest_item, USER_ITEM_PROP_LOGGED_IN, TRUE); - } - - return; + return self->priv->guest_ssid != NULL; } -gboolean users_service_dbus_guest_session_enabled (UsersServiceDbus * self) +gboolean +users_service_dbus_is_user_logged_in (UsersServiceDbus * self, + AccountsUser * user) { - g_return_val_if_fail(IS_USERS_SERVICE_DBUS(self), FALSE); - UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self); - - return priv->guest_session_enabled; -} + g_return_val_if_fail (IS_USERS_SERVICE_DBUS(self), FALSE); + g_return_val_if_fail (IS_ACCOUNTS_USER(user), FALSE); + return user_count_sessions (user) > 0; +} diff --git a/src/users-service-dbus.h b/src/users-service-dbus.h index b7db690..0f082c3 100644 --- a/src/users-service-dbus.h +++ b/src/users-service-dbus.h @@ -3,6 +3,7 @@ * * Authors: * Cody Russell <crussell@canonical.com> + * Charles Kerr <charles.kerr@canonical.com> * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License version 3, as published @@ -22,69 +23,74 @@ #include <glib.h> #include <glib-object.h> -#include <libdbusmenu-glib/menuitem.h> -G_BEGIN_DECLS - -#define USERS_SERVICE_DBUS_TYPE (users_service_dbus_get_type ()) -#define USERS_SERVICE_DBUS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), USERS_SERVICE_DBUS_TYPE, UsersServiceDbus)) -#define USERS_SERVICE_DBUS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), USERS_SERVICE_DBUS_TYPE, UsersServiceDbusClass)) -#define IS_USERS_SERVICE_DBUS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), USERS_SERVICE_DBUS_TYPE)) -#define IS_USERS_SERVICE_DBUS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), USERS_SERVICE_DBUS_TYPE)) -#define USERS_SERVICE_DBUS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), USERS_SERVICE_DBUS_TYPE, UsersServiceDbusClass)) - -typedef struct _UsersServiceDbus UsersServiceDbus; -typedef struct _UsersServiceDbusClass UsersServiceDbusClass; -typedef struct _UserData UserData; - -struct _UserData -{ - gint64 uid; - gchar *user_name; - gchar *real_name; - gchar *icon_file; +#include "dbus-user.h" /* for AccountsUser */ - GList *sessions; +G_BEGIN_DECLS - /* Whether the real name here conflicts with another in the system */ - gboolean real_name_conflict; - /* The menuitem representing this user if there is one. */ - DbusmenuMenuitem * menuitem; +#define USERS_SERVICE_DBUS_TYPE (users_service_dbus_get_type ()) +#define USERS_SERVICE_DBUS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), USERS_SERVICE_DBUS_TYPE, UsersServiceDbus)) +#define IS_USERS_SERVICE_DBUS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), USERS_SERVICE_DBUS_TYPE)) - UsersServiceDbus *service; -}; +typedef struct _UsersServiceDbus UsersServiceDbus; +typedef struct _UsersServiceDbusClass UsersServiceDbusClass; +typedef struct _UsersServiceDbusPrivate UsersServiceDbusPrivate; -/* XXX - MAXIMUM_USERS should be set to 7 once we've - * got some gdm issues worked out. +/** + * A facade class which interacts with multiple DBus services to + * track info which is useful to the interactor's user menu: + * + * 1. A list of users to add to the user menu. + * + * Each user is an AccountsUser object, which is a GDBusProxy + * to an org.freedesktop.Accounts.User object. + * + * We initially build this list by calling org.freedesktop.Accounts' + * GetCachedUsers method. We also monitor o.f.Accounts' UserAdded + * and UserDeleted and update the list accordingly. + * + * 2. Track which users currently have X sessions. + * This is used for the menuitems' USER_ITEM_PROP_LOGGED_IN property. + * + * We initially build this list by calling org.freedesktop.ConsoleKit.Seat's + * GetDevices method. We also monitor the seat for SessionAdded and + * SessionRemoved and update the list accordingly. + * + * 3. Provide an API for user switching and guest sessions. + * These are typically pass-through functions to GDBusProxies. + * */ -#define MINIMUM_USERS 0 - -struct _UsersServiceDbus { +struct _UsersServiceDbus +{ + /*< private >*/ GObject parent; + UsersServiceDbusPrivate * priv; }; -struct _UsersServiceDbusClass { +struct _UsersServiceDbusClass +{ GObjectClass parent_class; /* Signals */ - void (* user_added) (UsersServiceDbus *self, const gchar *user_id, gpointer user_data); - void (* user_deleted) (UsersServiceDbus *self, const gchar *user_id, gpointer user_data); + void (* user_list_changed) (UsersServiceDbus*, gpointer); + void (* user_logged_in_changed) (UsersServiceDbus*, AccountsUser*, gpointer); + void (* guest_logged_in_changed) (UsersServiceDbus*, gpointer); }; -GType users_service_dbus_get_type (void) G_GNUC_CONST; +GType users_service_dbus_get_type (void) G_GNUC_CONST; + +GList * users_service_dbus_get_user_list (UsersServiceDbus * self); -UserData *users_service_dbus_get_user_by_username (UsersServiceDbus *self, - const gchar *username); -GList *users_service_dbus_get_user_list (UsersServiceDbus *self); -gboolean users_service_dbus_show_greeter (UsersServiceDbus *self); -gboolean users_service_dbus_can_activate_session (UsersServiceDbus *self); -gboolean users_service_dbus_activate_user_session (UsersServiceDbus *self, - UserData *user); -gboolean users_service_dbus_activate_guest_session (UsersServiceDbus *self); -void users_service_dbus_set_guest_item (UsersServiceDbus * self, - DbusmenuMenuitem * mi); +gboolean users_service_dbus_is_guest_logged_in (UsersServiceDbus * self); +gboolean users_service_dbus_is_user_logged_in (UsersServiceDbus * self, + AccountsUser * user); -gboolean users_service_dbus_guest_session_enabled (UsersServiceDbus * self); +void users_service_dbus_show_greeter (UsersServiceDbus * self); +gboolean users_service_dbus_guest_session_enabled (UsersServiceDbus * self); +gboolean users_service_dbus_can_activate_session (UsersServiceDbus * self); +void users_service_dbus_activate_guest_session (UsersServiceDbus * self); +void users_service_dbus_activate_user_session (UsersServiceDbus * self, + AccountsUser * user); G_END_DECLS diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..5f22130 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,29 @@ +TESTS = +CLEANFILES = + +# stock UMB tests on user-visible strings +include $(srcdir)/Makefile.am.strings + +AM_CPPFLAGS = \ + $(GTEST_CPPFLAGS) \ + $(XORG_GTEST_CPPFLAGS) \ + $(INDICATOR_CFLAGS) \ + -I${top_srcdir}/src \ + -Wall -Werror +AM_CXXFLAGS = $(GTEST_CXXFLAGS) + +TESTS = test-service +check_PROGRAMS = test-service +test_service_SOURCES = test-service.cc +test_service_LDADD = $(TEST_SERVICE_LIBS) libgtest.a $(XORG_GTEST_MAIN_LIBS) $(X11_LIBS) +test_service_CPPFLAGS = \ + $(TEST_SERVICE_CFLAGS) \ + $(AM_CPPFLAGS) \ + -DINDICATOR_SERVICE_PATH="\"$(top_builddir)/src/indicator-session-service\"" + +check_LIBRARIES = libgtest.a +nodist_libgtest_a_SOURCES = \ + $(XORG_GTEST_SOURCE)/src/xorg-gtest-all.cpp \ + $(GTEST_SOURCE)/src/gtest-all.cc \ + $(XORG_GTEST_SOURCE)/src/xorg-gtest_main.cpp + diff --git a/tests/Makefile.am.strings b/tests/Makefile.am.strings new file mode 100644 index 0000000..26a23a8 --- /dev/null +++ b/tests/Makefile.am.strings @@ -0,0 +1,38 @@ +TESTS += \ + test-ellipsis \ + test-space-ellipsis \ + test-ascii-quotes + +##### +# Tests for there being proper ellipsis instead of three periods in a row +##### +test-ellipsis: $(top_srcdir)/po + @echo "#!/bin/bash" > $@ + @echo "(cd $(top_srcdir)/po && make $(GETTEXT_PACKAGE).pot)" >> $@ + @echo "grep -c -e \"^msgid.*\.\.\.\\\"\" $(top_srcdir)/po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"Ellipsis found in user visible strings\" >&2 && exit 1" >> $@ + @echo "exit 0" >> $@ + @chmod +x $@ + +##### +# Tests for there being a space before an ellipsis +##### +test-space-ellipsis: $(top_srcdir)/po + @echo "#!/bin/bash" > $@ + @echo "(cd $(top_srcdir)/po && make $(GETTEXT_PACKAGE).pot)" >> $@ + @echo "grep -c -e \"^msgid.* …\\\"\" $(top_srcdir)/po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"Space before ellipsis found in user visible strings\" >&2 && exit 1" >> $@ + @echo "exit 0" >> $@ + @chmod +x $@ + +##### +# Tests for ASCII quote types +##### +test-ascii-quotes: $(top_srcdir)/po + @echo "#!/bin/bash" > $@ + @echo "(cd $(top_srcdir)/po && make $(GETTEXT_PACKAGE).pot)" >> $@ + @echo "grep -c -e \"^msgid \\\".*'.*\\\"\" $(top_srcdir)/po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"ASCII apostrophy found in user visible strings\" >&2 && exit 1" >> $@ + @echo "grep -c -e \"^msgid \\\".*\\\".*\\\"\" $(top_srcdir)/po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"ASCII quote found in user visible strings\" >&2 && exit 1" >> $@ + @echo "grep -c -e \"^msgid \\\".*\\\`.*\\\"\" $(top_srcdir)/po/$(GETTEXT_PACKAGE).pot > /dev/null && echo \"ASCII backtick found in user visible strings\" >&2 && exit 1" >> $@ + @echo "exit 0" >> $@ + @chmod +x $@ + +CLEANFILES += $(TESTS) diff --git a/tests/test-service.cc b/tests/test-service.cc new file mode 100644 index 0000000..73d905b --- /dev/null +++ b/tests/test-service.cc @@ -0,0 +1,56 @@ +/* +Copyright 2012 Canonical Ltd. + +Authors: + Charles Kerr <charles.kerr@canonical.com> + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, as published +by the Free Software Foundation. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranties of +MERCHANTABILITY, SATISFACTORY QUALITY, 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 <http://www.gnu.org/licenses/>. +*/ + +#include <libindicator/indicator-service-test.h> + +#include "shared-names.h" + +/*** +**** +***/ + +/** + * Fixture class for testing indicator-session-service with Google Test. + */ +class SessionServiceTest: public IndicatorServiceTest +{ + public: + virtual ~SessionServiceTest() {} + SessionServiceTest(): IndicatorServiceTest(INDICATOR_SESSION_DBUS_NAME, + INDICATOR_SESSION_DBUS_OBJECT, + INDICATOR_SERVICE_PATH) { } + public: + virtual void SetUp() { + wait_seconds(1); + IndicatorServiceTest::SetUp(); + } + virtual void TearDown() { + IndicatorServiceTest::TearDown(); + } +}; + + +/** + * Basic sanity test to see if we can account for all our menuitems. + */ +TEST_F(SessionServiceTest, HelloWorld) +{ + ASSERT_TRUE(true); +} + |