aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCody Russell <crussell@canonical.com>2009-09-10 16:26:01 -0500
committerCody Russell <crussell@canonical.com>2009-09-10 16:26:01 -0500
commitefd24605727ee979b35053397463246456cf0ed0 (patch)
tree621f85a05dc90b0fe0a519108ba2b8d18897c494
parent3211a5e810fbbe830a237127092d221018f4f6a2 (diff)
downloadayatana-indicator-session-efd24605727ee979b35053397463246456cf0ed0.tar.gz
ayatana-indicator-session-efd24605727ee979b35053397463246456cf0ed0.tar.bz2
ayatana-indicator-session-efd24605727ee979b35053397463246456cf0ed0.zip
work in progress
-rw-r--r--src/Makefile.am22
-rw-r--r--src/dbus-shared-names.h14
-rw-r--r--src/status-service.c16
-rw-r--r--src/users-service-dbus.c379
-rw-r--r--src/users-service-dbus.h73
-rw-r--r--src/users-service.c144
-rw-r--r--src/users-service.xml56
7 files changed, 656 insertions, 48 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index e2f0008..f7fa7a7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -11,7 +11,8 @@ sessionlib_LTLIBRARIES = libsession.la
libsession_la_SOURCES = \
indicator-session.c \
dbus-shared-names.h \
- status-service-client.h
+ status-service-client.h \
+ users-service-client.h
libsession_la_CFLAGS = $(APPLET_CFLAGS) -Wall -Werror
libsession_la_LIBADD = $(APPLET_LIBS)
libsession_la_LDFLAGS = -module -avoid-version
@@ -25,6 +26,9 @@ indicator_status_service_SOURCES = \
status-service-dbus.h \
status-service-dbus.c \
status-service-server.h \
+ users-service-dbus.h \
+ users-service-dbus.c \
+ users-service-server.h \
status-provider.h \
status-provider.c \
status-provider-pidgin.h \
@@ -38,6 +42,20 @@ indicator_status_service_SOURCES = \
indicator_status_service_CFLAGS = $(STATUSSERVICE_CFLAGS) -Wall -Werror
indicator_status_service_LDADD = $(STATUSSERVICE_LIBS)
+users-service-client.h: $(srcdir)/users-service.xml
+ dbus-binding-tool \
+ --prefix=_users_service_client \
+ --mode=glib-client \
+ --output=users-service-client.h \
+ $(srcdir)/users-service.xml
+
+users-service-server.h: $(srcdir)/users-service.xml
+ dbus-binding-tool \
+ --prefix=_users_service_server \
+ --mode=glib-server \
+ --output=users-service-server.h \
+ $(srcdir)/users-service.xml
+
status-service-client.h: $(srcdir)/status-service.xml
dbus-binding-tool \
--prefix=_status_service_client \
@@ -93,6 +111,8 @@ indicator_session_service_LDADD = $(SESSIONSERVICE_LIBS) $(GCONF_LIBS)
###############
BUILT_SOURCES = \
+ users-service-client.h \
+ users-service-server.h \
status-service-client.h \
status-service-server.h \
status-provider-pidgin-marshal.h \
diff --git a/src/dbus-shared-names.h b/src/dbus-shared-names.h
index a645830..7e7d456 100644
--- a/src/dbus-shared-names.h
+++ b/src/dbus-shared-names.h
@@ -7,16 +7,16 @@ Copyright 2009 Canonical Ltd.
Authors:
Ted Gould <ted@canonical.com>
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 3, as published
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 3, as published
by the Free Software Foundation.
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranties of
+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU General Public License for more details.
-You should have received a copy of the GNU General Public License along
+You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -31,6 +31,8 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#define INDICATOR_USERS_DBUS_NAME "org.ayatana.indicator.users"
#define INDICATOR_USERS_DBUS_OBJECT "/org/ayatana/indicator/users/menu"
+#define INDICATOR_USERS_SERVICE_DBUS_OBJECT "/org/gnome/DisplayManager/UserManager"
+#define INDICATOR_USERS_SERVICE_DBUS_INTERFACE "org.gnome.DisplayManager.UserManager"
#define INDICATOR_SESSION_DBUS_NAME "org.ayatana.indicator.session"
#define INDICATOR_SESSION_DBUS_OBJECT "/org/ayatana/indicator/session/menu"
diff --git a/src/status-service.c b/src/status-service.c
index b210dcd..542317a 100644
--- a/src/status-service.c
+++ b/src/status-service.c
@@ -7,16 +7,16 @@ Copyright 2009 Canonical Ltd.
Authors:
Ted Gould <ted@canonical.com>
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 3, as published
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 3, as published
by the Free Software Foundation.
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranties of
+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU General Public License for more details.
-You should have received a copy of the GNU General Public License along
+You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -228,12 +228,12 @@ main (int argc, char ** argv)
if (!org_freedesktop_DBus_request_name(bus_proxy, INDICATOR_STATUS_DBUS_NAME, 0, &nameret, &error)) {
g_error("Unable to call to request name");
return 1;
- }
+ }
if (nameret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
g_error("Unable to get name");
return 1;
- }
+ }
g_idle_add(build_providers, NULL);
diff --git a/src/users-service-dbus.c b/src/users-service-dbus.c
new file mode 100644
index 0000000..95b0f49
--- /dev/null
+++ b/src/users-service-dbus.c
@@ -0,0 +1,379 @@
+/*
+ * Copyright 2009 Canonical Ltd.
+ *
+ * Authors:
+ * Cody Russell <crussell@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 <dbus/dbus-glib.h>
+
+#include "dbus-shared-names.h"
+#include "users-service-dbus.h"
+#include "users-service-client.h"
+
+static void users_service_dbus_class_init (UsersServiceDbusClass *klass);
+static void users_service_dbus_init (UsersServiceDbus *self);
+static void users_service_dbus_dispose (GObject *object);
+static void users_service_dbus_finalize (GObject *object);
+static gboolean _users_service_server_count_users (UsersServiceDbus *service,
+ gint *count,
+ GError **error);
+static gboolean _users_service_server_get_user_list (UsersServiceDbus *service,
+ GArray **list,
+ GError **error);
+static gboolean _users_service_server_get_user_info (UsersServiceDbus *service,
+ const gint64 uid,
+ gchar **username,
+ gchar **real_name,
+ gchar **shell,
+ char **icon_url,
+ GError **error);
+static gboolean _users_service_server_get_users_info (UsersServiceDbus *service,
+ const GArray *uids,
+ GPtrArray **user_info,
+ GError **error);
+static void users_loaded (DBusGProxy *proxy,
+ gpointer user_data);
+static void user_added (DBusGProxy *proxy,
+ guint uid,
+ gpointer user_data);
+static void user_removed (DBusGProxy *proxy,
+ guint uid,
+ gpointer user_data);
+
+#include "users-service-server.h"
+
+/* Private */
+typedef struct _UsersServiceDbusPrivate UsersServiceDbusPrivate;
+
+struct _UsersServiceDbusPrivate
+{
+ GList *users;
+ gint count;
+
+ DBusGConnection *session_bus;
+ DBusGConnection *system_bus;
+ DBusGProxy *dbus_proxy_session;
+ DBusGProxy *dbus_proxy_system;
+};
+
+#define USERS_SERVICE_DBUS_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), USERS_SERVICE_DBUS_TYPE, UsersServiceDbusPrivate))
+
+/* Signals */
+enum {
+ USERS_LOADED,
+ USER_ADDED,
+ USER_REMOVED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+/* GObject Boilerplate */
+G_DEFINE_TYPE (UsersServiceDbus, users_service_dbus, G_TYPE_OBJECT);
+
+static void
+users_service_dbus_class_init (UsersServiceDbusClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (object_class, sizeof (UsersServiceDbusPrivate));
+
+ object_class->dispose = users_service_dbus_dispose;
+ object_class->finalize = users_service_dbus_finalize;
+
+ signals[USERS_LOADED] = g_signal_new ("users-loaded",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (UsersServiceDbusClass, users_loaded),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals[USER_ADDED] = g_signal_new ("user-added",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (UsersServiceDbusClass, user_added),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__INT,
+ G_TYPE_NONE, 1, G_TYPE_INT);
+
+ signals[USER_REMOVED] = g_signal_new ("user-removed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (UsersServiceDbusClass, user_removed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__INT,
+ G_TYPE_NONE, 1, G_TYPE_INT);
+
+ dbus_g_object_type_install_info (USERS_SERVICE_DBUS_TYPE, &dbus_glib__users_service_server_object_info);
+}
+
+static void
+users_service_dbus_init (UsersServiceDbus *self)
+{
+ GError *error = NULL;
+ UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self);
+
+ priv->users = NULL;
+ priv->count = 0;
+
+ /* Get the buses */
+ priv->session_bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
+ if (error != NULL) {
+ g_error ("Unable to get session bus: %s", error->message);
+ g_error_free (error);
+
+ return;
+ }
+
+ priv->system_bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (error != NULL) {
+ g_error("Unable to get system bus: %s", error->message);
+ g_error_free(error);
+
+ return;
+ }
+
+ dbus_g_connection_register_g_object (priv->session_bus,
+ INDICATOR_USERS_SERVICE_DBUS_OBJECT,
+ G_OBJECT (self));
+
+ /* Set up the DBUS service proxies */
+ priv->dbus_proxy_session = dbus_g_proxy_new_for_name_owner (priv->session_bus,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS,
+ &error);
+ if (error != NULL) {
+ g_error ("Unable to get dbus proxy on session bus: %s", error->message);
+ g_error_free (error);
+
+ return;
+ }
+
+ priv->dbus_proxy_system = dbus_g_proxy_new_for_name_owner (priv->system_bus,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS,
+ &error);
+ if (error != NULL) {
+ g_error ("Unable to get dbus proxy on system bus: %s", error->message);
+ g_error_free (error);
+
+ return;
+ }
+
+ dbus_g_proxy_connect_signal (priv->dbus_proxy_system,
+ "UsersLoaded",
+ G_CALLBACK (users_loaded),
+ self,
+ NULL);
+
+ dbus_g_proxy_connect_signal (priv->dbus_proxy_system,
+ "UserAdded",
+ G_CALLBACK (user_added),
+ self,
+ NULL);
+
+ dbus_g_proxy_connect_signal (priv->dbus_proxy_system,
+ "UserRemoved",
+ G_CALLBACK (user_removed),
+ self,
+ NULL);
+}
+
+static void
+users_service_dbus_dispose (GObject *object)
+{
+ G_OBJECT_CLASS (users_service_dbus_parent_class)->dispose (object);
+}
+
+static void
+users_service_dbus_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (users_service_dbus_parent_class)->finalize (object);
+}
+
+static void
+users_loaded (DBusGProxy *proxy,
+ gpointer user_data)
+{
+ UsersServiceDbus *service;
+ UsersServiceDbusPrivate *priv;
+ GError *error = NULL;
+ GArray *uids;
+ GPtrArray *users_info;
+ gint count;
+ int i;
+
+ service = (UsersServiceDbus *)user_data;
+ priv = USERS_SERVICE_DBUS_GET_PRIVATE (service);
+
+ if (!org_gnome_DisplayManager_UserManager_count_users (proxy,
+ &count,
+ &error))
+ {
+ g_warning ("failed to retrieve user count: %s", error->message);
+ g_error_free (error);
+
+ return;
+ }
+
+ priv->count = count;
+
+ if (!org_gnome_DisplayManager_UserManager_get_user_list (proxy,
+ &uids,
+ &error))
+ {
+ g_warning ("failed to retrieve user list: %s", error->message);
+ g_error_free (error);
+
+ return;
+ }
+
+ if (!org_gnome_DisplayManager_UserManager_get_users_info (proxy,
+ uids,
+ &users_info,
+ &error))
+ {
+ g_warning ("failed to retrieve user info: %s", error->message);
+ g_error_free (error);
+
+ return;
+ }
+
+ for (i = 0; i < users_info->len; i++)
+ {
+ UserData *data = g_ptr_array_index (users_info, i);
+
+ priv->users = g_list_prepend (priv->users, data);
+ }
+}
+
+gint
+users_service_dbus_get_user_count (UsersServiceDbus *self)
+{
+ UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self);
+
+ return priv->count;
+}
+
+GList *
+users_service_dbus_get_user_list (UsersServiceDbus *self)
+{
+ UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (self);
+
+ return priv->users;
+}
+
+static void
+user_added (DBusGProxy *proxy,
+ guint uid,
+ gpointer user_data)
+{
+ UsersServiceDbus *service = (UsersServiceDbus *)user_data;
+ UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service);
+ UserData *user = g_new0 (UserData, 1);
+ GError *error = NULL;
+
+ priv->count++;
+
+ if (!org_gnome_DisplayManager_UserManager_get_user_info (proxy,
+ uid,
+ &user->user_name,
+ &user->real_name,
+ &user->shell,
+ &user->icon_url,
+ &error))
+ {
+ g_warning ("unable to retrieve user info: %s", error->message);
+ g_error_free (error);
+
+ g_free (user);
+
+ return;
+ }
+
+ user->uid = uid;
+
+ priv->users = g_list_prepend (priv->users, user);
+
+ g_signal_emit (G_OBJECT (service), signals[USER_ADDED], 0, user, TRUE);
+}
+
+static void
+user_removed (DBusGProxy *proxy,
+ guint uid,
+ gpointer user_data)
+{
+ UsersServiceDbus *service = (UsersServiceDbus *)user_data;
+ UsersServiceDbusPrivate *priv = USERS_SERVICE_DBUS_GET_PRIVATE (service);
+ GList *l;
+
+ priv->count--;
+
+ for (l = priv->users; l != NULL; l = g_list_next (l))
+ {
+ UserData *user = (UserData *)l->data;
+
+ if (user->uid == uid)
+ {
+ priv->users = g_list_remove (priv->users, l->data);
+ g_signal_emit (G_OBJECT (service), signals[USER_REMOVED], 0, user, TRUE);
+ }
+ }
+}
+
+static gboolean
+_users_service_server_count_users (UsersServiceDbus *service,
+ gint *uids,
+ GError **error)
+{
+ return TRUE;
+}
+
+static gboolean
+_users_service_server_get_user_list (UsersServiceDbus *service,
+ GArray **list,
+ GError **error)
+{
+ return TRUE;
+}
+
+static gboolean
+_users_service_server_get_user_info (UsersServiceDbus *service,
+ const gint64 uid,
+ gchar **username,
+ gchar **real_name,
+ gchar **shell,
+ char **icon_url,
+ GError **error)
+{
+ return TRUE;
+}
+
+static gboolean
+_users_service_server_get_users_info (UsersServiceDbus *service,
+ const GArray *uids,
+ GPtrArray **user_info,
+ GError **error)
+{
+ return TRUE;
+}
diff --git a/src/users-service-dbus.h b/src/users-service-dbus.h
new file mode 100644
index 0000000..df07e61
--- /dev/null
+++ b/src/users-service-dbus.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2009 Canonical Ltd.
+ *
+ * Authors:
+ * Cody Russell <crussell@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 __USERS_SERVICE_DBUS_H__
+#define __USERS_SERVICE_DBUS_H__
+
+#include <glib.h>
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define USERS_SERVICE_DBUS_TYPE (users_service_dbus_get_type ())
+#define USERS_SERVICE_DBUS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), USERS_SERVICE_DBUS_TYPE, UsersServiceDbus))
+#define USERS_SERVICE_DBUS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), USERS_SERVICE_DBUS_TYPE, UsersServiceDbusClass))
+#define IS_USERS_SERVICE_DBUS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), USERS_SERVICE_DBUS_TYPE))
+#define IS_USERS_SERVICE_DBUS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), USERS_SERVICE_DBUS_TYPE))
+#define USERS_SERVICE_DBUS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), USERS_SERVICE_DBUS_TYPE, UsersServiceDbusClass))
+
+typedef struct _UsersServiceDbus UsersServiceDbus;
+typedef struct _UsersServiceDbusClass UsersServiceDbusClass;
+typedef struct _UserData UserData;
+
+struct _UserData
+{
+ guint64 uid;
+ gchar *user_name;
+ gchar *real_name;
+ gchar *shell;
+ gchar *icon_url;
+};
+
+struct _UsersServiceDbus {
+ GObject parent;
+};
+
+struct _UsersServiceDbusClass {
+ GObjectClass parent_class;
+
+ /* Signals */
+ gboolean (*user_changed) (UsersServiceDbus *self, gchar **name, gpointer user_data);
+ gboolean (*users_icons_changed) (UsersServiceDbus *self, GArray **icons, gpointer user_data);
+
+ void (* users_loaded) (UsersServiceDbus *self, gpointer user_data);
+
+ void (* user_added) (UsersServiceDbus *self, gint64 uid, gpointer user_data);
+ void (* user_removed) (UsersServiceDbus *self, gint64 uid, gpointer user_data);
+ void (* user_updated) (UsersServiceDbus *self, gint64 uid, gpointer user_data);
+};
+
+GType users_service_dbus_get_type (void) G_GNUC_CONST;
+
+gint users_service_dbus_get_user_count (UsersServiceDbus *self);
+GList *users_service_dbus_get_user_list (UsersServiceDbus *self);
+
+G_END_DECLS
+
+#endif
diff --git a/src/users-service.c b/src/users-service.c
index 5db832b..77b5f95 100644
--- a/src/users-service.c
+++ b/src/users-service.c
@@ -7,16 +7,16 @@ Copyright 2009 Canonical Ltd.
Authors:
Ted Gould <ted@canonical.com>
-This program is free software: you can redistribute it and/or modify it
-under the terms of the GNU General Public License version 3, as published
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 3, as published
by the Free Software Foundation.
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranties of
+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
PURPOSE. See the GNU General Public License for more details.
-You should have received a copy of the GNU General Public License along
+You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>.
*/
@@ -31,15 +31,22 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <libdbusmenu-glib/menuitem.h>
#include "dbus-shared-names.h"
+#include "users-service-dbus.h"
#define GUEST_SESSION_LAUNCHER "/usr/share/gdm/guest-session/guest-session-launch"
+#define MINIMUM_USERS 1
+#define MAXIMUM_USERS 7
-static DBusGConnection * session_bus = NULL;
-static DBusGConnection * system_bus = NULL;
-static DBusGProxy * bus_proxy = NULL;
-static DBusGProxy * gdm_proxy = NULL;
-static DbusmenuMenuitem * root_menuitem = NULL;
-static GMainLoop * mainloop = NULL;
+static DBusGConnection *session_bus = NULL;
+static DBusGConnection *system_bus = NULL;
+static DBusGProxy *bus_proxy = NULL;
+static DBusGProxy *gdm_proxy = NULL;
+static DbusmenuMenuitem *root_menuitem = NULL;
+static GMainLoop *mainloop = NULL;
+static UsersServiceDbus *dbus_interface = NULL;
+
+static gint count;
+static GList *users;
static gboolean
check_guest_session (void)
@@ -108,24 +115,84 @@ activate_new_session (DbusmenuMenuitem * mi, gpointer user_data)
}
static void
-create_items (DbusmenuMenuitem * root) {
- DbusmenuMenuitem * mi = NULL;
-
- if (check_guest_session()) {
- mi = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set(mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Guest Session"));
- dbusmenu_menuitem_child_append(root, mi);
- g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(activate_guest_session), NULL);
- }
+activate_user_session (DbusmenuMenuitem *mi, gpointer user_data)
+{
+}
- if (check_new_session()) {
- mi = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set(mi, DBUSMENU_MENUITEM_PROP_LABEL, _("New Session..."));
- dbusmenu_menuitem_child_append(root, mi);
- g_signal_connect(G_OBJECT(mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(activate_new_session), NULL);
- }
+static void
+remove_menu_item (DbusmenuMenuitem *root, gpointer user_data)
+{
+ DbusmenuMenuitem *child = (DbusmenuMenuitem *)user_data;
- return;
+ dbusmenu_menuitem_child_delete (root, child);
+}
+
+static void
+rebuild_items (DbusmenuMenuitem *root,
+ UsersServiceDbus *service)
+{
+ DbusmenuMenuitem *mi = NULL;
+ GList *u;
+ UserData *user;
+
+ if (check_guest_session ()) {
+ mi = dbusmenu_menuitem_new ();
+ dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Guest Session"));
+ dbusmenu_menuitem_child_append (root, mi);
+ g_signal_connect (G_OBJECT (mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK (activate_guest_session), NULL);
+ }
+
+ if (count > 1 && count < 7)
+ {
+ for (u = users; u != NULL; u = g_list_next (u))
+ {
+ user = u->data;
+
+ mi = dbusmenu_menuitem_new ();
+ dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_LABEL, 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);
+ }
+ }
+
+ if (check_new_session ()) {
+ mi = dbusmenu_menuitem_new ();
+ dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_LABEL, _("New Session..."));
+ dbusmenu_menuitem_child_append (root, mi);
+ g_signal_connect (G_OBJECT (mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK (activate_new_session), NULL);
+ }
+}
+
+static void
+create_items (DbusmenuMenuitem *root,
+ UsersServiceDbus *service)
+{
+ g_return_if_fail (IS_USERS_SERVICE_DBUS (service));
+
+ dbusmenu_menuitem_foreach (root, remove_menu_item, NULL);
+
+ count = users_service_dbus_get_user_count (service);
+ if (count > 1 && count < 7)
+ {
+ users = users_service_dbus_get_user_list (service);
+ }
+
+ rebuild_items (root, service);
+}
+
+static void
+user_added (UsersServiceDbus *service,
+ gpointer user_data)
+{
+ /* Never thought you'd see a gpointer user_data get casted to a UserData* did you? */
+ users = g_list_append (users, (UserData *) user_data);
+}
+
+static void
+user_removed (UsersServiceDbus *service,
+ gpointer user_data)
+{
+ users = g_list_remove (users, (UserData *) user_data);
}
int
@@ -134,28 +201,39 @@ main (int argc, char ** argv)
g_type_init();
session_bus = dbus_g_bus_get(DBUS_BUS_SESSION, NULL);
- bus_proxy = dbus_g_proxy_new_for_name(session_bus, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
+ bus_proxy = dbus_g_proxy_new_for_name (session_bus, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
GError * error = NULL;
guint nameret = 0;
if (!org_freedesktop_DBus_request_name(bus_proxy, INDICATOR_USERS_DBUS_NAME, 0, &nameret, &error)) {
g_error("Unable to call to request name");
return 1;
- }
+ }
if (nameret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
g_error("Unable to get name");
return 1;
- }
+ }
+
+ dbus_interface = g_object_new (USERS_SERVICE_DBUS_TYPE, NULL);
root_menuitem = dbusmenu_menuitem_new();
- g_debug("Root ID: %d", dbusmenu_menuitem_get_id(root_menuitem));
+ g_debug ("Root ID: %d", dbusmenu_menuitem_get_id (root_menuitem));
- create_items(root_menuitem);
+ create_items (root_menuitem, dbus_interface);
DbusmenuServer * server = dbusmenu_server_new(INDICATOR_USERS_DBUS_OBJECT);
dbusmenu_server_set_root(server, root_menuitem);
+ g_signal_connect (G_OBJECT (dbus_interface),
+ "user-added",
+ G_CALLBACK (user_added),
+ root_menuitem);
+ g_signal_connect (G_OBJECT (dbus_interface),
+ "user-removed",
+ G_CALLBACK (user_removed),
+ root_menuitem);
+
mainloop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(mainloop);
diff --git a/src/users-service.xml b/src/users-service.xml
new file mode 100644
index 0000000..9eccf5d
--- /dev/null
+++ b/src/users-service.xml
@@ -0,0 +1,56 @@
+<!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/UserManager">
+ <interface name="org.gnome.DisplayManager.UserManager">
+
+ <!-- Get the number of known users -->
+ <method name="CountUsers">
+ <arg name="user_count" direction="out" type="i"/>
+ </method>
+
+ <!-- Get the list of known UIDs -->
+ <method name="GetUserList">
+ <arg name="uids" direction="out" type="ax"/>
+ </method>
+
+ <!-- Get user info for a user -->
+ <method name="GetUserInfo">
+ <arg name="uid" direction="in" type="x"/>
+ <arg name="user_name" direction="out" type="s"/>
+ <arg name="real_name" direction="out" type="s"/>
+ <arg name="shell" direction="out" type="s"/>
+ <arg name="icon_url" direction="out" type="s"/>
+ </method>
+
+ <!-- Get user info for a list of users -->
+ <method name="GetUsersInfo">
+ <arg name="uid" direction="in" type="ax"/>
+ <!-- (uid, user_name, real_name, shell, icon_url) -->
+ <arg name="user_info" direction="out" type="a(xssss)"/>
+ </method>
+
+ <!-- Triggered when user information is being reloaded.
+ All existing user information is invalid from this signal.
+ Wait for the UsersLoaded signal -->
+ <signal name="LoadingUsers"></signal>
+
+ <!-- Triggered when user information has been reloaded.
+ A client should call GetUserList() now -->
+ <signal name="UsersLoaded"></signal>
+
+ <!-- Triggered when a user has updated information -->
+ <signal name="UserUpdated">
+ <arg name="uid" type="x"/>
+ </signal>
+
+ <!-- Triggered when a users are added to/removed from the system.
+ Clients should monitor these signals as soon as they connect to
+ this object -->
+ <signal name="UserAdded">
+ <arg name="uid" type="x"/>
+ </signal>
+ <signal name="UserRemoved">
+ <arg name="uid" type="x"/>
+ </signal>
+
+ </interface>
+</node>