9#import "flutter/shell/platform/common/platform_provided_menu.h"
10#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterChannels.h"
11#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterCodecs.h"
22static NSString*
const kIdKey =
@"id";
65 @0x00100000008 : [NSNumber numberWithInt:NSBackspaceCharacter],
66 @0x00100000009 : [NSNumber numberWithInt:NSTabCharacter],
67 @0x0010000000a : [NSNumber numberWithInt:NSNewlineCharacter],
68 @0x0010000000c : [NSNumber numberWithInt:NSFormFeedCharacter],
69 @0x0010000000d : [NSNumber numberWithInt:NSCarriageReturnCharacter],
70 @0x0010000007f : [NSNumber numberWithInt:NSDeleteCharacter],
71 @0x00100000801 : [NSNumber numberWithInt:NSF1FunctionKey],
72 @0x00100000802 : [NSNumber numberWithInt:NSF2FunctionKey],
73 @0x00100000803 : [NSNumber numberWithInt:NSF3FunctionKey],
74 @0x00100000804 : [NSNumber numberWithInt:NSF4FunctionKey],
75 @0x00100000805 : [NSNumber numberWithInt:NSF5FunctionKey],
76 @0x00100000806 : [NSNumber numberWithInt:NSF6FunctionKey],
77 @0x00100000807 : [NSNumber numberWithInt:NSF7FunctionKey],
78 @0x00100000808 : [NSNumber numberWithInt:NSF8FunctionKey],
79 @0x00100000809 : [NSNumber numberWithInt:NSF9FunctionKey],
80 @0x0010000080a : [NSNumber numberWithInt:NSF10FunctionKey],
81 @0x0010000080b : [NSNumber numberWithInt:NSF11FunctionKey],
82 @0x0010000080c : [NSNumber numberWithInt:NSF12FunctionKey],
83 @0x0010000080d : [NSNumber numberWithInt:NSF13FunctionKey],
84 @0x0010000080e : [NSNumber numberWithInt:NSF14FunctionKey],
85 @0x0010000080f : [NSNumber numberWithInt:NSF15FunctionKey],
86 @0x00100000810 : [NSNumber numberWithInt:NSF16FunctionKey],
87 @0x00100000811 : [NSNumber numberWithInt:NSF17FunctionKey],
88 @0x00100000812 : [NSNumber numberWithInt:NSF18FunctionKey],
89 @0x00100000813 : [NSNumber numberWithInt:NSF19FunctionKey],
90 @0x00100000814 : [NSNumber numberWithInt:NSF20FunctionKey],
95 @0x00100000302 : @0xf702,
96 @0x00100000303 : @0xf703,
97 @0x00100000304 : @0xf700,
98 @0x00100000301 : @0xf701,
99 @0x00100000306 : @0xf729,
100 @0x00100000305 : @0xf72B,
101 @0x00100000308 : @0xf72c,
102 @0x00100000307 : @0xf72d,
103 @0x0010000001b : @0x001B,
136 int flutterModifierFlags = modifiers.intValue;
137 NSEventModifierFlags
flags = 0;
139 flags |= NSEventModifierFlagCommand;
142 flags |= NSEventModifierFlagShift;
145 flags |= NSEventModifierFlagOption;
148 flags |= NSEventModifierFlagControl;
183- (void)menuWillOpen:(NSMenu*)menu {
184 [_channel invokeMethod:kMenuOpenedMethod arguments:@(_identifier)];
187- (void)menuDidClose:(NSMenu*)menu {
188 [_channel invokeMethod:kMenuClosedMethod arguments:@(_identifier)];
198- (void)replaceAppName:(NSArray<NSMenuItem*>*)items;
202- (NSMenuItem*)findProvidedMenuItem:(NSMenu*)menu ofType:(
SEL)selector;
208- (NSMenuItem*)menuItemFromFlutterRepresentation:(NSDictionary*)representation;
213- (void)flutterMenuItemSelected:(
id)sender;
217- (void)setMenus:(nonnull NSDictionary*)representation;
232#pragma mark - Private Methods
246 [
self replaceAppName:_platformProvidedItems];
255- (void)replaceAppName:(NSArray<NSMenuItem*>*)items {
256 NSString* appName = [NSRunningApplication currentApplication].localizedName;
257 for (NSMenuItem* item in items) {
258 if ([[item title] containsString:
kAppName]) {
259 [item setTitle:[[item title] stringByReplacingOccurrencesOfString:kAppName
260 withString:appName]];
262 if ([item hasSubmenu]) {
263 [
self replaceAppName:[[item submenu] itemArray]];
268- (NSMenuItem*)findProvidedMenuItem:(NSMenu*)menu ofType:(
SEL)selector {
270 for (NSMenuItem* item in items) {
271 if ([item
action] == selector) {
274 if ([[item submenu] numberOfItems] > 0) {
275 NSMenuItem* foundChild = [
self findProvidedMenuItem:[item submenu] ofType:selector];
286 auto found_type = providedMenus.find(
type);
287 if (found_type == providedMenus.end()) {
290 SEL selectorTarget = found_type->second;
296 ? [_platformProvidedItems[0] submenu]
298 NSMenuItem* found = [
self findProvidedMenuItem:startingMenu ofType:selectorTarget];
305- (NSMenuItem*)menuItemFromFlutterRepresentation:(NSDictionary*)representation {
306 if ([(NSNumber*)([representation valueForKey:
kDividerKey]) intValue] == YES) {
307 return [NSMenuItem separatorItem];
309 NSNumber* platformProvidedMenuId = representation[kPlatformProvidedMenuKey];
310 NSString* keyEquivalent =
@"";
312 if (platformProvidedMenuId) {
314 createPlatformProvidedMenu:(flutter::PlatformProvidedMenu)platformProvidedMenuId.intValue];
317 keyEquivalent = representation[kShortcutCharacterKey];
319 NSNumber* triggerKeyId = representation[kShortcutTriggerKey];
321 NSNumber* trigger = specialKeys[triggerKeyId];
323 keyEquivalent = [NSString stringWithFormat:@"%C", [trigger unsignedShortValue]];
327 keyEquivalent = [[NSString
328 stringWithFormat:@"%C", (unichar)([triggerKeyId unsignedLongLongValue] &
329 kFlutterKeyIdValueMask)] lowercaseString];
335 NSNumber*
identifier = representation[kIdKey];
337 NSString* appName = [NSRunningApplication currentApplication].localizedName;
338 NSString* title = [representation[kLabelKey] stringByReplacingOccurrencesOfString:kAppName
340 NSMenuItem* item = [[NSMenuItem alloc] initWithTitle:title
342 keyEquivalent:keyEquivalent];
343 if ([keyEquivalent
length] > 0) {
344 item.keyEquivalentModifierMask =
351 NSNumber* enabled = representation[kEnabledKey];
353 item.enabled = enabled.boolValue;
356 NSArray* children = representation[kChildrenKey];
357 if (children && children.count > 0) {
358 NSMenu* submenu = [[NSMenu alloc] initWithTitle:title];
361 [_menuDelegates addObject:delegate];
362 submenu.delegate = delegate;
363 submenu.autoenablesItems = NO;
364 for (NSDictionary* child in children) {
365 NSMenuItem* newItem = [
self menuItemFromFlutterRepresentation:child];
367 [submenu addItem:newItem];
370 item.submenu = submenu;
375- (void)flutterMenuItemSelected:(
id)sender {
376 NSMenuItem* item = sender;
377 [_channel invokeMethod:kMenuSelectedCallbackMethod arguments:@(item.tag)];
384 NSDictionary* menus =
call.arguments;
385 [
self setMenus:menus];
392- (void)setMenus:(NSDictionary*)representation {
393 [_menuDelegates removeAllObjects];
394 NSMenu* newMenu = [[NSMenu alloc] init];
397 for (NSDictionary* item in representation[
@"0"]) {
398 NSMenuItem* menuItem = [
self menuItemFromFlutterRepresentation:item];
399 menuItem.representedObject =
self;
402 [[
FlutterMenuDelegate alloc] initWithIdentifier:identifier.longLongValue channel:_channel];
403 [_menuDelegates addObject:delegate];
404 [menuItem submenu].delegate = delegate;
405 [newMenu addItem:menuItem];
407 NSApp.mainMenu = newMenu;
410#pragma mark - Public Class Methods
void(^ FlutterResult)(id _Nullable result)
FLUTTER_DARWIN_EXPORT NSObject const * FlutterMethodNotImplemented
FlutterMethodChannel * _channel
static SkString identifier(const FontFamilyDesc &family, const FontDesc &font)
FlutterSemanticsFlag flags
static FlMethodResponse * hide(FlTextInputPlugin *self)
instancetype methodChannelWithName:binaryMessenger:(NSString *name,[binaryMessenger] NSObject< FlutterBinaryMessenger > *messenger)
void addMethodCallDelegate:channel:(NSObject< FlutterPlugin > *delegate,[channel] FlutterMethodChannel *channel)