Skip to content

Commit bf89f50

Browse files
[macOS] Align FLEPlugin with iOS Flutter
Changes FLEPlugin to be a subset of iOS's FlutterPlugin's API, including changing the plugin creation and registration system. Plugins now create and manage their own channels, instead of relying on FLEViewController for high-level message APIs. This is a breaking change for any FLEPlugin implementation, as well as application-level code that was calling addPlugin:. (The later may require additional changes in the future as noted in the comment on registerPlugin:, but the plugin implemention API should now be stable.) This essentially completes issue google#102 for macOS.
1 parent 5c75476 commit bf89f50

15 files changed

+247
-284
lines changed

example/macos/ExampleWindow.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ class ExampleWindow: NSWindow {
1818
@IBOutlet weak var flutterViewController: FLEViewController!
1919

2020
override func awakeFromNib() {
21-
flutterViewController.add(FLEColorPanelPlugin())
22-
flutterViewController.add(FLEFileChooserPlugin())
23-
flutterViewController.add(FLEMenubarPlugin())
21+
flutterViewController.register(FLEColorPanelPlugin.self)
22+
flutterViewController.register(FLEFileChooserPlugin.self)
23+
flutterViewController.register(FLEMenubarPlugin.self)
2424

2525
let assets = NSURL.fileURL(withPath: "flutter_assets", relativeTo: Bundle.main.resourceURL)
2626
// Pass through argument zero, since the Flutter engine expects to be processing a full

library/macos/FLEKeyEventPlugin.h

Lines changed: 0 additions & 26 deletions
This file was deleted.

library/macos/FLEKeyEventPlugin.m

Lines changed: 0 additions & 61 deletions
This file was deleted.

library/macos/FLEPlugin.h

Lines changed: 15 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,52 +18,38 @@
1818
#import "FLEMethodChannel.h"
1919
#import "FLEMethodCodec.h"
2020

21-
@class FLEViewController;
21+
@protocol FLEPluginRegistrar;
2222

2323
/**
24-
* A plugin is an object that can respond appropriately to Flutter platform messages over a specific
25-
* named system channel. See https://flutter.io/platform-channels/.
24+
* Implemented by the platform side of a Flutter plugin.
2625
*
27-
* Note: This interface will be changing in the future to more closely match the iOS Flutter
28-
* platform message API. It will be a one-time breaking change.
26+
* Defines a set of optional callback methods and a method to set up the plugin
27+
* and register it to be called by other application components.
28+
*
29+
* Currently FLEPlugin has very limited functionality, but is expected to expand over time to
30+
* more closely match the functionality of FlutterPlugin.
2931
*/
3032
@protocol FLEPlugin <NSObject>
3133

3234
/**
33-
* A weak reference to the owning controller. May be used to send messages to the Flutter
34-
* framework.
35+
* Creates an instance of the plugin to register with |registrar| using the desired
36+
* FLEPluginRegistrar methods.
3537
*/
36-
@property(nullable, weak) FLEViewController *controller;
38+
+ (void)registerWithRegistrar:(nonnull id<FLEPluginRegistrar>)registrar;
3739

38-
/**
39-
* The name of the system channel via which this plugin communicates.
40-
*/
41-
@property(nonnull, readonly) NSString *channel;
40+
@optional
4241

4342
/**
44-
* Called when a message is sent from Flutter on this plugin's channel.
45-
* The result callback must be called exactly once, with one of:
43+
* Called when a message is sent from Flutter on a channel that a plugin instance has subscribed
44+
* to via -[FLEPluginRegistrar addMethodCallDelegate:channel:].
45+
*
46+
* The |result| callback must be called exactly once, with one of:
4647
* - FLEMethodNotImplemented, if the method call is unknown.
4748
* - An FLEMethodError, if the method call was understood but there was a
4849
* problem handling it.
4950
* - Any other value (including nil) to indicate success. The value will
5051
* be returned to the Flutter caller, and must be serializable to JSON.
51-
*
52-
* If handling the method involves multiple responses to Flutter, follow-up
53-
* messages can be sent by calling the other direction using
54-
* -[FLEViewController invokeMethod:arguments:onChannel:].
5552
*/
5653
- (void)handleMethodCall:(nonnull FLEMethodCall *)call result:(nonnull FLEMethodResult)result;
5754

58-
@optional
59-
60-
/**
61-
* If implemented, returns the codec to use for method calls to this plugin.
62-
*
63-
* If not implemented, the codec is assumed to be FLEJSONMethodCodec. Note that this is different
64-
* from existing Flutter platforms, which default to the standard codec; this is to preserve
65-
* backwards compatibility for FLEPlugin until the breaking change for the platform messages API.
66-
*/
67-
@property(nonnull, readonly) id<FLEMethodCodec> codec;
68-
6955
@end

library/macos/FLEPluginRegistrar.h

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright 2018 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#import <Cocoa/Cocoa.h>
16+
17+
#import "FLEBinaryMessenger.h"
18+
#import "FLEMethodChannel.h"
19+
20+
/**
21+
* The protocol for an object managing registration for a plugin. It provides access to application
22+
* context, as as allowing registering for callbacks for handling various conditions.
23+
*
24+
* Currently FLEPluginRegistrar has very limited functionality, but is expected to expand over time
25+
* to more closely match the functionality of FlutterPluginRegistrar.
26+
*/
27+
@protocol FLEPluginRegistrar <NSObject>
28+
29+
/**
30+
* The binary messenger used for creating channels to communicate with the Flutter engine.
31+
*/
32+
@property(nonnull, readonly) id<FLEBinaryMessenger> messenger;
33+
34+
/**
35+
* The view displaying Flutter content.
36+
*
37+
* WARNING: If/when multiple Flutter views within the same application are supported (#98), this
38+
* API will change.
39+
*/
40+
@property(nullable, readonly) NSView *view;
41+
42+
/**
43+
* Registers |delegate| to receive handleMethodCall:result: callbacks for the given |channel|.
44+
*/
45+
- (void)addMethodCallDelegate:(nonnull id<FLEPlugin>)delegate
46+
channel:(nonnull FLEMethodChannel *)channel;
47+
48+
@end

library/macos/FLETextInputPlugin.h

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,23 @@
1414

1515
#import <Cocoa/Cocoa.h>
1616

17-
#import "FLEPlugin.h"
17+
#import "FLEBinaryMessenger.h"
18+
#import "FLEViewController.h"
1819

1920
/**
20-
* A FlutterPlugin to handle text input. Owned by the FlutterViewController.
21-
* Responsible for bridging the native macOS text input system with the
22-
* Flutter framework text editing classes, via system channels.
21+
* A plugin to handle text input.
22+
*
23+
* Responsible for bridging the native macOS text input system with the Flutter framework text
24+
* editing classes, via system channels.
25+
*
26+
* This is not an FLEPlugin since it needs access to FLEViewController internals, so needs to be
27+
* managed differently.
2328
*/
24-
@interface FLETextInputPlugin : NSResponder <FLEPlugin>
29+
@interface FLETextInputPlugin : NSResponder
30+
31+
/**
32+
* Initializes a text input plugin that coordinates key event handling with |viewController|.
33+
*/
34+
- (instancetype)initWithViewController:(FLEViewController*)viewController;
2535

2636
@end

library/macos/FLETextInputPlugin.m

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#import <objc/message.h>
1818

19+
#import "FLEJSONMethodCodec.h"
1920
#import "FLETextInputModel.h"
2021
#import "FLEViewController+Internal.h"
2122

@@ -33,7 +34,6 @@
3334
static NSString *const kNewLine = @"TextInputAction.newline";
3435
static NSString *const kDone = @"TextInputAction.done";
3536

36-
3737
/**
3838
* Private properties of FlutterTextInputPlugin.
3939
*/
@@ -42,42 +42,61 @@ @interface FLETextInputPlugin () <NSTextInputClient>
4242
/**
4343
* A text input context, representing a connection to the Cocoa text input system.
4444
*/
45-
@property NSTextInputContext *textInputContext;
45+
@property(nonatomic) NSTextInputContext *textInputContext;
4646

4747
/**
4848
* A dictionary of text input models, one per client connection, keyed
4949
* by the client connection ID.
5050
*/
51-
@property NSMutableDictionary<NSNumber *, FLETextInputModel *> *textInputModels;
51+
@property(nonatomic) NSMutableDictionary<NSNumber *, FLETextInputModel *> *textInputModels;
5252

5353
/**
5454
* The currently active client connection ID.
5555
*/
56-
@property(nullable) NSNumber *activeClientID;
56+
@property(nonatomic, nullable) NSNumber *activeClientID;
5757

5858
/**
5959
* The currently active text input model.
6060
*/
61-
@property(readonly, nullable) FLETextInputModel *activeModel;
61+
@property(nonatomic, readonly, nullable) FLETextInputModel *activeModel;
62+
63+
/**
64+
* The channel used to communicate with Flutter.
65+
*/
66+
@property(nonatomic) FLEMethodChannel *channel;
67+
68+
/**
69+
* The FLEViewController to manage input for.
70+
*/
71+
@property(nonatomic, weak) FLEViewController *flutterViewController;
72+
73+
/**
74+
* Handles a Flutter system message on the text input channel.
75+
*/
76+
- (void)handleMethodCall:(FLEMethodCall *)call result:(FLEMethodResult)result;
6277

6378
@end
6479

6580
@implementation FLETextInputPlugin
6681

67-
@synthesize controller = _controller;
68-
69-
- (instancetype)init {
82+
- (instancetype)initWithViewController:(FLEViewController *)viewController {
7083
self = [super init];
7184
if (self != nil) {
85+
_flutterViewController = viewController;
86+
_channel = [FLEMethodChannel methodChannelWithName:kTextInputChannel
87+
binaryMessenger:viewController
88+
codec:[FLEJSONMethodCodec sharedInstance]];
89+
__weak FLETextInputPlugin *weakSelf = self;
90+
[_channel setMethodCallHandler:^(FLEMethodCall *call, FLEMethodResult result) {
91+
[weakSelf handleMethodCall:call result:result];
92+
}];
7293
_textInputModels = [[NSMutableDictionary alloc] init];
7394
_textInputContext = [[NSTextInputContext alloc] initWithClient:self];
7495
}
7596
return self;
7697
}
7798

78-
- (NSString *)channel {
79-
return kTextInputChannel;
80-
}
99+
#pragma mark - Private
81100

82101
- (FLETextInputModel *)activeModel {
83102
return (_activeClientID == nil) ? nil : _textInputModels[_activeClientID];
@@ -95,10 +114,10 @@ - (void)handleMethodCall:(FLEMethodCall *)call result:(FLEMethodResult)result {
95114
_textInputModels[_activeClientID] = [[FLETextInputModel alloc] init];
96115
}
97116
} else if ([method isEqualToString:kShowMethod]) {
98-
[self.controller addKeyResponder:self];
117+
[self.flutterViewController addKeyResponder:self];
99118
[_textInputContext activate];
100119
} else if ([method isEqualToString:kHideMethod]) {
101-
[self.controller removeKeyResponder:self];
120+
[self.flutterViewController removeKeyResponder:self];
102121
[_textInputContext deactivate];
103122
} else if ([method isEqualToString:kClearClientMethod]) {
104123
_activeClientID = nil;
@@ -120,9 +139,8 @@ - (void)updateEditState {
120139
return;
121140
}
122141

123-
[_controller invokeMethod:kUpdateEditStateResponseMethod
124-
arguments:@[ _activeClientID, _textInputModels[_activeClientID].state ]
125-
onChannel:kTextInputChannel];
142+
[_channel invokeMethod:kUpdateEditStateResponseMethod
143+
arguments:@[ _activeClientID, _textInputModels[_activeClientID].state ]];
126144
}
127145

128146
#pragma mark -
@@ -226,9 +244,7 @@ - (void)insertNewline:(id)sender {
226244
// There is a PR in Flutter to identify if the widget is multiline, and act accordingly
227245
// (https://github.com/flutter/flutter/pull/23015). Once merged, this action should be changed
228246
// to kNewLine.
229-
[_controller invokeMethod:kPerformAction
230-
arguments:@[ _activeClientID, kDone ]
231-
onChannel:kTextInputChannel];
247+
[_channel invokeMethod:kPerformAction arguments:@[ _activeClientID, kDone ]];
232248
}
233249

234250
- (void)setMarkedText:(id)string

library/macos/FLEViewController+Internal.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,4 @@
2727
*/
2828
- (void)removeKeyResponder:(nonnull NSResponder *)responder;
2929

30-
/**
31-
* Sends a platform message to the Flutter engine on the given channel.
32-
* @param message The raw message.
33-
*/
34-
- (void)dispatchMessage:(nonnull NSDictionary *)message onChannel:(nonnull NSString *)channel;
35-
3630
@end

0 commit comments

Comments
 (0)