From ae39f7001e5603010afc02de29787ade6d48ef14 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 22 Mar 2013 16:34:34 -0500 Subject: port indicator-session to GMenu/cmake. Code coverage increased from 0% to 95.4%. --- src/service.c | 1192 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1192 insertions(+) create mode 100644 src/service.c (limited to 'src/service.c') diff --git a/src/service.c b/src/service.c new file mode 100644 index 0000000..1345681 --- /dev/null +++ b/src/service.c @@ -0,0 +1,1192 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * Authors: + * Charles Kerr + * + * 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 . + */ + +#include + +#include +#include + +#include "backend.h" +#include "service.h" + +/* FIXME: remove -test */ +#define BUS_NAME "com.canonical.indicator.session-test" +#define BUS_PATH "/com/canonical/indicator/session" + +#define ICON_DEFAULT "system-devices-panel" +#define ICON_INFO "system-devices-panel-information" +#define ICON_ALERT "system-devices-panel-alert" + +G_DEFINE_TYPE (IndicatorSessionService, + indicator_session_service, + G_TYPE_OBJECT) + +enum +{ + PROP_0, + PROP_REPLACE, + PROP_MAX_USERS, + PROP_LAST +}; + +static GParamSpec * properties[PROP_LAST]; + +enum +{ + SECTION_HEADER = (1<<0), + SECTION_ADMIN = (1<<1), + SECTION_SETTINGS = (1<<2), + SECTION_SWITCH = (1<<3), + SECTION_SESSION = (1<<4) +}; + +enum +{ + FORM_DESKTOP, + FORM_GREETER, + N_FORMS +}; + +static const char * const menu_names[N_FORMS] = +{ + "desktop", + "desktop_greeter" +}; + +struct FormMenuInfo +{ + /* the root level -- the header is the only child of this */ + GMenu * menu; + + /* parent of the sections. This is the header's submenu */ + GMenu * submenu; + + guint export_id; +}; + +struct _IndicatorSessionServicePrivate +{ + guint own_id; + guint max_users; + IndicatorSessionUsers * backend_users; + IndicatorSessionGuest * backend_guest; + IndicatorSessionActions * backend_actions; + GSettings * indicator_settings; + GSettings * keybinding_settings; + GSimpleActionGroup * actions; + guint actions_export_id; + struct FormMenuInfo menus[N_FORMS]; + GSimpleAction * header_action; + GSimpleAction * user_switcher_action; + GSimpleAction * guest_switcher_action; + GHashTable * users; + guint rebuild_id; + int rebuild_flags; + GDBusConnection * conn; + + gboolean replace; +}; + +typedef IndicatorSessionServicePrivate priv_t; + +static const char * get_current_real_name (IndicatorSessionService * self); + +/*** +**** +***/ + +static void rebuild_now (IndicatorSessionService * self, int section); +static void rebuild_soon (IndicatorSessionService * self, int section); + +static inline void +rebuild_header_soon (IndicatorSessionService * self) +{ + rebuild_soon (self, SECTION_HEADER); +} +static inline void +rebuild_switch_section_soon (IndicatorSessionService * self) +{ + rebuild_soon (self, SECTION_SWITCH); +} +static inline void +rebuild_session_section_soon (IndicatorSessionService * self) +{ + rebuild_soon (self, SECTION_SESSION); +} +static inline void +rebuild_settings_section_soon (IndicatorSessionService * self) +{ + rebuild_soon (self, SECTION_SETTINGS); +} + +/*** +**** +***/ + +static void +update_header_action (IndicatorSessionService * self) +{ + gchar * a11y; + gboolean need_attn; + gboolean show_name; + GVariant * variant; + const gchar * real_name; + const gchar * label; + const gchar * iconstr; + const priv_t * const p = self->priv; + + g_return_if_fail (p->header_action != NULL); + + if (indicator_session_actions_has_online_account_error (p->backend_actions)) + { + need_attn = TRUE; + iconstr = ICON_ALERT; + } + else + { + need_attn = FALSE; + iconstr = ICON_DEFAULT; + } + + 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) + { + /* 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")); + } + + variant = g_variant_new ("(sssb)", label, iconstr, a11y, TRUE); + g_simple_action_set_state (p->header_action, variant); + g_free (a11y); +} + +/*** +**** USERS +***/ + +static GMenuModel * create_switch_section (IndicatorSessionService * self); + +static void +add_user (IndicatorSessionService * self, const gchar * key) +{ + IndicatorSessionUser * u; + + /* update our user table */ + u = indicator_session_users_get_user (self->priv->backend_users, key); + g_hash_table_insert (self->priv->users, g_strdup(key), u); + + /* enqueue rebuilds for the affected sections */ + rebuild_switch_section_soon (self); + if (u->is_current_user) + rebuild_header_soon (self); +} + +static void +on_user_added (IndicatorSessionUsers * backend_users G_GNUC_UNUSED, + const char * key, + gpointer gself) +{ + add_user (INDICATOR_SESSION_SERVICE(gself), key); +} + +static void +on_user_changed (IndicatorSessionUsers * backend_users G_GNUC_UNUSED, + const char * key, + gpointer gself) +{ + add_user (INDICATOR_SESSION_SERVICE(gself), key); +} + +static void +on_user_removed (IndicatorSessionUsers * backend_users G_GNUC_UNUSED, + const char * key, + gpointer gself) +{ + IndicatorSessionService * self = INDICATOR_SESSION_SERVICE (gself); + g_return_if_fail (self != NULL); + + /* update our user table */ + g_hash_table_remove (self->priv->users, key); + + /* enqueue rebuilds for the affected sections */ + rebuild_switch_section_soon (self); +} + +static const char * +get_current_real_name (IndicatorSessionService * self) +{ + GHashTableIter iter; + gpointer key, value; + + /* is it the guest? */ + if (indicator_session_guest_is_active (self->priv->backend_guest)) + return _("Guest"); + + /* is it a user? */ + g_hash_table_iter_init (&iter, self->priv->users); + while (g_hash_table_iter_next (&iter, &key, &value)) + { + IndicatorSessionUser * user = value; + if (user->is_current_user) + return user->real_name; + } + + return ""; +} + +/*** +**** +***/ + +static GMenuModel * +create_admin_section (void) +{ + GMenu * menu; + GMenuItem * item; + + menu = g_menu_new (); + + item = g_menu_item_new (_("About This Computer"), "indicator.about"); + g_menu_append_item (menu, item); + g_object_unref (G_OBJECT(item)); + + item = g_menu_item_new (_("Ubuntu Help"), "indicator.help"); + g_menu_append_item (menu, item); + g_object_unref (G_OBJECT(item)); + + return G_MENU_MODEL (menu); +} + +static GMenuModel * +create_settings_section (IndicatorSessionService * self) +{ + GMenu * menu; + GMenuItem * item; + priv_t * p = self->priv; + + menu = g_menu_new (); + + item = g_menu_item_new (_("System Settings\342\200\246"), "indicator.settings"); + g_menu_append_item (menu, item); + g_object_unref (G_OBJECT(item)); + + if (indicator_session_actions_has_online_account_error (p->backend_actions)) + { + item = g_menu_item_new (_("Online Accounts\342\200\246"), "indicator.online-accounts"); + g_menu_append_item (menu, item); + g_object_unref (G_OBJECT(item)); + } + + return G_MENU_MODEL (menu); +} + +/** + * The switch-to-guest action's state is a dictionary with these entries: + * - "is-active" (boolean) + * - "is-logged-in" (boolean) + */ +static GVariant * +create_guest_switcher_state (IndicatorSessionService * self) +{ + GVariant * val; + GVariantBuilder * b; + IndicatorSessionGuest * const g = self->priv->backend_guest; + + b = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}")); + val = g_variant_new_boolean (indicator_session_guest_is_active (g)); + g_variant_builder_add (b, "{sv}", "is-active", val); + val = g_variant_new_boolean (indicator_session_guest_is_logged_in (g)); + g_variant_builder_add (b, "{sv}", "is-logged-in", val); + return g_variant_builder_end (b); +} + +/** + * The switch-to-user action's state is a dictionary with these entries: + * - "active-user" (username string) + * - "logged-in-users" (array of username strings) + */ +static GVariant * +create_user_switcher_state (IndicatorSessionService * self) +{ + GVariantBuilder * a; + GVariantBuilder * b; + GVariant * val; + GHashTableIter ht_iter; + gpointer ht_key, ht_value; + const char * current_user; + + current_user = ""; + a = g_variant_builder_new (G_VARIANT_TYPE("as")); + g_hash_table_iter_init (&ht_iter, self->priv->users); + while (g_hash_table_iter_next (&ht_iter, &ht_key, &ht_value)) + { + const IndicatorSessionUser * u = ht_value; + + if (u->is_current_user) + current_user = u->user_name; + + if (u->is_logged_in) + g_variant_builder_add (a, "s", u->user_name); + } + + b = g_variant_builder_new (G_VARIANT_TYPE("a{sv}")); + val = g_variant_new_string (current_user); + g_variant_builder_add (b, "{sv}", "active-user", val); + val = g_variant_builder_end (a); + g_variant_builder_add (b, "{sv}", "logged-in-users", val); + return g_variant_builder_end (b); +} + +static void +update_switch_actions (IndicatorSessionService * self) +{ + g_simple_action_set_state (self->priv->guest_switcher_action, + create_guest_switcher_state (self)); + + g_simple_action_set_state (self->priv->user_switcher_action, + create_user_switcher_state (self)); +} + +static gboolean +use_ellipsis (IndicatorSessionService * self) +{ + /* does the backend support confirmation prompts? */ + if (!indicator_session_actions_can_prompt (self->priv->backend_actions)) + return FALSE; + + /* has the user disabled prompts? */ + if (g_settings_get_boolean (self->priv->indicator_settings, + "suppress-logout-restart-shutdown")) + return FALSE; + + return TRUE; +} + +/* lower index == more useful. + When there are too many users for the menu, + we use this to decide which to cull. */ +static int +compare_users_by_usefulness (gconstpointer ga, gconstpointer gb) +{ + const IndicatorSessionUser * a = *(const IndicatorSessionUser**)ga; + const IndicatorSessionUser * b = *(const IndicatorSessionUser**)gb; + + if (a->is_current_user != b->is_current_user) + return a->is_current_user ? -1 : 1; + + if (a->is_logged_in != b->is_logged_in) + return a->is_logged_in ? -1 : 1; + + if (a->login_frequency != b->login_frequency) + return a->login_frequency > b->login_frequency ? -1 : 1; + + return 0; +} + +/* sorting them for display in the menu */ +static int +compare_users_by_label (gconstpointer ga, gconstpointer gb) +{ + int i; + const IndicatorSessionUser * a = *(const IndicatorSessionUser**)ga; + const IndicatorSessionUser * b = *(const IndicatorSessionUser**)gb; + + if ((i = g_strcmp0 (a->real_name, b->real_name))) + return i; + + return g_strcmp0 (a->user_name, b->user_name); +} + +static GMenuModel * +create_switch_section (IndicatorSessionService * self) +{ + gchar * str; + GMenu * menu; + GMenuItem * item; + guint i; + gpointer guser; + GHashTableIter iter; + GPtrArray * users; + const priv_t * const p = self->priv; + const gboolean ellipsis = use_ellipsis (self); + + menu = g_menu_new (); + + /* lockswitch */ + if (indicator_session_users_is_live_session (p->backend_users)) + { + const char * action = "indicator.switch-to-screensaver"; + item = g_menu_item_new (_("Start Screen Saver"), action); + } + else if (indicator_session_guest_is_active (p->backend_guest)) + { + const char * action = "indicator.switch-to-greeter"; + item = g_menu_item_new (ellipsis ? _("Switch Account\342\200\246") + : _("Switch Account"), action); + } + else if (g_hash_table_size (p->users) == 1) + { + const char * action = "indicator.switch-to-greeter"; + item = g_menu_item_new (ellipsis ? _("Lock\342\200\246") + : _("Lock"), action); + } + else + { + const char * action = "indicator.switch-to-greeter"; + item = g_menu_item_new (ellipsis ? _("Lock/Switch Account\342\200\246") + : _("Lock/Switch Account"), action); + } + str = g_settings_get_string (p->keybinding_settings, "screensaver"); + g_menu_item_set_attribute (item, "accel", "s", str); + g_free (str); + g_menu_append_item (menu, item); + g_object_unref (G_OBJECT(item)); + + if (indicator_session_guest_is_allowed (p->backend_guest)) + { + item = g_menu_item_new (_("Guest Session"), "indicator.switch-to-guest"); + g_menu_append_item (menu, item); + g_object_unref (G_OBJECT(item)); + } + + /* build an array of all the users we know of */ + users = g_ptr_array_new (); + g_hash_table_iter_init (&iter, p->users); + while (g_hash_table_iter_next (&iter, NULL, &guser)) + g_ptr_array_add (users, guser); + + /* if there are too many users, cull out the less interesting ones */ + if (users->len > p->max_users) + { + g_ptr_array_sort (users, compare_users_by_usefulness); + g_ptr_array_set_size (users, p->max_users); + } + + /* sort the users by name */ + g_ptr_array_sort (users, compare_users_by_label); + + /* add the users */ + for (i=0; ilen; ++i) + { + const IndicatorSessionUser * u = g_ptr_array_index (users, i); + item = g_menu_item_new (u->real_name, NULL); + g_menu_item_set_action_and_target (item, "indicator.switch-to-user", "s", u->user_name); + g_menu_append_item (menu, item); + g_object_unref (G_OBJECT(item)); + } + + /* cleanup */ + g_ptr_array_free (users, TRUE); + return G_MENU_MODEL (menu); +} + +static GMenuModel * +create_session_section (IndicatorSessionService * self) +{ + GMenu * menu; + GMenuItem * item; + const priv_t * const p = self->priv; + GSettings * const s = p->indicator_settings; + const gboolean ellipsis = use_ellipsis (self); + + menu = g_menu_new (); + + if (indicator_session_actions_can_logout (p->backend_actions) && !g_settings_get_boolean (s, "suppress-logout-menuitem")) + { + item = g_menu_item_new (ellipsis ? _("Log Out\342\200\246") + : _("Log Out"), "indicator.logout"); + g_menu_append_item (menu, item); + g_object_unref (G_OBJECT(item)); + } + + if (indicator_session_actions_can_suspend (p->backend_actions)) + { + item = g_menu_item_new (_("Suspend"), "indicator.suspend"); + g_menu_append_item (menu, item); + g_object_unref (G_OBJECT(item)); + } + + if (indicator_session_actions_can_hibernate (p->backend_actions)) + { + item = g_menu_item_new (_("Hibernate"), "indicator.hibernate"); + g_menu_append_item (menu, item); + g_object_unref (G_OBJECT(item)); + } + + if (!g_settings_get_boolean (s, "suppress-restart-menuitem")) + { + item = g_menu_item_new (ellipsis ? _("Restart\342\200\246") + : _("Restart"), "indicator.restart"); + g_menu_append_item (menu, item); + g_object_unref (G_OBJECT(item)); + } + + if (!g_settings_get_boolean (s, "suppress-shutdown-menuitem")) + { + item = g_menu_item_new (ellipsis ? _("Shutdown\342\200\246") + : _("Shutdown"), "indicator.shutdown"); + g_menu_append_item (menu, item); + g_object_unref (G_OBJECT(item)); + } + + return G_MENU_MODEL (menu); +} + +static void +create_menu (IndicatorSessionService * self, int form_factor) +{ + GMenu * menu; + GMenu * submenu; + GMenuItem * header; + GMenuModel * sections[16]; + int i; + int n = 0; + + g_assert (0<=form_factor && form_factorpriv->menus[form_factor].menu == NULL); + + if (form_factor == FORM_DESKTOP) + { + sections[n++] = create_admin_section (); + sections[n++] = create_settings_section (self); + sections[n++] = create_switch_section (self); + sections[n++] = create_session_section (self); + } + else if (form_factor == FORM_GREETER) + { + sections[n++] = create_session_section (self); + } + + /* add sections to the submenu */ + submenu = g_menu_new (); + for (i=0; ipriv->menus[form_factor].menu = menu; + self->priv->menus[form_factor].submenu = submenu; +} + +/*** +**** GActions +***/ + +static IndicatorSessionActions * +get_backend_actions (gpointer gself) +{ + return INDICATOR_SESSION_SERVICE(gself)->priv->backend_actions; +} + +static void +on_about_activated (GSimpleAction * a G_GNUC_UNUSED, + GVariant * param G_GNUC_UNUSED, + gpointer gself) +{ + indicator_session_actions_about (get_backend_actions(gself)); +} + +static void +on_help_activated (GSimpleAction * a G_GNUC_UNUSED, + GVariant * param G_GNUC_UNUSED, + gpointer gself) +{ + indicator_session_actions_help (get_backend_actions(gself)); +} + +static void +on_settings_activated (GSimpleAction * a G_GNUC_UNUSED, + GVariant * param G_GNUC_UNUSED, + gpointer gself) +{ + indicator_session_actions_settings (get_backend_actions(gself)); +} + +static void +on_logout_activated (GSimpleAction * a G_GNUC_UNUSED, + GVariant * param G_GNUC_UNUSED, + gpointer gself) +{ + indicator_session_actions_logout (get_backend_actions(gself)); +} + +static void +on_suspend_activated (GSimpleAction * a G_GNUC_UNUSED, + GVariant * param G_GNUC_UNUSED, + gpointer gself) +{ + indicator_session_actions_suspend (get_backend_actions(gself)); +} + +static void +on_hibernate_activated (GSimpleAction * a G_GNUC_UNUSED, + GVariant * param G_GNUC_UNUSED, + gpointer gself) +{ + indicator_session_actions_hibernate (get_backend_actions(gself)); +} + +static void +on_restart_activated (GSimpleAction * action G_GNUC_UNUSED, + GVariant * param G_GNUC_UNUSED, + gpointer gself) +{ + indicator_session_actions_restart (get_backend_actions(gself)); +} + +static void +on_shutdown_activated (GSimpleAction * a G_GNUC_UNUSED, + GVariant * param G_GNUC_UNUSED, + gpointer gself) +{ + indicator_session_actions_shutdown (get_backend_actions(gself)); +} + +static void +on_guest_activated (GSimpleAction * a G_GNUC_UNUSED, + GVariant * param G_GNUC_UNUSED, + gpointer gself) +{ + indicator_session_actions_switch_to_guest (get_backend_actions(gself)); +} + +static void +on_screensaver_activated (GSimpleAction * a G_GNUC_UNUSED, + GVariant * param G_GNUC_UNUSED, + gpointer gself) +{ + indicator_session_actions_switch_to_screensaver (get_backend_actions(gself)); +} + +static void +on_greeter_activated (GSimpleAction * a G_GNUC_UNUSED, + GVariant * param G_GNUC_UNUSED, + gpointer gself) +{ + indicator_session_actions_switch_to_greeter (get_backend_actions(gself)); +} + +static void +on_user_activated (GSimpleAction * a G_GNUC_UNUSED, + GVariant * param, + gpointer gself) +{ + const char * username = g_variant_get_string (param, NULL); + indicator_session_actions_switch_to_username (get_backend_actions(gself), + username); +} + +static void +init_gactions (IndicatorSessionService * self) +{ + GVariant * v; + GSimpleAction * a; + priv_t * p = self->priv; + + GActionEntry entries[] = { + { "about", on_about_activated }, + { "help", on_help_activated }, + { "settings", on_settings_activated }, + { "logout", on_logout_activated }, + { "suspend", on_suspend_activated }, + { "hibernate", on_hibernate_activated }, + { "restart", on_restart_activated }, + { "shutdown", on_shutdown_activated }, + { "switch-to-screensaver", on_screensaver_activated }, + { "switch-to-greeter", on_greeter_activated } + }; + + p->actions = g_simple_action_group_new (); + + g_action_map_add_action_entries (G_ACTION_MAP(p->actions), + entries, + G_N_ELEMENTS(entries), + self); + + /* add switch-to-guest action */ + v = create_guest_switcher_state (self); + a = g_simple_action_new_stateful ("switch-to-guest", NULL, v); + g_signal_connect (a, "activate", G_CALLBACK(on_guest_activated), self); + g_simple_action_group_insert (p->actions, G_ACTION(a)); + p->guest_switcher_action = a; + + /* add switch-to-user action... parameter is the uesrname */ + v = create_user_switcher_state (self); + a = g_simple_action_new_stateful ("switch-to-user", G_VARIANT_TYPE_STRING, v); + g_signal_connect (a, "activate", G_CALLBACK(on_user_activated), self); + g_simple_action_group_insert (p->actions, G_ACTION(a)); + p->user_switcher_action = a; + + /* add the header action */ + v = g_variant_new ("(sssb)", "label", ICON_DEFAULT, "a11y", TRUE); + a = g_simple_action_new_stateful ("_header", NULL, v); + g_simple_action_group_insert (p->actions, G_ACTION(a)); + p->header_action = a; + + rebuild_now (self, SECTION_HEADER); +} + +/*** +**** +***/ + +static void +replace_section (GMenu * parent, int pos, GMenuModel * new_section) +{ + g_menu_remove (parent, pos); + g_menu_insert_section (parent, pos, NULL, new_section); + g_object_unref (G_OBJECT(new_section)); +} + +static void +rebuild_now (IndicatorSessionService * self, int sections) +{ + priv_t * p = self->priv; + struct FormMenuInfo * desktop = &p->menus[FORM_DESKTOP]; + struct FormMenuInfo * greeter = &p->menus[FORM_GREETER]; + + if (sections & SECTION_HEADER) + { + update_header_action (self); + } + + if (sections & SECTION_ADMIN) + { + replace_section (desktop->submenu, 0, create_admin_section()); + } + + if (sections & SECTION_SETTINGS) + { + replace_section (desktop->submenu, 1, create_settings_section(self)); + } + + if (sections & SECTION_SWITCH) + { + replace_section (desktop->submenu, 2, create_switch_section(self)); + update_switch_actions (self); + } + + if (sections & SECTION_SESSION) + { + replace_section (desktop->submenu, 3, create_session_section(self)); + replace_section (greeter->submenu, 0, create_session_section(self)); + } +} + +static int +rebuild_timeout_func (IndicatorSessionService * self) +{ + priv_t * p = self->priv; + rebuild_now (self, p->rebuild_flags); + p->rebuild_flags = 0; + p->rebuild_id = 0; + return G_SOURCE_REMOVE; +} + +static void +rebuild_soon (IndicatorSessionService * self, int section) +{ + priv_t * p = self->priv; + + p->rebuild_flags |= section; + + if (p->rebuild_id == 0) + { + static const int REBUILD_INTERVAL_MSEC = 500; + + p->rebuild_id = g_timeout_add (REBUILD_INTERVAL_MSEC, + (GSourceFunc)rebuild_timeout_func, + self); + } +} + +/*** +**** GDBus +***/ + +static void +on_bus_acquired (GDBusConnection * connection, + const gchar * name, + gpointer gself) +{ + int i; + guint id; + GError * err = NULL; + IndicatorSessionService * self = INDICATOR_SESSION_SERVICE(gself); + priv_t * p = self->priv; + + g_debug ("bus acquired: %s", name); + + p->conn = g_object_ref (G_OBJECT (connection)); + + /* export the actions */ + if ((id = g_dbus_connection_export_action_group (connection, + BUS_PATH, + G_ACTION_GROUP (p->actions), + &err))) + { + p->actions_export_id = id; + } + else + { + g_warning ("cannot export action group: %s", err->message); + g_clear_error (&err); + } + + /* export the menus */ + for (i=0; imenus[i]; + + if (menu->menu == NULL) + create_menu (self, i); + + if ((id = g_dbus_connection_export_menu_model (connection, + path, + G_MENU_MODEL (menu->menu), + &err))) + { + menu->export_id = id; + } + else + { + g_warning ("cannot export %s menu: %s", menu_names[i], err->message); + g_clear_error (&err); + } + + g_free (path); + } +} + +static void +unexport (IndicatorSessionService * self) +{ + int i; + priv_t * p = self->priv; + + /* unexport the menus */ + for (i=0; ipriv->menus[i].export_id; + + if (*id) + { + g_dbus_connection_unexport_menu_model (p->conn, *id); + *id = 0; + } + } + + /* unexport the actions */ + if (p->actions_export_id) + { + g_dbus_connection_unexport_action_group (p->conn, p->actions_export_id); + p->actions_export_id = 0; + } +} + +static void +on_name_lost (GDBusConnection * connection G_GNUC_UNUSED, + const gchar * name, + gpointer gself) +{ + g_debug ("%s %s name lost %s", G_STRLOC, G_STRFUNC, name); + + unexport (INDICATOR_SESSION_SERVICE (gself)); +} + +/*** +**** +***/ + +static void +/* cppcheck-suppress unusedFunction */ +indicator_session_service_init (IndicatorSessionService * self) +{ + int i; + GStrv keys; + priv_t * p; + gpointer gp; + + /* init our priv pointer */ + p = G_TYPE_INSTANCE_GET_PRIVATE (self, + INDICATOR_TYPE_SESSION_SERVICE, + IndicatorSessionServicePrivate); + p->indicator_settings = g_settings_new ("com.canonical.indicator.session"); + p->keybinding_settings = g_settings_new ("org.gnome.settings-daemon.plugins.media-keys"); + self->priv = p; + + /* init the backend objects */ + backend_get (g_cancellable_new (), &p->backend_actions, + &p->backend_users, + &p->backend_guest); + + /* init our key-to-User table */ + p->users = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + (GDestroyNotify)indicator_session_user_free); + keys = indicator_session_users_get_keys (p->backend_users); + for (i=0; keys && keys[i]; ++i) + add_user (self, keys[i]); + g_strfreev (keys); + + init_gactions (self); + + /* watch for changes in backend_users */ + gp = p->backend_users; + g_signal_connect (gp, INDICATOR_SESSION_USERS_SIGNAL_USER_ADDED, + G_CALLBACK(on_user_added), self); + g_signal_connect (gp, INDICATOR_SESSION_USERS_SIGNAL_USER_CHANGED, + G_CALLBACK(on_user_changed), self); + g_signal_connect (gp, INDICATOR_SESSION_USERS_SIGNAL_USER_REMOVED, + G_CALLBACK(on_user_removed), self); + g_signal_connect_swapped (gp, "notify::is-live-session", + G_CALLBACK(rebuild_switch_section_soon), self); + + /* watch for changes in backend_guest */ + gp = p->backend_guest; + g_signal_connect_swapped (gp, "notify::guest-is-active-session", + G_CALLBACK(rebuild_header_soon), self); + g_signal_connect_swapped (gp, "notify", + G_CALLBACK(rebuild_switch_section_soon), self); + + /* watch for updates in backend_actions */ + gp = p->backend_actions; + g_signal_connect_swapped (gp, "notify", + G_CALLBACK(rebuild_switch_section_soon), self); + g_signal_connect_swapped (gp, "notify", + G_CALLBACK(rebuild_session_section_soon), self); + g_signal_connect_swapped (gp, "notify::has-online-account-error", + G_CALLBACK(rebuild_header_soon), self); + g_signal_connect_swapped (gp, "notify::has-online-account-error", + G_CALLBACK(rebuild_settings_section_soon), self); + + /* watch for changes in the indicator's settings */ + gp = p->indicator_settings; + g_signal_connect_swapped (gp, "changed::suppress-logout-restart-shutdown", + G_CALLBACK(rebuild_switch_section_soon), self); + g_signal_connect_swapped (gp, "changed::suppress-logout-restart-shutdown", + G_CALLBACK(rebuild_session_section_soon), self); + g_signal_connect_swapped (gp, "changed::suppress-logout-menuitem", + G_CALLBACK(rebuild_session_section_soon), self); + g_signal_connect_swapped (gp, "changed::suppress-restart-menuitem", + G_CALLBACK(rebuild_session_section_soon), self); + g_signal_connect_swapped (gp, "changed::suppress-shutdown-menuitem", + G_CALLBACK(rebuild_session_section_soon), self); + g_signal_connect_swapped (gp, "changed::show-real-name-on-panel", + G_CALLBACK(rebuild_header_soon), self); + + /* watch for changes to the lock keybinding */ + gp = p->keybinding_settings; + g_signal_connect_swapped (gp, "changed::screensaver", + G_CALLBACK(rebuild_switch_section_soon), self); +} + +static void +my_constructed (GObject * o) +{ + GBusNameOwnerFlags owner_flags; + IndicatorSessionService * self = INDICATOR_SESSION_SERVICE(o); + + /* own the name in constructed() instead of init() so that + we'll know the value of the 'replace' property */ + owner_flags = G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT; + if (self->priv->replace) + owner_flags |= G_BUS_NAME_OWNER_FLAGS_REPLACE; + + self->priv->own_id = g_bus_own_name (G_BUS_TYPE_SESSION, + BUS_NAME, + owner_flags, + on_bus_acquired, + NULL, + on_name_lost, + self, + NULL); +} + +/*** +**** GObject plumbing: properties +***/ + +static void +my_get_property (GObject * o, + guint property_id, + GValue * value, + GParamSpec * pspec) +{ + IndicatorSessionService * self = INDICATOR_SESSION_SERVICE (o); + + switch (property_id) + { + case PROP_REPLACE: + g_value_set_boolean (value, self->priv->replace); + break; + + case PROP_MAX_USERS: + g_value_set_uint (value, self->priv->max_users); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec); + } +} + +static void +my_set_property (GObject * o, + guint property_id, + const GValue * value G_GNUC_UNUSED, + GParamSpec * pspec) +{ + IndicatorSessionService * self = INDICATOR_SESSION_SERVICE (o); + + switch (property_id) + { + case PROP_REPLACE: + self->priv->replace = g_value_get_boolean (value); + break; + + case PROP_MAX_USERS: + self->priv->max_users = g_value_get_uint (value); + rebuild_switch_section_soon (self); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (o, property_id, pspec); + } +} + +/*** +**** GObject plumbing: life cycle +***/ + +static void +my_dispose (GObject * o) +{ + int i; + IndicatorSessionService * self = INDICATOR_SESSION_SERVICE(o); + priv_t * p = self->priv; + + unexport (self); + + if (p->rebuild_id) + { + g_source_remove (p->rebuild_id); + p->rebuild_id = 0; + } + + if (p->own_id) + { + g_bus_unown_name (p->own_id); + p->own_id = 0; + } + + g_clear_pointer (&p->users, g_hash_table_destroy); + g_clear_object (&p->backend_users); + g_clear_object (&p->backend_guest); + g_clear_object (&p->backend_actions); + g_clear_object (&p->indicator_settings); + g_clear_object (&p->keybinding_settings); + g_clear_object (&p->actions); + + for (i=0; imenus[i].menu); + + g_clear_object (&p->header_action); + g_clear_object (&p->user_switcher_action); + g_clear_object (&p->guest_switcher_action); + g_clear_object (&p->conn); + + G_OBJECT_CLASS (indicator_session_service_parent_class)->dispose (o); +} + +static void +/* cppcheck-suppress unusedFunction */ +indicator_session_service_class_init (IndicatorSessionServiceClass * klass) +{ + GObjectClass * object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = my_dispose; + object_class->constructed = my_constructed; + object_class->get_property = my_get_property; + object_class->set_property = my_set_property; + + g_type_class_add_private (klass, sizeof (IndicatorSessionServicePrivate)); + + properties[PROP_0] = NULL; + + properties[PROP_REPLACE] = g_param_spec_boolean ("replace", + "Replace Service", + "Replace existing service", + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + properties[PROP_MAX_USERS] = g_param_spec_uint ("max-users", + "Max Users", + "Max visible users", + 0, INT_MAX, 12, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties (object_class, PROP_LAST, properties); +} + +IndicatorSessionService * +indicator_session_service_new (gboolean replace) +{ + GObject * o = g_object_new (INDICATOR_TYPE_SESSION_SERVICE, + "replace", replace, + NULL); + + return INDICATOR_SESSION_SERVICE (o); +} -- cgit v1.2.3 From 4bc93061f407194434de187ea55a0317af4b71ac Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 26 Mar 2013 15:52:55 -0500 Subject: remove unnecessary G_GNUC_UNUSED --- src/service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/service.c') diff --git a/src/service.c b/src/service.c index 1345681..8e2921e 100644 --- a/src/service.c +++ b/src/service.c @@ -1082,7 +1082,7 @@ my_get_property (GObject * o, static void my_set_property (GObject * o, guint property_id, - const GValue * value G_GNUC_UNUSED, + const GValue * value, GParamSpec * pspec) { IndicatorSessionService * self = INDICATOR_SESSION_SERVICE (o); -- cgit v1.2.3 From d87fb5d14091b22eaf6226dc8f9656bd6d514571 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 18 Apr 2013 10:10:17 -0500 Subject: where appropriate, use g_menu_append() to save a few lines. --- src/service.c | 62 +++++++++++++---------------------------------------------- 1 file changed, 13 insertions(+), 49 deletions(-) (limited to 'src/service.c') diff --git a/src/service.c b/src/service.c index 8e2921e..e62250e 100644 --- a/src/service.c +++ b/src/service.c @@ -277,18 +277,10 @@ static GMenuModel * create_admin_section (void) { GMenu * menu; - GMenuItem * item; menu = g_menu_new (); - - item = g_menu_item_new (_("About This Computer"), "indicator.about"); - g_menu_append_item (menu, item); - g_object_unref (G_OBJECT(item)); - - item = g_menu_item_new (_("Ubuntu Help"), "indicator.help"); - g_menu_append_item (menu, item); - g_object_unref (G_OBJECT(item)); - + g_menu_append (menu, _("About This Computer"), "indicator.about"); + g_menu_append (menu, _("Ubuntu Help"), "indicator.help"); return G_MENU_MODEL (menu); } @@ -296,21 +288,12 @@ static GMenuModel * create_settings_section (IndicatorSessionService * self) { GMenu * menu; - GMenuItem * item; priv_t * p = self->priv; menu = g_menu_new (); - - item = g_menu_item_new (_("System Settings\342\200\246"), "indicator.settings"); - g_menu_append_item (menu, item); - g_object_unref (G_OBJECT(item)); - + g_menu_append (menu, _("System Settings\342\200\246"), "indicator.settings"); if (indicator_session_actions_has_online_account_error (p->backend_actions)) - { - item = g_menu_item_new (_("Online Accounts\342\200\246"), "indicator.online-accounts"); - g_menu_append_item (menu, item); - g_object_unref (G_OBJECT(item)); - } + g_menu_append (menu, _("Online Accounts\342\200\246"), "indicator.online-accounts"); return G_MENU_MODEL (menu); } @@ -478,11 +461,7 @@ create_switch_section (IndicatorSessionService * self) g_object_unref (G_OBJECT(item)); if (indicator_session_guest_is_allowed (p->backend_guest)) - { - item = g_menu_item_new (_("Guest Session"), "indicator.switch-to-guest"); - g_menu_append_item (menu, item); - g_object_unref (G_OBJECT(item)); - } + g_menu_append (menu, _("Guest Session"), "indicator.switch-to-guest"); /* build an array of all the users we know of */ users = g_ptr_array_new (); @@ -519,7 +498,6 @@ static GMenuModel * create_session_section (IndicatorSessionService * self) { GMenu * menu; - GMenuItem * item; const priv_t * const p = self->priv; GSettings * const s = p->indicator_settings; const gboolean ellipsis = use_ellipsis (self); @@ -528,40 +506,26 @@ create_session_section (IndicatorSessionService * self) if (indicator_session_actions_can_logout (p->backend_actions) && !g_settings_get_boolean (s, "suppress-logout-menuitem")) { - item = g_menu_item_new (ellipsis ? _("Log Out\342\200\246") - : _("Log Out"), "indicator.logout"); - g_menu_append_item (menu, item); - g_object_unref (G_OBJECT(item)); + const char * label = ellipsis ? _("Log Out\342\200\246") : _("Log Out"); + g_menu_append (menu, label, "indicator.logout"); } if (indicator_session_actions_can_suspend (p->backend_actions)) - { - item = g_menu_item_new (_("Suspend"), "indicator.suspend"); - g_menu_append_item (menu, item); - g_object_unref (G_OBJECT(item)); - } + g_menu_append (menu, _("Suspend"), "indicator.suspend"); if (indicator_session_actions_can_hibernate (p->backend_actions)) - { - item = g_menu_item_new (_("Hibernate"), "indicator.hibernate"); - g_menu_append_item (menu, item); - g_object_unref (G_OBJECT(item)); - } + g_menu_append (menu, _("Hibernate"), "indicator.hibernate"); if (!g_settings_get_boolean (s, "suppress-restart-menuitem")) { - item = g_menu_item_new (ellipsis ? _("Restart\342\200\246") - : _("Restart"), "indicator.restart"); - g_menu_append_item (menu, item); - g_object_unref (G_OBJECT(item)); + const char * label = ellipsis ? _("Restart\342\200\246") : _("Restart"); + g_menu_append (menu, label, "indicator.restart"); } if (!g_settings_get_boolean (s, "suppress-shutdown-menuitem")) { - item = g_menu_item_new (ellipsis ? _("Shutdown\342\200\246") - : _("Shutdown"), "indicator.shutdown"); - g_menu_append_item (menu, item); - g_object_unref (G_OBJECT(item)); + const char * label = ellipsis ? _("Shutdown\342\200\246") : _("Shutdown"); + g_menu_append (menu, label, "indicator.shutdown"); } return G_MENU_MODEL (menu); -- cgit v1.2.3 From 033cc134729679757e96715e32e0d517143ef49e Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 18 Apr 2013 10:26:20 -0500 Subject: add a small comment explaining replace_section() --- src/service.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'src/service.c') diff --git a/src/service.c b/src/service.c index e62250e..2206621 100644 --- a/src/service.c +++ b/src/service.c @@ -741,8 +741,13 @@ init_gactions (IndicatorSessionService * self) **** ***/ +/** + * A small helper function for rebuild_now(). + * - removes the previous section + * - adds and unrefs the new section + */ static void -replace_section (GMenu * parent, int pos, GMenuModel * new_section) +rebuild_section (GMenu * parent, int pos, GMenuModel * new_section) { g_menu_remove (parent, pos); g_menu_insert_section (parent, pos, NULL, new_section); @@ -763,24 +768,24 @@ rebuild_now (IndicatorSessionService * self, int sections) if (sections & SECTION_ADMIN) { - replace_section (desktop->submenu, 0, create_admin_section()); + rebuild_section (desktop->submenu, 0, create_admin_section()); } if (sections & SECTION_SETTINGS) { - replace_section (desktop->submenu, 1, create_settings_section(self)); + rebuild_section (desktop->submenu, 1, create_settings_section(self)); } if (sections & SECTION_SWITCH) { - replace_section (desktop->submenu, 2, create_switch_section(self)); + rebuild_section (desktop->submenu, 2, create_switch_section(self)); update_switch_actions (self); } if (sections & SECTION_SESSION) { - replace_section (desktop->submenu, 3, create_session_section(self)); - replace_section (greeter->submenu, 0, create_session_section(self)); + rebuild_section (desktop->submenu, 3, create_session_section(self)); + rebuild_section (greeter->submenu, 0, create_session_section(self)); } } -- cgit v1.2.3 From d79745bdb2e9bbd02e162a5209de9f227d1dbbc3 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 18 Apr 2013 10:29:50 -0500 Subject: in rebuild_soon(), add a comment explaining the 500 msec interval --- src/service.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/service.c') diff --git a/src/service.c b/src/service.c index 2206621..2a10290 100644 --- a/src/service.c +++ b/src/service.c @@ -808,6 +808,10 @@ rebuild_soon (IndicatorSessionService * self, int section) if (p->rebuild_id == 0) { + /* Change events seem to come over the bus in small bursts. This msec + value is an arbitrary number that tries to be large enough to fold + multiple events into a single rebuild, but small enough that the + user won't notice any lag. */ static const int REBUILD_INTERVAL_MSEC = 500; p->rebuild_id = g_timeout_add (REBUILD_INTERVAL_MSEC, -- cgit v1.2.3 From 67218e58889b101ceb5a50bcb40c37045fb2855d Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 18 Apr 2013 11:13:03 -0500 Subject: indicator-session-service should exit when it loses ownership of its name on the bus. --- src/main.c | 9 +++++++++ src/service.c | 23 ++++++++++++++++++++++- src/service.h | 7 +++++++ 3 files changed, 38 insertions(+), 1 deletion(-) (limited to 'src/service.c') diff --git a/src/main.c b/src/main.c index 17b50b4..4511fce 100644 --- a/src/main.c +++ b/src/main.c @@ -60,6 +60,13 @@ parse_command_line (int * argc, char *** argv) **** ***/ +static void +on_name_lost (gpointer instance, gpointer loop) +{ + g_debug ("exiting: service couldn't acquire or lost ownership of busname"); + g_main_loop_quit ((GMainLoop*)loop); +} + int main (int argc, char ** argv) { @@ -76,6 +83,8 @@ main (int argc, char ** argv) /* run */ service = indicator_session_service_new (replace); loop = g_main_loop_new (NULL, FALSE); + g_signal_connect (service, INDICATOR_SESSION_SERVICE_SIGNAL_NAME_LOST, + G_CALLBACK(on_name_lost), loop); g_main_loop_run (loop); /* cleanup */ diff --git a/src/service.c b/src/service.c index 2a10290..bcd88ff 100644 --- a/src/service.c +++ b/src/service.c @@ -37,6 +37,15 @@ G_DEFINE_TYPE (IndicatorSessionService, indicator_session_service, G_TYPE_OBJECT) +/* signals enum */ +enum +{ + NAME_LOST, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + enum { PROP_0, @@ -910,9 +919,13 @@ on_name_lost (GDBusConnection * connection G_GNUC_UNUSED, const gchar * name, gpointer gself) { + IndicatorSessionService * self = INDICATOR_SESSION_SERVICE (gself); + g_debug ("%s %s name lost %s", G_STRLOC, G_STRFUNC, name); - unexport (INDICATOR_SESSION_SERVICE (gself)); + unexport (self); + + g_signal_emit (self, signals[NAME_LOST], 0, NULL); } /*** @@ -1133,6 +1146,14 @@ indicator_session_service_class_init (IndicatorSessionServiceClass * klass) g_type_class_add_private (klass, sizeof (IndicatorSessionServicePrivate)); + signals[NAME_LOST] = g_signal_new (INDICATOR_SESSION_SERVICE_SIGNAL_NAME_LOST, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IndicatorSessionServiceClass, name_lost), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + properties[PROP_0] = NULL; properties[PROP_REPLACE] = g_param_spec_boolean ("replace", diff --git a/src/service.h b/src/service.h index 2a78855..3fad6bf 100644 --- a/src/service.h +++ b/src/service.h @@ -36,6 +36,9 @@ typedef struct _IndicatorSessionService IndicatorSessionService; typedef struct _IndicatorSessionServiceClass IndicatorSessionServiceClass; typedef struct _IndicatorSessionServicePrivate IndicatorSessionServicePrivate; +/* signal keys */ +#define INDICATOR_SESSION_SERVICE_SIGNAL_NAME_LOST "name-lost" + /** * The Indicator Session Service. */ @@ -49,6 +52,10 @@ struct _IndicatorSessionService struct _IndicatorSessionServiceClass { GObjectClass parent_class; + + /* signals */ + + void (* name_lost)(IndicatorSessionService * self); }; /*** -- cgit v1.2.3 From 348a5c53f4ca0d1ee197bc0822f0c8d712cd8972 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 18 Apr 2013 11:19:05 -0500 Subject: in indicator_session_service_init(), don't leak a GCancellable --- src/service.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'src/service.c') diff --git a/src/service.c b/src/service.c index bcd88ff..14d41cd 100644 --- a/src/service.c +++ b/src/service.c @@ -108,6 +108,7 @@ struct _IndicatorSessionServicePrivate guint rebuild_id; int rebuild_flags; GDBusConnection * conn; + GCancellable * cancellable; gboolean replace; }; @@ -950,9 +951,10 @@ indicator_session_service_init (IndicatorSessionService * self) self->priv = p; /* init the backend objects */ - backend_get (g_cancellable_new (), &p->backend_actions, - &p->backend_users, - &p->backend_guest); + p->cancellable = g_cancellable_new (); + backend_get (p->cancellable, &p->backend_actions, + &p->backend_users, + &p->backend_guest); /* init our key-to-User table */ p->users = g_hash_table_new_full (g_str_hash, @@ -1102,6 +1104,12 @@ my_dispose (GObject * o) unexport (self); + if (p->cancellable != NULL) + { + g_cancellable_cancel (p->cancellable); + g_clear_object (&p->cancellable); + } + if (p->rebuild_id) { g_source_remove (p->rebuild_id); -- cgit v1.2.3 From 75d79800ffbc0bdc8598b2b34164c4dabc9888c8 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 18 Apr 2013 11:25:13 -0500 Subject: in the service's dispose() function, unown the busname before unexporting the actions and menus. --- src/service.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/service.c') diff --git a/src/service.c b/src/service.c index 14d41cd..9a4e561 100644 --- a/src/service.c +++ b/src/service.c @@ -1102,6 +1102,12 @@ my_dispose (GObject * o) IndicatorSessionService * self = INDICATOR_SESSION_SERVICE(o); priv_t * p = self->priv; + if (p->own_id) + { + g_bus_unown_name (p->own_id); + p->own_id = 0; + } + unexport (self); if (p->cancellable != NULL) @@ -1116,12 +1122,6 @@ my_dispose (GObject * o) p->rebuild_id = 0; } - if (p->own_id) - { - g_bus_unown_name (p->own_id); - p->own_id = 0; - } - g_clear_pointer (&p->users, g_hash_table_destroy); g_clear_object (&p->backend_users); g_clear_object (&p->backend_guest); -- cgit v1.2.3 From 29befc58e1f1fd61d4d6d1a6db024d32182f7488 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 18 Apr 2013 11:41:22 -0500 Subject: g_object_unref doesn't need a G_OBJECT() cast --- src/service.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/service.c') diff --git a/src/service.c b/src/service.c index 9a4e561..2e42bd0 100644 --- a/src/service.c +++ b/src/service.c @@ -468,7 +468,7 @@ create_switch_section (IndicatorSessionService * self) g_menu_item_set_attribute (item, "accel", "s", str); g_free (str); g_menu_append_item (menu, item); - g_object_unref (G_OBJECT(item)); + g_object_unref (item); if (indicator_session_guest_is_allowed (p->backend_guest)) g_menu_append (menu, _("Guest Session"), "indicator.switch-to-guest"); @@ -496,7 +496,7 @@ create_switch_section (IndicatorSessionService * self) item = g_menu_item_new (u->real_name, NULL); g_menu_item_set_action_and_target (item, "indicator.switch-to-user", "s", u->user_name); g_menu_append_item (menu, item); - g_object_unref (G_OBJECT(item)); + g_object_unref (item); } /* cleanup */ @@ -571,19 +571,19 @@ create_menu (IndicatorSessionService * self, int form_factor) for (i=0; ipriv->menus[form_factor].menu = menu; self->priv->menus[form_factor].submenu = submenu; @@ -761,7 +761,7 @@ rebuild_section (GMenu * parent, int pos, GMenuModel * new_section) { g_menu_remove (parent, pos); g_menu_insert_section (parent, pos, NULL, new_section); - g_object_unref (G_OBJECT(new_section)); + g_object_unref (new_section); } static void -- cgit v1.2.3 From 6729218076bdfebfc5b5c48742abb72a3a899314 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 18 Apr 2013 12:30:14 -0500 Subject: refer to profiles as profiles instead of forms. --- src/service.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'src/service.c') diff --git a/src/service.c b/src/service.c index 2e42bd0..d912176 100644 --- a/src/service.c +++ b/src/service.c @@ -67,18 +67,18 @@ enum enum { - FORM_DESKTOP, - FORM_GREETER, - N_FORMS + PROFILE_DESKTOP, + PROFILE_GREETER, + N_PROFILES }; -static const char * const menu_names[N_FORMS] = +static const char * const menu_names[N_PROFILES] = { "desktop", "desktop_greeter" }; -struct FormMenuInfo +struct ProfileMenuInfo { /* the root level -- the header is the only child of this */ GMenu * menu; @@ -100,7 +100,7 @@ struct _IndicatorSessionServicePrivate GSettings * keybinding_settings; GSimpleActionGroup * actions; guint actions_export_id; - struct FormMenuInfo menus[N_FORMS]; + struct ProfileMenuInfo menus[N_PROFILES]; GSimpleAction * header_action; GSimpleAction * user_switcher_action; GSimpleAction * guest_switcher_action; @@ -542,7 +542,7 @@ create_session_section (IndicatorSessionService * self) } static void -create_menu (IndicatorSessionService * self, int form_factor) +create_menu (IndicatorSessionService * self, int profile) { GMenu * menu; GMenu * submenu; @@ -551,17 +551,17 @@ create_menu (IndicatorSessionService * self, int form_factor) int i; int n = 0; - g_assert (0<=form_factor && form_factorpriv->menus[form_factor].menu == NULL); + g_assert (0<=profile && profilepriv->menus[profile].menu == NULL); - if (form_factor == FORM_DESKTOP) + if (profile == PROFILE_DESKTOP) { sections[n++] = create_admin_section (); sections[n++] = create_settings_section (self); sections[n++] = create_switch_section (self); sections[n++] = create_session_section (self); } - else if (form_factor == FORM_GREETER) + else if (profile == PROFILE_GREETER) { sections[n++] = create_session_section (self); } @@ -585,8 +585,8 @@ create_menu (IndicatorSessionService * self, int form_factor) g_menu_append_item (menu, header); g_object_unref (header); - self->priv->menus[form_factor].menu = menu; - self->priv->menus[form_factor].submenu = submenu; + self->priv->menus[profile].menu = menu; + self->priv->menus[profile].submenu = submenu; } /*** @@ -768,8 +768,8 @@ static void rebuild_now (IndicatorSessionService * self, int sections) { priv_t * p = self->priv; - struct FormMenuInfo * desktop = &p->menus[FORM_DESKTOP]; - struct FormMenuInfo * greeter = &p->menus[FORM_GREETER]; + struct ProfileMenuInfo * desktop = &p->menus[PROFILE_DESKTOP]; + struct ProfileMenuInfo * greeter = &p->menus[PROFILE_GREETER]; if (sections & SECTION_HEADER) { @@ -864,10 +864,10 @@ on_bus_acquired (GDBusConnection * connection, } /* export the menus */ - for (i=0; imenus[i]; + struct ProfileMenuInfo * menu = &p->menus[i]; if (menu->menu == NULL) create_menu (self, i); @@ -896,7 +896,7 @@ unexport (IndicatorSessionService * self) priv_t * p = self->priv; /* unexport the menus */ - for (i=0; ipriv->menus[i].export_id; @@ -1130,7 +1130,7 @@ my_dispose (GObject * o) g_clear_object (&p->keybinding_settings); g_clear_object (&p->actions); - for (i=0; imenus[i].menu); g_clear_object (&p->header_action); -- cgit v1.2.3 From 2babf3e334649031a4e8fff308358f6974ceb155 Mon Sep 17 00:00:00 2001 From: Lars Uebernickel Date: Thu, 23 May 2013 18:48:56 -0400 Subject: Set x-canonical-type for user and guest menu items --- README | 4 ++-- src/service.c | 11 ++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) (limited to 'src/service.c') diff --git a/README b/README index 420541e..29a135f 100644 --- a/README +++ b/README @@ -12,7 +12,7 @@ As per the https://wiki.ubuntu.com/SystemMenu specification, both need four visual components: (1) an Active Session Mark, the user's (2) icon, (3) name, and (4) a Logged In Mark. -== User menuitems can be recognized by their "indicator.switch-to-user" action. +== User menuitems have "x-canonical-type" set to "indicator.user-menu-item" Their four visual components are determined by: 1. You can test for the Action Session Mark by checking the action's state. @@ -30,7 +30,7 @@ and (4) a Logged In Mark. an array of usernames. If the array contains the username in this menuitem's "target" attribute, show the Logged In Mark. -== The Guest switcher can be recognized by its "indicator.switch-to-guest" +== The Guest switcher has "x-canonical-type" set to "indicator.guest-menu-item" action. Its four visual components are determined by: 1. You can test for the Active Session Mark by checking the action's state. diff --git a/src/service.c b/src/service.c index d912176..59728d1 100644 --- a/src/service.c +++ b/src/service.c @@ -471,7 +471,15 @@ create_switch_section (IndicatorSessionService * self) g_object_unref (item); if (indicator_session_guest_is_allowed (p->backend_guest)) - g_menu_append (menu, _("Guest Session"), "indicator.switch-to-guest"); + { + GMenuItem *item; + + item = g_menu_item_new (_("Guest Session"), "indicator.switch-to-guest"); + g_menu_item_set_attribute (item, "x-canonical-type", "s", "indicator.guest-menu-item"); + g_menu_append_item (menu, item); + + g_object_unref (item); + } /* build an array of all the users we know of */ users = g_ptr_array_new (); @@ -495,6 +503,7 @@ create_switch_section (IndicatorSessionService * self) const IndicatorSessionUser * u = g_ptr_array_index (users, i); item = g_menu_item_new (u->real_name, 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"); g_menu_append_item (menu, item); g_object_unref (item); } -- cgit v1.2.3 From a4c536391abbd2057ddbcd8d0bc83a9e67de3273 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 19 Jun 2013 18:16:25 -0500 Subject: in service.c, remove unnecesssary locale #include --- src/service.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/service.c') diff --git a/src/service.c b/src/service.c index d912176..7852adf 100644 --- a/src/service.c +++ b/src/service.c @@ -17,8 +17,6 @@ * with this program. If not, see . */ -#include - #include #include -- cgit v1.2.3 From 4df0aceb48e9b3d6c77f6e06c7acde89747ff878 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 19 Jun 2013 18:27:08 -0500 Subject: use the production dbus name --- data/com.canonical.indicator.session | 10 ++++++++++ data/session.indicator | 4 ---- src/service.c | 3 +-- tests/test-service.cc | 6 +++--- 4 files changed, 14 insertions(+), 9 deletions(-) create mode 100644 data/com.canonical.indicator.session delete mode 100644 data/session.indicator (limited to 'src/service.c') diff --git a/data/com.canonical.indicator.session b/data/com.canonical.indicator.session new file mode 100644 index 0000000..fce3554 --- /dev/null +++ b/data/com.canonical.indicator.session @@ -0,0 +1,10 @@ +[Indicator Service] +Name=indicator-session +ObjectPath=/com/canonical/indicator/session + +[desktop] +ObjectPath=/com/canonical/indicator/session/desktop + +[greeter] +ObjectPath=/com/canonical/indicator/session/greeter + diff --git a/data/session.indicator b/data/session.indicator deleted file mode 100644 index b5f6802..0000000 --- a/data/session.indicator +++ /dev/null @@ -1,4 +0,0 @@ -[Indicator Service] -Name=indicator-session -BusName=com.canonical.indicator.session-test -ObjectPath=/com/canonical/indicator/session diff --git a/src/service.c b/src/service.c index 7852adf..862028b 100644 --- a/src/service.c +++ b/src/service.c @@ -23,8 +23,7 @@ #include "backend.h" #include "service.h" -/* FIXME: remove -test */ -#define BUS_NAME "com.canonical.indicator.session-test" +#define BUS_NAME "com.canonical.indicator.session" #define BUS_PATH "/com/canonical/indicator/session" #define ICON_DEFAULT "system-devices-panel" diff --git a/tests/test-service.cc b/tests/test-service.cc index 058fc3d..76dcd75 100644 --- a/tests/test-service.cc +++ b/tests/test-service.cc @@ -170,7 +170,7 @@ class ServiceTest: public GTestDBusFixture // wait for the service to show up on the bus const guint watch_id = g_bus_watch_name_on_connection (conn, - "com.canonical.indicator.session-test", + "com.canonical.indicator.session", G_BUS_NAME_WATCHER_FLAGS_NONE, on_name_appeared, // quits the loop NULL, this, NULL); @@ -182,10 +182,10 @@ class ServiceTest: public GTestDBusFixture // get the actions & menus that the service exported. action_group = g_dbus_action_group_get (conn, - "com.canonical.indicator.session-test", + "com.canonical.indicator.session", "/com/canonical/indicator/session"); menu_model = g_dbus_menu_model_get (conn, - "com.canonical.indicator.session-test", + "com.canonical.indicator.session", "/com/canonical/indicator/session/desktop"); // the actions are added asynchronously, so wait for the actions if (!g_action_group_has_action (G_ACTION_GROUP(action_group), "about")) -- cgit v1.2.3 From fab2853f35eb108988b5ddb16cd9f6e43de79773 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 20 Jun 2013 13:54:41 -0500 Subject: remove the --replace command-line argument and property as we're using upstart for that --- src/main.c | 42 +++++------------------------------------- src/service.c | 41 +++-------------------------------------- src/service.h | 2 +- tests/test-service.cc | 7 +------ 4 files changed, 10 insertions(+), 82 deletions(-) (limited to 'src/service.c') diff --git a/src/main.c b/src/main.c index 4511fce..8df5e60 100644 --- a/src/main.c +++ b/src/main.c @@ -29,46 +29,16 @@ **** ***/ -static gboolean replace = FALSE; - -static void -parse_command_line (int * argc, char *** argv) -{ - GError * error; - GOptionContext * option_context; - - static GOptionEntry entries[] = - { - { "replace", 'r', 0, G_OPTION_ARG_NONE, &replace, "Replace the currently-running service", NULL }, - { NULL } - }; - - error = NULL; - option_context = g_option_context_new ("- indicator-session service"); - g_option_context_add_main_entries (option_context, entries, GETTEXT_PACKAGE); - if (!g_option_context_parse (option_context, argc, argv, &error)) - { - g_print ("option parsing failed: %s\n", error->message); - g_error_free (error); - exit (EXIT_FAILURE); - } - - g_option_context_free (option_context); -} - -/*** -**** -***/ - static void on_name_lost (gpointer instance, gpointer loop) { - g_debug ("exiting: service couldn't acquire or lost ownership of busname"); - g_main_loop_quit ((GMainLoop*)loop); + g_warning ("exiting: service couldn't acquire, or lost ownership of, busname"); + + g_main_loop_quit (loop); } int -main (int argc, char ** argv) +main (int argc G_GNUC_UNUSED, char ** argv G_GNUC_UNUSED) { GMainLoop * loop; IndicatorSessionService * service; @@ -78,10 +48,8 @@ main (int argc, char ** argv) bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR); textdomain (GETTEXT_PACKAGE); - parse_command_line (&argc, &argv); - /* run */ - service = indicator_session_service_new (replace); + service = indicator_session_service_new (); loop = g_main_loop_new (NULL, FALSE); g_signal_connect (service, INDICATOR_SESSION_SERVICE_SIGNAL_NAME_LOST, G_CALLBACK(on_name_lost), loop); diff --git a/src/service.c b/src/service.c index 862028b..83bfeaa 100644 --- a/src/service.c +++ b/src/service.c @@ -46,7 +46,6 @@ static guint signals[LAST_SIGNAL] = { 0 }; enum { PROP_0, - PROP_REPLACE, PROP_MAX_USERS, PROP_LAST }; @@ -106,8 +105,6 @@ struct _IndicatorSessionServicePrivate int rebuild_flags; GDBusConnection * conn; GCancellable * cancellable; - - gboolean replace; }; typedef IndicatorSessionServicePrivate priv_t; @@ -1013,23 +1010,10 @@ indicator_session_service_init (IndicatorSessionService * self) gp = p->keybinding_settings; g_signal_connect_swapped (gp, "changed::screensaver", G_CALLBACK(rebuild_switch_section_soon), self); -} - -static void -my_constructed (GObject * o) -{ - GBusNameOwnerFlags owner_flags; - IndicatorSessionService * self = INDICATOR_SESSION_SERVICE(o); - - /* own the name in constructed() instead of init() so that - we'll know the value of the 'replace' property */ - owner_flags = G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT; - if (self->priv->replace) - owner_flags |= G_BUS_NAME_OWNER_FLAGS_REPLACE; self->priv->own_id = g_bus_own_name (G_BUS_TYPE_SESSION, BUS_NAME, - owner_flags, + G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT, on_bus_acquired, NULL, on_name_lost, @@ -1051,10 +1035,6 @@ my_get_property (GObject * o, switch (property_id) { - case PROP_REPLACE: - g_value_set_boolean (value, self->priv->replace); - break; - case PROP_MAX_USERS: g_value_set_uint (value, self->priv->max_users); break; @@ -1074,10 +1054,6 @@ my_set_property (GObject * o, switch (property_id) { - case PROP_REPLACE: - self->priv->replace = g_value_get_boolean (value); - break; - case PROP_MAX_USERS: self->priv->max_users = g_value_get_uint (value); rebuild_switch_section_soon (self); @@ -1145,7 +1121,6 @@ indicator_session_service_class_init (IndicatorSessionServiceClass * klass) GObjectClass * object_class = G_OBJECT_CLASS (klass); object_class->dispose = my_dispose; - object_class->constructed = my_constructed; object_class->get_property = my_get_property; object_class->set_property = my_set_property; @@ -1161,14 +1136,6 @@ indicator_session_service_class_init (IndicatorSessionServiceClass * klass) properties[PROP_0] = NULL; - properties[PROP_REPLACE] = g_param_spec_boolean ("replace", - "Replace Service", - "Replace existing service", - FALSE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - properties[PROP_MAX_USERS] = g_param_spec_uint ("max-users", "Max Users", "Max visible users", @@ -1181,11 +1148,9 @@ indicator_session_service_class_init (IndicatorSessionServiceClass * klass) } IndicatorSessionService * -indicator_session_service_new (gboolean replace) +indicator_session_service_new (void) { - GObject * o = g_object_new (INDICATOR_TYPE_SESSION_SERVICE, - "replace", replace, - NULL); + GObject * o = g_object_new (INDICATOR_TYPE_SESSION_SERVICE, NULL); return INDICATOR_SESSION_SERVICE (o); } diff --git a/src/service.h b/src/service.h index 3fad6bf..fa870e5 100644 --- a/src/service.h +++ b/src/service.h @@ -64,7 +64,7 @@ struct _IndicatorSessionServiceClass GType indicator_session_service_get_type (void); -IndicatorSessionService * indicator_session_service_new (gboolean replace); +IndicatorSessionService * indicator_session_service_new (void); G_END_DECLS diff --git a/tests/test-service.cc b/tests/test-service.cc index 76dcd75..57b4221 100644 --- a/tests/test-service.cc +++ b/tests/test-service.cc @@ -161,12 +161,7 @@ class ServiceTest: public GTestDBusFixture // Start an IndicatorSessionService and wait for it to appear on the bus. // This way our calls to g_dbus_*_get() in the next paragraph won't activate // a second copy of the service... - service = indicator_session_service_new (true); - - // confirm that the property got set - gboolean replace = FALSE; - g_object_get (service, "replace", &replace, NULL); - ASSERT_TRUE (replace); + service = indicator_session_service_new (); // wait for the service to show up on the bus const guint watch_id = g_bus_watch_name_on_connection (conn, -- cgit v1.2.3 From f6ab8644d81f403b0264e126e9631a00dd578418 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sun, 23 Jun 2013 18:26:25 -0500 Subject: add icon support to user menuitems --- src/service.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/service.c') diff --git a/src/service.c b/src/service.c index 4a62bd1..ede3a9f 100644 --- a/src/service.c +++ b/src/service.c @@ -498,6 +498,16 @@ create_switch_section (IndicatorSessionService * self) item = g_menu_item_new (u->real_name, 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"); + + if (u->icon_file != NULL) + { + GFile * file = g_file_new_for_path (u->icon_file); + GIcon * icon = g_file_icon_new (file); + g_menu_item_set_attribute_value (item, G_MENU_ATTRIBUTE_ICON, g_icon_serialize (icon)); + g_clear_object (&icon); + g_clear_object (&file); + } + g_menu_append_item (menu, item); g_object_unref (item); } -- cgit v1.2.3 From eb6abe95552df3aa95f6a263cac3b79462c797ae Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 24 Jun 2013 17:05:27 -0500 Subject: use login1's terminology 'power off', 'reboot' --- src/actions.c | 12 ++++++------ src/actions.h | 8 ++++---- src/service.c | 24 ++++++++++++------------ 3 files changed, 22 insertions(+), 22 deletions(-) (limited to 'src/service.c') diff --git a/src/actions.c b/src/actions.c index 788f418..babc285 100644 --- a/src/actions.c +++ b/src/actions.c @@ -103,8 +103,8 @@ indicator_session_actions_class_init (IndicatorSessionActionsClass * klass) klass->logout = NULL; klass->suspend = NULL; klass->hibernate = NULL; - klass->restart = NULL; - klass->shutdown = NULL; + klass->reboot = NULL; + klass->power_off = NULL; klass->switch_to_screensaver = NULL; klass->switch_to_greeter = NULL; klass->switch_to_guest = NULL; @@ -246,11 +246,11 @@ indicator_session_actions_logout (IndicatorSessionActions * self) } void -indicator_session_actions_shutdown (IndicatorSessionActions * self) +indicator_session_actions_power_off (IndicatorSessionActions * self) { g_return_if_fail (INDICATOR_IS_SESSION_ACTIONS (self)); - INDICATOR_SESSION_ACTIONS_GET_CLASS (self)->shutdown (self); + INDICATOR_SESSION_ACTIONS_GET_CLASS (self)->power_off (self); } void @@ -270,11 +270,11 @@ indicator_session_actions_about (IndicatorSessionActions * self) } void -indicator_session_actions_restart (IndicatorSessionActions * self) +indicator_session_actions_reboot (IndicatorSessionActions * self) { g_return_if_fail (INDICATOR_IS_SESSION_ACTIONS (self)); - INDICATOR_SESSION_ACTIONS_GET_CLASS (self)->restart (self); + INDICATOR_SESSION_ACTIONS_GET_CLASS (self)->reboot (self); } void diff --git a/src/actions.h b/src/actions.h index e0d0ec5..bba6045 100644 --- a/src/actions.h +++ b/src/actions.h @@ -71,8 +71,8 @@ struct _IndicatorSessionActionsClass void (*suspend) (IndicatorSessionActions * self); void (*hibernate) (IndicatorSessionActions * self); void (*logout) (IndicatorSessionActions * self); - void (*restart) (IndicatorSessionActions * self); - void (*shutdown) (IndicatorSessionActions * self); + void (*reboot) (IndicatorSessionActions * self); + void (*power_off) (IndicatorSessionActions * self); void (*help) (IndicatorSessionActions * self); void (*about) (IndicatorSessionActions * self); void (*settings) (IndicatorSessionActions * self); @@ -111,8 +111,8 @@ void indicator_session_actions_lock (IndicatorSession void indicator_session_actions_suspend (IndicatorSessionActions * self); void indicator_session_actions_hibernate (IndicatorSessionActions * self); void indicator_session_actions_logout (IndicatorSessionActions * self); -void indicator_session_actions_restart (IndicatorSessionActions * self); -void indicator_session_actions_shutdown (IndicatorSessionActions * self); +void indicator_session_actions_reboot (IndicatorSessionActions * self); +void indicator_session_actions_power_off (IndicatorSessionActions * self); void indicator_session_actions_help (IndicatorSessionActions * self); void indicator_session_actions_about (IndicatorSessionActions * self); diff --git a/src/service.c b/src/service.c index ede3a9f..e41cca6 100644 --- a/src/service.c +++ b/src/service.c @@ -542,13 +542,13 @@ create_session_section (IndicatorSessionService * self) if (!g_settings_get_boolean (s, "suppress-restart-menuitem")) { const char * label = ellipsis ? _("Restart\342\200\246") : _("Restart"); - g_menu_append (menu, label, "indicator.restart"); + g_menu_append (menu, label, "indicator.reboot"); } if (!g_settings_get_boolean (s, "suppress-shutdown-menuitem")) { const char * label = ellipsis ? _("Shutdown\342\200\246") : _("Shutdown"); - g_menu_append (menu, label, "indicator.shutdown"); + g_menu_append (menu, label, "indicator.power-off"); } return G_MENU_MODEL (menu); @@ -661,19 +661,19 @@ on_hibernate_activated (GSimpleAction * a G_GNUC_UNUSED, } static void -on_restart_activated (GSimpleAction * action G_GNUC_UNUSED, - GVariant * param G_GNUC_UNUSED, - gpointer gself) +on_reboot_activated (GSimpleAction * action G_GNUC_UNUSED, + GVariant * param G_GNUC_UNUSED, + gpointer gself) { - indicator_session_actions_restart (get_backend_actions(gself)); + indicator_session_actions_reboot (get_backend_actions(gself)); } static void -on_shutdown_activated (GSimpleAction * a G_GNUC_UNUSED, - GVariant * param G_GNUC_UNUSED, - gpointer gself) +on_power_off_activated (GSimpleAction * a G_GNUC_UNUSED, + GVariant * param G_GNUC_UNUSED, + gpointer gself) { - indicator_session_actions_shutdown (get_backend_actions(gself)); + indicator_session_actions_power_off (get_backend_actions(gself)); } static void @@ -724,8 +724,8 @@ init_gactions (IndicatorSessionService * self) { "logout", on_logout_activated }, { "suspend", on_suspend_activated }, { "hibernate", on_hibernate_activated }, - { "restart", on_restart_activated }, - { "shutdown", on_shutdown_activated }, + { "reboot", on_reboot_activated }, + { "power-off", on_power_off_activated }, { "switch-to-screensaver", on_screensaver_activated }, { "switch-to-greeter", on_greeter_activated } }; -- cgit v1.2.3 From b3938a1f14b687d62ad1d6e4e27bac47f58722de Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 25 Jun 2013 11:16:34 -0500 Subject: in IndicatorSessionUsers, use the uid as the user's key. Users.ActivateUser is now green. --- src/backend-dbus/users.c | 73 +++++++++---------------- src/service.c | 40 +++++++------- src/users.c | 38 ++++++------- src/users.h | 30 +++++------ tests/CMakeLists.txt | 4 +- tests/backend-dbus/test-users.cc | 114 +++++++++++++++++++-------------------- tests/backend-mock-users.c | 52 +++++++----------- tests/backend-mock-users.h | 3 +- tests/test-service.cc | 43 +++++++-------- 9 files changed, 178 insertions(+), 219 deletions(-) (limited to 'src/service.c') diff --git a/src/backend-dbus/users.c b/src/backend-dbus/users.c index c135610..48de06c 100644 --- a/src/backend-dbus/users.c +++ b/src/backend-dbus/users.c @@ -53,33 +53,22 @@ G_DEFINE_TYPE (IndicatorSessionUsersDbus, **** ***/ -static const gchar * -get_public_key_for_uid (guint uid) -{ - static char buf[16]; - g_snprintf (buf, sizeof(buf), "%u", uid); - return buf; -} - static void emit_user_added (IndicatorSessionUsersDbus * self, guint uid) { - const gchar * const public_key = get_public_key_for_uid (uid); - indicator_session_users_added (INDICATOR_SESSION_USERS(self), public_key); + indicator_session_users_added (INDICATOR_SESSION_USERS(self), uid); } static void emit_user_changed (IndicatorSessionUsersDbus * self, guint uid) { - const gchar * const public_key = get_public_key_for_uid (uid); - indicator_session_users_changed (INDICATOR_SESSION_USERS(self), public_key); + indicator_session_users_changed (INDICATOR_SESSION_USERS(self), uid); } static void emit_user_removed (IndicatorSessionUsersDbus * self, guint uid) { - const gchar * const public_key = get_public_key_for_uid (uid); - indicator_session_users_removed (INDICATOR_SESSION_USERS(self), public_key); + indicator_session_users_removed (INDICATOR_SESSION_USERS(self), uid); } /*** @@ -124,22 +113,22 @@ static void set_logins (IndicatorSessionUsersDbus * self, GHashTable * logins) { GHashTable * old_logins = self->priv->logins; - gpointer key; + gpointer uid; GHashTableIter iter; self->priv->logins = logins; /* fire 'user changed' event for users who logged out */ g_hash_table_iter_init (&iter, old_logins); - while ((g_hash_table_iter_next (&iter, &key, NULL))) - if (!g_hash_table_contains (logins, key)) - emit_user_changed (self, GPOINTER_TO_INT(key)); + while ((g_hash_table_iter_next (&iter, &uid, NULL))) + if (!g_hash_table_contains (logins, uid)) + emit_user_changed (self, GPOINTER_TO_UINT(uid)); /* fire 'user changed' event for users who logged in */ g_hash_table_iter_init (&iter, logins); - while ((g_hash_table_iter_next (&iter, &key, NULL))) - if (!g_hash_table_contains (old_logins, key)) - emit_user_changed (self, GPOINTER_TO_INT(key)); + while ((g_hash_table_iter_next (&iter, &uid, NULL))) + if (!g_hash_table_contains (old_logins, uid)) + emit_user_changed (self, GPOINTER_TO_UINT(uid)); g_hash_table_destroy (old_logins); } @@ -205,12 +194,6 @@ get_user_for_uid (IndicatorSessionUsersDbus * self, guint uid) return g_hash_table_lookup (p->uid_to_account, GUINT_TO_POINTER(uid)); } -static AccountsUser * -get_user_for_public_key (IndicatorSessionUsersDbus * self, const char * public_key) -{ - return get_user_for_uid (self, g_ascii_strtoull (public_key, NULL, 10)); -} - /*** **** User Account Tracking ***/ @@ -520,19 +503,19 @@ set_display_manager_seat (IndicatorSessionUsersDbus * self, /* switch to (or create) a session for the specified user */ static void -my_activate_user (IndicatorSessionUsers * users, const char * public_key) +my_activate_user (IndicatorSessionUsers * users, guint uid) { IndicatorSessionUsersDbus * self = INDICATOR_SESSION_USERS_DBUS(users); priv_t * p = self->priv; AccountsUser * au; const char * username; - au = get_user_for_public_key (self, public_key); + au = get_user_for_uid (self, uid); username = au ? accounts_user_get_user_name (au) : NULL; if (!username) { - g_warning ("%s %s can't find user for '%s'", G_STRLOC, G_STRFUNC, public_key); + g_warning ("%s %s can't find user '%u'", G_STRLOC, G_STRFUNC, uid); } else { @@ -556,36 +539,31 @@ my_is_live_session (IndicatorSessionUsers * users) return INDICATOR_SESSION_USERS_DBUS(users)->priv->is_live; } -/* get a list of public keys for the users that we know about */ -static GStrv -my_get_keys (IndicatorSessionUsers * users) +/* get a list of our user ids */ +static GList * +my_get_uids (IndicatorSessionUsers * users) { - int i; priv_t * p; - gchar ** keys; + GList * uids; GHashTableIter iter; gpointer uid; gpointer user; - GHashTable * h; g_return_val_if_fail (INDICATOR_IS_SESSION_USERS_DBUS(users), NULL); p = INDICATOR_SESSION_USERS_DBUS (users)->priv; - i = 0; - h = p->uid_to_account; - keys = g_new (gchar*, g_hash_table_size(h)+1); - g_hash_table_iter_init (&iter, h); + uids = NULL; + g_hash_table_iter_init (&iter, p->uid_to_account); while (g_hash_table_iter_next (&iter, &uid, &user)) if (!accounts_user_get_system_account (user)) - keys[i++] = g_strdup (get_public_key_for_uid ((guint)uid)); - keys[i] = NULL; + uids = g_list_prepend (uids, uid); - return keys; + return uids; } /* build a new struct populated with info on the specified user */ static IndicatorSessionUser * -my_get_user (IndicatorSessionUsers * users, const gchar * public_key) +my_get_user (IndicatorSessionUsers * users, guint uid) { IndicatorSessionUsersDbus * self = INDICATOR_SESSION_USERS_DBUS (users); priv_t * p = self->priv; @@ -593,11 +571,10 @@ my_get_user (IndicatorSessionUsers * users, const gchar * public_key) AccountsUser * au; ret = NULL; - au = get_user_for_public_key (self, public_key); - + au = get_user_for_uid (self, uid); if (au && !accounts_user_get_system_account(au)) { - const guint uid = accounts_user_get_uid (au); + g_assert (uid == accounts_user_get_uid (au)); ret = g_new0 (IndicatorSessionUser, 1); ret->uid = uid; @@ -662,7 +639,7 @@ indicator_session_users_dbus_class_init (IndicatorSessionUsersDbusClass * klass) users_class = INDICATOR_SESSION_USERS_CLASS (klass); users_class->is_live_session = my_is_live_session; - users_class->get_keys = my_get_keys; + users_class->get_uids = my_get_uids; users_class->get_user = my_get_user; users_class->activate_user = my_activate_user; diff --git a/src/service.c b/src/service.c index e41cca6..1fcbd07 100644 --- a/src/service.c +++ b/src/service.c @@ -206,13 +206,13 @@ update_header_action (IndicatorSessionService * self) static GMenuModel * create_switch_section (IndicatorSessionService * self); static void -add_user (IndicatorSessionService * self, const gchar * key) +add_user (IndicatorSessionService * self, guint uid) { IndicatorSessionUser * u; /* update our user table */ - u = indicator_session_users_get_user (self->priv->backend_users, key); - g_hash_table_insert (self->priv->users, g_strdup(key), u); + u = indicator_session_users_get_user (self->priv->backend_users, uid); + g_hash_table_insert (self->priv->users, GUINT_TO_POINTER(uid), u); /* enqueue rebuilds for the affected sections */ rebuild_switch_section_soon (self); @@ -222,30 +222,30 @@ add_user (IndicatorSessionService * self, const gchar * key) static void on_user_added (IndicatorSessionUsers * backend_users G_GNUC_UNUSED, - const char * key, + guint uid, gpointer gself) { - add_user (INDICATOR_SESSION_SERVICE(gself), key); + add_user (INDICATOR_SESSION_SERVICE(gself), uid); } static void on_user_changed (IndicatorSessionUsers * backend_users G_GNUC_UNUSED, - const char * key, + guint uid, gpointer gself) { - add_user (INDICATOR_SESSION_SERVICE(gself), key); + add_user (INDICATOR_SESSION_SERVICE(gself), uid); } static void on_user_removed (IndicatorSessionUsers * backend_users G_GNUC_UNUSED, - const char * key, + guint uid, gpointer gself) { IndicatorSessionService * self = INDICATOR_SESSION_SERVICE (gself); g_return_if_fail (self != NULL); /* update our user table */ - g_hash_table_remove (self->priv->users, key); + g_hash_table_remove (self->priv->users, GUINT_TO_POINTER(uid)); /* enqueue rebuilds for the affected sections */ rebuild_switch_section_soon (self); @@ -334,13 +334,13 @@ create_user_switcher_state (IndicatorSessionService * self) GVariantBuilder * b; GVariant * val; GHashTableIter ht_iter; - gpointer ht_key, ht_value; + gpointer ht_value; const char * current_user; current_user = ""; a = g_variant_builder_new (G_VARIANT_TYPE("as")); g_hash_table_iter_init (&ht_iter, self->priv->users); - while (g_hash_table_iter_next (&ht_iter, &ht_key, &ht_value)) + while (g_hash_table_iter_next (&ht_iter, NULL, &ht_value)) { const IndicatorSessionUser * u = ht_value; @@ -950,8 +950,8 @@ static void /* cppcheck-suppress unusedFunction */ indicator_session_service_init (IndicatorSessionService * self) { - int i; - GStrv keys; + GList * l; + GList * uids; priv_t * p; gpointer gp; @@ -970,14 +970,14 @@ indicator_session_service_init (IndicatorSessionService * self) &p->backend_guest); /* init our key-to-User table */ - p->users = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, + p->users = g_hash_table_new_full (g_direct_hash, + g_direct_equal, + NULL, (GDestroyNotify)indicator_session_user_free); - keys = indicator_session_users_get_keys (p->backend_users); - for (i=0; keys && keys[i]; ++i) - add_user (self, keys[i]); - g_strfreev (keys); + 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); init_gactions (self); diff --git a/src/users.c b/src/users.c index 4b9c0ad..5e4d910 100644 --- a/src/users.c +++ b/src/users.c @@ -75,24 +75,24 @@ indicator_session_users_class_init (IndicatorSessionUsersClass * klass) G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (IndicatorSessionUsersClass, user_added), NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); + g_cclosure_marshal_VOID__UINT, + G_TYPE_NONE, 1, G_TYPE_UINT); signals[USER_REMOVED] = g_signal_new (INDICATOR_SESSION_USERS_SIGNAL_USER_REMOVED, G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (IndicatorSessionUsersClass, user_removed), NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); + g_cclosure_marshal_VOID__UINT, + G_TYPE_NONE, 1, G_TYPE_UINT); signals[USER_CHANGED] = g_signal_new (INDICATOR_SESSION_USERS_SIGNAL_USER_CHANGED, G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (IndicatorSessionUsersClass, user_changed), NULL, NULL, - g_cclosure_marshal_VOID__STRING, - G_TYPE_NONE, 1, G_TYPE_STRING); + g_cclosure_marshal_VOID__UINT, + G_TYPE_NONE, 1, G_TYPE_UINT); properties[PROP_IS_LIVE_SESSION] = @@ -115,30 +115,30 @@ indicator_session_users_init (IndicatorSessionUsers * self G_GNUC_UNUSED) **** Virtual Functions ***/ -GStrv -indicator_session_users_get_keys (IndicatorSessionUsers * self) +GList * +indicator_session_users_get_uids (IndicatorSessionUsers * self) { g_return_val_if_fail (INDICATOR_IS_SESSION_USERS (self), NULL); - return INDICATOR_SESSION_USERS_GET_CLASS (self)->get_keys (self); + return INDICATOR_SESSION_USERS_GET_CLASS (self)->get_uids (self); } IndicatorSessionUser * indicator_session_users_get_user (IndicatorSessionUsers * self, - const char * key) + guint uid) { g_return_val_if_fail (INDICATOR_IS_SESSION_USERS (self), NULL); - return INDICATOR_SESSION_USERS_GET_CLASS (self)->get_user (self, key); + return INDICATOR_SESSION_USERS_GET_CLASS (self)->get_user (self, uid); } void indicator_session_users_activate_user (IndicatorSessionUsers * self, - const char * key) + guint uid) { g_return_if_fail (INDICATOR_IS_SESSION_USERS (self)); - INDICATOR_SESSION_USERS_GET_CLASS (self)->activate_user (self, key); + INDICATOR_SESSION_USERS_GET_CLASS (self)->activate_user (self, uid); } gboolean @@ -165,27 +165,27 @@ indicator_session_user_free (IndicatorSessionUser * user) ***/ void -indicator_session_users_added (IndicatorSessionUsers * self, const char * key) +indicator_session_users_added (IndicatorSessionUsers * self, guint uid) { g_return_if_fail (INDICATOR_IS_SESSION_USERS (self)); - g_signal_emit (self, signals[USER_ADDED], 0, key); + g_signal_emit (self, signals[USER_ADDED], 0, uid); } void -indicator_session_users_removed (IndicatorSessionUsers * self, const char * key) +indicator_session_users_removed (IndicatorSessionUsers * self, guint uid) { g_return_if_fail (INDICATOR_IS_SESSION_USERS (self)); - g_signal_emit (self, signals[USER_REMOVED], 0, key); + g_signal_emit (self, signals[USER_REMOVED], 0, uid); } void -indicator_session_users_changed (IndicatorSessionUsers * self, const char * key) +indicator_session_users_changed (IndicatorSessionUsers * self, guint uid) { g_return_if_fail (INDICATOR_IS_SESSION_USERS (self)); - g_signal_emit (self, signals[USER_CHANGED], 0, key); + g_signal_emit (self, signals[USER_CHANGED], 0, uid); } void diff --git a/src/users.h b/src/users.h index f2d7404..9871766 100644 --- a/src/users.h +++ b/src/users.h @@ -72,13 +72,13 @@ struct _IndicatorSessionUsersClass /* signals */ void (* user_added) (IndicatorSessionUsers * self, - const gchar * key); + guint uid); void (* user_removed) (IndicatorSessionUsers * self, - const gchar * key); + guint uid); void (* user_changed) (IndicatorSessionUsers * self, - const gchar * key); + guint uid); /* pure virtual functions */ @@ -86,13 +86,13 @@ struct _IndicatorSessionUsersClass gboolean (* is_live_session) (IndicatorSessionUsers * self); - GStrv (* get_keys) (IndicatorSessionUsers * self); + GList* (* get_uids) (IndicatorSessionUsers * self); IndicatorSessionUser * (* get_user) (IndicatorSessionUsers * self, - const gchar * key); + guint uid); void ( * activate_user) (IndicatorSessionUsers * self, - const gchar * key); + guint uid); }; /*** @@ -103,15 +103,15 @@ GType indicator_session_users_get_type (void); /* emits the "user-added" signal */ void indicator_session_users_added (IndicatorSessionUsers * self, - const gchar * key); + guint uid); /* emits the "user-removed" signal */ void indicator_session_users_removed (IndicatorSessionUsers * self, - const gchar * key); + guint uid); /* emits the "user-changed" signal */ void indicator_session_users_changed (IndicatorSessionUsers * self, - const gchar * key); + guint uid); /* notify listeners of a change to the 'is-live-session' property */ void indicator_session_users_notify_is_live_session (IndicatorSessionUsers * self); @@ -125,12 +125,12 @@ void indicator_session_users_notify_is_live_session (IndicatorSessionUsers * sel gboolean indicator_session_users_is_live_session (IndicatorSessionUsers * users); /** - * Get a list of user keys. + * Get a list of the users to show in the indicator * - * Return value: (transfer full): a NULL-terminated array of user keys. - * Free with g_strfreev() when done. + * Return value: (transfer container): a GList of guint user ids. + * Free with g_slist_free() when done. */ -GStrv indicator_session_users_get_keys (IndicatorSessionUsers * users); +GList * indicator_session_users_get_uids (IndicatorSessionUsers * users); /** * Get information about a particular user. @@ -141,14 +141,14 @@ GStrv indicator_session_users_get_keys (IndicatorSessionUsers * users); */ IndicatorSessionUser * indicator_session_users_get_user (IndicatorSessionUsers * users, - const gchar * key); + guint uid); /* frees a IndicatorSessionUser struct */ void indicator_session_user_free (IndicatorSessionUser * user); /* activate to a different session */ void indicator_session_users_activate_user (IndicatorSessionUsers * self, - const char * key); + guint uid); G_END_DECLS diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 45ab69f..f67008e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -39,13 +39,13 @@ add_library (backendmock STATIC backend-mock-guest.h backend-mock-users.c backend-mock-users.h) -set_target_properties (backendmock PROPERTIES COMPILE_FLAGS " ${CC_WARNING_ARGS}") +set_target_properties (backendmock PROPERTIES COMPILE_FLAGS " ${CC_WARNING_ARGS} -std=c++0x -g") # test-service add_executable (test-service test-service.cc gschemas.compiled) -set_target_properties (test-service PROPERTIES COMPILE_FLAGS " ${CC_WARNING_ARGS}") +set_target_properties (test-service PROPERTIES COMPILE_FLAGS " ${CC_WARNING_ARGS} -std=c++0x -g") add_test (test-service test-service) add_dependencies (test-service libindicatorsessionservice backendmock) target_link_libraries (test-service libindicatorsessionservice backendmock gtest ${SERVICE_LIBRARIES} ${GTEST_LIBS}) diff --git a/tests/backend-dbus/test-users.cc b/tests/backend-dbus/test-users.cc index d477a4f..279796e 100644 --- a/tests/backend-dbus/test-users.cc +++ b/tests/backend-dbus/test-users.cc @@ -74,10 +74,18 @@ class Users: public GTestMockDBusFixture ASSERT_EQ (user_state=="active", isu->is_current_user); } - void compare_user (const MockUser * mu, const std::string& key, const std::string& user_state) + void compare_user (const MockUser * mu, guint uid, const std::string& user_state) { IndicatorSessionUser * isu; - isu = indicator_session_users_get_user (users, key.c_str()); + isu = indicator_session_users_get_user (users, uid); + compare_user (mu, isu, user_state); + indicator_session_user_free (isu); + } + + void compare_user (guint uid, const std::string& user_state) + { + IndicatorSessionUser * isu = indicator_session_users_get_user (users, uid); + MockUser * mu = accounts->find_by_uid (uid); compare_user (mu, isu, user_state); indicator_session_user_free (isu); } @@ -99,12 +107,12 @@ class Users: public GTestMockDBusFixture static void wait_for_signals__event (IndicatorSessionUser * u G_GNUC_UNUSED, - const char * key, - gpointer gself) + guint uid, + gpointer gself) { Users * self = static_cast(gself); - self->event_keys.push_back (key); + self->event_keys.push_back (uid); if (self->event_keys.size() == self->expected_event_count) g_main_loop_quit (self->loop); @@ -112,7 +120,7 @@ class Users: public GTestMockDBusFixture protected: - std::vector event_keys; + std::vector event_keys; size_t expected_event_count; void wait_for_signals (gpointer o, const gchar * name, size_t n) @@ -150,19 +158,18 @@ TEST_F (Users, HelloWorld) */ TEST_F (Users, InitialUsers) { - GStrv keys = indicator_session_users_get_keys (users); + GList * l; + GList * uids = indicator_session_users_get_uids (users); - ASSERT_EQ (12, g_strv_length (keys)); + ASSERT_EQ (12, g_list_length (uids)); - for (int i=0; keys && keys[i]; ++i) + for (l=uids; l!=NULL; l=l->next) { - IndicatorSessionUser * isu = indicator_session_users_get_user (users, keys[i]); - MockUser * mu = accounts->find_by_uid (isu->uid); - compare_user (mu, isu, login1_seat->user_state (isu->uid)); - indicator_session_user_free (isu); + const guint uid = GPOINTER_TO_UINT (l->data); + compare_user (uid, login1_seat->user_state (uid)); } - g_strfreev (keys); + g_list_free (uids); } /** @@ -188,17 +195,10 @@ TEST_F (Users, UserRemoved) MockUser * mu = accounts->find_by_username ("pdavison"); /* confirm that users knows about pdavison */ - bool found = false; - GStrv keys = indicator_session_users_get_keys (users); - ASSERT_EQ (12, g_strv_length (keys)); - for (int i=0; !found && keys && keys[i]; i++) - { - IndicatorSessionUser * isu = indicator_session_users_get_user (users, keys[i]); - found = isu->uid == mu->uid(); - indicator_session_user_free (isu); - } - g_strfreev (keys); - ASSERT_TRUE (found); + IndicatorSessionUser * isu = indicator_session_users_get_user (users, mu->uid()); + ASSERT_TRUE (isu != NULL); + compare_user (mu, isu, "offline"); + g_clear_pointer (&isu, indicator_session_user_free); /* on the bus, remove pdavison. */ accounts->remove_user (mu); @@ -208,17 +208,14 @@ TEST_F (Users, UserRemoved) wait_for_signals (users, INDICATOR_SESSION_USERS_SIGNAL_USER_REMOVED, 1); ASSERT_EQ (1, event_keys.size()); - /* confirm that users doesn't know about pdavison */ - keys = indicator_session_users_get_keys (users); - ASSERT_EQ (11, g_strv_length (keys)); - for (int i=0; keys && keys[i]; i++) - { - IndicatorSessionUser * isu = indicator_session_users_get_user (users, keys[i]); - ASSERT_NE (event_keys[0], keys[i]); - ASSERT_NE (mu->uid(), isu->uid); - indicator_session_user_free (isu); - } - g_strfreev (keys); + /* confirm that users won't give us pdavison's info */ + isu = indicator_session_users_get_user (users, mu->uid()); + ASSERT_TRUE (isu == NULL); + + /* confirm that users won't give us pdavison's uid */ + GList * uids = indicator_session_users_get_uids (users); + ASSERT_TRUE (g_list_find (uids, GUINT_TO_POINTER(mu->uid())) == NULL); + g_list_free (uids); delete mu; } @@ -296,43 +293,42 @@ TEST_F (Users, ActivateSession) compare_user (msmith, event_keys[1], "active"); } -#if 0 /** * Confirm that we can change the active session via users' API. * This is nearly the same as ActivateSession but uses users' API */ TEST_F (Users, ActivateUser) { - // The fist doctor logs in. - // Confirm that 'users' notices. - MockUser * mu = accounts->find_by_username ("whartnell"); - compare_user (mu->path(), mu, false, false); - MockConsoleKitSession * session = ck_seat->add_session_by_user (mu); + // confirm preconditions: msmith is active, msmith is offline + MockUser * const whartnell = accounts->find_by_username ("whartnell"); + ASSERT_EQ (login1_seat->user_state (whartnell->uid()), "offline"); + MockUser * const msmith = accounts->find_by_username ("msmith"); + ASSERT_EQ (login1_seat->user_state (msmith->uid()), "active"); + + // whartnell logs in... confirm that 'users' notices + login1_manager->add_session (login1_seat, whartnell); wait_for_signals (users, INDICATOR_SESSION_USERS_SIGNAL_USER_CHANGED, 1); - ASSERT_STREQ (mu->path(), event_keys[0].c_str()); - compare_user (mu->path(), mu, true, false); + ASSERT_EQ (1, event_keys.size()); + compare_user (whartnell, event_keys[0], "online"); - // activate the first doctor's session. - // confirm that 'users' sees he's active and that ck_session isn't. - // this should come in the form of two 'user-changed' events - indicator_session_users_activate_user (users, mu->path()); - ck_seat->activate_session (session); + // activate whartnell's session... confirm that 'users' sees: + // 1. msmith changes from 'active' to 'online' + // 2. whartnell changes from 'online' to 'active' + indicator_session_users_activate_user (users, whartnell->uid()); wait_for_signals (users, INDICATOR_SESSION_USERS_SIGNAL_USER_CHANGED, 2); ASSERT_EQ (2, event_keys.size()); - compare_user (event_keys[0], ck_session->user(), true, false); - compare_user (event_keys[1], mu, true, true); - - // switch back to the previous - // confirm that 'users' sees it's active and the first doctor's session isn't - // this should come in the form of two 'user-changed' events - indicator_session_users_activate_user (users, ck_session->user()->path()); - ck_seat->activate_session (ck_session); + compare_user (msmith, event_keys[0], "online"); + compare_user (whartnell, event_keys[1], "active"); + + // reverse the test + indicator_session_users_activate_user (users, msmith->uid()); wait_for_signals (users, INDICATOR_SESSION_USERS_SIGNAL_USER_CHANGED, 2); ASSERT_EQ (2, event_keys.size()); - compare_user (event_keys[0], mu, true, false); - compare_user (event_keys[1], ck_session->user(), true, true); + compare_user (whartnell, event_keys[0], "online"); + compare_user (msmith, event_keys[1], "active"); } +#if 0 /** * Confirm that adding a Guest doesn't show up in the users list */ diff --git a/tests/backend-mock-users.c b/tests/backend-mock-users.c index d9ab5a8..bae40b6 100644 --- a/tests/backend-mock-users.c +++ b/tests/backend-mock-users.c @@ -58,35 +58,21 @@ my_is_live_session (IndicatorSessionUsers * users G_GNUC_UNUSED) } static void -my_activate_user (IndicatorSessionUsers * users, const char * key) +my_activate_user (IndicatorSessionUsers * users, guint uid) { - g_message ("%s %s users %p key %s FIXME", G_STRLOC, G_STRFUNC, (void*)users, key); + g_message ("%s %s users %p uid %u FIXME", G_STRLOC, G_STRFUNC, (void*)users, uid); } -static GStrv -my_get_keys (IndicatorSessionUsers * users) +static GList * +my_get_uids (IndicatorSessionUsers * users) { - int i; - priv_t * p; - gchar ** keys; - GHashTableIter iter; - gpointer key; - g_return_val_if_fail (INDICATOR_IS_SESSION_USERS_MOCK(users), NULL); - p = INDICATOR_SESSION_USERS_MOCK (users)->priv; - - i = 0; - keys = g_new (gchar*, g_hash_table_size(p->users)+1); - g_hash_table_iter_init (&iter, p->users); - while (g_hash_table_iter_next (&iter, &key, NULL)) - keys[i++] = g_strdup (key); - keys[i] = NULL; - return keys; + return g_hash_table_get_keys (INDICATOR_SESSION_USERS_MOCK(users)->priv->users); } static IndicatorSessionUser * -my_get_user (IndicatorSessionUsers * self, const gchar * key) +my_get_user (IndicatorSessionUsers * self, guint uid) { priv_t * p; const IndicatorSessionUser * src; @@ -95,7 +81,7 @@ my_get_user (IndicatorSessionUsers * self, const gchar * key) g_return_val_if_fail (INDICATOR_IS_SESSION_USERS_MOCK(self), NULL); p = INDICATOR_SESSION_USERS_MOCK (self)->priv; - if ((src = g_hash_table_lookup (p->users, key))) + if ((src = g_hash_table_lookup (p->users, GUINT_TO_POINTER(uid)))) { ret = g_new0 (IndicatorSessionUser, 1); ret->is_current_user = src->is_current_user; @@ -123,7 +109,7 @@ indicator_session_users_mock_class_init (IndicatorSessionUsersMockClass * klass) users_class = INDICATOR_SESSION_USERS_CLASS (klass); users_class->is_live_session = my_is_live_session; - users_class->get_keys = my_get_keys; + users_class->get_uids = my_get_uids; users_class->get_user = my_get_user; users_class->activate_user = my_activate_user; @@ -141,9 +127,9 @@ indicator_session_users_mock_init (IndicatorSessionUsersMock * self) IndicatorSessionUsersMockPriv); self->priv = p; - p->users = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, + p->users = g_hash_table_new_full (g_direct_hash, + g_direct_equal, + NULL, (GDestroyNotify)indicator_session_user_free); g_signal_connect_swapped (mock_settings, "changed::is-live-session", @@ -165,25 +151,25 @@ indicator_session_users_mock_new (void) void indicator_session_users_mock_add_user (IndicatorSessionUsersMock * self, - const char * key, IndicatorSessionUser * user) { g_return_if_fail (INDICATOR_IS_SESSION_USERS_MOCK (self)); - g_return_if_fail (key && *key); g_return_if_fail (user != NULL); + g_return_if_fail (user->uid > 0); + g_return_if_fail (!g_hash_table_contains (self->priv->users, GUINT_TO_POINTER(user->uid))); - g_hash_table_insert (self->priv->users, g_strdup(key), user); - indicator_session_users_added (INDICATOR_SESSION_USERS (self), key); + g_hash_table_insert (self->priv->users, GUINT_TO_POINTER(user->uid), user); + indicator_session_users_added (INDICATOR_SESSION_USERS (self), user->uid); } void indicator_session_users_mock_remove_user (IndicatorSessionUsersMock * self, - const char * key) + guint uid) { g_return_if_fail (INDICATOR_IS_SESSION_USERS_MOCK (self)); - g_return_if_fail (key && *key); + g_return_if_fail (uid > 0); - g_hash_table_remove (self->priv->users, key); - indicator_session_users_removed (INDICATOR_SESSION_USERS (self), key); + g_hash_table_remove (self->priv->users, GUINT_TO_POINTER(uid)); + indicator_session_users_removed (INDICATOR_SESSION_USERS (self), uid); } diff --git a/tests/backend-mock-users.h b/tests/backend-mock-users.h index c7e11d3..7470ec9 100644 --- a/tests/backend-mock-users.h +++ b/tests/backend-mock-users.h @@ -57,11 +57,10 @@ GType indicator_session_users_mock_get_type (void); IndicatorSessionUsers * indicator_session_users_mock_new (void); void indicator_session_users_mock_add_user (IndicatorSessionUsersMock * self, - const char * key, IndicatorSessionUser * user); void indicator_session_users_mock_remove_user (IndicatorSessionUsersMock * self, - const char * key); + guint uid); diff --git a/tests/test-service.cc b/tests/test-service.cc index 2d81441..996332d 100644 --- a/tests/test-service.cc +++ b/tests/test-service.cc @@ -619,23 +619,24 @@ TEST_F (ServiceTest, User) const char * const error_key = "has-online-account-error"; const char * const show_name_key = "show-real-name-on-panel"; - const struct { + struct { + guint uid; guint64 login_frequency; const gchar * user_name; const gchar * real_name; } account_info[] = { - { 134, "whartnell", "First Doctor" }, - { 119, "ptroughton", "Second Doctor" }, - { 128, "jpertwee", "Third Doctor" }, - { 172, "tbaker", "Fourth Doctor" }, - { 69, "pdavison", "Fifth Doctor" }, - { 31, "cbaker", "Sixth Doctor" }, - { 42, "smccoy", "Seventh Doctor" }, - { 1, "pmcgann", "Eigth Doctor" }, - { 13, "ceccleston", "Ninth Doctor" }, - { 47, "dtennant", "Tenth Doctor" }, - { 34, "msmith", "Eleventh Doctor" }, - { 1, "rhurndall", "First Doctor" } + { 101, 134, "whartnell", "First Doctor" }, + { 102, 119, "ptroughton", "Second Doctor" }, + { 103, 128, "jpertwee", "Third Doctor" }, + { 104, 172, "tbaker", "Fourth Doctor" }, + { 105, 69, "pdavison", "Fifth Doctor" }, + { 106, 31, "cbaker", "Sixth Doctor" }, + { 107, 42, "smccoy", "Seventh Doctor" }, + { 108, 1, "pmcgann", "Eigth Doctor" }, + { 109, 13, "ceccleston", "Ninth Doctor" }, + { 110, 47, "dtennant", "Tenth Doctor" }, + { 111, 34, "msmith", "Eleventh Doctor" }, + { 201, 1, "rhurndall", "First Doctor" } }; // Find the switcher menu model. @@ -656,11 +657,11 @@ TEST_F (ServiceTest, User) IndicatorSessionUser * u = g_new0 (IndicatorSessionUser, 1); u->is_current_user = false; u->is_logged_in = false; - u->uid = 101 + i; + u->uid = account_info[i].uid; u->login_frequency = account_info[i].login_frequency; u->user_name = g_strdup (account_info[i].user_name); u->real_name = g_strdup (account_info[i].real_name); - indicator_session_users_mock_add_user (INDICATOR_SESSION_USERS_MOCK(mock_users), u->user_name, u); + indicator_session_users_mock_add_user (INDICATOR_SESSION_USERS_MOCK(mock_users), u); users[i] = u; } @@ -679,8 +680,8 @@ TEST_F (ServiceTest, User) g_clear_object (&switch_menu); // now remove a couple of 'em - indicator_session_users_mock_remove_user (INDICATOR_SESSION_USERS_MOCK(mock_users), account_info[3].user_name); - indicator_session_users_mock_remove_user (INDICATOR_SESSION_USERS_MOCK(mock_users), account_info[4].user_name); + indicator_session_users_mock_remove_user (INDICATOR_SESSION_USERS_MOCK(mock_users), account_info[3].uid); + indicator_session_users_mock_remove_user (INDICATOR_SESSION_USERS_MOCK(mock_users), account_info[4].uid); wait_for_menu_resync (); @@ -697,7 +698,7 @@ TEST_F (ServiceTest, User) // now let's have the third one be the current user users[2]->is_current_user = true; users[2]->is_logged_in = true; - indicator_session_users_changed (mock_users, users[2]->user_name); + indicator_session_users_changed (mock_users, users[2]->uid); wait_for_menu_resync (); @@ -749,14 +750,14 @@ TEST_F (ServiceTest, User) u->login_frequency = account_info[i].login_frequency; u->user_name = g_strdup (account_info[i].user_name); u->real_name = g_strdup (account_info[i].real_name); - indicator_session_users_mock_add_user (INDICATOR_SESSION_USERS_MOCK(mock_users), u->user_name, u); + indicator_session_users_mock_add_user (INDICATOR_SESSION_USERS_MOCK(mock_users), u); users[i] = u; } users[2]->is_current_user = false; - indicator_session_users_changed (mock_users, users[2]->user_name); + indicator_session_users_changed (mock_users, users[2]->uid); users[10]->is_current_user = true; users[10]->is_logged_in = true; - indicator_session_users_changed (mock_users, users[10]->user_name); + indicator_session_users_changed (mock_users, users[10]->uid); wait_for_menu_resync (); ASSERT_TRUE (find_menu_item_for_action ("indicator.switch-to-greeter", &switch_menu, &pos)); ASSERT_EQ (0, pos); -- cgit v1.2.3 From c23454157d46837d5cc6acd9cdd551c371819699 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 25 Jun 2013 14:12:19 -0500 Subject: sync text with trunk: make the shutdown menuitem read 'Shut Down' instead of 'Shutdown' --- src/service.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/service.c') diff --git a/src/service.c b/src/service.c index 1fcbd07..7f90c9c 100644 --- a/src/service.c +++ b/src/service.c @@ -547,7 +547,7 @@ create_session_section (IndicatorSessionService * self) if (!g_settings_get_boolean (s, "suppress-shutdown-menuitem")) { - const char * label = ellipsis ? _("Shutdown\342\200\246") : _("Shutdown"); + const char * label = ellipsis ? _("Shut Down\342\200\246") : _("Shut Down"); g_menu_append (menu, label, "indicator.power-off"); } -- cgit v1.2.3 From 951592e1349e863b721ca32273577e6f1b517d13 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 26 Jun 2013 11:40:14 -0500 Subject: fix regression that displayed the 'restart' button even when prompting was enabled and the user was running Unity --- TODO | 2 +- src/service.c | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src/service.c') diff --git a/TODO b/TODO index 93ca1a0..eab0f56 100644 --- a/TODO +++ b/TODO @@ -12,5 +12,5 @@ cmake x test schema installation bugs - - Suspend button should be hidden when shell is available + x Suspend button should be hidden when shell is available - J Random User is showing up when we switch sessions diff --git a/src/service.c b/src/service.c index 7f90c9c..d8fc961 100644 --- a/src/service.c +++ b/src/service.c @@ -539,7 +539,9 @@ create_session_section (IndicatorSessionService * self) if (indicator_session_actions_can_hibernate (p->backend_actions)) g_menu_append (menu, _("Hibernate"), "indicator.hibernate"); - if (!g_settings_get_boolean (s, "suppress-restart-menuitem")) + /* NB: check 'ellipsis' here to skip this item if prompting is enabled + because this shows the same prompt as 'Shut Down' in Unity */ + if (!ellipsis && !g_settings_get_boolean (s, "suppress-restart-menuitem")) { const char * label = ellipsis ? _("Restart\342\200\246") : _("Restart"); g_menu_append (menu, label, "indicator.reboot"); -- cgit v1.2.3 From b6467f327dcfc2c4fb60b57f293747259d0b7228 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 27 Jun 2013 21:44:03 -0500 Subject: in create_guest_switcher_state() and create_user_switcher_state(), don't leak GVariantBuilders --- src/service.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'src/service.c') diff --git a/src/service.c b/src/service.c index d8fc961..931c626 100644 --- a/src/service.c +++ b/src/service.c @@ -311,15 +311,15 @@ static GVariant * create_guest_switcher_state (IndicatorSessionService * self) { GVariant * val; - GVariantBuilder * b; + GVariantBuilder b; IndicatorSessionGuest * const g = self->priv->backend_guest; - b = g_variant_builder_new (G_VARIANT_TYPE ("a{sv}")); + g_variant_builder_init (&b, G_VARIANT_TYPE ("a{sv}")); val = g_variant_new_boolean (indicator_session_guest_is_active (g)); - g_variant_builder_add (b, "{sv}", "is-active", val); + g_variant_builder_add (&b, "{sv}", "is-active", val); val = g_variant_new_boolean (indicator_session_guest_is_logged_in (g)); - g_variant_builder_add (b, "{sv}", "is-logged-in", val); - return g_variant_builder_end (b); + g_variant_builder_add (&b, "{sv}", "is-logged-in", val); + return g_variant_builder_end (&b); } /** @@ -330,15 +330,15 @@ create_guest_switcher_state (IndicatorSessionService * self) static GVariant * create_user_switcher_state (IndicatorSessionService * self) { - GVariantBuilder * a; - GVariantBuilder * b; + GVariantBuilder a; + GVariantBuilder b; GVariant * val; GHashTableIter ht_iter; gpointer ht_value; const char * current_user; current_user = ""; - a = g_variant_builder_new (G_VARIANT_TYPE("as")); + g_variant_builder_init (&a, G_VARIANT_TYPE("as")); g_hash_table_iter_init (&ht_iter, self->priv->users); while (g_hash_table_iter_next (&ht_iter, NULL, &ht_value)) { @@ -348,15 +348,15 @@ create_user_switcher_state (IndicatorSessionService * self) current_user = u->user_name; if (u->is_logged_in) - g_variant_builder_add (a, "s", u->user_name); + g_variant_builder_add (&a, "s", u->user_name); } - b = g_variant_builder_new (G_VARIANT_TYPE("a{sv}")); + g_variant_builder_init (&b, G_VARIANT_TYPE("a{sv}")); val = g_variant_new_string (current_user); - g_variant_builder_add (b, "{sv}", "active-user", val); - val = g_variant_builder_end (a); - g_variant_builder_add (b, "{sv}", "logged-in-users", val); - return g_variant_builder_end (b); + g_variant_builder_add (&b, "{sv}", "active-user", val); + val = g_variant_builder_end (&a); + g_variant_builder_add (&b, "{sv}", "logged-in-users", val); + return g_variant_builder_end (&b); } static void -- cgit v1.2.3 From 3bd279a7de3b32bc33ab2f80d4eae0ecfe83dd38 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 28 Jun 2013 09:47:32 -0500 Subject: use the unicode '…' directly intead of \342\200\246 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/service.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/service.c') diff --git a/src/service.c b/src/service.c index 931c626..a9f2f65 100644 --- a/src/service.c +++ b/src/service.c @@ -295,9 +295,9 @@ create_settings_section (IndicatorSessionService * self) priv_t * p = self->priv; menu = g_menu_new (); - g_menu_append (menu, _("System Settings\342\200\246"), "indicator.settings"); + g_menu_append (menu, _("System Settings…"), "indicator.settings"); if (indicator_session_actions_has_online_account_error (p->backend_actions)) - g_menu_append (menu, _("Online Accounts\342\200\246"), "indicator.online-accounts"); + g_menu_append (menu, _("Online Accounts…"), "indicator.online-accounts"); return G_MENU_MODEL (menu); } @@ -443,19 +443,19 @@ create_switch_section (IndicatorSessionService * self) else if (indicator_session_guest_is_active (p->backend_guest)) { const char * action = "indicator.switch-to-greeter"; - item = g_menu_item_new (ellipsis ? _("Switch Account\342\200\246") + item = g_menu_item_new (ellipsis ? _("Switch Account…") : _("Switch Account"), action); } else if (g_hash_table_size (p->users) == 1) { const char * action = "indicator.switch-to-greeter"; - item = g_menu_item_new (ellipsis ? _("Lock\342\200\246") + item = g_menu_item_new (ellipsis ? _("Lock…") : _("Lock"), action); } else { const char * action = "indicator.switch-to-greeter"; - item = g_menu_item_new (ellipsis ? _("Lock/Switch Account\342\200\246") + item = g_menu_item_new (ellipsis ? _("Lock/Switch Account…") : _("Lock/Switch Account"), action); } str = g_settings_get_string (p->keybinding_settings, "screensaver"); @@ -529,7 +529,7 @@ create_session_section (IndicatorSessionService * self) if (indicator_session_actions_can_logout (p->backend_actions) && !g_settings_get_boolean (s, "suppress-logout-menuitem")) { - const char * label = ellipsis ? _("Log Out\342\200\246") : _("Log Out"); + const char * label = ellipsis ? _("Log Out…") : _("Log Out"); g_menu_append (menu, label, "indicator.logout"); } @@ -543,13 +543,13 @@ create_session_section (IndicatorSessionService * self) because this shows the same prompt as 'Shut Down' in Unity */ if (!ellipsis && !g_settings_get_boolean (s, "suppress-restart-menuitem")) { - const char * label = ellipsis ? _("Restart\342\200\246") : _("Restart"); + const char * label = ellipsis ? _("Restart…") : _("Restart"); g_menu_append (menu, label, "indicator.reboot"); } if (!g_settings_get_boolean (s, "suppress-shutdown-menuitem")) { - const char * label = ellipsis ? _("Shut Down\342\200\246") : _("Shut Down"); + const char * label = ellipsis ? _("Shut Down…") : _("Shut Down"); g_menu_append (menu, label, "indicator.power-off"); } -- cgit v1.2.3 From 9a3e46e73ee201771c8bc9ae9f95adecbb71fe69 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 28 Jun 2013 18:38:51 -0500 Subject: in service.c's add_user(), test for NULL before adding the user struct to our collection --- src/service.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'src/service.c') diff --git a/src/service.c b/src/service.c index a9f2f65..36ef282 100644 --- a/src/service.c +++ b/src/service.c @@ -210,14 +210,16 @@ add_user (IndicatorSessionService * self, guint uid) { IndicatorSessionUser * u; - /* update our user table */ - u = indicator_session_users_get_user (self->priv->backend_users, uid); - g_hash_table_insert (self->priv->users, GUINT_TO_POINTER(uid), u); + if ((u = indicator_session_users_get_user (self->priv->backend_users, uid))) + { + /* update our user table */ + g_hash_table_insert (self->priv->users, GUINT_TO_POINTER(uid), u); - /* enqueue rebuilds for the affected sections */ - rebuild_switch_section_soon (self); - if (u->is_current_user) - rebuild_header_soon (self); + /* queue rebuilds for the affected sections */ + rebuild_switch_section_soon (self); + if (u->is_current_user) + rebuild_header_soon (self); + } } static void -- cgit v1.2.3 From 39750137bbbbe1f3ba1aa7ae8dc5d39e0f354313 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 1 Jul 2013 09:53:32 -0500 Subject: when user switching isn't available, don't ellipsize the 'Lock' menuitem --- src/service.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/service.c') diff --git a/src/service.c b/src/service.c index 36ef282..45bbdad 100644 --- a/src/service.c +++ b/src/service.c @@ -451,8 +451,7 @@ create_switch_section (IndicatorSessionService * self) else if (g_hash_table_size (p->users) == 1) { const char * action = "indicator.switch-to-greeter"; - item = g_menu_item_new (ellipsis ? _("Lock…") - : _("Lock"), action); + item = g_menu_item_new (_("Lock"), action); } else { -- cgit v1.2.3 From d7248cf9ca466a9a3fbb9c722ad7029f9150fd0d Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 5 Jul 2013 07:24:39 -0500 Subject: make the desktop greeter menu's name consistent across indicators: 'desktop_greeter' --- data/com.canonical.indicator.session | 2 +- src/service.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'src/service.c') diff --git a/data/com.canonical.indicator.session b/data/com.canonical.indicator.session index 28f11a0..7b1b39e 100644 --- a/data/com.canonical.indicator.session +++ b/data/com.canonical.indicator.session @@ -7,5 +7,5 @@ Position=10 ObjectPath=/com/canonical/indicator/session/desktop [desktop_greeter] -ObjectPath=/com/canonical/indicator/session/greeter +ObjectPath=/com/canonical/indicator/session/desktop_greeter diff --git a/src/service.c b/src/service.c index 45bbdad..6cb9123 100644 --- a/src/service.c +++ b/src/service.c @@ -531,6 +531,7 @@ create_session_section (IndicatorSessionService * self) if (indicator_session_actions_can_logout (p->backend_actions) && !g_settings_get_boolean (s, "suppress-logout-menuitem")) { const char * label = ellipsis ? _("Log Out…") : _("Log Out"); + label = "Logggg outttt....."; g_menu_append (menu, label, "indicator.logout"); } -- cgit v1.2.3 From 6c4e44173ea46125697ed33e989f23db1f36b744 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Tue, 9 Jul 2013 23:25:12 -0500 Subject: in the desktop greeter, skip the logout menuitem --- src/service.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'src/service.c') diff --git a/src/service.c b/src/service.c index 6cb9123..166f729 100644 --- a/src/service.c +++ b/src/service.c @@ -519,7 +519,7 @@ create_switch_section (IndicatorSessionService * self) } static GMenuModel * -create_session_section (IndicatorSessionService * self) +create_session_section (IndicatorSessionService * self, int profile) { GMenu * menu; const priv_t * const p = self->priv; @@ -528,10 +528,11 @@ create_session_section (IndicatorSessionService * self) menu = g_menu_new (); - if (indicator_session_actions_can_logout (p->backend_actions) && !g_settings_get_boolean (s, "suppress-logout-menuitem")) + if ((profile == PROFILE_DESKTOP) && + (indicator_session_actions_can_logout (p->backend_actions)) && + (!g_settings_get_boolean (s, "suppress-logout-menuitem"))) { const char * label = ellipsis ? _("Log Out…") : _("Log Out"); - label = "Logggg outttt....."; g_menu_append (menu, label, "indicator.logout"); } @@ -576,11 +577,11 @@ create_menu (IndicatorSessionService * self, int profile) sections[n++] = create_admin_section (); sections[n++] = create_settings_section (self); sections[n++] = create_switch_section (self); - sections[n++] = create_session_section (self); + sections[n++] = create_session_section (self, profile); } else if (profile == PROFILE_GREETER) { - sections[n++] = create_session_section (self); + sections[n++] = create_session_section (self, profile); } /* add sections to the submenu */ @@ -811,8 +812,8 @@ rebuild_now (IndicatorSessionService * self, int sections) if (sections & SECTION_SESSION) { - rebuild_section (desktop->submenu, 3, create_session_section(self)); - rebuild_section (greeter->submenu, 0, create_session_section(self)); + rebuild_section (desktop->submenu, 3, create_session_section(self, PROFILE_DESKTOP)); + rebuild_section (greeter->submenu, 0, create_session_section(self, PROFILE_GREETER)); } } -- cgit v1.2.3 From 98d1379784757b63e317bcd9ac7af69836e473d9 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 12 Jul 2013 02:03:13 -0500 Subject: Add a 'can-reboot' property to the Actions class. This is used for handling a couple of pathological cases where features and states mix and match: 1. unity has the same dialog for 'reboot' and 'power off', so remove the duplicate menuitem, EXCEPT: 2. if the unity prompt isn't available (such as in the greeter), show both menuitems, OR 3. if the user has prompting disabled we need both, OR 4. if the user has the 'power off' button disabled, don't treat 'reboot' as redundant. --- src/actions.c | 26 ++++++++++++++++++++++ src/actions.h | 4 ++++ src/service.c | 11 ++------- tests/backend-mock-actions.c | 7 ++++++ ...nical.indicator.session.backendmock.gschema.xml | 4 ++++ 5 files changed, 43 insertions(+), 9 deletions(-) (limited to 'src/service.c') diff --git a/src/actions.c b/src/actions.c index babc285..ca086b7 100644 --- a/src/actions.c +++ b/src/actions.c @@ -34,6 +34,7 @@ enum PROP_CAN_SUSPEND, PROP_CAN_LOCK, PROP_CAN_LOGOUT, + PROP_CAN_REBOOT, PROP_CAN_PROMPT, PROP_HAS_ONLINE_ACCOUNT_ERROR, PROP_LAST @@ -71,6 +72,10 @@ my_get_property (GObject * o, g_value_set_boolean (value, indicator_session_actions_can_logout (self)); break; + case PROP_CAN_REBOOT: + g_value_set_boolean (value, indicator_session_actions_can_reboot (self)); + break; + case PROP_CAN_PROMPT: g_value_set_boolean (value, indicator_session_actions_can_prompt (self)); break; @@ -96,6 +101,7 @@ indicator_session_actions_class_init (IndicatorSessionActionsClass * klass) klass->can_lock = NULL; klass->can_logout = NULL; + klass->can_reboot = NULL; klass->can_switch = NULL; klass->can_suspend = NULL; klass->can_hibernate = NULL; @@ -144,6 +150,12 @@ indicator_session_actions_class_init (IndicatorSessionActionsClass * klass) "Whether or not the system services allow the user to logout", TRUE, flags); + properties[PROP_CAN_REBOOT] = + g_param_spec_boolean (INDICATOR_SESSION_ACTIONS_PROP_CAN_REBOOT, + "Can Reboot", + "Whether or not the system services allow the user to reboot", + TRUE, flags); + properties[PROP_CAN_PROMPT] = g_param_spec_boolean (INDICATOR_SESSION_ACTIONS_PROP_CAN_PROMPT, "Can Show End Session Dialog", @@ -185,6 +197,14 @@ indicator_session_actions_can_logout (IndicatorSessionActions * self) return INDICATOR_SESSION_ACTIONS_GET_CLASS (self)->can_logout (self); } +gboolean +indicator_session_actions_can_reboot (IndicatorSessionActions * self) +{ + g_return_val_if_fail (INDICATOR_IS_SESSION_ACTIONS (self), FALSE); + + return INDICATOR_SESSION_ACTIONS_GET_CLASS (self)->can_reboot (self); +} + gboolean indicator_session_actions_can_switch (IndicatorSessionActions * self) { @@ -352,6 +372,12 @@ indicator_session_actions_notify_can_logout (IndicatorSessionActions * self) notify_func (self, PROP_CAN_LOGOUT); } +void +indicator_session_actions_notify_can_reboot (IndicatorSessionActions * self) +{ + notify_func (self, PROP_CAN_REBOOT); +} + void indicator_session_actions_notify_can_switch (IndicatorSessionActions * self) { diff --git a/src/actions.h b/src/actions.h index bba6045..0f8aa1d 100644 --- a/src/actions.h +++ b/src/actions.h @@ -38,6 +38,7 @@ typedef struct _IndicatorSessionActionsClass IndicatorSessionActionsClass; /* property keys */ #define INDICATOR_SESSION_ACTIONS_PROP_CAN_LOCK "can-lock" #define INDICATOR_SESSION_ACTIONS_PROP_CAN_LOGOUT "can-logout" +#define INDICATOR_SESSION_ACTIONS_PROP_CAN_REBOOT "can-reboot" #define INDICATOR_SESSION_ACTIONS_PROP_CAN_SWITCH "can-switch" #define INDICATOR_SESSION_ACTIONS_PROP_CAN_SUSPEND "can-suspend" #define INDICATOR_SESSION_ACTIONS_PROP_CAN_HIBERNATE "can-hibernate" @@ -62,6 +63,7 @@ struct _IndicatorSessionActionsClass gboolean (*can_lock) (IndicatorSessionActions * self); gboolean (*can_logout) (IndicatorSessionActions * self); + gboolean (*can_reboot) (IndicatorSessionActions * self); gboolean (*can_switch) (IndicatorSessionActions * self); gboolean (*can_suspend) (IndicatorSessionActions * self); gboolean (*can_hibernate) (IndicatorSessionActions * self); @@ -92,6 +94,7 @@ GType indicator_session_actions_get_type (void); gboolean indicator_session_actions_can_lock (IndicatorSessionActions * self); gboolean indicator_session_actions_can_logout (IndicatorSessionActions * self); +gboolean indicator_session_actions_can_reboot (IndicatorSessionActions * self); gboolean indicator_session_actions_can_switch (IndicatorSessionActions * self); gboolean indicator_session_actions_can_suspend (IndicatorSessionActions * self); gboolean indicator_session_actions_can_hibernate (IndicatorSessionActions * self); @@ -101,6 +104,7 @@ gboolean indicator_session_actions_has_online_account_error (IndicatorSession void indicator_session_actions_notify_can_lock (IndicatorSessionActions * self); void indicator_session_actions_notify_can_logout (IndicatorSessionActions * self); +void indicator_session_actions_notify_can_reboot (IndicatorSessionActions * self); void indicator_session_actions_notify_can_switch (IndicatorSessionActions * self); void indicator_session_actions_notify_can_suspend (IndicatorSessionActions * self); void indicator_session_actions_notify_can_hibernate (IndicatorSessionActions * self); diff --git a/src/service.c b/src/service.c index 166f729..3de37e3 100644 --- a/src/service.c +++ b/src/service.c @@ -529,8 +529,7 @@ create_session_section (IndicatorSessionService * self, int profile) menu = g_menu_new (); if ((profile == PROFILE_DESKTOP) && - (indicator_session_actions_can_logout (p->backend_actions)) && - (!g_settings_get_boolean (s, "suppress-logout-menuitem"))) + (indicator_session_actions_can_logout (p->backend_actions))) { const char * label = ellipsis ? _("Log Out…") : _("Log Out"); g_menu_append (menu, label, "indicator.logout"); @@ -542,9 +541,7 @@ create_session_section (IndicatorSessionService * self, int profile) if (indicator_session_actions_can_hibernate (p->backend_actions)) g_menu_append (menu, _("Hibernate"), "indicator.hibernate"); - /* NB: check 'ellipsis' here to skip this item if prompting is enabled - because this shows the same prompt as 'Shut Down' in Unity */ - if (!ellipsis && !g_settings_get_boolean (s, "suppress-restart-menuitem")) + if (indicator_session_actions_can_reboot (p->backend_actions)) { const char * label = ellipsis ? _("Restart…") : _("Restart"); g_menu_append (menu, label, "indicator.reboot"); @@ -1021,10 +1018,6 @@ indicator_session_service_init (IndicatorSessionService * self) G_CALLBACK(rebuild_switch_section_soon), self); g_signal_connect_swapped (gp, "changed::suppress-logout-restart-shutdown", G_CALLBACK(rebuild_session_section_soon), self); - g_signal_connect_swapped (gp, "changed::suppress-logout-menuitem", - G_CALLBACK(rebuild_session_section_soon), self); - g_signal_connect_swapped (gp, "changed::suppress-restart-menuitem", - G_CALLBACK(rebuild_session_section_soon), self); g_signal_connect_swapped (gp, "changed::suppress-shutdown-menuitem", G_CALLBACK(rebuild_session_section_soon), self); g_signal_connect_swapped (gp, "changed::show-real-name-on-panel", diff --git a/tests/backend-mock-actions.c b/tests/backend-mock-actions.c index d5a506b..af4afd9 100644 --- a/tests/backend-mock-actions.c +++ b/tests/backend-mock-actions.c @@ -43,6 +43,12 @@ my_can_logout (IndicatorSessionActions * self G_GNUC_UNUSED) return g_settings_get_boolean (mock_settings, "can-logout"); } +static gboolean +my_can_reboot (IndicatorSessionActions * self G_GNUC_UNUSED) +{ + return g_settings_get_boolean (mock_settings, "can-reboot"); +} + static gboolean my_can_switch (IndicatorSessionActions * self G_GNUC_UNUSED) { @@ -177,6 +183,7 @@ indicator_session_actions_mock_class_init (IndicatorSessionActionsMockClass * kl actions_class = INDICATOR_SESSION_ACTIONS_CLASS (klass); actions_class->can_lock = my_can_lock; actions_class->can_logout = my_can_logout; + actions_class->can_reboot = my_can_reboot; actions_class->can_switch = my_can_switch; actions_class->can_suspend = my_can_suspend; actions_class->can_hibernate = my_can_hibernate; diff --git a/tests/com.canonical.indicator.session.backendmock.gschema.xml b/tests/com.canonical.indicator.session.backendmock.gschema.xml index 34479df..79d0c02 100644 --- a/tests/com.canonical.indicator.session.backendmock.gschema.xml +++ b/tests/com.canonical.indicator.session.backendmock.gschema.xml @@ -21,6 +21,10 @@ true Is logging out allowed? + + true + Is rebooting allowed? + true Is locking the session allowed? -- cgit v1.2.3 From a19955f3f81b1a5eb8fc928bc5dcf8a24bb6833f Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 12 Jul 2013 07:42:07 -0500 Subject: add the online-accounts action and unit tests for it --- src/actions.c | 8 ++++++++ src/actions.h | 2 ++ src/backend-dbus/actions.c | 10 ++++++++++ src/service.c | 29 +++++++++++++++++++---------- tests/backend-mock-actions.c | 7 +++++++ tests/test-service.cc | 9 +++++++++ 6 files changed, 55 insertions(+), 10 deletions(-) (limited to 'src/service.c') diff --git a/src/actions.c b/src/actions.c index ca086b7..563f626 100644 --- a/src/actions.c +++ b/src/actions.c @@ -249,6 +249,14 @@ indicator_session_actions_has_online_account_error (IndicatorSessionActions * se **** ***/ +void +indicator_session_actions_online_accounts (IndicatorSessionActions * self) +{ + g_return_if_fail (INDICATOR_IS_SESSION_ACTIONS (self)); + + INDICATOR_SESSION_ACTIONS_GET_CLASS (self)->online_accounts (self); +} + void indicator_session_actions_settings (IndicatorSessionActions * self) { diff --git a/src/actions.h b/src/actions.h index 0f8aa1d..e31685e 100644 --- a/src/actions.h +++ b/src/actions.h @@ -78,6 +78,7 @@ struct _IndicatorSessionActionsClass void (*help) (IndicatorSessionActions * self); void (*about) (IndicatorSessionActions * self); void (*settings) (IndicatorSessionActions * self); + void (*online_accounts) (IndicatorSessionActions * self); void (*switch_to_greeter) (IndicatorSessionActions * self); void (*switch_to_screensaver) (IndicatorSessionActions * self); @@ -121,6 +122,7 @@ void indicator_session_actions_power_off (IndicatorSession void indicator_session_actions_help (IndicatorSessionActions * self); void indicator_session_actions_about (IndicatorSessionActions * self); void indicator_session_actions_settings (IndicatorSessionActions * self); +void indicator_session_actions_online_accounts (IndicatorSessionActions * self); void indicator_session_actions_switch_to_screensaver (IndicatorSessionActions * self); void indicator_session_actions_switch_to_greeter (IndicatorSessionActions * self); diff --git a/src/backend-dbus/actions.c b/src/backend-dbus/actions.c index ed1e708..9030ca7 100644 --- a/src/backend-dbus/actions.c +++ b/src/backend-dbus/actions.c @@ -311,6 +311,9 @@ on_webcredentials_proxy_ready (GObject * o G_GNUC_UNUSED, GAsyncResult * res, gp g_signal_connect_swapped (webcredentials, "notify::error-status", G_CALLBACK(indicator_session_actions_notify_has_online_account_error), gself); + + if (webcredentials_get_error_status (webcredentials)) + indicator_session_actions_notify_has_online_account_error (gself); } log_and_clear_error (&err, G_STRLOC, G_STRFUNC); @@ -714,6 +717,12 @@ my_settings (IndicatorSessionActions * self G_GNUC_UNUSED) run_outside_app ("gnome-control-center"); } +static void +my_online_accounts (IndicatorSessionActions * self G_GNUC_UNUSED) +{ + run_outside_app ("gnome-control-center credentials"); +} + static void my_about (IndicatorSessionActions * self G_GNUC_UNUSED) { @@ -855,6 +864,7 @@ indicator_session_actions_dbus_class_init (IndicatorSessionActionsDbusClass * kl actions_class->reboot = my_reboot; actions_class->power_off = my_power_off; actions_class->settings = my_settings; + actions_class->online_accounts = my_online_accounts; actions_class->help = my_help; actions_class->about = my_about; actions_class->switch_to_screensaver = my_switch_to_screensaver; diff --git a/src/service.c b/src/service.c index 3de37e3..74acd89 100644 --- a/src/service.c +++ b/src/service.c @@ -622,6 +622,14 @@ on_about_activated (GSimpleAction * a G_GNUC_UNUSED, indicator_session_actions_about (get_backend_actions(gself)); } +static void +on_online_accounts_activated (GSimpleAction * a G_GNUC_UNUSED, + GVariant * param G_GNUC_UNUSED, + gpointer gself) +{ + indicator_session_actions_online_accounts (get_backend_actions(gself)); +} + static void on_help_activated (GSimpleAction * a G_GNUC_UNUSED, GVariant * param G_GNUC_UNUSED, @@ -720,16 +728,17 @@ init_gactions (IndicatorSessionService * self) priv_t * p = self->priv; GActionEntry entries[] = { - { "about", on_about_activated }, - { "help", on_help_activated }, - { "settings", on_settings_activated }, - { "logout", on_logout_activated }, - { "suspend", on_suspend_activated }, - { "hibernate", on_hibernate_activated }, - { "reboot", on_reboot_activated }, - { "power-off", on_power_off_activated }, - { "switch-to-screensaver", on_screensaver_activated }, - { "switch-to-greeter", on_greeter_activated } + { "about", on_about_activated }, + { "help", on_help_activated }, + { "hibernate", on_hibernate_activated }, + { "logout", on_logout_activated }, + { "online-accounts", on_online_accounts_activated }, + { "reboot", on_reboot_activated }, + { "settings", on_settings_activated }, + { "switch-to-screensaver", on_screensaver_activated }, + { "switch-to-greeter", on_greeter_activated }, + { "suspend", on_suspend_activated }, + { "power-off", on_power_off_activated } }; p->actions = g_simple_action_group_new (); diff --git a/tests/backend-mock-actions.c b/tests/backend-mock-actions.c index af4afd9..25a606f 100644 --- a/tests/backend-mock-actions.c +++ b/tests/backend-mock-actions.c @@ -141,6 +141,12 @@ my_settings (IndicatorSessionActions * self G_GNUC_UNUSED) g_settings_set_string (mock_settings, "last-command", "settings"); } +static void +my_online_accounts (IndicatorSessionActions * self G_GNUC_UNUSED) +{ + g_settings_set_string (mock_settings, "last-command", "online-accounts"); +} + static gboolean my_can_prompt (IndicatorSessionActions * self G_GNUC_UNUSED) { @@ -195,6 +201,7 @@ indicator_session_actions_mock_class_init (IndicatorSessionActionsMockClass * kl actions_class->reboot = my_reboot; actions_class->power_off = my_power_off; actions_class->settings = my_settings; + actions_class->online_accounts = my_online_accounts; actions_class->help = my_help; actions_class->about = my_about; actions_class->switch_to_screensaver = my_switch_to_screensaver; diff --git a/tests/test-service.cc b/tests/test-service.cc index 86f49e6..2027ec0 100644 --- a/tests/test-service.cc +++ b/tests/test-service.cc @@ -589,6 +589,15 @@ TEST_F (ServiceTest, OnlineAccountError) ASSERT_TRUE (find_menu_item_for_action ("indicator.online-accounts", &model, &pos)); g_clear_object (&model); + // check that the service has a corresponding action + ASSERT_TRUE (g_action_group_has_action (G_ACTION_GROUP(action_group), "online-accounts")); + ASSERT_TRUE (g_action_group_get_action_enabled (G_ACTION_GROUP(action_group), "online-accounts")); + + // confirm that activating the action is handled by the service + g_action_group_activate_action (G_ACTION_GROUP(action_group), "online-accounts", NULL); + wait_for_signal (mock_settings, "changed::last-command"); + check_last_command_is ("online-accounts"); + // check that the header's icon and a11y adjusted to the error state check_header ("", "system-devices-panel-alert", "System (Attention Required)"); -- cgit v1.2.3 From 843fa1f19c2d6c1072ab3479c0969eb0b6b73076 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 8 Aug 2013 16:00:42 -0500 Subject: as discussed with dednick and ted, have a header action state type of a{sv} rather than the obsoleted (sssb) --- src/service.c | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) (limited to 'src/service.c') diff --git a/src/service.c b/src/service.c index 74acd89..41dba10 100644 --- a/src/service.c +++ b/src/service.c @@ -143,29 +143,28 @@ rebuild_settings_section_soon (IndicatorSessionService * self) **** ***/ -static void -update_header_action (IndicatorSessionService * self) +static GVariant * +action_state_for_header (IndicatorSessionService * self) { - gchar * a11y; + const priv_t * const p = self->priv; gboolean need_attn; + GIcon * icon; gboolean show_name; - GVariant * variant; const gchar * real_name; const gchar * label; - const gchar * iconstr; - const priv_t * const p = self->priv; - - g_return_if_fail (p->header_action != NULL); + gchar * a11y; + GVariantBuilder b; + GVariant * state; if (indicator_session_actions_has_online_account_error (p->backend_actions)) { need_attn = TRUE; - iconstr = ICON_ALERT; + icon = g_themed_icon_new (ICON_ALERT); } else { need_attn = FALSE; - iconstr = ICON_DEFAULT; + icon = g_themed_icon_new (ICON_DEFAULT); } show_name = g_settings_get_boolean (p->indicator_settings, @@ -194,9 +193,27 @@ update_header_action (IndicatorSessionService * self) a11y = g_strdup (_("System")); } - variant = g_variant_new ("(sssb)", label, iconstr, a11y, TRUE); - g_simple_action_set_state (p->header_action, variant); + /* 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)); + g_variant_builder_add (&b, "{sv}", "icon", g_icon_serialize (icon)); + 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)); + state = g_variant_builder_end (&b); +g_message ("---\n%s\n---\n", g_variant_print(state, TRUE)); + + /* cleanup */ g_free (a11y); + g_object_unref (G_OBJECT (icon)); + + return state; +} + +static void +update_header_action (IndicatorSessionService * self) +{ + g_simple_action_set_state (self->priv->header_action, action_state_for_header (self)); } /*** @@ -763,8 +780,7 @@ init_gactions (IndicatorSessionService * self) p->user_switcher_action = a; /* add the header action */ - v = g_variant_new ("(sssb)", "label", ICON_DEFAULT, "a11y", TRUE); - a = g_simple_action_new_stateful ("_header", NULL, v); + a = g_simple_action_new_stateful ("_header", NULL, action_state_for_header (self)); g_simple_action_group_insert (p->actions, G_ACTION(a)); p->header_action = a; -- cgit v1.2.3 From a699afab31403d69bbd6f20c45a6f601b1ea3dc5 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 8 Aug 2013 16:02:22 -0500 Subject: remove debugging stub --- src/service.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src/service.c') diff --git a/src/service.c b/src/service.c index 41dba10..a097876 100644 --- a/src/service.c +++ b/src/service.c @@ -201,7 +201,6 @@ action_state_for_header (IndicatorSessionService * self) g_variant_builder_add (&b, "{sv}", "label", g_variant_new_string (label)); g_variant_builder_add (&b, "{sv}", "visible", g_variant_new_boolean (TRUE)); state = g_variant_builder_end (&b); -g_message ("---\n%s\n---\n", g_variant_print(state, TRUE)); /* cleanup */ g_free (a11y); -- cgit v1.2.3 From 3b35ef115b35d21b627f5802f364906243418247 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 22 Aug 2013 10:04:10 -0500 Subject: don't use deprecated API calls to GSimpleActionGroup --- src/service.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/service.c') diff --git a/src/service.c b/src/service.c index 74acd89..7303fcf 100644 --- a/src/service.c +++ b/src/service.c @@ -752,20 +752,20 @@ init_gactions (IndicatorSessionService * self) v = create_guest_switcher_state (self); a = g_simple_action_new_stateful ("switch-to-guest", NULL, v); g_signal_connect (a, "activate", G_CALLBACK(on_guest_activated), self); - g_simple_action_group_insert (p->actions, G_ACTION(a)); + g_action_map_add_action (G_ACTION_MAP (p->actions), G_ACTION(a)); p->guest_switcher_action = a; /* add switch-to-user action... parameter is the uesrname */ v = create_user_switcher_state (self); a = g_simple_action_new_stateful ("switch-to-user", G_VARIANT_TYPE_STRING, v); g_signal_connect (a, "activate", G_CALLBACK(on_user_activated), self); - g_simple_action_group_insert (p->actions, G_ACTION(a)); + g_action_map_add_action (G_ACTION_MAP (p->actions), G_ACTION(a)); p->user_switcher_action = a; /* add the header action */ v = g_variant_new ("(sssb)", "label", ICON_DEFAULT, "a11y", TRUE); a = g_simple_action_new_stateful ("_header", NULL, v); - g_simple_action_group_insert (p->actions, G_ACTION(a)); + g_action_map_add_action (G_ACTION_MAP (p->actions), G_ACTION(a)); p->header_action = a; rebuild_now (self, SECTION_HEADER); -- cgit v1.2.3