1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef UI_VIEWS_ACCESSIBILITY_NATIVE_VIEW_ACCESSIBILITY_WIN_H_ 6 #define UI_VIEWS_ACCESSIBILITY_NATIVE_VIEW_ACCESSIBILITY_WIN_H_ 7 8 #include <atlbase.h> 9 #include <atlcom.h> 10 #include <oleacc.h> 11 12 #include <UIAutomationCore.h> 13 14 #include <set> 15 #include <vector> 16 17 #include "third_party/iaccessible2/ia2_api_all.h" 18 #include "ui/accessibility/ax_view_state.h" 19 #include "ui/views/accessibility/native_view_accessibility.h" 20 #include "ui/views/controls/native/native_view_host.h" 21 #include "ui/views/view.h" 22 23 namespace ui { 24 enum TextBoundaryDirection; 25 enum TextBoundaryType; 26 } 27 28 namespace views { 29 30 //////////////////////////////////////////////////////////////////////////////// 31 // 32 // NativeViewAccessibilityWin 33 // 34 // Class implementing the MSAA IAccessible COM interface for a generic View, 35 // providing accessibility to be used by screen readers and other assistive 36 // technology (AT). 37 // 38 //////////////////////////////////////////////////////////////////////////////// 39 class __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2")) 40 NativeViewAccessibilityWin 41 : public CComObjectRootEx<CComMultiThreadModel>, 42 public IDispatchImpl<IAccessible2_2, &IID_IAccessible2_2, 43 &LIBID_IAccessible2Lib>, 44 public IAccessibleText, 45 public IServiceProvider, 46 public IAccessibleEx, 47 public IRawElementProviderSimple, 48 public NativeViewAccessibility { 49 public: 50 BEGIN_COM_MAP(NativeViewAccessibilityWin) 51 COM_INTERFACE_ENTRY2(IDispatch, IAccessible2_2) 52 COM_INTERFACE_ENTRY(IAccessible) 53 COM_INTERFACE_ENTRY(IAccessible2) 54 COM_INTERFACE_ENTRY(IAccessible2_2) 55 COM_INTERFACE_ENTRY(IAccessibleEx) 56 COM_INTERFACE_ENTRY(IAccessibleText) 57 COM_INTERFACE_ENTRY(IRawElementProviderSimple) 58 COM_INTERFACE_ENTRY(IServiceProvider) 59 END_COM_MAP() 60 61 virtual ~NativeViewAccessibilityWin(); 62 63 // NativeViewAccessibility. 64 virtual void NotifyAccessibilityEvent( 65 ui::AXEvent event_type) OVERRIDE; 66 virtual gfx::NativeViewAccessible GetNativeObject() OVERRIDE; 67 virtual void Destroy() OVERRIDE; 68 69 void set_view(views::View* view) { view_ = view; } 70 71 // Supported IAccessible methods. 72 73 // Retrieves the child element or child object at a given point on the screen. 74 virtual STDMETHODIMP accHitTest(LONG x_left, LONG y_top, VARIANT* child); 75 76 // Performs the object's default action. 77 STDMETHODIMP accDoDefaultAction(VARIANT var_id); 78 79 // Retrieves the specified object's current screen location. 80 STDMETHODIMP accLocation(LONG* x_left, 81 LONG* y_top, 82 LONG* width, 83 LONG* height, 84 VARIANT var_id); 85 86 // Traverses to another UI element and retrieves the object. 87 STDMETHODIMP accNavigate(LONG nav_dir, VARIANT start, VARIANT* end); 88 89 // Retrieves an IDispatch interface pointer for the specified child. 90 virtual STDMETHODIMP get_accChild(VARIANT var_child, IDispatch** disp_child); 91 92 // Retrieves the number of accessible children. 93 virtual STDMETHODIMP get_accChildCount(LONG* child_count); 94 95 // Retrieves a string that describes the object's default action. 96 STDMETHODIMP get_accDefaultAction(VARIANT var_id, BSTR* default_action); 97 98 // Retrieves the tooltip description. 99 STDMETHODIMP get_accDescription(VARIANT var_id, BSTR* desc); 100 101 // Retrieves the object that has the keyboard focus. 102 STDMETHODIMP get_accFocus(VARIANT* focus_child); 103 104 // Retrieves the specified object's shortcut. 105 STDMETHODIMP get_accKeyboardShortcut(VARIANT var_id, BSTR* access_key); 106 107 // Retrieves the name of the specified object. 108 STDMETHODIMP get_accName(VARIANT var_id, BSTR* name); 109 110 // Retrieves the IDispatch interface of the object's parent. 111 STDMETHODIMP get_accParent(IDispatch** disp_parent); 112 113 // Retrieves information describing the role of the specified object. 114 STDMETHODIMP get_accRole(VARIANT var_id, VARIANT* role); 115 116 // Retrieves the current state of the specified object. 117 STDMETHODIMP get_accState(VARIANT var_id, VARIANT* state); 118 119 // Retrieve or set the string value associated with the specified object. 120 // Setting the value is not typically used by screen readers, but it's 121 // used frequently by automation software. 122 STDMETHODIMP get_accValue(VARIANT var_id, BSTR* value); 123 STDMETHODIMP put_accValue(VARIANT var_id, BSTR new_value); 124 125 // Selections not applicable to views. 126 STDMETHODIMP get_accSelection(VARIANT* selected); 127 STDMETHODIMP accSelect(LONG flags_sel, VARIANT var_id); 128 129 // Help functions not supported. 130 STDMETHODIMP get_accHelp(VARIANT var_id, BSTR* help); 131 STDMETHODIMP get_accHelpTopic(BSTR* help_file, 132 VARIANT var_id, 133 LONG* topic_id); 134 135 // Deprecated functions, not implemented here. 136 STDMETHODIMP put_accName(VARIANT var_id, BSTR put_name); 137 138 // 139 // IAccessible2 140 // 141 142 STDMETHODIMP role(LONG* role); 143 144 STDMETHODIMP get_states(AccessibleStates* states); 145 146 STDMETHODIMP get_uniqueID(LONG* unique_id); 147 148 STDMETHODIMP get_windowHandle(HWND* window_handle); 149 150 STDMETHODIMP get_relationTargetsOfType(BSTR type, 151 long max_targets, 152 IUnknown ***targets, 153 long *n_targets); 154 155 // 156 // IAccessible2 methods not implemented. 157 // 158 159 STDMETHODIMP get_attributes(BSTR* attributes) { 160 return E_NOTIMPL; 161 } 162 STDMETHODIMP get_attribute(BSTR name, VARIANT* attribute) { 163 return E_NOTIMPL; 164 } 165 STDMETHODIMP get_indexInParent(LONG* index_in_parent) { 166 return E_NOTIMPL; 167 } 168 STDMETHODIMP get_extendedRole(BSTR* extended_role) { 169 return E_NOTIMPL; 170 } 171 STDMETHODIMP get_nRelations(LONG* n_relations) { 172 return E_NOTIMPL; 173 } 174 STDMETHODIMP get_relation(LONG relation_index, 175 IAccessibleRelation** relation) { 176 return E_NOTIMPL; 177 } 178 STDMETHODIMP get_relations(LONG max_relations, 179 IAccessibleRelation** relations, 180 LONG* n_relations) { 181 return E_NOTIMPL; 182 } 183 STDMETHODIMP scrollTo(enum IA2ScrollType scroll_type) { 184 return E_NOTIMPL; 185 } 186 STDMETHODIMP scrollToPoint( 187 enum IA2CoordinateType coordinate_type, 188 LONG x, 189 LONG y) { 190 return E_NOTIMPL; 191 } 192 STDMETHODIMP get_groupPosition(LONG* group_level, 193 LONG* similar_items_in_group, 194 LONG* position_in_group) { 195 return E_NOTIMPL; 196 } 197 STDMETHODIMP get_localizedExtendedRole( 198 BSTR* localized_extended_role) { 199 return E_NOTIMPL; 200 } 201 STDMETHODIMP get_nExtendedStates(LONG* n_extended_states) { 202 return E_NOTIMPL; 203 } 204 STDMETHODIMP get_extendedStates(LONG max_extended_states, 205 BSTR** extended_states, 206 LONG* n_extended_states) { 207 return E_NOTIMPL; 208 } 209 STDMETHODIMP get_localizedExtendedStates( 210 LONG max_localized_extended_states, 211 BSTR** localized_extended_states, 212 LONG* n_localized_extended_states) { 213 return E_NOTIMPL; 214 } 215 STDMETHODIMP get_locale(IA2Locale* locale) { 216 return E_NOTIMPL; 217 } 218 STDMETHODIMP get_accessibleWithCaret(IUnknown** accessible, 219 long* caret_offset) { 220 return E_NOTIMPL; 221 } 222 223 // 224 // IAccessibleText methods. 225 // 226 227 STDMETHODIMP get_nCharacters(LONG* n_characters); 228 229 STDMETHODIMP get_caretOffset(LONG* offset); 230 231 STDMETHODIMP get_nSelections(LONG* n_selections); 232 233 STDMETHODIMP get_selection(LONG selection_index, 234 LONG* start_offset, 235 LONG* end_offset); 236 237 STDMETHODIMP get_text(LONG start_offset, LONG end_offset, BSTR* text); 238 239 STDMETHODIMP get_textAtOffset(LONG offset, 240 enum IA2TextBoundaryType boundary_type, 241 LONG* start_offset, LONG* end_offset, 242 BSTR* text); 243 244 STDMETHODIMP get_textBeforeOffset(LONG offset, 245 enum IA2TextBoundaryType boundary_type, 246 LONG* start_offset, LONG* end_offset, 247 BSTR* text); 248 249 STDMETHODIMP get_textAfterOffset(LONG offset, 250 enum IA2TextBoundaryType boundary_type, 251 LONG* start_offset, LONG* end_offset, 252 BSTR* text); 253 254 STDMETHODIMP get_offsetAtPoint(LONG x, LONG y, 255 enum IA2CoordinateType coord_type, 256 LONG* offset); 257 258 // 259 // IAccessibleText methods not implemented. 260 // 261 262 STDMETHODIMP get_newText(IA2TextSegment* new_text) { 263 return E_NOTIMPL; 264 } 265 STDMETHODIMP get_oldText(IA2TextSegment* old_text) { 266 return E_NOTIMPL; 267 } 268 STDMETHODIMP addSelection(LONG start_offset, LONG end_offset) { 269 return E_NOTIMPL; 270 } 271 STDMETHODIMP get_attributes(LONG offset, 272 LONG* start_offset, 273 LONG* end_offset, 274 BSTR* text_attributes) { 275 return E_NOTIMPL; 276 } 277 STDMETHODIMP get_characterExtents(LONG offset, 278 enum IA2CoordinateType coord_type, 279 LONG* x, LONG* y, 280 LONG* width, LONG* height) { 281 return E_NOTIMPL; 282 } 283 STDMETHODIMP removeSelection(LONG selection_index) { 284 return E_NOTIMPL; 285 } 286 STDMETHODIMP setCaretOffset(LONG offset) { 287 return E_NOTIMPL; 288 } 289 STDMETHODIMP setSelection(LONG selection_index, 290 LONG start_offset, 291 LONG end_offset) { 292 return E_NOTIMPL; 293 } 294 STDMETHODIMP scrollSubstringTo(LONG start_index, 295 LONG end_index, 296 enum IA2ScrollType scroll_type) { 297 return E_NOTIMPL; 298 } 299 STDMETHODIMP scrollSubstringToPoint(LONG start_index, 300 LONG end_index, 301 enum IA2CoordinateType coordinate_type, 302 LONG x, LONG y) { 303 return E_NOTIMPL; 304 } 305 306 // 307 // IServiceProvider methods. 308 // 309 310 STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, void** object); 311 312 // 313 // IAccessibleEx methods not implemented. 314 // 315 STDMETHODIMP GetObjectForChild(long child_id, IAccessibleEx** ret) { 316 return E_NOTIMPL; 317 } 318 319 STDMETHODIMP GetIAccessiblePair(IAccessible** acc, long* child_id) { 320 return E_NOTIMPL; 321 } 322 323 STDMETHODIMP GetRuntimeId(SAFEARRAY** runtime_id) { 324 return E_NOTIMPL; 325 } 326 327 STDMETHODIMP ConvertReturnedElement(IRawElementProviderSimple* element, 328 IAccessibleEx** acc) { 329 return E_NOTIMPL; 330 } 331 332 // 333 // IRawElementProviderSimple methods. 334 // 335 // The GetPatternProvider/GetPropertyValue methods need to be implemented for 336 // the on-screen keyboard to show up in Windows 8 metro. 337 STDMETHODIMP GetPatternProvider(PATTERNID id, IUnknown** provider); 338 STDMETHODIMP GetPropertyValue(PROPERTYID id, VARIANT* ret); 339 340 // 341 // IRawElementProviderSimple methods not implemented. 342 // 343 STDMETHODIMP get_ProviderOptions(enum ProviderOptions* ret) { 344 return E_NOTIMPL; 345 } 346 347 STDMETHODIMP get_HostRawElementProvider( 348 IRawElementProviderSimple** provider) { 349 return E_NOTIMPL; 350 } 351 352 // Static methods 353 354 // Returns a conversion from the event (as defined in ax_enums.idl) 355 // to an MSAA event. 356 static int32 MSAAEvent(ui::AXEvent event); 357 358 // Returns a conversion from the Role (as defined in ax_enums.idl) 359 // to an MSAA role. 360 static int32 MSAARole(ui::AXRole role); 361 362 // Returns a conversion from the State (as defined in ax_enums.idl) 363 // to MSAA states set. 364 static int32 MSAAState(const ui::AXViewState& state); 365 366 protected: 367 NativeViewAccessibilityWin(); 368 369 const View* view() const { return view_; } 370 371 private: 372 // Determines navigation direction for accNavigate, based on left, up and 373 // previous being mapped all to previous and right, down, next being mapped 374 // to next. Returns true if navigation direction is next, false otherwise. 375 bool IsNavDirNext(int nav_dir) const; 376 377 // Determines if the navigation target is within the allowed bounds. Returns 378 // true if it is, false otherwise. 379 bool IsValidNav(int nav_dir, 380 int start_id, 381 int lower_bound, 382 int upper_bound) const; 383 384 // Determines if the child id variant is valid. 385 bool IsValidId(const VARIANT& child) const; 386 387 // Helper function which sets applicable states of view. 388 void SetState(VARIANT* msaa_state, View* view); 389 390 // Return the text to use for IAccessibleText. 391 base::string16 TextForIAccessibleText(); 392 393 // If offset is a member of IA2TextSpecialOffsets this function updates the 394 // value of offset and returns, otherwise offset remains unchanged. 395 void HandleSpecialTextOffset(const base::string16& text, LONG* offset); 396 397 // Convert from a IA2TextBoundaryType to a ui::TextBoundaryType. 398 ui::TextBoundaryType IA2TextBoundaryToTextBoundary(IA2TextBoundaryType type); 399 400 // Search forwards (direction == 1) or backwards (direction == -1) 401 // from the given offset until the given boundary is found, and 402 // return the offset of that boundary. 403 LONG FindBoundary(const base::string16& text, 404 IA2TextBoundaryType ia2_boundary, 405 LONG start_offset, 406 ui::TextBoundaryDirection direction); 407 408 // Populates the given vector with all widgets that are either a child 409 // or are owned by this view's widget, and who are not contained in a 410 // NativeViewHost. 411 void PopulateChildWidgetVector(std::vector<Widget*>* child_widgets); 412 413 // Adds this view to alert_target_view_storage_ids_. 414 void AddAlertTarget(); 415 416 // Removes this view from alert_target_view_storage_ids_. 417 void RemoveAlertTarget(); 418 419 // Give CComObject access to the class constructor. 420 template <class Base> friend class CComObject; 421 422 // Member View needed for view-specific calls. 423 View* view_; 424 425 // A unique id for each object, needed for IAccessible2. 426 long unique_id_; 427 428 // Next unique id to assign. 429 static long next_unique_id_; 430 431 // Circular queue size. 432 static const int kMaxViewStorageIds = 20; 433 434 // Circular queue of view storage ids corresponding to child ids 435 // used to post notifications using NotifyWinEvent. 436 static int view_storage_ids_[kMaxViewStorageIds]; 437 438 // Next index into |view_storage_ids_| to use. 439 static int next_view_storage_id_index_; 440 441 // A vector of view storage ids of views that have been the target of 442 // an alert event, in order to provide an api to quickly identify all 443 // open alerts. 444 static std::vector<int> alert_target_view_storage_ids_; 445 446 DISALLOW_COPY_AND_ASSIGN(NativeViewAccessibilityWin); 447 }; 448 449 } // namespace views 450 451 #endif // UI_VIEWS_ACCESSIBILITY_NATIVE_VIEW_ACCESSIBILITY_WIN_H_ 452