send text with modifiers

This commit is contained in:
antelle 2016-08-07 18:24:25 +03:00
parent 08d22f8465
commit 0bd22add57
9 changed files with 145 additions and 47 deletions

View File

@ -38,7 +38,7 @@ AutoTypeEmitter.prototype.setMod = function(mod, enabled) {
};
AutoTypeEmitter.prototype.text = function(text) {
this.pendingScript.push('text ' + text);
this.pendingScript.push('text ' + this.modString() + ' ' + text);
this.callback();
};

View File

@ -20,9 +20,9 @@
[pasteboard clearContents];
[pasteboard setString:text forType:NSStringPboardType];
usleep(500000);
[KeyRunner keyUpDown:0 code:kVK_Command flags:0 down:true];
[KeyRunner keyModUpDown:kCGEventFlagMaskCommand down:true];
[KeyRunner keyPress:0 code:kVK_ANSI_V flags:kCGEventFlagMaskCommand];
[KeyRunner keyUpDown:0 code:kVK_Command flags:0 down:false];
[KeyRunner keyModUpDown:kCGEventFlagMaskCommand down:false];
usleep(500000);
}

View File

@ -13,30 +13,12 @@
}
- (void)execute {
if (modifier & kCGEventFlagMaskCommand) {
[KeyRunner keyUpDown:0 code:kVK_Command flags:0 down:true];
}
if (modifier & kCGEventFlagMaskAlternate) {
[KeyRunner keyUpDown:0 code:kVK_Option flags:0 down:true];
}
if (modifier & kCGEventFlagMaskControl) {
[KeyRunner keyUpDown:0 code:kVK_Control flags:0 down:true];
}
if (modifier & kCGEventFlagMaskShift) {
[KeyRunner keyUpDown:0 code:kVK_Shift flags:0 down:true];
if (modifier) {
[KeyRunner keyModUpDown:modifier down:true];
}
[KeyRunner keyPress:0 code:key flags:modifier];
if (modifier & kCGEventFlagMaskCommand) {
[KeyRunner keyUpDown:0 code:kVK_Command flags:0 down:false];
}
if (modifier & kCGEventFlagMaskAlternate) {
[KeyRunner keyUpDown:0 code:kVK_Option flags:0 down:false];
}
if (modifier & kCGEventFlagMaskControl) {
[KeyRunner keyUpDown:0 code:kVK_Control flags:0 down:false];
}
if (modifier & kCGEventFlagMaskShift) {
[KeyRunner keyUpDown:0 code:kVK_Shift flags:0 down:false];
if (modifier) {
[KeyRunner keyModUpDown:modifier down:false];
}
}

View File

@ -4,8 +4,10 @@
@interface SendTextCommand : NSObject<InputCommandBase> {
NSString *text;
CGEventFlags modifier;
}
- (id)initWithText:(NSString *)aText;
- (id)initWithText:(NSString *)aText andModifier:(CGEventFlags)aModifier;
+ (void)initialize;
@end

View File

@ -3,19 +3,110 @@
@implementation SendTextCommand
- (id)initWithText:(NSString *)aText {
NSDictionary *knownKeyCodes;
- (id)initWithText:(NSString *)aText andModifier:(CGEventFlags)aModifier {
self = [super init];
if (self) {
text = aText;
modifier = aModifier;
}
return self;
}
- (void)execute {
if (modifier) {
[KeyRunner keyModUpDown:modifier down:true];
}
NSString *textLower = [text lowercaseString];
for (int i = 0; i < text.length; i++) {
unichar ch = [text characterAtIndex:i];
[KeyRunner keyPress:ch code:0 flags:0];
unichar chLower = [textLower characterAtIndex:i];
id knownKeyCode = [knownKeyCodes objectForKey:@(chLower)];
CGKeyCode keyCode = knownKeyCode == nil ? 0 : (CGKeyCode)[knownKeyCode unsignedShortValue];
if (modifier && modifier != kCGEventFlagMaskShift) {
ch = 0;
}
[KeyRunner keyPress:ch code:keyCode flags:modifier];
}
if (modifier) {
[KeyRunner keyModUpDown:modifier down:false];
}
}
+ (void)initialize {
knownKeyCodes = @{
@'0': @(kVK_ANSI_0),
@'1': @(kVK_ANSI_1),
@'2': @(kVK_ANSI_2),
@'3': @(kVK_ANSI_3),
@'4': @(kVK_ANSI_4),
@'5': @(kVK_ANSI_5),
@'6': @(kVK_ANSI_6),
@'7': @(kVK_ANSI_7),
@'8': @(kVK_ANSI_8),
@'9': @(kVK_ANSI_9),
@'0': @(kVK_ANSI_0),
@'a': @(kVK_ANSI_A),
@'b': @(kVK_ANSI_B),
@'c': @(kVK_ANSI_C),
@'d': @(kVK_ANSI_D),
@'e': @(kVK_ANSI_E),
@'f': @(kVK_ANSI_F),
@'g': @(kVK_ANSI_G),
@'h': @(kVK_ANSI_H),
@'i': @(kVK_ANSI_I),
@'j': @(kVK_ANSI_J),
@'k': @(kVK_ANSI_K),
@'l': @(kVK_ANSI_L),
@'m': @(kVK_ANSI_M),
@'n': @(kVK_ANSI_N),
@'o': @(kVK_ANSI_O),
@'p': @(kVK_ANSI_P),
@'q': @(kVK_ANSI_Q),
@'r': @(kVK_ANSI_R),
@'s': @(kVK_ANSI_S),
@'t': @(kVK_ANSI_T),
@'u': @(kVK_ANSI_U),
@'v': @(kVK_ANSI_V),
@'w': @(kVK_ANSI_W),
@'x': @(kVK_ANSI_X),
@'y': @(kVK_ANSI_Y),
@'z': @(kVK_ANSI_Z),
@'!': @(kVK_ANSI_1),
@'@': @(kVK_ANSI_2),
@'#': @(kVK_ANSI_3),
@'$': @(kVK_ANSI_4),
@'%': @(kVK_ANSI_5),
@'^': @(kVK_ANSI_6),
@'&': @(kVK_ANSI_7),
@'*': @(kVK_ANSI_8),
@'(': @(kVK_ANSI_9),
@')': @(kVK_ANSI_0),
@'-': @(kVK_ANSI_Minus),
@'_': @(kVK_ANSI_Minus),
@'=': @(kVK_ANSI_Equal),
@'+': @(kVK_ANSI_Equal),
@'`': @(kVK_ANSI_Grave),
@'~': @(kVK_ANSI_Grave),
@',': @(kVK_ANSI_Comma),
@'<': @(kVK_ANSI_Comma),
@'.': @(kVK_ANSI_Period),
@'>': @(kVK_ANSI_Period),
@'/': @(kVK_ANSI_Slash),
@'?': @(kVK_ANSI_Slash),
@'\\': @(kVK_ANSI_Backslash),
@'|': @(kVK_ANSI_Backslash),
@';': @(kVK_ANSI_Semicolon),
@':': @(kVK_ANSI_Semicolon),
@'\'': @(kVK_ANSI_Quote),
@'"': @(kVK_ANSI_Quote),
@'[': @(kVK_ANSI_LeftBracket),
@'{': @(kVK_ANSI_LeftBracket),
@']': @(kVK_ANSI_RightBracket),
@'}': @(kVK_ANSI_RightBracket),
@'\t': @(kVK_Tab)
};
}
@end

View File

@ -27,13 +27,9 @@
if ([command isEqualToString:@"exit"]) {
return nil;
} else if ([command isEqualToString:@"key"]) {
return [self parseSendKeyCommand:line];
return [self parseSendCommand:line text:false];
} else if ([command isEqualToString:@"text"]) {
if (line.length) {
return [[SendTextCommand alloc] initWithText:line];
} else {
return [[NoOpCommand alloc] init];
}
return [self parseSendCommand:line text:true];
} else if ([command isEqualToString:@"copypaste"]) {
if (line.length) {
return [[CopyPasteCommand alloc] initWithText:line];
@ -54,16 +50,18 @@
}
}
- (id<InputCommandBase>)parseSendKeyCommand:(NSString*)args {
- (id<InputCommandBase>)parseSendCommand:(NSString*)args text:(bool)text {
if (!args.length) {
return [[NoOpCommand alloc] init];
}
CGEventFlags modifier = 0;
NSCharacterSet *digitChars = [NSCharacterSet decimalDigitCharacterSet];
NSMutableCharacterSet *stopChars = [[NSMutableCharacterSet alloc] init];
[stopChars formUnionWithCharacterSet:[NSCharacterSet decimalDigitCharacterSet]];
[stopChars formUnionWithCharacterSet:[NSCharacterSet whitespaceCharacterSet]];
NSInteger index = 0;
while (args.length) {
unichar firstChar = [args characterAtIndex:index];
if ([digitChars characterIsMember:firstChar]) {
if ([stopChars characterIsMember:firstChar]) {
break;
}
switch (firstChar) {
@ -84,17 +82,24 @@
}
index++;
}
if (text) {
index++;
}
if (index > 0) {
if (index == args.length) {
if (index >= args.length) {
return [[NoOpCommand alloc] initWithMessage:@"No key code"];
}
args = [args substringFromIndex:index];
}
NSInteger key = [args integerValue];
if (key <= 0) {
return [[NoOpCommand alloc] initWithMessage:@"Bad key code"];
if (text) {
return [[SendTextCommand alloc] initWithText:args andModifier:modifier];
} else {
NSInteger key = [args integerValue];
if (key <= 0) {
return [[NoOpCommand alloc] initWithMessage:@"Bad key code"];
}
return [[SendKeyCommand alloc] initWithKey:(CGKeyCode)key andModifier:modifier];
}
return [[SendKeyCommand alloc] initWithKey:(CGKeyCode)key andModifier:modifier];
}
@end

View File

@ -4,7 +4,9 @@
@interface KeyRunner : NSObject
+ (void)initialize;
+ (void)keyPress:(unichar)ch code:(CGKeyCode)code flags:(CGEventFlags)flags;
+ (void)keyUpDown:(unichar)ch code:(CGKeyCode)code flags:(CGEventFlags)flags down:(bool)down;
+ (void)keyModUpDown:(CGEventFlags)flags down:(bool)down;
@end

View File

@ -4,15 +4,31 @@
CGEventSourceRef eventSource = nil;
+ (void)initialize {
eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
}
+ (void)keyPress:(unichar)ch code:(CGKeyCode)code flags:(CGEventFlags)flags {
[self keyUpDown:ch code:code flags:flags down:false];
[self keyUpDown:ch code:code flags:flags down:true];
[self keyUpDown:ch code:code flags:flags down:false];
}
+ (void)keyModUpDown:(CGEventFlags)modifier down:(bool)down {
if (modifier & kCGEventFlagMaskCommand) {
[self keyUpDown:0 code:kVK_Command flags:0 down:down];
}
if (modifier & kCGEventFlagMaskAlternate) {
[self keyUpDown:0 code:kVK_Option flags:0 down:down];
}
if (modifier & kCGEventFlagMaskControl) {
[self keyUpDown:0 code:kVK_Control flags:0 down:down];
}
if (modifier & kCGEventFlagMaskShift) {
[self keyUpDown:0 code:kVK_Shift flags:0 down:down];
}
}
+ (void)keyUpDown:(unichar)ch code:(CGKeyCode)code flags:(CGEventFlags)flags down:(bool)down {
if (!eventSource) {
eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
}
CGEventRef keyEvent = CGEventCreateKeyboardEvent(eventSource, code, down);
if (ch) {
CGEventKeyboardSetUnicodeString(keyEvent, 1, &ch);

View File

@ -25,6 +25,6 @@ int main(int argc, const char * argv[]) {
}
}
// TODO: ugly way to wait for all keystrokes to be sent. is there a better way?
usleep(100);
usleep(100000);
return 0;
}