mirror of https://github.com/keeweb/keeweb.git
send text with modifiers
This commit is contained in:
parent
08d22f8465
commit
0bd22add57
|
@ -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();
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue