Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6)

Side by Side Diff: chrome/browser/gtk/accessibility_event_router_gtk.cc

Issue 2811023: Make the location bar generate accessibility extension API events... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/gtk/accessibility_event_router_gtk.h" 5 #include "chrome/browser/gtk/accessibility_event_router_gtk.h"
6 6
7 #include "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/callback.h" 8 #include "base/callback.h"
9 #include "base/message_loop.h" 9 #include "base/message_loop.h"
10 #include "base/stl_util-inl.h" 10 #include "base/stl_util-inl.h"
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 return TRUE; 110 return TRUE;
111 } 111 }
112 // The text hasn't changed yet, so defer calling 112 // The text hasn't changed yet, so defer calling
113 // DispatchAccessibilityNotification. 113 // DispatchAccessibilityNotification.
114 reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)-> 114 reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
115 PostDispatchAccessibilityNotification( 115 PostDispatchAccessibilityNotification(
116 widget, NotificationType::ACCESSIBILITY_TEXT_CHANGED); 116 widget, NotificationType::ACCESSIBILITY_TEXT_CHANGED);
117 return TRUE; 117 return TRUE;
118 } 118 }
119 119
120 gboolean OnTextBufferChanged(GSignalInvocationHint *ihint,
121 guint n_param_values,
122 const GValue* param_values,
123 gpointer user_data) {
124 // The text hasn't changed yet, so defer calling
125 // DispatchAccessibilityNotification.
126 reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
127 PostDispatchAccessibilityNotification(
128 NULL, NotificationType::ACCESSIBILITY_TEXT_CHANGED);
129 return TRUE;
130 }
131
132 gboolean OnTextViewChanged(GSignalInvocationHint *ihint,
133 guint n_param_values,
134 const GValue* param_values,
135 gpointer user_data) {
136 GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
137 if (!GTK_IS_TEXT_VIEW(widget)) {
138 return TRUE;
139 }
140 // The text hasn't changed yet, so defer calling
141 // DispatchAccessibilityNotification.
142 reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
143 PostDispatchAccessibilityNotification(
144 widget, NotificationType::ACCESSIBILITY_TEXT_CHANGED);
145 return TRUE;
146 }
147
120 gboolean OnMenuMoveCurrent(GSignalInvocationHint *ihint, 148 gboolean OnMenuMoveCurrent(GSignalInvocationHint *ihint,
121 guint n_param_values, 149 guint n_param_values,
122 const GValue* param_values, 150 const GValue* param_values,
123 gpointer user_data) { 151 gpointer user_data) {
124 // Get the widget (the GtkMenu). 152 // Get the widget (the GtkMenu).
125 GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values)); 153 GtkWidget* widget = GTK_WIDGET(g_value_get_object(param_values));
126 154
127 // Moving may move us into or out of a submenu, so after the menu 155 // Moving may move us into or out of a submenu, so after the menu
128 // item moves, |widget| may not be valid anymore. To be safe, then, 156 // item moves, |widget| may not be valid anymore. To be safe, then,
129 // find the topmost ancestor of this menu and post the notification 157 // find the topmost ancestor of this menu and post the notification
130 // dispatch on that menu. Then the dispatcher will recurse into submenus 158 // dispatch on that menu. Then the dispatcher will recurse into submenus
131 // as necessary to figure out which item is focused. 159 // as necessary to figure out which item is focused.
132 while (GTK_MENU_SHELL(widget)->parent_menu_shell) 160 while (GTK_MENU_SHELL(widget)->parent_menu_shell)
133 widget = GTK_MENU_SHELL(widget)->parent_menu_shell; 161 widget = GTK_MENU_SHELL(widget)->parent_menu_shell;
134 162
135 // The menu item hasn't moved yet, so we want to defer calling 163 // The menu item hasn't moved yet, so we want to defer calling
136 // DispatchAccessibilityNotification until after it does. 164 // DispatchAccessibilityNotification until after it does.
137 reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)-> 165 reinterpret_cast<AccessibilityEventRouterGtk*>(user_data)->
138 PostDispatchAccessibilityNotification( 166 PostDispatchAccessibilityNotification(
139 widget, NotificationType::ACCESSIBILITY_CONTROL_FOCUSED); 167 widget, NotificationType::ACCESSIBILITY_CONTROL_FOCUSED);
140 return TRUE; 168 return TRUE;
141 } 169 }
142 170
143 } // anonymous namespace 171 } // anonymous namespace
144 172
145 AccessibilityEventRouterGtk::AccessibilityEventRouterGtk() 173 AccessibilityEventRouterGtk::AccessibilityEventRouterGtk()
146 : listening_(false), 174 : listening_(false),
147 most_recent_profile_(NULL), 175 most_recent_profile_(NULL),
176 most_recent_widget_(NULL),
148 method_factory_(this) { 177 method_factory_(this) {
149 // We don't want our event listeners to be installed if accessibility is 178 // We don't want our event listeners to be installed if accessibility is
150 // disabled. Install listeners so we can install and uninstall them as 179 // disabled. Install listeners so we can install and uninstall them as
151 // needed, then install them now if it's currently enabled. 180 // needed, then install them now if it's currently enabled.
152 ExtensionAccessibilityEventRouter *extension_event_router = 181 ExtensionAccessibilityEventRouter *extension_event_router =
153 ExtensionAccessibilityEventRouter::GetInstance(); 182 ExtensionAccessibilityEventRouter::GetInstance();
154 extension_event_router->AddOnEnabledListener( 183 extension_event_router->AddOnEnabledListener(
155 NewCallback(this, 184 NewCallback(this,
156 &AccessibilityEventRouterGtk::InstallEventListeners)); 185 &AccessibilityEventRouterGtk::InstallEventListeners));
157 extension_event_router->AddOnDisabledListener( 186 extension_event_router->AddOnDisabledListener(
(...skipping 25 matching lines...) Expand all
183 212
184 void AccessibilityEventRouterGtk::InstallEventListeners() { 213 void AccessibilityEventRouterGtk::InstallEventListeners() {
185 // Create and destroy each type of widget we need signals for, 214 // Create and destroy each type of widget we need signals for,
186 // to ensure their modules are loaded, otherwise g_signal_lookup 215 // to ensure their modules are loaded, otherwise g_signal_lookup
187 // might fail. 216 // might fail.
188 g_object_unref(g_object_ref_sink(gtk_combo_box_new())); 217 g_object_unref(g_object_ref_sink(gtk_combo_box_new()));
189 g_object_unref(g_object_ref_sink(gtk_entry_new())); 218 g_object_unref(g_object_ref_sink(gtk_entry_new()));
190 g_object_unref(g_object_ref_sink(gtk_notebook_new())); 219 g_object_unref(g_object_ref_sink(gtk_notebook_new()));
191 g_object_unref(g_object_ref_sink(gtk_toggle_button_new())); 220 g_object_unref(g_object_ref_sink(gtk_toggle_button_new()));
192 g_object_unref(g_object_ref_sink(gtk_tree_view_new())); 221 g_object_unref(g_object_ref_sink(gtk_tree_view_new()));
222 g_object_unref(g_object_ref_sink(gtk_text_view_new()));
223 g_object_unref(g_object_ref_sink(gtk_text_buffer_new(NULL)));
193 224
194 // Add signal emission hooks for the events we're interested in. 225 // Add signal emission hooks for the events we're interested in.
195 InstallEventListener("clicked", GTK_TYPE_BUTTON, OnButtonClicked); 226 InstallEventListener("clicked", GTK_TYPE_BUTTON, OnButtonClicked);
196 InstallEventListener("changed", GTK_TYPE_COMBO_BOX, OnComboBoxChanged); 227 InstallEventListener("changed", GTK_TYPE_COMBO_BOX, OnComboBoxChanged);
197 InstallEventListener("cursor-changed", GTK_TYPE_TREE_VIEW, 228 InstallEventListener("cursor-changed", GTK_TYPE_TREE_VIEW,
198 OnTreeViewCursorChanged); 229 OnTreeViewCursorChanged);
199 InstallEventListener("changed", GTK_TYPE_ENTRY, OnEntryChanged); 230 InstallEventListener("changed", GTK_TYPE_ENTRY, OnEntryChanged);
200 InstallEventListener("insert-text", GTK_TYPE_ENTRY, OnEntryChanged); 231 InstallEventListener("insert-text", GTK_TYPE_ENTRY, OnEntryChanged);
201 InstallEventListener("delete-text", GTK_TYPE_ENTRY, OnEntryChanged); 232 InstallEventListener("delete-text", GTK_TYPE_ENTRY, OnEntryChanged);
202 InstallEventListener("move-cursor", GTK_TYPE_ENTRY, OnEntryChanged); 233 InstallEventListener("move-cursor", GTK_TYPE_ENTRY, OnEntryChanged);
203 InstallEventListener("focus-in-event", GTK_TYPE_WIDGET, OnWidgetFocused); 234 InstallEventListener("focus-in-event", GTK_TYPE_WIDGET, OnWidgetFocused);
204 InstallEventListener("switch-page", GTK_TYPE_NOTEBOOK, OnPageSwitched); 235 InstallEventListener("switch-page", GTK_TYPE_NOTEBOOK, OnPageSwitched);
205 InstallEventListener("toggled", GTK_TYPE_TOGGLE_BUTTON, OnButtonToggled); 236 InstallEventListener("toggled", GTK_TYPE_TOGGLE_BUTTON, OnButtonToggled);
206 InstallEventListener("move-current", GTK_TYPE_MENU, OnMenuMoveCurrent); 237 InstallEventListener("move-current", GTK_TYPE_MENU, OnMenuMoveCurrent);
238 InstallEventListener("changed", GTK_TYPE_TEXT_BUFFER, OnTextBufferChanged);
239 InstallEventListener("move-cursor", GTK_TYPE_TEXT_VIEW, OnTextViewChanged);
207 240
208 listening_ = true; 241 listening_ = true;
209 } 242 }
210 243
211 void AccessibilityEventRouterGtk::RemoveEventListeners() { 244 void AccessibilityEventRouterGtk::RemoveEventListeners() {
212 for (size_t i = 0; i < installed_hooks_.size(); i++) { 245 for (size_t i = 0; i < installed_hooks_.size(); i++) {
213 g_signal_remove_emission_hook( 246 g_signal_remove_emission_hook(
214 installed_hooks_[i].signal_id, 247 installed_hooks_[i].signal_id,
215 installed_hooks_[i].hook_id); 248 installed_hooks_[i].hook_id);
216 } 249 }
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 listening_ = false; 323 listening_ = false;
291 } 324 }
292 325
293 void AccessibilityEventRouterGtk::DispatchAccessibilityNotification( 326 void AccessibilityEventRouterGtk::DispatchAccessibilityNotification(
294 GtkWidget* widget, NotificationType type) { 327 GtkWidget* widget, NotificationType type) {
295 if (!listening_) 328 if (!listening_)
296 return; 329 return;
297 330
298 Profile* profile = NULL; 331 Profile* profile = NULL;
299 bool is_accessible; 332 bool is_accessible;
333
334 // Special case: when we get ACCESSIBILITY_TEXT_CHANGED, we don't get
335 // a pointer to the widget, so we try to retrieve it from the most recent
336 // widget.
337 if (widget == NULL &&
338 type == NotificationType::ACCESSIBILITY_TEXT_CHANGED &&
339 most_recent_widget_ &&
340 GTK_IS_TEXT_VIEW(most_recent_widget_)) {
341 widget = most_recent_widget_;
342 }
343
344 if (!widget)
345 return;
346
347 most_recent_widget_ = widget;
300 FindWidget(widget, &profile, &is_accessible); 348 FindWidget(widget, &profile, &is_accessible);
301 if (profile) 349 if (profile)
302 most_recent_profile_ = profile; 350 most_recent_profile_ = profile;
303 351
304 // Special case: a GtkMenu isn't associated with any particular 352 // Special case: a GtkMenu isn't associated with any particular
305 // toplevel window, so menu events get routed to the profile of 353 // toplevel window, so menu events get routed to the profile of
306 // the most recent event that was associated with a window. 354 // the most recent event that was associated with a window.
307 if (GTK_IS_MENU_SHELL(widget) && most_recent_profile_) { 355 if (GTK_IS_MENU_SHELL(widget) && most_recent_profile_) {
308 SendMenuItemNotification(widget, type, most_recent_profile_); 356 SendMenuItemNotification(widget, type, most_recent_profile_);
309 return; 357 return;
(...skipping 14 matching lines...) Expand all
324 SendComboBoxNotification(widget, type, profile); 372 SendComboBoxNotification(widget, type, profile);
325 } else if (parent && GTK_IS_COMBO_BOX(parent)) { 373 } else if (parent && GTK_IS_COMBO_BOX(parent)) {
326 SendComboBoxNotification(parent, type, profile); 374 SendComboBoxNotification(parent, type, profile);
327 } else if (GTK_IS_RADIO_BUTTON(widget)) { 375 } else if (GTK_IS_RADIO_BUTTON(widget)) {
328 SendRadioButtonNotification(widget, type, profile); 376 SendRadioButtonNotification(widget, type, profile);
329 } else if (GTK_IS_TOGGLE_BUTTON(widget)) { 377 } else if (GTK_IS_TOGGLE_BUTTON(widget)) {
330 SendCheckboxNotification(widget, type, profile); 378 SendCheckboxNotification(widget, type, profile);
331 } else if (GTK_IS_BUTTON(widget)) { 379 } else if (GTK_IS_BUTTON(widget)) {
332 SendButtonNotification(widget, type, profile); 380 SendButtonNotification(widget, type, profile);
333 } else if (GTK_IS_ENTRY(widget)) { 381 } else if (GTK_IS_ENTRY(widget)) {
334 SendTextBoxNotification(widget, type, profile); 382 SendEntryNotification(widget, type, profile);
383 } else if (GTK_IS_TEXT_VIEW(widget)) {
384 SendTextViewNotification(widget, type, profile);
335 } else if (GTK_IS_NOTEBOOK(widget)) { 385 } else if (GTK_IS_NOTEBOOK(widget)) {
336 SendTabNotification(widget, type, profile); 386 SendTabNotification(widget, type, profile);
337 } else if (GTK_IS_TREE_VIEW(widget)) { 387 } else if (GTK_IS_TREE_VIEW(widget)) {
338 SendListBoxNotification(widget, type, profile); 388 SendListBoxNotification(widget, type, profile);
339 } else { 389 } else {
340 // If we have no idea what this control is, return and skip the 390 // If we have no idea what this control is, return and skip the
341 // temporary pause in event listening. 391 // temporary pause in event listening.
342 return; 392 return;
343 } 393 }
344 394
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 453
404 void AccessibilityEventRouterGtk::SendButtonNotification( 454 void AccessibilityEventRouterGtk::SendButtonNotification(
405 GtkWidget* widget, NotificationType type, Profile* profile) { 455 GtkWidget* widget, NotificationType type, Profile* profile) {
406 std::string button_name = GetWidgetName(widget); 456 std::string button_name = GetWidgetName(widget);
407 if (button_name.empty() && gtk_button_get_label(GTK_BUTTON(widget))) 457 if (button_name.empty() && gtk_button_get_label(GTK_BUTTON(widget)))
408 button_name = gtk_button_get_label(GTK_BUTTON(widget)); 458 button_name = gtk_button_get_label(GTK_BUTTON(widget));
409 AccessibilityButtonInfo info(profile, button_name); 459 AccessibilityButtonInfo info(profile, button_name);
410 SendAccessibilityNotification(type, &info); 460 SendAccessibilityNotification(type, &info);
411 } 461 }
412 462
413 void AccessibilityEventRouterGtk::SendTextBoxNotification( 463 void AccessibilityEventRouterGtk::SendEntryNotification(
414 GtkWidget* widget, NotificationType type, Profile* profile) { 464 GtkWidget* widget, NotificationType type, Profile* profile) {
415 std::string name = GetWidgetName(widget); 465 std::string name = GetWidgetName(widget);
416 std::string value = gtk_entry_get_text(GTK_ENTRY(widget)); 466 std::string value = gtk_entry_get_text(GTK_ENTRY(widget));
417 gint start_pos; 467 gint start_pos;
418 gint end_pos; 468 gint end_pos;
419 gtk_editable_get_selection_bounds(GTK_EDITABLE(widget), &start_pos, &end_pos); 469 gtk_editable_get_selection_bounds(GTK_EDITABLE(widget), &start_pos, &end_pos);
420 AccessibilityTextBoxInfo info(profile, name, false); 470 AccessibilityTextBoxInfo info(profile, name, false);
421 info.SetValue(value, start_pos, end_pos); 471 info.SetValue(value, start_pos, end_pos);
422 SendAccessibilityNotification(type, &info); 472 SendAccessibilityNotification(type, &info);
423 } 473 }
424 474
475 void AccessibilityEventRouterGtk::SendTextViewNotification(
476 GtkWidget* widget, NotificationType type, Profile* profile) {
477 std::string name = GetWidgetName(widget);
478 GtkTextBuffer* buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget));
479 GtkTextIter start, end;
480 gtk_text_buffer_get_bounds(buffer, &start, &end);
481 gchar* text = gtk_text_buffer_get_text(buffer, &start, &end, false);
482 std::string value = text;
483 g_free(text);
484 GtkTextIter sel_start, sel_end;
485 gtk_text_buffer_get_selection_bounds(buffer, &sel_start, &sel_end);
486 int start_pos = gtk_text_iter_get_offset(&sel_start);
487 int end_pos = gtk_text_iter_get_offset(&sel_end);
488 AccessibilityTextBoxInfo info(profile, name, false);
489 info.SetValue(value, start_pos, end_pos);
490 SendAccessibilityNotification(type, &info);
491 }
492
425 void AccessibilityEventRouterGtk::SendTabNotification( 493 void AccessibilityEventRouterGtk::SendTabNotification(
426 GtkWidget* widget, NotificationType type, Profile* profile) { 494 GtkWidget* widget, NotificationType type, Profile* profile) {
427 int index = gtk_notebook_get_current_page(GTK_NOTEBOOK(widget)); 495 int index = gtk_notebook_get_current_page(GTK_NOTEBOOK(widget));
428 int page_count = gtk_notebook_get_n_pages(GTK_NOTEBOOK(widget)); 496 int page_count = gtk_notebook_get_n_pages(GTK_NOTEBOOK(widget));
429 GtkWidget* page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(widget), index); 497 GtkWidget* page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(widget), index);
430 GtkWidget* label = gtk_notebook_get_tab_label(GTK_NOTEBOOK(widget), page); 498 GtkWidget* label = gtk_notebook_get_tab_label(GTK_NOTEBOOK(widget), page);
431 std::string name = GetWidgetName(widget); 499 std::string name = GetWidgetName(widget);
432 if (name.empty() && gtk_label_get_text(GTK_LABEL(label))) { 500 if (name.empty() && gtk_label_get_text(GTK_LABEL(label))) {
433 name = gtk_label_get_text(GTK_LABEL(label)); 501 name = gtk_label_get_text(GTK_LABEL(label));
434 } 502 }
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
559 name = gtk_label_get_label(GTK_LABEL(child)); 627 name = gtk_label_get_label(GTK_LABEL(child));
560 break; 628 break;
561 } 629 }
562 } 630 }
563 #endif 631 #endif
564 632
565 // Send the event. 633 // Send the event.
566 AccessibilityMenuItemInfo info(profile, name, submenu != NULL, index, count); 634 AccessibilityMenuItemInfo info(profile, name, submenu != NULL, index, count);
567 SendAccessibilityNotification(type, &info); 635 SendAccessibilityNotification(type, &info);
568 } 636 }
OLDNEW
« no previous file with comments | « chrome/browser/gtk/accessibility_event_router_gtk.h ('k') | chrome/browser/gtk/accessible_widget_helper_gtk.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698