1
- /* *
2
- * Copyright (c) 2015-present, Facebook, Inc.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- */
7
-
8
1
#import " RCTKeyCommands.h"
9
-
10
- #import < AppKit/AppKit.h>
11
-
12
2
#import " RCTDefines.h"
13
3
#import " RCTUtils.h"
14
4
15
- @interface RCTKeyCommand : NSObject <NSCopying >
16
-
17
- @property (nonatomic , strong ) NSString *keyCommand;
18
- @property (nonatomic ) NSEventModifierFlags modifierFlags;
19
- @property (nonatomic , copy ) void (^block)(NSEvent *);
20
-
21
- @end
22
-
23
5
@implementation RCTKeyCommand
6
+ {
7
+ BOOL _preventDefault;
8
+ }
24
9
25
- - (instancetype )initWithKeyCommand : (NSString *)keyCommand
26
- modifierFlags : (NSEventModifierFlags )modifierFlags
27
- block : (void (^)(NSEvent *))block
10
+ - (instancetype )initWithEvent : (NSEvent *)event
28
11
{
29
12
if ((self = [super init ])) {
30
- _keyCommand = keyCommand;
31
- _modifierFlags = modifierFlags;
32
- _block = block;
13
+ _event = event;
33
14
}
34
15
return self;
35
16
}
36
17
37
18
RCT_NOT_IMPLEMENTED (- (instancetype )init)
38
19
39
- - (id )copyWithZone:(__unused NSZone *)zone
20
+ - (NSString *)input
40
21
{
41
- return self ;
22
+ return _event. characters ;
42
23
}
43
24
44
- - (NSUInteger ) hash
25
+ - (unsigned short ) keyCode
45
26
{
46
- return _keyCommand. hash ^ _modifierFlags ;
27
+ return _event. keyCode ;
47
28
}
48
29
49
- - (BOOL )isEqual : (RCTKeyCommand *) object
30
+ - (BOOL )isDown
50
31
{
51
- if (![object isKindOfClass: [RCTKeyCommand class ]]) {
52
- return NO ;
53
- }
54
- return [self matchesInput: object.keyCommand
55
- flags: object.modifierFlags];
32
+ return _event.type == NSEventTypeKeyDown;
56
33
}
57
34
58
- - (BOOL ) matchesInput : ( NSString *) keyCommand flags : ( int )flags
35
+ - (NSEventModifierFlags )flags
59
36
{
60
- return [_keyCommand isEqual: keyCommand] && _modifierFlags == flags ;
37
+ return _event. modifierFlags & NSEventModifierFlagDeviceIndependentFlagsMask ;
61
38
}
62
39
63
- - (NSString *)description
40
+ - (NSWindow *)window
64
41
{
65
- return [NSString stringWithFormat: @" <%@ :%p input=\" %@ \" flags=%zd hasBlock=%@ >" ,
66
- [self class ], self , _keyCommand, _modifierFlags,
67
- _block ? @" YES" : @" NO" ];
42
+ return _event.window ;
68
43
}
69
44
70
- @end
71
-
72
- @interface RCTKeyCommands ()
45
+ - (NSString *)description
46
+ {
47
+ return [NSString stringWithFormat: @" <%@ :%p input=\" %@ \" flags=%zd isDown=%@ >" ,
48
+ [self class ], self , self .input, self .flags, self .isDown ? @" YES" : @" NO" ];
49
+ }
73
50
74
- @property (nonatomic , strong ) NSMutableSet <RCTKeyCommand *> *commands;
51
+ - (BOOL )matchesInput : (NSString *)input
52
+ {
53
+ return [self matchesInput: input flags: 0 ];
54
+ }
75
55
76
- @end
56
+ - (BOOL )matchesInput : (NSString *)input flags : (NSEventModifierFlags )flags
57
+ {
58
+ return [self .input isEqualToString: input] && self.flags == flags;
59
+ }
77
60
61
+ - (BOOL )matchesKeyCode : (RCTKeyCode)keyCode
62
+ {
63
+ return [self matchesKeyCode: keyCode flags: 0 ];
64
+ }
78
65
79
- @implementation NSWindow (RCTKeyCommands)
66
+ - (BOOL )matchesKeyCode : (RCTKeyCode)keyCode flags : (NSEventModifierFlags )flags
67
+ {
68
+ return self.keyCode == keyCode && self.flags == flags;
69
+ }
80
70
81
- - (void )keyDown : ( NSEvent *) theEvent
71
+ - (void )preventDefault
82
72
{
83
- for (RCTKeyCommand *command in [RCTKeyCommands sharedInstance ].commands ) {
84
- if ([command.keyCommand isEqualToString: theEvent.characters] &&
85
- command.modifierFlags == (theEvent.modifierFlags & NSDeviceIndependentModifierFlagsMask )) {
86
- if (command.block ) {
87
- command.block (theEvent);
88
- }
89
- return ;
90
- }
91
- }
73
+ _preventDefault = YES ;
74
+ }
92
75
93
- [super keyDown: theEvent];
76
+ - (BOOL )isDefaultPrevented
77
+ {
78
+ return _preventDefault;
94
79
}
95
80
96
81
@end
97
82
98
83
@implementation RCTKeyCommands
84
+ {
85
+ NSHashTable <id <RCTKeyCommandObserver>> *_observers;
86
+ }
99
87
100
88
+ (instancetype )sharedInstance
101
89
{
@@ -111,46 +99,52 @@ + (instancetype)sharedInstance
111
99
- (instancetype )init
112
100
{
113
101
if ((self = [super init ])) {
114
- _commands = [NSMutableSet new ];
102
+ _observers = [NSHashTable weakObjectsHashTable ];
115
103
}
116
104
return self;
117
105
}
118
106
119
- - (void )registerKeyCommandWithInput : (NSString *)input
120
- modifierFlags : (NSEventModifierFlags )flags
121
- action : (void (^)(NSEvent *))block
107
+ - (void )addObserver : (NSObject <RCTKeyCommandObserver> *)observer
122
108
{
123
109
RCTAssertMainQueue ();
124
-
125
- RCTKeyCommand *keyCommand = [[RCTKeyCommand alloc ] initWithKeyCommand: input modifierFlags: flags block: block];
126
- [_commands removeObject: keyCommand];
127
- [_commands addObject: keyCommand];
110
+ [_observers addObject: observer];
128
111
}
129
112
130
- - (void )unregisterKeyCommandWithInput : (NSString *)input
131
- modifierFlags : (NSEventModifierFlags )flags
113
+ - (void )removeObserver : (NSObject <RCTKeyCommandObserver> *)observer
132
114
{
133
115
RCTAssertMainQueue ();
116
+ [_observers removeObject: observer];
117
+ }
134
118
135
- for (RCTKeyCommand *command in _commands.allObjects ) {
136
- if ([command matchesInput: input flags: flags]) {
137
- [_commands removeObject: command];
138
- break ;
139
- }
119
+ - (BOOL )observeEvent : (NSEvent *)event
120
+ {
121
+ RCTAssertMainQueue ();
122
+ RCTKeyCommand *command = [[RCTKeyCommand alloc ] initWithEvent: event];
123
+ for (id <RCTKeyCommandObserver> observer in _observers) {
124
+ [observer observeKeyCommand: command];
140
125
}
126
+ return command.isDefaultPrevented ;
141
127
}
142
128
143
- - (BOOL )isKeyCommandRegisteredForInput : (NSString *)input
144
- modifierFlags : (NSEventModifierFlags )flags
129
+ @end
130
+
131
+ @implementation NSWindow (RCTKeyCommands)
132
+
133
+ - (void )keyDown : (NSEvent *)event
145
134
{
146
- RCTAssertMainQueue ();
135
+ BOOL isDefaultPrevented = [[RCTKeyCommands sharedInstance ] observeEvent: event];
136
+ if (!isDefaultPrevented) {
137
+ [super keyDown: event];
138
+ }
139
+ }
147
140
148
- for (RCTKeyCommand *command in _commands) {
149
- if ([command matchesInput: input flags: flags]) {
150
- return YES ;
151
- }
141
+ - (void )keyUp : (NSEvent *)event
142
+ {
143
+ BOOL isDefaultPrevented = [[RCTKeyCommands sharedInstance ] observeEvent: event];
144
+ if (!isDefaultPrevented) {
145
+ [super keyUp: event];
152
146
}
153
- return NO ;
154
147
}
155
148
156
149
@end
150
+
0 commit comments