diff options
-rw-r--r-- | data/CMakeLists.txt | 20 | ||||
-rw-r--r-- | data/com.canonical.indicator.session.gschema.xml.in | 5 | ||||
-rw-r--r-- | data/indicator-session.conf.in | 3 | ||||
-rw-r--r-- | data/indicator-session.desktop.in | 4 | ||||
-rw-r--r-- | data/indicator-session.upstart.desktop.in | 9 | ||||
-rw-r--r-- | debian/changelog | 42 | ||||
-rw-r--r-- | debian/control | 2 | ||||
-rw-r--r-- | src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/recoverable-problem.c | 167 | ||||
-rw-r--r-- | src/recoverable-problem.h | 26 | ||||
-rw-r--r-- | src/service.c | 160 | ||||
-rw-r--r-- | tests/com.canonical.indicator.session.gschema.xml | 7 | ||||
-rw-r--r-- | tests/gtest-dbus-fixture.h | 55 | ||||
-rw-r--r-- | tests/test-service.cc | 17 |
14 files changed, 438 insertions, 81 deletions
diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt index 163e2cd..a6a2e9f 100644 --- a/data/CMakeLists.txt +++ b/data/CMakeLists.txt @@ -57,6 +57,26 @@ configure_file ("${XDG_AUTOSTART_FILE_IN}" "${XDG_AUTOSTART_FILE}") install (FILES "${XDG_AUTOSTART_FILE}" DESTINATION "${XDG_AUTOSTART_DIR}") +## +## Upstart XDG Autostart Override +## + +# where to install +set (UPSTART_XDG_AUTOSTART_DIR "${CMAKE_INSTALL_FULL_DATAROOTDIR}/upstart/xdg/autostart") +message (STATUS "${UPSTART_XDG_AUTOSTART_DIR} is the Upstart XDG autostart override dir") + +set (UPSTART_XDG_AUTOSTART_NAME "${CMAKE_PROJECT_NAME}.upstart.desktop") +set (UPSTART_XDG_AUTOSTART_FILE "${CMAKE_CURRENT_BINARY_DIR}/${UPSTART_XDG_AUTOSTART_NAME}") +set (UPSTART_XDG_AUTOSTART_FILE_IN "${CMAKE_CURRENT_SOURCE_DIR}/${UPSTART_XDG_AUTOSTART_NAME}.in") + +# build it +set (pkglibexecdir "${CMAKE_INSTALL_FULL_PKGLIBEXECDIR}") +configure_file ("${UPSTART_XDG_AUTOSTART_FILE_IN}" "${UPSTART_XDG_AUTOSTART_FILE}") + +# install it +install (FILES "${UPSTART_XDG_AUTOSTART_FILE}" + DESTINATION "${UPSTART_XDG_AUTOSTART_DIR}" + RENAME "${XDG_AUTOSTART_NAME}") ## ## Unity Indicator File diff --git a/data/com.canonical.indicator.session.gschema.xml.in b/data/com.canonical.indicator.session.gschema.xml.in index 6010b3f..d5e852e 100644 --- a/data/com.canonical.indicator.session.gschema.xml.in +++ b/data/com.canonical.indicator.session.gschema.xml.in @@ -25,6 +25,11 @@ <summary>Determine the visibility of the User's real name on the panel</summary> <description>Allow for the Removal of the users name from the panel</description> </key> + <key type="b" name="user-show-menu"> + <default>true</default> + <summary>Show the list of users</summary> + <description>Allow for the user list to be hidden by the user.</description> + </key> </schema> diff --git a/data/indicator-session.conf.in b/data/indicator-session.conf.in index 6bd93a2..c7530e3 100644 --- a/data/indicator-session.conf.in +++ b/data/indicator-session.conf.in @@ -1,8 +1,9 @@ description "Indicator Session Service" -start on indicators-loaded or indicator-services-start +start on indicator-services-start stop on desktop-end or indicator-services-end respawn +respawn limit 2 10 exec @pkglibexecdir@/indicator-session-service diff --git a/data/indicator-session.desktop.in b/data/indicator-session.desktop.in index b6d289d..10dcadd 100644 --- a/data/indicator-session.desktop.in +++ b/data/indicator-session.desktop.in @@ -2,8 +2,8 @@ Type=Application Name=Indicator Session Exec=@pkglibexecdir@/indicator-session-service -NotShowIn=Unity; +OnlyShowIn=Unity;GNOME; NoDisplay=true StartupNotify=false Terminal=false - +AutostartCondition=GNOME3 unless-session gnome diff --git a/data/indicator-session.upstart.desktop.in b/data/indicator-session.upstart.desktop.in new file mode 100644 index 0000000..f4970f6 --- /dev/null +++ b/data/indicator-session.upstart.desktop.in @@ -0,0 +1,9 @@ +[Desktop Entry] +Type=Application +Name=Indicator Session +Exec=@pkglibexecdir@/indicator-session-service +OnlyShowIn=Unity; +NoDisplay=true +StartupNotify=false +Terminal=false +Hidden=true diff --git a/debian/changelog b/debian/changelog index 5e12a0f..3a25d37 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,45 @@ +indicator-session (12.10.5+14.04.20140403-0ubuntu1) trusty; urgency=low + + [ Charles Kerr ] + * Fix the phantom "J Random User" menuitem that shows up under some + conditions. (LP: #1256590) + + -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Thu, 03 Apr 2014 17:13:30 +0000 + +indicator-session (12.10.5+14.04.20140324-0ubuntu1) trusty; urgency=low + + [ Charles Kerr ] + * Don't show a red icon in indicator-session when there's an online + user account error. (LP: #1206550) + + [ Iain Lane ] + * Re-add the feature to hide the user list if + com.canonical.indicator.session user-show-menu is false (LP: + #1211772) + + -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Mon, 24 Mar 2014 10:19:12 +0000 + +indicator-session (12.10.5+14.04.20140320-0ubuntu1) trusty; urgency=low + + [ Charles Kerr ] + * Don't show the lockscreen accelerator in switch-user mode. (LP: + #1241906) + * indicator-session relies on the org.gnome.desktop.lockdown schema + provided by gsettings-desktop-schemas. (LP: #1212664) + + [ Ted Gould ] + * Synchronize process management across indicators + + -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Thu, 20 Mar 2014 19:18:01 +0000 + +indicator-session (12.10.5+14.04.20140311.1-0ubuntu1) trusty; urgency=low + + [ Marco Trevisan (Treviño) ] + * IndicatorSessionService: add desktop_lockscreen mode, show users and + switch to account items + + -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Tue, 11 Mar 2014 19:21:29 +0000 + indicator-session (12.10.5+14.04.20140214-0ubuntu1) trusty; urgency=low [ Robert Ancell ] diff --git a/debian/control b/debian/control index 03c19f2..eb148bf 100644 --- a/debian/control +++ b/debian/control @@ -25,12 +25,14 @@ Depends: ${shlibs:Depends}, ${misc:Depends}, systemd-services, gnome-settings-daemon-schemas, + gsettings-desktop-schemas, Recommends: indicator-applet (>= 0.2) | indicator-renderer, gnome-screensaver, yelp, unity-control-center | gnome-control-center, unity-control-center-signon | gnome-control-center-signon Suggests: lightdm, + apport, zenity Description: indicator showing session management, status and user switching This indicator is designed to be placed on the right side of a panel and diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a00b6f1..9528f7d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -5,6 +5,8 @@ add_library (libindicatorsessionservice STATIC actions.h guest.c guest.h + recoverable-problem.c + recoverable-problem.h service.c service.h users.c diff --git a/src/recoverable-problem.c b/src/recoverable-problem.c new file mode 100644 index 0000000..7aff163 --- /dev/null +++ b/src/recoverable-problem.c @@ -0,0 +1,167 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Ted Gould <ted.gould@canonical.com> + */ + +#include "recoverable-problem.h" +#include <glib/gstdio.h> +#include <string.h> +#include <errno.h> + +/* Helpers to ensure we write nicely */ +static void +write_string (int fd, + const gchar *string) +{ + int res; + do + res = write (fd, string, strlen (string)); + while (G_UNLIKELY (res == -1 && errno == EINTR)); +} + +/* Make NULLs fast and fun! */ +static void +write_null (int fd) +{ + int res; + do + res = write (fd, "", 1); + while (G_UNLIKELY (res == -1 && errno == EINTR)); +} + +/* Child watcher */ +static gboolean +apport_child_watch (GPid pid G_GNUC_UNUSED, gint status G_GNUC_UNUSED, gpointer user_data) +{ + g_main_loop_quit((GMainLoop *)user_data); + return FALSE; +} + +static gboolean +apport_child_timeout (gpointer user_data) +{ + g_warning("Recoverable Error Reporter Timeout"); + g_main_loop_quit((GMainLoop *)user_data); + return FALSE; +} + +/* Code to report an error */ +void +report_recoverable_problem (const gchar * signature, GPid report_pid, gboolean wait, gchar * additional_properties[]) +{ + GSpawnFlags flags; + gboolean first; + GError * error = NULL; + gint error_stdin = 0; + GPid pid = 0; + gchar * pid_str = NULL; + gchar ** argv = NULL; + gchar * argv_nopid[2] = { + "/usr/share/apport/recoverable_problem", + NULL + }; + gchar * argv_pid[4] = { + "/usr/share/apport/recoverable_problem", + "-p", + NULL, /* put pid_str when allocated here */ + NULL + }; + + + argv = (gchar **)argv_nopid; + + if (report_pid != 0) { + pid_str = g_strdup_printf("%d", report_pid); + argv_pid[2] = pid_str; + argv = (gchar**)argv_pid; + } + + flags = G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL; + if (wait) { + flags |= G_SPAWN_DO_NOT_REAP_CHILD; + } + + g_spawn_async_with_pipes(NULL, /* cwd */ + argv, + NULL, /* envp */ + flags, + NULL, NULL, /* child setup func */ + &pid, + &error_stdin, + NULL, /* stdout */ + NULL, /* stderr */ + &error); + + if (error != NULL) { + g_warning("Unable to report a recoverable error: %s", error->message); + g_error_free(error); + } + + first = TRUE; + + if (error_stdin != 0 && signature != NULL) { + write_string(error_stdin, "DuplicateSignature"); + write_null(error_stdin); + write_string(error_stdin, signature); + + first = FALSE; + } + + if (error_stdin != 0 && additional_properties != NULL) { + gint i; + for (i = 0; additional_properties[i] != NULL; i++) { + if (!first) { + write_null(error_stdin); + } else { + first = FALSE; + } + + write_string(error_stdin, additional_properties[i]); + } + } + + if (error_stdin != 0) { + close(error_stdin); + } + + if (wait && pid != 0) { + GSource * child_source, * timeout_source; + GMainContext * context = g_main_context_new(); + GMainLoop * loop = g_main_loop_new(context, FALSE); + + child_source = g_child_watch_source_new(pid); + g_source_attach(child_source, context); + g_source_set_callback(child_source, (GSourceFunc)apport_child_watch, loop, NULL); + + timeout_source = g_timeout_source_new_seconds(5); + g_source_attach(timeout_source, context); + g_source_set_callback(timeout_source, apport_child_timeout, loop, NULL); + + g_main_loop_run(loop); + + g_source_destroy(timeout_source); + g_source_destroy(child_source); + g_main_loop_unref(loop); + g_main_context_unref(context); + + g_spawn_close_pid(pid); + } + + g_free(pid_str); + + return; +} diff --git a/src/recoverable-problem.h b/src/recoverable-problem.h new file mode 100644 index 0000000..e5fadab --- /dev/null +++ b/src/recoverable-problem.h @@ -0,0 +1,26 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + * + * Authors: + * Ted Gould <ted.gould@canonical.com> + */ + +#include <gio/gio.h> + +void report_recoverable_problem (const gchar * signature, + GPid report_pid, + gboolean wait, + gchar * additional_properties[]); + diff --git a/src/service.c b/src/service.c index 60ddae0..7484134 100644 --- a/src/service.c +++ b/src/service.c @@ -21,6 +21,7 @@ #include <gio/gio.h> #include "backend.h" +#include "recoverable-problem.h" #include "service.h" #define BUS_NAME "com.canonical.indicator.session" @@ -104,13 +105,11 @@ struct _IndicatorSessionServicePrivate GSimpleAction * user_switcher_action; GSimpleAction * guest_switcher_action; GHashTable * users; + GHashTable * reported_users; guint rebuild_id; int rebuild_flags; GDBusConnection * conn; GCancellable * cancellable; - - /* serialized icon cache */ - GVariant * alert_icon_serialized; GVariant * default_icon_serialized; }; @@ -155,12 +154,18 @@ rebuild_settings_section_soon (IndicatorSessionService * self) **** ***/ +static gboolean +show_user_list (IndicatorSessionService * self) +{ + return g_settings_get_boolean (self->priv->indicator_settings, + "user-show-menu"); +} + + static GVariant * action_state_for_header (IndicatorSessionService * self) { const priv_t * const p = self->priv; - gboolean need_attn; - GVariant * serialized_icon; gboolean show_name; const gchar * real_name; const gchar * label; @@ -168,38 +173,17 @@ action_state_for_header (IndicatorSessionService * self) GVariantBuilder b; GVariant * state; - if (indicator_session_actions_has_online_account_error (p->backend_actions)) - { - need_attn = TRUE; - serialized_icon = p->alert_icon_serialized; - } - else - { - need_attn = FALSE; - serialized_icon = p->default_icon_serialized; - } - show_name = g_settings_get_boolean (p->indicator_settings, "show-real-name-on-panel"); real_name = get_current_real_name (self); label = show_name && real_name ? real_name : ""; - if (*label && need_attn) - { - /* Translators: the name of the menu ("System"), then the user's name, - then a hint that something in this menu requires user attention */ - a11y = g_strdup_printf (_("System, %s (Attention Required)"), real_name); - } - else if (*label) + if (*label) { /* Translators: the name of the menu ("System"), then the user's name */ a11y = g_strdup_printf (_("System, %s"), label); } - else if (need_attn) - { - a11y = g_strdup (_("System (Attention Required)")); - } else { a11y = g_strdup (_("System")); @@ -208,8 +192,7 @@ action_state_for_header (IndicatorSessionService * self) /* build the state */ g_variant_builder_init (&b, G_VARIANT_TYPE("a{sv}")); g_variant_builder_add (&b, "{sv}", "accessible-desc", g_variant_new_string (a11y)); - if (serialized_icon != NULL) - g_variant_builder_add (&b, "{sv}", "icon", serialized_icon); + g_variant_builder_add (&b, "{sv}", "icon", p->default_icon_serialized); if (label && *label) g_variant_builder_add (&b, "{sv}", "label", g_variant_new_string (label)); g_variant_builder_add (&b, "{sv}", "visible", g_variant_new_boolean (TRUE)); @@ -267,6 +250,32 @@ on_user_changed (IndicatorSessionUsers * backend_users G_GNUC_UNUSED, } static void +maybe_add_users (IndicatorSessionService * self) +{ + if (show_user_list (self)) + { + GList * uids, * l; + + uids = indicator_session_users_get_uids (self->priv->backend_users); + for (l=uids; l!=NULL; l=l->next) + add_user (self, GPOINTER_TO_UINT(l->data)); + g_list_free (uids); + } +} + + +static void +user_show_menu_changed (IndicatorSessionService * self) +{ + if (show_user_list (self)) + maybe_add_users (self); + else + g_hash_table_remove_all (self->priv->users); + + rebuild_switch_section_soon (self); +} + +static void on_user_removed (IndicatorSessionUsers * backend_users G_GNUC_UNUSED, guint uid, gpointer gself) @@ -481,12 +490,55 @@ serialize_icon_file (const gchar * filename) return serialized_icon; } +static void +report_unusable_user (IndicatorSessionService * self, const IndicatorSessionUser * u) +{ + const priv_t * const p = self->priv; + gpointer key; + + g_return_if_fail(u != NULL); + + key = GUINT_TO_POINTER(u->uid); + + if (!g_hash_table_contains (p->reported_users, key)) + { + gchar * uid_str; + GPtrArray * additional; + const gchar * const error_name = "indicator-session-unknown-user-error"; + + /* don't spam apport with duplicates */ + g_hash_table_add (p->reported_users, key); + + uid_str = g_strdup_printf("%u", u->uid); + + additional = g_ptr_array_new (); /* null-terminated key/value pair strs */ + g_ptr_array_add (additional, "uid"); + g_ptr_array_add (additional, uid_str); + g_ptr_array_add (additional, "icon_file"); + g_ptr_array_add (additional, u->icon_file ? u->icon_file : "(null)"); + g_ptr_array_add (additional, "is_current_user"); + g_ptr_array_add (additional, u->is_current_user ? "true" : "false"); + g_ptr_array_add (additional, "is_logged_in"); + g_ptr_array_add (additional, u->is_logged_in ? "true" : "false"); + g_ptr_array_add (additional, "real_name"); + g_ptr_array_add (additional, u->real_name ? u->real_name : "(null)"); + g_ptr_array_add (additional, "user_name"); + g_ptr_array_add (additional, u->user_name ? u->user_name : "(null)"); + g_ptr_array_add (additional, NULL); /* null termination */ + report_recoverable_problem(error_name, (GPid)0, FALSE, (gchar**)additional->pdata); + + /* cleanup */ + g_free (uid_str); + g_ptr_array_free (additional, TRUE); + } +} + static GMenuModel * create_switch_section (IndicatorSessionService * self, int profile) { - gchar * str; GMenu * menu; GMenuItem * item; + gboolean want_accel; guint i; gpointer guser; GHashTableIter iter; @@ -501,6 +553,7 @@ create_switch_section (IndicatorSessionService * self, int profile) { const char * action = "indicator.switch-to-screensaver"; item = g_menu_item_new (_("Start Screen Saver"), action); + want_accel = TRUE; } else if (profile == PROFILE_LOCKSCREEN || indicator_session_guest_is_active (p->backend_guest)) @@ -508,6 +561,7 @@ create_switch_section (IndicatorSessionService * self, int profile) const char * action = "indicator.switch-to-greeter"; item = g_menu_item_new (ellipsis ? _("Switch Account…") : _("Switch Account"), action); + want_accel = FALSE; } else { @@ -518,11 +572,13 @@ create_switch_section (IndicatorSessionService * self, int profile) else item = g_menu_item_new (ellipsis ? _("Lock/Switch Account…") : _("Lock/Switch Account"), action); + + want_accel = TRUE; } - if (profile != PROFILE_LOCKSCREEN) + if (want_accel) { - str = g_settings_get_string (p->keybinding_settings, "screensaver"); + gchar * str = g_settings_get_string (p->keybinding_settings, "screensaver"); g_menu_item_set_attribute (item, "accel", "s", str); g_free (str); } @@ -541,7 +597,11 @@ create_switch_section (IndicatorSessionService * self, int profile) g_object_unref (item); } - /* build an array of all the users we know of */ + /* if we need to show the user list, build an array of all the users we know + * of, otherwise get out now */ + if (!show_user_list (self)) + return G_MENU_MODEL (menu); + users = g_ptr_array_new (); g_hash_table_iter_init (&iter, p->users); while (g_hash_table_iter_next (&iter, NULL, &guser)) @@ -561,12 +621,23 @@ create_switch_section (IndicatorSessionService * self, int profile) for (i=0; i<users->len; ++i) { const IndicatorSessionUser * u = g_ptr_array_index (users, i); + const char * label; GVariant * serialized_icon; if (profile == PROFILE_LOCKSCREEN && u->is_current_user) continue; - item = g_menu_item_new (get_user_label (u), NULL); + /* Sometimes we get a user without a username? bus hiccup. + I can't reproduce it, but let's not confuse users with + a meaningless menuitem. (see bug #1263228) */ + label = get_user_label (u); + if (!label || !*label) + { + report_unusable_user (self, u); + continue; + } + + item = g_menu_item_new (label, NULL); g_menu_item_set_action_and_target (item, "indicator.switch-to-user", "s", u->user_name); g_menu_item_set_attribute (item, "x-canonical-type", "s", "indicator.user-menu-item"); @@ -1053,8 +1124,6 @@ static void /* cppcheck-suppress unusedFunction */ indicator_session_service_init (IndicatorSessionService * self) { - GList * l; - GList * uids; priv_t * p; gpointer gp; GIcon * icon; @@ -1073,12 +1142,6 @@ indicator_session_service_init (IndicatorSessionService * self) &p->backend_users, &p->backend_guest); - /* build the serialized icon cache */ - - icon = g_themed_icon_new_with_default_fallbacks (ICON_ALERT); - p->alert_icon_serialized = g_icon_serialize (icon); - g_object_unref (icon); - icon = g_themed_icon_new_with_default_fallbacks (ICON_DEFAULT); p->default_icon_serialized = g_icon_serialize (icon); g_object_unref (icon); @@ -1088,10 +1151,10 @@ indicator_session_service_init (IndicatorSessionService * self) g_direct_equal, NULL, (GDestroyNotify)indicator_session_user_free); - uids = indicator_session_users_get_uids (p->backend_users); - for (l=uids; l!=NULL; l=l->next) - add_user (self, GPOINTER_TO_UINT(l->data)); - g_list_free (uids); + + p->reported_users = g_hash_table_new (g_direct_hash, g_direct_equal); + + maybe_add_users (self); init_gactions (self); @@ -1138,6 +1201,8 @@ indicator_session_service_init (IndicatorSessionService * self) G_CALLBACK(rebuild_session_section_soon), self); g_signal_connect_swapped (gp, "changed::show-real-name-on-panel", G_CALLBACK(rebuild_header_soon), self); + g_signal_connect_swapped (gp, "changed::user-show-menu", + G_CALLBACK(user_show_menu_changed), self); /* watch for changes to the lock keybinding */ gp = p->keybinding_settings; @@ -1229,6 +1294,7 @@ my_dispose (GObject * o) } g_clear_pointer (&p->users, g_hash_table_destroy); + g_clear_pointer (&p->reported_users, g_hash_table_destroy); g_clear_object (&p->backend_users); g_clear_object (&p->backend_guest); g_clear_object (&p->backend_actions); @@ -1244,8 +1310,6 @@ my_dispose (GObject * o) g_clear_object (&p->guest_switcher_action); g_clear_object (&p->conn); - /* clear the serialized icon cache */ - g_clear_pointer (&p->alert_icon_serialized, g_variant_unref); g_clear_pointer (&p->default_icon_serialized, g_variant_unref); G_OBJECT_CLASS (indicator_session_service_parent_class)->dispose (o); diff --git a/tests/com.canonical.indicator.session.gschema.xml b/tests/com.canonical.indicator.session.gschema.xml index 76b2be3..60e680b 100644 --- a/tests/com.canonical.indicator.session.gschema.xml +++ b/tests/com.canonical.indicator.session.gschema.xml @@ -26,7 +26,12 @@ <summary>Determine the visibility of the User's real name on the panel</summary> <description>Allow for the Removal of the users name from the panel</description> </key> + <key type="b" name="user-show-menu"> + <default>true</default> + <summary>Show the list of users</summary> + <description>Allow for the user menu to be hidden by the user.</description> + </key> </schema> -</schemalist>
\ No newline at end of file +</schemalist> diff --git a/tests/gtest-dbus-fixture.h b/tests/gtest-dbus-fixture.h index e6cd9c7..dedb727 100644 --- a/tests/gtest-dbus-fixture.h +++ b/tests/gtest-dbus-fixture.h @@ -54,13 +54,6 @@ class GTestDBusFixture : public ::testing::Test g_main_loop_quit (self->loop); } - static gboolean - wait_for_signal__timeout (gpointer name) - { - g_error ("%s: timed out waiting for signal '%s'", G_STRLOC, (char*)name); - return G_SOURCE_REMOVE; - } - protected: virtual void SetUp () @@ -103,29 +96,45 @@ class GTestDBusFixture : public ::testing::Test g_clear_pointer (&loop, g_main_loop_unref); } - /* convenience func to loop while waiting for a GObject's signal */ - void wait_for_signal (gpointer o, const gchar * signal) + private: + + static gboolean + wait_for_signal__timeout(gpointer name) { - const int timeout_seconds = 5; // arbitrary + g_error("%s: timed out waiting for signal '%s'", G_STRLOC, (char*)name); + return G_SOURCE_REMOVE; + } + static gboolean + wait_msec__timeout(gpointer loop) + { + g_main_loop_quit(static_cast<GMainLoop*>(loop)); + return G_SOURCE_CONTINUE; + } + + protected: + + /* convenience func to loop while waiting for a GObject's signal */ + void wait_for_signal(gpointer o, const gchar * signal, const int timeout_seconds=5) + { // wait for the signal or for timeout, whichever comes first - guint handler_id = g_signal_connect_swapped (o, signal, - G_CALLBACK(g_main_loop_quit), - loop); - gulong timeout_id = g_timeout_add_seconds (timeout_seconds, - wait_for_signal__timeout, - loop); - g_main_loop_run (loop); - g_source_remove (timeout_id); - g_signal_handler_disconnect (o, handler_id); + const auto handler_id = g_signal_connect_swapped(o, signal, + G_CALLBACK(g_main_loop_quit), + loop); + const auto timeout_id = g_timeout_add_seconds(timeout_seconds, + wait_for_signal__timeout, + loop); + g_main_loop_run(loop); + g_source_remove(timeout_id); + g_signal_handler_disconnect(o, handler_id); } /* convenience func to loop for N msec */ - void wait_msec (int msec) + void wait_msec(int msec=50) { - guint id = g_timeout_add (msec, (GSourceFunc)g_main_loop_quit, loop); - g_main_loop_run (loop); - g_source_remove (id); + const auto id = g_timeout_add(msec, wait_msec__timeout, loop); + g_main_loop_run(loop); + g_source_remove(id); } GMainLoop * loop; diff --git a/tests/test-service.cc b/tests/test-service.cc index f14fe61..ab84459 100644 --- a/tests/test-service.cc +++ b/tests/test-service.cc @@ -616,7 +616,7 @@ TEST_F (ServiceTest, OnlineAccountError) 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)"); + check_header ("", "system-devices-panel", "System"); // cleanup g_settings_reset (mock_settings, error_key); @@ -756,12 +756,7 @@ TEST_F (ServiceTest, User) g_settings_set_boolean (indicator_settings, show_name_key, true); wait_for_signal (action_group, "action-state-changed"); check_header ("Third Doctor", "system-devices-panel", "System, Third Doctor"); - g_settings_set_boolean (mock_settings, error_key, true); - wait_for_signal (action_group, "action-state-changed"); - check_header ("Third Doctor", "system-devices-panel-alert", "System, Third Doctor (Attention Required)"); - g_settings_reset (mock_settings, error_key); g_settings_reset (indicator_settings, show_name_key); - wait_for_menu_resync (); // try setting the max user count to 2... // since troughton has the fewest logins, he should get culled @@ -812,6 +807,16 @@ TEST_F (ServiceTest, User) check_label ("Third Doctor", switch_menu, 8); g_clear_object (&switch_menu); + /* Hide the user list */ + g_settings_set_boolean (indicator_settings, "user-show-menu", FALSE); + wait_for_menu_resync (); + // now there should be 2 menuitems: greeter + guest + ASSERT_TRUE (find_menu_item_for_action ("indicator.switch-to-screensaver", &switch_menu, &pos)); + ASSERT_EQ (0, pos); + ASSERT_EQ (2, g_menu_model_get_n_items (switch_menu)); + g_clear_object (&switch_menu); + g_settings_set_boolean (indicator_settings, "user-show-menu", TRUE); + // now switch to one of the doctors g_action_group_activate_action (G_ACTION_GROUP(action_group), "switch-to-user", |