mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2024-11-22 18:59:59 +08:00
Mouse support. Fix & verify Webassembly support.
There was some undefined behavior to be fixed in the terminal input parser. The behavior of flush seems to have change. The fix was to invert '\0' and std::flush.
This commit is contained in:
parent
0b9b6c692a
commit
a27c878a3f
@ -10,7 +10,7 @@
|
||||
<div class="page">
|
||||
<h1>FTXUI WebAssembly Example </h1>
|
||||
<p>
|
||||
<a href="https://github.com/ArthurSonzogni/FTXUI">FTXUI</a> is a single
|
||||
<a href="https://github.com/ArthurSonzogni/FTXUI">FTXUI</a> is a simple
|
||||
C++ library for terminal user interface.
|
||||
</p>
|
||||
<p>
|
||||
@ -69,10 +69,8 @@
|
||||
];
|
||||
|
||||
const url_search_params = new URLSearchParams(window.location.search);
|
||||
const example_index = url_search_params.get("id") || 16;
|
||||
const example = example_list[example_index];
|
||||
|
||||
var select = document.getElementById("selectExample");
|
||||
const example = url_search_params.get("file") || "./dom/color_gallery.js"
|
||||
const select = document.getElementById("selectExample");
|
||||
|
||||
for(var i = 0; i < example_list.length; i++) {
|
||||
var opt = example_list[i];
|
||||
@ -81,9 +79,10 @@
|
||||
el.value = opt;
|
||||
select.appendChild(el);
|
||||
}
|
||||
select.selectedIndex = example_index;
|
||||
select.selectedIndex = example_list.findIndex(path => path == example) || 0;
|
||||
select.addEventListener("change", () => {
|
||||
location.href = (location.href).split('?')[0] + "?id=" + select.selectedIndex;
|
||||
location.href = (location.href).split('?')[0] + "?file=" +
|
||||
example_list[select.selectedIndex];
|
||||
});
|
||||
|
||||
let stdin_buffer = [];
|
||||
@ -94,6 +93,7 @@
|
||||
stdout_buffer = [];
|
||||
let stdout = code => {
|
||||
if (code == 0) {
|
||||
console.log(code);
|
||||
term.write(new Uint8Array(stdout_buffer));
|
||||
stdout_buffer = [];
|
||||
} else {
|
||||
|
@ -27,6 +27,11 @@ class Input : public Component {
|
||||
// Component implementation.
|
||||
Element Render() override;
|
||||
bool OnEvent(Event) override;
|
||||
|
||||
private:
|
||||
bool OnMouseEvent(Event);
|
||||
Box input_box_;
|
||||
Box cursor_box_;
|
||||
};
|
||||
|
||||
} // namespace ftxui
|
||||
|
@ -15,14 +15,15 @@ Element Input::Render() {
|
||||
// Placeholder.
|
||||
if (content.size() == 0) {
|
||||
if (is_focused)
|
||||
return text(placeholder) | focus | dim | inverted | main_decorator;
|
||||
return text(placeholder) | focus | dim | inverted | main_decorator |
|
||||
reflect(input_box_);
|
||||
else
|
||||
return text(placeholder) | dim | main_decorator;
|
||||
return text(placeholder) | dim | main_decorator | reflect(input_box_);
|
||||
}
|
||||
|
||||
// Not focused.
|
||||
if (!is_focused)
|
||||
return text(content) | main_decorator;
|
||||
return text(content) | main_decorator | reflect(input_box_);
|
||||
|
||||
std::wstring part_before_cursor = content.substr(0, cursor_position);
|
||||
std::wstring part_at_cursor = cursor_position < (int)content.size()
|
||||
@ -37,13 +38,18 @@ Element Input::Render() {
|
||||
return
|
||||
hbox(
|
||||
text(part_before_cursor),
|
||||
text(part_at_cursor) | underlined | focused,
|
||||
text(part_at_cursor) | underlined | focused | reflect(cursor_box_),
|
||||
text(part_after_cursor)
|
||||
) | flex | inverted | frame | main_decorator;
|
||||
// clang-format off
|
||||
) | flex | inverted | frame | main_decorator | reflect(input_box_);
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
bool Input::OnEvent(Event event) {
|
||||
cursor_position = std::max(0, std::min<int>(content.size(), cursor_position));
|
||||
|
||||
if (event.is_mouse())
|
||||
return OnMouseEvent(event);
|
||||
|
||||
std::wstring c;
|
||||
|
||||
// Backspace.
|
||||
@ -95,6 +101,26 @@ bool Input::OnEvent(Event event) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Input::OnMouseEvent(Event event) {
|
||||
if (!input_box_.Contain(event.mouse().x, event.mouse().y))
|
||||
return false;
|
||||
|
||||
TakeFocus();
|
||||
|
||||
if (event.mouse().button == Mouse::Left &&
|
||||
event.mouse().motion == Mouse::Pressed) {
|
||||
int new_cursor_position =
|
||||
cursor_position + event.mouse().x - cursor_box_.x_min;
|
||||
new_cursor_position =
|
||||
std::max(0, std::min<int>(content.size(), new_cursor_position));
|
||||
if (cursor_position != new_cursor_position) {
|
||||
cursor_position = new_cursor_position;
|
||||
on_change();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
||||
|
@ -40,7 +40,7 @@ namespace {
|
||||
|
||||
void Flush() {
|
||||
// Emscripten doesn't implement flush. We interpret zero as flush.
|
||||
std::cout << std::flush << (char)0;
|
||||
std::cout << '\0' << std::flush;
|
||||
}
|
||||
|
||||
constexpr int timeout_milliseconds = 20;
|
||||
@ -353,6 +353,8 @@ void ScreenInteractive::Loop(Component* component) {
|
||||
DECMode::kMouseSgrExtMode,
|
||||
});
|
||||
|
||||
flush();
|
||||
|
||||
auto event_listener =
|
||||
std::thread(&EventListener, &quit_, event_receiver_->MakeSender());
|
||||
|
||||
|
@ -41,19 +41,23 @@ void TerminalInputParser::Send(TerminalInputParser::Output output) {
|
||||
|
||||
case CHARACTER:
|
||||
out_->Send(Event::Character(std::move(pending_)));
|
||||
pending_.clear();
|
||||
return;
|
||||
|
||||
case SPECIAL:
|
||||
out_->Send(Event::Special(std::move(pending_)));
|
||||
pending_.clear();
|
||||
return;
|
||||
|
||||
case MOUSE:
|
||||
out_->Send(Event::Mouse(std::move(pending_), output.mouse));
|
||||
pending_.clear();
|
||||
return;
|
||||
|
||||
case CURSOR_REPORTING:
|
||||
out_->Send(Event::CursorReporting(std::move(pending_), output.cursor.x,
|
||||
output.cursor.y));
|
||||
pending_.clear();
|
||||
return;
|
||||
}
|
||||
// NOT_REACHED().
|
||||
@ -133,7 +137,7 @@ TerminalInputParser::Output TerminalInputParser::ParseDCS() {
|
||||
|
||||
TerminalInputParser::Output TerminalInputParser::ParseCSI() {
|
||||
bool altered = false;
|
||||
int argument;
|
||||
int argument = 0;
|
||||
std::vector<int> arguments;
|
||||
while (true) {
|
||||
if (!Eat())
|
||||
@ -205,9 +209,8 @@ TerminalInputParser::Output TerminalInputParser::ParseMouse(
|
||||
output.mouse.button = Mouse::Button((arguments[0] & 3) + //
|
||||
((arguments[0] & 64) >> 4));
|
||||
output.mouse.motion = Mouse::Motion(pressed);
|
||||
output.mouse.shift = arguments[0] & 4;
|
||||
output.mouse.meta = arguments[0] & 8;
|
||||
output.mouse.control = arguments[0] & 16;
|
||||
output.mouse.shift = bool(arguments[0] & 4);
|
||||
output.mouse.meta = bool(arguments[0] & 8);
|
||||
output.mouse.x = arguments[1];
|
||||
output.mouse.y = arguments[2];
|
||||
return output;
|
||||
|
@ -184,7 +184,7 @@ std::string Screen::ToString() {
|
||||
}
|
||||
|
||||
void Screen::Print() {
|
||||
std::cout << ToString() << std::flush << (char)0;
|
||||
std::cout << ToString() << '\0' << std::flush;
|
||||
}
|
||||
|
||||
/// @brief Access a character a given position.
|
||||
|
Loading…
Reference in New Issue
Block a user