aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am48
-rw-r--r--src/consolekit-session.xml435
-rw-r--r--src/dbus-shared-names.h12
-rw-r--r--src/gconf-helper.c57
-rw-r--r--src/gconf-helper.h8
-rw-r--r--src/gdm-local-display-factory.xml20
-rw-r--r--src/indicator-session.c164
-rw-r--r--src/lock-helper.c100
-rw-r--r--src/lock-helper.h2
-rw-r--r--src/session-dbus.c139
-rw-r--r--src/session-dbus.h55
-rw-r--r--src/session-dbus.xml15
-rw-r--r--src/session-service.c305
-rw-r--r--src/upower.xml309
-rw-r--r--src/users-service-dbus.c211
-rw-r--r--src/users-service-dbus.h7
16 files changed, 1684 insertions, 203 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index cd525bd..24e00e4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -11,6 +11,7 @@ sessionlibdir = $(INDICATORDIR)
sessionlib_LTLIBRARIES = libsession.la
libsession_la_SOURCES = \
indicator-session.c \
+ session-dbus-client.h \
dbus-shared-names.h \
dbusmenu-shared.h \
users-service-client.h
@@ -25,6 +26,20 @@ consolekit-manager-client.h: $(srcdir)/consolekit-manager.xml
--output=consolekit-manager-client.h \
$(srcdir)/consolekit-manager.xml
+consolekit-session-client.h: $(srcdir)/consolekit-session.xml
+ dbus-binding-tool \
+ --prefix=_consolekit_session_client \
+ --mode=glib-client \
+ --output=consolekit-session-client.h \
+ $(srcdir)/consolekit-session.xml
+
+gdm-local-display-factory-client.h: $(srcdir)/gdm-local-display-factory.xml
+ dbus-binding-tool \
+ --prefix=_gdm_local_display_factory_client \
+ --mode=glib-client \
+ --output=gdm-local-display-factory-client.h \
+ $(srcdir)/gdm-local-display-factory.xml
+
users-service-client.h: $(srcdir)/users-service.xml
dbus-binding-tool \
--prefix=_users_service_client \
@@ -32,6 +47,27 @@ users-service-client.h: $(srcdir)/users-service.xml
--output=users-service-client.h \
$(srcdir)/users-service.xml
+upower-client.h: $(srcdir)/upower.xml
+ dbus-binding-tool \
+ --prefix=_upower_client \
+ --mode=glib-client \
+ --output=upower-client.h \
+ $(srcdir)/upower.xml
+
+session-dbus-client.h: $(srcdir)/session-dbus.xml
+ dbus-binding-tool \
+ --prefix=_session_dbus_client \
+ --mode=glib-client \
+ --output=session-dbus-client.h \
+ $(srcdir)/session-dbus.xml
+
+session-dbus-server.h: $(srcdir)/session-dbus.xml
+ dbus-binding-tool \
+ --prefix=_session_dbus_server \
+ --mode=glib-server \
+ --output=session-dbus-server.h \
+ $(srcdir)/session-dbus.xml
+
users-service-marshal.h: $(srcdir)/users-service.list
glib-genmarshal --header \
--prefix=_users_service_marshal $(srcdir)/users-service.list \
@@ -50,6 +86,9 @@ indicator_session_service_SOURCES = \
lock-helper.c \
lock-helper.h \
session-service.c \
+ session-dbus.c \
+ session-dbus.h \
+ session-dbus-server.h \
dbusmenu-shared.h \
gconf-helper.c \
users-service-dbus.h \
@@ -88,12 +127,21 @@ gtk_logout_helper_LDADD = \
BUILT_SOURCES = \
consolekit-manager-client.h \
+ consolekit-session-client.h \
+ gdm-local-display-factory-client.h \
+ session-dbus-client.h \
+ session-dbus-server.h \
+ upower-client.h \
users-service-client.h \
users-service-marshal.h \
users-service-marshal.c
EXTRA_DIST = \
consolekit-manager.xml \
+ consolekit-session.xml \
+ gdm-local-display-factory.xml \
+ session-dbus.xml \
+ upower.xml \
users-service.xml \
users-service.list
diff --git a/src/consolekit-session.xml b/src/consolekit-session.xml
new file mode 100644
index 0000000..b6e1cdb
--- /dev/null
+++ b/src/consolekit-session.xml
@@ -0,0 +1,435 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<node xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+
+ <interface name="org.freedesktop.ConsoleKit.Session">
+ <doc:doc>
+ <doc:description>
+ <doc:para>Session objects represent and store information
+ related to a user session.
+ </doc:para>
+ <doc:para>The properties associated with the Session
+ specifically refer to the properties of the "session leader".
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ <method name="GetId">
+ <arg name="ssid" direction="out" type="o">
+ <doc:doc>
+ <doc:summary>Session ID</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description><doc:para>Returns the ID for Session.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+ <method name="GetSeatId">
+ <arg name="sid" direction="out" type="o">
+ <doc:doc>
+ <doc:summary>Seat ID</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description><doc:para>Returns the ID for the Seat the Session is
+ attached to.</doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="interface" to="Seat">org.freedesktop.ConsoleKit.Seat</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+ <method name="GetSessionType">
+ <arg name="type" direction="out" type="s">
+ <doc:doc>
+ <doc:summary>Session type</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Returns the type of the session.</doc:para>
+ <doc:para>Warning: we haven't yet defined the allowed values for this property.
+ It is probably best to avoid this until we do.
+ </doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="property" to="Session:session-type">session-type</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+ <method name="GetUser">
+ <arg name="uid" direction="out" type="u">
+ <doc:doc>
+ <doc:summary>User ID</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description><doc:para>Returns the user that the session belongs to.</doc:para>
+ </doc:description>
+ <doc:deprecated version="0.1.3" instead="GetUnixUser"/>
+ <doc:seealso><doc:ref type="property" to="Session:user">user</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+ <method name="GetUnixUser">
+ <arg name="uid" direction="out" type="u">
+ <doc:doc>
+ <doc:summary>POSIX User ID</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description><doc:para>Returns the POSIX user ID that the session belongs to.</doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="property" to="Session:unix-user">unix-user</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+ <method name="GetX11Display">
+ <arg name="display" direction="out" type="s">
+ <doc:doc>
+ <doc:summary>The value of the X11 display</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description><doc:para>Returns the value of the X11 DISPLAY for this session
+ if one is present.</doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="property" to="Session:x11-display">x11-display</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+ <method name="GetX11DisplayDevice">
+ <arg name="x11_display_device" direction="out" type="s">
+ <doc:doc>
+ <doc:summary>The value of the X11 display device</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description><doc:para>Returns the value of the display device (aka TTY) that the
+ X11 display for the session is connected to. If there is no x11-display set then this value
+ is undefined.</doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="property" to="Session:x11-display-device">x11-display-device</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+ <method name="GetDisplayDevice">
+ <arg name="display_device" direction="out" type="s">
+ <doc:doc>
+ <doc:summary>The value of the display device</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description><doc:para>Returns the value of the display device (aka TTY) that the
+ session is connected to.</doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="property" to="Session:display-device">display-device</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+ <method name="GetRemoteHostName">
+ <arg name="remote_host_name" direction="out" type="s">
+ <doc:doc>
+ <doc:summary>The remote host name</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description><doc:para>Returns the value of the remote host name for the session.
+ </doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="property" to="Session:remote-host-name">remote-host-name</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+ <method name="GetLoginSessionId">
+ <arg name="login_session_id" direction="out" type="s">
+ <doc:doc>
+ <doc:summary>The value of the native system login session ID</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description><doc:para>Returns the value of the login session ID that the
+ underlying system uses to enforce session boundaries. If there is no login session ID
+ set then this value is an empty string.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+ <method name="IsActive">
+ <arg name="active" direction="out" type="b">
+ <doc:doc>
+ <doc:summary>TRUE if the session is active, otherwise FALSE</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description><doc:para>Returns whether the session is active on the Seat that
+ it is attached to.</doc:para>
+ <doc:para>If the session is not attached to a seat this value is undefined.
+ </doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="property" to="Session:active">active</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+ <method name="IsLocal">
+ <arg name="local" direction="out" type="b">
+ <doc:doc>
+ <doc:summary>TRUE if the session is local, otherwise FALSE</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description><doc:para>Returns whether the session is local</doc:para>
+ <doc:para>FIXME: we need to come up with a concrete definition for this value.
+ It was originally used as a way to identify XDMCP sessions that originate
+ from a remote system.
+ </doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="property" to="Session:is-local">is-local</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+ <method name="GetCreationTime">
+ <arg name="iso8601_datetime" type="s" direction="out">
+ <doc:doc>
+ <doc:summary>An ISO 8601 format date-type string</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Returns an ISO 8601 date-time string that corresponds to
+ the time that the session was opened.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <method name="Activate">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Attempt to activate the this session. In most
+ cases, if successful, this will cause the session to
+ become visible and become active on the seat that it
+ is attached to.</doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="method" to="Seat.ActivateSession">Seat.ActivateSession()</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+ <method name="Lock">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <doc:doc>
+ <doc:description>
+ <doc:para>This will cause a <doc:ref type="signal" to="Session::Lock">Lock</doc:ref>
+ signal to be emitted for this session.
+ </doc:para>
+ </doc:description>
+ <doc:permission>This method is restricted to privileged users by D-Bus policy.</doc:permission>
+ <doc:seealso><doc:ref type="signal" to="Session::Lock">Lock signal</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+ <method name="Unlock">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <doc:doc>
+ <doc:description>
+ <doc:para>This will cause an <doc:ref type="signal" to="Session::Unlock">Unlock</doc:ref>
+ signal to be emitted for this session.
+ </doc:para>
+ <doc:para>This can be used by login managers to unlock a session before it is
+ re-activated during fast-user-switching.
+ </doc:para>
+ </doc:description>
+ <doc:permission>This method is restricted to privileged users by D-Bus policy.</doc:permission>
+ <doc:seealso><doc:ref type="signal" to="Session::Unlock">Unlock signal</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+
+ <method name="GetIdleHint">
+ <arg name="idle_hint" type="b" direction="out">
+ <doc:doc>
+ <doc:summary>The value of the idle-hint</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Gets the value of the <doc:ref type="property" to="Session:idle-hint">idle-hint</doc:ref>
+ property.
+ </doc:para>
+ </doc:description>
+ <doc:seealso><doc:ref type="property" to="Session:idle-hint">idle-hint</doc:ref></doc:seealso>
+ </doc:doc>
+ </method>
+ <method name="GetIdleSinceHint">
+ <arg name="iso8601_datetime" type="s" direction="out">
+ <doc:doc>
+ <doc:summary>An ISO 8601 format date-type string</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Returns an ISO 8601 date-time string that corresponds to
+ the time of the last change of the idle-hint.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+ <method name="SetIdleHint">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="idle_hint" type="b" direction="in">
+ <doc:doc>
+ <doc:summary>boolean value to set the idle-hint to</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>This may be used by the session to indicate that
+ it is idle.
+ </doc:para>
+ <doc:para>Use of this method is restricted to the user
+ that owns the session.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <signal name="ActiveChanged">
+ <arg name="is_active" type="b">
+ <doc:doc>
+ <doc:summary>TRUE if the session is active, otherwise FALSE</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Emitted when the active property has changed.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+ <signal name="IdleHintChanged">
+ <arg name="hint" type="b">
+ <doc:doc>
+ <doc:summary>the new value of idle-hint</doc:summary>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>Emitted when the idle-hint property has changed.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+ <signal name="Lock">
+ <doc:doc>
+ <doc:description>
+ <doc:para>Emitted in response to a call to the <doc:ref type="method" to="Session.Lock">Lock()</doc:ref> method.</doc:para>
+ <doc:para>It is intended that the screensaver for the session should lock the screen in response to this signal.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+ <signal name="Unlock">
+ <doc:doc>
+ <doc:description>
+ <doc:para>Emitted in response to a call to the <doc:ref type="method" to="Session.Unlock">Unlock()</doc:ref> method.</doc:para>
+ <doc:para>It is intended that the screensaver for the session should unlock the screen in response to this signal.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <property name="unix-user" type="u" access="readwrite">
+ <doc:doc>
+ <doc:description>
+ <doc:para>The user assigned to the session.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+ <property name="user" type="u" access="readwrite">
+ <doc:doc>
+ <doc:description>
+ <doc:para>The user assigned to the session.</doc:para>
+ </doc:description>
+ <doc:deprecated version="0.1.3" instead="unix-user"/>
+ </doc:doc>
+ </property>
+ <property name="session-type" type="s" access="readwrite">
+ <doc:doc>
+ <doc:description>
+ <doc:para>The type of the session.</doc:para>
+ <doc:para>Warning: we haven't yet defined the allowed values for this property.
+ It is probably best to avoid this until we do.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+ <property name="remote-host-name" type="s" access="readwrite">
+ <doc:doc>
+ <doc:description>
+ <doc:para>The remote host name for the session.
+ </doc:para>
+ <doc:para>This will be set in situations where the session is
+ opened and controlled from a remote system.
+ </doc:para>
+ <doc:para>For example, this value will be set when the
+ session is created from an SSH or XDMCP connection.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+ <property name="display-device" type="s" access="readwrite">
+ <doc:doc>
+ <doc:description>
+ <doc:para>The display device (aka TTY) that the
+ session is connected to.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+ <property name="x11-display" type="s" access="readwrite">
+ <doc:doc>
+ <doc:description>
+ <doc:para>Value of the X11 DISPLAY for this session
+ if one is present.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+ <property name="x11-display-device" type="s" access="readwrite">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ The display device (aka TTY) that the X11 display for the
+ session is connected to. If there is no x11-display set then
+ this value is undefined.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+ <property name="active" type="b" access="readwrite">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Whether the session is active on the Seat that
+ it is attached to.</doc:para>
+ <doc:para>If the session is not attached to a seat this value is undefined.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+ <property name="is-local" type="b" access="readwrite">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Whether the session is local</doc:para>
+ <doc:para>FIXME: we need to come up with a concrete definition for this value.
+ It was originally used as a way to identify XDMCP sessions that originate
+ from a remote system.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+ <property name="idle-hint" type="b" access="readwrite">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ This is a hint used to indicate that the session may be idle.
+ </doc:para>
+ <doc:para>
+ For sessions with a <doc:ref type="property" to="Session:x11-display">x11-display</doc:ref> set (ie. graphical
+ sessions), it is up to each session to delegate the
+ responsibility for updating this value. Typically, the
+ screensaver will set this.
+ </doc:para>
+ <doc:para>However, for non-graphical sessions with a <doc:ref type="property" to="Session:display-device">display-device</doc:ref> set
+ the Session object itself will periodically update this value based
+ on the activity detected on the display-device itself.
+ </doc:para>
+ <doc:para>
+ This should not be considered authoritative.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ </interface>
+</node>
diff --git a/src/dbus-shared-names.h b/src/dbus-shared-names.h
index 253cba8..3ac14b3 100644
--- a/src/dbus-shared-names.h
+++ b/src/dbus-shared-names.h
@@ -38,8 +38,20 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#define INDICATOR_SESSION_DBUS_OBJECT "/org/ayatana/indicator/session/menu"
#define INDICATOR_SESSION_DBUS_VERSION 0
+#define INDICATOR_SESSION_SERVICE_DBUS_OBJECT "/org/ayatana/indicator/session/service"
+#define INDICATOR_SESSION_SERVICE_DBUS_IFACE "org.ayatana.indicator.session.service"
+
#define USER_ITEM_TYPE "x-canonical-user-item"
#define USER_ITEM_PROP_NAME "user-item-name"
#define USER_ITEM_PROP_LOGGED_IN "user-item-logged-in"
+#define USER_ITEM_PROP_ICON "user-item-icon-path"
+#define USER_ITEM_ICON_DEFAULT "default-icon"
+
+#define RESTART_ITEM_TYPE "x-canonical-restart-item"
+#define RESTART_ITEM_LABEL "restart-label"
+#define RESTART_ITEM_ICON "restart-icon"
+
+#define ICON_DEFAULT "system-shutdown-panel"
+#define ICON_RESTART "system-shutdown-panel-restart"
#endif /* __DBUS_SHARED_NAMES_H__ */
diff --git a/src/gconf-helper.c b/src/gconf-helper.c
index 9262b19..29d8526 100644
--- a/src/gconf-helper.c
+++ b/src/gconf-helper.c
@@ -30,9 +30,12 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <libdbusmenu-glib/server.h>
#include <libdbusmenu-glib/menuitem.h>
+#include "dbus-shared-names.h"
#include "gconf-helper.h"
static GConfClient * gconf_client = NULL;
+static guint confirmation_notify = 0;
+static guint logout_notify = 0;
gboolean
supress_confirmations (void) {
@@ -42,6 +45,14 @@ supress_confirmations (void) {
return gconf_client_get_bool (gconf_client, SUPPRESS_KEY, NULL) ;
}
+gboolean
+show_logout (void) {
+ if(!gconf_client) {
+ gconf_client = gconf_client_get_default ();
+ }
+ return !gconf_client_get_bool (gconf_client, LOGOUT_KEY, NULL) ;
+}
+
static void update_menu_entries_callback (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer data) {
RestartShutdownLogoutMenuItems * restart_shutdown_logout_mi = (RestartShutdownLogoutMenuItems*) data;
GConfValue * value = gconf_entry_get_value (entry);
@@ -50,24 +61,54 @@ static void update_menu_entries_callback (GConfClient *client, guint cnxn_id, GC
if(g_strcmp0 (key, SUPPRESS_KEY) == 0) {
if (gconf_value_get_bool (value)) {
dbusmenu_menuitem_property_set(restart_shutdown_logout_mi->logout_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Log Out"));
- dbusmenu_menuitem_property_set(restart_shutdown_logout_mi->restart_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Restart"));
- dbusmenu_menuitem_property_set(restart_shutdown_logout_mi->shutdown_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Switch Off"));
+ dbusmenu_menuitem_property_set(restart_shutdown_logout_mi->restart_mi, RESTART_ITEM_LABEL, _("Restart"));
+ dbusmenu_menuitem_property_set(restart_shutdown_logout_mi->shutdown_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Shut Down"));
} else {
dbusmenu_menuitem_property_set(restart_shutdown_logout_mi->logout_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Log Out..."));
- dbusmenu_menuitem_property_set(restart_shutdown_logout_mi->restart_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Restart..."));
- dbusmenu_menuitem_property_set(restart_shutdown_logout_mi->shutdown_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Switch Off..."));
+ dbusmenu_menuitem_property_set(restart_shutdown_logout_mi->restart_mi, RESTART_ITEM_LABEL, _("Restart..."));
+ dbusmenu_menuitem_property_set(restart_shutdown_logout_mi->shutdown_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Shut Down..."));
}
}
}
+static void
+update_logout_callback (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer data) {
+ DbusmenuMenuitem * mi = (DbusmenuMenuitem*) data;
+ GConfValue * value = gconf_entry_get_value (entry);
+ const gchar * key = gconf_entry_get_key (entry);
+
+ if(g_strcmp0 (key, LOGOUT_KEY) == 0) {
+ dbusmenu_menuitem_property_set_bool(mi, DBUSMENU_MENUITEM_PROP_VISIBLE, !gconf_value_get_bool(value));
+ }
+}
+
void
-update_menu_entries(RestartShutdownLogoutMenuItems * restart_shutdown_logout_mi) {
+update_menu_entries(RestartShutdownLogoutMenuItems * restart_shutdown_logout_mi, DbusmenuMenuitem * logoutitem) {
+ /* If we don't have a client, build one. */
if(!gconf_client) {
gconf_client = gconf_client_get_default ();
}
- gconf_client_add_dir (gconf_client, GLOBAL_DIR,
- GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
- gconf_client_notify_add (gconf_client, SUPPRESS_KEY,
+
+ /* If we've not gotten any notifications, then we need
+ to add the directory for notifications to come from. */
+ if (confirmation_notify == 0 || logout_notify == 0) {
+ gconf_client_add_dir (gconf_client, GLOBAL_DIR,
+ GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+ }
+
+ if (confirmation_notify != 0) {
+ gconf_client_notify_remove (gconf_client, confirmation_notify);
+ confirmation_notify = 0;
+ }
+
+ if (logout_notify != 0) {
+ gconf_client_notify_remove (gconf_client, logout_notify);
+ logout_notify = 0;
+ }
+
+ confirmation_notify = gconf_client_notify_add (gconf_client, SUPPRESS_KEY,
update_menu_entries_callback, restart_shutdown_logout_mi, NULL, NULL);
+ logout_notify = gconf_client_notify_add (gconf_client, LOGOUT_KEY,
+ update_logout_callback, logoutitem, NULL, NULL);
}
diff --git a/src/gconf-helper.h b/src/gconf-helper.h
index 951bb0f..6f9bcb7 100644
--- a/src/gconf-helper.h
+++ b/src/gconf-helper.h
@@ -33,8 +33,9 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <libdbusmenu-glib/server.h>
#include <libdbusmenu-glib/menuitem.h>
-#define SUPPRESS_KEY "/apps/indicator-session/suppress_logout_restart_shutdown"
-#define GLOBAL_DIR "/apps/indicator-session"
+#define GLOBAL_DIR "/apps/indicator-session"
+#define SUPPRESS_KEY GLOBAL_DIR "/suppress_logout_restart_shutdown"
+#define LOGOUT_KEY GLOBAL_DIR "/suppress_logout_menuitem"
typedef struct _RestartShutdownLogoutMenuItems
{
@@ -44,7 +45,8 @@ typedef struct _RestartShutdownLogoutMenuItems
}
RestartShutdownLogoutMenuItems;
-void update_menu_entries(RestartShutdownLogoutMenuItems*);
+void update_menu_entries(RestartShutdownLogoutMenuItems*, DbusmenuMenuitem * logoutitem);
gboolean supress_confirmations (void);
+gboolean show_logout (void);
#endif /* __GCONF_HELPER__ */
diff --git a/src/gdm-local-display-factory.xml b/src/gdm-local-display-factory.xml
new file mode 100644
index 0000000..66fb77c
--- /dev/null
+++ b/src/gdm-local-display-factory.xml
@@ -0,0 +1,20 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node name="/org/gnome/DisplayManager/LocalDisplayFactory">
+ <interface name="org.gnome.DisplayManager.LocalDisplayFactory">
+ <method name="CreateProductDisplay">
+ <arg name="parent_display_id" direction="in" type="o"/>
+ <arg name="relay_address" direction="in" type="s"/>
+ <arg name="id" direction="out" type="o"/>
+ </method>
+ <method name="CreateTransientDisplay">
+ <arg name="id" direction="out" type="o"/>
+ </method>
+ <method name="StartGuestSession">
+ <arg name="id" direction="out" type="o"/>
+ </method>
+ <method name="SwitchToUser">
+ <arg name="username" direction="in" type="s"/>
+ <arg name="id" direction="out" type="o"/>
+ </method>
+ </interface>
+</node>
diff --git a/src/indicator-session.c b/src/indicator-session.c
index 54431ee..b54a5d9 100644
--- a/src/indicator-session.c
+++ b/src/indicator-session.c
@@ -28,6 +28,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <glib-object.h>
#include <glib/gi18n-lib.h>
#include <gtk/gtk.h>
+#include <gio/gio.h>
#include <libdbusmenu-gtk/menu.h>
#include <dbus/dbus-glib.h>
@@ -36,9 +37,11 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <libindicator/indicator.h>
#include <libindicator/indicator-object.h>
#include <libindicator/indicator-service-manager.h>
+#include <libindicator/indicator-image-helper.h>
#include "dbus-shared-names.h"
#include "dbusmenu-shared.h"
+#include "session-dbus-client.h"
#define INDICATOR_SESSION_TYPE (indicator_session_get_type ())
#define INDICATOR_SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_SESSION_TYPE, IndicatorSession))
@@ -59,6 +62,7 @@ struct _IndicatorSession {
IndicatorServiceManager * service;
GtkImage * status_image;
DbusmenuGtkMenu * menu;
+ DBusGProxy * service_proxy;
};
GType indicator_session_get_type (void);
@@ -73,6 +77,9 @@ static GtkImage * get_icon (IndicatorObject * io);
static GtkMenu * get_menu (IndicatorObject * io);
static gboolean build_menu_switch (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client);
static gboolean new_user_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client);
+static void icon_changed (DBusGProxy * proxy, gchar * icon_name, gpointer user_data);
+static void service_connection_cb (IndicatorServiceManager * sm, gboolean connected, gpointer user_data);
+static gboolean build_restart_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client);
static void indicator_session_class_init (IndicatorSessionClass *klass);
static void indicator_session_init (IndicatorSession *self);
@@ -105,13 +112,29 @@ indicator_session_init (IndicatorSession *self)
/* Now let's fire these guys up. */
self->service = indicator_service_manager_new_version(INDICATOR_SESSION_DBUS_NAME, INDICATOR_SESSION_DBUS_VERSION);
+ g_signal_connect(G_OBJECT(self->service), INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE, G_CALLBACK(service_connection_cb), self);
- self->status_image = GTK_IMAGE(gtk_image_new_from_icon_name("system-shutdown-panel", GTK_ICON_SIZE_MENU));
+ self->status_image = indicator_image_helper(ICON_DEFAULT);
self->menu = dbusmenu_gtkmenu_new(INDICATOR_SESSION_DBUS_NAME, INDICATOR_SESSION_DBUS_OBJECT);
DbusmenuClient * client = DBUSMENU_CLIENT(dbusmenu_gtkmenu_get_client(self->menu));
dbusmenu_client_add_type_handler(client, MENU_SWITCH_TYPE, build_menu_switch);
dbusmenu_client_add_type_handler(client, USER_ITEM_TYPE, new_user_item);
+ dbusmenu_client_add_type_handler(client, RESTART_ITEM_TYPE, build_restart_item);
+
+ DBusGConnection * session_bus = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
+ self->service_proxy = dbus_g_proxy_new_for_name(session_bus,
+ INDICATOR_SESSION_DBUS_NAME,
+ INDICATOR_SESSION_SERVICE_DBUS_OBJECT,
+ INDICATOR_SESSION_SERVICE_DBUS_IFACE);
+
+ dbus_g_proxy_add_signal(self->service_proxy, "IconUpdated",
+ G_TYPE_STRING, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal(self->service_proxy,
+ "IconUpdated",
+ G_CALLBACK(icon_changed),
+ self,
+ NULL);
return;
}
@@ -126,6 +149,11 @@ indicator_session_dispose (GObject *object)
self->service = NULL;
}
+ if (self->service_proxy != NULL) {
+ g_object_unref(self->service_proxy);
+ self->service_proxy = NULL;
+ }
+
G_OBJECT_CLASS (indicator_session_parent_class)->dispose (object);
return;
}
@@ -138,12 +166,50 @@ indicator_session_finalize (GObject *object)
return;
}
+static void
+icon_name_get_cb (DBusGProxy *proxy, char * OUT_name, GError *error, gpointer userdata)
+{
+ if (error != NULL) {
+ return;
+ }
+
+ if (OUT_name == NULL || OUT_name[0] == '\0') {
+ return;
+ }
+
+ IndicatorSession * self = INDICATOR_SESSION(userdata);
+ indicator_image_helper_update(self->status_image, OUT_name);
+ return;
+}
+
+static void
+service_connection_cb (IndicatorServiceManager * sm, gboolean connected, gpointer user_data)
+{
+ IndicatorSession * self = INDICATOR_SESSION(user_data);
+
+ if (connected) {
+ org_ayatana_indicator_session_service_get_icon_async(self->service_proxy, icon_name_get_cb, user_data);
+ } else {
+ indicator_image_helper_update(self->status_image, ICON_DEFAULT);
+ }
+
+ return;
+}
+
static GtkLabel *
get_label (IndicatorObject * io)
{
return NULL;
}
+static void
+icon_changed (DBusGProxy * proxy, gchar * icon_name, gpointer user_data)
+{
+ IndicatorSession * session = INDICATOR_SESSION(user_data);
+ indicator_image_helper_update(session->status_image, icon_name);
+ return;
+}
+
static GtkImage *
get_icon (IndicatorObject * io)
{
@@ -151,12 +217,45 @@ get_icon (IndicatorObject * io)
return INDICATOR_SESSION(io)->status_image;
}
+static void
+user_property_change (DbusmenuMenuitem * item, const gchar * property, const GValue * value, gpointer user_data)
+{
+ if (g_strcmp0(property, USER_ITEM_PROP_LOGGED_IN) == 0) {
+ if (g_value_get_boolean(value)) {
+ gtk_widget_show(GTK_WIDGET(user_data));
+ } else {
+ gtk_widget_hide(GTK_WIDGET(user_data));
+ }
+ }
+ return;
+}
+
/* Builds an item with a hip little logged in icon. */
static gboolean
new_user_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client)
{
GtkMenuItem * gmi = GTK_MENU_ITEM(gtk_menu_item_new());
- GtkWidget * hbox = gtk_hbox_new(FALSE, 0);
+ gint padding = 0;
+ gtk_widget_style_get(GTK_WIDGET(gmi), "horizontal-padding", &padding, NULL);
+ GtkWidget * hbox = gtk_hbox_new(FALSE, padding);
+
+ GtkWidget * usericon = NULL;
+ const gchar * icon_name = dbusmenu_menuitem_property_get(newitem, USER_ITEM_PROP_ICON);
+ g_debug("Using user icon for '%s' from file: %s", dbusmenu_menuitem_property_get(newitem, USER_ITEM_PROP_NAME), icon_name);
+ if (icon_name != NULL && icon_name[0] != '\0') {
+ if (g_strcmp0(icon_name, USER_ITEM_ICON_DEFAULT) == 0 || !g_file_test(icon_name, G_FILE_TEST_EXISTS)) {
+ GIcon * gicon = g_themed_icon_new_with_default_fallbacks("stock_person-panel");
+ usericon = gtk_image_new_from_gicon(gicon, GTK_ICON_SIZE_MENU);
+ g_object_unref(gicon);
+ } else {
+ usericon = gtk_image_new_from_file(icon_name);
+ }
+ }
+ if (usericon != NULL) {
+ gtk_misc_set_alignment(GTK_MISC(usericon), 0.0, 0.5);
+ gtk_box_pack_start(GTK_BOX(hbox), usericon, FALSE, FALSE, 0);
+ gtk_widget_show(usericon);
+ }
GtkWidget * label = gtk_label_new(dbusmenu_menuitem_property_get(newitem, USER_ITEM_PROP_NAME));
gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.5);
@@ -177,6 +276,8 @@ new_user_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuCl
dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, gmi, parent);
+ g_signal_connect(G_OBJECT(newitem), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(user_property_change), icon);
+
return TRUE;
}
@@ -233,7 +334,7 @@ switch_property_change (DbusmenuMenuitem * item, const gchar * property, const G
/* TODO: We need some way to remove the elipsis from appearing
twice in the label. Not sure how to do that yet. */
- finalstring = g_strdup_printf(_("Switch from %s..."), username);
+ finalstring = g_strdup_printf(_("Switch From %s..."), username);
if (ems >= 20.0f) {
set_ellipsize = TRUE;
} else {
@@ -257,6 +358,62 @@ switch_property_change (DbusmenuMenuitem * item, const gchar * property, const G
static const gchar * dbusmenu_item_data = "dbusmenu-item";
+/* IF the label or icon changes we need to grab that and update
+ the menu item */
+static void
+restart_property_change (DbusmenuMenuitem * item, const gchar * property, const GValue * value, gpointer user_data)
+{
+ DbusmenuGtkClient * client = DBUSMENU_GTKCLIENT(user_data);
+ GtkMenuItem * gmi = dbusmenu_gtkclient_menuitem_get(client, item);
+
+ if (g_strcmp0(property, RESTART_ITEM_LABEL) == 0) {
+ gtk_menu_item_set_label(gmi, g_value_get_string(value));
+ } else if (g_strcmp0(property, RESTART_ITEM_ICON) == 0) {
+ GtkWidget * image = gtk_image_menu_item_get_image(GTK_IMAGE_MENU_ITEM(gmi));
+
+ GIcon * gicon = g_themed_icon_new_with_default_fallbacks(g_value_get_string(value));
+ if (image == NULL) {
+ image = gtk_image_new_from_gicon(gicon, GTK_ICON_SIZE_MENU);
+ gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(gmi), image);
+ } else {
+ gtk_image_set_from_gicon(GTK_IMAGE(image), gicon, GTK_ICON_SIZE_MENU);
+ }
+ g_object_unref(G_OBJECT(gicon));
+ }
+
+ return;
+}
+
+/* Builds the restart item which is a more traditional GTK image
+ menu item that puts the graphic into the gutter. */
+static gboolean
+build_restart_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client)
+{
+ GtkMenuItem * gmi = GTK_MENU_ITEM(gtk_image_menu_item_new());
+ if (gmi == NULL) {
+ return FALSE;
+ }
+
+ dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, gmi, parent);
+
+ g_signal_connect(G_OBJECT(newitem), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(restart_property_change), client);
+
+ /* Grab the inital values and put them into the item */
+ const GValue * value;
+ value = dbusmenu_menuitem_property_get_value(newitem, RESTART_ITEM_LABEL);
+ if (value != NULL) {
+ restart_property_change(newitem, RESTART_ITEM_LABEL, value, client);
+ }
+
+ value = dbusmenu_menuitem_property_get_value(newitem, RESTART_ITEM_ICON);
+ if (value != NULL) {
+ restart_property_change(newitem, RESTART_ITEM_ICON, value, client);
+ }
+
+ return TRUE;
+}
+
+
/* Callback for when the style changes so we can reevaluate the
size of the user name with the potentially new font. */
static void
@@ -269,7 +426,6 @@ switch_style_set (GtkWidget * widget, GtkStyle * prev_style, gpointer user_data)
return;
}
-
/* This function checks to see if the user name is short enough
to not need ellipsing itself, or if, it will get ellipsed by
the standard label processor. */
diff --git a/src/lock-helper.c b/src/lock-helper.c
index b38be65..ba6b182 100644
--- a/src/lock-helper.c
+++ b/src/lock-helper.c
@@ -19,9 +19,14 @@ You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <glib/gi18n.h>
+#include <gconf/gconf-client.h>
#include <dbus/dbus-glib.h>
#include "lock-helper.h"
+#define GCONF_DIR "/apps/gnome-screensaver"
+#define GCONF_KEY GCONF_DIR "/lock_enabled"
+
static DBusGProxy * gss_proxy = NULL;
static GMainLoop * gss_mainloop = NULL;
static guint cookie = 0;
@@ -29,6 +34,8 @@ static DBusGProxyCall * cookie_call = NULL;
static gboolean is_guest = FALSE;
+static GConfClient * gconf_client = NULL;
+
void build_gss_proxy (void);
/* Checks to see if there is an error and reports
@@ -124,7 +131,11 @@ will_lock_screen (void)
return FALSE;
}
- return TRUE;
+ if (gconf_client == NULL) {
+ gconf_client = gconf_client_get_default();
+ }
+
+ return gconf_client_get_bool (gconf_client, GCONF_KEY, NULL);
}
/* When the screensave go active, if we've got a mainloop
@@ -175,24 +186,45 @@ activate_timeout (gpointer data)
return FALSE;
}
+/* Handle errors from activating the screensaver */
+static void
+active_cb (DBusGProxy * proxy, DBusGProxyCall * call, gpointer user_data)
+{
+ GError * error = NULL;
+
+ dbus_g_proxy_end_call(proxy, call, &error, G_TYPE_INVALID);
+
+ if (error != NULL) {
+ g_warning("Unable to activate screensaver: %s", error->message);
+ g_error_free(error);
+ }
+
+ return;
+}
+
/* A fun little function to actually lock the screen. If,
that's what you want, let's do it! */
void
lock_screen (DbusmenuMenuitem * mi, guint timestamp, gpointer data)
{
g_debug("Lock Screen");
- if (!will_lock_screen()) {
- g_debug("\tGDM set to autologin, blocking lock");
- return;
- }
build_gss_proxy();
g_return_if_fail(gss_proxy != NULL);
- dbus_g_proxy_call_no_reply(gss_proxy,
- "Lock",
- G_TYPE_INVALID,
- G_TYPE_INVALID);
+ if (will_lock_screen()) {
+ dbus_g_proxy_call_no_reply(gss_proxy,
+ "Lock",
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+ } else {
+ dbus_g_proxy_begin_call(gss_proxy,
+ "SetActive",
+ active_cb, NULL,
+ NULL,
+ G_TYPE_BOOLEAN, TRUE,
+ G_TYPE_INVALID);
+ }
if (gss_mainloop == NULL) {
gss_mainloop = g_main_loop_new(NULL, FALSE);
@@ -221,3 +253,53 @@ lock_screen_setup (gpointer data)
return FALSE;
}
+/* When the GConf key changes we need to adjust the text on
+ what we're going to do with the menu item */
+static void
+lockscreen_update (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer data) {
+ DbusmenuMenuitem * mi = (DbusmenuMenuitem*) data;
+ const gchar * key = gconf_entry_get_key (entry);
+
+ if(g_strcmp0 (key, GCONF_KEY) == 0) {
+ if (will_lock_screen()) {
+ dbusmenu_menuitem_property_set(mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Lock Screen"));
+ } else {
+ dbusmenu_menuitem_property_set(mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Start Screensaver"));
+ }
+ }
+}
+
+/* Notification handler for lock menuitems. */
+static guint lock_notify = 0;
+
+/* Sets the menu item to be updating. There can
+ only be one. So we clear and reset if we get
+ another. */
+void
+lock_screen_update_item (DbusmenuMenuitem * mi)
+{
+ if (gconf_client == NULL) {
+ gconf_client = gconf_client_get_default();
+ }
+
+ if (lock_notify == 0) {
+ gconf_client_add_dir (gconf_client,
+ GCONF_DIR,
+ GCONF_CLIENT_PRELOAD_ONELEVEL,
+ NULL);
+ }
+
+ if (lock_notify != 0) {
+ gconf_client_notify_remove(gconf_client, lock_notify);
+ lock_notify = 0;
+ }
+
+ lock_notify = gconf_client_notify_add(gconf_client,
+ GCONF_KEY,
+ lockscreen_update,
+ mi,
+ NULL,
+ NULL);
+
+ return;
+}
diff --git a/src/lock-helper.h b/src/lock-helper.h
index 37f1448..1d707d8 100644
--- a/src/lock-helper.h
+++ b/src/lock-helper.h
@@ -31,4 +31,6 @@ gboolean will_lock_screen (void);
void lock_screen (DbusmenuMenuitem * mi, guint timestamp, gpointer data);
gboolean lock_screen_setup (gpointer data);
+void lock_screen_update_item (DbusmenuMenuitem * mi);
+
#endif /* LOCK_HELPER_H__ */
diff --git a/src/session-dbus.c b/src/session-dbus.c
new file mode 100644
index 0000000..20a0fa0
--- /dev/null
+++ b/src/session-dbus.c
@@ -0,0 +1,139 @@
+/*
+The Dbus object on the bus for the indicator.
+
+Copyright 2010 Canonical Ltd.
+
+Authors:
+ Ted Gould <ted@canonical.com>
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 3, as published
+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/>.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "session-dbus.h"
+#include "dbus-shared-names.h"
+
+static gboolean _session_dbus_server_get_icon (SessionDbus * service, gchar ** icon, GError ** error);
+
+#include "session-dbus-server.h"
+
+typedef struct _SessionDbusPrivate SessionDbusPrivate;
+struct _SessionDbusPrivate {
+ gchar * name;
+};
+
+/* Signals */
+enum {
+ ICON_UPDATED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+#define SESSION_DBUS_GET_PRIVATE(o) \
+(G_TYPE_INSTANCE_GET_PRIVATE ((o), SESSION_DBUS_TYPE, SessionDbusPrivate))
+
+static void session_dbus_class_init (SessionDbusClass *klass);
+static void session_dbus_init (SessionDbus *self);
+static void session_dbus_dispose (GObject *object);
+static void session_dbus_finalize (GObject *object);
+
+G_DEFINE_TYPE (SessionDbus, session_dbus, G_TYPE_OBJECT);
+
+static void
+session_dbus_class_init (SessionDbusClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (SessionDbusPrivate));
+
+ object_class->dispose = session_dbus_dispose;
+ object_class->finalize = session_dbus_finalize;
+
+ signals[ICON_UPDATED] = g_signal_new ("icon-updated",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (SessionDbusClass, icon_updated),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1, G_TYPE_STRING);
+
+ dbus_g_object_type_install_info(SESSION_DBUS_TYPE, &dbus_glib__session_dbus_server_object_info);
+
+ return;
+}
+
+static void
+session_dbus_init (SessionDbus *self)
+{
+ DBusGConnection * session = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
+ dbus_g_connection_register_g_object(session, INDICATOR_SESSION_SERVICE_DBUS_OBJECT, G_OBJECT(self));
+
+ SessionDbusPrivate * priv = SESSION_DBUS_GET_PRIVATE(self);
+
+ priv->name = g_strdup(ICON_DEFAULT);
+
+ return;
+}
+
+static void
+session_dbus_dispose (GObject *object)
+{
+
+ G_OBJECT_CLASS (session_dbus_parent_class)->dispose (object);
+ return;
+}
+
+static void
+session_dbus_finalize (GObject *object)
+{
+ SessionDbusPrivate * priv = SESSION_DBUS_GET_PRIVATE(object);
+
+ if (priv->name != NULL) {
+ g_free(priv->name);
+ priv->name = NULL;
+ }
+
+ G_OBJECT_CLASS (session_dbus_parent_class)->finalize (object);
+ return;
+}
+
+static gboolean
+_session_dbus_server_get_icon (SessionDbus * service, gchar ** icon, GError ** error)
+{
+ SessionDbusPrivate * priv = SESSION_DBUS_GET_PRIVATE(service);
+ *icon = g_strdup(priv->name);
+ return TRUE;
+}
+
+SessionDbus *
+session_dbus_new (void)
+{
+ return SESSION_DBUS(g_object_new(SESSION_DBUS_TYPE, NULL));
+}
+
+void
+session_dbus_set_name (SessionDbus * session, const gchar * name)
+{
+ SessionDbusPrivate * priv = SESSION_DBUS_GET_PRIVATE(session);
+ if (priv->name != NULL) {
+ g_free(priv->name);
+ priv->name = NULL;
+ }
+ priv->name = g_strdup(name);
+ g_signal_emit(G_OBJECT(session), signals[ICON_UPDATED], 0, priv->name, TRUE);
+ return;
+}
diff --git a/src/session-dbus.h b/src/session-dbus.h
new file mode 100644
index 0000000..792917b
--- /dev/null
+++ b/src/session-dbus.h
@@ -0,0 +1,55 @@
+/*
+The Dbus object on the bus for the indicator.
+
+Copyright 2010 Canonical Ltd.
+
+Authors:
+ Ted Gould <ted@canonical.com>
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 3, as published
+by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranties of
+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __SESSION_DBUS_H__
+#define __SESSION_DBUS_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define SESSION_DBUS_TYPE (session_dbus_get_type ())
+#define SESSION_DBUS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SESSION_DBUS_TYPE, SessionDbus))
+#define SESSION_DBUS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SESSION_DBUS_TYPE, SessionDbusClass))
+#define IS_SESSION_DBUS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SESSION_DBUS_TYPE))
+#define IS_SESSION_DBUS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SESSION_DBUS_TYPE))
+#define SESSION_DBUS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SESSION_DBUS_TYPE, SessionDbusClass))
+
+typedef struct _SessionDbus SessionDbus;
+typedef struct _SessionDbusClass SessionDbusClass;
+
+struct _SessionDbusClass {
+ GObjectClass parent_class;
+ void (*icon_updated) (SessionDbus * session, gchar * icon, gpointer user_data);
+};
+
+struct _SessionDbus {
+ GObject parent;
+};
+
+GType session_dbus_get_type (void);
+SessionDbus * session_dbus_new (void);
+void session_dbus_set_name (SessionDbus * session, const gchar * name);
+
+G_END_DECLS
+
+#endif
diff --git a/src/session-dbus.xml b/src/session-dbus.xml
new file mode 100644
index 0000000..3ce1693
--- /dev/null
+++ b/src/session-dbus.xml
@@ -0,0 +1,15 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node name="/org/ayatana/indicator/session/service">
+ <interface name="org.ayatana.indicator.session.service">
+
+ <!-- Icon -->
+ <method name="GetIcon">
+ <arg name="name" direction="out" type="s"/>
+ </method>
+
+ <signal name="IconUpdated">
+ <arg name="name" type="s"/>
+ </signal>
+
+ </interface>
+</node>
diff --git a/src/session-service.c b/src/session-service.c
index febf007..c1c2e57 100644
--- a/src/session-service.c
+++ b/src/session-service.c
@@ -28,6 +28,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <glib/gi18n.h>
#include <gio/gio.h>
+#include <gio/gdesktopappinfo.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-bindings.h>
@@ -43,17 +44,22 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#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 DESKTOP_FILE "/usr/share/applications/indicator-session-extra.desktop"
+
#define GUEST_SESSION_LAUNCHER "/usr/share/gdm/guest-session/guest-session-launch"
-#define LOCKDOWN_DIR "/desktop/gnome/lockdown"
-#define LOCKDOWN_KEY LOCKDOWN_DIR "/disable_user_switching"
+#define LOCKDOWN_DIR "/desktop/gnome/lockdown"
+#define LOCKDOWN_KEY_USER LOCKDOWN_DIR "/disable_user_switching"
+#define LOCKDOWN_KEY_SCREENSAVER LOCKDOWN_DIR "/disable_lock_screen"
typedef struct _ActivateData ActivateData;
struct _ActivateData
@@ -65,6 +71,7 @@ struct _ActivateData
static DBusGConnection *system_bus = NULL;
static DBusGProxy *gdm_proxy = NULL;
static UsersServiceDbus *dbus_interface = NULL;
+static SessionDbus *session_dbus = NULL;
static DbusmenuMenuitem *lock_menuitem = NULL;
static DbusmenuMenuitem *switch_menuitem = NULL;
@@ -83,8 +90,14 @@ 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 guint notify_lockdown_id = 0;
+
+static void rebuild_items (DbusmenuMenuitem *root, UsersServiceDbus *service);
static void
lockdown_changed (GConfClient *client,
@@ -92,42 +105,44 @@ lockdown_changed (GConfClient *client,
GConfEntry *entry,
gpointer user_data)
{
- GConfValue *value = gconf_entry_get_value (entry);
- const gchar *key = gconf_entry_get_key (entry);
+ GConfValue *value = gconf_entry_get_value (entry);
+ const gchar *key = gconf_entry_get_key (entry);
- if (!value || !key)
- return;
+ if (value == NULL || key == NULL) {
+ return;
+ }
- if (g_strcmp0 (key, LOCKDOWN_KEY) == 0)
- {
- if (switch_menuitem)
- {
- if (gconf_value_get_bool (value))
- {
- dbusmenu_menuitem_property_set_bool (switch_menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- }
- else
- {
- dbusmenu_menuitem_property_set_bool (switch_menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
- }
- }
- }
+ if (g_strcmp0 (key, LOCKDOWN_KEY_USER) == 0 || g_strcmp0 (key, LOCKDOWN_KEY_SCREENSAVER) == 0) {
+ rebuild_items(root_menuitem, dbus_interface);
+ }
+
+ 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 ();
-
- notify_lockdown_id = gconf_client_notify_add (gconf_client,
- LOCKDOWN_KEY,
- lockdown_changed,
- NULL,
- NULL,
- NULL);
- }
+ 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);
+ }
+ 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
@@ -151,7 +166,7 @@ machine_sleep (DbusmenuMenuitem * mi, guint timestamp, gpointer userdata)
}
screensaver_throttle(type);
- lock_screen(NULL, 0, NULL);
+ lock_if_possible();
dbus_g_proxy_begin_call(up_main_proxy,
type,
@@ -179,8 +194,10 @@ suspend_prop_cb (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata)
}
g_debug("Got Suspend: %s", g_value_get_boolean(&candoit) ? "true" : "false");
- if (suspend_mi != NULL) {
- dbusmenu_menuitem_property_set_value(suspend_mi, DBUSMENU_MENUITEM_PROP_VISIBLE, &candoit);
+ gboolean local_can_suspend = g_value_get_boolean(&candoit);
+ if (local_can_suspend != can_suspend) {
+ can_suspend = local_can_suspend;
+ rebuild_items(root_menuitem, dbus_interface);
}
return;
@@ -202,8 +219,10 @@ hibernate_prop_cb (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata)
}
g_debug("Got Hibernate: %s", g_value_get_boolean(&candoit) ? "true" : "false");
- if (suspend_mi != NULL) {
- dbusmenu_menuitem_property_set_value(hibernate_mi, DBUSMENU_MENUITEM_PROP_VISIBLE, &candoit);
+ gboolean local_can_hibernate = g_value_get_boolean(&candoit);
+ if (local_can_hibernate != can_hibernate) {
+ can_hibernate = local_can_hibernate;
+ rebuild_items(root_menuitem, dbus_interface);
}
return;
@@ -249,6 +268,25 @@ up_changed_cb (DBusGProxy * proxy, gpointer user_data)
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_items (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 */
@@ -270,23 +308,31 @@ setup_up (void) {
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);
- /* 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);
/* 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;
}
@@ -337,6 +383,16 @@ static void
activate_guest_session (DbusmenuMenuitem * mi, guint timestamp, gpointer user_data)
{
GError * error = NULL;
+
+ lock_if_possible();
+
+ if (dbusmenu_menuitem_property_get_bool(mi, USER_ITEM_PROP_LOGGED_IN)) {
+ if (users_service_dbus_activate_guest_session(USERS_SERVICE_DBUS(user_data))) {
+ return;
+ }
+ g_warning("Unable to activate guest session, falling back to command line activation.");
+ }
+
if (!g_spawn_command_line_async(GUEST_SESSION_LAUNCHER, &error)) {
g_warning("Unable to start guest session: %s", error->message);
g_error_free(error);
@@ -377,6 +433,9 @@ static void
activate_new_session (DbusmenuMenuitem * mi, guint timestamp, gpointer user_data)
{
GError * error = NULL;
+
+ lock_if_possible();
+
if (!g_spawn_command_line_async("gdmflexiserver --startnew", &error)) {
g_warning("Unable to start new session: %s", error->message);
g_error_free(error);
@@ -392,6 +451,8 @@ 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);
}
@@ -415,6 +476,16 @@ compare_users_by_username (const gchar *a,
return retval;
}
+/* Take a desktop file and execute it */
+static void
+desktop_activate_cb (DbusmenuMenuitem * mi, guint timestamp, gpointer data)
+{
+ GAppInfo * appinfo = G_APP_INFO(data);
+ g_return_if_fail(appinfo != NULL);
+ g_app_info_launch(appinfo, NULL, NULL, NULL);
+ return;
+}
+
/* Builds up the menu for us */
static void
rebuild_items (DbusmenuMenuitem *root,
@@ -425,29 +496,47 @@ rebuild_items (DbusmenuMenuitem *root,
GList *u;
UserData *user;
gboolean can_activate;
+ gboolean can_lockscreen;
GList *children;
- can_activate = users_service_dbus_can_activate_session (service);
+ /* 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);
+ can_lockscreen = !gconf_client_get_bool (gconf_client, LOCKDOWN_KEY_SCREENSAVER, 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);
- lock_menuitem = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set(lock_menuitem, DBUSMENU_MENUITEM_PROP_LABEL, _("Lock Screen"));
- g_signal_connect(G_OBJECT(lock_menuitem), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(lock_screen), NULL);
- dbusmenu_menuitem_child_append(root, lock_menuitem);
- if (!will_lock_screen()) {
- dbusmenu_menuitem_property_set_bool(lock_menuitem, DBUSMENU_MENUITEM_PROP_ENABLED, FALSE);
- } else {
- dbusmenu_menuitem_property_set_bool(lock_menuitem, DBUSMENU_MENUITEM_PROP_ENABLED, TRUE);
+ /* Lock screen item */
+ if (can_lockscreen) {
+ lock_menuitem = dbusmenu_menuitem_new();
+ if (will_lock_screen()) {
+ dbusmenu_menuitem_property_set(lock_menuitem, DBUSMENU_MENUITEM_PROP_LABEL, _("Lock Screen"));
+ } else {
+ dbusmenu_menuitem_property_set(lock_menuitem, DBUSMENU_MENUITEM_PROP_LABEL, _("Start Screensaver"));
+ }
+ g_signal_connect(G_OBJECT(lock_menuitem), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(lock_screen), NULL);
+ dbusmenu_menuitem_child_append(root, lock_menuitem);
+ lock_screen_update_item(lock_menuitem);
}
+ /* 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)
{
- DbusmenuMenuitem * separator1 = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set(separator1, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
- dbusmenu_menuitem_child_append(root, separator1);
+ if (can_lockscreen) {
+ DbusmenuMenuitem * separator1 = dbusmenu_menuitem_new();
+ dbusmenu_menuitem_property_set(separator1, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
+ dbusmenu_menuitem_child_append(root, separator1);
+ }
if (check_guest_session ())
{
@@ -457,26 +546,17 @@ rebuild_items (DbusmenuMenuitem *root,
dbusmenu_menuitem_property_set_bool (guest_mi, USER_ITEM_PROP_LOGGED_IN, FALSE);
dbusmenu_menuitem_child_append (root, guest_mi);
g_signal_connect (G_OBJECT (guest_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK (activate_guest_session), NULL);
+ users_service_dbus_set_guest_item(service, guest_mi);
}
if (check_new_session ())
{
- ensure_gconf_client ();
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), NULL);
-
- if (gconf_client_get_bool (gconf_client, LOCKDOWN_KEY, NULL))
- {
- dbusmenu_menuitem_property_set_bool (switch_menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- }
- else
- {
- dbusmenu_menuitem_property_set_bool (switch_menuitem, DBUSMENU_MENUITEM_PROP_VISIBLE, TRUE);
- }
}
GList * users = NULL;
@@ -521,17 +601,29 @@ rebuild_items (DbusmenuMenuitem *root,
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_url != NULL && user->icon_url[0] != '\0' && g_str_has_prefix(user->icon_url, "file://")) {
+ dbusmenu_menuitem_property_set(mi, USER_ITEM_PROP_ICON, user->icon_url + strlen("file://"));
+ } else {
+ dbusmenu_menuitem_property_set(mi, USER_ITEM_PROP_ICON, USER_ITEM_ICON_DEFAULT);
+ }
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);
}
- DbusmenuMenuitem * separator = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
- dbusmenu_menuitem_child_append(root, separator);
+ /* If there were a bunch of items before us, we need a
+ separator. */
+ if (can_lockscreen || can_activate) {
+ DbusmenuMenuitem * separator = dbusmenu_menuitem_new();
+ dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
+ dbusmenu_menuitem_child_append(root, separator);
+ }
+
+ /* Start going through the session based items. */
logout_mi = dbusmenu_menuitem_new();
if (supress_confirmations()) {
@@ -539,35 +631,39 @@ rebuild_items (DbusmenuMenuitem *root,
} else {
dbusmenu_menuitem_property_set(logout_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Log Out..."));
}
+ 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");
- suspend_mi = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set_bool(suspend_mi, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- dbusmenu_menuitem_property_set(suspend_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Sleep"));
- 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_suspend && allow_suspend) {
+ suspend_mi = dbusmenu_menuitem_new();
+ dbusmenu_menuitem_property_set(suspend_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Sleep"));
+ dbusmenu_menuitem_child_append(root, suspend_mi);
+ g_signal_connect(G_OBJECT(suspend_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(machine_sleep), "Suspend");
+ }
- hibernate_mi = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set_bool(hibernate_mi, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);
- 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");
+ 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, DBUSMENU_MENUITEM_PROP_LABEL, _("Restart"));
+ dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("Restart"));
} else {
- dbusmenu_menuitem_property_set(restart_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Restart..."));
+ dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("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, _("Switch Off"));
+ dbusmenu_menuitem_property_set(shutdown_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Shut Down"));
} else {
- dbusmenu_menuitem_property_set(shutdown_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Switch Off..."));
+ dbusmenu_menuitem_property_set(shutdown_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Shut Down..."));
}
dbusmenu_menuitem_child_append(root, shutdown_mi);
g_signal_connect(G_OBJECT(shutdown_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(show_dialog), "shutdown");
@@ -577,7 +673,22 @@ rebuild_items (DbusmenuMenuitem *root,
restart_shutdown_logout_mi->restart_mi = restart_mi;
restart_shutdown_logout_mi->shutdown_mi = shutdown_mi;
- update_menu_entries(restart_shutdown_logout_mi);
+ update_menu_entries(restart_shutdown_logout_mi, logout_mi);
+
+ if (g_file_test(DESKTOP_FILE, G_FILE_TEST_EXISTS)) {
+ GAppInfo * appinfo = G_APP_INFO(g_desktop_app_info_new_from_filename(DESKTOP_FILE));
+
+ if (appinfo != NULL) {
+ DbusmenuMenuitem * separator = dbusmenu_menuitem_new();
+ dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
+ dbusmenu_menuitem_child_append(root, separator);
+
+ DbusmenuMenuitem * desktop_mi = dbusmenu_menuitem_new();
+ dbusmenu_menuitem_property_set(desktop_mi, DBUSMENU_MENUITEM_PROP_LABEL, g_app_info_get_name(appinfo));
+ g_signal_connect(G_OBJECT(desktop_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(desktop_activate_cb), appinfo);
+ dbusmenu_menuitem_child_append(root, desktop_mi);
+ }
+ }
return;
}
@@ -615,18 +726,24 @@ restart_dir_changed (void)
if (restart_required) {
if (supress_confirmations()) {
- dbusmenu_menuitem_property_set(restart_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Restart Required"));
+ dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("Restart Required"));
} else {
- dbusmenu_menuitem_property_set(restart_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Restart Required..."));
+ dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("Restart Required..."));
+ }
+ dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_ICON, "system-restart-panel");
+ if (session_dbus != NULL) {
+ session_dbus_set_name(session_dbus, ICON_RESTART);
}
- dbusmenu_menuitem_property_set(restart_mi, DBUSMENU_MENUITEM_PROP_ICON_NAME, "emblem-important");
} else {
if (supress_confirmations()) {
- dbusmenu_menuitem_property_set(restart_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Restart"));
+ dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("Restart"));
} else {
- dbusmenu_menuitem_property_set(restart_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Restart..."));
+ dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("Restart..."));
+ }
+ dbusmenu_menuitem_property_remove(restart_mi, RESTART_ITEM_ICON);
+ if (session_dbus != NULL) {
+ session_dbus_set_name(session_dbus, ICON_DEFAULT);
}
- dbusmenu_menuitem_property_remove(restart_mi, DBUSMENU_MENUITEM_PROP_ICON_NAME);
}
return;
@@ -666,6 +783,8 @@ main (int argc, char ** argv)
INDICATOR_SERVICE_SIGNAL_SHUTDOWN,
G_CALLBACK(service_shutdown), NULL);
+ session_dbus = session_dbus_new();
+
g_idle_add(lock_screen_setup, NULL);
root_menuitem = dbusmenu_menuitem_new();
diff --git a/src/upower.xml b/src/upower.xml
new file mode 100644
index 0000000..a4066ff
--- /dev/null
+++ b/src/upower.xml
@@ -0,0 +1,309 @@
+<!DOCTYPE node PUBLIC
+"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd">
+
+ <interface name="org.freedesktop.UPower">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ The DeviceKit-power service is available via the system message
+ bus. To access the service, use
+ the <doc:tt>org.freedesktop.UPower</doc:tt> interface on
+ the <doc:tt>/org/freedesktop/UPower</doc:tt> object on
+ the D-Bus system bus service with the well-known
+ name <doc:tt>org.freedesktop.UPower</doc:tt>.
+ </doc:para>
+ <doc:para>
+ <doc:example language="shell" title="simple example">
+ <doc:code>
+$ dbus-send --print-reply \
+ --system \
+ --dest=org.freedesktop.UPower \
+ /org/freedesktop/UPower \
+ org.freedesktop.UPower.EnumerateDevices
+
+method return sender=:1.386 -> dest=:1.451 reply_serial=2
+ array [
+ object path "/org/freedesktop/UPower/devices/line_power_AC"
+ object path "/org/freedesktop/UPower/devices/battery_BAT0"
+ ]
+ </doc:code>
+ </doc:example>
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+
+ <!-- ************************************************************ -->
+
+ <method name="EnumerateDevices">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="devices" direction="out" type="ao">
+ <doc:doc><doc:summary>An array of object paths for devices.</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Enumerate all power objects on the system.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <signal name="DeviceAdded">
+ <arg name="device" type="o">
+ <doc:doc><doc:summary>Object path of device that was added.</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Emitted when a device is added.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <!-- ************************************************************ -->
+
+ <signal name="DeviceRemoved">
+ <arg name="device" type="o">
+ <doc:doc><doc:summary>Object path of device that was removed.</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Emitted when a device is removed.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <!-- ************************************************************ -->
+
+ <signal name="DeviceChanged">
+ <arg name="device" type="o">
+ <doc:doc><doc:summary>Object path of device that was changed.</doc:summary></doc:doc>
+ </arg>
+
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Emitted when a device changed.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <!-- ************************************************************ -->
+
+ <signal name="Changed">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Emitted when one or more properties on the object changes.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <!-- ************************************************************ -->
+
+ <signal name="Sleeping">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ This signal is sent when the session is about to be suspended or
+ hibernated.
+ Session and system programs have one second to do anything required
+ before the sleep action is taken (such as sending out Avahi or
+ Jabber messages).
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <!-- ************************************************************ -->
+
+ <signal name="Resuming">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ This signal is sent when the session has just returned from
+ Suspend() or Hibernate().
+ Session and system programs can then do anything required (such as
+ sending out Avahi or Jabber messages).
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </signal>
+
+ <!-- ************************************************************ -->
+
+ <method name="AboutToSleep">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ This method tells UPower that the Suspend() or Hibernate() method
+ is about to be called.
+ This allows UPower to emit the Suspending signal whilst
+ session activities are happening that have to be done before the
+ suspend process is started.
+ </doc:para>
+ <doc:para>
+ This method would typically be called by the session power
+ management daemon, before it locks the screen and waits for the
+ screen to fade to black.
+ The session power management component would then call Suspend() or
+ Hibernate() when these syncronous tasks have completed.
+ </doc:para>
+ <doc:para>
+ If this method is not called than nothing bad will happen and
+ Suspend() or Hibernate() will block for the required second.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <method name="Suspend">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Suspends the computer into a low power state.
+ System state is not preserved if the power is lost.
+ </doc:para>
+ <doc:para>
+ If AboutToRequestSleep() has not been called then UPower will send
+ the Sleeping() signal and block for one second.
+ </doc:para>
+ <doc:para>
+ If AboutToRequestSleep() has been called less than one second
+ before this method is called then UPower will block for the
+ remaining time to complete one second of delay.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <method name="SuspendAllowed">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="allowed" direction="out" type="b">
+ <doc:doc><doc:summary>TRUE if allowed, otherwise FALSE</doc:summary></doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Check if the caller has (or can get) the PolicyKit privilege to call
+ <doc:ref type="method" to="Power.Suspend">Suspend</doc:ref>.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <method name="Hibernate">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Hibernates the computer into a low power state.
+ System state is preserved if the power is lost.
+ </doc:para>
+ <doc:para>
+ If AboutToRequestSleep() has not been called then UPower will send
+ the Sleeping() signal and block for one second.
+ </doc:para>
+ <doc:para>
+ If AboutToRequestSleep() has been called less than one second
+ before this method is called then UPower will block for the
+ remaining time to complete one second of delay.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <method name="HibernateAllowed">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="allowed" direction="out" type="b">
+ <doc:doc><doc:summary>TRUE if allowed, otherwise FALSE</doc:summary></doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Check if the caller has (or can get) the PolicyKit privilege to call
+ <doc:ref type="method" to="Power.Hibernate">Hibernate</doc:ref>.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <!-- ************************************************************ -->
+
+ <property name="DaemonVersion" type="s" access="read">
+ <doc:doc><doc:description><doc:para>
+ Version of the running daemon, e.g. <doc:tt>002</doc:tt>.
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="CanSuspend" type="b" access="read">
+ <doc:doc><doc:description><doc:para>
+ Whether the system is able to suspend.
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="CanHibernate" type="b" access="read">
+ <doc:doc><doc:description><doc:para>
+ Whether the system is able to hibernate.
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="OnBattery" type="b" access="read">
+ <doc:doc><doc:description><doc:para>
+ Indicates whether the system is running on battery power.
+ This property is provided for convenience.
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="OnLowBattery" type="b" access="read">
+ <doc:doc><doc:description><doc:para>
+ Indicates whether the system is running on battery power and if the battery is critically low.
+ This property is provided for convenience.
+ </doc:para></doc:description></doc:doc>
+ </property>
+
+ <property name="LidIsClosed" type="b" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ Indicates if the laptop lid is closed where the display cannot be seen.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ <property name="LidIsPresent" type="b" access="read">
+ <doc:doc>
+ <doc:description>
+ <doc:para>
+ If the system has a lid device.
+ </doc:para>
+ </doc:description>
+ </doc:doc>
+ </property>
+
+ </interface>
+
+</node>
diff --git a/src/users-service-dbus.c b/src/users-service-dbus.c
index 4aefdff..86007c3 100644
--- a/src/users-service-dbus.c
+++ b/src/users-service-dbus.c
@@ -31,10 +31,16 @@
#include <dbus/dbus-glib-lowlevel.h>
#include "dbus-shared-names.h"
+#include "gdm-local-display-factory-client.h"
#include "users-service-dbus.h"
#include "users-service-client.h"
#include "users-service-marshal.h"
#include "consolekit-manager-client.h"
+#include "consolekit-session-client.h"
+
+#define CK_ADDR "org.freedesktop.ConsoleKit"
+#define CK_SESSION_IFACE "org.freedesktop.ConsoleKit.Session"
+
static void users_service_dbus_class_init (UsersServiceDbusClass *klass);
static void users_service_dbus_init (UsersServiceDbus *self);
@@ -65,7 +71,7 @@ static void seat_proxy_session_removed (DBusGProxy *seat_
static gboolean do_add_session (UsersServiceDbus *service,
UserData *user,
const gchar *ssid);
-static gchar * get_seat_internal (UsersServiceDbus *self);
+static gchar * get_seat_internal (DBusGProxy *proxy);
/* Private */
typedef struct _UsersServiceDbusPrivate UsersServiceDbusPrivate;
@@ -80,12 +86,16 @@ struct _UsersServiceDbusPrivate
DBusGConnection *system_bus;
DBusGProxy *gdm_proxy;
+ DBusGProxy *gdm_local_proxy;
DBusGProxy *ck_proxy;
DBusGProxy *seat_proxy;
DBusGProxy *session_proxy;
GHashTable *exclusions;
GHashTable *sessions;
+
+ DbusmenuMenuitem * guest_item;
+ gchar * guest_session_id;
};
#define USERS_SERVICE_DBUS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), USERS_SERVICE_DBUS_TYPE, UsersServiceDbusPrivate))
@@ -155,6 +165,8 @@ users_service_dbus_init (UsersServiceDbus *self)
priv->users = NULL;
priv->count = 0;
+ priv->guest_item = NULL;
+ priv->guest_session_id = NULL;
/* Get the system bus */
priv->system_bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
@@ -198,6 +210,13 @@ users_service_dbus_dispose (GObject *object)
static void
users_service_dbus_finalize (GObject *object)
{
+ UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (object);
+
+ if (priv->guest_session_id != NULL) {
+ g_free(priv->guest_session_id);
+ priv->guest_session_id = NULL;
+ }
+
G_OBJECT_CLASS (users_service_dbus_parent_class)->finalize (object);
}
@@ -266,6 +285,11 @@ create_gdm_proxy (UsersServiceDbus *self)
G_CALLBACK (user_updated),
self,
NULL);
+
+ priv->gdm_local_proxy = dbus_g_proxy_new_for_name (priv->system_bus,
+ "org.gnome.DisplayManager",
+ "/org/gnome/DisplayManager/LocalDisplayFactory",
+ "org.gnome.DisplayManager.LocalDisplayFactory");
}
static void
@@ -341,9 +365,9 @@ create_cksession_proxy (UsersServiceDbus *service)
UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service);
priv->session_proxy = dbus_g_proxy_new_for_name (priv->system_bus,
- "org.freedesktop.ConsoleKit",
+ CK_ADDR,
priv->ssid,
- "org.freedesktop.ConsoleKit.Session");
+ CK_SESSION_IFACE);
if (!priv->session_proxy)
{
@@ -383,24 +407,18 @@ get_seat (UsersServiceDbus *service)
priv->ssid = ssid;
create_cksession_proxy (service);
- seat = get_seat_internal (service);
+ seat = get_seat_internal (priv->session_proxy);
return seat;
}
static gchar *
-get_seat_internal (UsersServiceDbus *self)
+get_seat_internal (DBusGProxy *proxy)
{
- UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self);
GError *error = NULL;
gchar *seat = NULL;
- if (!dbus_g_proxy_call (priv->session_proxy,
- "GetSeatId",
- &error,
- G_TYPE_INVALID,
- DBUS_TYPE_G_OBJECT_PATH, &seat,
- G_TYPE_INVALID))
+ if (!org_freedesktop_ConsoleKit_Session_get_seat_id (proxy, &seat, &error))
{
if (error)
{
@@ -421,13 +439,22 @@ get_unix_user (UsersServiceDbus *service,
UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service);
GError *error = NULL;
guint uid;
+ DBusGProxy *session_proxy;
+
+ g_debug("Building session proxy for: %s", session_id);
+ session_proxy = dbus_g_proxy_new_for_name_owner(priv->system_bus,
+ CK_ADDR,
+ session_id,
+ CK_SESSION_IFACE,
+ &error);
+
+ if (error != NULL) {
+ g_warning("Unable to get CK Session proxy: %s", error->message);
+ g_error_free(error);
+ return FALSE;
+ }
- if (dbus_g_proxy_call (priv->session_proxy,
- "GetUnixUser",
- &error,
- G_TYPE_INVALID,
- G_TYPE_UINT, &uid,
- G_TYPE_INVALID))
+ if (!org_freedesktop_ConsoleKit_Session_get_unix_user(session_proxy, &uid, &error))
{
if (error)
{
@@ -435,6 +462,7 @@ get_unix_user (UsersServiceDbus *service,
g_error_free (error);
}
+ g_object_unref(session_proxy);
return FALSE;
}
@@ -443,6 +471,7 @@ get_unix_user (UsersServiceDbus *service,
*uidp = (uid_t)uid;
}
+ g_object_unref(session_proxy);
return TRUE;
}
@@ -455,19 +484,29 @@ do_add_session (UsersServiceDbus *service,
GError *error = NULL;
gchar *seat = NULL;
gchar *xdisplay = NULL;
+ DBusGProxy * session_proxy;
GList *l;
- seat = get_seat_internal (service);
+ session_proxy = dbus_g_proxy_new_for_name_owner(priv->system_bus,
+ CK_ADDR,
+ ssid,
+ CK_SESSION_IFACE,
+ &error);
- if (!seat || !priv->seat || strcmp (seat, priv->seat) != 0)
+ if (error != NULL) {
+ g_warning("Unable to get CK Session proxy: %s", error->message);
+ g_error_free(error);
return FALSE;
+ }
- if (!dbus_g_proxy_call (priv->session_proxy,
- "GetX11Display",
- &error,
- G_TYPE_INVALID,
- G_TYPE_STRING, &xdisplay,
- G_TYPE_INVALID))
+ seat = get_seat_internal (session_proxy);
+
+ if (!seat || !priv->seat || strcmp (seat, priv->seat) != 0) {
+ g_object_unref(session_proxy);
+ return FALSE;
+ }
+
+ if (!org_freedesktop_ConsoleKit_Session_get_x11_display (session_proxy, &xdisplay, &error))
{
if (error)
{
@@ -475,9 +514,12 @@ do_add_session (UsersServiceDbus *service,
g_error_free (error);
}
+ g_object_unref(session_proxy);
return FALSE;
}
+ g_object_unref(session_proxy);
+
if (!xdisplay || xdisplay[0] == '\0')
return FALSE;
@@ -491,6 +533,10 @@ do_add_session (UsersServiceDbus *service,
g_debug ("Adding session %s", ssid);
user->sessions = g_list_prepend (user->sessions, g_strdup (ssid));
+
+ if (user->menuitem != NULL) {
+ dbusmenu_menuitem_property_set_bool(user->menuitem, USER_ITEM_PROP_LOGGED_IN, TRUE);
+ }
}
else
{
@@ -556,6 +602,17 @@ seat_proxy_session_added (DBusGProxy *seat_proxy,
return;
}
+ /* We need to special case guest here because it doesn't
+ show up in the GDM user tables. */
+ if (g_strcmp0("guest", pwent->pw_name) == 0) {
+ if (priv->guest_item != NULL) {
+ dbusmenu_menuitem_property_set_bool(priv->guest_item, USER_ITEM_PROP_LOGGED_IN, TRUE);
+ }
+ priv->guest_session_id = g_strdup(session_id);
+ g_debug("Found guest session: %s", priv->guest_session_id);
+ return;
+ }
+
user = g_hash_table_lookup (priv->users, pwent->pw_name);
if (!user)
{
@@ -576,8 +633,17 @@ seat_proxy_session_removed (DBusGProxy *seat_proxy,
GList *l;
username = g_hash_table_lookup (priv->sessions, session_id);
- if (!username)
+ if (!username) {
+ if (g_strcmp0(session_id, priv->guest_session_id) == 0) {
+ g_debug("Removing guest session: %s", priv->guest_session_id);
+ if (priv->guest_item != NULL) {
+ dbusmenu_menuitem_property_set_bool(priv->guest_item, USER_ITEM_PROP_LOGGED_IN, FALSE);
+ }
+ g_free(priv->guest_session_id);
+ priv->guest_session_id = NULL;
+ }
return;
+ }
user = g_hash_table_lookup (priv->users, username);
if (!user)
@@ -592,6 +658,9 @@ seat_proxy_session_removed (DBusGProxy *seat_proxy,
g_free (l->data);
user->sessions = g_list_delete_link (user->sessions, l);
+ if (user->menuitem != NULL && user->sessions == NULL) {
+ dbusmenu_menuitem_property_set_bool(user->menuitem, USER_ITEM_PROP_LOGGED_IN, FALSE);
+ }
}
else
{
@@ -657,6 +726,7 @@ sync_users (UsersServiceDbus *self)
user->login_count = g_value_get_int (g_value_array_get_nth (values, 4));
user->icon_url = g_strdup (g_value_get_string (g_value_array_get_nth (values, 5)));
user->real_name_conflict = FALSE;
+ user->menuitem = NULL;
g_hash_table_insert (priv->users,
g_strdup (user->user_name),
@@ -706,21 +776,16 @@ session_is_login_window (UsersServiceDbus *self,
char *type = NULL;
if (!(proxy = dbus_g_proxy_new_for_name (priv->system_bus,
- "org.freedesktop.ConsoleKit",
+ CK_ADDR,
ssid,
- "org.freedesktop.ConsoleKit.Session")))
+ CK_SESSION_IFACE)))
{
g_warning ("Failed to get ConsoleKit proxy");
return FALSE;
}
- if (!dbus_g_proxy_call (proxy,
- "GetSessionType",
- &error,
- G_TYPE_INVALID,
- G_TYPE_STRING, &type,
- G_TYPE_INVALID))
+ if (!org_freedesktop_ConsoleKit_Session_get_session_type (proxy, &type, &error))
{
g_warning ("Can't call GetSessionType: %s", error->message);
g_error_free (error);
@@ -1005,61 +1070,21 @@ users_service_dbus_get_user_list (UsersServiceDbus *self)
return g_hash_table_get_values (priv->users);
}
+/* Activates the guest account if it can. */
+gboolean
+users_service_dbus_activate_guest_session (UsersServiceDbus *self)
+{
+ UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self);
+ return org_gnome_DisplayManager_LocalDisplayFactory_switch_to_user(priv->gdm_local_proxy, "guest", NULL, NULL);
+}
+
+/* Activates a specific user */
gboolean
users_service_dbus_activate_user_session (UsersServiceDbus *self,
UserData *user)
{
- UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self);
- DBusMessage *message = NULL;
- DBusMessage *reply = NULL;
- DBusError error;
-
- dbus_error_init (&error);
-
- if (!(message = dbus_message_new_method_call ("org.gnome.DisplayManager",
- "/org/gnome/DisplayManager/LocalDisplayFactory",
- "org.gnome.DisplayManager.LocalDisplayFactory",
- "SwitchToUser")))
- {
- g_warning ("failed to create new message");
- return FALSE;
- }
-
- if (!dbus_message_append_args (message,
- DBUS_TYPE_STRING, &user->user_name,
- DBUS_TYPE_INVALID))
- {
- g_warning ("failed to append args");
- return FALSE;
- }
-
- if (!(reply = dbus_connection_send_with_reply_and_block (dbus_g_connection_get_connection (priv->system_bus),
- message,
- -1,
- &error)))
- {
- if (dbus_error_is_set (&error))
- {
- g_warning ("Failed to send message: %s", error.message);
- dbus_error_free (&error);
-
- return FALSE;
- }
- }
-
- if (message)
- {
- dbus_message_unref (message);
- }
-
- if (reply)
- {
- dbus_message_unref (reply);
- }
-
- dbus_error_free (&error);
-
- return TRUE;
+ UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self);
+ return org_gnome_DisplayManager_LocalDisplayFactory_switch_to_user(priv->gdm_local_proxy, user->user_name, NULL, NULL);
}
gboolean
@@ -1094,3 +1119,17 @@ users_service_dbus_can_activate_session (UsersServiceDbus *self)
return can_activate;
}
+
+/* Sets the menu item that represents the guest account */
+void
+users_service_dbus_set_guest_item (UsersServiceDbus * self, DbusmenuMenuitem * mi)
+{
+ UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self);
+ priv->guest_item = mi;
+
+ if (priv->guest_session_id != NULL) {
+ dbusmenu_menuitem_property_set_bool(priv->guest_item, USER_ITEM_PROP_LOGGED_IN, TRUE);
+ }
+
+ return;
+}
diff --git a/src/users-service-dbus.h b/src/users-service-dbus.h
index bba88a7..4798d64 100644
--- a/src/users-service-dbus.h
+++ b/src/users-service-dbus.h
@@ -22,6 +22,7 @@
#include <glib.h>
#include <glib-object.h>
+#include <libdbusmenu-glib/menuitem.h>
G_BEGIN_DECLS
@@ -47,7 +48,10 @@ struct _UserData
GList *sessions;
+ /* Whether the real name here conflicts with another in the system */
gboolean real_name_conflict;
+ /* The menuitem representing this user if there is one. */
+ DbusmenuMenuitem * menuitem;
UsersServiceDbus *service;
};
@@ -80,6 +84,9 @@ GList *users_service_dbus_get_user_list (UsersServiceDbus *self);
gboolean users_service_dbus_can_activate_session (UsersServiceDbus *self);
gboolean users_service_dbus_activate_user_session (UsersServiceDbus *self,
UserData *user);
+gboolean users_service_dbus_activate_guest_session (UsersServiceDbus *self);
+void users_service_dbus_set_guest_item (UsersServiceDbus * self,
+ DbusmenuMenuitem * mi);
G_END_DECLS