diff options
author | Kristian Monsen <kristianm@google.com> | 2011-05-31 20:30:28 +0100 |
---|---|---|
committer | Kristian Monsen <kristianm@google.com> | 2011-06-14 20:31:41 -0700 |
commit | 72a454cd3513ac24fbdd0e0cb9ad70b86a99b801 (patch) | |
tree | 382278a54ce7a744d62fa510a9a80688cc12434b /chrome/browser/gtk/accessibility_event_router_gtk.cc | |
parent | c4becdd46e31d261b930e4b5a539cbc1d45c23a6 (diff) | |
download | external_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.cc | 658 |
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); -} |