diff options
Diffstat (limited to 'src/service.c')
-rw-r--r-- | src/service.c | 160 |
1 files changed, 112 insertions, 48 deletions
diff --git a/src/service.c b/src/service.c index 60ddae0..7484134 100644 --- a/src/service.c +++ b/src/service.c @@ -21,6 +21,7 @@ #include <gio/gio.h> #include "backend.h" +#include "recoverable-problem.h" #include "service.h" #define BUS_NAME "com.canonical.indicator.session" @@ -104,13 +105,11 @@ struct _IndicatorSessionServicePrivate GSimpleAction * user_switcher_action; GSimpleAction * guest_switcher_action; GHashTable * users; + GHashTable * reported_users; guint rebuild_id; int rebuild_flags; GDBusConnection * conn; GCancellable * cancellable; - - /* serialized icon cache */ - GVariant * alert_icon_serialized; GVariant * default_icon_serialized; }; @@ -155,12 +154,18 @@ rebuild_settings_section_soon (IndicatorSessionService * self) **** ***/ +static gboolean +show_user_list (IndicatorSessionService * self) +{ + return g_settings_get_boolean (self->priv->indicator_settings, + "user-show-menu"); +} + + static GVariant * action_state_for_header (IndicatorSessionService * self) { const priv_t * const p = self->priv; - gboolean need_attn; - GVariant * serialized_icon; gboolean show_name; const gchar * real_name; const gchar * label; @@ -168,38 +173,17 @@ action_state_for_header (IndicatorSessionService * self) GVariantBuilder b; GVariant * state; - if (indicator_session_actions_has_online_account_error (p->backend_actions)) - { - need_attn = TRUE; - serialized_icon = p->alert_icon_serialized; - } - else - { - need_attn = FALSE; - serialized_icon = p->default_icon_serialized; - } - show_name = g_settings_get_boolean (p->indicator_settings, "show-real-name-on-panel"); real_name = get_current_real_name (self); label = show_name && real_name ? real_name : ""; - if (*label && need_attn) - { - /* Translators: the name of the menu ("System"), then the user's name, - then a hint that something in this menu requires user attention */ - a11y = g_strdup_printf (_("System, %s (Attention Required)"), real_name); - } - else if (*label) + if (*label) { /* Translators: the name of the menu ("System"), then the user's name */ a11y = g_strdup_printf (_("System, %s"), label); } - else if (need_attn) - { - a11y = g_strdup (_("System (Attention Required)")); - } else { a11y = g_strdup (_("System")); @@ -208,8 +192,7 @@ action_state_for_header (IndicatorSessionService * self) /* build the state */ g_variant_builder_init (&b, G_VARIANT_TYPE("a{sv}")); g_variant_builder_add (&b, "{sv}", "accessible-desc", g_variant_new_string (a11y)); - if (serialized_icon != NULL) - g_variant_builder_add (&b, "{sv}", "icon", serialized_icon); + g_variant_builder_add (&b, "{sv}", "icon", p->default_icon_serialized); if (label && *label) g_variant_builder_add (&b, "{sv}", "label", g_variant_new_string (label)); g_variant_builder_add (&b, "{sv}", "visible", g_variant_new_boolean (TRUE)); @@ -267,6 +250,32 @@ on_user_changed (IndicatorSessionUsers * backend_users G_GNUC_UNUSED, } static void +maybe_add_users (IndicatorSessionService * self) +{ + if (show_user_list (self)) + { + GList * uids, * l; + + uids = indicator_session_users_get_uids (self->priv->backend_users); + for (l=uids; l!=NULL; l=l->next) + add_user (self, GPOINTER_TO_UINT(l->data)); + g_list_free (uids); + } +} + + +static void +user_show_menu_changed (IndicatorSessionService * self) +{ + if (show_user_list (self)) + maybe_add_users (self); + else + g_hash_table_remove_all (self->priv->users); + + rebuild_switch_section_soon (self); +} + +static void on_user_removed (IndicatorSessionUsers * backend_users G_GNUC_UNUSED, guint uid, gpointer gself) @@ -481,12 +490,55 @@ serialize_icon_file (const gchar * filename) return serialized_icon; } +static void +report_unusable_user (IndicatorSessionService * self, const IndicatorSessionUser * u) +{ + const priv_t * const p = self->priv; + gpointer key; + + g_return_if_fail(u != NULL); + + key = GUINT_TO_POINTER(u->uid); + + if (!g_hash_table_contains (p->reported_users, key)) + { + gchar * uid_str; + GPtrArray * additional; + const gchar * const error_name = "indicator-session-unknown-user-error"; + + /* don't spam apport with duplicates */ + g_hash_table_add (p->reported_users, key); + + uid_str = g_strdup_printf("%u", u->uid); + + additional = g_ptr_array_new (); /* null-terminated key/value pair strs */ + g_ptr_array_add (additional, "uid"); + g_ptr_array_add (additional, uid_str); + g_ptr_array_add (additional, "icon_file"); + g_ptr_array_add (additional, u->icon_file ? u->icon_file : "(null)"); + g_ptr_array_add (additional, "is_current_user"); + g_ptr_array_add (additional, u->is_current_user ? "true" : "false"); + g_ptr_array_add (additional, "is_logged_in"); + g_ptr_array_add (additional, u->is_logged_in ? "true" : "false"); + g_ptr_array_add (additional, "real_name"); + g_ptr_array_add (additional, u->real_name ? u->real_name : "(null)"); + g_ptr_array_add (additional, "user_name"); + g_ptr_array_add (additional, u->user_name ? u->user_name : "(null)"); + g_ptr_array_add (additional, NULL); /* null termination */ + report_recoverable_problem(error_name, (GPid)0, FALSE, (gchar**)additional->pdata); + + /* cleanup */ + g_free (uid_str); + g_ptr_array_free (additional, TRUE); + } +} + static GMenuModel * create_switch_section (IndicatorSessionService * self, int profile) { - gchar * str; GMenu * menu; GMenuItem * item; + gboolean want_accel; guint i; gpointer guser; GHashTableIter iter; @@ -501,6 +553,7 @@ create_switch_section (IndicatorSessionService * self, int profile) { const char * action = "indicator.switch-to-screensaver"; item = g_menu_item_new (_("Start Screen Saver"), action); + want_accel = TRUE; } else if (profile == PROFILE_LOCKSCREEN || indicator_session_guest_is_active (p->backend_guest)) @@ -508,6 +561,7 @@ create_switch_section (IndicatorSessionService * self, int profile) const char * action = "indicator.switch-to-greeter"; item = g_menu_item_new (ellipsis ? _("Switch Account…") : _("Switch Account"), action); + want_accel = FALSE; } else { @@ -518,11 +572,13 @@ create_switch_section (IndicatorSessionService * self, int profile) else item = g_menu_item_new (ellipsis ? _("Lock/Switch Account…") : _("Lock/Switch Account"), action); + + want_accel = TRUE; } - if (profile != PROFILE_LOCKSCREEN) + if (want_accel) { - str = g_settings_get_string (p->keybinding_settings, "screensaver"); + gchar * str = g_settings_get_string (p->keybinding_settings, "screensaver"); g_menu_item_set_attribute (item, "accel", "s", str); g_free (str); } @@ -541,7 +597,11 @@ create_switch_section (IndicatorSessionService * self, int profile) g_object_unref (item); } - /* build an array of all the users we know of */ + /* if we need to show the user list, build an array of all the users we know + * of, otherwise get out now */ + if (!show_user_list (self)) + return G_MENU_MODEL (menu); + users = g_ptr_array_new (); g_hash_table_iter_init (&iter, p->users); while (g_hash_table_iter_next (&iter, NULL, &guser)) @@ -561,12 +621,23 @@ create_switch_section (IndicatorSessionService * self, int profile) for (i=0; i<users->len; ++i) { const IndicatorSessionUser * u = g_ptr_array_index (users, i); + const char * label; GVariant * serialized_icon; if (profile == PROFILE_LOCKSCREEN && u->is_current_user) continue; - item = g_menu_item_new (get_user_label (u), NULL); + /* Sometimes we get a user without a username? bus hiccup. + I can't reproduce it, but let's not confuse users with + a meaningless menuitem. (see bug #1263228) */ + label = get_user_label (u); + if (!label || !*label) + { + report_unusable_user (self, u); + continue; + } + + item = g_menu_item_new (label, NULL); g_menu_item_set_action_and_target (item, "indicator.switch-to-user", "s", u->user_name); g_menu_item_set_attribute (item, "x-canonical-type", "s", "indicator.user-menu-item"); @@ -1053,8 +1124,6 @@ static void /* cppcheck-suppress unusedFunction */ indicator_session_service_init (IndicatorSessionService * self) { - GList * l; - GList * uids; priv_t * p; gpointer gp; GIcon * icon; @@ -1073,12 +1142,6 @@ indicator_session_service_init (IndicatorSessionService * self) &p->backend_users, &p->backend_guest); - /* build the serialized icon cache */ - - icon = g_themed_icon_new_with_default_fallbacks (ICON_ALERT); - p->alert_icon_serialized = g_icon_serialize (icon); - g_object_unref (icon); - icon = g_themed_icon_new_with_default_fallbacks (ICON_DEFAULT); p->default_icon_serialized = g_icon_serialize (icon); g_object_unref (icon); @@ -1088,10 +1151,10 @@ indicator_session_service_init (IndicatorSessionService * self) g_direct_equal, NULL, (GDestroyNotify)indicator_session_user_free); - uids = indicator_session_users_get_uids (p->backend_users); - for (l=uids; l!=NULL; l=l->next) - add_user (self, GPOINTER_TO_UINT(l->data)); - g_list_free (uids); + + p->reported_users = g_hash_table_new (g_direct_hash, g_direct_equal); + + maybe_add_users (self); init_gactions (self); @@ -1138,6 +1201,8 @@ indicator_session_service_init (IndicatorSessionService * self) G_CALLBACK(rebuild_session_section_soon), self); g_signal_connect_swapped (gp, "changed::show-real-name-on-panel", G_CALLBACK(rebuild_header_soon), self); + g_signal_connect_swapped (gp, "changed::user-show-menu", + G_CALLBACK(user_show_menu_changed), self); /* watch for changes to the lock keybinding */ gp = p->keybinding_settings; @@ -1229,6 +1294,7 @@ my_dispose (GObject * o) } g_clear_pointer (&p->users, g_hash_table_destroy); + g_clear_pointer (&p->reported_users, g_hash_table_destroy); g_clear_object (&p->backend_users); g_clear_object (&p->backend_guest); g_clear_object (&p->backend_actions); @@ -1244,8 +1310,6 @@ my_dispose (GObject * o) g_clear_object (&p->guest_switcher_action); g_clear_object (&p->conn); - /* clear the serialized icon cache */ - g_clear_pointer (&p->alert_icon_serialized, g_variant_unref); g_clear_pointer (&p->default_icon_serialized, g_variant_unref); G_OBJECT_CLASS (indicator_session_service_parent_class)->dispose (o); |