Skip to content

Commit aae5a96

Browse files
committed
async process key event and forward; fix hallelujah comma committed before word
1 parent 49b4b64 commit aae5a96

File tree

9 files changed

+98
-72
lines changed

9 files changed

+98
-72
lines changed

iosfrontend/iosfrontend.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ bool IosFrontend::keyEvent(const Key &key, bool isRelease) {
1919
return event.accepted();
2020
}
2121

22+
void IosFrontend::forwardKey(const std::string &key, const std::string &code) {
23+
SwiftFrontend::forwardKeyAsync(ic_->getClient(), key, code);
24+
}
25+
2226
void IosFrontend::focusIn(id client) {
2327
ic_->setClient(client);
2428
ic_->focusIn();

iosfrontend/iosfrontend.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class IosFrontend : public AddonInstance {
2424

2525
void createInputContext();
2626
bool keyEvent(const Key &key, bool isRelease);
27+
void forwardKey(const std::string &key, const std::string &code);
2728
void focusIn(id client);
2829
void focusOut(id client);
2930
void resetInput();

iosfrontend/iosfrontend.swift

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import FcitxProtocol
22
import Foundation
33

4-
public func commitStringAsync(_ clientPtr: UnsafeMutableRawPointer, _ commit: String) {
4+
private func getClient(_ clientPtr: UnsafeMutableRawPointer) -> FcitxProtocol? {
55
let client: AnyObject = Unmanaged.fromOpaque(clientPtr).takeUnretainedValue()
6-
guard let client = client as? FcitxProtocol else {
6+
return client as? FcitxProtocol
7+
}
8+
9+
public func commitStringAsync(_ clientPtr: UnsafeMutableRawPointer, _ commit: String) {
10+
guard let client = getClient(clientPtr) else {
711
return
812
}
913
DispatchQueue.main.async {
@@ -13,11 +17,19 @@ public func commitStringAsync(_ clientPtr: UnsafeMutableRawPointer, _ commit: St
1317

1418
public func setPreeditAsync(_ clientPtr: UnsafeMutableRawPointer, _ preedit: String, _ cursor: Int)
1519
{
16-
let client: AnyObject = Unmanaged.fromOpaque(clientPtr).takeUnretainedValue()
17-
guard let client = client as? FcitxProtocol else {
20+
guard let client = getClient(clientPtr) else {
1821
return
1922
}
2023
DispatchQueue.main.async {
2124
client.setPreedit(preedit, cursor)
2225
}
2326
}
27+
28+
public func forwardKeyAsync(_ clientPtr: UnsafeMutableRawPointer, _ key: String, _ code: String) {
29+
guard let client = getClient(clientPtr) else {
30+
return
31+
}
32+
DispatchQueue.main.async {
33+
client.forwardKey(key, code)
34+
}
35+
}

keyboard/KeyboardViewController.swift

Lines changed: 51 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -111,60 +111,62 @@ class KeyboardViewController: UIInputViewController, FcitxProtocol {
111111
}
112112

113113
public func keyPressed(_ key: String, _ code: String) {
114+
processKey(key, code)
115+
}
116+
117+
public func forwardKey(_ key: String, _ code: String) {
114118
// documentContextBeforeInput could be all text or text in current line before cursor.
115119
// In the latter case, it will be '\n' if caret is at the beginning of a non-first line.
116-
if !processKey(key, code) {
117-
switch code {
118-
case "ArrowDown":
119-
let offset = lengthOfLastLine(textDocumentProxy.documentContextBeforeInput ?? "")
120-
let step = lengthOfFirstLine(textDocumentProxy.documentContextAfterInput ?? "")
121-
textDocumentProxy.adjustTextPosition(byCharacterOffset: step)
122-
DispatchQueue.main.async {
123-
// Move to the start of next line if exists.
124-
self.textDocumentProxy.adjustTextPosition(byCharacterOffset: 1)
125-
// Must have a delay, otherwise nextLineLength is always 0.
126-
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
127-
let nextLineLength = lengthOfFirstLine(
128-
self.textDocumentProxy.documentContextAfterInput ?? "")
129-
self.textDocumentProxy.adjustTextPosition(
130-
byCharacterOffset: min(offset, nextLineLength))
131-
}
120+
switch code {
121+
case "ArrowDown":
122+
let offset = lengthOfLastLine(textDocumentProxy.documentContextBeforeInput ?? "")
123+
let step = lengthOfFirstLine(textDocumentProxy.documentContextAfterInput ?? "")
124+
textDocumentProxy.adjustTextPosition(byCharacterOffset: step)
125+
DispatchQueue.main.async {
126+
// Move to the start of next line if exists.
127+
self.textDocumentProxy.adjustTextPosition(byCharacterOffset: 1)
128+
// Must have a delay, otherwise nextLineLength is always 0.
129+
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
130+
let nextLineLength = lengthOfFirstLine(
131+
self.textDocumentProxy.documentContextAfterInput ?? "")
132+
self.textDocumentProxy.adjustTextPosition(
133+
byCharacterOffset: min(offset, nextLineLength))
132134
}
133-
case "ArrowLeft":
134-
textDocumentProxy.adjustTextPosition(byCharacterOffset: -1)
135-
case "ArrowRight":
136-
textDocumentProxy.adjustTextPosition(byCharacterOffset: 1)
137-
case "ArrowUp":
138-
let offset = lengthOfLastLine(textDocumentProxy.documentContextBeforeInput ?? "")
139-
textDocumentProxy.adjustTextPosition(byCharacterOffset: -offset)
140-
DispatchQueue.main.async {
141-
// Move to the end of previous line if exists.
142-
self.textDocumentProxy.adjustTextPosition(byCharacterOffset: -1)
143-
// Must have a delay, otherwise previousLineLength may always be 0.
144-
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
145-
let previousLineLength = lengthOfLastLine(
146-
self.textDocumentProxy.documentContextBeforeInput ?? "")
147-
if previousLineLength > offset {
148-
self.textDocumentProxy.adjustTextPosition(
149-
byCharacterOffset: -(previousLineLength - offset))
150-
}
135+
}
136+
case "ArrowLeft":
137+
textDocumentProxy.adjustTextPosition(byCharacterOffset: -1)
138+
case "ArrowRight":
139+
textDocumentProxy.adjustTextPosition(byCharacterOffset: 1)
140+
case "ArrowUp":
141+
let offset = lengthOfLastLine(textDocumentProxy.documentContextBeforeInput ?? "")
142+
textDocumentProxy.adjustTextPosition(byCharacterOffset: -offset)
143+
DispatchQueue.main.async {
144+
// Move to the end of previous line if exists.
145+
self.textDocumentProxy.adjustTextPosition(byCharacterOffset: -1)
146+
// Must have a delay, otherwise previousLineLength may always be 0.
147+
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
148+
let previousLineLength = lengthOfLastLine(
149+
self.textDocumentProxy.documentContextBeforeInput ?? "")
150+
if previousLineLength > offset {
151+
self.textDocumentProxy.adjustTextPosition(
152+
byCharacterOffset: -(previousLineLength - offset))
151153
}
152154
}
153-
case "Backspace":
154-
textDocumentProxy.deleteBackward()
155-
updateTextIsEmpty()
156-
case "End":
157-
let textAfter = textDocumentProxy.documentContextAfterInput ?? ""
158-
textDocumentProxy.adjustTextPosition(byCharacterOffset: lengthOfFirstLine(textAfter))
159-
case "Enter":
160-
commitString("\n") // \r doesn't work in Safari address bar.
161-
case "Home":
162-
let textBefore = textDocumentProxy.documentContextBeforeInput ?? ""
163-
textDocumentProxy.adjustTextPosition(byCharacterOffset: -lengthOfLastLine(textBefore))
164-
default:
165-
if !key.isEmpty {
166-
commitString(key)
167-
}
155+
}
156+
case "Backspace":
157+
textDocumentProxy.deleteBackward()
158+
updateTextIsEmpty()
159+
case "End":
160+
let textAfter = textDocumentProxy.documentContextAfterInput ?? ""
161+
textDocumentProxy.adjustTextPosition(byCharacterOffset: lengthOfFirstLine(textAfter))
162+
case "Enter":
163+
commitString("\n") // \r doesn't work in Safari address bar.
164+
case "Home":
165+
let textBefore = textDocumentProxy.documentContextBeforeInput ?? ""
166+
textDocumentProxy.adjustTextPosition(byCharacterOffset: -lengthOfLastLine(textBefore))
167+
default:
168+
if !key.isEmpty {
169+
commitString(key)
168170
}
169171
}
170172
}

keyboard/fcitx.cpp

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,28 +22,32 @@ void startFcitx(const char *appBundlePath, const char *xdgDataDirs,
2222
}
2323

2424
void focusIn(id client) {
25-
return with_fcitx([client] { frontend->focusIn(client); });
25+
return dispatcher->schedule([client] { frontend->focusIn(client); });
2626
}
2727

2828
void focusOut(id client) {
29-
return with_fcitx([client] { frontend->focusOut(client); });
29+
return dispatcher->schedule([client] { frontend->focusOut(client); });
3030
}
3131

32-
bool processKey(const char *key, const char *code) {
33-
return with_fcitx([=] {
34-
return frontend->keyEvent(
35-
fcitx::js_key_to_fcitx_key(key, code,
36-
1 << 29 /* KeyState::Virtual */),
37-
false);
32+
void processKey(const char *k, const char *c) {
33+
std::string key = k, code = c;
34+
dispatcher->schedule([=] {
35+
bool accepted =
36+
frontend->keyEvent(fcitx::js_key_to_fcitx_key(
37+
key, code, 1 << 29 /* KeyState::Virtual */),
38+
false);
39+
if (!accepted) {
40+
frontend->forwardKey(key, code);
41+
}
3842
});
3943
}
4044

4145
void resetInput() {
42-
with_fcitx([] { frontend->resetInput(); });
46+
dispatcher->schedule([] { frontend->resetInput(); });
4347
}
4448

4549
void reload() {
46-
with_fcitx([] {
50+
dispatcher->schedule([] {
4751
instance->reloadConfig();
4852
instance->refresh();
4953
auto &addonManager = instance->addonManager();
@@ -63,9 +67,10 @@ void reload() {
6367
}
6468

6569
void toggle() {
66-
with_fcitx([] { instance->toggle(); });
70+
dispatcher->schedule([] { instance->toggle(); });
6771
}
6872

69-
void setCurrentInputMethod(const char *inputMethod) {
70-
with_fcitx([=] { instance->setCurrentInputMethod(inputMethod); });
73+
void setCurrentInputMethod(const char *im) {
74+
std::string inputMethod = im;
75+
dispatcher->schedule([=] { instance->setCurrentInputMethod(inputMethod); });
7176
}

keyboard/fcitx.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ void startFcitx(const char *appBundlePath, const char *xdgDataDirs,
66
const char *appGroupPath);
77
void focusIn(id client);
88
void focusOut(id client);
9-
bool processKey(const char *key, const char *code);
9+
void processKey(const char *key, const char *code);
1010
void resetInput();
1111
void reload();
1212
void toggle();

protocol/FcitxProtocol.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
public protocol FcitxProtocol {
22
func keyPressed(_ key: String, _ code: String)
3+
func forwardKey(_ key: String, _ code: String)
34
func resetInput()
45
func commitString(_ string: String)
56
func setPreedit(_ preedit: String, _ cursor: Int)

src/fcitx.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ void startFcitx(const char *appBundlePath, const char *xdgDataDirs,
1212
setupFcitx(appBundlePath, xdgDataDirs, appGroupPath, true);
1313
}
1414

15-
void setInputMethods(const char *json) {
16-
with_fcitx([=] {
15+
void setInputMethods(const char *s) {
16+
std::string json = s;
17+
dispatcher->schedule([=] {
1718
auto &imMgr = instance->inputMethodManager();
1819
auto group = imMgr.currentGroup();
1920
auto &imList = group.inputMethodList();

uipanel/uipanel.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ static std::string serializeActions(ActionableCandidateList *actionableList,
162162
FCITX_ADDON_FACTORY_V2(uipanel, fcitx::UIPanelFactory);
163163

164164
void scroll(int start, int count) {
165-
with_fcitx([start, count] { fcitx::ui->scroll(start, count); });
165+
dispatcher->schedule([start, count] { fcitx::ui->scroll(start, count); });
166166
}
167167

168168
std::string getCandidateActions(int index) {
@@ -228,7 +228,7 @@ void activateCandidateAction(int index, int id) {
228228
}
229229

230230
void selectCandidate(int index) {
231-
with_fcitx([index] {
231+
dispatcher->schedule([index] {
232232
auto ic = instance->mostRecentInputContext();
233233
const auto &list = ic->inputPanel().candidateList();
234234
if (!list)
@@ -252,7 +252,7 @@ void selectCandidate(int index) {
252252
}
253253

254254
void activateStatusAreaAction(int id) {
255-
with_fcitx([id] {
255+
dispatcher->schedule([id] {
256256
if (auto *ic = instance->mostRecentInputContext()) {
257257
auto *action =
258258
instance->userInterfaceManager().lookupActionById(id);

0 commit comments

Comments
 (0)