From c2012fa19527fb58adf4ae0a7af2b30ca44ad3ab Mon Sep 17 00:00:00 2001 From: Sergio Alvarez-Napagao Date: Wed, 29 Aug 2018 23:37:12 +0200 Subject: [PATCH] Improve keyboard support --- Limelight/Input/KeyboardSupport.h | 2 +- Limelight/Input/KeyboardSupport.m | 27 +++++++++- Limelight/Input/StreamView.m | 84 +++++++++++++++++++++++++------ 3 files changed, 97 insertions(+), 16 deletions(-) diff --git a/Limelight/Input/KeyboardSupport.h b/Limelight/Input/KeyboardSupport.h index a1569f6..770de8a 100644 --- a/Limelight/Input/KeyboardSupport.h +++ b/Limelight/Input/KeyboardSupport.h @@ -16,6 +16,6 @@ struct KeyEvent { u_char modifier; }; -+ (struct KeyEvent) translateKeyEvent:(unichar) inputChar; ++ (struct KeyEvent) translateKeyEvent:(unichar) inputChar withModifierFlags:(UIKeyModifierFlags)modifierFlags; @end diff --git a/Limelight/Input/KeyboardSupport.m b/Limelight/Input/KeyboardSupport.m index d07f895..642dda9 100644 --- a/Limelight/Input/KeyboardSupport.m +++ b/Limelight/Input/KeyboardSupport.m @@ -11,12 +11,27 @@ @implementation KeyboardSupport -+ (struct KeyEvent)translateKeyEvent:(unichar)inputChar { ++ (struct KeyEvent)translateKeyEvent:(unichar)inputChar withModifierFlags:(UIKeyModifierFlags)modifierFlags { struct KeyEvent event; event.keycode = 0; event.modifier = 0; event.modifierKeycode = 0; + switch (modifierFlags) { + case UIKeyModifierAlphaShift: + case UIKeyModifierShift: + [KeyboardSupport addShiftModifier:&event]; + break; + case UIKeyModifierControl: + [KeyboardSupport addControlModifier:&event]; + break; + case UIKeyModifierAlternate: + [KeyboardSupport addAltModifier:&event]; + break; + case UIKeyModifierCommand: + case UIKeyModifierNumericPad: + break; + } if (inputChar >= 0x30 && inputChar <= 0x39) { // Numbers 0-9 event.keycode = inputChar; @@ -163,4 +178,14 @@ event->modifierKeycode = 0x10; } ++ (void) addControlModifier:(struct KeyEvent*)event { + event->modifier = MODIFIER_CTRL; + event->modifierKeycode = 0x11; +} + ++ (void) addAltModifier:(struct KeyEvent*)event { + event->modifier = MODIFIER_ALT; + event->modifierKeycode = 0x12; +} + @end diff --git a/Limelight/Input/StreamView.m b/Limelight/Input/StreamView.m index cfb1677..80c949b 100644 --- a/Limelight/Input/StreamView.m +++ b/Limelight/Input/StreamView.m @@ -25,6 +25,8 @@ float xDeltaFactor; float yDeltaFactor; float screenFactor; + + NSDictionary *dictCodes; } - (void) setMouseDeltaFactors:(float)x y:(float)y { @@ -46,6 +48,7 @@ Log(LOG_I, @"Setting manual on-screen controls level: %d", (int)level); [onScreenControls setLevel:level]; } + [self becomeFirstResponder]; } - (Boolean)isConfirmedMove:(CGPoint)currentPoint from:(CGPoint)originalPoint { @@ -215,25 +218,13 @@ } else { // Character 0 will be our known sentinel value for (int i = 1; i < [inputText length]; i++) { - struct KeyEvent event = [KeyboardSupport translateKeyEvent:[inputText characterAtIndex:i]]; + struct KeyEvent event = [KeyboardSupport translateKeyEvent:[inputText characterAtIndex:i] withModifierFlags:0]; if (event.keycode == 0) { // If we don't know the code, don't send anything. Log(LOG_W, @"Unknown key code: [%c]", [inputText characterAtIndex:i]); continue; } - - // When we want to send a modified key (like uppercase letters) we need to send the - // modifier ("shift") seperately from the key itself. - if (event.modifier != 0) { - LiSendKeyboardEvent(event.modifierKeycode, KEY_ACTION_DOWN, event.modifier); - usleep(50 * 1000); - } - LiSendKeyboardEvent(event.keycode, KEY_ACTION_DOWN, event.modifier); - usleep(50 * 1000); - LiSendKeyboardEvent(event.keycode, KEY_ACTION_UP, event.modifier); - if (event.modifier != 0) { - LiSendKeyboardEvent(event.modifierKeycode, KEY_ACTION_UP, event.modifier); - } + [self sendLowLevelEvent:event]; } } }); @@ -246,4 +237,69 @@ [textField setSelectedTextRange:textRange]; } +- (void)specialCharPressed:(UIKeyCommand *)cmd { + struct KeyEvent event = [KeyboardSupport translateKeyEvent:0x20 withModifierFlags:[cmd modifierFlags]]; + event.keycode = [[dictCodes valueForKey:[cmd input]] intValue]; + [self sendLowLevelEvent:event]; +} + +- (void)keyPressed:(UIKeyCommand *)cmd { + struct KeyEvent event = [KeyboardSupport translateKeyEvent:[[cmd input] characterAtIndex:0] withModifierFlags:[cmd modifierFlags]]; + [self sendLowLevelEvent:event]; +} + +- (void)sendLowLevelEvent:(struct KeyEvent)event { + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ + // When we want to send a modified key (like uppercase letters) we need to send the + // modifier ("shift") seperately from the key itself. + if (event.modifier != 0) { + LiSendKeyboardEvent(event.modifierKeycode, KEY_ACTION_DOWN, event.modifier); + } + LiSendKeyboardEvent(event.keycode, KEY_ACTION_DOWN, event.modifier); + usleep(50 * 1000); + LiSendKeyboardEvent(event.keycode, KEY_ACTION_UP, event.modifier); + if (event.modifier != 0) { + LiSendKeyboardEvent(event.modifierKeycode, KEY_ACTION_UP, event.modifier); + } + }); +} + +- (BOOL)canBecomeFirstResponder { + return YES; +} + +- (NSArray *)keyCommands +{ + NSString *charset = @"qwertyuiopasdfghjklzxcvbnm1234567890\t§[]\\'\"/.,`<>-´ç+`¡'º;ñ= "; + + NSMutableArray * commands = [NSMutableArray array]; + dictCodes = [[NSDictionary alloc] initWithObjectsAndKeys: [NSNumber numberWithInt: 0x0d], @"\r", [NSNumber numberWithInt: 0x08], @"\b", [NSNumber numberWithInt: 0x1b], UIKeyInputEscape, [NSNumber numberWithInt: 0x28], UIKeyInputDownArrow, [NSNumber numberWithInt: 0x26], UIKeyInputUpArrow, [NSNumber numberWithInt: 0x25], UIKeyInputLeftArrow, [NSNumber numberWithInt: 0x27], UIKeyInputRightArrow, nil]; + + [charset enumerateSubstringsInRange:NSMakeRange(0, charset.length) + options:NSStringEnumerationByComposedCharacterSequences + usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) { + [commands addObject:[UIKeyCommand keyCommandWithInput:substring modifierFlags:0 action:@selector(keyPressed:)]]; + [commands addObject:[UIKeyCommand keyCommandWithInput:substring modifierFlags:UIKeyModifierShift action:@selector(keyPressed:)]]; + [commands addObject:[UIKeyCommand keyCommandWithInput:substring modifierFlags:UIKeyModifierControl action:@selector(keyPressed:)]]; + [commands addObject:[UIKeyCommand keyCommandWithInput:substring modifierFlags:UIKeyModifierAlternate action:@selector(keyPressed:)]]; + }]; + + for (NSString *c in [dictCodes keyEnumerator]) { + [commands addObject:[UIKeyCommand keyCommandWithInput:c + modifierFlags:0 + action:@selector(specialCharPressed:)]]; + [commands addObject:[UIKeyCommand keyCommandWithInput:c + modifierFlags:UIKeyModifierShift + action:@selector(specialCharPressed:)]]; + [commands addObject:[UIKeyCommand keyCommandWithInput:c + modifierFlags:UIKeyModifierControl + action:@selector(specialCharPressed:)]]; + [commands addObject:[UIKeyCommand keyCommandWithInput:c + modifierFlags:UIKeyModifierAlternate + action:@selector(specialCharPressed:)]]; + } + + return commands; +} + @end