Commit 6931f4c0 authored by Christopher Cameron's avatar Christopher Cameron Committed by Commit Bot

RemoteMacViews: Generalize remote accessibility focus override

Move ScopedAccessibilityFocus from ui/views/cocoa to ui/base/cocoa,
because it is going to be used by content/ (which, for the moment,
does not depends on ui/views, though I would like to add an explicit
dependency at some point).

Rename ScopedAccessibilityFocus to AccessibilityFocusOverrider, and
- make it track
  - whether or not the view it represents if the first responder for
    its window
  - whether or not its window is key
- override -[NSApplication accessibilityFocusedUIElement] only when
  both of those conditions are true

Apply this scheme to the two main NSViews
- BridgedContentView uses an AccessibilityFocusOverrider in
  BridgedNativeWidgetHostImpl
- RenderWidgetHostViewCocoa uses an AccessibilityFocusOverrider in
  RenderWidgetHostViewMac

Change slightly the way that NSWindow key status is tracked between
RenderWidgetHostViewCocoa/Mac.
- These changes were only send to the browser when the view was also
  first responder
- Change this to always send changes in key status, and early-out
  when the view is not first responder on the browser side.

Bug: 900846
Change-Id: I15bb144ae4570eeffa51c4609f58aa8b58b892d9
Reviewed-on: https://chromium-review.googlesource.com/c/1345121Reviewed-by: default avatarElly Fong-Jones <ellyjones@chromium.org>
Commit-Queue: ccameron <ccameron@chromium.org>
Cr-Commit-Position: refs/heads/master@{#610209}
parent 0ec959f9
......@@ -34,8 +34,8 @@ struct NativeWebKeyboardEvent;
// communicate with the RenderWidgetHostViewMac (potentially in another
// process). Unlike mojom::RenderWidgetHostNSViewClient, this object is always
// instantiated in the local process. This is to implement functions that
// cannot be sent across mojo (e.g, GetRootBrowserAccessibilityManager), or
// to avoid unnecessary translation of event types.
// cannot be sent across mojo or to avoid unnecessary translation of event
// types.
class RenderWidgetHostNSViewClientHelper {
public:
// Create a RenderWidgetHostNSViewClientHelper that will only implement
......@@ -47,10 +47,9 @@ class RenderWidgetHostNSViewClientHelper {
RenderWidgetHostNSViewClientHelper() {}
virtual ~RenderWidgetHostNSViewClientHelper() {}
// Return the RenderWidget's BrowserAccessibilityManager.
// TODO(ccameron): This returns nullptr for non-local NSViews. A scheme for
// non-local accessibility needs to be developed.
virtual BrowserAccessibilityManager* GetRootBrowserAccessibilityManager() = 0;
// Return the RenderWidget's BrowserAccessibilityManager's root accessibility
// node.
virtual id GetRootBrowserAccessibilityElement() = 0;
// Forward a keyboard event to the RenderWidgetHost that is currently handling
// the key-down event.
......
......@@ -24,9 +24,7 @@ class ForwardingClientHelper : public RenderWidgetHostNSViewClientHelper {
}
// RenderWidgetHostNSViewClientHelper implementation.
BrowserAccessibilityManager* GetRootBrowserAccessibilityManager() override {
return nullptr;
}
id GetRootBrowserAccessibilityElement() override { return nil; }
void ForwardKeyboardEvent(const NativeWebKeyboardEvent& key_event,
const ui::LatencyInfo& latency_info) override {
const blink::WebKeyboardEvent* web_event =
......
......@@ -34,8 +34,6 @@
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/gfx/mac/coordinate_conversion.h"
using content::BrowserAccessibility;
using content::BrowserAccessibilityManager;
using content::EditCommand;
using content::InputEvent;
using content::NativeWebKeyboardEvent;
......@@ -1248,7 +1246,7 @@ void ExtractUnderlines(NSAttributedString* string,
DCHECK_EQ([self window], [notification object]);
if ([responderDelegate_ respondsToSelector:@selector(windowDidBecomeKey)])
[responderDelegate_ windowDidBecomeKey];
if ([self window].isKeyWindow && [[self window] firstResponder] == self)
if ([self window].isKeyWindow)
client_->OnWindowIsKeyChanged(true);
}
......@@ -1263,8 +1261,7 @@ void ExtractUnderlines(NSAttributedString* string,
if ([NSApp isActive] && ([NSApp keyWindow] == [self window]))
return;
if ([[self window] firstResponder] == self)
client_->OnWindowIsKeyChanged(false);
client_->OnWindowIsKeyChanged(false);
}
- (BOOL)becomeFirstResponder {
......@@ -1370,17 +1367,14 @@ void ExtractUnderlines(NSAttributedString* string,
}
- (id)accessibilityAttributeValue:(NSString*)attribute {
BrowserAccessibilityManager* manager =
clientHelper_->GetRootBrowserAccessibilityManager();
id root_element = clientHelper_->GetRootBrowserAccessibilityElement();
// Contents specifies document view of RenderWidgetHostViewCocoa provided by
// BrowserAccessibilityManager. Children includes all subviews in addition to
// contents. Currently we do not have subviews besides the document view.
if (([attribute isEqualToString:NSAccessibilityChildrenAttribute] ||
[attribute isEqualToString:NSAccessibilityContentsAttribute]) &&
manager) {
return [NSArray
arrayWithObjects:ToBrowserAccessibilityCocoa(manager->GetRoot()), nil];
root_element) {
return [NSArray arrayWithObjects:root_element, nil];
} else if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) {
return NSAccessibilityScrollAreaRole;
}
......@@ -1396,31 +1390,26 @@ void ExtractUnderlines(NSAttributedString* string,
}
- (id)accessibilityHitTest:(NSPoint)point {
BrowserAccessibilityManager* manager =
clientHelper_->GetRootBrowserAccessibilityManager();
if (!manager)
id root_element = clientHelper_->GetRootBrowserAccessibilityElement();
if (!root_element)
return self;
NSPoint pointInWindow =
ui::ConvertPointFromScreenToWindow([self window], point);
NSPoint localPoint = [self convertPoint:pointInWindow fromView:nil];
localPoint.y = NSHeight([self bounds]) - localPoint.y;
BrowserAccessibilityCocoa* root =
ToBrowserAccessibilityCocoa(manager->GetRoot());
id obj = [root accessibilityHitTest:localPoint];
id obj = [root_element accessibilityHitTest:localPoint];
return obj;
}
- (BOOL)accessibilityIsIgnored {
BrowserAccessibilityManager* manager =
clientHelper_->GetRootBrowserAccessibilityManager();
return !manager;
id root_element = clientHelper_->GetRootBrowserAccessibilityElement();
return !root_element;
}
- (NSUInteger)accessibilityGetIndexOf:(id)child {
BrowserAccessibilityManager* manager =
clientHelper_->GetRootBrowserAccessibilityManager();
id root_element = clientHelper_->GetRootBrowserAccessibilityElement();
// Only child is root.
if (manager && ToBrowserAccessibilityCocoa(manager->GetRoot()) == child) {
if (root_element == child) {
return 0;
} else {
return NSNotFound;
......@@ -1428,29 +1417,9 @@ void ExtractUnderlines(NSAttributedString* string,
}
- (id)accessibilityFocusedUIElement {
// If content is overlayed with a focused popup from native UI code, this
// getter must return the current menu item as the focused element, rather
// than the focus within the content. An example of this occurs with the
// Autofill feature, where focus is actually still in the textbox although
// the UX acts as if focus is in the popup.
gfx::NativeViewAccessible popup_focus_override =
ui::AXPlatformNode::GetPopupFocusOverride();
if (popup_focus_override)
return popup_focus_override;
BrowserAccessibilityManager* manager =
clientHelper_->GetRootBrowserAccessibilityManager();
if (manager) {
BrowserAccessibility* focused_item = manager->GetFocus();
DCHECK(focused_item);
if (focused_item) {
BrowserAccessibilityCocoa* focused_item_cocoa =
ToBrowserAccessibilityCocoa(focused_item);
DCHECK(focused_item_cocoa);
if (focused_item_cocoa)
return focused_item_cocoa;
}
}
// This function should almost-never be called because when |self| is the
// first responder for the key NSWindow, RenderWidgetHostViewMac's
// AccessibilityFocusOverrider will override the accessibility focus query.
return [super accessibilityFocusedUIElement];
}
......@@ -1793,6 +1762,7 @@ extern NSString* NSTextInputReplacementRangeAttributeName;
[self sendWindowFrameInScreenToClient];
[self sendViewBoundsInWindowToClient];
[self updateScreenProperties];
client_->OnWindowIsKeyChanged([[self window] isKeyWindow]);
client_->OnFirstResponderChanged([[self window] firstResponder] == self);
// If we switch windows (or are removed from the view hierarchy), cancel any
......
......@@ -26,6 +26,7 @@
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
#include "ui/accelerated_widget_mac/display_link_mac.h"
#include "ui/base/cocoa/accessibility_focus_overrider.h"
#include "ui/base/cocoa/remote_layer_api.h"
#include "ui/events/gesture_detection/filtered_gesture_provider.h"
......@@ -72,6 +73,7 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
public TextInputManager::Observer,
public ui::GestureProviderClient,
public ui::AcceleratedWidgetMacNSView,
public ui::AccessibilityFocusOverrider::Client,
public IPC::Sender {
public:
// The view will associate itself with the given widget. The native view must
......@@ -297,7 +299,7 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
void UpdateNSViewAndDisplayProperties();
// RenderWidgetHostNSViewClientHelper implementation.
BrowserAccessibilityManager* GetRootBrowserAccessibilityManager() override;
id GetRootBrowserAccessibilityElement() override;
void ForwardKeyboardEvent(const NativeWebKeyboardEvent& key_event,
const ui::LatencyInfo& latency_info) override;
void ForwardKeyboardEventWithCommands(
......@@ -398,6 +400,9 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// AcceleratedWidgetMacNSView implementation.
void AcceleratedWidgetCALayerParamsUpdated() override;
// ui::AccessibilityFocusOverrider::Client:
id GetAccessibilityFocusedUIElement() override;
void SetShowingContextMenu(bool showing) override;
// Helper method to obtain ui::TextInputType for the active widget from the
......@@ -533,6 +538,9 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// Cached copy of the display information pushed to us from the NSView.
display::Display display_;
// Whether or not the NSView's NSWindow is the key window.
bool is_window_key_ = false;
// Whether or not the NSView is first responder.
bool is_first_responder_ = false;
......@@ -619,6 +627,11 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// EnsureSurfaceSynchronizedForLayoutTest().
uint32_t latest_capture_sequence_number_ = 0u;
// Used to force the NSApplication's focused accessibility element to be the
// content::BrowserAccessibilityCocoa accessibility tree when the NSView for
// this is focused.
ui::AccessibilityFocusOverrider accessibility_focus_overrider_;
// Factory used to safely scope delayed calls to ShutdownHost().
base::WeakPtrFactory<RenderWidgetHostViewMac> weak_factory_;
......
......@@ -19,6 +19,8 @@
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "components/viz/common/switches.h"
#import "content/browser/accessibility/browser_accessibility_cocoa.h"
#import "content/browser/accessibility/browser_accessibility_mac.h"
#include "content/browser/accessibility/browser_accessibility_manager_mac.h"
#include "content/browser/renderer_host/cursor_manager.h"
#include "content/browser/renderer_host/input/motion_event_web.h"
......@@ -131,6 +133,35 @@ void RenderWidgetHostViewMac::AcceleratedWidgetCALayerParamsUpdated() {
}
}
////////////////////////////////////////////////////////////////////////////////
// views::AccessibilityFocusOverrider::Client:
id RenderWidgetHostViewMac::GetAccessibilityFocusedUIElement() {
// If content is overlayed with a focused popup from native UI code, this
// getter must return the current menu item as the focused element, rather
// than the focus within the content. An example of this occurs with the
// Autofill feature, where focus is actually still in the textbox although
// the UX acts as if focus is in the popup.
gfx::NativeViewAccessible popup_focus_override =
ui::AXPlatformNode::GetPopupFocusOverride();
if (popup_focus_override)
return popup_focus_override;
BrowserAccessibilityManager* manager =
host()->GetRootBrowserAccessibilityManager();
if (manager) {
BrowserAccessibility* focused_item = manager->GetFocus();
DCHECK(focused_item);
if (focused_item) {
BrowserAccessibilityCocoa* focused_item_cocoa =
ToBrowserAccessibilityCocoa(focused_item);
DCHECK(focused_item_cocoa);
if (focused_item_cocoa)
return focused_item_cocoa;
}
}
return nil;
}
///////////////////////////////////////////////////////////////////////////////
// RenderWidgetHostViewMac, public:
......@@ -147,6 +178,7 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget,
gesture_provider_(ui::GetGestureProviderConfig(
ui::GestureProviderConfigType::CURRENT_PLATFORM),
this),
accessibility_focus_overrider_(this),
weak_factory_(this) {
// The NSView is on the other side of |ns_view_bridge_|.
ns_view_bridge_local_ =
......@@ -1395,9 +1427,10 @@ MouseWheelPhaseHandler* RenderWidgetHostViewMac::GetMouseWheelPhaseHandler() {
// RenderWidgetHostNSViewClientHelper and mojom::RenderWidgetHostNSViewClient
// implementation:
BrowserAccessibilityManager*
RenderWidgetHostViewMac::GetRootBrowserAccessibilityManager() {
return host()->GetRootBrowserAccessibilityManager();
id RenderWidgetHostViewMac::GetRootBrowserAccessibilityElement() {
if (auto* manager = host()->GetRootBrowserAccessibilityManager())
return ToBrowserAccessibilityCocoa(manager->GetRoot());
return nil;
}
bool RenderWidgetHostViewMac::SyncIsRenderViewHost(bool* is_render_view) {
......@@ -1424,6 +1457,7 @@ void RenderWidgetHostViewMac::OnFirstResponderChanged(bool is_first_responder) {
if (is_first_responder_ == is_first_responder)
return;
is_first_responder_ = is_first_responder;
accessibility_focus_overrider_.SetViewIsFirstResponder(is_first_responder_);
if (is_first_responder_) {
host()->GotFocus();
SetTextInputActive(true);
......@@ -1434,7 +1468,12 @@ void RenderWidgetHostViewMac::OnFirstResponderChanged(bool is_first_responder) {
}
void RenderWidgetHostViewMac::OnWindowIsKeyChanged(bool is_key) {
SetActive(is_key);
if (is_window_key_ == is_key)
return;
is_window_key_ = is_key;
accessibility_focus_overrider_.SetWindowIsKey(is_window_key_);
if (is_first_responder_)
SetActive(is_key);
}
void RenderWidgetHostViewMac::OnBoundsInWindowChanged(
......
......@@ -91,6 +91,8 @@ jumbo_component("base") {
"clipboard/clipboard_win.cc",
"clipboard/clipboard_win.h",
"clipboard/custom_data_helper_mac.mm",
"cocoa/accessibility_focus_overrider.h",
"cocoa/accessibility_focus_overrider.mm",
"cocoa/animation_utils.h",
"cocoa/appkit_utils.h",
"cocoa/appkit_utils.mm",
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_BASE_COCOA_ACCESSIBILITY_FOCUS_OVERRIDER_H_
#define UI_BASE_COCOA_ACCESSIBILITY_FOCUS_OVERRIDER_H_
#include "ui/base/ui_base_export.h"
namespace ui {
// This object will swizzle -[NSApplication accessibilityFocusedUIElement] to
// return the value of its client's GetAccessibilityFocusedUIElement method
// whenever both |window_is_key_| is true and |view_is_first_responder_| is
// true. If two instances both claim that their window is key and their view
// is first responder at the same time, then the more recent instance to have
// made that claim will "win". This mechanism is used for accessibility in
// RemoteMacViews.
class UI_BASE_EXPORT AccessibilityFocusOverrider {
public:
class Client {
public:
virtual id GetAccessibilityFocusedUIElement() = 0;
};
AccessibilityFocusOverrider(Client* client);
~AccessibilityFocusOverrider();
// Indicate whether or not the view's window is currently key. This object
// will override the application's focused accessibility element only if its
// window is key (and the view is the window's first responder).
void SetWindowIsKey(bool window_is_key);
// Indicate whether or not the view is its window's first responder. This
// object will override the application's focused accessibility element only
// if the view is the window's first responder (and its window is key).
void SetViewIsFirstResponder(bool view_is_first_responder);
private:
void UpdateOverriddenKeyElement();
bool window_is_key_ = false;
bool view_is_first_responder_ = false;
Client* const client_;
};
} // namespace ui
#endif // UI_BASE_COCOA_ACCESSIBILITY_FOCUS_OVERRIDER_H_
......@@ -2,35 +2,30 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/views/cocoa/scoped_accessibility_focus.h"
#include "ui/base/cocoa/accessibility_focus_overrider.h"
#import <AppKit/AppKit.h>
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#include "ui/views/cocoa/bridged_native_widget_host_impl.h"
namespace views {
namespace ui {
namespace {
bool g_has_swizzled_method = false;
BridgedNativeWidgetHostImpl* g_overridden_key_element = nil;
AccessibilityFocusOverrider::Client* g_overridden_focused_element = nil;
// Swizzled method for -[NSApplication accessibilityFocusedUIElement]. This
// will return the overridden element if one is present. Otherwise, it will
// return the key window.
id SwizzledAccessibilityFocusedUIElement(NSApplication* app, SEL) {
if (g_overridden_key_element) {
return [g_overridden_key_element->GetLocalNSWindow()
accessibilityFocusedUIElement];
}
if (g_overridden_focused_element)
return g_overridden_focused_element->GetAccessibilityFocusedUIElement();
return [[app keyWindow] accessibilityFocusedUIElement];
}
} // namespace
ScopedAccessibilityFocus::ScopedAccessibilityFocus(
BridgedNativeWidgetHostImpl* host)
: host_(host) {
AccessibilityFocusOverrider::AccessibilityFocusOverrider(Client* client)
: client_(client) {
if (!g_has_swizzled_method) {
Method method = class_getInstanceMethod(
[NSApplication class], @selector(accessibilityFocusedUIElement));
......@@ -38,12 +33,30 @@ ScopedAccessibilityFocus::ScopedAccessibilityFocus(
(IMP)SwizzledAccessibilityFocusedUIElement);
g_has_swizzled_method = true;
}
g_overridden_key_element = host_;
}
ScopedAccessibilityFocus::~ScopedAccessibilityFocus() {
if (g_overridden_key_element == host_)
g_overridden_key_element = nullptr;
AccessibilityFocusOverrider::~AccessibilityFocusOverrider() {
if (g_overridden_focused_element == client_)
g_overridden_focused_element = nullptr;
}
void AccessibilityFocusOverrider::SetWindowIsKey(bool window_is_key) {
window_is_key_ = window_is_key;
UpdateOverriddenKeyElement();
}
void AccessibilityFocusOverrider::SetViewIsFirstResponder(
bool view_is_first_responder) {
view_is_first_responder_ = view_is_first_responder;
UpdateOverriddenKeyElement();
}
void AccessibilityFocusOverrider::UpdateOverriddenKeyElement() {
if (window_is_key_ && view_is_first_responder_) {
g_overridden_focused_element = client_;
} else if (g_overridden_focused_element == client_) {
g_overridden_focused_element = nullptr;
}
}
} // namespace views
} // namespace ui
......@@ -466,8 +466,6 @@ jumbo_component("views") {
"cocoa/bridged_native_widget_host_impl.mm",
"cocoa/drag_drop_client_mac.h",
"cocoa/drag_drop_client_mac.mm",
"cocoa/scoped_accessibility_focus.h",
"cocoa/scoped_accessibility_focus.mm",
"cocoa/tooltip_manager_mac.h",
"cocoa/tooltip_manager_mac.mm",
"controls/button/label_button_label.cc",
......
......@@ -13,6 +13,7 @@
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
#include "ui/accelerated_widget_mac/display_link_mac.h"
#include "ui/base/cocoa/accessibility_focus_overrider.h"
#include "ui/base/ime/input_method_delegate.h"
#include "ui/compositor/layer_owner.h"
#include "ui/views/cocoa/bridge_factory_host.h"
......@@ -37,7 +38,6 @@ namespace views {
class BridgedNativeWidgetImpl;
class NativeWidgetMac;
class ScopedAccessibilityFocus;
// The portion of NativeWidgetMac that lives in the browser process. This
// communicates to the BridgedNativeWidgetImpl, which interacts with the Cocoa
......@@ -49,6 +49,7 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
public DialogObserver,
public FocusChangeListener,
public ui::internal::InputMethodDelegate,
public ui::AccessibilityFocusOverrider::Client,
public ui::LayerDelegate,
public ui::LayerOwner,
public ui::AcceleratedWidgetMacNSView {
......@@ -311,6 +312,9 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
ui::KeyEvent* key,
base::OnceCallback<void(bool)> ack_callback) override;
// ui::AccessibilityFocusOverrider::Client:
id GetAccessibilityFocusedUIElement() override;
// ui::LayerDelegate:
void OnPaintLayer(const ui::PaintContext& context) override;
void OnDeviceScaleFactorChanged(float old_device_scale_factor,
......@@ -348,6 +352,10 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
remote_window_accessible_;
base::scoped_nsobject<NSAccessibilityRemoteUIElement> remote_view_accessible_;
// Used to force the NSApplication's focused accessibility element to be the
// views::Views accessibility tree when the NSView for this is focused.
ui::AccessibilityFocusOverrider accessibility_focus_overrider_;
// TODO(ccameron): Rather than instantiate a BridgedNativeWidgetImpl here,
// we will instantiate a mojo BridgedNativeWidgetImpl interface to a Cocoa
// instance that may be in another process.
......@@ -381,10 +389,6 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
std::unique_ptr<ui::RecyclableCompositorMac> compositor_;
// When allocated, this object will swizzle calls to -[NSApplication
// accessibilityFocusedUIElement] to return GetNativeViewAccessible.
std::unique_ptr<ScopedAccessibilityFocus> scoped_accessibility_focus_;
// Properties used by Set/GetNativeWindowProperty.
std::map<std::string, void*> native_window_properties_;
......
......@@ -18,7 +18,6 @@
#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/mac/coordinate_conversion.h"
#include "ui/native_theme/native_theme_mac.h"
#include "ui/views/cocoa/scoped_accessibility_focus.h"
#include "ui/views/cocoa/tooltip_manager_mac.h"
#include "ui/views/controls/menu/menu_config.h"
#include "ui/views/controls/menu/menu_controller.h"
......@@ -91,6 +90,7 @@ BridgedNativeWidgetHostImpl::BridgedNativeWidgetHostImpl(NativeWidgetMac* owner)
: widget_id_(++g_last_bridged_native_widget_id),
native_widget_mac_(owner),
root_view_id_(ui::NSViewIds::GetNewId()),
accessibility_focus_overrider_(this),
host_mojo_binding_(this) {
DCHECK(GetIdToWidgetHostImplMap().find(widget_id_) ==
GetIdToWidgetHostImplMap().end());
......@@ -99,7 +99,6 @@ BridgedNativeWidgetHostImpl::BridgedNativeWidgetHostImpl(NativeWidgetMac* owner)
}
BridgedNativeWidgetHostImpl::~BridgedNativeWidgetHostImpl() {
scoped_accessibility_focus_.reset();
DCHECK(children_.empty());
if (bridge_factory_host_) {
bridge_ptr_.reset();
......@@ -599,6 +598,7 @@ void BridgedNativeWidgetHostImpl::SetKeyboardAccessible(bool enabled) {
void BridgedNativeWidgetHostImpl::OnIsFirstResponderChanged(
bool is_first_responder) {
accessibility_focus_overrider_.SetViewIsFirstResponder(is_first_responder);
if (is_first_responder) {
root_view_->GetWidget()->GetFocusManager()->RestoreFocusedView();
} else {
......@@ -789,13 +789,7 @@ void BridgedNativeWidgetHostImpl::OnWindowKeyStatusChanged(
bool is_key,
bool is_content_first_responder,
bool full_keyboard_access_enabled) {
if (is_key) {
scoped_accessibility_focus_ =
std::make_unique<ScopedAccessibilityFocus>(this);
} else {
scoped_accessibility_focus_.reset();
}
accessibility_focus_overrider_.SetWindowIsKey(is_key);
is_window_key_ = is_key;
Widget* widget = native_widget_mac_->GetWidget();
if (!widget->OnNativeWidgetActivationChanged(is_key))
......@@ -1073,6 +1067,13 @@ ui::EventDispatchDetails BridgedNativeWidgetHostImpl::DispatchKeyEventPostIME(
return ui::EventDispatchDetails();
}
////////////////////////////////////////////////////////////////////////////////
// BridgedNativeWidgetHostImpl, AccessibilityFocusOverrider::Client:
id BridgedNativeWidgetHostImpl::GetAccessibilityFocusedUIElement() {
return [GetNativeViewAccessible() accessibilityFocusedUIElement];
}
////////////////////////////////////////////////////////////////////////////////
// BridgedNativeWidgetHostImpl, LayerDelegate:
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef UI_VIEWS_COCOA_SCOPED_ACCESSIBILITY_FOCUS_H_
#define UI_VIEWS_COCOA_SCOPED_ACCESSIBILITY_FOCUS_H_
#include "ui/views/views_export.h"
namespace views {
class BridgedNativeWidgetHostImpl;
// This object, while instantiated, will swizzle -[NSApplication
// accessibilityFocusedUIElement] to return the NSWindow of the specified
// BridgedNativeWidgetHostHelper. This is needed to handle remote accessibility
// queries. If two of these objects are instantiated at the same time, the most
// recently created object will take precedence.
class VIEWS_EXPORT ScopedAccessibilityFocus {
public:
ScopedAccessibilityFocus(BridgedNativeWidgetHostImpl* host);
~ScopedAccessibilityFocus();
private:
BridgedNativeWidgetHostImpl* const host_;
};
} // namespace views
#endif // UI_VIEWS_COCOA_SCOPED_ACCESSIBILITY_FOCUS_H_
......@@ -1611,6 +1611,9 @@ ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
}
- (id)accessibilityFocusedUIElement {
// This function should almost-never be called because when |self| is the
// first responder for the key NSWindow, BridgedNativeWidgetHostImpl's
// AccessibilityFocusOverrider will override the accessibility focus query.
if (!bridge_)
return nil;
return [bridge_->host_helper()->GetNativeViewAccessible()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment