Enhance physical keyboard support on iOS 13.4

Fixes #394
This commit is contained in:
Cameron Gutman
2020-03-25 18:24:04 -07:00
parent 69d1ff15a1
commit 75ab28a2c3
4 changed files with 257 additions and 7 deletions

View File

@@ -6,20 +6,20 @@ git:
matrix:
include:
- os: osx
osx_image: xcode11
osx_image: xcode11.4
env:
- SCHEME="Moonlight"
- TARGET="platform=iOS Simulator,OS=13.0,name=iPhone 11 Pro"
- TARGET="platform=iOS Simulator,OS=13.4,name=iPhone 11 Pro"
- os: osx
osx_image: xcode11
osx_image: xcode11.4
env:
- SCHEME="Moonlight"
- TARGET="platform=iOS Simulator,OS=13.0,name=iPad Pro (9.7-inch)"
- TARGET="platform=iOS Simulator,OS=13.4,name=iPad Pro (9.7-inch)"
- os: osx
osx_image: xcode11
osx_image: xcode11.4
env:
- SCHEME="Moonlight TV"
- TARGET="platform=tvOS Simulator,OS=13.0,name=Apple TV 4K"
- TARGET="platform=tvOS Simulator,OS=13.4,name=Apple TV 4K"
script:
- set -o pipefail && xcodebuild -project Moonlight.xcodeproj -scheme "$SCHEME" -destination "$TARGET" build | xcpretty

View File

@@ -16,6 +16,7 @@ struct KeyEvent {
u_char modifier;
};
+ (BOOL)sendKeyEvent:(UIKey*)key down:(BOOL)down API_AVAILABLE(ios(13.4));
+ (struct KeyEvent) translateKeyEvent:(unichar) inputChar withModifierFlags:(UIKeyModifierFlags)modifierFlags;
@end

View File

@@ -11,6 +11,216 @@
@implementation KeyboardSupport
+ (BOOL)sendKeyEvent:(UIKey*)key down:(BOOL)down API_AVAILABLE(ios(13.4)){
char modifierFlags = 0;
short keyCode = 0;
if (key.modifierFlags & UIKeyModifierShift) {
modifierFlags |= MODIFIER_SHIFT;
}
if (key.modifierFlags & UIKeyModifierAlternate) {
modifierFlags |= MODIFIER_ALT;
}
if (key.modifierFlags & UIKeyModifierControl) {
modifierFlags |= MODIFIER_CTRL;
}
// This converts UIKeyboardHIDUsage values to Win32 VK_* values
// https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
if (key.keyCode >= UIKeyboardHIDUsageKeyboardA &&
key.keyCode <= UIKeyboardHIDUsageKeyboardZ) {
keyCode = (key.keyCode - UIKeyboardHIDUsageKeyboardA) + 0x41;
}
else if (key.keyCode == UIKeyboardHIDUsageKeyboard0) {
// This key is at the beginning of the VK_ range but the end
// of the UIKeyboardHIDUsageKeyboard range.
keyCode = 0x30;
}
else if (key.keyCode >= UIKeyboardHIDUsageKeyboard1 &&
key.keyCode <= UIKeyboardHIDUsageKeyboard9) {
keyCode = (key.keyCode - UIKeyboardHIDUsageKeyboard1) + 0x31;
}
else if (key.keyCode == UIKeyboardHIDUsageKeypad0) {
// This key is at the beginning of the VK_ range but the end
// of the UIKeyboardHIDUsageKeypad range.
keyCode = 0x60;
}
else if (key.keyCode >= UIKeyboardHIDUsageKeypad1 &&
key.keyCode <= UIKeyboardHIDUsageKeypad9) {
keyCode = (key.keyCode - UIKeyboardHIDUsageKeypad1) + 0x61;
}
else if (key.keyCode >= UIKeyboardHIDUsageKeyboardF1 &&
key.keyCode <= UIKeyboardHIDUsageKeyboardF12) {
keyCode = (key.keyCode - UIKeyboardHIDUsageKeyboardF1) + 0x70;
}
else if (key.keyCode >= UIKeyboardHIDUsageKeyboardF13 &&
key.keyCode <= UIKeyboardHIDUsageKeyboardF24) {
keyCode = (key.keyCode - UIKeyboardHIDUsageKeyboardF13) + 0x7C;
}
else {
switch (key.keyCode) {
case UIKeyboardHIDUsageKeyboardReturnOrEnter:
keyCode = 0x0D;
break;
case UIKeyboardHIDUsageKeyboardEscape:
keyCode = 0x1B;
break;
case UIKeyboardHIDUsageKeyboardDeleteOrBackspace:
keyCode = 0x08;
break;
case UIKeyboardHIDUsageKeyboardTab:
keyCode = 0x09;
break;
case UIKeyboardHIDUsageKeyboardSpacebar:
keyCode = 0x20;
break;
case UIKeyboardHIDUsageKeyboardHyphen:
keyCode = 0xBD;
break;
case UIKeyboardHIDUsageKeyboardEqualSign:
keyCode = 0xBB;
break;
case UIKeyboardHIDUsageKeyboardOpenBracket:
keyCode = 0xDB;
break;
case UIKeyboardHIDUsageKeyboardCloseBracket:
keyCode = 0xDD;
break;
case UIKeyboardHIDUsageKeyboardBackslash:
keyCode = 0xDC;
break;
case UIKeyboardHIDUsageKeyboardSemicolon:
keyCode = 0xBA;
break;
case UIKeyboardHIDUsageKeyboardQuote:
keyCode = 0xDE;
break;
case UIKeyboardHIDUsageKeyboardGraveAccentAndTilde:
keyCode = 0xC0;
break;
case UIKeyboardHIDUsageKeyboardComma:
keyCode = 0xBC;
break;
case UIKeyboardHIDUsageKeyboardPeriod:
keyCode = 0xBE;
break;
case UIKeyboardHIDUsageKeyboardSlash:
keyCode = 0xBF;
break;
case UIKeyboardHIDUsageKeyboardCapsLock:
keyCode = 0x14;
break;
case UIKeyboardHIDUsageKeyboardPrintScreen:
keyCode = 0x2A;
break;
case UIKeyboardHIDUsageKeyboardScrollLock:
keyCode = 0x91;
break;
case UIKeyboardHIDUsageKeyboardPause:
keyCode = 0x13;
break;
case UIKeyboardHIDUsageKeyboardInsert:
keyCode = 0x2D;
break;
case UIKeyboardHIDUsageKeyboardHome:
keyCode = 0x24;
break;
case UIKeyboardHIDUsageKeyboardPageUp:
keyCode = 0x21;
break;
case UIKeyboardHIDUsageKeyboardDeleteForward:
keyCode = 0x2E;
break;
case UIKeyboardHIDUsageKeyboardEnd:
keyCode = 0x23;
break;
case UIKeyboardHIDUsageKeyboardPageDown:
keyCode = 0x22;
break;
case UIKeyboardHIDUsageKeyboardRightArrow:
keyCode = 0x27;
break;
case UIKeyboardHIDUsageKeyboardLeftArrow:
keyCode = 0x25;
break;
case UIKeyboardHIDUsageKeyboardDownArrow:
keyCode = 0x28;
break;
case UIKeyboardHIDUsageKeyboardUpArrow:
keyCode = 0x26;
break;
case UIKeyboardHIDUsageKeypadNumLock:
keyCode = 0x90;
break;
case UIKeyboardHIDUsageKeypadSlash:
keyCode = 0x6F;
break;
case UIKeyboardHIDUsageKeypadAsterisk:
keyCode = 0x6A;
break;
case UIKeyboardHIDUsageKeypadHyphen:
keyCode = 0x6D;
break;
case UIKeyboardHIDUsageKeypadPlus:
keyCode = 0x6B;
break;
case UIKeyboardHIDUsageKeypadEnter:
keyCode = 0x0D; // FIXME: Is this correct?
break;
case UIKeyboardHIDUsageKeypadPeriod:
keyCode = 0x6E;
break;
case UIKeyboardHIDUsageKeyboardNonUSBackslash:
keyCode = 0xE2;
break;
case UIKeyboardHIDUsageKeypadComma:
keyCode = 0x6C;
break;
case UIKeyboardHIDUsageKeyboardCancel:
keyCode = 0x03;
break;
case UIKeyboardHIDUsageKeyboardClear:
keyCode = 0x0C;
break;
case UIKeyboardHIDUsageKeyboardCrSelOrProps:
keyCode = 0xF7;
break;
case UIKeyboardHIDUsageKeyboardExSel:
keyCode = 0xF8;
break;
case UIKeyboardHIDUsageKeyboardLeftGUI:
case UIKeyboardHIDUsageKeyboardLeftControl:
keyCode = 0xA2;
break;
case UIKeyboardHIDUsageKeyboardLeftShift:
keyCode = 0xA0;
break;
case UIKeyboardHIDUsageKeyboardLeftAlt:
keyCode = 0xA4;
break;
case UIKeyboardHIDUsageKeyboardRightGUI:
case UIKeyboardHIDUsageKeyboardRightControl:
keyCode = 0xA3;
break;
case UIKeyboardHIDUsageKeyboardRightShift:
keyCode = 0xA1;
break;
case UIKeyboardHIDUsageKeyboardRightAlt:
keyCode = 0xA5;
break;
default:
NSLog(@"Unhandled HID usage: %lu", (unsigned long)key.keyCode);
assert(0);
return false;
}
}
LiSendKeyboardEvent(keyCode,
down ? KEY_ACTION_DOWN : KEY_ACTION_UP,
modifierFlags);
return true;
}
+ (struct KeyEvent)translateKeyEvent:(unichar)inputChar withModifierFlags:(UIKeyModifierFlags)modifierFlags {
struct KeyEvent event;
event.keycode = 0;
@@ -22,13 +232,13 @@
case UIKeyModifierShift:
[KeyboardSupport addShiftModifier:&event];
break;
case UIKeyModifierCommand:
case UIKeyModifierControl:
[KeyboardSupport addControlModifier:&event];
break;
case UIKeyModifierAlternate:
[KeyboardSupport addAltModifier:&event];
break;
case UIKeyModifierCommand:
case UIKeyModifierNumericPad:
break;
}

View File

@@ -10,6 +10,7 @@
#include <Limelight.h>
#import "DataManager.h"
#import "ControllerSupport.h"
#import "KeyboardSupport.h"
#import "TextFieldKeyboardDelegate.h"
@implementation StreamView {
@@ -211,6 +212,44 @@
}
- (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event {
BOOL handled = NO;
if (@available(iOS 13.4, tvOS 13.4, *)) {
for (UIPress* press in presses) {
// For now, we'll treated it as handled if we handle at least one of the
// UIPress events inside the set.
if (press.key != nil && [KeyboardSupport sendKeyEvent:press.key down:YES]) {
// This will prevent the legacy UITextField from receiving the event
handled = YES;
}
}
}
if (!handled) {
[super pressesBegan:presses withEvent:event];
}
}
- (void)pressesEnded:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event {
BOOL handled = NO;
if (@available(iOS 13.4, tvOS 13.4, *)) {
for (UIPress* press in presses) {
// For now, we'll treated it as handled if we handle at least one of the
// UIPress events inside the set.
if (press.key != nil && [KeyboardSupport sendKeyEvent:press.key down:NO]) {
// This will prevent the legacy UITextField from receiving the event
handled = YES;
}
}
}
if (!handled) {
[super pressesEnded:presses withEvent:event];
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
Log(LOG_D, @"Touch up");