macOS: handle preedit text changes outside of key event

pull/7121/head
Mitchell Hashimoto 2025-04-17 13:36:15 -07:00
parent b3cb38c3fa
commit ded9be39c0
No known key found for this signature in database
GPG Key ID: 523D5DC389D273BC
1 changed files with 33 additions and 15 deletions

View File

@ -954,20 +954,7 @@ extension Ghostty {
// If we have marked text, we're in a preedit state. The order we // If we have marked text, we're in a preedit state. The order we
// do this and the key event callbacks below doesn't matter since // do this and the key event callbacks below doesn't matter since
// we control the preedit state only through the preedit API. // we control the preedit state only through the preedit API.
if markedText.length > 0 { syncPreedit(clearIfNeeded: markedTextBefore)
let str = markedText.string
let len = str.utf8CString.count
if len > 0 {
markedText.string.withCString { ptr in
// Subtract 1 for the null terminator
ghostty_surface_preedit(surface, ptr, UInt(len - 1))
}
}
} else if markedTextBefore {
// If we had marked text before but don't now, we're no longer
// in a preedit state so we can clear it.
ghostty_surface_preedit(surface, nil, 0)
}
if let list = keyTextAccumulator, list.count > 0 { if let list = keyTextAccumulator, list.count > 0 {
// If we have text, then we've composed a character, send that down. // If we have text, then we've composed a character, send that down.
@ -1466,10 +1453,21 @@ extension Ghostty.SurfaceView: NSTextInputClient {
default: default:
print("unknown marked text: \(string)") print("unknown marked text: \(string)")
} }
// If we're not in a keyDown event, then we want to update our preedit
// text immediately. This can happen due to external events, for example
// changing keyboard layouts while composing: (1) set US intl (2) type '
// to enter dead key state (3)
if keyTextAccumulator == nil {
syncPreedit()
}
} }
func unmarkText() { func unmarkText() {
if self.markedText.length > 0 {
self.markedText.mutableString.setString("") self.markedText.mutableString.setString("")
syncPreedit()
}
} }
func validAttributesForMarkedText() -> [NSAttributedString.Key] { func validAttributesForMarkedText() -> [NSAttributedString.Key] {
@ -1608,6 +1606,26 @@ extension Ghostty.SurfaceView: NSTextInputClient {
print("SEL: \(selector)") print("SEL: \(selector)")
} }
/// Sync the preedit state based on the markedText value to libghostty
private func syncPreedit(clearIfNeeded: Bool = true) {
guard let surface else { return }
if markedText.length > 0 {
let str = markedText.string
let len = str.utf8CString.count
if len > 0 {
markedText.string.withCString { ptr in
// Subtract 1 for the null terminator
ghostty_surface_preedit(surface, ptr, UInt(len - 1))
}
}
} else if clearIfNeeded {
// If we had marked text before but don't now, we're no longer
// in a preedit state so we can clear it.
ghostty_surface_preedit(surface, nil, 0)
}
}
} }
// MARK: Services // MARK: Services