summaryrefslogtreecommitdiffstats
path: root/chrome/browser/gtk/accessibility_event_router_gtk.cc
diff options
context:
space:
mode:
authorKristian Monsen <kristianm@google.com>2011-05-31 20:30:28 +0100
committerKristian Monsen <kristianm@google.com>2011-06-14 20:31:41 -0700
commit72a454cd3513ac24fbdd0e0cb9ad70b86a99b801 (patch)
tree382278a54ce7a744d62fa510a9a80688cc12434b /chrome/browser/gtk/accessibility_event_router_gtk.cc
parentc4becdd46e31d261b930e4b5a539cbc1d45c23a6 (diff)
downloadexternal_chromium-72a454cd3513ac24fbdd0e0cb9ad70b86a99b801.zip
external_chromium-72a454cd3513ac24fbdd0e0cb9ad70b86a99b801.tar.gz
external_chromium-72a454cd3513ac24fbdd0e0cb9ad70b86a99b801.tar.bz2
Merge Chromium.org at r11.0.672.0: Initial merge by git.
Change-Id: I8b4aaf611a2a405fe3fe10e8a94ea7658645c192
Diffstat (limited to 'chrome/browser/gtk/accessibility_event_router_gtk.cc')
-rw-r--r--chrome/browser/gtk/accessibility_event_router_gtk.cc658
1 files changed, 0 insertions, 658 deletions
diff --git a/chrome/browser/gtk/accessibility_event_router_gtk.cc b/chrome/browser/gtk/accessibility_event_router_gtk.cc
deleted file mode 100644
index 1248247..0000000
--- a/chrome/browser/gtk/accessibility_event_router_gtk.cc
+++ /dev/null
@@ -1,658 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/gtk/accessibility_event_router_gtk.h"
-
-#include "base/basictypes.h"
-#include "base/callback.h"
-#include "base/message_loop.h"
-#include "base/stl_util-inl.h"
-#include "chrome/browser/extensions/extension_accessibility_api.h"
-#include "chrome/browser/gtk/gtk_chrome_link_button.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/common/notification_type.h"
-
-#if defined(TOOLKIT_VIEWS)
-#include "views/controls/textfield/gtk_views_textview.h"
-#include "views/controls/textfield/gtk_views_entry.h"
-#include "views/controls/textfield/native_textfield_gtk.h"
-#endif
-
-namespace {
-
-//
-// Callbacks triggered by signals on gtk widgets.
-//
-
-gboolean OnWidgetFocused(GSignalInvocationHint *ihint,
- guint n_param_values,
- const GValue* param_values,
- gpointer user_data) {
- GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
- reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
- DispatchAccessibilityNotification(
- widget, NotificationType::ACCESSIBILITY_CONTROL_FOCUSED);
- return TRUE;
-}
-
-gboolean OnButtonClicked(GSignalInvocationHint *ihint,
- guint n_param_values,
- const GValue* param_values,
- gpointer user_data) {
- GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
- // Skip toggle buttons because we're also listening on "toggle" events.
- if (GTK_IS_TOGGLE_BUTTON(widget))
- return true;
- reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
- DispatchAccessibilityNotification(
- widget, NotificationType::ACCESSIBILITY_CONTROL_ACTION);
- return TRUE;
-}
-
-gboolean OnButtonToggled(GSignalInvocationHint *ihint,
- guint n_param_values,
- const GValue* param_values,
- gpointer user_data) {
- GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
- bool checked = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
- // Skip propagating an "uncheck" event for a radio button because it's
- // redundant; there will always be a corresponding "check" event for
- // a different radio button the group.
- if (GTK_IS_RADIO_BUTTON(widget) && !checked)
- return true;
- reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
- DispatchAccessibilityNotification(
- widget, NotificationType::ACCESSIBILITY_CONTROL_ACTION);
- return TRUE;
-}
-
-gboolean OnPageSwitched(GSignalInvocationHint *ihint,
- guint n_param_values,
- const GValue* param_values,
- gpointer user_data) {
- GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
- // The page hasn't switched yet, so defer calling
- // DispatchAccessibilityNotification.
- reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
- PostDispatchAccessibilityNotification(
- widget, NotificationType::ACCESSIBILITY_CONTROL_ACTION);
- return TRUE;
-}
-
-gboolean OnComboBoxChanged(GSignalInvocationHint *ihint,
- guint n_param_values,
- const GValue* param_values,
- gpointer user_data) {
- GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
- if (!GTK_IS_COMBO_BOX(widget))
- return true;
- reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
- DispatchAccessibilityNotification(
- widget, NotificationType::ACCESSIBILITY_CONTROL_ACTION);
- return TRUE;
-}
-
-gboolean OnTreeViewCursorChanged(GSignalInvocationHint *ihint,
- guint n_param_values,
- const GValue* param_values,
- gpointer user_data) {
- GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
- if (!GTK_IS_TREE_VIEW(widget)) {
- return true;
- }
- reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
- DispatchAccessibilityNotification(
- widget, NotificationType::ACCESSIBILITY_CONTROL_ACTION);
- return TRUE;
-}
-
-gboolean OnEntryChanged(GSignalInvocationHint *ihint,
- guint n_param_values,
- const GValue* param_values,
- gpointer user_data) {
- GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
- if (!GTK_IS_ENTRY(widget)) {
- return TRUE;
- }
- // The text hasn't changed yet, so defer calling
- // DispatchAccessibilityNotification.
- reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
- PostDispatchAccessibilityNotification(
- widget, NotificationType::ACCESSIBILITY_TEXT_CHANGED);
- return TRUE;
-}
-
-gboolean OnTextBufferChanged(GSignalInvocationHint *ihint,
- guint n_param_values,
- const GValue* param_values,
- gpointer user_data) {
- // The text hasn't changed yet, so defer calling
- // DispatchAccessibilityNotification.
- reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
- PostDispatchAccessibilityNotification(
- NULL, NotificationType::ACCESSIBILITY_TEXT_CHANGED);
- return TRUE;
-}
-
-gboolean OnTextViewChanged(GSignalInvocationHint *ihint,
- guint n_param_values,
- const GValue* param_values,
- gpointer user_data) {
- GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
- if (!GTK_IS_TEXT_VIEW(widget)) {
- return TRUE;
- }
- // The text hasn't changed yet, so defer calling
- // DispatchAccessibilityNotification.
- reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
- PostDispatchAccessibilityNotification(
- widget, NotificationType::ACCESSIBILITY_TEXT_CHANGED);
- return TRUE;
-}
-
-gboolean OnMenuMoveCurrent(GSignalInvocationHint *ihint,
- guint n_param_values,
- const GValue* param_values,
- gpointer user_data) {
- // Get the widget (the GtkMenu).
- GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
-
- // Moving may move us into or out of a submenu, so after the menu
- // item moves, |widget| may not be valid anymore. To be safe, then,
- // find the topmost ancestor of this menu and post the notification
- // dispatch on that menu. Then the dispatcher will recurse into submenus
- // as necessary to figure out which item is focused.
- while (GTK_MENU_SHELL(widget)->parent_menu_shell)
- widget = GTK_MENU_SHELL(widget)->parent_menu_shell;
-
- // The menu item hasn't moved yet, so we want to defer calling
- // DispatchAccessibilityNotification until after it does.
- reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
- PostDispatchAccessibilityNotification(
- widget, NotificationType::ACCESSIBILITY_CONTROL_FOCUSED);
- return TRUE;
-}
-
-} // anonymous namespace
-
-AccessibilityEventRouterGtk::AccessibilityEventRouterGtk()
- : listening_(false),
- most_recent_profile_(NULL),
- most_recent_widget_(NULL),
- method_factory_(this) {
- // We don't want our event listeners to be installed if accessibility is
- // disabled. Install listeners so we can install and uninstall them as
- // needed, then install them now if it's currently enabled.
- ExtensionAccessibilityEventRouter *extension_event_router =
- ExtensionAccessibilityEventRouter::GetInstance();
- extension_event_router->AddOnEnabledListener(
- NewCallback(this,
- &AccessibilityEventRouterGtk::InstallEventListeners));
- extension_event_router->AddOnDisabledListener(
- NewCallback(this,
- &AccessibilityEventRouterGtk::RemoveEventListeners));
- if (extension_event_router->IsAccessibilityEnabled()) {
- InstallEventListeners();
- }
-}
-
-AccessibilityEventRouterGtk::~AccessibilityEventRouterGtk() {
- RemoveEventListeners();
-}
-
-// static
-AccessibilityEventRouterGtk* AccessibilityEventRouterGtk::GetInstance() {
- return Singleton<AccessibilityEventRouterGtk>::get();
-}
-
-void AccessibilityEventRouterGtk::InstallEventListener(
- const char* signal_name,
- GType widget_type,
- GSignalEmissionHook hook_func) {
- guint signal_id = g_signal_lookup(signal_name, widget_type);
- gulong hook_id = g_signal_add_emission_hook(
- signal_id, 0, hook_func, reinterpret_cast<gpointer>(this), NULL);
- installed_hooks_.push_back(InstalledHook(signal_id, hook_id));
-}
-
-bool AccessibilityEventRouterGtk::IsPassword(GtkWidget* widget) {
- bool is_password = false;
-#if defined (TOOLKIT_VIEWS)
- is_password = (GTK_IS_VIEWS_ENTRY(widget) &&
- GTK_VIEWS_ENTRY(widget)->host != NULL &&
- GTK_VIEWS_ENTRY(widget)->host->IsPassword()) ||
- (GTK_IS_VIEWS_TEXTVIEW(widget) &&
- GTK_VIEWS_TEXTVIEW(widget)->host != NULL &&
- GTK_VIEWS_TEXTVIEW(widget)->host->IsPassword());
-#endif
- return is_password;
-}
-
-
-void AccessibilityEventRouterGtk::InstallEventListeners() {
- // Create and destroy each type of widget we need signals for,
- // to ensure their modules are loaded, otherwise g_signal_lookup
- // might fail.
- g_object_unref(g_object_ref_sink(gtk_combo_box_new()));
- g_object_unref(g_object_ref_sink(gtk_entry_new()));
- g_object_unref(g_object_ref_sink(gtk_notebook_new()));
- g_object_unref(g_object_ref_sink(gtk_toggle_button_new()));
- g_object_unref(g_object_ref_sink(gtk_tree_view_new()));
- g_object_unref(g_object_ref_sink(gtk_text_view_new()));
- g_object_unref(g_object_ref_sink(gtk_text_buffer_new(NULL)));
-
- // Add signal emission hooks for the events we're interested in.
- InstallEventListener("clicked", GTK_TYPE_BUTTON, OnButtonClicked);
- InstallEventListener("changed", GTK_TYPE_COMBO_BOX, OnComboBoxChanged);
- InstallEventListener("cursor-changed", GTK_TYPE_TREE_VIEW,
- OnTreeViewCursorChanged);
- InstallEventListener("changed", GTK_TYPE_ENTRY, OnEntryChanged);
- InstallEventListener("insert-text", GTK_TYPE_ENTRY, OnEntryChanged);
- InstallEventListener("delete-text", GTK_TYPE_ENTRY, OnEntryChanged);
- InstallEventListener("move-cursor", GTK_TYPE_ENTRY, OnEntryChanged);
- InstallEventListener("focus-in-event", GTK_TYPE_WIDGET, OnWidgetFocused);
- InstallEventListener("switch-page", GTK_TYPE_NOTEBOOK, OnPageSwitched);
- InstallEventListener("toggled", GTK_TYPE_TOGGLE_BUTTON, OnButtonToggled);
- InstallEventListener("move-current", GTK_TYPE_MENU, OnMenuMoveCurrent);
- InstallEventListener("changed", GTK_TYPE_TEXT_BUFFER, OnTextBufferChanged);
- InstallEventListener("move-cursor", GTK_TYPE_TEXT_VIEW, OnTextViewChanged);
-
- listening_ = true;
-}
-
-void AccessibilityEventRouterGtk::RemoveEventListeners() {
- for (size_t i = 0; i < installed_hooks_.size(); i++) {
- g_signal_remove_emission_hook(
- installed_hooks_[i].signal_id,
- installed_hooks_[i].hook_id);
- }
- installed_hooks_.clear();
-
- listening_ = false;
-}
-
-void AccessibilityEventRouterGtk::AddRootWidget(
- GtkWidget* root_widget, Profile* profile) {
- root_widget_info_map_[root_widget].refcount++;
- root_widget_info_map_[root_widget].profile = profile;
-}
-
-void AccessibilityEventRouterGtk::RemoveRootWidget(GtkWidget* root_widget) {
- DCHECK(root_widget_info_map_.find(root_widget) !=
- root_widget_info_map_.end());
- root_widget_info_map_[root_widget].refcount--;
- if (root_widget_info_map_[root_widget].refcount == 0) {
- root_widget_info_map_.erase(root_widget);
- }
-}
-
-void AccessibilityEventRouterGtk::AddWidgetNameOverride(
- GtkWidget* widget, std::string name) {
- widget_info_map_[widget].name = name;
- widget_info_map_[widget].refcount++;
-}
-
-void AccessibilityEventRouterGtk::RemoveWidgetNameOverride(GtkWidget* widget) {
- DCHECK(widget_info_map_.find(widget) != widget_info_map_.end());
- widget_info_map_[widget].refcount--;
- if (widget_info_map_[widget].refcount == 0) {
- widget_info_map_.erase(widget);
- }
-}
-
-void AccessibilityEventRouterGtk::FindWidget(
- GtkWidget* widget, Profile** profile, bool* is_accessible) {
- *is_accessible = false;
-
- for (base::hash_map<GtkWidget*, RootWidgetInfo>::const_iterator iter =
- root_widget_info_map_.begin();
- iter != root_widget_info_map_.end();
- ++iter) {
- if (widget == iter->first || gtk_widget_is_ancestor(widget, iter->first)) {
- *is_accessible = true;
- if (profile)
- *profile = iter->second.profile;
- break;
- }
- }
-}
-
-std::string AccessibilityEventRouterGtk::GetWidgetName(GtkWidget* widget) {
- base::hash_map<GtkWidget*, WidgetInfo>::const_iterator iter =
- widget_info_map_.find(widget);
- if (iter != widget_info_map_.end()) {
- return iter->second.name;
- } else {
- return "";
- }
-}
-
-void AccessibilityEventRouterGtk::StartListening() {
- listening_ = true;
-}
-
-void AccessibilityEventRouterGtk::StopListening() {
- listening_ = false;
-}
-
-void AccessibilityEventRouterGtk::DispatchAccessibilityNotification(
- GtkWidget* widget, NotificationType type) {
- // If there's no message loop, we must be about to shutdown or we're
- // running inside a test; either way, there's no reason to do any
- // further processing.
- if (!MessageLoop::current())
- return;
-
- if (!listening_)
- return;
-
- Profile* profile = NULL;
- bool is_accessible;
-
- // Special case: when we get ACCESSIBILITY_TEXT_CHANGED, we don't get
- // a pointer to the widget, so we try to retrieve it from the most recent
- // widget.
- if (widget == NULL &&
- type == NotificationType::ACCESSIBILITY_TEXT_CHANGED &&
- most_recent_widget_ &&
- GTK_IS_TEXT_VIEW(most_recent_widget_)) {
- widget = most_recent_widget_;
- }
-
- if (!widget)
- return;
-
- most_recent_widget_ = widget;
- FindWidget(widget, &profile, &is_accessible);
- if (profile)
- most_recent_profile_ = profile;
-
- // Special case: a GtkMenu isn't associated with any particular
- // toplevel window, so menu events get routed to the profile of
- // the most recent event that was associated with a window.
- if (GTK_IS_MENU_SHELL(widget) && most_recent_profile_) {
- SendMenuItemNotification(widget, type, most_recent_profile_);
- return;
- }
-
- // In all other cases, return if this widget wasn't marked as accessible.
- if (!is_accessible)
- return;
-
- // The order of these checks matters, because, for example, a radio button
- // is a subclass of button, and a combo box is a composite control where
- // the focus event goes to the button that's a child of the combo box.
- GtkWidget* parent = gtk_widget_get_parent(widget);
- if (parent && GTK_IS_BUTTON(widget) && GTK_IS_TREE_VIEW(parent)) {
- // This is a list box column header. Currently not supported.
- return;
- } else if (GTK_IS_COMBO_BOX(widget)) {
- SendComboBoxNotification(widget, type, profile);
- } else if (parent && GTK_IS_COMBO_BOX(parent)) {
- SendComboBoxNotification(parent, type, profile);
- } else if (GTK_IS_RADIO_BUTTON(widget)) {
- SendRadioButtonNotification(widget, type, profile);
- } else if (GTK_IS_TOGGLE_BUTTON(widget)) {
- SendCheckboxNotification(widget, type, profile);
- } else if (GTK_IS_BUTTON(widget)) {
- SendButtonNotification(widget, type, profile);
- } else if (GTK_IS_ENTRY(widget)) {
- SendEntryNotification(widget, type, profile);
- } else if (GTK_IS_TEXT_VIEW(widget)) {
- SendTextViewNotification(widget, type, profile);
- } else if (GTK_IS_NOTEBOOK(widget)) {
- SendTabNotification(widget, type, profile);
- } else if (GTK_IS_TREE_VIEW(widget)) {
- SendListBoxNotification(widget, type, profile);
- } else {
- // If we have no idea what this control is, return and skip the
- // temporary pause in event listening.
- return;
- }
-
- // After this method returns, additional signal handlers will run,
- // which will sometimes generate additional signals. To avoid
- // generating redundant accessibility notifications for the same
- // initial event, stop listening to all signals generated from now
- // until this posted task runs.
- StopListening();
- MessageLoop::current()->PostTask(
- FROM_HERE, method_factory_.NewRunnableMethod(
- &AccessibilityEventRouterGtk::StartListening));
-}
-
-void AccessibilityEventRouterGtk::PostDispatchAccessibilityNotification(
- GtkWidget* widget, NotificationType type) {
- if (!MessageLoop::current())
- return;
-
- MessageLoop::current()->PostTask(
- FROM_HERE, method_factory_.NewRunnableMethod(
- &AccessibilityEventRouterGtk::DispatchAccessibilityNotification,
- widget,
- type));
-}
-
-void AccessibilityEventRouterGtk::SendRadioButtonNotification(
- GtkWidget* widget, NotificationType type, Profile* profile) {
- // Get the radio button name
- std::string button_name = GetWidgetName(widget);
- if (button_name.empty() && gtk_button_get_label(GTK_BUTTON(widget)))
- button_name = gtk_button_get_label(GTK_BUTTON(widget));
-
- // Get its state
- bool checked = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
-
- // Get the index of this radio button and the total number of
- // radio buttons in the group.
- int item_count = 0;
- int item_index = -1;
- for (GSList* group = gtk_radio_button_get_group(GTK_RADIO_BUTTON(widget));
- group;
- group = group->next) {
- if (group->data == widget) {
- item_index = item_count;
- }
- item_count++;
- }
- item_index = item_count - 1 - item_index;
-
- AccessibilityRadioButtonInfo info(
- profile, button_name, checked, item_index, item_count);
- SendAccessibilityNotification(type, &info);
-}
-
-void AccessibilityEventRouterGtk::SendCheckboxNotification(
- GtkWidget* widget, NotificationType type, Profile* profile) {
- std::string button_name = GetWidgetName(widget);
- if (button_name.empty() && gtk_button_get_label(GTK_BUTTON(widget)))
- button_name = gtk_button_get_label(GTK_BUTTON(widget));
- bool checked = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
- AccessibilityCheckboxInfo info(profile, button_name, checked);
- SendAccessibilityNotification(type, &info);
-}
-
-void AccessibilityEventRouterGtk::SendButtonNotification(
- GtkWidget* widget, NotificationType type, Profile* profile) {
- std::string button_name = GetWidgetName(widget);
- if (button_name.empty() && gtk_button_get_label(GTK_BUTTON(widget)))
- button_name = gtk_button_get_label(GTK_BUTTON(widget));
- AccessibilityButtonInfo info(profile, button_name);
- SendAccessibilityNotification(type, &info);
-}
-
-void AccessibilityEventRouterGtk::SendEntryNotification(
- GtkWidget* widget, NotificationType type, Profile* profile) {
- std::string name = GetWidgetName(widget);
- std::string value = gtk_entry_get_text(GTK_ENTRY(widget));
- gint start_pos;
- gint end_pos;
- gtk_editable_get_selection_bounds(GTK_EDITABLE(widget), &start_pos, &end_pos);
- AccessibilityTextBoxInfo info(profile, name, IsPassword(widget));
- info.SetValue(value, start_pos, end_pos);
- SendAccessibilityNotification(type, &info);
-}
-
-void AccessibilityEventRouterGtk::SendTextViewNotification(
- GtkWidget* widget, NotificationType type, Profile* profile) {
- std::string name = GetWidgetName(widget);
- GtkTextBuffer* buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget));
- GtkTextIter start, end;
- gtk_text_buffer_get_bounds(buffer, &start, &end);
- gchar* text = gtk_text_buffer_get_text(buffer, &start, &end, false);
- std::string value = text;
- g_free(text);
- GtkTextIter sel_start, sel_end;
- gtk_text_buffer_get_selection_bounds(buffer, &sel_start, &sel_end);
- int start_pos = gtk_text_iter_get_offset(&sel_start);
- int end_pos = gtk_text_iter_get_offset(&sel_end);
- AccessibilityTextBoxInfo info(profile, name, IsPassword(widget));
- info.SetValue(value, start_pos, end_pos);
- SendAccessibilityNotification(type, &info);
-}
-
-void AccessibilityEventRouterGtk::SendTabNotification(
- GtkWidget* widget, NotificationType type, Profile* profile) {
- int index = gtk_notebook_get_current_page(GTK_NOTEBOOK(widget));
- int page_count = gtk_notebook_get_n_pages(GTK_NOTEBOOK(widget));
- GtkWidget* page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(widget), index);
- GtkWidget* label = gtk_notebook_get_tab_label(GTK_NOTEBOOK(widget), page);
- std::string name = GetWidgetName(widget);
- if (name.empty() && gtk_label_get_text(GTK_LABEL(label))) {
- name = gtk_label_get_text(GTK_LABEL(label));
- }
- AccessibilityTabInfo info(profile, name, index, page_count);
- SendAccessibilityNotification(type, &info);
-}
-
-void AccessibilityEventRouterGtk::SendComboBoxNotification(
- GtkWidget* widget, NotificationType type, Profile* profile) {
- // Get the index of the selected item. Will return -1 if no item is
- // active, which matches the semantics of the extension API.
- int index = gtk_combo_box_get_active(GTK_COMBO_BOX(widget));
-
- // Get the number of items.
- GtkTreeModel* model = gtk_combo_box_get_model(GTK_COMBO_BOX(widget));
- int count = gtk_tree_model_iter_n_children(model, NULL);
-
- // Get the value of the current item, if possible. Note that the
- // model behind the combo box could be arbitrarily complex in theory,
- // but this code just handles flat lists where the first string column
- // contains the display value.
- std::string value;
- int string_column_index = -1;
- for (int i = 0; i < gtk_tree_model_get_n_columns(model); i++) {
- if (gtk_tree_model_get_column_type(model, i) == G_TYPE_STRING) {
- string_column_index = i;
- break;
- }
- }
- if (string_column_index) {
- GtkTreeIter iter;
- if (gtk_combo_box_get_active_iter(GTK_COMBO_BOX(widget), &iter)) {
- GValue gvalue = { 0 };
- gtk_tree_model_get_value(model, &iter, string_column_index, &gvalue);
- const char* string_value = g_value_get_string(&gvalue);
- if (string_value) {
- value = string_value;
- }
- g_value_unset(&gvalue);
- }
- } else {
- // Otherwise this must be a gtk_combo_box_text, in which case this
- // function will return the value of the current item, instead.
- value = gtk_combo_box_get_active_text(GTK_COMBO_BOX(widget));
- }
-
- // Get the name of this combo box.
- std::string name = GetWidgetName(widget);
-
- // Send the notification.
- AccessibilityComboBoxInfo info(profile, name, value, index, count);
- SendAccessibilityNotification(type, &info);
-}
-
-void AccessibilityEventRouterGtk::SendListBoxNotification(
- GtkWidget* widget, NotificationType type, Profile* profile) {
- // Get the number of items.
- GtkTreeModel* model = gtk_tree_view_get_model(GTK_TREE_VIEW(widget));
- int count = gtk_tree_model_iter_n_children(model, NULL);
-
- // Get the current selected index and its value.
- int index = -1;
- std::string value;
- GtkTreePath* path;
- gtk_tree_view_get_cursor(GTK_TREE_VIEW(widget), &path, NULL);
- if (path != NULL) {
- gint* indices = gtk_tree_path_get_indices(path);
- if (indices)
- index = indices[0];
-
- GtkTreeIter iter;
- if (gtk_tree_model_get_iter(model, &iter, path)) {
- for (int i = 0; i < gtk_tree_model_get_n_columns(model); i++) {
- if (gtk_tree_model_get_column_type(model, i) == G_TYPE_STRING) {
- GValue gvalue = { 0 };
- gtk_tree_model_get_value(model, &iter, i, &gvalue);
- const char* string_value = g_value_get_string(&gvalue);
- if (string_value) {
- if (!value.empty())
- value += " ";
- value += string_value;
- }
- g_value_unset(&gvalue);
- }
- }
- }
-
- gtk_tree_path_free(path);
- }
-
- // Get the name of this control.
- std::string name = GetWidgetName(widget);
-
- // Send the notification.
- AccessibilityListBoxInfo info(profile, name, value, index, count);
- SendAccessibilityNotification(type, &info);
-}
-
-void AccessibilityEventRouterGtk::SendMenuItemNotification(
- GtkWidget* menu, NotificationType type, Profile* profile) {
- // Find the focused menu item, recursing into submenus as needed.
- GtkWidget* menu_item = GTK_MENU_SHELL(menu)->active_menu_item;
- if (!menu_item)
- return;
- GtkWidget* submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu_item));
- while (submenu && GTK_MENU_SHELL(submenu)->active_menu_item) {
- menu = submenu;
- menu_item = GTK_MENU_SHELL(menu)->active_menu_item;
- if (!menu_item)
- return;
- submenu = gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu_item));
- }
-
- // Figure out the item index and total number of items.
- GList* items = gtk_container_get_children(GTK_CONTAINER(menu));
- guint count = g_list_length(items);
- int index = g_list_index(items, static_cast<gconstpointer>(menu_item));
-
- // Get the menu item's label.
- std::string name;
-#if GTK_CHECK_VERSION(2, 16, 0)
- name = gtk_menu_item_get_label(GTK_MENU_ITEM(menu_item));
-#else
- GList* children = gtk_container_get_children(GTK_CONTAINER(menu_item));
- for (GList* l = g_list_first(children); l != NULL; l = g_list_next(l)) {
- GtkWidget* child = static_cast<GtkWidget*>(l->data);
- if (GTK_IS_LABEL(child)) {
- name = gtk_label_get_label(GTK_LABEL(child));
- break;
- }
- }
-#endif
-
- // Send the event.
- AccessibilityMenuItemInfo info(profile, name, submenu != NULL, index, count);
- SendAccessibilityNotification(type, &info);
-}