mirror of
https://github.com/MacPass/MacPass.git
synced 2025-12-14 17:32:17 +00:00
Introducing MPModifiedKey to encapulate keyCode and modifier flags
This commit is contained in:
@@ -17,12 +17,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)execute {
|
- (void)execute {
|
||||||
CGKeyCode keyCode = [MPKeyMapper keyCodeForCharacter:@"a" modifier:NULL];
|
MPModifiedKey key = [MPKeyMapper modifiedKeyForCharacter:@"a"];
|
||||||
if(keyCode == kMPUnknownKeyCode) {
|
if(key.keyCode == kMPUnknownKeyCode) {
|
||||||
NSLog(@"Unable to generate key code for 'A'");
|
NSLog(@"Unable to generate key code for 'A'");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
[self sendPressKey:keyCode modifierFlags:kCGEventFlagMaskCommand];
|
[self sendPressKey:key.keyCode modifierFlags:kCGEventFlagMaskCommand];
|
||||||
[self sendPressKey:kVK_Delete modifierFlags:0];
|
[self sendPressKey:kVK_Delete modifierFlags:0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -238,17 +238,16 @@ static CGKeyCode kMPFunctionKeyCodes[] = { kVK_F1, kVK_F2, kVK_F3, kVK_F4, kVK_F
|
|||||||
NSUInteger part = random() % 2;
|
NSUInteger part = random() % 2;
|
||||||
|
|
||||||
unichar key = [pasteContent characterAtIndex:i];
|
unichar key = [pasteContent characterAtIndex:i];
|
||||||
CGKeyCode keyCode = [MPKeyMapper keyCodeForCharacter:[NSString stringWithFormat:@"%c", key] modifier:NULL];
|
MPModifiedKey mKey = [MPKeyMapper modifiedKeyForCharacter:[NSString stringWithFormat:@"%c", key]];
|
||||||
|
|
||||||
/* append unknown keycodes to the paste since we can't type them */
|
/* append unknown keycodes to the paste since we can't type them */
|
||||||
if (part == 0 || keyCode == kMPUnknownKeyCode) {
|
if (part == 0 || mKey.keyCode == kMPUnknownKeyCode) {
|
||||||
paste = [paste stringByAppendingFormat:@"%c", key];
|
paste = [paste stringByAppendingFormat:@"%c", key];
|
||||||
|
|
||||||
[typeKeys addObject:@(kVK_RightArrow)];
|
[typeKeys addObject:@(kVK_RightArrow)];
|
||||||
[modifiers addObject:@0];
|
[modifiers addObject:@0];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
[typeKeys addObject:@(keyCode)];
|
[typeKeys addObject:@(mKey.keyCode)];
|
||||||
|
|
||||||
if ([[NSCharacterSet uppercaseLetterCharacterSet] characterIsMember:key])
|
if ([[NSCharacterSet uppercaseLetterCharacterSet] characterIsMember:key])
|
||||||
[modifiers addObject:@(kCGEventFlagMaskShift)];
|
[modifiers addObject:@(kCGEventFlagMaskShift)];
|
||||||
@@ -398,11 +397,11 @@ static CGKeyCode kMPFunctionKeyCodes[] = { kVK_F1, kVK_F2, kVK_F3, kVK_F4, kVK_F
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)sendPasteKeyCode {
|
- (void)sendPasteKeyCode {
|
||||||
CGKeyCode keyCode = [MPKeyMapper keyCodeForCharacter:@"v" modifier:NULL];
|
MPModifiedKey mKey = [MPKeyMapper modifiedKeyForCharacter:@"v"];
|
||||||
if(keyCode == kMPUnknownKeyCode) {
|
if(mKey.keyCode == kMPUnknownKeyCode) {
|
||||||
return; // We did not find a mapping for "V"
|
return; // We did not find a mapping for "V"
|
||||||
}
|
}
|
||||||
[self sendPressKey:keyCode modifierFlags:kCGEventFlagMaskCommand];
|
[self sendPressKey:mKey.keyCode modifierFlags:kCGEventFlagMaskCommand];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)execute {
|
- (void)execute {
|
||||||
|
|||||||
@@ -32,16 +32,15 @@ static CGEventFlags _updateModifierMaskForCurrentDefaults(CGEventFlags modifiers
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (instancetype)initWithModifierMask:(CGEventFlags)modiferMask character:(NSString *)character {
|
- (instancetype)initWithModifierMask:(CGEventFlags)modiferMask character:(NSString *)character {
|
||||||
CGEventFlags modifiers;
|
MPModifiedKey mappedKey = [MPKeyMapper modifiedKeyForCharacter:character];
|
||||||
CGKeyCode mappedKey = [MPKeyMapper keyCodeForCharacter:character modifier:&modifiers];
|
if(mappedKey.keyCode == kMPUnknownKeyCode) {
|
||||||
if(mappedKey == kMPUnknownKeyCode) {
|
|
||||||
self = nil;
|
self = nil;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(modifiers && (modiferMask != modifiers)) {
|
if(mappedKey.modifier && (modiferMask != mappedKey.modifier)) {
|
||||||
NSLog(@"Supplied modifiers for character %@ do not match required modifiers", character);
|
NSLog(@"Supplied modifiers for character %@ do not match required modifiers", character);
|
||||||
}
|
}
|
||||||
self = [self initWithModifierMask:modiferMask keyCode:mappedKey];
|
self = [self initWithModifierMask:modiferMask keyCode:mappedKey.modifier];
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,18 @@
|
|||||||
|
|
||||||
FOUNDATION_EXTERN uint16_t const kMPUnknownKeyCode;
|
FOUNDATION_EXTERN uint16_t const kMPUnknownKeyCode;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
CGEventFlags modifier;
|
||||||
|
CGKeyCode keyCode;
|
||||||
|
} MPModifiedKey;
|
||||||
|
|
||||||
|
NS_INLINE MPModifiedKey MPMakeModifiedKey(CGEventFlags modifier, CGKeyCode keyCode) {
|
||||||
|
MPModifiedKey k;
|
||||||
|
k.keyCode = keyCode;
|
||||||
|
k.modifier = modifier;
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
|
||||||
@interface MPKeyMapper : NSObject
|
@interface MPKeyMapper : NSObject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -19,16 +31,16 @@ FOUNDATION_EXTERN uint16_t const kMPUnknownKeyCode;
|
|||||||
* @param modifier State of modifier flags being pressed with the key
|
* @param modifier State of modifier flags being pressed with the key
|
||||||
* @return NSString containing the current mapping for the keyCode
|
* @return NSString containing the current mapping for the keyCode
|
||||||
*/
|
*/
|
||||||
+ (NSString *)stringForKey:(CGKeyCode)keyCode modifier:(CGEventFlags)modifier;
|
|
||||||
+ (NSString *)stringForKey:(CGKeyCode)keyCode;
|
+ (NSString *)stringForKey:(CGKeyCode)keyCode;
|
||||||
|
+ (NSString *)stringForModifiedKey:(MPModifiedKey)modifiedKey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines the keyCode (if possible) for the character. Modifiers might be needed
|
* Determines the modifiedkey (if possible) for the character. Modifiers might be needed
|
||||||
*
|
*
|
||||||
* @param character NSString with a single character to be transformed
|
* @param character NSString with a single character to be transformed
|
||||||
* @param modifier pointer to a modifer structure to return the modifer to use with the key code for the character
|
* @param modifier pointer to a modifer structure to return the modifer to use with the key code for the character
|
||||||
* @return virtual Keycode for the supplied string. If none is found, kMPUnkonwKeyCode is returned
|
* @return ModifiedKey if one was found. If none is found, the returned modifiedKey.keyCode has the value kMPUnkonwKeyCode.
|
||||||
*/
|
*/
|
||||||
+ (CGKeyCode)keyCodeForCharacter:(NSString *)character modifier:(CGEventFlags *)modifer;
|
+ (MPModifiedKey)modifiedKeyForCharacter:(NSString *)character;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -20,18 +20,19 @@
|
|||||||
|
|
||||||
|
|
||||||
#import "MPKeyMapper.h"
|
#import "MPKeyMapper.h"
|
||||||
|
|
||||||
#import <Carbon/Carbon.h>
|
#import <Carbon/Carbon.h>
|
||||||
|
|
||||||
|
#define MPSafeSetPointer(pointer, value) if(pointer != 0) { *pointer = value; }
|
||||||
|
|
||||||
uint16_t const kMPUnknownKeyCode = UINT16_MAX;
|
uint16_t const kMPUnknownKeyCode = UINT16_MAX;
|
||||||
|
|
||||||
@implementation MPKeyMapper
|
@implementation MPKeyMapper
|
||||||
|
|
||||||
+ (NSString *)stringForKey:(CGKeyCode)keyCode {
|
+ (NSString *)stringForKey:(CGKeyCode)keyCode {
|
||||||
return [self stringForKey:keyCode modifier:0];
|
return [self stringForModifiedKey:MPMakeModifiedKey(0, keyCode)];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSString *)stringForKey:(CGKeyCode)keyCode modifier:(CGEventFlags)modifier {
|
+ (NSString *)stringForModifiedKey:(MPModifiedKey)modifiedKey {
|
||||||
TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
|
TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
|
||||||
CFDataRef layoutData = TISGetInputSourceProperty(currentKeyboard,kTISPropertyUnicodeKeyLayoutData);
|
CFDataRef layoutData = TISGetInputSourceProperty(currentKeyboard,kTISPropertyUnicodeKeyLayoutData);
|
||||||
|
|
||||||
@@ -49,21 +50,21 @@ uint16_t const kMPUnknownKeyCode = UINT16_MAX;
|
|||||||
|
|
||||||
|
|
||||||
uint32_t modifierKeyState = 0;
|
uint32_t modifierKeyState = 0;
|
||||||
if(modifier & kCGEventFlagMaskCommand) {
|
if(modifiedKey.modifier & kCGEventFlagMaskCommand) {
|
||||||
modifierKeyState |= ((cmdKey >> 8 ) & 0xFF);
|
modifierKeyState |= ((cmdKey >> 8 ) & 0xFF);
|
||||||
}
|
}
|
||||||
if(modifier & kCGEventFlagMaskShift) {
|
if(modifiedKey.modifier & kCGEventFlagMaskShift) {
|
||||||
modifierKeyState |= ((shiftKey >> 8) & 0xFF);
|
modifierKeyState |= ((shiftKey >> 8) & 0xFF);
|
||||||
}
|
}
|
||||||
if(modifier & kCGEventFlagMaskAlternate) {
|
if(modifiedKey.modifier & kCGEventFlagMaskAlternate) {
|
||||||
modifierKeyState |= ((optionKey >> 8) & 0xFF);
|
modifierKeyState |= ((optionKey >> 8) & 0xFF);
|
||||||
}
|
}
|
||||||
if(modifier & kCGEventFlagMaskControl) {
|
if(modifiedKey.modifier & kCGEventFlagMaskControl) {
|
||||||
modifierKeyState |= ((controlKey >> 8) & 0xFF);
|
modifierKeyState |= ((controlKey >> 8) & 0xFF);
|
||||||
}
|
}
|
||||||
OSStatus success = 0;
|
OSStatus success = 0;
|
||||||
success = UCKeyTranslate(keyboardLayout,
|
success = UCKeyTranslate(keyboardLayout,
|
||||||
keyCode,
|
modifiedKey.keyCode,
|
||||||
kUCKeyActionDisplay,
|
kUCKeyActionDisplay,
|
||||||
modifierKeyState,
|
modifierKeyState,
|
||||||
LMGetKbdType(),
|
LMGetKbdType(),
|
||||||
@@ -76,7 +77,7 @@ uint16_t const kMPUnknownKeyCode = UINT16_MAX;
|
|||||||
return CFBridgingRelease(CFStringCreateWithCharacters(kCFAllocatorDefault, chars, 1));
|
return CFBridgingRelease(CFStringCreateWithCharacters(kCFAllocatorDefault, chars, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (CGKeyCode)keyCodeForCharacter:(NSString *)character modifier:(CGEventFlags *)modifer {
|
+ (MPModifiedKey)modifiedKeyForCharacter:(NSString *)character {
|
||||||
static NSMutableDictionary *keyboardCodeDictionary;
|
static NSMutableDictionary *keyboardCodeDictionary;
|
||||||
|
|
||||||
TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
|
TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
|
||||||
@@ -89,21 +90,32 @@ uint16_t const kMPUnknownKeyCode = UINT16_MAX;
|
|||||||
keyboardCodeDictionary = [[NSMutableDictionary alloc] initWithCapacity:2];
|
keyboardCodeDictionary = [[NSMutableDictionary alloc] initWithCapacity:2];
|
||||||
}
|
}
|
||||||
/* search for current character mapping */
|
/* search for current character mapping */
|
||||||
NSDictionary<NSString *, NSArray<NSNumber *> *> *charToCodeDict = keyboardCodeDictionary[localizedName];
|
NSDictionary<NSString *, NSValue *> *charToCodeDict = keyboardCodeDictionary[localizedName];
|
||||||
|
|
||||||
if(nil == charToCodeDict) {
|
if(nil == charToCodeDict) {
|
||||||
/* Add mapping */
|
/* Add mapping */
|
||||||
|
static uint64_t modifierCombinations[] = {
|
||||||
|
0,
|
||||||
|
kCGEventFlagMaskShift,
|
||||||
|
kCGEventFlagMaskAlternate,
|
||||||
|
kCGEventFlagMaskControl,
|
||||||
|
(kCGEventFlagMaskShift | kCGEventFlagMaskAlternate),
|
||||||
|
(kCGEventFlagMaskShift | kCGEventFlagMaskControl),
|
||||||
|
(kCGEventFlagMaskShift | kCGEventFlagMaskAlternate | kCGEventFlagMaskControl)
|
||||||
|
};
|
||||||
|
|
||||||
NSMutableDictionary *tempCharToCodeDict = [[NSMutableDictionary alloc] initWithCapacity:128];
|
NSMutableDictionary *tempCharToCodeDict = [[NSMutableDictionary alloc] initWithCapacity:128];
|
||||||
|
|
||||||
/* Generate table of keycodes and characters. */
|
/* Generate table of keycodes and characters. */
|
||||||
/* Loop through every keycode (0 - 127) to find its current mapping. */
|
/* Loop through every keycode (0 - 127) to find its current mapping. */
|
||||||
/* Loop throuhg every control key compbination for every virutal key */
|
/* Loop throuhg every control key compbination for every virutal key */
|
||||||
for(CGKeyCode keyCode = 0; keyCode < 128; ++keyCode) {
|
for(CGKeyCode keyCode = 0; keyCode < 128; ++keyCode) {
|
||||||
uint64_t modifiers[] = { 0, kCGEventFlagMaskShift, kCGEventFlagMaskAlternate, kCGEventFlagMaskControl, kCGEventFlagMaskShift | kCGEventFlagMaskAlternate, kCGEventFlagMaskShift | kCGEventFlagMaskControl, kCGEventFlagMaskShift | kCGEventFlagMaskAlternate | kCGEventFlagMaskControl };
|
for(int modifierIndex = 0; modifierIndex < sizeof(modifierCombinations); modifierIndex++) {
|
||||||
for(int modifierIndex = 0; modifierIndex < sizeof(modifiers); modifierIndex++) {
|
MPModifiedKey mKey = MPMakeModifiedKey(modifierCombinations[modifierIndex], keyCode);
|
||||||
NSString *string = [self stringForKey:keyCode modifier:modifiers[modifierIndex]];
|
NSString *string = [self stringForModifiedKey:mKey];
|
||||||
if(string != nil && string.length > 0 && nil == tempCharToCodeDict[string]) {
|
if(string != nil && string.length > 0 && nil == tempCharToCodeDict[string]) {
|
||||||
tempCharToCodeDict[string] = @[@(keyCode), @(modifiers[modifierIndex])];
|
NSValue *value = [NSValue valueWithBytes:&mKey objCType:@encode(MPModifiedKey)];
|
||||||
|
tempCharToCodeDict[string] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,18 +123,13 @@ uint16_t const kMPUnknownKeyCode = UINT16_MAX;
|
|||||||
keyboardCodeDictionary[localizedName] = charToCodeDict;
|
keyboardCodeDictionary[localizedName] = charToCodeDict;
|
||||||
}
|
}
|
||||||
NSString *singleCharacter = [character substringToIndex:1].lowercaseString;
|
NSString *singleCharacter = [character substringToIndex:1].lowercaseString;
|
||||||
NSArray<NSNumber *> *result = charToCodeDict[singleCharacter];
|
NSValue *result = charToCodeDict[singleCharacter];
|
||||||
if(result) {
|
if(!result) {
|
||||||
if(modifer) {
|
return MPMakeModifiedKey(0, kMPUnknownKeyCode);
|
||||||
*modifer = result[1].unsignedIntegerValue;
|
|
||||||
}
|
}
|
||||||
/* false positive when no modifier was supplied! */
|
MPModifiedKey mKey;
|
||||||
return result[0].integerValue;
|
[result getValue:&mKey];
|
||||||
}
|
return mKey;
|
||||||
if(modifer) {
|
|
||||||
*modifer = 0;
|
|
||||||
}
|
|
||||||
return kMPUnknownKeyCode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -19,10 +19,10 @@
|
|||||||
@implementation MPTestKeyMapper
|
@implementation MPTestKeyMapper
|
||||||
|
|
||||||
- (void)testKeyMapper {
|
- (void)testKeyMapper {
|
||||||
CGEventFlags flags = 0;
|
|
||||||
CGKeyCode keyCode = [MPKeyMapper keyCodeForCharacter:@"A" modifier:&flags];
|
MPModifiedKey key = [MPKeyMapper modifiedKeyForCharacter:@"A"];
|
||||||
XCTAssertEqual(kVK_ANSI_A, keyCode);
|
XCTAssertEqual(kVK_ANSI_A, key.keyCode);
|
||||||
XCTAssertEqual(kCGEventFlagMaskShift, flags);
|
XCTAssertEqual(kCGEventFlagMaskShift, key.modifier);
|
||||||
|
|
||||||
/* Test only works for german keyboard layout!
|
/* Test only works for german keyboard layout!
|
||||||
XCTAssertEqualObjects(@"a",[MPKeyMapper stringForKey:kVK_ANSI_A modifier:0]);
|
XCTAssertEqualObjects(@"a",[MPKeyMapper stringForKey:kVK_ANSI_A modifier:0]);
|
||||||
|
|||||||
Reference in New Issue
Block a user