From f3673fa4a84acfe8c7325a5cbe636a1c5e18130a Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Thu, 10 Aug 2023 14:51:09 +0800 Subject: [PATCH] NSEvent // Implement keyModifierFlags, etc. --- .../ShiftKeyUpChecker/ShiftKeyUpChecker.swift | 2 +- .../CocoaExtension/CocoaExtension_NSEvent.swift | 4 ++++ .../Sources/PhraseEditorUI/PhraseEditorUI.swift | 2 +- .../Shared/Protocols/InputSignalProtocol.swift | 1 + Source/Modules/InputHandler_Core.swift | 2 +- Source/Modules/InputHandler_HandleCandidate.swift | 8 ++++---- Source/Modules/InputHandler_HandleStates.swift | 12 ++++++------ Source/Modules/InputHandler_TriageInput.swift | 10 +++++----- Source/Modules/SessionCtl_Core.swift | 2 +- Source/Modules/SessionCtl_HandleEvent.swift | 6 +++--- Source/Modules/SessionCtl_IMKCandidatesData.swift | 2 +- Source/Modules/SessionCtl_Menu.swift | 4 ++-- .../UIModules/PrefUI/VwrPrefPaneCassette.swift | 2 +- .../UIModules/PrefUI/VwrPrefPaneDictionary.swift | 3 ++- Source/Modules/WindowControllers/CtlPrefWindow.swift | 4 ++-- .../CtlPrefWindow_PhraseEditor.swift | 2 +- 16 files changed, 36 insertions(+), 30 deletions(-) diff --git a/Packages/Qwertyyb_ShiftKeyUpChecker/Sources/ShiftKeyUpChecker/ShiftKeyUpChecker.swift b/Packages/Qwertyyb_ShiftKeyUpChecker/Sources/ShiftKeyUpChecker/ShiftKeyUpChecker.swift index 965fa436..6181ae84 100644 --- a/Packages/Qwertyyb_ShiftKeyUpChecker/Sources/ShiftKeyUpChecker/ShiftKeyUpChecker.swift +++ b/Packages/Qwertyyb_ShiftKeyUpChecker/Sources/ShiftKeyUpChecker/ShiftKeyUpChecker.swift @@ -59,7 +59,7 @@ public struct ShiftKeyUpChecker { if isKeyDown { // modifier keydown event lastTime = Date() - if event.modifierFlags == .shift { shiftIsBeingPressed = true } + if event.modifierFlags.intersection(.deviceIndependentFlagsMask) == .shift { shiftIsBeingPressed = true } } else { lastTime = Date(timeInterval: -3600 * 4, since: Date()) shiftIsBeingPressed = false diff --git a/Packages/vChewing_CocoaExtension/Sources/CocoaExtension/CocoaExtension_NSEvent.swift b/Packages/vChewing_CocoaExtension/Sources/CocoaExtension/CocoaExtension_NSEvent.swift index 1914604b..4a2bc713 100644 --- a/Packages/vChewing_CocoaExtension/Sources/CocoaExtension/CocoaExtension_NSEvent.swift +++ b/Packages/vChewing_CocoaExtension/Sources/CocoaExtension/CocoaExtension_NSEvent.swift @@ -94,6 +94,10 @@ public extension NSEvent { return result <= UInt16.max ? UInt16(result) : UInt16.max } + var keyModifierFlags: ModifierFlags { modifierFlags.intersection(.deviceIndependentFlagsMask) } + + static var keyModifierFlags: ModifierFlags { Self.modifierFlags.intersection(.deviceIndependentFlagsMask) } + var isFlagChanged: Bool { type == .flagsChanged } var isEmacsKey: Bool { diff --git a/Packages/vChewing_PhraseEditorUI/Sources/PhraseEditorUI/PhraseEditorUI.swift b/Packages/vChewing_PhraseEditorUI/Sources/PhraseEditorUI/PhraseEditorUI.swift index 9d430203..702ab4f2 100644 --- a/Packages/vChewing_PhraseEditorUI/Sources/PhraseEditorUI/PhraseEditorUI.swift +++ b/Packages/vChewing_PhraseEditorUI/Sources/PhraseEditorUI/PhraseEditorUI.swift @@ -187,7 +187,7 @@ public struct VwrPhraseEditorUI: View { } private func callExternalAppToOpenPhraseFile() { - let app: String = NSEvent.modifierFlags.contains(.option) ? "TextEdit" : "Finder" + let app: String = NSEvent.keyModifierFlags.contains(.option) ? "TextEdit" : "Finder" delegate?.openPhraseFile(mode: selInputMode, type: selUserDataType, app: app) } diff --git a/Packages/vChewing_Shared/Sources/Shared/Protocols/InputSignalProtocol.swift b/Packages/vChewing_Shared/Sources/Shared/Protocols/InputSignalProtocol.swift index e462606e..2404b413 100644 --- a/Packages/vChewing_Shared/Sources/Shared/Protocols/InputSignalProtocol.swift +++ b/Packages/vChewing_Shared/Sources/Shared/Protocols/InputSignalProtocol.swift @@ -15,6 +15,7 @@ extension NSEvent: InputSignalProtocol {} public protocol InputSignalProtocol { var modifierFlags: NSEvent.ModifierFlags { get } + var keyModifierFlags: NSEvent.ModifierFlags { get } var isTypingVertical: Bool { get } var text: String { get } var inputTextIgnoringModifiers: String? { get } diff --git a/Source/Modules/InputHandler_Core.swift b/Source/Modules/InputHandler_Core.swift index 1406b547..9fdf7864 100644 --- a/Source/Modules/InputHandler_Core.swift +++ b/Source/Modules/InputHandler_Core.swift @@ -559,7 +559,7 @@ public class InputHandler: InputHandlerProtocol { if prefs.halfWidthPunctuationEnabled { return "_half_punctuation_" } // 注意:這一行為 SHIFT+ALT+主鍵盤數字鍵專用,強制無視不同地區的鍵盤在這個按鍵組合下的符號輸入差異。 // 但如果去掉「input.isMainAreaNumKey」這個限定條件的話,可能會影響其他依賴 Shift 鍵輸入的符號。 - if input.isMainAreaNumKey, input.modifierFlags == [.option, .shift] { return "_shift_alt_punctuation_" } + if input.isMainAreaNumKey, input.keyModifierFlags == [.option, .shift] { return "_shift_alt_punctuation_" } var result = "" switch (input.isControlHold, input.isOptionHold) { case (true, true): result.append("_alt_ctrl_punctuation_") diff --git a/Source/Modules/InputHandler_HandleCandidate.swift b/Source/Modules/InputHandler_HandleCandidate.swift index 2f38584a..1f8d09f3 100644 --- a/Source/Modules/InputHandler_HandleCandidate.swift +++ b/Source/Modules/InputHandler_HandleCandidate.swift @@ -41,7 +41,7 @@ extension InputHandler { if candidates[highlightedIndex].keyArray.count < 2 || candidates[highlightedIndex].value.count < 2 { break manipulator } - switch input.modifierFlags { + switch input.keyModifierFlags { case [.option, .command] where input.keyCode == 27: // 減號鍵 ctlCandidate.delegate?.candidatePairRightClicked(at: highlightedIndex, action: .toNerf) return true @@ -274,8 +274,8 @@ extension InputHandler { // MARK: - Flipping pages by using modified bracket keys (when they are not occupied). // Shift+Command+[] 被 Chrome 系瀏覽器佔用,所以改用 Ctrl。 - let ctrlCMD: Bool = input.modifierFlags == [.control, .command] - let ctrlShiftCMD: Bool = input.modifierFlags == [.control, .command, .shift] + let ctrlCMD: Bool = input.keyModifierFlags == [.control, .command] + let ctrlShiftCMD: Bool = input.keyModifierFlags == [.control, .command, .shift] if ctrlShiftCMD || ctrlCMD { // 此處 JIS 鍵盤判定無法用於螢幕鍵盤。所以,螢幕鍵盤的場合,系統會依照 US 鍵盤的判定方案。 let isJIS: Bool = KBGetLayoutType(Int16(LMGetKbdType())) == kKeyboardJIS @@ -293,7 +293,7 @@ extension InputHandler { // MARK: - Flipping pages by using symbol menu keys (when they are not occupied). if input.isSymbolMenuPhysicalKey { - switch input.modifierFlags { + switch input.keyModifierFlags { case .shift, [], .option where state.type != .ofSymbolTable: var updated = true diff --git a/Source/Modules/InputHandler_HandleStates.swift b/Source/Modules/InputHandler_HandleStates.swift index 95ec1585..550c0e56 100644 --- a/Source/Modules/InputHandler_HandleStates.swift +++ b/Source/Modules/InputHandler_HandleStates.swift @@ -339,7 +339,7 @@ extension InputHandler { var displayedText = state.displayedText - if input.modifierFlags == [.option, .shift] { + if input.keyModifierFlags == [.option, .shift] { displayedText = displayedText.map(\.description).joined(separator: " ") } else if readingOnly { displayedText = commissionByCtrlCommandEnter() @@ -446,7 +446,7 @@ extension InputHandler { delegate.switchState(updatedState) } strCodePointBuffer = strCodePointBuffer.dropLast(1).description - if input.modifierFlags == .option { + if input.keyModifierFlags == .option { strCodePointBuffer.removeAll() refreshState() isCodePointInputMode = true @@ -488,7 +488,7 @@ extension InputHandler { let steps = getStepsToNearbyNodeBorder(direction: .rear) var actualSteps = 1 - switch input.modifierFlags { + switch input.keyModifierFlags { case .shift: delegate.switchState(IMEState.ofAbortion()) return true @@ -507,7 +507,7 @@ extension InputHandler { } walk() } else { - _ = input.modifierFlags == .option + _ = input.keyModifierFlags == .option ? clearComposerAndCalligrapher() : letComposerAndCalligrapherDoBackSpace() } @@ -549,7 +549,7 @@ extension InputHandler { // macOS 認為 PC Delete 鍵訊號是必然有 .function 這個修飾鍵在起作用的。 // 總之處理起來非常機車就是了。 - switch input.modifierFlags { + switch input.keyModifierFlags { case _ where input.isShiftHold && !input.isOptionHold && !input.isControlHold: delegate.switchState(IMEState.ofAbortion()) return true @@ -1044,7 +1044,7 @@ extension InputHandler { // 否則會導致對上下左右鍵與翻頁鍵的判斷失效。 let notEmpty = state.hasComposition && !compositor.isEmpty && isComposerOrCalligrapherEmpty let bannedModifiers: NSEvent.ModifierFlags = [.option, .shift, .command, .control] - let noBannedModifiers = bannedModifiers.intersection(input.modifierFlags).isEmpty + let noBannedModifiers = bannedModifiers.intersection(input.keyModifierFlags).isEmpty var triggered = input.isCursorClockLeft || input.isCursorClockRight triggered = triggered || (input.isSpace && prefs.chooseCandidateUsingSpace) triggered = triggered || input.isPageDown || input.isPageUp diff --git a/Source/Modules/InputHandler_TriageInput.swift b/Source/Modules/InputHandler_TriageInput.swift index e7f5d9d1..c62ab416 100644 --- a/Source/Modules/InputHandler_TriageInput.swift +++ b/Source/Modules/InputHandler_TriageInput.swift @@ -47,7 +47,7 @@ public extension InputHandler { case .kCarriageReturn, .kLineFeed: return handleEnter(input: input) case .kSymbolMenuPhysicalKeyJIS, .kSymbolMenuPhysicalKeyIntl: let isJIS = keyCodeType == .kSymbolMenuPhysicalKeyJIS - switch input.modifierFlags { + switch input.keyModifierFlags { case []: return handlePunctuationList(alternative: false, isJIS: isJIS) case [.option, .shift]: @@ -141,13 +141,13 @@ public extension InputHandler { // 判斷是否響應傳統的漢音鍵盤符號模式熱鍵。 haninSymbolInput: if prefs.classicHaninKeyboardSymbolModeShortcutEnabled { guard let x = input.inputTextIgnoringModifiers, - "¥\\".contains(x), input.modifierFlags.isEmpty + "¥\\".contains(x), input.keyModifierFlags.isEmpty else { break haninSymbolInput } return handleHaninKeyboardSymbolModeToggle() } // 注音按鍵輸入與漢音鍵盤符號輸入處理。 - if isHaninKeyboardSymbolMode, [[], .shift].contains(input.modifierFlags) { + if isHaninKeyboardSymbolMode, [[], .shift].contains(input.keyModifierFlags) { return handleHaninKeyboardSymbolModeInput(input: input) } else if let compositionHandled = handleComposition(input: input) { return compositionHandled @@ -158,8 +158,8 @@ public extension InputHandler { // Ctrl+Command+[] 輪替候選字。 // Shift+Command+[] 被 Chrome 系瀏覽器佔用,所以改用 Ctrl。 - let ctrlCMD: Bool = input.modifierFlags == [.control, .command] - let ctrlShiftCMD: Bool = input.modifierFlags == [.control, .command, .shift] + let ctrlCMD: Bool = input.keyModifierFlags == [.control, .command] + let ctrlShiftCMD: Bool = input.keyModifierFlags == [.control, .command, .shift] revolveCandidateWithBrackets: if ctrlShiftCMD || ctrlCMD { if state.type != .ofInputting { break revolveCandidateWithBrackets } // 此處 JIS 鍵盤判定無法用於螢幕鍵盤。所以,螢幕鍵盤的場合,系統會依照 US 鍵盤的判定方案。 diff --git a/Source/Modules/SessionCtl_Core.swift b/Source/Modules/SessionCtl_Core.swift index b90cd55f..75d16f5d 100644 --- a/Source/Modules/SessionCtl_Core.swift +++ b/Source/Modules/SessionCtl_Core.swift @@ -97,7 +97,7 @@ public class SessionCtl: IMKInputController { // MARK: - /// 當前 Caps Lock 按鍵是否被摁下。 - public var isCapsLocked: Bool { NSEvent.modifierFlags.intersection(.deviceIndependentFlagsMask).contains(.capsLock) } + public static var isCapsLocked: Bool { NSEvent.keyModifierFlags.contains(.capsLock) } /// 當前這個 SessionCtl 副本是否處於英數輸入模式。 public var isASCIIMode: Bool { diff --git a/Source/Modules/SessionCtl_HandleEvent.swift b/Source/Modules/SessionCtl_HandleEvent.swift index f1595272..bab132d2 100644 --- a/Source/Modules/SessionCtl_HandleEvent.swift +++ b/Source/Modules/SessionCtl_HandleEvent.swift @@ -80,7 +80,7 @@ public extension SessionCtl { if #available(macOS 12, *) { if event.type == .flagsChanged, event.keyCode == KeyCode.kCapsLock.rawValue { DispatchQueue.main.async { - let isCapsLockTurnedOn = event.modifierFlags.intersection(.deviceIndependentFlagsMask).contains(.capsLock) + let isCapsLockTurnedOn = Self.isCapsLocked let status = NSLocalizedString("NotificationSwitchRevolver", comment: "") guard PrefMgr.shared.showNotificationsWhenTogglingCapsLock else { return } Notifier.notify( @@ -102,7 +102,7 @@ public extension SessionCtl { // MARK: 針對客體的具體處理 // 不再讓威注音處理由 Shift 切換到的英文模式的按鍵輸入。 - if isASCIIMode, !isCapsLocked { return false } + if isASCIIMode, !Self.isCapsLocked { return false } /// 這裡仍舊需要判斷 flags。之前使輸入法狀態卡住無法敲漢字的問題已在 InputHandler 內修復。 /// 這裡不判斷 flags 的話,用方向鍵前後定位光標之後,再次試圖觸發組字區時、反而會在首次按鍵時失敗。 @@ -166,7 +166,7 @@ public extension SessionCtl { } // 準備修飾鍵,用來判定要新增的詞彙是否需要賦以非常低的權重。 - Self.areWeNerfing = eventToDeal.modifierFlags == [.shift, .command] + Self.areWeNerfing = eventToDeal.keyModifierFlags == [.shift, .command] /// 直接交給 commonEventHandler 來處理。 let result = inputHandler.triageInput(event: eventToDeal) diff --git a/Source/Modules/SessionCtl_IMKCandidatesData.swift b/Source/Modules/SessionCtl_IMKCandidatesData.swift index 9aeb39f2..b250a27d 100644 --- a/Source/Modules/SessionCtl_IMKCandidatesData.swift +++ b/Source/Modules/SessionCtl_IMKCandidatesData.swift @@ -104,7 +104,7 @@ public extension SessionCtl { let candidateString: String = candidateString?.string ?? "" if state.type == .ofAssociates { // 聯想詞的 Shift+選字鍵的處理已經在其它位置實作完成。 - let isShiftHold = NSEvent.modifierFlags.contains(.shift) + let isShiftHold = NSEvent.keyModifierFlags.contains(.shift) if !(isShiftHold || PrefMgr.shared.alsoConfirmAssociatedCandidatesByEnter) { switchState(IMEState.ofAbortion()) return diff --git a/Source/Modules/SessionCtl_Menu.swift b/Source/Modules/SessionCtl_Menu.swift index 19821dba..57182faf 100644 --- a/Source/Modules/SessionCtl_Menu.swift +++ b/Source/Modules/SessionCtl_Menu.swift @@ -22,7 +22,7 @@ private extension Bool { // 因為選單部分的內容又臭又長,所以就單獨拉到一個檔案內管理了。 extension SessionCtl { - var optionKeyPressed: Bool { NSEvent.modifierFlags.contains(.option) } + var optionKeyPressed: Bool { NSEvent.keyModifierFlags.contains(.option) } override public func menu() -> NSMenu! { let menu = NSMenu(title: "Input Method Menu") @@ -217,7 +217,7 @@ extension SessionCtl { public extension SessionCtl { @objc override func showPreferences(_: Any? = nil) { osCheck: if #available(macOS 10.15, *) { - switch NSEvent.modifierFlags { + switch NSEvent.keyModifierFlags { case .option: break osCheck // case .shift: // CtlPrefUIShared.shared.controller.show(preferencePane: PrefUITabs.tabGeneral.ssPaneIdentifier) diff --git a/Source/Modules/UIModules/PrefUI/VwrPrefPaneCassette.swift b/Source/Modules/UIModules/PrefUI/VwrPrefPaneCassette.swift index c2173d97..00a4b015 100644 --- a/Source/Modules/UIModules/PrefUI/VwrPrefPaneCassette.swift +++ b/Source/Modules/UIModules/PrefUI/VwrPrefPaneCassette.swift @@ -69,7 +69,7 @@ struct VwrPrefPaneCassette: View { return false } Button { - if NSEvent.modifierFlags == .option, !cassettePath.isEmpty { + if NSEvent.keyModifierFlags == .option, !cassettePath.isEmpty { NSWorkspace.shared.activateFileViewerSelecting( [URL(fileURLWithPath: cassettePath)] ) diff --git a/Source/Modules/UIModules/PrefUI/VwrPrefPaneDictionary.swift b/Source/Modules/UIModules/PrefUI/VwrPrefPaneDictionary.swift index 784db6cb..6f8ea4d3 100644 --- a/Source/Modules/UIModules/PrefUI/VwrPrefPaneDictionary.swift +++ b/Source/Modules/UIModules/PrefUI/VwrPrefPaneDictionary.swift @@ -7,6 +7,7 @@ // requirements defined in MIT License. import BookmarkManager +import CocoaExtension import Shared import SSPreferences import SwiftExtension @@ -87,7 +88,7 @@ struct VwrPrefPaneDictionary: View { return false } Button { - if NSEvent.modifierFlags == .option, !userDataFolderSpecified.isEmpty { + if NSEvent.keyModifierFlags == .option, !userDataFolderSpecified.isEmpty { NSWorkspace.shared.activateFileViewerSelecting( [URL(fileURLWithPath: userDataFolderSpecified)] ) diff --git a/Source/Modules/WindowControllers/CtlPrefWindow.swift b/Source/Modules/WindowControllers/CtlPrefWindow.swift index 1fe1e03e..46afb1d4 100644 --- a/Source/Modules/WindowControllers/CtlPrefWindow.swift +++ b/Source/Modules/WindowControllers/CtlPrefWindow.swift @@ -337,7 +337,7 @@ class CtlPrefWindow: NSWindowController, NSWindowDelegate { } @IBAction func chooseUserDataFolderToSpecify(_: Any) { - if NSEvent.modifierFlags == .option, let url = pctUserDictionaryFolder.url { + if NSEvent.keyModifierFlags == .option, let url = pctUserDictionaryFolder.url { NSWorkspace.shared.activateFileViewerSelecting([url]) return } @@ -412,7 +412,7 @@ class CtlPrefWindow: NSWindowController, NSWindowDelegate { } @IBAction func chooseCassettePath(_: Any) { - if NSEvent.modifierFlags == .option, let url = pctCassetteFilePath.url { + if NSEvent.keyModifierFlags == .option, let url = pctCassetteFilePath.url { NSWorkspace.shared.activateFileViewerSelecting([url]) return } diff --git a/Source/Modules/WindowControllers/CtlPrefWindow_PhraseEditor.swift b/Source/Modules/WindowControllers/CtlPrefWindow_PhraseEditor.swift index b876ec4d..c3fa0861 100644 --- a/Source/Modules/WindowControllers/CtlPrefWindow_PhraseEditor.swift +++ b/Source/Modules/WindowControllers/CtlPrefWindow_PhraseEditor.swift @@ -192,7 +192,7 @@ extension CtlPrefWindow: NSTextViewDelegate, NSTextFieldDelegate { @IBAction func openExternallyPEButtonClicked(_: NSButton) { DispatchQueue.main.async { [self] in - let app: String = NSEvent.modifierFlags.contains(.option) ? "TextEdit" : "Finder" + let app: String = NSEvent.keyModifierFlags.contains(.option) ? "TextEdit" : "Finder" LMMgr.shared.openPhraseFile(mode: selInputMode, type: selUserDataType, app: app) } }