mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
macos: detect IME input source change as part of keyDown event (#4609)
Fixes #4539 AquaSKK is a Japanese IME (Input Method Editor) for macOS. It uses keyboard inputs to switch between input modes. I don't know any other IMEs that do this, but it's possible that there are others. Prior to this change, the keyboard inputs to switch between input modes were being sent to the terminal, resulting in erroneous characters being written. This change adds a check during keyDown events to see if the input source changed _during the event_. If it did, we assume an IME captured it and we don't pass the event to the terminal. This makes AquaSKK functional in Ghostty.
This commit is contained in:
@ -71,6 +71,7 @@
|
|||||||
A5A1F8852A489D6800D1E8BC /* terminfo in Resources */ = {isa = PBXBuildFile; fileRef = A5A1F8842A489D6800D1E8BC /* terminfo */; };
|
A5A1F8852A489D6800D1E8BC /* terminfo in Resources */ = {isa = PBXBuildFile; fileRef = A5A1F8842A489D6800D1E8BC /* terminfo */; };
|
||||||
A5A6F72A2CC41B8900B232A5 /* Xcode.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5A6F7292CC41B8700B232A5 /* Xcode.swift */; };
|
A5A6F72A2CC41B8900B232A5 /* Xcode.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5A6F7292CC41B8700B232A5 /* Xcode.swift */; };
|
||||||
A5B30539299BEAAB0047F10C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A5B30538299BEAAB0047F10C /* Assets.xcassets */; };
|
A5B30539299BEAAB0047F10C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A5B30538299BEAAB0047F10C /* Assets.xcassets */; };
|
||||||
|
A5CA378C2D2A4DEB00931030 /* KeyboardLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CA378B2D2A4DE800931030 /* KeyboardLayout.swift */; };
|
||||||
A5CBD0562C9E65B80017A1AE /* DraggableWindowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CBD0552C9E65A50017A1AE /* DraggableWindowView.swift */; };
|
A5CBD0562C9E65B80017A1AE /* DraggableWindowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CBD0552C9E65A50017A1AE /* DraggableWindowView.swift */; };
|
||||||
A5CBD0582C9F30960017A1AE /* Cursor.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CBD0572C9F30860017A1AE /* Cursor.swift */; };
|
A5CBD0582C9F30960017A1AE /* Cursor.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CBD0572C9F30860017A1AE /* Cursor.swift */; };
|
||||||
A5CBD0592C9F37B10017A1AE /* Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CEAFFE29C2410700646FDA /* Backport.swift */; };
|
A5CBD0592C9F37B10017A1AE /* Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5CEAFFE29C2410700646FDA /* Backport.swift */; };
|
||||||
@ -164,6 +165,7 @@
|
|||||||
A5B30531299BEAAA0047F10C /* Ghostty.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Ghostty.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
A5B30531299BEAAA0047F10C /* Ghostty.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Ghostty.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
A5B30538299BEAAB0047F10C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
A5B30538299BEAAB0047F10C /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
A5B3053D299BEAAB0047F10C /* Ghostty.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Ghostty.entitlements; sourceTree = "<group>"; };
|
A5B3053D299BEAAB0047F10C /* Ghostty.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Ghostty.entitlements; sourceTree = "<group>"; };
|
||||||
|
A5CA378B2D2A4DE800931030 /* KeyboardLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardLayout.swift; sourceTree = "<group>"; };
|
||||||
A5CBD0552C9E65A50017A1AE /* DraggableWindowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraggableWindowView.swift; sourceTree = "<group>"; };
|
A5CBD0552C9E65A50017A1AE /* DraggableWindowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraggableWindowView.swift; sourceTree = "<group>"; };
|
||||||
A5CBD0572C9F30860017A1AE /* Cursor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Cursor.swift; sourceTree = "<group>"; };
|
A5CBD0572C9F30860017A1AE /* Cursor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Cursor.swift; sourceTree = "<group>"; };
|
||||||
A5CBD05B2CA0C5C70017A1AE /* QuickTerminal.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = QuickTerminal.xib; sourceTree = "<group>"; };
|
A5CBD05B2CA0C5C70017A1AE /* QuickTerminal.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = QuickTerminal.xib; sourceTree = "<group>"; };
|
||||||
@ -267,6 +269,7 @@
|
|||||||
A5D0AF3C2B37804400D21823 /* CodableBridge.swift */,
|
A5D0AF3C2B37804400D21823 /* CodableBridge.swift */,
|
||||||
A52FFF582CAA4FF1000C6A5B /* Fullscreen.swift */,
|
A52FFF582CAA4FF1000C6A5B /* Fullscreen.swift */,
|
||||||
A59630962AEE163600D64628 /* HostingWindow.swift */,
|
A59630962AEE163600D64628 /* HostingWindow.swift */,
|
||||||
|
A5CA378B2D2A4DE800931030 /* KeyboardLayout.swift */,
|
||||||
A59FB5D02AE0DEA7009128F3 /* MetalView.swift */,
|
A59FB5D02AE0DEA7009128F3 /* MetalView.swift */,
|
||||||
A5CBD0552C9E65A50017A1AE /* DraggableWindowView.swift */,
|
A5CBD0552C9E65A50017A1AE /* DraggableWindowView.swift */,
|
||||||
C159E81C2B66A06B00FDFE9C /* OSColor+Extension.swift */,
|
C159E81C2B66A06B00FDFE9C /* OSColor+Extension.swift */,
|
||||||
@ -655,6 +658,7 @@
|
|||||||
A5CDF1932AAF9E0800513312 /* ConfigurationErrorsController.swift in Sources */,
|
A5CDF1932AAF9E0800513312 /* ConfigurationErrorsController.swift in Sources */,
|
||||||
A53A6C032CCC1B7F00943E98 /* Ghostty.Action.swift in Sources */,
|
A53A6C032CCC1B7F00943E98 /* Ghostty.Action.swift in Sources */,
|
||||||
A54B0CED2D0CFB7700CBEFF8 /* ColorizedGhosttyIcon.swift in Sources */,
|
A54B0CED2D0CFB7700CBEFF8 /* ColorizedGhosttyIcon.swift in Sources */,
|
||||||
|
A5CA378C2D2A4DEB00931030 /* KeyboardLayout.swift in Sources */,
|
||||||
A54B0CEF2D0D2E2800CBEFF8 /* ColorizedGhosttyIconImage.swift in Sources */,
|
A54B0CEF2D0D2E2800CBEFF8 /* ColorizedGhosttyIconImage.swift in Sources */,
|
||||||
A59FB5D12AE0DEA7009128F3 /* MetalView.swift in Sources */,
|
A59FB5D12AE0DEA7009128F3 /* MetalView.swift in Sources */,
|
||||||
A55685E029A03A9F004303CE /* AppError.swift in Sources */,
|
A55685E029A03A9F004303CE /* AppError.swift in Sources */,
|
||||||
|
@ -805,8 +805,23 @@ extension Ghostty {
|
|||||||
// know if these events cleared it.
|
// know if these events cleared it.
|
||||||
let markedTextBefore = markedText.length > 0
|
let markedTextBefore = markedText.length > 0
|
||||||
|
|
||||||
|
// We need to know the keyboard layout before below because some keyboard
|
||||||
|
// input events will change our keyboard layout and we don't want those
|
||||||
|
// going to the terminal.
|
||||||
|
let keyboardIdBefore: String? = if (!markedTextBefore) {
|
||||||
|
KeyboardLayout.id
|
||||||
|
} else {
|
||||||
|
nil
|
||||||
|
}
|
||||||
|
|
||||||
self.interpretKeyEvents([translationEvent])
|
self.interpretKeyEvents([translationEvent])
|
||||||
|
|
||||||
|
// If our keyboard changed from this we just assume an input method
|
||||||
|
// grabbed it and do nothing.
|
||||||
|
if (!markedTextBefore && keyboardIdBefore != KeyboardLayout.id) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// If we have text, then we've composed a character, send that down. We do this
|
// If we have text, then we've composed a character, send that down. We do this
|
||||||
// first because if we completed a preedit, the text will be available here
|
// first because if we completed a preedit, the text will be available here
|
||||||
// AND we'll have a preedit.
|
// AND we'll have a preedit.
|
||||||
|
14
macos/Sources/Helpers/KeyboardLayout.swift
Normal file
14
macos/Sources/Helpers/KeyboardLayout.swift
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import Carbon
|
||||||
|
|
||||||
|
class KeyboardLayout {
|
||||||
|
/// Return a string ID of the current keyboard input source.
|
||||||
|
static var id: String? {
|
||||||
|
if let source = TISCopyCurrentKeyboardInputSource()?.takeRetainedValue(),
|
||||||
|
let sourceIdPointer = TISGetInputSourceProperty(source, kTISPropertyInputSourceID) {
|
||||||
|
let sourceId = unsafeBitCast(sourceIdPointer, to: CFString.self)
|
||||||
|
return sourceId as String
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user