Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

A11y callback #8005

Merged
merged 8 commits into from
Mar 7, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions shell/platform/darwin/ios/framework/Headers/FlutterEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,26 @@ FLUTTER_EXPORT
*/
- (void)destroyContext;

/**
* Ensures that Flutter will generate a semantics tree.
*
* This is enabled by default if certain accessibility services are turned on by
* the user, or when using a Simulator. This method allows a user to turn
* semantics on when they would not ordinarily be generated and the performance
* overhead is not a concern, e.g. for UI testing. Note that semantics should
* never be programatically turned off, as it would potentially disable
* accessibility services an end user has requested.
*
* This method must only be called after launching the engine via
* `-runWithEntrypoint:` or `-runWithEntryPoint:libraryURI`.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me know if I'm wrong: In the perspective FlutterViewController user, it's hard to find a right time to enable semantics before the first semantics tree being built.

I think it will be easier if FlutterViewController can take the preference and invoke this method when _engineNeedsLaunch is used :).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Semantics might already be enabled based on device settings or if it's a simulator. It should be safe to call this method even if semantics are enabled - if they're not, no semantics tree will be built.

We could make it an option in the initializer, but I'm not sure how that would help for testing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or maybe a property/one-way-method of FlutterViewController? User can check if they need to force enabling semantics through several ways, such as plist or envs. If it's the case, they can flip the bit after calling initilizer, but before load the VC.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ensureSemanticsEnabled is safe to call at any time. Basically, the idea is to just call it right after you register for the callback. You could in theory call it in a loop after that as long as you let the main runloop make progress.

*
* You can subscribe to semantics updates via `NSNotificationCenter` by adding
* an observer for the name `FlutterSemanticsUpdateNotification`. The `object`
* parameter will be the `FlutterViewController` associated with the semantics
* update.
*/
- (void)ensureSemanticsEnabled;

/**
* Sets the `FlutterViewController` for this instance. The FlutterEngine must be
* running (e.g. a successful call to `-runWithEntrypoint:` or `-runWithEntrypoint:libraryURI`)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@

@class FlutterEngine;

/**
* The name used for semantic update nofications via `NSNotificationCenter`.
*
* The object passed as the sender is the `FlutterViewController` associated
* with the update.
*/
const NSNotificationName FlutterSemanticsUpdateNotification = @"FlutterSemanticsUpdate";

/**
* A `UIViewController` implementation for Flutter views.
*
Expand Down
4 changes: 4 additions & 0 deletions shell/platform/darwin/ios/framework/Source/FlutterEngine.mm
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@ - (void)dispatchPointerDataPacket:(std::unique_ptr<blink::PointerDataPacket>)pac
return _shell->GetTaskRunners().GetPlatformTaskRunner();
}

- (void)ensureSemanticsEnabled {
self.iosPlatformView->SetSemanticsEnabled(true);
}

- (void)setViewController:(FlutterViewController*)viewController {
FML_DCHECK(self.iosPlatformView);
_viewController = [viewController getWeakPtr];
Expand Down
6 changes: 3 additions & 3 deletions shell/platform/darwin/ios/platform_view_ios.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ class PlatformViewIOS final : public PlatformView {

void SetTextInputPlugin(fml::scoped_nsprotocol<FlutterTextInputPlugin*> plugin);

// |shell::PlatformView|
void SetSemanticsEnabled(bool enabled) override;

private:
fml::WeakPtr<FlutterViewController> owner_controller_;
std::unique_ptr<IOSSurface> ios_surface_;
Expand All @@ -57,9 +60,6 @@ class PlatformViewIOS final : public PlatformView {
// |shell::PlatformView|
sk_sp<GrContext> CreateResourceContext() const override;

// |shell::PlatformView|
void SetSemanticsEnabled(bool enabled) override;

// |shell::PlatformView|
void SetAccessibilityFeatures(int32_t flags) override;

Expand Down
7 changes: 5 additions & 2 deletions shell/platform/darwin/ios/platform_view_ios.mm
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@
// |shell::PlatformView|
void PlatformViewIOS::SetSemanticsEnabled(bool enabled) {
if (!owner_controller_) {
FML_DLOG(WARNING) << "Could not set semantics to enabled, this "
"PlatformViewIOS has no ViewController.";
FML_LOG(WARNING) << "Could not set semantics to enabled, this "
"PlatformViewIOS has no ViewController.";
return;
}
if (enabled && !accessibility_bridge_) {
Expand All @@ -111,8 +111,11 @@
// |shell::PlatformView|
void PlatformViewIOS::UpdateSemantics(blink::SemanticsNodeUpdates update,
blink::CustomAccessibilityActionUpdates actions) {
FML_DCHECK(owner_controller_);
if (accessibility_bridge_) {
accessibility_bridge_->UpdateSemantics(std::move(update), std::move(actions));
[[NSNotificationCenter defaultCenter] postNotificationName:FlutterSemanticsUpdateNotification
object:owner_controller_.get()];
}
}

Expand Down