blob: 5858ea798b949213cb4e1d9513837bb2aad738c0 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
#include "seqmatcher.h"
#include <stdexcept>
#include <cassert>
SeqMatcher::SeqMatcher(Display *dpy) : dpy{dpy} {}
SeqMatcher::SeqMatcher(Display *dpy, std::vector<SymSequence> seqs)
: dpy{dpy} {
for (const auto &seq : seqs) addSequence(seq.syms, seq.callback);
}
void SeqMatcher::addSequence(const std::vector<x::Keysym> &syms, Callback callback) {
if (syms.empty()) {
throw std::logic_error("Cannot register empty key sequence");
}
Node *current = &rootNode;
for (x::Keysym sym : syms) {
if (std::holds_alternative<Callback>(current->v)) {
throw std::logic_error("Overlapping key sequences (second is longer)");
} else {
if (!std::holds_alternative<NodeMap>(current->v)) {
current->v.emplace<NodeMap>();
}
NodeMap &map = std::get<NodeMap>(current->v);
x::Keycode code = sym.toCode(dpy);
auto it = map.find(code);
if (it != map.end()) {
current = it->second.get();
} else {
current = map.emplace(sym.toCode(dpy), std::make_unique<Node>()).first->second.get();
}
}
}
if (auto *map = std::get_if<NodeMap>(¤t->v)) {
if (!map->empty()) {
throw std::logic_error("Overlapping key sequences (second is shorter)");
}
}
if (std::holds_alternative<Callback>(current->v)) {
throw std::logic_error("Overlapping key sequences (equally long)");
}
current->v.emplace<Callback>(callback);
}
std::optional<SeqMatcher::Callback> SeqMatcher::observe(const XKeyEvent &ev) {
auto *map = std::get_if<NodeMap>(&curNode->v);
assert(map);
auto it = map->find(x::Keycode{ev.keycode});
if (it == map->end()) {
// Sequence not found
reset();
return [dpy = dpy]() { x::bel(dpy); };
}
curNode = it->second.get();
if (auto *cb = std::get_if<Callback>(&curNode->v)) {
// Sequence completed
reset();
return *cb;
}
// Need more keys
return std::nullopt;
}
void SeqMatcher::reset() {
curNode = &rootNode;
}
|