Thanks to visit codestin.com
Credit goes to github.com

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

Access on/off labels accessibility setting for switches on iOS #30764

Merged
merged 1 commit into from
Mar 7, 2022

Conversation

RtgrV
Copy link
Contributor

@RtgrV RtgrV commented Jan 10, 2022

Description

Read the "On/Off switch labels enabled" setting from iOS accessibility settings and pass it together with the rest of the accessibility flags.

Issue: flutter/flutter#4830

This was the previous attempt to add the feature to the flutter engine but was reverted due to iOS version compatibility issues: #12404

Used a different PR (adding high contrast accessibility feature) as a reference: #15343

Tests

I wasn't able to find a similair test for any of the other platform-specific accessibility flags.

@flutter-dashboard
Copy link

It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption to this rule, contact Hixie on the #hackers channel in Chat.

If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix?

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

@flutter-dashboard flutter-dashboard bot added platform-ios platform-web Code specifically for the web engine needs tests labels Jan 10, 2022
@RtgrV RtgrV force-pushed the accessibility-onofflabels-ios branch from 3359419 to fc64f83 Compare January 10, 2022 17:35
@RtgrV
Copy link
Contributor Author

RtgrV commented Jan 10, 2022

I've looked into adding unit testing to the code but it seems to be either not possible or very relevant:

  • The C code makes use of private system frameworks which are hard to test against. I believe the only way to test this integration is by swizzling the system method UIAccessibilityIsOnOffSwitchLabelsEnabled, which I wouldn't recommend.
  • The dart code makes the values available coming from C. The only test I could think of is by testing the bit map. Which in my opinion that test wouldn't be worth having.

Please let me know what you think, I'm open to any other suggestions I might have overlooked. πŸ‘

@RtgrV RtgrV force-pushed the accessibility-onofflabels-ios branch from fc64f83 to 6795625 Compare February 21, 2022 12:43
@skia-gold
Copy link

Gold has detected about 2 new digest(s) on patchset 1.
View them at https://flutter-engine-gold.skia.org/cl/github/30764

@RtgrV RtgrV force-pushed the accessibility-onofflabels-ios branch 3 times, most recently from 9a3da84 to 58e7e56 Compare February 21, 2022 21:11
@skia-gold
Copy link

Gold has detected about 2 new digest(s) on patchset 1.
View them at https://flutter-engine-gold.skia.org/cl/github/30764

@RtgrV RtgrV force-pushed the accessibility-onofflabels-ios branch 2 times, most recently from 718ae5d to 65c9d03 Compare February 21, 2022 23:12
@jmagman jmagman removed the platform-web Code specifically for the web engine label Mar 2, 2022
Copy link
Member

@jmagman jmagman left a comment

Choose a reason for hiding this comment

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

The Obj-C parts look good with request for minor changes.

I'm less familiar with the dart code, but it looks really similar to other iOS-only accessibility support like BoldText and ReduceMotion.
LGTM, will let engine PR chime for the second review.

int32_t flags = [viewController accessibilityFlags];

// Verify behavior.
XCTAssert(flags == 0);
Copy link
Member

Choose a reason for hiding this comment

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

Just in case the test device has some other UIAccessibility features on can you instead just check that the kOnOffSwitchLabels bit is off?

int32_t flags = [viewController accessibilityFlags];

// Verify behavior.
XCTAssert(flags == 1 << 6);
Copy link
Member

Choose a reason for hiding this comment

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

Same, just check that the kOnOffSwitchLabels bit is on?

@@ -0,0 +1,18 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
Copy link
Member

Choose a reason for hiding this comment

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

I know you added this for testability, but it seems like overkill to add a new header and implementation file for a single wrapper around a function. FlutterPlatformViews_Internal might be a better spot.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tried adding it to FlutterPlatformViews_Internal, but in the end, failed to do so. I struggled with some ARC-related errors coming in from the underlying imports having an effect on existing test cases.

Instead of going for FlutterPlatformViews, I was able to add it to the FlutterViewController_Internal instead. Hope that will also work for you. Please let me know!

Copy link
Member

Choose a reason for hiding this comment

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

FlutterViewController_Internal.mm doesn't make sense, the implementation is already "internal", the _Internal.h suffix is used to indicate it's not a "public" header and is not exported in the module.

What ARC errors were you seeing?

Copy link
Contributor Author

@RtgrV RtgrV Mar 4, 2022

Choose a reason for hiding this comment

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

I can commit the changes if you like if that gives a clearer view. A grasp of the console log, there is more but similair. Do you know how to resolve these issues?

../../flutter/fml/platform/darwin/scoped_nsobject.h:153:28: error: 'NSAutoreleasePool' is unavailable: not available in automatic reference counting mode
  explicit scoped_nsobject(NSAutoreleasePool* object = nil);
                           ^
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator15.0.sdk/System/Library/Frameworks/Foundation.framework/Headers/NSAutoreleasePool.h:10:12: note: 'NSAutoreleasePool' has been explicitly marked unavailable here
@interface NSAutoreleasePool : NSObject {
           ^
In file included from ../../flutter/shell/platform/darwin/ios/framework/Source/FlutterViewControllerTest.mm:16:
In file included from ../../flutter/shell/platform/darwin/ios/framework/Source/FlutterPlatformViews_Internal.h:10:
../../flutter/fml/platform/darwin/scoped_nsobject.h:51:35: error: 'release' is unavailable: not available in automatic reference counting mode
  ~scoped_nsprotocol() { [object_ release]; }
                                  ^
../../flutter/fml/platform/darwin/scoped_nsobject.h:133:12: note: in instantiation of member function 'fml::scoped_nsprotocol<id>::~scoped_nsprotocol' requested here
  explicit scoped_nsobject(id object = nil) : scoped_nsprotocol<id>(object) {}
           ^
/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator15.0.sdk/usr/include/objc/NSObject.h:37:1: note: 'release' has been explicitly marked unavailable here
- (oneway void)release OBJC_ARC_UNAVAILABLE;

Copy link
Member

Choose a reason for hiding this comment

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

I pasted AccessibilityValueProvider at the bottom of FlutterViewController.m and it compiled fine. You can push up your change if you want me to take a look though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah that's also an option ofcourse, I didn't consider that one yet. Thanks! Will take a look.

@RtgrV RtgrV force-pushed the accessibility-onofflabels-ios branch from 65c9d03 to 40c0faf Compare March 3, 2022 20:39
@RtgrV
Copy link
Contributor Author

RtgrV commented Mar 3, 2022

Thanks for ur review! Will fix the minor requests.

@RtgrV RtgrV force-pushed the accessibility-onofflabels-ios branch 6 times, most recently from 157745b to 61a8bae Compare March 4, 2022 08:31
Copy link
Member

@jmagman jmagman left a comment

Choose a reason for hiding this comment

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

Thanks for the contribution, we're almost there!

Comment on lines 48 to 53
- (int32_t)accessibilityFlags;
@end

@interface AccessibilityValueProvider : NSObject
+ (BOOL)accessibilityIsOnOffSwitchLabelsEnabled;
@end
Copy link
Member

Choose a reason for hiding this comment

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

Let's try just adding it (as a class property) as the first declaration of FlutterViewController , then testing a partial mock in the test. Kind of a smell to mock out the object under test, but adding a new class for this just to wrap the test still seems like overkill.

@interface FlutterViewController () <FlutterViewResponder>

@property(class, nonatomic, readonly) BOOL accessibilityIsOnOffSwitchLabelsEnabled;
@property(nonatomic, readonly) BOOL isPresentingViewController;
...

Then move the implementation to right under accessibilityFlags

  if ([self class].accessibilityIsOnOffSwitchLabelsEnabled) {
    flags |= static_cast<int32_t>(flutter::AccessibilityFeatureFlag::kOnOffSwitchLabels);
  }

  return flags;
}

+ (BOOL)accessibilityIsOnOffSwitchLabelsEnabled {
  if (@available(iOS 13, *)) {
    return UIAccessibilityIsOnOffSwitchLabelsEnabled();
  } else {
    return NO;
  }
}

Comment on lines 635 to 642
FlutterViewController* viewController =
[[FlutterViewController alloc] initWithEngine:self.mockEngine nibName:nil bundle:nil];

id valueProvider = OCMClassMock([AccessibilityValueProvider class]);
OCMStub([valueProvider accessibilityIsOnOffSwitchLabelsEnabled]).andReturn(false);

// Exercise behavior under test.
int32_t flags = [viewController accessibilityFlags];
Copy link
Member

Choose a reason for hiding this comment

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

Then (also not the NO and YES BOOLs):

Suggested change
FlutterViewController* viewController =
[[FlutterViewController alloc] initWithEngine:self.mockEngine nibName:nil bundle:nil];
id valueProvider = OCMClassMock([AccessibilityValueProvider class]);
OCMStub([valueProvider accessibilityIsOnOffSwitchLabelsEnabled]).andReturn(false);
// Exercise behavior under test.
int32_t flags = [viewController accessibilityFlags];
FlutterViewController* viewController =
[[FlutterViewController alloc] initWithEngine:self.mockEngine nibName:nil bundle:nil];
id partialMockViewController = OCMPartialMock(viewController);
OCMStub([partialMockViewController accessibilityIsOnOffSwitchLabelsEnabled]).andReturn(NO);
// Exercise behavior under test.
int32_t flags = [partialMockViewController accessibilityFlags]

Comment on lines 656 to 663
FlutterViewController* viewController =
[[FlutterViewController alloc] initWithEngine:self.mockEngine nibName:nil bundle:nil];

id valueProvider = OCMClassMock([AccessibilityValueProvider class]);
OCMStub([valueProvider accessibilityIsOnOffSwitchLabelsEnabled]).andReturn(true);

// Exercise behavior under test.
int32_t flags = [viewController accessibilityFlags];
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
FlutterViewController* viewController =
[[FlutterViewController alloc] initWithEngine:self.mockEngine nibName:nil bundle:nil];
id valueProvider = OCMClassMock([AccessibilityValueProvider class]);
OCMStub([valueProvider accessibilityIsOnOffSwitchLabelsEnabled]).andReturn(true);
// Exercise behavior under test.
int32_t flags = [viewController accessibilityFlags];
FlutterViewController* viewController =
[[FlutterViewController alloc] initWithEngine:self.mockEngine nibName:nil bundle:nil];
id partialMockViewController = OCMPartialMock(viewController);
OCMStub([partialMockViewController accessibilityIsOnOffSwitchLabelsEnabled]).andReturn(YES);
// Exercise behavior under test.
int32_t flags = [partialMockViewController accessibilityFlags];

@RtgrV RtgrV force-pushed the accessibility-onofflabels-ios branch 3 times, most recently from dbe49bf to 83be62f Compare March 7, 2022 15:57
@RtgrV RtgrV force-pushed the accessibility-onofflabels-ios branch from 83be62f to b49fa74 Compare March 7, 2022 16:19
Copy link
Member

@jmagman jmagman left a comment

Choose a reason for hiding this comment

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

Adding @cyanglaz as second reviewer

Comment on lines -28 to -30
namespace flutter {
class PointerDataPacket {};
}
Copy link
Member

Choose a reason for hiding this comment

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

Did you mean to change this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, if I didn't it wouldn't compile.

I had to import

#import "flutter/lib/ui/window/platform_configuration.h"

to get access to the AccessibilityFeatureFlag enum.

platform_configuration imports the implementation of the PointerDataPacket class. Making the one in the tests obsolete.

#include "flutter/lib/ui/window/pointer_data_packet.h"

@@ -1052,7 +1089,7 @@ - (void)testMouseSupport API_AVAILABLE(ios(13.4)) {
[vc scrollEvent:mockPanGestureRecognizer];

[[[self.mockEngine verify] ignoringNonObjectArgs]
dispatchPointerDataPacket:std::make_unique<flutter::PointerDataPacket>()];
dispatchPointerDataPacket:std::make_unique<flutter::PointerDataPacket>(0)];
Copy link
Member

Choose a reason for hiding this comment

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

or this?

@jmagman jmagman requested a review from cyanglaz March 7, 2022 19:18
Copy link
Member

@jmagman jmagman left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@cyanglaz cyanglaz left a comment

Choose a reason for hiding this comment

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

LGTM

@jmagman jmagman added the waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land. label Mar 7, 2022
@fluttergithubbot fluttergithubbot merged commit 977cb0e into flutter:main Mar 7, 2022
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Mar 8, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
needs tests platform-ios waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants