diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 36 | ||||
-rw-r--r-- | src/indicator-image-helper.c | 16 | ||||
-rw-r--r-- | src/indicator-ng.c | 31 | ||||
-rw-r--r-- | src/indicator-service.c | 835 | ||||
-rw-r--r-- | src/indicator.symbols | 6 |
5 files changed, 477 insertions, 447 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9a63eb8..aa6b9a2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,13 +6,21 @@ # indicator-service.h # indicator.h -install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/indicator-desktop-shortcuts.h" DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/libayatana-indicator3-0.4/libayatana-indicator") -install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/indicator-image-helper.h" DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/libayatana-indicator3-0.4/libayatana-indicator") -install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/indicator-ng.h" DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/libayatana-indicator3-0.4/libayatana-indicator") -install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/indicator-object.h" DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/libayatana-indicator3-0.4/libayatana-indicator") -install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/indicator-service-manager.h" DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/libayatana-indicator3-0.4/libayatana-indicator") -install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/indicator-service.h" DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/libayatana-indicator3-0.4/libayatana-indicator") -install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/indicator.h" DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/libayatana-indicator3-0.4/libayatana-indicator") +if (FLAVOUR_GTK3) + # libayatana-indicator3.so + set (ayatana_indicator_gtkver "ayatana-indicator3") +else() + # libayatana-indicator.so + set (ayatana_indicator_gtkver "ayatana-indicator") +endif() + +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/indicator-desktop-shortcuts.h" DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/lib${ayatana_indicator_gtkver}-0.${API_VERSION}/libayatana-indicator") +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/indicator-image-helper.h" DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/lib${ayatana_indicator_gtkver}-0.${API_VERSION}/libayatana-indicator") +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/indicator-ng.h" DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/lib${ayatana_indicator_gtkver}-0.${API_VERSION}/libayatana-indicator") +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/indicator-object.h" DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/lib${ayatana_indicator_gtkver}-0.${API_VERSION}/libayatana-indicator") +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/indicator-service-manager.h" DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/lib${ayatana_indicator_gtkver}-0.${API_VERSION}/libayatana-indicator") +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/indicator-service.h" DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/lib${ayatana_indicator_gtkver}-0.${API_VERSION}/libayatana-indicator") +install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/indicator.h" DESTINATION "${CMAKE_INSTALL_FULL_INCLUDEDIR}/lib${ayatana_indicator_gtkver}-0.${API_VERSION}/libayatana-indicator") set(HEADERS indicator.h @@ -123,25 +131,15 @@ string(APPEND GEN_INDICATOR_SERVICE_XML_C "\;") file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/gen-indicator-service.xml.c" ${GEN_INDICATOR_SERVICE_XML_C}) -if (FLAVOUR_GTK3) - # libayatana-indicator3.so - set (ayatana_indicator_gtkver "ayatana-indicator3") -else() - # libayatana-indicator.so - set (ayatana_indicator_gtkver "ayatana-indicator") -endif() - # libayatana-indicator{,3}.so -set_source_files_properties(${SOURCES} PROPERTIES COMPILE_FLAGS ${COMPILE_FLAGS}) add_library("${ayatana_indicator_gtkver}" SHARED ${SOURCES}) set_target_properties("${ayatana_indicator_gtkver}" PROPERTIES VERSION ${ABI_VERSION}.0.0 SOVERSION ${ABI_VERSION}) target_compile_definitions("${ayatana_indicator_gtkver}" PUBLIC DG_LOG_DOMAIN="libayatana-indicator") target_include_directories("${ayatana_indicator_gtkver}" PUBLIC ${PROJECT_DEPS_INCLUDE_DIRS}) target_include_directories("${ayatana_indicator_gtkver}" PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories("${ayatana_indicator_gtkver}" PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) +target_link_options("${ayatana_indicator_gtkver}" PRIVATE "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/indicator.symbols") target_link_libraries("${ayatana_indicator_gtkver}" ${PROJECT_DEPS_LIBRARIES} ${EXTRA_LIBS}) add_dependencies("${ayatana_indicator_gtkver}" "src-generated") -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/lib${ayatana_indicator_gtkver}.so" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}") -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/lib${ayatana_indicator_gtkver}.so.${ABI_VERSION}" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}") -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/lib${ayatana_indicator_gtkver}.so.${ABI_VERSION}.0.0" DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}") +install(TARGETS "${ayatana_indicator_gtkver}" LIBRARY DESTINATION "${CMAKE_INSTALL_FULL_LIBDIR}") diff --git a/src/indicator-image-helper.c b/src/indicator-image-helper.c index 2c0e244..4a22539 100644 --- a/src/indicator-image-helper.c +++ b/src/indicator-image-helper.c @@ -79,13 +79,15 @@ refresh_image (GtkImage * image) } 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); + GError* error = NULL; + GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file_at_scale(icon_filename, ICON_SIZE, ICON_SIZE, TRUE, &error); + if (pixbuf != NULL) { + /* Put the pixbuf on the image */ + gtk_image_set_from_pixbuf(image, pixbuf); + g_object_unref(G_OBJECT(pixbuf)); + } else { + g_error_free(error); + gtk_image_set_from_icon_name(image, "image-missing", ICON_SIZE); } } else if (G_IS_LOADABLE_ICON(icon_names)) { /* Build a pixbuf if needed */ diff --git a/src/indicator-ng.c b/src/indicator-ng.c index f057600..a94f57e 100644 --- a/src/indicator-ng.c +++ b/src/indicator-ng.c @@ -1,5 +1,6 @@ /* * Copyright 2013 Canonical Ltd. + * Copyright 2021-2022 Robert Tari * * 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 @@ -15,6 +16,7 @@ * * Authors: * Lars Uebernickel <lars.uebernickel@canonical.com> + * Robert Tari <robert@tari.in> */ #include "indicator-ng.h" @@ -39,9 +41,9 @@ struct _IndicatorNg gchar *secondary_action; gchar *submenu_action; gint position; - + gchar *sTooltip; guint name_watch_id; - + gboolean bMenuShown; GDBusConnection *session_bus; GActionGroup *actions; GMenuModel *menu; @@ -244,7 +246,7 @@ static gboolean indicator_ng_menu_insert_idos(IndicatorNg *self, GMenuModel *pSe GtkWidget *pMenuItemOld = GTK_WIDGET(g_list_nth_data(lMenuItems, nMenuItem)); const gchar *sName = gtk_widget_get_name(pMenuItemOld); - if (!g_str_equal(sName, sType)) + if (sName != NULL && !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); @@ -421,10 +423,26 @@ static void indicator_ng_menu_section_changed(__attribute__((unused)) GMenuModel } } +static void indicator_ng_set_tooltip(IndicatorNg *self, gchar *sTooltip) +{ + if (self->entry.label != NULL) + { + gtk_widget_set_tooltip_text(GTK_WIDGET(self->entry.label), sTooltip); + } + + if (self->entry.image != NULL) + { + gtk_widget_set_tooltip_text(GTK_WIDGET(self->entry.image), sTooltip); + } +} + static void indicator_ng_menu_shown(__attribute__((unused)) GtkWidget *pWidget, gpointer pUserData) { IndicatorNg *self = pUserData; guint nSectionCount = 0; + self->bMenuShown = TRUE; + + indicator_ng_set_tooltip(self, NULL); if (!self->lMenuSections[0]) { @@ -472,10 +490,13 @@ indicator_ng_menu_hidden (__attribute__((unused)) GtkWidget *widget, gpointer user_data) { IndicatorNg *self = user_data; + self->bMenuShown = FALSE; if (self->submenu_action) g_action_group_change_action_state (self->actions, self->submenu_action, g_variant_new_boolean (FALSE)); + + indicator_ng_set_tooltip(self, self->sTooltip); } static void @@ -594,6 +615,7 @@ indicator_ng_update_entry (IndicatorNg *self) g_variant_lookup (state, "icon", "*", &icon); g_variant_lookup (state, "accessible-desc", "&s", &accessible_desc); g_variant_lookup (state, "visible", "b", &visible); + g_variant_lookup (state, "tooltip", "&s", &self->sTooltip); } else g_warning ("the action of the indicator menu item must have state with type (sssb) or a{sv}"); @@ -601,6 +623,7 @@ indicator_ng_update_entry (IndicatorNg *self) indicator_ng_set_label (self, label); indicator_ng_set_icon_from_variant (self, icon); indicator_ng_set_accessible_desc (self, accessible_desc); + indicator_ng_set_tooltip (self, self->bMenuShown ? NULL : self->sTooltip); indicator_object_set_visible (INDICATOR_OBJECT (self), visible); if (icon) @@ -954,6 +977,8 @@ indicator_ng_initable_iface_init (GInitableIface *initable) static void indicator_ng_init (IndicatorNg *self) { + self->sTooltip = NULL; + self->bMenuShown = FALSE; m_pActionMuxer = g_quark_from_static_string ("gtk-widget-action-muxer"); for (guint nMenuSection = 0; nMenuSection < MENU_SECTIONS; nMenuSection++) diff --git a/src/indicator-service.c b/src/indicator-service.c index de3a0cf..c10d67f 100644 --- a/src/indicator-service.c +++ b/src/indicator-service.c @@ -3,9 +3,11 @@ An object used to provide a simple interface for a service to query version and manage whether it's running. Copyright 2009 Canonical Ltd. +Copyright 2022 Robert Tari Authors: Ted Gould <ted@canonical.com> + Robert Tari <robert@tari.in> This library is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -25,8 +27,6 @@ License along with this library. If not, see #include "config.h" #endif -#include <stdlib.h> /* exit() */ - #include <gio/gio.h> #include "indicator-service.h" @@ -40,32 +40,32 @@ 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. + 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; + 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 + SHUTDOWN, + LAST_SIGNAL }; static guint signals[LAST_SIGNAL] = { 0 }; @@ -74,9 +74,9 @@ static guint signals[LAST_SIGNAL] = { 0 }; /* Enum for the properties so that they can be quickly found and looked up. */ enum { - PROP_0, - PROP_NAME, - PROP_VERSION + PROP_0, + PROP_NAME, + PROP_VERSION }; /* The strings so that they can be slowly looked up. */ @@ -85,7 +85,7 @@ enum { /* GObject Stuff */ #define INDICATOR_SERVICE_GET_PRIVATE(o) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((o), INDICATOR_SERVICE_TYPE, IndicatorServicePrivate)) + (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); @@ -96,15 +96,15 @@ static void indicator_service_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 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); +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 */ + .method_call = bus_method_call, + .get_property = NULL, /* No properties */ + .set_property = NULL /* No properties */ }; /* THE define */ @@ -113,66 +113,66 @@ 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; + 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 @@ -182,46 +182,46 @@ indicator_service_class_init (IndicatorServiceClass *klass) 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; + 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 @@ -229,32 +229,32 @@ indicator_service_init (IndicatorService *self) static void indicator_service_dispose (GObject *object) { - IndicatorService * service = INDICATOR_SERVICE(object); - IndicatorServicePrivate * priv = indicator_service_get_instance_private(service); + IndicatorService * service = INDICATOR_SERVICE(object); + IndicatorServicePrivate * priv = indicator_service_get_instance_private(service); - g_clear_pointer (&priv->watchers, g_hash_table_destroy); + g_clear_pointer (&priv->watchers, g_hash_table_destroy); - if (priv->timeout != 0) { - g_source_remove(priv->timeout); - priv->timeout = 0; - } + 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; - } + 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); + 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; - } + 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; + G_OBJECT_CLASS (indicator_service_parent_class)->dispose (object); + return; } /* Freeing the name we're looking for and all of the @@ -262,14 +262,14 @@ indicator_service_dispose (GObject *object) static void indicator_service_finalize (GObject *object) { - IndicatorService * service = INDICATOR_SERVICE(object); - IndicatorServicePrivate * priv = indicator_service_get_instance_private(service); + 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_free (priv->name); + g_clear_pointer (&priv->watchers, g_hash_table_destroy); - G_OBJECT_CLASS (indicator_service_parent_class)->finalize (object); - return; + G_OBJECT_CLASS (indicator_service_parent_class)->finalize (object); + return; } /* Either copies a string for the name or it just grabs @@ -277,36 +277,36 @@ indicator_service_finalize (GObject *object) 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; + 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. @@ -314,70 +314,69 @@ set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec 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; + 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; + GError * error = NULL; + GDBusConnection * connection = g_bus_get_finish(res, &error); + + if (error != NULL) + { + g_error("Unable to get a connection to the session DBus: %s", error->message); + } + + 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 @@ -385,21 +384,21 @@ bus_get_cb (__attribute__((unused)) GObject * object, GAsyncResult * res, gpoint 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; + 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 @@ -407,8 +406,8 @@ bus_method_call (__attribute__((unused)) GDBusConnection * connection, const gch static void watchers_remove (gpointer value) { - g_bus_unwatch_name(GPOINTER_TO_UINT(value)); - return; + g_bus_unwatch_name(GPOINTER_TO_UINT(value)); + return; } /* This is the function that gets executed if we timeout @@ -417,13 +416,13 @@ watchers_remove (gpointer value) 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; + 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 @@ -432,23 +431,23 @@ timeout_no_watchers (gpointer data) 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)); + g_return_if_fail(connection != NULL); + g_return_if_fail(INDICATOR_IS_SERVICE(user_data)); - IndicatorServicePrivate * priv = indicator_service_get_instance_private(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; - } + /* 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); + /* 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; + return; } /* Callback saying that we didn't get the name, so we need to @@ -456,57 +455,57 @@ try_and_get_name_acquired_cb (GDBusConnection * connection, __attribute__((unuse 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; + 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; + 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 @@ -514,17 +513,17 @@ try_and_get_name (IndicatorService * service) 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); + 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); - } + 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; + return; } /* Here is the function that gets called by the dbus @@ -534,31 +533,31 @@ watcher_vanished_cb (__attribute__((unused)) GDBusConnection * connection, const 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); + 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 @@ -567,83 +566,83 @@ bus_watch (IndicatorService * service, const gchar * sender) 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; + 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 + 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. + 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. + 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); + GObject * obj = g_object_new(INDICATOR_SERVICE_TYPE, + PROP_NAME_S, name, + NULL); - return INDICATOR_SERVICE(obj); + 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. + 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); + GObject * obj = g_object_new(INDICATOR_SERVICE_TYPE, + PROP_NAME_S, name, + PROP_VERSION_S, version, + NULL); - return INDICATOR_SERVICE(obj); + return INDICATOR_SERVICE(obj); } diff --git a/src/indicator.symbols b/src/indicator.symbols new file mode 100644 index 0000000..1cb68cd --- /dev/null +++ b/src/indicator.symbols @@ -0,0 +1,6 @@ +{ + global: indicator_*; + INDICATOR_*; + ICON_SIZE*; + local: _indicator_*; +}; |