aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am6
-rw-r--r--src/dbus-shared-names.h10
-rw-r--r--src/gconf-helper.h6
-rw-r--r--src/indicator-session.c729
-rw-r--r--src/session-dbus.c74
-rw-r--r--src/session-dbus.h4
-rw-r--r--src/session-dbus.xml13
-rw-r--r--src/session-service.c466
-rw-r--r--src/user-menu-mgr.c358
-rw-r--r--src/user-menu-mgr.h53
-rw-r--r--src/user-widget.c341
-rw-r--r--src/user-widget.h54
12 files changed, 1430 insertions, 684 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index df0ec0f..9bf43cd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -14,6 +14,8 @@ libsession_la_SOURCES = \
gen-session-dbus.xml.h \
dbus-shared-names.h \
dbusmenu-shared.h \
+ user-widget.c \
+ user-widget.h \
accounts-service-client.h \
accounts-service-user-client.h
libsession_la_CFLAGS = \
@@ -89,7 +91,9 @@ indicator_session_service_SOURCES = \
dbusmenu-shared.h \
gconf-helper.c \
users-service-dbus.h \
- users-service-dbus.c
+ users-service-dbus.c \
+ user-menu-mgr.h \
+ user-menu-mgr.c
indicator_session_service_CFLAGS = \
$(SESSIONSERVICE_CFLAGS) \
$(GCONF_CFLAGS) \
diff --git a/src/dbus-shared-names.h b/src/dbus-shared-names.h
index f97dddc..c4ccd05 100644
--- a/src/dbus-shared-names.h
+++ b/src/dbus-shared-names.h
@@ -24,12 +24,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef __DBUS_SHARED_NAMES_H__
#define __DBUS_SHARED_NAMES_H__ 1
-#define INDICATOR_STATUS_DBUS_NAME "com.canonical.indicator.status"
-#define INDICATOR_STATUS_DBUS_OBJECT "/com/canonical/indicator/status/menu"
-#define INDICATOR_STATUS_SERVICE_DBUS_OBJECT "/com/canonical/indicator/status/service"
-#define INDICATOR_STATUS_SERVICE_DBUS_INTERFACE "com.canonical.indicator.status.service"
-
-#define INDICATOR_USERS_DBUS_NAME "com.canonical.indicator.users"
+#define INDICATOR_USERS_DBUS_NAME INDICATOR_SESSION_DBUS_NAME
#define INDICATOR_USERS_DBUS_OBJECT "/com/canonical/indicator/users/menu"
#define INDICATOR_USERS_SERVICE_DBUS_OBJECT "/org/gnome/DisplayManager/UserManager"
#define INDICATOR_USERS_SERVICE_DBUS_INTERFACE "org.gnome.DisplayManager.UserManager"
@@ -44,8 +39,9 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#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_IS_CURRENT_USER "user-item-is-current-user"
#define USER_ITEM_PROP_ICON "user-item-icon-path"
-#define USER_ITEM_ICON_DEFAULT "default-icon"
+#define USER_ITEM_ICON_DEFAULT "user-offline"
#define RESTART_ITEM_TYPE "x-canonical-restart-item"
#define RESTART_ITEM_LABEL "restart-label"
diff --git a/src/gconf-helper.h b/src/gconf-helper.h
index 505c24f..039b309 100644
--- a/src/gconf-helper.h
+++ b/src/gconf-helper.h
@@ -39,6 +39,12 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#define RESTART_KEY GLOBAL_DIR "/suppress_restart_menuitem"
#define SHUTDOWN_KEY GLOBAL_DIR "/suppress_shutdown_menuitem"
+#define LOCKDOWN_DIR "/desktop/gnome/lockdown"
+#define LOCKDOWN_KEY_USER LOCKDOWN_DIR "/disable_user_switching"
+#define LOCKDOWN_KEY_SCREENSAVER LOCKDOWN_DIR "/disable_lock_screen"
+#define KEYBINDING_DIR "/apps/gnome_settings_daemon/keybindings"
+#define KEY_LOCK_SCREEN KEYBINDING_DIR "/screensaver"
+
typedef struct _RestartShutdownLogoutMenuItems
{
DbusmenuMenuitem * logout_mi;
diff --git a/src/indicator-session.c b/src/indicator-session.c
index c9617c4..068ffef 100644
--- a/src/indicator-session.c
+++ b/src/indicator-session.c
@@ -20,6 +20,7 @@ You should have received a copy of the GNU General Public License along
with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+//TODO - remember to reinsert Ted's comments.
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -43,6 +44,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include "dbus-shared-names.h"
#include "dbusmenu-shared.h"
+#include "user-widget.h"
#define INDICATOR_SESSION_TYPE (indicator_session_get_type ())
#define INDICATOR_SESSION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_SESSION_TYPE, IndicatorSession))
@@ -61,8 +63,9 @@ struct _IndicatorSessionClass {
struct _IndicatorSession {
IndicatorObject parent;
IndicatorServiceManager * service;
- GtkImage * status_image;
- DbusmenuGtkMenu * menu;
+ IndicatorObjectEntry users;
+ IndicatorObjectEntry devices;
+ gboolean show_users_entry;
GCancellable * service_proxy_cancel;
GDBusProxy * service_proxy;
};
@@ -74,26 +77,37 @@ INDICATOR_SET_VERSION
INDICATOR_SET_TYPE(INDICATOR_SESSION_TYPE)
/* Prototypes */
-static GtkLabel * get_label (IndicatorObject * io);
-static GtkImage * get_icon (IndicatorObject * io);
-static GtkMenu * get_menu (IndicatorObject * io);
-static const gchar * get_accessible_desc (IndicatorObject * io);
-static gboolean build_menu_switch (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data);
-static gboolean new_user_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data);
-static void icon_changed (IndicatorSession * session, const gchar * icon_name);
+static gboolean build_menu_switch (DbusmenuMenuitem * newitem,
+ DbusmenuMenuitem * parent,
+ DbusmenuClient * client,
+ gpointer user_data);
+static gboolean new_user_item (DbusmenuMenuitem * newitem,
+ DbusmenuMenuitem * parent,
+ DbusmenuClient * client,
+ gpointer user_data);
+static gboolean build_restart_item (DbusmenuMenuitem * newitem,
+ DbusmenuMenuitem * parent,
+ DbusmenuClient * client,
+ gpointer user_data);
+static void indicator_session_update_users_label (IndicatorSession* self,
+ const gchar* name);
static void service_connection_cb (IndicatorServiceManager * sm, gboolean connected, gpointer user_data);
-static gboolean build_restart_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data);
static void receive_signal (GDBusProxy * proxy, gchar * sender_name, gchar * signal_name, GVariant * parameters, gpointer user_data);
static void service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data);
+static void user_real_name_get_cb (GObject * obj, GAsyncResult * res, gpointer user_data);
+static void user_menu_visibility_get_cb (GObject* obj, GAsyncResult* res, gpointer user_data);
static void indicator_session_class_init (IndicatorSessionClass *klass);
static void indicator_session_init (IndicatorSession *self);
static void indicator_session_dispose (GObject *object);
static void indicator_session_finalize (GObject *object);
-
+static GList* indicator_session_get_entries (IndicatorObject* obj);
+static guint indicator_session_get_location (IndicatorObject * io,
+ IndicatorObjectEntry * entry);
+
G_DEFINE_TYPE (IndicatorSession, indicator_session, INDICATOR_OBJECT_TYPE);
-static void
+static void
indicator_session_class_init (IndicatorSessionClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
@@ -102,82 +116,89 @@ indicator_session_class_init (IndicatorSessionClass *klass)
object_class->finalize = indicator_session_finalize;
IndicatorObjectClass * io_class = INDICATOR_OBJECT_CLASS(klass);
- io_class->get_label = get_label;
- io_class->get_image = get_icon;
- io_class->get_menu = get_menu;
- io_class->get_accessible_desc = get_accessible_desc;
-
+ io_class->get_entries = indicator_session_get_entries;
+ io_class->get_location = indicator_session_get_location;
return;
}
static void
indicator_session_init (IndicatorSession *self)
{
- /* Set good defaults */
self->service = NULL;
self->service_proxy_cancel = NULL;
self->service_proxy = NULL;
-
+ self->show_users_entry = FALSE;
+
/* Now let's fire these guys up. */
- self->service = indicator_service_manager_new_version(INDICATOR_SESSION_DBUS_NAME, 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 = 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);
-
+ self->service = indicator_service_manager_new_version(INDICATOR_SESSION_DBUS_NAME,
+ INDICATOR_SESSION_DBUS_VERSION);
+ g_signal_connect(G_OBJECT(self->service),
+ INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE,
+ G_CALLBACK(service_connection_cb), self);
+
+ GtkWidget* avatar_icon = NULL;
+ // users
+ self->users.menu = GTK_MENU (dbusmenu_gtkmenu_new (INDICATOR_USERS_DBUS_NAME,
+ INDICATOR_USERS_DBUS_OBJECT));
+ // Set the image to the default avator image
+ GdkPixbuf* pixbuf = NULL;
+ GError* error = NULL;
+ pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
+ "avatar-default",
+ 17,
+ GTK_ICON_LOOKUP_FORCE_SIZE,
+ &error);
+
+ // I think the avatar image is available always but just in case have a fallback
+ if (error != NULL) {
+ g_warning ("Could not load the default avatar image for some reason");
+ self->users.image = indicator_image_helper (USER_ITEM_ICON_DEFAULT);
+ }
+ else{
+ avatar_icon = gtk_image_new ();
+ gtk_image_set_from_pixbuf (GTK_IMAGE (avatar_icon), pixbuf);
+ self->users.image = GTK_IMAGE (avatar_icon);
+ g_object_unref (pixbuf);
+ g_error_free (error);
+ }
+
+ self->users.label = GTK_LABEL (gtk_label_new (NULL));
+ // Only show once we have a valid username
+ // gtk_widget_hide (GTK_WIDGET(self->users.label));
+
+ // devices
+ self->devices.menu = GTK_MENU (dbusmenu_gtkmenu_new(INDICATOR_SESSION_DBUS_NAME,
+ INDICATOR_SESSION_DBUS_OBJECT));
+ self->devices.image = indicator_image_helper (ICON_DEFAULT);
+
+ gtk_widget_show (GTK_WIDGET(self->devices.menu));
+ gtk_widget_show (GTK_WIDGET(self->devices.image));
+ gtk_widget_show (GTK_WIDGET(self->users.image));
+ gtk_widget_show (GTK_WIDGET(self->users.menu));
+
+ g_object_ref_sink (self->users.menu);
+ g_object_ref_sink (self->users.image);
+ g_object_ref_sink (self->devices.menu);
+ g_object_ref_sink (self->devices.image);
+
+ // Setup the handlers for users
+ DbusmenuClient * users_client = DBUSMENU_CLIENT(dbusmenu_gtkmenu_get_client(DBUSMENU_GTKMENU(self->users.menu)));
+ dbusmenu_client_add_type_handler (users_client,
+ USER_ITEM_TYPE,
+ new_user_item);
+ dbusmenu_client_add_type_handler_full (users_client,
+ MENU_SWITCH_TYPE,
+ build_menu_switch,
+ self, NULL);
+
+ // Setup the handlers for devices
+ DbusmenuClient * devices_client = DBUSMENU_CLIENT(dbusmenu_gtkmenu_get_client(DBUSMENU_GTKMENU(self->devices.menu)));
+ dbusmenu_client_add_type_handler (devices_client,
+ RESTART_ITEM_TYPE,
+ build_restart_item);
+
GtkAccelGroup * agroup = gtk_accel_group_new();
- dbusmenu_gtkclient_set_accel_group(DBUSMENU_GTKCLIENT(client), agroup);
-
- self->service_proxy_cancel = g_cancellable_new();
-
- g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
- G_DBUS_PROXY_FLAGS_NONE,
- NULL,
- INDICATOR_SESSION_DBUS_NAME,
- INDICATOR_SESSION_SERVICE_DBUS_OBJECT,
- INDICATOR_SESSION_SERVICE_DBUS_IFACE,
- self->service_proxy_cancel,
- service_proxy_cb,
- self);
-
- return;
-}
-
-/* Callback from trying to create the proxy for the serivce, this
- could include starting the service. Sometime it'll fail and
- we'll try to start that dang service again! */
-static void
-service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data)
-{
- GError * error = NULL;
-
- IndicatorSession * self = INDICATOR_SESSION(user_data);
- g_return_if_fail(self != NULL);
-
- GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish(res, &error);
-
- if (self->service_proxy_cancel != NULL) {
- g_object_unref(self->service_proxy_cancel);
- self->service_proxy_cancel = NULL;
- }
-
- if (error != NULL) {
- g_warning("Could not grab DBus proxy for %s: %s", INDICATOR_SESSION_DBUS_NAME, error->message);
- g_error_free(error);
- return;
- }
-
- /* Okay, we're good to grab the proxy at this point, we're
- sure that it's ours. */
- self->service_proxy = proxy;
-
- g_signal_connect(proxy, "g-signal", G_CALLBACK(receive_signal), self);
-
+ dbusmenu_gtkclient_set_accel_group(DBUSMENU_GTKCLIENT(devices_client), agroup);
return;
}
@@ -201,6 +222,14 @@ indicator_session_dispose (GObject *object)
g_object_unref(self->service_proxy_cancel);
self->service_proxy_cancel = NULL;
}
+
+ if (self->users.menu != NULL) {
+ g_object_unref (self->users.menu);
+ }
+
+ if (self->devices.menu != NULL) {
+ g_object_unref (self->devices.menu);
+ }
G_OBJECT_CLASS (indicator_session_parent_class)->dispose (object);
return;
@@ -214,256 +243,348 @@ indicator_session_finalize (GObject *object)
return;
}
-static void
-icon_name_get_cb (GObject * obj, GAsyncResult * res, gpointer user_data)
+static GList*
+indicator_session_get_entries (IndicatorObject* obj)
{
- IndicatorSession * self = INDICATOR_SESSION(user_data);
- GError * error = NULL;
- gchar * name;
- GVariant * result;
-
- result = g_dbus_proxy_call_finish(self->service_proxy, res, &error);
-
- if (error != NULL) {
- return;
- }
-
- g_variant_get(result, "(&s)", &name);
-
- if (name == NULL || name[0] == '\0') {
- return;
+ g_return_val_if_fail(IS_INDICATOR_SESSION(obj), NULL);
+ IndicatorSession* self = INDICATOR_SESSION (obj);
+
+ g_debug ("get entries");
+ GList * retval = NULL;
+ // Only show the users menu if we have more than one
+ if (self->show_users_entry == TRUE){
+ retval = g_list_prepend (retval, &self->users);
+ }
+ retval = g_list_prepend (retval, &self->devices);
+
+ if (retval != NULL) {
+ retval = g_list_reverse(retval);
}
+ return retval;
+}
- indicator_image_helper_update(self->status_image, name);
- return;
+static guint
+indicator_session_get_location (IndicatorObject * io,
+ IndicatorObjectEntry * entry)
+{
+ IndicatorSession * self = INDICATOR_SESSION (io);
+ if (entry == &self->users){
+ return 1;
+ }
+ else if (entry == &self->devices){
+ return 0;
+ }
+ g_warning ("IOEntry handed to us to position but we don't own it!");
+ return 0;
}
+/* callback for the service manager state of being */
static void
service_connection_cb (IndicatorServiceManager * sm, gboolean connected, gpointer user_data)
{
- IndicatorSession * self = INDICATOR_SESSION(user_data);
+ IndicatorSession * self = INDICATOR_SESSION (user_data);
if (connected) {
- g_dbus_proxy_call(self->service_proxy, "GetIcon", NULL,
- G_DBUS_CALL_FLAGS_NONE, -1, NULL,
- icon_name_get_cb, user_data);
- } else {
- indicator_image_helper_update(self->status_image, ICON_DEFAULT);
- }
-
+ if (self->service_proxy != NULL){
+ // Its a reconnect !
+ // Fetch synchronisation data and return (proxy is still legit)
+ g_dbus_proxy_call (self->service_proxy,
+ "GetUserMenuVisibility",
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ user_menu_visibility_get_cb,
+ user_data);
+ g_dbus_proxy_call (self->service_proxy,
+ "GetUserRealName",
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ user_real_name_get_cb,
+ user_data);
+ return;
+ }
+
+ self->service_proxy_cancel = g_cancellable_new();
+ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+ G_DBUS_PROXY_FLAGS_NONE,
+ NULL,
+ INDICATOR_SESSION_DBUS_NAME,
+ INDICATOR_SESSION_SERVICE_DBUS_OBJECT,
+ INDICATOR_SESSION_SERVICE_DBUS_IFACE,
+ self->service_proxy_cancel,
+ service_proxy_cb,
+ self);
+ }
return;
}
-static GtkLabel *
-get_label (IndicatorObject * io)
-{
- return NULL;
-}
-
-static const gchar *
-get_accessible_desc (IndicatorObject * io)
-{
- return _("Session");
-}
static void
-icon_changed (IndicatorSession * session, const gchar * icon_name)
+service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data)
{
- indicator_image_helper_update(session->status_image, icon_name);
- return;
-}
+ GError * error = NULL;
-/* Receives all signals from the service, routed to the appropriate functions */
-static void
-receive_signal (GDBusProxy * proxy, gchar * sender_name, gchar * signal_name,
- GVariant * parameters, gpointer user_data)
-{
IndicatorSession * self = INDICATOR_SESSION(user_data);
+ g_return_if_fail(self != NULL);
- if (g_strcmp0(signal_name, "IconUpdated") == 0) {
- const gchar *name;
- g_variant_get (parameters, "(&s)", &name);
- icon_changed(self, name);
+ GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish(res, &error);
+
+ if (self->service_proxy_cancel != NULL) {
+ g_object_unref(self->service_proxy_cancel);
+ self->service_proxy_cancel = NULL;
}
- return;
-}
+ if (error != NULL) {
+ g_warning("Could not grab DBus proxy for %s: %s", INDICATOR_SESSION_DBUS_NAME, error->message);
+ g_error_free(error);
+ return;
+ }
-static GtkImage *
-get_icon (IndicatorObject * io)
-{
- gtk_widget_show(GTK_WIDGET(INDICATOR_SESSION(io)->status_image));
- return INDICATOR_SESSION(io)->status_image;
-}
+ /* Okay, we're good to grab the proxy at this point, we're
+ sure that it's ours. */
+ self->service_proxy = proxy;
-static void
-user_property_change (DbusmenuMenuitem * item, const gchar * property, GVariant * variant, gpointer user_data)
-{
- if (g_strcmp0(property, USER_ITEM_PROP_LOGGED_IN) == 0) {
- if (g_variant_get_boolean(variant)) {
- gtk_widget_show(GTK_WIDGET(user_data));
- } else {
- gtk_widget_hide(GTK_WIDGET(user_data));
- }
- }
+ g_signal_connect(proxy, "g-signal", G_CALLBACK(receive_signal), self);
+
+ // Figure out whether we should show the user menu at all.
+ g_dbus_proxy_call (self->service_proxy,
+ "GetUserMenuVisibility",
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ user_menu_visibility_get_cb,
+ user_data);
+
+ // Fetch the user's real name for the user entry label
+ g_dbus_proxy_call (self->service_proxy,
+ "GetUserRealName",
+ NULL,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL,
+ user_real_name_get_cb,
+ user_data);
return;
}
-/* Builds an item with a hip little logged in icon. */
+
static gboolean
-new_user_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data)
+new_user_item (DbusmenuMenuitem * newitem,
+ DbusmenuMenuitem * parent,
+ DbusmenuClient * client,
+ gpointer user_data)
{
- GtkMenuItem * gmi = GTK_MENU_ITEM(gtk_menu_item_new());
- 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)) {
- gint width, height;
- gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height);
-
- GError * error = NULL;
- GdkPixbuf * pixbuf = gdk_pixbuf_new_from_file_at_size(icon_name, width, height, &error);
-
- if (error == NULL) {
- usericon = gtk_image_new_from_pixbuf(pixbuf);
- g_object_unref(pixbuf);
- } else {
- g_warning("Unable to load user icon '%s': %s", icon_name, error->message);
- g_error_free(error);
- }
- }
+
- if (usericon == NULL) {
- 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);
- }
- }
- 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* user_item = NULL;
- 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);
- gtk_box_pack_start(GTK_BOX(hbox), label, TRUE, TRUE, 0);
- gtk_widget_show(label);
-
- GtkWidget * icon = gtk_image_new_from_icon_name("account-logged-in", GTK_ICON_SIZE_MENU);
- gtk_misc_set_alignment(GTK_MISC(icon), 1.0, 0.5);
- gtk_box_pack_start(GTK_BOX(hbox), icon, FALSE, FALSE, 0);
- if (dbusmenu_menuitem_property_get_bool(newitem, USER_ITEM_PROP_LOGGED_IN)) {
- gtk_widget_show(icon);
- } else {
- gtk_widget_hide(icon);
- }
+ g_return_val_if_fail(DBUSMENU_IS_MENUITEM(newitem), FALSE);
+ g_return_val_if_fail(DBUSMENU_IS_GTKCLIENT(client), FALSE);
- gtk_container_add(GTK_CONTAINER(gmi), hbox);
- gtk_widget_show(hbox);
+ user_item = user_widget_new(newitem);
- dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, gmi, parent);
+ GtkMenuItem *user_widget = GTK_MENU_ITEM(user_item);
- g_signal_connect(G_OBJECT(newitem), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(user_property_change), icon);
+ dbusmenu_gtkclient_newitem_base (DBUSMENU_GTKCLIENT(client),
+ newitem,
+ user_widget,
+ parent);
- return TRUE;
-}
+ g_debug ("%s (\"%s\")", __func__,
+ dbusmenu_menuitem_property_get (newitem,
+ USER_ITEM_PROP_NAME));
+ gtk_widget_show_all (user_item);
-/* Indicator based function to get the menu for the whole
- applet. This starts up asking for the parts of the menu
- from the various services. */
-static GtkMenu *
-get_menu (IndicatorObject * io)
-{
- return GTK_MENU(INDICATOR_SESSION(io)->menu);
+ return TRUE;
}
+
static void
-switch_property_change (DbusmenuMenuitem * item, const gchar * property, GVariant * variant, gpointer user_data)
+user_real_name_get_cb (GObject * obj, GAsyncResult * res, gpointer user_data)
{
- if (g_strcmp0(property, MENU_SWITCH_USER) != 0) {
- return;
- }
-
- GtkMenuItem * gmi = dbusmenu_gtkclient_menuitem_get(DBUSMENU_GTKCLIENT(user_data), item);
- gchar * finalstring = NULL;
- gboolean set_ellipsize = FALSE;
- gboolean no_name_in_lang = FALSE;
-
- /* TRANSLATORS: Translate the '1' below into anything other than
- '1' if "Switch From %s..." doesn't make sense in your language.
- Instead, the string "Switch User..." will be used. */
- const gchar * translate = C_("session_menu:switchfrom", "1");
- if (g_strcmp0(translate, "1") != 0) {
- no_name_in_lang = TRUE;
- }
+ IndicatorSession * self = INDICATOR_SESSION(user_data);
+ GError * error = NULL;
+ GVariant * result;
- /* If there's a NULL string of some type, then we want to
- go back to our old 'Switch User' which isn't great but
- eh, this error condition should never happen. */
- if (variant == NULL || g_variant_get_string(variant, NULL) == NULL || g_variant_get_string(variant, NULL)[0] == '\0' || no_name_in_lang) {
- finalstring = _("Switch User...");
- set_ellipsize = FALSE;
- }
+ result = g_dbus_proxy_call_finish(self->service_proxy, res, &error);
- if (finalstring == NULL) {
- const gchar * username = g_variant_get_string(variant, NULL);
- GtkStyle * style = gtk_widget_get_style(GTK_WIDGET(gmi));
+ if (error != NULL) {
+ g_warning ("unable to complete real name dbus query");
+ g_error_free (error);
+ return;
+ }
+
+ const gchar* username = NULL;
+ g_variant_get (result, "(s)", &username);
+ indicator_session_update_users_label (self, username);
+ return;
+}
- PangoLayout * layout = pango_layout_new(gtk_widget_get_pango_context(GTK_WIDGET(gmi)));
- pango_layout_set_text(layout, username, -1);
- pango_layout_set_font_description(layout, style->font_desc);
+static void
+user_menu_visibility_get_cb (GObject* obj, GAsyncResult* res, gpointer user_data)
+{
+ IndicatorSession * self = INDICATOR_SESSION(user_data);
+ GError * error = NULL;
+ GVariant * result;
- gint width;
- pango_layout_get_pixel_size(layout, &width, NULL);
- g_object_unref(layout);
- g_debug("Username width %dpx", width);
+ result = g_dbus_proxy_call_finish(self->service_proxy, res, &error);
- gint point = pango_font_description_get_size(style->font_desc);
- g_debug("Font size %f pt", (gfloat)point / PANGO_SCALE);
+ if (error != NULL) {
+ g_warning ("unable to complete real name dbus query");
+ g_error_free (error);
+ return;
+ }
+ gboolean update;
+ g_variant_get (result, "(b)", &update);
+
+ // If it is what we had before no need to do anything...
+ if (self->show_users_entry == update){
+ return;
+ }
+
+ //Otherwise
+ self->show_users_entry = update;
+
+ IndicatorObjectEntry user_entry = self->users;
+
+ if (self->show_users_entry == TRUE){
+ g_signal_emit_by_name ((gpointer)self,
+ "entry-added",
+ &user_entry);
+ }
+ else{
+ g_signal_emit_by_name ((gpointer)self,
+ "entry-removed",
+ &user_entry);
+ }
+}
- gdouble dpi = gdk_screen_get_resolution(gdk_screen_get_default());
- g_debug("Screen DPI %f", dpi);
+/* Receives all signals from the service, routed to the appropriate functions */
+static void
+receive_signal (GDBusProxy * proxy,
+ gchar * sender_name,
+ gchar * signal_name,
+ GVariant * parameters,
+ gpointer user_data)
+{
+ IndicatorSession * self = INDICATOR_SESSION(user_data);
- gdouble pixels_per_em = ((point * dpi) / 72.0f) / PANGO_SCALE;
- gdouble ems = width / pixels_per_em;
- g_debug("Username width %fem", ems);
+ if (g_strcmp0(signal_name, "UserRealNameUpdated") == 0) {
+ const gchar* username = NULL;
+ g_variant_get (parameters, "(s)", &username);
+ indicator_session_update_users_label (self, username);
+ }
+ else if (g_strcmp0(signal_name, "UserMenuIsVisible") == 0) {
+ gboolean update;
+ g_variant_get (parameters, "(b)", &update);
+
+ // If it is what we had before no need to do anything...
+ if (self->show_users_entry == update){
+ return;
+ }
+
+ //Otherwise
+ self->show_users_entry = update;
+
+ IndicatorObjectEntry user_entry = self->users;
+
+ if (self->show_users_entry == TRUE){
+ g_signal_emit_by_name ((gpointer)self,
+ "entry-added",
+ &user_entry);
+ }
+ else{
+ g_signal_emit_by_name ((gpointer)self,
+ "entry-removed",
+ &user_entry);
+ }
+ }
+}
- /* 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);
- if (ems >= 20.0f) {
- set_ellipsize = TRUE;
- } else {
- set_ellipsize = FALSE;
- }
- }
- gtk_menu_item_set_label(gmi, finalstring);
- GtkLabel * label = GTK_LABEL(gtk_bin_get_child(GTK_BIN(gmi)));
- if (label != NULL) {
- if (set_ellipsize) {
- gtk_label_set_ellipsize(label, PANGO_ELLIPSIZE_END);
- } else {
- gtk_label_set_ellipsize(label, PANGO_ELLIPSIZE_NONE);
- }
- }
+static void
+switch_property_change (DbusmenuMenuitem * item,
+ const gchar * property,
+ GVariant * variant,
+ gpointer user_data)
+{
+ if (g_strcmp0 (property, MENU_SWITCH_USER) != 0) {
+ return;
+ }
+
+ GtkMenuItem * gmi = dbusmenu_gtkclient_menuitem_get(DBUSMENU_GTKCLIENT(user_data), item);
+ gchar * finalstring = NULL;
+ gboolean set_ellipsize = FALSE;
+ gboolean no_name_in_lang = FALSE;
+
+ const gchar * translate = C_("session_menu:switchfrom", "1");
+ if (g_strcmp0(translate, "1") != 0) {
+ no_name_in_lang = TRUE;
+ }
+
+ if (variant == NULL || g_variant_get_string(variant, NULL) == NULL ||
+ g_variant_get_string(variant, NULL)[0] == '\0' || no_name_in_lang) {
+ finalstring = _("Switch User...");
+ set_ellipsize = FALSE;
+ }
+
+ if (finalstring == NULL) {
+ const gchar * username = g_variant_get_string(variant, NULL);
+ GtkStyle * style = gtk_widget_get_style(GTK_WIDGET(gmi));
+
+ PangoLayout * layout = pango_layout_new(gtk_widget_get_pango_context(GTK_WIDGET(gmi)));
+ pango_layout_set_text (layout, username, -1);
+ pango_layout_set_font_description(layout, style->font_desc);
+
+ gint width;
+ pango_layout_get_pixel_size(layout, &width, NULL);
+ g_object_unref(layout);
+ g_debug("Username width %dpx", width);
+
+ gint point = pango_font_description_get_size(style->font_desc);
+ g_debug("Font size %f pt", (gfloat)point / PANGO_SCALE);
+
+ gdouble dpi = gdk_screen_get_resolution(gdk_screen_get_default());
+ g_debug("Screen DPI %f", dpi);
+
+ gdouble pixels_per_em = ((point * dpi) / 72.0f) / PANGO_SCALE;
+ gdouble ems = width / pixels_per_em;
+ g_debug("Username width %fem", ems);
+
+ finalstring = g_strdup_printf(_("Switch From %s..."), username);
+ if (ems >= 20.0f) {
+ set_ellipsize = TRUE;
+ } else {
+ set_ellipsize = FALSE;
+ }
+
+ }
+ gtk_menu_item_set_label(gmi, finalstring);
+
+ GtkLabel * label = GTK_LABEL(gtk_bin_get_child(GTK_BIN(gmi)));
+ if (label != NULL) {
+ if (set_ellipsize) {
+ gtk_label_set_ellipsize(label, PANGO_ELLIPSIZE_END);
+ } else {
+ gtk_label_set_ellipsize(label, PANGO_ELLIPSIZE_NONE);
+ }
+ }
return;
}
static const gchar * dbusmenu_item_data = "dbusmenu-item";
-/* 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, GVariant * variant, gpointer user_data)
+restart_property_change (DbusmenuMenuitem * item,
+ const gchar * property,
+ GVariant * variant,
+ gpointer user_data)
{
DbusmenuGtkClient * client = DBUSMENU_GTKCLIENT(user_data);
GtkMenuItem * gmi = dbusmenu_gtkclient_menuitem_get(client, item);
@@ -482,14 +603,14 @@ restart_property_change (DbusmenuMenuitem * item, const gchar * property, GVaria
}
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, gpointer user_data)
+build_restart_item (DbusmenuMenuitem * newitem,
+ DbusmenuMenuitem * parent,
+ DbusmenuClient * client,
+ gpointer user_data)
{
GtkMenuItem * gmi = GTK_MENU_ITEM(gtk_image_menu_item_new());
if (gmi == NULL) {
@@ -500,7 +621,6 @@ build_restart_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, Dbusm
g_signal_connect(G_OBJECT(newitem), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(restart_property_change), client);
- /* Grab the inital variants and put them into the item */
GVariant * variant;
variant = dbusmenu_menuitem_property_get_variant(newitem, RESTART_ITEM_LABEL);
if (variant != NULL) {
@@ -515,36 +635,63 @@ build_restart_item (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, Dbusm
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
-switch_style_set (GtkWidget * widget, GtkStyle * prev_style, gpointer user_data)
+switch_style_set (GtkWidget * widget,
+ GtkStyle * prev_style,
+ gpointer user_data)
{
DbusmenuGtkClient * client = DBUSMENU_GTKCLIENT(user_data);
- DbusmenuMenuitem * mi = DBUSMENU_MENUITEM(g_object_get_data(G_OBJECT(widget), dbusmenu_item_data));
+ DbusmenuMenuitem * mi = DBUSMENU_MENUITEM(g_object_get_data(G_OBJECT(widget),
+ dbusmenu_item_data));
- switch_property_change(mi, MENU_SWITCH_USER, dbusmenu_menuitem_property_get_variant(mi, MENU_SWITCH_USER), client);
+ switch_property_change (mi,
+ MENU_SWITCH_USER,
+ dbusmenu_menuitem_property_get_variant(mi, MENU_SWITCH_USER),
+ client);
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. */
static gboolean
-build_menu_switch (DbusmenuMenuitem * newitem, DbusmenuMenuitem * parent, DbusmenuClient * client, gpointer user_data)
+build_menu_switch (DbusmenuMenuitem * newitem,
+ DbusmenuMenuitem * parent,
+ DbusmenuClient * client,
+ gpointer user_data)
{
GtkMenuItem * gmi = GTK_MENU_ITEM(gtk_menu_item_new());
if (gmi == NULL) {
return FALSE;
}
- g_object_set_data(G_OBJECT(gmi), dbusmenu_item_data, newitem);
+
+ g_object_set_data(G_OBJECT(gmi), dbusmenu_item_data, newitem);
dbusmenu_gtkclient_newitem_base(DBUSMENU_GTKCLIENT(client), newitem, gmi, parent);
- g_signal_connect(G_OBJECT(newitem), DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED, G_CALLBACK(switch_property_change), client);
- g_signal_connect(G_OBJECT(gmi), "style-set", G_CALLBACK(switch_style_set), client);
- switch_property_change(newitem, MENU_SWITCH_USER, dbusmenu_menuitem_property_get_variant(newitem, MENU_SWITCH_USER), client);
+ g_signal_connect (G_OBJECT(newitem),
+ DBUSMENU_MENUITEM_SIGNAL_PROPERTY_CHANGED,
+ G_CALLBACK(switch_property_change),
+ client);
+ g_signal_connect (G_OBJECT(gmi),
+ "style-set",
+ G_CALLBACK(switch_style_set),
+ client);
+
+ switch_property_change (newitem,
+ MENU_SWITCH_USER,
+ dbusmenu_menuitem_property_get_variant(newitem, MENU_SWITCH_USER), client);
+
+ return TRUE;
+}
- return TRUE;
+static void
+indicator_session_update_users_label (IndicatorSession* self,
+ const gchar* name)
+{
+ g_debug ("update users label");
+
+ if (name == NULL){
+ gtk_widget_hide(GTK_WIDGET(self->users.label));
+ return;
+ }
+ gtk_label_set_text (self->users.label, g_strdup(name));
+ gtk_widget_show(GTK_WIDGET(self->users.label));
}
diff --git a/src/session-dbus.c b/src/session-dbus.c
index fa9ea54..9aa75ef 100644
--- a/src/session-dbus.c
+++ b/src/session-dbus.c
@@ -5,6 +5,7 @@ Copyright 2010 Canonical Ltd.
Authors:
Ted Gould <ted@canonical.com>
+ Conor Curran <conor.curran@canonical.com>
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License version 3, as published
@@ -28,7 +29,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include "session-dbus.h"
#include "dbus-shared-names.h"
-static GVariant * get_icon (SessionDbus * service);
+static GVariant * get_users_real_name (SessionDbus * service);
static void bus_get_cb (GObject * object, GAsyncResult * res, gpointer user_data);
static void bus_method_call (GDBusConnection * connection, const gchar * sender, const gchar * path, const gchar * interface, const gchar * method, GVariant * params, GDBusMethodInvocation * invocation, gpointer user_data);
@@ -37,6 +38,7 @@ static void bus_method_call (GDBusConnection * connection, const gchar * sender,
typedef struct _SessionDbusPrivate SessionDbusPrivate;
struct _SessionDbusPrivate {
gchar * name;
+ gboolean user_menu_is_visible;
GDBusConnection * bus;
GCancellable * bus_cancel;
guint dbus_registration;
@@ -98,10 +100,11 @@ session_dbus_init (SessionDbus *self)
{
SessionDbusPrivate * priv = SESSION_DBUS_GET_PRIVATE(self);
- priv->name = g_strdup(ICON_DEFAULT);
+ priv->name = NULL;
priv->bus = NULL;
priv->bus_cancel = NULL;
priv->dbus_registration = 0;
+ priv->user_menu_is_visible = FALSE;
priv->bus_cancel = g_cancellable_new();
g_bus_get(G_BUS_TYPE_SESSION,
@@ -160,15 +163,20 @@ bus_method_call (GDBusConnection * connection, const gchar * sender,
const gchar * method, GVariant * params,
GDBusMethodInvocation * invocation, gpointer user_data)
{
- SessionDbus * service = SESSION_DBUS(user_data);
+ SessionDbus * service = SESSION_DBUS (user_data);
+ SessionDbusPrivate * priv = SESSION_DBUS_GET_PRIVATE (service);
+
GVariant * retval = NULL;
- if (g_strcmp0(method, "GetIcon") == 0) {
- retval = get_icon(service);
- } else {
- g_warning("Calling method '%s' on the indicator service and it's unknown", method);
+ if (g_strcmp0(method, "GetUserRealName") == 0) {
+ retval = get_users_real_name (service);
+ }
+ else if (g_strcmp0 (method, "GetUserMenuVisibility") == 0){
+ retval = g_variant_new ("(b)", priv->user_menu_is_visible);
+ }
+ else {
+ g_warning("Calling method '%s' on the indicator service and it's unknown", method);
}
-
g_dbus_method_invocation_return_value(invocation, retval);
return;
}
@@ -214,10 +222,10 @@ session_dbus_finalize (GObject *object)
}
static GVariant *
-get_icon (SessionDbus * service)
+get_users_real_name (SessionDbus * service)
{
SessionDbusPrivate * priv = SESSION_DBUS_GET_PRIVATE(service);
- return g_variant_new("(s)", priv->name);
+ return g_variant_new ("(s)", priv->name);
}
SessionDbus *
@@ -229,29 +237,59 @@ session_dbus_new (void)
void
session_dbus_set_name (SessionDbus * session, const gchar * name)
{
+}
+
+void
+session_dbus_set_users_real_name (SessionDbus * session, const gchar * name)
+{
SessionDbusPrivate * priv = SESSION_DBUS_GET_PRIVATE(session);
GError * error = NULL;
if (priv->name != NULL) {
g_free(priv->name);
priv->name = NULL;
}
+
priv->name = g_strdup(name);
if (priv->bus != NULL) {
g_dbus_connection_emit_signal (priv->bus,
- NULL,
- INDICATOR_SESSION_SERVICE_DBUS_OBJECT,
- INDICATOR_SESSION_SERVICE_DBUS_IFACE,
- "IconUpdated",
- g_variant_new ("(s)", priv->name, NULL),
- &error);
+ NULL,
+ INDICATOR_SESSION_SERVICE_DBUS_OBJECT,
+ INDICATOR_SESSION_SERVICE_DBUS_IFACE,
+ "UserRealNameUpdated",
+ g_variant_new ("(s)", priv->name, NULL),
+ &error);
if (error != NULL) {
- g_warning("Unable to send IconUpdated signal: %s", error->message);
+ g_warning("Unable to send UserRealNameUpdated signal: %s", error->message);
g_error_free(error);
return;
}
}
-
return;
}
+
+void
+session_dbus_set_user_menu_visibility (SessionDbus* session,
+ gboolean visible)
+{
+ SessionDbusPrivate * priv = SESSION_DBUS_GET_PRIVATE(session);
+ GError * error = NULL;
+
+ priv->user_menu_is_visible = visible;
+
+ if (priv->bus != NULL) {
+ g_dbus_connection_emit_signal (priv->bus,
+ NULL,
+ INDICATOR_SESSION_SERVICE_DBUS_OBJECT,
+ INDICATOR_SESSION_SERVICE_DBUS_IFACE,
+ "UserMenuIsVisible",
+ g_variant_new ("(b)", priv->user_menu_is_visible),
+ &error);
+
+ if (error != NULL) {
+ g_warning("Unable to send UserMenuIsVisible signal: %s", error->message);
+ g_error_free(error);
+ }
+ }
+}
diff --git a/src/session-dbus.h b/src/session-dbus.h
index 792917b..45ebae2 100644
--- a/src/session-dbus.h
+++ b/src/session-dbus.h
@@ -48,7 +48,9 @@ struct _SessionDbus {
GType session_dbus_get_type (void);
SessionDbus * session_dbus_new (void);
-void session_dbus_set_name (SessionDbus * session, const gchar * name);
+void session_dbus_set_name (SessionDbus * session, const gchar * name);
+void session_dbus_set_users_real_name (SessionDbus * session, const gchar * name);
+void session_dbus_set_user_menu_visibility (SessionDbus* session, gboolean visible);
G_END_DECLS
diff --git a/src/session-dbus.xml b/src/session-dbus.xml
index ee724f5..f496ff1 100644
--- a/src/session-dbus.xml
+++ b/src/session-dbus.xml
@@ -2,14 +2,17 @@
<node name="/com/canonical/indicator/session/service">
<interface name="com.canonical.indicator.session.service">
- <!-- Icon -->
- <method name="GetIcon">
+ <method name="GetUserRealName">
<arg name="name" direction="out" type="s"/>
</method>
-
- <signal name="IconUpdated">
+ <method name="GetUserMenuVisibility">
+ <arg name="update" direction="out" type="b"/>
+ </method>
+ <signal name="UserRealNameUpdated">
<arg name="name" type="s"/>
</signal>
-
+ <signal name="UserMenuIsVisible">
+ <arg name="update" type="b"/>
+ </signal>
</interface>
</node>
diff --git a/src/session-service.c b/src/session-service.c
index dfc3805..2b00d87 100644
--- a/src/session-service.c
+++ b/src/session-service.c
@@ -8,6 +8,7 @@ Authors:
Ted Gould <ted@canonical.com>
Christoph Korn <c_korn@gmx.de>
Cody Russell <crussell@canonical.com>
+ Conor Curran <conor.curran@canonical.com>
This program is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License version 3, as published
@@ -36,17 +37,24 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#include <libdbusmenu-glib/server.h>
#include <libdbusmenu-glib/menuitem.h>
#include <libdbusmenu-glib/client.h>
+
+#include <gtk/gtk.h>
+#if GTK_CHECK_VERSION(3, 0, 0)
#include <libdbusmenu-gtk3/menuitem.h>
+#else
+#include <libdbusmenu-gtk/menuitem.h>
+#endif
#include <libindicator/indicator-service.h>
#include "dbus-shared-names.h"
#include "dbusmenu-shared.h"
+#include "users-service-dbus.h"
+#include "user-menu-mgr.h"
#include "gconf-helper.h"
#include "session-dbus.h"
-#include "users-service-dbus.h"
#include "lock-helper.h"
#include "upower-client.h"
@@ -56,12 +64,6 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
#define EXTRA_LAUNCHER_DIR "/usr/share/indicators/session/applications"
-#define LOCKDOWN_DIR "/desktop/gnome/lockdown"
-#define LOCKDOWN_KEY_USER LOCKDOWN_DIR "/disable_user_switching"
-#define LOCKDOWN_KEY_SCREENSAVER LOCKDOWN_DIR "/disable_lock_screen"
-
-#define KEYBINDING_DIR "/apps/gnome_settings_daemon/keybindings"
-#define KEY_LOCK_SCREEN KEYBINDING_DIR "/screensaver"
typedef struct _ActivateData ActivateData;
struct _ActivateData
@@ -70,13 +72,11 @@ struct _ActivateData
UserData *user;
};
-static UsersServiceDbus *dbus_interface = NULL;
+//static UsersServiceDbus *dbus_interface = NULL;
static SessionDbus *session_dbus = NULL;
-
static DbusmenuMenuitem *lock_menuitem = NULL;
-static DbusmenuMenuitem *switch_menuitem = NULL;
+static DbusmenuMenuitem * session_root_menuitem = NULL;
-static DbusmenuMenuitem * root_menuitem = NULL;
static GMainLoop * mainloop = NULL;
static DBusGProxy * up_main_proxy = NULL;
static DBusGProxy * up_prop_proxy = NULL;
@@ -97,7 +97,7 @@ static gboolean allow_suspend = TRUE;
static GConfClient * gconf_client = NULL;
-static void rebuild_items (DbusmenuMenuitem *root, UsersServiceDbus *service);
+static void rebuild_session_items (DbusmenuMenuitem *root);
static void
lockdown_changed (GConfClient *client,
@@ -113,7 +113,7 @@ lockdown_changed (GConfClient *client,
}
if (g_strcmp0 (key, LOCKDOWN_KEY_USER) == 0 || g_strcmp0 (key, LOCKDOWN_KEY_SCREENSAVER) == 0) {
- rebuild_items(root_menuitem, dbus_interface);
+ rebuild_session_items(session_root_menuitem);
}
return;
@@ -138,7 +138,6 @@ keybinding_changed (GConfClient *client,
dbusmenu_menuitem_property_set_shortcut_string(lock_menuitem, gconf_value_get_string(value));
}
}
-
return;
}
@@ -156,7 +155,7 @@ ensure_gconf_client (void)
gconf_client_add_dir(gconf_client, KEYBINDING_DIR, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
gconf_client_notify_add(gconf_client, KEYBINDING_DIR, keybinding_changed, NULL, NULL, NULL);
}
- return;
+ return;
}
/* Check to see if the lockdown key is protecting from
@@ -166,9 +165,8 @@ lock_if_possible (void) {
ensure_gconf_client ();
if (!gconf_client_get_bool (gconf_client, LOCKDOWN_KEY_SCREENSAVER, NULL)) {
- lock_screen(NULL, 0, NULL);
+ lock_screen (NULL, 0, NULL);
}
-
return;
}
@@ -224,7 +222,7 @@ suspend_prop_cb (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata)
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);
+ rebuild_session_items(session_root_menuitem);
}
return;
@@ -249,7 +247,7 @@ hibernate_prop_cb (DBusGProxy * proxy, DBusGProxyCall * call, gpointer userdata)
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);
+ rebuild_session_items(session_root_menuitem);
}
return;
@@ -310,7 +308,7 @@ allowed_cb (DBusGProxy *proxy, gboolean OUT_allowed, GError *error, gpointer use
if (OUT_allowed != *can_do) {
*can_do = OUT_allowed;
- rebuild_items (root_menuitem, dbus_interface);
+ rebuild_session_items (session_root_menuitem);
}
}
@@ -387,145 +385,26 @@ show_dialog (DbusmenuMenuitem * mi, guint timestamp, gchar * type)
return;
}
-/* Checks to see if we should show the guest session item */
-static gboolean
-check_guest_session (void)
-{
- if (geteuid() < 500) {
- /* System users shouldn't have guest account shown. Mosly
- this would be the case of the guest user itself. */
- return FALSE;
- }
- // FIXME: Ask DisplayManager
-
- return TRUE;
-}
-
-/* Called when someone clicks on the guest session item. */
-static void
-activate_guest_session (DbusmenuMenuitem * mi, guint timestamp, gpointer user_data)
-{
- lock_if_possible();
-
- if (!users_service_dbus_activate_guest_session(USERS_SERVICE_DBUS(user_data)))
- g_warning("Unable to activate guest session");
-
- return;
-}
-
-/* Checks to see if we can create sessions */
-static gboolean
-check_new_session (void)
-{
- return TRUE;
-}
-
-/* Starts a new generic session */
-static void
-activate_new_session (DbusmenuMenuitem * mi, guint timestamp, gpointer user_data)
-{
- lock_if_possible();
-
- users_service_dbus_show_greeter (USERS_SERVICE_DBUS(user_data));
-
- return;
-}
-
-/* Activates a session for a particular user. */
-static void
-activate_user_session (DbusmenuMenuitem *mi, guint timestamp, gpointer user_data)
-{
- UserData *user = (UserData *)user_data;
- UsersServiceDbus *service = user->service;
-
- lock_if_possible();
-
- users_service_dbus_activate_user_session (service, user);
-}
-
-/* Comparison function to look into the UserData struct
- to compare by using the username value */
-static gint
-compare_users_by_username (const gchar *a,
- const gchar *b)
-{
- UserData *user1 = (UserData *)a;
- UserData *user2 = (UserData *)b;
-
- gint retval = g_strcmp0 (user1->real_name, user2->real_name);
-
- /* If they're the same, they're both in conflict. */
- if (retval == 0) {
- user1->real_name_conflict = TRUE;
- user2->real_name_conflict = TRUE;
- }
-
- return retval;
-}
-
-/* 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;
-}
-
-/* Look at the GAppInfo structures and sort based on
- the application names */
-static gint
-sort_app_infos (gconstpointer a, gconstpointer b)
-{
- GAppInfo * appa = G_APP_INFO(a);
- GAppInfo * appb = G_APP_INFO(b);
-
- const gchar * namea = NULL;
- const gchar * nameb = NULL;
-
- if (appa != NULL) {
- namea = g_app_info_get_name(appa);
- }
-
- if (appb != NULL) {
- nameb = g_app_info_get_name(appb);
- }
-
- return g_strcmp0(namea, nameb);
-}
-/* Builds up the menu for us */
static void
-rebuild_items (DbusmenuMenuitem *root,
- UsersServiceDbus *service)
+rebuild_session_items (DbusmenuMenuitem *root)
+
{
- DbusmenuMenuitem *mi = NULL;
- DbusmenuMenuitem * guest_mi = NULL;
- GList *u;
- UserData *user;
- gboolean can_activate;
gboolean can_lockscreen;
- GList *children;
/* Make sure we have a valid GConf client, and build one
if needed */
ensure_gconf_client ();
- /* Check to see which menu items we're allowed to have */
- can_activate = users_service_dbus_can_activate_session (service) &&
- !gconf_client_get_bool (gconf_client, LOCKDOWN_KEY_USER, NULL);
- 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);
-
+ can_lockscreen = !gconf_client_get_bool ( gconf_client,
+ LOCKDOWN_KEY_SCREENSAVER,
+ NULL);
/* Lock screen item */
if (can_lockscreen) {
lock_menuitem = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set(lock_menuitem, DBUSMENU_MENUITEM_PROP_LABEL, _("Lock Screen"));
+ dbusmenu_menuitem_property_set (lock_menuitem,
+ DBUSMENU_MENUITEM_PROP_LABEL,
+ _("Lock Screen"));
gchar * shortcut = gconf_client_get_string(gconf_client, KEY_LOCK_SCREEN, NULL);
if (shortcut != NULL) {
@@ -536,154 +415,93 @@ rebuild_items (DbusmenuMenuitem *root,
g_debug("Unable to get lock screen shortcut.");
}
- g_signal_connect(G_OBJECT(lock_menuitem), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(lock_screen), NULL);
+ g_signal_connect (G_OBJECT(lock_menuitem),
+ DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+ G_CALLBACK(lock_screen), NULL);
dbusmenu_menuitem_child_append(root, 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)
- {
- 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 ())
- {
- guest_mi = dbusmenu_menuitem_new ();
- dbusmenu_menuitem_property_set (guest_mi, DBUSMENU_MENUITEM_PROP_TYPE, USER_ITEM_TYPE);
- dbusmenu_menuitem_property_set (guest_mi, USER_ITEM_PROP_NAME, _("Guest Session"));
- dbusmenu_menuitem_property_set_bool (guest_mi, USER_ITEM_PROP_LOGGED_IN, FALSE);
- dbusmenu_menuitem_child_append (root, guest_mi);
- g_signal_connect (G_OBJECT (guest_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK (activate_guest_session), service);
- users_service_dbus_set_guest_item(service, guest_mi);
- }
-
- if (check_new_session ())
- {
-
- switch_menuitem = dbusmenu_menuitem_new ();
- dbusmenu_menuitem_property_set (switch_menuitem, DBUSMENU_MENUITEM_PROP_TYPE, MENU_SWITCH_TYPE);
- dbusmenu_menuitem_property_set (switch_menuitem, MENU_SWITCH_USER, g_get_user_name());
- dbusmenu_menuitem_child_append (root, switch_menuitem);
- g_signal_connect (G_OBJECT (switch_menuitem), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK (activate_new_session), service);
- }
-
- GList * users = NULL;
- users = users_service_dbus_get_user_list (service);
- guint user_count = g_list_length(users);
-
- if (user_count > MINIMUM_USERS && user_count < MAXIMUM_USERS) {
- users = g_list_sort (users, (GCompareFunc)compare_users_by_username);
- }
-
- for (u = users; u != NULL; u = g_list_next (u)) {
- user = u->data;
- user->service = service;
-
- if (user->uid == getuid()) {
- /* Hide me from the list */
- continue;
- }
- g_debug ("%li %s", user->uid, user->user_name);
-
- if (g_strcmp0(user->user_name, "guest") == 0) {
- /* Check to see if the guest has sessions and so therefore should
- get a check mark. */
- if (user->sessions != NULL) {
- dbusmenu_menuitem_property_set_bool (guest_mi, USER_ITEM_PROP_LOGGED_IN, TRUE);
- }
- /* If we're showing user accounts, keep going through the list */
- if (user_count > MINIMUM_USERS && user_count < MAXIMUM_USERS) {
- continue;
- }
- /* If not, we can stop here */
- break;
- }
-
- if (user_count > MINIMUM_USERS && user_count < MAXIMUM_USERS) {
- mi = dbusmenu_menuitem_new ();
- dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_TYPE, USER_ITEM_TYPE);
- if (user->real_name_conflict) {
- gchar * conflictedname = g_strdup_printf("%s (%s)", user->real_name, user->user_name);
- dbusmenu_menuitem_property_set (mi, USER_ITEM_PROP_NAME, conflictedname);
- g_free(conflictedname);
- } else {
- dbusmenu_menuitem_property_set (mi, USER_ITEM_PROP_NAME, user->real_name);
- }
- dbusmenu_menuitem_property_set_bool (mi, USER_ITEM_PROP_LOGGED_IN, user->sessions != NULL);
- if (user->icon_file != NULL && user->icon_file[0] != '\0') {
- dbusmenu_menuitem_property_set(mi, USER_ITEM_PROP_ICON, user->icon_file);
- } else {
- dbusmenu_menuitem_property_set(mi, USER_ITEM_PROP_ICON, USER_ITEM_ICON_DEFAULT);
- }
- 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);
- }
-
- /* 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()) {
- dbusmenu_menuitem_property_set(logout_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Log Out"));
+ dbusmenu_menuitem_property_set (logout_mi,
+ DBUSMENU_MENUITEM_PROP_LABEL,
+ _("Log Out"));
} else {
- dbusmenu_menuitem_property_set(logout_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Log Out\342\200\246"));
+ dbusmenu_menuitem_property_set (logout_mi,
+ DBUSMENU_MENUITEM_PROP_LABEL,
+ _("Log Out\342\200\246"));
}
- dbusmenu_menuitem_property_set_bool(logout_mi, DBUSMENU_MENUITEM_PROP_VISIBLE, show_logout());
+ dbusmenu_menuitem_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");
+ g_signal_connect( G_OBJECT(logout_mi),
+ DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+ G_CALLBACK(show_dialog), "logout");
if (can_suspend && allow_suspend) {
suspend_mi = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set(suspend_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Suspend"));
- dbusmenu_menuitem_child_append(root, suspend_mi);
- g_signal_connect(G_OBJECT(suspend_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(machine_sleep), "Suspend");
+ dbusmenu_menuitem_property_set (suspend_mi,
+ DBUSMENU_MENUITEM_PROP_LABEL,
+ _("Suspend"));
+ dbusmenu_menuitem_child_append (root, suspend_mi);
+ g_signal_connect( G_OBJECT(suspend_mi),
+ DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+ G_CALLBACK(machine_sleep),
+ "Suspend");
}
if (can_hibernate && allow_hibernate) {
hibernate_mi = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set(hibernate_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Hibernate"));
+ dbusmenu_menuitem_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");
+ 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);
+ dbusmenu_menuitem_property_set (restart_mi,
+ DBUSMENU_MENUITEM_PROP_TYPE,
+ RESTART_ITEM_TYPE);
if (supress_confirmations()) {
- dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("Restart"));
+ dbusmenu_menuitem_property_set (restart_mi,
+ RESTART_ITEM_LABEL,
+ _("Restart"));
} else {
- dbusmenu_menuitem_property_set(restart_mi, RESTART_ITEM_LABEL, _("Restart\342\200\246"));
+ dbusmenu_menuitem_property_set (restart_mi,
+ RESTART_ITEM_LABEL,
+ _("Restart\342\200\246"));
}
- dbusmenu_menuitem_property_set_bool(restart_mi, DBUSMENU_MENUITEM_PROP_VISIBLE, show_restart());
+ dbusmenu_menuitem_property_set_bool (restart_mi,
+ DBUSMENU_MENUITEM_PROP_VISIBLE,
+ show_restart());
dbusmenu_menuitem_child_append(root, restart_mi);
- g_signal_connect(G_OBJECT(restart_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(show_dialog), "restart");
+ g_signal_connect (G_OBJECT(restart_mi),
+ DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+ G_CALLBACK(show_dialog), "restart");
shutdown_mi = dbusmenu_menuitem_new();
if (supress_confirmations()) {
- dbusmenu_menuitem_property_set(shutdown_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Shut Down"));
+ dbusmenu_menuitem_property_set (shutdown_mi,
+ DBUSMENU_MENUITEM_PROP_LABEL,
+ _("Shut Down"));
} else {
- dbusmenu_menuitem_property_set(shutdown_mi, DBUSMENU_MENUITEM_PROP_LABEL, _("Shut Down\342\200\246"));
- }
- dbusmenu_menuitem_property_set_bool(shutdown_mi, DBUSMENU_MENUITEM_PROP_VISIBLE, show_shutdown());
- dbusmenu_menuitem_child_append(root, shutdown_mi);
- g_signal_connect(G_OBJECT(shutdown_mi), DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(show_dialog), "shutdown");
+ dbusmenu_menuitem_property_set (shutdown_mi,
+ DBUSMENU_MENUITEM_PROP_LABEL,
+ _("Shut Down\342\200\246"));
+ }
+ dbusmenu_menuitem_property_set_bool (shutdown_mi,
+ DBUSMENU_MENUITEM_PROP_VISIBLE,
+ show_shutdown());
+ dbusmenu_menuitem_child_append (root, shutdown_mi);
+ g_signal_connect (G_OBJECT(shutdown_mi),
+ DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+ G_CALLBACK(show_dialog), "shutdown");
RestartShutdownLogoutMenuItems * restart_shutdown_logout_mi = g_new0 (RestartShutdownLogoutMenuItems, 1);
restart_shutdown_logout_mi->logout_mi = logout_mi;
@@ -692,75 +510,9 @@ rebuild_items (DbusmenuMenuitem *root,
update_menu_entries(restart_shutdown_logout_mi);
- /* now add extra launchers */
- GDir *extra_launchers_dir;
- extra_launchers_dir = g_dir_open (EXTRA_LAUNCHER_DIR, 0, NULL);
- if (extra_launchers_dir != NULL) {
- GList * launchers = NULL;
-
- /* Find all the desktop files we want to use */
- for (;;) {
- const gchar *extra_launcher_file;
-
- extra_launcher_file = g_dir_read_name (extra_launchers_dir);
- if (extra_launcher_file == NULL)
- break;
- if (!g_str_has_suffix (extra_launcher_file, ".desktop"))
- continue;
-
- gchar *full_path = g_build_filename (EXTRA_LAUNCHER_DIR, extra_launcher_file, NULL);
- GAppInfo * appinfo = G_APP_INFO(g_desktop_app_info_new_from_filename (full_path));
- g_free (full_path);
-
- launchers = g_list_prepend(launchers, appinfo);
- }
- g_dir_close(extra_launchers_dir);
-
- /* Sort the desktop files based on their names */
- launchers = g_list_sort(launchers, sort_app_infos);
-
- /* Turn each one into a separate menu item */
- GList * launcher = NULL;
- gboolean sepadded = FALSE;
- for (launcher = launchers; launcher != NULL; launcher = g_list_next(launcher)) {
- GAppInfo * appinfo = G_APP_INFO(launcher->data);
-
- /* Make sure we have a separator */
- if (!sepadded) {
- DbusmenuMenuitem * separator = dbusmenu_menuitem_new();
- dbusmenu_menuitem_property_set(separator, DBUSMENU_MENUITEM_PROP_TYPE, DBUSMENU_CLIENT_TYPES_SEPARATOR);
- dbusmenu_menuitem_child_append(root, separator);
- g_object_unref(separator);
- sepadded = TRUE;
- }
-
- /* Build the item */
- 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);
- g_object_weak_ref(G_OBJECT(desktop_mi), (GWeakNotify)g_object_unref, appinfo);
-
- /* Put into the menu */
- dbusmenu_menuitem_child_append(root, desktop_mi);
- }
-
- g_list_free(launchers);
- }
-
return;
}
-/* Signal called when a user is added. It updates the count and
- rebuilds the menu */
-static void
-user_change (UsersServiceDbus *service,
- const gchar *user_id,
- gpointer user_data)
-{
- DbusmenuMenuitem *root = (DbusmenuMenuitem *)user_data;
- rebuild_items (root, service);
- return;
-}
/* When the service interface starts to shutdown, we
should follow it. */
@@ -802,7 +554,6 @@ restart_dir_changed (void)
session_dbus_set_name(session_dbus, ICON_DEFAULT);
}
}
-
return;
}
@@ -826,7 +577,7 @@ setup_restart_watch (void)
int
main (int argc, char ** argv)
{
- g_type_init();
+ g_type_init();
/* Setting up i18n and gettext. Apparently, we need
all of these. */
@@ -834,42 +585,35 @@ main (int argc, char ** argv)
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
textdomain (GETTEXT_PACKAGE);
- IndicatorService * service = indicator_service_new_version(INDICATOR_SESSION_DBUS_NAME,
- INDICATOR_SESSION_DBUS_VERSION);
+ IndicatorService * service = indicator_service_new_version (INDICATOR_SESSION_DBUS_NAME,
+ INDICATOR_SESSION_DBUS_VERSION);
g_signal_connect(G_OBJECT(service),
- INDICATOR_SERVICE_SIGNAL_SHUTDOWN,
- G_CALLBACK(service_shutdown), NULL);
+ 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();
- g_debug("Root ID: %d", dbusmenu_menuitem_get_id(root_menuitem));
-
- dbus_interface = g_object_new (USERS_SERVICE_DBUS_TYPE, NULL);
-
- rebuild_items (root_menuitem, dbus_interface);
-
- g_signal_connect (G_OBJECT (dbus_interface),
- "user-added",
- G_CALLBACK (user_change),
- root_menuitem);
- g_signal_connect (G_OBJECT (dbus_interface),
- "user-deleted",
- G_CALLBACK (user_change),
- root_menuitem);
-
- setup_restart_watch();
+ session_root_menuitem = dbusmenu_menuitem_new();
+ rebuild_session_items (session_root_menuitem);
+ DbusmenuServer * server = dbusmenu_server_new(INDICATOR_SESSION_DBUS_OBJECT);
+ dbusmenu_server_set_root(server, session_root_menuitem);
+
+ // Users
+ UserMenuMgr* user_mgr = user_menu_mgr_new (session_dbus);
+
+ setup_restart_watch();
setup_up();
- DbusmenuServer * server = dbusmenu_server_new(INDICATOR_SESSION_DBUS_OBJECT);
- dbusmenu_server_set_root(server, root_menuitem);
-
- mainloop = g_main_loop_new(NULL, FALSE);
- g_main_loop_run(mainloop);
+ DbusmenuServer* users_server = dbusmenu_server_new (INDICATOR_USERS_DBUS_OBJECT);
+
+ dbusmenu_server_set_root (users_server, user_mgr_get_root_item (user_mgr));
- return 0;
+ mainloop = g_main_loop_new(NULL, FALSE);
+ g_main_loop_run(mainloop);
+
+ return 0;
}
diff --git a/src/user-menu-mgr.c b/src/user-menu-mgr.c
new file mode 100644
index 0000000..8338739
--- /dev/null
+++ b/src/user-menu-mgr.c
@@ -0,0 +1,358 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * user-menu-mgr.c
+ * Copyright (C) Conor Curran 2011 <conor.curran@canonical.com>
+ *
+ * user-menu-mgr.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * user-menu-mgr.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ */
+
+#include <libdbusmenu-glib/client.h>
+
+#include "user-menu-mgr.h"
+#include "gconf-helper.h"
+#include "dbus-shared-names.h"
+#include "dbusmenu-shared.h"
+#include "lock-helper.h"
+#include "users-service-dbus.h"
+
+static GConfClient * gconf_client = NULL;
+static DbusmenuMenuitem *switch_menuitem = NULL;
+
+struct _UserMenuMgr
+{
+ GObject parent_instance;
+ UsersServiceDbus* users_dbus_interface;
+ DbusmenuMenuitem* root_item;
+ gint user_count;
+ SessionDbus* session_dbus_interface;
+};
+
+static void activate_new_session (DbusmenuMenuitem * mi,
+ guint timestamp,
+ gpointer user_data);
+static void activate_user_session (DbusmenuMenuitem *mi,
+ guint timestamp,
+ gpointer user_data);
+static gint compare_users_by_username (const gchar *a,
+ const gchar *b);
+static void activate_online_accounts (DbusmenuMenuitem *mi,
+ guint timestamp,
+ gpointer user_data);
+static void user_menu_mgr_rebuild_items (UserMenuMgr *self);
+static gboolean check_new_session ();
+static void user_change (UsersServiceDbus *service,
+ const gchar *user_id,
+ gpointer user_data);
+
+static void ensure_gconf_client ();
+
+G_DEFINE_TYPE (UserMenuMgr, user_menu_mgr, G_TYPE_OBJECT);
+
+
+static void
+user_menu_mgr_init (UserMenuMgr *self)
+{
+ self->users_dbus_interface = g_object_new (USERS_SERVICE_DBUS_TYPE, NULL);
+ self->root_item = dbusmenu_menuitem_new ();
+ g_signal_connect (G_OBJECT (self->users_dbus_interface),
+ "user-added",
+ G_CALLBACK (user_change),
+ self);
+ g_signal_connect (G_OBJECT (self->users_dbus_interface),
+ "user-removed",
+ G_CALLBACK (user_change),
+ self);
+}
+
+static void
+user_menu_mgr_finalize (GObject *object)
+{
+ /* TODO: Add deinitalization code here */
+ G_OBJECT_CLASS (user_menu_mgr_parent_class)->finalize (object);
+}
+
+static void
+user_menu_mgr_class_init (UserMenuMgrClass *klass)
+{
+ GObjectClass* object_class = G_OBJECT_CLASS (klass);
+ //GObjectClass* parent_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = user_menu_mgr_finalize;
+}
+
+/* Builds up the menu for us */
+static void
+user_menu_mgr_rebuild_items (UserMenuMgr *self)
+{
+ DbusmenuMenuitem *mi = NULL;
+ DbusmenuMenuitem *guest_mi = NULL;
+ GList *u;
+ UserData *user;
+ gboolean can_activate;
+ GList *children;
+
+ /* Make sure we have a valid GConf client, and build one
+ if needed */
+ ensure_gconf_client ();
+
+ /* Check to see which menu items we're allowed to have */
+ can_activate = users_service_dbus_can_activate_session (self->users_dbus_interface) &&
+ !gconf_client_get_bool (gconf_client, LOCKDOWN_KEY_USER, NULL);
+
+ /* Remove the old menu items if that makes sense */
+ children = dbusmenu_menuitem_take_children (self->root_item);
+ g_list_foreach (children, (GFunc)g_object_unref, NULL);
+ g_list_free (children);
+
+ /* Set to NULL just incase we don't end up building one */
+ users_service_dbus_set_guest_item(self->users_dbus_interface, NULL);
+
+ /* Build all of the user switching items */
+ if (can_activate == TRUE)
+ {
+ if (check_new_session ()){
+ switch_menuitem = dbusmenu_menuitem_new ();
+ dbusmenu_menuitem_property_set (switch_menuitem,
+ DBUSMENU_MENUITEM_PROP_TYPE,
+ MENU_SWITCH_TYPE);
+ dbusmenu_menuitem_property_set (switch_menuitem,
+ MENU_SWITCH_USER,
+ g_get_user_name());
+ dbusmenu_menuitem_child_append (self->root_item, switch_menuitem);
+ g_signal_connect (G_OBJECT (switch_menuitem),
+ DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+ G_CALLBACK (activate_new_session),
+ self->users_dbus_interface);
+ }
+
+ GList * users = NULL;
+ users = users_service_dbus_get_user_list (self->users_dbus_interface);
+ self->user_count = g_list_length(users);
+
+ g_debug ("USER COUNT = %i", self->user_count);
+ session_dbus_set_user_menu_visibility (self->session_dbus_interface, self->user_count > 1);
+
+ if (self->user_count > MINIMUM_USERS && self->user_count < MAXIMUM_USERS) {
+ users = g_list_sort (users, (GCompareFunc)compare_users_by_username);
+ }
+
+ for (u = users; u != NULL; u = g_list_next (u)) {
+ user = u->data;
+ user->service = self->users_dbus_interface;
+
+ g_debug ("%i %s", (gint)user->uid, user->user_name);
+
+ if (g_strcmp0(user->user_name, "guest") == 0) {
+ /* Check to see if the guest has sessions and so therefore should
+ get a check mark. */
+ if (user->sessions != NULL) {
+ dbusmenu_menuitem_property_set_bool (guest_mi,
+ USER_ITEM_PROP_LOGGED_IN,
+ TRUE);
+ }
+ /* If we're showing user accounts, keep going through the list */
+ if (self->user_count > MINIMUM_USERS && self->user_count < MAXIMUM_USERS) {
+ continue;
+ }
+ /* If not, we can stop here */
+ break;
+ }
+
+ if (self->user_count > MINIMUM_USERS && self->user_count < MAXIMUM_USERS) {
+ mi = dbusmenu_menuitem_new ();
+ dbusmenu_menuitem_property_set (mi, DBUSMENU_MENUITEM_PROP_TYPE, USER_ITEM_TYPE);
+ if (user->real_name_conflict) {
+ gchar * conflictedname = g_strdup_printf("%s (%s)", user->real_name, user->user_name);
+ dbusmenu_menuitem_property_set (mi, USER_ITEM_PROP_NAME, conflictedname);
+ g_free(conflictedname);
+ } else {
+ dbusmenu_menuitem_property_set (mi, USER_ITEM_PROP_NAME, user->real_name);
+ }
+ dbusmenu_menuitem_property_set_bool (mi,
+ USER_ITEM_PROP_LOGGED_IN,
+ user->sessions != NULL);
+ if (user->icon_file != NULL && user->icon_file[0] != '\0') {
+ dbusmenu_menuitem_property_set(mi, USER_ITEM_PROP_ICON, user->icon_file);
+ } else {
+ dbusmenu_menuitem_property_set(mi, USER_ITEM_PROP_ICON, USER_ITEM_ICON_DEFAULT);
+ }
+
+ gboolean logged_in = g_strcmp0 (user->user_name, g_get_user_name()) == 0;
+ dbusmenu_menuitem_property_set_bool (mi,
+ USER_ITEM_PROP_IS_CURRENT_USER,
+ logged_in);
+ if (logged_in == TRUE){
+ g_debug ("about to set the users real name to %s for user %s",
+ user->real_name, user->user_name);
+ session_dbus_set_users_real_name (self->session_dbus_interface, user->real_name);
+ }
+
+ dbusmenu_menuitem_child_append (self->root_item, mi);
+ g_signal_connect (G_OBJECT (mi),
+ DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+ G_CALLBACK (activate_user_session),
+ user);
+ user->menuitem = mi;
+ }
+ }
+ g_list_free(users);
+ }
+ // Add the online accounts and separator
+ DbusmenuMenuitem * separator1 = dbusmenu_menuitem_new();
+ dbusmenu_menuitem_property_set (separator1,
+ DBUSMENU_MENUITEM_PROP_TYPE,
+ DBUSMENU_CLIENT_TYPES_SEPARATOR);
+ dbusmenu_menuitem_child_append (self->root_item, separator1);
+ DbusmenuMenuitem * online_accounts_item = dbusmenu_menuitem_new();
+ dbusmenu_menuitem_property_set (online_accounts_item,
+ DBUSMENU_MENUITEM_PROP_TYPE,
+ DBUSMENU_CLIENT_TYPES_DEFAULT);
+ dbusmenu_menuitem_property_set (online_accounts_item,
+ DBUSMENU_MENUITEM_PROP_LABEL,
+ _("Online Accounts..."));
+
+ g_signal_connect (G_OBJECT (online_accounts_item),
+ DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+ G_CALLBACK (activate_online_accounts),
+ NULL);
+
+ dbusmenu_menuitem_child_append (self->root_item, online_accounts_item);
+}
+
+/* Checks to see if we can create sessions */
+// TODO what is this ?
+static gboolean
+check_new_session ()
+{
+ return TRUE;
+}
+
+/* Check to see if the lockdown key is protecting from
+ locking the screen. If not, lock it. */
+static void
+lock_if_possible (void) {
+ ensure_gconf_client ();
+
+ if (!gconf_client_get_bool (gconf_client, LOCKDOWN_KEY_SCREENSAVER, NULL)) {
+ lock_screen(NULL, 0, NULL);
+ }
+
+ return;
+}
+
+
+/* Starts a new generic session */
+static void
+activate_new_session (DbusmenuMenuitem * mi, guint timestamp, gpointer user_data)
+{
+ lock_if_possible();
+
+ users_service_dbus_show_greeter (USERS_SERVICE_DBUS(user_data));
+
+ return;
+}
+
+/* Activates a session for a particular user. */
+static void
+activate_user_session (DbusmenuMenuitem *mi, guint timestamp, gpointer user_data)
+{
+ UserData *user = (UserData *)user_data;
+ UsersServiceDbus *service = user->service;
+
+ lock_if_possible();
+
+ users_service_dbus_activate_user_session (service, user);
+}
+
+/* Comparison function to look into the UserData struct
+ to compare by using the username value */
+static gint
+compare_users_by_username (const gchar *a,
+ const gchar *b)
+{
+ UserData *user1 = (UserData *)a;
+ UserData *user2 = (UserData *)b;
+
+ gint retval = g_strcmp0 (user1->real_name, user2->real_name);
+
+ /* If they're the same, they're both in conflict. */
+ if (retval == 0) {
+ user1->real_name_conflict = TRUE;
+ user2->real_name_conflict = TRUE;
+ }
+
+ return retval;
+}
+
+// TODO
+// Wait until dialog is complete to find out name to pass
+// to the control centre.
+static void
+activate_online_accounts (DbusmenuMenuitem *mi,
+ guint timestamp,
+ gpointer user_data)
+{
+ GError * error = NULL;
+ if (!g_spawn_command_line_async("gnome-control-center online-accounts", &error))
+ {
+ g_warning("Unable to show control centre: %s", error->message);
+ g_error_free(error);
+ }
+}
+
+/* Signal called when a user is added. It updates the count and
+ rebuilds the menu */
+static void
+user_change (UsersServiceDbus *service,
+ const gchar *user_id,
+ gpointer user_data)
+{
+ //DbusmenuMenuitem *root = (DbusmenuMenuitem *)user_data;
+ // TODO sort this out.
+ //rebuild_user_items (root, service);
+ return;
+}
+
+/* Ensures that we have a GConf client and if we build one
+ set up the signal handler. */
+static void
+ensure_gconf_client ()
+{
+ if (!gconf_client) {
+ gconf_client = gconf_client_get_default ();
+ gconf_client_add_dir (gconf_client, LOCKDOWN_DIR, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+ gconf_client_add_dir (gconf_client, KEYBINDING_DIR, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
+ }
+}
+
+DbusmenuMenuitem*
+user_mgr_get_root_item (UserMenuMgr* self)
+{
+ return self->root_item;
+}
+
+
+/*
+ * Clean Entry Point
+ */
+UserMenuMgr* user_menu_mgr_new (SessionDbus* session_dbus)
+{
+ UserMenuMgr* user_mgr = g_object_new (USER_TYPE_MENU_MGR, NULL);
+ user_mgr->session_dbus_interface = session_dbus;
+ user_menu_mgr_rebuild_items (user_mgr);
+ return user_mgr;
+}
+
+
diff --git a/src/user-menu-mgr.h b/src/user-menu-mgr.h
new file mode 100644
index 0000000..16ac055
--- /dev/null
+++ b/src/user-menu-mgr.h
@@ -0,0 +1,53 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
+/*
+ * user-menu-mgr.c
+ * Copyright (C) Conor Curran 2011 <conor.curran@canonical.com>
+ *
+ * user-menu-mgr.c is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * user-menu-mgr.c is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+
+ */
+
+#ifndef _USER_MENU_MGR_H_
+#define _USER_MENU_MGR_H_
+
+
+#include <glib-object.h>
+#include <libdbusmenu-gtk3/menuitem.h>
+
+#include "session-dbus.h"
+
+G_BEGIN_DECLS
+
+#define USER_TYPE_MENU_MGR (user_menu_mgr_get_type ())
+#define USER_MENU_MGR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), USER_TYPE_MENU_MGR, UserMenuMgr))
+#define USER_MENU_MGR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), USER_TYPE_MENU_MGR, UserMenuMgrClass))
+#define USER_IS_MENU_MGR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), USER_TYPE_MENU_MGR))
+#define USER_IS_MENU_MGR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), USER_TYPE_MENU_MGR))
+#define USER_MENU_MGR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), USER_TYPE_MENU_MGR, UserMenuMgrClass))
+
+typedef struct _UserMenuMgrClass UserMenuMgrClass;
+typedef struct _UserMenuMgr UserMenuMgr;
+
+struct _UserMenuMgrClass
+{
+ GObjectClass parent_class;
+};
+
+GType user_menu_mgr_get_type (void) G_GNUC_CONST;
+UserMenuMgr* user_menu_mgr_new (SessionDbus* session_dbus);
+
+DbusmenuMenuitem* user_mgr_get_root_item (UserMenuMgr* self);
+G_END_DECLS
+
+#endif /* _USER_MENU_MGR_H_ */
diff --git a/src/user-widget.c b/src/user-widget.c
new file mode 100644
index 0000000..9b046c5
--- /dev/null
+++ b/src/user-widget.c
@@ -0,0 +1,341 @@
+/*
+Copyright 2011 Canonical Ltd.
+
+Authors:
+ Conor Curran <conor.curran@canonical.com>
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 3, as published
+by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranties of
+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <glib.h>
+#include <libindicator/indicator-image-helper.h>
+#include "user-widget.h"
+#include "dbus-shared-names.h"
+
+
+typedef struct _UserWidgetPrivate UserWidgetPrivate;
+
+struct _UserWidgetPrivate
+{
+ DbusmenuMenuitem* twin_item;
+ GtkWidget* user_image;
+ GtkWidget* user_name;
+ GtkWidget* container;
+ GtkWidget* tick_icon;
+ gboolean logged_in;
+ gboolean sessions_active;
+};
+
+#define USER_WIDGET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), USER_WIDGET_TYPE, UserWidgetPrivate))
+
+/* Prototypes */
+static void user_widget_class_init (UserWidgetClass *klass);
+static void user_widget_init (UserWidget *self);
+static void user_widget_dispose (GObject *object);
+static void user_widget_finalize (GObject *object);
+
+static void user_widget_set_twin_item (UserWidget* self,
+ DbusmenuMenuitem* twin_item);
+// keyevent consumers
+static gboolean user_widget_button_release_event (GtkWidget *menuitem,
+ GdkEventButton *event);
+// Dbusmenuitem properties update callback
+static void user_widget_property_update (DbusmenuMenuitem* item,
+ gchar* property,
+ GVariant* value,
+ gpointer userdata);
+#if GTK_CHECK_VERSION(3, 0, 0)
+static gboolean user_widget_primitive_draw_cb_gtk_3 (GtkWidget *image,
+ cairo_t* cr,
+ gpointer user_data);
+#else
+static gboolean user_widget_primitive_draw_cb (GtkWidget *image,
+ GdkEventExpose *event,
+ gpointer user_data);
+#endif
+
+G_DEFINE_TYPE (UserWidget, user_widget, GTK_TYPE_MENU_ITEM);
+
+static void
+user_widget_class_init (UserWidgetClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ widget_class->button_release_event = user_widget_button_release_event;
+
+ g_type_class_add_private (klass, sizeof (UserWidgetPrivate));
+
+ gobject_class->dispose = user_widget_dispose;
+ gobject_class->finalize = user_widget_finalize;
+}
+
+static void
+user_widget_init (UserWidget *self)
+{
+ UserWidgetPrivate * priv = USER_WIDGET_GET_PRIVATE(self);
+
+ gint padding = 0;
+ gtk_widget_style_get (GTK_WIDGET(self),
+ "horizontal-padding",
+ &padding,
+ NULL);
+
+ priv->user_image = NULL;
+ priv->user_name = NULL;
+ priv->logged_in = FALSE;
+ priv->sessions_active = FALSE;
+ priv->container = NULL;
+ priv->tick_icon = NULL;
+
+ // Create the UI elements.
+ priv->user_image = gtk_image_new ();
+
+ // Just for now set the image to the default avator image
+ GdkPixbuf* pixbuf = NULL;
+ GError* error = NULL;
+ pixbuf = gtk_icon_theme_load_icon (gtk_icon_theme_get_default (),
+ "avatar-default",
+ 32,
+ GTK_ICON_LOOKUP_FORCE_SIZE,
+ &error);
+
+ if (pixbuf == NULL || error != NULL) {
+ g_warning ("Could not load the default avatar image for some reason");
+ }
+ else{
+ gtk_image_set_from_pixbuf (GTK_IMAGE(priv->user_image), pixbuf);
+ g_object_unref (pixbuf);
+ }
+
+ priv->user_name = gtk_label_new ("");
+ priv->container = gtk_hbox_new (FALSE, 0);
+ // TODO:
+ // Delete tick icon and draw primitively.
+ priv->tick_icon = gtk_image_new_from_icon_name ("account-logged-in",
+ GTK_ICON_SIZE_MENU);
+ gtk_misc_set_alignment(GTK_MISC(priv->tick_icon), 1.0, 0.5);
+
+ // Pack it together
+ gtk_box_pack_start (GTK_BOX (priv->container),
+ priv->user_image,
+ FALSE,
+ FALSE,
+ 0);
+ gtk_box_pack_start (GTK_BOX (priv->container),
+ priv->user_name,
+ FALSE,
+ FALSE,
+ 3);
+ gtk_box_pack_start (GTK_BOX(priv->container),
+ priv->tick_icon,
+ FALSE,
+ FALSE, 5);
+
+ gtk_widget_show_all (priv->container);
+ gtk_container_add (GTK_CONTAINER (self), priv->container);
+
+ // Fetch the drawing context.
+ #if GTK_CHECK_VERSION(3, 0, 0)
+ g_signal_connect_after (GTK_WIDGET(self), "draw",
+ G_CALLBACK(user_widget_primitive_draw_cb_gtk_3),
+ GTK_WIDGET(self));
+ #else
+ g_signal_connect_after (GTK_WIDGET(self), "expose-event",
+ G_CALLBACK(user_widget_primitive_draw_cb),
+ GTK_WIDGET(self));
+ #endif
+}
+
+static void
+user_widget_dispose (GObject *object)
+{
+ //UserWidgetPrivate * priv = USER_WIDGET_GET_PRIVATE(USER_WIDGET(object));
+
+ G_OBJECT_CLASS (user_widget_parent_class)->dispose (object);
+}
+
+// TODO tidy up image and name
+static void
+user_widget_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (user_widget_parent_class)->finalize (object);
+}
+
+/**
+ * We override the expose method to enable primitive drawing of the
+ * empty album art image and rounded rectangles on the album art.
+ */
+
+#if GTK_CHECK_VERSION(3, 0, 0)
+
+// Draw the radio dot and/or green check mark
+// TODO handle drawing of green check mark
+static gboolean
+user_widget_primitive_draw_cb_gtk_3 (GtkWidget *widget,
+ cairo_t* cr,
+ gpointer user_data)
+{
+
+ g_return_val_if_fail(IS_USER_WIDGET(user_data), FALSE);
+ UserWidget* meta = USER_WIDGET(user_data);
+ UserWidgetPrivate * priv = USER_WIDGET_GET_PRIVATE(meta);
+
+ // Draw dot only when user is the current user.
+ if (!dbusmenu_menuitem_property_get_bool (priv->twin_item,
+ USER_ITEM_PROP_IS_CURRENT_USER)){
+ return FALSE;
+ }
+
+ GtkStyle *style;
+ gdouble x, y;
+ gdouble offset = 15.0;
+
+ style = gtk_widget_get_style (widget);
+
+ GtkAllocation allocation;
+ gtk_widget_get_allocation (widget, &allocation);
+ x = allocation.x + 13;
+ y = offset;
+
+ cairo_arc (cr, x, y, 3.0, 0.0, 2 * G_PI);;
+
+ cairo_set_source_rgb (cr, style->fg[gtk_widget_get_state(widget)].red/65535.0,
+ style->fg[gtk_widget_get_state(widget)].green/65535.0,
+ style->fg[gtk_widget_get_state(widget)].blue/65535.0);
+ cairo_fill (cr);
+
+ return FALSE;
+}
+
+// GTK 2 Expose handler
+#else
+
+// Draw the triangle if the player is running ...
+static gboolean
+user_widget_primitive_draw_cb (GtkWidget *widget,
+ GdkEventExpose *event,
+ gpointer user_data)
+{
+ /*
+ g_return_val_if_fail(IS_USER_WIDGET(user_data), FALSE);
+ UserWidget* meta = USER_WIDGET(user_data);
+ UserWidgetPrivate * priv = USER_WIDGET_GET_PRIVATE(meta);
+
+ GtkStyle *style;
+ cairo_t *cr;
+ int x, y, arrow_width, arrow_height;
+
+ gint offset = 3;
+ arrow_width = 5;
+ arrow_height = 9;
+
+ style = gtk_widget_get_style (widget);
+
+ cr = (cairo_t*) gdk_cairo_create (gtk_widget_get_window (widget));
+
+ GtkAllocation allocation;
+ gtk_widget_get_allocation (widget, &allocation);
+ x = allocation.x;
+ y = allocation.y;
+
+ // Draw player icon
+ if (priv->icon_buf != NULL){
+ gdk_cairo_set_source_pixbuf (cr,
+ priv->icon_buf,
+ x + arrow_width + 1,
+ y + offset);
+ cairo_paint (cr);
+ }
+
+ // Draw triangle but only if the player is running.
+ if (dbusmenu_menuitem_property_get_bool (priv->twin_item,
+ DBUSMENU_METADATA_MENUITEM_PLAYER_RUNNING)){
+ y += (double)arrow_height/2.0 + offset;
+ cairo_set_line_width (cr, 1.0);
+
+ cairo_move_to (cr, x, y);
+ cairo_line_to (cr, x, y + arrow_height);
+ cairo_line_to (cr, x + arrow_width, y + (double)arrow_height/2.0);
+ cairo_close_path (cr);
+ cairo_set_source_rgb (cr, style->fg[gtk_widget_get_state(widget)].red/65535.0,
+ style->fg[gtk_widget_get_state(widget)].green/65535.0,
+ style->fg[gtk_widget_get_state(widget)].blue/65535.0);
+ cairo_fill (cr);
+ }
+
+ cairo_destroy (cr);*/
+ return FALSE;
+}
+#endif
+
+
+/* Suppress/consume keyevents */
+static gboolean
+user_widget_button_release_event (GtkWidget *menuitem,
+ GdkEventButton *event)
+{
+ return FALSE;
+}
+
+static void
+user_widget_property_update (DbusmenuMenuitem* item, gchar* property,
+ GVariant* value, gpointer userdata)
+{
+ g_return_if_fail (IS_USER_WIDGET (userdata));
+ //gtk_widget_queue_redraw (GTK_WIDGET(userdata));
+}
+
+
+static void
+user_widget_set_twin_item (UserWidget* self,
+ DbusmenuMenuitem* twin_item)
+{
+ UserWidgetPrivate* priv = USER_WIDGET_GET_PRIVATE(self);
+ priv->twin_item = twin_item;
+ g_signal_connect( G_OBJECT(priv->twin_item), "property-changed",
+ G_CALLBACK(user_widget_property_update), self);
+
+ const gchar * icon_name = dbusmenu_menuitem_property_get (twin_item,
+ USER_ITEM_PROP_ICON);
+ gtk_label_set_label (GTK_LABEL (priv->user_name),
+ dbusmenu_menuitem_property_get (twin_item, USER_ITEM_PROP_NAME));
+
+ //if (dbusmenu_menuitem_property_get_bool (twin_item, USER_ITEM_PROP_LOGGED_IN)) {
+ // gtk_widget_show(priv->tick_icon);
+ //} else {
+ gtk_widget_show(priv->tick_icon);
+ //}
+
+ g_debug("Using user icon for '%s' from file: %s",
+ dbusmenu_menuitem_property_get(twin_item, USER_ITEM_PROP_NAME), icon_name);
+
+}
+
+ /**
+ * transport_new:
+ * @returns: a new #UserWidget.
+ **/
+GtkWidget*
+user_widget_new(DbusmenuMenuitem *item)
+{
+ GtkWidget* widget = g_object_new(USER_WIDGET_TYPE, NULL);
+ user_widget_set_twin_item ( USER_WIDGET(widget), item );
+ return widget;
+}
diff --git a/src/user-widget.h b/src/user-widget.h
new file mode 100644
index 0000000..e1f6d1a
--- /dev/null
+++ b/src/user-widget.h
@@ -0,0 +1,54 @@
+/*
+Copyright 2011 Canonical Ltd.
+
+Authors:
+ Conor Curran <conor.curran@canonical.com>
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License version 3, as published
+by the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranties of
+MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef __USER_WIDGET_H__
+#define __USER_WIDGET_H__
+
+#include <gtk/gtk.h>
+#if GTK_CHECK_VERSION(3, 0, 0)
+#include <libdbusmenu-gtk3/menuitem.h>
+#else
+#include <libdbusmenu-gtk/menuitem.h>
+#endif
+
+G_BEGIN_DECLS
+
+#define USER_WIDGET_TYPE (user_widget_get_type ())
+#define USER_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), USER_WIDGET_TYPE, UserWidget))
+#define USER_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), USER_WIDGET_TYPE, UserWidgetClass))
+#define IS_USER_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), USER_WIDGET_TYPE))
+#define IS_USER_WIDGET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), USER_WIDGET_TYPE))
+#define USER_WIDGET_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), USER_WIDGET_TYPE, UserWidgetClass))
+
+typedef struct _UserWidget UserWidget;
+typedef struct _UserWidgetClass UserWidgetClass;
+
+struct _UserWidgetClass {
+ GtkMenuItemClass parent_class;
+};
+
+struct _UserWidget {
+ GtkMenuItem parent;
+};
+
+GType user_widget_get_type (void);
+GtkWidget* user_widget_new(DbusmenuMenuitem *twin_item);
+
+G_END_DECLS
+
+#endif