From 2406ba2c50824c92939f8c8674921250496a9d50 Mon Sep 17 00:00:00 2001 From: Inoki Date: Sat, 28 Dec 2024 17:43:32 +0100 Subject: [PATCH 1/6] Add KeyAction and use AlphabetKeyAction in keyboard --- uipanel/CMakeLists.txt | 1 + uipanel/Key.swift | 6 ++++-- uipanel/KeyAction.swift | 23 +++++++++++++++++++++++ uipanel/Keyboard.swift | 4 ++-- 4 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 uipanel/KeyAction.swift 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..6419e80 --- /dev/null +++ b/uipanel/KeyAction.swift @@ -0,0 +1,23 @@ +import FcitxProtocol + +class KeyAction { + var key: String + var action: (_ client: FcitxProtocol) -> Void + + init(key: String, action: @escaping (_ client: FcitxProtocol) -> Void) { + self.key = key + self.action = action + } + + func perform(_ client: FcitxProtocol) { + self.action(client) + } +} + +class AlphabetKeyAction: KeyAction { + init(key: String) { + super.init(key: key, action: { client in + client.keyPressed(key) + }) + } +} diff --git a/uipanel/Keyboard.swift b/uipanel/Keyboard.swift index 23e370d..2eeaacc 100644 --- a/uipanel/Keyboard.swift +++ b/uipanel/Keyboard.swift @@ -8,7 +8,7 @@ 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"], + ["`", "z", "x", "c", "v", "b", "n", "m", "⌫"], [",", " ", "."], ] @@ -36,7 +36,7 @@ class Keyboard: UIStackView { rowStackView.spacing = 5 for key in row { - let button = Key(client, key) + let button = Key(client, key, AlphabetKeyAction(key: key)) rowStackView.addArrangedSubview(button) } addArrangedSubview(rowStackView) From 1673bab7172193df9080cfc03d728cce484923d3 Mon Sep 17 00:00:00 2001 From: Inoki Date: Sat, 28 Dec 2024 18:23:23 +0100 Subject: [PATCH 2/6] Add a backspace button to handle backspace --- keyboard/KeyboardViewController.swift | 18 +++++++++++++++++- keyboard/fcitx.cpp | 10 ++++++++-- uipanel/KeyAction.swift | 8 ++++++++ uipanel/Keyboard.swift | 7 +++++++ 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/keyboard/KeyboardViewController.swift b/keyboard/KeyboardViewController.swift index 18fcf18..613d3c4 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 + processBackspace() + return + } + + // Handle normal keys + 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..972054a 100644 --- a/keyboard/fcitx.cpp +++ b/keyboard/fcitx.cpp @@ -28,8 +28,14 @@ void focusOut() { } bool processKey(const char *key) { - return with_fcitx( - [key] { return frontend->keyEvent(fcitx::Key{key}, false); }); + return with_fcitx([key] { + // Handle backspace. + if (strcmp(key, "Backspace") == 0) { + return frontend->keyEvent(fcitx::Key{fcitx::KeySym::FcitxKey_BackSpace}, + false); + } + return frontend->keyEvent(fcitx::Key{key}, false); + }); } void reload() { diff --git a/uipanel/KeyAction.swift b/uipanel/KeyAction.swift index 6419e80..8a0b649 100644 --- a/uipanel/KeyAction.swift +++ b/uipanel/KeyAction.swift @@ -21,3 +21,11 @@ class AlphabetKeyAction: KeyAction { }) } } + +class BackspaceKeyAction: KeyAction { + init() { + super.init(key: "Backspace", action: { client in + client.keyPressed("⌫") + }) + } +} diff --git a/uipanel/Keyboard.swift b/uipanel/Keyboard.swift index 2eeaacc..fe24894 100644 --- a/uipanel/Keyboard.swift +++ b/uipanel/Keyboard.swift @@ -36,6 +36,13 @@ class Keyboard: UIStackView { rowStackView.spacing = 5 for key in row { + // TODO(Inoki): find a better way to handle special keys + if key == "⌫" { + let button = Key(client, key, BackspaceKeyAction()) + rowStackView.addArrangedSubview(button) + continue + } + let button = Key(client, key, AlphabetKeyAction(key: key)) rowStackView.addArrangedSubview(button) } From 96355abf48df4b7b13d8affa6e8376caf843b987 Mon Sep 17 00:00:00 2001 From: Inoki Date: Sun, 29 Dec 2024 10:27:26 +0100 Subject: [PATCH 3/6] Use "BackSpace" in Fcitx5 to avoid processing everywhere --- keyboard/KeyboardViewController.swift | 6 +++--- keyboard/fcitx.cpp | 5 ----- uipanel/KeyAction.swift | 3 ++- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/keyboard/KeyboardViewController.swift b/keyboard/KeyboardViewController.swift index 613d3c4..140f8a8 100644 --- a/keyboard/KeyboardViewController.swift +++ b/keyboard/KeyboardViewController.swift @@ -96,20 +96,20 @@ class KeyboardViewController: UIInputViewController, FcitxProtocol { public func keyPressed(_ key: String) { var finalKey = key // Handle special keys - if key == "⌫" { + if key == "BackSpace" { // backspace processBackspace() return } - // Handle normal keys + // Handle normal keys and other symbols if !processKey(finalKey) { textDocumentProxy.insertText(key) } } private func processBackspace() { - if !processKey("Backspace") { + if !processKey("BackSpace") { // Fallback to the default behavior textDocumentProxy.deleteBackward() } diff --git a/keyboard/fcitx.cpp b/keyboard/fcitx.cpp index 972054a..1b91287 100644 --- a/keyboard/fcitx.cpp +++ b/keyboard/fcitx.cpp @@ -29,11 +29,6 @@ void focusOut() { bool processKey(const char *key) { return with_fcitx([key] { - // Handle backspace. - if (strcmp(key, "Backspace") == 0) { - return frontend->keyEvent(fcitx::Key{fcitx::KeySym::FcitxKey_BackSpace}, - false); - } return frontend->keyEvent(fcitx::Key{key}, false); }); } diff --git a/uipanel/KeyAction.swift b/uipanel/KeyAction.swift index 8a0b649..e3c3101 100644 --- a/uipanel/KeyAction.swift +++ b/uipanel/KeyAction.swift @@ -25,7 +25,8 @@ class AlphabetKeyAction: KeyAction { class BackspaceKeyAction: KeyAction { init() { super.init(key: "Backspace", action: { client in - client.keyPressed("⌫") + // Use the symbol name of keyNameList in `fcitx5/src/lib/fcitx-utils/keynametable.h` + client.keyPressed("BackSpace") }) } } From 6424a796686f0585dd959b9ac09b6efaddf4fe65 Mon Sep 17 00:00:00 2001 From: Inoki Date: Sun, 29 Dec 2024 10:42:02 +0100 Subject: [PATCH 4/6] Create a symbol key action --- uipanel/KeyAction.swift | 52 ++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 21 deletions(-) diff --git a/uipanel/KeyAction.swift b/uipanel/KeyAction.swift index e3c3101..a190d7b 100644 --- a/uipanel/KeyAction.swift +++ b/uipanel/KeyAction.swift @@ -1,32 +1,42 @@ import FcitxProtocol class KeyAction { - var key: String - var action: (_ client: FcitxProtocol) -> Void + var key: String + var action: (_ client: FcitxProtocol) -> Void - init(key: String, action: @escaping (_ client: FcitxProtocol) -> Void) { - self.key = key - self.action = action - } + init(key: String, action: @escaping (_ client: FcitxProtocol) -> Void) { + self.key = key + self.action = action + } - func perform(_ client: FcitxProtocol) { - self.action(client) - } + func perform(_ client: FcitxProtocol) { + self.action(client) + } } class AlphabetKeyAction: KeyAction { - init(key: String) { - super.init(key: key, action: { client in - client.keyPressed(key) - }) - } + init(key: String) { + super.init( + key: key, + action: { client in + client.keyPressed(key) + }) + } } -class BackspaceKeyAction: KeyAction { - init() { - super.init(key: "Backspace", action: { client in - // Use the symbol name of keyNameList in `fcitx5/src/lib/fcitx-utils/keynametable.h` - client.keyPressed("BackSpace") - }) - } +class SymbolKeyAction: KeyAction { + init(symbol: String) { + // Use the symbol name of keyNameList in `fcitx5/src/lib/fcitx-utils/keynametable.h` + super.init( + key: symbol, + action: { client in + client.keyPressed(symbol) + }) + } +} + +class BackspaceKeyAction: SymbolKeyAction { + init() { + super.init(symbol: "BackSpace") + } } From 8ac4f8ac01833f343694b1cab14b822aa4c54c3e Mon Sep 17 00:00:00 2001 From: Inoki Date: Sun, 29 Dec 2024 11:05:58 +0100 Subject: [PATCH 5/6] Improve symbol and alphabet key actions --- uipanel/KeyAction.swift | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/uipanel/KeyAction.swift b/uipanel/KeyAction.swift index a190d7b..5f488c2 100644 --- a/uipanel/KeyAction.swift +++ b/uipanel/KeyAction.swift @@ -2,13 +2,31 @@ import FcitxProtocol class KeyAction { var key: String + var capsKey: String + var label: String + var capsLabel: String var action: (_ client: FcitxProtocol) -> Void - init(key: String, action: @escaping (_ 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) } @@ -18,6 +36,9 @@ class AlphabetKeyAction: KeyAction { init(key: String) { super.init( key: key, + capsKey: key.uppercased(), + label: key, + capsLabel: key.uppercased(), action: { client in client.keyPressed(key) }) @@ -25,10 +46,13 @@ class AlphabetKeyAction: KeyAction { } class SymbolKeyAction: KeyAction { - init(symbol: String) { + 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) }) @@ -37,6 +61,6 @@ class SymbolKeyAction: KeyAction { class BackspaceKeyAction: SymbolKeyAction { init() { - super.init(symbol: "BackSpace") + super.init(symbol: "BackSpace", label: "⌫") } } From b7bf8bce8f66e993fe659aa18a17ec77e692ef8b Mon Sep 17 00:00:00 2001 From: Inoki Date: Sun, 29 Dec 2024 11:57:36 +0100 Subject: [PATCH 6/6] Use internal state key to change keyboard state --- uipanel/KeyAction.swift | 12 ++++++++++++ uipanel/Keyboard.swift | 16 ++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/uipanel/KeyAction.swift b/uipanel/KeyAction.swift index 5f488c2..cee954c 100644 --- a/uipanel/KeyAction.swift +++ b/uipanel/KeyAction.swift @@ -64,3 +64,15 @@ class BackspaceKeyAction: SymbolKeyAction { 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 fe24894..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) { @@ -41,6 +41,18 @@ class Keyboard: UIStackView { 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))