2.4.0 SP2 // Emacs key. Merge PR #125 from upd/2.4.0sp2

This commit is contained in:
ShikiSuen 2022-09-06 19:58:08 +08:00 committed by GitHub
commit 3f7d0d1bdf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 83 additions and 63 deletions

View File

@ -112,7 +112,7 @@ extension KeyHandler {
// MARK: PgDn // MARK: PgDn
if input.isPageDown || input.emacsKey == EmacsKey.nextPage { if input.isPageDown {
let updated: Bool = ctlCandidateCurrent.showNextPage() let updated: Bool = ctlCandidateCurrent.showNextPage()
if !updated { if !updated {
IME.prtDebugIntel("9B691919") IME.prtDebugIntel("9B691919")
@ -150,17 +150,6 @@ extension KeyHandler {
return true return true
} }
// MARK: EmacsKey Backward
if input.emacsKey == EmacsKey.backward {
let updated: Bool = ctlCandidateCurrent.highlightPreviousCandidate()
if !updated {
IME.prtDebugIntel("9B89308D")
errorCallback()
}
return true
}
// MARK: Right Arrow // MARK: Right Arrow
if input.isRight { if input.isRight {
@ -179,17 +168,6 @@ extension KeyHandler {
return true return true
} }
// MARK: EmacsKey Forward
if input.emacsKey == EmacsKey.forward {
let updated: Bool = ctlCandidateCurrent.highlightNextCandidate()
if !updated {
IME.prtDebugIntel("9B2428D")
errorCallback()
}
return true
}
// MARK: Up Arrow // MARK: Up Arrow
if input.isUp { if input.isUp {
@ -228,7 +206,7 @@ extension KeyHandler {
// MARK: Home Key // MARK: Home Key
if input.isHome || input.emacsKey == EmacsKey.home { if input.isHome {
if ctlCandidateCurrent.selectedCandidateIndex == 0 { if ctlCandidateCurrent.selectedCandidateIndex == 0 {
IME.prtDebugIntel("9B6EDE8D") IME.prtDebugIntel("9B6EDE8D")
errorCallback() errorCallback()
@ -244,7 +222,7 @@ extension KeyHandler {
if state.candidates.isEmpty { if state.candidates.isEmpty {
return false return false
} else { // count > 0!isEmpty滿 } else { // count > 0!isEmpty滿
if input.isEnd || input.emacsKey == EmacsKey.end { if input.isEnd {
if ctlCandidateCurrent.selectedCandidateIndex == state.candidates.count - 1 { if ctlCandidateCurrent.selectedCandidateIndex == state.candidates.count - 1 {
IME.prtDebugIntel("9B69AAAD") IME.prtDebugIntel("9B69AAAD")
errorCallback() errorCallback()

View File

@ -71,7 +71,9 @@ extension KeyHandler {
stateCallback(IMEState.ofEmpty()) stateCallback(IMEState.ofEmpty())
// Shift // Shift
if input.isUpperCaseASCIILetterKey { if (input.isUpperCaseASCIILetterKey && input.isASCIIModeInput)
|| (input.isCapsLockOn && input.isShiftHold)
{
return false return false
} }
@ -195,7 +197,7 @@ extension KeyHandler {
// MARK: Cursor backward // MARK: Cursor backward
if input.isCursorBackward || input.emacsKey == EmacsKey.backward { if input.isCursorBackward {
return handleBackward( return handleBackward(
state: state, input: input, stateCallback: stateCallback, errorCallback: errorCallback state: state, input: input, stateCallback: stateCallback, errorCallback: errorCallback
) )
@ -203,7 +205,7 @@ extension KeyHandler {
// MARK: Cursor forward // MARK: Cursor forward
if input.isCursorForward || input.emacsKey == EmacsKey.forward { if input.isCursorForward {
return handleForward( return handleForward(
state: state, input: input, stateCallback: stateCallback, errorCallback: errorCallback state: state, input: input, stateCallback: stateCallback, errorCallback: errorCallback
) )
@ -211,13 +213,13 @@ extension KeyHandler {
// MARK: Home // MARK: Home
if input.isHome || input.emacsKey == EmacsKey.home { if input.isHome {
return handleHome(state: state, stateCallback: stateCallback, errorCallback: errorCallback) return handleHome(state: state, stateCallback: stateCallback, errorCallback: errorCallback)
} }
// MARK: End // MARK: End
if input.isEnd || input.emacsKey == EmacsKey.end { if input.isEnd {
return handleEnd(state: state, stateCallback: stateCallback, errorCallback: errorCallback) return handleEnd(state: state, stateCallback: stateCallback, errorCallback: errorCallback)
} }
@ -259,7 +261,7 @@ extension KeyHandler {
// MARK: Delete // MARK: Delete
if input.isDelete || input.emacsKey == EmacsKey.delete { if input.isDelete {
return handleDelete(state: state, input: input, stateCallback: stateCallback, errorCallback: errorCallback) return handleDelete(state: state, input: input, stateCallback: stateCallback, errorCallback: errorCallback)
} }

View File

@ -190,7 +190,7 @@ extension KeyHandler {
} }
// Shift + Left // Shift + Left
if input.isCursorBackward || input.emacsKey == EmacsKey.backward, input.isShiftHold { if input.isCursorBackward, input.isShiftHold {
if compositor.marker > 0 { if compositor.marker > 0 {
compositor.marker -= 1 compositor.marker -= 1
if isCursorCuttingChar(isMarker: true) { if isCursorCuttingChar(isMarker: true) {
@ -213,7 +213,7 @@ extension KeyHandler {
} }
// Shift + Right // Shift + Right
if input.isCursorForward || input.emacsKey == EmacsKey.forward, input.isShiftHold { if input.isCursorForward, input.isShiftHold {
if compositor.marker < compositor.width { if compositor.marker < compositor.width {
compositor.marker += 1 compositor.marker += 1
if isCursorCuttingChar(isMarker: true) { if isCursorCuttingChar(isMarker: true) {

View File

@ -35,6 +35,38 @@ extension NSEvent {
keyCode: keyCode ?? self.keyCode keyCode: keyCode ?? self.keyCode
) )
} }
/// Emacs NSEvent NSEvent NSEvent
/// - Parameter isVerticalTyping:
/// - Returns:
public func convertFromEmacKeyEvent(isVerticalContext: Bool) -> NSEvent {
guard isEmacsKey else { return self }
let newKeyCode: UInt16 = {
switch isVerticalContext {
case false: return IME.vChewingEmacsKey.charKeyMapHorizontal[charCode] ?? 0
case true: return IME.vChewingEmacsKey.charKeyMapVertical[charCode] ?? 0
}
}()
guard newKeyCode != 0 else { return self }
let newCharScalar: Unicode.Scalar = {
switch charCode {
case 6:
return isVerticalContext
? NSEvent.SpecialKey.downArrow.unicodeScalar : NSEvent.SpecialKey.rightArrow.unicodeScalar
case 2:
return isVerticalContext
? NSEvent.SpecialKey.upArrow.unicodeScalar : NSEvent.SpecialKey.leftArrow.unicodeScalar
case 1: return NSEvent.SpecialKey.home.unicodeScalar
case 5: return NSEvent.SpecialKey.end.unicodeScalar
case 4: return NSEvent.SpecialKey.deleteForward.unicodeScalar // Use "deleteForward" for PC delete.
case 22: return NSEvent.SpecialKey.pageDown.unicodeScalar
default: return .init(0)
}
}()
let newChar = String(newCharScalar)
return reinitiate(modifierFlags: [], characters: newChar, charactersIgnoringModifiers: newChar, keyCode: newKeyCode)
?? self
}
} }
// MARK: - NSEvent Extension - InputSignalProtocol // MARK: - NSEvent Extension - InputSignalProtocol
@ -58,8 +90,9 @@ extension NSEvent: InputSignalProtocol {
public var isFlagChanged: Bool { type == .flagsChanged } public var isFlagChanged: Bool { type == .flagsChanged }
public var emacsKey: EmacsKey { public var isEmacsKey: Bool {
NSEvent.detectEmacsKey(charCode: charCode, flags: modifierFlags) // isControlHold
[6, 2, 1, 5, 4, 22].contains(charCode) && modifierFlags == .control
} }
// Alt+Shift+ macOS // Alt+Shift+ macOS
@ -150,13 +183,6 @@ extension NSEvent: InputSignalProtocol {
public var isSymbolMenuPhysicalKey: Bool { public var isSymbolMenuPhysicalKey: Bool {
[KeyCode.kSymbolMenuPhysicalKeyIntl, KeyCode.kSymbolMenuPhysicalKeyJIS].contains(KeyCode(rawValue: keyCode)) [KeyCode.kSymbolMenuPhysicalKeyIntl, KeyCode.kSymbolMenuPhysicalKeyJIS].contains(KeyCode(rawValue: keyCode))
} }
static func detectEmacsKey(charCode: UniChar, flags: NSEvent.ModifierFlags) -> EmacsKey {
if flags.contains(.control) {
return EmacsKey(rawValue: charCode) ?? .none
}
return .none
}
} }
// MARK: - InputSignalProtocol // MARK: - InputSignalProtocol
@ -169,7 +195,6 @@ public protocol InputSignalProtocol {
var charCode: UInt16 { get } var charCode: UInt16 { get }
var keyCode: UInt16 { get } var keyCode: UInt16 { get }
var isFlagChanged: Bool { get } var isFlagChanged: Bool { get }
var emacsKey: EmacsKey { get }
var mainAreaNumKeyChar: String? { get } var mainAreaNumKeyChar: String? { get }
var isASCII: Bool { get } var isASCII: Bool { get }
var isInvalid: Bool { get } var isInvalid: Bool { get }
@ -319,13 +344,3 @@ enum CharCode: UInt16 {
// KeyCode doesn't give a phuque about the character sent through macOS keyboard layouts ... // KeyCode doesn't give a phuque about the character sent through macOS keyboard layouts ...
// ... but only focuses on which physical key is pressed. // ... but only focuses on which physical key is pressed.
} }
public enum EmacsKey: UInt16 {
case none = 0
case forward = 6 // F
case backward = 2 // B
case home = 1 // A
case end = 5 // E
case delete = 4 // D
case nextPage = 22 // V
}

View File

@ -46,6 +46,15 @@ extension ctlInputMethod {
/// ///
guard client() != nil else { return false } guard client() != nil else { return false }
var event = event
// 使 NSEvent Emacs NSEvent NSEvent
if event.isEmacsKey {
let verticalProcessing =
(state.isCandidateContainer)
? ctlInputMethod.isVerticalCandidateSituation : ctlInputMethod.isVerticalTypingSituation
event = event.convertFromEmacKeyEvent(isVerticalContext: verticalProcessing)
}
/// flags使 KeyHandler /// flags使 KeyHandler
/// flags /// flags
/// event.type == .flagsChanged return false /// event.type == .flagsChanged return false

View File

@ -36,6 +36,8 @@ class ctlInputMethod: IMKInputController {
static var isASCIIModeSituation: Bool = false static var isASCIIModeSituation: Bool = false
/// ctlInputMethod /// ctlInputMethod
static var isVerticalTypingSituation: Bool = false static var isVerticalTypingSituation: Bool = false
/// ctlInputMethod
static var isVerticalCandidateSituation: Bool = false
/// ctlInputMethod /// ctlInputMethod
var isASCIIMode: Bool = false var isASCIIMode: Bool = false
/// 調 /// 調
@ -221,7 +223,11 @@ class ctlInputMethod: IMKInputController {
// - delegate ctlInputMethod KeyHandler // - delegate ctlInputMethod KeyHandler
proc: if let ctlCandidateCurrent = ctlInputMethod.ctlCandidateCurrent as? ctlCandidateIMK { proc: if let ctlCandidateCurrent = ctlInputMethod.ctlCandidateCurrent as? ctlCandidateIMK {
guard ctlCandidateCurrent.visible else { break proc } guard ctlCandidateCurrent.visible else { break proc }
let event: NSEvent = ctlCandidateIMK.replaceNumPadKeyCodes(target: event) ?? event var event: NSEvent = ctlCandidateIMK.replaceNumPadKeyCodes(target: event) ?? event
// 使 NSEvent Emacs NSEvent NSEvent
if event.isEmacsKey {
event = event.convertFromEmacKeyEvent(isVerticalContext: ctlInputMethod.isVerticalCandidateSituation)
}
// Shift+Enter delegate keyHandler // Shift+Enter delegate keyHandler
// Shift Flags // Shift Flags
@ -247,6 +253,7 @@ class ctlInputMethod: IMKInputController {
/// commonEventHandler /// commonEventHandler
/// IMK 便 /// IMK 便
/// event event var Shift
return commonEventHandler(event) return commonEventHandler(event)
} }

View File

@ -58,6 +58,8 @@ extension ctlInputMethod {
// true // true
} }
ctlInputMethod.isVerticalCandidateSituation = (isCandidateWindowVertical || !mgrPrefs.useHorizontalCandidateList)
ctlInputMethod.ctlCandidateCurrent.delegate = nil ctlInputMethod.ctlCandidateCurrent.delegate = nil
/// currentLayout /// currentLayout

View File

@ -26,6 +26,13 @@ public enum IME {
fileURLWithFileSystemRepresentation: getpwuid(getuid()).pointee.pw_dir, isDirectory: true, relativeTo: nil fileURLWithFileSystemRepresentation: getpwuid(getuid()).pointee.pw_dir, isDirectory: true, relativeTo: nil
) )
// MARK: - vChewing Emacs CharCode-KeyCode translation tables.
public enum vChewingEmacsKey {
static let charKeyMapHorizontal: [UInt16: UInt16] = [6: 124, 2: 123, 1: 115, 5: 119, 4: 117, 22: 121]
static let charKeyMapVertical: [UInt16: UInt16] = [6: 125, 2: 126, 1: 115, 5: 119, 4: 117, 22: 121]
}
// MARK: - Bundle Identifier // MARK: - Bundle Identifier
/// Bundle Identifier Shift /// Bundle Identifier Shift

View File

@ -5,7 +5,7 @@
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>2.4.0</string> <string>2.4.0</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>2400</string> <string>2402</string>
<key>UpdateInfoEndpoint</key> <key>UpdateInfoEndpoint</key>
<string>https://gitee.com/vchewing/vChewing-macOS/raw/main/Update-Info.plist</string> <string>https://gitee.com/vchewing/vChewing-macOS/raw/main/Update-Info.plist</string>
<key>UpdateInfoSite</key> <key>UpdateInfoSite</key>

View File

@ -1455,7 +1455,7 @@
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2400; CURRENT_PROJECT_VERSION = 2402;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO; GCC_DYNAMIC_NO_PIC = NO;
GCC_PREPROCESSOR_DEFINITIONS = ( GCC_PREPROCESSOR_DEFINITIONS = (
@ -1494,7 +1494,7 @@
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2400; CURRENT_PROJECT_VERSION = 2402;
ENABLE_NS_ASSERTIONS = NO; ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
@ -1532,7 +1532,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2400; CURRENT_PROJECT_VERSION = 2402;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
@ -1584,7 +1584,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2400; CURRENT_PROJECT_VERSION = 2402;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
ENABLE_NS_ASSERTIONS = NO; ENABLE_NS_ASSERTIONS = NO;
@ -1718,7 +1718,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2400; CURRENT_PROJECT_VERSION = 2402;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
@ -1777,7 +1777,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2400; CURRENT_PROJECT_VERSION = 2402;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_ASSET_PATHS = ""; DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
@ -1824,7 +1824,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2400; CURRENT_PROJECT_VERSION = 2402;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;
@ -1868,7 +1868,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 2400; CURRENT_PROJECT_VERSION = 2402;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = YES;