Home | History | Annotate | Download | only in accessibility
      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   // 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   STDMETHODIMP get_relationTargetsOfType(BSTR type,
    149                                          long max_targets,
    150                                          IUnknown ***targets,
    151                                          long *n_targets);
    152 
    153   STDMETHODIMP get_attributes(BSTR* attributes);
    154 
    155   //
    156   // IAccessible2 methods not implemented.
    157   //
    158 
    159   STDMETHODIMP get_attribute(BSTR name, VARIANT* attribute) {
    160     return E_NOTIMPL;
    161   }
    162   STDMETHODIMP get_indexInParent(LONG* index_in_parent) {
    163     return E_NOTIMPL;
    164   }
    165   STDMETHODIMP get_extendedRole(BSTR* extended_role) {
    166     return E_NOTIMPL;
    167   }
    168   STDMETHODIMP get_nRelations(LONG* n_relations) {
    169     return E_NOTIMPL;
    170   }
    171   STDMETHODIMP get_relation(LONG relation_index,
    172                             IAccessibleRelation** relation) {
    173     return E_NOTIMPL;
    174   }
    175   STDMETHODIMP get_relations(LONG max_relations,
    176       IAccessibleRelation** relations,
    177       LONG* n_relations) {
    178     return E_NOTIMPL;
    179   }
    180   STDMETHODIMP scrollTo(enum IA2ScrollType scroll_type) {
    181     return E_NOTIMPL;
    182   }
    183   STDMETHODIMP scrollToPoint(
    184       enum IA2CoordinateType coordinate_type,
    185       LONG x,
    186       LONG y) {
    187     return E_NOTIMPL;
    188   }
    189   STDMETHODIMP get_groupPosition(LONG* group_level,
    190                                  LONG* similar_items_in_group,
    191                                  LONG* position_in_group) {
    192     return E_NOTIMPL;
    193   }
    194   STDMETHODIMP get_localizedExtendedRole(
    195       BSTR* localized_extended_role) {
    196     return E_NOTIMPL;
    197   }
    198   STDMETHODIMP get_nExtendedStates(LONG* n_extended_states) {
    199     return E_NOTIMPL;
    200   }
    201   STDMETHODIMP get_extendedStates(LONG max_extended_states,
    202                                   BSTR** extended_states,
    203                                   LONG* n_extended_states) {
    204     return E_NOTIMPL;
    205   }
    206   STDMETHODIMP get_localizedExtendedStates(
    207       LONG max_localized_extended_states,
    208       BSTR** localized_extended_states,
    209       LONG* n_localized_extended_states) {
    210     return E_NOTIMPL;
    211   }
    212   STDMETHODIMP get_locale(IA2Locale* locale) {
    213     return E_NOTIMPL;
    214   }
    215   STDMETHODIMP get_accessibleWithCaret(IUnknown** accessible,
    216                                        long* caret_offset) {
    217     return E_NOTIMPL;
    218   }
    219 
    220   //
    221   // IAccessibleText methods.
    222   //
    223 
    224   STDMETHODIMP get_nCharacters(LONG* n_characters);
    225 
    226   STDMETHODIMP get_caretOffset(LONG* offset);
    227 
    228   STDMETHODIMP get_nSelections(LONG* n_selections);
    229 
    230   STDMETHODIMP get_selection(LONG selection_index,
    231                              LONG* start_offset,
    232                              LONG* end_offset);
    233 
    234   STDMETHODIMP get_text(LONG start_offset, LONG end_offset, BSTR* text);
    235 
    236   STDMETHODIMP get_textAtOffset(LONG offset,
    237                                 enum IA2TextBoundaryType boundary_type,
    238                                 LONG* start_offset, LONG* end_offset,
    239                                 BSTR* text);
    240 
    241   STDMETHODIMP get_textBeforeOffset(LONG offset,
    242                                     enum IA2TextBoundaryType boundary_type,
    243                                     LONG* start_offset, LONG* end_offset,
    244                                     BSTR* text);
    245 
    246   STDMETHODIMP get_textAfterOffset(LONG offset,
    247                                    enum IA2TextBoundaryType boundary_type,
    248                                    LONG* start_offset, LONG* end_offset,
    249                                    BSTR* text);
    250 
    251   STDMETHODIMP get_offsetAtPoint(LONG x, LONG y,
    252       enum IA2CoordinateType coord_type,
    253       LONG* offset);
    254 
    255   //
    256   // IAccessibleText methods not implemented.
    257   //
    258 
    259   STDMETHODIMP get_newText(IA2TextSegment* new_text) {
    260     return E_NOTIMPL;
    261   }
    262   STDMETHODIMP get_oldText(IA2TextSegment* old_text) {
    263     return E_NOTIMPL;
    264   }
    265   STDMETHODIMP addSelection(LONG start_offset, LONG end_offset) {
    266     return E_NOTIMPL;
    267   }
    268   STDMETHODIMP get_attributes(LONG offset,
    269                               LONG* start_offset,
    270                               LONG* end_offset,
    271                               BSTR* text_attributes) {
    272     return E_NOTIMPL;
    273   }
    274   STDMETHODIMP get_characterExtents(LONG offset,
    275       enum IA2CoordinateType coord_type,
    276       LONG* x, LONG* y,
    277       LONG* width, LONG* height) {
    278     return E_NOTIMPL;
    279   }
    280   STDMETHODIMP removeSelection(LONG selection_index) {
    281     return E_NOTIMPL;
    282   }
    283   STDMETHODIMP setCaretOffset(LONG offset) {
    284     return E_NOTIMPL;
    285   }
    286   STDMETHODIMP setSelection(LONG selection_index,
    287                             LONG start_offset,
    288                             LONG end_offset) {
    289     return E_NOTIMPL;
    290   }
    291   STDMETHODIMP scrollSubstringTo(LONG start_index,
    292                                  LONG end_index,
    293                                  enum IA2ScrollType scroll_type) {
    294     return E_NOTIMPL;
    295   }
    296   STDMETHODIMP scrollSubstringToPoint(LONG start_index,
    297       LONG end_index,
    298       enum IA2CoordinateType coordinate_type,
    299       LONG x, LONG y) {
    300     return E_NOTIMPL;
    301   }
    302 
    303   //
    304   // IServiceProvider methods.
    305   //
    306 
    307   STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, void** object);
    308 
    309   //
    310   // IAccessibleEx methods not implemented.
    311   //
    312   STDMETHODIMP GetObjectForChild(long child_id, IAccessibleEx** ret) {
    313     return E_NOTIMPL;
    314   }
    315 
    316   STDMETHODIMP GetIAccessiblePair(IAccessible** acc, long* child_id) {
    317     return E_NOTIMPL;
    318   }
    319 
    320   STDMETHODIMP GetRuntimeId(SAFEARRAY** runtime_id) {
    321     return E_NOTIMPL;
    322   }
    323 
    324   STDMETHODIMP ConvertReturnedElement(IRawElementProviderSimple* element,
    325                                       IAccessibleEx** acc) {
    326     return E_NOTIMPL;
    327   }
    328 
    329   //
    330   // IRawElementProviderSimple methods.
    331   //
    332   // The GetPatternProvider/GetPropertyValue methods need to be implemented for
    333   // the on-screen keyboard to show up in Windows 8 metro.
    334   STDMETHODIMP GetPatternProvider(PATTERNID id, IUnknown** provider);
    335   STDMETHODIMP GetPropertyValue(PROPERTYID id, VARIANT* ret);
    336 
    337   //
    338   // IRawElementProviderSimple methods not implemented.
    339   //
    340   STDMETHODIMP get_ProviderOptions(enum ProviderOptions* ret) {
    341     return E_NOTIMPL;
    342   }
    343 
    344   STDMETHODIMP get_HostRawElementProvider(
    345       IRawElementProviderSimple** provider) {
    346     return E_NOTIMPL;
    347   }
    348 
    349   // Static methods
    350 
    351   // Returns a conversion from the event (as defined in ax_enums.idl)
    352   // to an MSAA event.
    353   static int32 MSAAEvent(ui::AXEvent event);
    354 
    355   // Returns a conversion from the Role (as defined in ax_enums.idl)
    356   // to an MSAA role.
    357   static int32 MSAARole(ui::AXRole role);
    358 
    359   // Returns a conversion from the State (as defined in ax_enums.idl)
    360   // to MSAA states set.
    361   static int32 MSAAState(const ui::AXViewState& state);
    362 
    363  protected:
    364   NativeViewAccessibilityWin();
    365 
    366  private:
    367   // Determines navigation direction for accNavigate, based on left, up and
    368   // previous being mapped all to previous and right, down, next being mapped
    369   // to next. Returns true if navigation direction is next, false otherwise.
    370   bool IsNavDirNext(int nav_dir) const;
    371 
    372   // Determines if the navigation target is within the allowed bounds. Returns
    373   // true if it is, false otherwise.
    374   bool IsValidNav(int nav_dir,
    375                   int start_id,
    376                   int lower_bound,
    377                   int upper_bound) const;
    378 
    379   // Determines if the child id variant is valid.
    380   bool IsValidId(const VARIANT& child) const;
    381 
    382   // Helper function which sets applicable states of view.
    383   void SetState(VARIANT* msaa_state, View* view);
    384 
    385   // Return the text to use for IAccessibleText.
    386   base::string16 TextForIAccessibleText();
    387 
    388   // If offset is a member of IA2TextSpecialOffsets this function updates the
    389   // value of offset and returns, otherwise offset remains unchanged.
    390   void HandleSpecialTextOffset(const base::string16& text, LONG* offset);
    391 
    392   // Convert from a IA2TextBoundaryType to a ui::TextBoundaryType.
    393   ui::TextBoundaryType IA2TextBoundaryToTextBoundary(IA2TextBoundaryType type);
    394 
    395   // Search forwards (direction == 1) or backwards (direction == -1)
    396   // from the given offset until the given boundary is found, and
    397   // return the offset of that boundary.
    398   LONG FindBoundary(const base::string16& text,
    399                     IA2TextBoundaryType ia2_boundary,
    400                     LONG start_offset,
    401                     ui::TextBoundaryDirection direction);
    402 
    403   // Populates the given vector with all widgets that are either a child
    404   // or are owned by this view's widget, and who are not contained in a
    405   // NativeViewHost.
    406   void PopulateChildWidgetVector(std::vector<Widget*>* child_widgets);
    407 
    408   // Adds this view to alert_target_view_storage_ids_.
    409   void AddAlertTarget();
    410 
    411   // Removes this view from alert_target_view_storage_ids_.
    412   void RemoveAlertTarget();
    413 
    414   // Give CComObject access to the class constructor.
    415   template <class Base> friend class CComObject;
    416 
    417   // A unique id for each object, needed for IAccessible2.
    418   long unique_id_;
    419 
    420   // Next unique id to assign.
    421   static long next_unique_id_;
    422 
    423   // Circular queue size.
    424   static const int kMaxViewStorageIds = 20;
    425 
    426   // Circular queue of view storage ids corresponding to child ids
    427   // used to post notifications using NotifyWinEvent.
    428   static int view_storage_ids_[kMaxViewStorageIds];
    429 
    430   // Next index into |view_storage_ids_| to use.
    431   static int next_view_storage_id_index_;
    432 
    433   // A vector of view storage ids of views that have been the target of
    434   // an alert event, in order to provide an api to quickly identify all
    435   // open alerts.
    436   static std::vector<int> alert_target_view_storage_ids_;
    437 
    438   DISALLOW_COPY_AND_ASSIGN(NativeViewAccessibilityWin);
    439 };
    440 
    441 }  // namespace views
    442 
    443 #endif  // UI_VIEWS_ACCESSIBILITY_NATIVE_VIEW_ACCESSIBILITY_WIN_H_
    444