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

Send locale information in the macOS embedding #20461

Merged
merged 1 commit into from
Aug 13, 2020
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
49 changes: 49 additions & 0 deletions shell/platform/darwin/macos/framework/Source/FlutterEngine.mm
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,30 @@
#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterViewController_Internal.h"
#import "flutter/shell/platform/embedder/embedder.h"

/**
* Constructs and returns a FlutterLocale struct corresponding to |locale|, which must outlive
* the returned struct.
*/
static FlutterLocale FlutterLocaleFromNSLocale(NSLocale* locale) {
FlutterLocale flutterLocale = {};
flutterLocale.struct_size = sizeof(FlutterLocale);
flutterLocale.language_code = [[locale objectForKey:NSLocaleLanguageCode] UTF8String];
flutterLocale.country_code = [[locale objectForKey:NSLocaleCountryCode] UTF8String];
flutterLocale.script_code = [[locale objectForKey:NSLocaleScriptCode] UTF8String];
flutterLocale.variant_code = [[locale objectForKey:NSLocaleVariantCode] UTF8String];
return flutterLocale;
}

/**
* Private interface declaration for FlutterEngine.
*/
@interface FlutterEngine () <FlutterBinaryMessenger>

/**
* Sends the list of user-preferred locales to the Flutter engine.
*/
- (void)sendUserLocales;

/**
* Called by the engine to make the context the engine should draw into current.
*/
Expand Down Expand Up @@ -181,6 +200,12 @@ - (instancetype)initWithName:(NSString*)labelPrefix
_textures = [[NSMutableDictionary alloc] init];
_allowHeadlessExecution = allowHeadlessExecution;

NSNotificationCenter* notificationCenter = [NSNotificationCenter defaultCenter];
Copy link
Member

Choose a reason for hiding this comment

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

The observer needs to be removed in the notification center explicitly in the dealloc. Not doing so will lead to a dangling pointer on older versions of macOS.

Copy link
Member

Choose a reason for hiding this comment

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

The discussion in https://developer.apple.com/documentation/foundation/nsnotificationcenter/1415360-addobserver says macOS 10.11. I am not sure we support stuff that old but its good practice to cleanup anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

10.11 is our lower limit, which is why I didn't unregister it.

but its good practice to cleanup anyway

My experience with modern ObjC (in iOS projects that target 9+) is that it's become standard practice not to unregister, given that it's explicitly documented that you no longer need to. As with the transition from manual ref counting to ARC, it's one of those things that looks really wrong at first, but you get used to :)

[notificationCenter addObserver:self
selector:@selector(sendUserLocales)
name:NSCurrentLocaleDidChangeNotification
object:nil];

return self;
}

Expand Down Expand Up @@ -254,6 +279,7 @@ - (BOOL)runWithEntrypoint:(NSString*)entrypoint {
return NO;
}

[self sendUserLocales];
[self updateWindowMetrics];
return YES;
}
Expand Down Expand Up @@ -314,6 +340,29 @@ - (void)sendPointerEvent:(const FlutterPointerEvent&)event {

#pragma mark - Private methods

- (void)sendUserLocales {
if (!self.running) {
return;
}

// Create a list of FlutterLocales corresponding to the preferred languages.
NSMutableArray<NSLocale*>* locales = [NSMutableArray array];
std::vector<FlutterLocale> flutterLocales;
flutterLocales.reserve(locales.count);
for (NSString* localeID in [NSLocale preferredLanguages]) {
NSLocale* locale = [[NSLocale alloc] initWithLocaleIdentifier:localeID];
[locales addObject:locale];
flutterLocales.push_back(FlutterLocaleFromNSLocale(locale));
}
// Convert to a list of pointers, and send to the engine.
std::vector<const FlutterLocale*> flutterLocaleList;
flutterLocaleList.reserve(flutterLocales.size());
std::transform(
flutterLocales.begin(), flutterLocales.end(), std::back_inserter(flutterLocaleList),
[](const auto& arg) -> const auto* { return &arg; });
FlutterEngineUpdateLocales(_engine, flutterLocaleList.data(), flutterLocaleList.size());
}

- (bool)engineCallbackOnMakeCurrent {
if (!_mainOpenGLContext) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ - (BOOL)launchEngine {
}
// Send the initial user settings such as brightness and text scale factor
// to the engine.
// TODO(stuartmorgan): Move this logic to FlutterEngine.
[self sendInitialSettings];
return YES;
}
Expand Down