diff options
Diffstat (limited to 'src/app-indicator.c')
-rw-r--r-- | src/app-indicator.c | 161 |
1 files changed, 160 insertions, 1 deletions
diff --git a/src/app-indicator.c b/src/app-indicator.c index f4e9173..c3da8ed 100644 --- a/src/app-indicator.c +++ b/src/app-indicator.c @@ -80,7 +80,9 @@ struct _AppIndicatorPrivate { guint32 ordering_index; gchar * label; gchar * label_guide; + gchar * accessible_desc; guint label_change_idle; + guint accessible_desc_change_idle; GtkStatusIcon * status_icon; gint fallback_timer; @@ -104,6 +106,7 @@ enum { CONNECTION_CHANGED, NEW_ICON_THEME_PATH, SCROLL_EVENT, + NEW_ACCESSIBLE_DESC, LAST_SIGNAL }; @@ -123,7 +126,8 @@ enum { PROP_LABEL, PROP_LABEL_GUIDE, PROP_ORDERING_INDEX, - PROP_DBUS_MENU_SERVER + PROP_DBUS_MENU_SERVER, + PROP_ACCESSIBLE_DESC }; /* The strings so that they can be slowly looked up. */ @@ -138,6 +142,7 @@ enum { #define PROP_LABEL_GUIDE_S "label-guide" #define PROP_ORDERING_INDEX_S "ordering-index" #define PROP_DBUS_MENU_SERVER_S "dbus-menu-server" +#define PROP_ACCESSIBLE_DESC_S "accessible-desc" /* Private macro, shhhh! */ #define APP_INDICATOR_GET_PRIVATE(o) \ @@ -165,6 +170,7 @@ static void app_indicator_set_property (GObject * object, guint prop_id, const G static void app_indicator_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); /* Other stuff */ static void signal_label_change (AppIndicator * self); +static void signal_accessible_desc_change (AppIndicator * self); static void check_connect (AppIndicator * self); static void register_service_cb (GObject * obj, GAsyncResult * res, gpointer user_data); static void start_fallback_timer (AppIndicator * self, gboolean disable_timeout); @@ -346,6 +352,22 @@ app_indicator_class_init (AppIndicatorClass *klass) NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); /** + AppIndicator:accessible-desc: + + A string that describes the indicator in text form. This string is + used to identify the indicator to users of assistive technologies, such + as screen readers. If the indicator has a label, then duplicating the + contents of the label is fine, if the label alone conveys enough + information about the state of the indicator to the user. + */ + g_object_class_install_property(object_class, + PROP_ACCESSIBLE_DESC, + g_param_spec_string (PROP_ACCESSIBLE_DESC_S, + "A string that describes the indicator in text form.", + "This string should convey a description of the indicator's current status, for users who use assistive technologies.", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** AppIndicator:ordering-index: The ordering index is an odd parameter, and if you think you don't need @@ -442,6 +464,21 @@ app_indicator_class_init (AppIndicatorClass *klass) _application_service_marshal_VOID__STRING_STRING, G_TYPE_NONE, 2, G_TYPE_STRING, G_TYPE_STRING); + /** + AppIndicator::new-accessible-desc: + @arg0: The #AppIndicator object + @arg1: The string for the accessible description + + Emitted when #AppIndicator:accessible_desc changes. + */ + signals[NEW_ACCESSIBLE_DESC] = g_signal_new (APP_INDICATOR_SIGNAL_NEW_ACCESSIBLE_DESC, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (AppIndicatorClass, new_accessible_desc), + NULL, NULL, + _application_service_marshal_VOID__STRING_STRING, + G_TYPE_NONE, 1, G_TYPE_STRING); + /** AppIndicator::connection-changed: @@ -548,6 +585,7 @@ app_indicator_init (AppIndicator *self) priv->label = NULL; priv->label_guide = NULL; priv->label_change_idle = 0; + priv->accessible_desc_change_idle = 0; priv->watcher_proxy = NULL; priv->connection = NULL; @@ -611,6 +649,11 @@ app_indicator_dispose (GObject *object) priv->label_change_idle = 0; } + if (priv->accessible_desc_change_idle != 0) { + g_source_remove(priv->accessible_desc_change_idle); + priv->accessible_desc_change_idle = 0; + } + if (priv->menu != NULL) { g_signal_handlers_disconnect_by_func (G_OBJECT (priv->menu), client_menu_changed, @@ -688,6 +731,11 @@ app_indicator_finalize (GObject *object) priv->label_guide = NULL; } + if (priv->accessible_desc != NULL) { + g_free(priv->accessible_desc); + priv->accessible_desc = NULL; + } + if (priv->path != NULL) { g_free(priv->path); priv->path = NULL; @@ -799,6 +847,24 @@ app_indicator_set_property (GObject * object, guint prop_id, const GValue * valu } break; } + case PROP_ACCESSIBLE_DESC: { + gchar * olda11ydesc = priv->accessible_desc; + priv->accessible_desc = g_value_dup_string(value); + + if (g_strcmp0(olda11ydesc, priv->accessible_desc) != 0) { + signal_accessible_desc_change(APP_INDICATOR(object)); + } + + if (priv->accessible_desc != NULL && priv->accessible_desc[0] == '\0') { + g_free(priv->accessible_desc); + priv->accessible_desc = NULL; + } + + if (olda11ydesc != NULL) { + g_free(olda11ydesc); + } + break; + } case PROP_ORDERING_INDEX: priv->ordering_index = g_value_get_uint(value); break; @@ -877,6 +943,10 @@ app_indicator_get_property (GObject * object, guint prop_id, GValue * value, GPa g_value_set_string (value, priv->label_guide); break; + case PROP_ACCESSIBLE_DESC: + g_value_set_string (value, priv->accessible_desc); + break; + case PROP_ORDERING_INDEX: g_value_set_uint(value, priv->ordering_index); break; @@ -999,6 +1069,8 @@ bus_get_prop (GDBusConnection * connection, const gchar * sender, const gchar * return g_variant_new_string(priv->label_guide ? priv->label_guide : ""); } else if (g_strcmp0(property, "XAyatanaOrderingIndex") == 0) { return g_variant_new_uint32(priv->ordering_index); + } else if (g_strcmp0(property, "AccessibleDesc") == 0) { + return g_variant_new_string(priv->accessible_desc ? priv->accessible_desc : ""); } *error = g_error_new(0, 0, "Unknown property: %s", property); @@ -1055,6 +1127,55 @@ signal_label_change (AppIndicator * self) return; } +/* Sends the accessible description changed signal and resets the source ID */ +static gboolean +signal_accessible_desc_change_idle (gpointer user_data) +{ + AppIndicator * self = (AppIndicator *)user_data; + AppIndicatorPrivate *priv = self->priv; + + gchar * accessible_desc = priv->accessible_desc != NULL ? priv->accessible_desc : ""; + + g_signal_emit(G_OBJECT(self), signals[NEW_ACCESSIBLE_DESC], 0, + accessible_desc, TRUE); + if (priv->dbus_registration != 0 && priv->connection != NULL) { + GError * error = NULL; + + g_dbus_connection_emit_signal(priv->connection, + NULL, + priv->path, + NOTIFICATION_ITEM_DBUS_IFACE, + "NewAccessibleDesc", + g_variant_new("(s)", accessible_desc), + &error); + + if (error != NULL) { + g_warning("Unable to send signal for NewAccessibleDesc: %s", error->message); + g_error_free(error); + } + } + + priv->accessible_desc_change_idle = 0; + + return FALSE; +} + +/* Sets up an idle function to send the accessible description + changed signal so that we don't send it too many times. */ +static void +signal_accessible_desc_change (AppIndicator * self) +{ + AppIndicatorPrivate *priv = self->priv; + + /* don't set it twice */ + if (priv->accessible_desc_change_idle != 0) { + return; + } + + priv->accessible_desc_change_idle = g_idle_add(signal_accessible_desc_change_idle, self); + return; +} + /* This function is used to see if we have enough information to connect to things. If we do, and we're not connected, it connects for us. */ @@ -1721,6 +1842,28 @@ app_indicator_set_label (AppIndicator *self, const gchar * label, const gchar * } /** + app_indicator_set_accessible_desc: + @self: The #AppIndicator object to use + @accessible_desc: The accessible description used by assistive technologies. + + This is a wrapper function for the #AppIndicator:accessible_desc + property. This function can take #NULL as @accessible_desc and + will clear the entry. +*/ +void +app_indicator_set_accessible_desc (AppIndicator *self, const gchar * accessible_desc) +{ + g_return_if_fail (IS_APP_INDICATOR (self)); + /* Note: The accessible description can be NULL, it's okay */ + + g_object_set(G_OBJECT(self), + PROP_ACCESSIBLE_DESC_S, accessible_desc == NULL ? "" : accessible_desc, + NULL); + + return; +} + +/** app_indicator_set_icon_theme_path: @self: The #AppIndicator object to use @icon_theme_path: The icon theme path to set. @@ -2015,6 +2158,22 @@ app_indicator_get_label_guide (AppIndicator *self) } /** + app_indicator_get_accessible_desc: + @self: The #AppIndicator object to use + + Wrapper function for property #AppIndicator:accessible_desc. + + Return value: The current accessible description. +*/ +const gchar * +app_indicator_get_accessible_desc (AppIndicator *self) +{ + g_return_val_if_fail (IS_APP_INDICATOR (self), NULL); + + return self->priv->accessible_desc; +} + +/** app_indicator_get_ordering_index: @self: The #AppIndicator object to use |