OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "content/browser/accessibility/browser_accessibility_win.h" | 5 #include "content/browser/accessibility/browser_accessibility_win.h" |
6 | 6 |
7 #include <UIAutomationClient.h> | 7 #include <UIAutomationClient.h> |
8 #include <UIAutomationCoreApi.h> | 8 #include <UIAutomationCoreApi.h> |
9 | 9 |
10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
(...skipping 17 matching lines...) Expand all Loading... | |
28 // These nonstandard GUIDs are taken directly from the Mozilla sources | 28 // These nonstandard GUIDs are taken directly from the Mozilla sources |
29 // (accessible/src/msaa/nsAccessNodeWrap.cpp); some documentation is here: | 29 // (accessible/src/msaa/nsAccessNodeWrap.cpp); some documentation is here: |
30 // http://developer.mozilla.org/en/Accessibility/AT-APIs/ImplementationFeatures/ MSAA | 30 // http://developer.mozilla.org/en/Accessibility/AT-APIs/ImplementationFeatures/ MSAA |
31 const GUID GUID_ISimpleDOM = { | 31 const GUID GUID_ISimpleDOM = { |
32 0x0c539790, 0x12e4, 0x11cf, | 32 0x0c539790, 0x12e4, 0x11cf, |
33 0xb6, 0x61, 0x00, 0xaa, 0x00, 0x4c, 0xd6, 0xd8}; | 33 0xb6, 0x61, 0x00, 0xaa, 0x00, 0x4c, 0xd6, 0xd8}; |
34 const GUID GUID_IAccessibleContentDocument = { | 34 const GUID GUID_IAccessibleContentDocument = { |
35 0xa5d8e1f3, 0x3571, 0x4d8f, | 35 0xa5d8e1f3, 0x3571, 0x4d8f, |
36 0x95, 0x21, 0x07, 0xed, 0x28, 0xfb, 0x07, 0x2e}; | 36 0x95, 0x21, 0x07, 0xed, 0x28, 0xfb, 0x07, 0x2e}; |
37 | 37 |
38 const base::char16 BrowserAccessibilityWin::kEmbeddedCharacter[] = L"\xfffc"; | 38 const base::char16 BrowserAccessibilityWin::kEmbeddedCharacter = L'\xfffc'; |
39 | 39 |
40 // static | 40 // static |
41 LONG BrowserAccessibilityWin::next_unique_id_win_ = | 41 LONG BrowserAccessibilityWin::next_unique_id_win_ = |
42 base::win::kFirstBrowserAccessibilityManagerAccessibilityId; | 42 base::win::kFirstBrowserAccessibilityManagerAccessibilityId; |
43 | 43 |
44 // | 44 // |
45 // BrowserAccessibilityRelation | 45 // BrowserAccessibilityRelation |
46 // | 46 // |
47 // A simple implementation of IAccessibleRelation, used to represent | 47 // A simple implementation of IAccessibleRelation, used to represent |
48 // a relationship between two accessible nodes in the tree. | 48 // a relationship between two accessible nodes in the tree. |
(...skipping 2118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2167 return get_text(*start_offset, *end_offset, text); | 2167 return get_text(*start_offset, *end_offset, text); |
2168 } | 2168 } |
2169 | 2169 |
2170 STDMETHODIMP BrowserAccessibilityWin::get_newText(IA2TextSegment* new_text) { | 2170 STDMETHODIMP BrowserAccessibilityWin::get_newText(IA2TextSegment* new_text) { |
2171 if (!instance_active()) | 2171 if (!instance_active()) |
2172 return E_FAIL; | 2172 return E_FAIL; |
2173 | 2173 |
2174 if (!new_text) | 2174 if (!new_text) |
2175 return E_INVALIDARG; | 2175 return E_INVALIDARG; |
2176 | 2176 |
2177 if (!old_win_attributes_) | |
2178 return E_FAIL; | |
2179 | |
2177 int start, old_len, new_len; | 2180 int start, old_len, new_len; |
2178 ComputeHypertextRemovedAndInserted(&start, &old_len, &new_len); | 2181 ComputeHypertextRemovedAndInserted(&start, &old_len, &new_len); |
2179 if (new_len == 0) | 2182 if (new_len == 0) |
2180 return E_FAIL; | 2183 return E_FAIL; |
2181 | 2184 |
2182 base::string16 substr = hypertext_.substr(start, new_len); | 2185 base::string16 substr = hypertext().substr(start, new_len); |
2183 new_text->text = SysAllocString(substr.c_str()); | 2186 new_text->text = SysAllocString(substr.c_str()); |
2184 new_text->start = static_cast<long>(start); | 2187 new_text->start = static_cast<long>(start); |
2185 new_text->end = static_cast<long>(start + new_len); | 2188 new_text->end = static_cast<long>(start + new_len); |
2186 return S_OK; | 2189 return S_OK; |
2187 } | 2190 } |
2188 | 2191 |
2189 STDMETHODIMP BrowserAccessibilityWin::get_oldText(IA2TextSegment* old_text) { | 2192 STDMETHODIMP BrowserAccessibilityWin::get_oldText(IA2TextSegment* old_text) { |
2190 if (!instance_active()) | 2193 if (!instance_active()) |
2191 return E_FAIL; | 2194 return E_FAIL; |
2192 | 2195 |
2193 if (!old_text) | 2196 if (!old_text) |
2194 return E_INVALIDARG; | 2197 return E_INVALIDARG; |
2195 | 2198 |
2199 if (!old_win_attributes_) | |
2200 return E_FAIL; | |
2201 | |
2196 int start, old_len, new_len; | 2202 int start, old_len, new_len; |
2197 ComputeHypertextRemovedAndInserted(&start, &old_len, &new_len); | 2203 ComputeHypertextRemovedAndInserted(&start, &old_len, &new_len); |
2198 if (old_len == 0) | 2204 if (old_len == 0) |
2199 return E_FAIL; | 2205 return E_FAIL; |
2200 | 2206 |
2201 base::string16 substr = old_hypertext_.substr(start, old_len); | 2207 base::string16 old_hypertext = old_win_attributes_->hypertext; |
2208 base::string16 substr = old_hypertext.substr(start, old_len); | |
2202 old_text->text = SysAllocString(substr.c_str()); | 2209 old_text->text = SysAllocString(substr.c_str()); |
2203 old_text->start = static_cast<long>(start); | 2210 old_text->start = static_cast<long>(start); |
2204 old_text->end = static_cast<long>(start + old_len); | 2211 old_text->end = static_cast<long>(start + old_len); |
2205 return S_OK; | 2212 return S_OK; |
2206 } | 2213 } |
2207 | 2214 |
2208 STDMETHODIMP BrowserAccessibilityWin::get_offsetAtPoint( | 2215 STDMETHODIMP BrowserAccessibilityWin::get_offsetAtPoint( |
2209 LONG x, | 2216 LONG x, |
2210 LONG y, | 2217 LONG y, |
2211 enum IA2CoordinateType coord_type, | 2218 enum IA2CoordinateType coord_type, |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2295 // IAccessibleHypertext methods. | 2302 // IAccessibleHypertext methods. |
2296 // | 2303 // |
2297 | 2304 |
2298 STDMETHODIMP BrowserAccessibilityWin::get_nHyperlinks(long* hyperlink_count) { | 2305 STDMETHODIMP BrowserAccessibilityWin::get_nHyperlinks(long* hyperlink_count) { |
2299 if (!instance_active()) | 2306 if (!instance_active()) |
2300 return E_FAIL; | 2307 return E_FAIL; |
2301 | 2308 |
2302 if (!hyperlink_count) | 2309 if (!hyperlink_count) |
2303 return E_INVALIDARG; | 2310 return E_INVALIDARG; |
2304 | 2311 |
2305 *hyperlink_count = hyperlink_offset_to_index_.size(); | 2312 *hyperlink_count = hyperlink_offset_to_index().size(); |
2306 return S_OK; | 2313 return S_OK; |
2307 } | 2314 } |
2308 | 2315 |
2309 STDMETHODIMP BrowserAccessibilityWin::get_hyperlink( | 2316 STDMETHODIMP BrowserAccessibilityWin::get_hyperlink( |
2310 long index, | 2317 long index, |
2311 IAccessibleHyperlink** hyperlink) { | 2318 IAccessibleHyperlink** hyperlink) { |
2312 if (!instance_active()) | 2319 if (!instance_active()) |
2313 return E_FAIL; | 2320 return E_FAIL; |
2314 | 2321 |
2315 if (!hyperlink || | 2322 if (!hyperlink || |
2316 index < 0 || | 2323 index < 0 || |
2317 index >= static_cast<long>(hyperlinks_.size())) { | 2324 index >= static_cast<long>(hyperlinks().size())) { |
2318 return E_INVALIDARG; | 2325 return E_INVALIDARG; |
2319 } | 2326 } |
2320 | 2327 |
2328 int32 id = hyperlinks()[index]; | |
2321 BrowserAccessibilityWin* child = | 2329 BrowserAccessibilityWin* child = |
2322 InternalGetChild(hyperlinks_[index])->ToBrowserAccessibilityWin(); | 2330 manager()->GetFromID(id)->ToBrowserAccessibilityWin(); |
2323 *hyperlink = static_cast<IAccessibleHyperlink*>(child->NewReference()); | 2331 if (child) { |
2324 return S_OK; | 2332 *hyperlink = static_cast<IAccessibleHyperlink*>(child->NewReference()); |
2333 return S_OK; | |
2334 } | |
2335 | |
2336 return E_FAIL; | |
2325 } | 2337 } |
2326 | 2338 |
2327 STDMETHODIMP BrowserAccessibilityWin::get_hyperlinkIndex( | 2339 STDMETHODIMP BrowserAccessibilityWin::get_hyperlinkIndex( |
2328 long char_index, | 2340 long char_index, |
2329 long* hyperlink_index) { | 2341 long* hyperlink_index) { |
2330 if (!instance_active()) | 2342 if (!instance_active()) |
2331 return E_FAIL; | 2343 return E_FAIL; |
2332 | 2344 |
2333 if (!hyperlink_index) | 2345 if (!hyperlink_index) |
2334 return E_INVALIDARG; | 2346 return E_INVALIDARG; |
2335 | 2347 |
2336 *hyperlink_index = -1; | 2348 *hyperlink_index = -1; |
2337 | 2349 |
2338 if (char_index < 0 || | 2350 if (char_index < 0 || |
2339 char_index >= static_cast<long>(hypertext_.size())) { | 2351 char_index >= static_cast<long>(hypertext().size())) { |
2340 return E_INVALIDARG; | 2352 return E_INVALIDARG; |
2341 } | 2353 } |
2342 | 2354 |
2343 std::map<int32, int32>::iterator it = | 2355 std::map<int32, int32>::iterator it = |
2344 hyperlink_offset_to_index_.find(char_index); | 2356 hyperlink_offset_to_index().find(char_index); |
2345 if (it == hyperlink_offset_to_index_.end()) | 2357 if (it == hyperlink_offset_to_index().end()) |
2346 return E_FAIL; | 2358 return E_FAIL; |
2347 | 2359 |
2348 *hyperlink_index = it->second; | 2360 *hyperlink_index = it->second; |
2349 return S_OK; | 2361 return S_OK; |
2350 } | 2362 } |
2351 | 2363 |
2352 // | 2364 // |
2353 // IAccessibleValue methods. | 2365 // IAccessibleValue methods. |
2354 // | 2366 // |
2355 | 2367 |
(...skipping 580 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2936 } | 2948 } |
2937 | 2949 |
2938 return CComObjectRootBase::InternalQueryInterface( | 2950 return CComObjectRootBase::InternalQueryInterface( |
2939 this_ptr, entries, iid, object); | 2951 this_ptr, entries, iid, object); |
2940 } | 2952 } |
2941 | 2953 |
2942 // | 2954 // |
2943 // Private methods. | 2955 // Private methods. |
2944 // | 2956 // |
2945 | 2957 |
2946 // Called every time this node's data changes, while the tree update is | 2958 void BrowserAccessibilityWin::UpdateStep1ComputeWinAttributes() { |
2947 // still in progress. | 2959 // Swap win_attributes_ to old_win_attributes_, allowing us to see |
2948 void BrowserAccessibilityWin::OnDataChanged() { | 2960 // exactly what changed and fire appropriate events. Note that |
2949 BrowserAccessibility::OnDataChanged(); | 2961 // old_win_attributes_ is cleared at the end of FireIAccessibleTextEvents. |
2950 } | |
2951 | |
2952 // Called every time this node's data changes, after an atomic tree update. | |
2953 void BrowserAccessibilityWin::OnUpdateFinished() { | |
2954 BrowserAccessibility::OnUpdateFinished(); | |
2955 | |
2956 if (PlatformIsChildOfLeaf()) | |
2957 return; | |
2958 | |
2959 bool is_new_object = ia_role() == 0 && role_name().empty(); | |
2960 | |
2961 old_win_attributes_.swap(win_attributes_); | 2962 old_win_attributes_.swap(win_attributes_); |
2962 win_attributes_.reset(new WinAttributes()); | 2963 win_attributes_.reset(new WinAttributes()); |
2963 | 2964 |
2964 InitRoleAndState(); | 2965 InitRoleAndState(); |
2965 | 2966 |
2966 win_attributes_->ia2_attributes.clear(); | 2967 win_attributes_->ia2_attributes.clear(); |
2967 | 2968 |
2968 // Expose autocomplete attribute for combobox and textbox. | 2969 // Expose autocomplete attribute for combobox and textbox. |
2969 StringAttributeToIA2(ui::AX_ATTR_AUTO_COMPLETE, "autocomplete"); | 2970 StringAttributeToIA2(ui::AX_ATTR_AUTO_COMPLETE, "autocomplete"); |
2970 | 2971 |
(...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3188 win_attributes_->ia2_attributes.push_back(L"valuetext:" + GetValueText()); | 3189 win_attributes_->ia2_attributes.push_back(L"valuetext:" + GetValueText()); |
3189 } | 3190 } |
3190 | 3191 |
3191 // If this is a web area for a presentational iframe, give it a role of | 3192 // If this is a web area for a presentational iframe, give it a role of |
3192 // something other than DOCUMENT so that the fact that it's a separate doc | 3193 // something other than DOCUMENT so that the fact that it's a separate doc |
3193 // is not exposed to AT. | 3194 // is not exposed to AT. |
3194 if (IsWebAreaForPresentationalIframe()) { | 3195 if (IsWebAreaForPresentationalIframe()) { |
3195 win_attributes_->ia_role = ROLE_SYSTEM_GROUPING; | 3196 win_attributes_->ia_role = ROLE_SYSTEM_GROUPING; |
3196 win_attributes_->ia2_role = ROLE_SYSTEM_GROUPING; | 3197 win_attributes_->ia2_role = ROLE_SYSTEM_GROUPING; |
3197 } | 3198 } |
3199 } | |
3198 | 3200 |
3201 void BrowserAccessibilityWin::UpdateStep2ComputeHypertext() { | |
3202 // Construct the hypertext for this node, which contains the concatenation | |
3203 // of all of the static text of this node's children and an embedded object | |
3204 // character for all non-static-text children. Build up a map from the | |
3205 // character index of each embedded object character to the id of the | |
3206 // child object it points to. | |
3207 for (unsigned int i = 0; i < PlatformChildCount(); ++i) { | |
3208 BrowserAccessibilityWin* child = | |
3209 PlatformGetChild(i)->ToBrowserAccessibilityWin(); | |
3210 if (child->GetRole() == ui::AX_ROLE_STATIC_TEXT) { | |
3211 win_attributes_->hypertext += child->name(); | |
3212 } else { | |
3213 int32 char_offset = hypertext().size(); | |
3214 int32 child_id = child->GetId(); | |
3215 int32 index = hyperlinks().size(); | |
3216 win_attributes_->hyperlink_offset_to_index[char_offset] = index; | |
3217 win_attributes_->hyperlinks.push_back(child_id); | |
3218 win_attributes_->hypertext += kEmbeddedCharacter; | |
3219 } | |
3220 } | |
3221 } | |
3222 | |
3223 void BrowserAccessibilityWin::UpdateStep3FireEvents(bool is_subtree_creation) { | |
3199 BrowserAccessibilityManagerWin* manager = | 3224 BrowserAccessibilityManagerWin* manager = |
3200 this->manager()->ToBrowserAccessibilityManagerWin(); | 3225 this->manager()->ToBrowserAccessibilityManagerWin(); |
3201 | 3226 |
3202 // Fire an event when an alert first appears. | 3227 // Fire an event when an alert first appears. |
3203 if (ia_role() == ROLE_SYSTEM_ALERT && | 3228 if (ia_role() == ROLE_SYSTEM_ALERT && |
3204 old_win_attributes_->ia_role != ROLE_SYSTEM_ALERT) { | 3229 old_win_attributes_->ia_role != ROLE_SYSTEM_ALERT) { |
3205 manager->NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, this); | 3230 manager->NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, this); |
3206 } | 3231 } |
3207 | 3232 |
3233 // Fire an event when a new subtree is created. | |
3234 if (is_subtree_creation) | |
3235 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SHOW, this); | |
3236 | |
3237 // No other events fire on new objects, only on objects that changed, | |
3238 // so exit now if this is a new object. | |
3239 bool is_new_object = old_win_attributes_->ia_role == 0 && | |
3240 old_win_attributes_->role_name.empty(); | |
3241 if (is_new_object) | |
David Tseng
2015/01/30 23:57:25
nit: no need for this local var.
dmazzoni
2015/01/31 07:45:21
Done.
| |
3242 return; | |
3243 | |
3208 // Fire an event if the name, description, help, or value changes. | 3244 // Fire an event if the name, description, help, or value changes. |
3209 if (!is_new_object) { | 3245 if (name() != old_win_attributes_->name) |
3210 if (name != old_win_attributes_->name) | 3246 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, this); |
3211 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_NAMECHANGE, this); | 3247 if (description() != old_win_attributes_->description) |
3212 if (description != old_win_attributes_->description) | 3248 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_DESCRIPTIONCHANGE, this); |
3213 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_DESCRIPTIONCHANGE, this); | 3249 if (help() != old_win_attributes_->help) |
3214 if (help != old_win_attributes_->help) | 3250 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_HELPCHANGE, this); |
3215 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_HELPCHANGE, this); | 3251 if (value() != old_win_attributes_->value) |
3216 if (value != old_win_attributes_->value) | 3252 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_VALUECHANGE, this); |
3217 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_VALUECHANGE, this); | 3253 if (ia_state() != old_win_attributes_->ia_state) |
3218 if (ia_state() != old_win_attributes_->ia_state) | 3254 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_STATECHANGE, this); |
3219 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_STATECHANGE, this); | |
3220 | 3255 |
3221 // Normally focus events are handled elsewhere, however | 3256 // Normally focus events are handled elsewhere, however |
3222 // focus for managed descendants is platform-specific. | 3257 // focus for managed descendants is platform-specific. |
3223 // Fire a focus event if the focused descendant in a multi-select | 3258 // Fire a focus event if the focused descendant in a multi-select |
3224 // list box changes. | 3259 // list box changes. |
3225 if (GetRole() == ui::AX_ROLE_LIST_BOX_OPTION && | 3260 if (GetRole() == ui::AX_ROLE_LIST_BOX_OPTION && |
3226 (ia_state() & STATE_SYSTEM_FOCUSABLE) && | 3261 (ia_state() & STATE_SYSTEM_FOCUSABLE) && |
3227 (ia_state() & STATE_SYSTEM_SELECTABLE) && | 3262 (ia_state() & STATE_SYSTEM_SELECTABLE) && |
3228 (ia_state() & STATE_SYSTEM_FOCUSED) && | 3263 (ia_state() & STATE_SYSTEM_FOCUSED) && |
3229 !(old_win_attributes_->ia_state & STATE_SYSTEM_FOCUSED)) { | 3264 !(old_win_attributes_->ia_state & STATE_SYSTEM_FOCUSED)) { |
3230 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_FOCUS, this); | 3265 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_FOCUS, this); |
3231 } | |
3232 | |
3233 // Handle selection being added or removed. | |
3234 bool is_selected_now = (ia_state() & STATE_SYSTEM_SELECTED) != 0; | |
3235 bool was_selected_before = | |
3236 (old_win_attributes_->ia_state & STATE_SYSTEM_SELECTED) != 0; | |
3237 if (is_selected_now && !was_selected_before) { | |
3238 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTIONADD, this); | |
3239 } else if (!is_selected_now && was_selected_before) { | |
3240 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTIONREMOVE, this); | |
3241 } | |
3242 | |
3243 // Fire an event if this container object has scrolled. | |
3244 int sx = 0; | |
3245 int sy = 0; | |
3246 if (GetIntAttribute(ui::AX_ATTR_SCROLL_X, &sx) && | |
3247 GetIntAttribute(ui::AX_ATTR_SCROLL_Y, &sy)) { | |
3248 if (sx != previous_scroll_x_ || sy != previous_scroll_y_) | |
3249 manager->MaybeCallNotifyWinEvent(EVENT_SYSTEM_SCROLLINGEND, this); | |
3250 previous_scroll_x_ = sx; | |
3251 previous_scroll_y_ = sy; | |
3252 } | |
3253 | |
3254 // Changing a static text node can affect the IAccessibleText hypertext | |
3255 // of the parent node, so force it to be recomputed here. | |
3256 if (GetParent() && | |
3257 GetRole() == ui::AX_ROLE_STATIC_TEXT && | |
3258 name != old_win_attributes_->name) { | |
3259 GetParent()->ToBrowserAccessibilityWin()->UpdateIAccessibleText(); | |
3260 } | |
3261 } | 3266 } |
3262 | 3267 |
3268 // Handle selection being added or removed. | |
3269 bool is_selected_now = (ia_state() & STATE_SYSTEM_SELECTED) != 0; | |
3270 bool was_selected_before = | |
3271 (old_win_attributes_->ia_state & STATE_SYSTEM_SELECTED) != 0; | |
3272 if (is_selected_now && !was_selected_before) { | |
3273 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTIONADD, this); | |
3274 } else if (!is_selected_now && was_selected_before) { | |
3275 manager->MaybeCallNotifyWinEvent(EVENT_OBJECT_SELECTIONREMOVE, this); | |
3276 } | |
3277 | |
3278 // Fire an event if this container object has scrolled. | |
3279 int sx = 0; | |
3280 int sy = 0; | |
3281 if (GetIntAttribute(ui::AX_ATTR_SCROLL_X, &sx) && | |
3282 GetIntAttribute(ui::AX_ATTR_SCROLL_Y, &sy)) { | |
3283 if (sx != previous_scroll_x_ || sy != previous_scroll_y_) | |
3284 manager->MaybeCallNotifyWinEvent(EVENT_SYSTEM_SCROLLINGEND, this); | |
3285 previous_scroll_x_ = sx; | |
3286 previous_scroll_y_ = sy; | |
3287 } | |
3288 | |
3289 // Changing a static text node can affect the IAccessibleText hypertext | |
3290 // of the parent node, so force an update on the parent. | |
3291 if (GetParent() && | |
David Tseng
2015/01/30 23:57:25
nit: store parent in a local variable.
dmazzoni
2015/01/31 07:45:21
Done.
| |
3292 GetRole() == ui::AX_ROLE_STATIC_TEXT && | |
3293 name() != old_win_attributes_->name) { | |
3294 GetParent()->ToBrowserAccessibilityWin()->UpdateStep1ComputeWinAttributes(); | |
3295 GetParent()->ToBrowserAccessibilityWin()->UpdateStep2ComputeHypertext(); | |
3296 GetParent()->ToBrowserAccessibilityWin()->UpdateStep3FireEvents(false); | |
3297 GetParent()->ToBrowserAccessibilityWin()-> | |
3298 UpdateStep4DeleteOldWinAttributes(); | |
3299 } | |
3300 | |
3301 // Fire hypertext-related events. | |
David Tseng
2015/01/30 23:57:25
This would mean this object's parent fires hyperte
dmazzoni
2015/01/31 07:45:21
No, I checked with NV Access. The order in which w
| |
3302 int start, old_len, new_len; | |
3303 ComputeHypertextRemovedAndInserted(&start, &old_len, &new_len); | |
3304 if (old_len) { | |
David Tseng
2015/01/30 23:57:25
nit: old_len > 0?
dmazzoni
2015/01/31 07:45:21
Done.
| |
3305 // In-process screen readers may call IAccessibleText::get_oldText | |
3306 // to retrieve the text that was removed. | |
3307 manager->MaybeCallNotifyWinEvent(IA2_EVENT_TEXT_REMOVED, this); | |
3308 } | |
3309 if (new_len) { | |
David Tseng
2015/01/30 23:57:25
ditto
dmazzoni
2015/01/31 07:45:21
Done.
| |
3310 // In-process screen readers may call IAccessibleText::get_newText | |
David Tseng
2015/01/30 23:57:25
in reaction to this event?
dmazzoni
2015/01/31 07:45:21
Done.
| |
3311 // to retrieve the text that was inserted. | |
3312 manager->MaybeCallNotifyWinEvent(IA2_EVENT_TEXT_INSERTED, this); | |
3313 } | |
3314 } | |
3315 | |
3316 void BrowserAccessibilityWin::UpdateStep4DeleteOldWinAttributes() { | |
3263 old_win_attributes_.reset(nullptr); | 3317 old_win_attributes_.reset(nullptr); |
3264 } | 3318 } |
3265 | 3319 |
3266 void BrowserAccessibilityWin::UpdateIAccessibleText() { | |
3267 old_hypertext_ = hypertext_; | |
3268 hypertext_.clear(); | |
3269 | |
3270 // Construct the hypertext for this node. | |
3271 hyperlink_offset_to_index_.clear(); | |
3272 hyperlinks_.clear(); | |
3273 for (unsigned int i = 0; i < PlatformChildCount(); ++i) { | |
3274 BrowserAccessibilityWin* child = | |
3275 PlatformGetChild(i)->ToBrowserAccessibilityWin(); | |
3276 if (child->GetRole() == ui::AX_ROLE_STATIC_TEXT) { | |
3277 hypertext_ += child->name(); | |
3278 } else { | |
3279 hyperlink_offset_to_index_[hypertext_.size()] = | |
3280 hyperlinks_.size(); | |
3281 hypertext_ += kEmbeddedCharacter; | |
3282 hyperlinks_.push_back(i); | |
3283 } | |
3284 } | |
3285 DCHECK_EQ(hyperlink_offset_to_index_.size(), hyperlinks_.size()); | |
3286 | |
3287 if (hypertext_ != old_hypertext_) { | |
3288 BrowserAccessibilityManagerWin* manager = | |
3289 this->manager()->ToBrowserAccessibilityManagerWin(); | |
3290 | |
3291 int start, old_len, new_len; | |
3292 ComputeHypertextRemovedAndInserted(&start, &old_len, &new_len); | |
3293 if (old_len) { | |
3294 // In-process screen readers may call IAccessibleText::get_oldText | |
3295 // to retrieve the text that was removed. | |
3296 manager->MaybeCallNotifyWinEvent(IA2_EVENT_TEXT_REMOVED, this); | |
3297 } | |
3298 if (new_len) { | |
3299 // In-process screen readers may call IAccessibleText::get_newText | |
3300 // to retrieve the text that was inserted. | |
3301 manager->MaybeCallNotifyWinEvent(IA2_EVENT_TEXT_INSERTED, this); | |
3302 } | |
3303 } | |
3304 | |
3305 old_hypertext_.clear(); | |
3306 } | |
3307 | |
3308 void BrowserAccessibilityWin::OnSubtreeWillBeDeleted() { | 3320 void BrowserAccessibilityWin::OnSubtreeWillBeDeleted() { |
3309 manager()->ToBrowserAccessibilityManagerWin()->MaybeCallNotifyWinEvent( | 3321 manager()->ToBrowserAccessibilityManagerWin()->MaybeCallNotifyWinEvent( |
3310 EVENT_OBJECT_HIDE, this); | 3322 EVENT_OBJECT_HIDE, this); |
3311 } | 3323 } |
3312 | 3324 |
3313 void BrowserAccessibilityWin::OnSubtreeCreationFinished() { | |
3314 manager()->ToBrowserAccessibilityManagerWin()->MaybeCallNotifyWinEvent( | |
3315 EVENT_OBJECT_SHOW, this); | |
3316 } | |
3317 | |
3318 void BrowserAccessibilityWin::NativeAddReference() { | 3325 void BrowserAccessibilityWin::NativeAddReference() { |
3319 AddRef(); | 3326 AddRef(); |
3320 } | 3327 } |
3321 | 3328 |
3322 void BrowserAccessibilityWin::NativeReleaseReference() { | 3329 void BrowserAccessibilityWin::NativeReleaseReference() { |
3323 Release(); | 3330 Release(); |
3324 } | 3331 } |
3325 | 3332 |
3326 bool BrowserAccessibilityWin::IsNative() const { | 3333 bool BrowserAccessibilityWin::IsNative() const { |
3327 return true; | 3334 return true; |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3422 if (value.empty() && | 3429 if (value.empty() && |
3423 GetFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE, &fval)) { | 3430 GetFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE, &fval)) { |
3424 value = base::UTF8ToUTF16(base::DoubleToString(fval)); | 3431 value = base::UTF8ToUTF16(base::DoubleToString(fval)); |
3425 } | 3432 } |
3426 return value; | 3433 return value; |
3427 } | 3434 } |
3428 | 3435 |
3429 base::string16 BrowserAccessibilityWin::TextForIAccessibleText() { | 3436 base::string16 BrowserAccessibilityWin::TextForIAccessibleText() { |
3430 if (IsEditableText()) | 3437 if (IsEditableText()) |
3431 return value(); | 3438 return value(); |
3432 return (GetRole() == ui::AX_ROLE_STATIC_TEXT) ? name() : hypertext_; | 3439 return (GetRole() == ui::AX_ROLE_STATIC_TEXT) ? name() : hypertext(); |
3440 } | |
3441 | |
3442 bool BrowserAccessibilityWin::IsSameHypertextCharacter(size_t old_char_index, | |
3443 size_t new_char_index) { | |
3444 CHECK(old_win_attributes_); | |
3445 | |
3446 // For anything other than the "embedded character", we just compare the | |
3447 // characters directly. | |
3448 base::char16 old_ch = old_win_attributes_->hypertext[old_char_index]; | |
3449 base::char16 new_ch = win_attributes_->hypertext[new_char_index]; | |
3450 if (old_ch != new_ch) | |
3451 return false; | |
3452 if (old_ch == new_ch && new_ch != kEmbeddedCharacter) | |
3453 return true; | |
3454 | |
3455 // If it's an embedded character, they're only identical if the child id | |
3456 // the hyperlink points to is the same. | |
3457 std::map<int32, int32>& old_offset_to_index = | |
3458 old_win_attributes_->hyperlink_offset_to_index; | |
3459 std::vector<int32>& old_hyperlinks = old_win_attributes_->hyperlinks; | |
3460 int32 old_hyperlinks_count = static_cast<int32>(old_hyperlinks.size()); | |
3461 std::map<int32, int32>::iterator iter; | |
3462 iter = old_offset_to_index.find(old_char_index); | |
3463 int old_index = (iter != old_offset_to_index.end()) ? iter->second : -1; | |
3464 int old_child_id = (old_index >= 0 && old_index < old_hyperlinks_count) ? | |
3465 old_hyperlinks[old_index] : -1; | |
3466 | |
3467 std::map<int32, int32>& new_offset_to_index = | |
3468 win_attributes_->hyperlink_offset_to_index; | |
3469 std::vector<int32>& new_hyperlinks = win_attributes_->hyperlinks; | |
3470 int32 new_hyperlinks_count = static_cast<int32>(new_hyperlinks.size()); | |
3471 iter = new_offset_to_index.find(new_char_index); | |
3472 int new_index = (iter != new_offset_to_index.end()) ? iter->second : -1; | |
3473 int new_child_id = (new_index >= 0 && new_index < new_hyperlinks_count) ? | |
3474 new_hyperlinks[new_index] : -1; | |
3475 | |
3476 return old_child_id == new_child_id; | |
3433 } | 3477 } |
3434 | 3478 |
3435 void BrowserAccessibilityWin::ComputeHypertextRemovedAndInserted( | 3479 void BrowserAccessibilityWin::ComputeHypertextRemovedAndInserted( |
3436 int* start, int* old_len, int* new_len) { | 3480 int* start, int* old_len, int* new_len) { |
3481 CHECK(old_win_attributes_); | |
3482 | |
3437 *start = 0; | 3483 *start = 0; |
3438 *old_len = 0; | 3484 *old_len = 0; |
3439 *new_len = 0; | 3485 *new_len = 0; |
3440 | 3486 |
3441 const base::string16& old_text = old_hypertext_; | 3487 const base::string16& old_text = old_win_attributes_->hypertext; |
3442 const base::string16& new_text = hypertext_; | 3488 const base::string16& new_text = hypertext(); |
3443 | 3489 |
3444 size_t common_prefix = 0; | 3490 size_t common_prefix = 0; |
3445 while (common_prefix < old_text.size() && | 3491 while (common_prefix < old_text.size() && |
3446 common_prefix < new_text.size() && | 3492 common_prefix < new_text.size() && |
3447 old_text[common_prefix] == new_text[common_prefix]) { | 3493 IsSameHypertextCharacter(common_prefix, common_prefix)) { |
3448 ++common_prefix; | 3494 ++common_prefix; |
3449 } | 3495 } |
3450 | 3496 |
3451 size_t common_suffix = 0; | 3497 size_t common_suffix = 0; |
3452 while (common_prefix + common_suffix < old_text.size() && | 3498 while (common_prefix + common_suffix < old_text.size() && |
3453 common_prefix + common_suffix < new_text.size() && | 3499 common_prefix + common_suffix < new_text.size() && |
3454 old_text[old_text.size() - common_suffix - 1] == | 3500 IsSameHypertextCharacter( |
3455 new_text[new_text.size() - common_suffix - 1]) { | 3501 old_text.size() - common_suffix - 1, |
3502 new_text.size() - common_suffix - 1)) { | |
3456 ++common_suffix; | 3503 ++common_suffix; |
3457 } | 3504 } |
3458 | 3505 |
3459 *start = common_prefix; | 3506 *start = common_prefix; |
3460 *old_len = old_text.size() - common_prefix - common_suffix; | 3507 *old_len = old_text.size() - common_prefix - common_suffix; |
3461 *new_len = new_text.size() - common_prefix - common_suffix; | 3508 *new_len = new_text.size() - common_prefix - common_suffix; |
3462 } | 3509 } |
3463 | 3510 |
3464 void BrowserAccessibilityWin::HandleSpecialTextOffset( | 3511 void BrowserAccessibilityWin::HandleSpecialTextOffset( |
3465 const base::string16& text, | 3512 const base::string16& text, |
(...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4040 ia2_role = ia_role; | 4087 ia2_role = ia_role; |
4041 | 4088 |
4042 win_attributes_->ia_role = ia_role; | 4089 win_attributes_->ia_role = ia_role; |
4043 win_attributes_->ia_state = ia_state; | 4090 win_attributes_->ia_state = ia_state; |
4044 win_attributes_->role_name = role_name; | 4091 win_attributes_->role_name = role_name; |
4045 win_attributes_->ia2_role = ia2_role; | 4092 win_attributes_->ia2_role = ia2_role; |
4046 win_attributes_->ia2_state = ia2_state; | 4093 win_attributes_->ia2_state = ia2_state; |
4047 } | 4094 } |
4048 | 4095 |
4049 } // namespace content | 4096 } // namespace content |
OLD | NEW |