From 13c1c80b1e0cedea938960baf2229e29ab350830 Mon Sep 17 00:00:00 2001 From: Mike Gabriel Date: Thu, 6 May 2021 14:04:47 +0200 Subject: Travis CI: Also support CMake based CI builds. --- .build.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.build.yml b/.build.yml index 261f72e..16d1816 100644 --- a/.build.yml +++ b/.build.yml @@ -104,15 +104,15 @@ build_scripts: - cppcheck --enable=warning,style,performance,portability,information,missingInclude . - fi - - - if [ -e ./autogen.sh ]; then - - NOCONFIGURE=1 ./autogen.sh - - scan-build $CHECKERS ./configure --prefix=/usr --enable-gtk-doc --enable-compile-warnings=maximum - - elif [ -e ./CMakeLists.txt ]; then + - if [ -e ./CMakeLists.txt ]; then - if [ ${DISTRO_NAME} == "debian" ];then - scan-build $CHECKERS cmake . -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_VERBOSE_MAKEFILE=ON -DENABLE_TESTS=ON - else - scan-build $CHECKERS cmake . -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_VERBOSE_MAKEFILE=ON - fi + - elif [ -e ./autogen.sh ]; then + - NOCONFIGURE=1 ./autogen.sh + - scan-build $CHECKERS ./configure --prefix=/usr --enable-gtk-doc --enable-compile-warnings=maximum - else - exit 1 - fi @@ -135,11 +135,11 @@ after_scripts: - if [ ${BUILD_TYPE} == "scripts" ];then - XVFB_RUN="$(which xvfb-run || true)" - if [ ${DISTRO_NAME} == "debian" ];then - - if [ -e ./autogen.sh ]; then + - if [ -e ./CMakeLists.txt ]; then + - ${XVFB_RUN} env CTEST_OUTPUT_ON_FAILURE=1 make test + - elif [ -e ./autogen.sh ]; then - ${XVFB_RUN} make check - cat tests/test-suite.log - - elif [ -e ./CMakeLists.txt ]; then - - ${XVFB_RUN} env CTEST_OUTPUT_ON_FAILURE=1 make test - fi - fi - fi -- cgit v1.2.3 From b8b206c6e84757c6d4d36cec619a1e7c37d1eb5f Mon Sep 17 00:00:00 2001 From: Robert Tari Date: Wed, 10 Feb 2021 13:06:05 +0100 Subject: Move source files to src --- Makefile.am | 2 +- configure.ac | 34 +- libayatana-indicator/Makefile.am | 149 --- .../ayatana-indicator-0.4.pc.in.in | 17 - .../ayatana-indicator3-0.4.pc.in.in | 16 - libayatana-indicator/dbus-shared.h | 28 - libayatana-indicator/indicator-desktop-shortcuts.c | 682 ------------- libayatana-indicator/indicator-desktop-shortcuts.h | 80 -- libayatana-indicator/indicator-image-helper.c | 218 ----- libayatana-indicator/indicator-image-helper.h | 35 - libayatana-indicator/indicator-ng.c | 1031 -------------------- libayatana-indicator/indicator-ng.h | 48 - .../indicator-object-enum-types.c.template | 30 - .../indicator-object-enum-types.h.template | 27 - libayatana-indicator/indicator-object-marshal.list | 4 - libayatana-indicator/indicator-object.c | 967 ------------------ libayatana-indicator/indicator-object.h | 216 ---- libayatana-indicator/indicator-service-manager.c | 704 ------------- libayatana-indicator/indicator-service-manager.h | 88 -- libayatana-indicator/indicator-service.c | 649 ------------ libayatana-indicator/indicator-service.h | 85 -- libayatana-indicator/indicator-service.xml | 22 - libayatana-indicator/indicator.h | 41 - src/Makefile.am | 149 +++ src/ayatana-indicator-0.4.pc.in.in | 17 + src/ayatana-indicator3-0.4.pc.in.in | 16 + src/dbus-shared.h | 28 + src/indicator-desktop-shortcuts.c | 682 +++++++++++++ src/indicator-desktop-shortcuts.h | 80 ++ src/indicator-image-helper.c | 218 +++++ src/indicator-image-helper.h | 35 + src/indicator-ng.c | 1031 ++++++++++++++++++++ src/indicator-ng.h | 48 + src/indicator-object-enum-types.c.template | 30 + src/indicator-object-enum-types.h.template | 27 + src/indicator-object-marshal.list | 4 + src/indicator-object.c | 967 ++++++++++++++++++ src/indicator-object.h | 216 ++++ src/indicator-service-manager.c | 704 +++++++++++++ src/indicator-service-manager.h | 88 ++ src/indicator-service.c | 649 ++++++++++++ src/indicator-service.h | 85 ++ src/indicator-service.xml | 22 + src/indicator.h | 41 + tests/Makefile.am | 42 +- tests/dummy-indicator-blank.c | 2 +- tests/dummy-indicator-entry-func.h | 14 +- tests/dummy-indicator-null.c | 44 +- tests/dummy-indicator-signaler.c | 90 +- tests/dummy-indicator-simple.c | 52 +- tests/dummy-indicator-visible.c | 68 +- tests/service-manager-connect-service.c | 2 +- tests/service-manager-connect.c | 2 +- tests/service-manager-no-connect.c | 2 +- tests/service-manager-nostart-connect.c | 2 +- tests/service-shutdown-timeout.c | 2 +- tests/service-version-bad-service.c | 2 +- tests/service-version-good-service.c | 2 +- tests/service-version-manager.c | 2 +- .../service-version-multiwatch-manager-impolite.c | 2 +- tests/service-version-multiwatch-manager.c | 2 +- tests/service-version-multiwatch-service.c | 2 +- tests/test-desktop-shortcuts.c | 2 +- tests/test-indicator-ng.c | 2 +- tests/test-loader.c | 380 ++++---- tools/Makefile.am | 2 +- tools/indicator-loader.c | 8 +- 67 files changed, 5519 insertions(+), 5519 deletions(-) delete mode 100644 libayatana-indicator/Makefile.am delete mode 100644 libayatana-indicator/ayatana-indicator-0.4.pc.in.in delete mode 100644 libayatana-indicator/ayatana-indicator3-0.4.pc.in.in delete mode 100644 libayatana-indicator/dbus-shared.h delete mode 100644 libayatana-indicator/indicator-desktop-shortcuts.c delete mode 100644 libayatana-indicator/indicator-desktop-shortcuts.h delete mode 100644 libayatana-indicator/indicator-image-helper.c delete mode 100644 libayatana-indicator/indicator-image-helper.h delete mode 100644 libayatana-indicator/indicator-ng.c delete mode 100644 libayatana-indicator/indicator-ng.h delete mode 100644 libayatana-indicator/indicator-object-enum-types.c.template delete mode 100644 libayatana-indicator/indicator-object-enum-types.h.template delete mode 100644 libayatana-indicator/indicator-object-marshal.list delete mode 100644 libayatana-indicator/indicator-object.c delete mode 100644 libayatana-indicator/indicator-object.h delete mode 100644 libayatana-indicator/indicator-service-manager.c delete mode 100644 libayatana-indicator/indicator-service-manager.h delete mode 100644 libayatana-indicator/indicator-service.c delete mode 100644 libayatana-indicator/indicator-service.h delete mode 100644 libayatana-indicator/indicator-service.xml delete mode 100644 libayatana-indicator/indicator.h create mode 100644 src/Makefile.am create mode 100644 src/ayatana-indicator-0.4.pc.in.in create mode 100644 src/ayatana-indicator3-0.4.pc.in.in create mode 100644 src/dbus-shared.h create mode 100644 src/indicator-desktop-shortcuts.c create mode 100644 src/indicator-desktop-shortcuts.h create mode 100644 src/indicator-image-helper.c create mode 100644 src/indicator-image-helper.h create mode 100644 src/indicator-ng.c create mode 100644 src/indicator-ng.h create mode 100644 src/indicator-object-enum-types.c.template create mode 100644 src/indicator-object-enum-types.h.template create mode 100644 src/indicator-object-marshal.list create mode 100644 src/indicator-object.c create mode 100644 src/indicator-object.h create mode 100644 src/indicator-service-manager.c create mode 100644 src/indicator-service-manager.h create mode 100644 src/indicator-service.c create mode 100644 src/indicator-service.h create mode 100644 src/indicator-service.xml create mode 100644 src/indicator.h diff --git a/Makefile.am b/Makefile.am index 0a03376..bd052fd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,7 +2,7 @@ ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} SUBDIRS = \ data \ - libayatana-indicator \ + src \ tools tools: libayatana-indicator diff --git a/configure.ac b/configure.ac index 95398ec..9ba72ec 100644 --- a/configure.ac +++ b/configure.ac @@ -146,17 +146,17 @@ PKG_CHECK_MODULES(SYSTEMD, systemd, [] ) if test "x$has_systemd" = "xyes"; then - SYSTEMD_USERDIR=`$PKG_CONFIG --variable=systemduserunitdir systemd` - AC_SUBST(SYSTEMD_USERDIR) - AC_DEFINE(HAVE_SYSTEMD, 1, [create ayatana-indicators-pre.target for systemd]) + SYSTEMD_USERDIR=`$PKG_CONFIG --variable=systemduserunitdir systemd` + AC_SUBST(SYSTEMD_USERDIR) + AC_DEFINE(HAVE_SYSTEMD, 1, [create ayatana-indicators-pre.target for systemd]) fi ######################### # Check if build tests ######################### AC_ARG_ENABLE([tests], - AC_HELP_STRING([--disable-tests], [disable tests]),, - [enable_tests=yes]) + AC_HELP_STRING([--disable-tests], [disable tests]),, + [enable_tests=yes]) AM_CONDITIONAL([WANT_TESTS], [test "x$enable_tests" != "xno"]) ######################### @@ -167,8 +167,8 @@ AC_ARG_ENABLE([debug], [enable_debug=no]) if test "x$enable_debug" = "xyes"; then - CFLAGS="-g $CFLAGS" - AC_DEFINE(ENABLE_DEBUG, 1, [build with extra debug information]) + CFLAGS="-g $CFLAGS" + AC_DEFINE(ENABLE_DEBUG, 1, [build with extra debug information]) fi AM_CONDITIONAL(ENABLE_DEBUG, test "$enable_debug" = "yes") @@ -192,9 +192,9 @@ AC_SUBST(COVERAGE_LDFLAGS) AC_CONFIG_FILES([ Makefile data/Makefile -libayatana-indicator/Makefile -libayatana-indicator/ayatana-indicator-0.4.pc.in -libayatana-indicator/ayatana-indicator3-0.4.pc.in +src/Makefile +src/ayatana-indicator-0.4.pc.in +src/ayatana-indicator3-0.4.pc.in tests/Makefile tools/Makefile ]) @@ -208,11 +208,11 @@ AC_MSG_NOTICE([ Libindicator Configuration: - Prefix: $prefix - GTK+ Version: $with_gtk - - Enable IDO loader: $enable_ido - Enable tests: $enable_tests - Enable debugging: $enable_debug - Coverage reporting: $use_gcov + Prefix: $prefix + GTK+ Version: $with_gtk + + Enable IDO loader: $enable_ido + Enable tests: $enable_tests + Enable debugging: $enable_debug + Coverage reporting: $use_gcov ]) diff --git a/libayatana-indicator/Makefile.am b/libayatana-indicator/Makefile.am deleted file mode 100644 index 4933c71..0000000 --- a/libayatana-indicator/Makefile.am +++ /dev/null @@ -1,149 +0,0 @@ -if USE_GTK3 -VER=3 -lib_LTLIBRARIES = libayatana-indicator3.la -else -VER= -lib_LTLIBRARIES = libayatana-indicator.la -GTK_DISABLE_DEPRECATED = -DGTK_DISABLE_DEPRECATED -endif - -BUILT_SOURCES = indicator-object-enum-types.h indicator-object-enum-types.c -CLEANFILES = -DISTCLEANFILES = -EXTRA_DIST = \ - ayatana-indicator3-0.$(INDICATOR_API_VERSION).pc.in.in \ - ayatana-indicator-0.$(INDICATOR_API_VERSION).pc.in.in - -INDICATOR_ABI_VERSION = 7 -INDICATOR_API_VERSION = 4 - -%.pc: %.pc.in - sed \ - -e "s|\@indicator_api_version\@|$(INDICATOR_API_VERSION)|" \ - -e "s|\@indicator_abi_version\@|$(INDICATOR_ABI_VERSION)|" \ - $< > $@ - -CLEANFILES += ayatana-indicator$(VER)-0.$(INDICATOR_API_VERSION).pc - -include $(top_srcdir)/Makefile.am.marshal - -libayatana_indicatorincludedir=$(includedir)/libayatana-indicator$(VER)-0.$(INDICATOR_API_VERSION)/libayatana-indicator - -indicator_headers = \ - indicator.h \ - indicator-desktop-shortcuts.h \ - indicator-image-helper.h \ - indicator-object.h \ - indicator-service.h \ - indicator-service-manager.h - -if USE_GTK3 -indicator_headers += \ - indicator-ng.h -endif - -libayatana_indicatorinclude_HEADERS = \ - $(indicator_headers) - -libayatana_indicator_la_SOURCES = \ - $(indicator_headers) \ - dbus-shared.h \ - gen-indicator-service.xml.h \ - gen-indicator-service.xml.c \ - indicator-object.c \ - indicator-object-enum-types.c \ - indicator-desktop-shortcuts.c \ - indicator-image-helper.c \ - indicator-object-marshal.h \ - indicator-object-marshal.c \ - indicator-service.c \ - indicator-service-manager.c - -if USE_GTK3 -libayatana_indicator_la_SOURCES += \ - indicator-ng.c -endif - -libayatana_indicator_la_CFLAGS = \ - $(LIBINDICATOR_CFLAGS) \ - $(LIBINDICATOR_IDO_CFLAGS) \ - $(COVERAGE_CFLAGS) \ - $(GTK_DISABLE_DEPRECATED) \ - -DG_LOG_DOMAIN=\"libayatana-indicator\" \ - -Wall -Wno-error=deprecated-declarations - -libayatana_indicator_la_LIBADD = \ - $(LIBINDICATOR_LIBS) \ - $(LIBINDICATOR_IDO_LIBS) \ - $(LIBM) - -libayatana_indicator_la_LDFLAGS = \ - $(COVERAGE_LDFLAGS) \ - -version-info $(INDICATOR_ABI_VERSION):0:0 \ - -no-undefined \ - -export-symbols-regex "^[^_].*" - -# We duplicate these here because Automake won't let us use $(VER) on the left hand side. -# Since we carefully use $(VER) in the right hand side above, we can assign the same values. -# Only one version of the library is every compiled at the same time, so it is safe to reuse -# the right hand sides like this. -libayatana_indicator3includedir = $(libayatana_indicatorincludedir) -libayatana_indicator3include_HEADERS = $(indicator_headers) -libayatana_indicator3_la_SOURCES = $(libayatana_indicator_la_SOURCES) -libayatana_indicator3_la_CFLAGS = $(libayatana_indicator_la_CFLAGS) -libayatana_indicator3_la_LIBADD = $(libayatana_indicator_la_LIBADD) -libayatana_indicator3_la_LDFLAGS = $(libayatana_indicator_la_LDFLAGS) - -pkgconfig_DATA = ayatana-indicator$(VER)-0.$(INDICATOR_API_VERSION).pc -pkgconfigdir = $(libdir)/pkgconfig - -glib_marshal_list = indicator-object-marshal.list -glib_marshal_prefix = _indicator_object_marshal - -indicator-object-enum-types.h: s-enum-types-h - @true -s-enum-types-h: $(indicator_headers) - ( cd $(srcdir) && $(GLIB_MKENUMS) --template $(abs_srcdir)/indicator-object-enum-types.h.template \ - $(indicator_headers) ) >> tmp-indicator-object-enum-types.h \ - && (cmp -s tmp-indicator-object-enum-types.h indicator-object-enum-types.h || cp tmp-indicator-object-enum-types.h indicator-object-enum-types.h ) \ - && rm -f tmp-indicator-object-enum-types.h && echo timestamp > $(@F) - -indicator-object-enum-types.c: s-enum-types-c - @true -s-enum-types-c: $(indicator_headers) - ( cd $(srcdir) && $(GLIB_MKENUMS) --template $(abs_srcdir)/indicator-object-enum-types.c.template \ - $(indicator_headers) ) > tmp-indicator-object-enum-types.c \ - && (cmp -s tmp-indicator-object-enum-types.c indicator-object-enum-types.c || cp tmp-indicator-object-enum-types.c indicator-object-enum-types.c ) \ - && rm -f tmp-indicator-object-enum-types.c - -EXTRA_DIST += indicator-object-enum-types.h.template indicator-object-enum-types.c.template -CLEANFILES += \ - indicator-object-enum-types.h \ - indicator-object-enum-types.c \ - s-enum-types-h \ - s-enum-types-c - -################################## -# DBus Specs -################################## - -DBUS_SPECS = \ - indicator-service.xml - -gen-%.xml.h: %.xml - @echo "Building $@ from $<" - @echo "extern const char * _$(subst -,_,$(subst .,_,$(basename $(notdir $<))));" > $@ - -gen-%.xml.c: %.xml - @echo "Building $@ from $<" - echo "const char * _$(subst -,_,$(subst .,_,$(basename $(notdir $<)))) = " > $@ - @sed -e "s:\":\\\\\":g" -e s:^:\": -e s:\$$:\\\\n\": $< >> $@ - @echo ";" >> $@ - -BUILT_SOURCES += \ - gen-indicator-service.xml.h \ - gen-indicator-service.xml.c - -CLEANFILES += $(BUILT_SOURCES) - -EXTRA_DIST += $(DBUS_SPECS) diff --git a/libayatana-indicator/ayatana-indicator-0.4.pc.in.in b/libayatana-indicator/ayatana-indicator-0.4.pc.in.in deleted file mode 100644 index 02ff40d..0000000 --- a/libayatana-indicator/ayatana-indicator-0.4.pc.in.in +++ /dev/null @@ -1,17 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -bindir=@bindir@ -includedir=@includedir@ - -indicatordir=${exec_prefix}/lib/ayatana-indicators/@indicator_abi_version@ -iconsdir=@datarootdir@/@PACKAGE@/icons/ - -Cflags: -I${includedir}/libayatana-indicator-0.@indicator_api_version@ -Requires: gtk+-2.0 -Libs: -layatana-indicator - -Name: libayatana-indicator -Description: libayatana-indicator. -Version: @VERSION@ - diff --git a/libayatana-indicator/ayatana-indicator3-0.4.pc.in.in b/libayatana-indicator/ayatana-indicator3-0.4.pc.in.in deleted file mode 100644 index ff0862e..0000000 --- a/libayatana-indicator/ayatana-indicator3-0.4.pc.in.in +++ /dev/null @@ -1,16 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -bindir=@bindir@ -includedir=@includedir@ - -indicatordir=${exec_prefix}/lib/ayatana-indicators3/@indicator_abi_version@/ -iconsdir=@datarootdir@/@PACKAGE@/icons/ - -Cflags: -I${includedir}/libayatana-indicator3-0.@indicator_api_version@ -Requires: gtk+-3.0 -Libs: -layatana-indicator3 - -Name: libayatana-indicator3 -Description: libayatana-indicator3. -Version: @VERSION@ diff --git a/libayatana-indicator/dbus-shared.h b/libayatana-indicator/dbus-shared.h deleted file mode 100644 index b55acef..0000000 --- a/libayatana-indicator/dbus-shared.h +++ /dev/null @@ -1,28 +0,0 @@ -/* -Shared defines for DBus interfaces and API versions to -make sure the server and client agree. - -Copyright 2009 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 -. -*/ - -#define INDICATOR_SERVICE_INTERFACE "org.ayatana.indicator.service" -#define INDICATOR_SERVICE_OBJECT "/org/ayatana/indicator/service" - -#define INDICATOR_SERVICE_VERSION 1 - diff --git a/libayatana-indicator/indicator-desktop-shortcuts.c b/libayatana-indicator/indicator-desktop-shortcuts.c deleted file mode 100644 index be1d632..0000000 --- a/libayatana-indicator/indicator-desktop-shortcuts.c +++ /dev/null @@ -1,682 +0,0 @@ -/* -A small file to parse through the actions that are available -in the desktop file and making those easily usable. - -Copyright 2010 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 -. -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include "indicator-desktop-shortcuts.h" - -#define ACTIONS_KEY "Actions" -#define ACTION_GROUP_PREFIX "Desktop Action" - -#define OLD_GROUP_SUFFIX "Shortcut Group" -#define OLD_SHORTCUTS_KEY "X-Ayatana-Desktop-Shortcuts" -#define OLD_ENVIRON_KEY "TargetEnvironment" - -#define PROP_DESKTOP_FILE_S "desktop-file" -#define PROP_IDENTITY_S "identity" - -typedef enum _actions_t actions_t; -enum _actions_t { - ACTIONS_NONE, - ACTIONS_XAYATANA, - ACTIONS_DESKTOP_SPEC -}; - -typedef struct { - actions_t actions; - GKeyFile * keyfile; - gchar * identity; - GArray * nicks; - gchar * domain; -} IndicatorDesktopShortcutsPrivate; - -enum { - PROP_0, - PROP_DESKTOP_FILE, - PROP_IDENTITY -}; - -static void indicator_desktop_shortcuts_class_init (IndicatorDesktopShortcutsClass *klass); -static void indicator_desktop_shortcuts_init (IndicatorDesktopShortcuts *self); -static void indicator_desktop_shortcuts_dispose (GObject *object); -static void indicator_desktop_shortcuts_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 parse_keyfile (IndicatorDesktopShortcuts * ids); -static gboolean should_show (GKeyFile * keyfile, const gchar * group, const gchar * identity, gboolean should_have_target); - -G_DEFINE_TYPE_WITH_PRIVATE (IndicatorDesktopShortcuts, indicator_desktop_shortcuts, G_TYPE_OBJECT); - -/* Build up the class */ -static void -indicator_desktop_shortcuts_class_init (IndicatorDesktopShortcutsClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = indicator_desktop_shortcuts_dispose; - object_class->finalize = indicator_desktop_shortcuts_finalize; - - /* Property funcs */ - object_class->set_property = set_property; - object_class->get_property = get_property; - - g_object_class_install_property(object_class, PROP_DESKTOP_FILE, - g_param_spec_string(PROP_DESKTOP_FILE_S, - "The path of the desktop file to read", - "A path to a desktop file that we'll look for shortcuts in.", - NULL, - G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY)); - g_object_class_install_property(object_class, PROP_IDENTITY, - g_param_spec_string(PROP_IDENTITY_S, - "The string that represents the identity that we're acting as.", - "Used to process ShowIn and NotShownIn fields of the desktop shortcust to get the proper list.", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY)); - - return; -} - -/* Initialize instance data */ -static void -indicator_desktop_shortcuts_init (IndicatorDesktopShortcuts *self) -{ - IndicatorDesktopShortcutsPrivate * priv = indicator_desktop_shortcuts_get_instance_private(self); - - priv->keyfile = NULL; - priv->identity = NULL; - priv->domain = NULL; - priv->nicks = g_array_new(TRUE, TRUE, sizeof(gchar *)); - priv->actions = ACTIONS_NONE; - - return; -} - -/* Clear object references */ -static void -indicator_desktop_shortcuts_dispose (GObject *object) -{ - IndicatorDesktopShortcuts * self = INDICATOR_DESKTOP_SHORTCUTS(object); - IndicatorDesktopShortcutsPrivate * priv = indicator_desktop_shortcuts_get_instance_private(self); - - if (priv->keyfile) { - g_key_file_free(priv->keyfile); - priv->keyfile = NULL; - } - - G_OBJECT_CLASS (indicator_desktop_shortcuts_parent_class)->dispose (object); - return; -} - -/* Free all memory */ -static void -indicator_desktop_shortcuts_finalize (GObject *object) -{ - IndicatorDesktopShortcuts * self = INDICATOR_DESKTOP_SHORTCUTS(object); - IndicatorDesktopShortcutsPrivate * priv = indicator_desktop_shortcuts_get_instance_private(self); - - if (priv->identity != NULL) { - g_free(priv->identity); - priv->identity = NULL; - } - - if (priv->domain != NULL) { - g_free(priv->domain); - priv->domain = NULL; - } - - if (priv->nicks != NULL) { - guint i; - for (i = 0; i < priv->nicks->len; i++) { - gchar * nick = g_array_index(priv->nicks, gchar *, i); - g_free(nick); - } - g_array_free(priv->nicks, TRUE); - priv->nicks = NULL; - } - - G_OBJECT_CLASS (indicator_desktop_shortcuts_parent_class)->finalize (object); - return; -} - -/* Sets one of the two properties we have, only at construction though */ -static void -set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) -{ - g_return_if_fail(INDICATOR_IS_DESKTOP_SHORTCUTS(object)); - IndicatorDesktopShortcuts * self = INDICATOR_DESKTOP_SHORTCUTS(object); - IndicatorDesktopShortcutsPrivate * priv = indicator_desktop_shortcuts_get_instance_private(self); - - switch(prop_id) { - case PROP_DESKTOP_FILE: { - if (priv->keyfile != NULL) { - g_key_file_free(priv->keyfile); - priv->keyfile = NULL; - priv->actions = ACTIONS_NONE; - } - - GError * error = NULL; - GKeyFile * keyfile = g_key_file_new(); - g_key_file_load_from_file(keyfile, g_value_get_string(value), G_KEY_FILE_NONE, &error); - - if (error != NULL) { - g_warning("Unable to load keyfile from file '%s': %s", g_value_get_string(value), error->message); - g_error_free(error); - g_key_file_free(keyfile); - break; - } - - /* Always prefer the desktop spec if we can get it */ - if (priv->actions == ACTIONS_NONE && g_key_file_has_key(keyfile, G_KEY_FILE_DESKTOP_GROUP, ACTIONS_KEY, NULL)) { - priv->actions = ACTIONS_DESKTOP_SPEC; - } - - /* But fallback if we can't */ - if (priv->actions == ACTIONS_NONE && g_key_file_has_key(keyfile, G_KEY_FILE_DESKTOP_GROUP, OLD_SHORTCUTS_KEY, NULL)) { - priv->actions = ACTIONS_XAYATANA; - g_warning("Desktop file '%s' is using a deprecated format for its actions that will be dropped soon.", g_value_get_string(value)); - } - - if (priv->actions == ACTIONS_NONE) { - g_key_file_free(keyfile); - break; - } - - priv->keyfile = keyfile; - parse_keyfile(INDICATOR_DESKTOP_SHORTCUTS(object)); - break; - } - case PROP_IDENTITY: - if (priv->identity != NULL) { - g_warning("Identity already set to '%s' and trying to set it to '%s'.", priv->identity, g_value_get_string(value)); - return; - } - priv->identity = g_value_dup_string(value); - parse_keyfile(INDICATOR_DESKTOP_SHORTCUTS(object)); - break; - /* *********************** */ - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } - - return; -} - -/* Gets either the desktop file our the identity. */ -static void -get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) -{ - g_return_if_fail(INDICATOR_IS_DESKTOP_SHORTCUTS(object)); - IndicatorDesktopShortcuts * self = INDICATOR_DESKTOP_SHORTCUTS(object); - IndicatorDesktopShortcutsPrivate * priv = indicator_desktop_shortcuts_get_instance_private(self); - - switch(prop_id) { - case PROP_IDENTITY: - g_value_set_string(value, priv->identity); - break; - /* *********************** */ - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } - - return; -} - -/* Checks to see if we can, and if we can it goes through - and parses the keyfile entries. */ -static void -parse_keyfile (IndicatorDesktopShortcuts * ids) -{ - IndicatorDesktopShortcuts * self = INDICATOR_DESKTOP_SHORTCUTS(ids); - IndicatorDesktopShortcutsPrivate * priv = indicator_desktop_shortcuts_get_instance_private(self); - - if (priv->keyfile == NULL) { - return; - } - - if (priv->identity == NULL) { - return; - } - - /* Remove a previous translation domain if we had one - from a previously parsed file. */ - if (priv->domain != NULL) { - g_free(priv->domain); - priv->domain = NULL; - } - - /* Check to see if there is a custom translation domain that - we should take into account. */ - if (priv->domain == NULL && - g_key_file_has_key(priv->keyfile, G_KEY_FILE_DESKTOP_GROUP, "X-GNOME-Gettext-Domain", NULL)) { - priv->domain = g_key_file_get_string(priv->keyfile, G_KEY_FILE_DESKTOP_GROUP, "X-GNOME-Gettext-Domain", NULL); - } - - if (priv->domain == NULL && - g_key_file_has_key(priv->keyfile, G_KEY_FILE_DESKTOP_GROUP, "X-Ubuntu-Gettext-Domain", NULL)) { - priv->domain = g_key_file_get_string(priv->keyfile, G_KEY_FILE_DESKTOP_GROUP, "X-Ubuntu-Gettext-Domain", NULL); - } - - /* We need to figure out what we're looking for and what we want to - look for in the rest of the file */ - const gchar * list_name = NULL; - const gchar * group_format = NULL; - gboolean should_have_target = FALSE; - - switch (priv->actions) { - case ACTIONS_NONE: - /* None, let's just get outta here */ - return; - case ACTIONS_XAYATANA: - list_name = OLD_SHORTCUTS_KEY; - group_format = "%s " OLD_GROUP_SUFFIX; - should_have_target = TRUE; - break; - case ACTIONS_DESKTOP_SPEC: - list_name = ACTIONS_KEY; - group_format = ACTION_GROUP_PREFIX " %s"; - should_have_target = FALSE; - break; - default: - g_assert_not_reached(); - return; - } - - /* Okay, we've got everything we need. Let's get it on! */ - gsize i; - gsize num_nicks = 0; - gchar ** nicks = g_key_file_get_string_list(priv->keyfile, G_KEY_FILE_DESKTOP_GROUP, list_name, &num_nicks, NULL); - - /* If there is an error from get_string_list num_nicks should still - be zero, so this loop will drop out. */ - for (i = 0; i < num_nicks; i++) { - /* g_debug("Looking at group nick %s", nicks[i]); */ - gchar * groupname = g_strdup_printf(group_format, nicks[i]); - if (!g_key_file_has_group(priv->keyfile, groupname)) { - g_warning("Unable to find group '%s'", groupname); - g_free(groupname); - continue; - } - - if (!should_show(priv->keyfile, G_KEY_FILE_DESKTOP_GROUP, priv->identity, FALSE)) { - g_free(groupname); - continue; - } - - if (!should_show(priv->keyfile, groupname, priv->identity, should_have_target)) { - g_free(groupname); - continue; - } - - gchar * nickalloc = g_strdup(nicks[i]); - g_array_append_val(priv->nicks, nickalloc); - g_free(groupname); - } - - if (nicks != NULL) { - g_strfreev(nicks); - } - - return; -} - -/* Checks the ONLY_SHOW_IN and NOT_SHOW_IN keys for a group to - see if we should be showing ourselves. */ -static gboolean -should_show (GKeyFile * keyfile, const gchar * group, const gchar * identity, gboolean should_have_target) -{ - if (should_have_target && g_key_file_has_key(keyfile, group, OLD_ENVIRON_KEY, NULL)) { - /* If we've got this key, we're going to return here and not - process the deprecated keys. */ - gsize j; - gsize num_env = 0; - gchar ** envs = g_key_file_get_string_list(keyfile, group, OLD_ENVIRON_KEY, &num_env, NULL); - - for (j = 0; j < num_env; j++) { - if (g_strcmp0(envs[j], identity) == 0) { - break; - } - } - - if (envs != NULL) { - g_strfreev(envs); - } - - if (j == num_env) { - return FALSE; - } - return TRUE; - } - - /* If there is a list of OnlyShowIn entries we need to check - to see if we're in that list. If not, we drop this nick */ - if (g_key_file_has_key(keyfile, group, G_KEY_FILE_DESKTOP_KEY_ONLY_SHOW_IN, NULL)) { - gsize j; - gsize num_only = 0; - gchar ** onlies = g_key_file_get_string_list(keyfile, group, G_KEY_FILE_DESKTOP_KEY_ONLY_SHOW_IN, &num_only, NULL); - - for (j = 0; j < num_only; j++) { - if (g_strcmp0(onlies[j], identity) == 0) { - break; - } - } - - if (onlies != NULL) { - g_strfreev(onlies); - } - - if (j == num_only) { - return FALSE; - } - } - - /* If there is a NotShowIn entry we need to make sure that we're - not in that list. If we are, we need to drop out. */ - if (g_key_file_has_key(keyfile, group, G_KEY_FILE_DESKTOP_KEY_NOT_SHOW_IN, NULL)) { - gsize j; - gsize num_not = 0; - gchar ** nots = g_key_file_get_string_list(keyfile, group, G_KEY_FILE_DESKTOP_KEY_NOT_SHOW_IN, &num_not, NULL); - - for (j = 0; j < num_not; j++) { - if (g_strcmp0(nots[j], identity) == 0) { - break; - } - } - - if (nots != NULL) { - g_strfreev(nots); - } - - if (j != num_not) { - return FALSE; - } - } - - return TRUE; -} - -/* 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) -{ - if (*list == NULL) - return FALSE; - /* g_debug("Checking Nick: %s", list[0]); */ - if (g_strcmp0(list[0], nick) == 0) - return TRUE; - return is_valid_nick(&list[1], nick); -} - -/* API */ - -/** - indicator_desktop_shortcuts_new: - @file: The desktop file that would be opened to - find the actions. - @identity: This is a string that represents the identity - that should be used in searching those actions. It - relates to the ShowIn and NotShownIn properties. - - This function creates the basic object. It involves opening - the file and parsing it. It could potentially block on IO. At - the end of the day you'll have a fully functional object. - - Return value: A new #IndicatorDesktopShortcuts object. -*/ -IndicatorDesktopShortcuts * -indicator_desktop_shortcuts_new (const gchar * file, const gchar * identity) -{ - GObject * obj = g_object_new(INDICATOR_TYPE_DESKTOP_SHORTCUTS, - PROP_DESKTOP_FILE_S, file, - PROP_IDENTITY_S, identity, - NULL); - return INDICATOR_DESKTOP_SHORTCUTS(obj); -} - -/** - indicator_desktop_shortcuts_get_nicks: - @ids: The #IndicatorDesktopShortcuts object to look in - - Give you the list of commands that are available for this desktop - file given the identity that was passed in at creation. This will - filter out the various items in the desktop file. These nicks can - then be used as keys for working with the desktop file. - - Return value: A #NULL terminated list of strings. This memory - is managed by the @ids object. -*/ -const gchar ** -indicator_desktop_shortcuts_get_nicks (IndicatorDesktopShortcuts * ids) -{ - g_return_val_if_fail(INDICATOR_IS_DESKTOP_SHORTCUTS(ids), NULL); - IndicatorDesktopShortcuts * self = INDICATOR_DESKTOP_SHORTCUTS(ids); - IndicatorDesktopShortcutsPrivate * priv = indicator_desktop_shortcuts_get_instance_private(self); - return (const gchar **)priv->nicks->data; -} - -/** - indicator_desktop_shortcuts_nick_get_name: - @ids: The #IndicatorDesktopShortcuts object to look in - @nick: Which command that we're referencing. - - This function looks in a desktop file for a nick to find the - user visible name for that shortcut. The @nick parameter - should be gotten from #indicator_desktop_shortcuts_get_nicks - though it's not required that the exact memory location - be the same. - - Return value: A user visible string for the shortcut or - #NULL on error. -*/ -gchar * -indicator_desktop_shortcuts_nick_get_name (IndicatorDesktopShortcuts * ids, const gchar * nick) -{ - g_return_val_if_fail(INDICATOR_IS_DESKTOP_SHORTCUTS(ids), NULL); - IndicatorDesktopShortcuts * self = INDICATOR_DESKTOP_SHORTCUTS(ids); - IndicatorDesktopShortcutsPrivate * priv = indicator_desktop_shortcuts_get_instance_private(self); - - g_return_val_if_fail(priv->actions != ACTIONS_NONE, NULL); - g_return_val_if_fail(priv->keyfile != NULL, NULL); - g_return_val_if_fail(is_valid_nick((gchar **)priv->nicks->data, nick), NULL); - - const gchar * group_format = NULL; - - switch (priv->actions) { - case ACTIONS_XAYATANA: - group_format = "%s " OLD_GROUP_SUFFIX; - break; - case ACTIONS_DESKTOP_SPEC: - group_format = ACTION_GROUP_PREFIX " %s"; - break; - default: - g_assert_not_reached(); - return NULL; - } - - gchar * groupheader = g_strdup_printf(group_format, nick); - if (!g_key_file_has_group(priv->keyfile, groupheader)) { - g_warning("The group for nick '%s' doesn't exist anymore.", nick); - g_free(groupheader); - return NULL; - } - - if (!g_key_file_has_key(priv->keyfile, groupheader, G_KEY_FILE_DESKTOP_KEY_NAME, NULL)) { - g_warning("No name available for nick '%s'", nick); - g_free(groupheader); - return NULL; - } - - gchar * name = NULL; - gchar * keyvalue = g_key_file_get_string(priv->keyfile, - groupheader, - G_KEY_FILE_DESKTOP_KEY_NAME, - NULL); - gchar * localeval = g_key_file_get_locale_string(priv->keyfile, - groupheader, - G_KEY_FILE_DESKTOP_KEY_NAME, - NULL, - NULL); - g_free(groupheader); - - if (priv->domain != NULL && g_strcmp0(keyvalue, localeval) == 0) { - name = g_strdup(g_dgettext(priv->domain, keyvalue)); - g_free(localeval); - } else { - name = localeval; - } - - g_free(keyvalue); - - return name; -} - -/** - indicator_desktop_shortcuts_nick_exec_with_context: - @ids: The #IndicatorDesktopShortcuts object to look in - @nick: Which command that we're referencing. - @launch_context: The #GAppLaunchContext to use for launching the shortcut - - Here we take a @nick and try and execute the action that is - associated with it. The @nick parameter should be gotten - from #indicator_desktop_shortcuts_get_nicks though it's not - required that the exact memory location be the same. - - Return value: #TRUE on success or #FALSE on error. -*/ -gboolean -indicator_desktop_shortcuts_nick_exec_with_context (IndicatorDesktopShortcuts * ids, const gchar * nick, GAppLaunchContext * launch_context) -{ - GError * error = NULL; - - g_return_val_if_fail(INDICATOR_IS_DESKTOP_SHORTCUTS(ids), FALSE); - IndicatorDesktopShortcuts * self = INDICATOR_DESKTOP_SHORTCUTS(ids); - IndicatorDesktopShortcutsPrivate * priv = indicator_desktop_shortcuts_get_instance_private(self); - - g_return_val_if_fail(priv->actions != ACTIONS_NONE, FALSE); - g_return_val_if_fail(priv->keyfile != NULL, FALSE); - g_return_val_if_fail(is_valid_nick((gchar **)priv->nicks->data, nick), FALSE); - - const gchar * group_format = NULL; - - switch (priv->actions) { - case ACTIONS_XAYATANA: - group_format = "%s " OLD_GROUP_SUFFIX; - break; - case ACTIONS_DESKTOP_SPEC: - group_format = ACTION_GROUP_PREFIX " %s"; - break; - default: - g_assert_not_reached(); - return FALSE; - } - - gchar * groupheader = g_strdup_printf(group_format, nick); - if (!g_key_file_has_group(priv->keyfile, groupheader)) { - g_warning("The group for nick '%s' doesn't exist anymore.", nick); - g_free(groupheader); - return FALSE; - } - - if (!g_key_file_has_key(priv->keyfile, groupheader, G_KEY_FILE_DESKTOP_KEY_NAME, NULL)) { - g_warning("No name available for nick '%s'", nick); - g_free(groupheader); - return FALSE; - } - - if (!g_key_file_has_key(priv->keyfile, groupheader, G_KEY_FILE_DESKTOP_KEY_EXEC, NULL)) { - g_warning("No exec available for nick '%s'", nick); - g_free(groupheader); - return FALSE; - } - - /* Grab the name and the exec entries out of our current group */ - gchar * name = g_key_file_get_locale_string(priv->keyfile, - groupheader, - G_KEY_FILE_DESKTOP_KEY_NAME, - NULL, - NULL); - - gchar * exec = g_key_file_get_locale_string(priv->keyfile, - groupheader, - G_KEY_FILE_DESKTOP_KEY_EXEC, - NULL, - NULL); - - g_free(groupheader); - - GAppInfoCreateFlags flags = G_APP_INFO_CREATE_NONE; - - if (launch_context) { - flags |= G_APP_INFO_CREATE_SUPPORTS_STARTUP_NOTIFICATION; - } - - GAppInfo * appinfo = g_app_info_create_from_commandline(exec, name, flags, &error); - g_free(name); g_free(exec); - - if (error != NULL) { - g_warning("Unable to build Command line App info: %s", error->message); - g_error_free(error); - return FALSE; - } - - if (appinfo == NULL) { - g_warning("Unable to build Command line App info (unknown)"); - return FALSE; - } - - gboolean launched = g_app_info_launch(appinfo, NULL, launch_context, &error); - - if (error != NULL) { - g_warning("Unable to launch file from nick '%s': %s", nick, error->message); - g_clear_error(&error); - } - - g_object_unref(appinfo); - - return launched; -} - -/** - indicator_desktop_shortcuts_nick_exec: - @ids: The #IndicatorDesktopShortcuts object to look in - @nick: Which command that we're referencing. - - Here we take a @nick and try and execute the action that is - associated with it. The @nick parameter should be gotten - from #indicator_desktop_shortcuts_get_nicks though it's not - required that the exact memory location be the same. - This function is deprecated and shouldn't be used in newly - written code. - - Return value: #TRUE on success or #FALSE on error. -*/ -gboolean -indicator_desktop_shortcuts_nick_exec (IndicatorDesktopShortcuts * ids, const gchar * nick) -{ - return indicator_desktop_shortcuts_nick_exec_with_context (ids, nick, NULL); -} diff --git a/libayatana-indicator/indicator-desktop-shortcuts.h b/libayatana-indicator/indicator-desktop-shortcuts.h deleted file mode 100644 index fb997ea..0000000 --- a/libayatana-indicator/indicator-desktop-shortcuts.h +++ /dev/null @@ -1,80 +0,0 @@ -/* -A small file to parse through the actions that are available -in the desktop file and making those easily usable. - -Copyright 2010 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 __INDICATOR_DESKTOP_SHORTCUTS_H__ -#define __INDICATOR_DESKTOP_SHORTCUTS_H__ - -#include -#include -#include - -G_BEGIN_DECLS - -#define INDICATOR_TYPE_DESKTOP_SHORTCUTS (indicator_desktop_shortcuts_get_type ()) -#define INDICATOR_DESKTOP_SHORTCUTS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_TYPE_DESKTOP_SHORTCUTS, IndicatorDesktopShortcuts)) -#define INDICATOR_DESKTOP_SHORTCUTS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INDICATOR_TYPE_DESKTOP_SHORTCUTS, IndicatorDesktopShortcutsClass)) -#define INDICATOR_IS_DESKTOP_SHORTCUTS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_TYPE_DESKTOP_SHORTCUTS)) -#define INDICATOR_IS_DESKTOP_SHORTCUTS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INDICATOR_TYPE_DESKTOP_SHORTCUTS)) -#define INDICATOR_DESKTOP_SHORTCUTS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), INDICATOR_TYPE_DESKTOP_SHORTCUTS, IndicatorDesktopShortcutsClass)) - -typedef struct _IndicatorDesktopShortcuts IndicatorDesktopShortcuts; -typedef struct _IndicatorDesktopShortcutsClass IndicatorDesktopShortcutsClass; - -/** - IndicatorDesktopShortcutsClass: - @parent_class: Space for #GObjectClass - - The vtable for our precious #IndicatorDesktopShortcutsClass. -*/ -struct _IndicatorDesktopShortcutsClass { - GObjectClass parent_class; -}; - -/** - IndicatorDesktopShortcuts: - @parent: The parent data from #GObject - - The public data for an instance of the class - #IndicatorDesktopShortcuts. -*/ -struct _IndicatorDesktopShortcuts { - GObject parent; -}; - -GType indicator_desktop_shortcuts_get_type (void); -IndicatorDesktopShortcuts * indicator_desktop_shortcuts_new (const gchar * file, - const gchar * identity); -const gchar ** indicator_desktop_shortcuts_get_nicks (IndicatorDesktopShortcuts * ids); -gchar * indicator_desktop_shortcuts_nick_get_name (IndicatorDesktopShortcuts * ids, - const gchar * nick); -gboolean indicator_desktop_shortcuts_nick_exec_with_context (IndicatorDesktopShortcuts * ids, - const gchar * nick, - GAppLaunchContext * launch_context); - -GLIB_DEPRECATED_FOR(indicator_desktop_shortcuts_nick_exec_with_context) -gboolean indicator_desktop_shortcuts_nick_exec (IndicatorDesktopShortcuts * ids, - const gchar * nick); - -G_END_DECLS - -#endif diff --git a/libayatana-indicator/indicator-image-helper.c b/libayatana-indicator/indicator-image-helper.c deleted file mode 100644 index 2c0e244..0000000 --- a/libayatana-indicator/indicator-image-helper.c +++ /dev/null @@ -1,218 +0,0 @@ -/* -A little helper to make a themed image with fallbacks that -is only constrained in the vertical dimention. - -Copyright 2010 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 "indicator-image-helper.h" - -const gchar * INDICATOR_NAMES_DATA = "indicator-names-data"; -const gint ICON_SIZE = 22; - -static void -refresh_image (GtkImage * image) -{ - g_return_if_fail(GTK_IS_IMAGE(image)); - const gchar * icon_filename = NULL; - GtkIconInfo * icon_info = NULL; - - GIcon * icon_names = (GIcon *)g_object_get_data(G_OBJECT(image), INDICATOR_NAMES_DATA); - g_return_if_fail(G_IS_ICON (icon_names)); - - /* Get the default theme */ - GtkIconTheme * default_theme = gtk_icon_theme_get_default(); - g_return_if_fail(default_theme != NULL); - - /* Look through the themes for that icon */ - icon_info = gtk_icon_theme_lookup_by_gicon(default_theme, icon_names, ICON_SIZE, 0); - if (icon_info == NULL) { - /* Maybe the icon was just added to the theme, see if a rescan helps */ - gtk_icon_theme_rescan_if_needed(default_theme); - icon_info = gtk_icon_theme_lookup_by_gicon(default_theme, icon_names, ICON_SIZE, 0); - } - if (icon_info == NULL) { - /* Try using the second item in the names, which should be the original filename supplied */ - const gchar * const * names = g_themed_icon_get_names(G_THEMED_ICON( icon_names )); - if (names) { - icon_filename = names[1]; - } else { - g_warning("Unable to find icon\n"); - gtk_image_clear(image); - return; - } - } else { - /* Grab the filename */ - icon_filename = gtk_icon_info_get_filename(icon_info); - } - - if (icon_filename == NULL && !G_IS_BYTES_ICON(icon_names)) { - /* show a broken image if we don't have a filename or image data */ - gtk_image_set_from_icon_name(image, "image-missing", GTK_ICON_SIZE_LARGE_TOOLBAR); - return; - } - - if (icon_info != NULL && !G_IS_BYTES_ICON(icon_names)) { - GdkPixbuf *pixbuf = gtk_icon_info_load_icon(icon_info, NULL); - - if (gdk_pixbuf_get_height(pixbuf) < ICON_SIZE) { - gtk_image_set_from_file(image, icon_filename); - } else { - gtk_image_set_from_gicon(image, icon_names, GTK_ICON_SIZE_LARGE_TOOLBAR); - } - g_object_unref (pixbuf); - } else if (icon_filename != NULL) { - gtk_image_set_from_file(image, icon_filename); - - gint height; - gdk_pixbuf_get_file_info(icon_filename, NULL, &height); - - if (height > ICON_SIZE) { - gtk_image_set_pixel_size(image, ICON_SIZE); - } - } else if (G_IS_LOADABLE_ICON(icon_names)) { - /* Build a pixbuf if needed */ - GdkPixbuf * pixbuf = NULL; - GError * error = NULL; - GInputStream * stream = g_loadable_icon_load(G_LOADABLE_ICON(icon_names), ICON_SIZE, NULL, NULL, &error); - - if (stream != NULL) { - pixbuf = gdk_pixbuf_new_from_stream(stream, NULL, &error); - g_input_stream_close (stream, NULL, NULL); - g_object_unref (stream); - - if (pixbuf != NULL) { - /* Scale icon if all we get is something too big. */ - if (gdk_pixbuf_get_height(pixbuf) > ICON_SIZE) { - gfloat scale = (gfloat)ICON_SIZE / (gfloat)gdk_pixbuf_get_height(pixbuf); - gint width = round(gdk_pixbuf_get_width(pixbuf) * scale); - - GdkPixbuf * scaled = gdk_pixbuf_scale_simple(pixbuf, width, ICON_SIZE, GDK_INTERP_BILINEAR); - g_object_unref(G_OBJECT(pixbuf)); - pixbuf = scaled; - } - - /* Put the pixbuf on the image */ - gtk_image_set_from_pixbuf(image, pixbuf); - g_object_unref(G_OBJECT(pixbuf)); - } else { - g_warning ("Unable to load icon from data: %s", error->message); - g_error_free (error); - } - } else { - g_warning ("Unable to load icon from data: %s", error->message); - g_error_free (error); - } - } - - if (icon_info != NULL) { -#if GTK_CHECK_VERSION(3, 8, 0) - g_object_unref(icon_info); -#else - /* NOTE: Leaving this in for lower version as it seems - the object_unref() doesn't work on earlier versions. */ - gtk_icon_info_free (icon_info); -#endif - } -} - -/* Handles the theme changed signal to refresh the icon to make - sure that it changes appropriately */ -static void -theme_changed_cb (__attribute__((unused)) GtkIconTheme * theme, gpointer user_data) -{ - GtkImage * image = GTK_IMAGE(user_data); - refresh_image(image); - return; -} - -/* Removes the signal on the theme that was calling update on this - image. */ -static void -image_destroyed_cb (GtkImage * image, __attribute__((unused)) gpointer user_data) -{ - g_signal_handlers_disconnect_by_func(gtk_icon_theme_get_default(), theme_changed_cb, image); - return; -} - -/* Catch the style changing on the image to make sure - we've got the latest. */ -static void -image_style_change_cb (GtkImage * image, __attribute__((unused)) GtkStyle * previous_style, __attribute__((unused)) gpointer user_data) -{ - refresh_image(image); - return; -} - -/* Builds an image with the name and fallbacks and all kinds of fun - stuff . */ -GtkImage * -indicator_image_helper (const gchar * name) -{ - /* Build us an image */ - GtkImage * image = GTK_IMAGE(gtk_image_new()); - - if (name) - indicator_image_helper_update(image, name); - - return image; -} - -/* Updates and image with all the fun stuff */ -void -indicator_image_helper_update (GtkImage * image, const gchar * name) -{ - g_return_if_fail(name != NULL); - g_return_if_fail(name[0] != '\0'); - g_return_if_fail(GTK_IS_IMAGE(image)); - - /* Build us a GIcon */ - GIcon * icon_names = g_themed_icon_new_with_default_fallbacks(name); - g_warn_if_fail(icon_names != NULL); - g_return_if_fail(icon_names != NULL); - - indicator_image_helper_update_from_gicon (image, icon_names); - - g_object_unref (icon_names); - return; -} - -void -indicator_image_helper_update_from_gicon (GtkImage *image, GIcon *icon) -{ - gboolean seen_previously = FALSE; - - seen_previously = (g_object_get_data(G_OBJECT(image), INDICATOR_NAMES_DATA) != NULL); - - /* Attach our names to the image */ - g_object_set_data_full(G_OBJECT(image), INDICATOR_NAMES_DATA, g_object_ref (icon), g_object_unref); - - /* Put the pixbuf in */ - refresh_image(image); - - /* Connect to all changes */ - if (!seen_previously) { - g_signal_connect(G_OBJECT(gtk_icon_theme_get_default()), "changed", G_CALLBACK(theme_changed_cb), image); - g_signal_connect(G_OBJECT(image), "destroy", G_CALLBACK(image_destroyed_cb), NULL); - g_signal_connect(G_OBJECT(image), "style-set", G_CALLBACK(image_style_change_cb), NULL); - } - - return; -} diff --git a/libayatana-indicator/indicator-image-helper.h b/libayatana-indicator/indicator-image-helper.h deleted file mode 100644 index 290f4e2..0000000 --- a/libayatana-indicator/indicator-image-helper.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -A little helper to make a themed image with fallbacks that -is only constrained in the vertical dimention. - -Copyright 2010 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 __INDICATOR_IMAGE_HELPER_H__ -#define __INDICATOR_IMAGE_HELPER_H__ - -#include - -GtkImage * indicator_image_helper (const gchar * name); -void indicator_image_helper_update (GtkImage * image, - const gchar * name); -void indicator_image_helper_update_from_gicon (GtkImage * image, - GIcon * icon); - -#endif /* __INDICATOR_IMAGE_HELPER_H__ */ diff --git a/libayatana-indicator/indicator-ng.c b/libayatana-indicator/indicator-ng.c deleted file mode 100644 index f057600..0000000 --- a/libayatana-indicator/indicator-ng.c +++ /dev/null @@ -1,1031 +0,0 @@ -/* - * Copyright 2013 Canonical Ltd. - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - * - * Authors: - * Lars Uebernickel - */ - -#include "indicator-ng.h" -#include "indicator-image-helper.h" -#include -#include - -#define MENU_SECTIONS 20 - -struct _IndicatorNg -{ - IndicatorObject parent; - - gchar *service_file; - gchar *name; - gchar *object_path; - gchar *menu_object_path; - gchar *bus_name; - gchar *profile; - gchar *header_action; - gchar *scroll_action; - gchar *secondary_action; - gchar *submenu_action; - gint position; - - guint name_watch_id; - - GDBusConnection *session_bus; - GActionGroup *actions; - GMenuModel *menu; - - IndicatorObjectEntry entry; - gchar *accessible_desc; - - gint64 last_service_restart; - GMenuModel *lMenuSections[MENU_SECTIONS]; -}; - -static void indicator_ng_initable_iface_init (GInitableIface *initable); -G_DEFINE_TYPE_WITH_CODE (IndicatorNg, indicator_ng, INDICATOR_OBJECT_TYPE, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, indicator_ng_initable_iface_init)) - -enum -{ - PROP_0, - PROP_SERVICE_FILE, - PROP_PROFILE, - N_PROPERTIES -}; - -static GQuark m_pActionMuxer = 0; -static GParamSpec *properties[N_PROPERTIES]; - -static void -indicator_ng_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - IndicatorNg *self = INDICATOR_NG (object); - - switch (property_id) - { - case PROP_SERVICE_FILE: - g_value_set_string (value, self->service_file); - break; - - case PROP_PROFILE: - g_value_set_string (value, self->profile); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - -static void -indicator_ng_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - IndicatorNg *self = INDICATOR_NG (object); - - switch (property_id) - { - case PROP_SERVICE_FILE: /* construct-only */ - self->service_file = g_strdup (g_value_get_string (value)); - break; - - case PROP_PROFILE: /* construct-only */ - self->profile = g_strdup (g_value_get_string (value)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - } -} - -static void -indicator_ng_free_actions_and_menu (IndicatorNg *self) -{ - if (self->actions) - { - gtk_widget_insert_action_group (GTK_WIDGET (self->entry.menu), "indicator", NULL); - g_signal_handlers_disconnect_by_data (self->actions, self); - g_clear_object (&self->actions); - } - - if (self->menu) - { - for (guint nMenuSection = 0; nMenuSection < MENU_SECTIONS; nMenuSection++) - { - if (self->lMenuSections[nMenuSection]) - { - g_object_unref(self->lMenuSections[nMenuSection]); - self->lMenuSections[nMenuSection] = NULL; - } - } - - g_signal_handlers_disconnect_by_data (self->menu, self); - g_clear_object (&self->menu); - } -} - -static void -indicator_ng_dispose (GObject *object) -{ - IndicatorNg *self = INDICATOR_NG (object); - - if (self->name_watch_id) - { - g_bus_unwatch_name (self->name_watch_id); - self->name_watch_id = 0; - } - - g_clear_object (&self->session_bus); - - indicator_ng_free_actions_and_menu (self); - - g_clear_object (&self->entry.label); - g_clear_object (&self->entry.image); - g_clear_object (&self->entry.menu); - - G_OBJECT_CLASS (indicator_ng_parent_class)->dispose (object); -} - -static void -indicator_ng_finalize (GObject *object) -{ - IndicatorNg *self = INDICATOR_NG (object); - - g_free (self->service_file); - g_free (self->name); - g_free (self->object_path); - g_free (self->menu_object_path); - g_free (self->bus_name); - g_free (self->accessible_desc); - g_free (self->header_action); - g_free (self->scroll_action); - g_free (self->secondary_action); - g_free (self->submenu_action); - - G_OBJECT_CLASS (indicator_ng_parent_class)->finalize (object); -} - -static GList * -indicator_ng_get_entries (IndicatorObject *io) -{ - IndicatorNg *self = INDICATOR_NG (io); - - return g_list_append (NULL, &self->entry); -} - -static gint -indicator_ng_get_position (IndicatorObject *io) -{ - IndicatorNg *self = INDICATOR_NG (io); - - return self->position; -} - -static void -indicator_ng_entry_scrolled (IndicatorObject *io, - __attribute__((unused)) IndicatorObjectEntry *entry, - gint delta, - IndicatorScrollDirection direction) -{ - IndicatorNg *self = INDICATOR_NG (io); - - if (self->actions && self->scroll_action) - { - if (direction == INDICATOR_OBJECT_SCROLL_DOWN || - direction == INDICATOR_OBJECT_SCROLL_LEFT) - { - delta *= -1; - } - - g_action_group_activate_action (self->actions, self->scroll_action, - g_variant_new_int32 (delta)); - } -} - -void -indicator_ng_secondary_activate (IndicatorObject *io, - __attribute__((unused)) IndicatorObjectEntry *entry, - __attribute__((unused)) guint timestamp, - __attribute__((unused)) gpointer user_data) -{ - IndicatorNg *self = INDICATOR_NG (io); - - if (self->actions && self->secondary_action) - { - g_action_group_activate_action (self->actions, self->secondary_action, NULL); - } -} - -static gboolean indicator_ng_menu_insert_idos(IndicatorNg *self, GMenuModel *pSection, guint nModelItem, guint nMenuItem, gboolean bNamespace, gchar *sNamespace) -{ - gboolean bChanged = FALSE; - gchar *sType; - gboolean bHasType = g_menu_model_get_item_attribute(pSection, nModelItem, "x-ayatana-type", "s", &sType); - - if (bHasType) - { - GList *lMenuItems = gtk_container_get_children(GTK_CONTAINER(self->entry.menu)); - GtkWidget *pMenuItemOld = GTK_WIDGET(g_list_nth_data(lMenuItems, nMenuItem)); - const gchar *sName = gtk_widget_get_name(pMenuItemOld); - - if (!g_str_equal(sName, sType)) - { - GActionGroup *pActionGroup = (GActionGroup*)g_object_get_qdata(G_OBJECT(self->entry.menu), m_pActionMuxer); - GMenuItem *pMenuModelItem = g_menu_item_new_from_model(pSection, nModelItem); - GtkMenuItem* pMenuItemNew = NULL; - gchar *sAction; - - if (bNamespace && g_menu_item_get_attribute(pMenuModelItem, G_MENU_ATTRIBUTE_ACTION, "s", &sAction)) - { - gchar *sNamespacedAction = g_strconcat(sNamespace, ".", sAction, NULL); - g_menu_item_set_attribute(pMenuModelItem, G_MENU_ATTRIBUTE_ACTION, "s", sNamespacedAction); - g_free (sNamespacedAction); - g_free (sAction); - } - - for (GList *pFactory = ayatana_menu_item_factory_get_all(); pFactory != NULL && pMenuItemNew == NULL; pFactory = pFactory->next) - { - pMenuItemNew = ayatana_menu_item_factory_create_menu_item(pFactory->data, sType, pMenuModelItem, pActionGroup); - bChanged = TRUE; - } - - if (pMenuItemNew == NULL) - { - pMenuItemNew = GTK_MENU_ITEM(gtk_menu_item_new_with_label("Failed to create IDO object")); - } - - gtk_widget_set_name(GTK_WIDGET(pMenuItemNew), sType); - gtk_widget_show(GTK_WIDGET(pMenuItemNew)); - gtk_container_remove(GTK_CONTAINER(self->entry.menu), pMenuItemOld); - gtk_menu_shell_insert(GTK_MENU_SHELL(self->entry.menu), GTK_WIDGET(pMenuItemNew), nMenuItem); - g_object_unref(pMenuModelItem); - } - - g_list_free(lMenuItems); - g_free(sType); - } - - return bChanged; -} - -static void indicator_ng_menu_size_allocate(__attribute__((unused)) GtkWidget *pWidget, __attribute__((unused)) GtkAllocation *pAllocation, gpointer pUserData) -{ - IndicatorNg *self = pUserData; - GList *pMenuItem = gtk_container_get_children(GTK_CONTAINER(self->entry.menu)); - guint nWidth = 0; - guint nHeight = 0; - GdkWindow *pWindowBin = NULL; - - while (pMenuItem) - { - if (!pWindowBin) - { - pWindowBin = gtk_widget_get_parent_window(pMenuItem->data); - } - - gint nWidthNat; - gint nHeightNat; - gtk_widget_get_preferred_width(pMenuItem->data, NULL, &nWidthNat); - gtk_widget_get_preferred_height(pMenuItem->data, NULL, &nHeightNat); - nWidth = MAX((gint)nWidth, nWidthNat); - nHeight += nHeightNat; - GtkBorder cPadding; - GtkStyleContext *pContext = gtk_widget_get_style_context(GTK_WIDGET(pMenuItem->data)); - gtk_style_context_get_padding(pContext, gtk_style_context_get_state(pContext), &cPadding); - nWidth += cPadding.left + cPadding.right; - pMenuItem = g_list_next(pMenuItem); - } - - g_list_free(pMenuItem); - GtkBorder cPadding; - GtkStyleContext *pContext = gtk_widget_get_style_context(GTK_WIDGET(self->entry.menu)); - gtk_style_context_get_padding(pContext, gtk_style_context_get_state(pContext), &cPadding); - gint nBorderWidth = gtk_container_get_border_width(GTK_CONTAINER(self->entry.menu)); - gint nIconWidth; - gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &nIconWidth, NULL); - nWidth += (2 * nBorderWidth) + cPadding.left + cPadding.right + (nIconWidth * 3) / 2; - nHeight += (2 * nBorderWidth) + cPadding.top + cPadding.bottom + (nIconWidth * 3) / 4; - - GdkRectangle cRectangle = {0}; - GdkDisplay *pDisplay = gdk_display_get_default(); - GdkMonitor *pMonitor = gdk_display_get_primary_monitor(pDisplay); - gdk_monitor_get_workarea(pMonitor, &cRectangle); - - if ((gint)nHeight <= cRectangle.height) - { - gdk_window_move_resize(pWindowBin, 0, 0, nWidth, nHeight); - } - - nHeight = MIN((gint)nHeight, cRectangle.height); - - GdkWindow *pWindow = gtk_widget_get_parent_window(GTK_WIDGET(self->entry.menu)); - gdk_window_resize(pWindow, nWidth, nHeight); - - gtk_menu_reposition(self->entry.menu); -} - -static void indicator_ng_menu_section_changed(__attribute__((unused)) GMenuModel *pMenuSection, __attribute__((unused)) gint nPosition, __attribute__((unused)) gint nRemoved, __attribute__((unused)) gint nAdded, gpointer pUserData) -{ - IndicatorNg *self = pUserData; - GMenuModel *pModel = g_menu_model_get_item_link(self->menu, 0, G_MENU_LINK_SUBMENU); - guint nMenuItem = 0; - gboolean bChanged = FALSE; - - if (pModel) - { - guint nSections = g_menu_model_get_n_items(pModel); - - for (guint nSection = 0; nSection < nSections; nSection++) - { - GMenuModel *pSection = g_menu_model_get_item_link(pModel, nSection, G_MENU_LINK_SECTION); - guint nSubsections = 0; - - if (pSection) - { - gchar *sNamespace; - gboolean bNamespace = g_menu_model_get_item_attribute(pModel, nSection, G_MENU_ATTRIBUTE_ACTION_NAMESPACE, "s", &sNamespace); - nSubsections = g_menu_model_get_n_items(pSection); - - for (guint nSubsection = 0; nSubsection < nSubsections; nSubsection++) - { - GMenuModel *pSubsection = g_menu_model_get_item_link(pSection, nSubsection, G_MENU_LINK_SECTION); - - if (pSubsection) - { - guint nItems = g_menu_model_get_n_items(pSubsection); - - // Skip the subsection separator (if there is one) - GList *lMenuItems = gtk_container_get_children(GTK_CONTAINER(self->entry.menu)); - GtkWidget *pMenuItem = GTK_WIDGET(g_list_nth_data(lMenuItems, nMenuItem)); - - if (GTK_IS_SEPARATOR_MENU_ITEM(pMenuItem)) - { - nMenuItem++; - } - - g_list_free(lMenuItems); - - for (guint nItem = 0; nItem < nItems; nItem++) - { - bChanged = indicator_ng_menu_insert_idos(self, pSubsection, nItem, nMenuItem, bNamespace, sNamespace) || bChanged; - nMenuItem++; - } - } - - g_object_unref(pSubsection); - - bChanged = indicator_ng_menu_insert_idos(self, pSection, nSubsection, nMenuItem, bNamespace, sNamespace) || bChanged; - - if (!g_str_equal(self->name, "ayatana-indicator-messages")) - { - nMenuItem++; - } - } - - if (bNamespace) - { - g_free(sNamespace); - } - - g_object_unref(pSection); - } - - if (pSection && nSubsections) - { - nMenuItem++; - } - } - - g_object_unref(pModel); - } - - if (bChanged) - { - indicator_ng_menu_size_allocate(NULL, NULL, self); - } -} - -static void indicator_ng_menu_shown(__attribute__((unused)) GtkWidget *pWidget, gpointer pUserData) -{ - IndicatorNg *self = pUserData; - guint nSectionCount = 0; - - if (!self->lMenuSections[0]) - { - self->lMenuSections[0] = g_menu_model_get_item_link(self->menu, 0, G_MENU_LINK_SUBMENU); - - if (self->lMenuSections[0]) - { - guint nSections = g_menu_model_get_n_items(self->lMenuSections[0]); - - for (guint nSection = 0; nSection < nSections; nSection++) - { - self->lMenuSections[++nSectionCount] = g_menu_model_get_item_link(self->lMenuSections[0], nSection, G_MENU_LINK_SECTION); - - if (self->lMenuSections[nSectionCount]) - { - g_signal_connect(self->lMenuSections[nSectionCount], "items-changed", G_CALLBACK(indicator_ng_menu_section_changed), self); - guint nSubsections = g_menu_model_get_n_items(self->lMenuSections[nSectionCount]); - guint nParent = nSectionCount; - - for (guint nSubsection = 0; nSubsection < nSubsections; nSubsection++) - { - self->lMenuSections[++nSectionCount] = g_menu_model_get_item_link(self->lMenuSections[nParent], nSubsection, G_MENU_LINK_SECTION); - - if (self->lMenuSections[nSectionCount]) - { - g_signal_connect(self->lMenuSections[nSectionCount], "items-changed", G_CALLBACK(indicator_ng_menu_section_changed), self); - } - } - } - } - - g_signal_connect(self->lMenuSections[0], "items-changed", G_CALLBACK(indicator_ng_menu_section_changed), self); - indicator_ng_menu_section_changed(self->lMenuSections[0], 0, 0, 1, self); - } - } - - if (self->submenu_action) - { - g_action_group_change_action_state(self->actions, self->submenu_action, g_variant_new_boolean(TRUE)); - } -} - -static void -indicator_ng_menu_hidden (__attribute__((unused)) GtkWidget *widget, - gpointer user_data) -{ - IndicatorNg *self = user_data; - - if (self->submenu_action) - g_action_group_change_action_state (self->actions, self->submenu_action, - g_variant_new_boolean (FALSE)); -} - -static void -indicator_ng_set_accessible_desc (IndicatorNg *self, - const gchar *accessible_desc) -{ - g_free (self->accessible_desc); - self->accessible_desc = g_strdup (accessible_desc); - - self->entry.accessible_desc = self->accessible_desc; - g_signal_emit_by_name (self, INDICATOR_OBJECT_SIGNAL_ACCESSIBLE_DESC_UPDATE, &self->entry); -} - -static void -indicator_ng_set_icon_from_variant (IndicatorNg *self, - GVariant *variant) -{ - GIcon *icon; - - if (variant == NULL) - { - if (self->entry.image) - { - gtk_image_clear (self->entry.image); - gtk_widget_hide (GTK_WIDGET (self->entry.image)); - } - return; - } - - gtk_widget_show (GTK_WIDGET (self->entry.image)); - - icon = g_icon_deserialize (variant); - if (icon) - { - indicator_image_helper_update_from_gicon (self->entry.image, icon); - g_object_unref (icon); - } - else - { - gchar *text = g_variant_print (variant, TRUE); - g_warning ("invalid icon variant '%s'", text); - gtk_image_set_from_icon_name (self->entry.image, "image-missing", GTK_ICON_SIZE_LARGE_TOOLBAR); - g_free (text); - } -} - -static void indicator_ng_set_label(IndicatorNg *self, const gchar *label) -{ - if (!self->entry.label) - { - return; - } - - const gchar *sLabel = label; - guint nSpacing = 3; - guint nPadding = 6; - - if (label == NULL || *label == '\0' || !self->entry.image || !gtk_widget_get_visible(GTK_WIDGET(self->entry.image))) - { - nSpacing = 0; - nPadding = 0; - } - - GtkWidget *pParent = gtk_widget_get_parent(GTK_WIDGET(self->entry.label)); - GtkCssProvider *pCssProvider = gtk_css_provider_new(); - GtkStyleContext *pStyleContext = gtk_widget_get_style_context(GTK_WIDGET(self->entry.label)); - gtk_style_context_add_provider(pStyleContext, GTK_STYLE_PROVIDER(pCssProvider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); - gchar *sCss = g_strdup_printf("label{padding-left: %ipx;}", nPadding); - gtk_css_provider_load_from_data(pCssProvider, sCss, -1, NULL); - g_free(sCss); - g_object_unref(pCssProvider); - if (GTK_IS_BOX(pParent)) - { - gtk_box_set_spacing(GTK_BOX(pParent), nSpacing); - } - gtk_label_set_label(GTK_LABEL (self->entry.label), sLabel); - - if (label) - { - gtk_widget_show(GTK_WIDGET (self->entry.label)); - } -} - -static void -indicator_ng_update_entry (IndicatorNg *self) -{ - GVariant *state; - const gchar *label = NULL; - GVariant *icon = NULL; - const gchar *accessible_desc = NULL; - gboolean visible = TRUE; - - g_return_if_fail (self->menu != NULL); - g_return_if_fail (self->actions != NULL); - - if (!self->header_action || - !g_action_group_has_action (self->actions, self->header_action)) - { - indicator_object_set_visible (INDICATOR_OBJECT (self), FALSE); - return; - } - - state = g_action_group_get_action_state (self->actions, self->header_action); - if (state && g_variant_is_of_type (state, G_VARIANT_TYPE ("(sssb)"))) - { - const gchar *iconstr = NULL; - - g_variant_get (state, "(&s&s&sb)", &label, &iconstr, &accessible_desc, &visible); - - if (iconstr) - icon = g_variant_ref_sink (g_variant_new_string (iconstr)); - } - else if (state && g_variant_is_of_type (state, G_VARIANT_TYPE ("a{sv}"))) - { - g_variant_lookup (state, "label", "&s", &label); - g_variant_lookup (state, "icon", "*", &icon); - g_variant_lookup (state, "accessible-desc", "&s", &accessible_desc); - g_variant_lookup (state, "visible", "b", &visible); - } - else - g_warning ("the action of the indicator menu item must have state with type (sssb) or a{sv}"); - - indicator_ng_set_label (self, label); - indicator_ng_set_icon_from_variant (self, icon); - indicator_ng_set_accessible_desc (self, accessible_desc); - indicator_object_set_visible (INDICATOR_OBJECT (self), visible); - - if (icon) - g_variant_unref (icon); - if (state) - g_variant_unref (state); -} - -static gboolean -indicator_ng_menu_item_is_of_type (GMenuModel *menu, - gint index, - const gchar *expected_type) -{ - gchar *type; - gboolean has_type = FALSE; - - if (g_menu_model_get_item_attribute (menu, index, "x-ayatana-type", "s", &type)) - { - has_type = g_str_equal (type, expected_type); - g_free (type); - } - - return has_type; -} - -static void -indicator_ng_menu_changed (__attribute__((unused)) GMenuModel *menu, - gint position, - gint removed, - gint added, - gpointer user_data) -{ - IndicatorNg *self = user_data; - - /* The menu may only contain one item (the indicator title menu). - * Thus, the position is always 0, and there is either exactly one - * item added or exactly one item removed. - */ - g_return_if_fail (position == 0); - g_return_if_fail (added < 2 && removed < 2 && added ^ removed); - - if (removed) - indicator_object_set_visible (INDICATOR_OBJECT (self), FALSE); - - if (added) - { - g_clear_pointer (&self->header_action, g_free); - g_clear_pointer (&self->scroll_action, g_free); - g_clear_pointer (&self->secondary_action, g_free); - - if (indicator_ng_menu_item_is_of_type (self->menu, 0, "org.ayatana.indicator.root")) - { - GMenuModel *popup; - gchar *action; - - if (g_menu_model_get_item_attribute (self->menu, 0, G_MENU_ATTRIBUTE_ACTION, "s", &action)) - { - if (g_str_has_prefix (action, "indicator.")) - self->header_action = g_strdup (action + strlen ("indicator.")); - g_free (action); - } - - if (g_menu_model_get_item_attribute (self->menu, 0, "x-ayatana-scroll-action", "s", &action)) - { - if (g_str_has_prefix (action, "indicator.")) - self->scroll_action = g_strdup (action + strlen ("indicator.")); - g_free (action); - } - - if (g_menu_model_get_item_attribute (self->menu, 0, "x-ayatana-secondary-action", "s", &action)) - { - if (g_str_has_prefix (action, "indicator.")) - self->secondary_action = g_strdup (action + strlen ("indicator.")); - g_free (action); - } - - if (g_menu_model_get_item_attribute (self->menu, 0, "submenu-action", "s", &action)) - { - if (g_str_has_prefix (action, "indicator.")) - self->submenu_action = g_strdup (action + strlen ("indicator.")); - g_free (action); - } - - for (guint nMenuSection = 0; nMenuSection < MENU_SECTIONS; nMenuSection++) - { - if (self->lMenuSections[nMenuSection]) - { - g_object_unref(self->lMenuSections[nMenuSection]); - } - } - - popup = g_menu_model_get_item_link (self->menu, 0, G_MENU_LINK_SUBMENU); - if (popup) - { - gtk_menu_shell_bind_model (GTK_MENU_SHELL (self->entry.menu), popup, NULL, TRUE); - g_object_unref (popup); - } - - indicator_ng_update_entry (self); - } - else - g_warning ("indicator menu item must be of type 'org.ayatana.indicator.root'"); - } -} - -static void -indicator_ng_service_appeared (GDBusConnection *connection, - __attribute__((unused)) const gchar *name, - const gchar *name_owner, - gpointer user_data) -{ - IndicatorNg *self = user_data; - - g_assert (!self->actions); - g_assert (!self->menu); - - /* watch is not established when menu_object_path == NULL */ - g_assert (self->menu_object_path); - - self->session_bus = g_object_ref (connection); - - self->actions = G_ACTION_GROUP (g_dbus_action_group_get (connection, name_owner, self->object_path)); - gtk_widget_insert_action_group (GTK_WIDGET (self->entry.menu), "indicator", self->actions); - g_signal_connect_swapped (self->actions, "action-added", G_CALLBACK (indicator_ng_update_entry), self); - g_signal_connect_swapped (self->actions, "action-removed", G_CALLBACK (indicator_ng_update_entry), self); - g_signal_connect_swapped (self->actions, "action-state-changed", G_CALLBACK (indicator_ng_update_entry), self); - - self->menu = G_MENU_MODEL (g_dbus_menu_model_get (connection, name_owner, self->menu_object_path)); - g_signal_connect (self->menu, "items-changed", G_CALLBACK (indicator_ng_menu_changed), self); - if (g_menu_model_get_n_items (self->menu)) - indicator_ng_menu_changed (self->menu, 0, 0, 1, self); - - indicator_ng_update_entry (self); -} - -static void -indicator_ng_service_started (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - IndicatorNg *self = user_data; - GError *error = NULL; - GVariant *result; - guint32 start_service_reply; - - result = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object), res, &error); - if (!result) - { - g_warning ("Could not activate service '%s': %s", self->name, error->message); - indicator_object_set_visible (INDICATOR_OBJECT (self), FALSE); - g_error_free (error); - return; - } - - start_service_reply = 0; - g_variant_get (result, "(u)", &start_service_reply); - - switch (start_service_reply) - { - case 1: /* DBUS_START_REPLY_SUCCESS */ - break; - - case 2: /* DBUS_START_REPLY_ALREADY_RUNNING */ - g_warning ("could not start service '%s': it is already running", self->name); - break; - - default: - g_assert_not_reached (); - } - - g_variant_unref (result); -} - -static void -indicator_ng_service_vanished (__attribute__((unused)) GDBusConnection *connection, - __attribute__((unused)) const gchar *name, - gpointer user_data) -{ - IndicatorNg *self = user_data; - - indicator_ng_free_actions_and_menu (self); - - /* Names may vanish because the service decided it doesn't need to - * show its indicator anymore, or because it crashed. Let's assume it - * crashes and restart it unless it explicitly hid its indicator. */ - - if (indicator_object_entry_is_visible (INDICATOR_OBJECT (self), &self->entry)) - { - gint64 now; - - /* take care not to start it if it repeatedly crashes */ - now = g_get_monotonic_time (); - if (now - self->last_service_restart < 1 * G_USEC_PER_SEC) - { - g_warning ("The indicator '%s' vanished too quickly after appearing. It won't " - "be respawned anymore, as it could be crashing repeatedly.", self->name); - return; - } - - self->last_service_restart = now; - - g_dbus_connection_call (self->session_bus, - "org.freedesktop.DBus", - "/", - "org.freedesktop.DBus", - "StartServiceByName", - g_variant_new ("(su)", self->bus_name, 0), - G_VARIANT_TYPE ("(u)"), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - indicator_ng_service_started, - self); - } -} - -/* Get an integer from a keyfile. Returns @default_value if the key - * doesn't exist exists or is not an integer */ -static gint -g_key_file_maybe_get_integer (GKeyFile *keyfile, - const gchar *group, - const gchar *key, - gint default_value) -{ - GError *error = NULL; - gint i; - - i = g_key_file_get_integer (keyfile, group, key, &error); - if (error) - { - g_error_free (error); - return default_value; - } - - return i; -} - -static gboolean -indicator_ng_load_from_keyfile (IndicatorNg *self, - GKeyFile *keyfile, - GError **error) -{ - g_assert (self->name == NULL); - g_assert (self->object_path == NULL); - g_assert (self->menu_object_path == NULL); - - self->name = g_key_file_get_string (keyfile, "Indicator Service", "Name", error); - if (self->name == NULL) - return FALSE; - - self->object_path = g_key_file_get_string (keyfile, "Indicator Service", "ObjectPath", error); - if (self->object_path == NULL) - return FALSE; - - self->position = g_key_file_maybe_get_integer (keyfile, "Indicator Service", "Position", -1); - - /* - * Don't throw an error when the profile doesn't exist. Non-existant - * profiles are silently ignored by not showing an indicator at all. - */ - if (g_key_file_has_group (keyfile, self->profile)) - { - /* however, if the profile exists, it must have "ObjectPath" */ - self->menu_object_path = g_key_file_get_string (keyfile, self->profile, "ObjectPath", error); - if (self->menu_object_path == NULL) - return FALSE; - - /* a position in the profile overrides the global one */ - self->position = g_key_file_maybe_get_integer (keyfile, self->profile, "Position", self->position); - } - - return TRUE; -} - -static gboolean -indicator_ng_initable_init (GInitable *initable, - __attribute__((unused)) GCancellable *cancellable, - GError **error) -{ - IndicatorNg *self = INDICATOR_NG (initable); - GKeyFile *keyfile; - gboolean success = FALSE; - - self->bus_name = g_path_get_basename (self->service_file); - - keyfile = g_key_file_new (); - if (g_key_file_load_from_file (keyfile, self->service_file, G_KEY_FILE_NONE, error) && - indicator_ng_load_from_keyfile (self, keyfile, error)) - { - self->entry.name_hint = self->name; - - /* only watch the service when it supports the proile we're interested in */ - if (self->menu_object_path) - { - self->name_watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION, - self->bus_name, - G_BUS_NAME_WATCHER_FLAGS_AUTO_START, - indicator_ng_service_appeared, - indicator_ng_service_vanished, - self, NULL); - } - - success = TRUE; - } - - g_key_file_free (keyfile); - return success; -} - -static void -indicator_ng_class_init (IndicatorNgClass *class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (class); - IndicatorObjectClass *io_class = INDICATOR_OBJECT_CLASS (class); - - object_class->get_property = indicator_ng_get_property; - object_class->set_property = indicator_ng_set_property; - object_class->dispose = indicator_ng_dispose; - object_class->finalize = indicator_ng_finalize; - - io_class->get_entries = indicator_ng_get_entries; - io_class->get_position = indicator_ng_get_position; - io_class->entry_scrolled = indicator_ng_entry_scrolled; - io_class->secondary_activate = indicator_ng_secondary_activate; - - properties[PROP_SERVICE_FILE] = g_param_spec_string ("service-file", - "Service file", - "Path of the service file", - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - - properties[PROP_PROFILE] = g_param_spec_string ("profile", - "Profile", - "Indicator profile", - "desktop", - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(object_class, N_PROPERTIES, properties); -} - -static void -indicator_ng_initable_iface_init (GInitableIface *initable) -{ - initable->init = indicator_ng_initable_init; -} - -static void -indicator_ng_init (IndicatorNg *self) -{ - m_pActionMuxer = g_quark_from_static_string ("gtk-widget-action-muxer"); - - for (guint nMenuSection = 0; nMenuSection < MENU_SECTIONS; nMenuSection++) - { - self->lMenuSections[nMenuSection] = NULL; - } - - self->entry.label = (GtkLabel*)g_object_ref_sink (gtk_label_new (NULL)); - self->entry.image = (GtkImage*)g_object_ref_sink (gtk_image_new ()); - - self->entry.menu = (GtkMenu*)g_object_ref_sink (gtk_menu_new ()); - - g_signal_connect (self->entry.menu, "show", G_CALLBACK (indicator_ng_menu_shown), self); - g_signal_connect (self->entry.menu, "hide", G_CALLBACK (indicator_ng_menu_hidden), self); - g_signal_connect (self->entry.menu, "size-allocate", G_CALLBACK (indicator_ng_menu_size_allocate), self); - - GtkCssProvider *pCssProvider = gtk_css_provider_new(); - GtkStyleContext *pStyleContext = gtk_widget_get_style_context(GTK_WIDGET(self->entry.menu)); - gtk_style_context_add_provider(pStyleContext, GTK_STYLE_PROVIDER(pCssProvider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); - gtk_css_provider_load_from_data(pCssProvider, "menu > arrow{min-height: 0; padding: 0; margin: 0;}", -1, NULL); - - GtkWidget *pWindow = gtk_widget_get_parent(GTK_WIDGET(self->entry.menu)); - pStyleContext = gtk_widget_get_style_context(pWindow); - gtk_style_context_add_provider(pStyleContext, GTK_STYLE_PROVIDER(pCssProvider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); - gtk_css_provider_load_from_data(pCssProvider, "window > decoration {box-shadow: 0 1px 2px rgba(0,0,0,0.2), 0 0 0 1px rgba(0,0,0,0.13);}", -1, NULL); - - g_object_unref(pCssProvider); - - /* work around IndicatorObject's warning that the accessible - * description is missing. We never set it on construction, but when - * the menu model has arrived on the bus. - */ - self->accessible_desc = g_strdup (""); - self->entry.accessible_desc = self->accessible_desc; - - self->position = -1; - - indicator_object_set_visible (INDICATOR_OBJECT (self), FALSE); -} - -IndicatorNg * -indicator_ng_new (const gchar *service_file, - GError **error) -{ - return g_initable_new (INDICATOR_TYPE_NG, NULL, error, - "service-file", service_file, - NULL); -} - -IndicatorNg * -indicator_ng_new_for_profile (const gchar *service_file, - const gchar *profile, - GError **error) -{ - return g_initable_new (INDICATOR_TYPE_NG, NULL, error, - "service-file", service_file, - "profile", profile, - NULL); -} - -const gchar * -indicator_ng_get_service_file (IndicatorNg *self) -{ - g_return_val_if_fail (INDICATOR_IS_NG (self), NULL); - - return self->service_file; -} - -const gchar * -indicator_ng_get_profile (IndicatorNg *self) -{ - g_return_val_if_fail (INDICATOR_IS_NG (self), NULL); - - return self->profile; -} diff --git a/libayatana-indicator/indicator-ng.h b/libayatana-indicator/indicator-ng.h deleted file mode 100644 index f074a47..0000000 --- a/libayatana-indicator/indicator-ng.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2013 Canonical Ltd. - * - * This program is free software: you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 3, as published - * by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranties of - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR - * PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program. If not, see . - * - * Authors: - * Lars Uebernickel - */ - -#ifndef __INDICATOR_NG_H__ -#define __INDICATOR_NG_H__ - -#include "indicator-object.h" - -#define INDICATOR_TYPE_NG (indicator_ng_get_type ()) -#define INDICATOR_NG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_TYPE_NG, IndicatorNg)) -#define INDICATOR_NG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INDICATOR_TYPE_NG, IndicatorNgClass)) -#define INDICATOR_IS_NG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_TYPE_NG)) -#define INDICATOR_IS_NG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INDICATOR_TYPE_NG)) -#define INDICATOR_NG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), INDICATOR_TYPE_NG, IndicatorNgClass)) - -typedef struct _IndicatorNg IndicatorNg; -typedef IndicatorObjectClass IndicatorNgClass; - -GType indicator_ng_get_type (void); - -IndicatorNg * indicator_ng_new (const gchar *service_file, - GError **error); - -IndicatorNg * indicator_ng_new_for_profile (const gchar *service_file, - const gchar *profile, - GError **error); - -const gchar * indicator_ng_get_service_file (IndicatorNg *indicator); - -const gchar * indicator_ng_get_profile (IndicatorNg *indicator); - -#endif diff --git a/libayatana-indicator/indicator-object-enum-types.c.template b/libayatana-indicator/indicator-object-enum-types.c.template deleted file mode 100644 index e5b3352..0000000 --- a/libayatana-indicator/indicator-object-enum-types.c.template +++ /dev/null @@ -1,30 +0,0 @@ -/*** BEGIN file-header ***/ -#include "indicator-object-enum-types.h" -/*** END file-header ***/ - -/*** BEGIN file-production ***/ -/* enumerations from "@basename@" */ -#include "@basename@" -/*** END file-production ***/ - -/*** BEGIN value-header ***/ -GType -@enum_name@_get_type (void) { - static GType enum_type_id = 0; - if (G_UNLIKELY (!enum_type_id)) - { - static const G@Type@Value values[] = { -/*** END value-header ***/ - -/*** BEGIN value-production ***/ - { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, -/*** END value-production ***/ - -/*** BEGIN value-tail ***/ - { 0, NULL, NULL } - }; - enum_type_id = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); - } - return enum_type_id; -} -/*** END value-tail ***/ diff --git a/libayatana-indicator/indicator-object-enum-types.h.template b/libayatana-indicator/indicator-object-enum-types.h.template deleted file mode 100644 index 2ac8ef8..0000000 --- a/libayatana-indicator/indicator-object-enum-types.h.template +++ /dev/null @@ -1,27 +0,0 @@ -/*** BEGIN file-header ***/ - -#ifndef __INDICATOR_OBJECT_ENUM_TYPES_H__ -#define __INDICATOR_OBJECT_ENUM_TYPES_H__ - -#include - -G_BEGIN_DECLS - -/*** END file-header ***/ - -/*** BEGIN file-production ***/ -/* enumerations from "@basename@" */ -/*** END file-production ***/ - -/*** BEGIN file-tail ***/ -G_END_DECLS - -#endif /* !__INDICATOR_OBJECT_ENUM_TYPES_H__ */ -/*** END file-tail ***/ - -/*** BEGIN value-header ***/ - -GType @enum_name@_get_type (void) G_GNUC_CONST; -#define INDICATOR_OBJECT_TYPE_@ENUMSHORT@ (@enum_name@_get_type()) - -/*** END value-header ***/ diff --git a/libayatana-indicator/indicator-object-marshal.list b/libayatana-indicator/indicator-object-marshal.list deleted file mode 100644 index 4896ac4..0000000 --- a/libayatana-indicator/indicator-object-marshal.list +++ /dev/null @@ -1,4 +0,0 @@ -VOID: POINTER, UINT, UINT -VOID: POINTER, UINT, ENUM -VOID: POINTER, UINT -VOID: POINTER, BOOLEAN diff --git a/libayatana-indicator/indicator-object.c b/libayatana-indicator/indicator-object.c deleted file mode 100644 index 50b3078..0000000 --- a/libayatana-indicator/indicator-object.c +++ /dev/null @@ -1,967 +0,0 @@ -/* -An object to represent loadable indicator modules to make loading -them easy and objectified. - -Copyright 2009 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 -. -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "indicator.h" -#include "indicator-object.h" -#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. - @ENTRY_VISIBLE: The entry is visible - @ENTRY_INVISIBLE: The entry is invisible -*/ -typedef enum { - ENTRY_INIT, - ENTRY_VISIBLE, - ENTRY_INVISIBLE -} -EntryVisibility; - -typedef struct _IndicatorObjectEntryPrivate { - EntryVisibility visibility; -} -IndicatorObjectEntryPrivate; - -/** - IndicatorObjectPrivate: - @module: The loaded module representing the object. Note to - subclasses: This will not be set when you're initalized. - @entry: A default entry for objects that don't need all the - fancy stuff. This works with #get_entries_default. - @gotten_entries: A check to see if the @entry has been - populated intelligently yet. - - Structure to define the memory for the private area - of the object instance. -*/ -struct _IndicatorObjectPrivate { - GModule * module; - - /* For get_entries_default */ - IndicatorObjectEntry entry; - gboolean gotten_entries; - - /* Whether or not entries are visible by default */ - gboolean default_visibility; - GHashTable * entry_privates; - - GStrv environments; -}; - -/* Signals Stuff */ -enum { - ENTRY_ADDED, - ENTRY_REMOVED, - ENTRY_MOVED, - ENTRY_SCROLLED, - MENU_SHOW, - SHOW_NOW_CHANGED, - ACCESSIBLE_DESC_UPDATE, - SECONDARY_ACTIVATE, - LAST_SIGNAL -}; - -/* Properties */ -/* Enum for the properties so that they can be quickly - found and looked up. */ -enum { - PROP_0, - PROP_GSETTINGS_SCHEMA_ID, - PROP_DEFAULT_VISIBILITY, -}; - - -static guint signals[LAST_SIGNAL] = { 0 }; - -/* GObject stuff */ -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*, guint prop_id, const GValue*, GParamSpec* ); -static void get_property (GObject*, guint prop_id, GValue*, GParamSpec* ); - -/* entries' visibility */ -static GList * get_entries_default (IndicatorObject*); -static GList * get_all_entries (IndicatorObject*); -static void indicator_object_entry_being_removed (IndicatorObject*, IndicatorObjectEntry*); -static void indicator_object_entry_was_added (IndicatorObject*, IndicatorObjectEntry*); -static gint indicator_object_real_get_position (IndicatorObject*); -static IndicatorObjectEntryPrivate * entry_get_private (IndicatorObject*, IndicatorObjectEntry*); - -G_DEFINE_TYPE_WITH_PRIVATE (IndicatorObject, indicator_object, G_TYPE_OBJECT); - -/* Setup the class and put the functions into the - class structure */ -static void -indicator_object_class_init (IndicatorObjectClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - 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; - klass->get_image = NULL; - klass->get_accessible_desc = NULL; - klass->get_entries = get_entries_default; - klass->get_location = NULL; - klass->entry_being_removed = NULL; - klass->entry_was_added = NULL; - klass->get_position = indicator_object_real_get_position; - - klass->entry_activate = NULL; - klass->entry_activate_window = NULL; - klass->entry_close = NULL; - - /** - IndicatorObject::entry-added: - @arg0: The #IndicatorObject object - @arg1: A pointer to the #IndicatorObjectEntry that - is being added. - - Signaled when a new entry is added and should - be shown by the person using this object. - */ - signals[ENTRY_ADDED] = g_signal_new (INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED, - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (IndicatorObjectClass, entry_added), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER, G_TYPE_NONE); - - /** - IndicatorObject::entry-removed: - @arg0: The #IndicatorObject object - @arg1: A pointer to the #IndicatorObjectEntry that - is being removed. - - Signaled when an entry is removed and should - be removed by the person using this object. - */ - signals[ENTRY_REMOVED] = g_signal_new (INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED, - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (IndicatorObjectClass, entry_removed), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER, G_TYPE_NONE); - /** - IndicatorObject::entry-moved: - @arg0: The #IndicatorObject object - @arg1: A pointer to the #IndicatorObjectEntry that - is being moved. - @arg2: The old location of the entry - @arg3: The new location of the entry - - When the order of the entries change, then this signal - is sent to tell the new location. - */ - signals[ENTRY_MOVED] = g_signal_new (INDICATOR_OBJECT_SIGNAL_ENTRY_MOVED, - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (IndicatorObjectClass, entry_moved), - NULL, NULL, - _indicator_object_marshal_VOID__POINTER_UINT_UINT, - G_TYPE_NONE, 3, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_NONE); - /** - IndicatorObject::entry-scrolled: - @arg0: The #IndicatorObject object - @arg1: A pointer to the #IndicatorObjectEntry that - receives the scroll event. - @arg2: The delta of the scroll event - @arg3: The orientation of the scroll event. - - When the indicator receives a mouse scroll wheel event - from the user, this signal is emitted. - */ - signals[ENTRY_SCROLLED] = g_signal_new (INDICATOR_OBJECT_SIGNAL_ENTRY_SCROLLED, - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (IndicatorObjectClass, entry_scrolled), - NULL, NULL, - _indicator_object_marshal_VOID__POINTER_UINT_ENUM, - G_TYPE_NONE, 3, G_TYPE_POINTER, G_TYPE_UINT, - INDICATOR_OBJECT_TYPE_SCROLL_DIRECTION); - /** - IndicatorObject::secondary-activate: - @arg0: The #IndicatorObject object - @arg1: A pointer to the #IndicatorObjectEntry that - receives the secondary activate event. - @arg2: The timestamp of the event - - When the indicator receives a secondary activation event - from the user, this signal is emitted. - */ - signals[SECONDARY_ACTIVATE] = g_signal_new (INDICATOR_OBJECT_SIGNAL_SECONDARY_ACTIVATE, - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (IndicatorObjectClass, secondary_activate), - NULL, NULL, - _indicator_object_marshal_VOID__POINTER_UINT, - G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_UINT); - - /** - IndicatorObject::menu-show: - @arg0: The #IndicatorObject object - @arg1: A pointer to the #IndicatorObjectEntry that - is being shown. - @arg2: The timestamp of the event - - Used when the indicator wants to signal up the stack - that the menu should be shown. - */ - signals[MENU_SHOW] = g_signal_new (INDICATOR_OBJECT_SIGNAL_MENU_SHOW, - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (IndicatorObjectClass, menu_show), - NULL, NULL, - _indicator_object_marshal_VOID__POINTER_UINT, - G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_UINT); - - /** - IndicatorObject::show-now-changed: - @arg0: The #IndicatorObject object - @arg1: A pointer to the #IndicatorObjectEntry that - is changing it's state - @arg2: The state of whether the entry should be shown - - Whether the entry should be shown or not has changed so we need - to tell whoever is displaying it. - */ - signals[SHOW_NOW_CHANGED] = g_signal_new (INDICATOR_OBJECT_SIGNAL_SHOW_NOW_CHANGED, - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (IndicatorObjectClass, show_now_changed), - NULL, NULL, - _indicator_object_marshal_VOID__POINTER_BOOLEAN, - G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_BOOLEAN); - - /** - IndicatorObject::accessible-desc-update:: - @arg0: The #IndicatorObject object - @arg1: A pointer to the #IndicatorObjectEntry whos - accessible description has been updated. - - Signaled when an indicator's accessible description - has been updated, so that the displayer of the - indicator can fetch the new description. - */ - signals[ACCESSIBLE_DESC_UPDATE] = g_signal_new (INDICATOR_OBJECT_SIGNAL_ACCESSIBLE_DESC_UPDATE, - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (IndicatorObjectClass, accessible_desc_update), - NULL, NULL, - g_cclosure_marshal_VOID__POINTER, - G_TYPE_NONE, 1, G_TYPE_POINTER, G_TYPE_NONE); - - /* Properties */ - - GParamSpec * 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) -{ - IndicatorObjectPrivate * priv = indicator_object_get_instance_private(self); - - priv->module = NULL; - - priv->entry.parent_object = self; - priv->entry.menu = NULL; - priv->entry.label = NULL; - priv->entry.image = NULL; - priv->entry.accessible_desc = NULL; - priv->entry.name_hint = NULL; - priv->entry.parent_window = 0; - - 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); - - priv->environments = NULL; - - self->priv = priv; - - GObject * o = G_OBJECT(self); - /* Invoke the entry-being-removed virtual function first */ - g_signal_connect (o, INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED, - 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(indicator_object_entry_was_added), NULL); -} - -/* Unref the objects that we're holding on to. */ -static void -indicator_object_dispose (GObject *object) -{ - /* Ensure that hidden entries are re-added so their widgetry will - be cleaned up properly by the client */ - indicator_object_set_visible (INDICATOR_OBJECT (object), TRUE); - - G_OBJECT_CLASS (indicator_object_parent_class)->dispose (object); -} - -/* A small helper function that closes a module but - in the function prototype of a GSourceFunc. */ -static gboolean -module_unref (gpointer data) -{ - if (!g_module_close((GModule *)data)) { - /* All we can do is warn. */ - g_warning("Unable to close module!"); - } - return FALSE; -} - -/* Free memory */ -static void -indicator_object_finalize (GObject *object) -{ - - IndicatorObject * obj = INDICATOR_OBJECT (object); - IndicatorObjectPrivate * priv = indicator_object_get_instance_private(obj); - - 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; - } - - 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 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. - Slightly non-deterministic, but should work. */ - g_idle_add(module_unref, priv->module); - priv->module = NULL; - } - - G_OBJECT_CLASS (indicator_object_parent_class)->finalize (object); - return; -} - -/** - indicator_object_new_from_file: - @file: Filename containing a loadable module - - This function builds an #IndicatorObject using the symbols - that are found in @file. The module is loaded and the - references are all kept by the object. To unload the - module the object must be destroyed. - - Return value: A valid #IndicatorObject or #NULL if error. -*/ -IndicatorObject * -indicator_object_new_from_file (const gchar * file) -{ - GObject * object = NULL; - GModule * module = NULL; - - /* Check to make sure the name exists and that the - file itself exists */ - if (file == NULL) { - g_warning("Invalid filename."); - return NULL; - } - - if (!g_file_test(file, G_FILE_TEST_EXISTS)) { - g_warning("File '%s' does not exist.", file); - return NULL; - } - - /* Grab the g_module reference, pull it in but let's - keep the symbols local to avoid conflicts. */ - module = g_module_open(file, - G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); - if (module == NULL) { - g_warning("Unable to load module: %s", file); - return NULL; - } - - /* Look for the version function, error if not found. */ - get_version_t lget_version = NULL; - if (!g_module_symbol(module, INDICATOR_GET_VERSION_S, (gpointer *)(&lget_version))) { - g_warning("Unable to get the symbol for getting the version."); - return NULL; - } - - /* Check the version with the macro and make sure we're - all talking the same language. */ - if (!INDICATOR_VERSION_CHECK(lget_version())) { - g_warning("Indicator using API version '%s' we're expecting '%s'", lget_version(), INDICATOR_VERSION); - return NULL; - } - - /* The function for grabbing a label from the module - execute it, and make sure everything is a-okay */ - get_type_t lget_type = NULL; - if (!g_module_symbol(module, INDICATOR_GET_TYPE_S, (gpointer *)(&lget_type))) { - g_warning("Unable to get '" INDICATOR_GET_TYPE_S "' symbol from module: %s", file); - goto unrefandout; - } - if (lget_type == NULL) { - g_warning("Symbol '" INDICATOR_GET_TYPE_S "' is (null) in module: %s", file); - goto unrefandout; - } - - /* A this point we allocate the object, any code beyond - here needs to deallocate it if we're returning in an - error'd state. */ - object = g_object_new(lget_type(), NULL); - if (object == NULL) { - g_warning("Unable to build an object if type '%d' in module: %s", (gint)lget_type(), file); - goto unrefandout; - } - if (!INDICATOR_IS_OBJECT(object)) { - g_warning("Type '%d' in file %s is not a subclass of IndicatorObject.", (gint)lget_type(), file); - goto unrefandout; - } - - /* Now we can track the module */ - IndicatorObject * obj = INDICATOR_OBJECT(object); - IndicatorObjectPrivate * priv = indicator_object_get_instance_private(obj); - priv->module = module; - - return obj; - - /* Error, let's drop the object and return NULL. Sad when - this happens. */ -unrefandout: - g_clear_object (&object); - g_clear_object (&module); - g_warning("Error building IndicatorObject from file: %s", file); - return NULL; -} - -/* The default get entries function uses the other single - entries in the class to create an entry structure and - put it into a list. This makes it simple for simple objects - to create the list. Small changes from the way they - previously were. */ -static GList * -get_entries_default (IndicatorObject * io) -{ - IndicatorObjectPrivate * priv = indicator_object_get_instance_private(io); - - if (!priv->gotten_entries) { - IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io); - - priv->entry.parent_object = io; - - if (class->get_label) { - priv->entry.label = class->get_label(io); - } - - if (class->get_image) { - priv->entry.image = class->get_image(io); - } - - if (priv->entry.image == NULL && priv->entry.label == NULL) { - g_warning("IndicatorObject class does not create an image or a label. We need one of those."); - return NULL; - } - - if (class->get_menu) { - priv->entry.menu = class->get_menu(io); - } - - if (priv->entry.menu == NULL) { - g_warning("IndicatorObject class does not create a menu. We need one of those."); - return NULL; - } - - if (class->get_accessible_desc) { - priv->entry.accessible_desc = class->get_accessible_desc(io); - } - - if (priv->entry.accessible_desc == NULL) { - g_warning("IndicatorObject class does not have an accessible description."); - } - - if (class->get_name_hint) { - priv->entry.name_hint = class->get_name_hint(io); - } - - if (class->get_parent_window) { - priv->entry.parent_window = class->get_parent_window(io); - } - - priv->gotten_entries = TRUE; - } - - return g_list_append(NULL, &(priv->entry)); -} - -/* returns a list of all IndicatorObjectEntries, visible or not */ -static GList* -get_all_entries (IndicatorObject * io) -{ - GList * all_entries = NULL, *l; - - 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); - - for (l = all_entries; l; l = l->next) - { - IndicatorObjectEntry *entry = l->data; - - if (entry) - entry->parent_object = io; - } - } - - return all_entries; -} - -/* get the private structure that corresponds to a caller-specified entry */ -static 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); - - 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 (h, entry, priv); - } - - return priv; -} - -/** - 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. - - Return value: (element-type IndicatorObjectEntry) (transfer container): - A list if #IndicatorObjectEntry structures or NULL on error. -*/ -GList * -indicator_object_get_entries (IndicatorObject * io) -{ - GList * l; - GList * ret = NULL; - GList * all_entries = get_all_entries (io); - IndicatorObjectPrivate * priv = indicator_object_get_instance_private(io); - const gboolean default_visibility = priv->default_visibility; - - for (l=all_entries; l!=NULL; l=l->next) - { - gboolean show_me; - IndicatorObjectEntry * entry = l->data; - - switch (entry_get_private(io,entry)->visibility) { - 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_prepend (ret, entry); - } - - g_list_free (all_entries); - return g_list_reverse (ret); -} - -/** - indicator_object_get_location: - @io: #IndicatorObject to query - @entry: The #IndicatorObjectEntry to look for. - - This function looks on the class for the object and calls - it's #IndicatorObjectClass::get_location function. If the - function doesn't exist it returns zero. - - Return value: Location of the @entry in the display or - zero if no location is specified. -*/ -guint -indicator_object_get_location (IndicatorObject * io, IndicatorObjectEntry * entry) -{ - g_return_val_if_fail(INDICATOR_IS_OBJECT(io), 0); - IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io); - - if (class->get_location) { - return class->get_location(io, entry); - } - - return 0; -} - -/** - indicator_object_get_show_now: - @io: #IndicatorObject to query - @entry: The #IndicatorObjectEntry to look for. - - This function returns whether the entry should be shown with - priority on the panel. If the object does not support checking - it assumes that its entries should never have priority. - - Return value: Whether the entry should be shown with priority. -*/ -guint -indicator_object_get_show_now (IndicatorObject * io, IndicatorObjectEntry * entry) -{ - g_return_val_if_fail(INDICATOR_IS_OBJECT(io), 0); - IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io); - - if (class->get_show_now) { - return class->get_show_now(io, entry); - } - - 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) -{ - 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; -} - -/** - indicator_object_entry_activate: - @io: #IndicatorObject to query - @entry: The #IndicatorObjectEntry whose entry was shown - @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. Note, this does not actually show the menu that's - left up to the reader. -*/ -void -indicator_object_entry_activate (IndicatorObject * io, IndicatorObjectEntry * entry, guint timestamp) -{ - g_return_if_fail(INDICATOR_IS_OBJECT(io)); - IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io); - - if (class->entry_activate != NULL) { - return class->entry_activate(io, entry, timestamp); - } - - return; -} - -/** - indicator_object_entry_close: - @io: #IndicatorObject to query - @entry: The #IndicatorObjectEntry whose menu was closed - @timestamp: The X11 timestamp of the event - - Used to tell the indicator that a menu has been closed for the - entry that is specified. -*/ -void -indicator_object_entry_close (IndicatorObject * io, IndicatorObjectEntry * entry, guint timestamp) -{ - g_return_if_fail(INDICATOR_IS_OBJECT(io)); - IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io); - - if (class->entry_close != NULL) { - return class->entry_close(io, entry, timestamp); - } - - 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 (entry) - entry->parent_object = NULL; - - 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 (entry) - entry->parent_object = io; - - if (class->entry_was_added != NULL) - { - class->entry_was_added (io, entry); - } -} - -static gint -indicator_object_real_get_position (IndicatorObject *io) -{ - g_return_val_if_fail (INDICATOR_IS_OBJECT (io), -1); - - return -1; -} - -/** - indicator_object_set_environment: - @io: #IndicatorObject to set on - @env: List of enviroment names to use - - Sets the names of the environment that the indicator is being - loaded into. This allows for indicators to behave differently - in different hosts if need be. -*/ -void -indicator_object_set_environment (IndicatorObject * io, GStrv env) -{ - /* FIXME: should this be a property? */ - g_return_if_fail(INDICATOR_IS_OBJECT(io)); - - if (io->priv->environments != NULL) { - g_strfreev(io->priv->environments); - io->priv->environments = NULL; - } - - io->priv->environments = g_strdupv(env); - - return; -} - -/** - indicator_object_get_environment: - @io: #IndicatorObject to get the environment from - - Gets the list of environment strings that this object is - placed into. - - Return value: (transfer none): Gets the list of strings that - represent the environment or NULL if none were given. -*/ -GStrv -indicator_object_get_environment (IndicatorObject * io) -{ - g_return_val_if_fail(INDICATOR_IS_OBJECT(io), NULL); - return io->priv->environments; -} - -/** - indicator_object_check_environment: - @io: #IndicatorObject to check on - @env: Environment that we're looking for - - Convience function to check to see if the specified environment - @env is in our list of environments. - - Return Value: Whether we're in environment @env -*/ -gboolean -indicator_object_check_environment (IndicatorObject * io, const gchar * env) -{ - g_return_val_if_fail(INDICATOR_IS_OBJECT(io), FALSE); - g_return_val_if_fail(env != NULL, FALSE); - - if (io->priv->environments == NULL) { - return FALSE; - } - - int i; - for (i = 0; io->priv->environments[i] != NULL; i++) { - if (g_strcmp0(env, io->priv->environments[i]) == 0) { - return TRUE; - } - } - - 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) -{ - g_return_if_fail(INDICATOR_IS_OBJECT(io)); - - GList * l; - GList * entries = get_all_entries (io); - const guint signal_id = signals[visible ? ENTRY_ADDED : ENTRY_REMOVED]; - EntryVisibility visibility = visible ? ENTRY_VISIBLE : ENTRY_INVISIBLE; - const GQuark detail = (GQuark)0; - - for (l=entries; l!=NULL; l=l->next) { - IndicatorObjectEntry *entry = l->data; - if (entry_get_private (io, entry)->visibility != visibility) - g_signal_emit(io, signal_id, detail, entry); - } - g_list_free (entries); -} - -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_instance_private(self); - g_return_if_fail(priv != NULL); - - switch (prop_id) { - /* *********************** */ - 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; - /* *********************** */ - 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_instance_private(self); - g_return_if_fail (priv != NULL); - - - switch (prop_id) { - - /* *********************** */ - 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; - } -} - -gboolean -indicator_object_entry_is_visible (IndicatorObject * io, IndicatorObjectEntry * entry) -{ - g_return_val_if_fail (INDICATOR_IS_OBJECT (io), FALSE); - - return entry_get_private (io, entry)->visibility == ENTRY_VISIBLE; -} - -gint -indicator_object_get_position (IndicatorObject *io) -{ - g_return_val_if_fail (INDICATOR_IS_OBJECT (io), FALSE); - - return INDICATOR_OBJECT_GET_CLASS (io)->get_position (io); -} diff --git a/libayatana-indicator/indicator-object.h b/libayatana-indicator/indicator-object.h deleted file mode 100644 index e542c0d..0000000 --- a/libayatana-indicator/indicator-object.h +++ /dev/null @@ -1,216 +0,0 @@ -/* -An object to represent loadable indicator modules to make loading -them easy and objectified. - -Copyright 2009 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 __INDICATOR_OBJECT_H__ -#define __INDICATOR_OBJECT_H__ - -#include - -G_BEGIN_DECLS - -typedef enum -{ - INDICATOR_OBJECT_SCROLL_UP, - INDICATOR_OBJECT_SCROLL_DOWN, - INDICATOR_OBJECT_SCROLL_LEFT, - INDICATOR_OBJECT_SCROLL_RIGHT -} IndicatorScrollDirection; - -#define INDICATOR_OBJECT_TYPE (indicator_object_get_type ()) -#define INDICATOR_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_OBJECT_TYPE, IndicatorObject)) -#define INDICATOR_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INDICATOR_OBJECT_TYPE, IndicatorObjectClass)) -#define INDICATOR_IS_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_OBJECT_TYPE)) -#define INDICATOR_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INDICATOR_OBJECT_TYPE)) -#define INDICATOR_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), INDICATOR_OBJECT_TYPE, IndicatorObjectClass)) - -#define INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED "entry-added" -#define INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED_ID (g_signal_lookup(INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED, INDICATOR_OBJECT_TYPE)) -#define INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED "entry-removed" -#define INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED_ID (g_signal_lookup(INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED, INDICATOR_OBJECT_TYPE)) -#define INDICATOR_OBJECT_SIGNAL_ENTRY_MOVED "entry-moved" -#define INDICATOR_OBJECT_SIGNAL_ENTRY_MOVED_ID (g_signal_lookup(INDICATOR_OBJECT_SIGNAL_ENTRY_MOVED, INDICATOR_OBJECT_TYPE)) -#define INDICATOR_OBJECT_SIGNAL_ENTRY_SCROLLED "entry-scrolled" -#define INDICATOR_OBJECT_SIGNAL_ENTRY_SCROLLED_ID (g_signal_lookup(INDICATOR_OBJECT_SIGNAL_ENTRY_SCROLLED, INDICATOR_OBJECT_TYPE)) -#define INDICATOR_OBJECT_SIGNAL_MENU_SHOW "menu-show" -#define INDICATOR_OBJECT_SIGNAL_MENU_SHOW_ID (g_signal_lookup(INDICATOR_OBJECT_SIGNAL_MENU_SHOW, INDICATOR_OBJECT_TYPE)) -#define INDICATOR_OBJECT_SIGNAL_SHOW_NOW_CHANGED "show-now-changed" -#define INDICATOR_OBJECT_SIGNAL_SHOW_NOW_CHANGED_ID (g_signal_lookup(INDICATOR_OBJECT_SIGNAL_SHOW_NOW_CHANGED, INDICATOR_OBJECT_TYPE)) -#define INDICATOR_OBJECT_SIGNAL_ACCESSIBLE_DESC_UPDATE "accessible-desc-update" -#define INDICATOR_OBJECT_SIGNAL_ACCESSIBLE_DESC_UPDATE_ID (g_signal_lookup(INDICATOR_OBJECT_SIGNAL_ACCESSIBLE_DESC_UPDATE, INDICATOR_OBJECT_TYPE)) -#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 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; -typedef struct _IndicatorObjectPrivate IndicatorObjectPrivate; -typedef struct _IndicatorObjectEntry IndicatorObjectEntry; - -/** - IndicatorObjectClass: - @parent_class: #GObjectClass - @get_label: Gets the label for this object. Should be set - to #NULL if @get_entries is set. Should NOT ref the - object. - @get_image: Gets the image for this object. Should be set - to #NULL if @get_entries is set. Should NOT ref the - object. - @get_menu: Gets the image for this object. Should be set - to #NULL if @get_entries is set. Should NOT ref the - object. - @get_accessible_desc: Gets the accessible descriptionfor this - object. - @get_name_hint: Gets the hint of the type of indicator that this - is for the caller. - @get_entries: Gets all of the entires for this object returning - a #GList of #IndicatorObjectEntries. The list should be - under the ownership of the caller but the entires will - not be. - @get_location: Returns the location that a particular entry - should be placed in. This is really only relevant for - indicators that have more than one entry. - @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. - @entry_added: Slot for #IndicatorObject::entry-added - @entry_removed: Slot for #IndicatorObject::entry-removed - @entry_moved: Slot for #IndicatorObject::entry-moved - @menu_show: Slot for #IndicatorObject::menu-show - @entry_scrolled: Slot for #IndicatorObject::entry-scrolled - @show_now_changed: Slot for #IndicatorObject::show-now-changed - @accessible_desc_update: Slot for #IndicatorObject::accessible-desc-update - @secondary_activate: Slot for #IndicatorObject::secondary-activate - @get_position: returns the desired position on the panel (0 is right-most), or -1 -*/ -struct _IndicatorObjectClass { - GObjectClass parent_class; - - /* Virtual Functions */ - GtkLabel * (*get_label) (IndicatorObject * io); - GtkImage * (*get_image) (IndicatorObject * io); - GtkMenu * (*get_menu) (IndicatorObject * io); - const gchar * (*get_accessible_desc) (IndicatorObject * io); - const gchar * (*get_name_hint) (IndicatorObject * io); - - GList * (*get_entries) (IndicatorObject * io); - 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_activate_window) (IndicatorObject * io, IndicatorObjectEntry * entry, guint windowid, guint timestamp); - void (*entry_close) (IndicatorObject * io, IndicatorObjectEntry * entry, guint timestamp); - - /* Signals */ - void (*entry_added) (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer user_data); - void (*entry_removed) (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer user_data); - void (*entry_moved) (IndicatorObject * io, IndicatorObjectEntry * entry, guint old_pos, guint new_pos, gpointer user_data); - void (*entry_scrolled) (IndicatorObject * io, IndicatorObjectEntry * entry, gint delta, IndicatorScrollDirection direction); - void (*menu_show) (IndicatorObject * io, IndicatorObjectEntry * entry, guint timestamp, gpointer user_data); - void (*show_now_changed) (IndicatorObject * io, IndicatorObjectEntry * entry, gboolean show_now_state, gpointer user_data); - void (*accessible_desc_update) (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer user_data); - void (*secondary_activate) (IndicatorObject * io, IndicatorObjectEntry * entry, guint timestamp, gpointer user_data); - - gint (*get_position) (IndicatorObject *io); - guint (*get_parent_window) (IndicatorObject *io); - - /* Reserved */ - void (*reserved1) (void); - void (*reserved2) (void); - void (*reserved3) (void); -}; - -/** - IndicatorObject: - @parent: #GObject - @priv: A cached reference to the private data for the - instance. -*/ -struct _IndicatorObject { - GObject parent; - IndicatorObjectPrivate * priv; -}; - -/** - 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 - @accessible_desc: The accessible description - of the indicator - @name_hint: A name to describe the indicator being placed to allow - the caller to be more aware of the individual entries. - @parent_window: the id of the parent window of the indicator entry (if any). - - @reserved1: Reserved for future use - @reserved2: Reserved for future use - @reserved3: Reserved for future use -*/ -struct _IndicatorObjectEntry { - IndicatorObject * parent_object; - GtkLabel * label; - GtkImage * image; - GtkMenu * menu; - const gchar * accessible_desc; - const gchar * name_hint; - guint parent_window; - - void (*reserved1) (void); - void (*reserved2) (void); - void (*reserved3) (void); -}; - -GType indicator_object_get_type (void); -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); -gboolean indicator_object_entry_is_visible (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); -gint indicator_object_get_position (IndicatorObject *io); - -void indicator_object_set_environment (IndicatorObject * io, GStrv env); -GStrv indicator_object_get_environment (IndicatorObject * io); -gboolean indicator_object_check_environment (IndicatorObject * io, const gchar * env); - -G_END_DECLS - -#endif diff --git a/libayatana-indicator/indicator-service-manager.c b/libayatana-indicator/indicator-service-manager.c deleted file mode 100644 index 33bcba9..0000000 --- a/libayatana-indicator/indicator-service-manager.c +++ /dev/null @@ -1,704 +0,0 @@ -/* -An object used to manage services. Either start them or -just connect to them. - -Copyright 2009 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 -. -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include - -#include "indicator-service-manager.h" -#include "gen-indicator-service.xml.h" -#include "dbus-shared.h" - -/* Private Stuff */ -/** - IndicatorServiceManagerPrivate: - @name: The well known dbus name the service should be on. - @service_proxy: The proxy to the service itself. - @connected: Whether we're connected to the service or not. - @this_service_version: The version of the service that we're looking for. - @restart_count: The number of times we've restarted this service. -*/ -typedef struct _IndicatorServiceManagerPrivate IndicatorServiceManagerPrivate; -struct _IndicatorServiceManagerPrivate { - gchar * name; - GDBusProxy * service_proxy; - GCancellable * service_proxy_cancel; - guint name_watcher; - gboolean connected; - guint this_service_version; - guint restart_count; - gint restart_source; - GCancellable * watch_cancel; -}; - -/* Signals Stuff */ -enum { - CONNECTION_CHANGE, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -/* If this env variable is set, we don't restart */ -#define TIMEOUT_ENV_NAME "INDICATOR_SERVICE_RESTART_DISABLE" -#define TIMEOUT_MULTIPLIER 100 /* In ms */ -/* What to reset the restart_count to if we know that we're - in a recoverable error condition, but waiting a little bit - will probably make things better. 5 ~= 3 sec. */ -#define TIMEOUT_A_LITTLE_WHILE 5 - -/* Properties */ -/* Enum for the properties so that they can be quickly - found and looked up. */ -enum { - PROP_0, - PROP_NAME, - PROP_VERSION -}; - -/* The strings so that they can be slowly looked up. */ -#define PROP_NAME_S "name" -#define PROP_VERSION_S "version" - -/* GDBus Stuff */ -static GDBusNodeInfo * node_info = NULL; -static GDBusInterfaceInfo * interface_info = NULL; - -static void indicator_service_manager_class_init (IndicatorServiceManagerClass *klass); -static void indicator_service_manager_init (IndicatorServiceManager *self); -static void indicator_service_manager_dispose (GObject *object); -static void indicator_service_manager_finalize (GObject *object); - -/* Prototypes */ -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 start_service (IndicatorServiceManager * service); -static void start_service_again (IndicatorServiceManager * manager); -static void unwatch (GDBusProxy * proxy); -static void service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data); -static void service_proxy_name_changed (GDBusConnection * connection, const gchar * sender_name, const gchar * object_path, const gchar * interface_name, const gchar * signal_name, GVariant * parameters, gpointer user_data); - -G_DEFINE_TYPE_WITH_PRIVATE (IndicatorServiceManager, indicator_service_manager, G_TYPE_OBJECT); - -/* Build all of our signals and proxies and tie everything - all together. Lovely. */ -static void -indicator_service_manager_class_init (IndicatorServiceManagerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = indicator_service_manager_dispose; - object_class->finalize = indicator_service_manager_finalize; - - /* Property funcs */ - object_class->set_property = set_property; - object_class->get_property = get_property; - - /** - IndicatorServiceManager::connecton-change: - @arg0: The #IndicatorServiceManager object - @arg1: The state of the connection, TRUE is connected. - - Signaled when the service is connected or disconnected - depending on it's previous state. - */ - signals[CONNECTION_CHANGE] = g_signal_new (INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE, - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (IndicatorServiceManagerClass, connection_change), - NULL, NULL, - g_cclosure_marshal_VOID__BOOLEAN, - G_TYPE_NONE, 1, G_TYPE_BOOLEAN, G_TYPE_NONE); - - /* Properties */ - g_object_class_install_property(object_class, PROP_NAME, - g_param_spec_string(PROP_NAME_S, - "The DBus name for the service to monitor", - "This is the name that should be used to start a service.", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property(object_class, PROP_VERSION, - g_param_spec_uint(PROP_VERSION_S, - "The version of the service that we're expecting.", - "A number to check and reject a service if it gives us the wrong number. This should match across the manager and the service", - 0, G_MAXUINT, 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - /* Setting up the DBus interfaces */ - if (node_info == NULL) { - GError * error = NULL; - - node_info = g_dbus_node_info_new_for_xml(_indicator_service, &error); - if (error != NULL) { - g_error("Unable to parse Indicator Service Interface description: %s", error->message); - g_error_free(error); - } - } - - if (interface_info == NULL) { - interface_info = g_dbus_node_info_lookup_interface(node_info, INDICATOR_SERVICE_INTERFACE); - - if (interface_info == NULL) { - g_error("Unable to find interface '" INDICATOR_SERVICE_INTERFACE "'"); - } - } - - return; -} - -/* This inits all the variable and sets up the proxy - to dbus. It doesn't look for the service as at this - point we don't know it's name. */ -static void -indicator_service_manager_init (IndicatorServiceManager *self) -{ - IndicatorServiceManagerPrivate * priv = indicator_service_manager_get_instance_private(self); - - /* Get the private variables in a decent state */ - priv->name = NULL; - priv->service_proxy = NULL; - priv->service_proxy_cancel = NULL; - priv->name_watcher = 0; - priv->connected = FALSE; - priv->this_service_version = 0; - priv->restart_count = 0; - priv->restart_source = 0; - priv->watch_cancel = NULL; - - return; -} - -/* If we're connected this provides all the signals to say - that we're about to not be. Then it takes down the proxies - and tells the service that we're not interested in being - its friend anymore either. */ -static void -indicator_service_manager_dispose (GObject *object) -{ - IndicatorServiceManager * sm = INDICATOR_SERVICE_MANAGER(object); - IndicatorServiceManagerPrivate * priv = indicator_service_manager_get_instance_private(sm); - - /* Removing the idle task to restart if it exists. */ - if (priv->restart_source != 0) { - g_source_remove(priv->restart_source); - } - /* Block any restart calls */ - priv->restart_source = -1; - - /* If we were connected we need to make sure to - tell people that it's no longer the case. */ - if (priv->connected) { - priv->connected = FALSE; - g_signal_emit(object, signals[CONNECTION_CHANGE], 0, FALSE, TRUE); - } - - if (priv->name_watcher != 0) { - g_dbus_connection_signal_unsubscribe(g_dbus_proxy_get_connection(priv->service_proxy), - priv->name_watcher); - priv->name_watcher = 0; - } - - /* If we're still getting the proxy, stop looking so we - can then clean up some more. */ - if (priv->service_proxy_cancel != NULL) { - g_cancellable_cancel(priv->service_proxy_cancel); - g_object_unref(priv->service_proxy_cancel); - priv->service_proxy_cancel = NULL; - } - - /* If we've sent a watch, cancel looking for the reply before - sending the unwatch */ - if (priv->watch_cancel != NULL) { - g_cancellable_cancel(priv->watch_cancel); - g_object_unref(priv->watch_cancel); - priv->watch_cancel = NULL; - } - - /* If we have a proxy, tell it we're shutting down. Just - to be polite about it. */ - if (priv->service_proxy != NULL) { - unwatch(priv->service_proxy); - } - - /* Destory our service proxy, we won't need it. */ - if (priv->service_proxy != NULL) { - g_object_unref(G_OBJECT(priv->service_proxy)); - priv->service_proxy = NULL; - } - - /* Let's see if our parents want to do anything. */ - G_OBJECT_CLASS (indicator_service_manager_parent_class)->dispose (object); - return; -} - -/* Ironically, we don't allocate a lot of memory ourselves. */ -static void -indicator_service_manager_finalize (GObject *object) -{ - IndicatorServiceManager * sm = INDICATOR_SERVICE_MANAGER(object); - IndicatorServiceManagerPrivate * priv = indicator_service_manager_get_instance_private(sm); - - if (priv->name != NULL) { - g_free(priv->name); - priv->name = NULL; - } - - G_OBJECT_CLASS (indicator_service_manager_parent_class)->finalize (object); - return; -} - -/* Either copies the name into the private variable or - sets the version. Do it wrong and it'll get upset. */ -static void -set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) -{ - IndicatorServiceManager * self = INDICATOR_SERVICE_MANAGER(object); - g_return_if_fail(self != NULL); - - IndicatorServiceManagerPrivate * priv = indicator_service_manager_get_instance_private(self); - g_return_if_fail(priv != NULL); - - switch (prop_id) { - /* *********************** */ - case PROP_NAME: - if (priv->name != NULL) { - g_error("Name can not be set twice!"); - } - priv->name = g_value_dup_string(value); - start_service(self); - break; - /* *********************** */ - case PROP_VERSION: - priv->this_service_version = g_value_get_uint(value); - break; - /* *********************** */ - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } - - return; -} - -/* Grabs the values from the private variables and - puts them into the value. */ -static void -get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) -{ - IndicatorServiceManager * self = INDICATOR_SERVICE_MANAGER(object); - g_return_if_fail(self != NULL); - - IndicatorServiceManagerPrivate * priv = indicator_service_manager_get_instance_private(self); - g_return_if_fail(priv != NULL); - - switch (prop_id) { - /* *********************** */ - case PROP_NAME: - g_value_set_string(value, priv->name); - break; - /* *********************** */ - case PROP_VERSION: - g_value_set_uint(value, priv->this_service_version); - break; - /* *********************** */ - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } - - return; -} - -/* Small little function to make a long function call a little - bit cleaner. */ -static void -unwatch (GDBusProxy * proxy) -{ - g_dbus_proxy_call(proxy, - "UnWatch", - NULL, /* parameters */ - G_DBUS_CALL_FLAGS_NONE, - -1, /* timeout */ - NULL, /* cancelable */ - NULL, /* callback */ - NULL); /* user data */ - return; -} - -/* A callback from telling a service that we want to watch - it. It gives us the service API version and the version - of the other APIs it supports. We check both of those. - If they don't match then we unwatch it. Otherwise, we - signal a connection change to tell the rest of the world - that we have a service now. */ -static void -watch_cb (GObject * object, GAsyncResult * res, gpointer user_data) -{ - GError * error = NULL; - IndicatorServiceManagerPrivate * priv = indicator_service_manager_get_instance_private(user_data); - - GVariant * params = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error); - - if (error != NULL) { - g_warning("Unable to set watch on '%s': '%s'", priv->name, error->message); - g_error_free(error); - start_service_again(INDICATOR_SERVICE_MANAGER(user_data)); - return; - } - - guint service_api_version; - guint this_service_version; - - g_variant_get(params, "(uu)", &service_api_version, &this_service_version); - g_variant_unref(params); - - /* We've done it, now let's stop counting. */ - /* Note: we're not checking versions. Because, the hope is that - the guy holding the name we want with the wrong version will - drop and we can start another service quickly. */ - priv->restart_count = 0; - - if (service_api_version != INDICATOR_SERVICE_VERSION) { - g_warning("Service is using a different version of the service interface. Expecting %d and got %d.", INDICATOR_SERVICE_VERSION, service_api_version); - unwatch(priv->service_proxy); - - /* Let's make us wait a little while, then try again */ - priv->restart_count = TIMEOUT_A_LITTLE_WHILE; - start_service_again(INDICATOR_SERVICE_MANAGER(user_data)); - return; - } - - if (this_service_version != priv->this_service_version) { - g_warning("Service is using a different API version than the manager. Expecting %d and got %d.", priv->this_service_version, this_service_version); - unwatch(priv->service_proxy); - - /* Let's make us wait a little while, then try again */ - priv->restart_count = TIMEOUT_A_LITTLE_WHILE; - start_service_again(INDICATOR_SERVICE_MANAGER(user_data)); - return; - } - - if (!priv->connected) { - priv->connected = TRUE; - g_signal_emit(G_OBJECT(user_data), signals[CONNECTION_CHANGE], 0, TRUE, TRUE); - } - - return; -} - -/* The function that handles getting us connected to the service. - In many cases it will start the service, but if the service - is already there it just allocates the service proxy and acts - like it was no big deal. */ -static void -start_service (IndicatorServiceManager * service) -{ - IndicatorServiceManagerPrivate * priv = indicator_service_manager_get_instance_private(service); - - g_return_if_fail(priv->name != NULL); - - if (priv->service_proxy_cancel != NULL) { - /* A service proxy is being gotten currently */ - return; - } - - if (priv->service_proxy != NULL) { - g_object_unref(priv->service_proxy); - priv->service_proxy = NULL; - } - - priv->service_proxy_cancel = g_cancellable_new(); - - g_dbus_proxy_new_for_bus(G_BUS_TYPE_SESSION, - G_DBUS_PROXY_FLAGS_NONE, - interface_info, - priv->name, - INDICATOR_SERVICE_OBJECT, - INDICATOR_SERVICE_INTERFACE, - priv->service_proxy_cancel, - service_proxy_cb, - service); - - return; -} - -/* Callback from trying to create the proxy for the service, this - could include starting the service. Sometime it'll fail and - we'll try to start that dang service again! */ -static void -service_proxy_cb (__attribute__((unused)) GObject * object, GAsyncResult * res, gpointer user_data) -{ - GError * error = NULL; - - IndicatorServiceManager * service = INDICATOR_SERVICE_MANAGER(user_data); - g_return_if_fail(service != NULL); - - GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish(res, &error); - - IndicatorServiceManagerPrivate * priv = indicator_service_manager_get_instance_private(user_data); - - if (priv->service_proxy_cancel != NULL) { - g_object_unref(priv->service_proxy_cancel); - priv->service_proxy_cancel = NULL; - } - - if (error != NULL) { - /* Unable to create the proxy, eh, let's try again - in a bit */ - g_error_free(error); - start_service_again(service); - return; - } - - gchar * name = g_dbus_proxy_get_name_owner(proxy); - if (name == NULL) { - /* Hmm, since creating the proxy should start it, it seems very - odd that it wouldn't have an owner at this point. But, all - we can do is try again. */ - g_object_unref(proxy); - start_service_again(service); - return; - } - g_free(name); - - /* Okay, we're good to grab the proxy at this point, we're - sure that it's ours. */ - priv->service_proxy = proxy; - - /* Signal for drop */ - priv->name_watcher = g_dbus_connection_signal_subscribe( - g_dbus_proxy_get_connection(proxy), - "org.freedesktop.DBus", - "org.freedesktop.DBus", - "NameOwnerChanged", - "/org/freedesktop/DBus", - g_dbus_proxy_get_name(proxy), - G_DBUS_SIGNAL_FLAGS_NONE, - service_proxy_name_changed, - user_data, - NULL); - - /* Build cancelable if we need it */ - if (priv->watch_cancel == NULL) { - priv->watch_cancel = g_cancellable_new(); - } - - /* Send watch */ - g_dbus_proxy_call(priv->service_proxy, - "Watch", - NULL, /* params */ - G_DBUS_CALL_FLAGS_NONE, - -1, - priv->watch_cancel, - watch_cb, - user_data); - - return; -} - -/* Responds to the name owner changing of the proxy, this - usually means the service died. We're dropping the proxy - and recreating it so that it'll restart the service. */ -static void -service_proxy_name_changed (__attribute__((unused)) GDBusConnection * connection, - __attribute__((unused)) const gchar * sender_name, - __attribute__((unused)) const gchar * object_path, - __attribute__((unused)) const gchar * interface_name, - __attribute__((unused)) const gchar * signal_name, - GVariant * parameters, - gpointer user_data) - -{ - IndicatorServiceManagerPrivate * priv = indicator_service_manager_get_instance_private(user_data); - - const gchar * new_name = NULL; - const gchar * prev_name = NULL; - g_variant_get(parameters, "(&s&s&s)", NULL, &prev_name, &new_name); - - if (new_name == NULL || new_name[0] == 0) { - if (priv->connected) { - priv->connected = FALSE; - g_signal_emit(G_OBJECT(user_data), signals[CONNECTION_CHANGE], 0, FALSE, TRUE); - } - - start_service_again(INDICATOR_SERVICE_MANAGER(user_data)); - } else { - /* If we weren't connected before, we are now. Let's tell the - world! */ - if (!priv->connected) { - priv->connected = TRUE; - g_signal_emit(G_OBJECT(user_data), signals[CONNECTION_CHANGE], 0, TRUE, TRUE); - } - - /* If the names are both valid, and they're not the same, it means that - we've actually changed. So we need to tell the new guy that we're - watching them */ - if (new_name != NULL && prev_name != NULL && new_name[0] != 0 && prev_name != 0 && g_strcmp0(prev_name, new_name) != 0) { - /* Send watch */ - g_dbus_proxy_call(priv->service_proxy, - "Watch", - NULL, /* params */ - G_DBUS_CALL_FLAGS_NONE, - -1, - priv->watch_cancel, - watch_cb, - user_data); - } - } - - return; -} - -/* The callback that starts the service for real after - the timeout as determined in 'start_service_again'. - This could be in the idle or a timer. */ -static gboolean -start_service_again_cb (gpointer data) -{ - IndicatorServiceManagerPrivate * priv = indicator_service_manager_get_instance_private(data); - priv->restart_count++; - g_debug("Restarting service '%s' count %d", priv->name, priv->restart_count); - start_service(INDICATOR_SERVICE_MANAGER(data)); - priv->restart_source = 0; - return FALSE; -} - -/* This function tries to start a new service, perhaps - after a timeout that it determines. The real issue - here is that it throttles restarting if we're not - being successful. */ -static void -start_service_again (IndicatorServiceManager * manager) -{ - IndicatorServiceManagerPrivate * priv = indicator_service_manager_get_instance_private(manager); - - /* If we've already got a restart source running then - let's not do this again. */ - if (priv->restart_source != 0) { - return; - } - - /* Allow the restarting to be disabled */ - if (g_getenv(TIMEOUT_ENV_NAME)) { - return; - } - - if (priv->restart_count == 0) { - /* First time, do it in idle */ - g_idle_add(start_service_again_cb, manager); - } else { - /* Not our first time 'round the block. Let's slow this down. */ - if (priv->restart_count > 16) - priv->restart_count = 16; /* Not more than 1024x */ - priv->restart_source = g_timeout_add((1 << priv->restart_count) * TIMEOUT_MULTIPLIER, start_service_again_cb, manager); - } - - return; -} - -/* API */ - -/** - indicator_service_manager_new: - @dbus_name: The well known name of the service on DBus - - This creates a new service manager object. If the service - is not running it will start it. No matter what, it will - give a IndicatorServiceManager::connection-changed event - signal when it gets connected. - - Return value: A brand new lovely #IndicatorServiceManager - object. -*/ -IndicatorServiceManager * -indicator_service_manager_new (const gchar * dbus_name) -{ - GObject * obj = g_object_new(INDICATOR_SERVICE_MANAGER_TYPE, - PROP_NAME_S, dbus_name, - NULL); - - return INDICATOR_SERVICE_MANAGER(obj); -} - -/** - inicator_service_manager_new_version: - @dbus_name: The well known name of the service on DBus - @version: Version of the service we expect - - This creates a new service manager object. It also sets - the version of the service that we're expecting to see. - In general, it behaves similarly to #indicator_service_manager_new() - except that it checks @version against the version returned - by the service. - - Return value: A brand new lovely #IndicatorServiceManager - object. -*/ -IndicatorServiceManager * -indicator_service_manager_new_version (const gchar * dbus_name, guint version) -{ - GObject * obj = g_object_new(INDICATOR_SERVICE_MANAGER_TYPE, - PROP_NAME_S, dbus_name, - PROP_VERSION_S, version, - NULL); - - return INDICATOR_SERVICE_MANAGER(obj); -} - -/** - indicator_service_manager_connected: - @sm: #IndicatorServiceManager object to check - - Checks to see if the service manager is connected to a - service. - - Return value: #TRUE if there is a service connceted. -*/ -gboolean -indicator_service_manager_connected (IndicatorServiceManager * sm) -{ - g_return_val_if_fail(INDICATOR_IS_SERVICE_MANAGER(sm), FALSE); - IndicatorServiceManagerPrivate * priv = indicator_service_manager_get_instance_private(sm); - return priv->connected; -} - -/** - indicator_service_manager_set_refresh: - @sm: #IndicatorServiceManager object to configure - @time_in_ms: The refresh time in milliseconds - - Use this function to set the amount of time between restarting - services that may crash or shutdown. This is mostly useful - for testing and development. - - NOTE: Not yet implemented. -*/ -void -indicator_service_manager_set_refresh (__attribute__((unused)) IndicatorServiceManager * sm, __attribute__((unused)) guint time_in_ms) -{ - - return; -} diff --git a/libayatana-indicator/indicator-service-manager.h b/libayatana-indicator/indicator-service-manager.h deleted file mode 100644 index 7d444c6..0000000 --- a/libayatana-indicator/indicator-service-manager.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -An object used to manage services. Either start them or -just connect to them. - -Copyright 2009 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 __INDICATOR_SERVICE_MANAGER_H__ -#define __INDICATOR_SERVICE_MANAGER_H__ - -#include -#include - -G_BEGIN_DECLS - -#define INDICATOR_SERVICE_MANAGER_TYPE (indicator_service_manager_get_type ()) -#define INDICATOR_SERVICE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_SERVICE_MANAGER_TYPE, IndicatorServiceManager)) -#define INDICATOR_SERVICE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INDICATOR_SERVICE_MANAGER_TYPE, IndicatorServiceManagerClass)) -#define INDICATOR_IS_SERVICE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_SERVICE_MANAGER_TYPE)) -#define INDICATOR_IS_SERVICE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INDICATOR_SERVICE_MANAGER_TYPE)) -#define INDICATOR_SERVICE_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), INDICATOR_SERVICE_MANAGER_TYPE, IndicatorServiceManagerClass)) - -#define INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE "connection-change" - -typedef struct _IndicatorServiceManager IndicatorServiceManager; -typedef struct _IndicatorServiceManagerClass IndicatorServiceManagerClass; - -/** - IndicatorServiceManagerClass: - @parent: #GObjectClass - @connection_changed: Slot for #IndicatorServiceManager::connection-changed. - @indicator_service_manager_reserved1: Reserved for future use. - @indicator_service_manager_reserved2: Reserved for future use. - @indicator_service_manager_reserved3: Reserved for future use. - @indicator_service_manager_reserved4: Reserved for future use. - -*/ -struct _IndicatorServiceManagerClass { - GObjectClass parent_class; - - /* Signals */ - void (*connection_change) (IndicatorServiceManager * sm, gboolean connected, gpointer user_data); - - /* Buffer */ - void (*indicator_service_manager_reserved1) (void); - void (*indicator_service_manager_reserved2) (void); - void (*indicator_service_manager_reserved3) (void); - void (*indicator_service_manager_reserved4) (void); -}; - -/** - IndicatorServiceManager: - @parent: #GObject - -*/ -struct _IndicatorServiceManager { - GObject parent; - -}; - -GType indicator_service_manager_get_type (void); - -IndicatorServiceManager * indicator_service_manager_new (const gchar * dbus_name); -IndicatorServiceManager * indicator_service_manager_new_version (const gchar * dbus_name, - guint version); -gboolean indicator_service_manager_connected (IndicatorServiceManager * sm); -void indicator_service_manager_set_refresh (IndicatorServiceManager * sm, - guint time_in_ms); - -G_END_DECLS - -#endif diff --git a/libayatana-indicator/indicator-service.c b/libayatana-indicator/indicator-service.c deleted file mode 100644 index de3a0cf..0000000 --- a/libayatana-indicator/indicator-service.c +++ /dev/null @@ -1,649 +0,0 @@ -/* -An object used to provide a simple interface for a service -to query version and manage whether it's running. - -Copyright 2009 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 -. -*/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include /* exit() */ - -#include - -#include "indicator-service.h" -#include "gen-indicator-service.xml.h" -#include "dbus-shared.h" - -static void unwatch_core (IndicatorService * service, const gchar * name); -static void watchers_remove (gpointer value); -static void bus_get_cb (GObject * object, GAsyncResult * res, gpointer user_data); -static GVariant * bus_watch (IndicatorService * service, const gchar * sender); - -/* Private Stuff */ -/** - IndicatorSevicePrivate: - @name: The DBus well known name for the service. - @timeout: The source ID for the timeout event. - @watcher: A list of processes on dbus that are watching us. - @this_service_version: The version to hand out that we're - implementing. May not be set, so we'll send zero (default). - @dbus_registration: The handle for this object being registered - on dbus. -*/ -typedef struct _IndicatorServicePrivate IndicatorServicePrivate; -struct _IndicatorServicePrivate { - gchar * name; - GDBusConnection * bus; - GCancellable * bus_cancel; - guint timeout; - guint timeout_length; - GHashTable * watchers; - guint this_service_version; - guint dbus_registration; - gboolean replace_mode; -}; - -/* Signals Stuff */ -enum { - SHUTDOWN, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -/* Properties */ -/* Enum for the properties so that they can be quickly - found and looked up. */ -enum { - PROP_0, - PROP_NAME, - PROP_VERSION -}; - -/* The strings so that they can be slowly looked up. */ -#define PROP_NAME_S "name" -#define PROP_VERSION_S "version" - -/* GObject Stuff */ -#define INDICATOR_SERVICE_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), INDICATOR_SERVICE_TYPE, IndicatorServicePrivate)) - -static void indicator_service_class_init (IndicatorServiceClass *klass); -static void indicator_service_init (IndicatorService *self); -static void indicator_service_dispose (GObject *object); -static void indicator_service_finalize (GObject *object); - -/* Other prototypes */ -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 try_and_get_name (IndicatorService * service); -static void bus_method_call (GDBusConnection * connection, const gchar * sender, const gchar * path, const gchar * interface, const gchar * method, GVariant * params, GDBusMethodInvocation * invocation, gpointer user_data); - -/* GDBus Stuff */ -static GDBusNodeInfo * node_info = NULL; -static GDBusInterfaceInfo * interface_info = NULL; -static GDBusInterfaceVTable interface_table = { - .method_call = bus_method_call, - .get_property = NULL, /* No properties */ - .set_property = NULL /* No properties */ -}; - -/* THE define */ -G_DEFINE_TYPE_WITH_PRIVATE (IndicatorService, indicator_service, G_TYPE_OBJECT); - -static void -indicator_service_class_init (IndicatorServiceClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = indicator_service_dispose; - object_class->finalize = indicator_service_finalize; - - /* Property funcs */ - object_class->set_property = set_property; - object_class->get_property = get_property; - - /* Properties */ - g_object_class_install_property(object_class, PROP_NAME, - g_param_spec_string(PROP_NAME_S, - "The DBus name for this service", - "This is the name that should be used on DBus for this service.", - NULL, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property(object_class, PROP_VERSION, - g_param_spec_uint(PROP_VERSION_S, - "The version of the service that we're implementing.", - "A number to represent the version of the other APIs the service provides. This should match across the manager and the service", - 0, G_MAXUINT, 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - /* Signals */ - - /** - IndicatorService::shutdown: - @arg0: The #IndicatorService object - - Signaled when the service should shutdown as no one - is listening anymore. - */ - signals[SHUTDOWN] = g_signal_new (INDICATOR_SERVICE_SIGNAL_SHUTDOWN, - G_TYPE_FROM_CLASS(klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (IndicatorServiceClass, shutdown), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0, G_TYPE_NONE); - - /* Setting up the DBus interfaces */ - if (node_info == NULL) { - GError * error = NULL; - - node_info = g_dbus_node_info_new_for_xml(_indicator_service, &error); - if (error != NULL) { - g_error("Unable to parse Indicator Service Interface description: %s", error->message); - g_error_free(error); - } - } - - if (interface_info == NULL) { - interface_info = g_dbus_node_info_lookup_interface(node_info, INDICATOR_SERVICE_INTERFACE); - - if (interface_info == NULL) { - g_error("Unable to find interface '" INDICATOR_SERVICE_INTERFACE "'"); - } - } - - return; -} - -/* This function builds the variables, sets up the dbus - proxy and registers the object on dbus. Importantly, - it does not request a name as we don't know what name - we have yet. */ -static void -indicator_service_init (IndicatorService *self) -{ - IndicatorServicePrivate * priv = indicator_service_get_instance_private(self); - - /* Get the private variables in a decent state */ - priv->name = NULL; - priv->timeout = 0; - priv->watchers = NULL; - priv->bus = NULL; - priv->bus_cancel = NULL; - priv->this_service_version = 0; - priv->timeout_length = 500; - priv->dbus_registration = 0; - priv->replace_mode = FALSE; - - const gchar * timeoutenv = g_getenv("INDICATOR_SERVICE_SHUTDOWN_TIMEOUT"); - if (timeoutenv != NULL) { - gdouble newtimeout = g_strtod(timeoutenv, NULL); - if (newtimeout >= 1.0f) { - priv->timeout_length = newtimeout; - g_debug("Setting shutdown timeout to: %u", priv->timeout_length); - } - } - - const gchar * replaceenv = g_getenv("INDICATOR_SERVICE_REPLACE_MODE"); - if (replaceenv != NULL) { - priv->replace_mode = TRUE; - g_debug("Putting into replace mode"); - } - - /* NOTE: We're using g_free here because that's what needs to - happen and we're watchers_remove as well to clean up the dbus - watches we've setup. */ - priv->watchers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, watchers_remove); - - priv->bus_cancel = g_cancellable_new(); - g_bus_get(G_BUS_TYPE_SESSION, - priv->bus_cancel, - bus_get_cb, - self); - - return; -} - -/* Unrefcounting the proxies and making sure that our - timeout doesn't come to haunt us. */ -static void -indicator_service_dispose (GObject *object) -{ - IndicatorService * service = INDICATOR_SERVICE(object); - IndicatorServicePrivate * priv = indicator_service_get_instance_private(service); - - g_clear_pointer (&priv->watchers, g_hash_table_destroy); - - if (priv->timeout != 0) { - g_source_remove(priv->timeout); - priv->timeout = 0; - } - - if (priv->dbus_registration != 0) { - g_dbus_connection_unregister_object(priv->bus, priv->dbus_registration); - /* Don't care if it fails, there's nothing we can do */ - priv->dbus_registration = 0; - } - - g_clear_object (&priv->bus); - - if (priv->bus_cancel != NULL) { - g_cancellable_cancel(priv->bus_cancel); - g_object_unref(priv->bus_cancel); - priv->bus_cancel = NULL; - } - - G_OBJECT_CLASS (indicator_service_parent_class)->dispose (object); - return; -} - -/* Freeing the name we're looking for and all of the - information on the watchers we're tracking. */ -static void -indicator_service_finalize (GObject *object) -{ - IndicatorService * service = INDICATOR_SERVICE(object); - IndicatorServicePrivate * priv = indicator_service_get_instance_private(service); - - g_free (priv->name); - g_clear_pointer (&priv->watchers, g_hash_table_destroy); - - G_OBJECT_CLASS (indicator_service_parent_class)->finalize (object); - return; -} - -/* Either copies a string for the name or it just grabs - the value of the version. */ -static void -set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) -{ - IndicatorService * self = INDICATOR_SERVICE(object); - g_return_if_fail(self != NULL); - - IndicatorServicePrivate * priv = indicator_service_get_instance_private(self); - g_return_if_fail(priv != NULL); - - switch (prop_id) { - /* *********************** */ - case PROP_NAME: - if (G_VALUE_HOLDS_STRING(value)) { - if (priv->name != NULL) { - g_error("Name can not be set twice!"); - } - priv->name = g_value_dup_string(value); - try_and_get_name(self); - } else { - g_warning("Name property requires a string value."); - } - break; - /* *********************** */ - case PROP_VERSION: - priv->this_service_version = g_value_get_uint(value); - break; - /* *********************** */ - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } - - return; -} - -/* Copies out the name into a value or the version number. - Probably this is the least useful code in this file. */ -static void -get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) -{ - IndicatorService * self = INDICATOR_SERVICE(object); - g_return_if_fail(self != NULL); - - IndicatorServicePrivate * priv = indicator_service_get_instance_private(self); - g_return_if_fail(priv != NULL); - - switch (prop_id) { - /* *********************** */ - case PROP_NAME: - if (G_VALUE_HOLDS_STRING(value)) { - g_value_set_string(value, priv->name); - } else { - g_warning("Name property requires a string value."); - } - break; - /* *********************** */ - case PROP_VERSION: - g_value_set_uint(value, priv->this_service_version); - break; - /* *********************** */ - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } - - return; -} - -/* Callback for getting our connection to DBus */ -static void -bus_get_cb (__attribute__((unused)) GObject * object, GAsyncResult * res, gpointer user_data) -{ - GError * error = NULL; - GDBusConnection * connection = g_bus_get_finish(res, &error); - - if (error != NULL) { - g_warning("Unable to get a connection to the session DBus: %s", error->message); - g_error_free(error); - exit (0); - } - - IndicatorServicePrivate * priv = indicator_service_get_instance_private(user_data); - - g_warn_if_fail(priv->bus == NULL); - priv->bus = connection; - - if (priv->bus_cancel != NULL) { - g_object_unref(priv->bus_cancel); - priv->bus_cancel = NULL; - } - - /* Now register our object on our new connection */ - priv->dbus_registration = g_dbus_connection_register_object(priv->bus, - INDICATOR_SERVICE_OBJECT, - interface_info, - &interface_table, - user_data, - NULL, - &error); - if (error != NULL) { - g_error("Unable to register the object to DBus: %s", error->message); - } - - return; -} - -/* A method has been called from our dbus inteface. Figure out what it - is and dispatch it. */ -static void -bus_method_call (__attribute__((unused)) GDBusConnection * connection, const gchar * sender, __attribute__((unused)) const gchar * path, __attribute__((unused)) const gchar * interface, const gchar * method, __attribute__((unused)) GVariant * params, GDBusMethodInvocation * invocation, gpointer user_data) -{ - IndicatorService * service = INDICATOR_SERVICE(user_data); - GVariant * retval = NULL; - - if (g_strcmp0(method, "Watch") == 0) { - retval = bus_watch(service, sender); - } else if (g_strcmp0(method, "UnWatch") == 0) { - unwatch_core(service, sender); - } else if (g_strcmp0(method, "Shutdown") == 0) { - g_signal_emit(G_OBJECT(service), signals[SHUTDOWN], 0, TRUE); - } else { - g_warning("Calling method '%s' on the indicator service and it's unknown", method); - } - - g_dbus_method_invocation_return_value(invocation, retval); - return; -} - -/* A function to remove the signals on a proxy before we destroy - it because in this case we've stopped caring. */ -static void -watchers_remove (gpointer value) -{ - g_bus_unwatch_name(GPOINTER_TO_UINT(value)); - return; -} - -/* This is the function that gets executed if we timeout - because there are no watchers. We sent the shutdown - signal and hope someone does something sane with it. */ -static gboolean -timeout_no_watchers (gpointer data) -{ - g_warning("No watchers, service timing out."); - if (g_getenv("INDICATOR_ALLOW_NO_WATCHERS") == NULL) { - g_signal_emit(G_OBJECT(data), signals[SHUTDOWN], 0, TRUE); - } else { - g_warning("\tblocked by environment variable."); - } - return FALSE; -} - -/* Callback saying that the name we were looking for has been - found and we've got it. Now start the timer to see if anyone - cares about us. */ -static void -try_and_get_name_acquired_cb (GDBusConnection * connection, __attribute__((unused)) const gchar * name, gpointer user_data) -{ - g_return_if_fail(connection != NULL); - g_return_if_fail(INDICATOR_IS_SERVICE(user_data)); - - IndicatorServicePrivate * priv = indicator_service_get_instance_private(user_data); - - /* Check to see if we already had a timer, if so we want to - extend it a bit. */ - if (priv->timeout != 0) { - g_source_remove(priv->timeout); - priv->timeout = 0; - } - - /* Allow some extra time at start up as things can be in high - contention then. */ - priv->timeout = g_timeout_add(priv->timeout_length * 2, timeout_no_watchers, user_data); - - return; -} - -/* Callback saying that we didn't get the name, so we need to - shutdown this service. */ -static void -try_and_get_name_lost_cb (GDBusConnection * connection, const gchar * name, gpointer user_data) -{ - g_return_if_fail(connection != NULL); - g_return_if_fail(INDICATOR_IS_SERVICE(user_data)); - - IndicatorServicePrivate * priv = indicator_service_get_instance_private(user_data); - - if (!priv->replace_mode) { - g_warning("Name request failed."); - g_signal_emit(G_OBJECT(user_data), signals[SHUTDOWN], 0, TRUE); - } else { - /* If we're in replace mode we can be a little more trickey - here. We're going to tell the other guy to shutdown and hope - that we get the name. */ - GDBusMessage * message = NULL; - message = g_dbus_message_new_method_call(name, - INDICATOR_SERVICE_OBJECT, - INDICATOR_SERVICE_INTERFACE, - "Shutdown"); - - g_dbus_connection_send_message(connection, message, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL); - g_object_unref(message); - - /* Check to see if we need to clean up a timeout */ - if (priv->timeout != 0) { - g_source_remove(priv->timeout); - priv->timeout = 0; - } - - /* Set a timeout for no watchers if we can't get the name */ - priv->timeout = g_timeout_add(priv->timeout_length * 4, timeout_no_watchers, user_data); - } - - return; -} - -/* This function sets up the request for the name on dbus. */ -static void -try_and_get_name (IndicatorService * service) -{ - IndicatorServicePrivate * priv = indicator_service_get_instance_private(service); - g_return_if_fail(priv->name != NULL); - - g_bus_own_name(G_BUS_TYPE_SESSION, - priv->name, - G_BUS_NAME_OWNER_FLAGS_NONE, - NULL, /* bus acquired */ - try_and_get_name_acquired_cb, /* name acquired */ - try_and_get_name_lost_cb, /* name lost */ - service, - NULL); /* user data destroy */ - - return; -} - -/* When the watcher vanishes we don't really care about it - anymore. */ -static void -watcher_vanished_cb (__attribute__((unused)) GDBusConnection * connection, const gchar * name, gpointer user_data) -{ - g_return_if_fail(INDICATOR_IS_SERVICE(user_data)); - IndicatorServicePrivate * priv = indicator_service_get_instance_private(user_data); - - gpointer finddata = g_hash_table_lookup(priv->watchers, name); - if (finddata != NULL) { - unwatch_core(INDICATOR_SERVICE(user_data), name); - } else { - g_warning("Odd, we were watching for '%s' and it disappeard, but then it wasn't in the hashtable.", name); - } - - return; -} - -/* Here is the function that gets called by the dbus - interface "Watch" function. It is an async function so - that we can get the sender and store that information. We - put them in a list and reset the timeout. */ -static GVariant * -bus_watch (IndicatorService * service, const gchar * sender) -{ - g_return_val_if_fail(INDICATOR_IS_SERVICE(service), NULL); - IndicatorServicePrivate * priv = indicator_service_get_instance_private(service); - - if (GPOINTER_TO_UINT(g_hash_table_lookup(priv->watchers, sender)) == 0) { - guint watch = g_bus_watch_name_on_connection(priv->bus, - sender, - G_BUS_NAME_WATCHER_FLAGS_NONE, - NULL, /* appeared, we dont' care, should have already happened. */ - watcher_vanished_cb, - service, - NULL); - - if (watch != 0) { - g_hash_table_insert(priv->watchers, g_strdup(sender), GUINT_TO_POINTER(watch)); - } else { - g_warning("Unable watch for '%s'", sender); - } - } - - if (priv->timeout != 0) { - g_source_remove(priv->timeout); - priv->timeout = 0; - } - - return g_variant_new("(uu)", INDICATOR_SERVICE_VERSION, priv->this_service_version); -} - -/* Performs the core of loosing a watcher; it removes them - from the list of watchers. If there are none left, it then - starts the timer for the shutdown signal. */ -static void -unwatch_core (IndicatorService * service, const gchar * name) -{ - g_return_if_fail(name != NULL); - g_return_if_fail(INDICATOR_IS_SERVICE(service)); - - IndicatorServicePrivate * priv = indicator_service_get_instance_private(service); - - /* Remove us from the watcher list here */ - gpointer watcher_item = g_hash_table_lookup(priv->watchers, name); - if (watcher_item != NULL) { - gchar * safe_name = g_strdup(name); - g_hash_table_remove(priv->watchers, safe_name); - g_free(safe_name); - } else { - /* Odd that we couldn't find the person, but, eh */ - g_warning("Unable to find watcher who is unwatching: %s", name); - } - - /* If we're out of watchers set the timeout for shutdown */ - if (g_hash_table_size(priv->watchers) == 0) { - if (priv->timeout != 0) { - /* This should never really happen, but let's ensure that - bad things don't happen if it does. */ - g_warning("No watchers timeout set twice. Resolving, but odd."); - g_source_remove(priv->timeout); - priv->timeout = 0; - } - /* If we don't get a new watcher quickly, we'll shutdown. */ - priv->timeout = g_timeout_add(priv->timeout_length, timeout_no_watchers, service); - } - - return; -} - -/* API */ - -/** - indicator_service_new: - @name: The name for the service on dbus - - This function creates the service on DBus and tries to - get a well-known name specified in @name. If the name - can't be estabilished then the #IndicatorService::shutdown - signal will be sent. - - Return value: A brand new #IndicatorService object or #NULL - if there is an error. -*/ -IndicatorService * -indicator_service_new (gchar * name) -{ - GObject * obj = g_object_new(INDICATOR_SERVICE_TYPE, - PROP_NAME_S, name, - NULL); - - return INDICATOR_SERVICE(obj); -} - -/** - indicator_service_new_version: - @name: The name for the service on dbus - @version: The version of the other interfaces provide - by the service. - - This function creates the service on DBus and tries to - get a well-known name specified in @name. If the name - can't be estabilished then the #IndicatorService::shutdown - signal will be sent. - - Return value: A brand new #IndicatorService object or #NULL - if there is an error. -*/ -IndicatorService * -indicator_service_new_version (gchar * name, guint version) -{ - GObject * obj = g_object_new(INDICATOR_SERVICE_TYPE, - PROP_NAME_S, name, - PROP_VERSION_S, version, - NULL); - - return INDICATOR_SERVICE(obj); -} diff --git a/libayatana-indicator/indicator-service.h b/libayatana-indicator/indicator-service.h deleted file mode 100644 index bda9cb7..0000000 --- a/libayatana-indicator/indicator-service.h +++ /dev/null @@ -1,85 +0,0 @@ -/* -An object used to provide a simple interface for a service -to query version and manage whether it's running. - -Copyright 2009 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 __INDICATOR_SERVICE_H__ -#define __INDICATOR_SERVICE_H__ - -#include -#include - -G_BEGIN_DECLS - -#define INDICATOR_SERVICE_TYPE (indicator_service_get_type ()) -#define INDICATOR_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_SERVICE_TYPE, IndicatorService)) -#define INDICATOR_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INDICATOR_SERVICE_TYPE, IndicatorServiceClass)) -#define INDICATOR_IS_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_SERVICE_TYPE)) -#define INDICATOR_IS_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INDICATOR_SERVICE_TYPE)) -#define INDICATOR_SERVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), INDICATOR_SERVICE_TYPE, IndicatorServiceClass)) - -#define INDICATOR_SERVICE_SIGNAL_SHUTDOWN "shutdown" - -typedef struct _IndicatorService IndicatorService; -typedef struct _IndicatorServiceClass IndicatorServiceClass; - -/** - IndicatorServiceClass: - @parent_class: #GObjectClass - @shutdown: Slot for IndicatorServiceClass::shutdown - @indicator_service_reserved1: Reserved for future use - @indicator_service_reserved2: Reserved for future use - @indicator_service_reserved3: Reserved for future use - @indicator_service_reserved4: Reserved for future use - -*/ -struct _IndicatorServiceClass { - GObjectClass parent_class; - - /* Signals */ - void (*shutdown) (IndicatorService * service, gpointer user_data); - - /* Reserved */ - void (*indicator_service_reserved1) (void); - void (*indicator_service_reserved2) (void); - void (*indicator_service_reserved3) (void); - void (*indicator_service_reserved4) (void); -}; - -/** - IndicatorService: - @parent: #GObject - -*/ -struct _IndicatorService { - GObject parent; - -}; - -GType indicator_service_get_type (void); - -IndicatorService * indicator_service_new (gchar * name); -IndicatorService * indicator_service_new_version (gchar * name, - guint version); - -G_END_DECLS - -#endif diff --git a/libayatana-indicator/indicator-service.xml b/libayatana-indicator/indicator-service.xml deleted file mode 100644 index 71ef4df..0000000 --- a/libayatana-indicator/indicator-service.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/libayatana-indicator/indicator.h b/libayatana-indicator/indicator.h deleted file mode 100644 index 8bff270..0000000 --- a/libayatana-indicator/indicator.h +++ /dev/null @@ -1,41 +0,0 @@ -/* -An interface for indicators to link to for creation. - -Copyright 2009 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 __LIBINDICATOR_INDICATOR_H_SEEN__ -#define __LIBINDICATOR_INDICATOR_H_SEEN__ 1 - -#include - -#define INDICATOR_GET_VERSION_S "get_version" -typedef gchar * (*get_version_t) (void); -gchar * get_version (void); - -#define INDICATOR_VERSION "0.3.0" -#define INDICATOR_SET_VERSION gchar * get_version(void) { return INDICATOR_VERSION; } -#define INDICATOR_VERSION_CHECK(x) (!g_strcmp0(x, INDICATOR_VERSION)) - -#define INDICATOR_GET_TYPE_S "get_type" -typedef GType (*get_type_t) (void); -#define INDICATOR_SET_TYPE(x) GType get_type (void) { return x; } - -#endif /* __LIBINDICATOR_INDICATOR_H_SEEN__ */ - diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..4933c71 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,149 @@ +if USE_GTK3 +VER=3 +lib_LTLIBRARIES = libayatana-indicator3.la +else +VER= +lib_LTLIBRARIES = libayatana-indicator.la +GTK_DISABLE_DEPRECATED = -DGTK_DISABLE_DEPRECATED +endif + +BUILT_SOURCES = indicator-object-enum-types.h indicator-object-enum-types.c +CLEANFILES = +DISTCLEANFILES = +EXTRA_DIST = \ + ayatana-indicator3-0.$(INDICATOR_API_VERSION).pc.in.in \ + ayatana-indicator-0.$(INDICATOR_API_VERSION).pc.in.in + +INDICATOR_ABI_VERSION = 7 +INDICATOR_API_VERSION = 4 + +%.pc: %.pc.in + sed \ + -e "s|\@indicator_api_version\@|$(INDICATOR_API_VERSION)|" \ + -e "s|\@indicator_abi_version\@|$(INDICATOR_ABI_VERSION)|" \ + $< > $@ + +CLEANFILES += ayatana-indicator$(VER)-0.$(INDICATOR_API_VERSION).pc + +include $(top_srcdir)/Makefile.am.marshal + +libayatana_indicatorincludedir=$(includedir)/libayatana-indicator$(VER)-0.$(INDICATOR_API_VERSION)/libayatana-indicator + +indicator_headers = \ + indicator.h \ + indicator-desktop-shortcuts.h \ + indicator-image-helper.h \ + indicator-object.h \ + indicator-service.h \ + indicator-service-manager.h + +if USE_GTK3 +indicator_headers += \ + indicator-ng.h +endif + +libayatana_indicatorinclude_HEADERS = \ + $(indicator_headers) + +libayatana_indicator_la_SOURCES = \ + $(indicator_headers) \ + dbus-shared.h \ + gen-indicator-service.xml.h \ + gen-indicator-service.xml.c \ + indicator-object.c \ + indicator-object-enum-types.c \ + indicator-desktop-shortcuts.c \ + indicator-image-helper.c \ + indicator-object-marshal.h \ + indicator-object-marshal.c \ + indicator-service.c \ + indicator-service-manager.c + +if USE_GTK3 +libayatana_indicator_la_SOURCES += \ + indicator-ng.c +endif + +libayatana_indicator_la_CFLAGS = \ + $(LIBINDICATOR_CFLAGS) \ + $(LIBINDICATOR_IDO_CFLAGS) \ + $(COVERAGE_CFLAGS) \ + $(GTK_DISABLE_DEPRECATED) \ + -DG_LOG_DOMAIN=\"libayatana-indicator\" \ + -Wall -Wno-error=deprecated-declarations + +libayatana_indicator_la_LIBADD = \ + $(LIBINDICATOR_LIBS) \ + $(LIBINDICATOR_IDO_LIBS) \ + $(LIBM) + +libayatana_indicator_la_LDFLAGS = \ + $(COVERAGE_LDFLAGS) \ + -version-info $(INDICATOR_ABI_VERSION):0:0 \ + -no-undefined \ + -export-symbols-regex "^[^_].*" + +# We duplicate these here because Automake won't let us use $(VER) on the left hand side. +# Since we carefully use $(VER) in the right hand side above, we can assign the same values. +# Only one version of the library is every compiled at the same time, so it is safe to reuse +# the right hand sides like this. +libayatana_indicator3includedir = $(libayatana_indicatorincludedir) +libayatana_indicator3include_HEADERS = $(indicator_headers) +libayatana_indicator3_la_SOURCES = $(libayatana_indicator_la_SOURCES) +libayatana_indicator3_la_CFLAGS = $(libayatana_indicator_la_CFLAGS) +libayatana_indicator3_la_LIBADD = $(libayatana_indicator_la_LIBADD) +libayatana_indicator3_la_LDFLAGS = $(libayatana_indicator_la_LDFLAGS) + +pkgconfig_DATA = ayatana-indicator$(VER)-0.$(INDICATOR_API_VERSION).pc +pkgconfigdir = $(libdir)/pkgconfig + +glib_marshal_list = indicator-object-marshal.list +glib_marshal_prefix = _indicator_object_marshal + +indicator-object-enum-types.h: s-enum-types-h + @true +s-enum-types-h: $(indicator_headers) + ( cd $(srcdir) && $(GLIB_MKENUMS) --template $(abs_srcdir)/indicator-object-enum-types.h.template \ + $(indicator_headers) ) >> tmp-indicator-object-enum-types.h \ + && (cmp -s tmp-indicator-object-enum-types.h indicator-object-enum-types.h || cp tmp-indicator-object-enum-types.h indicator-object-enum-types.h ) \ + && rm -f tmp-indicator-object-enum-types.h && echo timestamp > $(@F) + +indicator-object-enum-types.c: s-enum-types-c + @true +s-enum-types-c: $(indicator_headers) + ( cd $(srcdir) && $(GLIB_MKENUMS) --template $(abs_srcdir)/indicator-object-enum-types.c.template \ + $(indicator_headers) ) > tmp-indicator-object-enum-types.c \ + && (cmp -s tmp-indicator-object-enum-types.c indicator-object-enum-types.c || cp tmp-indicator-object-enum-types.c indicator-object-enum-types.c ) \ + && rm -f tmp-indicator-object-enum-types.c + +EXTRA_DIST += indicator-object-enum-types.h.template indicator-object-enum-types.c.template +CLEANFILES += \ + indicator-object-enum-types.h \ + indicator-object-enum-types.c \ + s-enum-types-h \ + s-enum-types-c + +################################## +# DBus Specs +################################## + +DBUS_SPECS = \ + indicator-service.xml + +gen-%.xml.h: %.xml + @echo "Building $@ from $<" + @echo "extern const char * _$(subst -,_,$(subst .,_,$(basename $(notdir $<))));" > $@ + +gen-%.xml.c: %.xml + @echo "Building $@ from $<" + echo "const char * _$(subst -,_,$(subst .,_,$(basename $(notdir $<)))) = " > $@ + @sed -e "s:\":\\\\\":g" -e s:^:\": -e s:\$$:\\\\n\": $< >> $@ + @echo ";" >> $@ + +BUILT_SOURCES += \ + gen-indicator-service.xml.h \ + gen-indicator-service.xml.c + +CLEANFILES += $(BUILT_SOURCES) + +EXTRA_DIST += $(DBUS_SPECS) diff --git a/src/ayatana-indicator-0.4.pc.in.in b/src/ayatana-indicator-0.4.pc.in.in new file mode 100644 index 0000000..02ff40d --- /dev/null +++ b/src/ayatana-indicator-0.4.pc.in.in @@ -0,0 +1,17 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +bindir=@bindir@ +includedir=@includedir@ + +indicatordir=${exec_prefix}/lib/ayatana-indicators/@indicator_abi_version@ +iconsdir=@datarootdir@/@PACKAGE@/icons/ + +Cflags: -I${includedir}/libayatana-indicator-0.@indicator_api_version@ +Requires: gtk+-2.0 +Libs: -layatana-indicator + +Name: libayatana-indicator +Description: libayatana-indicator. +Version: @VERSION@ + diff --git a/src/ayatana-indicator3-0.4.pc.in.in b/src/ayatana-indicator3-0.4.pc.in.in new file mode 100644 index 0000000..ff0862e --- /dev/null +++ b/src/ayatana-indicator3-0.4.pc.in.in @@ -0,0 +1,16 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +bindir=@bindir@ +includedir=@includedir@ + +indicatordir=${exec_prefix}/lib/ayatana-indicators3/@indicator_abi_version@/ +iconsdir=@datarootdir@/@PACKAGE@/icons/ + +Cflags: -I${includedir}/libayatana-indicator3-0.@indicator_api_version@ +Requires: gtk+-3.0 +Libs: -layatana-indicator3 + +Name: libayatana-indicator3 +Description: libayatana-indicator3. +Version: @VERSION@ diff --git a/src/dbus-shared.h b/src/dbus-shared.h new file mode 100644 index 0000000..b55acef --- /dev/null +++ b/src/dbus-shared.h @@ -0,0 +1,28 @@ +/* +Shared defines for DBus interfaces and API versions to +make sure the server and client agree. + +Copyright 2009 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 +. +*/ + +#define INDICATOR_SERVICE_INTERFACE "org.ayatana.indicator.service" +#define INDICATOR_SERVICE_OBJECT "/org/ayatana/indicator/service" + +#define INDICATOR_SERVICE_VERSION 1 + diff --git a/src/indicator-desktop-shortcuts.c b/src/indicator-desktop-shortcuts.c new file mode 100644 index 0000000..be1d632 --- /dev/null +++ b/src/indicator-desktop-shortcuts.c @@ -0,0 +1,682 @@ +/* +A small file to parse through the actions that are available +in the desktop file and making those easily usable. + +Copyright 2010 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 +. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "indicator-desktop-shortcuts.h" + +#define ACTIONS_KEY "Actions" +#define ACTION_GROUP_PREFIX "Desktop Action" + +#define OLD_GROUP_SUFFIX "Shortcut Group" +#define OLD_SHORTCUTS_KEY "X-Ayatana-Desktop-Shortcuts" +#define OLD_ENVIRON_KEY "TargetEnvironment" + +#define PROP_DESKTOP_FILE_S "desktop-file" +#define PROP_IDENTITY_S "identity" + +typedef enum _actions_t actions_t; +enum _actions_t { + ACTIONS_NONE, + ACTIONS_XAYATANA, + ACTIONS_DESKTOP_SPEC +}; + +typedef struct { + actions_t actions; + GKeyFile * keyfile; + gchar * identity; + GArray * nicks; + gchar * domain; +} IndicatorDesktopShortcutsPrivate; + +enum { + PROP_0, + PROP_DESKTOP_FILE, + PROP_IDENTITY +}; + +static void indicator_desktop_shortcuts_class_init (IndicatorDesktopShortcutsClass *klass); +static void indicator_desktop_shortcuts_init (IndicatorDesktopShortcuts *self); +static void indicator_desktop_shortcuts_dispose (GObject *object); +static void indicator_desktop_shortcuts_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 parse_keyfile (IndicatorDesktopShortcuts * ids); +static gboolean should_show (GKeyFile * keyfile, const gchar * group, const gchar * identity, gboolean should_have_target); + +G_DEFINE_TYPE_WITH_PRIVATE (IndicatorDesktopShortcuts, indicator_desktop_shortcuts, G_TYPE_OBJECT); + +/* Build up the class */ +static void +indicator_desktop_shortcuts_class_init (IndicatorDesktopShortcutsClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = indicator_desktop_shortcuts_dispose; + object_class->finalize = indicator_desktop_shortcuts_finalize; + + /* Property funcs */ + object_class->set_property = set_property; + object_class->get_property = get_property; + + g_object_class_install_property(object_class, PROP_DESKTOP_FILE, + g_param_spec_string(PROP_DESKTOP_FILE_S, + "The path of the desktop file to read", + "A path to a desktop file that we'll look for shortcuts in.", + NULL, + G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY)); + g_object_class_install_property(object_class, PROP_IDENTITY, + g_param_spec_string(PROP_IDENTITY_S, + "The string that represents the identity that we're acting as.", + "Used to process ShowIn and NotShownIn fields of the desktop shortcust to get the proper list.", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY)); + + return; +} + +/* Initialize instance data */ +static void +indicator_desktop_shortcuts_init (IndicatorDesktopShortcuts *self) +{ + IndicatorDesktopShortcutsPrivate * priv = indicator_desktop_shortcuts_get_instance_private(self); + + priv->keyfile = NULL; + priv->identity = NULL; + priv->domain = NULL; + priv->nicks = g_array_new(TRUE, TRUE, sizeof(gchar *)); + priv->actions = ACTIONS_NONE; + + return; +} + +/* Clear object references */ +static void +indicator_desktop_shortcuts_dispose (GObject *object) +{ + IndicatorDesktopShortcuts * self = INDICATOR_DESKTOP_SHORTCUTS(object); + IndicatorDesktopShortcutsPrivate * priv = indicator_desktop_shortcuts_get_instance_private(self); + + if (priv->keyfile) { + g_key_file_free(priv->keyfile); + priv->keyfile = NULL; + } + + G_OBJECT_CLASS (indicator_desktop_shortcuts_parent_class)->dispose (object); + return; +} + +/* Free all memory */ +static void +indicator_desktop_shortcuts_finalize (GObject *object) +{ + IndicatorDesktopShortcuts * self = INDICATOR_DESKTOP_SHORTCUTS(object); + IndicatorDesktopShortcutsPrivate * priv = indicator_desktop_shortcuts_get_instance_private(self); + + if (priv->identity != NULL) { + g_free(priv->identity); + priv->identity = NULL; + } + + if (priv->domain != NULL) { + g_free(priv->domain); + priv->domain = NULL; + } + + if (priv->nicks != NULL) { + guint i; + for (i = 0; i < priv->nicks->len; i++) { + gchar * nick = g_array_index(priv->nicks, gchar *, i); + g_free(nick); + } + g_array_free(priv->nicks, TRUE); + priv->nicks = NULL; + } + + G_OBJECT_CLASS (indicator_desktop_shortcuts_parent_class)->finalize (object); + return; +} + +/* Sets one of the two properties we have, only at construction though */ +static void +set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) +{ + g_return_if_fail(INDICATOR_IS_DESKTOP_SHORTCUTS(object)); + IndicatorDesktopShortcuts * self = INDICATOR_DESKTOP_SHORTCUTS(object); + IndicatorDesktopShortcutsPrivate * priv = indicator_desktop_shortcuts_get_instance_private(self); + + switch(prop_id) { + case PROP_DESKTOP_FILE: { + if (priv->keyfile != NULL) { + g_key_file_free(priv->keyfile); + priv->keyfile = NULL; + priv->actions = ACTIONS_NONE; + } + + GError * error = NULL; + GKeyFile * keyfile = g_key_file_new(); + g_key_file_load_from_file(keyfile, g_value_get_string(value), G_KEY_FILE_NONE, &error); + + if (error != NULL) { + g_warning("Unable to load keyfile from file '%s': %s", g_value_get_string(value), error->message); + g_error_free(error); + g_key_file_free(keyfile); + break; + } + + /* Always prefer the desktop spec if we can get it */ + if (priv->actions == ACTIONS_NONE && g_key_file_has_key(keyfile, G_KEY_FILE_DESKTOP_GROUP, ACTIONS_KEY, NULL)) { + priv->actions = ACTIONS_DESKTOP_SPEC; + } + + /* But fallback if we can't */ + if (priv->actions == ACTIONS_NONE && g_key_file_has_key(keyfile, G_KEY_FILE_DESKTOP_GROUP, OLD_SHORTCUTS_KEY, NULL)) { + priv->actions = ACTIONS_XAYATANA; + g_warning("Desktop file '%s' is using a deprecated format for its actions that will be dropped soon.", g_value_get_string(value)); + } + + if (priv->actions == ACTIONS_NONE) { + g_key_file_free(keyfile); + break; + } + + priv->keyfile = keyfile; + parse_keyfile(INDICATOR_DESKTOP_SHORTCUTS(object)); + break; + } + case PROP_IDENTITY: + if (priv->identity != NULL) { + g_warning("Identity already set to '%s' and trying to set it to '%s'.", priv->identity, g_value_get_string(value)); + return; + } + priv->identity = g_value_dup_string(value); + parse_keyfile(INDICATOR_DESKTOP_SHORTCUTS(object)); + break; + /* *********************** */ + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + return; +} + +/* Gets either the desktop file our the identity. */ +static void +get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) +{ + g_return_if_fail(INDICATOR_IS_DESKTOP_SHORTCUTS(object)); + IndicatorDesktopShortcuts * self = INDICATOR_DESKTOP_SHORTCUTS(object); + IndicatorDesktopShortcutsPrivate * priv = indicator_desktop_shortcuts_get_instance_private(self); + + switch(prop_id) { + case PROP_IDENTITY: + g_value_set_string(value, priv->identity); + break; + /* *********************** */ + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + return; +} + +/* Checks to see if we can, and if we can it goes through + and parses the keyfile entries. */ +static void +parse_keyfile (IndicatorDesktopShortcuts * ids) +{ + IndicatorDesktopShortcuts * self = INDICATOR_DESKTOP_SHORTCUTS(ids); + IndicatorDesktopShortcutsPrivate * priv = indicator_desktop_shortcuts_get_instance_private(self); + + if (priv->keyfile == NULL) { + return; + } + + if (priv->identity == NULL) { + return; + } + + /* Remove a previous translation domain if we had one + from a previously parsed file. */ + if (priv->domain != NULL) { + g_free(priv->domain); + priv->domain = NULL; + } + + /* Check to see if there is a custom translation domain that + we should take into account. */ + if (priv->domain == NULL && + g_key_file_has_key(priv->keyfile, G_KEY_FILE_DESKTOP_GROUP, "X-GNOME-Gettext-Domain", NULL)) { + priv->domain = g_key_file_get_string(priv->keyfile, G_KEY_FILE_DESKTOP_GROUP, "X-GNOME-Gettext-Domain", NULL); + } + + if (priv->domain == NULL && + g_key_file_has_key(priv->keyfile, G_KEY_FILE_DESKTOP_GROUP, "X-Ubuntu-Gettext-Domain", NULL)) { + priv->domain = g_key_file_get_string(priv->keyfile, G_KEY_FILE_DESKTOP_GROUP, "X-Ubuntu-Gettext-Domain", NULL); + } + + /* We need to figure out what we're looking for and what we want to + look for in the rest of the file */ + const gchar * list_name = NULL; + const gchar * group_format = NULL; + gboolean should_have_target = FALSE; + + switch (priv->actions) { + case ACTIONS_NONE: + /* None, let's just get outta here */ + return; + case ACTIONS_XAYATANA: + list_name = OLD_SHORTCUTS_KEY; + group_format = "%s " OLD_GROUP_SUFFIX; + should_have_target = TRUE; + break; + case ACTIONS_DESKTOP_SPEC: + list_name = ACTIONS_KEY; + group_format = ACTION_GROUP_PREFIX " %s"; + should_have_target = FALSE; + break; + default: + g_assert_not_reached(); + return; + } + + /* Okay, we've got everything we need. Let's get it on! */ + gsize i; + gsize num_nicks = 0; + gchar ** nicks = g_key_file_get_string_list(priv->keyfile, G_KEY_FILE_DESKTOP_GROUP, list_name, &num_nicks, NULL); + + /* If there is an error from get_string_list num_nicks should still + be zero, so this loop will drop out. */ + for (i = 0; i < num_nicks; i++) { + /* g_debug("Looking at group nick %s", nicks[i]); */ + gchar * groupname = g_strdup_printf(group_format, nicks[i]); + if (!g_key_file_has_group(priv->keyfile, groupname)) { + g_warning("Unable to find group '%s'", groupname); + g_free(groupname); + continue; + } + + if (!should_show(priv->keyfile, G_KEY_FILE_DESKTOP_GROUP, priv->identity, FALSE)) { + g_free(groupname); + continue; + } + + if (!should_show(priv->keyfile, groupname, priv->identity, should_have_target)) { + g_free(groupname); + continue; + } + + gchar * nickalloc = g_strdup(nicks[i]); + g_array_append_val(priv->nicks, nickalloc); + g_free(groupname); + } + + if (nicks != NULL) { + g_strfreev(nicks); + } + + return; +} + +/* Checks the ONLY_SHOW_IN and NOT_SHOW_IN keys for a group to + see if we should be showing ourselves. */ +static gboolean +should_show (GKeyFile * keyfile, const gchar * group, const gchar * identity, gboolean should_have_target) +{ + if (should_have_target && g_key_file_has_key(keyfile, group, OLD_ENVIRON_KEY, NULL)) { + /* If we've got this key, we're going to return here and not + process the deprecated keys. */ + gsize j; + gsize num_env = 0; + gchar ** envs = g_key_file_get_string_list(keyfile, group, OLD_ENVIRON_KEY, &num_env, NULL); + + for (j = 0; j < num_env; j++) { + if (g_strcmp0(envs[j], identity) == 0) { + break; + } + } + + if (envs != NULL) { + g_strfreev(envs); + } + + if (j == num_env) { + return FALSE; + } + return TRUE; + } + + /* If there is a list of OnlyShowIn entries we need to check + to see if we're in that list. If not, we drop this nick */ + if (g_key_file_has_key(keyfile, group, G_KEY_FILE_DESKTOP_KEY_ONLY_SHOW_IN, NULL)) { + gsize j; + gsize num_only = 0; + gchar ** onlies = g_key_file_get_string_list(keyfile, group, G_KEY_FILE_DESKTOP_KEY_ONLY_SHOW_IN, &num_only, NULL); + + for (j = 0; j < num_only; j++) { + if (g_strcmp0(onlies[j], identity) == 0) { + break; + } + } + + if (onlies != NULL) { + g_strfreev(onlies); + } + + if (j == num_only) { + return FALSE; + } + } + + /* If there is a NotShowIn entry we need to make sure that we're + not in that list. If we are, we need to drop out. */ + if (g_key_file_has_key(keyfile, group, G_KEY_FILE_DESKTOP_KEY_NOT_SHOW_IN, NULL)) { + gsize j; + gsize num_not = 0; + gchar ** nots = g_key_file_get_string_list(keyfile, group, G_KEY_FILE_DESKTOP_KEY_NOT_SHOW_IN, &num_not, NULL); + + for (j = 0; j < num_not; j++) { + if (g_strcmp0(nots[j], identity) == 0) { + break; + } + } + + if (nots != NULL) { + g_strfreev(nots); + } + + if (j != num_not) { + return FALSE; + } + } + + return TRUE; +} + +/* 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) +{ + if (*list == NULL) + return FALSE; + /* g_debug("Checking Nick: %s", list[0]); */ + if (g_strcmp0(list[0], nick) == 0) + return TRUE; + return is_valid_nick(&list[1], nick); +} + +/* API */ + +/** + indicator_desktop_shortcuts_new: + @file: The desktop file that would be opened to + find the actions. + @identity: This is a string that represents the identity + that should be used in searching those actions. It + relates to the ShowIn and NotShownIn properties. + + This function creates the basic object. It involves opening + the file and parsing it. It could potentially block on IO. At + the end of the day you'll have a fully functional object. + + Return value: A new #IndicatorDesktopShortcuts object. +*/ +IndicatorDesktopShortcuts * +indicator_desktop_shortcuts_new (const gchar * file, const gchar * identity) +{ + GObject * obj = g_object_new(INDICATOR_TYPE_DESKTOP_SHORTCUTS, + PROP_DESKTOP_FILE_S, file, + PROP_IDENTITY_S, identity, + NULL); + return INDICATOR_DESKTOP_SHORTCUTS(obj); +} + +/** + indicator_desktop_shortcuts_get_nicks: + @ids: The #IndicatorDesktopShortcuts object to look in + + Give you the list of commands that are available for this desktop + file given the identity that was passed in at creation. This will + filter out the various items in the desktop file. These nicks can + then be used as keys for working with the desktop file. + + Return value: A #NULL terminated list of strings. This memory + is managed by the @ids object. +*/ +const gchar ** +indicator_desktop_shortcuts_get_nicks (IndicatorDesktopShortcuts * ids) +{ + g_return_val_if_fail(INDICATOR_IS_DESKTOP_SHORTCUTS(ids), NULL); + IndicatorDesktopShortcuts * self = INDICATOR_DESKTOP_SHORTCUTS(ids); + IndicatorDesktopShortcutsPrivate * priv = indicator_desktop_shortcuts_get_instance_private(self); + return (const gchar **)priv->nicks->data; +} + +/** + indicator_desktop_shortcuts_nick_get_name: + @ids: The #IndicatorDesktopShortcuts object to look in + @nick: Which command that we're referencing. + + This function looks in a desktop file for a nick to find the + user visible name for that shortcut. The @nick parameter + should be gotten from #indicator_desktop_shortcuts_get_nicks + though it's not required that the exact memory location + be the same. + + Return value: A user visible string for the shortcut or + #NULL on error. +*/ +gchar * +indicator_desktop_shortcuts_nick_get_name (IndicatorDesktopShortcuts * ids, const gchar * nick) +{ + g_return_val_if_fail(INDICATOR_IS_DESKTOP_SHORTCUTS(ids), NULL); + IndicatorDesktopShortcuts * self = INDICATOR_DESKTOP_SHORTCUTS(ids); + IndicatorDesktopShortcutsPrivate * priv = indicator_desktop_shortcuts_get_instance_private(self); + + g_return_val_if_fail(priv->actions != ACTIONS_NONE, NULL); + g_return_val_if_fail(priv->keyfile != NULL, NULL); + g_return_val_if_fail(is_valid_nick((gchar **)priv->nicks->data, nick), NULL); + + const gchar * group_format = NULL; + + switch (priv->actions) { + case ACTIONS_XAYATANA: + group_format = "%s " OLD_GROUP_SUFFIX; + break; + case ACTIONS_DESKTOP_SPEC: + group_format = ACTION_GROUP_PREFIX " %s"; + break; + default: + g_assert_not_reached(); + return NULL; + } + + gchar * groupheader = g_strdup_printf(group_format, nick); + if (!g_key_file_has_group(priv->keyfile, groupheader)) { + g_warning("The group for nick '%s' doesn't exist anymore.", nick); + g_free(groupheader); + return NULL; + } + + if (!g_key_file_has_key(priv->keyfile, groupheader, G_KEY_FILE_DESKTOP_KEY_NAME, NULL)) { + g_warning("No name available for nick '%s'", nick); + g_free(groupheader); + return NULL; + } + + gchar * name = NULL; + gchar * keyvalue = g_key_file_get_string(priv->keyfile, + groupheader, + G_KEY_FILE_DESKTOP_KEY_NAME, + NULL); + gchar * localeval = g_key_file_get_locale_string(priv->keyfile, + groupheader, + G_KEY_FILE_DESKTOP_KEY_NAME, + NULL, + NULL); + g_free(groupheader); + + if (priv->domain != NULL && g_strcmp0(keyvalue, localeval) == 0) { + name = g_strdup(g_dgettext(priv->domain, keyvalue)); + g_free(localeval); + } else { + name = localeval; + } + + g_free(keyvalue); + + return name; +} + +/** + indicator_desktop_shortcuts_nick_exec_with_context: + @ids: The #IndicatorDesktopShortcuts object to look in + @nick: Which command that we're referencing. + @launch_context: The #GAppLaunchContext to use for launching the shortcut + + Here we take a @nick and try and execute the action that is + associated with it. The @nick parameter should be gotten + from #indicator_desktop_shortcuts_get_nicks though it's not + required that the exact memory location be the same. + + Return value: #TRUE on success or #FALSE on error. +*/ +gboolean +indicator_desktop_shortcuts_nick_exec_with_context (IndicatorDesktopShortcuts * ids, const gchar * nick, GAppLaunchContext * launch_context) +{ + GError * error = NULL; + + g_return_val_if_fail(INDICATOR_IS_DESKTOP_SHORTCUTS(ids), FALSE); + IndicatorDesktopShortcuts * self = INDICATOR_DESKTOP_SHORTCUTS(ids); + IndicatorDesktopShortcutsPrivate * priv = indicator_desktop_shortcuts_get_instance_private(self); + + g_return_val_if_fail(priv->actions != ACTIONS_NONE, FALSE); + g_return_val_if_fail(priv->keyfile != NULL, FALSE); + g_return_val_if_fail(is_valid_nick((gchar **)priv->nicks->data, nick), FALSE); + + const gchar * group_format = NULL; + + switch (priv->actions) { + case ACTIONS_XAYATANA: + group_format = "%s " OLD_GROUP_SUFFIX; + break; + case ACTIONS_DESKTOP_SPEC: + group_format = ACTION_GROUP_PREFIX " %s"; + break; + default: + g_assert_not_reached(); + return FALSE; + } + + gchar * groupheader = g_strdup_printf(group_format, nick); + if (!g_key_file_has_group(priv->keyfile, groupheader)) { + g_warning("The group for nick '%s' doesn't exist anymore.", nick); + g_free(groupheader); + return FALSE; + } + + if (!g_key_file_has_key(priv->keyfile, groupheader, G_KEY_FILE_DESKTOP_KEY_NAME, NULL)) { + g_warning("No name available for nick '%s'", nick); + g_free(groupheader); + return FALSE; + } + + if (!g_key_file_has_key(priv->keyfile, groupheader, G_KEY_FILE_DESKTOP_KEY_EXEC, NULL)) { + g_warning("No exec available for nick '%s'", nick); + g_free(groupheader); + return FALSE; + } + + /* Grab the name and the exec entries out of our current group */ + gchar * name = g_key_file_get_locale_string(priv->keyfile, + groupheader, + G_KEY_FILE_DESKTOP_KEY_NAME, + NULL, + NULL); + + gchar * exec = g_key_file_get_locale_string(priv->keyfile, + groupheader, + G_KEY_FILE_DESKTOP_KEY_EXEC, + NULL, + NULL); + + g_free(groupheader); + + GAppInfoCreateFlags flags = G_APP_INFO_CREATE_NONE; + + if (launch_context) { + flags |= G_APP_INFO_CREATE_SUPPORTS_STARTUP_NOTIFICATION; + } + + GAppInfo * appinfo = g_app_info_create_from_commandline(exec, name, flags, &error); + g_free(name); g_free(exec); + + if (error != NULL) { + g_warning("Unable to build Command line App info: %s", error->message); + g_error_free(error); + return FALSE; + } + + if (appinfo == NULL) { + g_warning("Unable to build Command line App info (unknown)"); + return FALSE; + } + + gboolean launched = g_app_info_launch(appinfo, NULL, launch_context, &error); + + if (error != NULL) { + g_warning("Unable to launch file from nick '%s': %s", nick, error->message); + g_clear_error(&error); + } + + g_object_unref(appinfo); + + return launched; +} + +/** + indicator_desktop_shortcuts_nick_exec: + @ids: The #IndicatorDesktopShortcuts object to look in + @nick: Which command that we're referencing. + + Here we take a @nick and try and execute the action that is + associated with it. The @nick parameter should be gotten + from #indicator_desktop_shortcuts_get_nicks though it's not + required that the exact memory location be the same. + This function is deprecated and shouldn't be used in newly + written code. + + Return value: #TRUE on success or #FALSE on error. +*/ +gboolean +indicator_desktop_shortcuts_nick_exec (IndicatorDesktopShortcuts * ids, const gchar * nick) +{ + return indicator_desktop_shortcuts_nick_exec_with_context (ids, nick, NULL); +} diff --git a/src/indicator-desktop-shortcuts.h b/src/indicator-desktop-shortcuts.h new file mode 100644 index 0000000..fb997ea --- /dev/null +++ b/src/indicator-desktop-shortcuts.h @@ -0,0 +1,80 @@ +/* +A small file to parse through the actions that are available +in the desktop file and making those easily usable. + +Copyright 2010 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 __INDICATOR_DESKTOP_SHORTCUTS_H__ +#define __INDICATOR_DESKTOP_SHORTCUTS_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +#define INDICATOR_TYPE_DESKTOP_SHORTCUTS (indicator_desktop_shortcuts_get_type ()) +#define INDICATOR_DESKTOP_SHORTCUTS(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_TYPE_DESKTOP_SHORTCUTS, IndicatorDesktopShortcuts)) +#define INDICATOR_DESKTOP_SHORTCUTS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INDICATOR_TYPE_DESKTOP_SHORTCUTS, IndicatorDesktopShortcutsClass)) +#define INDICATOR_IS_DESKTOP_SHORTCUTS(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_TYPE_DESKTOP_SHORTCUTS)) +#define INDICATOR_IS_DESKTOP_SHORTCUTS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INDICATOR_TYPE_DESKTOP_SHORTCUTS)) +#define INDICATOR_DESKTOP_SHORTCUTS_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), INDICATOR_TYPE_DESKTOP_SHORTCUTS, IndicatorDesktopShortcutsClass)) + +typedef struct _IndicatorDesktopShortcuts IndicatorDesktopShortcuts; +typedef struct _IndicatorDesktopShortcutsClass IndicatorDesktopShortcutsClass; + +/** + IndicatorDesktopShortcutsClass: + @parent_class: Space for #GObjectClass + + The vtable for our precious #IndicatorDesktopShortcutsClass. +*/ +struct _IndicatorDesktopShortcutsClass { + GObjectClass parent_class; +}; + +/** + IndicatorDesktopShortcuts: + @parent: The parent data from #GObject + + The public data for an instance of the class + #IndicatorDesktopShortcuts. +*/ +struct _IndicatorDesktopShortcuts { + GObject parent; +}; + +GType indicator_desktop_shortcuts_get_type (void); +IndicatorDesktopShortcuts * indicator_desktop_shortcuts_new (const gchar * file, + const gchar * identity); +const gchar ** indicator_desktop_shortcuts_get_nicks (IndicatorDesktopShortcuts * ids); +gchar * indicator_desktop_shortcuts_nick_get_name (IndicatorDesktopShortcuts * ids, + const gchar * nick); +gboolean indicator_desktop_shortcuts_nick_exec_with_context (IndicatorDesktopShortcuts * ids, + const gchar * nick, + GAppLaunchContext * launch_context); + +GLIB_DEPRECATED_FOR(indicator_desktop_shortcuts_nick_exec_with_context) +gboolean indicator_desktop_shortcuts_nick_exec (IndicatorDesktopShortcuts * ids, + const gchar * nick); + +G_END_DECLS + +#endif diff --git a/src/indicator-image-helper.c b/src/indicator-image-helper.c new file mode 100644 index 0000000..2c0e244 --- /dev/null +++ b/src/indicator-image-helper.c @@ -0,0 +1,218 @@ +/* +A little helper to make a themed image with fallbacks that +is only constrained in the vertical dimention. + +Copyright 2010 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 "indicator-image-helper.h" + +const gchar * INDICATOR_NAMES_DATA = "indicator-names-data"; +const gint ICON_SIZE = 22; + +static void +refresh_image (GtkImage * image) +{ + g_return_if_fail(GTK_IS_IMAGE(image)); + const gchar * icon_filename = NULL; + GtkIconInfo * icon_info = NULL; + + GIcon * icon_names = (GIcon *)g_object_get_data(G_OBJECT(image), INDICATOR_NAMES_DATA); + g_return_if_fail(G_IS_ICON (icon_names)); + + /* Get the default theme */ + GtkIconTheme * default_theme = gtk_icon_theme_get_default(); + g_return_if_fail(default_theme != NULL); + + /* Look through the themes for that icon */ + icon_info = gtk_icon_theme_lookup_by_gicon(default_theme, icon_names, ICON_SIZE, 0); + if (icon_info == NULL) { + /* Maybe the icon was just added to the theme, see if a rescan helps */ + gtk_icon_theme_rescan_if_needed(default_theme); + icon_info = gtk_icon_theme_lookup_by_gicon(default_theme, icon_names, ICON_SIZE, 0); + } + if (icon_info == NULL) { + /* Try using the second item in the names, which should be the original filename supplied */ + const gchar * const * names = g_themed_icon_get_names(G_THEMED_ICON( icon_names )); + if (names) { + icon_filename = names[1]; + } else { + g_warning("Unable to find icon\n"); + gtk_image_clear(image); + return; + } + } else { + /* Grab the filename */ + icon_filename = gtk_icon_info_get_filename(icon_info); + } + + if (icon_filename == NULL && !G_IS_BYTES_ICON(icon_names)) { + /* show a broken image if we don't have a filename or image data */ + gtk_image_set_from_icon_name(image, "image-missing", GTK_ICON_SIZE_LARGE_TOOLBAR); + return; + } + + if (icon_info != NULL && !G_IS_BYTES_ICON(icon_names)) { + GdkPixbuf *pixbuf = gtk_icon_info_load_icon(icon_info, NULL); + + if (gdk_pixbuf_get_height(pixbuf) < ICON_SIZE) { + gtk_image_set_from_file(image, icon_filename); + } else { + gtk_image_set_from_gicon(image, icon_names, GTK_ICON_SIZE_LARGE_TOOLBAR); + } + g_object_unref (pixbuf); + } else if (icon_filename != NULL) { + gtk_image_set_from_file(image, icon_filename); + + gint height; + gdk_pixbuf_get_file_info(icon_filename, NULL, &height); + + if (height > ICON_SIZE) { + gtk_image_set_pixel_size(image, ICON_SIZE); + } + } else if (G_IS_LOADABLE_ICON(icon_names)) { + /* Build a pixbuf if needed */ + GdkPixbuf * pixbuf = NULL; + GError * error = NULL; + GInputStream * stream = g_loadable_icon_load(G_LOADABLE_ICON(icon_names), ICON_SIZE, NULL, NULL, &error); + + if (stream != NULL) { + pixbuf = gdk_pixbuf_new_from_stream(stream, NULL, &error); + g_input_stream_close (stream, NULL, NULL); + g_object_unref (stream); + + if (pixbuf != NULL) { + /* Scale icon if all we get is something too big. */ + if (gdk_pixbuf_get_height(pixbuf) > ICON_SIZE) { + gfloat scale = (gfloat)ICON_SIZE / (gfloat)gdk_pixbuf_get_height(pixbuf); + gint width = round(gdk_pixbuf_get_width(pixbuf) * scale); + + GdkPixbuf * scaled = gdk_pixbuf_scale_simple(pixbuf, width, ICON_SIZE, GDK_INTERP_BILINEAR); + g_object_unref(G_OBJECT(pixbuf)); + pixbuf = scaled; + } + + /* Put the pixbuf on the image */ + gtk_image_set_from_pixbuf(image, pixbuf); + g_object_unref(G_OBJECT(pixbuf)); + } else { + g_warning ("Unable to load icon from data: %s", error->message); + g_error_free (error); + } + } else { + g_warning ("Unable to load icon from data: %s", error->message); + g_error_free (error); + } + } + + if (icon_info != NULL) { +#if GTK_CHECK_VERSION(3, 8, 0) + g_object_unref(icon_info); +#else + /* NOTE: Leaving this in for lower version as it seems + the object_unref() doesn't work on earlier versions. */ + gtk_icon_info_free (icon_info); +#endif + } +} + +/* Handles the theme changed signal to refresh the icon to make + sure that it changes appropriately */ +static void +theme_changed_cb (__attribute__((unused)) GtkIconTheme * theme, gpointer user_data) +{ + GtkImage * image = GTK_IMAGE(user_data); + refresh_image(image); + return; +} + +/* Removes the signal on the theme that was calling update on this + image. */ +static void +image_destroyed_cb (GtkImage * image, __attribute__((unused)) gpointer user_data) +{ + g_signal_handlers_disconnect_by_func(gtk_icon_theme_get_default(), theme_changed_cb, image); + return; +} + +/* Catch the style changing on the image to make sure + we've got the latest. */ +static void +image_style_change_cb (GtkImage * image, __attribute__((unused)) GtkStyle * previous_style, __attribute__((unused)) gpointer user_data) +{ + refresh_image(image); + return; +} + +/* Builds an image with the name and fallbacks and all kinds of fun + stuff . */ +GtkImage * +indicator_image_helper (const gchar * name) +{ + /* Build us an image */ + GtkImage * image = GTK_IMAGE(gtk_image_new()); + + if (name) + indicator_image_helper_update(image, name); + + return image; +} + +/* Updates and image with all the fun stuff */ +void +indicator_image_helper_update (GtkImage * image, const gchar * name) +{ + g_return_if_fail(name != NULL); + g_return_if_fail(name[0] != '\0'); + g_return_if_fail(GTK_IS_IMAGE(image)); + + /* Build us a GIcon */ + GIcon * icon_names = g_themed_icon_new_with_default_fallbacks(name); + g_warn_if_fail(icon_names != NULL); + g_return_if_fail(icon_names != NULL); + + indicator_image_helper_update_from_gicon (image, icon_names); + + g_object_unref (icon_names); + return; +} + +void +indicator_image_helper_update_from_gicon (GtkImage *image, GIcon *icon) +{ + gboolean seen_previously = FALSE; + + seen_previously = (g_object_get_data(G_OBJECT(image), INDICATOR_NAMES_DATA) != NULL); + + /* Attach our names to the image */ + g_object_set_data_full(G_OBJECT(image), INDICATOR_NAMES_DATA, g_object_ref (icon), g_object_unref); + + /* Put the pixbuf in */ + refresh_image(image); + + /* Connect to all changes */ + if (!seen_previously) { + g_signal_connect(G_OBJECT(gtk_icon_theme_get_default()), "changed", G_CALLBACK(theme_changed_cb), image); + g_signal_connect(G_OBJECT(image), "destroy", G_CALLBACK(image_destroyed_cb), NULL); + g_signal_connect(G_OBJECT(image), "style-set", G_CALLBACK(image_style_change_cb), NULL); + } + + return; +} diff --git a/src/indicator-image-helper.h b/src/indicator-image-helper.h new file mode 100644 index 0000000..290f4e2 --- /dev/null +++ b/src/indicator-image-helper.h @@ -0,0 +1,35 @@ +/* +A little helper to make a themed image with fallbacks that +is only constrained in the vertical dimention. + +Copyright 2010 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 __INDICATOR_IMAGE_HELPER_H__ +#define __INDICATOR_IMAGE_HELPER_H__ + +#include + +GtkImage * indicator_image_helper (const gchar * name); +void indicator_image_helper_update (GtkImage * image, + const gchar * name); +void indicator_image_helper_update_from_gicon (GtkImage * image, + GIcon * icon); + +#endif /* __INDICATOR_IMAGE_HELPER_H__ */ diff --git a/src/indicator-ng.c b/src/indicator-ng.c new file mode 100644 index 0000000..f057600 --- /dev/null +++ b/src/indicator-ng.c @@ -0,0 +1,1031 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Lars Uebernickel + */ + +#include "indicator-ng.h" +#include "indicator-image-helper.h" +#include +#include + +#define MENU_SECTIONS 20 + +struct _IndicatorNg +{ + IndicatorObject parent; + + gchar *service_file; + gchar *name; + gchar *object_path; + gchar *menu_object_path; + gchar *bus_name; + gchar *profile; + gchar *header_action; + gchar *scroll_action; + gchar *secondary_action; + gchar *submenu_action; + gint position; + + guint name_watch_id; + + GDBusConnection *session_bus; + GActionGroup *actions; + GMenuModel *menu; + + IndicatorObjectEntry entry; + gchar *accessible_desc; + + gint64 last_service_restart; + GMenuModel *lMenuSections[MENU_SECTIONS]; +}; + +static void indicator_ng_initable_iface_init (GInitableIface *initable); +G_DEFINE_TYPE_WITH_CODE (IndicatorNg, indicator_ng, INDICATOR_OBJECT_TYPE, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, indicator_ng_initable_iface_init)) + +enum +{ + PROP_0, + PROP_SERVICE_FILE, + PROP_PROFILE, + N_PROPERTIES +}; + +static GQuark m_pActionMuxer = 0; +static GParamSpec *properties[N_PROPERTIES]; + +static void +indicator_ng_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + IndicatorNg *self = INDICATOR_NG (object); + + switch (property_id) + { + case PROP_SERVICE_FILE: + g_value_set_string (value, self->service_file); + break; + + case PROP_PROFILE: + g_value_set_string (value, self->profile); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +indicator_ng_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + IndicatorNg *self = INDICATOR_NG (object); + + switch (property_id) + { + case PROP_SERVICE_FILE: /* construct-only */ + self->service_file = g_strdup (g_value_get_string (value)); + break; + + case PROP_PROFILE: /* construct-only */ + self->profile = g_strdup (g_value_get_string (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +indicator_ng_free_actions_and_menu (IndicatorNg *self) +{ + if (self->actions) + { + gtk_widget_insert_action_group (GTK_WIDGET (self->entry.menu), "indicator", NULL); + g_signal_handlers_disconnect_by_data (self->actions, self); + g_clear_object (&self->actions); + } + + if (self->menu) + { + for (guint nMenuSection = 0; nMenuSection < MENU_SECTIONS; nMenuSection++) + { + if (self->lMenuSections[nMenuSection]) + { + g_object_unref(self->lMenuSections[nMenuSection]); + self->lMenuSections[nMenuSection] = NULL; + } + } + + g_signal_handlers_disconnect_by_data (self->menu, self); + g_clear_object (&self->menu); + } +} + +static void +indicator_ng_dispose (GObject *object) +{ + IndicatorNg *self = INDICATOR_NG (object); + + if (self->name_watch_id) + { + g_bus_unwatch_name (self->name_watch_id); + self->name_watch_id = 0; + } + + g_clear_object (&self->session_bus); + + indicator_ng_free_actions_and_menu (self); + + g_clear_object (&self->entry.label); + g_clear_object (&self->entry.image); + g_clear_object (&self->entry.menu); + + G_OBJECT_CLASS (indicator_ng_parent_class)->dispose (object); +} + +static void +indicator_ng_finalize (GObject *object) +{ + IndicatorNg *self = INDICATOR_NG (object); + + g_free (self->service_file); + g_free (self->name); + g_free (self->object_path); + g_free (self->menu_object_path); + g_free (self->bus_name); + g_free (self->accessible_desc); + g_free (self->header_action); + g_free (self->scroll_action); + g_free (self->secondary_action); + g_free (self->submenu_action); + + G_OBJECT_CLASS (indicator_ng_parent_class)->finalize (object); +} + +static GList * +indicator_ng_get_entries (IndicatorObject *io) +{ + IndicatorNg *self = INDICATOR_NG (io); + + return g_list_append (NULL, &self->entry); +} + +static gint +indicator_ng_get_position (IndicatorObject *io) +{ + IndicatorNg *self = INDICATOR_NG (io); + + return self->position; +} + +static void +indicator_ng_entry_scrolled (IndicatorObject *io, + __attribute__((unused)) IndicatorObjectEntry *entry, + gint delta, + IndicatorScrollDirection direction) +{ + IndicatorNg *self = INDICATOR_NG (io); + + if (self->actions && self->scroll_action) + { + if (direction == INDICATOR_OBJECT_SCROLL_DOWN || + direction == INDICATOR_OBJECT_SCROLL_LEFT) + { + delta *= -1; + } + + g_action_group_activate_action (self->actions, self->scroll_action, + g_variant_new_int32 (delta)); + } +} + +void +indicator_ng_secondary_activate (IndicatorObject *io, + __attribute__((unused)) IndicatorObjectEntry *entry, + __attribute__((unused)) guint timestamp, + __attribute__((unused)) gpointer user_data) +{ + IndicatorNg *self = INDICATOR_NG (io); + + if (self->actions && self->secondary_action) + { + g_action_group_activate_action (self->actions, self->secondary_action, NULL); + } +} + +static gboolean indicator_ng_menu_insert_idos(IndicatorNg *self, GMenuModel *pSection, guint nModelItem, guint nMenuItem, gboolean bNamespace, gchar *sNamespace) +{ + gboolean bChanged = FALSE; + gchar *sType; + gboolean bHasType = g_menu_model_get_item_attribute(pSection, nModelItem, "x-ayatana-type", "s", &sType); + + if (bHasType) + { + GList *lMenuItems = gtk_container_get_children(GTK_CONTAINER(self->entry.menu)); + GtkWidget *pMenuItemOld = GTK_WIDGET(g_list_nth_data(lMenuItems, nMenuItem)); + const gchar *sName = gtk_widget_get_name(pMenuItemOld); + + if (!g_str_equal(sName, sType)) + { + GActionGroup *pActionGroup = (GActionGroup*)g_object_get_qdata(G_OBJECT(self->entry.menu), m_pActionMuxer); + GMenuItem *pMenuModelItem = g_menu_item_new_from_model(pSection, nModelItem); + GtkMenuItem* pMenuItemNew = NULL; + gchar *sAction; + + if (bNamespace && g_menu_item_get_attribute(pMenuModelItem, G_MENU_ATTRIBUTE_ACTION, "s", &sAction)) + { + gchar *sNamespacedAction = g_strconcat(sNamespace, ".", sAction, NULL); + g_menu_item_set_attribute(pMenuModelItem, G_MENU_ATTRIBUTE_ACTION, "s", sNamespacedAction); + g_free (sNamespacedAction); + g_free (sAction); + } + + for (GList *pFactory = ayatana_menu_item_factory_get_all(); pFactory != NULL && pMenuItemNew == NULL; pFactory = pFactory->next) + { + pMenuItemNew = ayatana_menu_item_factory_create_menu_item(pFactory->data, sType, pMenuModelItem, pActionGroup); + bChanged = TRUE; + } + + if (pMenuItemNew == NULL) + { + pMenuItemNew = GTK_MENU_ITEM(gtk_menu_item_new_with_label("Failed to create IDO object")); + } + + gtk_widget_set_name(GTK_WIDGET(pMenuItemNew), sType); + gtk_widget_show(GTK_WIDGET(pMenuItemNew)); + gtk_container_remove(GTK_CONTAINER(self->entry.menu), pMenuItemOld); + gtk_menu_shell_insert(GTK_MENU_SHELL(self->entry.menu), GTK_WIDGET(pMenuItemNew), nMenuItem); + g_object_unref(pMenuModelItem); + } + + g_list_free(lMenuItems); + g_free(sType); + } + + return bChanged; +} + +static void indicator_ng_menu_size_allocate(__attribute__((unused)) GtkWidget *pWidget, __attribute__((unused)) GtkAllocation *pAllocation, gpointer pUserData) +{ + IndicatorNg *self = pUserData; + GList *pMenuItem = gtk_container_get_children(GTK_CONTAINER(self->entry.menu)); + guint nWidth = 0; + guint nHeight = 0; + GdkWindow *pWindowBin = NULL; + + while (pMenuItem) + { + if (!pWindowBin) + { + pWindowBin = gtk_widget_get_parent_window(pMenuItem->data); + } + + gint nWidthNat; + gint nHeightNat; + gtk_widget_get_preferred_width(pMenuItem->data, NULL, &nWidthNat); + gtk_widget_get_preferred_height(pMenuItem->data, NULL, &nHeightNat); + nWidth = MAX((gint)nWidth, nWidthNat); + nHeight += nHeightNat; + GtkBorder cPadding; + GtkStyleContext *pContext = gtk_widget_get_style_context(GTK_WIDGET(pMenuItem->data)); + gtk_style_context_get_padding(pContext, gtk_style_context_get_state(pContext), &cPadding); + nWidth += cPadding.left + cPadding.right; + pMenuItem = g_list_next(pMenuItem); + } + + g_list_free(pMenuItem); + GtkBorder cPadding; + GtkStyleContext *pContext = gtk_widget_get_style_context(GTK_WIDGET(self->entry.menu)); + gtk_style_context_get_padding(pContext, gtk_style_context_get_state(pContext), &cPadding); + gint nBorderWidth = gtk_container_get_border_width(GTK_CONTAINER(self->entry.menu)); + gint nIconWidth; + gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &nIconWidth, NULL); + nWidth += (2 * nBorderWidth) + cPadding.left + cPadding.right + (nIconWidth * 3) / 2; + nHeight += (2 * nBorderWidth) + cPadding.top + cPadding.bottom + (nIconWidth * 3) / 4; + + GdkRectangle cRectangle = {0}; + GdkDisplay *pDisplay = gdk_display_get_default(); + GdkMonitor *pMonitor = gdk_display_get_primary_monitor(pDisplay); + gdk_monitor_get_workarea(pMonitor, &cRectangle); + + if ((gint)nHeight <= cRectangle.height) + { + gdk_window_move_resize(pWindowBin, 0, 0, nWidth, nHeight); + } + + nHeight = MIN((gint)nHeight, cRectangle.height); + + GdkWindow *pWindow = gtk_widget_get_parent_window(GTK_WIDGET(self->entry.menu)); + gdk_window_resize(pWindow, nWidth, nHeight); + + gtk_menu_reposition(self->entry.menu); +} + +static void indicator_ng_menu_section_changed(__attribute__((unused)) GMenuModel *pMenuSection, __attribute__((unused)) gint nPosition, __attribute__((unused)) gint nRemoved, __attribute__((unused)) gint nAdded, gpointer pUserData) +{ + IndicatorNg *self = pUserData; + GMenuModel *pModel = g_menu_model_get_item_link(self->menu, 0, G_MENU_LINK_SUBMENU); + guint nMenuItem = 0; + gboolean bChanged = FALSE; + + if (pModel) + { + guint nSections = g_menu_model_get_n_items(pModel); + + for (guint nSection = 0; nSection < nSections; nSection++) + { + GMenuModel *pSection = g_menu_model_get_item_link(pModel, nSection, G_MENU_LINK_SECTION); + guint nSubsections = 0; + + if (pSection) + { + gchar *sNamespace; + gboolean bNamespace = g_menu_model_get_item_attribute(pModel, nSection, G_MENU_ATTRIBUTE_ACTION_NAMESPACE, "s", &sNamespace); + nSubsections = g_menu_model_get_n_items(pSection); + + for (guint nSubsection = 0; nSubsection < nSubsections; nSubsection++) + { + GMenuModel *pSubsection = g_menu_model_get_item_link(pSection, nSubsection, G_MENU_LINK_SECTION); + + if (pSubsection) + { + guint nItems = g_menu_model_get_n_items(pSubsection); + + // Skip the subsection separator (if there is one) + GList *lMenuItems = gtk_container_get_children(GTK_CONTAINER(self->entry.menu)); + GtkWidget *pMenuItem = GTK_WIDGET(g_list_nth_data(lMenuItems, nMenuItem)); + + if (GTK_IS_SEPARATOR_MENU_ITEM(pMenuItem)) + { + nMenuItem++; + } + + g_list_free(lMenuItems); + + for (guint nItem = 0; nItem < nItems; nItem++) + { + bChanged = indicator_ng_menu_insert_idos(self, pSubsection, nItem, nMenuItem, bNamespace, sNamespace) || bChanged; + nMenuItem++; + } + } + + g_object_unref(pSubsection); + + bChanged = indicator_ng_menu_insert_idos(self, pSection, nSubsection, nMenuItem, bNamespace, sNamespace) || bChanged; + + if (!g_str_equal(self->name, "ayatana-indicator-messages")) + { + nMenuItem++; + } + } + + if (bNamespace) + { + g_free(sNamespace); + } + + g_object_unref(pSection); + } + + if (pSection && nSubsections) + { + nMenuItem++; + } + } + + g_object_unref(pModel); + } + + if (bChanged) + { + indicator_ng_menu_size_allocate(NULL, NULL, self); + } +} + +static void indicator_ng_menu_shown(__attribute__((unused)) GtkWidget *pWidget, gpointer pUserData) +{ + IndicatorNg *self = pUserData; + guint nSectionCount = 0; + + if (!self->lMenuSections[0]) + { + self->lMenuSections[0] = g_menu_model_get_item_link(self->menu, 0, G_MENU_LINK_SUBMENU); + + if (self->lMenuSections[0]) + { + guint nSections = g_menu_model_get_n_items(self->lMenuSections[0]); + + for (guint nSection = 0; nSection < nSections; nSection++) + { + self->lMenuSections[++nSectionCount] = g_menu_model_get_item_link(self->lMenuSections[0], nSection, G_MENU_LINK_SECTION); + + if (self->lMenuSections[nSectionCount]) + { + g_signal_connect(self->lMenuSections[nSectionCount], "items-changed", G_CALLBACK(indicator_ng_menu_section_changed), self); + guint nSubsections = g_menu_model_get_n_items(self->lMenuSections[nSectionCount]); + guint nParent = nSectionCount; + + for (guint nSubsection = 0; nSubsection < nSubsections; nSubsection++) + { + self->lMenuSections[++nSectionCount] = g_menu_model_get_item_link(self->lMenuSections[nParent], nSubsection, G_MENU_LINK_SECTION); + + if (self->lMenuSections[nSectionCount]) + { + g_signal_connect(self->lMenuSections[nSectionCount], "items-changed", G_CALLBACK(indicator_ng_menu_section_changed), self); + } + } + } + } + + g_signal_connect(self->lMenuSections[0], "items-changed", G_CALLBACK(indicator_ng_menu_section_changed), self); + indicator_ng_menu_section_changed(self->lMenuSections[0], 0, 0, 1, self); + } + } + + if (self->submenu_action) + { + g_action_group_change_action_state(self->actions, self->submenu_action, g_variant_new_boolean(TRUE)); + } +} + +static void +indicator_ng_menu_hidden (__attribute__((unused)) GtkWidget *widget, + gpointer user_data) +{ + IndicatorNg *self = user_data; + + if (self->submenu_action) + g_action_group_change_action_state (self->actions, self->submenu_action, + g_variant_new_boolean (FALSE)); +} + +static void +indicator_ng_set_accessible_desc (IndicatorNg *self, + const gchar *accessible_desc) +{ + g_free (self->accessible_desc); + self->accessible_desc = g_strdup (accessible_desc); + + self->entry.accessible_desc = self->accessible_desc; + g_signal_emit_by_name (self, INDICATOR_OBJECT_SIGNAL_ACCESSIBLE_DESC_UPDATE, &self->entry); +} + +static void +indicator_ng_set_icon_from_variant (IndicatorNg *self, + GVariant *variant) +{ + GIcon *icon; + + if (variant == NULL) + { + if (self->entry.image) + { + gtk_image_clear (self->entry.image); + gtk_widget_hide (GTK_WIDGET (self->entry.image)); + } + return; + } + + gtk_widget_show (GTK_WIDGET (self->entry.image)); + + icon = g_icon_deserialize (variant); + if (icon) + { + indicator_image_helper_update_from_gicon (self->entry.image, icon); + g_object_unref (icon); + } + else + { + gchar *text = g_variant_print (variant, TRUE); + g_warning ("invalid icon variant '%s'", text); + gtk_image_set_from_icon_name (self->entry.image, "image-missing", GTK_ICON_SIZE_LARGE_TOOLBAR); + g_free (text); + } +} + +static void indicator_ng_set_label(IndicatorNg *self, const gchar *label) +{ + if (!self->entry.label) + { + return; + } + + const gchar *sLabel = label; + guint nSpacing = 3; + guint nPadding = 6; + + if (label == NULL || *label == '\0' || !self->entry.image || !gtk_widget_get_visible(GTK_WIDGET(self->entry.image))) + { + nSpacing = 0; + nPadding = 0; + } + + GtkWidget *pParent = gtk_widget_get_parent(GTK_WIDGET(self->entry.label)); + GtkCssProvider *pCssProvider = gtk_css_provider_new(); + GtkStyleContext *pStyleContext = gtk_widget_get_style_context(GTK_WIDGET(self->entry.label)); + gtk_style_context_add_provider(pStyleContext, GTK_STYLE_PROVIDER(pCssProvider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + gchar *sCss = g_strdup_printf("label{padding-left: %ipx;}", nPadding); + gtk_css_provider_load_from_data(pCssProvider, sCss, -1, NULL); + g_free(sCss); + g_object_unref(pCssProvider); + if (GTK_IS_BOX(pParent)) + { + gtk_box_set_spacing(GTK_BOX(pParent), nSpacing); + } + gtk_label_set_label(GTK_LABEL (self->entry.label), sLabel); + + if (label) + { + gtk_widget_show(GTK_WIDGET (self->entry.label)); + } +} + +static void +indicator_ng_update_entry (IndicatorNg *self) +{ + GVariant *state; + const gchar *label = NULL; + GVariant *icon = NULL; + const gchar *accessible_desc = NULL; + gboolean visible = TRUE; + + g_return_if_fail (self->menu != NULL); + g_return_if_fail (self->actions != NULL); + + if (!self->header_action || + !g_action_group_has_action (self->actions, self->header_action)) + { + indicator_object_set_visible (INDICATOR_OBJECT (self), FALSE); + return; + } + + state = g_action_group_get_action_state (self->actions, self->header_action); + if (state && g_variant_is_of_type (state, G_VARIANT_TYPE ("(sssb)"))) + { + const gchar *iconstr = NULL; + + g_variant_get (state, "(&s&s&sb)", &label, &iconstr, &accessible_desc, &visible); + + if (iconstr) + icon = g_variant_ref_sink (g_variant_new_string (iconstr)); + } + else if (state && g_variant_is_of_type (state, G_VARIANT_TYPE ("a{sv}"))) + { + g_variant_lookup (state, "label", "&s", &label); + g_variant_lookup (state, "icon", "*", &icon); + g_variant_lookup (state, "accessible-desc", "&s", &accessible_desc); + g_variant_lookup (state, "visible", "b", &visible); + } + else + g_warning ("the action of the indicator menu item must have state with type (sssb) or a{sv}"); + + indicator_ng_set_label (self, label); + indicator_ng_set_icon_from_variant (self, icon); + indicator_ng_set_accessible_desc (self, accessible_desc); + indicator_object_set_visible (INDICATOR_OBJECT (self), visible); + + if (icon) + g_variant_unref (icon); + if (state) + g_variant_unref (state); +} + +static gboolean +indicator_ng_menu_item_is_of_type (GMenuModel *menu, + gint index, + const gchar *expected_type) +{ + gchar *type; + gboolean has_type = FALSE; + + if (g_menu_model_get_item_attribute (menu, index, "x-ayatana-type", "s", &type)) + { + has_type = g_str_equal (type, expected_type); + g_free (type); + } + + return has_type; +} + +static void +indicator_ng_menu_changed (__attribute__((unused)) GMenuModel *menu, + gint position, + gint removed, + gint added, + gpointer user_data) +{ + IndicatorNg *self = user_data; + + /* The menu may only contain one item (the indicator title menu). + * Thus, the position is always 0, and there is either exactly one + * item added or exactly one item removed. + */ + g_return_if_fail (position == 0); + g_return_if_fail (added < 2 && removed < 2 && added ^ removed); + + if (removed) + indicator_object_set_visible (INDICATOR_OBJECT (self), FALSE); + + if (added) + { + g_clear_pointer (&self->header_action, g_free); + g_clear_pointer (&self->scroll_action, g_free); + g_clear_pointer (&self->secondary_action, g_free); + + if (indicator_ng_menu_item_is_of_type (self->menu, 0, "org.ayatana.indicator.root")) + { + GMenuModel *popup; + gchar *action; + + if (g_menu_model_get_item_attribute (self->menu, 0, G_MENU_ATTRIBUTE_ACTION, "s", &action)) + { + if (g_str_has_prefix (action, "indicator.")) + self->header_action = g_strdup (action + strlen ("indicator.")); + g_free (action); + } + + if (g_menu_model_get_item_attribute (self->menu, 0, "x-ayatana-scroll-action", "s", &action)) + { + if (g_str_has_prefix (action, "indicator.")) + self->scroll_action = g_strdup (action + strlen ("indicator.")); + g_free (action); + } + + if (g_menu_model_get_item_attribute (self->menu, 0, "x-ayatana-secondary-action", "s", &action)) + { + if (g_str_has_prefix (action, "indicator.")) + self->secondary_action = g_strdup (action + strlen ("indicator.")); + g_free (action); + } + + if (g_menu_model_get_item_attribute (self->menu, 0, "submenu-action", "s", &action)) + { + if (g_str_has_prefix (action, "indicator.")) + self->submenu_action = g_strdup (action + strlen ("indicator.")); + g_free (action); + } + + for (guint nMenuSection = 0; nMenuSection < MENU_SECTIONS; nMenuSection++) + { + if (self->lMenuSections[nMenuSection]) + { + g_object_unref(self->lMenuSections[nMenuSection]); + } + } + + popup = g_menu_model_get_item_link (self->menu, 0, G_MENU_LINK_SUBMENU); + if (popup) + { + gtk_menu_shell_bind_model (GTK_MENU_SHELL (self->entry.menu), popup, NULL, TRUE); + g_object_unref (popup); + } + + indicator_ng_update_entry (self); + } + else + g_warning ("indicator menu item must be of type 'org.ayatana.indicator.root'"); + } +} + +static void +indicator_ng_service_appeared (GDBusConnection *connection, + __attribute__((unused)) const gchar *name, + const gchar *name_owner, + gpointer user_data) +{ + IndicatorNg *self = user_data; + + g_assert (!self->actions); + g_assert (!self->menu); + + /* watch is not established when menu_object_path == NULL */ + g_assert (self->menu_object_path); + + self->session_bus = g_object_ref (connection); + + self->actions = G_ACTION_GROUP (g_dbus_action_group_get (connection, name_owner, self->object_path)); + gtk_widget_insert_action_group (GTK_WIDGET (self->entry.menu), "indicator", self->actions); + g_signal_connect_swapped (self->actions, "action-added", G_CALLBACK (indicator_ng_update_entry), self); + g_signal_connect_swapped (self->actions, "action-removed", G_CALLBACK (indicator_ng_update_entry), self); + g_signal_connect_swapped (self->actions, "action-state-changed", G_CALLBACK (indicator_ng_update_entry), self); + + self->menu = G_MENU_MODEL (g_dbus_menu_model_get (connection, name_owner, self->menu_object_path)); + g_signal_connect (self->menu, "items-changed", G_CALLBACK (indicator_ng_menu_changed), self); + if (g_menu_model_get_n_items (self->menu)) + indicator_ng_menu_changed (self->menu, 0, 0, 1, self); + + indicator_ng_update_entry (self); +} + +static void +indicator_ng_service_started (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + IndicatorNg *self = user_data; + GError *error = NULL; + GVariant *result; + guint32 start_service_reply; + + result = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object), res, &error); + if (!result) + { + g_warning ("Could not activate service '%s': %s", self->name, error->message); + indicator_object_set_visible (INDICATOR_OBJECT (self), FALSE); + g_error_free (error); + return; + } + + start_service_reply = 0; + g_variant_get (result, "(u)", &start_service_reply); + + switch (start_service_reply) + { + case 1: /* DBUS_START_REPLY_SUCCESS */ + break; + + case 2: /* DBUS_START_REPLY_ALREADY_RUNNING */ + g_warning ("could not start service '%s': it is already running", self->name); + break; + + default: + g_assert_not_reached (); + } + + g_variant_unref (result); +} + +static void +indicator_ng_service_vanished (__attribute__((unused)) GDBusConnection *connection, + __attribute__((unused)) const gchar *name, + gpointer user_data) +{ + IndicatorNg *self = user_data; + + indicator_ng_free_actions_and_menu (self); + + /* Names may vanish because the service decided it doesn't need to + * show its indicator anymore, or because it crashed. Let's assume it + * crashes and restart it unless it explicitly hid its indicator. */ + + if (indicator_object_entry_is_visible (INDICATOR_OBJECT (self), &self->entry)) + { + gint64 now; + + /* take care not to start it if it repeatedly crashes */ + now = g_get_monotonic_time (); + if (now - self->last_service_restart < 1 * G_USEC_PER_SEC) + { + g_warning ("The indicator '%s' vanished too quickly after appearing. It won't " + "be respawned anymore, as it could be crashing repeatedly.", self->name); + return; + } + + self->last_service_restart = now; + + g_dbus_connection_call (self->session_bus, + "org.freedesktop.DBus", + "/", + "org.freedesktop.DBus", + "StartServiceByName", + g_variant_new ("(su)", self->bus_name, 0), + G_VARIANT_TYPE ("(u)"), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, + indicator_ng_service_started, + self); + } +} + +/* Get an integer from a keyfile. Returns @default_value if the key + * doesn't exist exists or is not an integer */ +static gint +g_key_file_maybe_get_integer (GKeyFile *keyfile, + const gchar *group, + const gchar *key, + gint default_value) +{ + GError *error = NULL; + gint i; + + i = g_key_file_get_integer (keyfile, group, key, &error); + if (error) + { + g_error_free (error); + return default_value; + } + + return i; +} + +static gboolean +indicator_ng_load_from_keyfile (IndicatorNg *self, + GKeyFile *keyfile, + GError **error) +{ + g_assert (self->name == NULL); + g_assert (self->object_path == NULL); + g_assert (self->menu_object_path == NULL); + + self->name = g_key_file_get_string (keyfile, "Indicator Service", "Name", error); + if (self->name == NULL) + return FALSE; + + self->object_path = g_key_file_get_string (keyfile, "Indicator Service", "ObjectPath", error); + if (self->object_path == NULL) + return FALSE; + + self->position = g_key_file_maybe_get_integer (keyfile, "Indicator Service", "Position", -1); + + /* + * Don't throw an error when the profile doesn't exist. Non-existant + * profiles are silently ignored by not showing an indicator at all. + */ + if (g_key_file_has_group (keyfile, self->profile)) + { + /* however, if the profile exists, it must have "ObjectPath" */ + self->menu_object_path = g_key_file_get_string (keyfile, self->profile, "ObjectPath", error); + if (self->menu_object_path == NULL) + return FALSE; + + /* a position in the profile overrides the global one */ + self->position = g_key_file_maybe_get_integer (keyfile, self->profile, "Position", self->position); + } + + return TRUE; +} + +static gboolean +indicator_ng_initable_init (GInitable *initable, + __attribute__((unused)) GCancellable *cancellable, + GError **error) +{ + IndicatorNg *self = INDICATOR_NG (initable); + GKeyFile *keyfile; + gboolean success = FALSE; + + self->bus_name = g_path_get_basename (self->service_file); + + keyfile = g_key_file_new (); + if (g_key_file_load_from_file (keyfile, self->service_file, G_KEY_FILE_NONE, error) && + indicator_ng_load_from_keyfile (self, keyfile, error)) + { + self->entry.name_hint = self->name; + + /* only watch the service when it supports the proile we're interested in */ + if (self->menu_object_path) + { + self->name_watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION, + self->bus_name, + G_BUS_NAME_WATCHER_FLAGS_AUTO_START, + indicator_ng_service_appeared, + indicator_ng_service_vanished, + self, NULL); + } + + success = TRUE; + } + + g_key_file_free (keyfile); + return success; +} + +static void +indicator_ng_class_init (IndicatorNgClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + IndicatorObjectClass *io_class = INDICATOR_OBJECT_CLASS (class); + + object_class->get_property = indicator_ng_get_property; + object_class->set_property = indicator_ng_set_property; + object_class->dispose = indicator_ng_dispose; + object_class->finalize = indicator_ng_finalize; + + io_class->get_entries = indicator_ng_get_entries; + io_class->get_position = indicator_ng_get_position; + io_class->entry_scrolled = indicator_ng_entry_scrolled; + io_class->secondary_activate = indicator_ng_secondary_activate; + + properties[PROP_SERVICE_FILE] = g_param_spec_string ("service-file", + "Service file", + "Path of the service file", + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + properties[PROP_PROFILE] = g_param_spec_string ("profile", + "Profile", + "Indicator profile", + "desktop", + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + + g_object_class_install_properties(object_class, N_PROPERTIES, properties); +} + +static void +indicator_ng_initable_iface_init (GInitableIface *initable) +{ + initable->init = indicator_ng_initable_init; +} + +static void +indicator_ng_init (IndicatorNg *self) +{ + m_pActionMuxer = g_quark_from_static_string ("gtk-widget-action-muxer"); + + for (guint nMenuSection = 0; nMenuSection < MENU_SECTIONS; nMenuSection++) + { + self->lMenuSections[nMenuSection] = NULL; + } + + self->entry.label = (GtkLabel*)g_object_ref_sink (gtk_label_new (NULL)); + self->entry.image = (GtkImage*)g_object_ref_sink (gtk_image_new ()); + + self->entry.menu = (GtkMenu*)g_object_ref_sink (gtk_menu_new ()); + + g_signal_connect (self->entry.menu, "show", G_CALLBACK (indicator_ng_menu_shown), self); + g_signal_connect (self->entry.menu, "hide", G_CALLBACK (indicator_ng_menu_hidden), self); + g_signal_connect (self->entry.menu, "size-allocate", G_CALLBACK (indicator_ng_menu_size_allocate), self); + + GtkCssProvider *pCssProvider = gtk_css_provider_new(); + GtkStyleContext *pStyleContext = gtk_widget_get_style_context(GTK_WIDGET(self->entry.menu)); + gtk_style_context_add_provider(pStyleContext, GTK_STYLE_PROVIDER(pCssProvider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + gtk_css_provider_load_from_data(pCssProvider, "menu > arrow{min-height: 0; padding: 0; margin: 0;}", -1, NULL); + + GtkWidget *pWindow = gtk_widget_get_parent(GTK_WIDGET(self->entry.menu)); + pStyleContext = gtk_widget_get_style_context(pWindow); + gtk_style_context_add_provider(pStyleContext, GTK_STYLE_PROVIDER(pCssProvider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + gtk_css_provider_load_from_data(pCssProvider, "window > decoration {box-shadow: 0 1px 2px rgba(0,0,0,0.2), 0 0 0 1px rgba(0,0,0,0.13);}", -1, NULL); + + g_object_unref(pCssProvider); + + /* work around IndicatorObject's warning that the accessible + * description is missing. We never set it on construction, but when + * the menu model has arrived on the bus. + */ + self->accessible_desc = g_strdup (""); + self->entry.accessible_desc = self->accessible_desc; + + self->position = -1; + + indicator_object_set_visible (INDICATOR_OBJECT (self), FALSE); +} + +IndicatorNg * +indicator_ng_new (const gchar *service_file, + GError **error) +{ + return g_initable_new (INDICATOR_TYPE_NG, NULL, error, + "service-file", service_file, + NULL); +} + +IndicatorNg * +indicator_ng_new_for_profile (const gchar *service_file, + const gchar *profile, + GError **error) +{ + return g_initable_new (INDICATOR_TYPE_NG, NULL, error, + "service-file", service_file, + "profile", profile, + NULL); +} + +const gchar * +indicator_ng_get_service_file (IndicatorNg *self) +{ + g_return_val_if_fail (INDICATOR_IS_NG (self), NULL); + + return self->service_file; +} + +const gchar * +indicator_ng_get_profile (IndicatorNg *self) +{ + g_return_val_if_fail (INDICATOR_IS_NG (self), NULL); + + return self->profile; +} diff --git a/src/indicator-ng.h b/src/indicator-ng.h new file mode 100644 index 0000000..f074a47 --- /dev/null +++ b/src/indicator-ng.h @@ -0,0 +1,48 @@ +/* + * Copyright 2013 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Lars Uebernickel + */ + +#ifndef __INDICATOR_NG_H__ +#define __INDICATOR_NG_H__ + +#include "indicator-object.h" + +#define INDICATOR_TYPE_NG (indicator_ng_get_type ()) +#define INDICATOR_NG(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_TYPE_NG, IndicatorNg)) +#define INDICATOR_NG_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INDICATOR_TYPE_NG, IndicatorNgClass)) +#define INDICATOR_IS_NG(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_TYPE_NG)) +#define INDICATOR_IS_NG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INDICATOR_TYPE_NG)) +#define INDICATOR_NG_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), INDICATOR_TYPE_NG, IndicatorNgClass)) + +typedef struct _IndicatorNg IndicatorNg; +typedef IndicatorObjectClass IndicatorNgClass; + +GType indicator_ng_get_type (void); + +IndicatorNg * indicator_ng_new (const gchar *service_file, + GError **error); + +IndicatorNg * indicator_ng_new_for_profile (const gchar *service_file, + const gchar *profile, + GError **error); + +const gchar * indicator_ng_get_service_file (IndicatorNg *indicator); + +const gchar * indicator_ng_get_profile (IndicatorNg *indicator); + +#endif diff --git a/src/indicator-object-enum-types.c.template b/src/indicator-object-enum-types.c.template new file mode 100644 index 0000000..e5b3352 --- /dev/null +++ b/src/indicator-object-enum-types.c.template @@ -0,0 +1,30 @@ +/*** BEGIN file-header ***/ +#include "indicator-object-enum-types.h" +/*** END file-header ***/ + +/*** BEGIN file-production ***/ +/* enumerations from "@basename@" */ +#include "@basename@" +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +GType +@enum_name@_get_type (void) { + static GType enum_type_id = 0; + if (G_UNLIKELY (!enum_type_id)) + { + static const G@Type@Value values[] = { +/*** END value-header ***/ + +/*** BEGIN value-production ***/ + { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, +/*** END value-production ***/ + +/*** BEGIN value-tail ***/ + { 0, NULL, NULL } + }; + enum_type_id = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values); + } + return enum_type_id; +} +/*** END value-tail ***/ diff --git a/src/indicator-object-enum-types.h.template b/src/indicator-object-enum-types.h.template new file mode 100644 index 0000000..2ac8ef8 --- /dev/null +++ b/src/indicator-object-enum-types.h.template @@ -0,0 +1,27 @@ +/*** BEGIN file-header ***/ + +#ifndef __INDICATOR_OBJECT_ENUM_TYPES_H__ +#define __INDICATOR_OBJECT_ENUM_TYPES_H__ + +#include + +G_BEGIN_DECLS + +/*** END file-header ***/ + +/*** BEGIN file-production ***/ +/* enumerations from "@basename@" */ +/*** END file-production ***/ + +/*** BEGIN file-tail ***/ +G_END_DECLS + +#endif /* !__INDICATOR_OBJECT_ENUM_TYPES_H__ */ +/*** END file-tail ***/ + +/*** BEGIN value-header ***/ + +GType @enum_name@_get_type (void) G_GNUC_CONST; +#define INDICATOR_OBJECT_TYPE_@ENUMSHORT@ (@enum_name@_get_type()) + +/*** END value-header ***/ diff --git a/src/indicator-object-marshal.list b/src/indicator-object-marshal.list new file mode 100644 index 0000000..4896ac4 --- /dev/null +++ b/src/indicator-object-marshal.list @@ -0,0 +1,4 @@ +VOID: POINTER, UINT, UINT +VOID: POINTER, UINT, ENUM +VOID: POINTER, UINT +VOID: POINTER, BOOLEAN diff --git a/src/indicator-object.c b/src/indicator-object.c new file mode 100644 index 0000000..50b3078 --- /dev/null +++ b/src/indicator-object.c @@ -0,0 +1,967 @@ +/* +An object to represent loadable indicator modules to make loading +them easy and objectified. + +Copyright 2009 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 +. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "indicator.h" +#include "indicator-object.h" +#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. + @ENTRY_VISIBLE: The entry is visible + @ENTRY_INVISIBLE: The entry is invisible +*/ +typedef enum { + ENTRY_INIT, + ENTRY_VISIBLE, + ENTRY_INVISIBLE +} +EntryVisibility; + +typedef struct _IndicatorObjectEntryPrivate { + EntryVisibility visibility; +} +IndicatorObjectEntryPrivate; + +/** + IndicatorObjectPrivate: + @module: The loaded module representing the object. Note to + subclasses: This will not be set when you're initalized. + @entry: A default entry for objects that don't need all the + fancy stuff. This works with #get_entries_default. + @gotten_entries: A check to see if the @entry has been + populated intelligently yet. + + Structure to define the memory for the private area + of the object instance. +*/ +struct _IndicatorObjectPrivate { + GModule * module; + + /* For get_entries_default */ + IndicatorObjectEntry entry; + gboolean gotten_entries; + + /* Whether or not entries are visible by default */ + gboolean default_visibility; + GHashTable * entry_privates; + + GStrv environments; +}; + +/* Signals Stuff */ +enum { + ENTRY_ADDED, + ENTRY_REMOVED, + ENTRY_MOVED, + ENTRY_SCROLLED, + MENU_SHOW, + SHOW_NOW_CHANGED, + ACCESSIBLE_DESC_UPDATE, + SECONDARY_ACTIVATE, + LAST_SIGNAL +}; + +/* Properties */ +/* Enum for the properties so that they can be quickly + found and looked up. */ +enum { + PROP_0, + PROP_GSETTINGS_SCHEMA_ID, + PROP_DEFAULT_VISIBILITY, +}; + + +static guint signals[LAST_SIGNAL] = { 0 }; + +/* GObject stuff */ +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*, guint prop_id, const GValue*, GParamSpec* ); +static void get_property (GObject*, guint prop_id, GValue*, GParamSpec* ); + +/* entries' visibility */ +static GList * get_entries_default (IndicatorObject*); +static GList * get_all_entries (IndicatorObject*); +static void indicator_object_entry_being_removed (IndicatorObject*, IndicatorObjectEntry*); +static void indicator_object_entry_was_added (IndicatorObject*, IndicatorObjectEntry*); +static gint indicator_object_real_get_position (IndicatorObject*); +static IndicatorObjectEntryPrivate * entry_get_private (IndicatorObject*, IndicatorObjectEntry*); + +G_DEFINE_TYPE_WITH_PRIVATE (IndicatorObject, indicator_object, G_TYPE_OBJECT); + +/* Setup the class and put the functions into the + class structure */ +static void +indicator_object_class_init (IndicatorObjectClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + 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; + klass->get_image = NULL; + klass->get_accessible_desc = NULL; + klass->get_entries = get_entries_default; + klass->get_location = NULL; + klass->entry_being_removed = NULL; + klass->entry_was_added = NULL; + klass->get_position = indicator_object_real_get_position; + + klass->entry_activate = NULL; + klass->entry_activate_window = NULL; + klass->entry_close = NULL; + + /** + IndicatorObject::entry-added: + @arg0: The #IndicatorObject object + @arg1: A pointer to the #IndicatorObjectEntry that + is being added. + + Signaled when a new entry is added and should + be shown by the person using this object. + */ + signals[ENTRY_ADDED] = g_signal_new (INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IndicatorObjectClass, entry_added), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER, G_TYPE_NONE); + + /** + IndicatorObject::entry-removed: + @arg0: The #IndicatorObject object + @arg1: A pointer to the #IndicatorObjectEntry that + is being removed. + + Signaled when an entry is removed and should + be removed by the person using this object. + */ + signals[ENTRY_REMOVED] = g_signal_new (INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IndicatorObjectClass, entry_removed), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER, G_TYPE_NONE); + /** + IndicatorObject::entry-moved: + @arg0: The #IndicatorObject object + @arg1: A pointer to the #IndicatorObjectEntry that + is being moved. + @arg2: The old location of the entry + @arg3: The new location of the entry + + When the order of the entries change, then this signal + is sent to tell the new location. + */ + signals[ENTRY_MOVED] = g_signal_new (INDICATOR_OBJECT_SIGNAL_ENTRY_MOVED, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IndicatorObjectClass, entry_moved), + NULL, NULL, + _indicator_object_marshal_VOID__POINTER_UINT_UINT, + G_TYPE_NONE, 3, G_TYPE_POINTER, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_NONE); + /** + IndicatorObject::entry-scrolled: + @arg0: The #IndicatorObject object + @arg1: A pointer to the #IndicatorObjectEntry that + receives the scroll event. + @arg2: The delta of the scroll event + @arg3: The orientation of the scroll event. + + When the indicator receives a mouse scroll wheel event + from the user, this signal is emitted. + */ + signals[ENTRY_SCROLLED] = g_signal_new (INDICATOR_OBJECT_SIGNAL_ENTRY_SCROLLED, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IndicatorObjectClass, entry_scrolled), + NULL, NULL, + _indicator_object_marshal_VOID__POINTER_UINT_ENUM, + G_TYPE_NONE, 3, G_TYPE_POINTER, G_TYPE_UINT, + INDICATOR_OBJECT_TYPE_SCROLL_DIRECTION); + /** + IndicatorObject::secondary-activate: + @arg0: The #IndicatorObject object + @arg1: A pointer to the #IndicatorObjectEntry that + receives the secondary activate event. + @arg2: The timestamp of the event + + When the indicator receives a secondary activation event + from the user, this signal is emitted. + */ + signals[SECONDARY_ACTIVATE] = g_signal_new (INDICATOR_OBJECT_SIGNAL_SECONDARY_ACTIVATE, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IndicatorObjectClass, secondary_activate), + NULL, NULL, + _indicator_object_marshal_VOID__POINTER_UINT, + G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_UINT); + + /** + IndicatorObject::menu-show: + @arg0: The #IndicatorObject object + @arg1: A pointer to the #IndicatorObjectEntry that + is being shown. + @arg2: The timestamp of the event + + Used when the indicator wants to signal up the stack + that the menu should be shown. + */ + signals[MENU_SHOW] = g_signal_new (INDICATOR_OBJECT_SIGNAL_MENU_SHOW, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IndicatorObjectClass, menu_show), + NULL, NULL, + _indicator_object_marshal_VOID__POINTER_UINT, + G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_UINT); + + /** + IndicatorObject::show-now-changed: + @arg0: The #IndicatorObject object + @arg1: A pointer to the #IndicatorObjectEntry that + is changing it's state + @arg2: The state of whether the entry should be shown + + Whether the entry should be shown or not has changed so we need + to tell whoever is displaying it. + */ + signals[SHOW_NOW_CHANGED] = g_signal_new (INDICATOR_OBJECT_SIGNAL_SHOW_NOW_CHANGED, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IndicatorObjectClass, show_now_changed), + NULL, NULL, + _indicator_object_marshal_VOID__POINTER_BOOLEAN, + G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_BOOLEAN); + + /** + IndicatorObject::accessible-desc-update:: + @arg0: The #IndicatorObject object + @arg1: A pointer to the #IndicatorObjectEntry whos + accessible description has been updated. + + Signaled when an indicator's accessible description + has been updated, so that the displayer of the + indicator can fetch the new description. + */ + signals[ACCESSIBLE_DESC_UPDATE] = g_signal_new (INDICATOR_OBJECT_SIGNAL_ACCESSIBLE_DESC_UPDATE, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IndicatorObjectClass, accessible_desc_update), + NULL, NULL, + g_cclosure_marshal_VOID__POINTER, + G_TYPE_NONE, 1, G_TYPE_POINTER, G_TYPE_NONE); + + /* Properties */ + + GParamSpec * 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) +{ + IndicatorObjectPrivate * priv = indicator_object_get_instance_private(self); + + priv->module = NULL; + + priv->entry.parent_object = self; + priv->entry.menu = NULL; + priv->entry.label = NULL; + priv->entry.image = NULL; + priv->entry.accessible_desc = NULL; + priv->entry.name_hint = NULL; + priv->entry.parent_window = 0; + + 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); + + priv->environments = NULL; + + self->priv = priv; + + GObject * o = G_OBJECT(self); + /* Invoke the entry-being-removed virtual function first */ + g_signal_connect (o, INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED, + 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(indicator_object_entry_was_added), NULL); +} + +/* Unref the objects that we're holding on to. */ +static void +indicator_object_dispose (GObject *object) +{ + /* Ensure that hidden entries are re-added so their widgetry will + be cleaned up properly by the client */ + indicator_object_set_visible (INDICATOR_OBJECT (object), TRUE); + + G_OBJECT_CLASS (indicator_object_parent_class)->dispose (object); +} + +/* A small helper function that closes a module but + in the function prototype of a GSourceFunc. */ +static gboolean +module_unref (gpointer data) +{ + if (!g_module_close((GModule *)data)) { + /* All we can do is warn. */ + g_warning("Unable to close module!"); + } + return FALSE; +} + +/* Free memory */ +static void +indicator_object_finalize (GObject *object) +{ + + IndicatorObject * obj = INDICATOR_OBJECT (object); + IndicatorObjectPrivate * priv = indicator_object_get_instance_private(obj); + + 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; + } + + 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 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. + Slightly non-deterministic, but should work. */ + g_idle_add(module_unref, priv->module); + priv->module = NULL; + } + + G_OBJECT_CLASS (indicator_object_parent_class)->finalize (object); + return; +} + +/** + indicator_object_new_from_file: + @file: Filename containing a loadable module + + This function builds an #IndicatorObject using the symbols + that are found in @file. The module is loaded and the + references are all kept by the object. To unload the + module the object must be destroyed. + + Return value: A valid #IndicatorObject or #NULL if error. +*/ +IndicatorObject * +indicator_object_new_from_file (const gchar * file) +{ + GObject * object = NULL; + GModule * module = NULL; + + /* Check to make sure the name exists and that the + file itself exists */ + if (file == NULL) { + g_warning("Invalid filename."); + return NULL; + } + + if (!g_file_test(file, G_FILE_TEST_EXISTS)) { + g_warning("File '%s' does not exist.", file); + return NULL; + } + + /* Grab the g_module reference, pull it in but let's + keep the symbols local to avoid conflicts. */ + module = g_module_open(file, + G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); + if (module == NULL) { + g_warning("Unable to load module: %s", file); + return NULL; + } + + /* Look for the version function, error if not found. */ + get_version_t lget_version = NULL; + if (!g_module_symbol(module, INDICATOR_GET_VERSION_S, (gpointer *)(&lget_version))) { + g_warning("Unable to get the symbol for getting the version."); + return NULL; + } + + /* Check the version with the macro and make sure we're + all talking the same language. */ + if (!INDICATOR_VERSION_CHECK(lget_version())) { + g_warning("Indicator using API version '%s' we're expecting '%s'", lget_version(), INDICATOR_VERSION); + return NULL; + } + + /* The function for grabbing a label from the module + execute it, and make sure everything is a-okay */ + get_type_t lget_type = NULL; + if (!g_module_symbol(module, INDICATOR_GET_TYPE_S, (gpointer *)(&lget_type))) { + g_warning("Unable to get '" INDICATOR_GET_TYPE_S "' symbol from module: %s", file); + goto unrefandout; + } + if (lget_type == NULL) { + g_warning("Symbol '" INDICATOR_GET_TYPE_S "' is (null) in module: %s", file); + goto unrefandout; + } + + /* A this point we allocate the object, any code beyond + here needs to deallocate it if we're returning in an + error'd state. */ + object = g_object_new(lget_type(), NULL); + if (object == NULL) { + g_warning("Unable to build an object if type '%d' in module: %s", (gint)lget_type(), file); + goto unrefandout; + } + if (!INDICATOR_IS_OBJECT(object)) { + g_warning("Type '%d' in file %s is not a subclass of IndicatorObject.", (gint)lget_type(), file); + goto unrefandout; + } + + /* Now we can track the module */ + IndicatorObject * obj = INDICATOR_OBJECT(object); + IndicatorObjectPrivate * priv = indicator_object_get_instance_private(obj); + priv->module = module; + + return obj; + + /* Error, let's drop the object and return NULL. Sad when + this happens. */ +unrefandout: + g_clear_object (&object); + g_clear_object (&module); + g_warning("Error building IndicatorObject from file: %s", file); + return NULL; +} + +/* The default get entries function uses the other single + entries in the class to create an entry structure and + put it into a list. This makes it simple for simple objects + to create the list. Small changes from the way they + previously were. */ +static GList * +get_entries_default (IndicatorObject * io) +{ + IndicatorObjectPrivate * priv = indicator_object_get_instance_private(io); + + if (!priv->gotten_entries) { + IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io); + + priv->entry.parent_object = io; + + if (class->get_label) { + priv->entry.label = class->get_label(io); + } + + if (class->get_image) { + priv->entry.image = class->get_image(io); + } + + if (priv->entry.image == NULL && priv->entry.label == NULL) { + g_warning("IndicatorObject class does not create an image or a label. We need one of those."); + return NULL; + } + + if (class->get_menu) { + priv->entry.menu = class->get_menu(io); + } + + if (priv->entry.menu == NULL) { + g_warning("IndicatorObject class does not create a menu. We need one of those."); + return NULL; + } + + if (class->get_accessible_desc) { + priv->entry.accessible_desc = class->get_accessible_desc(io); + } + + if (priv->entry.accessible_desc == NULL) { + g_warning("IndicatorObject class does not have an accessible description."); + } + + if (class->get_name_hint) { + priv->entry.name_hint = class->get_name_hint(io); + } + + if (class->get_parent_window) { + priv->entry.parent_window = class->get_parent_window(io); + } + + priv->gotten_entries = TRUE; + } + + return g_list_append(NULL, &(priv->entry)); +} + +/* returns a list of all IndicatorObjectEntries, visible or not */ +static GList* +get_all_entries (IndicatorObject * io) +{ + GList * all_entries = NULL, *l; + + 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); + + for (l = all_entries; l; l = l->next) + { + IndicatorObjectEntry *entry = l->data; + + if (entry) + entry->parent_object = io; + } + } + + return all_entries; +} + +/* get the private structure that corresponds to a caller-specified entry */ +static 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); + + 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 (h, entry, priv); + } + + return priv; +} + +/** + 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. + + Return value: (element-type IndicatorObjectEntry) (transfer container): + A list if #IndicatorObjectEntry structures or NULL on error. +*/ +GList * +indicator_object_get_entries (IndicatorObject * io) +{ + GList * l; + GList * ret = NULL; + GList * all_entries = get_all_entries (io); + IndicatorObjectPrivate * priv = indicator_object_get_instance_private(io); + const gboolean default_visibility = priv->default_visibility; + + for (l=all_entries; l!=NULL; l=l->next) + { + gboolean show_me; + IndicatorObjectEntry * entry = l->data; + + switch (entry_get_private(io,entry)->visibility) { + 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_prepend (ret, entry); + } + + g_list_free (all_entries); + return g_list_reverse (ret); +} + +/** + indicator_object_get_location: + @io: #IndicatorObject to query + @entry: The #IndicatorObjectEntry to look for. + + This function looks on the class for the object and calls + it's #IndicatorObjectClass::get_location function. If the + function doesn't exist it returns zero. + + Return value: Location of the @entry in the display or + zero if no location is specified. +*/ +guint +indicator_object_get_location (IndicatorObject * io, IndicatorObjectEntry * entry) +{ + g_return_val_if_fail(INDICATOR_IS_OBJECT(io), 0); + IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io); + + if (class->get_location) { + return class->get_location(io, entry); + } + + return 0; +} + +/** + indicator_object_get_show_now: + @io: #IndicatorObject to query + @entry: The #IndicatorObjectEntry to look for. + + This function returns whether the entry should be shown with + priority on the panel. If the object does not support checking + it assumes that its entries should never have priority. + + Return value: Whether the entry should be shown with priority. +*/ +guint +indicator_object_get_show_now (IndicatorObject * io, IndicatorObjectEntry * entry) +{ + g_return_val_if_fail(INDICATOR_IS_OBJECT(io), 0); + IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io); + + if (class->get_show_now) { + return class->get_show_now(io, entry); + } + + 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) +{ + 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; +} + +/** + indicator_object_entry_activate: + @io: #IndicatorObject to query + @entry: The #IndicatorObjectEntry whose entry was shown + @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. Note, this does not actually show the menu that's + left up to the reader. +*/ +void +indicator_object_entry_activate (IndicatorObject * io, IndicatorObjectEntry * entry, guint timestamp) +{ + g_return_if_fail(INDICATOR_IS_OBJECT(io)); + IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io); + + if (class->entry_activate != NULL) { + return class->entry_activate(io, entry, timestamp); + } + + return; +} + +/** + indicator_object_entry_close: + @io: #IndicatorObject to query + @entry: The #IndicatorObjectEntry whose menu was closed + @timestamp: The X11 timestamp of the event + + Used to tell the indicator that a menu has been closed for the + entry that is specified. +*/ +void +indicator_object_entry_close (IndicatorObject * io, IndicatorObjectEntry * entry, guint timestamp) +{ + g_return_if_fail(INDICATOR_IS_OBJECT(io)); + IndicatorObjectClass * class = INDICATOR_OBJECT_GET_CLASS(io); + + if (class->entry_close != NULL) { + return class->entry_close(io, entry, timestamp); + } + + 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 (entry) + entry->parent_object = NULL; + + 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 (entry) + entry->parent_object = io; + + if (class->entry_was_added != NULL) + { + class->entry_was_added (io, entry); + } +} + +static gint +indicator_object_real_get_position (IndicatorObject *io) +{ + g_return_val_if_fail (INDICATOR_IS_OBJECT (io), -1); + + return -1; +} + +/** + indicator_object_set_environment: + @io: #IndicatorObject to set on + @env: List of enviroment names to use + + Sets the names of the environment that the indicator is being + loaded into. This allows for indicators to behave differently + in different hosts if need be. +*/ +void +indicator_object_set_environment (IndicatorObject * io, GStrv env) +{ + /* FIXME: should this be a property? */ + g_return_if_fail(INDICATOR_IS_OBJECT(io)); + + if (io->priv->environments != NULL) { + g_strfreev(io->priv->environments); + io->priv->environments = NULL; + } + + io->priv->environments = g_strdupv(env); + + return; +} + +/** + indicator_object_get_environment: + @io: #IndicatorObject to get the environment from + + Gets the list of environment strings that this object is + placed into. + + Return value: (transfer none): Gets the list of strings that + represent the environment or NULL if none were given. +*/ +GStrv +indicator_object_get_environment (IndicatorObject * io) +{ + g_return_val_if_fail(INDICATOR_IS_OBJECT(io), NULL); + return io->priv->environments; +} + +/** + indicator_object_check_environment: + @io: #IndicatorObject to check on + @env: Environment that we're looking for + + Convience function to check to see if the specified environment + @env is in our list of environments. + + Return Value: Whether we're in environment @env +*/ +gboolean +indicator_object_check_environment (IndicatorObject * io, const gchar * env) +{ + g_return_val_if_fail(INDICATOR_IS_OBJECT(io), FALSE); + g_return_val_if_fail(env != NULL, FALSE); + + if (io->priv->environments == NULL) { + return FALSE; + } + + int i; + for (i = 0; io->priv->environments[i] != NULL; i++) { + if (g_strcmp0(env, io->priv->environments[i]) == 0) { + return TRUE; + } + } + + 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) +{ + g_return_if_fail(INDICATOR_IS_OBJECT(io)); + + GList * l; + GList * entries = get_all_entries (io); + const guint signal_id = signals[visible ? ENTRY_ADDED : ENTRY_REMOVED]; + EntryVisibility visibility = visible ? ENTRY_VISIBLE : ENTRY_INVISIBLE; + const GQuark detail = (GQuark)0; + + for (l=entries; l!=NULL; l=l->next) { + IndicatorObjectEntry *entry = l->data; + if (entry_get_private (io, entry)->visibility != visibility) + g_signal_emit(io, signal_id, detail, entry); + } + g_list_free (entries); +} + +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_instance_private(self); + g_return_if_fail(priv != NULL); + + switch (prop_id) { + /* *********************** */ + 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; + /* *********************** */ + 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_instance_private(self); + g_return_if_fail (priv != NULL); + + + switch (prop_id) { + + /* *********************** */ + 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; + } +} + +gboolean +indicator_object_entry_is_visible (IndicatorObject * io, IndicatorObjectEntry * entry) +{ + g_return_val_if_fail (INDICATOR_IS_OBJECT (io), FALSE); + + return entry_get_private (io, entry)->visibility == ENTRY_VISIBLE; +} + +gint +indicator_object_get_position (IndicatorObject *io) +{ + g_return_val_if_fail (INDICATOR_IS_OBJECT (io), FALSE); + + return INDICATOR_OBJECT_GET_CLASS (io)->get_position (io); +} diff --git a/src/indicator-object.h b/src/indicator-object.h new file mode 100644 index 0000000..e542c0d --- /dev/null +++ b/src/indicator-object.h @@ -0,0 +1,216 @@ +/* +An object to represent loadable indicator modules to make loading +them easy and objectified. + +Copyright 2009 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 __INDICATOR_OBJECT_H__ +#define __INDICATOR_OBJECT_H__ + +#include + +G_BEGIN_DECLS + +typedef enum +{ + INDICATOR_OBJECT_SCROLL_UP, + INDICATOR_OBJECT_SCROLL_DOWN, + INDICATOR_OBJECT_SCROLL_LEFT, + INDICATOR_OBJECT_SCROLL_RIGHT +} IndicatorScrollDirection; + +#define INDICATOR_OBJECT_TYPE (indicator_object_get_type ()) +#define INDICATOR_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_OBJECT_TYPE, IndicatorObject)) +#define INDICATOR_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INDICATOR_OBJECT_TYPE, IndicatorObjectClass)) +#define INDICATOR_IS_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_OBJECT_TYPE)) +#define INDICATOR_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INDICATOR_OBJECT_TYPE)) +#define INDICATOR_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), INDICATOR_OBJECT_TYPE, IndicatorObjectClass)) + +#define INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED "entry-added" +#define INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED_ID (g_signal_lookup(INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED, INDICATOR_OBJECT_TYPE)) +#define INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED "entry-removed" +#define INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED_ID (g_signal_lookup(INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED, INDICATOR_OBJECT_TYPE)) +#define INDICATOR_OBJECT_SIGNAL_ENTRY_MOVED "entry-moved" +#define INDICATOR_OBJECT_SIGNAL_ENTRY_MOVED_ID (g_signal_lookup(INDICATOR_OBJECT_SIGNAL_ENTRY_MOVED, INDICATOR_OBJECT_TYPE)) +#define INDICATOR_OBJECT_SIGNAL_ENTRY_SCROLLED "entry-scrolled" +#define INDICATOR_OBJECT_SIGNAL_ENTRY_SCROLLED_ID (g_signal_lookup(INDICATOR_OBJECT_SIGNAL_ENTRY_SCROLLED, INDICATOR_OBJECT_TYPE)) +#define INDICATOR_OBJECT_SIGNAL_MENU_SHOW "menu-show" +#define INDICATOR_OBJECT_SIGNAL_MENU_SHOW_ID (g_signal_lookup(INDICATOR_OBJECT_SIGNAL_MENU_SHOW, INDICATOR_OBJECT_TYPE)) +#define INDICATOR_OBJECT_SIGNAL_SHOW_NOW_CHANGED "show-now-changed" +#define INDICATOR_OBJECT_SIGNAL_SHOW_NOW_CHANGED_ID (g_signal_lookup(INDICATOR_OBJECT_SIGNAL_SHOW_NOW_CHANGED, INDICATOR_OBJECT_TYPE)) +#define INDICATOR_OBJECT_SIGNAL_ACCESSIBLE_DESC_UPDATE "accessible-desc-update" +#define INDICATOR_OBJECT_SIGNAL_ACCESSIBLE_DESC_UPDATE_ID (g_signal_lookup(INDICATOR_OBJECT_SIGNAL_ACCESSIBLE_DESC_UPDATE, INDICATOR_OBJECT_TYPE)) +#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 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; +typedef struct _IndicatorObjectPrivate IndicatorObjectPrivate; +typedef struct _IndicatorObjectEntry IndicatorObjectEntry; + +/** + IndicatorObjectClass: + @parent_class: #GObjectClass + @get_label: Gets the label for this object. Should be set + to #NULL if @get_entries is set. Should NOT ref the + object. + @get_image: Gets the image for this object. Should be set + to #NULL if @get_entries is set. Should NOT ref the + object. + @get_menu: Gets the image for this object. Should be set + to #NULL if @get_entries is set. Should NOT ref the + object. + @get_accessible_desc: Gets the accessible descriptionfor this + object. + @get_name_hint: Gets the hint of the type of indicator that this + is for the caller. + @get_entries: Gets all of the entires for this object returning + a #GList of #IndicatorObjectEntries. The list should be + under the ownership of the caller but the entires will + not be. + @get_location: Returns the location that a particular entry + should be placed in. This is really only relevant for + indicators that have more than one entry. + @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. + @entry_added: Slot for #IndicatorObject::entry-added + @entry_removed: Slot for #IndicatorObject::entry-removed + @entry_moved: Slot for #IndicatorObject::entry-moved + @menu_show: Slot for #IndicatorObject::menu-show + @entry_scrolled: Slot for #IndicatorObject::entry-scrolled + @show_now_changed: Slot for #IndicatorObject::show-now-changed + @accessible_desc_update: Slot for #IndicatorObject::accessible-desc-update + @secondary_activate: Slot for #IndicatorObject::secondary-activate + @get_position: returns the desired position on the panel (0 is right-most), or -1 +*/ +struct _IndicatorObjectClass { + GObjectClass parent_class; + + /* Virtual Functions */ + GtkLabel * (*get_label) (IndicatorObject * io); + GtkImage * (*get_image) (IndicatorObject * io); + GtkMenu * (*get_menu) (IndicatorObject * io); + const gchar * (*get_accessible_desc) (IndicatorObject * io); + const gchar * (*get_name_hint) (IndicatorObject * io); + + GList * (*get_entries) (IndicatorObject * io); + 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_activate_window) (IndicatorObject * io, IndicatorObjectEntry * entry, guint windowid, guint timestamp); + void (*entry_close) (IndicatorObject * io, IndicatorObjectEntry * entry, guint timestamp); + + /* Signals */ + void (*entry_added) (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer user_data); + void (*entry_removed) (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer user_data); + void (*entry_moved) (IndicatorObject * io, IndicatorObjectEntry * entry, guint old_pos, guint new_pos, gpointer user_data); + void (*entry_scrolled) (IndicatorObject * io, IndicatorObjectEntry * entry, gint delta, IndicatorScrollDirection direction); + void (*menu_show) (IndicatorObject * io, IndicatorObjectEntry * entry, guint timestamp, gpointer user_data); + void (*show_now_changed) (IndicatorObject * io, IndicatorObjectEntry * entry, gboolean show_now_state, gpointer user_data); + void (*accessible_desc_update) (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer user_data); + void (*secondary_activate) (IndicatorObject * io, IndicatorObjectEntry * entry, guint timestamp, gpointer user_data); + + gint (*get_position) (IndicatorObject *io); + guint (*get_parent_window) (IndicatorObject *io); + + /* Reserved */ + void (*reserved1) (void); + void (*reserved2) (void); + void (*reserved3) (void); +}; + +/** + IndicatorObject: + @parent: #GObject + @priv: A cached reference to the private data for the + instance. +*/ +struct _IndicatorObject { + GObject parent; + IndicatorObjectPrivate * priv; +}; + +/** + 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 + @accessible_desc: The accessible description + of the indicator + @name_hint: A name to describe the indicator being placed to allow + the caller to be more aware of the individual entries. + @parent_window: the id of the parent window of the indicator entry (if any). + + @reserved1: Reserved for future use + @reserved2: Reserved for future use + @reserved3: Reserved for future use +*/ +struct _IndicatorObjectEntry { + IndicatorObject * parent_object; + GtkLabel * label; + GtkImage * image; + GtkMenu * menu; + const gchar * accessible_desc; + const gchar * name_hint; + guint parent_window; + + void (*reserved1) (void); + void (*reserved2) (void); + void (*reserved3) (void); +}; + +GType indicator_object_get_type (void); +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); +gboolean indicator_object_entry_is_visible (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); +gint indicator_object_get_position (IndicatorObject *io); + +void indicator_object_set_environment (IndicatorObject * io, GStrv env); +GStrv indicator_object_get_environment (IndicatorObject * io); +gboolean indicator_object_check_environment (IndicatorObject * io, const gchar * env); + +G_END_DECLS + +#endif diff --git a/src/indicator-service-manager.c b/src/indicator-service-manager.c new file mode 100644 index 0000000..33bcba9 --- /dev/null +++ b/src/indicator-service-manager.c @@ -0,0 +1,704 @@ +/* +An object used to manage services. Either start them or +just connect to them. + +Copyright 2009 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 +. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "indicator-service-manager.h" +#include "gen-indicator-service.xml.h" +#include "dbus-shared.h" + +/* Private Stuff */ +/** + IndicatorServiceManagerPrivate: + @name: The well known dbus name the service should be on. + @service_proxy: The proxy to the service itself. + @connected: Whether we're connected to the service or not. + @this_service_version: The version of the service that we're looking for. + @restart_count: The number of times we've restarted this service. +*/ +typedef struct _IndicatorServiceManagerPrivate IndicatorServiceManagerPrivate; +struct _IndicatorServiceManagerPrivate { + gchar * name; + GDBusProxy * service_proxy; + GCancellable * service_proxy_cancel; + guint name_watcher; + gboolean connected; + guint this_service_version; + guint restart_count; + gint restart_source; + GCancellable * watch_cancel; +}; + +/* Signals Stuff */ +enum { + CONNECTION_CHANGE, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +/* If this env variable is set, we don't restart */ +#define TIMEOUT_ENV_NAME "INDICATOR_SERVICE_RESTART_DISABLE" +#define TIMEOUT_MULTIPLIER 100 /* In ms */ +/* What to reset the restart_count to if we know that we're + in a recoverable error condition, but waiting a little bit + will probably make things better. 5 ~= 3 sec. */ +#define TIMEOUT_A_LITTLE_WHILE 5 + +/* Properties */ +/* Enum for the properties so that they can be quickly + found and looked up. */ +enum { + PROP_0, + PROP_NAME, + PROP_VERSION +}; + +/* The strings so that they can be slowly looked up. */ +#define PROP_NAME_S "name" +#define PROP_VERSION_S "version" + +/* GDBus Stuff */ +static GDBusNodeInfo * node_info = NULL; +static GDBusInterfaceInfo * interface_info = NULL; + +static void indicator_service_manager_class_init (IndicatorServiceManagerClass *klass); +static void indicator_service_manager_init (IndicatorServiceManager *self); +static void indicator_service_manager_dispose (GObject *object); +static void indicator_service_manager_finalize (GObject *object); + +/* Prototypes */ +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 start_service (IndicatorServiceManager * service); +static void start_service_again (IndicatorServiceManager * manager); +static void unwatch (GDBusProxy * proxy); +static void service_proxy_cb (GObject * object, GAsyncResult * res, gpointer user_data); +static void service_proxy_name_changed (GDBusConnection * connection, const gchar * sender_name, const gchar * object_path, const gchar * interface_name, const gchar * signal_name, GVariant * parameters, gpointer user_data); + +G_DEFINE_TYPE_WITH_PRIVATE (IndicatorServiceManager, indicator_service_manager, G_TYPE_OBJECT); + +/* Build all of our signals and proxies and tie everything + all together. Lovely. */ +static void +indicator_service_manager_class_init (IndicatorServiceManagerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = indicator_service_manager_dispose; + object_class->finalize = indicator_service_manager_finalize; + + /* Property funcs */ + object_class->set_property = set_property; + object_class->get_property = get_property; + + /** + IndicatorServiceManager::connecton-change: + @arg0: The #IndicatorServiceManager object + @arg1: The state of the connection, TRUE is connected. + + Signaled when the service is connected or disconnected + depending on it's previous state. + */ + signals[CONNECTION_CHANGE] = g_signal_new (INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IndicatorServiceManagerClass, connection_change), + NULL, NULL, + g_cclosure_marshal_VOID__BOOLEAN, + G_TYPE_NONE, 1, G_TYPE_BOOLEAN, G_TYPE_NONE); + + /* Properties */ + g_object_class_install_property(object_class, PROP_NAME, + g_param_spec_string(PROP_NAME_S, + "The DBus name for the service to monitor", + "This is the name that should be used to start a service.", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property(object_class, PROP_VERSION, + g_param_spec_uint(PROP_VERSION_S, + "The version of the service that we're expecting.", + "A number to check and reject a service if it gives us the wrong number. This should match across the manager and the service", + 0, G_MAXUINT, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /* Setting up the DBus interfaces */ + if (node_info == NULL) { + GError * error = NULL; + + node_info = g_dbus_node_info_new_for_xml(_indicator_service, &error); + if (error != NULL) { + g_error("Unable to parse Indicator Service Interface description: %s", error->message); + g_error_free(error); + } + } + + if (interface_info == NULL) { + interface_info = g_dbus_node_info_lookup_interface(node_info, INDICATOR_SERVICE_INTERFACE); + + if (interface_info == NULL) { + g_error("Unable to find interface '" INDICATOR_SERVICE_INTERFACE "'"); + } + } + + return; +} + +/* This inits all the variable and sets up the proxy + to dbus. It doesn't look for the service as at this + point we don't know it's name. */ +static void +indicator_service_manager_init (IndicatorServiceManager *self) +{ + IndicatorServiceManagerPrivate * priv = indicator_service_manager_get_instance_private(self); + + /* Get the private variables in a decent state */ + priv->name = NULL; + priv->service_proxy = NULL; + priv->service_proxy_cancel = NULL; + priv->name_watcher = 0; + priv->connected = FALSE; + priv->this_service_version = 0; + priv->restart_count = 0; + priv->restart_source = 0; + priv->watch_cancel = NULL; + + return; +} + +/* If we're connected this provides all the signals to say + that we're about to not be. Then it takes down the proxies + and tells the service that we're not interested in being + its friend anymore either. */ +static void +indicator_service_manager_dispose (GObject *object) +{ + IndicatorServiceManager * sm = INDICATOR_SERVICE_MANAGER(object); + IndicatorServiceManagerPrivate * priv = indicator_service_manager_get_instance_private(sm); + + /* Removing the idle task to restart if it exists. */ + if (priv->restart_source != 0) { + g_source_remove(priv->restart_source); + } + /* Block any restart calls */ + priv->restart_source = -1; + + /* If we were connected we need to make sure to + tell people that it's no longer the case. */ + if (priv->connected) { + priv->connected = FALSE; + g_signal_emit(object, signals[CONNECTION_CHANGE], 0, FALSE, TRUE); + } + + if (priv->name_watcher != 0) { + g_dbus_connection_signal_unsubscribe(g_dbus_proxy_get_connection(priv->service_proxy), + priv->name_watcher); + priv->name_watcher = 0; + } + + /* If we're still getting the proxy, stop looking so we + can then clean up some more. */ + if (priv->service_proxy_cancel != NULL) { + g_cancellable_cancel(priv->service_proxy_cancel); + g_object_unref(priv->service_proxy_cancel); + priv->service_proxy_cancel = NULL; + } + + /* If we've sent a watch, cancel looking for the reply before + sending the unwatch */ + if (priv->watch_cancel != NULL) { + g_cancellable_cancel(priv->watch_cancel); + g_object_unref(priv->watch_cancel); + priv->watch_cancel = NULL; + } + + /* If we have a proxy, tell it we're shutting down. Just + to be polite about it. */ + if (priv->service_proxy != NULL) { + unwatch(priv->service_proxy); + } + + /* Destory our service proxy, we won't need it. */ + if (priv->service_proxy != NULL) { + g_object_unref(G_OBJECT(priv->service_proxy)); + priv->service_proxy = NULL; + } + + /* Let's see if our parents want to do anything. */ + G_OBJECT_CLASS (indicator_service_manager_parent_class)->dispose (object); + return; +} + +/* Ironically, we don't allocate a lot of memory ourselves. */ +static void +indicator_service_manager_finalize (GObject *object) +{ + IndicatorServiceManager * sm = INDICATOR_SERVICE_MANAGER(object); + IndicatorServiceManagerPrivate * priv = indicator_service_manager_get_instance_private(sm); + + if (priv->name != NULL) { + g_free(priv->name); + priv->name = NULL; + } + + G_OBJECT_CLASS (indicator_service_manager_parent_class)->finalize (object); + return; +} + +/* Either copies the name into the private variable or + sets the version. Do it wrong and it'll get upset. */ +static void +set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) +{ + IndicatorServiceManager * self = INDICATOR_SERVICE_MANAGER(object); + g_return_if_fail(self != NULL); + + IndicatorServiceManagerPrivate * priv = indicator_service_manager_get_instance_private(self); + g_return_if_fail(priv != NULL); + + switch (prop_id) { + /* *********************** */ + case PROP_NAME: + if (priv->name != NULL) { + g_error("Name can not be set twice!"); + } + priv->name = g_value_dup_string(value); + start_service(self); + break; + /* *********************** */ + case PROP_VERSION: + priv->this_service_version = g_value_get_uint(value); + break; + /* *********************** */ + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + return; +} + +/* Grabs the values from the private variables and + puts them into the value. */ +static void +get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) +{ + IndicatorServiceManager * self = INDICATOR_SERVICE_MANAGER(object); + g_return_if_fail(self != NULL); + + IndicatorServiceManagerPrivate * priv = indicator_service_manager_get_instance_private(self); + g_return_if_fail(priv != NULL); + + switch (prop_id) { + /* *********************** */ + case PROP_NAME: + g_value_set_string(value, priv->name); + break; + /* *********************** */ + case PROP_VERSION: + g_value_set_uint(value, priv->this_service_version); + break; + /* *********************** */ + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + return; +} + +/* Small little function to make a long function call a little + bit cleaner. */ +static void +unwatch (GDBusProxy * proxy) +{ + g_dbus_proxy_call(proxy, + "UnWatch", + NULL, /* parameters */ + G_DBUS_CALL_FLAGS_NONE, + -1, /* timeout */ + NULL, /* cancelable */ + NULL, /* callback */ + NULL); /* user data */ + return; +} + +/* A callback from telling a service that we want to watch + it. It gives us the service API version and the version + of the other APIs it supports. We check both of those. + If they don't match then we unwatch it. Otherwise, we + signal a connection change to tell the rest of the world + that we have a service now. */ +static void +watch_cb (GObject * object, GAsyncResult * res, gpointer user_data) +{ + GError * error = NULL; + IndicatorServiceManagerPrivate * priv = indicator_service_manager_get_instance_private(user_data); + + GVariant * params = g_dbus_proxy_call_finish(G_DBUS_PROXY(object), res, &error); + + if (error != NULL) { + g_warning("Unable to set watch on '%s': '%s'", priv->name, error->message); + g_error_free(error); + start_service_again(INDICATOR_SERVICE_MANAGER(user_data)); + return; + } + + guint service_api_version; + guint this_service_version; + + g_variant_get(params, "(uu)", &service_api_version, &this_service_version); + g_variant_unref(params); + + /* We've done it, now let's stop counting. */ + /* Note: we're not checking versions. Because, the hope is that + the guy holding the name we want with the wrong version will + drop and we can start another service quickly. */ + priv->restart_count = 0; + + if (service_api_version != INDICATOR_SERVICE_VERSION) { + g_warning("Service is using a different version of the service interface. Expecting %d and got %d.", INDICATOR_SERVICE_VERSION, service_api_version); + unwatch(priv->service_proxy); + + /* Let's make us wait a little while, then try again */ + priv->restart_count = TIMEOUT_A_LITTLE_WHILE; + start_service_again(INDICATOR_SERVICE_MANAGER(user_data)); + return; + } + + if (this_service_version != priv->this_service_version) { + g_warning("Service is using a different API version than the manager. Expecting %d and got %d.", priv->this_service_version, this_service_version); + unwatch(priv->service_proxy); + + /* Let's make us wait a little while, then try again */ + priv->restart_count = TIMEOUT_A_LITTLE_WHILE; + start_service_again(INDICATOR_SERVICE_MANAGER(user_data)); + return; + } + + if (!priv->connected) { + priv->connected = TRUE; + g_signal_emit(G_OBJECT(user_data), signals[CONNECTION_CHANGE], 0, TRUE, TRUE); + } + + return; +} + +/* The function that handles getting us connected to the service. + In many cases it will start the service, but if the service + is already there it just allocates the service proxy and acts + like it was no big deal. */ +static void +start_service (IndicatorServiceManager * service) +{ + IndicatorServiceManagerPrivate * priv = indicator_service_manager_get_instance_private(service); + + g_return_if_fail(priv->name != NULL); + + if (priv->service_proxy_cancel != NULL) { + /* A service proxy is being gotten currently */ + return; + } + + if (priv->service_proxy != NULL) { + g_object_unref(priv->service_proxy); + priv->service_proxy = NULL; + } + + priv->service_proxy_cancel = g_cancellable_new(); + + g_dbus_proxy_new_for_bus(G_BUS_TYPE_SESSION, + G_DBUS_PROXY_FLAGS_NONE, + interface_info, + priv->name, + INDICATOR_SERVICE_OBJECT, + INDICATOR_SERVICE_INTERFACE, + priv->service_proxy_cancel, + service_proxy_cb, + service); + + return; +} + +/* Callback from trying to create the proxy for the service, this + could include starting the service. Sometime it'll fail and + we'll try to start that dang service again! */ +static void +service_proxy_cb (__attribute__((unused)) GObject * object, GAsyncResult * res, gpointer user_data) +{ + GError * error = NULL; + + IndicatorServiceManager * service = INDICATOR_SERVICE_MANAGER(user_data); + g_return_if_fail(service != NULL); + + GDBusProxy * proxy = g_dbus_proxy_new_for_bus_finish(res, &error); + + IndicatorServiceManagerPrivate * priv = indicator_service_manager_get_instance_private(user_data); + + if (priv->service_proxy_cancel != NULL) { + g_object_unref(priv->service_proxy_cancel); + priv->service_proxy_cancel = NULL; + } + + if (error != NULL) { + /* Unable to create the proxy, eh, let's try again + in a bit */ + g_error_free(error); + start_service_again(service); + return; + } + + gchar * name = g_dbus_proxy_get_name_owner(proxy); + if (name == NULL) { + /* Hmm, since creating the proxy should start it, it seems very + odd that it wouldn't have an owner at this point. But, all + we can do is try again. */ + g_object_unref(proxy); + start_service_again(service); + return; + } + g_free(name); + + /* Okay, we're good to grab the proxy at this point, we're + sure that it's ours. */ + priv->service_proxy = proxy; + + /* Signal for drop */ + priv->name_watcher = g_dbus_connection_signal_subscribe( + g_dbus_proxy_get_connection(proxy), + "org.freedesktop.DBus", + "org.freedesktop.DBus", + "NameOwnerChanged", + "/org/freedesktop/DBus", + g_dbus_proxy_get_name(proxy), + G_DBUS_SIGNAL_FLAGS_NONE, + service_proxy_name_changed, + user_data, + NULL); + + /* Build cancelable if we need it */ + if (priv->watch_cancel == NULL) { + priv->watch_cancel = g_cancellable_new(); + } + + /* Send watch */ + g_dbus_proxy_call(priv->service_proxy, + "Watch", + NULL, /* params */ + G_DBUS_CALL_FLAGS_NONE, + -1, + priv->watch_cancel, + watch_cb, + user_data); + + return; +} + +/* Responds to the name owner changing of the proxy, this + usually means the service died. We're dropping the proxy + and recreating it so that it'll restart the service. */ +static void +service_proxy_name_changed (__attribute__((unused)) GDBusConnection * connection, + __attribute__((unused)) const gchar * sender_name, + __attribute__((unused)) const gchar * object_path, + __attribute__((unused)) const gchar * interface_name, + __attribute__((unused)) const gchar * signal_name, + GVariant * parameters, + gpointer user_data) + +{ + IndicatorServiceManagerPrivate * priv = indicator_service_manager_get_instance_private(user_data); + + const gchar * new_name = NULL; + const gchar * prev_name = NULL; + g_variant_get(parameters, "(&s&s&s)", NULL, &prev_name, &new_name); + + if (new_name == NULL || new_name[0] == 0) { + if (priv->connected) { + priv->connected = FALSE; + g_signal_emit(G_OBJECT(user_data), signals[CONNECTION_CHANGE], 0, FALSE, TRUE); + } + + start_service_again(INDICATOR_SERVICE_MANAGER(user_data)); + } else { + /* If we weren't connected before, we are now. Let's tell the + world! */ + if (!priv->connected) { + priv->connected = TRUE; + g_signal_emit(G_OBJECT(user_data), signals[CONNECTION_CHANGE], 0, TRUE, TRUE); + } + + /* If the names are both valid, and they're not the same, it means that + we've actually changed. So we need to tell the new guy that we're + watching them */ + if (new_name != NULL && prev_name != NULL && new_name[0] != 0 && prev_name != 0 && g_strcmp0(prev_name, new_name) != 0) { + /* Send watch */ + g_dbus_proxy_call(priv->service_proxy, + "Watch", + NULL, /* params */ + G_DBUS_CALL_FLAGS_NONE, + -1, + priv->watch_cancel, + watch_cb, + user_data); + } + } + + return; +} + +/* The callback that starts the service for real after + the timeout as determined in 'start_service_again'. + This could be in the idle or a timer. */ +static gboolean +start_service_again_cb (gpointer data) +{ + IndicatorServiceManagerPrivate * priv = indicator_service_manager_get_instance_private(data); + priv->restart_count++; + g_debug("Restarting service '%s' count %d", priv->name, priv->restart_count); + start_service(INDICATOR_SERVICE_MANAGER(data)); + priv->restart_source = 0; + return FALSE; +} + +/* This function tries to start a new service, perhaps + after a timeout that it determines. The real issue + here is that it throttles restarting if we're not + being successful. */ +static void +start_service_again (IndicatorServiceManager * manager) +{ + IndicatorServiceManagerPrivate * priv = indicator_service_manager_get_instance_private(manager); + + /* If we've already got a restart source running then + let's not do this again. */ + if (priv->restart_source != 0) { + return; + } + + /* Allow the restarting to be disabled */ + if (g_getenv(TIMEOUT_ENV_NAME)) { + return; + } + + if (priv->restart_count == 0) { + /* First time, do it in idle */ + g_idle_add(start_service_again_cb, manager); + } else { + /* Not our first time 'round the block. Let's slow this down. */ + if (priv->restart_count > 16) + priv->restart_count = 16; /* Not more than 1024x */ + priv->restart_source = g_timeout_add((1 << priv->restart_count) * TIMEOUT_MULTIPLIER, start_service_again_cb, manager); + } + + return; +} + +/* API */ + +/** + indicator_service_manager_new: + @dbus_name: The well known name of the service on DBus + + This creates a new service manager object. If the service + is not running it will start it. No matter what, it will + give a IndicatorServiceManager::connection-changed event + signal when it gets connected. + + Return value: A brand new lovely #IndicatorServiceManager + object. +*/ +IndicatorServiceManager * +indicator_service_manager_new (const gchar * dbus_name) +{ + GObject * obj = g_object_new(INDICATOR_SERVICE_MANAGER_TYPE, + PROP_NAME_S, dbus_name, + NULL); + + return INDICATOR_SERVICE_MANAGER(obj); +} + +/** + inicator_service_manager_new_version: + @dbus_name: The well known name of the service on DBus + @version: Version of the service we expect + + This creates a new service manager object. It also sets + the version of the service that we're expecting to see. + In general, it behaves similarly to #indicator_service_manager_new() + except that it checks @version against the version returned + by the service. + + Return value: A brand new lovely #IndicatorServiceManager + object. +*/ +IndicatorServiceManager * +indicator_service_manager_new_version (const gchar * dbus_name, guint version) +{ + GObject * obj = g_object_new(INDICATOR_SERVICE_MANAGER_TYPE, + PROP_NAME_S, dbus_name, + PROP_VERSION_S, version, + NULL); + + return INDICATOR_SERVICE_MANAGER(obj); +} + +/** + indicator_service_manager_connected: + @sm: #IndicatorServiceManager object to check + + Checks to see if the service manager is connected to a + service. + + Return value: #TRUE if there is a service connceted. +*/ +gboolean +indicator_service_manager_connected (IndicatorServiceManager * sm) +{ + g_return_val_if_fail(INDICATOR_IS_SERVICE_MANAGER(sm), FALSE); + IndicatorServiceManagerPrivate * priv = indicator_service_manager_get_instance_private(sm); + return priv->connected; +} + +/** + indicator_service_manager_set_refresh: + @sm: #IndicatorServiceManager object to configure + @time_in_ms: The refresh time in milliseconds + + Use this function to set the amount of time between restarting + services that may crash or shutdown. This is mostly useful + for testing and development. + + NOTE: Not yet implemented. +*/ +void +indicator_service_manager_set_refresh (__attribute__((unused)) IndicatorServiceManager * sm, __attribute__((unused)) guint time_in_ms) +{ + + return; +} diff --git a/src/indicator-service-manager.h b/src/indicator-service-manager.h new file mode 100644 index 0000000..7d444c6 --- /dev/null +++ b/src/indicator-service-manager.h @@ -0,0 +1,88 @@ +/* +An object used to manage services. Either start them or +just connect to them. + +Copyright 2009 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 __INDICATOR_SERVICE_MANAGER_H__ +#define __INDICATOR_SERVICE_MANAGER_H__ + +#include +#include + +G_BEGIN_DECLS + +#define INDICATOR_SERVICE_MANAGER_TYPE (indicator_service_manager_get_type ()) +#define INDICATOR_SERVICE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_SERVICE_MANAGER_TYPE, IndicatorServiceManager)) +#define INDICATOR_SERVICE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INDICATOR_SERVICE_MANAGER_TYPE, IndicatorServiceManagerClass)) +#define INDICATOR_IS_SERVICE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_SERVICE_MANAGER_TYPE)) +#define INDICATOR_IS_SERVICE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INDICATOR_SERVICE_MANAGER_TYPE)) +#define INDICATOR_SERVICE_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), INDICATOR_SERVICE_MANAGER_TYPE, IndicatorServiceManagerClass)) + +#define INDICATOR_SERVICE_MANAGER_SIGNAL_CONNECTION_CHANGE "connection-change" + +typedef struct _IndicatorServiceManager IndicatorServiceManager; +typedef struct _IndicatorServiceManagerClass IndicatorServiceManagerClass; + +/** + IndicatorServiceManagerClass: + @parent: #GObjectClass + @connection_changed: Slot for #IndicatorServiceManager::connection-changed. + @indicator_service_manager_reserved1: Reserved for future use. + @indicator_service_manager_reserved2: Reserved for future use. + @indicator_service_manager_reserved3: Reserved for future use. + @indicator_service_manager_reserved4: Reserved for future use. + +*/ +struct _IndicatorServiceManagerClass { + GObjectClass parent_class; + + /* Signals */ + void (*connection_change) (IndicatorServiceManager * sm, gboolean connected, gpointer user_data); + + /* Buffer */ + void (*indicator_service_manager_reserved1) (void); + void (*indicator_service_manager_reserved2) (void); + void (*indicator_service_manager_reserved3) (void); + void (*indicator_service_manager_reserved4) (void); +}; + +/** + IndicatorServiceManager: + @parent: #GObject + +*/ +struct _IndicatorServiceManager { + GObject parent; + +}; + +GType indicator_service_manager_get_type (void); + +IndicatorServiceManager * indicator_service_manager_new (const gchar * dbus_name); +IndicatorServiceManager * indicator_service_manager_new_version (const gchar * dbus_name, + guint version); +gboolean indicator_service_manager_connected (IndicatorServiceManager * sm); +void indicator_service_manager_set_refresh (IndicatorServiceManager * sm, + guint time_in_ms); + +G_END_DECLS + +#endif diff --git a/src/indicator-service.c b/src/indicator-service.c new file mode 100644 index 0000000..de3a0cf --- /dev/null +++ b/src/indicator-service.c @@ -0,0 +1,649 @@ +/* +An object used to provide a simple interface for a service +to query version and manage whether it's running. + +Copyright 2009 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 +. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include /* exit() */ + +#include + +#include "indicator-service.h" +#include "gen-indicator-service.xml.h" +#include "dbus-shared.h" + +static void unwatch_core (IndicatorService * service, const gchar * name); +static void watchers_remove (gpointer value); +static void bus_get_cb (GObject * object, GAsyncResult * res, gpointer user_data); +static GVariant * bus_watch (IndicatorService * service, const gchar * sender); + +/* Private Stuff */ +/** + IndicatorSevicePrivate: + @name: The DBus well known name for the service. + @timeout: The source ID for the timeout event. + @watcher: A list of processes on dbus that are watching us. + @this_service_version: The version to hand out that we're + implementing. May not be set, so we'll send zero (default). + @dbus_registration: The handle for this object being registered + on dbus. +*/ +typedef struct _IndicatorServicePrivate IndicatorServicePrivate; +struct _IndicatorServicePrivate { + gchar * name; + GDBusConnection * bus; + GCancellable * bus_cancel; + guint timeout; + guint timeout_length; + GHashTable * watchers; + guint this_service_version; + guint dbus_registration; + gboolean replace_mode; +}; + +/* Signals Stuff */ +enum { + SHUTDOWN, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +/* Properties */ +/* Enum for the properties so that they can be quickly + found and looked up. */ +enum { + PROP_0, + PROP_NAME, + PROP_VERSION +}; + +/* The strings so that they can be slowly looked up. */ +#define PROP_NAME_S "name" +#define PROP_VERSION_S "version" + +/* GObject Stuff */ +#define INDICATOR_SERVICE_GET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), INDICATOR_SERVICE_TYPE, IndicatorServicePrivate)) + +static void indicator_service_class_init (IndicatorServiceClass *klass); +static void indicator_service_init (IndicatorService *self); +static void indicator_service_dispose (GObject *object); +static void indicator_service_finalize (GObject *object); + +/* Other prototypes */ +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 try_and_get_name (IndicatorService * service); +static void bus_method_call (GDBusConnection * connection, const gchar * sender, const gchar * path, const gchar * interface, const gchar * method, GVariant * params, GDBusMethodInvocation * invocation, gpointer user_data); + +/* GDBus Stuff */ +static GDBusNodeInfo * node_info = NULL; +static GDBusInterfaceInfo * interface_info = NULL; +static GDBusInterfaceVTable interface_table = { + .method_call = bus_method_call, + .get_property = NULL, /* No properties */ + .set_property = NULL /* No properties */ +}; + +/* THE define */ +G_DEFINE_TYPE_WITH_PRIVATE (IndicatorService, indicator_service, G_TYPE_OBJECT); + +static void +indicator_service_class_init (IndicatorServiceClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = indicator_service_dispose; + object_class->finalize = indicator_service_finalize; + + /* Property funcs */ + object_class->set_property = set_property; + object_class->get_property = get_property; + + /* Properties */ + g_object_class_install_property(object_class, PROP_NAME, + g_param_spec_string(PROP_NAME_S, + "The DBus name for this service", + "This is the name that should be used on DBus for this service.", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property(object_class, PROP_VERSION, + g_param_spec_uint(PROP_VERSION_S, + "The version of the service that we're implementing.", + "A number to represent the version of the other APIs the service provides. This should match across the manager and the service", + 0, G_MAXUINT, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /* Signals */ + + /** + IndicatorService::shutdown: + @arg0: The #IndicatorService object + + Signaled when the service should shutdown as no one + is listening anymore. + */ + signals[SHUTDOWN] = g_signal_new (INDICATOR_SERVICE_SIGNAL_SHUTDOWN, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (IndicatorServiceClass, shutdown), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0, G_TYPE_NONE); + + /* Setting up the DBus interfaces */ + if (node_info == NULL) { + GError * error = NULL; + + node_info = g_dbus_node_info_new_for_xml(_indicator_service, &error); + if (error != NULL) { + g_error("Unable to parse Indicator Service Interface description: %s", error->message); + g_error_free(error); + } + } + + if (interface_info == NULL) { + interface_info = g_dbus_node_info_lookup_interface(node_info, INDICATOR_SERVICE_INTERFACE); + + if (interface_info == NULL) { + g_error("Unable to find interface '" INDICATOR_SERVICE_INTERFACE "'"); + } + } + + return; +} + +/* This function builds the variables, sets up the dbus + proxy and registers the object on dbus. Importantly, + it does not request a name as we don't know what name + we have yet. */ +static void +indicator_service_init (IndicatorService *self) +{ + IndicatorServicePrivate * priv = indicator_service_get_instance_private(self); + + /* Get the private variables in a decent state */ + priv->name = NULL; + priv->timeout = 0; + priv->watchers = NULL; + priv->bus = NULL; + priv->bus_cancel = NULL; + priv->this_service_version = 0; + priv->timeout_length = 500; + priv->dbus_registration = 0; + priv->replace_mode = FALSE; + + const gchar * timeoutenv = g_getenv("INDICATOR_SERVICE_SHUTDOWN_TIMEOUT"); + if (timeoutenv != NULL) { + gdouble newtimeout = g_strtod(timeoutenv, NULL); + if (newtimeout >= 1.0f) { + priv->timeout_length = newtimeout; + g_debug("Setting shutdown timeout to: %u", priv->timeout_length); + } + } + + const gchar * replaceenv = g_getenv("INDICATOR_SERVICE_REPLACE_MODE"); + if (replaceenv != NULL) { + priv->replace_mode = TRUE; + g_debug("Putting into replace mode"); + } + + /* NOTE: We're using g_free here because that's what needs to + happen and we're watchers_remove as well to clean up the dbus + watches we've setup. */ + priv->watchers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, watchers_remove); + + priv->bus_cancel = g_cancellable_new(); + g_bus_get(G_BUS_TYPE_SESSION, + priv->bus_cancel, + bus_get_cb, + self); + + return; +} + +/* Unrefcounting the proxies and making sure that our + timeout doesn't come to haunt us. */ +static void +indicator_service_dispose (GObject *object) +{ + IndicatorService * service = INDICATOR_SERVICE(object); + IndicatorServicePrivate * priv = indicator_service_get_instance_private(service); + + g_clear_pointer (&priv->watchers, g_hash_table_destroy); + + if (priv->timeout != 0) { + g_source_remove(priv->timeout); + priv->timeout = 0; + } + + if (priv->dbus_registration != 0) { + g_dbus_connection_unregister_object(priv->bus, priv->dbus_registration); + /* Don't care if it fails, there's nothing we can do */ + priv->dbus_registration = 0; + } + + g_clear_object (&priv->bus); + + if (priv->bus_cancel != NULL) { + g_cancellable_cancel(priv->bus_cancel); + g_object_unref(priv->bus_cancel); + priv->bus_cancel = NULL; + } + + G_OBJECT_CLASS (indicator_service_parent_class)->dispose (object); + return; +} + +/* Freeing the name we're looking for and all of the + information on the watchers we're tracking. */ +static void +indicator_service_finalize (GObject *object) +{ + IndicatorService * service = INDICATOR_SERVICE(object); + IndicatorServicePrivate * priv = indicator_service_get_instance_private(service); + + g_free (priv->name); + g_clear_pointer (&priv->watchers, g_hash_table_destroy); + + G_OBJECT_CLASS (indicator_service_parent_class)->finalize (object); + return; +} + +/* Either copies a string for the name or it just grabs + the value of the version. */ +static void +set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) +{ + IndicatorService * self = INDICATOR_SERVICE(object); + g_return_if_fail(self != NULL); + + IndicatorServicePrivate * priv = indicator_service_get_instance_private(self); + g_return_if_fail(priv != NULL); + + switch (prop_id) { + /* *********************** */ + case PROP_NAME: + if (G_VALUE_HOLDS_STRING(value)) { + if (priv->name != NULL) { + g_error("Name can not be set twice!"); + } + priv->name = g_value_dup_string(value); + try_and_get_name(self); + } else { + g_warning("Name property requires a string value."); + } + break; + /* *********************** */ + case PROP_VERSION: + priv->this_service_version = g_value_get_uint(value); + break; + /* *********************** */ + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + return; +} + +/* Copies out the name into a value or the version number. + Probably this is the least useful code in this file. */ +static void +get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) +{ + IndicatorService * self = INDICATOR_SERVICE(object); + g_return_if_fail(self != NULL); + + IndicatorServicePrivate * priv = indicator_service_get_instance_private(self); + g_return_if_fail(priv != NULL); + + switch (prop_id) { + /* *********************** */ + case PROP_NAME: + if (G_VALUE_HOLDS_STRING(value)) { + g_value_set_string(value, priv->name); + } else { + g_warning("Name property requires a string value."); + } + break; + /* *********************** */ + case PROP_VERSION: + g_value_set_uint(value, priv->this_service_version); + break; + /* *********************** */ + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } + + return; +} + +/* Callback for getting our connection to DBus */ +static void +bus_get_cb (__attribute__((unused)) GObject * object, GAsyncResult * res, gpointer user_data) +{ + GError * error = NULL; + GDBusConnection * connection = g_bus_get_finish(res, &error); + + if (error != NULL) { + g_warning("Unable to get a connection to the session DBus: %s", error->message); + g_error_free(error); + exit (0); + } + + IndicatorServicePrivate * priv = indicator_service_get_instance_private(user_data); + + g_warn_if_fail(priv->bus == NULL); + priv->bus = connection; + + if (priv->bus_cancel != NULL) { + g_object_unref(priv->bus_cancel); + priv->bus_cancel = NULL; + } + + /* Now register our object on our new connection */ + priv->dbus_registration = g_dbus_connection_register_object(priv->bus, + INDICATOR_SERVICE_OBJECT, + interface_info, + &interface_table, + user_data, + NULL, + &error); + if (error != NULL) { + g_error("Unable to register the object to DBus: %s", error->message); + } + + return; +} + +/* A method has been called from our dbus inteface. Figure out what it + is and dispatch it. */ +static void +bus_method_call (__attribute__((unused)) GDBusConnection * connection, const gchar * sender, __attribute__((unused)) const gchar * path, __attribute__((unused)) const gchar * interface, const gchar * method, __attribute__((unused)) GVariant * params, GDBusMethodInvocation * invocation, gpointer user_data) +{ + IndicatorService * service = INDICATOR_SERVICE(user_data); + GVariant * retval = NULL; + + if (g_strcmp0(method, "Watch") == 0) { + retval = bus_watch(service, sender); + } else if (g_strcmp0(method, "UnWatch") == 0) { + unwatch_core(service, sender); + } else if (g_strcmp0(method, "Shutdown") == 0) { + g_signal_emit(G_OBJECT(service), signals[SHUTDOWN], 0, TRUE); + } else { + g_warning("Calling method '%s' on the indicator service and it's unknown", method); + } + + g_dbus_method_invocation_return_value(invocation, retval); + return; +} + +/* A function to remove the signals on a proxy before we destroy + it because in this case we've stopped caring. */ +static void +watchers_remove (gpointer value) +{ + g_bus_unwatch_name(GPOINTER_TO_UINT(value)); + return; +} + +/* This is the function that gets executed if we timeout + because there are no watchers. We sent the shutdown + signal and hope someone does something sane with it. */ +static gboolean +timeout_no_watchers (gpointer data) +{ + g_warning("No watchers, service timing out."); + if (g_getenv("INDICATOR_ALLOW_NO_WATCHERS") == NULL) { + g_signal_emit(G_OBJECT(data), signals[SHUTDOWN], 0, TRUE); + } else { + g_warning("\tblocked by environment variable."); + } + return FALSE; +} + +/* Callback saying that the name we were looking for has been + found and we've got it. Now start the timer to see if anyone + cares about us. */ +static void +try_and_get_name_acquired_cb (GDBusConnection * connection, __attribute__((unused)) const gchar * name, gpointer user_data) +{ + g_return_if_fail(connection != NULL); + g_return_if_fail(INDICATOR_IS_SERVICE(user_data)); + + IndicatorServicePrivate * priv = indicator_service_get_instance_private(user_data); + + /* Check to see if we already had a timer, if so we want to + extend it a bit. */ + if (priv->timeout != 0) { + g_source_remove(priv->timeout); + priv->timeout = 0; + } + + /* Allow some extra time at start up as things can be in high + contention then. */ + priv->timeout = g_timeout_add(priv->timeout_length * 2, timeout_no_watchers, user_data); + + return; +} + +/* Callback saying that we didn't get the name, so we need to + shutdown this service. */ +static void +try_and_get_name_lost_cb (GDBusConnection * connection, const gchar * name, gpointer user_data) +{ + g_return_if_fail(connection != NULL); + g_return_if_fail(INDICATOR_IS_SERVICE(user_data)); + + IndicatorServicePrivate * priv = indicator_service_get_instance_private(user_data); + + if (!priv->replace_mode) { + g_warning("Name request failed."); + g_signal_emit(G_OBJECT(user_data), signals[SHUTDOWN], 0, TRUE); + } else { + /* If we're in replace mode we can be a little more trickey + here. We're going to tell the other guy to shutdown and hope + that we get the name. */ + GDBusMessage * message = NULL; + message = g_dbus_message_new_method_call(name, + INDICATOR_SERVICE_OBJECT, + INDICATOR_SERVICE_INTERFACE, + "Shutdown"); + + g_dbus_connection_send_message(connection, message, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL); + g_object_unref(message); + + /* Check to see if we need to clean up a timeout */ + if (priv->timeout != 0) { + g_source_remove(priv->timeout); + priv->timeout = 0; + } + + /* Set a timeout for no watchers if we can't get the name */ + priv->timeout = g_timeout_add(priv->timeout_length * 4, timeout_no_watchers, user_data); + } + + return; +} + +/* This function sets up the request for the name on dbus. */ +static void +try_and_get_name (IndicatorService * service) +{ + IndicatorServicePrivate * priv = indicator_service_get_instance_private(service); + g_return_if_fail(priv->name != NULL); + + g_bus_own_name(G_BUS_TYPE_SESSION, + priv->name, + G_BUS_NAME_OWNER_FLAGS_NONE, + NULL, /* bus acquired */ + try_and_get_name_acquired_cb, /* name acquired */ + try_and_get_name_lost_cb, /* name lost */ + service, + NULL); /* user data destroy */ + + return; +} + +/* When the watcher vanishes we don't really care about it + anymore. */ +static void +watcher_vanished_cb (__attribute__((unused)) GDBusConnection * connection, const gchar * name, gpointer user_data) +{ + g_return_if_fail(INDICATOR_IS_SERVICE(user_data)); + IndicatorServicePrivate * priv = indicator_service_get_instance_private(user_data); + + gpointer finddata = g_hash_table_lookup(priv->watchers, name); + if (finddata != NULL) { + unwatch_core(INDICATOR_SERVICE(user_data), name); + } else { + g_warning("Odd, we were watching for '%s' and it disappeard, but then it wasn't in the hashtable.", name); + } + + return; +} + +/* Here is the function that gets called by the dbus + interface "Watch" function. It is an async function so + that we can get the sender and store that information. We + put them in a list and reset the timeout. */ +static GVariant * +bus_watch (IndicatorService * service, const gchar * sender) +{ + g_return_val_if_fail(INDICATOR_IS_SERVICE(service), NULL); + IndicatorServicePrivate * priv = indicator_service_get_instance_private(service); + + if (GPOINTER_TO_UINT(g_hash_table_lookup(priv->watchers, sender)) == 0) { + guint watch = g_bus_watch_name_on_connection(priv->bus, + sender, + G_BUS_NAME_WATCHER_FLAGS_NONE, + NULL, /* appeared, we dont' care, should have already happened. */ + watcher_vanished_cb, + service, + NULL); + + if (watch != 0) { + g_hash_table_insert(priv->watchers, g_strdup(sender), GUINT_TO_POINTER(watch)); + } else { + g_warning("Unable watch for '%s'", sender); + } + } + + if (priv->timeout != 0) { + g_source_remove(priv->timeout); + priv->timeout = 0; + } + + return g_variant_new("(uu)", INDICATOR_SERVICE_VERSION, priv->this_service_version); +} + +/* Performs the core of loosing a watcher; it removes them + from the list of watchers. If there are none left, it then + starts the timer for the shutdown signal. */ +static void +unwatch_core (IndicatorService * service, const gchar * name) +{ + g_return_if_fail(name != NULL); + g_return_if_fail(INDICATOR_IS_SERVICE(service)); + + IndicatorServicePrivate * priv = indicator_service_get_instance_private(service); + + /* Remove us from the watcher list here */ + gpointer watcher_item = g_hash_table_lookup(priv->watchers, name); + if (watcher_item != NULL) { + gchar * safe_name = g_strdup(name); + g_hash_table_remove(priv->watchers, safe_name); + g_free(safe_name); + } else { + /* Odd that we couldn't find the person, but, eh */ + g_warning("Unable to find watcher who is unwatching: %s", name); + } + + /* If we're out of watchers set the timeout for shutdown */ + if (g_hash_table_size(priv->watchers) == 0) { + if (priv->timeout != 0) { + /* This should never really happen, but let's ensure that + bad things don't happen if it does. */ + g_warning("No watchers timeout set twice. Resolving, but odd."); + g_source_remove(priv->timeout); + priv->timeout = 0; + } + /* If we don't get a new watcher quickly, we'll shutdown. */ + priv->timeout = g_timeout_add(priv->timeout_length, timeout_no_watchers, service); + } + + return; +} + +/* API */ + +/** + indicator_service_new: + @name: The name for the service on dbus + + This function creates the service on DBus and tries to + get a well-known name specified in @name. If the name + can't be estabilished then the #IndicatorService::shutdown + signal will be sent. + + Return value: A brand new #IndicatorService object or #NULL + if there is an error. +*/ +IndicatorService * +indicator_service_new (gchar * name) +{ + GObject * obj = g_object_new(INDICATOR_SERVICE_TYPE, + PROP_NAME_S, name, + NULL); + + return INDICATOR_SERVICE(obj); +} + +/** + indicator_service_new_version: + @name: The name for the service on dbus + @version: The version of the other interfaces provide + by the service. + + This function creates the service on DBus and tries to + get a well-known name specified in @name. If the name + can't be estabilished then the #IndicatorService::shutdown + signal will be sent. + + Return value: A brand new #IndicatorService object or #NULL + if there is an error. +*/ +IndicatorService * +indicator_service_new_version (gchar * name, guint version) +{ + GObject * obj = g_object_new(INDICATOR_SERVICE_TYPE, + PROP_NAME_S, name, + PROP_VERSION_S, version, + NULL); + + return INDICATOR_SERVICE(obj); +} diff --git a/src/indicator-service.h b/src/indicator-service.h new file mode 100644 index 0000000..bda9cb7 --- /dev/null +++ b/src/indicator-service.h @@ -0,0 +1,85 @@ +/* +An object used to provide a simple interface for a service +to query version and manage whether it's running. + +Copyright 2009 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 __INDICATOR_SERVICE_H__ +#define __INDICATOR_SERVICE_H__ + +#include +#include + +G_BEGIN_DECLS + +#define INDICATOR_SERVICE_TYPE (indicator_service_get_type ()) +#define INDICATOR_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), INDICATOR_SERVICE_TYPE, IndicatorService)) +#define INDICATOR_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), INDICATOR_SERVICE_TYPE, IndicatorServiceClass)) +#define INDICATOR_IS_SERVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), INDICATOR_SERVICE_TYPE)) +#define INDICATOR_IS_SERVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), INDICATOR_SERVICE_TYPE)) +#define INDICATOR_SERVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), INDICATOR_SERVICE_TYPE, IndicatorServiceClass)) + +#define INDICATOR_SERVICE_SIGNAL_SHUTDOWN "shutdown" + +typedef struct _IndicatorService IndicatorService; +typedef struct _IndicatorServiceClass IndicatorServiceClass; + +/** + IndicatorServiceClass: + @parent_class: #GObjectClass + @shutdown: Slot for IndicatorServiceClass::shutdown + @indicator_service_reserved1: Reserved for future use + @indicator_service_reserved2: Reserved for future use + @indicator_service_reserved3: Reserved for future use + @indicator_service_reserved4: Reserved for future use + +*/ +struct _IndicatorServiceClass { + GObjectClass parent_class; + + /* Signals */ + void (*shutdown) (IndicatorService * service, gpointer user_data); + + /* Reserved */ + void (*indicator_service_reserved1) (void); + void (*indicator_service_reserved2) (void); + void (*indicator_service_reserved3) (void); + void (*indicator_service_reserved4) (void); +}; + +/** + IndicatorService: + @parent: #GObject + +*/ +struct _IndicatorService { + GObject parent; + +}; + +GType indicator_service_get_type (void); + +IndicatorService * indicator_service_new (gchar * name); +IndicatorService * indicator_service_new_version (gchar * name, + guint version); + +G_END_DECLS + +#endif diff --git a/src/indicator-service.xml b/src/indicator-service.xml new file mode 100644 index 0000000..71ef4df --- /dev/null +++ b/src/indicator-service.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/indicator.h b/src/indicator.h new file mode 100644 index 0000000..8bff270 --- /dev/null +++ b/src/indicator.h @@ -0,0 +1,41 @@ +/* +An interface for indicators to link to for creation. + +Copyright 2009 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 __LIBINDICATOR_INDICATOR_H_SEEN__ +#define __LIBINDICATOR_INDICATOR_H_SEEN__ 1 + +#include + +#define INDICATOR_GET_VERSION_S "get_version" +typedef gchar * (*get_version_t) (void); +gchar * get_version (void); + +#define INDICATOR_VERSION "0.3.0" +#define INDICATOR_SET_VERSION gchar * get_version(void) { return INDICATOR_VERSION; } +#define INDICATOR_VERSION_CHECK(x) (!g_strcmp0(x, INDICATOR_VERSION)) + +#define INDICATOR_GET_TYPE_S "get_type" +typedef GType (*get_type_t) (void); +#define INDICATOR_SET_TYPE(x) GType get_type (void) { return x; } + +#endif /* __LIBINDICATOR_INDICATOR_H_SEEN__ */ + diff --git a/tests/Makefile.am b/tests/Makefile.am index 100eb16..476de28 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -9,7 +9,7 @@ TESTS = DISTCLEANFILES = XFAIL_TESTS = -check_PROGRAMS = +check_PROGRAMS = lib_LTLIBRARIES = \ libdummy-indicator-blank.la \ @@ -46,7 +46,7 @@ test_loader_CFLAGS = \ test_loader_LDADD = \ $(LIBINDICATOR_LIBS) \ - -L$(top_builddir)/libayatana-indicator/.libs \ + -L$(top_builddir)/src/.libs \ $(INDICATOR_LIB) ############################# @@ -66,7 +66,7 @@ test_desktop_shortcuts_CFLAGS = \ test_desktop_shortcuts_LDADD = \ $(LIBINDICATOR_LIBS) \ - -L$(top_builddir)/libayatana-indicator/.libs \ + -L$(top_builddir)/src/.libs \ $(INDICATOR_LIB) DS_XML_REPORT = desktop-shortcuts-check-results.xml @@ -99,7 +99,7 @@ libdummy_indicator_blank_la_CFLAGS = \ libdummy_indicator_blank_la_LIBADD = \ $(LIBINDICATOR_LIBS) \ - -L$(top_builddir)/libayatana-indicator/.libs \ + -L$(top_builddir)/src/.libs \ $(INDICATOR_LIB) libdummy_indicator_blank_la_LDFLAGS = \ @@ -120,7 +120,7 @@ libdummy_indicator_null_la_CFLAGS = \ libdummy_indicator_null_la_LIBADD = \ $(LIBINDICATOR_LIBS) \ - -L$(top_builddir)/libayatana-indicator/.libs \ + -L$(top_builddir)/src/.libs \ $(INDICATOR_LIB) libdummy_indicator_null_la_LDFLAGS = \ @@ -141,7 +141,7 @@ libdummy_indicator_signaler_la_CFLAGS = \ libdummy_indicator_signaler_la_LIBADD = \ $(LIBINDICATOR_LIBS) \ - -L$(top_builddir)/libayatana-indicator/.libs \ + -L$(top_builddir)/src/.libs \ $(INDICATOR_LIB) libdummy_indicator_signaler_la_LDFLAGS = \ @@ -162,7 +162,7 @@ libdummy_indicator_simple_la_CFLAGS = \ libdummy_indicator_simple_la_LIBADD = \ $(LIBINDICATOR_LIBS) \ - -L$(top_builddir)/libayatana-indicator/.libs \ + -L$(top_builddir)/src/.libs \ $(INDICATOR_LIB) libdummy_indicator_simple_la_LDFLAGS = \ @@ -184,7 +184,7 @@ libdummy_indicator_entry_func_la_CFLAGS = \ libdummy_indicator_entry_func_la_LIBADD = \ $(LIBINDICATOR_LIBS) \ - -L$(top_builddir)/libayatana-indicator/.libs \ + -L$(top_builddir)/src/.libs \ $(INDICATOR_LIB) libdummy_indicator_entry_func_la_LDFLAGS = \ @@ -205,7 +205,7 @@ libdummy_indicator_visible_la_CFLAGS = \ libdummy_indicator_visible_la_LIBADD = \ $(LIBINDICATOR_LIBS) \ - -L$(top_builddir)/libayatana-indicator/.libs \ + -L$(top_builddir)/src/.libs \ $(INDICATOR_LIB) libdummy_indicator_visible_la_LDFLAGS = \ @@ -227,7 +227,7 @@ service_shutdown_timeout_CFLAGS = \ service_shutdown_timeout_LDADD = \ $(LIBINDICATOR_LIBS) \ - -L$(top_builddir)/libayatana-indicator/.libs \ + -L$(top_builddir)/src/.libs \ $(INDICATOR_LIB) service-shutdown-timeout-tester: service-shutdown-timeout Makefile @@ -253,7 +253,7 @@ service_manager_no_connect_CFLAGS = \ service_manager_no_connect_LDADD = \ $(LIBINDICATOR_LIBS) \ - -L$(top_builddir)/libayatana-indicator/.libs \ + -L$(top_builddir)/src/.libs \ $(INDICATOR_LIB) service-manager-no-connect-tester: service-manager-no-connect Makefile.am @@ -285,7 +285,7 @@ service_manager_connect_CFLAGS = \ service_manager_connect_LDADD = \ $(LIBINDICATOR_LIBS) \ - -L$(top_builddir)/libayatana-indicator/.libs \ + -L$(top_builddir)/src/.libs \ $(INDICATOR_LIB) check_PROGRAMS += service-manager-connect-service @@ -299,7 +299,7 @@ service_manager_connect_service_CFLAGS = \ service_manager_connect_service_LDADD = \ $(LIBINDICATOR_LIBS) \ - -L$(top_builddir)/libayatana-indicator/.libs \ + -L$(top_builddir)/src/.libs \ $(INDICATOR_LIB) service-manager-connect-tester: service-manager-connect service-manager-connect-service session.conf service-manager-connect.service Makefile.am @@ -332,7 +332,7 @@ service_version_manager_CFLAGS = \ service_version_manager_LDADD = \ $(LIBINDICATOR_LIBS) \ - -L$(top_builddir)/libayatana-indicator/.libs \ + -L$(top_builddir)/src/.libs \ $(INDICATOR_LIB) check_PROGRAMS += service-version-bad-service @@ -347,7 +347,7 @@ service_version_bad_service_CFLAGS = \ service_version_bad_service_LDADD = \ $(LIBINDICATOR_LIBS) \ - -L$(top_builddir)/libayatana-indicator/.libs \ + -L$(top_builddir)/src/.libs \ $(INDICATOR_LIB) check_PROGRAMS += service-version-good-service @@ -362,7 +362,7 @@ service_version_good_service_CFLAGS = \ service_version_good_service_LDADD = \ $(LIBINDICATOR_LIBS) \ - -L$(top_builddir)/libayatana-indicator/.libs \ + -L$(top_builddir)/src/.libs \ $(INDICATOR_LIB) service-version-tester: service-version-manager service-version-bad-service service-version-good-service session.conf service-version-bad.service service-version-good.service Makefile.am @@ -389,7 +389,7 @@ service_version_multiwatch_manager_CFLAGS = \ service_version_multiwatch_manager_LDADD = \ $(LIBINDICATOR_LIBS) \ - -L$(top_builddir)/libayatana-indicator/.libs \ + -L$(top_builddir)/src/.libs \ $(INDICATOR_LIB) check_PROGRAMS += service-version-multiwatch-manager-impolite @@ -404,7 +404,7 @@ service_version_multiwatch_manager_impolite_CFLAGS = \ service_version_multiwatch_manager_impolite_LDADD = \ $(LIBINDICATOR_LIBS) \ - -L$(top_builddir)/libayatana-indicator/.libs \ + -L$(top_builddir)/src/.libs \ $(INDICATOR_LIB) check_PROGRAMS += service-version-multiwatch-service @@ -419,7 +419,7 @@ service_version_multiwatch_service_CFLAGS = \ service_version_multiwatch_service_LDADD = \ $(LIBINDICATOR_LIBS) \ - -L$(top_builddir)/libayatana-indicator/.libs \ + -L$(top_builddir)/src/.libs \ $(INDICATOR_LIB) service-version-multiwatch-tester: service-version-multiwatch-manager service-version-multiwatch-service service-version-multiwatch-manager-impolite Makefile.am @@ -445,7 +445,7 @@ service_manager_nostart_connect_CFLAGS = \ service_manager_nostart_connect_LDADD = \ $(LIBINDICATOR_LIBS) \ - -L$(top_builddir)/libayatana-indicator/.libs \ + -L$(top_builddir)/src/.libs \ $(INDICATOR_LIB) service-manager-connect-nostart-tester: service-manager-nostart-connect service-manager-connect-service Makefile.am @@ -496,7 +496,7 @@ test_indicator_ng_CFLAGS = \ test_indicator_ng_LDADD = \ $(LIBINDICATOR_LIBS) \ - -L$(top_builddir)/libayatana-indicator/.libs \ + -L$(top_builddir)/src/.libs \ $(INDICATOR_LIB) diff --git a/tests/dummy-indicator-blank.c b/tests/dummy-indicator-blank.c index dcbb99f..b085c52 100644 --- a/tests/dummy-indicator-blank.c +++ b/tests/dummy-indicator-blank.c @@ -21,7 +21,7 @@ License along with this library. If not, see */ -#include "libayatana-indicator/indicator.h" +#include "src/indicator.h" INDICATOR_SET_VERSION diff --git a/tests/dummy-indicator-entry-func.h b/tests/dummy-indicator-entry-func.h index c1fa8d3..b5653c7 100644 --- a/tests/dummy-indicator-entry-func.h +++ b/tests/dummy-indicator-entry-func.h @@ -26,8 +26,8 @@ License along with this library. If not, see #include #include -#include "libayatana-indicator/indicator.h" -#include "libayatana-indicator/indicator-object.h" +#include "src/indicator.h" +#include "src/indicator-object.h" G_BEGIN_DECLS @@ -42,15 +42,15 @@ typedef struct _DummyIndicatorEntryFunc DummyIndicatorEntryFunc; typedef struct _DummyIndicatorEntryFuncClass DummyIndicatorEntryFuncClass; struct _DummyIndicatorEntryFuncClass { - IndicatorObjectClass parent_class; + IndicatorObjectClass parent_class; }; struct _DummyIndicatorEntryFunc { - IndicatorObject parent; + IndicatorObject parent; - gboolean entry_activate_called; - gboolean entry_activate_window_called; - gboolean entry_close_called; + gboolean entry_activate_called; + gboolean entry_activate_window_called; + gboolean entry_close_called; }; #endif /* __DUMMY_INDICATOR_ENTRY_FUNC__ */ diff --git a/tests/dummy-indicator-null.c b/tests/dummy-indicator-null.c index 5eb8716..ee424d4 100644 --- a/tests/dummy-indicator-null.c +++ b/tests/dummy-indicator-null.c @@ -24,8 +24,8 @@ License along with this library. If not, see #include #include -#include "libayatana-indicator/indicator.h" -#include "libayatana-indicator/indicator-object.h" +#include "src/indicator.h" +#include "src/indicator-object.h" #define DUMMY_INDICATOR_NULL_TYPE (dummy_indicator_null_get_type ()) #define DUMMY_INDICATOR_NULL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DUMMY_INDICATOR_NULL_TYPE, DummyIndicatorNull)) @@ -38,11 +38,11 @@ typedef struct _DummyIndicatorNull DummyIndicatorNull; typedef struct _DummyIndicatorNullClass DummyIndicatorNullClass; struct _DummyIndicatorNullClass { - IndicatorObjectClass parent_class; + IndicatorObjectClass parent_class; }; struct _DummyIndicatorNull { - IndicatorObject parent; + IndicatorObject parent; }; GType dummy_indicator_null_get_type (void); @@ -54,24 +54,24 @@ INDICATOR_SET_TYPE(DUMMY_INDICATOR_NULL_TYPE) GtkLabel * get_label (IndicatorObject * io) { - return NULL; + return NULL; } GtkImage * get_icon (IndicatorObject * io) { - return NULL; + return NULL; } GtkMenu * get_menu (IndicatorObject * io) { - return NULL; + return NULL; } const gchar * get_accessible_desc (IndicatorObject * io) { - return NULL; + return NULL; } static void dummy_indicator_null_class_init (DummyIndicatorNullClass *klass); @@ -84,40 +84,40 @@ G_DEFINE_TYPE (DummyIndicatorNull, dummy_indicator_null, INDICATOR_OBJECT_TYPE); static void dummy_indicator_null_class_init (DummyIndicatorNullClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); - object_class->dispose = dummy_indicator_null_dispose; - object_class->finalize = dummy_indicator_null_finalize; + object_class->dispose = dummy_indicator_null_dispose; + object_class->finalize = dummy_indicator_null_finalize; - IndicatorObjectClass * io_class = INDICATOR_OBJECT_CLASS(klass); + 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->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; + return; } static void dummy_indicator_null_init (DummyIndicatorNull *self) { - return; + return; } static void dummy_indicator_null_dispose (GObject *object) { - G_OBJECT_CLASS (dummy_indicator_null_parent_class)->dispose (object); - return; + G_OBJECT_CLASS (dummy_indicator_null_parent_class)->dispose (object); + return; } static void dummy_indicator_null_finalize (GObject *object) { - G_OBJECT_CLASS (dummy_indicator_null_parent_class)->finalize (object); - return; + G_OBJECT_CLASS (dummy_indicator_null_parent_class)->finalize (object); + return; } diff --git a/tests/dummy-indicator-signaler.c b/tests/dummy-indicator-signaler.c index f73f35e..c963c6d 100644 --- a/tests/dummy-indicator-signaler.c +++ b/tests/dummy-indicator-signaler.c @@ -23,8 +23,8 @@ License along with this library. If not, see #include #include -#include "libayatana-indicator/indicator.h" -#include "libayatana-indicator/indicator-object.h" +#include "src/indicator.h" +#include "src/indicator-object.h" #define DUMMY_INDICATOR_SIGNALER_TYPE (dummy_indicator_signaler_get_type ()) #define DUMMY_INDICATOR_SIGNALER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DUMMY_INDICATOR_SIGNALER_TYPE, DummyIndicatorSignaler)) @@ -37,12 +37,12 @@ typedef struct _DummyIndicatorSignaler DummyIndicatorSignaler; typedef struct _DummyIndicatorSignalerClass DummyIndicatorSignalerClass; struct _DummyIndicatorSignalerClass { - IndicatorObjectClass parent_class; + IndicatorObjectClass parent_class; }; struct _DummyIndicatorSignaler { - IndicatorObject parent; - IndicatorObjectEntry *entries; + IndicatorObject parent; + IndicatorObjectEntry *entries; }; GType dummy_indicator_signaler_get_type (void); @@ -53,30 +53,30 @@ INDICATOR_SET_TYPE(DUMMY_INDICATOR_SIGNALER_TYPE) GtkLabel * get_label (IndicatorObject * io) { - return GTK_LABEL(gtk_label_new("Signaler Item")); + return GTK_LABEL(gtk_label_new("Signaler Item")); } GtkImage * get_icon (IndicatorObject * io) { - return GTK_IMAGE(gtk_image_new()); + 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)); + 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; + return main_menu; } const gchar * get_accessible_desc (IndicatorObject * io) { - return "Signaler Item"; + return "Signaler Item"; } static void dummy_indicator_signaler_class_init (DummyIndicatorSignalerClass *klass); @@ -89,66 +89,66 @@ G_DEFINE_TYPE (DummyIndicatorSignaler, dummy_indicator_signaler, INDICATOR_OBJEC static void dummy_indicator_signaler_class_init (DummyIndicatorSignalerClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); - object_class->dispose = dummy_indicator_signaler_dispose; - object_class->finalize = dummy_indicator_signaler_finalize; + object_class->dispose = dummy_indicator_signaler_dispose; + object_class->finalize = dummy_indicator_signaler_finalize; - IndicatorObjectClass * io_class = INDICATOR_OBJECT_CLASS(klass); + 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 = NULL; - io_class->entry_was_added = NULL; + 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 = NULL; + io_class->entry_was_added = NULL; - return; + return; } static gboolean idle_signal (gpointer data) { - DummyIndicatorSignaler * self = DUMMY_INDICATOR_SIGNALER(data); + DummyIndicatorSignaler * self = DUMMY_INDICATOR_SIGNALER(data); - IndicatorObjectEntry *added_entry, *removed_entry, *moved_entry; + IndicatorObjectEntry *added_entry, *removed_entry, *moved_entry; - added_entry = &self->entries[0]; - moved_entry = &self->entries[1]; - removed_entry = &self->entries[2]; + added_entry = &self->entries[0]; + moved_entry = &self->entries[1]; + removed_entry = &self->entries[2]; - added_entry->name_hint = "added"; - moved_entry->name_hint = "moved"; - removed_entry->name_hint = "removed"; + added_entry->name_hint = "added"; + moved_entry->name_hint = "moved"; + removed_entry->name_hint = "removed"; - g_signal_emit(G_OBJECT(self), INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED_ID, 0, added_entry); - g_signal_emit(G_OBJECT(self), INDICATOR_OBJECT_SIGNAL_ENTRY_MOVED_ID, 0, moved_entry, 0, 1); - g_signal_emit(G_OBJECT(self), INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED_ID, 0, removed_entry); + g_signal_emit(G_OBJECT(self), INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED_ID, 0, added_entry); + g_signal_emit(G_OBJECT(self), INDICATOR_OBJECT_SIGNAL_ENTRY_MOVED_ID, 0, moved_entry, 0, 1); + g_signal_emit(G_OBJECT(self), INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED_ID, 0, removed_entry); - return FALSE; /* Don't queue again */ + return FALSE; /* Don't queue again */ } static void dummy_indicator_signaler_init (DummyIndicatorSignaler *self) { - self->entries = g_new0(IndicatorObjectEntry, 3); - g_idle_add(idle_signal, self); - return; + self->entries = g_new0(IndicatorObjectEntry, 3); + g_idle_add(idle_signal, self); + return; } static void dummy_indicator_signaler_dispose (GObject *object) { - G_OBJECT_CLASS (dummy_indicator_signaler_parent_class)->dispose (object); - return; + G_OBJECT_CLASS (dummy_indicator_signaler_parent_class)->dispose (object); + return; } static void dummy_indicator_signaler_finalize (GObject *object) { - DummyIndicatorSignaler * self = DUMMY_INDICATOR_SIGNALER(object); - g_free (self->entries); - G_OBJECT_CLASS (dummy_indicator_signaler_parent_class)->finalize (object); - return; + DummyIndicatorSignaler * self = DUMMY_INDICATOR_SIGNALER(object); + g_free (self->entries); + G_OBJECT_CLASS (dummy_indicator_signaler_parent_class)->finalize (object); + return; } diff --git a/tests/dummy-indicator-simple.c b/tests/dummy-indicator-simple.c index 69a9c1d..d62c991 100644 --- a/tests/dummy-indicator-simple.c +++ b/tests/dummy-indicator-simple.c @@ -23,8 +23,8 @@ License along with this library. If not, see #include #include -#include "libayatana-indicator/indicator.h" -#include "libayatana-indicator/indicator-object.h" +#include "src/indicator.h" +#include "src/indicator-object.h" #define DUMMY_INDICATOR_SIMPLE_TYPE (dummy_indicator_simple_get_type ()) #define DUMMY_INDICATOR_SIMPLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DUMMY_INDICATOR_SIMPLE_TYPE, DummyIndicatorSimple)) @@ -37,11 +37,11 @@ typedef struct _DummyIndicatorSimple DummyIndicatorSimple; typedef struct _DummyIndicatorSimpleClass DummyIndicatorSimpleClass; struct _DummyIndicatorSimpleClass { - IndicatorObjectClass parent_class; + IndicatorObjectClass parent_class; }; struct _DummyIndicatorSimple { - IndicatorObject parent; + IndicatorObject parent; }; GType dummy_indicator_simple_get_type (void); @@ -52,30 +52,30 @@ INDICATOR_SET_TYPE(DUMMY_INDICATOR_SIMPLE_TYPE) GtkLabel * get_label (IndicatorObject * io) { - return GTK_LABEL(gtk_label_new("Simple Item")); + return GTK_LABEL(gtk_label_new("Simple Item")); } GtkImage * get_icon (IndicatorObject * io) { - return GTK_IMAGE(gtk_image_new()); + 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)); + 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; + return main_menu; } const gchar * get_accessible_desc (IndicatorObject * io) { - return "Simple Item"; + return "Simple Item"; } static void dummy_indicator_simple_class_init (DummyIndicatorSimpleClass *klass); @@ -88,40 +88,40 @@ G_DEFINE_TYPE (DummyIndicatorSimple, dummy_indicator_simple, INDICATOR_OBJECT_TY static void dummy_indicator_simple_class_init (DummyIndicatorSimpleClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); - object_class->dispose = dummy_indicator_simple_dispose; - object_class->finalize = dummy_indicator_simple_finalize; + object_class->dispose = dummy_indicator_simple_dispose; + object_class->finalize = dummy_indicator_simple_finalize; - IndicatorObjectClass * io_class = INDICATOR_OBJECT_CLASS(klass); + 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->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; + return; } static void dummy_indicator_simple_init (DummyIndicatorSimple *self) { - return; + return; } static void dummy_indicator_simple_dispose (GObject *object) { - G_OBJECT_CLASS (dummy_indicator_simple_parent_class)->dispose (object); - return; + G_OBJECT_CLASS (dummy_indicator_simple_parent_class)->dispose (object); + return; } static void dummy_indicator_simple_finalize (GObject *object) { - G_OBJECT_CLASS (dummy_indicator_simple_parent_class)->finalize (object); - return; + G_OBJECT_CLASS (dummy_indicator_simple_parent_class)->finalize (object); + return; } diff --git a/tests/dummy-indicator-visible.c b/tests/dummy-indicator-visible.c index 05bc9ad..a9dbaf7 100644 --- a/tests/dummy-indicator-visible.c +++ b/tests/dummy-indicator-visible.c @@ -23,8 +23,8 @@ License along with this library. If not, see #include #include -#include "libayatana-indicator/indicator.h" -#include "libayatana-indicator/indicator-object.h" +#include "src/indicator.h" +#include "src/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)) @@ -37,11 +37,11 @@ typedef struct _DummyIndicatorVisible DummyIndicatorVisible; typedef struct _DummyIndicatorVisibleClass DummyIndicatorVisibleClass; struct _DummyIndicatorVisibleClass { - IndicatorObjectClass parent_class; + IndicatorObjectClass parent_class; }; struct _DummyIndicatorVisible { - IndicatorObject parent; + IndicatorObject parent; }; GType dummy_indicator_visible_get_type (void); @@ -52,30 +52,30 @@ INDICATOR_SET_TYPE(DUMMY_INDICATOR_VISIBLE_TYPE) GtkLabel * get_label (IndicatorObject * io) { - return GTK_LABEL(gtk_label_new("Visible Item")); + return GTK_LABEL(gtk_label_new("Visible Item")); } GtkImage * get_icon (IndicatorObject * io) { - return GTK_IMAGE(gtk_image_new()); + 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)); + 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; + return main_menu; } const gchar * get_accessible_desc (IndicatorObject * io) { - return "Visible Item"; + return "Visible Item"; } static void dummy_indicator_visible_class_init (DummyIndicatorVisibleClass *klass); @@ -88,43 +88,43 @@ G_DEFINE_TYPE (DummyIndicatorVisible, dummy_indicator_visible, INDICATOR_OBJECT_ static void dummy_indicator_entry_being_removed (IndicatorObject * io, IndicatorObjectEntry * entry) { - IndicatorObjectClass * indicator_object_class = INDICATOR_OBJECT_CLASS (dummy_indicator_visible_parent_class); + IndicatorObjectClass * indicator_object_class = INDICATOR_OBJECT_CLASS (dummy_indicator_visible_parent_class); - g_object_set_data(G_OBJECT(entry->label), "is-hidden", GINT_TO_POINTER(1)); + g_object_set_data(G_OBJECT(entry->label), "is-hidden", GINT_TO_POINTER(1)); - if (indicator_object_class->entry_being_removed != NULL) { - indicator_object_class->entry_being_removed (io, entry); - } + if (indicator_object_class->entry_being_removed != NULL) { + indicator_object_class->entry_being_removed (io, entry); + } } static void dummy_indicator_entry_was_added (IndicatorObject * io, IndicatorObjectEntry * entry) { - IndicatorObjectClass * indicator_object_class = INDICATOR_OBJECT_CLASS (dummy_indicator_visible_parent_class); + IndicatorObjectClass * indicator_object_class = INDICATOR_OBJECT_CLASS (dummy_indicator_visible_parent_class); - g_object_steal_data(G_OBJECT(entry->label), "is-hidden"); + g_object_steal_data(G_OBJECT(entry->label), "is-hidden"); - if (indicator_object_class->entry_was_added != NULL) { - indicator_object_class->entry_was_added (io, entry); - } + if (indicator_object_class->entry_was_added != NULL) { + indicator_object_class->entry_was_added (io, entry); + } } static void dummy_indicator_visible_class_init (DummyIndicatorVisibleClass *klass) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); - object_class->dispose = dummy_indicator_visible_dispose; - object_class->finalize = dummy_indicator_visible_finalize; + object_class->dispose = dummy_indicator_visible_dispose; + object_class->finalize = dummy_indicator_visible_finalize; - IndicatorObjectClass * io_class = INDICATOR_OBJECT_CLASS(klass); + 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; + 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 @@ -136,12 +136,12 @@ static void dummy_indicator_visible_dispose (GObject *object) { - G_OBJECT_CLASS (dummy_indicator_visible_parent_class)->dispose (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); + G_OBJECT_CLASS (dummy_indicator_visible_parent_class)->finalize (object); } diff --git a/tests/service-manager-connect-service.c b/tests/service-manager-connect-service.c index fb00712..85c353e 100644 --- a/tests/service-manager-connect-service.c +++ b/tests/service-manager-connect-service.c @@ -22,7 +22,7 @@ License along with this library. If not, see #include -#include "libayatana-indicator/indicator-service.h" +#include "src/indicator-service.h" static GMainLoop * mainloop = NULL; static gboolean passed = FALSE; diff --git a/tests/service-manager-connect.c b/tests/service-manager-connect.c index d4774f7..902efaa 100644 --- a/tests/service-manager-connect.c +++ b/tests/service-manager-connect.c @@ -22,7 +22,7 @@ License along with this library. If not, see #include -#include "libayatana-indicator/indicator-service-manager.h" +#include "src/indicator-service-manager.h" static GMainLoop * mainloop = NULL; static gboolean passed = FALSE; diff --git a/tests/service-manager-no-connect.c b/tests/service-manager-no-connect.c index 7aeffc2..5f81118 100644 --- a/tests/service-manager-no-connect.c +++ b/tests/service-manager-no-connect.c @@ -22,7 +22,7 @@ License along with this library. If not, see #include -#include "libayatana-indicator/indicator-service-manager.h" +#include "src/indicator-service-manager.h" static GMainLoop * mainloop = NULL; static gboolean passed = FALSE; diff --git a/tests/service-manager-nostart-connect.c b/tests/service-manager-nostart-connect.c index 36d1bdd..a0b09c3 100644 --- a/tests/service-manager-nostart-connect.c +++ b/tests/service-manager-nostart-connect.c @@ -22,7 +22,7 @@ License along with this library. If not, see #include -#include "libayatana-indicator/indicator-service-manager.h" +#include "src/indicator-service-manager.h" static GMainLoop * mainloop = NULL; static gboolean passed = FALSE; diff --git a/tests/service-shutdown-timeout.c b/tests/service-shutdown-timeout.c index e044216..5407c27 100644 --- a/tests/service-shutdown-timeout.c +++ b/tests/service-shutdown-timeout.c @@ -22,7 +22,7 @@ License along with this library. If not, see #include -#include "libayatana-indicator/indicator-service.h" +#include "src/indicator-service.h" static GMainLoop * mainloop = NULL; static gboolean passed = FALSE; diff --git a/tests/service-version-bad-service.c b/tests/service-version-bad-service.c index f78f6e1..e5e3287 100644 --- a/tests/service-version-bad-service.c +++ b/tests/service-version-bad-service.c @@ -22,7 +22,7 @@ License along with this library. If not, see #include -#include "libayatana-indicator/indicator-service.h" +#include "src/indicator-service.h" #include "service-version-values.h" static GMainLoop * mainloop = NULL; diff --git a/tests/service-version-good-service.c b/tests/service-version-good-service.c index a811d96..7a4abbb 100644 --- a/tests/service-version-good-service.c +++ b/tests/service-version-good-service.c @@ -22,7 +22,7 @@ License along with this library. If not, see #include -#include "libayatana-indicator/indicator-service.h" +#include "src/indicator-service.h" #include "service-version-values.h" static GMainLoop * mainloop = NULL; diff --git a/tests/service-version-manager.c b/tests/service-version-manager.c index 370dbd0..85e1b37 100644 --- a/tests/service-version-manager.c +++ b/tests/service-version-manager.c @@ -22,7 +22,7 @@ License along with this library. If not, see #include -#include "libayatana-indicator/indicator-service-manager.h" +#include "src/indicator-service-manager.h" #include "service-version-values.h" static GMainLoop * mainloop = NULL; diff --git a/tests/service-version-multiwatch-manager-impolite.c b/tests/service-version-multiwatch-manager-impolite.c index 4e3a5a9..c22736e 100644 --- a/tests/service-version-multiwatch-manager-impolite.c +++ b/tests/service-version-multiwatch-manager-impolite.c @@ -22,7 +22,7 @@ License along with this library. If not, see #include -#include "libayatana-indicator/indicator-service-manager.h" +#include "src/indicator-service-manager.h" #include "service-version-values.h" static GMainLoop * mainloop = NULL; diff --git a/tests/service-version-multiwatch-manager.c b/tests/service-version-multiwatch-manager.c index c24b41d..32a0079 100644 --- a/tests/service-version-multiwatch-manager.c +++ b/tests/service-version-multiwatch-manager.c @@ -22,7 +22,7 @@ License along with this library. If not, see #include -#include "libayatana-indicator/indicator-service-manager.h" +#include "src/indicator-service-manager.h" #include "service-version-values.h" static GMainLoop * mainloop = NULL; diff --git a/tests/service-version-multiwatch-service.c b/tests/service-version-multiwatch-service.c index 1a43414..ffad013 100644 --- a/tests/service-version-multiwatch-service.c +++ b/tests/service-version-multiwatch-service.c @@ -22,7 +22,7 @@ License along with this library. If not, see #include -#include "libayatana-indicator/indicator-service.h" +#include "src/indicator-service.h" #include "service-version-values.h" static GMainLoop * mainloop = NULL; diff --git a/tests/test-desktop-shortcuts.c b/tests/test-desktop-shortcuts.c index 59084dd..02e313a 100644 --- a/tests/test-desktop-shortcuts.c +++ b/tests/test-desktop-shortcuts.c @@ -21,7 +21,7 @@ License along with this library. If not, see */ #include -#include "libayatana-indicator/indicator-desktop-shortcuts.h" +#include "src/indicator-desktop-shortcuts.h" /* Basic object creation and destruction. Stop big f*** ups here. */ diff --git a/tests/test-indicator-ng.c b/tests/test-indicator-ng.c index 0844334..dd0592f 100644 --- a/tests/test-indicator-ng.c +++ b/tests/test-indicator-ng.c @@ -1,5 +1,5 @@ -#include +#include "src/indicator-ng.h" static void indicator_ng_test_func (gconstpointer user_data) diff --git a/tests/test-loader.c b/tests/test-loader.c index 5f9b8d3..c1e4b6d 100644 --- a/tests/test-loader.c +++ b/tests/test-loader.c @@ -21,78 +21,78 @@ License along with this library. If not, see */ #include -#include "libayatana-indicator/indicator-object.h" +#include "src/indicator-object.h" #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); + 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 (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; - } + if (klass->entry_activate_window == NULL) { + klass->entry_activate_window = saved_func; + } else { + klass->entry_activate_window = NULL; + } - return; + return; } 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); + IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-entry-func.so"); + g_assert(object != NULL); - DummyIndicatorEntryFunc * entryfunc = (DummyIndicatorEntryFunc *)(object); + DummyIndicatorEntryFunc * entryfunc = (DummyIndicatorEntryFunc *)(object); - entryfunc->entry_activate_called = FALSE; - entryfunc->entry_activate_window_called = FALSE; - entryfunc->entry_close_called = FALSE; + entryfunc->entry_activate_called = FALSE; + entryfunc->entry_activate_window_called = FALSE; + entryfunc->entry_close_called = FALSE; - entry_func_swap(object); - indicator_object_entry_activate_window(object, NULL, 0, 0); - g_assert(entryfunc->entry_activate_called); + entry_func_swap(object); + indicator_object_entry_activate_window(object, NULL, 0, 0); + g_assert(entryfunc->entry_activate_called); - entry_func_swap(object); - indicator_object_entry_activate_window(object, NULL, 0, 0); - g_assert(entryfunc->entry_activate_window_called); + entry_func_swap(object); + indicator_object_entry_activate_window(object, NULL, 0, 0); + g_assert(entryfunc->entry_activate_window_called); - g_object_unref(object); + g_object_unref(object); - return; + return; } 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); + IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-entry-func.so"); + g_assert(object != NULL); - DummyIndicatorEntryFunc * entryfunc = (DummyIndicatorEntryFunc *)(object); + DummyIndicatorEntryFunc * entryfunc = (DummyIndicatorEntryFunc *)(object); - entryfunc->entry_activate_called = FALSE; - entryfunc->entry_activate_window_called = FALSE; - entryfunc->entry_close_called = FALSE; + 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(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_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); + indicator_object_entry_close(object, NULL, 0); + g_assert(entryfunc->entry_close_called); - g_object_unref(object); + g_object_unref(object); - return; + return; } void destroy_cb (gpointer data, GObject * object); @@ -100,53 +100,53 @@ void destroy_cb (gpointer data, GObject * object); void entry_change_cb (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer data) { - IndicatorObjectEntry *other_entry = data; - other_entry->name_hint = entry->name_hint; - other_entry->parent_object = entry->parent_object; - return; + IndicatorObjectEntry *other_entry = data; + other_entry->name_hint = entry->name_hint; + other_entry->parent_object = entry->parent_object; + return; } void entry_move_cb (IndicatorObject * io, IndicatorObjectEntry * entry, gint old, gint new, gpointer data) { - return entry_change_cb(io, entry, data); + return entry_change_cb(io, entry, data); } void test_loader_filename_dummy_signaler (void) { - IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-signaler.so"); - g_assert(object != NULL); + IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-signaler.so"); + g_assert(object != NULL); - IndicatorObjectEntry *added_entry, *moved_entry, *removed_entry; - IndicatorObjectEntry entries[3]; + IndicatorObjectEntry *added_entry, *moved_entry, *removed_entry; + IndicatorObjectEntry entries[3]; - added_entry = &entries[0]; - moved_entry = &entries[1]; - removed_entry = &entries[2]; + added_entry = &entries[0]; + moved_entry = &entries[1]; + removed_entry = &entries[2]; - g_signal_connect_after(G_OBJECT(object), INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED, G_CALLBACK(entry_change_cb), added_entry); - g_signal_connect_after(G_OBJECT(object), INDICATOR_OBJECT_SIGNAL_ENTRY_MOVED, G_CALLBACK(entry_move_cb), moved_entry); - g_signal_connect_after(G_OBJECT(object), INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED, G_CALLBACK(entry_change_cb), removed_entry); + g_signal_connect_after(G_OBJECT(object), INDICATOR_OBJECT_SIGNAL_ENTRY_ADDED, G_CALLBACK(entry_change_cb), added_entry); + g_signal_connect_after(G_OBJECT(object), INDICATOR_OBJECT_SIGNAL_ENTRY_MOVED, G_CALLBACK(entry_move_cb), moved_entry); + g_signal_connect_after(G_OBJECT(object), INDICATOR_OBJECT_SIGNAL_ENTRY_REMOVED, G_CALLBACK(entry_change_cb), removed_entry); - GList * list = indicator_object_get_entries(object); - g_assert(list != NULL); - g_list_free(list); + GList * list = indicator_object_get_entries(object); + g_assert(list != NULL); + g_list_free(list); - while (g_main_context_pending(NULL)) { - g_main_context_iteration(NULL, TRUE); - } + while (g_main_context_pending(NULL)) { + g_main_context_iteration(NULL, TRUE); + } - g_assert(g_strcmp0(added_entry->name_hint, "added") == 0); - g_assert(g_strcmp0(removed_entry->name_hint, "removed") == 0); - g_assert(g_strcmp0(moved_entry->name_hint, "moved") == 0); + g_assert(g_strcmp0(added_entry->name_hint, "added") == 0); + g_assert(g_strcmp0(removed_entry->name_hint, "removed") == 0); + g_assert(g_strcmp0(moved_entry->name_hint, "moved") == 0); - g_assert(added_entry->parent_object == object); - g_assert(removed_entry->parent_object == NULL); + g_assert(added_entry->parent_object == object); + g_assert(removed_entry->parent_object == NULL); - g_object_unref(object); + g_object_unref(object); - return; + return; } /*** @@ -156,86 +156,86 @@ test_loader_filename_dummy_signaler (void) static void visible_entry_added (IndicatorObject * io, IndicatorObjectEntry * entry, gpointer box) { - GtkWidget * child = GTK_WIDGET (entry->label); - g_assert (child != NULL); - - if (g_object_get_data (G_OBJECT(child), "frame-parent") == NULL) - { - GtkWidget * frame = gtk_frame_new (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); - } + GtkWidget * child = GTK_WIDGET (entry->label); + g_assert (child != NULL); + + if (g_object_get_data (G_OBJECT(child), "frame-parent") == NULL) + { + GtkWidget * frame = gtk_frame_new (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) { - GtkWidget * child = GTK_WIDGET (entry->label); - g_assert (child != NULL); - g_assert (g_object_get_data (G_OBJECT(child), "frame-parent") != NULL); + GtkWidget * child = GTK_WIDGET (entry->label); + g_assert (child != NULL); + g_assert (g_object_get_data (G_OBJECT(child), "frame-parent") != NULL); } 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); + 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 + // create our local parent widgetry #if GTK_CHECK_VERSION(3,0,0) - GtkWidget * box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + GtkWidget * box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); #else - GtkWidget * box = gtk_hbox_new (TRUE, 0); + 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)); - g_assert(entry->parent_object == object); - g_assert(INDICATOR_IS_OBJECT(entry->parent_object)); - GtkWidget * label = GTK_WIDGET(entry->label); + 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)); + g_assert(entry->parent_object == object); + g_assert(INDICATOR_IS_OBJECT(entry->parent_object)); + 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)); + // 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) == 1); - 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)); + list = gtk_container_get_children (GTK_CONTAINER(box)); + g_assert(g_list_length(list) == 1); + 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); + 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); + // cleanup + g_object_unref(object); + gtk_widget_destroy(box); } /*** @@ -245,129 +245,129 @@ test_loader_filename_dummy_visible (void) void test_loader_filename_dummy_simple_location (void) { - IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-simple.so"); - g_assert(object != NULL); + IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-simple.so"); + g_assert(object != NULL); - GList * entries = indicator_object_get_entries(object); - g_assert(entries != NULL); - g_assert(g_list_length(entries) == 1); + GList * entries = indicator_object_get_entries(object); + g_assert(entries != NULL); + g_assert(g_list_length(entries) == 1); - IndicatorObjectEntry *entry = entries->data; + IndicatorObjectEntry *entry = entries->data; - g_assert(indicator_object_get_location(object, entry) == 0); - g_assert(indicator_object_get_location(object, NULL) == 0); - g_assert(entry->parent_object == object); + g_assert(indicator_object_get_location(object, entry) == 0); + g_assert(indicator_object_get_location(object, NULL) == 0); + g_assert(entry->parent_object == object); - g_object_unref(object); + g_object_unref(object); - return; + return; } void test_loader_filename_dummy_simple_accessors (void) { - IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-simple.so"); - g_assert(object != NULL); + IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-simple.so"); + g_assert(object != NULL); - g_assert(indicator_object_get_entries(object) != NULL); + g_assert(indicator_object_get_entries(object) != NULL); - g_object_unref(object); + g_object_unref(object); - return; + return; } void test_loader_filename_dummy_simple (void) { - IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-simple.so"); - g_assert(object != NULL); + IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-simple.so"); + g_assert(object != NULL); - gboolean unreffed = FALSE; - g_object_weak_ref(G_OBJECT(object), destroy_cb, &unreffed); + gboolean unreffed = FALSE; + g_object_weak_ref(G_OBJECT(object), destroy_cb, &unreffed); - g_object_unref(object); - g_assert(unreffed == TRUE); + g_object_unref(object); + g_assert(unreffed == TRUE); - return; + return; } void test_loader_filename_dummy_blank (void) { - IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-blank.so"); - g_assert(object == NULL); - return; + IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-blank.so"); + g_assert(object == NULL); + return; } void test_loader_filename_dummy_null (void) { - IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-null.so"); - g_assert(object != NULL); - g_assert(indicator_object_get_entries(object) == NULL); - g_object_unref(G_OBJECT(object)); - return; + IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-null.so"); + g_assert(object != NULL); + g_assert(indicator_object_get_entries(object) == NULL); + g_object_unref(G_OBJECT(object)); + return; } void test_loader_filename_bad (void) { - IndicatorObject * object = indicator_object_new_from_file("/this/file/should/not/exist.so"); - g_assert(object == NULL); - return; + IndicatorObject * object = indicator_object_new_from_file("/this/file/should/not/exist.so"); + g_assert(object == NULL); + return; } void destroy_cb (gpointer data, GObject * object) { - gboolean * bob = (gboolean *)data; - *bob = TRUE; - return; + gboolean * bob = (gboolean *)data; + *bob = TRUE; + return; } void test_loader_refunref (void) { - GObject * object = g_object_new(INDICATOR_OBJECT_TYPE, NULL); + GObject * object = g_object_new(INDICATOR_OBJECT_TYPE, NULL); - gboolean unreffed = FALSE; - g_object_weak_ref(object, destroy_cb, &unreffed); + gboolean unreffed = FALSE; + g_object_weak_ref(object, destroy_cb, &unreffed); - g_object_unref(object); + g_object_unref(object); - g_assert(unreffed == TRUE); + g_assert(unreffed == TRUE); - return; + return; } void test_loader_creation_deletion_suite (void) { - g_test_add_func ("/libindicator/loader/ref_and_unref", test_loader_refunref); - g_test_add_func ("/libindicator/loader/filename_bad", test_loader_filename_bad); - g_test_add_func ("/libindicator/loader/dummy/null_load", test_loader_filename_dummy_null); - g_test_add_func ("/libindicator/loader/dummy/blank_load", test_loader_filename_dummy_null); - g_test_add_func ("/libindicator/loader/dummy/simple_load", test_loader_filename_dummy_simple); - 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); - g_test_add_func ("/libindicator/loader/dummy/entry_func_window", test_loader_entry_func_window); - g_test_add_func ("/libindicator/loader/dummy/visible", test_loader_filename_dummy_visible); - - return; + g_test_add_func ("/libindicator/loader/ref_and_unref", test_loader_refunref); + g_test_add_func ("/libindicator/loader/filename_bad", test_loader_filename_bad); + g_test_add_func ("/libindicator/loader/dummy/null_load", test_loader_filename_dummy_null); + g_test_add_func ("/libindicator/loader/dummy/blank_load", test_loader_filename_dummy_null); + g_test_add_func ("/libindicator/loader/dummy/simple_load", test_loader_filename_dummy_simple); + 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); + g_test_add_func ("/libindicator/loader/dummy/entry_func_window", test_loader_entry_func_window); + g_test_add_func ("/libindicator/loader/dummy/visible", test_loader_filename_dummy_visible); + + return; } int main (int argc, char ** argv) { - g_test_init (&argc, &argv, NULL); - gtk_init(&argc, &argv); + g_test_init (&argc, &argv, NULL); + gtk_init(&argc, &argv); - test_loader_creation_deletion_suite(); + test_loader_creation_deletion_suite(); - g_log_set_always_fatal(G_LOG_LEVEL_CRITICAL); + g_log_set_always_fatal(G_LOG_LEVEL_CRITICAL); - return g_test_run(); + return g_test_run(); } diff --git a/tools/Makefile.am b/tools/Makefile.am index e871921..7d25b5c 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -23,7 +23,7 @@ ayatana_indicator_loader_CFLAGS = \ ayatana_indicator_loader_LDADD = \ $(LIBINDICATOR_LIBS) \ $(LIBINDICATOR_IDO_LIBS) \ - -L$(top_builddir)/libayatana-indicator/.libs \ + -L$(top_builddir)/src/.libs \ $(INDICATOR_LIB) # We duplicate these here because Automake won't let us use $(VER) on the left hand side. diff --git a/tools/indicator-loader.c b/tools/indicator-loader.c index 5b236db..a0db1b4 100644 --- a/tools/indicator-loader.c +++ b/tools/indicator-loader.c @@ -17,7 +17,7 @@ * 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 * . @@ -25,9 +25,9 @@ #include #include -#include +#include "src//indicator-object.h" #if GTK_CHECK_VERSION (3,0,0) - #include + #include "src/indicator-ng.h" #endif static GHashTable * entry_to_menu_item = NULL; @@ -159,7 +159,7 @@ entry_added (IndicatorObject * io, gtk_widget_show (menu_item); } -static void +static void entry_removed (__attribute__((unused)) IndicatorObject * io, IndicatorObjectEntry * entry, __attribute__((unused)) gpointer user_data) -- cgit v1.2.3 From 25c29224a1f4d2d6d87f2b7f7078fa6ec795edb9 Mon Sep 17 00:00:00 2001 From: Robert Tari Date: Wed, 10 Feb 2021 13:08:12 +0100 Subject: Add ayatana-indicator3-0.4.pc.in to data --- data/ayatana-indicator3-0.4.pc.in | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 data/ayatana-indicator3-0.4.pc.in diff --git a/data/ayatana-indicator3-0.4.pc.in b/data/ayatana-indicator3-0.4.pc.in new file mode 100644 index 0000000..231fa71 --- /dev/null +++ b/data/ayatana-indicator3-0.4.pc.in @@ -0,0 +1,15 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=${prefix} +libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@ +bindir=${exec_prefix}/@CMAKE_INSTALL_BINDIR@ +includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ +indicatordir=${exec_prefix}/lib/ayatana-indicators3/@ABI_VERSION@/ +iconsdir=${prefix}/@CMAKE_INSTALL_DATADIR@/@PROJECT_NAME@/icons/ + +Cflags: -I${includedir}/libayatana-indicator3-0.@API_VERSION@ +Requires: gtk+-3.0 +Libs: -layatana-indicator3 + +Name: libayatana-indicator3 +Description: libayatana-indicator3. +Version: @PROJECT_VERSION@ -- cgit v1.2.3 From 1cba9230eeb711fb00b3a2d53f1e51f99e493542 Mon Sep 17 00:00:00 2001 From: Robert Tari Date: Wed, 10 Feb 2021 13:15:05 +0100 Subject: Whitespace fix --- tools/indicator-loader.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/indicator-loader.c b/tools/indicator-loader.c index a0db1b4..ad4fdf4 100644 --- a/tools/indicator-loader.c +++ b/tools/indicator-loader.c @@ -25,7 +25,7 @@ #include #include -#include "src//indicator-object.h" +#include "src/indicator-object.h" #if GTK_CHECK_VERSION (3,0,0) #include "src/indicator-ng.h" #endif -- cgit v1.2.3 From 729e95bc9d9337fe87eae3ea98a051be52570153 Mon Sep 17 00:00:00 2001 From: Robert Tari Date: Thu, 11 Feb 2021 14:40:51 +0100 Subject: tests/test-indicator-ng.c: disable menu test for now, it will not work with GCovr --- tests/test-indicator-ng.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test-indicator-ng.c b/tests/test-indicator-ng.c index dd0592f..80bbbb1 100644 --- a/tests/test-indicator-ng.c +++ b/tests/test-indicator-ng.c @@ -105,7 +105,7 @@ test_instantiation_with_profile (void) * widgets to accommodate an icon. * */ -static const gchar * +/*static const gchar * get_label (GtkMenuItem *item) { GList *children = gtk_container_get_children (GTK_CONTAINER (item)); @@ -122,9 +122,9 @@ get_label (GtkMenuItem *item) } return label; -} +}*/ -static void +/*static void test_menu (void) { IndicatorNg *indicator; @@ -169,7 +169,7 @@ test_menu (void) g_list_free (entries); g_main_loop_unref (loop); g_object_unref (indicator); -} +}*/ int main (int argc, char **argv) @@ -187,7 +187,7 @@ main (int argc, char **argv) indicator_ng_test_add ("non-existing", test_non_existing); indicator_ng_test_add ("instantiation", test_instantiation); indicator_ng_test_add ("instantiation-with-profile", test_instantiation_with_profile); - indicator_ng_test_add ("menu", test_menu); + //indicator_ng_test_add ("menu", test_menu); return g_test_run (); } -- cgit v1.2.3 From 1fa174f54c9604499f059489e544cfc59c825f27 Mon Sep 17 00:00:00 2001 From: Robert Tari Date: Thu, 11 Feb 2021 15:22:22 +0100 Subject: Add CMakeLists.txt files + tests/test-loader.c: fix library paths + Fix include paths tests/test-loader.c: fix library paths --- CMakeLists.txt | 70 +++++++++ data/CMakeLists.txt | 12 ++ src/CMakeLists.txt | 127 +++++++++++++++++ tests/CMakeLists.txt | 156 +++++++++++++++++++++ tests/dummy-indicator-blank.c | 2 +- tests/dummy-indicator-entry-func.h | 4 +- tests/dummy-indicator-null.c | 4 +- tests/dummy-indicator-signaler.c | 4 +- tests/dummy-indicator-simple.c | 4 +- tests/dummy-indicator-visible.c | 4 +- tests/service-manager-connect-service.c | 2 +- tests/service-manager-connect.c | 2 +- tests/service-manager-no-connect.c | 2 +- tests/service-manager-nostart-connect.c | 2 +- tests/service-shutdown-timeout.c | 2 +- tests/service-version-bad-service.c | 2 +- tests/service-version-good-service.c | 2 +- tests/service-version-manager.c | 2 +- .../service-version-multiwatch-manager-impolite.c | 2 +- tests/service-version-multiwatch-manager.c | 2 +- tests/service-version-multiwatch-service.c | 2 +- tests/test-desktop-shortcuts.c | 2 +- tests/test-indicator-ng.c | 2 +- tests/test-loader.c | 20 +-- tools/CMakeLists.txt | 8 ++ tools/indicator-loader.c | 4 +- 26 files changed, 409 insertions(+), 36 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 data/CMakeLists.txt create mode 100644 src/CMakeLists.txt create mode 100644 tests/CMakeLists.txt create mode 100644 tools/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..e580790 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,70 @@ +cmake_minimum_required(VERSION 3.13) +project(libayatana-indicator C) + +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + SET(CMAKE_INSTALL_PREFIX "/usr" CACHE PATH "..." FORCE) +endif(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + +option(ENABLE_TESTS "Enable all tests and checks" OFF) +option(ENABLE_COVERAGE "Enable coverage reports (includes enabling all tests and checks)" OFF) + +if(ENABLE_COVERAGE) + set(ENABLE_TESTS ON) + set(CMAKE_BUILD_TYPE "Coverage") +else() + set(CMAKE_BUILD_TYPE "Release") +endif() + +# Check for prerequisites + +set(DEPS glib-2.0>=2.58 gtk+-3.0>=3.24 libayatana-ido3-0.4>=0.8.2) + +find_package (PkgConfig REQUIRED) +pkg_check_modules(PROJECT_DEPS REQUIRED ${DEPS}) + +# Set global variables + +include(GNUInstallDirs) +set(ABI_VERSION "7") +set(API_VERSION "4") +set(PROJECT_VERSION "0.8.4") +set(PROJECT_NAME "libayatana-indicator") + +if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + + set(COMPILE_FLAGS "${COMPILE_FLAGS} -Weverything") + set(COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-c++98-compat -Wno-padded") + set(COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-documentation") + +else() + + set(COMPILE_FLAGS "${COMPILE_FLAGS} -Wall") + +endif() + +# Make everything + +add_subdirectory(src) +add_subdirectory(data) + +if(ENABLE_TESTS) + include(CTest) + enable_testing() + add_subdirectory(tools) + add_subdirectory(tests) + + if (ENABLE_COVERAGE) + find_package(CoverageReport) + ENABLE_COVERAGE_REPORT( + TARGETS "ayatana-indicator3" + TESTS "test-desktop-shortcuts" "test-indicator-ng" "test-loader" + FILTER /usr/include ${CMAKE_BINARY_DIR}/* + ) + endif() + +endif() + +# Display config info + +message(STATUS "Install prefix: ${CMAKE_INSTALL_PREFIX}") +message(STATUS "Unit tests: ${ENABLE_TESTS}") diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt new file mode 100644 index 0000000..f6c71d9 --- /dev/null +++ b/data/CMakeLists.txt @@ -0,0 +1,12 @@ +# ayatana-indicator3-0.4.pc + +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/ayatana-indicator3-0.4.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/ayatana-indicator3-0.4.pc" @ONLY) +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/ayatana-indicator3-0.4.pc" DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/pkgconfig/") + +# ayatana-indicators.target + +pkg_check_modules(SYSTEMD systemd) + +if (${SYSTEMD_FOUND}) + install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/ayatana-indicators.target" DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/systemd/user") +endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..d6c6647 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,127 @@ +# indicator-desktop-shortcuts.h +# indicator-image-helper.h +# indicator-ng.h +# indicator-object.h +# indicator-service-manager.h +# indicator-service.h +# indicator.h + +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/indicator-desktop-shortcuts.h" DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/libayatana-indicator3-0.4/libayatana-indicator") +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/indicator-image-helper.h" DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/libayatana-indicator3-0.4/libayatana-indicator") +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/indicator-ng.h" DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/libayatana-indicator3-0.4/libayatana-indicator") +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/indicator-object.h" DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/libayatana-indicator3-0.4/libayatana-indicator") +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/indicator-service-manager.h" DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/libayatana-indicator3-0.4/libayatana-indicator") +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/indicator-service.h" DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/libayatana-indicator3-0.4/libayatana-indicator") +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/indicator.h" DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/libayatana-indicator3-0.4/libayatana-indicator") + +set(HEADERS + indicator.h + indicator-desktop-shortcuts.h + indicator-image-helper.h + indicator-object.h + indicator-service.h + indicator-service-manager.h + indicator-ng.h +) + +set(SOURCES + gen-indicator-service.xml.c + indicator-desktop-shortcuts.c + indicator-image-helper.c + indicator-ng.c + indicator-object.c + indicator-object-enum-types.c + indicator-object-marshal.c + indicator-service.c + indicator-service-manager.c + +) + +# indicator-object-enum-types.h + +find_program(GLIB_MKENUMS glib-mkenums) + +add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/indicator-object-enum-types.h" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMAND + ${GLIB_MKENUMS} + --template indicator-object-enum-types.h.template + ${HEADERS} + --output="${CMAKE_CURRENT_BINARY_DIR}/indicator-object-enum-types.h" +) + +# indicator-object-enum-types.c + +add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/indicator-object-enum-types.c" + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/indicator-object-enum-types.h" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMAND + ${GLIB_MKENUMS} + --template indicator-object-enum-types.c.template + ${HEADERS} + --output="${CMAKE_CURRENT_BINARY_DIR}/indicator-object-enum-types.c" +) + +find_program(GLIB_GENMARSHAL glib-genmarshal) + +# indicator-object-marshal.h + +add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/indicator-object-marshal.h" + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/indicator-object-enum-types.c" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMAND + ${GLIB_GENMARSHAL} + --prefix=_indicator_object_marshal + --header indicator-object-marshal.list + --quiet + --output="${CMAKE_CURRENT_BINARY_DIR}/indicator-object-marshal.h" +) + +# indicator-object-marshal.c + +add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/indicator-object-marshal.c" + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/indicator-object-marshal.h" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMAND + ${GLIB_GENMARSHAL} + --prefix=_indicator_object_marshal + --body indicator-object-marshal.list + --include-header=indicator-object-marshal.h + --quiet + --output="${CMAKE_CURRENT_BINARY_DIR}/indicator-object-marshal.c" +) + +add_custom_target("src-generated" DEPENDS "indicator-object-marshal.c") + +# gen-indicator-service.xml.h + +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/gen-indicator-service.xml.h" "extern const char * _indicator_service;") + +# gen-indicator-service.xml.c + +file(READ "${CMAKE_CURRENT_SOURCE_DIR}/indicator-service.xml" GEN_INDICATOR_SERVICE_XML_C) +string(REPLACE "\"" "\\\"" GEN_INDICATOR_SERVICE_XML_C ${GEN_INDICATOR_SERVICE_XML_C}) +string(REPLACE "\n" "\\n\"\n\"" GEN_INDICATOR_SERVICE_XML_C ${GEN_INDICATOR_SERVICE_XML_C}) +string(REGEX REPLACE "\n\"$" "\n" GEN_INDICATOR_SERVICE_XML_C ${GEN_INDICATOR_SERVICE_XML_C}) +string(PREPEND GEN_INDICATOR_SERVICE_XML_C "const char * _indicator_service = \n\"") +string(APPEND GEN_INDICATOR_SERVICE_XML_C "\;") +file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/gen-indicator-service.xml.c" ${GEN_INDICATOR_SERVICE_XML_C}) + +# libayatana-indicator3.so + +set_source_files_properties(${SOURCES} PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS}) +add_library("ayatana-indicator3" SHARED ${SOURCES}) +set_target_properties("ayatana-indicator3" PROPERTIES VERSION 7.0.0 SOVERSION 7) +target_compile_definitions("ayatana-indicator3" PUBLIC DG_LOG_DOMAIN="libayatana-indicator") +target_include_directories("ayatana-indicator3" PUBLIC ${PROJECT_DEPS_INCLUDE_DIRS}) +target_include_directories("ayatana-indicator3" PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) +target_include_directories("ayatana-indicator3" PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) +target_link_libraries("ayatana-indicator3" ${PROJECT_DEPS_LIBRARIES}) +add_dependencies("ayatana-indicator3" "src-generated") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libayatana-indicator3.so" DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libayatana-indicator3.so.7" DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libayatana-indicator3.so.7.0.0" DESTINATION "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..bb9c0f4 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,156 @@ +# dummy-indicator-blank + +set_source_files_properties(dummy-indicator-blank.c PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS}) +add_library("dummy-indicator-blank" SHARED dummy-indicator-blank.c) +target_include_directories("dummy-indicator-blank" PUBLIC ${PROJECT_DEPS_INCLUDE_DIRS}) +target_include_directories("dummy-indicator-blank" PUBLIC "${CMAKE_SOURCE_DIR}/src") + +# dummy-indicator-entry-func + +set_source_files_properties(dummy-indicator-entry-func.h PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS}) +add_library("dummy-indicator-entry-func" SHARED dummy-indicator-entry-func.c) +target_include_directories("dummy-indicator-entry-func" PUBLIC ${PROJECT_DEPS_INCLUDE_DIRS}) +target_include_directories("dummy-indicator-entry-func" PUBLIC "${CMAKE_SOURCE_DIR}/src") + +# dummy-indicator-null + +set_source_files_properties(dummy-indicator-null.c PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS}) +add_library("dummy-indicator-null" SHARED dummy-indicator-null.c) +target_include_directories("dummy-indicator-null" PUBLIC ${PROJECT_DEPS_INCLUDE_DIRS}) +target_include_directories("dummy-indicator-null" PUBLIC "${CMAKE_SOURCE_DIR}/src") + +# dummy-indicator-signaller + +set_source_files_properties(dummy-indicator-signaler.c PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS}) +add_library("dummy-indicator-signaler" SHARED dummy-indicator-signaler.c) +target_include_directories("dummy-indicator-signaler" PUBLIC ${PROJECT_DEPS_INCLUDE_DIRS}) +target_include_directories("dummy-indicator-signaler" PUBLIC "${CMAKE_SOURCE_DIR}/src") + +# dummy-indicator-simple + +set_source_files_properties(dummy-indicator-simple.c PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS}) +add_library("dummy-indicator-simple" SHARED dummy-indicator-simple.c) +target_include_directories("dummy-indicator-simple" PUBLIC ${PROJECT_DEPS_INCLUDE_DIRS}) +target_include_directories("dummy-indicator-simple" PUBLIC "${CMAKE_SOURCE_DIR}/src") + +# dummy-indicator-visible + +set_source_files_properties(dummy-indicator-visible.c PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS}) +add_library("dummy-indicator-visible" SHARED dummy-indicator-visible.c) +target_include_directories("dummy-indicator-visible" PUBLIC ${PROJECT_DEPS_INCLUDE_DIRS}) +target_include_directories("dummy-indicator-visible" PUBLIC "${CMAKE_SOURCE_DIR}/src") + +# service-manager-connect + +set_source_files_properties(service-manager-connect.c PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS}) +add_library("service-manager-connect" SHARED service-manager-connect.c) +target_include_directories("service-manager-connect" PUBLIC ${PROJECT_DEPS_INCLUDE_DIRS}) +target_include_directories("service-manager-connect" PUBLIC "${CMAKE_SOURCE_DIR}/src") + +# service-manager-connect-service + +set_source_files_properties(service-manager-connect-service.c PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS}) +add_library("service-manager-connect-service" SHARED service-manager-connect-service.c) +target_include_directories("service-manager-connect-service" PUBLIC ${PROJECT_DEPS_INCLUDE_DIRS}) +target_include_directories("service-manager-connect-service" PUBLIC "${CMAKE_SOURCE_DIR}/src") + +# service-manager-no-connect + +set_source_files_properties(service-manager-no-connect.c PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS}) +add_library("service-manager-no-connect" SHARED service-manager-no-connect.c) +target_include_directories("service-manager-no-connect" PUBLIC ${PROJECT_DEPS_INCLUDE_DIRS}) +target_include_directories("service-manager-no-connect" PUBLIC "${CMAKE_SOURCE_DIR}/src") + +# service-manager-nostart-connect + +set_source_files_properties(service-manager-nostart-connect.c PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS}) +add_library("service-manager-nostart-connect" SHARED service-manager-nostart-connect.c) +target_include_directories("service-manager-nostart-connect" PUBLIC ${PROJECT_DEPS_INCLUDE_DIRS}) +target_include_directories("service-manager-nostart-connect" PUBLIC "${CMAKE_SOURCE_DIR}/src") + +# service-shutdown-timeout + +set_source_files_properties(service-shutdown-timeout.c PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS}) +add_library("service-shutdown-timeout" SHARED service-shutdown-timeout.c) +target_include_directories("service-shutdown-timeout" PUBLIC ${PROJECT_DEPS_INCLUDE_DIRS}) +target_include_directories("service-shutdown-timeout" PUBLIC "${CMAKE_SOURCE_DIR}/src") + +# service-version-bad-service + +set_source_files_properties(service-version-bad-service.c PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS}) +add_library("service-version-bad-service" SHARED service-version-bad-service.c) +target_include_directories("service-version-bad-service" PUBLIC ${PROJECT_DEPS_INCLUDE_DIRS}) +target_include_directories("service-version-bad-service" PUBLIC "${CMAKE_SOURCE_DIR}/src") + +# service-version-good-service + +set_source_files_properties(service-version-good-service.c PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS}) +add_library("service-version-good-service" SHARED service-version-good-service.c) +target_include_directories("service-version-good-service" PUBLIC ${PROJECT_DEPS_INCLUDE_DIRS}) +target_include_directories("service-version-good-service" PUBLIC "${CMAKE_SOURCE_DIR}/src") + +# service-version-manager + +set_source_files_properties(service-version-manager.c PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS}) +add_library("service-version-manager" SHARED service-version-manager.c) +target_include_directories("service-version-manager" PUBLIC ${PROJECT_DEPS_INCLUDE_DIRS}) +target_include_directories("service-version-manager" PUBLIC "${CMAKE_SOURCE_DIR}/src") + +# service-version-multiwatch-manager + +set_source_files_properties(service-version-multiwatch-manager.c PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS}) +add_library("service-version-multiwatch-manager" SHARED service-version-multiwatch-manager.c) +target_include_directories("service-version-multiwatch-manager" PUBLIC ${PROJECT_DEPS_INCLUDE_DIRS}) +target_include_directories("service-version-multiwatch-manager" PUBLIC "${CMAKE_SOURCE_DIR}/src") + +# service-version-multiwatch-manager-impolite + +set_source_files_properties(service-version-multiwatch-manager-impolite.c PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS}) +add_library("service-version-multiwatch-manager-impolite" SHARED service-version-multiwatch-manager-impolite.c) +target_include_directories("service-version-multiwatch-manager-impolite" PUBLIC ${PROJECT_DEPS_INCLUDE_DIRS}) +target_include_directories("service-version-multiwatch-manager-impolite" PUBLIC "${CMAKE_SOURCE_DIR}/src") + +# service-version-multiwatch-service + +set_source_files_properties(service-version-multiwatch-service.c PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS}) +add_library("service-version-multiwatch-service" SHARED service-version-multiwatch-service.c) +target_include_directories("service-version-multiwatch-service" PUBLIC ${PROJECT_DEPS_INCLUDE_DIRS}) +target_include_directories("service-version-multiwatch-service" PUBLIC "${CMAKE_SOURCE_DIR}/src") + +# test-desktop-shortcuts + +set_source_files_properties(test-desktop-shortcuts.c PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS}) +add_executable("test-desktop-shortcuts" test-desktop-shortcuts.c) +target_compile_definitions("test-desktop-shortcuts" PUBLIC BUILD_DIR="${CMAKE_CURRENT_BINARY_DIR}") +target_compile_definitions("test-desktop-shortcuts" PUBLIC SRCDIR="${CMAKE_CURRENT_SOURCE_DIR}") +target_include_directories("test-desktop-shortcuts" PUBLIC ${PROJECT_DEPS_INCLUDE_DIRS}) +target_include_directories("test-desktop-shortcuts" PUBLIC "${CMAKE_SOURCE_DIR}/src") +target_link_libraries("test-desktop-shortcuts" ${PROJECT_DEPS_LIBRARIES} -layatana-indicator3) +target_link_directories("test-desktop-shortcuts" PUBLIC "${CMAKE_BINARY_DIR}/src") +add_dependencies("test-desktop-shortcuts" "ayatana-indicator3") +add_test("test-desktop-shortcuts" "test-desktop-shortcuts") + +# test-indicator-ng + +set_source_files_properties(test-indicator-ng.c PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS}) +add_executable("test-indicator-ng" test-indicator-ng.c) +target_compile_definitions("test-indicator-ng" PUBLIC BUILD_DIR="${CMAKE_CURRENT_BINARY_DIR}") +target_compile_definitions("test-indicator-ng" PUBLIC SRCDIR="${CMAKE_CURRENT_SOURCE_DIR}") +target_include_directories("test-indicator-ng" PUBLIC ${PROJECT_DEPS_INCLUDE_DIRS}) +target_include_directories("test-indicator-ng" PUBLIC "${CMAKE_SOURCE_DIR}/src") +target_link_libraries("test-indicator-ng" ${PROJECT_DEPS_LIBRARIES} -layatana-indicator3) +target_link_directories("test-indicator-ng" PUBLIC "${CMAKE_BINARY_DIR}/src") +add_dependencies("test-indicator-ng" "ayatana-indicator3") +add_test("test-indicator-ng" "test-indicator-ng") + +# test-loader + +set_source_files_properties(test-loader.c PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS}) +add_executable("test-loader" test-loader.c) +target_compile_definitions("test-loader" PUBLIC BUILD_DIR="${CMAKE_CURRENT_BINARY_DIR}") +target_include_directories("test-loader" PUBLIC ${PROJECT_DEPS_INCLUDE_DIRS}) +target_include_directories("test-loader" PUBLIC "${CMAKE_SOURCE_DIR}/src") +target_link_libraries("test-loader" ${PROJECT_DEPS_LIBRARIES} -layatana-indicator3) +target_link_directories("test-loader" PUBLIC "${CMAKE_BINARY_DIR}/src") +add_dependencies("test-loader" "ayatana-indicator3") +add_test("test-loader" "test-loader") diff --git a/tests/dummy-indicator-blank.c b/tests/dummy-indicator-blank.c index b085c52..e4711ef 100644 --- a/tests/dummy-indicator-blank.c +++ b/tests/dummy-indicator-blank.c @@ -21,7 +21,7 @@ License along with this library. If not, see */ -#include "src/indicator.h" +#include "indicator.h" INDICATOR_SET_VERSION diff --git a/tests/dummy-indicator-entry-func.h b/tests/dummy-indicator-entry-func.h index b5653c7..791b98b 100644 --- a/tests/dummy-indicator-entry-func.h +++ b/tests/dummy-indicator-entry-func.h @@ -26,8 +26,8 @@ License along with this library. If not, see #include #include -#include "src/indicator.h" -#include "src/indicator-object.h" +#include "indicator.h" +#include "indicator-object.h" G_BEGIN_DECLS diff --git a/tests/dummy-indicator-null.c b/tests/dummy-indicator-null.c index ee424d4..f306747 100644 --- a/tests/dummy-indicator-null.c +++ b/tests/dummy-indicator-null.c @@ -24,8 +24,8 @@ License along with this library. If not, see #include #include -#include "src/indicator.h" -#include "src/indicator-object.h" +#include "indicator.h" +#include "indicator-object.h" #define DUMMY_INDICATOR_NULL_TYPE (dummy_indicator_null_get_type ()) #define DUMMY_INDICATOR_NULL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DUMMY_INDICATOR_NULL_TYPE, DummyIndicatorNull)) diff --git a/tests/dummy-indicator-signaler.c b/tests/dummy-indicator-signaler.c index c963c6d..5caec72 100644 --- a/tests/dummy-indicator-signaler.c +++ b/tests/dummy-indicator-signaler.c @@ -23,8 +23,8 @@ License along with this library. If not, see #include #include -#include "src/indicator.h" -#include "src/indicator-object.h" +#include "indicator.h" +#include "indicator-object.h" #define DUMMY_INDICATOR_SIGNALER_TYPE (dummy_indicator_signaler_get_type ()) #define DUMMY_INDICATOR_SIGNALER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DUMMY_INDICATOR_SIGNALER_TYPE, DummyIndicatorSignaler)) diff --git a/tests/dummy-indicator-simple.c b/tests/dummy-indicator-simple.c index d62c991..07d56ed 100644 --- a/tests/dummy-indicator-simple.c +++ b/tests/dummy-indicator-simple.c @@ -23,8 +23,8 @@ License along with this library. If not, see #include #include -#include "src/indicator.h" -#include "src/indicator-object.h" +#include "indicator.h" +#include "indicator-object.h" #define DUMMY_INDICATOR_SIMPLE_TYPE (dummy_indicator_simple_get_type ()) #define DUMMY_INDICATOR_SIMPLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DUMMY_INDICATOR_SIMPLE_TYPE, DummyIndicatorSimple)) diff --git a/tests/dummy-indicator-visible.c b/tests/dummy-indicator-visible.c index a9dbaf7..dc06abc 100644 --- a/tests/dummy-indicator-visible.c +++ b/tests/dummy-indicator-visible.c @@ -23,8 +23,8 @@ License along with this library. If not, see #include #include -#include "src/indicator.h" -#include "src/indicator-object.h" +#include "indicator.h" +#include "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)) diff --git a/tests/service-manager-connect-service.c b/tests/service-manager-connect-service.c index 85c353e..0193c2c 100644 --- a/tests/service-manager-connect-service.c +++ b/tests/service-manager-connect-service.c @@ -22,7 +22,7 @@ License along with this library. If not, see #include -#include "src/indicator-service.h" +#include "indicator-service.h" static GMainLoop * mainloop = NULL; static gboolean passed = FALSE; diff --git a/tests/service-manager-connect.c b/tests/service-manager-connect.c index 902efaa..46fbe54 100644 --- a/tests/service-manager-connect.c +++ b/tests/service-manager-connect.c @@ -22,7 +22,7 @@ License along with this library. If not, see #include -#include "src/indicator-service-manager.h" +#include "indicator-service-manager.h" static GMainLoop * mainloop = NULL; static gboolean passed = FALSE; diff --git a/tests/service-manager-no-connect.c b/tests/service-manager-no-connect.c index 5f81118..2e52e3d 100644 --- a/tests/service-manager-no-connect.c +++ b/tests/service-manager-no-connect.c @@ -22,7 +22,7 @@ License along with this library. If not, see #include -#include "src/indicator-service-manager.h" +#include "indicator-service-manager.h" static GMainLoop * mainloop = NULL; static gboolean passed = FALSE; diff --git a/tests/service-manager-nostart-connect.c b/tests/service-manager-nostart-connect.c index a0b09c3..77d3691 100644 --- a/tests/service-manager-nostart-connect.c +++ b/tests/service-manager-nostart-connect.c @@ -22,7 +22,7 @@ License along with this library. If not, see #include -#include "src/indicator-service-manager.h" +#include "indicator-service-manager.h" static GMainLoop * mainloop = NULL; static gboolean passed = FALSE; diff --git a/tests/service-shutdown-timeout.c b/tests/service-shutdown-timeout.c index 5407c27..526be0f 100644 --- a/tests/service-shutdown-timeout.c +++ b/tests/service-shutdown-timeout.c @@ -22,7 +22,7 @@ License along with this library. If not, see #include -#include "src/indicator-service.h" +#include "indicator-service.h" static GMainLoop * mainloop = NULL; static gboolean passed = FALSE; diff --git a/tests/service-version-bad-service.c b/tests/service-version-bad-service.c index e5e3287..a991f7d 100644 --- a/tests/service-version-bad-service.c +++ b/tests/service-version-bad-service.c @@ -22,7 +22,7 @@ License along with this library. If not, see #include -#include "src/indicator-service.h" +#include "indicator-service.h" #include "service-version-values.h" static GMainLoop * mainloop = NULL; diff --git a/tests/service-version-good-service.c b/tests/service-version-good-service.c index 7a4abbb..b310c76 100644 --- a/tests/service-version-good-service.c +++ b/tests/service-version-good-service.c @@ -22,7 +22,7 @@ License along with this library. If not, see #include -#include "src/indicator-service.h" +#include "indicator-service.h" #include "service-version-values.h" static GMainLoop * mainloop = NULL; diff --git a/tests/service-version-manager.c b/tests/service-version-manager.c index 85e1b37..f6848da 100644 --- a/tests/service-version-manager.c +++ b/tests/service-version-manager.c @@ -22,7 +22,7 @@ License along with this library. If not, see #include -#include "src/indicator-service-manager.h" +#include "indicator-service-manager.h" #include "service-version-values.h" static GMainLoop * mainloop = NULL; diff --git a/tests/service-version-multiwatch-manager-impolite.c b/tests/service-version-multiwatch-manager-impolite.c index c22736e..19a5639 100644 --- a/tests/service-version-multiwatch-manager-impolite.c +++ b/tests/service-version-multiwatch-manager-impolite.c @@ -22,7 +22,7 @@ License along with this library. If not, see #include -#include "src/indicator-service-manager.h" +#include "indicator-service-manager.h" #include "service-version-values.h" static GMainLoop * mainloop = NULL; diff --git a/tests/service-version-multiwatch-manager.c b/tests/service-version-multiwatch-manager.c index 32a0079..385e17a 100644 --- a/tests/service-version-multiwatch-manager.c +++ b/tests/service-version-multiwatch-manager.c @@ -22,7 +22,7 @@ License along with this library. If not, see #include -#include "src/indicator-service-manager.h" +#include "indicator-service-manager.h" #include "service-version-values.h" static GMainLoop * mainloop = NULL; diff --git a/tests/service-version-multiwatch-service.c b/tests/service-version-multiwatch-service.c index ffad013..dc7d203 100644 --- a/tests/service-version-multiwatch-service.c +++ b/tests/service-version-multiwatch-service.c @@ -22,7 +22,7 @@ License along with this library. If not, see #include -#include "src/indicator-service.h" +#include "indicator-service.h" #include "service-version-values.h" static GMainLoop * mainloop = NULL; diff --git a/tests/test-desktop-shortcuts.c b/tests/test-desktop-shortcuts.c index 02e313a..7c870b9 100644 --- a/tests/test-desktop-shortcuts.c +++ b/tests/test-desktop-shortcuts.c @@ -21,7 +21,7 @@ License along with this library. If not, see */ #include -#include "src/indicator-desktop-shortcuts.h" +#include "indicator-desktop-shortcuts.h" /* Basic object creation and destruction. Stop big f*** ups here. */ diff --git a/tests/test-indicator-ng.c b/tests/test-indicator-ng.c index 80bbbb1..416c8da 100644 --- a/tests/test-indicator-ng.c +++ b/tests/test-indicator-ng.c @@ -1,5 +1,5 @@ -#include "src/indicator-ng.h" +#include "indicator-ng.h" static void indicator_ng_test_func (gconstpointer user_data) diff --git a/tests/test-loader.c b/tests/test-loader.c index c1e4b6d..d1288cc 100644 --- a/tests/test-loader.c +++ b/tests/test-loader.c @@ -21,7 +21,7 @@ License along with this library. If not, see */ #include -#include "src/indicator-object.h" +#include "indicator-object.h" #include "dummy-indicator-entry-func.h" @@ -47,7 +47,7 @@ entry_func_swap (IndicatorObject * io) void test_loader_entry_func_window (void) { - IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-entry-func.so"); + IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/libdummy-indicator-entry-func.so"); g_assert(object != NULL); DummyIndicatorEntryFunc * entryfunc = (DummyIndicatorEntryFunc *)(object); @@ -72,7 +72,7 @@ test_loader_entry_func_window (void) void test_loader_entry_funcs (void) { - IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-entry-func.so"); + IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/libdummy-indicator-entry-func.so"); g_assert(object != NULL); DummyIndicatorEntryFunc * entryfunc = (DummyIndicatorEntryFunc *)(object); @@ -115,7 +115,7 @@ entry_move_cb (IndicatorObject * io, IndicatorObjectEntry * entry, gint old, gin void test_loader_filename_dummy_signaler (void) { - IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-signaler.so"); + IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/libdummy-indicator-signaler.so"); g_assert(object != NULL); IndicatorObjectEntry *added_entry, *moved_entry, *removed_entry; @@ -180,7 +180,7 @@ 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"); + IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/libdummy-indicator-visible.so"); g_assert(object != NULL); // create our local parent widgetry @@ -245,7 +245,7 @@ test_loader_filename_dummy_visible (void) void test_loader_filename_dummy_simple_location (void) { - IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-simple.so"); + IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/libdummy-indicator-simple.so"); g_assert(object != NULL); GList * entries = indicator_object_get_entries(object); @@ -266,7 +266,7 @@ test_loader_filename_dummy_simple_location (void) void test_loader_filename_dummy_simple_accessors (void) { - IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-simple.so"); + IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/libdummy-indicator-simple.so"); g_assert(object != NULL); g_assert(indicator_object_get_entries(object) != NULL); @@ -279,7 +279,7 @@ test_loader_filename_dummy_simple_accessors (void) void test_loader_filename_dummy_simple (void) { - IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-simple.so"); + IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/libdummy-indicator-simple.so"); g_assert(object != NULL); gboolean unreffed = FALSE; @@ -294,7 +294,7 @@ test_loader_filename_dummy_simple (void) void test_loader_filename_dummy_blank (void) { - IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-blank.so"); + IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/libdummy-indicator-blank.so"); g_assert(object == NULL); return; } @@ -302,7 +302,7 @@ test_loader_filename_dummy_blank (void) void test_loader_filename_dummy_null (void) { - IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/.libs/libdummy-indicator-null.so"); + IndicatorObject * object = indicator_object_new_from_file(BUILD_DIR "/libdummy-indicator-null.so"); g_assert(object != NULL); g_assert(indicator_object_get_entries(object) == NULL); g_object_unref(G_OBJECT(object)); diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt new file mode 100644 index 0000000..4120f31 --- /dev/null +++ b/tools/CMakeLists.txt @@ -0,0 +1,8 @@ +# ayatana-indicator-loader3 + +set_source_files_properties(indicator-loader.c PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS}) +add_executable("ayatana-indicator-loader3" indicator-loader.c) +target_include_directories("ayatana-indicator-loader3" PUBLIC ${PROJECT_DEPS_INCLUDE_DIRS}) +target_include_directories("ayatana-indicator-loader3" PUBLIC "${CMAKE_SOURCE_DIR}/src") +target_link_libraries("ayatana-indicator-loader3" ${PROJECT_DEPS_LIBRARIES} "-L${CMAKE_BINARY_DIR}/src" -layatana-indicator3) +add_dependencies("ayatana-indicator-loader3" "ayatana-indicator3") diff --git a/tools/indicator-loader.c b/tools/indicator-loader.c index ad4fdf4..50b5143 100644 --- a/tools/indicator-loader.c +++ b/tools/indicator-loader.c @@ -25,9 +25,9 @@ #include #include -#include "src/indicator-object.h" +#include "indicator-object.h" #if GTK_CHECK_VERSION (3,0,0) - #include "src/indicator-ng.h" + #include "indicator-ng.h" #endif static GHashTable * entry_to_menu_item = NULL; -- cgit v1.2.3 From e20daf604e81ebd473c74dedda725bca27cd8dd1 Mon Sep 17 00:00:00 2001 From: Robert Tari Date: Thu, 11 Feb 2021 15:29:17 +0100 Subject: Remove Automake-related files --- Makefile.am | 22 ---- Makefile.am.coverage | 50 --------- Makefile.am.marshal | 44 -------- autogen.sh | 10 -- configure.ac | 218 ------------------------------------ data/Makefile.am | 5 - helper/test-loader-build | 3 - helper/test-loader.c | 18 --- m4/gcov.m4 | 86 -------------- src/Makefile.am | 149 ------------------------ src/ayatana-indicator-0.4.pc.in.in | 17 --- src/ayatana-indicator3-0.4.pc.in.in | 16 --- 12 files changed, 638 deletions(-) delete mode 100644 Makefile.am delete mode 100644 Makefile.am.coverage delete mode 100644 Makefile.am.marshal delete mode 100755 autogen.sh delete mode 100644 configure.ac delete mode 100644 data/Makefile.am delete mode 100755 helper/test-loader-build delete mode 100644 helper/test-loader.c delete mode 100644 m4/gcov.m4 delete mode 100644 src/Makefile.am delete mode 100644 src/ayatana-indicator-0.4.pc.in.in delete mode 100644 src/ayatana-indicator3-0.4.pc.in.in diff --git a/Makefile.am b/Makefile.am deleted file mode 100644 index bd052fd..0000000 --- a/Makefile.am +++ /dev/null @@ -1,22 +0,0 @@ -ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS} - -SUBDIRS = \ - data \ - src \ - tools - -tools: libayatana-indicator - -if WANT_TESTS -SUBDIRS += \ - tests - -tests: libayatana-indicator -endif - -DISTCHECK_CONFIGURE_FLAGS = --disable-deprecations --disable-silent-rules --with-gtk=3 - -DISTCLEANFILES = \ - libayatana-indicator-*.tar.gz - -include $(top_srcdir)/Makefile.am.coverage diff --git a/Makefile.am.coverage b/Makefile.am.coverage deleted file mode 100644 index dc3b9c8..0000000 --- a/Makefile.am.coverage +++ /dev/null @@ -1,50 +0,0 @@ - -# Coverage targets - -EXTRA_DIST = trim-lcov.py - -.PHONY: clean-gcno clean-gcda \ - coverage-html generate-coverage-html clean-coverage-html \ - coverage-gcovr generate-coverage-gcovr clean-coverage-gcovr - -clean-local: clean-gcno clean-coverage-html clean-coverage-gcovr - -if HAVE_GCOV - -clean-gcno: - @echo Removing old coverage instrumentation - -find -name '*.gcno' -print | xargs -r rm - -clean-gcda: - @echo Removing old coverage results - -find -name '*.gcda' -print | xargs -r rm - -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 --no-checksum --compat-libtool | $(top_srcdir)/trim-lcov.py > coverage.info - 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 - -if HAVE_GCOVR - -coverage-gcovr: clean-gcda - -$(MAKE) $(AM_MAKEFLAGS) -k check - $(MAKE) $(AM_MAKEFLAGS) generate-coverage-gcovr - -generate-coverage-gcovr: - @echo Generating coverage GCOVR report - $(GCOVR) -x -r $(top_builddir) -o $(top_builddir)/coverage.xml - -clean-coverage-gcovr: clean-gcda - -rm -rf $(top_builddir)/coverage.xml - -endif # HAVE_GCOVR - -endif # HAVE_GCOV diff --git a/Makefile.am.marshal b/Makefile.am.marshal deleted file mode 100644 index a1e1070..0000000 --- a/Makefile.am.marshal +++ /dev/null @@ -1,44 +0,0 @@ -# Rules for generating marshal files using glib-genmarshal -# -# Define: -# glib_marshal_list = marshal list file -# glib_marshal_prefix = prefix for marshal functions -# -# before including Makefile.am.marshal. You will also need to have -# the following targets already defined: -# -# CLEANFILES -# DISTCLEANFILES -# BUILT_SOURCES -# EXTRA_DIST -# -# Author: Emmanuele Bassi - -marshal_h = $(glib_marshal_list:.list=.h) -marshal_c = $(glib_marshal_list:.list=.c) - -CLEANFILES += stamp-marshal -DISTCLEANFILES += $(marshal_h) $(marshal_c) -BUILT_SOURCES += $(marshal_h) $(marshal_c) -EXTRA_DIST += $(glib_marshal_list) - -stamp-marshal: $(glib_marshal_list) - $(QUIET_GEN)$(GLIB_GENMARSHAL) \ - --prefix=$(glib_marshal_prefix) \ - --header \ - $(srcdir)/$(glib_marshal_list) > xgen-mh \ - && (cmp -s xgen-mh $(marshal_h) || cp -f xgen-mh $(marshal_h)) \ - && rm -f xgen-mh \ - && echo timestamp > $(@F) - -$(marshal_h): stamp-marshal - @true - -$(marshal_c): $(marshal_h) - $(QUIET_GEN)(echo "#include \"$(marshal_h)\"" ; \ - $(GLIB_GENMARSHAL) \ - --prefix=$(glib_marshal_prefix) \ - --body \ - $(srcdir)/$(glib_marshal_list)) > xgen-mc \ - && cp xgen-mc $(marshal_c) \ - && rm -f xgen-mc diff --git a/autogen.sh b/autogen.sh deleted file mode 100755 index 472f875..0000000 --- a/autogen.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -PKG_NAME="libayatana-indicator" - -which mate-autogen || { - echo "You need mate-common from https://git.mate-desktop.org/mate-common." - exit 1 -} - -. mate-autogen diff --git a/configure.ac b/configure.ac deleted file mode 100644 index 9ba72ec..0000000 --- a/configure.ac +++ /dev/null @@ -1,218 +0,0 @@ -AC_INIT([libayatana-indicator], - [0.8.4], - [https://github.com/ArcticaProject/libayatana-indicator/issues], - [libayatana-indicator], - [https://github.com/ArcticaProject/libayatana-indicator]) - -AC_PREREQ([2.64]) - -AC_CONFIG_HEADERS([config.h]) -AC_CONFIG_MACRO_DIR([m4]) -AC_CONFIG_AUX_DIR([build-aux]) -AC_SUBST([ac_aux_dir]) - -AM_INIT_AUTOMAKE([1.11 -Wall tar-pax]) - -AM_MAINTAINER_MODE([enable]) - -AM_SILENT_RULES([yes]) - -# Check for programs -AC_PROG_CC -AM_PROG_CC_C_O -AM_PROG_AR - -# Initialize libtool -LT_PREREQ([2.2]) -LT_INIT - -# Upstream's pkg.m4 (since 0.27) offers this now, but define our own -# compatible version in case the local version of pkgconfig isn't new enough. -# https://bugs.freedesktop.org/show_bug.cgi?id=48743 -m4_ifdef([PKG_INSTALLDIR], [PKG_INSTALLDIR], - [AC_ARG_WITH([pkgconfigdir], - [AS_HELP_STRING([--with-pkgconfigdir], - [install directory for nx-x11.pc pkg-config file])], - [],[with_pkgconfigdir='$(libdir)/pkgconfig']) - AC_SUBST([pkgconfigdir], [${with_pkgconfigdir}])]) - -# Required when PKG_CHECK_MODULES called within an if statement -PKG_PROG_PKG_CONFIG - - -AC_PATH_PROG([GLIB_MKENUMS], [glib-mkenums]) -AC_PATH_PROG([GLIB_GENMARSHAL], [glib-genmarshal]) - - -AC_ARG_ENABLE([deprecations], - [AS_HELP_STRING([--enable-deprecations], - [allow deprecated API usage @<:@default=yes@:>@])], - [], - [enable_deprecations=yes]) -AS_IF([test "x$enable_deprecations" = xno], - [CFLAGS="$CFLAGS -DG_DISABLE_DEPRECATED -DGDK_DISABLE_DEPRECATED -DGDK_PIXBUF_DISABLE_DEPRECATED -DGTK_DISABLE_DEPRECATED -DGSEAL_ENABLE -DGTK_DISABLE_SINGLE_INCLUDES"] -) - -AC_ARG_ENABLE([ido], - [AS_HELP_STRING([--enable-ido], - [enable indicator widget loader @<:@default=yes@:>@])], - [], - [enable_ido=yes]) - -############################## -# Dependencies -############################## - -GTK_REQUIRED_VERSION=2.18 -GTK3_REQUIRED_VERSION=3.6 -GIO_UNIX_REQUIRED_VERSION=2.37 -IDO_REQUIRED_VERSION=0.8.0 - - -AC_ARG_WITH([gtk], - [AS_HELP_STRING([--with-gtk], - [Which version of gtk to use @<:@default=3@:>@])], - [], - [with_gtk=3]) -AS_IF([test "x$with_gtk" = x3], - [PKG_CHECK_MODULES(LIBINDICATOR, gtk+-3.0 >= $GTK3_REQUIRED_VERSION - gmodule-2.0 - gio-unix-2.0 >= $GIO_UNIX_REQUIRED_VERSION) - AS_IF([test "x$enable_ido" = xyes], [ - PKG_CHECK_MODULES(LIBINDICATOR_IDO, libayatana-ido3-0.4 >= $IDO_REQUIRED_VERSION) - ]) - ], - [test "x$with_gtk" = x2], - [PKG_CHECK_MODULES(LIBINDICATOR, gtk+-2.0 >= $GTK_REQUIRED_VERSION - gmodule-2.0 - gio-unix-2.0 >= $GIO_UNIX_REQUIRED_VERSION) - ], - [AC_MSG_FAILURE([Value for --with-gtk was neither 2 nor 3])] -) - -AM_CONDITIONAL(USE_GTK3, [test "x$with_gtk" = x3]) -AM_CONDITIONAL(USE_IDO, [test "$enable_ido" = "yes"]) - -LT_LIB_M -AC_SUBST(LIBM) - -############################## -# Custom Junk -############################## - -AC_DEFUN([AC_DEFINE_PATH], [ - test "x$prefix" = xNONE && prefix="$ac_default_prefix" - test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' - ac_define_path=`eval echo [$]$2` - ac_define_path=`eval echo [$]ac_define_path` - $1="$ac_define_path" - AC_SUBST($1) - ifelse($3, , - AC_DEFINE_UNQUOTED($1, "$ac_define_path"), - AC_DEFINE_UNQUOTED($1, "$ac_define_path", $3)) -]) - -############################## -# ./configure Flags messings -############################## - -cflags_set=${CFLAGS+set} -# find the actual value for $prefix that we'll end up with -REAL_PREFIX= -if test "x$prefix" = "xNONE"; then - REAL_PREFIX=$ac_default_prefix -else - REAL_PREFIX=$prefix -fi - -# Have to go $sysconfdir->$prefix/etc->/usr/local/etc -# if you actually know how to code shell then fix this :-) -SYSCONFDIR_TMP="$sysconfdir" -old_prefix=$prefix -prefix=$REAL_PREFIX -EXPANDED_SYSCONFDIR=`eval echo $SYSCONFDIR_TMP` -prefix=$old_prefix -AC_SUBST(EXPANDED_SYSCONFDIR) - -AC_DEFINE_PATH(PREFIX, "${prefix}", [prefix directory]) -AC_DEFINE_PATH(SYSCONFDIR, "${sysconfdir}", [system configuration dir]) -AC_DEFINE_PATH(LIBDIR, "${libdir}", [system configuration dir]) - -######################### -# Check for systemd -######################### -PKG_CHECK_MODULES(SYSTEMD, systemd, - [has_systemd=yes], - [] -) -if test "x$has_systemd" = "xyes"; then - SYSTEMD_USERDIR=`$PKG_CONFIG --variable=systemduserunitdir systemd` - AC_SUBST(SYSTEMD_USERDIR) - AC_DEFINE(HAVE_SYSTEMD, 1, [create ayatana-indicators-pre.target for systemd]) -fi - -######################### -# 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 -######################### -AC_ARG_ENABLE([debug], - AS_HELP_STRING([--enable-debug],[build with debug symbols]),, - [enable_debug=no]) - -if test "x$enable_debug" = "xyes"; then - CFLAGS="-g $CFLAGS" - AC_DEFINE(ENABLE_DEBUG, 1, [build with extra debug information]) -fi - -AM_CONDITIONAL(ENABLE_DEBUG, test "$enable_debug" = "yes") - -########################### -# gcov coverage reporting -########################### -m4_include([m4/gcov.m4]) -AC_TDD_GCOV -AM_CONDITIONAL([HAVE_GCOV], [test "x$ac_cv_check_gcov" = xyes]) -AM_CONDITIONAL([HAVE_LCOV], [test "x$ac_cv_check_lcov" = xyes]) -AM_CONDITIONAL([HAVE_GCOVR], [test "x$ac_cv_check_gcovr" = xyes]) -AC_SUBST(COVERAGE_CFLAGS) -AC_SUBST(COVERAGE_CXXFLAGS) -AC_SUBST(COVERAGE_LDFLAGS) - -########################### -# Files -########################### - -AC_CONFIG_FILES([ -Makefile -data/Makefile -src/Makefile -src/ayatana-indicator-0.4.pc.in -src/ayatana-indicator3-0.4.pc.in -tests/Makefile -tools/Makefile -]) -AC_OUTPUT - -########################### -# Results -########################### - -AC_MSG_NOTICE([ - -Libindicator Configuration: - - Prefix: $prefix - GTK+ Version: $with_gtk - - Enable IDO loader: $enable_ido - Enable tests: $enable_tests - Enable debugging: $enable_debug - Coverage reporting: $use_gcov -]) diff --git a/data/Makefile.am b/data/Makefile.am deleted file mode 100644 index c4b1255..0000000 --- a/data/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ -#if defined(HAVE_SYSTEMD) -systemd_DATA = ayatana-indicators.target -systemddir = $(SYSTEMD_USERDIR) -EXTRA_DIST = $(systemd_DATA) -#endif diff --git a/helper/test-loader-build b/helper/test-loader-build deleted file mode 100755 index fa1e006..0000000 --- a/helper/test-loader-build +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -gcc `pkg-config --cflags --libs gtk+-2.0` -I../libindicator/ test-loader.c ../libindicator/indicator-image-helper.c -o test-loader diff --git a/helper/test-loader.c b/helper/test-loader.c deleted file mode 100644 index 6a06248..0000000 --- a/helper/test-loader.c +++ /dev/null @@ -1,18 +0,0 @@ - -#include -#include "indicator-image-helper.h" - -int -main (int argv, char * argc[]) -{ - gtk_init(&argv, &argc); - - GtkImage * image = indicator_image_helper(argc[1]); - - GdkPixbuf * pixbuf = gtk_image_get_pixbuf(image); - - g_debug("Pixbuf width: %d", gdk_pixbuf_get_width(pixbuf)); - g_debug("Pixbuf height: %d", gdk_pixbuf_get_height(pixbuf)); - - return; -} diff --git a/m4/gcov.m4 b/m4/gcov.m4 deleted file mode 100644 index 3163584..0000000 --- a/m4/gcov.m4 +++ /dev/null @@ -1,86 +0,0 @@ -# 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_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) - - 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 - - ac_cv_check_gcov=yes - ac_cv_check_lcov=yes - - # 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" - - # Check availability of gcovr - AC_CHECK_PROG(GCOVR, gcovr, gcovr) - if test -z "$GCOVR"; then - ac_cv_check_gcovr=no - else - ac_cv_check_gcovr=yes - fi - -fi -]) # AC_TDD_GCOV diff --git a/src/Makefile.am b/src/Makefile.am deleted file mode 100644 index 4933c71..0000000 --- a/src/Makefile.am +++ /dev/null @@ -1,149 +0,0 @@ -if USE_GTK3 -VER=3 -lib_LTLIBRARIES = libayatana-indicator3.la -else -VER= -lib_LTLIBRARIES = libayatana-indicator.la -GTK_DISABLE_DEPRECATED = -DGTK_DISABLE_DEPRECATED -endif - -BUILT_SOURCES = indicator-object-enum-types.h indicator-object-enum-types.c -CLEANFILES = -DISTCLEANFILES = -EXTRA_DIST = \ - ayatana-indicator3-0.$(INDICATOR_API_VERSION).pc.in.in \ - ayatana-indicator-0.$(INDICATOR_API_VERSION).pc.in.in - -INDICATOR_ABI_VERSION = 7 -INDICATOR_API_VERSION = 4 - -%.pc: %.pc.in - sed \ - -e "s|\@indicator_api_version\@|$(INDICATOR_API_VERSION)|" \ - -e "s|\@indicator_abi_version\@|$(INDICATOR_ABI_VERSION)|" \ - $< > $@ - -CLEANFILES += ayatana-indicator$(VER)-0.$(INDICATOR_API_VERSION).pc - -include $(top_srcdir)/Makefile.am.marshal - -libayatana_indicatorincludedir=$(includedir)/libayatana-indicator$(VER)-0.$(INDICATOR_API_VERSION)/libayatana-indicator - -indicator_headers = \ - indicator.h \ - indicator-desktop-shortcuts.h \ - indicator-image-helper.h \ - indicator-object.h \ - indicator-service.h \ - indicator-service-manager.h - -if USE_GTK3 -indicator_headers += \ - indicator-ng.h -endif - -libayatana_indicatorinclude_HEADERS = \ - $(indicator_headers) - -libayatana_indicator_la_SOURCES = \ - $(indicator_headers) \ - dbus-shared.h \ - gen-indicator-service.xml.h \ - gen-indicator-service.xml.c \ - indicator-object.c \ - indicator-object-enum-types.c \ - indicator-desktop-shortcuts.c \ - indicator-image-helper.c \ - indicator-object-marshal.h \ - indicator-object-marshal.c \ - indicator-service.c \ - indicator-service-manager.c - -if USE_GTK3 -libayatana_indicator_la_SOURCES += \ - indicator-ng.c -endif - -libayatana_indicator_la_CFLAGS = \ - $(LIBINDICATOR_CFLAGS) \ - $(LIBINDICATOR_IDO_CFLAGS) \ - $(COVERAGE_CFLAGS) \ - $(GTK_DISABLE_DEPRECATED) \ - -DG_LOG_DOMAIN=\"libayatana-indicator\" \ - -Wall -Wno-error=deprecated-declarations - -libayatana_indicator_la_LIBADD = \ - $(LIBINDICATOR_LIBS) \ - $(LIBINDICATOR_IDO_LIBS) \ - $(LIBM) - -libayatana_indicator_la_LDFLAGS = \ - $(COVERAGE_LDFLAGS) \ - -version-info $(INDICATOR_ABI_VERSION):0:0 \ - -no-undefined \ - -export-symbols-regex "^[^_].*" - -# We duplicate these here because Automake won't let us use $(VER) on the left hand side. -# Since we carefully use $(VER) in the right hand side above, we can assign the same values. -# Only one version of the library is every compiled at the same time, so it is safe to reuse -# the right hand sides like this. -libayatana_indicator3includedir = $(libayatana_indicatorincludedir) -libayatana_indicator3include_HEADERS = $(indicator_headers) -libayatana_indicator3_la_SOURCES = $(libayatana_indicator_la_SOURCES) -libayatana_indicator3_la_CFLAGS = $(libayatana_indicator_la_CFLAGS) -libayatana_indicator3_la_LIBADD = $(libayatana_indicator_la_LIBADD) -libayatana_indicator3_la_LDFLAGS = $(libayatana_indicator_la_LDFLAGS) - -pkgconfig_DATA = ayatana-indicator$(VER)-0.$(INDICATOR_API_VERSION).pc -pkgconfigdir = $(libdir)/pkgconfig - -glib_marshal_list = indicator-object-marshal.list -glib_marshal_prefix = _indicator_object_marshal - -indicator-object-enum-types.h: s-enum-types-h - @true -s-enum-types-h: $(indicator_headers) - ( cd $(srcdir) && $(GLIB_MKENUMS) --template $(abs_srcdir)/indicator-object-enum-types.h.template \ - $(indicator_headers) ) >> tmp-indicator-object-enum-types.h \ - && (cmp -s tmp-indicator-object-enum-types.h indicator-object-enum-types.h || cp tmp-indicator-object-enum-types.h indicator-object-enum-types.h ) \ - && rm -f tmp-indicator-object-enum-types.h && echo timestamp > $(@F) - -indicator-object-enum-types.c: s-enum-types-c - @true -s-enum-types-c: $(indicator_headers) - ( cd $(srcdir) && $(GLIB_MKENUMS) --template $(abs_srcdir)/indicator-object-enum-types.c.template \ - $(indicator_headers) ) > tmp-indicator-object-enum-types.c \ - && (cmp -s tmp-indicator-object-enum-types.c indicator-object-enum-types.c || cp tmp-indicator-object-enum-types.c indicator-object-enum-types.c ) \ - && rm -f tmp-indicator-object-enum-types.c - -EXTRA_DIST += indicator-object-enum-types.h.template indicator-object-enum-types.c.template -CLEANFILES += \ - indicator-object-enum-types.h \ - indicator-object-enum-types.c \ - s-enum-types-h \ - s-enum-types-c - -################################## -# DBus Specs -################################## - -DBUS_SPECS = \ - indicator-service.xml - -gen-%.xml.h: %.xml - @echo "Building $@ from $<" - @echo "extern const char * _$(subst -,_,$(subst .,_,$(basename $(notdir $<))));" > $@ - -gen-%.xml.c: %.xml - @echo "Building $@ from $<" - echo "const char * _$(subst -,_,$(subst .,_,$(basename $(notdir $<)))) = " > $@ - @sed -e "s:\":\\\\\":g" -e s:^:\": -e s:\$$:\\\\n\": $< >> $@ - @echo ";" >> $@ - -BUILT_SOURCES += \ - gen-indicator-service.xml.h \ - gen-indicator-service.xml.c - -CLEANFILES += $(BUILT_SOURCES) - -EXTRA_DIST += $(DBUS_SPECS) diff --git a/src/ayatana-indicator-0.4.pc.in.in b/src/ayatana-indicator-0.4.pc.in.in deleted file mode 100644 index 02ff40d..0000000 --- a/src/ayatana-indicator-0.4.pc.in.in +++ /dev/null @@ -1,17 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -bindir=@bindir@ -includedir=@includedir@ - -indicatordir=${exec_prefix}/lib/ayatana-indicators/@indicator_abi_version@ -iconsdir=@datarootdir@/@PACKAGE@/icons/ - -Cflags: -I${includedir}/libayatana-indicator-0.@indicator_api_version@ -Requires: gtk+-2.0 -Libs: -layatana-indicator - -Name: libayatana-indicator -Description: libayatana-indicator. -Version: @VERSION@ - diff --git a/src/ayatana-indicator3-0.4.pc.in.in b/src/ayatana-indicator3-0.4.pc.in.in deleted file mode 100644 index ff0862e..0000000 --- a/src/ayatana-indicator3-0.4.pc.in.in +++ /dev/null @@ -1,16 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -bindir=@bindir@ -includedir=@includedir@ - -indicatordir=${exec_prefix}/lib/ayatana-indicators3/@indicator_abi_version@/ -iconsdir=@datarootdir@/@PACKAGE@/icons/ - -Cflags: -I${includedir}/libayatana-indicator3-0.@indicator_api_version@ -Requires: gtk+-3.0 -Libs: -layatana-indicator3 - -Name: libayatana-indicator3 -Description: libayatana-indicator3. -Version: @VERSION@ -- cgit v1.2.3 From c277aa68455b232c37a4c52b39e948a6ab0b0e11 Mon Sep 17 00:00:00 2001 From: Robert Tari Date: Wed, 10 Feb 2021 13:29:38 +0100 Subject: Append us to copyright headers --- tests/dummy-indicator-blank.c | 2 ++ tests/dummy-indicator-entry-func.h | 2 ++ tests/dummy-indicator-null.c | 2 ++ tests/dummy-indicator-signaler.c | 2 ++ tests/dummy-indicator-simple.c | 2 ++ tests/dummy-indicator-visible.c | 2 ++ tests/service-manager-connect-service.c | 2 ++ tests/service-manager-connect.c | 2 ++ tests/service-manager-no-connect.c | 2 ++ tests/service-manager-nostart-connect.c | 2 ++ tests/service-shutdown-timeout.c | 2 ++ tests/service-version-bad-service.c | 2 ++ tests/service-version-good-service.c | 2 ++ tests/service-version-manager.c | 2 ++ tests/service-version-multiwatch-manager-impolite.c | 2 ++ tests/service-version-multiwatch-manager.c | 2 ++ tests/service-version-multiwatch-service.c | 2 ++ tests/test-desktop-shortcuts.c | 2 ++ tests/test-loader.c | 2 ++ tools/indicator-loader.c | 2 ++ 20 files changed, 40 insertions(+) diff --git a/tests/dummy-indicator-blank.c b/tests/dummy-indicator-blank.c index e4711ef..e447d6c 100644 --- a/tests/dummy-indicator-blank.c +++ b/tests/dummy-indicator-blank.c @@ -2,9 +2,11 @@ Test for libindicator Copyright 2009 Canonical Ltd. +Copyright 2021 AyatanaIndicators Authors: Ted Gould + Robert Tari This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/tests/dummy-indicator-entry-func.h b/tests/dummy-indicator-entry-func.h index 791b98b..97b3a04 100644 --- a/tests/dummy-indicator-entry-func.h +++ b/tests/dummy-indicator-entry-func.h @@ -2,9 +2,11 @@ Test for libindicator Copyright 2012 Canonical Ltd. +Copyright 2021 AyatanaIndicators Authors: Ted Gould + Robert Tari This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/tests/dummy-indicator-null.c b/tests/dummy-indicator-null.c index f306747..adb05d3 100644 --- a/tests/dummy-indicator-null.c +++ b/tests/dummy-indicator-null.c @@ -2,9 +2,11 @@ Test for libindicator Copyright 2009 Canonical Ltd. +Copyright 2021 AyatanaIndicators Authors: Ted Gould + Robert Tari This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/tests/dummy-indicator-signaler.c b/tests/dummy-indicator-signaler.c index 5caec72..2fa3a8b 100644 --- a/tests/dummy-indicator-signaler.c +++ b/tests/dummy-indicator-signaler.c @@ -2,9 +2,11 @@ Test for libindicator Copyright 2009 Canonical Ltd. +Copyright 2021 AyatanaIndicators Authors: Ted Gould + Robert Tari This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/tests/dummy-indicator-simple.c b/tests/dummy-indicator-simple.c index 07d56ed..e42d1fe 100644 --- a/tests/dummy-indicator-simple.c +++ b/tests/dummy-indicator-simple.c @@ -2,9 +2,11 @@ Test for libindicator Copyright 2009 Canonical Ltd. +Copyright 2021 AyatanaIndicators Authors: Ted Gould + Robert Tari This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/tests/dummy-indicator-visible.c b/tests/dummy-indicator-visible.c index dc06abc..639f7c8 100644 --- a/tests/dummy-indicator-visible.c +++ b/tests/dummy-indicator-visible.c @@ -2,9 +2,11 @@ Test for libindicator Copyright 2012 Canonical Ltd. +Copyright 2021 AyatanaIndicators Authors: Charles Kerr + Robert Tari This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/tests/service-manager-connect-service.c b/tests/service-manager-connect-service.c index 0193c2c..a17bada 100644 --- a/tests/service-manager-connect-service.c +++ b/tests/service-manager-connect-service.c @@ -2,9 +2,11 @@ Test for libayatana-indicator Copyright 2009 Canonical Ltd. +Copyright 2021 AyatanaIndicators Authors: Ted Gould + Robert Tari This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/tests/service-manager-connect.c b/tests/service-manager-connect.c index 46fbe54..cf7cb6a 100644 --- a/tests/service-manager-connect.c +++ b/tests/service-manager-connect.c @@ -2,9 +2,11 @@ Test for libayatana-indicator Copyright 2009 Canonical Ltd. +Copyright 2021 AyatanaIndicators Authors: Ted Gould + Robert Tari This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/tests/service-manager-no-connect.c b/tests/service-manager-no-connect.c index 2e52e3d..5b5d389 100644 --- a/tests/service-manager-no-connect.c +++ b/tests/service-manager-no-connect.c @@ -2,9 +2,11 @@ Test for libayatana-indicator Copyright 2009 Canonical Ltd. +Copyright 2021 AyatanaIndicators Authors: Ted Gould + Robert Tari This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/tests/service-manager-nostart-connect.c b/tests/service-manager-nostart-connect.c index 77d3691..44a87a9 100644 --- a/tests/service-manager-nostart-connect.c +++ b/tests/service-manager-nostart-connect.c @@ -2,9 +2,11 @@ Test for libayatana-indicator Copyright 2009 Canonical Ltd. +Copyright 2021 AyatanaIndicators Authors: Ted Gould + Robert Tari This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/tests/service-shutdown-timeout.c b/tests/service-shutdown-timeout.c index 526be0f..338ebb6 100644 --- a/tests/service-shutdown-timeout.c +++ b/tests/service-shutdown-timeout.c @@ -2,9 +2,11 @@ Test for libayatana-indicator Copyright 2009 Canonical Ltd. +Copyright 2021 AyatanaIndicators Authors: Ted Gould + Robert Tari This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/tests/service-version-bad-service.c b/tests/service-version-bad-service.c index a991f7d..46574cb 100644 --- a/tests/service-version-bad-service.c +++ b/tests/service-version-bad-service.c @@ -2,9 +2,11 @@ Test for libayatana-indicator Copyright 2009 Canonical Ltd. +Copyright 2021 AyatanaIndicators Authors: Ted Gould + Robert Tari This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/tests/service-version-good-service.c b/tests/service-version-good-service.c index b310c76..3257ce2 100644 --- a/tests/service-version-good-service.c +++ b/tests/service-version-good-service.c @@ -2,9 +2,11 @@ Test for libayatana-indicator Copyright 2009 Canonical Ltd. +Copyright 2021 AyatanaIndicators Authors: Ted Gould + Robert Tari This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/tests/service-version-manager.c b/tests/service-version-manager.c index f6848da..07c6173 100644 --- a/tests/service-version-manager.c +++ b/tests/service-version-manager.c @@ -2,9 +2,11 @@ Test for libayatana-indicator Copyright 2009 Canonical Ltd. +Copyright 2021 AyatanaIndicators Authors: Ted Gould + Robert Tari This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/tests/service-version-multiwatch-manager-impolite.c b/tests/service-version-multiwatch-manager-impolite.c index 19a5639..97678d3 100644 --- a/tests/service-version-multiwatch-manager-impolite.c +++ b/tests/service-version-multiwatch-manager-impolite.c @@ -2,9 +2,11 @@ Test for libayatana-indicator Copyright 2009 Canonical Ltd. +Copyright 2021 AyatanaIndicators Authors: Ted Gould + Robert Tari This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/tests/service-version-multiwatch-manager.c b/tests/service-version-multiwatch-manager.c index 385e17a..7f82e82 100644 --- a/tests/service-version-multiwatch-manager.c +++ b/tests/service-version-multiwatch-manager.c @@ -2,9 +2,11 @@ Test for libayatana-indicator Copyright 2009 Canonical Ltd. +Copyright 2021 AyatanaIndicators Authors: Ted Gould + Robert Tari This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/tests/service-version-multiwatch-service.c b/tests/service-version-multiwatch-service.c index dc7d203..e1ca660 100644 --- a/tests/service-version-multiwatch-service.c +++ b/tests/service-version-multiwatch-service.c @@ -2,9 +2,11 @@ Test for libayatana-indicator Copyright 2009 Canonical Ltd. +Copyright 2021 AyatanaIndicators Authors: Ted Gould + Robert Tari This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/tests/test-desktop-shortcuts.c b/tests/test-desktop-shortcuts.c index 7c870b9..48a668d 100644 --- a/tests/test-desktop-shortcuts.c +++ b/tests/test-desktop-shortcuts.c @@ -2,9 +2,11 @@ Test for libayatana-indicator Copyright 2009 Canonical Ltd. +Copyright 2021 AyatanaIndicators Authors: Ted Gould + Robert Tari This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/tests/test-loader.c b/tests/test-loader.c index d1288cc..d6dabc5 100644 --- a/tests/test-loader.c +++ b/tests/test-loader.c @@ -2,9 +2,11 @@ Test for libindicator Copyright 2009 Canonical Ltd. +Copyright 2021 AyatanaIndicators Authors: Ted Gould + Robert Tari This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/tools/indicator-loader.c b/tools/indicator-loader.c index 50b5143..159b17b 100644 --- a/tools/indicator-loader.c +++ b/tools/indicator-loader.c @@ -3,11 +3,13 @@ * and during development of them. * * Copyright 2009 Canonical Ltd. + * Copyright 2021 AyatanaIndicators * * Authors: * Ted Gould * Lars Uebernickel * Charles Kerr + * Robert Tari * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License -- cgit v1.2.3