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