diff --git a/keyboard/KeyboardViewController.swift b/keyboard/KeyboardViewController.swift index 18fcf18..140f8a8 100644 --- a/keyboard/KeyboardViewController.swift +++ b/keyboard/KeyboardViewController.swift @@ -94,11 +94,27 @@ class KeyboardViewController: UIInputViewController, FcitxProtocol { } public func keyPressed(_ key: String) { - if !processKey(key) { + var finalKey = key + // Handle special keys + if key == "BackSpace" { + // backspace + processBackspace() + return + } + + // Handle normal keys and other symbols + if !processKey(finalKey) { textDocumentProxy.insertText(key) } } + private func processBackspace() { + if !processKey("BackSpace") { + // Fallback to the default behavior + textDocumentProxy.deleteBackward() + } + } + public func commitString(_ commit: String) { textDocumentProxy.insertText(commit) } diff --git a/keyboard/fcitx.cpp b/keyboard/fcitx.cpp index 4af7a48..1b91287 100644 --- a/keyboard/fcitx.cpp +++ b/keyboard/fcitx.cpp @@ -28,8 +28,9 @@ void focusOut() { } bool processKey(const char *key) { - return with_fcitx( - [key] { return frontend->keyEvent(fcitx::Key{key}, false); }); + return with_fcitx([key] { + return frontend->keyEvent(fcitx::Key{key}, false); + }); } void reload() { diff --git a/uipanel/CMakeLists.txt b/uipanel/CMakeLists.txt index bd7f37e..9c776a4 100644 --- a/uipanel/CMakeLists.txt +++ b/uipanel/CMakeLists.txt @@ -1,6 +1,7 @@ add_library(KeyboardUI STATIC keyboardui.swift Key.swift + KeyAction.swift Keyboard.swift Candidate.swift CandidateBar.swift diff --git a/uipanel/Key.swift b/uipanel/Key.swift index 7590616..275844a 100644 --- a/uipanel/Key.swift +++ b/uipanel/Key.swift @@ -3,9 +3,11 @@ import UIKit class Key: UIButton { let client: FcitxProtocol + let action: KeyAction - init(_ client: FcitxProtocol, _ label: String) { + init(_ client: FcitxProtocol, _ label: String, _ action: KeyAction) { self.client = client + self.action = action super.init(frame: .zero) setTitle(label, for: .normal) titleLabel?.font = UIFont.systemFont(ofSize: 24) @@ -22,6 +24,6 @@ class Key: UIButton { guard let currentTitle = sender.currentTitle else { return } - client.keyPressed(currentTitle) + self.action.perform(self.client) } } diff --git a/uipanel/KeyAction.swift b/uipanel/KeyAction.swift new file mode 100644 index 0000000..cee954c --- /dev/null +++ b/uipanel/KeyAction.swift @@ -0,0 +1,78 @@ +import FcitxProtocol + +class KeyAction { + var key: String + var capsKey: String + var label: String + var capsLabel: String + var action: (_ client: FcitxProtocol) -> Void + + init(key: String, capsKey: String, label: String, capsLabel: String, action: @escaping (_ client: FcitxProtocol) -> Void) { + self.key = key + self.capsKey = capsKey + self.label = label + self.capsLabel = capsLabel + self.action = action + } + + convenience init(key: String, capsKey: String, action: @escaping (_ client: FcitxProtocol) -> Void) { + self.init(key: key, capsKey: capsKey, label: key, capsLabel: capsKey, action: action) + } + + convenience init(key: String, label: String, action: @escaping (_ client: FcitxProtocol) -> Void) { + self.init(key: key, capsKey: key, label: label, capsLabel: label, action: action) + } + + convenience init(key: String, action: @escaping (_ client: FcitxProtocol) -> Void) { + self.init(key: key, capsKey: key, action: action) + } + + func perform(_ client: FcitxProtocol) { + self.action(client) + } +} + +class AlphabetKeyAction: KeyAction { + init(key: String) { + super.init( + key: key, + capsKey: key.uppercased(), + label: key, + capsLabel: key.uppercased(), + action: { client in + client.keyPressed(key) + }) + } +} + +class SymbolKeyAction: KeyAction { + init(symbol: String, label: String) { + // Use the symbol name of keyNameList in `fcitx5/src/lib/fcitx-utils/keynametable.h` + super.init( + key: symbol, + capsKey: symbol, + label: label, + capsLabel: label, + action: { client in + client.keyPressed(symbol) + }) + } +} + +class BackspaceKeyAction: SymbolKeyAction { + init() { + super.init(symbol: "BackSpace", label: "⌫") + } +} + +class InternalStateKeyAction: KeyAction { + init(label: String, action: @escaping (_ client: FcitxProtocol) -> Void) { + super.init( + key: label, + capsKey: label, + label: label, + capsLabel: label, + action: action + ) + } +} diff --git a/uipanel/Keyboard.swift b/uipanel/Keyboard.swift index 23e370d..f9ac1c3 100644 --- a/uipanel/Keyboard.swift +++ b/uipanel/Keyboard.swift @@ -8,8 +8,8 @@ class Keyboard: UIStackView { ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"], ["q", "w", "e", "r", "t", "y", "u", "i", "o", "p"], ["a", "s", "d", "f", "g", "h", "j", "k", "l"], - ["`", "z", "x", "c", "v", "b", "n", "m"], - [",", " ", "."], + ["Shift", "`", "z", "x", "c", "v", "b", "n", "m", "⌫"], + [",", "🌐", " ", "."], ] init(_ client: FcitxProtocol) { @@ -36,7 +36,26 @@ class Keyboard: UIStackView { rowStackView.spacing = 5 for key in row { - let button = Key(client, key) + // TODO(Inoki): find a better way to handle special keys + if key == "⌫" { + let button = Key(client, key, BackspaceKeyAction()) + rowStackView.addArrangedSubview(button) + continue + } else if key == "🌐" { + let button = Key(client, key, InternalStateKeyAction(label: key, action: { client in + // TODO: switch keyboard + })) + rowStackView.addArrangedSubview(button) + continue + } else if key == "Shift" { + let button = Key(client, "⇧", InternalStateKeyAction(label: key, action: { client in + // TODO: switch keyboard + })) + rowStackView.addArrangedSubview(button) + continue + } + + let button = Key(client, key, AlphabetKeyAction(key: key)) rowStackView.addArrangedSubview(button) } addArrangedSubview(rowStackView)