5#import "flutter/shell/platform/darwin/macos/framework/Source/FlutterChannelKeyResponder.h"
7#include <Carbon/Carbon.h>
8#import <Foundation/Foundation.h>
10#include "flutter/shell/platform/embedder/test_utils/key_codes.g.h"
11#include "flutter/testing/autoreleasepool_test.h"
12#include "flutter/testing/testing.h"
13#include "third_party/googletest/googletest/include/gtest/gtest.h"
20@property(nonatomic, readonly) NSMutableArray<id>*
messages;
24- (void)sendMessage:(
id _Nullable)message;
25- (void)sendMessage:(
id _Nullable)message reply:(
FlutterReply _Nullable)callback;
32 _messages = [[NSMutableArray<id> alloc] init];
37- (void)sendMessage:(
id _Nullable)message {
38 [
self sendMessage:message reply:nil];
41- (void)sendMessage:(
id _Nullable)message reply:(
FlutterReply _Nullable)callback {
42 [_messages addObject:message];
54NSEvent* CreateKeyEvent(NSEventType
type,
55 NSEventModifierFlags modifierFlags,
57 NSString* charactersIgnoringModifiers,
59 unsigned short keyCode) {
60 return [NSEvent keyEventWithType:type
62 modifierFlags:modifierFlags
67 charactersIgnoringModifiers:charactersIgnoringModifiers
76 __block NSMutableArray<NSNumber*>* responses = [[NSMutableArray<NSNumber*> alloc] init];
87 [responder
handleEvent:CreateKeyEvent(NSEventTypeFlagsChanged, 0x100, @"", @"", NO, 60)
89 [responses addObject:@(handled)];
93 ASSERT_EQ([responses
count], 1u);
94 EXPECT_EQ([responses[0] boolValue], YES);
95 [responses removeAllObjects];
99 [responder
handleEvent:CreateKeyEvent(NSEventTypeKeyDown, 0x100, @"a", @"a", NO, 0)
101 [responses addObject:@(handled)];
105 EXPECT_STREQ([[channel.
messages lastObject][
@"keymap"] UTF8String],
"macos");
106 EXPECT_STREQ([[channel.
messages lastObject][
@"type"] UTF8String],
"keydown");
107 EXPECT_EQ([[channel.
messages lastObject][
@"keyCode"] intValue], 0);
108 EXPECT_EQ([[channel.
messages lastObject][
@"modifiers"] intValue], 0x0);
109 EXPECT_STREQ([[channel.
messages lastObject][
@"characters"] UTF8String],
"a");
110 EXPECT_STREQ([[channel.
messages lastObject][
@"charactersIgnoringModifiers"] UTF8String],
"a");
112 ASSERT_EQ([responses
count], 1u);
113 EXPECT_EQ([[responses lastObject] boolValue], YES);
115 [channel.messages removeAllObjects];
116 [responses removeAllObjects];
120 [responder
handleEvent:CreateKeyEvent(NSEventTypeKeyUp, 0x100, @"a", @"a", NO, 0)
122 [responses addObject:@(handled)];
126 EXPECT_STREQ([[channel.
messages lastObject][
@"keymap"] UTF8String],
"macos");
127 EXPECT_STREQ([[channel.
messages lastObject][
@"type"] UTF8String],
"keyup");
128 EXPECT_EQ([[channel.
messages lastObject][
@"keyCode"] intValue], 0);
129 EXPECT_EQ([[channel.
messages lastObject][
@"modifiers"] intValue], 0);
130 EXPECT_STREQ([[channel.
messages lastObject][
@"characters"] UTF8String],
"a");
131 EXPECT_STREQ([[channel.
messages lastObject][
@"charactersIgnoringModifiers"] UTF8String],
"a");
133 ASSERT_EQ([responses
count], 1u);
134 EXPECT_EQ([[responses lastObject] boolValue], NO);
136 [channel.messages removeAllObjects];
137 [responses removeAllObjects];
141 [responder
handleEvent:CreateKeyEvent(NSEventTypeFlagsChanged, 0x20102, @"", @"", NO, 56)
143 [responses addObject:@(handled)];
147 EXPECT_STREQ([[channel.
messages lastObject][
@"keymap"] UTF8String],
"macos");
148 EXPECT_STREQ([[channel.
messages lastObject][
@"type"] UTF8String],
"keydown");
149 EXPECT_EQ([[channel.
messages lastObject][
@"keyCode"] intValue], 56);
150 EXPECT_EQ([[channel.
messages lastObject][
@"modifiers"] intValue], 0x20002);
152 ASSERT_EQ([responses
count], 1u);
153 EXPECT_EQ([[responses lastObject] boolValue], YES);
155 [channel.messages removeAllObjects];
156 [responses removeAllObjects];
160 [responder
handleEvent:CreateKeyEvent(NSEventTypeFlagsChanged, 0x20006, @"", @"", NO, 60)
162 [responses addObject:@(handled)];
166 EXPECT_STREQ([[channel.
messages lastObject][
@"keymap"] UTF8String],
"macos");
167 EXPECT_STREQ([[channel.
messages lastObject][
@"type"] UTF8String],
"keydown");
168 EXPECT_EQ([[channel.
messages lastObject][
@"keyCode"] intValue], 60);
169 EXPECT_EQ([[channel.
messages lastObject][
@"modifiers"] intValue], 0x20006);
171 ASSERT_EQ([responses
count], 1u);
172 EXPECT_EQ([[responses lastObject] boolValue], NO);
174 [channel.messages removeAllObjects];
175 [responses removeAllObjects];
179 [responder
handleEvent:CreateKeyEvent(NSEventTypeFlagsChanged, 0x20104, @"", @"", NO, 56)
181 [responses addObject:@(handled)];
185 EXPECT_STREQ([[channel.
messages lastObject][
@"keymap"] UTF8String],
"macos");
186 EXPECT_STREQ([[channel.
messages lastObject][
@"type"] UTF8String],
"keyup");
187 EXPECT_EQ([[channel.
messages lastObject][
@"keyCode"] intValue], 56);
188 EXPECT_EQ([[channel.
messages lastObject][
@"modifiers"] intValue], 0x20004);
190 ASSERT_EQ([responses
count], 1u);
191 EXPECT_EQ([[responses lastObject] boolValue], NO);
193 [channel.messages removeAllObjects];
194 [responses removeAllObjects];
198 [responder
handleEvent:CreateKeyEvent(NSEventTypeFlagsChanged, 0, @"", @"", NO, 60)
200 [responses addObject:@(handled)];
204 EXPECT_STREQ([[channel.
messages lastObject][
@"keymap"] UTF8String],
"macos");
205 EXPECT_STREQ([[channel.
messages lastObject][
@"type"] UTF8String],
"keyup");
206 EXPECT_EQ([[channel.
messages lastObject][
@"keyCode"] intValue], 60);
207 EXPECT_EQ([[channel.
messages lastObject][
@"modifiers"] intValue], 0);
209 ASSERT_EQ([responses
count], 1u);
210 EXPECT_EQ([[responses lastObject] boolValue], NO);
212 [channel.messages removeAllObjects];
213 [responses removeAllObjects];
218 [responder
handleEvent:CreateKeyEvent(NSEventTypeFlagsChanged, 0x100, @"", @"", NO, 60)
220 [responses addObject:@(handled)];
224 ASSERT_EQ([responses
count], 1u);
225 EXPECT_EQ([responses[0] boolValue], YES);
229 __block NSMutableArray<NSNumber*>* responses = [[NSMutableArray<NSNumber*> alloc] init];
235 [responder
handleEvent:CreateKeyEvent(NSEventTypeKeyDown, 0x100, @"a", @"a", NO, 0)
237 [responses addObject:@(handled)];
241 EXPECT_STREQ([[channel.
messages lastObject][
@"keymap"] UTF8String],
"macos");
242 EXPECT_STREQ([[channel.
messages lastObject][
@"type"] UTF8String],
"keydown");
243 EXPECT_EQ([[channel.
messages lastObject][
@"keyCode"] intValue], 0);
244 EXPECT_EQ([[channel.
messages lastObject][
@"modifiers"] intValue], 0);
245 EXPECT_STREQ([[channel.
messages lastObject][
@"characters"] UTF8String],
"a");
246 EXPECT_STREQ([[channel.
messages lastObject][
@"charactersIgnoringModifiers"] UTF8String],
"a");
248 ASSERT_EQ([responses
count], 1u);
249 EXPECT_EQ([[responses lastObject] boolValue], YES);
253 __block NSMutableArray<NSNumber*>* responses = [[NSMutableArray<NSNumber*> alloc] init];
258 NSMutableDictionary<NSNumber*, NSNumber*>* layoutMap =
259 [NSMutableDictionary<NSNumber*, NSNumber*> dictionary];
265 [responder
handleEvent:CreateKeyEvent(NSEventTypeKeyDown, kVK_ANSI_A, @"q", @"q", NO, 0)
267 [responses addObject:@(handled)];
271 EXPECT_STREQ([[channel.
messages lastObject][
@"keymap"] UTF8String],
"macos");
272 EXPECT_STREQ([[channel.
messages lastObject][
@"type"] UTF8String],
"keydown");
273 EXPECT_EQ([[channel.
messages lastObject][
@"keyCode"] intValue], 0);
274 EXPECT_EQ([[channel.
messages lastObject][
@"modifiers"] intValue], 0x0);
275 EXPECT_STREQ([[channel.
messages lastObject][
@"characters"] UTF8String],
"q");
276 EXPECT_STREQ([[channel.
messages lastObject][
@"charactersIgnoringModifiers"] UTF8String],
"q");
279 ASSERT_EQ([responses
count], 1u);
280 EXPECT_EQ([[responses lastObject] boolValue], YES);
282 [channel.messages removeAllObjects];
283 [responses removeAllObjects];
NS_ASSUME_NONNULL_BEGIN typedef void(^ FlutterReply)(id _Nullable reply)
FlKeyEvent uint64_t FlKeyResponderAsyncCallback callback
NSMutableArray< id > * messages
NSDictionary * nextResponse
void handleEvent:callback:(NSEvent *event, [callback] FlutterAsyncKeyCallback callback)
constexpr uint64_t kLogicalKeyQ
TEST_F(FlutterChannelKeyResponderTest, FollowsLayoutMap)
NSMutableDictionary< NSNumber *, NSNumber * > * layoutMap