Skip to content

Commit

Permalink
Add explicit Tab support to keyboarding (#723)
Browse files Browse the repository at this point in the history
* Update RCTCxxBridge.mm

* Update RCTCxxBridge.mm

* add explicit tab support

* missing tab validity check
  • Loading branch information
HeyImChris authored Feb 26, 2021
1 parent 068ed05 commit 39fdd68
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class KeyEventExample extends React.Component<{}, State> {
<View
acceptsKeyboardFocus={true}
enableFocusRing={true}
validKeysDown={['g', 'Escape', 'Enter', 'ArrowLeft']}
validKeysDown={['g', 'Tab', 'Esc', 'Enter', 'ArrowLeft']}
onKeyDown={this.onKeyDownEvent}
validKeysUp={['c', 'd']}
onKeyUp={this.onKeyUpEvent}>
Expand Down
25 changes: 18 additions & 7 deletions React/Views/RCTView.m
Original file line number Diff line number Diff line change
Expand Up @@ -1621,6 +1621,7 @@ - (RCTViewKeyboardEvent*)keyboardEvent:(NSEvent*)event downPress:(BOOL)downPress
BOOL rightArrowKey = NO;
BOOL upArrowKey = NO;
BOOL downArrowKey = NO;
BOOL tabKeyPressed = NO;
BOOL escapeKeyPressed = NO;
NSString *key = event.charactersIgnoringModifiers;
unichar const code = [key characterAtIndex:0];
Expand All @@ -1636,9 +1637,16 @@ - (RCTViewKeyboardEvent*)keyboardEvent:(NSEvent*)event downPress:(BOOL)downPress
downArrowKey = YES;
}

// detect Escape key presses via the key code
if (event.keyCode == 53) {
escapeKeyPressed = YES;
// detect special key presses via the key code
switch (event.keyCode) {
case 48: // Tab
tabKeyPressed = YES;
break;
case 53: // Escape
escapeKeyPressed = YES;
break;
default:
break;
}

// detect modifier flags
Expand All @@ -1663,7 +1671,7 @@ - (RCTViewKeyboardEvent*)keyboardEvent:(NSEvent*)event downPress:(BOOL)downPress
RCTViewKeyboardEvent *keyboardEvent = nil;
// only post events for keys we care about
if (downPress) {
NSString *keyToReturn = [self keyIsValid:key left:leftArrowKey right:rightArrowKey up:upArrowKey down:downArrowKey escapeKey:escapeKeyPressed validKeys:[self validKeysDown]];
NSString *keyToReturn = [self keyIsValid:key left:leftArrowKey right:rightArrowKey up:upArrowKey down:downArrowKey tabKey:tabKeyPressed escapeKey:escapeKeyPressed validKeys:[self validKeysDown]];
if (keyToReturn != nil) {
keyboardEvent = [RCTViewKeyboardEvent keyDownEventWithReactTag:self.reactTag
capsLockKey:capsLockKey
Expand All @@ -1681,7 +1689,7 @@ - (RCTViewKeyboardEvent*)keyboardEvent:(NSEvent*)event downPress:(BOOL)downPress
key:keyToReturn];
}
} else {
NSString *keyToReturn = [self keyIsValid:key left:leftArrowKey right:rightArrowKey up:upArrowKey down:downArrowKey escapeKey:escapeKeyPressed validKeys:[self validKeysUp]];
NSString *keyToReturn = [self keyIsValid:key left:leftArrowKey right:rightArrowKey up:upArrowKey down:downArrowKey tabKey:tabKeyPressed escapeKey:escapeKeyPressed validKeys:[self validKeysUp]];
if (keyToReturn != nil) {
keyboardEvent = [RCTViewKeyboardEvent keyUpEventWithReactTag:self.reactTag
capsLockKey:capsLockKey
Expand All @@ -1704,18 +1712,21 @@ - (RCTViewKeyboardEvent*)keyboardEvent:(NSEvent*)event downPress:(BOOL)downPress

// check if the user typed key matches a key we need to send an event for
// translate key codes over to JS compatible keys
- (NSString*)keyIsValid:(NSString*)key left:(BOOL)leftArrowPressed right:(BOOL)rightArrowPressed up:(BOOL)upArrowPressed down:(BOOL)downArrowPressed escapeKey:(BOOL)escapeKeyPressed validKeys:(NSArray<NSString*>*)validKeys {
- (NSString*)keyIsValid:(NSString*)key left:(BOOL)leftArrowPressed right:(BOOL)rightArrowPressed up:(BOOL)upArrowPressed down:(BOOL)downArrowPressed tabKey:(BOOL)tabKeyPressed escapeKey:(BOOL)escapeKeyPressed validKeys:(NSArray<NSString*>*)validKeys {
NSString *keyToReturn = key;

// Allow the flexibility of defining special keys in multiple ways
BOOL enterKeyValidityCheck = [key isEqualToString:@"\r"] && ([validKeys containsObject:@"Enter"] || [validKeys containsObject:@"\r"]);
BOOL tabKeyValidityCheck = tabKeyPressed && ([validKeys containsObject:@"Tab"]); // tab has to be checked via a key code so we can't just use the key itself here
BOOL escapeKeyValidityCheck = escapeKeyPressed && ([validKeys containsObject:@"Esc"] || [validKeys containsObject:@"Escape"]); // escape has to be checked via a key code so we can't just use the key itself here
BOOL leftArrowValidityCheck = [validKeys containsObject:leftArrowPressKey] && leftArrowPressed;
BOOL rightArrowValidityCheck = [validKeys containsObject:rightArrowPressKey] && rightArrowPressed;
BOOL upArrowValidityCheck = [validKeys containsObject:upArrowPressKey] && upArrowPressed;
BOOL downArrowValidityCheck = [validKeys containsObject:downArrowPressKey] && downArrowPressed;

if (escapeKeyValidityCheck) {
if (tabKeyValidityCheck) {
keyToReturn = @"Tab";
} else if (escapeKeyValidityCheck) {
keyToReturn = @"Escape";
} else if (enterKeyValidityCheck) {
keyToReturn = @"Enter";
Expand Down

0 comments on commit 39fdd68

Please sign in to comment.