aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/CMakeLists.txt20
-rw-r--r--data/com.canonical.indicator.session.gschema.xml.in5
-rw-r--r--data/indicator-session.conf.in3
-rw-r--r--data/indicator-session.desktop.in4
-rw-r--r--data/indicator-session.upstart.desktop.in9
-rw-r--r--debian/changelog42
-rw-r--r--debian/control2
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/recoverable-problem.c167
-rw-r--r--src/recoverable-problem.h26
-rw-r--r--src/service.c160
-rw-r--r--tests/com.canonical.indicator.session.gschema.xml7
-rw-r--r--tests/gtest-dbus-fixture.h55
-rw-r--r--tests/test-service.cc17
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",