1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177
|
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_ACCESSIBILITY_PLATFORM_BROWSER_ACCESSIBILITY_MANAGER_WIN_H_
#define UI_ACCESSIBILITY_PLATFORM_BROWSER_ACCESSIBILITY_MANAGER_WIN_H_
#include <oleacc.h>
#include <map>
#include <memory>
#include <set>
#include <vector>
#include "base/component_export.h"
#include "base/memory/raw_ptr.h"
#include "ui/accessibility/platform/ax_platform_node_win.h"
#include "ui/accessibility/platform/browser_accessibility_manager.h"
#include "ui/display/win/screen_win.h"
namespace ui {
class AXPlatformTreeManagerDelegate;
}
namespace ui {
class BrowserAccessibilityWin;
using UiaRaiseActiveTextPositionChangedEventFunction =
HRESULT(WINAPI*)(IRawElementProviderSimple*, ITextRangeProvider*);
// Manages a tree of BrowserAccessibilityWin objects.
class COMPONENT_EXPORT(AX_PLATFORM) BrowserAccessibilityManagerWin
: public BrowserAccessibilityManager {
public:
BrowserAccessibilityManagerWin(const AXTreeUpdate& initial_tree,
AXNodeIdDelegate& node_id_delegate,
AXPlatformTreeManagerDelegate* delegate);
BrowserAccessibilityManagerWin(const BrowserAccessibilityManagerWin&) =
delete;
BrowserAccessibilityManagerWin& operator=(
const BrowserAccessibilityManagerWin&) = delete;
~BrowserAccessibilityManagerWin() override;
static AXTreeUpdate GetEmptyDocument();
static bool IsUiaActiveTextPositionChangedEventSupported();
// Get the closest containing HWND.
HWND GetParentHWND() const;
// BrowserAccessibilityManager methods
void UserIsReloading() override;
bool IsIgnoredChangedNode(const BrowserAccessibility* node) const;
bool CanFireEvents() const override;
void FireAriaNotificationEvent(
BrowserAccessibility* node,
const std::string& announcement,
ax::mojom::AriaNotificationPriority priority_property,
ax::mojom::AriaNotificationInterrupt interrupt_property,
const std::string& type) override;
void FireFocusEvent(AXNode* node) override;
void FireBlinkEvent(ax::mojom::Event event_type,
BrowserAccessibility* node,
int action_request_id) override;
void FireGeneratedEvent(AXEventGenerator::Event event_type,
const AXNode* node) override;
void FireWinAccessibilityEvent(LONG win_event, BrowserAccessibility* node);
void FireUiaAccessibilityEvent(LONG uia_event, BrowserAccessibility* node);
void FireUiaActiveTextPositionChangedEvent(BrowserAccessibility* node);
void FireUiaPropertyChangedEvent(LONG uia_property,
BrowserAccessibility* node);
void FireUiaStructureChangedEvent(StructureChangeType change_type,
BrowserAccessibility* node);
gfx::Rect GetViewBoundsInScreenCoordinates() const override;
// Do event pre-processing
void BeforeAccessibilityEvents() override;
// Do event post-processing
void FinalizeAccessibilityEvents() override;
protected:
// AXTreeObserver methods.
void OnSubtreeWillBeDeleted(AXTree* tree, AXNode* node) override;
void OnAtomicUpdateFinished(
AXTree* tree,
bool root_changed,
const std::vector<AXTreeObserver::Change>& changes) override;
private:
struct SelectionEvents {
std::vector<raw_ptr<BrowserAccessibility, VectorExperimental>> added;
std::vector<raw_ptr<BrowserAccessibility, VectorExperimental>> removed;
SelectionEvents();
~SelectionEvents();
};
using SelectionEventsMap = std::map<BrowserAccessibility*, SelectionEvents>;
using IsSelectedPredicate =
base::RepeatingCallback<bool(BrowserAccessibility*)>;
using FirePlatformSelectionEventsCallback =
base::RepeatingCallback<void(BrowserAccessibility*,
BrowserAccessibility*,
const SelectionEvents&)>;
static bool IsIA2NodeSelected(BrowserAccessibility* node);
static bool IsUIANodeSelected(BrowserAccessibility* node);
void FireIA2SelectionEvents(BrowserAccessibility* container,
BrowserAccessibility* only_selected_child,
const SelectionEvents& changes);
void FireUIASelectionEvents(BrowserAccessibility* container,
BrowserAccessibility* only_selected_child,
const SelectionEvents& changes);
static void HandleSelectedStateChanged(
SelectionEventsMap& selection_events_map,
BrowserAccessibility* node,
bool is_selected);
static void FinalizeSelectionEvents(
SelectionEventsMap& selection_events_map,
IsSelectedPredicate is_selected_predicate,
FirePlatformSelectionEventsCallback fire_platform_events_callback);
// Retrieve UIA RaiseActiveTextPositionChangedEvent function if supported.
static UiaRaiseActiveTextPositionChangedEventFunction
GetUiaActiveTextPositionChangedEventFunction();
void HandleAriaPropertiesChangedEvent(BrowserAccessibility& node);
void EnqueueTextChangedEvent(BrowserAccessibility& node);
void EnqueueSelectionChangedEvent(BrowserAccessibility& node);
// Give BrowserAccessibilityManager::Create access to our constructor.
friend class BrowserAccessibilityManager;
// Since there could be multiple aria property changes on a node and we only
// want to fire UIA_AriaPropertiesPropertyId once for that node, we use the
// set here to keep track of the unique nodes that had aria property changes,
// so we only fire the event once for every node.
std::set<raw_ptr<BrowserAccessibility, SetExperimental>>
aria_properties_events_;
// Since there could be duplicate selection changed events on a node raised
// from both EventType::DOCUMENT_SELECTION_CHANGED and
// EventType::TEXT_SELECTION_CHANGED, we keep track of the unique
// nodes so we only fire the event once for every node.
std::set<raw_ptr<BrowserAccessibility, SetExperimental>>
selection_changed_nodes_;
// Since there could be duplicate text changed events on a node raised from
// both FireBlinkEvent and FireGeneratedEvent, we use the set here to keep
// track of the unique nodes that had UIA_Text_TextChangedEventId, so we only
// fire the event once for every node.
std::set<raw_ptr<BrowserAccessibility, SetExperimental>> text_changed_nodes_;
// When the ignored state changes for a node, we only want to fire the
// events relevant to the ignored state change (e.g. show / hide).
// This set keeps track of what nodes should suppress superfluous events.
std::set<raw_ptr<BrowserAccessibility, SetExperimental>>
ignored_changed_nodes_;
// Keep track of selection changes so we can optimize UIA event firing.
// Pointers are only stored for the duration of |OnAccessibilityEvents|, and
// the map is cleared in |FinalizeAccessibilityEvents|.
SelectionEventsMap ia2_selection_events_;
SelectionEventsMap uia_selection_events_;
};
} // namespace ui
#endif // UI_ACCESSIBILITY_PLATFORM_BROWSER_ACCESSIBILITY_MANAGER_WIN_H_
|