Skip to content

Commit

Permalink
fix(chord_composer): ignore repeated keys (#841)
Browse files Browse the repository at this point in the history
refactor: unify finish chord strategies

---------

Co-authored-by: 居戎氏 <[email protected]>
  • Loading branch information
fxliang and lotem authored Mar 10, 2024
1 parent ec4bdfe commit e554510
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 25 deletions.
44 changes: 24 additions & 20 deletions src/rime/gear/chord_composer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,16 @@ inline static int get_base_layer_key_code(const KeyEvent& key_event) {
: ch;
}

inline static bool finish_chord_on_all_keys_released(
const ChordingState& state) {
return state.pressed_keys.empty();
}

bool ChordComposer::FinishChordConditionIsMet() const {
return finish_chord_on_first_key_release_ ||
finish_chord_on_all_keys_released(state_);
}

ProcessResult ChordComposer::ProcessChordingKey(const KeyEvent& key_event) {
if (key_event.ctrl() || key_event.alt() || key_event.super() ||
key_event.caps()) {
Expand All @@ -106,19 +116,14 @@ ProcessResult ChordComposer::ProcessChordingKey(const KeyEvent& key_event) {
editing_chord_ = true;
bool is_key_up = key_event.release();
if (is_key_up) {
if (finish_chord_on_first_key_release_) {
if (pressed_.find(ch) != pressed_.end()) {
FinishChord();
pressed_.clear();
}
} else if (pressed_.erase(ch) != 0 && pressed_.empty()) {
FinishChord();
if (state_.ReleaseKey(ch) && FinishChordConditionIsMet() &&
!state_.recognized_chord.empty()) {
FinishChord(state_.recognized_chord);
}
} else { // key down, ignore repeated key down events
if (state_.PressKey(ch) && state_.AddKeyToChord(ch)) {
UpdateChord(state_.recognized_chord);
}
} else { // key down
pressed_.insert(ch);
bool updated = chord_.insert(ch).second;
if (updated)
UpdateChord();
}
editing_chord_ = false;
return kAccepted;
Expand Down Expand Up @@ -147,23 +152,23 @@ ProcessResult ChordComposer::ProcessKeyEvent(const KeyEvent& key_event) {
return ProcessFunctionKey(key_event);
}

string ChordComposer::SerializeChord() {
string ChordComposer::SerializeChord(const Chord& chord) {
KeySequence key_sequence;
for (KeyEvent key : chording_keys_) {
if (chord_.find(key.keycode()) != chord_.end())
if (chord.find(key.keycode()) != chord.end())
key_sequence.push_back(key);
}
string code = key_sequence.repr();
algebra_.Apply(&code);
return code;
}

void ChordComposer::UpdateChord() {
void ChordComposer::UpdateChord(const Chord& chord) {
if (!engine_)
return;
Context* ctx = engine_->context();
Composition& comp = ctx->composition();
string code = SerializeChord();
string code = SerializeChord(chord);
prompt_format_.Apply(&code);
if (comp.empty()) {
// add a placeholder segment
Expand All @@ -178,10 +183,10 @@ void ChordComposer::UpdateChord() {
last_segment.prompt = code;
}

void ChordComposer::FinishChord() {
void ChordComposer::FinishChord(const Chord& chord) {
if (!engine_)
return;
string code = SerializeChord();
string code = SerializeChord(chord);
output_format_.Apply(&code);
ClearChord();

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

void ChordComposer::ClearChord() {
pressed_.clear();
chord_.clear();
state_.ClearChord();
if (!engine_)
return;
Context* ctx = engine_->context();
Expand Down
29 changes: 24 additions & 5 deletions src/rime/gear/chord_composer.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,25 @@

namespace rime {

using Chord = set<int>;

struct ChordingState {
Chord pressed_keys;
Chord recognized_chord;

bool IsPressed(int ch) const {
return pressed_keys.find(ch) != pressed_keys.end();
}

bool PressKey(int ch) { return pressed_keys.insert(ch).second; }

bool ReleaseKey(int ch) { return pressed_keys.erase(ch) != 0; }

bool AddKeyToChord(int ch) { return recognized_chord.insert(ch).second; }

void ClearChord() { recognized_chord.clear(); }
};

class ChordComposer : public Processor {
public:
ChordComposer(const Ticket& ticket);
Expand All @@ -23,11 +42,12 @@ class ChordComposer : public Processor {
virtual ProcessResult ProcessKeyEvent(const KeyEvent& key_event);

protected:
bool FinishChordConditionIsMet() const;
ProcessResult ProcessChordingKey(const KeyEvent& key_event);
ProcessResult ProcessFunctionKey(const KeyEvent& key_event);
string SerializeChord();
void UpdateChord();
void FinishChord();
string SerializeChord(const Chord& chord);
void UpdateChord(const Chord& chord);
void FinishChord(const Chord& chord);
void ClearChord();
bool DeleteLastSyllable();
void OnContextUpdate(Context* ctx);
Expand All @@ -45,8 +65,7 @@ class ChordComposer : public Processor {
bool use_caps_ = false;
bool finish_chord_on_first_key_release_ = false;

set<int> pressed_;
set<int> chord_;
ChordingState state_;
bool editing_chord_ = false;
bool sending_chord_ = false;
bool composing_ = false;
Expand Down

0 comments on commit e554510

Please sign in to comment.