Parse mouse events.

This commit is contained in:
ArthurSonzogni 2021-04-18 18:32:38 +02:00
parent 476b9deaf8
commit cbd13499ae
No known key found for this signature in database
GPG Key ID: 41D98248C074CD6C
6 changed files with 251 additions and 44 deletions

View File

@ -23,10 +23,35 @@ class DrawKey : public Component {
code += L" " + std::to_wstring((unsigned int)it); code += L" " + std::to_wstring((unsigned int)it);
code = L"(" + code + L" ) -> "; code = L"(" + code + L" ) -> ";
if (keys[i].is_character()) if (keys[i].is_character()) {
code += keys[i].character(); code += std::wstring(L"character(") + keys[i].character() + L")";
else } else if (keys[i].is_mouse_move()) {
code += L"mouse_move(" + //
std::to_wstring(keys[i].mouse_x()) + L"," +
std::to_wstring(keys[i].mouse_y()) + L")";
} else if (keys[i].is_mouse_up()) {
code += L"mouse_up(" + //
std::to_wstring(keys[i].mouse_x()) + L"," +
std::to_wstring(keys[i].mouse_y()) + L")";
} else if (keys[i].is_mouse_left_down()) {
code += L"mouse_left_down(" + //
std::to_wstring(keys[i].mouse_x()) + L"," +
std::to_wstring(keys[i].mouse_y()) + L")";
} else if (keys[i].is_mouse_left_move()) {
code += L"mouse_left_move(" + //
std::to_wstring(keys[i].mouse_x()) + L"," +
std::to_wstring(keys[i].mouse_y()) + L")";
} else if (keys[i].is_mouse_right_down()) {
code += L"mouse_right_down(" + //
std::to_wstring(keys[i].mouse_x()) + L"," +
std::to_wstring(keys[i].mouse_y()) + L")";
} else if (keys[i].is_mouse_right_move()) {
code += L"mouse_right_move(" + //
std::to_wstring(keys[i].mouse_x()) + L"," +
std::to_wstring(keys[i].mouse_y()) + L")";
} else {
code += L"(special)"; code += L"(special)";
}
children.push_back(text(code)); children.push_back(text(code));
} }
return window(text(L"keys"), vbox(std::move(children))); return window(text(L"keys"), vbox(std::move(children)));

View File

@ -26,8 +26,14 @@ struct Event {
static Event Character(char); static Event Character(char);
static Event Character(wchar_t); static Event Character(wchar_t);
static Event Character(const std::string&); static Event Character(std::string);
static Event Special(const std::string&); static Event Special(std::string);
static Event MouseMove(std::string, int x, int y);
static Event MouseUp(std::string, int x, int y);
static Event MouseLeftMove(std::string, int x, int y);
static Event MouseLeftDown(std::string, int x, int y);
static Event MouseRightMove(std::string, int x, int y);
static Event MouseRightDown(std::string, int x, int y);
// --- Arrow --- // --- Arrow ---
static const Event ArrowLeft; static const Event ArrowLeft;
@ -48,17 +54,47 @@ struct Event {
static Event Custom; static Event Custom;
//--- Method section --------------------------------------------------------- //--- Method section ---------------------------------------------------------
bool is_character() const { return is_character_; } bool is_character() const { return type_ == Type::Character;}
wchar_t character() const { return character_; } wchar_t character() const { return character_; }
bool is_mouse_left_down() const { return type_ == Type::MouseLeftDown; }
bool is_mouse_left_move() const { return type_ == Type::MouseLeftMove; }
bool is_mouse_right_down() const { return type_ == Type::MouseRightDown; }
bool is_mouse_right_move() const { return type_ == Type::MouseRightMove; }
bool is_mouse_up() const { return type_ == Type::MouseUp; }
bool is_mouse_move() const { return type_ == Type::MouseMove; }
int mouse_x() const { return mouse_.x; }
int mouse_y() const { return mouse_.y; }
const std::string& input() const { return input_; } const std::string& input() const { return input_; }
bool operator==(const Event& other) const { return input_ == other.input_; } bool operator==(const Event& other) const { return input_ == other.input_; }
//--- State section ---------------------------------------------------------- //--- State section ----------------------------------------------------------
private: private:
std::string input_; enum class Type {
bool is_character_ = false; Unknown,
Character,
MouseMove,
MouseUp,
MouseLeftDown,
MouseLeftMove,
MouseRightDown,
MouseRightMove,
};
struct Mouse {
int x;
int y;
};
Type type_ = Type::Unknown;
union {
wchar_t character_ = U'?'; wchar_t character_ = U'?';
Mouse mouse_;
};
std::string input_;
}; };

View File

@ -6,11 +6,11 @@
namespace ftxui { namespace ftxui {
// static // static
Event Event::Character(const std::string& input) { Event Event::Character(std::string input) {
Event event; Event event;
event.input_ = input;
event.is_character_ = true;
event.character_ = to_wstring(input)[0]; event.character_ = to_wstring(input)[0];
event.input_ = std::move(input);
event.type_ = Type::Character;
return event; return event;
} }
@ -23,13 +23,67 @@ Event Event::Character(char c) {
Event Event::Character(wchar_t c) { Event Event::Character(wchar_t c) {
Event event; Event event;
event.input_ = {(char)c}; event.input_ = {(char)c};
event.is_character_ = true; event.type_ = Type::Character;
event.character_ = c; event.character_ = c;
return event; return event;
} }
// static // static
Event Event::Special(const std::string& input) { Event Event::MouseMove(std::string input, int x, int y) {
Event event;
event.input_ = std::move(input);
event.type_ = Type::MouseMove;
event.mouse_ = {x, y};
return event;
}
// static
Event Event::MouseUp(std::string input, int x, int y) {
Event event;
event.input_ = std::move(input);
event.type_ = Type::MouseUp;
event.mouse_ = {x, y};
return event;
}
// static
Event Event::MouseLeftDown(std::string input, int x, int y) {
Event event;
event.input_ = std::move(input);
event.type_ = Type::MouseLeftDown;
event.mouse_ = {x, y};
return event;
}
// static
Event Event::MouseLeftMove(std::string input, int x, int y) {
Event event;
event.input_ = std::move(input);
event.type_ = Type::MouseLeftMove;
event.mouse_ = {x, y};
return event;
}
// static
Event Event::MouseRightDown(std::string input, int x, int y) {
Event event;
event.input_ = std::move(input);
event.type_ = Type::MouseRightDown;
event.mouse_ = {x, y};
return event;
}
// static
Event Event::MouseRightMove(std::string input, int x, int y) {
Event event;
event.input_ = std::move(input);
event.type_ = Type::MouseRightMove;
event.mouse_ = {x, y};
return event;
}
// static
Event Event::Special(std::string input) {
Event event; Event event;
event.input_ = std::move(input); event.input_ = std::move(input);
return event; return event;

View File

@ -155,8 +155,8 @@ static const char DISABLE_LINE_WRAP[] = "\x1B[7l";
static const char USE_ALTERNATIVE_SCREEN[] = "\x1B[?1049h"; static const char USE_ALTERNATIVE_SCREEN[] = "\x1B[?1049h";
static const char USE_NORMAL_SCREEN[] = "\x1B[?1049l"; static const char USE_NORMAL_SCREEN[] = "\x1B[?1049l";
static const char ENABLE_MOUSE[] = "\x1B[?1000;1006;1015h"; static const char ENABLE_MOUSE[] = "\x1B[?1000;1003;1006;1015h";
static const char DISABLE_MOUSE[] = "\x1B[?1000;10006;1015l"; static const char DISABLE_MOUSE[] = "\x1B[?1000;1003;10006;1015l";
using SignalHandler = void(int); using SignalHandler = void(int);
std::stack<std::function<void()>> on_exit_functions; std::stack<std::function<void()>> on_exit_functions;

View File

@ -30,28 +30,56 @@ bool TerminalInputParser::Eat() {
return position_ < (int)pending_.size(); return position_ < (int)pending_.size();
} }
void TerminalInputParser::Send(TerminalInputParser::Type type) { void TerminalInputParser::Send(TerminalInputParser::Output output) {
switch (type) { switch (output.type) {
case UNCOMPLETED: case UNCOMPLETED:
return; return;
case DROP: case DROP:
pending_.clear(); break;
return;
case CHARACTER: case CHARACTER:
out_->Send(Event::Character(std::move(pending_))); out_->Send(Event::Character(std::move(pending_)));
pending_.clear(); break;
return;
case SPECIAL: case SPECIAL:
out_->Send(Event::Special(std::move(pending_))); out_->Send(Event::Special(std::move(pending_)));
pending_.clear(); break;
return;
case MOUSE_MOVE:
out_->Send(
Event::MouseMove(std::move(pending_), output.mouse.x, output.mouse.y));
break;
case MOUSE_UP:
out_->Send(
Event::MouseUp(std::move(pending_), output.mouse.x, output.mouse.y));
break;
case MOUSE_LEFT_DOWN:
out_->Send(Event::MouseLeftDown(std::move(pending_), output.mouse.x,
output.mouse.y));
break;
case MOUSE_LEFT_MOVE:
out_->Send(Event::MouseLeftMove(std::move(pending_), output.mouse.x,
output.mouse.y));
break;
case MOUSE_RIGHT_DOWN:
out_->Send(Event::MouseRightDown(std::move(pending_), output.mouse.x,
output.mouse.y));
break;
case MOUSE_RIGHT_MOVE:
out_->Send(Event::MouseRightMove(std::move(pending_), output.mouse.x,
output.mouse.y));
break;
} }
pending_.clear();
} }
TerminalInputParser::Type TerminalInputParser::Parse() { TerminalInputParser::Output TerminalInputParser::Parse() {
if (!Eat()) if (!Eat())
return UNCOMPLETED; return UNCOMPLETED;
@ -75,7 +103,7 @@ TerminalInputParser::Type TerminalInputParser::Parse() {
return ParseUTF8(); return ParseUTF8();
} }
TerminalInputParser::Type TerminalInputParser::ParseUTF8() { TerminalInputParser::Output TerminalInputParser::ParseUTF8() {
unsigned char head = static_cast<unsigned char>(Current()); unsigned char head = static_cast<unsigned char>(Current());
for (int i = 0; i < 3; ++i, head <<= 1) { for (int i = 0; i < 3; ++i, head <<= 1) {
if ((head & 0b11000000) != 0b11000000) if ((head & 0b11000000) != 0b11000000)
@ -86,7 +114,7 @@ TerminalInputParser::Type TerminalInputParser::ParseUTF8() {
return CHARACTER; return CHARACTER;
} }
TerminalInputParser::Type TerminalInputParser::ParseESC() { TerminalInputParser::Output TerminalInputParser::ParseESC() {
if (!Eat()) if (!Eat())
return UNCOMPLETED; return UNCOMPLETED;
switch (Current()) { switch (Current()) {
@ -103,7 +131,7 @@ TerminalInputParser::Type TerminalInputParser::ParseESC() {
} }
} }
TerminalInputParser::Type TerminalInputParser::ParseDCS() { TerminalInputParser::Output TerminalInputParser::ParseDCS() {
// Parse until the string terminator ST. // Parse until the string terminator ST.
while (1) { while (1) {
if (!Eat()) if (!Eat())
@ -122,19 +150,35 @@ TerminalInputParser::Type TerminalInputParser::ParseDCS() {
} }
} }
TerminalInputParser::Type TerminalInputParser::ParseCSI() { TerminalInputParser::Output TerminalInputParser::ParseCSI() {
int argument;
std::vector<int> arguments;
while (true) { while (true) {
if (!Eat()) if (!Eat())
return UNCOMPLETED; return UNCOMPLETED;
if (Current() >= '0' && Current() <= '9') if (Current() >= '0' && Current() <= '9') {
argument *= 10;
argument += int(Current() - '0');
continue; continue;
}
if (Current() == ';') if (Current() == ';') {
arguments.push_back(argument);
argument = 0;
continue; continue;
}
if (Current() >= ' ' && Current() <= '~') if (Current() >= ' ' && Current() <= '~') {
arguments.push_back(argument);
argument = 0;
switch (Current()) {
case 'M':
return ParseMouse(std::move(arguments));
default:
return SPECIAL; return SPECIAL;
}
}
// Invalid ESC in CSI. // Invalid ESC in CSI.
if (Current() == '\x1B') if (Current() == '\x1B')
@ -142,7 +186,7 @@ TerminalInputParser::Type TerminalInputParser::ParseCSI() {
} }
} }
TerminalInputParser::Type TerminalInputParser::ParseOSC() { TerminalInputParser::Output TerminalInputParser::ParseOSC() {
// Parse until the string terminator ST. // Parse until the string terminator ST.
while (true) { while (true) {
if (!Eat()) if (!Eat())
@ -156,4 +200,28 @@ TerminalInputParser::Type TerminalInputParser::ParseOSC() {
return SPECIAL; return SPECIAL;
} }
} }
TerminalInputParser::Output TerminalInputParser::ParseMouse(
std::vector<int> arguments) {
if (arguments.size() != 3)
return SPECIAL;
switch(arguments[0]) {
case 32:
return Output(MOUSE_LEFT_DOWN, arguments[1], arguments[2]);
case 64:
return Output(MOUSE_LEFT_MOVE, arguments[1], arguments[2]);
case 34:
return Output(MOUSE_RIGHT_DOWN, arguments[1], arguments[2]);
case 66:
return Output(MOUSE_RIGHT_MOVE, arguments[1], arguments[2]);
case 35:
return Output(MOUSE_UP, arguments[1], arguments[2]);
case 67:
return Output(MOUSE_MOVE, arguments[1], arguments[2]);
}
return SPECIAL;
}
} // namespace ftxui } // namespace ftxui

View File

@ -20,18 +20,42 @@ class TerminalInputParser {
bool Eat(); bool Eat();
enum Type { enum Type {
UNCOMPLETED = 0, UNCOMPLETED,
DROP = 1, DROP,
CHARACTER = 2, CHARACTER,
SPECIAL = 3, SPECIAL,
MOUSE_UP,
MOUSE_MOVE,
MOUSE_LEFT_DOWN,
MOUSE_LEFT_MOVE,
MOUSE_RIGHT_DOWN,
MOUSE_RIGHT_MOVE,
}; };
void Send(Type type);
Type Parse(); struct Mouse {
Type ParseUTF8(); int x;
Type ParseESC(); int y;
Type ParseDCS(); Mouse(int x, int y) : x(x), y(y) {}
Type ParseCSI(); };
Type ParseOSC();
struct Output {
Type type;
union {
Mouse mouse;
};
Output(Type type) : type(type) {}
Output(Type type, int x, int y) : type(type), mouse(x, y) {}
};
void Send(Output type);
Output Parse();
Output ParseUTF8();
Output ParseESC();
Output ParseDCS();
Output ParseCSI();
Output ParseOSC();
Output ParseMouse(std::vector<int> arguments);
Sender<Event> out_; Sender<Event> out_;
int position_ = -1; int position_ = -1;