From c0ac60b8fc5a146e22412d90ba7f2a38d99c157b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gy=C3=B6rgy=20Ball=C3=B3?= Date: Sun, 20 Nov 2011 02:17:19 +0100 Subject: Make building tests optional --- Makefile.am | 10 +++++++--- configure.ac | 9 +++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index 3bd312e..807cad0 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,13 +2,17 @@ ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} SUBDIRS = \ libindicator \ - tests \ tools -tests: libindicator - tools: libindicator +if WANT_TESTS +SUBDIRS += \ + tests + +tests: libindicator +endif + DISTCHECK_CONFIGURE_FLAGS = --disable-deprecations DISTCLEANFILES = \ diff --git a/configure.ac b/configure.ac index 2357f13..a2c39b5 100644 --- a/configure.ac +++ b/configure.ac @@ -107,6 +107,14 @@ AC_DEFINE_PATH(PREFIX, "${prefix}", [prefix directory]) AC_DEFINE_PATH(SYSCONFDIR, "${sysconfdir}", [system configuration dir]) AC_DEFINE_PATH(LIBDIR, "${libdir}", [system configuration dir]) +######################### +# Check if build tests +######################### +AC_ARG_ENABLE([tests], + AC_HELP_STRING([--disable-tests], [disable tests]),, + [enable_tests=yes]) +AM_CONDITIONAL([WANT_TESTS], [test "x$enable_tests" != "xno"]) + ######################### # Debug symbols ######################### @@ -146,5 +154,6 @@ Libindicator Configuration: Prefix: $prefix GTK+ Version: $with_gtk + Enable tests: $enable_tests Enable debugging: $enable_debug ]) -- cgit v1.2.3 From d1263521c78b88c2dfffe09aac10fc1a15cd790d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gy=C3=B6rgy=20Ball=C3=B3?= Date: Sun, 20 Nov 2011 02:19:45 +0100 Subject: Use different directory for headers of gtk3 library --- libindicator/Makefile.am | 2 +- libindicator/indicator3-0.4.pc.in.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libindicator/Makefile.am b/libindicator/Makefile.am index 53f9985..f9fb011 100644 --- a/libindicator/Makefile.am +++ b/libindicator/Makefile.am @@ -26,7 +26,7 @@ CLEANFILES += indicator$(VER)-0.$(INDICATOR_API_VERSION).pc include $(top_srcdir)/Makefile.am.marshal -libindicatorincludedir=$(includedir)/libindicator-0.$(INDICATOR_API_VERSION)/libindicator +libindicatorincludedir=$(includedir)/libindicator$(VER)-0.$(INDICATOR_API_VERSION)/libindicator indicator_headers = \ indicator.h \ diff --git a/libindicator/indicator3-0.4.pc.in.in b/libindicator/indicator3-0.4.pc.in.in index 1f34567..d4b5f0f 100644 --- a/libindicator/indicator3-0.4.pc.in.in +++ b/libindicator/indicator3-0.4.pc.in.in @@ -7,7 +7,7 @@ includedir=@includedir@ indicatordir=${libdir}/indicators3/@indicator_abi_version@/ iconsdir=@datarootdir@/@PACKAGE@/icons/ -Cflags: -I${includedir}/libindicator-0.@indicator_api_version@ +Cflags: -I${includedir}/libindicator3-0.@indicator_api_version@ Requires: gtk+-3.0 Libs: -lindicator3 -- cgit v1.2.3 From b1aebe568a4f0d0d76e9ea32df47385b26b45c5d Mon Sep 17 00:00:00 2001 From: Allan LeSage Date: Tue, 6 Dec 2011 15:21:45 -0600 Subject: Added coverage reporting via gcov config and targets. --- Makefile.am | 35 +++++++++++++++++++++ configure.ac | 10 ++++++ libindicator/Makefile.am | 2 ++ m4/gcov.m4 | 82 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 129 insertions(+) create mode 100644 m4/gcov.m4 diff --git a/Makefile.am b/Makefile.am index 3bd312e..1cb279e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -40,3 +40,38 @@ dist-hook: echo Failed to generate AUTHORS: not a branch >&2; \ fi + +# Coverage targets + +.PHONY: clean-gcda +clean-gcda: + @echo Removing old coverage results + -find -name '*.gcda' -print | xargs -r rm + +.PHONY: coverage-html generate-coverage-html clean-coverage-html +coverage-html: clean-gcda + -$(MAKE) $(AM_MAKEFLAGS) -k check + $(MAKE) $(AM_MAKEFLAGS) generate-coverage-html + +generate-coverage-html: + @echo Collecting coverage data + $(LCOV) --directory $(top_builddir) --capture --output-file coverage.info --no-checksum --compat-libtool + LANG=C $(GENHTML) --prefix $(top_builddir) --output-directory coveragereport --title "Code Coverage" --legend --show-details coverage.info + +clean-coverage-html: clean-gcda + -$(LCOV) --directory $(top_builddir) -z + -rm -rf coverage.info coveragereport + +.PHONY: coverage-xml generate-coverage-xml clean-coverage-xml +coverage-xml: clean-gcda + -$(MAKE) $(AM_MAKEFLAGS) -k check + $(MAKE) $(AM_MAKEFLAGS) generate-coverage-xml + +generate-coverage-xml: + @echo Generating coverage XML report + $(GCOVR) -x -r $(top_builddir) -o $(top_builddir)/coverage.xml + +clean-coverage-xml: clean-gcda + -rm -rf $(top_builddir)/coverage.xml + +clean-local: clean-coverage-html clean-coverage-xml diff --git a/configure.ac b/configure.ac index 2357f13..42a476a 100644 --- a/configure.ac +++ b/configure.ac @@ -121,6 +121,15 @@ fi AM_CONDITIONAL(ENABLE_DEBUG, test "$enable_debug" = "yes") +########################### +# gcov coverage reporting +########################### +m4_include([m4/gcov.m4]) +AC_TDD_GCOV +AC_SUBST(COVERAGE_CFLAGS) +AC_SUBST(COVERAGE_CXXFLAGS) +AC_SUBST(COVERAGE_LDFLAGS) + ########################### # Files ########################### @@ -147,4 +156,5 @@ Libindicator Configuration: GTK+ Version: $with_gtk Enable debugging: $enable_debug + Coverage reporting: $use_gcov ]) diff --git a/libindicator/Makefile.am b/libindicator/Makefile.am index 53f9985..0f5ad34 100644 --- a/libindicator/Makefile.am +++ b/libindicator/Makefile.am @@ -55,6 +55,7 @@ libindicator_la_SOURCES = \ libindicator_la_CFLAGS = \ $(LIBINDICATOR_CFLAGS) \ + $(COVERAGE_CFLAGS) \ -DG_LOG_DOMAIN=\"libindicator\" \ -Wall -Werror @@ -62,6 +63,7 @@ libindicator_la_LIBADD = \ $(LIBINDICATOR_LIBS) libindicator_la_LDFLAGS = \ + $(COVERAGE_LDFLAGS) \ -version-info $(INDICATOR_ABI_VERSION):0:0 \ -no-undefined \ -export-symbols-regex "^[^_].*" diff --git a/m4/gcov.m4 b/m4/gcov.m4 new file mode 100644 index 0000000..9331cd3 --- /dev/null +++ b/m4/gcov.m4 @@ -0,0 +1,82 @@ +# Checks for existence of coverage tools: +# * gcov +# * lcov +# * genhtml +# * gcovr +# +# Sets ac_cv_check_gcov to yes if tooling is present +# and reports the executables to the variables LCOV, GCOVR and GENHTML. +AC_DEFUN([AC_TDD_GCOV], +[AC_CACHE_CHECK([whether code coverage tools are available], ac_cv_check_gcov, +[ +AC_ARG_ENABLE(gcov, + AS_HELP_STRING([--enable-gcov], + [enable coverage testing with gcov]), + [use_gcov=$enableval], [use_gcov=no]) + + if test "x$use_gcov" = "xyes"; then + # we need gcc: + if test "$GCC" != "yes"; then + AC_MSG_ERROR([GCC is required for --enable-gcov]) + fi + + # Check if ccache is being used + AC_CHECK_PROG(SHTOOL, shtool, shtool) + case `$SHTOOL path $CC` in + *ccache*[)] gcc_ccache=yes;; + *[)] gcc_ccache=no;; + esac + + if test "$gcc_ccache" = "yes" && (test -z "$CCACHE_DISABLE" || test "$CCACHE_DISABLE" != "1"); then + AC_MSG_ERROR([ccache must be disabled when --enable-gcov option is used. You can disable ccache by setting environment variable CCACHE_DISABLE=1.]) + fi + + lcov_version_list="1.6 1.7 1.8 1.9" + AC_CHECK_PROG(LCOV, lcov, lcov) + AC_CHECK_PROG(GENHTML, genhtml, genhtml) + AC_CHECK_PROG(GCOVR, gcovr, gcovr) + + if test "$LCOV"; then + AC_CACHE_CHECK([for lcov version], glib_cv_lcov_version, [ + glib_cv_lcov_version=invalid + lcov_version=`$LCOV -v 2>/dev/null | $SED -e 's/^.* //'` + for lcov_check_version in $lcov_version_list; do + if test "$lcov_version" = "$lcov_check_version"; then + glib_cv_lcov_version="$lcov_check_version (ok)" + fi + done + ]) + else + lcov_msg="To enable code coverage reporting you must have one of the following lcov versions installed: $lcov_version_list" + AC_MSG_ERROR([$lcov_msg]) + fi + + case $glib_cv_lcov_version in + ""|invalid[)] + lcov_msg="You must have one of the following versions of lcov: $lcov_version_list (found: $lcov_version)." + AC_MSG_ERROR([$lcov_msg]) + LCOV="exit 0;" + ;; + esac + + if test -z "$GENHTML"; then + AC_MSG_ERROR([Could not find genhtml from the lcov package]) + fi + + if test -z "$GCOVR"; then + AC_MSG_ERROR([Could not find gcovr; easy_install (or pip) gcovr]) + fi + + + # Remove all optimization flags from CFLAGS + changequote({,}) + CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9]*//g'` + changequote([,]) + + # Add the special gcc flags + COVERAGE_CFLAGS="-O0 -fprofile-arcs -ftest-coverage" + COVERAGE_CXXFLAGS="-O0 -fprofile-arcs -ftest-coverage" + COVERAGE_LDFLAGS="-lgcov" + +fi +])]) # AC_TDD_GCOV -- cgit v1.2.3 From d3392a98f7b2ceb1bb4fce4a41feed261012346d Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 12 Jan 2012 14:51:30 +0100 Subject: initial revision for GSettings/GtkMenu visibility support --- libindicator/indicator-desktop-shortcuts.c | 2 +- libindicator/indicator-object.c | 279 +++++++++++++++++++++++++++-- libindicator/indicator-object.h | 3 + 3 files changed, 272 insertions(+), 12 deletions(-) diff --git a/libindicator/indicator-desktop-shortcuts.c b/libindicator/indicator-desktop-shortcuts.c index 5d16cda..62bf504 100644 --- a/libindicator/indicator-desktop-shortcuts.c +++ b/libindicator/indicator-desktop-shortcuts.c @@ -369,7 +369,7 @@ should_show (GKeyFile * keyfile, const gchar * group, const gchar * identity, gb return TRUE; } -/* Looks through the nicks ot see if this one is in the list, +/* Looks through the nicks to see if this one is in the list, and thus valid to use. */ static gboolean is_valid_nick (gchar ** list, const gchar * nick) diff --git a/libindicator/indicator-object.c b/libindicator/indicator-object.c index bd056f0..f808f32 100644 --- a/libindicator/indicator-object.c +++ b/libindicator/indicator-object.c @@ -49,6 +49,10 @@ struct _IndicatorObjectPrivate { IndicatorObjectEntry entry; gboolean gotten_entries; + /* For indicator objects that monitor a GSettings schema-id */ + GSettings * gsettings; + gchar * gsettings_schema_id; + GStrv environments; }; @@ -67,6 +71,15 @@ enum { LAST_SIGNAL }; +/* Properties */ +/* Enum for the properties so that they can be quickly + found and looked up. */ +enum { + PROP_0, + PROP_SETTINGS_SCHEMA_ID, +}; + + static guint signals[LAST_SIGNAL] = { 0 }; /* GObject stuff */ @@ -74,8 +87,15 @@ static void indicator_object_class_init (IndicatorObjectClass *klass); static void indicator_object_init (IndicatorObject *self); static void indicator_object_dispose (GObject *object); static void indicator_object_finalize (GObject *object); +static void set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); +static void get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); +static void schema_clear (IndicatorObject * object); +static void schema_set (IndicatorObject * object, const char * schema_id); static GList * get_entries_default (IndicatorObject * io); +static GList * get_all_entries (IndicatorObject * io); + +static void stop_listening_for_menu_visibility_changes (IndicatorObject * io); G_DEFINE_TYPE (IndicatorObject, indicator_object, G_TYPE_OBJECT); @@ -84,12 +104,16 @@ G_DEFINE_TYPE (IndicatorObject, indicator_object, G_TYPE_OBJECT); static void indicator_object_class_init (IndicatorObjectClass *klass) { + GParamSpec * param_spec; GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (IndicatorObjectPrivate)); object_class->dispose = indicator_object_dispose; object_class->finalize = indicator_object_finalize; + object_class->set_property = set_property; + object_class->get_property = get_property; + klass->get_label = NULL; klass->get_menu = NULL; @@ -241,6 +265,13 @@ indicator_object_class_init (IndicatorObjectClass *klass) g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER, G_TYPE_NONE); + /* Properties */ + param_spec = g_param_spec_string (INDICATOR_OBJECT_GSETTINGS_SCHEMA_ID, + "gsettings-schema-id", + "The schema-id of the GSettings (if any) to monitor.", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_SETTINGS_SCHEMA_ID, param_spec); return; } @@ -263,6 +294,9 @@ indicator_object_init (IndicatorObject *self) self->priv->environments = NULL; + self->priv->gsettings = NULL; + self->priv->gsettings_schema_id = NULL; + return; } @@ -270,6 +304,10 @@ indicator_object_init (IndicatorObject *self) static void indicator_object_dispose (GObject *object) { + IndicatorObject * io = INDICATOR_OBJECT(object); + + schema_clear (io); + stop_listening_for_menu_visibility_changes (io); G_OBJECT_CLASS (indicator_object_parent_class)->dispose (object); return; @@ -463,14 +501,119 @@ get_entries_default (IndicatorObject * io) return g_list_append(NULL, &(priv->entry)); } +/* finds the IndicatorObjectEntry* which contains the specified menu */ +static IndicatorObjectEntry* +find_entry_from_menu (IndicatorObject * io, GtkMenu * menu) +{ + GList * l; + GList * all_entries; + static IndicatorObjectEntry * match = NULL; + + g_return_val_if_fail (GTK_IS_MENU(menu), NULL); + g_return_val_if_fail (INDICATOR_IS_OBJECT(io), NULL); + + all_entries = get_all_entries (io); + for (l=all_entries; l && !match; l=l->next) { + IndicatorObjectEntry * entry = l->data; + if (menu == entry->menu) + match = entry; + } + + g_list_free (all_entries); + return match; +} + +static void +on_menu_show(GtkMenu * menu, gpointer io) +{ + IndicatorObjectEntry * entry = find_entry_from_menu (io, menu); + g_return_if_fail (entry != NULL); + g_signal_emit_by_name (io, INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED, entry); +} + +static void +on_menu_hide(GtkMenu * menu, gpointer io) +{ + IndicatorObjectEntry * entry = find_entry_from_menu (io, menu); + g_return_if_fail (entry != NULL); + g_signal_emit_by_name (io, INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED, entry); +} + +static void +ensure_signal_handler_is_connected(GObject * o, const char * key, + const char * signal_name, + GCallback callback, gpointer user_data) +{ + if (g_object_get_data (o, key) == NULL) + { + gulong * handler_id = g_new(gulong, 1); + *handler_id = g_signal_connect (o, signal_name, callback, user_data); + g_object_set_data (o, key, handler_id); + } +} + +#define HIDE_SIGNAL_KEY "indicator-object-signal-handler-id-hide" +#define SHOW_SIGNAL_KEY "indicator-object-signal-handler-id-show" + +/* returns a list of all IndicatorObjectEntires whether they're visible or not */ +static GList* +get_all_entries (IndicatorObject * io) +{ + GList * l; + GList * all_entries; + + g_return_val_if_fail(INDICATOR_IS_OBJECT(io), NULL); + IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io); + + if (class->get_entries == NULL) + g_error("No get_entries function on object. It must have been deleted?!?!"); + + all_entries = class->get_entries(io); + + /* N.B. probably bad form to have side-effects in a simple accessor... + We're doing it this way to add visibility support without changing + before freeze. */ + for (l=all_entries; l!=NULL; l=l->next) { + IndicatorObjectEntry * entry = l->data; + GObject * o = G_OBJECT(entry->menu); + ensure_signal_handler_is_connected (o, HIDE_SIGNAL_KEY, "hide", G_CALLBACK(on_menu_hide), io); + ensure_signal_handler_is_connected (o, SHOW_SIGNAL_KEY, "show", G_CALLBACK(on_menu_show), io); + } + + return all_entries; +} + +static void +stop_listening_for_menu_visibility_changes (IndicatorObject * io) +{ + GList * l; + GList * entries = get_all_entries (io); + + for (l=entries; l!=NULL; l=l->next) + { + gulong * handler_id; + GObject * menu = G_OBJECT(((IndicatorObjectEntry*)l->data)->menu); + + if((handler_id = g_object_get_data(menu, SHOW_SIGNAL_KEY))) { + g_signal_handler_disconnect(menu, *handler_id); + g_free (handler_id); + } + + if((handler_id = g_object_get_data(menu, HIDE_SIGNAL_KEY))) { + g_signal_handler_disconnect(menu, *handler_id); + g_free (handler_id); + } + } +} + /** indicator_object_get_entries: @io: #IndicatorObject to query - This function looks on the class for the object and calls - it's #IndicatorObjectClass::get_entries function. The - list should be owned by the caller, but the individual - entries should not be. + This function calls the object's #IndicatorObjectClass::get_entries virtual + function, filters out invisible entries, and returns a GList of visible ones. + Callers should free the GList with g_list_free(), but the entries are owned + by the IndicatorObject and should not be freed. Return value: (element-type IndicatorObjectEntry) (transfer container): A list if #IndicatorObjectEntry structures or NULL if there is an error. @@ -478,15 +621,18 @@ get_entries_default (IndicatorObject * io) GList * indicator_object_get_entries (IndicatorObject * io) { - g_return_val_if_fail(INDICATOR_IS_OBJECT(io), NULL); - IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io); - - if (class->get_entries) { - return class->get_entries(io); + GList * l; + GList * visible_entries = NULL; + GList * all_entries = get_all_entries (io); + + for (l=all_entries; l!=NULL; l=l->next) { + IndicatorObjectEntry * entry = l->data; + if(gtk_widget_get_visible(GTK_WIDGET(entry->menu))) + visible_entries = g_list_append (visible_entries, entry); } - g_error("No get_entries function on object. It must have been deleted?!?!"); - return NULL; + g_list_free (all_entries); + return visible_entries; } /** @@ -654,3 +800,114 @@ indicator_object_check_environment (IndicatorObject * io, const gchar * env) return FALSE; } + +static void +get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) +{ + IndicatorObject * self = INDICATOR_OBJECT(object); + g_return_if_fail(self != NULL); + + IndicatorObjectPrivate * priv = INDICATOR_OBJECT_GET_PRIVATE(self); + g_return_if_fail(priv != NULL); + + switch (prop_id) { + /* *********************** */ + case PROP_SETTINGS_SCHEMA_ID: + if (G_VALUE_HOLDS_STRING(value)) { + g_value_set_string(value, priv->gsettings_schema_id); + } else { + g_warning("Name property requires a string value."); + } + break; + /* *********************** */ + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) +{ + IndicatorObject * self = INDICATOR_OBJECT(object); + g_return_if_fail (self != NULL); + + IndicatorObjectPrivate * priv = INDICATOR_OBJECT_GET_PRIVATE(self); + g_return_if_fail (priv != NULL); + + + switch (prop_id) { + + /* *********************** */ + case PROP_SETTINGS_SCHEMA_ID: + if (G_VALUE_HOLDS_STRING(value)) { + schema_set (self, g_value_get_string (value)); + } else { + g_warning("Name property requires a string value."); + } + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + return; +} + +static void +on_settings_changed (GSettings * gsettings, gchar * key, gpointer user_data) +{ + g_message ("settings changed: %s", key); + + if (!g_strcmp0 (key, "visible")) + { + const gboolean visible = g_settings_get_boolean (gsettings, key); + const char * signal_name = visible ? "entry-added" : "entry-removed"; + + IndicatorObject * self = INDICATOR_OBJECT (user_data); + GList * entries = indicator_object_get_entries (self); + GList * walk; + + for (walk=entries; walk!=NULL; walk=walk->next) { + g_signal_emit_by_name (self, signal_name, walk->data); + } + + g_list_free (entries); + } +} + +static void +schema_set (IndicatorObject * object, const char * gsettings_schema_id) +{ + schema_clear (object); + + IndicatorObjectPrivate * priv = INDICATOR_OBJECT_GET_PRIVATE(object); + g_return_if_fail (priv != NULL); + + priv->gsettings_schema_id = g_strdup (gsettings_schema_id); + if (priv->gsettings_schema_id != NULL) { + priv->gsettings = g_settings_new (priv->gsettings_schema_id); + if (priv->gsettings != NULL) { + g_signal_connect (G_OBJECT(priv->gsettings), "changed", G_CALLBACK(on_settings_changed), object); + g_debug ("indicator %p is listening for GSettings change events from %s", priv->gsettings, gsettings_schema_id); + } + } +} + +static void +schema_clear (IndicatorObject * self) +{ + IndicatorObjectPrivate * priv = INDICATOR_OBJECT_GET_PRIVATE(self); + g_return_if_fail (priv != NULL); + + if (priv->gsettings != NULL) { + g_object_unref (priv->gsettings); + priv->gsettings = NULL; + } + + if (priv->gsettings_schema_id != NULL) { + g_free (priv->gsettings_schema_id); + priv->gsettings_schema_id = NULL; + } +} diff --git a/libindicator/indicator-object.h b/libindicator/indicator-object.h index 3a120f5..51ca758 100644 --- a/libindicator/indicator-object.h +++ b/libindicator/indicator-object.h @@ -60,6 +60,9 @@ typedef enum #define INDICATOR_OBJECT_SIGNAL_SECONDARY_ACTIVATE "secondary-activate" #define INDICATOR_OBJECT_SIGNAL_SECONDARY_ACTIVATE_ID (g_signal_lookup(INDICATOR_OBJECT_SIGNAL_SECONDARY_ACTIVATE, INDICATOR_OBJECT_TYPE)) +/* the name of the GSettings schema-id property */ +#define INDICATOR_OBJECT_GSETTINGS_SCHEMA_ID "gsettings-schema-id" + typedef struct _IndicatorObject IndicatorObject; typedef struct _IndicatorObjectClass IndicatorObjectClass; typedef struct _IndicatorObjectPrivate IndicatorObjectPrivate; -- cgit v1.2.3 From c52fbaa41bd72b45341f751ba2a19e00c42a4b6d Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 13 Jan 2012 05:54:17 +0100 Subject: Better implementation. This version handles the bootstrapping conditions better, and also refs+detaches the GtkMenu for safekeeping between removed->added events s.t. it can keep being reused. --- libindicator/indicator-object.c | 340 ++++++++++++++++++++++++++-------------- libindicator/indicator-object.h | 6 +- 2 files changed, 227 insertions(+), 119 deletions(-) diff --git a/libindicator/indicator-object.c b/libindicator/indicator-object.c index f808f32..55082c7 100644 --- a/libindicator/indicator-object.c +++ b/libindicator/indicator-object.c @@ -30,6 +30,25 @@ License along with this library. If not, see #include "indicator-object-marshal.h" #include "indicator-object-enum-types.h" +/** + @ENTRY_INIT: The entry hasn't been initialized yet, so its + visibility will depend upon the inital-visibility property + and the 'visible' setting in the optional GSettings schema-id + @ENTRY_INVISIBLE: The entry has been initialized but is not visible + @ENTRY_VISIBLE: The entry is visible +*/ +typedef enum { + ENTRY_INIT, + ENTRY_INVISIBLE, + ENTRY_VISIBLE +} +EntryVisibility; + +typedef struct IndicatorObjectEntryPrivate { + EntryVisibility visibility; +} +IndicatorObjectEntryPrivate; + /** IndicatorObjectPrivate: @module: The loaded module representing the object. Note to @@ -53,11 +72,16 @@ struct _IndicatorObjectPrivate { GSettings * gsettings; gchar * gsettings_schema_id; + /* Whether or not entries are visible by default */ + gboolean default_visibility; + GHashTable * entry_privates; + GStrv environments; }; #define INDICATOR_OBJECT_GET_PRIVATE(o) (INDICATOR_OBJECT(o)->priv) + /* Signals Stuff */ enum { ENTRY_ADDED, @@ -76,7 +100,8 @@ enum { found and looked up. */ enum { PROP_0, - PROP_SETTINGS_SCHEMA_ID, + PROP_GSETTINGS_SCHEMA_ID, + PROP_DEFAULT_VISIBILITY, }; @@ -90,12 +115,16 @@ static void indicator_object_finalize (GObject *object); static void set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); +/* GSettings schema handling */ static void schema_clear (IndicatorObject * object); static void schema_set (IndicatorObject * object, const char * schema_id); -static GList * get_entries_default (IndicatorObject * io); -static GList * get_all_entries (IndicatorObject * io); -static void stop_listening_for_menu_visibility_changes (IndicatorObject * io); +/* entries' visibility */ +static GList * get_entries_default (IndicatorObject*); +static GList * get_all_entries (IndicatorObject*); +static void remove_all_entries_from_limbo (IndicatorObject*); +static void on_entry_added (IndicatorObject*, IndicatorObjectEntry*, gpointer); +static void on_entry_removed (IndicatorObject*, IndicatorObjectEntry*, gpointer); G_DEFINE_TYPE (IndicatorObject, indicator_object, G_TYPE_OBJECT); @@ -266,12 +295,20 @@ indicator_object_class_init (IndicatorObjectClass *klass) G_TYPE_NONE, 1, G_TYPE_POINTER, G_TYPE_NONE); /* Properties */ + param_spec = g_param_spec_string (INDICATOR_OBJECT_GSETTINGS_SCHEMA_ID, - "gsettings-schema-id", + "schema id", "The schema-id of the GSettings (if any) to monitor.", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_SETTINGS_SCHEMA_ID, param_spec); + g_object_class_install_property (object_class, PROP_GSETTINGS_SCHEMA_ID, param_spec); + + param_spec = g_param_spec_string (INDICATOR_OBJECT_DEFAULT_VISIBILITY, + "default visibility", + "The schema-id of the GSettings (if any) to monitor.", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_DEFAULT_VISIBILITY, param_spec); return; } @@ -291,13 +328,16 @@ indicator_object_init (IndicatorObject *self) self->priv->entry.name_hint = NULL; self->priv->gotten_entries = FALSE; + self->priv->default_visibility = TRUE; + self->priv->entry_privates = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); self->priv->environments = NULL; self->priv->gsettings = NULL; self->priv->gsettings_schema_id = NULL; - return; + g_signal_connect (G_OBJECT(self), INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED, G_CALLBACK(on_entry_removed), NULL); + g_signal_connect_after (G_OBJECT(self), INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED, G_CALLBACK(on_entry_added), NULL); } /* Unref the objects that we're holding on to. */ @@ -307,7 +347,10 @@ indicator_object_dispose (GObject *object) IndicatorObject * io = INDICATOR_OBJECT(object); schema_clear (io); - stop_listening_for_menu_visibility_changes (io); + remove_all_entries_from_limbo (io); + + if ((io->priv != NULL) && (io->priv->entry_privates != NULL)) + g_hash_table_destroy (io->priv->entry_privates); G_OBJECT_CLASS (indicator_object_parent_class)->dispose (object); return; @@ -501,117 +544,56 @@ get_entries_default (IndicatorObject * io) return g_list_append(NULL, &(priv->entry)); } -/* finds the IndicatorObjectEntry* which contains the specified menu */ -static IndicatorObjectEntry* -find_entry_from_menu (IndicatorObject * io, GtkMenu * menu) -{ - GList * l; - GList * all_entries; - static IndicatorObjectEntry * match = NULL; - - g_return_val_if_fail (GTK_IS_MENU(menu), NULL); - g_return_val_if_fail (INDICATOR_IS_OBJECT(io), NULL); - - all_entries = get_all_entries (io); - for (l=all_entries; l && !match; l=l->next) { - IndicatorObjectEntry * entry = l->data; - if (menu == entry->menu) - match = entry; - } - - g_list_free (all_entries); - return match; -} - -static void -on_menu_show(GtkMenu * menu, gpointer io) -{ - IndicatorObjectEntry * entry = find_entry_from_menu (io, menu); - g_return_if_fail (entry != NULL); - g_signal_emit_by_name (io, INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED, entry); -} - -static void -on_menu_hide(GtkMenu * menu, gpointer io) -{ - IndicatorObjectEntry * entry = find_entry_from_menu (io, menu); - g_return_if_fail (entry != NULL); - g_signal_emit_by_name (io, INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED, entry); -} - -static void -ensure_signal_handler_is_connected(GObject * o, const char * key, - const char * signal_name, - GCallback callback, gpointer user_data) -{ - if (g_object_get_data (o, key) == NULL) - { - gulong * handler_id = g_new(gulong, 1); - *handler_id = g_signal_connect (o, signal_name, callback, user_data); - g_object_set_data (o, key, handler_id); - } -} - -#define HIDE_SIGNAL_KEY "indicator-object-signal-handler-id-hide" -#define SHOW_SIGNAL_KEY "indicator-object-signal-handler-id-show" - /* returns a list of all IndicatorObjectEntires whether they're visible or not */ static GList* get_all_entries (IndicatorObject * io) { - GList * l; - GList * all_entries; - g_return_val_if_fail(INDICATOR_IS_OBJECT(io), NULL); IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io); if (class->get_entries == NULL) g_error("No get_entries function on object. It must have been deleted?!?!"); - all_entries = class->get_entries(io); + return class->get_entries(io); +} - /* N.B. probably bad form to have side-effects in a simple accessor... - We're doing it this way to add visibility support without changing - before freeze. */ - for (l=all_entries; l!=NULL; l=l->next) { - IndicatorObjectEntry * entry = l->data; - GObject * o = G_OBJECT(entry->menu); - ensure_signal_handler_is_connected (o, HIDE_SIGNAL_KEY, "hide", G_CALLBACK(on_menu_hide), io); - ensure_signal_handler_is_connected (o, SHOW_SIGNAL_KEY, "show", G_CALLBACK(on_menu_show), io); +IndicatorObjectEntryPrivate * +entry_get_private (IndicatorObject * io, IndicatorObjectEntry * entry) +{ + g_return_val_if_fail (INDICATOR_IS_OBJECT(io), NULL); + g_return_val_if_fail (io->priv != NULL, NULL); + + IndicatorObjectEntryPrivate * priv = g_hash_table_lookup (io->priv->entry_privates, entry); + if (priv == NULL) + { + priv = g_new0 (IndicatorObjectEntryPrivate, 1); + priv->visibility = ENTRY_INIT; + g_hash_table_insert (io->priv->entry_privates, entry, priv); } - return all_entries; + return priv; } -static void -stop_listening_for_menu_visibility_changes (IndicatorObject * io) +static gboolean +get_default_visibility (IndicatorObject * io) { - GList * l; - GList * entries = get_all_entries (io); - - for (l=entries; l!=NULL; l=l->next) - { - gulong * handler_id; - GObject * menu = G_OBJECT(((IndicatorObjectEntry*)l->data)->menu); + g_return_val_if_fail (INDICATOR_IS_OBJECT(io), FALSE); + IndicatorObjectPrivate * priv = INDICATOR_OBJECT_GET_PRIVATE(io); + g_return_val_if_fail (priv != NULL, FALSE); - if((handler_id = g_object_get_data(menu, SHOW_SIGNAL_KEY))) { - g_signal_handler_disconnect(menu, *handler_id); - g_free (handler_id); - } + if (priv->gsettings != NULL) + return g_settings_get_boolean (priv->gsettings, "visible"); - if((handler_id = g_object_get_data(menu, HIDE_SIGNAL_KEY))) { - g_signal_handler_disconnect(menu, *handler_id); - g_free (handler_id); - } - } + return priv->default_visibility; } /** indicator_object_get_entries: @io: #IndicatorObject to query - This function calls the object's #IndicatorObjectClass::get_entries virtual - function, filters out invisible entries, and returns a GList of visible ones. + This function returns a list of visible entries. The list is built by calling + the object's #IndicatorObjectClass::get_entries virtual function and testing + each of the results for visibility. Callers should free the GList with g_list_free(), but the entries are owned by the IndicatorObject and should not be freed. @@ -622,17 +604,27 @@ GList * indicator_object_get_entries (IndicatorObject * io) { GList * l; - GList * visible_entries = NULL; + GList * ret = NULL; GList * all_entries = get_all_entries (io); - for (l=all_entries; l!=NULL; l=l->next) { + for (l=all_entries; l!=NULL; l=l->next) + { + gboolean show_me; IndicatorObjectEntry * entry = l->data; - if(gtk_widget_get_visible(GTK_WIDGET(entry->menu))) - visible_entries = g_list_append (visible_entries, entry); + IndicatorObjectEntryPrivate * entry_priv = entry_get_private (io, entry); + + switch (entry_priv->visibility) { + case ENTRY_VISIBLE: show_me = TRUE; break; + case ENTRY_INVISIBLE: show_me = FALSE; break; + default /*ENTRY_INIT*/: show_me = get_default_visibility (io); break; + } + + if (show_me) + ret = g_list_append (ret, entry); } g_list_free (all_entries); - return visible_entries; + return ret; } /** @@ -801,6 +793,29 @@ indicator_object_check_environment (IndicatorObject * io, const gchar * env) return FALSE; } +/** + indicator_object_set_visible: + @io: #IndicatorObject to check on + @visible: whether or not the entries should be visible + + Used to set all of an indicator's entries to be visible or hidden. +*/ +void +indicator_object_set_visible (IndicatorObject * io, gboolean visible) +{ + GList * l; + GList * entries; + const char * signal_name = visible ? INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED + : INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED; + + g_return_if_fail(INDICATOR_IS_OBJECT(io)); + + entries = get_all_entries (io); + for (l=entries; l!=NULL; l=l->next) + g_signal_emit_by_name (io, signal_name, l->data); + g_list_free (entries); +} + static void get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { @@ -812,11 +827,19 @@ get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspe switch (prop_id) { /* *********************** */ - case PROP_SETTINGS_SCHEMA_ID: + case PROP_GSETTINGS_SCHEMA_ID: if (G_VALUE_HOLDS_STRING(value)) { g_value_set_string(value, priv->gsettings_schema_id); } else { - g_warning("Name property requires a string value."); + g_warning("schema-id property requires a string value."); + } + break; + /* *********************** */ + case PROP_DEFAULT_VISIBILITY: + if (G_VALUE_HOLDS_BOOLEAN(value)) { + g_value_set_boolean(value, priv->default_visibility); + } else { + g_warning("default-visibility property requires a boolean value."); } break; /* *********************** */ @@ -839,14 +862,24 @@ set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec switch (prop_id) { /* *********************** */ - case PROP_SETTINGS_SCHEMA_ID: + case PROP_GSETTINGS_SCHEMA_ID: if (G_VALUE_HOLDS_STRING(value)) { schema_set (self, g_value_get_string (value)); } else { - g_warning("Name property requires a string value."); + g_warning("schema-id property requires a string value."); + } + break; + + /* *********************** */ + case PROP_DEFAULT_VISIBILITY: + if (G_VALUE_HOLDS_BOOLEAN(value)) { + priv->default_visibility = g_value_get_boolean (value); + } else { + g_warning("default-visibility property requires a boolean value."); } break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -858,23 +891,12 @@ set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec static void on_settings_changed (GSettings * gsettings, gchar * key, gpointer user_data) { - g_message ("settings changed: %s", key); - if (!g_strcmp0 (key, "visible")) { + IndicatorObject * io = INDICATOR_OBJECT (user_data); const gboolean visible = g_settings_get_boolean (gsettings, key); - const char * signal_name = visible ? "entry-added" : "entry-removed"; - - IndicatorObject * self = INDICATOR_OBJECT (user_data); - GList * entries = indicator_object_get_entries (self); - GList * walk; - - for (walk=entries; walk!=NULL; walk=walk->next) { - g_signal_emit_by_name (self, signal_name, walk->data); - } - - g_list_free (entries); - } + indicator_object_set_visible (io, visible); + } } static void @@ -911,3 +933,85 @@ schema_clear (IndicatorObject * self) priv->gsettings_schema_id = NULL; } } + +/*** +**** +**** +***/ + +#define LIMBO_REF_KEY "indicator-object-entry-limbo-key" + +/* Limbo is an idiom private to indicator-object.c + It is for entries which have been removed and are waiting to be re-added later */ + +static void +remove_widget_from_limbo (gpointer w) +{ + if (w != NULL) { + GObject * o = G_OBJECT(w); + + if (g_object_get_data(o, LIMBO_REF_KEY)) { + g_object_steal_data (o, LIMBO_REF_KEY); + g_object_unref (o); + } + } +} + +static void +remove_entry_from_limbo (IndicatorObject * io, IndicatorObjectEntry * entry) +{ + IndicatorObjectEntryPrivate * entry_priv = entry_get_private (io, entry); + + entry_priv->visibility = ENTRY_INVISIBLE; + + remove_widget_from_limbo (entry->image); + remove_widget_from_limbo (entry->label); + remove_widget_from_limbo (entry->menu); +} + +static void +remove_all_entries_from_limbo (IndicatorObject * io) +{ + GList * l; + GList * entries = get_all_entries(io); + for (l=entries; l!=NULL; l=l->next) + remove_entry_from_limbo (io, l->data); + g_list_free (entries); +} + +static void +on_entry_added (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer unused G_GNUC_UNUSED) +{ + remove_entry_from_limbo (io, entry); +} + +/* The panels like to destroy an entry's widgetry when it's removed. + Protect the image, label, and menu for safekeeping in case we ever + need to add it back again. */ +static void +put_widget_in_limbo (gpointer w) +{ + if (w != NULL) { + GtkWidget * parent; + + g_object_ref (G_OBJECT(w)); + g_object_set_data (G_OBJECT(w), LIMBO_REF_KEY, GINT_TO_POINTER(1)); + + if(GTK_IS_MENU(w)) + gtk_menu_detach (GTK_MENU(w)); + else if((parent = gtk_widget_get_parent(w))) + gtk_container_remove(GTK_CONTAINER(parent), w); + } +} + +static void +on_entry_removed (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer unused G_GNUC_UNUSED) +{ + IndicatorObjectEntryPrivate * entry_priv = entry_get_private (io, entry); + + entry_priv->visibility = ENTRY_VISIBLE; + + put_widget_in_limbo (entry->image); + put_widget_in_limbo (entry->label); + put_widget_in_limbo (entry->menu); +} diff --git a/libindicator/indicator-object.h b/libindicator/indicator-object.h index 51ca758..a46600f 100644 --- a/libindicator/indicator-object.h +++ b/libindicator/indicator-object.h @@ -61,7 +61,10 @@ typedef enum #define INDICATOR_OBJECT_SIGNAL_SECONDARY_ACTIVATE_ID (g_signal_lookup(INDICATOR_OBJECT_SIGNAL_SECONDARY_ACTIVATE, INDICATOR_OBJECT_TYPE)) /* the name of the GSettings schema-id property */ -#define INDICATOR_OBJECT_GSETTINGS_SCHEMA_ID "gsettings-schema-id" +#define INDICATOR_OBJECT_GSETTINGS_SCHEMA_ID "indicator-object-gsettings-schema-id" + +/* the name of the property to decide whether or not entries are visible by default */ +#define INDICATOR_OBJECT_DEFAULT_VISIBILITY "indicator-object-default-visibility" typedef struct _IndicatorObject IndicatorObject; typedef struct _IndicatorObjectClass IndicatorObjectClass; @@ -186,6 +189,7 @@ IndicatorObject * indicator_object_new_from_file (const gchar * file); GList * indicator_object_get_entries (IndicatorObject * io); guint indicator_object_get_location (IndicatorObject * io, IndicatorObjectEntry * entry); guint indicator_object_get_show_now (IndicatorObject * io, IndicatorObjectEntry * entry); +void indicator_object_set_visible (IndicatorObject * io, gboolean visible); void indicator_object_entry_activate (IndicatorObject * io, IndicatorObjectEntry * entry, guint timestamp); void indicator_object_entry_close (IndicatorObject * io, IndicatorObjectEntry * entry, guint timestamp); -- cgit v1.2.3 From 976209fbb36c9b09a59c8d51da80ae065cca8192 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 13 Jan 2012 13:04:25 +0100 Subject: Ignoring all the stuff we build --- .bzrignore | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.bzrignore b/.bzrignore index 5f78c4a..0874106 100644 --- a/.bzrignore +++ b/.bzrignore @@ -172,3 +172,10 @@ libindicator/s-enum-types-h libindicator/gen-indicator-service.xml.c libindicator/gen-indicator-service.xml.h libindicator/libindicator_la-gen-indicator-service.xml.lo +libindicator/indicator-0.4.pc.in +libindicator/indicator3-0.4.pc +libindicator/indicator3-0.4.pc.in +libindicator/libindicator3_la-gen-indicator-service.xml.lo +tools/indicator-loader3 +libindicator-[0-9]*.[0-9]*.[0-9]* +build-aux -- cgit v1.2.3 From 2bb19db591c96af488d90ec184ea458230a2c471 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 13 Jan 2012 15:01:01 +0100 Subject: Adding an activate window function, that can also be virtual! --- libindicator/indicator-object.c | 8 ++++++++ libindicator/indicator-object.h | 2 ++ 2 files changed, 10 insertions(+) diff --git a/libindicator/indicator-object.c b/libindicator/indicator-object.c index bd056f0..7cb75ae 100644 --- a/libindicator/indicator-object.c +++ b/libindicator/indicator-object.c @@ -538,6 +538,14 @@ indicator_object_get_show_now (IndicatorObject * io, IndicatorObjectEntry * entr return FALSE; } +void +indicator_object_entry_activate_window (IndicatorObject * io, IndicatorObjectEntry * entry, guint windowid, guint timestamp) +{ + + + return; +} + /** indicator_object_entry_activate: @io: #IndicatorObject to query diff --git a/libindicator/indicator-object.h b/libindicator/indicator-object.h index 3a120f5..bbc215a 100644 --- a/libindicator/indicator-object.h +++ b/libindicator/indicator-object.h @@ -118,6 +118,7 @@ struct _IndicatorObjectClass { gboolean (*get_show_now) (IndicatorObject * io, IndicatorObjectEntry * entry); void (*entry_activate) (IndicatorObject * io, IndicatorObjectEntry * entry, guint timestamp); + void (*entry_activate_window) (IndicatorObject * io, IndicatorObjectEntry * entry, guint windowid, guint timestamp); void (*entry_close) (IndicatorObject * io, IndicatorObjectEntry * entry, guint timestamp); /* Signals */ @@ -184,6 +185,7 @@ GList * indicator_object_get_entries (IndicatorObject * io); guint indicator_object_get_location (IndicatorObject * io, IndicatorObjectEntry * entry); guint indicator_object_get_show_now (IndicatorObject * io, IndicatorObjectEntry * entry); void indicator_object_entry_activate (IndicatorObject * io, IndicatorObjectEntry * entry, guint timestamp); +void indicator_object_entry_activate_window (IndicatorObject * io, IndicatorObjectEntry * entry, guint windowid, guint timestamp); void indicator_object_entry_close (IndicatorObject * io, IndicatorObjectEntry * entry, guint timestamp); void indicator_object_set_environment (IndicatorObject * io, const GStrv env); -- cgit v1.2.3 From a6ed65aead78749086a67f92f53252b82c1bfc3d Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 13 Jan 2012 15:07:18 +0100 Subject: Documenting what this stuff does --- libindicator/indicator-object.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/libindicator/indicator-object.c b/libindicator/indicator-object.c index 7cb75ae..e606077 100644 --- a/libindicator/indicator-object.c +++ b/libindicator/indicator-object.c @@ -538,6 +538,22 @@ indicator_object_get_show_now (IndicatorObject * io, IndicatorObjectEntry * entr return FALSE; } +/** + indicator_object_entry_activate_window: + @io: #IndicatorObject to query + @entry: The #IndicatorObjectEntry whose entry was shown + @windowid: ID of the window that is currently focused (or will + be very shortly) + @timestamp: The X11 timestamp of the event + + Used to signal to the indicator that the menu on an entry has + been clicked on. This can either be an activate or a showing + of the menu. Also includes a window ID so that we can know what + application is going to be getting focused soon. If there is + no override of this function, it is the same as calling + indicator_object_entry_activate and in general is preferable + if you have that information available. +*/ void indicator_object_entry_activate_window (IndicatorObject * io, IndicatorObjectEntry * entry, guint windowid, guint timestamp) { -- cgit v1.2.3 From a88097a93dcbd513d2d03d699c396e7b99ed4494 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 13 Jan 2012 15:25:42 +0100 Subject: Handling the activate_window function and going up the stack --- libindicator/indicator-object.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libindicator/indicator-object.c b/libindicator/indicator-object.c index e606077..1fad637 100644 --- a/libindicator/indicator-object.c +++ b/libindicator/indicator-object.c @@ -557,7 +557,14 @@ indicator_object_get_show_now (IndicatorObject * io, IndicatorObjectEntry * entr void indicator_object_entry_activate_window (IndicatorObject * io, IndicatorObjectEntry * entry, guint windowid, guint timestamp) { + g_return_if_fail(INDICATOR_IS_OBJECT(io)); + IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io); + if (class->entry_activate_window != NULL) { + return class->entry_activate_window(io, entry, windowid, timestamp); + } else { + indicator_object_entry_activate(io, entry, timestamp); + } return; } -- cgit v1.2.3 From 0419bac431d9820e3e611aeb2d95f3a6d2caf258 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 13 Jan 2012 15:34:48 +0100 Subject: Clearing the entry function pointers --- libindicator/indicator-object.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libindicator/indicator-object.c b/libindicator/indicator-object.c index 1fad637..7a3e393 100644 --- a/libindicator/indicator-object.c +++ b/libindicator/indicator-object.c @@ -99,6 +99,10 @@ indicator_object_class_init (IndicatorObjectClass *klass) klass->get_entries = get_entries_default; klass->get_location = NULL; + klass->entry_activate = NULL; + klass->entry_activate_window = NULL; + klass->entry_close = NULL; + /** IndicatorObject::entry-added: @arg0: The #IndicatorObject object -- cgit v1.2.3 From 68c166698b604451b1f14280c14838d4461121b2 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 13 Jan 2012 16:38:58 +0100 Subject: Build a new dummy indicator --- .bzrignore | 2 + tests/Makefile.am | 23 ++++++- tests/dummy-indicator-entry-func.c | 123 +++++++++++++++++++++++++++++++++++++ 3 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 tests/dummy-indicator-entry-func.c diff --git a/.bzrignore b/.bzrignore index 0874106..7da05f5 100644 --- a/.bzrignore +++ b/.bzrignore @@ -179,3 +179,5 @@ libindicator/libindicator3_la-gen-indicator-service.xml.lo tools/indicator-loader3 libindicator-[0-9]*.[0-9]*.[0-9]* build-aux +libdummy_indicator_entry_func_la-dummy-indicator-entry-func.lo +libdummy-indicator-entry-func.la diff --git a/tests/Makefile.am b/tests/Makefile.am index f11a9d1..9d16748 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -14,7 +14,8 @@ lib_LTLIBRARIES = \ libdummy-indicator-blank.la \ libdummy-indicator-null.la \ libdummy-indicator-signaler.la \ - libdummy-indicator-simple.la + libdummy-indicator-simple.la \ + libdummy-indicator-entry-func.la DBUS_RUNNER=dbus-test-runner --dbus-config /usr/share/dbus-test-runner/session.conf XVFB_RUN=". $(srcdir)/run-xvfb.sh" @@ -161,6 +162,26 @@ libdummy_indicator_simple_la_LDFLAGS = \ -module \ -avoid-version +############################# +# Dummy Indicator Entry Func +############################# + +libdummy_indicator_entry_func_la_SOURCES = \ + dummy-indicator-entry-func.c + +libdummy_indicator_entry_func_la_CFLAGS = \ + -Wall -Werror \ + $(LIBINDICATOR_CFLAGS) -I$(top_srcdir) + +libdummy_indicator_entry_func_la_LIBADD = \ + $(LIBINDICATOR_LIBS) \ + -L$(top_builddir)/libindicator/.libs \ + $(INDICATOR_LIB) + +libdummy_indicator_entry_func_la_LDFLAGS = \ + -module \ + -avoid-version + ############################# # Service Shutdown Timeout ############################# diff --git a/tests/dummy-indicator-entry-func.c b/tests/dummy-indicator-entry-func.c new file mode 100644 index 0000000..7271e86 --- /dev/null +++ b/tests/dummy-indicator-entry-func.c @@ -0,0 +1,123 @@ +/* +Test for libindicator + +Copyright 2012 Canonical Ltd. + +Authors: + Ted Gould + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +version 3.0 as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License version 3.0 for more details. + +You should have received a copy of the GNU General Public +License along with this library. If not, see +. +*/ + + +#include +#include + +#include "libindicator/indicator.h" +#include "libindicator/indicator-object.h" + +#define DUMMY_INDICATOR_ENTRY_FUNC_TYPE (dummy_indicator_entry_func_get_type ()) +#define DUMMY_INDICATOR_ENTRY_FUNC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DUMMY_INDICATOR_ENTRY_FUNC_TYPE, DummyIndicatorEntryFunc)) +#define DUMMY_INDICATOR_ENTRY_FUNC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DUMMY_INDICATOR_ENTRY_FUNC_TYPE, DummyIndicatorEntryFuncClass)) +#define IS_DUMMY_INDICATOR_ENTRY_FUNC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DUMMY_INDICATOR_ENTRY_FUNC_TYPE)) +#define IS_DUMMY_INDICATOR_ENTRY_FUNC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DUMMY_INDICATOR_ENTRY_FUNC_TYPE)) +#define DUMMY_INDICATOR_ENTRY_FUNC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DUMMY_INDICATOR_ENTRY_FUNC_TYPE, DummyIndicatorEntryFuncClass)) + +typedef struct _DummyIndicatorEntryFunc DummyIndicatorEntryFunc; +typedef struct _DummyIndicatorEntryFuncClass DummyIndicatorEntryFuncClass; + +struct _DummyIndicatorEntryFuncClass { + IndicatorObjectClass parent_class; +}; + +struct _DummyIndicatorEntryFunc { + IndicatorObject parent; +}; + +GType dummy_indicator_entry_func_get_type (void); + +INDICATOR_SET_VERSION +INDICATOR_SET_TYPE(DUMMY_INDICATOR_ENTRY_FUNC_TYPE) + + +GtkLabel * +get_label (IndicatorObject * io) +{ + return NULL; +} + +GtkImage * +get_icon (IndicatorObject * io) +{ + return NULL; +} + +GtkMenu * +get_menu (IndicatorObject * io) +{ + return NULL; +} +const gchar * +get_accessible_desc (IndicatorObject * io) +{ + return NULL; +} + +static void dummy_indicator_entry_func_class_init (DummyIndicatorEntryFuncClass *klass); +static void dummy_indicator_entry_func_init (DummyIndicatorEntryFunc *self); +static void dummy_indicator_entry_func_dispose (GObject *object); +static void dummy_indicator_entry_func_finalize (GObject *object); + +G_DEFINE_TYPE (DummyIndicatorEntryFunc, dummy_indicator_entry_func, INDICATOR_OBJECT_TYPE); + +static void +dummy_indicator_entry_func_class_init (DummyIndicatorEntryFuncClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = dummy_indicator_entry_func_dispose; + object_class->finalize = dummy_indicator_entry_func_finalize; + + IndicatorObjectClass * io_class = INDICATOR_OBJECT_CLASS(klass); + + io_class->get_label = get_label; + io_class->get_image = get_icon; + io_class->get_menu = get_menu; + io_class->get_accessible_desc = get_accessible_desc; + + return; +} + +static void +dummy_indicator_entry_func_init (DummyIndicatorEntryFunc *self) +{ + + return; +} + +static void +dummy_indicator_entry_func_dispose (GObject *object) +{ + + G_OBJECT_CLASS (dummy_indicator_entry_func_parent_class)->dispose (object); + return; +} + +static void +dummy_indicator_entry_func_finalize (GObject *object) +{ + + G_OBJECT_CLASS (dummy_indicator_entry_func_parent_class)->finalize (object); + return; +} -- cgit v1.2.3 From 347ab41628cd47e996663d47244749d2d9fa1ea7 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 13 Jan 2012 16:48:52 +0100 Subject: Moving things into a shared header --- tests/dummy-indicator-entry-func.c | 24 +----------------- tests/dummy-indicator-entry-func.h | 52 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 23 deletions(-) create mode 100644 tests/dummy-indicator-entry-func.h diff --git a/tests/dummy-indicator-entry-func.c b/tests/dummy-indicator-entry-func.c index 7271e86..76d8605 100644 --- a/tests/dummy-indicator-entry-func.c +++ b/tests/dummy-indicator-entry-func.c @@ -20,30 +20,8 @@ License along with this library. If not, see . */ +#include "dummy-indicator-entry-func.h" -#include -#include - -#include "libindicator/indicator.h" -#include "libindicator/indicator-object.h" - -#define DUMMY_INDICATOR_ENTRY_FUNC_TYPE (dummy_indicator_entry_func_get_type ()) -#define DUMMY_INDICATOR_ENTRY_FUNC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DUMMY_INDICATOR_ENTRY_FUNC_TYPE, DummyIndicatorEntryFunc)) -#define DUMMY_INDICATOR_ENTRY_FUNC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DUMMY_INDICATOR_ENTRY_FUNC_TYPE, DummyIndicatorEntryFuncClass)) -#define IS_DUMMY_INDICATOR_ENTRY_FUNC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DUMMY_INDICATOR_ENTRY_FUNC_TYPE)) -#define IS_DUMMY_INDICATOR_ENTRY_FUNC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DUMMY_INDICATOR_ENTRY_FUNC_TYPE)) -#define DUMMY_INDICATOR_ENTRY_FUNC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DUMMY_INDICATOR_ENTRY_FUNC_TYPE, DummyIndicatorEntryFuncClass)) - -typedef struct _DummyIndicatorEntryFunc DummyIndicatorEntryFunc; -typedef struct _DummyIndicatorEntryFuncClass DummyIndicatorEntryFuncClass; - -struct _DummyIndicatorEntryFuncClass { - IndicatorObjectClass parent_class; -}; - -struct _DummyIndicatorEntryFunc { - IndicatorObject parent; -}; GType dummy_indicator_entry_func_get_type (void); diff --git a/tests/dummy-indicator-entry-func.h b/tests/dummy-indicator-entry-func.h new file mode 100644 index 0000000..1134ee7 --- /dev/null +++ b/tests/dummy-indicator-entry-func.h @@ -0,0 +1,52 @@ +/* +Test for libindicator + +Copyright 2012 Canonical Ltd. + +Authors: + Ted Gould + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +version 3.0 as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License version 3.0 for more details. + +You should have received a copy of the GNU General Public +License along with this library. If not, see +. +*/ + +#ifndef __DUMMY_INDICATOR_ENTRY_FUNC__ +#define __DUMMY_INDICATOR_ENTRY_FUNC__ + +#include +#include + +#include "libindicator/indicator.h" +#include "libindicator/indicator-object.h" + +G_BEGIN_DECLS + +#define DUMMY_INDICATOR_ENTRY_FUNC_TYPE (dummy_indicator_entry_func_get_type ()) +#define DUMMY_INDICATOR_ENTRY_FUNC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DUMMY_INDICATOR_ENTRY_FUNC_TYPE, DummyIndicatorEntryFunc)) +#define DUMMY_INDICATOR_ENTRY_FUNC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DUMMY_INDICATOR_ENTRY_FUNC_TYPE, DummyIndicatorEntryFuncClass)) +#define IS_DUMMY_INDICATOR_ENTRY_FUNC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DUMMY_INDICATOR_ENTRY_FUNC_TYPE)) +#define IS_DUMMY_INDICATOR_ENTRY_FUNC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DUMMY_INDICATOR_ENTRY_FUNC_TYPE)) +#define DUMMY_INDICATOR_ENTRY_FUNC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DUMMY_INDICATOR_ENTRY_FUNC_TYPE, DummyIndicatorEntryFuncClass)) + +typedef struct _DummyIndicatorEntryFunc DummyIndicatorEntryFunc; +typedef struct _DummyIndicatorEntryFuncClass DummyIndicatorEntryFuncClass; + +struct _DummyIndicatorEntryFuncClass { + IndicatorObjectClass parent_class; +}; + +struct _DummyIndicatorEntryFunc { + IndicatorObject parent; +}; + +#endif /* __DUMMY_INDICATOR_ENTRY_FUNC__ */ -- cgit v1.2.3 From 530b2112773545b4449879ef45118e1469946a22 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 13 Jan 2012 16:52:42 +0100 Subject: Adding some public values to know if functions were called --- tests/dummy-indicator-entry-func.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/dummy-indicator-entry-func.h b/tests/dummy-indicator-entry-func.h index 1134ee7..f5c8264 100644 --- a/tests/dummy-indicator-entry-func.h +++ b/tests/dummy-indicator-entry-func.h @@ -47,6 +47,10 @@ struct _DummyIndicatorEntryFuncClass { struct _DummyIndicatorEntryFunc { IndicatorObject parent; + + gboolean entry_activate_called; + gboolean entry_activate_window_called; + gboolean entry_close_called; }; #endif /* __DUMMY_INDICATOR_ENTRY_FUNC__ */ -- cgit v1.2.3 From efcb3e654caba19ade1dbe905eb9ae8526f08791 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Fri, 13 Jan 2012 17:00:47 +0100 Subject: Setting up entry functions --- tests/dummy-indicator-entry-func.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/dummy-indicator-entry-func.c b/tests/dummy-indicator-entry-func.c index 76d8605..bccd818 100644 --- a/tests/dummy-indicator-entry-func.c +++ b/tests/dummy-indicator-entry-func.c @@ -52,6 +52,28 @@ get_accessible_desc (IndicatorObject * io) return NULL; } +static void +entry_activate (IndicatorObject * io, IndicatorObjectEntry * entry, guint timestamp) +{ + + return; +} + +static void +entry_activate_window (IndicatorObject * io, IndicatorObjectEntry * entry, guint windowid, guint timestamp) +{ + + return; +} + +static void +entry_close (IndicatorObject * io, IndicatorObjectEntry * entry, guint timestamp) +{ + + return; +} + + static void dummy_indicator_entry_func_class_init (DummyIndicatorEntryFuncClass *klass); static void dummy_indicator_entry_func_init (DummyIndicatorEntryFunc *self); static void dummy_indicator_entry_func_dispose (GObject *object); @@ -74,6 +96,10 @@ dummy_indicator_entry_func_class_init (DummyIndicatorEntryFuncClass *klass) io_class->get_menu = get_menu; io_class->get_accessible_desc = get_accessible_desc; + io_class->entry_activate = entry_activate; + io_class->entry_activate_window = entry_activate_window; + io_class->entry_close = entry_close; + return; } -- cgit v1.2.3 From b7c8a634f190e176b1d3b201ff08d861ba5e265b Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Sat, 14 Jan 2012 10:07:43 +0100 Subject: Mark the entry functions as called --- tests/dummy-indicator-entry-func.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/dummy-indicator-entry-func.c b/tests/dummy-indicator-entry-func.c index bccd818..96e5ad0 100644 --- a/tests/dummy-indicator-entry-func.c +++ b/tests/dummy-indicator-entry-func.c @@ -55,21 +55,24 @@ get_accessible_desc (IndicatorObject * io) static void entry_activate (IndicatorObject * io, IndicatorObjectEntry * entry, guint timestamp) { - + DummyIndicatorEntryFunc * self = DUMMY_INDICATOR_ENTRY_FUNC(io); + self->entry_activate_called = TRUE; return; } static void entry_activate_window (IndicatorObject * io, IndicatorObjectEntry * entry, guint windowid, guint timestamp) { - + DummyIndicatorEntryFunc * self = DUMMY_INDICATOR_ENTRY_FUNC(io); + self->entry_activate_window_called = TRUE; return; } static void entry_close (IndicatorObject * io, IndicatorObjectEntry * entry, guint timestamp) { - + DummyIndicatorEntryFunc * self = DUMMY_INDICATOR_ENTRY_FUNC(io); + self->entry_close_called = TRUE; return; } -- cgit v1.2.3 From 7586398a88487db955504cce8d348a65f95d4c22 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Sat, 14 Jan 2012 10:30:22 +0100 Subject: Adding a test functioin for the entry func demmy indicator --- tests/Makefile.am | 2 +- tests/test-loader.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index 9d16748..13a34c4 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -433,7 +433,7 @@ DISTCLEANFILES += service-manager-connect-nostart-tester XML_REPORT = loader-check-results.xml HTML_REPORT = loader-check-results.html -loader-tester: test-loader libdummy-indicator-null.la libdummy-indicator-simple.la Makefile +loader-tester: test-loader libdummy-indicator-null.la libdummy-indicator-simple.la libdummy-indicator-entry-func.la Makefile @echo "#!/bin/bash" > loader-tester @echo $(XVFB_RUN) >> $@ @echo gtester -k --verbose -o=$(XML_REPORT) ./test-loader >> loader-tester diff --git a/tests/test-loader.c b/tests/test-loader.c index ac9d4e5..3adce3b 100644 --- a/tests/test-loader.c +++ b/tests/test-loader.c @@ -23,6 +23,34 @@ License along with this library. If not, see #include #include "libindicator/indicator-object.h" +#include "dummy-indicator-entry-func.h" + +void +test_loader_entry_funcs (void) +{ + IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-entry-func.so"); + g_assert(object != NULL); + + DummyIndicatorEntryFunc * entryfunc = (DummyIndicatorEntryFunc *)(object); + + entryfunc->entry_activate_called = FALSE; + entryfunc->entry_activate_window_called = FALSE; + entryfunc->entry_close_called = FALSE; + + indicator_object_entry_activate(object, NULL, 0); + g_assert(entryfunc->entry_activate_called); + + indicator_object_entry_activate_window(object, NULL, 0, 0); + g_assert(entryfunc->entry_activate_window_called); + + indicator_object_entry_close(object, NULL, 0); + g_assert(entryfunc->entry_close_called); + + g_object_unref(object); + + return; +} + void destroy_cb (gpointer data, GObject * object); void @@ -174,6 +202,7 @@ test_loader_creation_deletion_suite (void) g_test_add_func ("/libindicator/loader/dummy/simple_accessors", test_loader_filename_dummy_simple_accessors); g_test_add_func ("/libindicator/loader/dummy/simple_location", test_loader_filename_dummy_simple_location); g_test_add_func ("/libindicator/loader/dummy/signaler", test_loader_filename_dummy_signaler); + g_test_add_func ("/libindicator/loader/dummy/entry_funcs", test_loader_entry_funcs); return; } -- cgit v1.2.3 From da798a2bfc8d4b1068eb1e9a1ec502cad09c59ac Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Sat, 14 Jan 2012 10:33:29 +0100 Subject: Getting the header in dist --- tests/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Makefile.am b/tests/Makefile.am index 13a34c4..c8a9ba7 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -167,7 +167,8 @@ libdummy_indicator_simple_la_LDFLAGS = \ ############################# libdummy_indicator_entry_func_la_SOURCES = \ - dummy-indicator-entry-func.c + dummy-indicator-entry-func.c \ + dummy-indicator-entry-func.h libdummy_indicator_entry_func_la_CFLAGS = \ -Wall -Werror \ -- cgit v1.2.3 From 2dfe3fff249cd22eea6a993dc5ec50b129d961f1 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Sat, 14 Jan 2012 10:51:55 +0100 Subject: Add a function to swap out the window entry handler --- tests/dummy-indicator-entry-func.c | 14 ++++++++++++++ tests/dummy-indicator-entry-func.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/tests/dummy-indicator-entry-func.c b/tests/dummy-indicator-entry-func.c index 96e5ad0..ac330aa 100644 --- a/tests/dummy-indicator-entry-func.c +++ b/tests/dummy-indicator-entry-func.c @@ -128,3 +128,17 @@ dummy_indicator_entry_func_finalize (GObject *object) G_OBJECT_CLASS (dummy_indicator_entry_func_parent_class)->finalize (object); return; } + +void +dummy_indicator_entry_func_support_window(DummyIndicatorEntryFunc * ind, gboolean different) +{ + DummyIndicatorEntryFuncClass * entry_class = DUMMY_INDICATOR_ENTRY_FUNC_GET_CLASS(ind); + + if (different) { + entry_class->parent_class.entry_activate_window = entry_activate_window; + } else { + entry_class->parent_class.entry_activate_window = NULL; + } + + return; +} diff --git a/tests/dummy-indicator-entry-func.h b/tests/dummy-indicator-entry-func.h index f5c8264..d22abed 100644 --- a/tests/dummy-indicator-entry-func.h +++ b/tests/dummy-indicator-entry-func.h @@ -53,4 +53,6 @@ struct _DummyIndicatorEntryFunc { gboolean entry_close_called; }; +void dummy_indicator_entry_func_support_window(DummyIndicatorEntryFunc * ind, gboolean different); + #endif /* __DUMMY_INDICATOR_ENTRY_FUNC__ */ -- cgit v1.2.3 From f898563b6eaff8a00dd0cc2f7adabed16b80b698 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Mon, 16 Jan 2012 03:45:00 +0100 Subject: Adding a test to look to make sure the fallback works --- tests/test-loader.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/tests/test-loader.c b/tests/test-loader.c index 3adce3b..48537c0 100644 --- a/tests/test-loader.c +++ b/tests/test-loader.c @@ -25,6 +25,31 @@ License along with this library. If not, see #include "dummy-indicator-entry-func.h" +void +test_loader_entry_func_window (void) +{ + IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-entry-func.so"); + g_assert(object != NULL); + + DummyIndicatorEntryFunc * entryfunc = (DummyIndicatorEntryFunc *)(object); + + entryfunc->entry_activate_called = FALSE; + entryfunc->entry_activate_window_called = FALSE; + entryfunc->entry_close_called = FALSE; + + dummy_indicator_entry_func_support_window(entryfunc, FALSE); + indicator_object_entry_activate_window(object, NULL, 0, 0); + g_assert(entryfunc->entry_activate_called); + + dummy_indicator_entry_func_support_window(entryfunc, TRUE); + indicator_object_entry_activate_window(object, NULL, 0, 0); + g_assert(entryfunc->entry_activate_window_called); + + g_object_unref(object); + + return; +} + void test_loader_entry_funcs (void) { @@ -203,6 +228,7 @@ test_loader_creation_deletion_suite (void) g_test_add_func ("/libindicator/loader/dummy/simple_location", test_loader_filename_dummy_simple_location); g_test_add_func ("/libindicator/loader/dummy/signaler", test_loader_filename_dummy_signaler); g_test_add_func ("/libindicator/loader/dummy/entry_funcs", test_loader_entry_funcs); + g_test_add_func ("/libindicator/loader/dummy/entry_func_window", test_loader_entry_func_window); return; } -- cgit v1.2.3 From 6a0f41aaa53cb79e03520a8214cc2c9305821496 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Mon, 16 Jan 2012 03:59:29 +0100 Subject: Moving the function into the tester to making linking simpler --- tests/dummy-indicator-entry-func.c | 14 -------------- tests/dummy-indicator-entry-func.h | 2 -- tests/test-loader.c | 23 +++++++++++++++++++++-- 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/tests/dummy-indicator-entry-func.c b/tests/dummy-indicator-entry-func.c index ac330aa..96e5ad0 100644 --- a/tests/dummy-indicator-entry-func.c +++ b/tests/dummy-indicator-entry-func.c @@ -128,17 +128,3 @@ dummy_indicator_entry_func_finalize (GObject *object) G_OBJECT_CLASS (dummy_indicator_entry_func_parent_class)->finalize (object); return; } - -void -dummy_indicator_entry_func_support_window(DummyIndicatorEntryFunc * ind, gboolean different) -{ - DummyIndicatorEntryFuncClass * entry_class = DUMMY_INDICATOR_ENTRY_FUNC_GET_CLASS(ind); - - if (different) { - entry_class->parent_class.entry_activate_window = entry_activate_window; - } else { - entry_class->parent_class.entry_activate_window = NULL; - } - - return; -} diff --git a/tests/dummy-indicator-entry-func.h b/tests/dummy-indicator-entry-func.h index d22abed..f5c8264 100644 --- a/tests/dummy-indicator-entry-func.h +++ b/tests/dummy-indicator-entry-func.h @@ -53,6 +53,4 @@ struct _DummyIndicatorEntryFunc { gboolean entry_close_called; }; -void dummy_indicator_entry_func_support_window(DummyIndicatorEntryFunc * ind, gboolean different); - #endif /* __DUMMY_INDICATOR_ENTRY_FUNC__ */ diff --git a/tests/test-loader.c b/tests/test-loader.c index 48537c0..2e9cf55 100644 --- a/tests/test-loader.c +++ b/tests/test-loader.c @@ -25,6 +25,25 @@ License along with this library. If not, see #include "dummy-indicator-entry-func.h" +void +entry_func_swap (IndicatorObject * io) +{ + static void (*saved_func) (IndicatorObject * io, IndicatorObjectEntry * entry, guint windowid, guint timestamp) = NULL; + IndicatorObjectClass * klass = INDICATOR_OBJECT_GET_CLASS(io); + + if (saved_func == NULL) { + saved_func = klass->entry_activate_window; + } + + if (klass->entry_activate_window == NULL) { + klass->entry_activate_window = saved_func; + } else { + klass->entry_activate_window = NULL; + } + + return; +} + void test_loader_entry_func_window (void) { @@ -37,11 +56,11 @@ test_loader_entry_func_window (void) entryfunc->entry_activate_window_called = FALSE; entryfunc->entry_close_called = FALSE; - dummy_indicator_entry_func_support_window(entryfunc, FALSE); + entry_func_swap(object); indicator_object_entry_activate_window(object, NULL, 0, 0); g_assert(entryfunc->entry_activate_called); - dummy_indicator_entry_func_support_window(entryfunc, TRUE); + entry_func_swap(object); indicator_object_entry_activate_window(object, NULL, 0, 0); g_assert(entryfunc->entry_activate_window_called); -- cgit v1.2.3 From 8a739e176e44cfff995711606c224caa9a1920b8 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Thu, 19 Jan 2012 11:44:37 -0600 Subject: Adding a parent object pointer to the entry --- libindicator/indicator-object.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libindicator/indicator-object.h b/libindicator/indicator-object.h index bbc215a..b8b9a8b 100644 --- a/libindicator/indicator-object.h +++ b/libindicator/indicator-object.h @@ -152,6 +152,7 @@ struct _IndicatorObject { /** IndicatorObjectEntry: + @parent_object: The #IndicatorObject that created this entry @label: The label to be shown on the panel @image: The image to be shown on the panel @menu: The menu to be added to the menubar @@ -166,6 +167,7 @@ struct _IndicatorObject { @reserved4: Reserved for future use */ struct _IndicatorObjectEntry { + IndicatorObject * parent_object; GtkLabel * label; GtkImage * image; GtkMenu * menu; -- cgit v1.2.3 From f2f9c5b63cfc8e9c9b8dfb77d2f8f9aed687720e Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Thu, 19 Jan 2012 11:46:28 -0600 Subject: Set the parent_object on the default entry --- libindicator/indicator-object.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libindicator/indicator-object.c b/libindicator/indicator-object.c index 7a3e393..adaa9ed 100644 --- a/libindicator/indicator-object.c +++ b/libindicator/indicator-object.c @@ -257,6 +257,7 @@ indicator_object_init (IndicatorObject *self) self->priv->module = NULL; + self->priv->entry.parent_object = self; self->priv->entry.menu = NULL; self->priv->entry.label = NULL; self->priv->entry.image = NULL; -- cgit v1.2.3 From e14c0872345cc6761b4b81adedf1aad8d694872a Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Thu, 19 Jan 2012 11:48:32 -0600 Subject: Adding a warning for entries that do not set their parent_object --- tools/indicator-loader.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/indicator-loader.c b/tools/indicator-loader.c index 59e90b1..10952dc 100644 --- a/tools/indicator-loader.c +++ b/tools/indicator-loader.c @@ -45,6 +45,10 @@ entry_added (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer user_d { g_debug("Signal: Entry Added"); + if (entry->parent_object == NULL) { + g_warning("Entry '%p' does not have a parent object", entry); + } + GtkWidget * menuitem = gtk_menu_item_new(); #if GTK_CHECK_VERSION(3,0,0) GtkWidget * hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 3); -- cgit v1.2.3 From a1ed503a7513d46ca530dd9e853140f2981e69a3 Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Thu, 19 Jan 2012 11:55:47 -0600 Subject: Checking to ensure the parent_object pointer gets set --- tests/test-loader.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test-loader.c b/tests/test-loader.c index 2e9cf55..38f2cb1 100644 --- a/tests/test-loader.c +++ b/tests/test-loader.c @@ -152,6 +152,7 @@ test_loader_filename_dummy_simple_location (void) g_assert(indicator_object_get_location(object, (IndicatorObjectEntry *)entries->data) == 0); g_assert(indicator_object_get_location(object, NULL) == 0); + g_assert(((IndicatorObjectEntry *)entries->data)->parent_object != NULL); g_object_unref(object); -- cgit v1.2.3 From 8cb8b9f16b2f24dd99e7e4d86cb46415bfa99cd9 Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Fri, 20 Jan 2012 14:02:16 -0600 Subject: fix bugs in IndicatorObject's visibility support. --- libindicator/indicator-object.c | 299 +++++++++++++++++++++------------------- 1 file changed, 161 insertions(+), 138 deletions(-) diff --git a/libindicator/indicator-object.c b/libindicator/indicator-object.c index 55082c7..f4a4265 100644 --- a/libindicator/indicator-object.c +++ b/libindicator/indicator-object.c @@ -34,12 +34,12 @@ License along with this library. If not, see @ENTRY_INIT: The entry hasn't been initialized yet, so its visibility will depend upon the inital-visibility property and the 'visible' setting in the optional GSettings schema-id - @ENTRY_INVISIBLE: The entry has been initialized but is not visible + @ENTRY_CLOAKED: The entry has been initialized but is not visible @ENTRY_VISIBLE: The entry is visible */ typedef enum { ENTRY_INIT, - ENTRY_INVISIBLE, + ENTRY_CLOAKED, ENTRY_VISIBLE } EntryVisibility; @@ -112,19 +112,19 @@ static void indicator_object_class_init (IndicatorObjectClass *klass); static void indicator_object_init (IndicatorObject *self); static void indicator_object_dispose (GObject *object); static void indicator_object_finalize (GObject *object); -static void set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); -static void get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); +static void set_property (GObject*, guint prop_id, const GValue*, GParamSpec* ); +static void get_property (GObject*, guint prop_id, GValue*, GParamSpec* ); /* GSettings schema handling */ -static void schema_clear (IndicatorObject * object); -static void schema_set (IndicatorObject * object, const char * schema_id); +static void schema_clear (IndicatorObject* ); +static void schema_set (IndicatorObject* , const char * schema_id); /* entries' visibility */ -static GList * get_entries_default (IndicatorObject*); -static GList * get_all_entries (IndicatorObject*); -static void remove_all_entries_from_limbo (IndicatorObject*); -static void on_entry_added (IndicatorObject*, IndicatorObjectEntry*, gpointer); -static void on_entry_removed (IndicatorObject*, IndicatorObjectEntry*, gpointer); +static void on_entry_added (IndicatorObject*, IndicatorObjectEntry*, gpointer); +static void on_entry_removed(IndicatorObject*, IndicatorObjectEntry*, gpointer); +static void decloak_entry (IndicatorObject*, IndicatorObjectEntry*); +static GList * get_entries_default (IndicatorObject*); +static GList * get_all_entries (IndicatorObject*); G_DEFINE_TYPE (IndicatorObject, indicator_object, G_TYPE_OBJECT); @@ -133,7 +133,6 @@ G_DEFINE_TYPE (IndicatorObject, indicator_object, G_TYPE_OBJECT); static void indicator_object_class_init (IndicatorObjectClass *klass) { - GParamSpec * param_spec; GObjectClass *object_class = G_OBJECT_CLASS (klass); g_type_class_add_private (klass, sizeof (IndicatorObjectPrivate)); @@ -143,12 +142,10 @@ indicator_object_class_init (IndicatorObjectClass *klass) object_class->set_property = set_property; object_class->get_property = get_property; - klass->get_label = NULL; - klass->get_menu = NULL; + klass->get_menu = NULL; klass->get_image = NULL; klass->get_accessible_desc = NULL; - klass->get_entries = get_entries_default; klass->get_location = NULL; @@ -296,48 +293,55 @@ indicator_object_class_init (IndicatorObjectClass *klass) /* Properties */ - param_spec = g_param_spec_string (INDICATOR_OBJECT_GSETTINGS_SCHEMA_ID, - "schema id", - "The schema-id of the GSettings (if any) to monitor.", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_GSETTINGS_SCHEMA_ID, param_spec); - - param_spec = g_param_spec_string (INDICATOR_OBJECT_DEFAULT_VISIBILITY, - "default visibility", - "The schema-id of the GSettings (if any) to monitor.", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_DEFAULT_VISIBILITY, param_spec); - - return; + GParamSpec * pspec; + pspec = g_param_spec_string (INDICATOR_OBJECT_GSETTINGS_SCHEMA_ID, + "schema id", + "The schema-id of the GSettings (if any) to monitor.", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_GSETTINGS_SCHEMA_ID, pspec); + + pspec = g_param_spec_boolean (INDICATOR_OBJECT_DEFAULT_VISIBILITY, + "default visibility", + "Whether or not entries should initially be visible.", + TRUE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + g_object_class_install_property (object_class, PROP_DEFAULT_VISIBILITY, pspec); } /* Initialize an instance */ static void indicator_object_init (IndicatorObject *self) { - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, INDICATOR_OBJECT_TYPE, IndicatorObjectPrivate); + IndicatorObjectPrivate * priv = G_TYPE_INSTANCE_GET_PRIVATE (self, INDICATOR_OBJECT_TYPE, IndicatorObjectPrivate); - self->priv->module = NULL; + priv->module = NULL; - self->priv->entry.menu = NULL; - self->priv->entry.label = NULL; - self->priv->entry.image = NULL; - self->priv->entry.accessible_desc = NULL; - self->priv->entry.name_hint = NULL; + priv->entry.menu = NULL; + priv->entry.label = NULL; + priv->entry.image = NULL; + priv->entry.accessible_desc = NULL; + priv->entry.name_hint = NULL; - self->priv->gotten_entries = FALSE; - self->priv->default_visibility = TRUE; - self->priv->entry_privates = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); + priv->gotten_entries = FALSE; + priv->default_visibility = TRUE; + priv->entry_privates = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); - self->priv->environments = NULL; + priv->environments = NULL; - self->priv->gsettings = NULL; - self->priv->gsettings_schema_id = NULL; + priv->gsettings = NULL; + priv->gsettings_schema_id = NULL; - g_signal_connect (G_OBJECT(self), INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED, G_CALLBACK(on_entry_removed), NULL); - g_signal_connect_after (G_OBJECT(self), INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED, G_CALLBACK(on_entry_added), NULL); + self->priv = priv; + + /* Listen for entries to be added/removed so that we can manage them. + By being first in line for the "removed" signal we can cloak the + entry before the client code destroys its widgetry... */ + GObject * o = G_OBJECT(self); + g_signal_connect (o, INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED, + G_CALLBACK(on_entry_removed), NULL); + g_signal_connect_after (o, INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED, + G_CALLBACK(on_entry_added), NULL); } /* Unref the objects that we're holding on to. */ @@ -346,14 +350,23 @@ indicator_object_dispose (GObject *object) { IndicatorObject * io = INDICATOR_OBJECT(object); + /* stop listening to schema changes */ schema_clear (io); - remove_all_entries_from_limbo (io); - if ((io->priv != NULL) && (io->priv->entry_privates != NULL)) + /* decloak any cloaked entries so they won't leak */ + GList * l; + GList * entries = get_all_entries (io); + for (l=entries; l!=NULL; l=l->next) + decloak_entry (io, l->data); + g_list_free (entries); + + /* destroy the EntryPrivate hashtable */ + if (io->priv && io->priv->entry_privates) { g_hash_table_destroy (io->priv->entry_privates); + io->priv->entry_privates = NULL; + } G_OBJECT_CLASS (indicator_object_parent_class)->dispose (object); - return; } /* A small helper function that closes a module but @@ -382,7 +395,7 @@ indicator_object_finalize (GObject *object) if (priv->module != NULL) { /* Wow, this is convoluted. So basically we want to unref the module which will cause the code it included to be - removed. But, since it's finalize function is the function + removed. But, since its finalize function is the function that called this one, we can't really remove it before it finishes being executed. So we're putting the job into the main loop to remove it the next time it gets a chance. @@ -544,36 +557,45 @@ get_entries_default (IndicatorObject * io) return g_list_append(NULL, &(priv->entry)); } -/* returns a list of all IndicatorObjectEntires whether they're visible or not */ +/* returns a list of all IndicatorObjectEntires, visible or not */ static GList* get_all_entries (IndicatorObject * io) { + GList * all_entries = NULL; + g_return_val_if_fail(INDICATOR_IS_OBJECT(io), NULL); IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io); if (class->get_entries == NULL) g_error("No get_entries function on object. It must have been deleted?!?!"); + else + all_entries = class->get_entries(io); - return class->get_entries(io); + return all_entries; } +/* get the private structure that corresponds to a caller-specified entry */ IndicatorObjectEntryPrivate * entry_get_private (IndicatorObject * io, IndicatorObjectEntry * entry) { g_return_val_if_fail (INDICATOR_IS_OBJECT(io), NULL); g_return_val_if_fail (io->priv != NULL, NULL); - IndicatorObjectEntryPrivate * priv = g_hash_table_lookup (io->priv->entry_privates, entry); + GHashTable * h = io->priv->entry_privates; + IndicatorObjectEntryPrivate * priv = g_hash_table_lookup (h, entry); if (priv == NULL) { priv = g_new0 (IndicatorObjectEntryPrivate, 1); priv->visibility = ENTRY_INIT; - g_hash_table_insert (io->priv->entry_privates, entry, priv); + g_hash_table_insert (h, entry, priv); } return priv; } +/* Returns whether or not entries should be shown by default on startup. + This is usually 'true', but can be changed via GSettings and/or by the + INDICATOR_OBJECT_DEFAULT_VISIBILITY property. */ static gboolean get_default_visibility (IndicatorObject * io) { @@ -591,14 +613,14 @@ get_default_visibility (IndicatorObject * io) indicator_object_get_entries: @io: #IndicatorObject to query - This function returns a list of visible entries. The list is built by calling - the object's #IndicatorObjectClass::get_entries virtual function and testing - each of the results for visibility. - Callers should free the GList with g_list_free(), but the entries are owned - by the IndicatorObject and should not be freed. + This function returns a list of visible entries. The list is built + by calling the object's #IndicatorObjectClass::get_entries + virtual function and testing each of the results for visibility. + Callers should free the GList with g_list_free(), but the entries + are owned by the IndicatorObject and should not be freed. - Return value: (element-type IndicatorObjectEntry) (transfer container): A list if #IndicatorObjectEntry structures or - NULL if there is an error. + Return value: (element-type IndicatorObjectEntry) (transfer container): + A list if #IndicatorObjectEntry structures or NULL on error. */ GList * indicator_object_get_entries (IndicatorObject * io) @@ -611,12 +633,11 @@ indicator_object_get_entries (IndicatorObject * io) { gboolean show_me; IndicatorObjectEntry * entry = l->data; - IndicatorObjectEntryPrivate * entry_priv = entry_get_private (io, entry); - switch (entry_priv->visibility) { + switch (entry_get_private(io,entry)->visibility) { case ENTRY_VISIBLE: show_me = TRUE; break; - case ENTRY_INVISIBLE: show_me = FALSE; break; - default /*ENTRY_INIT*/: show_me = get_default_visibility (io); break; + case ENTRY_CLOAKED: show_me = FALSE; break; + default: show_me = get_default_visibility (io); break; } if (show_me) @@ -734,6 +755,7 @@ indicator_object_entry_close (IndicatorObject * io, IndicatorObjectEntry * entry void indicator_object_set_environment (IndicatorObject * io, const GStrv env) { + /* FIXME: should this be a property? */ g_return_if_fail(INDICATOR_IS_OBJECT(io)); if (io->priv->environments != NULL) { @@ -805,19 +827,22 @@ indicator_object_set_visible (IndicatorObject * io, gboolean visible) { GList * l; GList * entries; - const char * signal_name = visible ? INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED - : INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED; + const char * name = visible ? INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED + : INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED; g_return_if_fail(INDICATOR_IS_OBJECT(io)); entries = get_all_entries (io); for (l=entries; l!=NULL; l=l->next) - g_signal_emit_by_name (io, signal_name, l->data); + g_signal_emit_by_name (io, name, l->data); g_list_free (entries); } static void -get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) +get_property (GObject * object, + guint prop_id, + GValue * value, + GParamSpec * pspec) { IndicatorObject * self = INDICATOR_OBJECT(object); g_return_if_fail(self != NULL); @@ -850,7 +875,10 @@ get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspe } static void -set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) +set_property (GObject * object, + guint prop_id, + const GValue * value, + GParamSpec * pspec) { IndicatorObject * self = INDICATOR_OBJECT(object); g_return_if_fail (self != NULL); @@ -884,39 +912,22 @@ set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } - - return; } +/*** +**** +***/ + static void on_settings_changed (GSettings * gsettings, gchar * key, gpointer user_data) { - if (!g_strcmp0 (key, "visible")) - { - IndicatorObject * io = INDICATOR_OBJECT (user_data); - const gboolean visible = g_settings_get_boolean (gsettings, key); - indicator_object_set_visible (io, visible); + if (!g_strcmp0 (key, "visible")) { + IndicatorObject * io = INDICATOR_OBJECT (user_data); + gboolean visible = g_settings_get_boolean (gsettings, key); + indicator_object_set_visible (io, visible); } } -static void -schema_set (IndicatorObject * object, const char * gsettings_schema_id) -{ - schema_clear (object); - - IndicatorObjectPrivate * priv = INDICATOR_OBJECT_GET_PRIVATE(object); - g_return_if_fail (priv != NULL); - - priv->gsettings_schema_id = g_strdup (gsettings_schema_id); - if (priv->gsettings_schema_id != NULL) { - priv->gsettings = g_settings_new (priv->gsettings_schema_id); - if (priv->gsettings != NULL) { - g_signal_connect (G_OBJECT(priv->gsettings), "changed", G_CALLBACK(on_settings_changed), object); - g_debug ("indicator %p is listening for GSettings change events from %s", priv->gsettings, gsettings_schema_id); - } - } -} - static void schema_clear (IndicatorObject * self) { @@ -934,84 +945,96 @@ schema_clear (IndicatorObject * self) } } +static void +schema_set (IndicatorObject * object, const char * gsettings_schema_id) +{ + schema_clear (object); + + IndicatorObjectPrivate * priv = INDICATOR_OBJECT_GET_PRIVATE(object); + g_return_if_fail (priv != NULL); + + priv->gsettings_schema_id = g_strdup (gsettings_schema_id); + if (priv->gsettings_schema_id != NULL) { + priv->gsettings = g_settings_new (priv->gsettings_schema_id); + } + if (priv->gsettings != NULL) { + g_signal_connect (G_OBJECT(priv->gsettings), "changed", + G_CALLBACK(on_settings_changed), object); + } +} + /*** **** -**** ***/ -#define LIMBO_REF_KEY "indicator-object-entry-limbo-key" - -/* Limbo is an idiom private to indicator-object.c - It is for entries which have been removed and are waiting to be re-added later */ +/* Cloaked entries are ones which are hidden but may be re-added later. + We cloak them by reffing them + unparenting to ensure their survival + even if their gtk parent's widgetry is destroyed */ +#define CLOAKED_KEY "entry-is-cloaked" static void -remove_widget_from_limbo (gpointer w) +decloak_widget (gpointer w) { if (w != NULL) { GObject * o = G_OBJECT(w); - - if (g_object_get_data(o, LIMBO_REF_KEY)) { - g_object_steal_data (o, LIMBO_REF_KEY); + if (g_object_get_data(o, CLOAKED_KEY)) { + g_object_steal_data (o, CLOAKED_KEY); g_object_unref (o); } } } static void -remove_entry_from_limbo (IndicatorObject * io, IndicatorObjectEntry * entry) +decloak_entry (IndicatorObject * io, IndicatorObjectEntry * entry) { - IndicatorObjectEntryPrivate * entry_priv = entry_get_private (io, entry); - - entry_priv->visibility = ENTRY_INVISIBLE; + entry_get_private (io, entry)->visibility = ENTRY_VISIBLE; - remove_widget_from_limbo (entry->image); - remove_widget_from_limbo (entry->label); - remove_widget_from_limbo (entry->menu); -} - -static void -remove_all_entries_from_limbo (IndicatorObject * io) -{ - GList * l; - GList * entries = get_all_entries(io); - for (l=entries; l!=NULL; l=l->next) - remove_entry_from_limbo (io, l->data); - g_list_free (entries); + decloak_widget (entry->image); + decloak_widget (entry->label); + decloak_widget (entry->menu); } static void -on_entry_added (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer unused G_GNUC_UNUSED) +on_entry_added (IndicatorObject * io, + IndicatorObjectEntry * entry, + gpointer unused G_GNUC_UNUSED) { - remove_entry_from_limbo (io, entry); + decloak_entry (io, entry); } /* The panels like to destroy an entry's widgetry when it's removed. - Protect the image, label, and menu for safekeeping in case we ever - need to add it back again. */ + Protect the image, label, and menu for future reuse */ static void -put_widget_in_limbo (gpointer w) +cloak_widget (gpointer w) { if (w != NULL) { GtkWidget * parent; - g_object_ref (G_OBJECT(w)); - g_object_set_data (G_OBJECT(w), LIMBO_REF_KEY, GINT_TO_POINTER(1)); - - if(GTK_IS_MENU(w)) - gtk_menu_detach (GTK_MENU(w)); - else if((parent = gtk_widget_get_parent(w))) + /* tag this object as cloaked */ + GObject * o = G_OBJECT(w); + g_object_ref (o); + g_object_set_data (o, CLOAKED_KEY, GINT_TO_POINTER(1)); + + /* remove it from its surrounding widgetry */ + if(GTK_IS_MENU(w)) { + if (gtk_menu_get_attach_widget (GTK_MENU(w)) != NULL) { + gtk_menu_detach (GTK_MENU(w)); + } + } + else if((parent = gtk_widget_get_parent(w))) { gtk_container_remove(GTK_CONTAINER(parent), w); + } } } static void -on_entry_removed (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer unused G_GNUC_UNUSED) +on_entry_removed (IndicatorObject * io, + IndicatorObjectEntry * entry, + gpointer unused G_GNUC_UNUSED) { - IndicatorObjectEntryPrivate * entry_priv = entry_get_private (io, entry); - - entry_priv->visibility = ENTRY_VISIBLE; + entry_get_private(io,entry)->visibility = ENTRY_CLOAKED; - put_widget_in_limbo (entry->image); - put_widget_in_limbo (entry->label); - put_widget_in_limbo (entry->menu); + cloak_widget (entry->image); + cloak_widget (entry->label); + cloak_widget (entry->menu); } -- cgit v1.2.3 From 4f4190f71f8495e5bcf6779d73157931572e42ac Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Mon, 23 Jan 2012 05:39:50 -0600 Subject: another iteration of the indicator-object visibility support patch, incorporating ideas from discussion with ted - some functions were public when they should have been private - the hide/show handler is now a virtual function & is documented in indicator-object.h - added unit tests - the GSettings monitor has been removed --- libindicator/indicator-object.c | 240 ++++++++++++--------------------------- libindicator/indicator-object.h | 12 +- tests/Makefile.am | 23 +++- tests/dummy-indicator-signaler.c | 2 + tests/dummy-indicator-visible.c | 139 +++++++++++++++++++++++ tests/test-loader.c | 90 +++++++++++++++ 6 files changed, 337 insertions(+), 169 deletions(-) create mode 100644 tests/dummy-indicator-visible.c diff --git a/libindicator/indicator-object.c b/libindicator/indicator-object.c index f4a4265..8deb706 100644 --- a/libindicator/indicator-object.c +++ b/libindicator/indicator-object.c @@ -32,19 +32,18 @@ License along with this library. If not, see /** @ENTRY_INIT: The entry hasn't been initialized yet, so its - visibility will depend upon the inital-visibility property - and the 'visible' setting in the optional GSettings schema-id - @ENTRY_CLOAKED: The entry has been initialized but is not visible + visibility will depend upon the inital-visibility property. @ENTRY_VISIBLE: The entry is visible + @ENTRY_INVISIBLE: The entry is invisible */ typedef enum { ENTRY_INIT, - ENTRY_CLOAKED, - ENTRY_VISIBLE + ENTRY_VISIBLE, + ENTRY_INVISIBLE } EntryVisibility; -typedef struct IndicatorObjectEntryPrivate { +typedef struct _IndicatorObjectEntryPrivate { EntryVisibility visibility; } IndicatorObjectEntryPrivate; @@ -68,10 +67,6 @@ struct _IndicatorObjectPrivate { IndicatorObjectEntry entry; gboolean gotten_entries; - /* For indicator objects that monitor a GSettings schema-id */ - GSettings * gsettings; - gchar * gsettings_schema_id; - /* Whether or not entries are visible by default */ gboolean default_visibility; GHashTable * entry_privates; @@ -115,16 +110,14 @@ static void indicator_object_finalize (GObject *object); static void set_property (GObject*, guint prop_id, const GValue*, GParamSpec* ); static void get_property (GObject*, guint prop_id, GValue*, GParamSpec* ); -/* GSettings schema handling */ -static void schema_clear (IndicatorObject* ); -static void schema_set (IndicatorObject* , const char * schema_id); - /* entries' visibility */ -static void on_entry_added (IndicatorObject*, IndicatorObjectEntry*, gpointer); -static void on_entry_removed(IndicatorObject*, IndicatorObjectEntry*, gpointer); -static void decloak_entry (IndicatorObject*, IndicatorObjectEntry*); -static GList * get_entries_default (IndicatorObject*); -static GList * get_all_entries (IndicatorObject*); +static GList * get_entries_default (IndicatorObject*); +static GList * get_all_entries (IndicatorObject*); +static void entry_being_removed_default (IndicatorObject*, IndicatorObjectEntry*); +static void indicator_object_entry_being_removed (IndicatorObject*, IndicatorObjectEntry*); +static void entry_was_added_default (IndicatorObject*, IndicatorObjectEntry*); +static void indicator_object_entry_was_added (IndicatorObject*, IndicatorObjectEntry*); +static IndicatorObjectEntryPrivate * entry_get_private (IndicatorObject*, IndicatorObjectEntry*); G_DEFINE_TYPE (IndicatorObject, indicator_object, G_TYPE_OBJECT); @@ -148,6 +141,8 @@ indicator_object_class_init (IndicatorObjectClass *klass) klass->get_accessible_desc = NULL; klass->get_entries = get_entries_default; klass->get_location = NULL; + klass->entry_being_removed = entry_being_removed_default; + klass->entry_was_added = entry_was_added_default; /** IndicatorObject::entry-added: @@ -293,15 +288,7 @@ indicator_object_class_init (IndicatorObjectClass *klass) /* Properties */ - GParamSpec * pspec; - pspec = g_param_spec_string (INDICATOR_OBJECT_GSETTINGS_SCHEMA_ID, - "schema id", - "The schema-id of the GSettings (if any) to monitor.", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); - g_object_class_install_property (object_class, PROP_GSETTINGS_SCHEMA_ID, pspec); - - pspec = g_param_spec_boolean (INDICATOR_OBJECT_DEFAULT_VISIBILITY, + GParamSpec * pspec = g_param_spec_boolean (INDICATOR_OBJECT_DEFAULT_VISIBILITY, "default visibility", "Whether or not entries should initially be visible.", TRUE, @@ -329,19 +316,15 @@ indicator_object_init (IndicatorObject *self) priv->environments = NULL; - priv->gsettings = NULL; - priv->gsettings_schema_id = NULL; - self->priv = priv; - /* Listen for entries to be added/removed so that we can manage them. - By being first in line for the "removed" signal we can cloak the - entry before the client code destroys its widgetry... */ GObject * o = G_OBJECT(self); + /* Invoke the entry-being-removed virtual function first */ g_signal_connect (o, INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED, - G_CALLBACK(on_entry_removed), NULL); + G_CALLBACK(indicator_object_entry_being_removed), NULL); + /* Invoke the entry-was-added virtual function last */ g_signal_connect_after (o, INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED, - G_CALLBACK(on_entry_added), NULL); + G_CALLBACK(indicator_object_entry_was_added), NULL); } /* Unref the objects that we're holding on to. */ @@ -350,21 +333,18 @@ indicator_object_dispose (GObject *object) { IndicatorObject * io = INDICATOR_OBJECT(object); - /* stop listening to schema changes */ - schema_clear (io); - - /* decloak any cloaked entries so they won't leak */ + /* Ensure that hidden entries are re-added so their widgetry will + be cleaned up properly by the client */ GList * l; GList * entries = get_all_entries (io); - for (l=entries; l!=NULL; l=l->next) - decloak_entry (io, l->data); - g_list_free (entries); - - /* destroy the EntryPrivate hashtable */ - if (io->priv && io->priv->entry_privates) { - g_hash_table_destroy (io->priv->entry_privates); - io->priv->entry_privates = NULL; + const GQuark detail = (GQuark)0; + for (l=entries; l!=NULL; l=l->next) { + IndicatorObjectEntry * entry = l->data; + if (entry_get_private(io, entry)->visibility == ENTRY_INVISIBLE) { + g_signal_emit(io, signals[ENTRY_ADDED], detail, entry); + } } + g_list_free (entries); G_OBJECT_CLASS (indicator_object_parent_class)->dispose (object); } @@ -387,6 +367,11 @@ indicator_object_finalize (GObject *object) { IndicatorObjectPrivate * priv = INDICATOR_OBJECT_GET_PRIVATE(object); + if (priv->entry_privates != NULL) { + g_hash_table_destroy (priv->entry_privates); + priv->entry_privates = NULL; + } + if (priv->environments != NULL) { g_strfreev(priv->environments); priv->environments = NULL; @@ -575,7 +560,7 @@ get_all_entries (IndicatorObject * io) } /* get the private structure that corresponds to a caller-specified entry */ -IndicatorObjectEntryPrivate * +static IndicatorObjectEntryPrivate * entry_get_private (IndicatorObject * io, IndicatorObjectEntry * entry) { g_return_val_if_fail (INDICATOR_IS_OBJECT(io), NULL); @@ -593,22 +578,6 @@ entry_get_private (IndicatorObject * io, IndicatorObjectEntry * entry) return priv; } -/* Returns whether or not entries should be shown by default on startup. - This is usually 'true', but can be changed via GSettings and/or by the - INDICATOR_OBJECT_DEFAULT_VISIBILITY property. */ -static gboolean -get_default_visibility (IndicatorObject * io) -{ - g_return_val_if_fail (INDICATOR_IS_OBJECT(io), FALSE); - IndicatorObjectPrivate * priv = INDICATOR_OBJECT_GET_PRIVATE(io); - g_return_val_if_fail (priv != NULL, FALSE); - - if (priv->gsettings != NULL) - return g_settings_get_boolean (priv->gsettings, "visible"); - - return priv->default_visibility; -} - /** indicator_object_get_entries: @io: #IndicatorObject to query @@ -628,6 +597,7 @@ indicator_object_get_entries (IndicatorObject * io) GList * l; GList * ret = NULL; GList * all_entries = get_all_entries (io); + const gboolean default_visibility = INDICATOR_OBJECT_GET_PRIVATE(io)->default_visibility; for (l=all_entries; l!=NULL; l=l->next) { @@ -635,17 +605,18 @@ indicator_object_get_entries (IndicatorObject * io) IndicatorObjectEntry * entry = l->data; switch (entry_get_private(io,entry)->visibility) { - case ENTRY_VISIBLE: show_me = TRUE; break; - case ENTRY_CLOAKED: show_me = FALSE; break; - default: show_me = get_default_visibility (io); break; + case ENTRY_VISIBLE: show_me = TRUE; break; + case ENTRY_INVISIBLE: show_me = FALSE; break; + case ENTRY_INIT: show_me = default_visibility; break; + default: show_me = TRUE; g_warn_if_reached(); break; } if (show_me) - ret = g_list_append (ret, entry); + ret = g_list_prepend (ret, entry); } g_list_free (all_entries); - return ret; + return g_list_reverse (ret); } /** @@ -743,6 +714,30 @@ indicator_object_entry_close (IndicatorObject * io, IndicatorObjectEntry * entry return; } +static void +indicator_object_entry_being_removed (IndicatorObject * io, IndicatorObjectEntry * entry) +{ + g_return_if_fail(INDICATOR_IS_OBJECT(io)); + IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io); + + entry_get_private (io, entry)->visibility = ENTRY_INVISIBLE; + + if (class->entry_being_removed != NULL) + class->entry_being_removed (io, entry); +} + +static void +indicator_object_entry_was_added (IndicatorObject * io, IndicatorObjectEntry * entry) +{ + g_return_if_fail(INDICATOR_IS_OBJECT(io)); + IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io); + + entry_get_private (io, entry)->visibility = ENTRY_VISIBLE; + + if (class->entry_was_added != NULL) + class->entry_was_added (io, entry); +} + /** indicator_object_set_environment: @io: #IndicatorObject to set on @@ -825,16 +820,14 @@ indicator_object_check_environment (IndicatorObject * io, const gchar * env) void indicator_object_set_visible (IndicatorObject * io, gboolean visible) { - GList * l; - GList * entries; - const char * name = visible ? INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED - : INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED; - g_return_if_fail(INDICATOR_IS_OBJECT(io)); - entries = get_all_entries (io); + GList * l; + GList * entries = get_all_entries (io); + const guint signal_id = signals[visible ? ENTRY_ADDED : ENTRY_REMOVED]; + const GQuark detail = (GQuark)0; for (l=entries; l!=NULL; l=l->next) - g_signal_emit_by_name (io, name, l->data); + g_signal_emit(io, signal_id, detail, l->data); g_list_free (entries); } @@ -852,14 +845,6 @@ get_property (GObject * object, switch (prop_id) { /* *********************** */ - case PROP_GSETTINGS_SCHEMA_ID: - if (G_VALUE_HOLDS_STRING(value)) { - g_value_set_string(value, priv->gsettings_schema_id); - } else { - g_warning("schema-id property requires a string value."); - } - break; - /* *********************** */ case PROP_DEFAULT_VISIBILITY: if (G_VALUE_HOLDS_BOOLEAN(value)) { g_value_set_boolean(value, priv->default_visibility); @@ -889,15 +874,6 @@ set_property (GObject * object, switch (prop_id) { - /* *********************** */ - case PROP_GSETTINGS_SCHEMA_ID: - if (G_VALUE_HOLDS_STRING(value)) { - schema_set (self, g_value_get_string (value)); - } else { - g_warning("schema-id property requires a string value."); - } - break; - /* *********************** */ case PROP_DEFAULT_VISIBILITY: if (G_VALUE_HOLDS_BOOLEAN(value)) { @@ -918,58 +894,9 @@ set_property (GObject * object, **** ***/ -static void -on_settings_changed (GSettings * gsettings, gchar * key, gpointer user_data) -{ - if (!g_strcmp0 (key, "visible")) { - IndicatorObject * io = INDICATOR_OBJECT (user_data); - gboolean visible = g_settings_get_boolean (gsettings, key); - indicator_object_set_visible (io, visible); - } -} - -static void -schema_clear (IndicatorObject * self) -{ - IndicatorObjectPrivate * priv = INDICATOR_OBJECT_GET_PRIVATE(self); - g_return_if_fail (priv != NULL); - - if (priv->gsettings != NULL) { - g_object_unref (priv->gsettings); - priv->gsettings = NULL; - } - - if (priv->gsettings_schema_id != NULL) { - g_free (priv->gsettings_schema_id); - priv->gsettings_schema_id = NULL; - } -} - -static void -schema_set (IndicatorObject * object, const char * gsettings_schema_id) -{ - schema_clear (object); - - IndicatorObjectPrivate * priv = INDICATOR_OBJECT_GET_PRIVATE(object); - g_return_if_fail (priv != NULL); - - priv->gsettings_schema_id = g_strdup (gsettings_schema_id); - if (priv->gsettings_schema_id != NULL) { - priv->gsettings = g_settings_new (priv->gsettings_schema_id); - } - if (priv->gsettings != NULL) { - g_signal_connect (G_OBJECT(priv->gsettings), "changed", - G_CALLBACK(on_settings_changed), object); - } -} - -/*** -**** -***/ - /* Cloaked entries are ones which are hidden but may be re-added later. - We cloak them by reffing them + unparenting to ensure their survival - even if their gtk parent's widgetry is destroyed */ + They are reffed + unparented so that they'll survive even if the + rest of the widgetry is destroyed */ #define CLOAKED_KEY "entry-is-cloaked" static void @@ -977,33 +904,20 @@ decloak_widget (gpointer w) { if (w != NULL) { GObject * o = G_OBJECT(w); - if (g_object_get_data(o, CLOAKED_KEY)) { - g_object_steal_data (o, CLOAKED_KEY); + if (g_object_steal_data (o, CLOAKED_KEY) != NULL) { g_object_unref (o); } } } static void -decloak_entry (IndicatorObject * io, IndicatorObjectEntry * entry) +entry_was_added_default (IndicatorObject * io, IndicatorObjectEntry * entry) { - entry_get_private (io, entry)->visibility = ENTRY_VISIBLE; - decloak_widget (entry->image); decloak_widget (entry->label); decloak_widget (entry->menu); } -static void -on_entry_added (IndicatorObject * io, - IndicatorObjectEntry * entry, - gpointer unused G_GNUC_UNUSED) -{ - decloak_entry (io, entry); -} - -/* The panels like to destroy an entry's widgetry when it's removed. - Protect the image, label, and menu for future reuse */ static void cloak_widget (gpointer w) { @@ -1028,12 +942,8 @@ cloak_widget (gpointer w) } static void -on_entry_removed (IndicatorObject * io, - IndicatorObjectEntry * entry, - gpointer unused G_GNUC_UNUSED) +entry_being_removed_default (IndicatorObject * io, IndicatorObjectEntry * entry) { - entry_get_private(io,entry)->visibility = ENTRY_CLOAKED; - cloak_widget (entry->image); cloak_widget (entry->label); cloak_widget (entry->menu); diff --git a/libindicator/indicator-object.h b/libindicator/indicator-object.h index a46600f..803f1b3 100644 --- a/libindicator/indicator-object.h +++ b/libindicator/indicator-object.h @@ -60,9 +60,6 @@ typedef enum #define INDICATOR_OBJECT_SIGNAL_SECONDARY_ACTIVATE "secondary-activate" #define INDICATOR_OBJECT_SIGNAL_SECONDARY_ACTIVATE_ID (g_signal_lookup(INDICATOR_OBJECT_SIGNAL_SECONDARY_ACTIVATE, INDICATOR_OBJECT_TYPE)) -/* the name of the GSettings schema-id property */ -#define INDICATOR_OBJECT_GSETTINGS_SCHEMA_ID "indicator-object-gsettings-schema-id" - /* the name of the property to decide whether or not entries are visible by default */ #define INDICATOR_OBJECT_DEFAULT_VISIBILITY "indicator-object-default-visibility" @@ -97,6 +94,12 @@ typedef struct _IndicatorObjectEntry IndicatorObjectEntry; @get_show_now: Returns whether the entry is requesting to be shown "right now" in that it has something important to tell the user. + @entry_being_removed: Called before an entry is removed. + The default implementation is to ref and unparent the + entry's widgets so that they can be re-added later. + @entry_was_added: Called after an entry is added. + The default implementation is to unref the entry's widgets if + previously reffed by entry_being_removed's default impementation @entry_activate: Should be called when the menus for a given entry are shown to the user. @entry_close: Called when the menu is closed. @@ -123,6 +126,9 @@ struct _IndicatorObjectClass { guint (*get_location) (IndicatorObject * io, IndicatorObjectEntry * entry); gboolean (*get_show_now) (IndicatorObject * io, IndicatorObjectEntry * entry); + void (*entry_being_removed) (IndicatorObject * io, IndicatorObjectEntry * entry); + void (*entry_was_added) (IndicatorObject * io, IndicatorObjectEntry * entry); + void (*entry_activate) (IndicatorObject * io, IndicatorObjectEntry * entry, guint timestamp); void (*entry_close) (IndicatorObject * io, IndicatorObjectEntry * entry, guint timestamp); diff --git a/tests/Makefile.am b/tests/Makefile.am index f11a9d1..a70ee58 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -14,7 +14,8 @@ lib_LTLIBRARIES = \ libdummy-indicator-blank.la \ libdummy-indicator-null.la \ libdummy-indicator-signaler.la \ - libdummy-indicator-simple.la + libdummy-indicator-simple.la \ + libdummy-indicator-visible.la DBUS_RUNNER=dbus-test-runner --dbus-config /usr/share/dbus-test-runner/session.conf XVFB_RUN=". $(srcdir)/run-xvfb.sh" @@ -161,6 +162,26 @@ libdummy_indicator_simple_la_LDFLAGS = \ -module \ -avoid-version +############################# +# Dummy Indicator Visible +############################# + +libdummy_indicator_visible_la_SOURCES = \ + dummy-indicator-visible.c + +libdummy_indicator_visible_la_CFLAGS = \ + -Wall -Werror \ + $(LIBINDICATOR_CFLAGS) -I$(top_srcdir) + +libdummy_indicator_visible_la_LIBADD = \ + $(LIBINDICATOR_LIBS) \ + -L$(top_builddir)/libindicator/.libs \ + $(INDICATOR_LIB) + +libdummy_indicator_visible_la_LDFLAGS = \ + -module \ + -avoid-version + ############################# # Service Shutdown Timeout ############################# diff --git a/tests/dummy-indicator-signaler.c b/tests/dummy-indicator-signaler.c index 00eee3b..c7a5c1f 100644 --- a/tests/dummy-indicator-signaler.c +++ b/tests/dummy-indicator-signaler.c @@ -99,6 +99,8 @@ dummy_indicator_signaler_class_init (DummyIndicatorSignalerClass *klass) io_class->get_image = get_icon; io_class->get_menu = get_menu; io_class->get_accessible_desc = get_accessible_desc; + io_class->entry_being_removed = NULL; + io_class->entry_was_added = NULL; return; } diff --git a/tests/dummy-indicator-visible.c b/tests/dummy-indicator-visible.c new file mode 100644 index 0000000..0bb9e89 --- /dev/null +++ b/tests/dummy-indicator-visible.c @@ -0,0 +1,139 @@ +/* +Test for libindicator + +Copyright 2012 Canonical Ltd. + +Authors: + Charles Kerr + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +version 3.0 as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License version 3.0 for more details. + +You should have received a copy of the GNU General Public +License along with this library. If not, see +. +*/ + +#include +#include + +#include "libindicator/indicator.h" +#include "libindicator/indicator-object.h" + +#define DUMMY_INDICATOR_VISIBLE_TYPE (dummy_indicator_visible_get_type ()) +#define DUMMY_INDICATOR_VISIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DUMMY_INDICATOR_VISIBLE_TYPE, DummyIndicatorVisible)) +#define DUMMY_INDICATOR_VISIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DUMMY_INDICATOR_VISIBLE_TYPE, DummyIndicatorVisibleClass)) +#define IS_DUMMY_INDICATOR_VISIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DUMMY_INDICATOR_VISIBLE_TYPE)) +#define IS_DUMMY_INDICATOR_VISIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DUMMY_INDICATOR_VISIBLE_TYPE)) +#define DUMMY_INDICATOR_VISIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DUMMY_INDICATOR_VISIBLE_TYPE, DummyIndicatorVisibleClass)) + +typedef struct _DummyIndicatorVisible DummyIndicatorVisible; +typedef struct _DummyIndicatorVisibleClass DummyIndicatorVisibleClass; + +struct _DummyIndicatorVisibleClass { + IndicatorObjectClass parent_class; +}; + +struct _DummyIndicatorVisible { + IndicatorObject parent; +}; + +GType dummy_indicator_visible_get_type (void); + +INDICATOR_SET_VERSION +INDICATOR_SET_TYPE(DUMMY_INDICATOR_VISIBLE_TYPE) + +GtkLabel * +get_label (IndicatorObject * io) +{ + return GTK_LABEL(gtk_label_new("Visible Item")); +} + +GtkImage * +get_icon (IndicatorObject * io) +{ + return GTK_IMAGE(gtk_image_new()); +} + +GtkMenu * +get_menu (IndicatorObject * io) +{ + GtkMenu * main_menu = GTK_MENU(gtk_menu_new()); + GtkWidget * loading_item = gtk_menu_item_new_with_label("Loading..."); + gtk_menu_shell_append(GTK_MENU_SHELL(main_menu), loading_item); + gtk_widget_show(GTK_WIDGET(loading_item)); + + return main_menu; +} + +const gchar * +get_accessible_desc (IndicatorObject * io) +{ + return "Visible Item"; +} + +static void dummy_indicator_visible_class_init (DummyIndicatorVisibleClass *klass); +static void dummy_indicator_visible_init (DummyIndicatorVisible *self); +static void dummy_indicator_visible_dispose (GObject *object); +static void dummy_indicator_visible_finalize (GObject *object); + +G_DEFINE_TYPE (DummyIndicatorVisible, dummy_indicator_visible, INDICATOR_OBJECT_TYPE); + +static void +dummy_indicator_entry_being_removed (IndicatorObject * io, IndicatorObjectEntry * entry) +{ + g_object_set_data(G_OBJECT(entry->label), "is-hidden", GINT_TO_POINTER(1)); + + INDICATOR_OBJECT_CLASS(dummy_indicator_visible_parent_class)->entry_being_removed (io, entry); +} + +static void +dummy_indicator_entry_was_added (IndicatorObject * io, IndicatorObjectEntry * entry) +{ + g_object_steal_data(G_OBJECT(entry->label), "is-hidden"); + + INDICATOR_OBJECT_CLASS(dummy_indicator_visible_parent_class)->entry_was_added (io, entry); +} + +static void +dummy_indicator_visible_class_init (DummyIndicatorVisibleClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = dummy_indicator_visible_dispose; + object_class->finalize = dummy_indicator_visible_finalize; + + IndicatorObjectClass * io_class = INDICATOR_OBJECT_CLASS(klass); + + io_class->get_label = get_label; + io_class->get_image = get_icon; + io_class->get_menu = get_menu; + io_class->get_accessible_desc = get_accessible_desc; + io_class->entry_being_removed = dummy_indicator_entry_being_removed; + io_class->entry_was_added = dummy_indicator_entry_was_added; +} + +static void +dummy_indicator_visible_init (DummyIndicatorVisible *self) +{ +} + +static void +dummy_indicator_visible_dispose (GObject *object) +{ + + G_OBJECT_CLASS (dummy_indicator_visible_parent_class)->dispose (object); +} + +static void +dummy_indicator_visible_finalize (GObject *object) +{ + + G_OBJECT_CLASS (dummy_indicator_visible_parent_class)->finalize (object); +} diff --git a/tests/test-loader.c b/tests/test-loader.c index ac9d4e5..51ea6f3 100644 --- a/tests/test-loader.c +++ b/tests/test-loader.c @@ -68,6 +68,95 @@ test_loader_filename_dummy_signaler (void) return; } +/*** +**** +***/ + +static void +visible_entry_added (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer box) +{ + // make a frame for the entry, and add the frame to the box + GtkWidget * frame = gtk_frame_new (NULL); + GtkWidget * child = GTK_WIDGET(entry->label); + g_assert (child != NULL); + gtk_container_add (GTK_CONTAINER(frame), child); + gtk_box_pack_start (GTK_BOX(box), frame, FALSE, FALSE, 0); + g_object_set_data (G_OBJECT(child), "frame-parent", frame); +} + +static void +visible_entry_removed (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer box) +{ + // destroy this entry's frame + gpointer parent = g_object_steal_data (G_OBJECT(entry->label), "frame-parent"); + if (GTK_IS_WIDGET(parent)) + gtk_widget_destroy(GTK_WIDGET(parent)); +} + +void +test_loader_filename_dummy_visible (void) +{ + const GQuark is_hidden_quark = g_quark_from_static_string ("is-hidden"); + IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-visible.so"); + g_assert(object != NULL); + + // create our local parent widgetry +#if GTK_CHECK_VERSION(3,0,0) + GtkWidget * box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); +#else + GtkWidget * box = gtk_hbox_new (TRUE, 0); +#endif + g_signal_connect(object, INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED, + G_CALLBACK(visible_entry_added), box); + g_signal_connect(object, INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED, + G_CALLBACK(visible_entry_removed), box); + + // on startup, DummyVisible has one entry and it has a label + GList * list = indicator_object_get_entries(object); + g_assert(g_list_length(list) == 1); + IndicatorObjectEntry * entry = list->data; + g_assert(entry != NULL); + g_list_free(list); + g_assert(GTK_IS_LABEL(entry->label)); + GtkWidget * label = GTK_WIDGET(entry->label); + g_assert(g_object_get_qdata(G_OBJECT(label), is_hidden_quark) == NULL); + + // add the inital entry to our local parent widgetry + visible_entry_added (object, entry, box); + entry = NULL; + list = gtk_container_get_children (GTK_CONTAINER(box)); + g_assert(g_list_length(list) == 1); + g_list_free(list); + + // hide the entries and confirm that the label survived + indicator_object_set_visible (object, FALSE); + while (g_main_context_pending(NULL)) + g_main_context_iteration(NULL, TRUE); + g_assert(GTK_IS_LABEL(label)); + g_assert(g_object_get_qdata(G_OBJECT(label), is_hidden_quark) != NULL); + list = gtk_container_get_children (GTK_CONTAINER(box)); + g_assert(g_list_length(list) == 0); + g_list_free(list); + + // restore the entries and confirm that the label survived + indicator_object_set_visible (object, TRUE); + while (g_main_context_pending(NULL)) + g_main_context_iteration(NULL, TRUE); + g_assert(GTK_IS_LABEL(label)); + g_assert(g_object_get_qdata(G_OBJECT(label), is_hidden_quark) == NULL); + list = gtk_container_get_children (GTK_CONTAINER(box)); + g_assert(g_list_length(list) == 1); + g_list_free(list); + + // cleanup + g_object_unref(object); + gtk_widget_destroy(box); +} + +/*** +**** +***/ + void test_loader_filename_dummy_simple_location (void) { @@ -174,6 +263,7 @@ test_loader_creation_deletion_suite (void) g_test_add_func ("/libindicator/loader/dummy/simple_accessors", test_loader_filename_dummy_simple_accessors); g_test_add_func ("/libindicator/loader/dummy/simple_location", test_loader_filename_dummy_simple_location); g_test_add_func ("/libindicator/loader/dummy/signaler", test_loader_filename_dummy_signaler); + g_test_add_func ("/libindicator/loader/dummy/visible", test_loader_filename_dummy_visible); return; } -- cgit v1.2.3 From 6f3976c52c5d551a6d33a54349441ac83d8b830c Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Mon, 23 Jan 2012 22:42:02 -0600 Subject: Bumping the ABI version --- libindicator/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libindicator/Makefile.am b/libindicator/Makefile.am index b574519..ef6c6c7 100644 --- a/libindicator/Makefile.am +++ b/libindicator/Makefile.am @@ -13,7 +13,7 @@ EXTRA_DIST = \ indicator3-0.$(INDICATOR_API_VERSION).pc.in.in \ indicator-0.$(INDICATOR_API_VERSION).pc.in.in -INDICATOR_ABI_VERSION = 6 +INDICATOR_ABI_VERSION = 7 INDICATOR_API_VERSION = 4 %.pc: %.pc.in -- cgit v1.2.3 From dbccdd5fd7c0850af8ffd411f906dc43785e599b Mon Sep 17 00:00:00 2001 From: Ted Gould Date: Tue, 24 Jan 2012 09:47:32 -0600 Subject: 0.4.90 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 4710901..e881de0 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_INIT([libindicator], - [0.4.1], + [0.4.90], [http://bugs.launchpad.net/libindicator], [libindicator], [http://launchpad.net/libindicator]) -- cgit v1.2.3