Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Sources/OpenKey/engine/DataType.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ struct vKeyHookState {
#define IS_CONSONANT(keyCode) !(keyCode == KEY_A || keyCode == KEY_E || keyCode == KEY_U || keyCode == KEY_Y || keyCode == KEY_I || keyCode == KEY_O)
//#define IS_MARK_KEY(keyCode) (keyCode == KEY_S || keyCode == KEY_F || keyCode == KEY_R || keyCode == KEY_J || keyCode == KEY_X)
#define CHR(index) (Uint16)TypingWord[index]
// Safer version with bounds checking
#define CHR_SAFE(index) ((index >= 0 && index < MAX_BUFF) ? (Uint16)TypingWord[index] : 0)
#define IS_SPECIALKEY(keyCode) \
(vInputType == vTelex ? \
keyCode == KEY_W || keyCode == KEY_E || keyCode == KEY_R || keyCode == KEY_O || keyCode == KEY_LEFT_BRACKET || \
Expand Down
43 changes: 26 additions & 17 deletions Sources/OpenKey/engine/Engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,30 +93,30 @@ static Uint32 KeyStates[MAX_BUFF];
static Byte _stateIndex = 0;

static bool tempDisableKey = false;
static int capsElem;
static int key;
static int markElem;
static int capsElem = 0;
static int key = 0;
static int markElem = 0;
static bool isCorect = false;
static bool isChanged = false;
static Byte vowelCount = 0;
static Byte vowelStartIndex = 0;
static Byte vowelEndIndex = 0;
static Byte vowelWillSetMark = 0;
static int i, ii, iii;
static int j;
static int k, kk;
static int l;
static bool isRestoredW;
static Uint16 keyForAEO;
static bool isCheckedGrammar;
static int i = 0, ii = 0, iii = 0;
static int j = 0;
static int k = 0, kk = 0;
static int l = 0;
static bool isRestoredW = false;
static Uint16 keyForAEO = 0;
static bool isCheckedGrammar = false;
static bool _isCaps = false;
static int _spaceCount = 0; //add: July 30th, 2019
static bool _hasHandledMacro = false; //for macro flag August 9th, 2019
static Byte _upperCaseStatus = 0; //for Write upper case for the first letter; 2: will upper case
static bool _isCharKeyCode;
static bool _isCharKeyCode = false;
static vector<Uint32> _specialChar;
static bool _useSpellCheckingBefore;
static bool _hasHandleQuickConsonant;
static bool _useSpellCheckingBefore = false;
static bool _hasHandleQuickConsonant = false;
static bool _willTempOffEngine = false;

//function prototype
Expand Down Expand Up @@ -353,7 +353,10 @@ void insertKey(const Uint16& keyCode, const bool& isCaps, const bool& isCheckSpe
for (iii = 0; iii < MAX_BUFF - 1; iii++) {
TypingWord[iii] = TypingWord[iii + 1];
}
setKeyData(_index-1, keyCode, isCaps);
// Fix: Ensure we don't write beyond array bounds
if (_index - 1 < MAX_BUFF) {
setKeyData(_index-1, keyCode, isCaps);
}
} else {
setKeyData(_index++, keyCode, isCaps);
}
Expand All @@ -372,7 +375,10 @@ void insertState(const Uint16& keyCode, const bool& isCaps) {
for (iii = 0; iii < MAX_BUFF - 1; iii++) {
KeyStates[iii] = KeyStates[iii + 1];
}
KeyStates[_stateIndex-1] = keyCode | (isCaps ? CAPS_MASK : 0);
// Fix: Ensure we don't write beyond array bounds
if (_stateIndex - 1 < MAX_BUFF) {
KeyStates[_stateIndex-1] = keyCode | (isCaps ? CAPS_MASK : 0);
}
} else {
KeyStates[_stateIndex++] = keyCode | (isCaps ? CAPS_MASK : 0);
}
Expand Down Expand Up @@ -442,13 +448,16 @@ void restoreLastTypingState() {
_index = 0;
} else if (std::find(_charKeyCode.begin(), _charKeyCode.end(), (Uint16)_typingStatesData[0]) != _charKeyCode.end()) {
_index = 0;
_specialChar = _typingStatesData;
// Fix: Make a proper copy to avoid potential issues
_specialChar.clear();
_specialChar.assign(_typingStatesData.begin(), _typingStatesData.end());
checkSpelling();
} else {
for (i = 0; i < _typingStatesData.size(); i++) {
TypingWord[i] = _typingStatesData[i];
}
_index = (Byte)_typingStatesData.size();
// Fix: Ensure _index doesn't exceed MAX_BUFF
_index = (Byte)min((int)_typingStatesData.size(), MAX_BUFF);
}
}
}
Expand Down
86 changes: 81 additions & 5 deletions Sources/OpenKey/macOS/ModernKey/OpenKey.mm
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// OpenKey
//
// Created by Tuyen on 1/18/19.
// Copyright © 2019 Tuyen Mai. All rights reserved.
// Copyright 2019 Tuyen Mai. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import <Carbon/Carbon.h>
Expand Down Expand Up @@ -52,6 +52,11 @@
NSArray* _niceSpaceApp = @[@"com.sublimetext.3",
@"com.sublimetext.2",
];

// Array of bundle IDs for apps that should be ignored
static NSArray* const IGNORED_BUNDLES = @[
@"com.apple.Spotlight" // Spotlight search
];

//app which error with unicode Compound
NSArray* _unicodeCompoundApp = @[@"com.apple.",
Expand Down Expand Up @@ -85,6 +90,21 @@

NSString* _frontMostApp = @"UnknownApp";

static NSString *lastFocusedAppBundleId = nil;
static pid_t lastFocusedAppPid = -1;
static bool _willUpdateFocusedApp = false;

// Global AX variables
static AXUIElementRef g_systemWide = NULL;

// Cleanup function for AX variables
static void cleanupAXVariables() {
if (g_systemWide) {
CFRelease(g_systemWide);
g_systemWide = NULL;
}
}

void OpenKeyInit() {
//load saved data
vFreeMark = 0;//(int)[[NSUserDefaults standardUserDefaults] integerForKey:@"FreeMark"];
Expand Down Expand Up @@ -143,6 +163,11 @@ void OpenKeyInit() {
}
}

void OpenKeyCleanup() {
cleanupAXVariables();
// ... other cleanup code ...
}

void RequestNewSession() {
//send event signal to Engine
vKeyHandleEvent(vKeyEvent::Mouse, vKeyEventState::MouseDown, 0);
Expand Down Expand Up @@ -182,6 +207,7 @@ void saveSmartSwitchKeyData() {
}

void OnActiveAppChanged() { //use for smart switch key; improved on Sep 28th, 2019
_willUpdateFocusedApp = true;
queryFrontMostApp();
_languageTemp = getAppInputMethodStatus(string(_frontMostApp.UTF8String), vLanguage | (vCodeTable << 1));
if ((_languageTemp & 0x01) != vLanguage) { //for input method
Expand Down Expand Up @@ -571,10 +597,45 @@ CGKeyCode ConvertEventToKeyboadLayoutCompatKeyCode(CGEventRef keyEvent, CGKeyCod
fallbackKeyCode);
}

void updateFocusedAppBundleId() {
if (!g_systemWide) {
g_systemWide = AXUIElementCreateSystemWide();
}

AXUIElementRef focusedApp = NULL;
AXError result = AXUIElementCopyAttributeValue(g_systemWide, kAXFocusedApplicationAttribute, (CFTypeRef*)&focusedApp);

if (result == kAXErrorSuccess && focusedApp) {
pid_t pid = 0;
AXUIElementGetPid(focusedApp, &pid);

// Check if the focused app has changed
if (pid != lastFocusedAppPid) {
NSRunningApplication *app = [NSRunningApplication runningApplicationWithProcessIdentifier:pid];
lastFocusedAppBundleId = app.bundleIdentifier;
lastFocusedAppPid = pid;
}

CFRelease(focusedApp);
return;
} else {
// Fallback to NSWorkspace when AX API fails
NSRunningApplication *frontApp = [[NSWorkspace sharedWorkspace] frontmostApplication];
if (frontApp && frontApp.processIdentifier != lastFocusedAppPid) {
lastFocusedAppBundleId = frontApp.bundleIdentifier;
lastFocusedAppPid = frontApp.processIdentifier;
}
}

if (focusedApp) {
CFRelease(focusedApp);
}
}

/**
* MAIN HOOK entry, very important function.
* MAIN Callback.
*/
*/
CGEventRef OpenKeyCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
//dont handle my event
if (CGEventGetIntegerValueField(event, kCGEventSourceStateID) == CGEventSourceGetSourceStateID(myEventSource)) {
Expand Down Expand Up @@ -663,6 +724,7 @@ CGEventRef OpenKeyCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef e

//handle mouse
if (type == kCGEventLeftMouseDown || type == kCGEventRightMouseDown || type == kCGEventLeftMouseDragged || type == kCGEventRightMouseDragged) {
_willUpdateFocusedApp = true;
RequestNewSession();
return event;
}
Expand All @@ -677,7 +739,7 @@ CGEventRef OpenKeyCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef e
if (CFArrayGetCount(languages) > 0) {
CFStringRef langRef = (CFStringRef)CFArrayGetValueAtIndex(languages, 0);
NSString *currentLanguage = (__bridge NSString *)langRef;
if(![currentLanguage isLike:@"en"]){
if(![currentLanguage isLike:@"en"] && ![currentLanguage isLike:@""]){ // empty for "unicode hex input"
return event;
}
CFRelease(langRef);
Expand All @@ -688,6 +750,21 @@ CGEventRef OpenKeyCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef e

//handle keyboard
if (type == kCGEventKeyDown) {

//update focused app
if (_willUpdateFocusedApp) {
updateFocusedAppBundleId();
_willUpdateFocusedApp = false;
}
if (OTHER_CONTROL_KEY) {
_willUpdateFocusedApp = true;
}

//ignore some apps
if (lastFocusedAppBundleId && [IGNORED_BUNDLES containsObject:lastFocusedAppBundleId]) {
return event;
}

//send event signal to Engine
vKeyHandleEvent(vKeyEvent::Keyboard,
vKeyEventState::KeyDown,
Expand All @@ -707,7 +784,6 @@ CGEventRef OpenKeyCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef e
}
_syncKey.pop_back();
}

} else if (pData->extCode == 3) { //normal key
InsertKeyLength(1);
}
Expand All @@ -732,7 +808,7 @@ CGEventRef OpenKeyCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef e

//send backspace
if (pData->backspaceCount > 0 && pData->backspaceCount < MAX_BUFF) {
for (_i = 0; _i < pData->backspaceCount; _i++) {
for (int i = 0; i < pData->backspaceCount; i++) {
SendBackspace();
}
}
Expand Down
6 changes: 4 additions & 2 deletions Sources/OpenKey/macOS/OpenKey.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,7 @@
buildSettings = {
CLANG_ENABLE_MODULES = NO;
CODE_SIGN_IDENTITY = "Mac Developer";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 48;
Expand All @@ -580,7 +581,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.10;
MACOSX_DEPLOYMENT_TARGET = 11.5;
MARKETING_VERSION = 2.0.4;
OTHER_LDFLAGS = (
"-lc++\n-lc++",
Expand All @@ -596,6 +597,7 @@
buildSettings = {
CLANG_ENABLE_MODULES = NO;
CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 48;
Expand All @@ -606,7 +608,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.10;
MACOSX_DEPLOYMENT_TARGET = 11.5;
MARKETING_VERSION = 2.0.4;
OTHER_LDFLAGS = (
"-lc++\n-lc++",
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<VariablesViewState
version = "1.0">
<ContextStates>
<ContextState
contextName = "OpenKeyCallback:OpenKey.mm">
<PersistentStrings>
<PersistentString
value = "OTHER_CONTROL_KEY">
</PersistentString>
</PersistentStrings>
</ContextState>
</ContextStates>
</VariablesViewState>
Loading