diff options
Diffstat (limited to 'src/indicator-session.c')
-rw-r--r-- | src/indicator-session.c | 729 |
1 files changed, 437 insertions, 292 deletions
diff --git a/src/indicator-session.c b/src/indicator-session.c index c9617c4..f6727d9 100644 --- a/src/indicator-session.c +++ b/src/indicator-session.c @@ -6,7 +6,8 @@ Copyright 2009 Canonical Ltd. Authors: Ted Gould <ted@canonical.com> - + Conor Curran <conor.curran@canonical.com> + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License version 3, as published by the Free Software Foundation. @@ -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,87 @@ 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)); + + // devices + self->devices.menu = GTK_MENU (dbusmenu_gtkmenu_new(INDICATOR_SESSION_DBUS_NAME, + INDICATOR_SESSION_DBUS_OBJECT)); + self->devices.image = indicator_image_helper ("system-devices-panel"); + + 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 +220,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 +241,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); + + GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish(res, &error); - if (g_strcmp0(signal_name, "IconUpdated") == 0) { - const gchar *name; - g_variant_get (parameters, "(&s)", &name); - icon_changed(self, name); + 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; + + if (self->show_users_entry == TRUE){ + g_signal_emit_by_name ((gpointer)self, + "entry-added", + &self->users); + } + else{ + g_signal_emit_by_name ((gpointer)self, + "entry-removed", + &self->users); + } +} - 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; + + if (self->show_users_entry == TRUE){ + g_signal_emit_by_name ((gpointer)self, + "entry-added", + &self->users); + + } + else{ + g_signal_emit_by_name ((gpointer)self, + "entry-removed", + &self->users); + } + } + else if (g_strcmp0(signal_name, "RebootRequired") == 0) { + // TODO waiting on design to give me a name. + self->devices.image = indicator_image_helper ("system-devices-alert-panel"); + } +} - /* 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 +601,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 +619,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 +633,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)); } |