Skip to content
Open
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
18 changes: 14 additions & 4 deletions sources/SquirrelApplicationDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -236,10 +236,13 @@ final class SquirrelApplicationDelegate: NSObject, NSApplicationDelegate, SPUSta
notifCenter.addObserver(forName: .init("SquirrelSyncNotification"), object: nil, queue: nil, using: rimeNeedsSync)
notifCenter.addObserver(forName: .init("SquirrelToggleASCIIModeNotification"), object: nil, queue: nil, using: rimeToggleASCIIMode)
notifCenter.addObserver(forName: .init("SquirrelGetASCIIModeNotification"), object: nil, queue: nil, using: rimeGetASCIIMode)
notifCenter.addObserver(forName: .init(kTISNotifySelectedKeyboardInputSourceChanged as String), object: nil, queue: .main) { [weak self] _ in
self?.updateStatusItemVisibility()
self?.finalizeStrandedComposition()
}
// Suspension behavior matters: the default coalescing holds notifications
// back while the process is inactive, which is exactly the state Squirrel
// enters when the user switches away — the icon would fail to hide until
// the next activation. Deliver immediately instead.
notifCenter.addObserver(self, selector: #selector(inputSourceChanged(_:)),
name: .init(kTISNotifySelectedKeyboardInputSourceChanged as String),
object: nil, suspensionBehavior: .deliverImmediately)
}

func applicationShouldTerminate(_ sender: NSApplication) -> NSApplication.TerminateReply {
Expand Down Expand Up @@ -361,6 +364,13 @@ private extension SquirrelApplicationDelegate {
updateStatusItemVisibility()
}

@objc func inputSourceChanged(_: Notification) {
DispatchQueue.main.async { [weak self] in
self?.updateStatusItemVisibility()
self?.finalizeStrandedComposition()
}
}

func updateStatusItemVisibility() {
guard let statusItem = statusItem else { return }
let currentInputSourceID = SquirrelInstaller.currentInputSourceID() ?? ""
Expand Down
24 changes: 24 additions & 0 deletions sources/SquirrelInputController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,30 @@
if keyboardLayout != "" {
client?.overrideKeyboard(withKeyboardNamed: keyboardLayout)
}
// Switching to Squirrel produces no flagsChanged event, so a Caps Lock
// already engaged in the previous input source would go unnoticed by Rime.
// NSEvent.modifierFlags only reflects this process's own event stream and
// is stale here; query the session-wide hardware state instead.
let capsLockOn = CGEventSource.flagsState(.combinedSessionState).contains(.maskAlphaShift)
// Do NOT force ascii_mode from a pre-existing Caps Lock here: macOS clears
// Caps Lock whenever the input source changes, so a Caps Lock observed at
// activation is transient — acting on it raced against that clearing and
// left ascii_mode stuck on with no way for Rime to learn caps was dropped.
// Instead, only repaint the icon from the session's actual state; it may
// be stale because a fresh session created with switches/@N/reset: 1
// never fires an option notification.
if session != 0 && rimeAPI.find_session(session) {
let asciiMode = rimeAPI.get_option(session, "ascii_mode")
let label = "ascii_mode".withCString { name in
rimeAPI.get_state_label_abbreviated(session, name, asciiMode, true).asString
}
NSApp.squirrelAppDelegate.updateStatusIcon(asciiMode: asciiMode, schemaLabel: label)
}
if capsLockOn {
lastModifiers.insert(.capsLock)
} else {
lastModifiers.remove(.capsLock)
}
preedit = ""
if session != 0 {
let state = rimeAPI.get_option(session, "ascii_mode")
Expand Down Expand Up @@ -434,7 +458,7 @@
}

// Preserve reserved comment marks when librime requests a UI-only refresh.
func rimeUpdate(clearReservedComments: Bool = true) {

Check warning on line 461 in sources/SquirrelInputController.swift

View workflow job for this annotation

GitHub Actions / build

Function should have complexity 10 or less; currently complexity is 13 (cyclomatic_complexity)
if clearReservedComments {
specialCommentIndices = [:]
}
Expand Down
Loading