Активировать нативный черновик до записи
This commit is contained in:
@@ -42,7 +42,9 @@ final class NativeCompositionBridge: NSObject {
|
|||||||
name: Message.ready,
|
name: Message.ready,
|
||||||
object: nil
|
object: nil
|
||||||
)
|
)
|
||||||
registerInstalledInputMethod()
|
if inputSource(withID: Self.inputSourceID) == nil {
|
||||||
|
registerInstalledInputMethod()
|
||||||
|
}
|
||||||
launchInputMethod()
|
launchInputMethod()
|
||||||
ping()
|
ping()
|
||||||
}
|
}
|
||||||
@@ -50,7 +52,6 @@ final class NativeCompositionBridge: NSObject {
|
|||||||
func activateForDictation() -> Bool {
|
func activateForDictation() -> Bool {
|
||||||
restoreWorkItem?.cancel()
|
restoreWorkItem?.cancel()
|
||||||
restoreWorkItem = nil
|
restoreWorkItem = nil
|
||||||
registerInstalledInputMethod()
|
|
||||||
launchInputMethod()
|
launchInputMethod()
|
||||||
|
|
||||||
guard let source = inputSource(withID: Self.inputSourceID) else { return false }
|
guard let source = inputSource(withID: Self.inputSourceID) else { return false }
|
||||||
@@ -58,11 +59,11 @@ final class NativeCompositionBridge: NSObject {
|
|||||||
if currentID != Self.inputSourceID {
|
if currentID != Self.inputSourceID {
|
||||||
previousInputSourceID = currentID
|
previousInputSourceID = currentID
|
||||||
}
|
}
|
||||||
guard TISEnableInputSource(source) == noErr,
|
guard TISSelectInputSource(source) == noErr else {
|
||||||
TISSelectInputSource(source) == noErr else {
|
|
||||||
restoreInputSource()
|
restoreInputSource()
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
wakeInputMethod()
|
||||||
ping()
|
ping()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -146,6 +147,29 @@ final class NativeCompositionBridge: NSObject {
|
|||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3, execute: work)
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3, execute: work)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func wakeInputMethod() {
|
||||||
|
guard let source = CGEventSource(stateID: .hidSystemState) else { return }
|
||||||
|
let flags: CGEventFlags = [
|
||||||
|
.maskCommand,
|
||||||
|
.maskAlternate,
|
||||||
|
.maskControl,
|
||||||
|
.maskShift,
|
||||||
|
]
|
||||||
|
guard let keyDown = CGEvent(
|
||||||
|
keyboardEventSource: source,
|
||||||
|
virtualKey: CGKeyCode(kVK_F20),
|
||||||
|
keyDown: true
|
||||||
|
), let keyUp = CGEvent(
|
||||||
|
keyboardEventSource: source,
|
||||||
|
virtualKey: CGKeyCode(kVK_F20),
|
||||||
|
keyDown: false
|
||||||
|
) else { return }
|
||||||
|
keyDown.flags = flags
|
||||||
|
keyUp.flags = flags
|
||||||
|
keyDown.post(tap: .cghidEventTap)
|
||||||
|
keyUp.post(tap: .cghidEventTap)
|
||||||
|
}
|
||||||
|
|
||||||
private func inputSource(withID identifier: String) -> TISInputSource? {
|
private func inputSource(withID identifier: String) -> TISInputSource? {
|
||||||
guard let sources = TISCreateInputSourceList(nil, true)?.takeRetainedValue()
|
guard let sources = TISCreateInputSourceList(nil, true)?.takeRetainedValue()
|
||||||
as? [TISInputSource] else {
|
as? [TISInputSource] else {
|
||||||
|
|||||||
@@ -87,6 +87,12 @@ private final class CompositionCoordinator: @unchecked Sendable {
|
|||||||
@objc(WhisperKeyInputController)
|
@objc(WhisperKeyInputController)
|
||||||
final class WhisperKeyInputController: IMKInputController {
|
final class WhisperKeyInputController: IMKInputController {
|
||||||
private var draft = ""
|
private var draft = ""
|
||||||
|
private static let wakeModifiers: NSEvent.ModifierFlags = [
|
||||||
|
.command,
|
||||||
|
.option,
|
||||||
|
.control,
|
||||||
|
.shift,
|
||||||
|
]
|
||||||
|
|
||||||
override init!(server: IMKServer!, delegate: Any!, client inputClient: Any!) {
|
override init!(server: IMKServer!, delegate: Any!, client inputClient: Any!) {
|
||||||
super.init(server: server, delegate: delegate, client: inputClient)
|
super.init(server: server, delegate: delegate, client: inputClient)
|
||||||
@@ -118,6 +124,16 @@ final class WhisperKeyInputController: IMKInputController {
|
|||||||
super.inputControllerWillClose()
|
super.inputControllerWillClose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func handle(_ event: NSEvent!, client sender: Any!) -> Bool {
|
||||||
|
let isWakeEvent = event.type == .keyDown
|
||||||
|
&& event.keyCode == UInt16(kVK_F20)
|
||||||
|
&& event.modifierFlags.contains(Self.wakeModifiers)
|
||||||
|
if isWakeEvent {
|
||||||
|
inputLog.notice("wake event consumed")
|
||||||
|
}
|
||||||
|
return isWakeEvent
|
||||||
|
}
|
||||||
|
|
||||||
func setDraft(_ text: String) {
|
func setDraft(_ text: String) {
|
||||||
inputLog.notice(
|
inputLog.notice(
|
||||||
"setting marked text for \(self.client().bundleIdentifier(), privacy: .public)"
|
"setting marked text for \(self.client().bundleIdentifier(), privacy: .public)"
|
||||||
|
|||||||
Reference in New Issue
Block a user