From 8baf408c8137e229c500cf62c5fca0698f527874 Mon Sep 17 00:00:00 2001 From: georgealbert Date: Sun, 6 Feb 2022 15:35:25 +0800 Subject: [PATCH 1/5] * NvimView.swift: save ime status in vars --- NvimView/Sources/NvimView/NvimView.swift | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/NvimView/Sources/NvimView/NvimView.swift b/NvimView/Sources/NvimView/NvimView.swift index 88e48777..9c2fca17 100644 --- a/NvimView/Sources/NvimView/NvimView.swift +++ b/NvimView/Sources/NvimView/NvimView.swift @@ -3,6 +3,7 @@ * See LICENSE */ +import Carbon import Cocoa import Commons import MessagePack @@ -213,6 +214,9 @@ public class NvimView: NSView, self.cellSize = FontUtils.cellSize( of: self.font, linespacing: self.linespacing, characterspacing: self.characterspacing ) + + self.asciiImSource = nil + self.lastImSource = nil } override public convenience init(frame rect: NSRect) { @@ -297,6 +301,9 @@ public class NvimView: NSView, var tabEntries = [TabEntry]() + var asciiImSource : TISInputSource? + var lastImSource : TISInputSource? + // MARK: - Private private var _linespacing = NvimView.defaultLinespacing From 5964544a04298bc6cfc2316375a9ae82b0ac05da Mon Sep 17 00:00:00 2001 From: georgealbert Date: Sun, 6 Feb 2022 15:37:40 +0800 Subject: [PATCH 2/5] * NvimView+UIBridge.swift: support ime auto switch between normal and insert mode --- .../Sources/NvimView/NvimView+UiBridge.swift | 70 ++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/NvimView/Sources/NvimView/NvimView+UiBridge.swift b/NvimView/Sources/NvimView/NvimView+UiBridge.swift index 0b43a126..2adaf5d4 100644 --- a/NvimView/Sources/NvimView/NvimView+UiBridge.swift +++ b/NvimView/Sources/NvimView/NvimView+UiBridge.swift @@ -3,7 +3,9 @@ * See LICENSE */ +import Carbon import Cocoa +import Foundation import MessagePack import NvimServerTypes import RxPack @@ -47,10 +49,28 @@ extension NvimView { } } + private func activateIm(enabled: Bool) { + if (self.asciiImSource == nil) { + self.asciiImSource = TISCopyCurrentASCIICapableKeyboardInputSource().takeRetainedValue() + // self.asciiImSource = TISCopyCurrentASCIICapableKeyboardInputSource().takeUnretainedValue() + self.bridgeLogger.info("ascii IME id: \(asciiImSource!.id), source: \(asciiImSource)") + } + + if enabled { + // In insert mode, set ime to last ime source + TISSelectInputSource(self.lastImSource) + } else { + // In normal mode, se ime to ascii input source + self.lastImSource = TISCopyCurrentKeyboardInputSource().takeRetainedValue() + TISSelectInputSource(self.asciiImSource) + } + + self.bridgeLogger.debug("lastImSource id: \(lastImSource!.id), source: \(lastImSource)") + } + final func modeChange(_ value: MessagePackValue) { guard let mode = MessagePackUtils.value( from: value, conversion: { v -> CursorModeShape? in - guard let rawValue = v.intValue else { return nil } return CursorModeShape(rawValue: UInt(rawValue)) } @@ -60,11 +80,20 @@ extension NvimView { } self.bridgeLogger.debug(self.name(ofCursorMode: mode)) + // self.bridgeLogger.info(self.name(ofCursorMode: mode)) gui.async { self.mode = mode self.markForRender( region: self.cursorRegion(for: self.ugrid.cursorPosition) ) + + if self.name(ofCursorMode: mode) == "Normal" { + self.activateIm(enabled: false) + } + + if self.name(ofCursorMode: mode) == "Insert" { + self.activateIm(enabled: true) + } } } @@ -674,4 +703,43 @@ extension NvimView { } } +extension TISInputSource { + enum Category { + static var keyboardInputSource: String { + return kTISCategoryKeyboardInputSource as String + } + } + + private func getProperty(_ key: CFString) -> AnyObject? { + let cfType = TISGetInputSourceProperty(self, key) + if (cfType != nil) { + return Unmanaged.fromOpaque(cfType!) + .takeUnretainedValue() + } else { + return nil + } + } + + var id: String { + return getProperty(kTISPropertyInputSourceID) as! String + } + + var name: String { + return getProperty(kTISPropertyLocalizedName) as! String + } + + var category: String { + return getProperty(kTISPropertyInputSourceCategory) as! String + } + + var isSelectable: Bool { + return getProperty(kTISPropertyInputSourceIsSelectCapable) as! Bool + } + + var sourceLanguages: [String] { + return getProperty(kTISPropertyInputSourceLanguages) as! [String] + } +} + + private let gui = DispatchQueue.main From e031c7deb2396bcd6e4131bcc8267df36085a6f3 Mon Sep 17 00:00:00 2001 From: georgealbert Date: Tue, 8 Feb 2022 21:43:20 +0800 Subject: [PATCH 3/5] * NvimView.swift: add var is_insert_mode for ime switch --- NvimView/Sources/NvimView/NvimView.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/NvimView/Sources/NvimView/NvimView.swift b/NvimView/Sources/NvimView/NvimView.swift index 9c2fca17..95aead08 100644 --- a/NvimView/Sources/NvimView/NvimView.swift +++ b/NvimView/Sources/NvimView/NvimView.swift @@ -304,6 +304,7 @@ public class NvimView: NSView, var asciiImSource : TISInputSource? var lastImSource : TISInputSource? + var is_insert_mode = false // MARK: - Private private var _linespacing = NvimView.defaultLinespacing From 359b2b582fe234bf262853992e14fcbab3b28829 Mon Sep 17 00:00:00 2001 From: georgealbert Date: Tue, 8 Feb 2022 21:48:00 +0800 Subject: [PATCH 4/5] * NvimView+UiBridge.swift: set lastImSource when exit from insert mode --- .../Sources/NvimView/NvimView+UiBridge.swift | 53 +++++++++++-------- 1 file changed, 32 insertions(+), 21 deletions(-) diff --git a/NvimView/Sources/NvimView/NvimView+UiBridge.swift b/NvimView/Sources/NvimView/NvimView+UiBridge.swift index 2adaf5d4..87284641 100644 --- a/NvimView/Sources/NvimView/NvimView+UiBridge.swift +++ b/NvimView/Sources/NvimView/NvimView+UiBridge.swift @@ -8,6 +8,7 @@ import Cocoa import Foundation import MessagePack import NvimServerTypes +import os import RxPack import RxSwift @@ -49,25 +50,6 @@ extension NvimView { } } - private func activateIm(enabled: Bool) { - if (self.asciiImSource == nil) { - self.asciiImSource = TISCopyCurrentASCIICapableKeyboardInputSource().takeRetainedValue() - // self.asciiImSource = TISCopyCurrentASCIICapableKeyboardInputSource().takeUnretainedValue() - self.bridgeLogger.info("ascii IME id: \(asciiImSource!.id), source: \(asciiImSource)") - } - - if enabled { - // In insert mode, set ime to last ime source - TISSelectInputSource(self.lastImSource) - } else { - // In normal mode, se ime to ascii input source - self.lastImSource = TISCopyCurrentKeyboardInputSource().takeRetainedValue() - TISSelectInputSource(self.asciiImSource) - } - - self.bridgeLogger.debug("lastImSource id: \(lastImSource!.id), source: \(lastImSource)") - } - final func modeChange(_ value: MessagePackValue) { guard let mode = MessagePackUtils.value( from: value, conversion: { v -> CursorModeShape? in @@ -79,8 +61,8 @@ extension NvimView { return } - self.bridgeLogger.debug(self.name(ofCursorMode: mode)) - // self.bridgeLogger.info(self.name(ofCursorMode: mode)) + // self.bridgeLogger.debug(self.name(ofCursorMode: mode)) + self.bridgeLogger.info(self.name(ofCursorMode: mode)) gui.async { self.mode = mode self.markForRender( @@ -92,6 +74,7 @@ extension NvimView { } if self.name(ofCursorMode: mode) == "Insert" { + self.is_insert_mode = true self.activateIm(enabled: true) } } @@ -415,6 +398,34 @@ extension NvimView { return min(0, top) } + + private func activateIm(enabled: Bool) { + if (self.asciiImSource == nil) { + self.asciiImSource = TISCopyCurrentASCIICapableKeyboardInputSource().takeRetainedValue() + // self.asciiImSource = TISCopyCurrentASCIICapableKeyboardInputSource().takeUnretainedValue() + self.bridgeLogger.info("ascii IME id: \(asciiImSource!.id), source: \(asciiImSource)") + } + + if enabled { + // In insert mode, set ime to last ime source + TISSelectInputSource(self.lastImSource) + } else { + // In normal mode, set ime to ascii input source + if self.is_insert_mode { + self.lastImSource = TISCopyCurrentKeyboardInputSource().takeRetainedValue() + self.bridgeLogger.info("lastImSource id: \(lastImSource!.id), source: \(lastImSource)") + + // Set is_insert_mode flag to avoid copy the wrong input source. + // We could enter Normal mode from Visual and OperaterPending mode. + self.is_insert_mode = false + } + + TISSelectInputSource(self.asciiImSource) + } + + // self.bridgeLogger.info("lastImSource id: \(lastImSource!.id), source: \(lastImSource)") + // os_log("lastImSource id: %@, source: %@", log: self.bridgeLogger, type: .debug, lastImSource!.id, lastImSource!.sourceLanguages) + } } // MARK: - Simple From c523a4816e442e6340131ad831821f69654b02c7 Mon Sep 17 00:00:00 2001 From: Albert Date: Sun, 13 Feb 2022 01:01:37 +0800 Subject: [PATCH 5/5] refactor IME switch. NvimView/NvimView.swift: Add lastMode and currentMode NvimView/NvimView+UiBridge.swift: Change IME by mode. --- .../Sources/NvimView/NvimView+UiBridge.swift | 44 +++++++------------ NvimView/Sources/NvimView/NvimView.swift | 3 +- 2 files changed, 19 insertions(+), 28 deletions(-) diff --git a/NvimView/Sources/NvimView/NvimView+UiBridge.swift b/NvimView/Sources/NvimView/NvimView+UiBridge.swift index 87284641..3374d299 100644 --- a/NvimView/Sources/NvimView/NvimView+UiBridge.swift +++ b/NvimView/Sources/NvimView/NvimView+UiBridge.swift @@ -61,22 +61,19 @@ extension NvimView { return } + self.lastMode = self.currentMode + self.currentMode = self.name(ofCursorMode: mode) + + self.bridgeLogger.info("\(self.lastMode) -> \(self.currentMode)") // self.bridgeLogger.debug(self.name(ofCursorMode: mode)) - self.bridgeLogger.info(self.name(ofCursorMode: mode)) + gui.async { self.mode = mode self.markForRender( region: self.cursorRegion(for: self.ugrid.cursorPosition) ) - if self.name(ofCursorMode: mode) == "Normal" { - self.activateIm(enabled: false) - } - - if self.name(ofCursorMode: mode) == "Insert" { - self.is_insert_mode = true - self.activateIm(enabled: true) - } + self.activateIm() } } @@ -399,32 +396,25 @@ extension NvimView { return min(0, top) } - private func activateIm(enabled: Bool) { + private func activateIm() { if (self.asciiImSource == nil) { self.asciiImSource = TISCopyCurrentASCIICapableKeyboardInputSource().takeRetainedValue() - // self.asciiImSource = TISCopyCurrentASCIICapableKeyboardInputSource().takeUnretainedValue() self.bridgeLogger.info("ascii IME id: \(asciiImSource!.id), source: \(asciiImSource)") } - if enabled { - // In insert mode, set ime to last ime source - TISSelectInputSource(self.lastImSource) - } else { - // In normal mode, set ime to ascii input source - if self.is_insert_mode { - self.lastImSource = TISCopyCurrentKeyboardInputSource().takeRetainedValue() - self.bridgeLogger.info("lastImSource id: \(lastImSource!.id), source: \(lastImSource)") - - // Set is_insert_mode flag to avoid copy the wrong input source. - // We could enter Normal mode from Visual and OperaterPending mode. - self.is_insert_mode = false - } - + // Exit from Insert mode, save ime used in Insert mode. + if self.lastMode == "Insert" && self.currentMode == "Normal" { + self.lastImSource = TISCopyCurrentKeyboardInputSource().takeRetainedValue() TISSelectInputSource(self.asciiImSource) + self.bridgeLogger.info("lastImSource id: \(lastImSource!.id), source: \(lastImSource)") } - // self.bridgeLogger.info("lastImSource id: \(lastImSource!.id), source: \(lastImSource)") - // os_log("lastImSource id: %@, source: %@", log: self.bridgeLogger, type: .debug, lastImSource!.id, lastImSource!.sourceLanguages) + // Enter into Insert mode, set ime to last used ime in Insert mode. + // Visual -> Insert + // Normal -> Insert + if self.currentMode == "Insert" { + TISSelectInputSource(self.lastImSource) + } } } diff --git a/NvimView/Sources/NvimView/NvimView.swift b/NvimView/Sources/NvimView/NvimView.swift index 95aead08..18dc3859 100644 --- a/NvimView/Sources/NvimView/NvimView.swift +++ b/NvimView/Sources/NvimView/NvimView.swift @@ -304,7 +304,8 @@ public class NvimView: NSView, var asciiImSource : TISInputSource? var lastImSource : TISInputSource? - var is_insert_mode = false + var lastMode = "" + var currentMode = "Normal" // MARK: - Private private var _linespacing = NvimView.defaultLinespacing