Skip to content

Commit e554510

Browse files
fxlianglotem
andauthored
fix(chord_composer): ignore repeated keys (#841)
refactor: unify finish chord strategies --------- Co-authored-by: 居戎氏 <chen.sst@gmail.com>
1 parent ec4bdfe commit e554510

2 files changed

Lines changed: 48 additions & 25 deletions

File tree

src/rime/gear/chord_composer.cc

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,16 @@ inline static int get_base_layer_key_code(const KeyEvent& key_event) {
8484
: ch;
8585
}
8686

87+
inline static bool finish_chord_on_all_keys_released(
88+
const ChordingState& state) {
89+
return state.pressed_keys.empty();
90+
}
91+
92+
bool ChordComposer::FinishChordConditionIsMet() const {
93+
return finish_chord_on_first_key_release_ ||
94+
finish_chord_on_all_keys_released(state_);
95+
}
96+
8797
ProcessResult ChordComposer::ProcessChordingKey(const KeyEvent& key_event) {
8898
if (key_event.ctrl() || key_event.alt() || key_event.super() ||
8999
key_event.caps()) {
@@ -106,19 +116,14 @@ ProcessResult ChordComposer::ProcessChordingKey(const KeyEvent& key_event) {
106116
editing_chord_ = true;
107117
bool is_key_up = key_event.release();
108118
if (is_key_up) {
109-
if (finish_chord_on_first_key_release_) {
110-
if (pressed_.find(ch) != pressed_.end()) {
111-
FinishChord();
112-
pressed_.clear();
113-
}
114-
} else if (pressed_.erase(ch) != 0 && pressed_.empty()) {
115-
FinishChord();
119+
if (state_.ReleaseKey(ch) && FinishChordConditionIsMet() &&
120+
!state_.recognized_chord.empty()) {
121+
FinishChord(state_.recognized_chord);
122+
}
123+
} else { // key down, ignore repeated key down events
124+
if (state_.PressKey(ch) && state_.AddKeyToChord(ch)) {
125+
UpdateChord(state_.recognized_chord);
116126
}
117-
} else { // key down
118-
pressed_.insert(ch);
119-
bool updated = chord_.insert(ch).second;
120-
if (updated)
121-
UpdateChord();
122127
}
123128
editing_chord_ = false;
124129
return kAccepted;
@@ -147,23 +152,23 @@ ProcessResult ChordComposer::ProcessKeyEvent(const KeyEvent& key_event) {
147152
return ProcessFunctionKey(key_event);
148153
}
149154

150-
string ChordComposer::SerializeChord() {
155+
string ChordComposer::SerializeChord(const Chord& chord) {
151156
KeySequence key_sequence;
152157
for (KeyEvent key : chording_keys_) {
153-
if (chord_.find(key.keycode()) != chord_.end())
158+
if (chord.find(key.keycode()) != chord.end())
154159
key_sequence.push_back(key);
155160
}
156161
string code = key_sequence.repr();
157162
algebra_.Apply(&code);
158163
return code;
159164
}
160165

161-
void ChordComposer::UpdateChord() {
166+
void ChordComposer::UpdateChord(const Chord& chord) {
162167
if (!engine_)
163168
return;
164169
Context* ctx = engine_->context();
165170
Composition& comp = ctx->composition();
166-
string code = SerializeChord();
171+
string code = SerializeChord(chord);
167172
prompt_format_.Apply(&code);
168173
if (comp.empty()) {
169174
// add a placeholder segment
@@ -178,10 +183,10 @@ void ChordComposer::UpdateChord() {
178183
last_segment.prompt = code;
179184
}
180185

181-
void ChordComposer::FinishChord() {
186+
void ChordComposer::FinishChord(const Chord& chord) {
182187
if (!engine_)
183188
return;
184-
string code = SerializeChord();
189+
string code = SerializeChord(chord);
185190
output_format_.Apply(&code);
186191
ClearChord();
187192

@@ -201,8 +206,7 @@ void ChordComposer::FinishChord() {
201206
}
202207

203208
void ChordComposer::ClearChord() {
204-
pressed_.clear();
205-
chord_.clear();
209+
state_.ClearChord();
206210
if (!engine_)
207211
return;
208212
Context* ctx = engine_->context();

src/rime/gear/chord_composer.h

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,25 @@
1515

1616
namespace rime {
1717

18+
using Chord = set<int>;
19+
20+
struct ChordingState {
21+
Chord pressed_keys;
22+
Chord recognized_chord;
23+
24+
bool IsPressed(int ch) const {
25+
return pressed_keys.find(ch) != pressed_keys.end();
26+
}
27+
28+
bool PressKey(int ch) { return pressed_keys.insert(ch).second; }
29+
30+
bool ReleaseKey(int ch) { return pressed_keys.erase(ch) != 0; }
31+
32+
bool AddKeyToChord(int ch) { return recognized_chord.insert(ch).second; }
33+
34+
void ClearChord() { recognized_chord.clear(); }
35+
};
36+
1837
class ChordComposer : public Processor {
1938
public:
2039
ChordComposer(const Ticket& ticket);
@@ -23,11 +42,12 @@ class ChordComposer : public Processor {
2342
virtual ProcessResult ProcessKeyEvent(const KeyEvent& key_event);
2443

2544
protected:
45+
bool FinishChordConditionIsMet() const;
2646
ProcessResult ProcessChordingKey(const KeyEvent& key_event);
2747
ProcessResult ProcessFunctionKey(const KeyEvent& key_event);
28-
string SerializeChord();
29-
void UpdateChord();
30-
void FinishChord();
48+
string SerializeChord(const Chord& chord);
49+
void UpdateChord(const Chord& chord);
50+
void FinishChord(const Chord& chord);
3151
void ClearChord();
3252
bool DeleteLastSyllable();
3353
void OnContextUpdate(Context* ctx);
@@ -45,8 +65,7 @@ class ChordComposer : public Processor {
4565
bool use_caps_ = false;
4666
bool finish_chord_on_first_key_release_ = false;
4767

48-
set<int> pressed_;
49-
set<int> chord_;
68+
ChordingState state_;
5069
bool editing_chord_ = false;
5170
bool sending_chord_ = false;
5271
bool composing_ = false;

0 commit comments

Comments
 (0)