Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 6 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
1 change: 1 addition & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -1036,6 +1036,7 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterView.mm
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController_Internal.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterViewTest.mm
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/IOKit.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/SemanticsObject.h
FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/SemanticsObject.mm
Expand Down
1 change: 1 addition & 0 deletions shell/platform/darwin/ios/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ source_set("ios_test_flutter_mrc") {
"framework/Source/FlutterEngineTest_mrc.mm",
"framework/Source/FlutterPlatformPluginTest.mm",
"framework/Source/FlutterPlatformViewsTest.mm",
"framework/Source/FlutterViewTest.mm",
"framework/Source/accessibility_bridge_test.mm",
]
deps = [
Expand Down
8 changes: 7 additions & 1 deletion shell/platform/darwin/ios/framework/Source/FlutterEngine.mm
Original file line number Diff line number Diff line change
Expand Up @@ -761,14 +761,20 @@ - (void)showAutocorrectionPromptRectForStart:(NSUInteger)start
arguments:@[ @(client), @(start), @(end) ]];
}

#pragma mark - Screenshot Delegate
#pragma mark - FlutterViewEngineDelegate

- (flutter::Rasterizer::Screenshot)takeScreenshot:(flutter::Rasterizer::ScreenshotType)type
asBase64Encoded:(BOOL)base64Encode {
FML_DCHECK(_shell) << "Cannot takeScreenshot without a shell";
return _shell->Screenshot(type, base64Encode);
}

- (void)flutterViewAccessibilityDidCall {
if (self.viewController.view.accessibilityElements == nil) {
[self ensureSemanticsEnabled];
}
}

- (NSObject<FlutterBinaryMessenger>*)binaryMessenger {
return _binaryMessenger;
}
Expand Down
10 changes: 10 additions & 0 deletions shell/platform/darwin/ios/framework/Source/FlutterView.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@
asBase64Encoded:(BOOL)base64Encode;

- (std::shared_ptr<flutter::FlutterPlatformViewsController>&)platformViewsController;

/**
* A callback that is called when iOS queries accessibility information of the Flutter view.
*
* This is useful to predict the current iOS accessibility status. For example, there is
* no API to listen whether voice control is turned on or off. The Flutter engine uses
* this callback to enable semantics in order to catch the case that voice control is
* on.
*/
- (void)flutterViewAccessibilityDidCall;
@end

@interface FlutterView : UIView
Expand Down
13 changes: 13 additions & 0 deletions shell/platform/darwin/ios/framework/Source/FlutterView.mm
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,17 @@ - (void)drawLayer:(CALayer*)layer inContext:(CGContextRef)context {
CGContextRestoreGState(context);
}

- (BOOL)isAccessibilityElement {
// iOS does not provide an API to query whether the voice control
// is turned on or off. It is likely at least one of the assitive
// technologies is turned on if this method is called. If we do
// not catch it in notification center, we will catch it here.
//
// TODO(chunhtai): Remove this workaround once iOS provides an
// API to query whether voice control is enabled.
// https://github.com/flutter/flutter/issues/76808.
[_delegate flutterViewAccessibilityDidCall];
return NO;
}

@end
35 changes: 35 additions & 0 deletions shell/platform/darwin/ios/framework/Source/FlutterViewTest.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#import <XCTest/XCTest.h>

#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterEngine_Internal.h"
#import "flutter/shell/platform/darwin/ios/framework/Source/FlutterView.h"

@interface FakeDelegate : FlutterEngine
@property(nonatomic) BOOL ensureSemanticsEnabledCalled;
@end

@implementation FakeDelegate

- (void)ensureSemanticsEnabled {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This method has to be updated, this test should be failing.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

No I inherited from the FlutterEngine so I only need to override ensureSemanticsEnabled. I want to test the FlutterView.isAccessibilityElement call eventually lead to ensureSemanticsEnabled

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

otheriwse, I will need to write two tests.
one for FlutterView.isAccessibilityElement calls FlutterViewEngineDelegate.flutterViewAccessibilityDidCall

the other one for FlutterEngine.flutterViewAccessibilityDidCall calls FlutterEngine.ensureSemanticsEnabled

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Ahh yea, sorry missed that. I think you should use a mock object to keep the test hermetic. Now you're tying your testing of functionality on FlutterView to implementation details in FlutterEngine which is fragile. It easy to replace it if you use OCMock, there are examples in other tests.

_ensureSemanticsEnabledCalled = YES;
}

@end

@interface FlutterViewTest : XCTestCase
@end

@implementation FlutterViewTest

- (void)testFlutterViewEnableSemanticsWhenIsAccessibilityElementIsCalled {
FakeDelegate* delegate = [[FakeDelegate alloc] initWithName:@"foobar"];
FlutterView* view = [[FlutterView alloc] initWithDelegate:delegate opaque:NO];
delegate.ensureSemanticsEnabledCalled = NO;
XCTAssertFalse(view.isAccessibilityElement);
XCTAssertTrue(delegate.ensureSemanticsEnabledCalled);
}

@end