Flutter Engine
The Flutter Engine
FlutterMouseCursorPlugin.mm
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#import <objc/message.h>
6
8#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterCodecs.h"
9
10static NSString* const kMouseCursorChannel = @"flutter/mousecursor";
11
12static NSString* const kActivateSystemCursorMethod = @"activateSystemCursor";
13static NSString* const kKindKey = @"kind";
14
15static NSString* const kKindValueNone = @"none";
16
17static NSDictionary* systemCursors;
18
19/**
20 * Maps a Flutter's constant to a platform's cursor object.
21 *
22 * Returns the arrow cursor for unknown constants, including kSystemShapeNone.
23 */
24static NSCursor* GetCursorForKind(NSString* kind) {
25 // The following mapping must be kept in sync with Flutter framework's
26 // mouse_cursor.dart
27
28 if ([kind isEqualToString:kKindValueNone]) {
29 NSImage* image = [[NSImage alloc] initWithSize:NSMakeSize(1, 1)];
30 return [[NSCursor alloc] initWithImage:image hotSpot:NSMakePoint(0, 0)];
31 }
32
33 if (systemCursors == nil) {
34 systemCursors = @{
35 @"alias" : [NSCursor dragLinkCursor],
36 @"basic" : [NSCursor arrowCursor],
37 @"click" : [NSCursor pointingHandCursor],
38 @"contextMenu" : [NSCursor contextualMenuCursor],
39 @"copy" : [NSCursor dragCopyCursor],
40 @"disappearing" : [NSCursor disappearingItemCursor],
41 @"forbidden" : [NSCursor operationNotAllowedCursor],
42 @"grab" : [NSCursor openHandCursor],
43 @"grabbing" : [NSCursor closedHandCursor],
44 @"noDrop" : [NSCursor operationNotAllowedCursor],
45 @"precise" : [NSCursor crosshairCursor],
46 @"text" : [NSCursor IBeamCursor],
47 @"resizeColumn" : [NSCursor resizeLeftRightCursor],
48 @"resizeDown" : [NSCursor resizeDownCursor],
49 @"resizeLeft" : [NSCursor resizeLeftCursor],
50 @"resizeLeftRight" : [NSCursor resizeLeftRightCursor],
51 @"resizeRight" : [NSCursor resizeRightCursor],
52 @"resizeRow" : [NSCursor resizeUpDownCursor],
53 @"resizeUp" : [NSCursor resizeUpCursor],
54 @"resizeUpDown" : [NSCursor resizeUpDownCursor],
55 @"verticalText" : [NSCursor IBeamCursorForVerticalLayout],
56 };
57 }
58 NSCursor* result = [systemCursors objectForKey:kind];
59 if (result == nil) {
60 return [NSCursor arrowCursor];
61 }
62 return result;
63}
64
65@interface FlutterMouseCursorPlugin ()
66
67@property(nonatomic, weak) id<FlutterMouseCursorPluginDelegate> delegate;
68
69/**
70 * Handles the method call that activates a system cursor.
71 *
72 * Returns a FlutterError if the arguments can not be recognized. Otherwise
73 * returns nil.
74 */
75- (FlutterError*)activateSystemCursor:(nonnull NSDictionary*)arguments;
76
77/**
78 * Displays the specified cursor.
79 *
80 * Unhides the cursor before displaying the cursor, and updates
81 * internal states.
82 */
83- (void)displayCursorObject:(nonnull NSCursor*)cursorObject;
84
85/**
86 * Handles all method calls from Flutter.
87 */
88- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result;
89
90@end
91
92@implementation FlutterMouseCursorPlugin
93
94#pragma mark - Private
95
96NSMutableDictionary* cachedSystemCursors;
97
98- (instancetype)init {
99 self = [super init];
100 if (self) {
101 cachedSystemCursors = [NSMutableDictionary dictionary];
102 }
103 return self;
104}
105
106- (FlutterError*)activateSystemCursor:(nonnull NSDictionary*)arguments {
107 NSString* kindArg = arguments[kKindKey];
108 if (!kindArg) {
109 return [FlutterError errorWithCode:@"error"
110 message:@"Missing argument"
111 details:@"Missing argument while trying to activate system cursor"];
112 }
113
114 NSCursor* cursorObject = [FlutterMouseCursorPlugin cursorFromKind:kindArg];
115 [self displayCursorObject:cursorObject];
116 return nil;
117}
118
119- (void)displayCursorObject:(nonnull NSCursor*)cursorObject {
120 [cursorObject set];
121 [self.delegate didUpdateMouseCursor:cursorObject];
122}
123
124+ (NSCursor*)cursorFromKind:(NSString*)kind {
125 NSCursor* cachedValue = [cachedSystemCursors objectForKey:kind];
126 if (!cachedValue) {
127 cachedValue = GetCursorForKind(kind);
128 [cachedSystemCursors setValue:cachedValue forKey:kind];
129 }
130 return cachedValue;
131}
132
133#pragma mark - FlutterPlugin implementation
134
135+ (void)registerWithRegistrar:(id<FlutterPluginRegistrar>)registrar {
136 [self registerWithRegistrar:registrar delegate:nil];
137}
138
139+ (void)registerWithRegistrar:(id<FlutterPluginRegistrar>)registrar
140 delegate:(id<FlutterMouseCursorPluginDelegate>)delegate {
142 binaryMessenger:registrar.messenger];
144 instance.delegate = delegate;
145 [registrar addMethodCallDelegate:instance channel:channel];
146}
147
148- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
149 NSString* method = call.method;
150 if ([method isEqualToString:kActivateSystemCursorMethod]) {
151 result([self activateSystemCursor:call.arguments]);
152 } else {
154 }
155}
156
157@end
void(^ FlutterResult)(id _Nullable result)
FLUTTER_DARWIN_EXPORT NSObject const * FlutterMethodNotImplemented
static NSString *const kActivateSystemCursorMethod
static NSString *const kMouseCursorChannel
NSMutableDictionary * cachedSystemCursors
static NSString *const kKindValueNone
static NSDictionary * systemCursors
static NSCursor * GetCursorForKind(NSString *kind)
static NSString *const kKindKey
VkInstance instance
Definition: main.cc:48
GAsyncResult * result
instancetype errorWithCode:message:details:(NSString *code,[message] NSString *_Nullable message,[details] id _Nullable details)
instancetype methodChannelWithName:binaryMessenger:(NSString *name,[binaryMessenger] NSObject< FlutterBinaryMessenger > *messenger)
NSCursor * cursorFromKind:(NSString *kind)
id< FlutterMouseCursorPluginDelegate > delegate
static bool init()
sk_sp< const SkImage > image
Definition: SkRecords.h:269
def call(args)
Definition: dom.py:159
void addMethodCallDelegate:channel:(NSObject< FlutterPlugin > *delegate,[channel] FlutterMethodChannel *channel)