diff options
author | Ken VanDine <ken.vandine@canonical.com> | 2011-07-22 13:41:06 -0400 |
---|---|---|
committer | Ken VanDine <ken.vandine@canonical.com> | 2011-07-22 13:41:06 -0400 |
commit | 108cec80746510d7f622ad0506a7f3d2a734c3ae (patch) | |
tree | 061bd5ba8a897fe82d74a941423192daa3b42a82 /src | |
parent | bd7fb2850d02ae416b2fd2a80f668f25dc861872 (diff) | |
parent | a1a7357b58d182e077ebfe8fb11c083e5eb18839 (diff) | |
download | ayatana-indicator-session-108cec80746510d7f622ad0506a7f3d2a734c3ae.tar.gz ayatana-indicator-session-108cec80746510d7f622ad0506a7f3d2a734c3ae.tar.bz2 ayatana-indicator-session-108cec80746510d7f622ad0506a7f3d2a734c3ae.zip |
Import upstream version 0.3.0
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 12 | ||||
-rw-r--r-- | src/Makefile.in | 104 | ||||
-rw-r--r-- | src/apt-transaction.c | 260 | ||||
-rw-r--r-- | src/apt-transaction.h | 49 | ||||
-rw-r--r-- | src/apt-watcher.c | 337 | ||||
-rw-r--r-- | src/apt-watcher.h | 60 | ||||
-rw-r--r-- | src/dbus-shared-names.h | 18 | ||||
-rw-r--r-- | src/device-menu-mgr.c | 798 | ||||
-rw-r--r-- | src/device-menu-mgr.h | 53 | ||||
-rw-r--r-- | src/dialog.c | 2 | ||||
-rw-r--r-- | src/gconf-helper.h | 6 | ||||
-rw-r--r-- | src/gen-session-dbus.xml.c | 6 | ||||
-rw-r--r-- | src/indicator-session.c | 19 | ||||
-rw-r--r-- | src/session-dbus.xml | 6 | ||||
-rw-r--r-- | src/session-service.c | 777 | ||||
-rw-r--r-- | src/udev-mgr.c | 46 | ||||
-rw-r--r-- | src/udev-mgr.h | 51 | ||||
-rw-r--r-- | src/user-menu-mgr.c | 357 | ||||
-rw-r--r-- | src/user-menu-mgr.h | 53 |
19 files changed, 2240 insertions, 774 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 71537c5..83d12bb 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -91,7 +91,17 @@ indicator_session_service_SOURCES = \ dbusmenu-shared.h \ gconf-helper.c \ users-service-dbus.h \ - users-service-dbus.c + users-service-dbus.c \ + user-menu-mgr.h \ + user-menu-mgr.c \ + device-menu-mgr.h \ + device-menu-mgr.c \ + apt-watcher.h \ + apt-watcher.c \ + apt-transaction.h \ + apt-transaction.c \ + udev-mgr.h \ + udev-mgr.c indicator_session_service_CFLAGS = \ $(SESSIONSERVICE_CFLAGS) \ $(GCONF_CFLAGS) \ diff --git a/src/Makefile.in b/src/Makefile.in index 4b282fd..2ef9128 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -100,7 +100,12 @@ am_indicator_session_service_OBJECTS = \ indicator_session_service-session-dbus.$(OBJEXT) \ indicator_session_service-gen-session-dbus.xml.$(OBJEXT) \ indicator_session_service-gconf-helper.$(OBJEXT) \ - indicator_session_service-users-service-dbus.$(OBJEXT) + indicator_session_service-users-service-dbus.$(OBJEXT) \ + indicator_session_service-user-menu-mgr.$(OBJEXT) \ + indicator_session_service-device-menu-mgr.$(OBJEXT) \ + indicator_session_service-apt-watcher.$(OBJEXT) \ + indicator_session_service-apt-transaction.$(OBJEXT) \ + indicator_session_service-udev-mgr.$(OBJEXT) indicator_session_service_OBJECTS = \ $(am_indicator_session_service_OBJECTS) indicator_session_service_DEPENDENCIES = $(am__DEPENDENCIES_1) \ @@ -337,7 +342,17 @@ indicator_session_service_SOURCES = \ dbusmenu-shared.h \ gconf-helper.c \ users-service-dbus.h \ - users-service-dbus.c + users-service-dbus.c \ + user-menu-mgr.h \ + user-menu-mgr.c \ + device-menu-mgr.h \ + device-menu-mgr.c \ + apt-watcher.h \ + apt-watcher.c \ + apt-transaction.h \ + apt-transaction.c \ + udev-mgr.h \ + udev-mgr.c indicator_session_service_CFLAGS = \ $(SESSIONSERVICE_CFLAGS) \ @@ -526,11 +541,16 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk_logout_helper-dialog.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk_logout_helper-gconf-helper.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gtk_logout_helper-gtk-logout-helper.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_session_service-apt-transaction.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_session_service-apt-watcher.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_session_service-device-menu-mgr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_session_service-gconf-helper.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_session_service-gen-session-dbus.xml.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_session_service-lock-helper.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_session_service-session-dbus.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_session_service-session-service.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_session_service-udev-mgr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_session_service-user-menu-mgr.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/indicator_session_service-users-service-dbus.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsession_la-indicator-session.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsession_la-user-widget.Plo@am__quote@ @@ -719,6 +739,86 @@ indicator_session_service-users-service-dbus.obj: users-service-dbus.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_session_service_CFLAGS) $(CFLAGS) -c -o indicator_session_service-users-service-dbus.obj `if test -f 'users-service-dbus.c'; then $(CYGPATH_W) 'users-service-dbus.c'; else $(CYGPATH_W) '$(srcdir)/users-service-dbus.c'; fi` +indicator_session_service-user-menu-mgr.o: user-menu-mgr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_session_service_CFLAGS) $(CFLAGS) -MT indicator_session_service-user-menu-mgr.o -MD -MP -MF $(DEPDIR)/indicator_session_service-user-menu-mgr.Tpo -c -o indicator_session_service-user-menu-mgr.o `test -f 'user-menu-mgr.c' || echo '$(srcdir)/'`user-menu-mgr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_session_service-user-menu-mgr.Tpo $(DEPDIR)/indicator_session_service-user-menu-mgr.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='user-menu-mgr.c' object='indicator_session_service-user-menu-mgr.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_session_service_CFLAGS) $(CFLAGS) -c -o indicator_session_service-user-menu-mgr.o `test -f 'user-menu-mgr.c' || echo '$(srcdir)/'`user-menu-mgr.c + +indicator_session_service-user-menu-mgr.obj: user-menu-mgr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_session_service_CFLAGS) $(CFLAGS) -MT indicator_session_service-user-menu-mgr.obj -MD -MP -MF $(DEPDIR)/indicator_session_service-user-menu-mgr.Tpo -c -o indicator_session_service-user-menu-mgr.obj `if test -f 'user-menu-mgr.c'; then $(CYGPATH_W) 'user-menu-mgr.c'; else $(CYGPATH_W) '$(srcdir)/user-menu-mgr.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_session_service-user-menu-mgr.Tpo $(DEPDIR)/indicator_session_service-user-menu-mgr.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='user-menu-mgr.c' object='indicator_session_service-user-menu-mgr.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_session_service_CFLAGS) $(CFLAGS) -c -o indicator_session_service-user-menu-mgr.obj `if test -f 'user-menu-mgr.c'; then $(CYGPATH_W) 'user-menu-mgr.c'; else $(CYGPATH_W) '$(srcdir)/user-menu-mgr.c'; fi` + +indicator_session_service-device-menu-mgr.o: device-menu-mgr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_session_service_CFLAGS) $(CFLAGS) -MT indicator_session_service-device-menu-mgr.o -MD -MP -MF $(DEPDIR)/indicator_session_service-device-menu-mgr.Tpo -c -o indicator_session_service-device-menu-mgr.o `test -f 'device-menu-mgr.c' || echo '$(srcdir)/'`device-menu-mgr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_session_service-device-menu-mgr.Tpo $(DEPDIR)/indicator_session_service-device-menu-mgr.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='device-menu-mgr.c' object='indicator_session_service-device-menu-mgr.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_session_service_CFLAGS) $(CFLAGS) -c -o indicator_session_service-device-menu-mgr.o `test -f 'device-menu-mgr.c' || echo '$(srcdir)/'`device-menu-mgr.c + +indicator_session_service-device-menu-mgr.obj: device-menu-mgr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_session_service_CFLAGS) $(CFLAGS) -MT indicator_session_service-device-menu-mgr.obj -MD -MP -MF $(DEPDIR)/indicator_session_service-device-menu-mgr.Tpo -c -o indicator_session_service-device-menu-mgr.obj `if test -f 'device-menu-mgr.c'; then $(CYGPATH_W) 'device-menu-mgr.c'; else $(CYGPATH_W) '$(srcdir)/device-menu-mgr.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_session_service-device-menu-mgr.Tpo $(DEPDIR)/indicator_session_service-device-menu-mgr.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='device-menu-mgr.c' object='indicator_session_service-device-menu-mgr.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_session_service_CFLAGS) $(CFLAGS) -c -o indicator_session_service-device-menu-mgr.obj `if test -f 'device-menu-mgr.c'; then $(CYGPATH_W) 'device-menu-mgr.c'; else $(CYGPATH_W) '$(srcdir)/device-menu-mgr.c'; fi` + +indicator_session_service-apt-watcher.o: apt-watcher.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_session_service_CFLAGS) $(CFLAGS) -MT indicator_session_service-apt-watcher.o -MD -MP -MF $(DEPDIR)/indicator_session_service-apt-watcher.Tpo -c -o indicator_session_service-apt-watcher.o `test -f 'apt-watcher.c' || echo '$(srcdir)/'`apt-watcher.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_session_service-apt-watcher.Tpo $(DEPDIR)/indicator_session_service-apt-watcher.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='apt-watcher.c' object='indicator_session_service-apt-watcher.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_session_service_CFLAGS) $(CFLAGS) -c -o indicator_session_service-apt-watcher.o `test -f 'apt-watcher.c' || echo '$(srcdir)/'`apt-watcher.c + +indicator_session_service-apt-watcher.obj: apt-watcher.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_session_service_CFLAGS) $(CFLAGS) -MT indicator_session_service-apt-watcher.obj -MD -MP -MF $(DEPDIR)/indicator_session_service-apt-watcher.Tpo -c -o indicator_session_service-apt-watcher.obj `if test -f 'apt-watcher.c'; then $(CYGPATH_W) 'apt-watcher.c'; else $(CYGPATH_W) '$(srcdir)/apt-watcher.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_session_service-apt-watcher.Tpo $(DEPDIR)/indicator_session_service-apt-watcher.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='apt-watcher.c' object='indicator_session_service-apt-watcher.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_session_service_CFLAGS) $(CFLAGS) -c -o indicator_session_service-apt-watcher.obj `if test -f 'apt-watcher.c'; then $(CYGPATH_W) 'apt-watcher.c'; else $(CYGPATH_W) '$(srcdir)/apt-watcher.c'; fi` + +indicator_session_service-apt-transaction.o: apt-transaction.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_session_service_CFLAGS) $(CFLAGS) -MT indicator_session_service-apt-transaction.o -MD -MP -MF $(DEPDIR)/indicator_session_service-apt-transaction.Tpo -c -o indicator_session_service-apt-transaction.o `test -f 'apt-transaction.c' || echo '$(srcdir)/'`apt-transaction.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_session_service-apt-transaction.Tpo $(DEPDIR)/indicator_session_service-apt-transaction.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='apt-transaction.c' object='indicator_session_service-apt-transaction.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_session_service_CFLAGS) $(CFLAGS) -c -o indicator_session_service-apt-transaction.o `test -f 'apt-transaction.c' || echo '$(srcdir)/'`apt-transaction.c + +indicator_session_service-apt-transaction.obj: apt-transaction.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_session_service_CFLAGS) $(CFLAGS) -MT indicator_session_service-apt-transaction.obj -MD -MP -MF $(DEPDIR)/indicator_session_service-apt-transaction.Tpo -c -o indicator_session_service-apt-transaction.obj `if test -f 'apt-transaction.c'; then $(CYGPATH_W) 'apt-transaction.c'; else $(CYGPATH_W) '$(srcdir)/apt-transaction.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_session_service-apt-transaction.Tpo $(DEPDIR)/indicator_session_service-apt-transaction.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='apt-transaction.c' object='indicator_session_service-apt-transaction.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_session_service_CFLAGS) $(CFLAGS) -c -o indicator_session_service-apt-transaction.obj `if test -f 'apt-transaction.c'; then $(CYGPATH_W) 'apt-transaction.c'; else $(CYGPATH_W) '$(srcdir)/apt-transaction.c'; fi` + +indicator_session_service-udev-mgr.o: udev-mgr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_session_service_CFLAGS) $(CFLAGS) -MT indicator_session_service-udev-mgr.o -MD -MP -MF $(DEPDIR)/indicator_session_service-udev-mgr.Tpo -c -o indicator_session_service-udev-mgr.o `test -f 'udev-mgr.c' || echo '$(srcdir)/'`udev-mgr.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_session_service-udev-mgr.Tpo $(DEPDIR)/indicator_session_service-udev-mgr.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='udev-mgr.c' object='indicator_session_service-udev-mgr.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_session_service_CFLAGS) $(CFLAGS) -c -o indicator_session_service-udev-mgr.o `test -f 'udev-mgr.c' || echo '$(srcdir)/'`udev-mgr.c + +indicator_session_service-udev-mgr.obj: udev-mgr.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_session_service_CFLAGS) $(CFLAGS) -MT indicator_session_service-udev-mgr.obj -MD -MP -MF $(DEPDIR)/indicator_session_service-udev-mgr.Tpo -c -o indicator_session_service-udev-mgr.obj `if test -f 'udev-mgr.c'; then $(CYGPATH_W) 'udev-mgr.c'; else $(CYGPATH_W) '$(srcdir)/udev-mgr.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/indicator_session_service-udev-mgr.Tpo $(DEPDIR)/indicator_session_service-udev-mgr.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='udev-mgr.c' object='indicator_session_service-udev-mgr.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(indicator_session_service_CFLAGS) $(CFLAGS) -c -o indicator_session_service-udev-mgr.obj `if test -f 'udev-mgr.c'; then $(CYGPATH_W) 'udev-mgr.c'; else $(CYGPATH_W) '$(srcdir)/udev-mgr.c'; fi` + mostlyclean-libtool: -rm -f *.lo diff --git a/src/apt-transaction.c b/src/apt-transaction.c new file mode 100644 index 0000000..78a0ff2 --- /dev/null +++ b/src/apt-transaction.c @@ -0,0 +1,260 @@ +/* +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 <gio/gio.h> + +#include "apt-transaction.h" +#include "dbus-shared-names.h" + +static void apt_transaction_investigate (AptTransaction* self); +static void apt_transaction_simulate_transaction_cb (GObject * obj, + GAsyncResult * res, + gpointer user_data); +static void apt_transaction_receive_signal (GDBusProxy * proxy, + gchar * sender_name, + gchar * signal_name, + GVariant * parameters, + gpointer user_data); +static void apt_transaction_finish_proxy_setup (GObject *source_object, + GAsyncResult *res, + gpointer user_data); + +struct _AptTransaction +{ + GObject parent_instance; + GDBusProxy * proxy; + GCancellable * proxy_cancel; + gchar* id; + TransactionType type; +}; + +enum { + UPDATE, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +G_DEFINE_TYPE (AptTransaction, apt_transaction, G_TYPE_OBJECT); + +static void +apt_transaction_init (AptTransaction *self) +{ + self->proxy = NULL; + self->id = NULL; + self->proxy_cancel = g_cancellable_new(); +} + +static void +apt_transaction_finalize (GObject *object) +{ + AptTransaction* self = APT_TRANSACTION(object); + g_signal_handlers_disconnect_by_func (G_OBJECT (self->proxy), + G_CALLBACK (apt_transaction_receive_signal), + self); + if (self->proxy != NULL){ + g_object_unref (self->proxy); + self->proxy = NULL; + } + g_free (self->id); + G_OBJECT_CLASS (apt_transaction_parent_class)->finalize (object); +} + +static void +apt_transaction_class_init (AptTransactionClass *klass) +{ + GObjectClass* object_class = G_OBJECT_CLASS (klass); + object_class->finalize = apt_transaction_finalize; + + signals[UPDATE] = g_signal_new("state-update", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); +} + +// TODO: you don't need this additional helper +// Just GObject properties properly +static void +apt_transaction_investigate (AptTransaction* self) +{ + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + "org.debian.apt", + self->id, + "org.debian.apt.transaction", + self->proxy_cancel, + apt_transaction_finish_proxy_setup, + self); +} + +static void +apt_transaction_finish_proxy_setup (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + g_return_if_fail (APT_IS_TRANSACTION (user_data)); + AptTransaction* self = APT_TRANSACTION(user_data); + GError * error = 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; + + g_signal_connect (G_OBJECT(self->proxy), + "g-signal", + G_CALLBACK (apt_transaction_receive_signal), + self); + + if (self->type == SIMULATION){ + g_dbus_proxy_call (self->proxy, + "Simulate", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + apt_transaction_simulate_transaction_cb, + self); + } +} + +static void +apt_transaction_receive_signal (GDBusProxy * proxy, + gchar * sender_name, + gchar * signal_name, + GVariant * parameters, + gpointer user_data) +{ + g_return_if_fail (APT_IS_TRANSACTION (user_data)); + AptTransaction* self = APT_TRANSACTION(user_data); + AptState current_state = DONT_KNOW; + + if (g_strcmp0(signal_name, "PropertyChanged") == 0 && self->type == SIMULATION) + { + gchar* prop_name= NULL; + GVariant* value = NULL; + g_variant_get (parameters, "(sv)", &prop_name, &value); + g_debug ("transaction prop update - prop = %s", prop_name); + + if (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING) == TRUE){ + gchar* key = NULL; + g_variant_get (value, "s", &key); + g_debug ("transaction prop update - value = %s", key); + } + + if (g_strcmp0 (prop_name, "Dependencies") == 0){ + + gchar** install = NULL; + gchar** reinstall = NULL; + gchar** remove = NULL; + gchar** purge = NULL; + gchar** upgrade = NULL; + gchar** downgrade = NULL; + gchar** keep = NULL; + g_variant_get (value, "(asasasasasasas)", &install, + &reinstall, &remove, &purge, &upgrade, &downgrade, + &keep); + //g_debug ("Seemed to uppack dependencies without any warnings"); + //g_debug ("Upgrade quantity : %u", g_strv_length(upgrade)); + gboolean upgrade_needed = (g_strv_length(upgrade) > 0) || + (g_strv_length(install) > 0) || + (g_strv_length(reinstall) > 0) || + (g_strv_length(remove) > 0) || + (g_strv_length(purge) > 0); + if (upgrade_needed == TRUE){ + current_state = UPDATES_AVAILABLE; + } + else{ + current_state = UP_TO_DATE; + } + } + } + else if (g_strcmp0(signal_name, "PropertyChanged") == 0 && + self->type == REAL) + { + GVariant* role = g_dbus_proxy_get_cached_property (self->proxy, + "Role"); + if (g_variant_is_of_type (role, G_VARIANT_TYPE_STRING) == TRUE){ + gchar* current_role = NULL; + g_variant_get (role, "s", ¤t_role); + g_debug ("Current transaction role = %s", current_role); + if (g_strcmp0 (current_role, "role-commit-packages") == 0 || + g_strcmp0 (current_role, "role-upgrade-system") == 0){ + g_debug ("UPGRADE IN PROGRESS"); + current_state = UPGRADE_IN_PROGRESS; + } + } + } + else if (g_strcmp0(signal_name, "Finished") == 0) + { + g_debug ("TRANSACTION Finished"); + current_state = FINISHED; + } + // Finally send out the state update + if (current_state != DONT_KNOW){ + g_signal_emit (self, + signals[UPDATE], + 0, + current_state); + } + g_variant_unref (parameters); +} + +static void +apt_transaction_simulate_transaction_cb (GObject * obj, + GAsyncResult * res, + gpointer user_data) +{ + GError * error = NULL; + if (error != NULL) { + g_warning ("unable to complete the simulate call"); + g_error_free (error); + return; + } +} +TransactionType +apt_transaction_get_transaction_type (AptTransaction* self) +{ + return self->type; +} + +AptTransaction* apt_transaction_new (gchar* transaction_id, TransactionType t) +{ + AptTransaction* tr = g_object_new (APT_TYPE_TRANSACTION, NULL); + tr->id = transaction_id; + tr->type = t; + g_debug ("Apt transaction new id = %s", tr->id); + apt_transaction_investigate (tr); + return tr; +} diff --git a/src/apt-transaction.h b/src/apt-transaction.h new file mode 100644 index 0000000..9e4370d --- /dev/null +++ b/src/apt-transaction.h @@ -0,0 +1,49 @@ +/* +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_TRANSACTION_H_ +#define _APT_TRANSACTION_H_ + +#include <glib-object.h> +#include "dbus-shared-names.h" + +G_BEGIN_DECLS + +#define APT_TYPE_TRANSACTION (apt_transaction_get_type ()) +#define APT_TRANSACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), APT_TYPE_TRANSACTION, AptTransaction)) +#define APT_TRANSACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), APT_TYPE_TRANSACTION, AptTransactionClass)) +#define APT_IS_TRANSACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), APT_TYPE_TRANSACTION)) +#define APT_IS_TRANSACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), APT_TYPE_TRANSACTION)) +#define APT_TRANSACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), APT_TYPE_TRANSACTION, AptTransactionClass)) + +typedef struct _AptTransactionClass AptTransactionClass; +typedef struct _AptTransaction AptTransaction; + +struct _AptTransactionClass +{ + GObjectClass parent_class; +}; + +AptTransaction* apt_transaction_new (gchar* transaction_id, TransactionType t); +TransactionType apt_transaction_get_transaction_type (AptTransaction* self); +GType apt_transaction_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* _APT_TRANSACTION_H_ */ diff --git a/src/apt-watcher.c b/src/apt-watcher.c new file mode 100644 index 0000000..285eb81 --- /dev/null +++ b/src/apt-watcher.c @@ -0,0 +1,337 @@ +/* +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 <gio/gio.h> +#include <glib/gi18n.h> +#include "apt-watcher.h" +#include "apt-transaction.h" + +static guint watcher_id; + +struct _AptWatcher +{ + GObject parent_instance; + GCancellable * proxy_cancel; + GDBusProxy * proxy; + SessionDbus* session_dbus_interface; + DbusmenuMenuitem* apt_item; + AptState current_state; + AptTransaction* current_transaction; +}; + +static void +apt_watcher_on_name_appeared (GDBusConnection *connection, + const gchar *name, + const gchar *name_owner, + gpointer user_data); +static void +apt_watcher_on_name_vanished (GDBusConnection *connection, + const gchar *name, + gpointer user_data); +static void fetch_proxy_cb (GObject * object, + GAsyncResult * res, + gpointer user_data); + +static void apt_watcher_upgrade_system_cb (GObject * obj, + GAsyncResult * res, + gpointer user_data); + + +static void apt_watcher_show_apt_dialog (DbusmenuMenuitem* mi, + guint timestamp, + gchar * type); + +static void apt_watcher_signal_cb (GDBusProxy* proxy, + gchar* sender_name, + gchar* signal_name, + GVariant* parameters, + gpointer user_data); +static void apt_watcher_manage_transactions (AptWatcher* self, + gchar* transaction_id); + + + +G_DEFINE_TYPE (AptWatcher, apt_watcher, G_TYPE_OBJECT); + +static void +apt_watcher_init (AptWatcher *self) +{ + self->current_state = UP_TO_DATE; + self->proxy_cancel = g_cancellable_new(); + self->proxy = NULL; + self->current_transaction = NULL; + g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, + G_DBUS_PROXY_FLAGS_NONE, + NULL, + "org.debian.apt", + "/org/debian/apt", + "org.debian.apt", + self->proxy_cancel, + fetch_proxy_cb, + 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; +} + +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.debian.apt", + 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 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); + + g_dbus_proxy_call (watcher->proxy, + "UpgradeSystem", + g_variant_new("(b)", TRUE), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + apt_watcher_upgrade_system_cb, + user_data); +} + +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 +apt_watcher_upgrade_system_cb (GObject * obj, + GAsyncResult * res, + gpointer user_data) +{ + g_return_if_fail (APT_IS_WATCHER (user_data)); + AptWatcher* self = APT_WATCHER (user_data); + + GError * error = NULL; + GVariant * result; + + result = g_dbus_proxy_call_finish(self->proxy, res, &error); + + if (error != NULL) { + g_warning ("unable to complete the UpgradeSystem apt call"); + g_error_free (error); + return; + } + + gchar* transaction_id = NULL; + g_variant_get (result, "(s)", &transaction_id); + + if (transaction_id == NULL){ + g_warning ("apt_watcher_upgrade_system_cb - transaction id is null"); + return; + } + + apt_watcher_manage_transactions (self, transaction_id); + +} + +static void +apt_watcher_show_apt_dialog (DbusmenuMenuitem * mi, + guint timestamp, + gchar * type) +{ + GError * error = NULL; + 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_transaction_state_update_cb (AptTransaction* trans, + gint update, + gpointer user_data) +{ + g_debug ("apt-watcher -transaction update %i", update); + g_return_if_fail (APT_IS_WATCHER (user_data)); + AptWatcher* self = APT_WATCHER (user_data); + + AptState state = (AptState)update; + + if (state == UP_TO_DATE){ + dbusmenu_menuitem_property_set (self->apt_item, + DBUSMENU_MENUITEM_PROP_LABEL, + _("Software Up to Date")); + // Simulations don't send a finished signal for some reason + // Anyway from a simulation we just need one state update + // (updates available or not) + if (apt_transaction_get_transaction_type (self->current_transaction) + == SIMULATION){ + g_object_unref (G_OBJECT(self->current_transaction)); + self->current_transaction = NULL; + } + } + else if (state == UPDATES_AVAILABLE){ + dbusmenu_menuitem_property_set (self->apt_item, + DBUSMENU_MENUITEM_PROP_LABEL, + _("Updates Available…")); + // Simulations don't send a finished signal for some reason + // Anyway from a simulation we just need one state update + // (updates available or not) + if (apt_transaction_get_transaction_type (self->current_transaction) + == SIMULATION){ + g_object_unref (G_OBJECT(self->current_transaction)); + self->current_transaction = NULL; + } + } + else if (state == UPGRADE_IN_PROGRESS){ + dbusmenu_menuitem_property_set (self->apt_item, + DBUSMENU_MENUITEM_PROP_LABEL, + _("Updates Installing…")); + } + else if (state == FINISHED){ + dbusmenu_menuitem_property_set (self->apt_item, + DBUSMENU_MENUITEM_PROP_LABEL, + _("Software Up to Date")); + g_object_unref (G_OBJECT(self->current_transaction)); + self->current_transaction = NULL; + } + self->current_state = state; +} + +static void +apt_watcher_manage_transactions (AptWatcher* self, gchar* transaction_id) +{ + if (self->current_transaction == NULL){ + self->current_transaction = apt_transaction_new (transaction_id, SIMULATION); + g_signal_connect (G_OBJECT(self->current_transaction), + "state-update", + G_CALLBACK(apt_watcher_transaction_state_update_cb), self); + } +} + +// TODO - Ask MVO about this. +// Signal is of type s not sas which is on d-feet !!! +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_variant_ref (parameters); + GVariant *value = g_variant_get_child_value (parameters, 0); + + if (g_strcmp0(signal_name, "ActiveTransactionsChanged") == 0){ + gchar* input = NULL; + g_variant_get(value, "s", & input); + if (g_str_has_prefix (input, "/org/debian/apt/transaction/") == TRUE){ + g_debug ("Active Transactions signal - input is null = %i", input == NULL); + + if (self->current_transaction != NULL) + { + g_object_unref (G_OBJECT(self->current_transaction)); + self->current_transaction = NULL; + } + + self->current_transaction = apt_transaction_new (input, REAL); + g_signal_connect (G_OBJECT(self->current_transaction), + "state-update", + G_CALLBACK(apt_watcher_transaction_state_update_cb), self); + + + } + } + g_variant_unref (parameters); +} + +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 new file mode 100644 index 0000000..7b98a44 --- /dev/null +++ b/src/apt-watcher.h @@ -0,0 +1,60 @@ +/* +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> +#if GTK_CHECK_VERSION(3, 0, 0) +#include <libdbusmenu-gtk3/menuitem.h> +#else +#include <libdbusmenu-gtk/menuitem.h> +#endif + +#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/dbus-shared-names.h b/src/dbus-shared-names.h index c4ccd05..d9dfff1 100644 --- a/src/dbus-shared-names.h +++ b/src/dbus-shared-names.h @@ -20,9 +20,23 @@ 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 __DBUS_SHARED_NAMES_H__ -#define __DBUS_SHARED_NAMES_H__ 1 +#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" diff --git a/src/device-menu-mgr.c b/src/device-menu-mgr.c new file mode 100644 index 0000000..324b3f1 --- /dev/null +++ b/src/device-menu-mgr.c @@ -0,0 +1,798 @@ +/* +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 <libdbusmenu-gtk3/menuitem.h> + +#include "device-menu-mgr.h" +#include "gconf-helper.h" +#include "dbus-shared-names.h" +#include "dbusmenu-shared.h" +#include "lock-helper.h" +#include "upower-client.h" +#include "apt-watcher.h" + + +#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; + AptWatcher* apt_watcher; +}; + +static GConfClient *gconf_client = NULL; +static DbusmenuMenuitem *lock_menuitem = NULL; +static DbusmenuMenuitem *system_settings_menuitem = NULL; +static DbusmenuMenuitem *display_settings_menuitem = NULL; +static DbusmenuMenuitem *bluetooth_settings_menuitem = NULL; +static DbusmenuMenuitem *login_settings_menuitem = NULL; +static DbusmenuMenuitem *software_updates_menuitem = NULL; +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 * restart_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_gconf_client (DeviceMenuMgr* self); +static void setup_restart_watch (DeviceMenuMgr* self); +static void setup_up (DeviceMenuMgr* self); +static void device_menu_mgr_rebuild_items (DeviceMenuMgr *self); +static void lock_if_possible (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 +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) +{ + self->apt_watcher = NULL; + self->root_item = dbusmenu_menuitem_new (); + setup_restart_watch(self); + 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 (GConfClient *client, + guint cnxd_id, + GConfEntry *entry, + gpointer user_data) +{ + DeviceMenuMgr* self = DEVICE_MENU_MGR (user_data); + GConfValue *value = gconf_entry_get_value (entry); + const gchar *key = gconf_entry_get_key (entry); + + if (value == NULL || 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 (GConfClient *client, + guint cnxd_id, + GConfEntry *entry, + gpointer user_data) +{ + GConfValue *value = gconf_entry_get_value (entry); + const gchar *key = gconf_entry_get_key (entry); + + if (value == NULL || key == NULL) { + return; + } + + if (g_strcmp0 (key, KEY_LOCK_SCREEN) == 0) { + g_debug("Keybinding changed to: %s", gconf_value_get_string(value)); + if (lock_menuitem != NULL) { + dbusmenu_menuitem_property_set_shortcut_string (lock_menuitem, + gconf_value_get_string(value)); + } + } + return; +} + +/* Check to see if the lockdown key is protecting from + locking the screen. If not, lock it. */ +static void +lock_if_possible (DeviceMenuMgr* self) { + device_menu_mgr_ensure_gconf_client (self); + + if (!gconf_client_get_bool (gconf_client, LOCKDOWN_KEY_SCREENSAVER, NULL)) { + lock_screen (NULL, 0, NULL); + } + return; +} + +/* A return from the command to sleep the system. Make sure + that we unthrottle the screensaver. */ +static void +sleep_response (DBusGProxy * proxy, DBusGProxyCall * call, gpointer data) +{ + screensaver_unthrottle(); + 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); + } + + screensaver_throttle(type); + lock_if_possible (self); + + dbus_g_proxy_begin_call(up_main_proxy, + type, + sleep_response, + 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) +{ + + gchar * helper = g_build_filename(LIBEXECDIR, "gtk-logout-helper", NULL); + 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_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); +} + +static void +device_menu_mgr_build_static_items (DeviceMenuMgr* self) +{ + // Static Setting items + 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); + bluetooth_settings_menuitem = dbusmenu_menuitem_new(); + dbusmenu_menuitem_property_set (bluetooth_settings_menuitem, + DBUSMENU_MENUITEM_PROP_LABEL, + _("Bluetooth...")); + g_signal_connect (G_OBJECT(bluetooth_settings_menuitem), + DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK(show_system_settings_with_context), "bluetooth"); + dbusmenu_menuitem_child_add_position(self->root_item, + bluetooth_settings_menuitem, + 2); + + 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, + 3); + 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, + 4); + + 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, 5); + + // Devices control + 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, + 6); + + 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_system_settings_with_context), + "printers"); + dbusmenu_menuitem_child_add_position(self->root_item, + printers_menuitem, + 7); + scanners_menuitem = dbusmenu_menuitem_new(); + dbusmenu_menuitem_property_set (scanners_menuitem, + DBUSMENU_MENUITEM_PROP_LABEL, + _("HP Scanners")); + g_signal_connect (G_OBJECT(scanners_menuitem), + DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK(show_system_settings_with_context), + "scanners"); + dbusmenu_menuitem_child_add_position (self->root_item, + scanners_menuitem, + 8); + //tmp + 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, + _("HP Webcam")); + g_signal_connect (G_OBJECT(webcam_menuitem), + DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK(show_system_settings_with_context), + "HP Webcam"); + dbusmenu_menuitem_child_add_position (self->root_item, + webcam_menuitem, + 10); + //tmp + 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, 11); + + // Session control + gboolean can_lockscreen; + + /* Make sure we have a valid GConf client, and build one + if needed */ + device_menu_mgr_ensure_gconf_client (self); + can_lockscreen = !gconf_client_get_bool ( gconf_client, + LOCKDOWN_KEY_SCREENSAVER, + NULL); + /* 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 = gconf_client_get_string(gconf_client, KEY_LOCK_SCREEN, NULL); + 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, + G_CALLBACK(show_dialog), "shutdown"); + + 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); +} + + +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); +} + +/* When the directory changes we need to figure out how our menu + item should look. */ +static void +restart_dir_changed (gpointer userdata) +{ + DeviceMenuMgr* self = DEVICE_MENU_MGR (userdata); + gboolean restart_required = g_file_test("/var/run/reboot-required", G_FILE_TEST_EXISTS); + + if (restart_required) { + if (supress_confirmations()) { + dbusmenu_menuitem_property_set (restart_mi, + RESTART_ITEM_LABEL, + _("Restart to Complete Update")); + } else { + dbusmenu_menuitem_property_set (restart_mi, + RESTART_ITEM_LABEL, + _("Restart to Complete Update\342\200\246")); + } + dbusmenu_menuitem_property_set (restart_mi, + RESTART_ITEM_ICON, + "system-restart-panel"); + if (self->session_dbus_interface != NULL) { + session_dbus_set_name (self->session_dbus_interface, ICON_RESTART); + } + } else { + if (supress_confirmations()) { + dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("Restart")); + } else { + dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("Restart\342\200\246")); + } + dbusmenu_menuitem_property_remove(restart_mi, RESTART_ITEM_ICON); + if (self->session_dbus_interface != NULL) { + session_dbus_set_name(self->session_dbus_interface, ICON_DEFAULT); + } + } + return; +} + +/* Buids a file watcher for the directory so that when it + changes we can check to see if our reboot-required is + there. */ +static void +setup_restart_watch (DeviceMenuMgr* self) +{ + GFile * filedir = g_file_new_for_path("/var/run"); + GFileMonitor * filemon = g_file_monitor_directory(filedir, G_FILE_MONITOR_NONE, NULL, NULL); + if (filemon != NULL) { + g_signal_connect (G_OBJECT(filemon), + "changed", + G_CALLBACK(restart_dir_changed), + self); + } + restart_dir_changed(self); + return; +} + +/* Ensures that we have a GConf client and if we build one + set up the signal handler. */ +static void +device_menu_mgr_ensure_gconf_client (DeviceMenuMgr* self) +{ + if (!gconf_client) { + gconf_client = gconf_client_get_default (); + + gconf_client_add_dir(gconf_client, LOCKDOWN_DIR, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL); + gconf_client_notify_add (gconf_client, + LOCKDOWN_DIR, + lockdown_changed, + self, + NULL, + NULL); + + gconf_client_add_dir(gconf_client, KEYBINDING_DIR, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL); + gconf_client_notify_add (gconf_client, + KEYBINDING_DIR, + keybinding_changed, + self, + NULL, + NULL); + } +} + +DbusmenuMenuitem* +device_mgr_get_root_item (DeviceMenuMgr* self) +{ + return self->root_item; +} + +/* + * Clean Entry Point + */ +DeviceMenuMgr* device_menu_mgr_new (SessionDbus* session_dbus) +{ + 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); + device_mgr->apt_watcher = apt_watcher_new (session_dbus, + software_updates_menuitem); + return device_mgr; +} diff --git a/src/device-menu-mgr.h b/src/device-menu-mgr.h new file mode 100644 index 0000000..503b36a --- /dev/null +++ b/src/device-menu-mgr.h @@ -0,0 +1,53 @@ +/* +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); + +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 9633224..d38f8bf 100644 --- a/src/dialog.c +++ b/src/dialog.c @@ -183,6 +183,8 @@ logout_dialog_new (LogoutDialogType type) "text", _(body_strings[type]), NULL)); + gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE); + gboolean allowed = FALSE; if (type == LOGOUT_DIALOG_TYPE_LOG_OUT) { allowed = ck_check_allowed(LOGOUT_DIALOG_TYPE_RESTART); diff --git a/src/gconf-helper.h b/src/gconf-helper.h index 505c24f..039b309 100644 --- a/src/gconf-helper.h +++ b/src/gconf-helper.h @@ -39,6 +39,12 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #define RESTART_KEY GLOBAL_DIR "/suppress_restart_menuitem" #define SHUTDOWN_KEY GLOBAL_DIR "/suppress_shutdown_menuitem" +#define LOCKDOWN_DIR "/desktop/gnome/lockdown" +#define LOCKDOWN_KEY_USER LOCKDOWN_DIR "/disable_user_switching" +#define LOCKDOWN_KEY_SCREENSAVER LOCKDOWN_DIR "/disable_lock_screen" +#define KEYBINDING_DIR "/apps/gnome_settings_daemon/keybindings" +#define KEY_LOCK_SCREEN KEYBINDING_DIR "/screensaver" + typedef struct _RestartShutdownLogoutMenuItems { DbusmenuMenuitem * logout_mi; diff --git a/src/gen-session-dbus.xml.c b/src/gen-session-dbus.xml.c index 9b20569..a945ca7 100644 --- a/src/gen-session-dbus.xml.c +++ b/src/gen-session-dbus.xml.c @@ -9,12 +9,18 @@ const char * _session_dbus = " <method name=\"GetUserMenuVisibility\">\n" " <arg name=\"update\" direction=\"out\" type=\"b\"/>\n" " </method>\n" +" <method name=\"IsUpdateNeeded\">\n" +" <arg name=\"update\" direction=\"out\" type=\"b\"/>\n" +" </method>\n" " <signal name=\"UserRealNameUpdated\">\n" " <arg name=\"name\" type=\"s\"/>\n" " </signal>\n" " <signal name=\"UserMenuIsVisible\">\n" " <arg name=\"update\" type=\"b\"/>\n" " </signal>\n" +" <signal name=\"RestartNeeded\">\n" +" <arg name=\"name\" type=\"s\"/>\n" +" </signal>\n" " </interface>\n" "</node>\n" ; diff --git a/src/indicator-session.c b/src/indicator-session.c index 068ffef..d7155f6 100644 --- a/src/indicator-session.c +++ b/src/indicator-session.c @@ -6,7 +6,8 @@ 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 by the Free Software Foundation. @@ -20,7 +21,6 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -//TODO - remember to reinsert Ted's comments. #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -444,22 +444,19 @@ user_menu_visibility_get_cb (GObject* obj, GAsyncResult* res, gpointer user_data // 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; - IndicatorObjectEntry user_entry = self->users; - if (self->show_users_entry == TRUE){ g_signal_emit_by_name ((gpointer)self, "entry-added", - &user_entry); + &self->users); } else{ g_signal_emit_by_name ((gpointer)self, "entry-removed", - &user_entry); + &self->users); } } @@ -489,18 +486,16 @@ receive_signal (GDBusProxy * proxy, //Otherwise self->show_users_entry = update; - - IndicatorObjectEntry user_entry = self->users; if (self->show_users_entry == TRUE){ g_signal_emit_by_name ((gpointer)self, "entry-added", - &user_entry); + &self->users); } else{ g_signal_emit_by_name ((gpointer)self, "entry-removed", - &user_entry); + &self->users); } } } diff --git a/src/session-dbus.xml b/src/session-dbus.xml index f496ff1..c42aca8 100644 --- a/src/session-dbus.xml +++ b/src/session-dbus.xml @@ -8,11 +8,17 @@ <method name="GetUserMenuVisibility"> <arg name="update" direction="out" type="b"/> </method> + <method name="IsUpdateNeeded"> + <arg name="update" direction="out" type="b"/> + </method> <signal name="UserRealNameUpdated"> <arg name="name" type="s"/> </signal> <signal name="UserMenuIsVisible"> <arg name="update" type="b"/> </signal> + <signal name="RestartNeeded"> + <arg name="name" type="s"/> + </signal> </interface> </node> diff --git a/src/session-service.c b/src/session-service.c index fb6ce37..bb473e9 100644 --- a/src/session-service.c +++ b/src/session-service.c @@ -37,32 +37,22 @@ with this program. If not, see <http://www.gnu.org/licenses/>. #include <libdbusmenu-glib/server.h> #include <libdbusmenu-glib/menuitem.h> #include <libdbusmenu-glib/client.h> + +#include <gtk/gtk.h> +#if GTK_CHECK_VERSION(3, 0, 0) #include <libdbusmenu-gtk3/menuitem.h> +#else +#include <libdbusmenu-gtk/menuitem.h> +#endif #include <libindicator/indicator-service.h> #include "dbus-shared-names.h" #include "dbusmenu-shared.h" - -#include "gconf-helper.h" - -#include "session-dbus.h" #include "users-service-dbus.h" -#include "lock-helper.h" -#include "upower-client.h" - -#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" - -#define LOCKDOWN_DIR "/desktop/gnome/lockdown" -#define LOCKDOWN_KEY_USER LOCKDOWN_DIR "/disable_user_switching" -#define LOCKDOWN_KEY_SCREENSAVER LOCKDOWN_DIR "/disable_lock_screen" - -#define KEYBINDING_DIR "/apps/gnome_settings_daemon/keybindings" -#define KEY_LOCK_SCREEN KEYBINDING_DIR "/screensaver" +#include "user-menu-mgr.h" +#include "device-menu-mgr.h" +#include "session-dbus.h" typedef struct _ActivateData ActivateData; struct _ActivateData @@ -71,672 +61,11 @@ struct _ActivateData UserData *user; }; -static UsersServiceDbus *dbus_interface = NULL; +//static UsersServiceDbus *dbus_interface = NULL; static SessionDbus *session_dbus = NULL; - -static DbusmenuMenuitem *lock_menuitem = NULL; -static DbusmenuMenuitem *switch_menuitem = NULL; - -static DbusmenuMenuitem * session_root_menuitem = NULL; -static DbusmenuMenuitem * users_root_menuitem = NULL; - static GMainLoop * mainloop = NULL; -static DBusGProxy * up_main_proxy = NULL; -static DBusGProxy * up_prop_proxy = 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 * restart_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 GConfClient * gconf_client = NULL; - -static void rebuild_session_items (DbusmenuMenuitem *root, UsersServiceDbus *service); -static void rebuild_user_items (DbusmenuMenuitem *root, UsersServiceDbus *service); -static void activate_online_accounts (DbusmenuMenuitem *mi, guint timestamp, gpointer user_data); - -static void -lockdown_changed (GConfClient *client, - guint cnxd_id, - GConfEntry *entry, - gpointer user_data) -{ - GConfValue *value = gconf_entry_get_value (entry); - const gchar *key = gconf_entry_get_key (entry); - - if (value == NULL || key == NULL) { - return; - } - - if (g_strcmp0 (key, LOCKDOWN_KEY_USER) == 0 || g_strcmp0 (key, LOCKDOWN_KEY_SCREENSAVER) == 0) { - rebuild_session_items(session_root_menuitem, dbus_interface); - } - - return; -} - -static void -keybinding_changed (GConfClient *client, - guint cnxd_id, - GConfEntry *entry, - gpointer user_data) -{ - GConfValue *value = gconf_entry_get_value (entry); - const gchar *key = gconf_entry_get_key (entry); - - if (value == NULL || key == NULL) { - return; - } - - if (g_strcmp0 (key, KEY_LOCK_SCREEN) == 0) { - g_debug("Keybinding changed to: %s", gconf_value_get_string(value)); - if (lock_menuitem != NULL) { - dbusmenu_menuitem_property_set_shortcut_string(lock_menuitem, gconf_value_get_string(value)); - } - } - return; -} - -/* Ensures that we have a GConf client and if we build one - set up the signal handler. */ -static void -ensure_gconf_client (void) -{ - if (!gconf_client) { - gconf_client = gconf_client_get_default (); - - gconf_client_add_dir(gconf_client, LOCKDOWN_DIR, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL); - gconf_client_notify_add(gconf_client, LOCKDOWN_DIR, lockdown_changed, NULL, NULL, NULL); - - gconf_client_add_dir(gconf_client, KEYBINDING_DIR, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL); - gconf_client_notify_add(gconf_client, KEYBINDING_DIR, keybinding_changed, NULL, NULL, NULL); - } - return; -} - -/* Check to see if the lockdown key is protecting from - locking the screen. If not, lock it. */ -static void -lock_if_possible (void) { - ensure_gconf_client (); - - if (!gconf_client_get_bool (gconf_client, LOCKDOWN_KEY_SCREENSAVER, NULL)) { - lock_screen(NULL, 0, NULL); - } - - return; -} - -/* A return from the command to sleep the system. Make sure - that we unthrottle the screensaver. */ -static void -sleep_response (DBusGProxy * proxy, DBusGProxyCall * call, gpointer data) -{ - screensaver_unthrottle(); - return; -} - -/* Let's put this machine to sleep, with some info on how - it should sleep. */ -static void -machine_sleep (DbusmenuMenuitem * mi, guint timestamp, gpointer userdata) -{ - gchar * type = (gchar *)userdata; - - if (up_main_proxy == NULL) { - g_warning("Can not %s as no upower proxy", type); - } - - screensaver_throttle(type); - lock_if_possible(); - - dbus_g_proxy_begin_call(up_main_proxy, - type, - sleep_response, - 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; - - 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; - rebuild_session_items(session_root_menuitem, dbus_interface); - } - - return; -} - -/* Response to getting the hibernate property */ -static void -hibernate_prop_cb (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata) -{ - hibernate_call = NULL; - - 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; - rebuild_session_items(session_root_menuitem, dbus_interface); - } - - return; -} - -/* 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, - NULL, - 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, - NULL, - NULL, - G_TYPE_STRING, - UP_INTERFACE, - G_TYPE_STRING, - "CanHibernate", - G_TYPE_INVALID, - G_TYPE_VALUE, - G_TYPE_INVALID); - } - - return; -} - -/* 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_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; - } - - gboolean * can_do = (gboolean *)userdata; - - if (OUT_allowed != *can_do) { - *can_do = OUT_allowed; - rebuild_session_items (session_root_menuitem, dbus_interface); - } -} - -/* 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 (void) { - 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), - NULL, - NULL); - } - g_return_if_fail(up_prop_proxy != NULL); - /* Force an original "changed" event */ - up_changed_cb(up_main_proxy, NULL); - - /* Check to see if these are getting blocked by PolicyKit */ - org_freedesktop_UPower_suspend_allowed_async(up_main_proxy, - allowed_cb, - &allow_suspend); - org_freedesktop_UPower_hibernate_allowed_async(up_main_proxy, - allowed_cb, - &allow_hibernate); - - 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) -{ - gchar * helper = g_build_filename(LIBEXECDIR, "gtk-logout-helper", NULL); - 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); - - return; -} - -/* Checks to see if we can create sessions */ -static gboolean -check_new_session (void) -{ - return TRUE; -} - -/* 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; -} - -/* Builds up the menu for us */ -static void -rebuild_user_items (DbusmenuMenuitem *root, - UsersServiceDbus *service) -{ - 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_gconf_client (); - - /* Check to see which menu items we're allowed to have */ - can_activate = users_service_dbus_can_activate_session (service) && - !gconf_client_get_bool (gconf_client, LOCKDOWN_KEY_USER, NULL); - - /* Remove the old menu items if that makes sense */ - children = dbusmenu_menuitem_take_children (root); - 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(service, NULL); - - /* Build all of the user switching items */ - if (can_activate == TRUE) - { - 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 (root, switch_menuitem); - g_signal_connect (G_OBJECT (switch_menuitem), - DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK (activate_new_session), - service); - } - - GList * users = NULL; - users = users_service_dbus_get_user_list (service); - guint user_count = g_list_length(users); - // g_debug ("USER COUNT = %i", user_count); - // We only want to show this menu when we have more than one registered - // user - session_dbus_set_user_menu_visibility (session_dbus, user_count > 1); - - if (user_count > MINIMUM_USERS && user_count < MAXIMUM_USERS) { - users = g_list_sort (users, (GCompareFunc)compare_users_by_username); - } - - for (u = users; u != NULL; u = g_list_next (u)) { - user = u->data; - user->service = service; - - g_debug ("%i %s", (gint)user->uid, user->user_name); - - if (g_strcmp0(user->user_name, "guest") == 0) { - /* Check to see if the guest has sessions and so therefore should - get a check mark. */ - if (user->sessions != NULL) { - dbusmenu_menuitem_property_set_bool (guest_mi, - USER_ITEM_PROP_LOGGED_IN, - TRUE); - } - /* If we're showing user accounts, keep going through the list */ - if (user_count > MINIMUM_USERS && user_count < MAXIMUM_USERS) { - continue; - } - /* If not, we can stop here */ - break; - } - - if (user_count > MINIMUM_USERS && user_count < MAXIMUM_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 { - 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') { - 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); - } - - gboolean logged_in = g_strcmp0 (user->user_name, g_get_user_name()) == 0; - dbusmenu_menuitem_property_set_bool (mi, - USER_ITEM_PROP_IS_CURRENT_USER, - logged_in); - if (logged_in == 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 (session_dbus, user->real_name); - } - - dbusmenu_menuitem_child_append (root, 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 online 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 (root, separator1); - DbusmenuMenuitem * online_accounts_item = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (online_accounts_item, - DBUSMENU_MENUITEM_PROP_TYPE, - DBUSMENU_CLIENT_TYPES_DEFAULT); - dbusmenu_menuitem_property_set (online_accounts_item, - DBUSMENU_MENUITEM_PROP_LABEL, - _("Online Accounts...")); - - g_signal_connect (G_OBJECT (online_accounts_item), - DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK (activate_online_accounts), - NULL); - - dbusmenu_menuitem_child_append (root, online_accounts_item); -} - -// TODO -// Wait until dialog is complete to find out name to pass -// to the control centre. -static void -activate_online_accounts (DbusmenuMenuitem *mi, - guint timestamp, - gpointer user_data) -{ - GError * error = NULL; - if (!g_spawn_command_line_async("gnome-control-center online-accounts", &error)) - { - g_warning("Unable to show control centre: %s", error->message); - g_error_free(error); - } -} - -static void -rebuild_session_items (DbusmenuMenuitem *root, - UsersServiceDbus *service) -{ - gboolean can_lockscreen; - - /* Make sure we have a valid GConf client, and build one - if needed */ - ensure_gconf_client (); - - can_lockscreen = !gconf_client_get_bool ( gconf_client, - LOCKDOWN_KEY_SCREENSAVER, - NULL); - /* 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 = gconf_client_get_string(gconf_client, KEY_LOCK_SCREEN, NULL); - 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(root, lock_menuitem); - } - - /* Start going through the session based items. */ - - 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(root, 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 (root, suspend_mi); - g_signal_connect( G_OBJECT(suspend_mi), - DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK(machine_sleep), - "Suspend"); - } - - 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(root, hibernate_mi); - g_signal_connect (G_OBJECT(hibernate_mi), - DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK(machine_sleep), "Hibernate"); - } - - restart_mi = dbusmenu_menuitem_new(); - dbusmenu_menuitem_property_set (restart_mi, - DBUSMENU_MENUITEM_PROP_TYPE, - RESTART_ITEM_TYPE); - if (supress_confirmations()) { - dbusmenu_menuitem_property_set (restart_mi, - RESTART_ITEM_LABEL, - _("Restart")); - } else { - dbusmenu_menuitem_property_set (restart_mi, - RESTART_ITEM_LABEL, - _("Restart\342\200\246")); - } - dbusmenu_menuitem_property_set_bool (restart_mi, - DBUSMENU_MENUITEM_PROP_VISIBLE, - show_restart()); - dbusmenu_menuitem_child_append(root, restart_mi); - g_signal_connect (G_OBJECT(restart_mi), - DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK(show_dialog), "restart"); - - 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 (root, shutdown_mi); - g_signal_connect (G_OBJECT(shutdown_mi), - DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, - G_CALLBACK(show_dialog), "shutdown"); - - RestartShutdownLogoutMenuItems * restart_shutdown_logout_mi = g_new0 (RestartShutdownLogoutMenuItems, 1); - restart_shutdown_logout_mi->logout_mi = logout_mi; - restart_shutdown_logout_mi->restart_mi = restart_mi; - restart_shutdown_logout_mi->shutdown_mi = shutdown_mi; - - update_menu_entries(restart_shutdown_logout_mi); - - return; -} - -/* 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) -{ - DbusmenuMenuitem *root = (DbusmenuMenuitem *)user_data; - rebuild_user_items (root, service); - return; -} - /* When the service interface starts to shutdown, we should follow it. */ void @@ -749,52 +78,6 @@ service_shutdown (IndicatorService * service, gpointer user_data) return; } -/* When the directory changes we need to figure out how our menu - item should look. */ -static void -restart_dir_changed (void) -{ - gboolean restart_required = g_file_test("/var/run/reboot-required", G_FILE_TEST_EXISTS); - - if (restart_required) { - if (supress_confirmations()) { - dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("Restart to Complete Update")); - } else { - dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("Restart to Complete Update\342\200\246")); - } - dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_ICON, "system-restart-panel"); - if (session_dbus != NULL) { - session_dbus_set_name(session_dbus, ICON_RESTART); - } - } else { - if (supress_confirmations()) { - dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("Restart")); - } else { - dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("Restart\342\200\246")); - } - dbusmenu_menuitem_property_remove(restart_mi, RESTART_ITEM_ICON); - if (session_dbus != NULL) { - session_dbus_set_name(session_dbus, ICON_DEFAULT); - } - } - return; -} - -/* Buids a file watcher for the directory so that when it - changes we can check to see if our reboot-required is - there. */ -static void -setup_restart_watch (void) -{ - GFile * filedir = g_file_new_for_path("/var/run"); - GFileMonitor * filemon = g_file_monitor_directory(filedir, G_FILE_MONITOR_NONE, NULL, NULL); - if (filemon != NULL) { - g_signal_connect(G_OBJECT(filemon), "changed", G_CALLBACK(restart_dir_changed), NULL); - } - restart_dir_changed(); - return; -} - /* Main, is well, main. It brings everything up and throws us into the mainloop of no return. */ int @@ -810,41 +93,21 @@ main (int argc, char ** argv) 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); + g_signal_connect (G_OBJECT(service), + INDICATOR_SERVICE_SIGNAL_SHUTDOWN, + G_CALLBACK(service_shutdown), NULL); session_dbus = session_dbus_new(); - g_idle_add(lock_screen_setup, NULL); - - session_root_menuitem = dbusmenu_menuitem_new(); - g_debug("Session Root ID: %d", dbusmenu_menuitem_get_id(session_root_menuitem)); - - dbus_interface = g_object_new (USERS_SERVICE_DBUS_TYPE, NULL); - - rebuild_session_items (session_root_menuitem, dbus_interface); - + // Devices + DeviceMenuMgr* device_mgr = device_menu_mgr_new (session_dbus); DbusmenuServer * server = dbusmenu_server_new(INDICATOR_SESSION_DBUS_OBJECT); - dbusmenu_server_set_root(server, session_root_menuitem); + dbusmenu_server_set_root(server, device_mgr_get_root_item (device_mgr)); - users_root_menuitem = dbusmenu_menuitem_new(); - rebuild_user_items (users_root_menuitem, dbus_interface); - g_signal_connect (G_OBJECT (dbus_interface), - "user-added", - G_CALLBACK (user_change), - users_root_menuitem); - g_signal_connect (G_OBJECT (dbus_interface), - "user-removed", - G_CALLBACK (user_change), - users_root_menuitem); - - setup_restart_watch(); - - setup_up(); - - DbusmenuServer * users_server = dbusmenu_server_new (INDICATOR_USERS_DBUS_OBJECT); - dbusmenu_server_set_root (users_server, users_root_menuitem); + // Users + UserMenuMgr* user_mgr = user_menu_mgr_new (session_dbus); + DbusmenuServer* users_server = dbusmenu_server_new (INDICATOR_USERS_DBUS_OBJECT); + dbusmenu_server_set_root (users_server, user_mgr_get_root_item (user_mgr)); mainloop = g_main_loop_new(NULL, FALSE); g_main_loop_run(mainloop); diff --git a/src/udev-mgr.c b/src/udev-mgr.c new file mode 100644 index 0000000..6575ca5 --- /dev/null +++ b/src/udev-mgr.c @@ -0,0 +1,46 @@ +/* +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 "udev-mgr.h" + + +G_DEFINE_TYPE (UdevMgr, udev_mgr, G_TYPE_OBJECT); + +static void +udev_mgr_init (UdevMgr *object) +{ + /* TODO: Add initialization code here */ +} + +static void +udev_mgr_finalize (GObject *object) +{ + /* TODO: Add deinitalization code here */ + + 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; +} + diff --git a/src/udev-mgr.h b/src/udev-mgr.h new file mode 100644 index 0000000..1c5ae73 --- /dev/null +++ b/src/udev-mgr.h @@ -0,0 +1,51 @@ +/* +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> + +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; +}; + +struct _UdevMgr +{ + GObject parent_instance; +}; + +GType udev_mgr_get_type (void) G_GNUC_CONST; + +G_END_DECLS + +#endif /* _UDEV_MGR_H_ */ diff --git a/src/user-menu-mgr.c b/src/user-menu-mgr.c new file mode 100644 index 0000000..611bcc7 --- /dev/null +++ b/src/user-menu-mgr.c @@ -0,0 +1,357 @@ +/* +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 "gconf-helper.h" +#include "dbus-shared-names.h" +#include "dbusmenu-shared.h" +#include "lock-helper.h" +#include "users-service-dbus.h" + +static GConfClient * gconf_client = NULL; +static DbusmenuMenuitem *switch_menuitem = NULL; + +struct _UserMenuMgr +{ + GObject parent_instance; + UsersServiceDbus* users_dbus_interface; + 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 gint compare_users_by_username (const gchar *a, + const gchar *b); +static void activate_online_accounts (DbusmenuMenuitem *mi, + guint timestamp, + gpointer user_data); +static void user_menu_mgr_rebuild_items (UserMenuMgr *self); +static gboolean check_new_session (); +static void user_change (UsersServiceDbus *service, + const gchar *user_id, + gpointer user_data); + +static void ensure_gconf_client (); + +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->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-removed", + 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); + //GObjectClass* parent_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) +{ + 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_gconf_client (); + + /* Check to see which menu items we're allowed to have */ + can_activate = users_service_dbus_can_activate_session (self->users_dbus_interface) && + !gconf_client_get_bool (gconf_client, LOCKDOWN_KEY_USER, NULL); + + /* 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) + { + 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); + } + + GList * users = NULL; + users = users_service_dbus_get_user_list (self->users_dbus_interface); + self->user_count = g_list_length(users); + + g_debug ("USER COUNT = %i", self->user_count); + session_dbus_set_user_menu_visibility (self->session_dbus_interface, self->user_count > 1); + + if (self->user_count > MINIMUM_USERS && self->user_count < MAXIMUM_USERS) { + users = g_list_sort (users, (GCompareFunc)compare_users_by_username); + } + + for (u = users; u != NULL; u = g_list_next (u)) { + user = u->data; + user->service = self->users_dbus_interface; + + g_debug ("%i %s", (gint)user->uid, user->user_name); + + if (g_strcmp0(user->user_name, "guest") == 0) { + /* Check to see if the guest has sessions and so therefore should + get a check mark. */ + if (user->sessions != NULL) { + dbusmenu_menuitem_property_set_bool (guest_mi, + USER_ITEM_PROP_LOGGED_IN, + TRUE); + } + /* If we're showing user accounts, keep going through the list */ + if (self->user_count > MINIMUM_USERS && self->user_count < MAXIMUM_USERS) { + continue; + } + /* If not, we can stop here */ + break; + } + + if (self->user_count > MINIMUM_USERS && self->user_count < MAXIMUM_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 { + 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') { + 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); + } + + gboolean logged_in = g_strcmp0 (user->user_name, g_get_user_name()) == 0; + dbusmenu_menuitem_property_set_bool (mi, + USER_ITEM_PROP_IS_CURRENT_USER, + logged_in); + if (logged_in == 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); + } + + 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 online 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 * online_accounts_item = dbusmenu_menuitem_new(); + dbusmenu_menuitem_property_set (online_accounts_item, + DBUSMENU_MENUITEM_PROP_TYPE, + DBUSMENU_CLIENT_TYPES_DEFAULT); + dbusmenu_menuitem_property_set (online_accounts_item, + DBUSMENU_MENUITEM_PROP_LABEL, + _("Online Accounts...")); + + g_signal_connect (G_OBJECT (online_accounts_item), + DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, + G_CALLBACK (activate_online_accounts), + NULL); + + dbusmenu_menuitem_child_append (self->root_item, online_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_gconf_client (); + + if (!gconf_client_get_bool (gconf_client, LOCKDOWN_KEY_SCREENSAVER, NULL)) { + 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; +} + +// TODO +// Wait until dialog is complete to find out name to pass +// to the control centre. +static void +activate_online_accounts (DbusmenuMenuitem *mi, + guint timestamp, + gpointer user_data) +{ + GError * error = NULL; + if (!g_spawn_command_line_async("gnome-control-center online-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) +{ + //DbusmenuMenuitem *root = (DbusmenuMenuitem *)user_data; + // TODO sort this out. + //rebuild_user_items (root, service); + return; +} + +/* Ensures that we have a GConf client and if we build one + set up the signal handler. */ +static void +ensure_gconf_client () +{ + if (!gconf_client) { + gconf_client = gconf_client_get_default (); + gconf_client_add_dir (gconf_client, LOCKDOWN_DIR, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL); + gconf_client_add_dir (gconf_client, KEYBINDING_DIR, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL); + } +} + +DbusmenuMenuitem* +user_mgr_get_root_item (UserMenuMgr* self) +{ + return self->root_item; +} + + +/* + * Clean Entry Point + */ +UserMenuMgr* user_menu_mgr_new (SessionDbus* session_dbus) +{ + 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); + return user_mgr; +} + + diff --git a/src/user-menu-mgr.h b/src/user-menu-mgr.h new file mode 100644 index 0000000..ff2cb77 --- /dev/null +++ b/src/user-menu-mgr.h @@ -0,0 +1,53 @@ +/* +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-gtk3/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); + +DbusmenuMenuitem* user_mgr_get_root_item (UserMenuMgr* self); +G_END_DECLS + +#endif /* _USER_MENU_MGR_H_ */ |