Skip to content

Commit bcdb17e

Browse files
committed
Support Telex entry on different keyboard layouts
- Add options to enable key layout compatibility - Tested on Dvorak, Coleman, custom Dvorak made with Ukelele application
1 parent 6614e99 commit bcdb17e

File tree

7 files changed

+109
-33
lines changed

7 files changed

+109
-33
lines changed

Sources/OpenKey/macOS/ModernKey/AppDelegate.m

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949

5050
int vShowIconOnDock = 0; //new on version 2.0
5151

52+
int vPerformLayoutCompat = 0;
53+
5254
//beta feature
5355
int vFixChromiumBrowser = 0; //new on version 2.0
5456

@@ -285,6 +287,7 @@ -(void)loadDefaultConfig {
285287
vTempOffOpenKey = 0;[[NSUserDefaults standardUserDefaults] setInteger:vTempOffOpenKey forKey:@"vTempOffOpenKey"];
286288
vShowIconOnDock = 0;[[NSUserDefaults standardUserDefaults] setInteger:vShowIconOnDock forKey:@"vShowIconOnDock"];
287289
vFixChromiumBrowser = 0;[[NSUserDefaults standardUserDefaults] setInteger:vFixChromiumBrowser forKey:@"vFixChromiumBrowser"];
290+
vPerformLayoutCompat = 0;[[NSUserDefaults standardUserDefaults] setInteger:vPerformLayoutCompat forKey:@"vPerformLayoutCompat"];
288291
[[NSUserDefaults standardUserDefaults] setInteger:1 forKey:@"RunOnStartup"];
289292

290293
[self fillData];

Sources/OpenKey/macOS/ModernKey/Base.lproj/Main.storyboard

Lines changed: 38 additions & 25 deletions
Large diffs are not rendered by default.

Sources/OpenKey/macOS/ModernKey/OpenKey.mm

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
extern AppDelegate* appDelegate;
2727
extern int vSendKeyStepByStep;
2828
extern int vFixChromiumBrowser;
29+
extern int vPerformLayoutCompat;
2930

3031
extern "C" {
3132
//app which must sent special empty character
@@ -90,6 +91,8 @@ void OpenKeyInit() {
9091

9192
LOAD_DATA(vFixChromiumBrowser, vFixChromiumBrowser);
9293

94+
LOAD_DATA(vPerformLayoutCompat, vPerformLayoutCompat);
95+
9396
myEventSource = CGEventSourceCreate(kCGEventSourceStatePrivate);
9497
pData = (vKeyHookState*)vKeyInit();
9598

@@ -523,6 +526,48 @@ void handleMacro() {
523526
SendKeyCode(_keycode | (_flag & kCGEventFlagMaskShift ? CAPS_MASK : 0));
524527
}
525528

529+
// TODO: Research API to convert character into CGKeyCode more elegantly!
530+
int ConvertKeyStringToKeyCode(NSString *keyString, CGKeyCode fallback) {
531+
// Infomation about capitalization (shift/caps) is already included
532+
// in the original CGEvent, only find out which position on keyboard a key is pressed
533+
NSString *lowercasedKeyString = [keyString lowercaseString];
534+
if (!lowercasedKeyString) {
535+
return fallback;
536+
}
537+
538+
// Ignore code for Modifier keys and numpad
539+
// Reference: https://eastmanreference.com/complete-list-of-applescript-key-codes
540+
NSDictionary *keyStringToKeyCodeMap = @{
541+
// Characters from number row
542+
@"`": @50, @"~": @50, @"1": @18, @"!": @18, @"2": @19, @"@": @19, @"3": @20, @"#": @20, @"4": @21, @"$": @21,
543+
@"5": @23, @"%": @23, @"6": @22, @"^": @22, @"7": @26, @"&": @26, @"8": @28, @"*": @28, @"9": @25, @"(": @25,
544+
@"0": @29, @")": @29, @"-": @27, @"_": @27, @"=": @24, @"+": @24,
545+
// Characters from first keyboard row
546+
@"q": @12, @"w": @13, @"e": @14, @"r": @15, @"t": @17, @"y": @16, @"u": @32, @"i": @34, @"o": @31, @"p": @35,
547+
@"[": @33, @"{": @33, @"]": @30, @"}": @30, @"\\": @42, @"|": @42,
548+
// Characters from second keyboard row
549+
@"a": @0, @"s": @1, @"d": @2, @"f": @3, @"g": @5, @"h": @4, @"j": @38, @"k": @40, @"l": @37,
550+
@";": @41, @":": @41, @"'": @39, @"\"": @39,
551+
// Characters from second third row
552+
@"z": @6, @"x": @7, @"c": @8, @"v": @9, @"b": @11, @"n": @45, @"m": @46,
553+
@",": @43, @"<": @43, @".": @47, @">": @47, @"/": @44, @"?": @44
554+
};
555+
NSNumber *keycode = [keyStringToKeyCodeMap objectForKey:lowercasedKeyString];
556+
557+
if (keycode) {
558+
return [keycode intValue];
559+
}
560+
return fallback;
561+
}
562+
563+
// If conversion fails, return fallbackKeyCode
564+
CGKeyCode ConvertEventToKeyboadLayoutCompatKeyCode(CGEventRef keyEvent, CGKeyCode fallbackKeyCode) {
565+
NSEvent *kbLayoutCompatEvent = [NSEvent eventWithCGEvent:keyEvent];
566+
NSString *kbLayoutCompatKeyString = kbLayoutCompatEvent.charactersIgnoringModifiers;
567+
return ConvertKeyStringToKeyCode(kbLayoutCompatKeyString,
568+
fallbackKeyCode);
569+
}
570+
526571
/**
527572
* MAIN HOOK entry, very important function.
528573
* MAIN Callback.
@@ -536,6 +581,11 @@ CGEventRef OpenKeyCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef e
536581
_flag = CGEventGetFlags(event);
537582
_keycode = (CGKeyCode)CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode);
538583

584+
if (type == kCGEventKeyDown && vPerformLayoutCompat) {
585+
// If conversion fail, use current keycode
586+
_keycode = ConvertEventToKeyboadLayoutCompatKeyCode(event, _keycode);
587+
}
588+
539589
//switch language shortcut; convert hotkey
540590
if (type == kCGEventKeyDown) {
541591
if (GET_SWITCH_KEY(vSwitchKeyStatus) != _keycode && GET_SWITCH_KEY(convertToolHotKey) != _keycode) {

Sources/OpenKey/macOS/ModernKey/ViewController.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
@property (weak) IBOutlet NSButton *ShowIconOnDock;
6262
@property (weak) IBOutlet NSButton *CheckNewVersionOnStartup;
6363
@property (weak) IBOutlet NSButton *FixChromiumBrowser;
64+
@property (weak) IBOutlet NSButton *PerformLayoutCompat;
6465

6566
@property (weak) IBOutlet NSButton *CheckNewVersionButton;
6667
@property (weak) IBOutlet NSTextField *VersionInfo;

Sources/OpenKey/macOS/ModernKey/ViewController.m

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
extern int vShowIconOnDock;
3737
extern int vAutoCapsMacro;
3838
extern int vFixChromiumBrowser;
39+
extern int vPerformLayoutCompat;
3940

4041
@implementation ViewController {
4142
__weak IBOutlet NSButton *CustomSwitchCommand;
@@ -268,6 +269,11 @@ - (IBAction)onSendKeyStepByStep:(id)sender {
268269
vSendKeyStepByStep = (int)val;
269270
}
270271

272+
- (IBAction)onPerformLayoutCompat:(id)sender {
273+
NSInteger val = [self setCustomValue:sender keyToSet:@"vPerformLayoutCompat"];
274+
vPerformLayoutCompat = (int)val;
275+
}
276+
271277
- (NSInteger)setCustomValue:(NSButton*)sender keyToSet:(NSString*) key {
272278
NSInteger val = 0;
273279
if (sender.state == NSControlStateValueOn) {
@@ -444,6 +450,9 @@ -(void)fillData {
444450
self.FixChromiumBrowser.state = value ? NSControlStateValueOn : NSControlStateValueOff;
445451
self.FixChromiumBrowser.enabled = fixRecommendBrowser ? YES : NO;
446452

453+
value = [[NSUserDefaults standardUserDefaults] integerForKey:@"vPerformLayoutCompat"];
454+
self.PerformLayoutCompat.state = value ? NSControlStateValueOn : NSControlStateValueOff;
455+
447456
CustomSwitchControl.state = (vSwitchKeyStatus & 0x100) ? NSControlStateValueOn : NSControlStateValueOff;
448457
CustomSwitchOption.state = (vSwitchKeyStatus & 0x200) ? NSControlStateValueOn : NSControlStateValueOff;
449458
CustomSwitchCommand.state = (vSwitchKeyStatus & 0x400) ? NSControlStateValueOn : NSControlStateValueOff;

Sources/OpenKey/macOS/OpenKey.xcodeproj/project.pbxproj

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,7 @@
308308
232EDA4C21F1B33E0085D362 /* Project object */ = {
309309
isa = PBXProject;
310310
attributes = {
311-
LastUpgradeCheck = 1010;
311+
LastUpgradeCheck = 1130;
312312
ORGANIZATIONNAME = "Tuyen Mai";
313313
TargetAttributes = {
314314
232EDA5321F1B33E0085D362 = {
@@ -548,6 +548,7 @@
548548
buildSettings = {
549549
CLANG_ENABLE_MODULES = NO;
550550
CODE_SIGN_ENTITLEMENTS = ModernKey/ModernKey.entitlements;
551+
CODE_SIGN_IDENTITY = "-";
551552
CODE_SIGN_STYLE = Automatic;
552553
COMBINE_HIDPI_IMAGES = YES;
553554
DEVELOPMENT_TEAM = 7X875U5EVD;
@@ -571,6 +572,7 @@
571572
buildSettings = {
572573
CLANG_ENABLE_MODULES = NO;
573574
CODE_SIGN_ENTITLEMENTS = ModernKey/ModernKey.entitlements;
575+
CODE_SIGN_IDENTITY = "-";
574576
CODE_SIGN_STYLE = Automatic;
575577
COMBINE_HIDPI_IMAGES = YES;
576578
DEVELOPMENT_TEAM = 7X875U5EVD;
@@ -594,6 +596,7 @@
594596
buildSettings = {
595597
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
596598
CODE_SIGN_ENTITLEMENTS = OpenKeyHelper/OpenKeyHelper.entitlements;
599+
CODE_SIGN_IDENTITY = "-";
597600
CODE_SIGN_STYLE = Automatic;
598601
COMBINE_HIDPI_IMAGES = YES;
599602
DEVELOPMENT_TEAM = 7X875U5EVD;
@@ -613,6 +616,7 @@
613616
buildSettings = {
614617
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
615618
CODE_SIGN_ENTITLEMENTS = OpenKeyHelper/OpenKeyHelper.entitlements;
619+
CODE_SIGN_IDENTITY = "-";
616620
CODE_SIGN_STYLE = Automatic;
617621
COMBINE_HIDPI_IMAGES = YES;
618622
DEVELOPMENT_TEAM = 7X875U5EVD;

Sources/OpenKey/macOS/OpenKey.xcodeproj/xcshareddata/xcschemes/OpenKeyHelper.xcscheme

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<Scheme
3-
LastUpgradeVersion = "1010"
3+
LastUpgradeVersion = "1130"
44
version = "1.3">
55
<BuildAction
66
parallelizeBuildables = "YES"
@@ -27,8 +27,6 @@
2727
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
2828
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
2929
shouldUseLaunchSchemeArgsEnv = "YES">
30-
<Testables>
31-
</Testables>
3230
<MacroExpansion>
3331
<BuildableReference
3432
BuildableIdentifier = "primary"
@@ -38,8 +36,8 @@
3836
ReferencedContainer = "container:OpenKey.xcodeproj">
3937
</BuildableReference>
4038
</MacroExpansion>
41-
<AdditionalOptions>
42-
</AdditionalOptions>
39+
<Testables>
40+
</Testables>
4341
</TestAction>
4442
<LaunchAction
4543
buildConfiguration = "Release"
@@ -61,8 +59,6 @@
6159
ReferencedContainer = "container:OpenKey.xcodeproj">
6260
</BuildableReference>
6361
</BuildableProductRunnable>
64-
<AdditionalOptions>
65-
</AdditionalOptions>
6662
</LaunchAction>
6763
<ProfileAction
6864
buildConfiguration = "Release"

0 commit comments

Comments
 (0)