mirror of
https://github.com/SoPat712/YTLitePlus.git
synced 2025-12-27 00:37:21 -05:00
added files via upload
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
//
|
||||
// FLEXKeyboardHelpViewController.h
|
||||
// FLEX
|
||||
//
|
||||
// Created by Ryan Olson on 9/19/15.
|
||||
// Copyright © 2015 f. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface FLEXKeyboardHelpViewController : UIViewController
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,42 @@
|
||||
//
|
||||
// FLEXKeyboardHelpViewController.m
|
||||
// FLEX
|
||||
//
|
||||
// Created by Ryan Olson on 9/19/15.
|
||||
// Copyright © 2015 f. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXKeyboardHelpViewController.h"
|
||||
#import "FLEXKeyboardShortcutManager.h"
|
||||
|
||||
@interface FLEXKeyboardHelpViewController ()
|
||||
|
||||
@property (nonatomic) UITextView *textView;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FLEXKeyboardHelpViewController
|
||||
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
|
||||
self.textView = [[UITextView alloc] initWithFrame:self.view.bounds];
|
||||
self.textView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
|
||||
[self.view addSubview:self.textView];
|
||||
#if TARGET_OS_SIMULATOR
|
||||
self.textView.text = FLEXKeyboardShortcutManager.sharedManager.keyboardShortcutsDescription;
|
||||
#endif
|
||||
self.textView.backgroundColor = UIColor.blackColor;
|
||||
self.textView.textColor = UIColor.whiteColor;
|
||||
self.textView.font = [UIFont boldSystemFontOfSize:14.0];
|
||||
self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque;
|
||||
|
||||
self.title = @"Simulator Shortcuts";
|
||||
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(donePressed:)];
|
||||
}
|
||||
|
||||
- (void)donePressed:(id)sender {
|
||||
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
29
Tweaks/FLEX/Utility/Keyboard/FLEXKeyboardShortcutManager.h
Normal file
29
Tweaks/FLEX/Utility/Keyboard/FLEXKeyboardShortcutManager.h
Normal file
@@ -0,0 +1,29 @@
|
||||
//
|
||||
// FLEXKeyboardShortcutManager.h
|
||||
// FLEX
|
||||
//
|
||||
// Created by Ryan Olson on 9/19/15.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface FLEXKeyboardShortcutManager : NSObject
|
||||
|
||||
@property (nonatomic, readonly, class) FLEXKeyboardShortcutManager *sharedManager;
|
||||
|
||||
/// @param key A single character string matching a key on the keyboard
|
||||
/// @param modifiers Modifier keys such as shift, command, or alt/option
|
||||
/// @param action The block to run on the main thread when the key & modifier combination is recognized.
|
||||
/// @param description Shown the the keyboard shortcut help menu, which is accessed via the '?' key.
|
||||
/// @param allowOverride Allow registering even if there's an existing action associated with that key/modifier.
|
||||
- (void)registerSimulatorShortcutWithKey:(NSString *)key
|
||||
modifiers:(UIKeyModifierFlags)modifiers
|
||||
action:(dispatch_block_t)action
|
||||
description:(NSString *)description
|
||||
allowOverride:(BOOL)allowOverride;
|
||||
|
||||
@property (nonatomic, getter=isEnabled) BOOL enabled;
|
||||
@property (nonatomic, readonly) NSString *keyboardShortcutsDescription;
|
||||
|
||||
@end
|
||||
326
Tweaks/FLEX/Utility/Keyboard/FLEXKeyboardShortcutManager.m
Normal file
326
Tweaks/FLEX/Utility/Keyboard/FLEXKeyboardShortcutManager.m
Normal file
@@ -0,0 +1,326 @@
|
||||
//
|
||||
// FLEXKeyboardShortcutManager.m
|
||||
// FLEX
|
||||
//
|
||||
// Created by Ryan Olson on 9/19/15.
|
||||
// Copyright © 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
#import "FLEXKeyboardShortcutManager.h"
|
||||
#import "FLEXUtility.h"
|
||||
#import <objc/runtime.h>
|
||||
#import <objc/message.h>
|
||||
|
||||
#if TARGET_OS_SIMULATOR
|
||||
|
||||
@interface UIEvent (UIPhysicalKeyboardEvent)
|
||||
|
||||
@property (nonatomic) NSString *_modifiedInput;
|
||||
@property (nonatomic) NSString *_unmodifiedInput;
|
||||
@property (nonatomic) UIKeyModifierFlags _modifierFlags;
|
||||
@property (nonatomic) BOOL _isKeyDown;
|
||||
@property (nonatomic) long _keyCode;
|
||||
|
||||
@end
|
||||
|
||||
@interface FLEXKeyInput : NSObject <NSCopying>
|
||||
|
||||
@property (nonatomic, copy, readonly) NSString *key;
|
||||
@property (nonatomic, readonly) UIKeyModifierFlags flags;
|
||||
@property (nonatomic, copy, readonly) NSString *helpDescription;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FLEXKeyInput
|
||||
|
||||
- (BOOL)isEqual:(id)object {
|
||||
BOOL isEqual = NO;
|
||||
if ([object isKindOfClass:[FLEXKeyInput class]]) {
|
||||
FLEXKeyInput *keyCommand = (FLEXKeyInput *)object;
|
||||
BOOL equalKeys = self.key == keyCommand.key || [self.key isEqual:keyCommand.key];
|
||||
BOOL equalFlags = self.flags == keyCommand.flags;
|
||||
isEqual = equalKeys && equalFlags;
|
||||
}
|
||||
return isEqual;
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
return self.key.hash ^ self.flags;
|
||||
}
|
||||
|
||||
- (id)copyWithZone:(NSZone *)zone {
|
||||
return [[self class] keyInputForKey:self.key flags:self.flags helpDescription:self.helpDescription];
|
||||
}
|
||||
|
||||
- (NSString *)description {
|
||||
NSDictionary<NSString *, NSString *> *keyMappings = @{
|
||||
UIKeyInputUpArrow : @"↑",
|
||||
UIKeyInputDownArrow : @"↓",
|
||||
UIKeyInputLeftArrow : @"←",
|
||||
UIKeyInputRightArrow : @"→",
|
||||
UIKeyInputEscape : @"␛",
|
||||
@" " : @"␠"
|
||||
};
|
||||
|
||||
NSString *prettyKey = nil;
|
||||
if (self.key && keyMappings[self.key]) {
|
||||
prettyKey = keyMappings[self.key];
|
||||
} else {
|
||||
prettyKey = [self.key uppercaseString];
|
||||
}
|
||||
|
||||
NSString *prettyFlags = @"";
|
||||
if (self.flags & UIKeyModifierControl) {
|
||||
prettyFlags = [prettyFlags stringByAppendingString:@"⌃"];
|
||||
}
|
||||
if (self.flags & UIKeyModifierAlternate) {
|
||||
prettyFlags = [prettyFlags stringByAppendingString:@"⌥"];
|
||||
}
|
||||
if (self.flags & UIKeyModifierShift) {
|
||||
prettyFlags = [prettyFlags stringByAppendingString:@"⇧"];
|
||||
}
|
||||
if (self.flags & UIKeyModifierCommand) {
|
||||
prettyFlags = [prettyFlags stringByAppendingString:@"⌘"];
|
||||
}
|
||||
|
||||
// Fudging to get easy columns with tabs
|
||||
if (prettyFlags.length < 2) {
|
||||
prettyKey = [prettyKey stringByAppendingString:@"\t"];
|
||||
}
|
||||
|
||||
return [NSString stringWithFormat:@"%@%@\t%@", prettyFlags, prettyKey, self.helpDescription];
|
||||
}
|
||||
|
||||
+ (instancetype)keyInputForKey:(NSString *)key flags:(UIKeyModifierFlags)flags {
|
||||
return [self keyInputForKey:key flags:flags helpDescription:nil];
|
||||
}
|
||||
|
||||
+ (instancetype)keyInputForKey:(NSString *)key
|
||||
flags:(UIKeyModifierFlags)flags
|
||||
helpDescription:(NSString *)helpDescription {
|
||||
FLEXKeyInput *keyInput = [self new];
|
||||
if (keyInput) {
|
||||
keyInput->_key = key;
|
||||
keyInput->_flags = flags;
|
||||
keyInput->_helpDescription = helpDescription;
|
||||
}
|
||||
return keyInput;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface FLEXKeyboardShortcutManager ()
|
||||
|
||||
@property (nonatomic) NSMutableDictionary<FLEXKeyInput *, dispatch_block_t> *actionsForKeyInputs;
|
||||
|
||||
@property (nonatomic, getter=isPressingShift) BOOL pressingShift;
|
||||
@property (nonatomic, getter=isPressingCommand) BOOL pressingCommand;
|
||||
@property (nonatomic, getter=isPressingControl) BOOL pressingControl;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FLEXKeyboardShortcutManager
|
||||
|
||||
+ (instancetype)sharedManager {
|
||||
static FLEXKeyboardShortcutManager *sharedManager = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
sharedManager = [self new];
|
||||
});
|
||||
return sharedManager;
|
||||
}
|
||||
|
||||
+ (void)load {
|
||||
SEL originalKeyEventSelector = NSSelectorFromString(@"handleKeyUIEvent:");
|
||||
SEL swizzledKeyEventSelector = [FLEXUtility swizzledSelectorForSelector:originalKeyEventSelector];
|
||||
|
||||
void (^handleKeyUIEventSwizzleBlock)(UIApplication *, UIEvent *) = ^(UIApplication *slf, UIEvent *event) {
|
||||
|
||||
[[[self class] sharedManager] handleKeyboardEvent:event];
|
||||
|
||||
((void(*)(id, SEL, id))objc_msgSend)(slf, swizzledKeyEventSelector, event);
|
||||
};
|
||||
|
||||
[FLEXUtility replaceImplementationOfKnownSelector:originalKeyEventSelector
|
||||
onClass:[UIApplication class]
|
||||
withBlock:handleKeyUIEventSwizzleBlock
|
||||
swizzledSelector:swizzledKeyEventSelector
|
||||
];
|
||||
|
||||
if ([[UITouch class] instancesRespondToSelector:@selector(maximumPossibleForce)]) {
|
||||
SEL originalSendEventSelector = NSSelectorFromString(@"sendEvent:");
|
||||
SEL swizzledSendEventSelector = [FLEXUtility swizzledSelectorForSelector:originalSendEventSelector];
|
||||
|
||||
void (^sendEventSwizzleBlock)(UIApplication *, UIEvent *) = ^(UIApplication *slf, UIEvent *event) {
|
||||
if (event.type == UIEventTypeTouches) {
|
||||
FLEXKeyboardShortcutManager *keyboardManager = FLEXKeyboardShortcutManager.sharedManager;
|
||||
NSInteger pressureLevel = 0;
|
||||
if (keyboardManager.isPressingShift) {
|
||||
pressureLevel++;
|
||||
}
|
||||
if (keyboardManager.isPressingCommand) {
|
||||
pressureLevel++;
|
||||
}
|
||||
if (keyboardManager.isPressingControl) {
|
||||
pressureLevel++;
|
||||
}
|
||||
if (pressureLevel > 0) {
|
||||
if (@available(iOS 9.0, *)) {
|
||||
for (UITouch *touch in [event allTouches]) {
|
||||
double adjustedPressureLevel = pressureLevel * 20 * touch.maximumPossibleForce;
|
||||
[touch setValue:@(adjustedPressureLevel) forKey:@"_pressure"];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
((void(*)(id, SEL, id))objc_msgSend)(slf, swizzledSendEventSelector, event);
|
||||
};
|
||||
|
||||
[FLEXUtility replaceImplementationOfKnownSelector:originalSendEventSelector
|
||||
onClass:[UIApplication class]
|
||||
withBlock:sendEventSwizzleBlock
|
||||
swizzledSelector:swizzledSendEventSelector
|
||||
];
|
||||
|
||||
SEL originalSupportsTouchPressureSelector = NSSelectorFromString(@"_supportsForceTouch");
|
||||
SEL swizzledSupportsTouchPressureSelector = [FLEXUtility swizzledSelectorForSelector:originalSupportsTouchPressureSelector];
|
||||
|
||||
BOOL (^supportsTouchPressureSwizzleBlock)(UIDevice *) = ^BOOL(UIDevice *slf) {
|
||||
return YES;
|
||||
};
|
||||
|
||||
[FLEXUtility replaceImplementationOfKnownSelector:originalSupportsTouchPressureSelector
|
||||
onClass:[UIDevice class]
|
||||
withBlock:supportsTouchPressureSwizzleBlock
|
||||
swizzledSelector:swizzledSupportsTouchPressureSelector
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
|
||||
if (self) {
|
||||
_actionsForKeyInputs = [NSMutableDictionary new];
|
||||
_enabled = YES;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)registerSimulatorShortcutWithKey:(NSString *)key
|
||||
modifiers:(UIKeyModifierFlags)modifiers
|
||||
action:(dispatch_block_t)action
|
||||
description:(NSString *)description
|
||||
allowOverride:(BOOL)allowOverride {
|
||||
FLEXKeyInput *keyInput = [FLEXKeyInput keyInputForKey:key flags:modifiers helpDescription:description];
|
||||
if (!allowOverride && self.actionsForKeyInputs[keyInput] != nil) {
|
||||
return;
|
||||
} else {
|
||||
[self.actionsForKeyInputs setObject:action forKey:keyInput];
|
||||
}
|
||||
}
|
||||
|
||||
static const long kFLEXControlKeyCode = 0xe0;
|
||||
static const long kFLEXShiftKeyCode = 0xe1;
|
||||
static const long kFLEXCommandKeyCode = 0xe3;
|
||||
|
||||
- (void)handleKeyboardEvent:(UIEvent *)event {
|
||||
if (!self.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *modifiedInput = nil;
|
||||
NSString *unmodifiedInput = nil;
|
||||
UIKeyModifierFlags flags = 0;
|
||||
BOOL isKeyDown = NO;
|
||||
|
||||
if ([event respondsToSelector:@selector(_modifiedInput)]) {
|
||||
modifiedInput = [event _modifiedInput];
|
||||
}
|
||||
|
||||
if ([event respondsToSelector:@selector(_unmodifiedInput)]) {
|
||||
unmodifiedInput = [event _unmodifiedInput];
|
||||
}
|
||||
|
||||
if ([event respondsToSelector:@selector(_modifierFlags)]) {
|
||||
flags = [event _modifierFlags];
|
||||
}
|
||||
|
||||
if ([event respondsToSelector:@selector(_isKeyDown)]) {
|
||||
isKeyDown = [event _isKeyDown];
|
||||
}
|
||||
|
||||
BOOL interactionEnabled = !UIApplication.sharedApplication.isIgnoringInteractionEvents;
|
||||
BOOL hasFirstResponder = NO;
|
||||
if (isKeyDown && modifiedInput.length > 0 && interactionEnabled) {
|
||||
UIResponder *firstResponder = nil;
|
||||
for (UIWindow *window in FLEXUtility.allWindows) {
|
||||
firstResponder = [window valueForKey:@"firstResponder"];
|
||||
if (firstResponder) {
|
||||
hasFirstResponder = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore key commands (except escape) when there's an active responder
|
||||
if (firstResponder) {
|
||||
if ([unmodifiedInput isEqual:UIKeyInputEscape]) {
|
||||
[firstResponder resignFirstResponder];
|
||||
}
|
||||
} else {
|
||||
FLEXKeyInput *exactMatch = [FLEXKeyInput keyInputForKey:unmodifiedInput flags:flags];
|
||||
|
||||
dispatch_block_t actionBlock = self.actionsForKeyInputs[exactMatch];
|
||||
|
||||
if (!actionBlock) {
|
||||
FLEXKeyInput *shiftMatch = [FLEXKeyInput
|
||||
keyInputForKey:modifiedInput flags:flags&(~UIKeyModifierShift)
|
||||
];
|
||||
actionBlock = self.actionsForKeyInputs[shiftMatch];
|
||||
}
|
||||
|
||||
if (!actionBlock) {
|
||||
FLEXKeyInput *capitalMatch = [FLEXKeyInput
|
||||
keyInputForKey:[unmodifiedInput uppercaseString] flags:flags
|
||||
];
|
||||
actionBlock = self.actionsForKeyInputs[capitalMatch];
|
||||
}
|
||||
|
||||
if (actionBlock) {
|
||||
actionBlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calling _keyCode on events from the simulator keyboard will crash.
|
||||
// It is only safe to call _keyCode when there's not an active responder.
|
||||
if (!hasFirstResponder && [event respondsToSelector:@selector(_keyCode)]) {
|
||||
long keyCode = [event _keyCode];
|
||||
if (keyCode == kFLEXControlKeyCode) {
|
||||
self.pressingControl = isKeyDown;
|
||||
} else if (keyCode == kFLEXCommandKeyCode) {
|
||||
self.pressingCommand = isKeyDown;
|
||||
} else if (keyCode == kFLEXShiftKeyCode) {
|
||||
self.pressingShift = isKeyDown;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)keyboardShortcutsDescription {
|
||||
NSMutableString *description = [NSMutableString new];
|
||||
NSArray<FLEXKeyInput *> *keyInputs = [self.actionsForKeyInputs.allKeys
|
||||
sortedArrayUsingComparator:^NSComparisonResult(FLEXKeyInput *input1, FLEXKeyInput *input2) {
|
||||
return [input1.key caseInsensitiveCompare:input2.key];
|
||||
}
|
||||
];
|
||||
for (FLEXKeyInput *keyInput in keyInputs) {
|
||||
[description appendFormat:@"%@\n", keyInput];
|
||||
}
|
||||
return [description copy];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user