Skip to content

Commit

Permalink
special key equivalents
Browse files Browse the repository at this point in the history
  • Loading branch information
groverlynn committed May 15, 2024
1 parent 9f0ad15 commit 4460598
Show file tree
Hide file tree
Showing 12 changed files with 370 additions and 323 deletions.
2 changes: 1 addition & 1 deletion Base.lproj/MainMenu.xib
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
<customObject id="770" userLabel="SquirrelPanel" customClass="SquirrelPanel"/>
<menu id="773" userLabel="Menu">
<items>
<menuItem title="Squirrel Switcher" allowsKeyEquivalentWhenHidden="YES" id="780">
<menuItem title="ㄓ⃣Squirrel Switcher" id="780">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="showSwitcher:" target="252" id="781"/>
Expand Down
36 changes: 17 additions & 19 deletions SquirrelApplicationDelegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ @implementation SquirrelApplicationDelegate {

- (IBAction)showSwitcher:(id)sender {
NSLog(@"Show Switcher");
RimeSessionId session = [sender unsignedLongValue];
rime_get_api()->process_key(session, _switcherKeyEquivalent,
_switcherKeyModifierMask);
if (_switcherKeyEquivalent) {
RimeSessionId session = [sender unsignedLongValue];
rime_get_api()->process_key(session, _switcherKeyEquivalent,
_switcherKeyModifierMask);
}
}

- (IBAction)deploy:(id)sender {
Expand Down Expand Up @@ -207,7 +209,7 @@ - (void)startRimeWithFullCheck:(BOOL)fullCheck {
NSLog(@"Initializing la rime...");
rime_get_api()->initialize(NULL);
// check for configuration updates
if (rime_get_api()->start_maintenance((Bool)fullCheck)) {
if (rime_get_api()->start_maintenance(fullCheck)) {
// update squirrel config
rime_get_api()->deploy_config_file("squirrel.yaml", "config_version");
}
Expand All @@ -219,32 +221,28 @@ - (void)shutdownRime {
}

- (void)loadSettings {
_switcherKeyModifierMask = 0;
_switcherKeyEquivalent = 0;
SquirrelConfig* defaultConfig = SquirrelConfig.alloc.init;
if ([defaultConfig openWithConfigId:@"default"]) {
NSString* hotKeys =
NSString* hotkey =
[defaultConfig getStringForOption:@"switcher/hotkeys/@0"];
NSArray<NSString*>* keys = [hotKeys componentsSeparatedByString:@"+"];
NSEventModifierFlags modifiers = 0;
int rime_modifiers = 0;
for (NSUInteger i = 0; i < keys.count - 1; ++i) {
modifiers |= parse_macos_modifiers(keys[i].UTF8String);
rime_modifiers |= parse_rime_modifiers(keys[i].UTF8String);
if (hotkey) {
NSArray<NSString*>* keys = [hotkey componentsSeparatedByString:@"+"];
for (NSUInteger i = 0; i < keys.count - 1; ++i) {
_switcherKeyModifierMask |=
rime_modifiers_from_name(keys[i].UTF8String);
}
_switcherKeyEquivalent =
rime_keycode_from_name(keys.lastObject.UTF8String);
}
int keycode = parse_keycode(keys.lastObject.UTF8String);
unichar keychar = keycode <= 0xFFFF ? (unichar)keycode : 0;
_menu.itemArray[0].keyEquivalent = [NSString stringWithCharacters:&keychar
length:1];
_menu.itemArray[0].keyEquivalentModifierMask = modifiers;
_switcherKeyEquivalent = keycode;
_switcherKeyModifierMask = rime_modifiers;
}
[defaultConfig close];

_config = SquirrelConfig.alloc.init;
if (!_config.openBaseConfig) {
return;
}

NSString* showNotificationsWhen =
[_config getStringForOption:@"show_notifications_when"];
if ([@"never" caseInsensitiveCompare:showNotificationsWhen] ==
Expand Down
2 changes: 1 addition & 1 deletion SquirrelConfig.hh
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ typedef NSDictionary<NSString*, NSNumber*> SquirrelAppOptions;
- (BOOL)setOption:(NSString* _Nonnull)option
withString:(NSString* _Nonnull)value;

- (BOOL)getBoolForOption:(NSString* _Nonnull)option;
- (bool)getBoolForOption:(NSString* _Nonnull)option;
- (int)getIntForOption:(NSString* _Nonnull)option;
- (double)getDoubleForOption:(NSString* _Nonnull)option;
- (double)getDoubleForOption:(NSString* _Nonnull)option
Expand Down
10 changes: 5 additions & 5 deletions SquirrelConfig.mm
Original file line number Diff line number Diff line change
Expand Up @@ -247,21 +247,21 @@ - (BOOL)setOption:(NSString*)option withString:(NSString*)value {
value.UTF8String));
}

- (BOOL)getBoolForOption:(NSString*)option {
return [self getOptionalBoolForOption:option].boolValue;
- (bool)getBoolForOption:(NSString*)option {
return [self getOptionalBoolForOption:option alias:nil].boolValue;
}

- (int)getIntForOption:(NSString*)option {
return [self getOptionalIntForOption:option].intValue;
return [self getOptionalIntForOption:option alias:nil].intValue;
}

- (double)getDoubleForOption:(NSString*)option {
return [self getOptionalDoubleForOption:option].doubleValue;
return [self getOptionalDoubleForOption:option alias:nil].doubleValue;
}

- (double)getDoubleForOption:(NSString*)option
applyConstraint:(double (*)(double param))func {
NSNumber* value = [self getOptionalDoubleForOption:option];
NSNumber* value = [self getOptionalDoubleForOption:option alias:nil];
return func(value.doubleValue);
}

Expand Down
113 changes: 60 additions & 53 deletions SquirrelInputController.mm
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ - (BOOL)handleEvent:(NSEvent*)event client:(id)sender {
}
NSEventModifierFlags modifiers =
event.modifierFlags & NSEventModifierFlagDeviceIndependentFlagsMask;
int rime_modifiers = get_rime_modifiers(modifiers);
int rime_modifiers = rime_modifiers_from_mac_modifiers(modifiers);
ushort keyCode = (ushort)CGEventGetIntegerValueField(
event.CGEvent, kCGKeyboardEventKeycode);

Expand All @@ -98,7 +98,7 @@ - (BOOL)handleEvent:(NSEvent*)event client:(id)sender {
// NSLog(@"FLAGSCHANGED client: %@, modifiers: 0x%lx", sender,
// modifiers);
int release_mask = 0;
int rime_keycode = get_rime_keycode(keyCode, 0, false, false);
int rime_keycode = rime_keycode_from_mac_keycode(keyCode);
uint eventCount =
CGEventSourceCounterForEventType(
kCGEventSourceStateCombinedSessionState, kCGEventFlagsChanged) +
Expand Down Expand Up @@ -189,27 +189,29 @@ - (BOOL)handleEvent:(NSEvent*)event client:(id)sender {
_lastEventCount = eventCount;
} break;
case NSEventTypeKeyDown: {
NSString* keyChars = ((modifiers & NSEventModifierFlagShift) &&
!(modifiers & NSEventModifierFlagControl) &&
!(modifiers & NSEventModifierFlagOption))
? event.characters
: event.charactersIgnoringModifiers;
// NSLog(@"KEYDOWN client: %@, modifiers: 0x%lx, keyCode: %d, keyChars:
// [%@]",
// sender, modifiers, keyCode, keyChars);

// translate osx keyevents to rime keyevents
int rime_keycode =
get_rime_keycode(keyCode, [keyChars characterAtIndex:0],
(modifiers & NSEventModifierFlagShift) != 0,
(modifiers & NSEventModifierFlagCapsLock) != 0);
if (rime_keycode != XK_VoidSymbol) {
// translate mac keydown events to rime keyevents
int rime_keycode = rime_keycode_from_mac_keycode(keyCode);
if (!rime_keycode) {
NSString* keyChars = ((modifiers & NSEventModifierFlagShift) &&
!(modifiers & (NSEventModifierFlagControl |
NSEventModifierFlagOption)))
? event.characters
: event.charactersIgnoringModifiers;
keyChars = keyChars.precomposedStringWithCanonicalMapping;
rime_keycode = rime_keycode_from_keychar(
[keyChars characterAtIndex:0],
(modifiers & NSEventModifierFlagShift) != 0,
(modifiers & NSEventModifierFlagCapsLock) != 0);
} else if ((keyCode <= 0xff && keyCode >= 0x60) || keyCode == 0x50 ||
keyCode == 0x4f || keyCode == 0x47 || keyCode == 0x40) {
// revert non-modifier function keys' FunctionKeyMask (FwdDel,
// Navigations, F1..F19)
if ((keyCode <= 0xff && keyCode >= 0x60) || keyCode == 0x50 ||
keyCode == 0x4f || keyCode == 0x47 || keyCode == 0x40) {
rime_modifiers ^= kHyperMask;
}
rime_modifiers ^= kHyperMask;
}
if (rime_keycode) {
if ((handled = [self processKey:rime_keycode
modifiers:rime_modifiers])) {
[self rimeUpdate];
Expand Down Expand Up @@ -288,12 +290,12 @@ - (BOOL)processKey:(int)rime_keycode
modifiers:(int)rime_modifiers __attribute__((objc_direct)) {
SquirrelPanel* panel = NSApp.squirrelAppDelegate.panel;
// with linear candidate list, arrow keys may behave differently.
Bool is_linear = (Bool)panel.linear;
bool is_linear = panel.linear;
if (is_linear != rime_get_api()->get_option(_session, "_linear")) {
rime_get_api()->set_option(_session, "_linear", is_linear);
}
// with vertical text, arrow keys may behave differently.
Bool is_vertical = (Bool)panel.vertical;
bool is_vertical = panel.vertical;
if (is_vertical != rime_get_api()->get_option(_session, "_vertical")) {
rime_get_api()->set_option(_session, "_vertical", is_vertical);
}
Expand Down Expand Up @@ -323,8 +325,8 @@ - (BOOL)processKey:(int)rime_keycode
}
}

BOOL handled =
(BOOL)rime_get_api()->process_key(_session, rime_keycode, rime_modifiers);
bool handled =
rime_get_api()->process_key(_session, rime_keycode, rime_modifiers);
// NSLog(@"rime_keycode: 0x%x, rime_modifiers: 0x%x, handled = %d",
// rime_keycode, rime_modifiers, handled);

Expand Down Expand Up @@ -618,6 +620,10 @@ - (void)activateServer:(id)sender {
[self showInitialStatus];
}
}

_lastModifiers = 0;
_lastEventCount = 0;
NSApp.squirrelAppDelegate.panel.IbeamRect = NSZeroRect;
[super activateServer:sender];
}

Expand Down Expand Up @@ -770,8 +776,8 @@ - (void)showPlaceholder:(NSString*)placeholder __attribute__((objc_direct)) {
[self markForStyle:kTSMHiliteSelectedRawText
atRange:NSMakeRange(0, placeholder ? placeholder.length : 1)];
_preeditString =
[[NSMutableAttributedString alloc] initWithString:placeholder ?: @""
attributes:attrs];
[NSMutableAttributedString.alloc initWithString:placeholder ?: @""
attributes:attrs];
_inlineCaretPos = 0;
[self updateComposition];
}
Expand All @@ -790,8 +796,8 @@ - (void)showPreeditString:(NSString*)preedit
// range.location, range.length, pos);
NSDictionary* attrs = [self markForStyle:kTSMHiliteRawText
atRange:NSMakeRange(0, preedit.length)];
_preeditString = [[NSMutableAttributedString alloc] initWithString:preedit
attributes:attrs];
_preeditString = [NSMutableAttributedString.alloc initWithString:preedit
attributes:attrs];
if (range.location > 0) {
[_preeditString
addAttributes:[self markForStyle:kTSMHiliteConvertedText
Expand Down Expand Up @@ -885,7 +891,6 @@ - (void)showPanelWithPreedit:(NSString*)preedit
if (NSIsEmptyRect(panel.IbeamRect) && panel.statusMessage.length > 0) {
[panel updateStatusLong:nil statusShort:nil];
} else {
_candidateIndices = candidateIndices;
[panel showPreedit:preedit
selRange:selRange
caretPos:caretPos
Expand All @@ -910,7 +915,7 @@ - (void)createSession __attribute__((objc_direct)) {
for (NSString* key in appOptions) {
NSNumber* number = appOptions[key];
if (strcmp(number.objCType, @encode(BOOL)) == 0) {
Bool value = number.intValue;
Bool value = number.boolValue;
// NSLog(@"set app option: %@ = %d", key, value);
rime_get_api()->set_option(_session, key.UTF8String, value);
}
Expand All @@ -923,9 +928,6 @@ - (void)createSession __attribute__((objc_direct)) {
}
_currentApp = app;
_asciiMode = -1;
_lastModifiers = 0;
_lastEventCount = 0;
NSApp.squirrelAppDelegate.panel.IbeamRect = NSZeroRect;
[self rimeUpdate];
}
}
Expand Down Expand Up @@ -957,14 +959,22 @@ - (BOOL)rimeConsumeCommittedText __attribute__((objc_direct)) {
return NO;
}

static NSUInteger inline UTF8LengthToUTF16Length(const char* string,
static inline NSUInteger UTF8LengthToUTF16Length(const char* string,
int length) {
return [[NSString alloc] initWithBytes:string
length:(NSUInteger)length
encoding:NSUTF8StringEncoding]
return [NSString.alloc initWithBytes:string
length:(NSUInteger)length
encoding:NSUTF8StringEncoding]
.length;
}

static inline NSUInteger fmin(NSUInteger int_a, NSUInteger int_b) {
return int_a < int_b ? int_a : int_b;
}

static inline NSUInteger fmax(NSUInteger int_a, NSUInteger int_b) {
return int_a < int_b ? int_b : int_a;
}

- (void)rimeUpdate __attribute__((objc_direct)) {
// NSLog(@"rimeUpdate");
BOOL didCommit = self.rimeConsumeCommittedText;
Expand Down Expand Up @@ -1002,11 +1012,11 @@ - (void)rimeUpdate __attribute__((objc_direct)) {
BOOL showingStatus = panel.statusMessage.length > 0;
// update preedit text
const char* preedit = ctx.composition.preedit;
NSString* preeditText = preedit ? @(preedit) : @"";
NSString* preeditText = @(preedit ?: "");

// update raw input
const char* raw_input = rime_get_api()->get_input(_session);
NSString* originalString = raw_input ? @(raw_input) : @"";
NSString* originalString = @(raw_input ?: "");
didCompose |= ![originalString isEqualToString:_originalString];
_originalString = originalString;

Expand Down Expand Up @@ -1041,7 +1051,7 @@ - (void)rimeUpdate __attribute__((objc_direct)) {
BOOL finalPage = (BOOL)ctx.menu.is_last_page;

NSRange selRange = NSMakeRange(start, end - start);
didCompose |= !NSEqualRanges(_selRange, selRange);
didCompose |= !NSEqualRanges(_selRange, selRange) && pageNum == 0;
_selRange = selRange;
// update expander and section status in tabular layout;
// already processed the action if _currentIndex == NSNotFound
Expand All @@ -1060,25 +1070,24 @@ - (void)rimeUpdate __attribute__((objc_direct)) {
if (panel.expanded && pageNum > currentPageNum &&
panel.sectionNum < (panel.vertical ? 2 : 4)) {
panel.sectionNum =
MIN(panel.sectionNum + pageNum - currentPageNum,
(finalPage ? 4UL : 3UL) - (panel.vertical ? 2UL : 0UL));
fmin(panel.sectionNum + pageNum - currentPageNum,
(finalPage ? 4UL : 3UL) - (panel.vertical ? 2UL : 0UL));
} else if (panel.expanded && pageNum < currentPageNum &&
panel.sectionNum > 0) {
panel.sectionNum = MAX(panel.sectionNum + pageNum - currentPageNum,
pageNum == 0 ? 0UL : 1UL);
panel.sectionNum = fmax(panel.sectionNum + pageNum - currentPageNum,
pageNum == 0 ? 0UL : 1UL);
}
}
highlightedIndex += pageSize * panel.sectionNum;
}
NSUInteger extraCandidates =
panel.expanded && caretPos >= end
panel.expanded
? (finalPage ? panel.sectionNum : (panel.vertical ? 2 : 4)) *
pageSize
: 0;
NSRange candidateIndices =
NSMakeRange((pageNum - panel.sectionNum) * pageSize,
numCandidates + extraCandidates);
_currentIndex = highlightedIndex + candidateIndices.location;
_candidateIndices = NSMakeRange((pageNum - panel.sectionNum) * pageSize,
numCandidates + extraCandidates);
_currentIndex = highlightedIndex + _candidateIndices.location;

if (showingStatus) {
[self clearBuffer];
Expand Down Expand Up @@ -1142,14 +1151,12 @@ - (void)rimeUpdate __attribute__((objc_direct)) {
}
}

// overwrite old cached candidates (index = 0) OR continue cache more
// candidates
// cache candidates
if (didCompose || numCandidates == 0) {
[_candidateTexts removeAllObjects];
[_candidateComments removeAllObjects];
}
NSUInteger index = _candidateTexts.count;
// cache candidates
if (index < pageSize * pageNum) {
RimeCandidateListIterator iterator;
if (rime_get_api()->candidate_list_from_index(_session, &iterator,
Expand All @@ -1167,7 +1174,7 @@ - (void)rimeUpdate __attribute__((objc_direct)) {
[self updateCandidate:&ctx.menu.candidates[i] atIndex:index++];
}
}
if (index < NSMaxRange(candidateIndices)) {
if (index < NSMaxRange(_candidateIndices)) {
RimeCandidateListIterator iterator;
if (rime_get_api()->candidate_list_from_index(_session, &iterator,
(int)index)) {
Expand All @@ -1178,7 +1185,7 @@ - (void)rimeUpdate __attribute__((objc_direct)) {
[self updateCandidate:&iterator.candidate atIndex:index++];
}
rime_get_api()->candidate_list_end(&iterator);
candidateIndices.length = index - candidateIndices.location;
_candidateIndices.length = index - _candidateIndices.location;
}
}
// remove old candidates that were not overwritted, if any, subscripted from
Expand All @@ -1190,7 +1197,7 @@ - (void)rimeUpdate __attribute__((objc_direct)) {
: preeditText
selRange:selRange
caretPos:_showingSwitcherMenu ? NSNotFound : caretPos
candidateIndices:candidateIndices
candidateIndices:_candidateIndices
highlightedIndex:highlightedIndex
pageNum:pageNum
finalPage:finalPage
Expand Down
Loading

0 comments on commit 4460598

Please sign in to comment.