From f94b63fafb1e99ba8a72e3ca529fc7d3a5544e2c Mon Sep 17 00:00:00 2001
From: Arthur Sonzogni <sonzogniarthur@gmail.com>
Date: Thu, 18 Oct 2018 22:58:38 +0200
Subject: [PATCH] Add Event.

---
 examples/CMakeLists.txt                       |  1 +
 examples/input/CMakeLists.txt                 |  4 ++
 examples/input/main.cpp                       | 47 +++++++++++++++++++
 examples/print_key_press/main.cpp             | 18 ++++---
 examples/toggle/main.cpp                      |  7 +--
 ftxui/CMakeLists.txt                          |  3 +-
 ftxui/include/ftxui/component/Event.hpp       | 34 --------------
 ftxui/include/ftxui/component/component.hpp   |  5 +-
 .../ftxui/component/component_direction.hpp   |  4 +-
 .../ftxui/component/component_horizontal.hpp  |  4 +-
 .../ftxui/component/component_vertical.hpp    |  4 +-
 ftxui/include/ftxui/component/input.hpp       | 35 ++++++++++++++
 ftxui/include/ftxui/component/menu.hpp        |  2 +-
 ftxui/include/ftxui/component/toggle.hpp      |  2 +-
 ftxui/include/ftxui/event.hpp                 | 37 +++++++++++++++
 ftxui/src/ftxui/component/component.cpp       |  2 +-
 .../ftxui/component/component_direction.cpp   |  6 +--
 .../ftxui/component/component_horizontal.cpp  |  6 +--
 .../ftxui/component/component_vertical.cpp    |  6 +--
 ftxui/src/ftxui/component/input.cpp           | 46 ++++++++++++++++++
 ftxui/src/ftxui/component/menu.cpp            |  9 ++--
 ftxui/src/ftxui/component/toggle.cpp          |  7 ++-
 ftxui/src/ftxui/event.cpp                     | 37 +++++++++++++++
 ftxui/src/ftxui/screen_interactive.cpp        | 19 ++++++--
 tutorial.md                                   |  4 ++
 25 files changed, 273 insertions(+), 76 deletions(-)
 create mode 100644 examples/input/CMakeLists.txt
 create mode 100644 examples/input/main.cpp
 delete mode 100644 ftxui/include/ftxui/component/Event.hpp
 create mode 100644 ftxui/include/ftxui/component/input.hpp
 create mode 100644 ftxui/include/ftxui/event.hpp
 create mode 100644 ftxui/src/ftxui/component/input.cpp
 create mode 100644 ftxui/src/ftxui/event.cpp

diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 53382c7d..9ffb08ec 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -1,6 +1,7 @@
 add_subdirectory(color)
 add_subdirectory(frame)
 add_subdirectory(gauge)
+add_subdirectory(input)
 add_subdirectory(menu)
 add_subdirectory(menu2)
 add_subdirectory(print_key_press)
diff --git a/examples/input/CMakeLists.txt b/examples/input/CMakeLists.txt
new file mode 100644
index 00000000..1e37595c
--- /dev/null
+++ b/examples/input/CMakeLists.txt
@@ -0,0 +1,4 @@
+add_executable(input_main
+  main.cpp
+)
+target_link_libraries(input_main PRIVATE ftxui)
diff --git a/examples/input/main.cpp b/examples/input/main.cpp
new file mode 100644
index 00000000..fa4e0be8
--- /dev/null
+++ b/examples/input/main.cpp
@@ -0,0 +1,47 @@
+#include <chrono>
+#include <iostream>
+#include <thread>
+
+#include "ftxui/screen_interactive.hpp"
+#include "ftxui/component/input.hpp"
+#include "ftxui/component/component_vertical.hpp"
+#include "ftxui/util/string.hpp"
+
+using namespace ftxui::component;
+using namespace ftxui::dom;
+
+class MyComponent : ComponentVertical {
+ public:
+  MyComponent(ftxui::component::Delegate* delegate)
+      : ComponentVertical(delegate),
+        input_1(delegate->NewChild()),
+        input_2(delegate->NewChild()),
+        input_3(delegate->NewChild()) {
+    Focus(&input_1);
+  }
+
+  std::function<void()> on_enter = []() {};
+
+ private:
+  Input input_1;
+  Input input_2;
+  Input input_3;
+
+  Element Render() override {
+    return
+      frame(
+        vbox(
+          hbox(text(L" input_1 : "), input_1.Render()),
+          hbox(text(L" input_2 : "), input_2.Render()),
+          hbox(text(L" input_3 : "), input_3.Render())
+        )
+      );
+  }
+};
+
+int main(int argc, const char* argv[]) {
+  ftxui::ScreenInteractive screen(60, 17);
+  MyComponent component(screen.delegate());
+  component.on_enter = screen.ExitLoopClosure();
+  screen.Loop();
+}
diff --git a/examples/print_key_press/main.cpp b/examples/print_key_press/main.cpp
index b36d2815..eb5e927c 100644
--- a/examples/print_key_press/main.cpp
+++ b/examples/print_key_press/main.cpp
@@ -15,26 +15,30 @@ class DrawKey : public ftxui::component::Component {
     using namespace ftxui::dom;
     Children children;
     for (size_t i = std::max(0, (int)keys.size() - 10); i < keys.size(); ++i) {
+        std::string code = "";
+      for(size_t j = 0; j<5; ++j)
+        code += " " + std::to_string(keys[i].values[j]);
+
       try {
-        std::string line = std::to_string(i) + " -> " + std::to_string(keys[i]) +
-                           " (" + char(keys[i]) + ")";
+        std::string line = code + " -> " + std::to_string(keys[i].values[0]) + " (" +
+                           char(keys[i].values[0]) + ")";
         children.push_back(text(to_wstring(line)));
       } catch (...) {
-        std::string line = std::to_string(i) + " -> " + std::to_string(keys[i]) +
-                           " (undefined)";
+        std::string line =
+            code + " -> " + std::to_string(keys[i].values[0]) + " (undefined)";
         children.push_back(text(to_wstring(line)));
       }
     }
     return vbox(std::move(children));
   }
 
-  bool Event(int key) override {
-    keys.push_back(key);
+  bool OnEvent(ftxui::Event event) override {
+    keys.push_back(event);
     return true;
   }
 
  private:
-  std::vector<int> keys;
+  std::vector<ftxui::Event> keys;
 };
 
 int main(int argc, const char* argv[]) {
diff --git a/examples/toggle/main.cpp b/examples/toggle/main.cpp
index 959cc705..e0323927 100644
--- a/examples/toggle/main.cpp
+++ b/examples/toggle/main.cpp
@@ -8,6 +8,7 @@
 #include "ftxui/component/component_vertical.hpp"
 #include "ftxui/util/string.hpp"
 
+using namespace ftxui;
 using namespace ftxui::component;
 using namespace ftxui::dom;
 
@@ -48,11 +49,11 @@ class MyComponent : ComponentVertical {
       );
   }
 
-  bool Event(int key) override {
-    if (ComponentVertical::Event(key))
+  bool OnEvent(Event event) override {
+    if (ComponentVertical::OnEvent(event))
       return true;
 
-    if (key == 10) {
+    if (event == Event::Return) {
       on_enter();
       return true;
     }
diff --git a/ftxui/CMakeLists.txt b/ftxui/CMakeLists.txt
index 7128aac9..6991e408 100644
--- a/ftxui/CMakeLists.txt
+++ b/ftxui/CMakeLists.txt
@@ -6,6 +6,7 @@ add_library(ftxui
   src/ftxui/component/component_direction.cpp
   src/ftxui/component/component_horizontal.cpp
   src/ftxui/component/component_vertical.cpp
+  src/ftxui/component/input.cpp
   src/ftxui/component/menu.cpp
   src/ftxui/component/toggle.cpp
   src/ftxui/dom/bold.cpp
@@ -14,7 +15,6 @@ add_library(ftxui
   src/ftxui/dom/dim.cpp
   src/ftxui/dom/flex.cpp
   src/ftxui/dom/frame.cpp
-  src/ftxui/dom/frame.cpp
   src/ftxui/dom/gauge.cpp
   src/ftxui/dom/hbox.cpp
   src/ftxui/dom/inverted.cpp
@@ -24,6 +24,7 @@ add_library(ftxui
   src/ftxui/dom/text.cpp
   src/ftxui/dom/underlined.cpp
   src/ftxui/dom/vbox.cpp
+  src/ftxui/event.cpp
   src/ftxui/screen.cpp
   src/ftxui/screen_interactive.cpp
   src/ftxui/terminal.cpp
diff --git a/ftxui/include/ftxui/component/Event.hpp b/ftxui/include/ftxui/component/Event.hpp
deleted file mode 100644
index 4ce8a77c..00000000
--- a/ftxui/include/ftxui/component/Event.hpp
+++ /dev/null
@@ -1,34 +0,0 @@
-#ifndef FTXUI_COMPONENT_EVENT
-#define FTXUI_COMPONENT_EVENT
-
-namespace ftxui {
-namespace component {
-
-struct Event{
-  // --- Character ---
-  static Event Character(char);
-
-  // --- Arrow ---
-  static Event Arrow_Left;
-  static Event Arrow_Right;
-  static Event Arrow_Up;
-  static Event Arrow_Down;
-  
-  // --- Other ---
-  static Event Backspace;
-  static Event Delete;
-  static Event Escape;
-  static Event F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12;
-
-  // Internal representation.
-  int values [3];
-  Event(int values[3]) : values(values);
-
-};
-
-
-} // namespace component
-} // namespace ftxui
-
-
-#endif /* end of include guard: FTXUI_COMPONENT_EVENT */
diff --git a/ftxui/include/ftxui/component/component.hpp b/ftxui/include/ftxui/component/component.hpp
index 80e77b7e..1c575ef8 100644
--- a/ftxui/include/ftxui/component/component.hpp
+++ b/ftxui/include/ftxui/component/component.hpp
@@ -1,8 +1,9 @@
 #ifndef FTXUI_COMPONENT_COMPONENT_HPP
 #define FTXUI_COMPONENT_COMPONENT_HPP
 
-#include "ftxui/dom/elements.hpp"
 #include "ftxui/component/delegate.hpp"
+#include "ftxui/dom/elements.hpp"
+#include "ftxui/event.hpp"
 
 namespace ftxui {
 namespace component {
@@ -20,7 +21,7 @@ class Component {
   virtual dom::Element Render();
 
   // Handle an event. By default, it calls this function on each children.
-  virtual bool Event(int key);
+  virtual bool OnEvent(Event even);
 
   // If this component contains children, this indicates which one is active. It
   // can be none of them.
diff --git a/ftxui/include/ftxui/component/component_direction.hpp b/ftxui/include/ftxui/component/component_direction.hpp
index d71f2ac0..55b99ef8 100644
--- a/ftxui/include/ftxui/component/component_direction.hpp
+++ b/ftxui/include/ftxui/component/component_direction.hpp
@@ -10,12 +10,12 @@ namespace component {
 class ComponentDirection : public Component {
  public:
   ComponentDirection(Delegate* delegate);
-  bool Event(int key) override;
+  bool OnEvent(Event) override;
   Component* GetActiveChild() override;
 
  protected:
   void Focus(Component* child);
-  virtual bool HandleDirection(int key) = 0;
+  virtual bool HandleDirection(Event) = 0;
   Component* active_child_;
 };
 
diff --git a/ftxui/include/ftxui/component/component_horizontal.hpp b/ftxui/include/ftxui/component/component_horizontal.hpp
index f518c328..35dadf2b 100644
--- a/ftxui/include/ftxui/component/component_horizontal.hpp
+++ b/ftxui/include/ftxui/component/component_horizontal.hpp
@@ -10,8 +10,8 @@ namespace component {
 // It assumes its children are put in the horizontal direction.
 class ComponentHorizontal : public ComponentDirection {
  public:
-  ComponentHorizontal(Delegate* delegate);
-  bool HandleDirection(int key) override;
+  ComponentHorizontal(Delegate*);
+  bool HandleDirection(Event) override;
 };
 
 } // namespace component
diff --git a/ftxui/include/ftxui/component/component_vertical.hpp b/ftxui/include/ftxui/component/component_vertical.hpp
index a8408589..22c91f25 100644
--- a/ftxui/include/ftxui/component/component_vertical.hpp
+++ b/ftxui/include/ftxui/component/component_vertical.hpp
@@ -10,8 +10,8 @@ namespace component {
 // It assumes its children are put in the vertical direction.
 class ComponentVertical : public ComponentDirection {
  public:
-  ComponentVertical(Delegate* delegate);
-  bool HandleDirection(int key) override;
+  ComponentVertical(Delegate*);
+  bool HandleDirection(Event) override;
 };
 
 } // namespace component
diff --git a/ftxui/include/ftxui/component/input.hpp b/ftxui/include/ftxui/component/input.hpp
new file mode 100644
index 00000000..b45256d9
--- /dev/null
+++ b/ftxui/include/ftxui/component/input.hpp
@@ -0,0 +1,35 @@
+#ifndef FTXUI_COMPONENT_INPUT_H_
+#define FTXUI_COMPONENT_INPUT_H_
+
+#include "ftxui/component/component.hpp"
+#include <functional>
+
+namespace ftxui {
+namespace component {
+
+class Input : public Component {
+ public:
+  // Constructor.
+  Input(Delegate*);
+  ~Input() override;
+
+  // State.
+  std::wstring content = L"input";
+  std::wstring placeholder = L"placeholder";
+
+  // State update callback.
+  std::function<void()> on_change = [](){};
+  std::function<void()> on_enter = [](){};
+
+  // Component implementation.
+  dom::Element Render() override;
+	bool OnEvent(Event) override;
+
+ private:
+  int cursor_position = 0;
+};
+
+}  // namespace component
+}  // namespace ftxui
+
+#endif /* end of include guard: FTXUI_COMPONENT_INPUT_H_ */
diff --git a/ftxui/include/ftxui/component/menu.hpp b/ftxui/include/ftxui/component/menu.hpp
index 79dd19f9..91aa484e 100644
--- a/ftxui/include/ftxui/component/menu.hpp
+++ b/ftxui/include/ftxui/component/menu.hpp
@@ -22,7 +22,7 @@ class Menu : public Component {
 
   // Component implementation.
   dom::Element Render() override;
-	bool Event(int key) override;
+	bool OnEvent(Event) override;
 };
 
 }  // namespace component
diff --git a/ftxui/include/ftxui/component/toggle.hpp b/ftxui/include/ftxui/component/toggle.hpp
index daa18e74..64eded36 100644
--- a/ftxui/include/ftxui/component/toggle.hpp
+++ b/ftxui/include/ftxui/component/toggle.hpp
@@ -22,7 +22,7 @@ class Toggle : public Component {
 
   // Component implementation.
   dom::Element Render() override;
-	bool Event(int key) override;
+  bool OnEvent(Event) override;
 };
 
 }  // namespace component
diff --git a/ftxui/include/ftxui/event.hpp b/ftxui/include/ftxui/event.hpp
new file mode 100644
index 00000000..15410d7c
--- /dev/null
+++ b/ftxui/include/ftxui/event.hpp
@@ -0,0 +1,37 @@
+#ifndef FTXUI_EVENT_H_
+#define FTXUI_EVENT_H_
+
+#include <vector>
+#include <array>
+
+namespace ftxui {
+
+struct Event{
+ public:
+  // --- Character ---
+  static Event Character(char);
+
+  // --- Arrow ---
+  static Event ArrowLeft;
+  static Event ArrowRight;
+  static Event ArrowUp;
+  static Event ArrowDown;
+  
+  // --- Other ---
+  static Event Backspace;
+  static Event Delete;
+  static Event Return;
+  static Event Escape;
+  static Event F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12;
+
+  bool operator==(const Event& other) { return values == other.values; }
+
+  // Internal representation.
+  std::array<char, 5> values = {0, 0, 0, 0, 0};
+};
+
+
+} // namespace ftxui
+
+
+#endif /* end of include guard: FTXUI_EVENT_H_ */
diff --git a/ftxui/src/ftxui/component/component.cpp b/ftxui/src/ftxui/component/component.cpp
index 369e9c34..9b40d594 100644
--- a/ftxui/src/ftxui/component/component.cpp
+++ b/ftxui/src/ftxui/component/component.cpp
@@ -17,7 +17,7 @@ dom::Element Component::Render() {
   return text(L"Not implemented component");
 }
 
-bool Component::Event(int key) {
+bool Component::OnEvent(Event event) {
   return false;
 }
 
diff --git a/ftxui/src/ftxui/component/component_direction.cpp b/ftxui/src/ftxui/component/component_direction.cpp
index fa77b813..74dc8462 100644
--- a/ftxui/src/ftxui/component/component_direction.cpp
+++ b/ftxui/src/ftxui/component/component_direction.cpp
@@ -6,17 +6,17 @@ namespace component {
 ComponentDirection::ComponentDirection(Delegate* delegate)
     : Component(delegate), active_child_(nullptr) {}
 
-bool ComponentDirection::Event(int key) {
+bool ComponentDirection::OnEvent(Event event) {
   if (!Focused())
     return false;
 
   if (!active_child_)
     return false;
 
-  if (active_child_->Event(key))
+  if (active_child_->OnEvent(event))
     return true;
 
-  return HandleDirection(key);
+  return HandleDirection(event);
 }
 
 Component* ComponentDirection::GetActiveChild() {
diff --git a/ftxui/src/ftxui/component/component_horizontal.cpp b/ftxui/src/ftxui/component/component_horizontal.cpp
index 012098ac..b9079cc8 100644
--- a/ftxui/src/ftxui/component/component_horizontal.cpp
+++ b/ftxui/src/ftxui/component/component_horizontal.cpp
@@ -6,9 +6,9 @@ namespace component {
 ComponentHorizontal::ComponentHorizontal(Delegate* delegate)
     : ComponentDirection(delegate) {}
 
-bool ComponentHorizontal::HandleDirection(int key) {
+bool ComponentHorizontal::HandleDirection(Event event) {
   // Left pressed ?
-  if (key == 68 || key == 'h') {
+  if (event == Event::ArrowLeft || event == Event::Character('h')) {
     Component* previous_sibling = active_child_->PreviousSibling();
     if (previous_sibling) {
       active_child_ = previous_sibling;
@@ -17,7 +17,7 @@ bool ComponentHorizontal::HandleDirection(int key) {
   }
 
   // Left pressed ?
-  if (key == 67 || key == 'l') {
+  if (event == Event::ArrowRight || event == Event::Character('l')) {
     Component* next_sibling = active_child_->NextSibling();
     if (next_sibling) {
       active_child_ = next_sibling;
diff --git a/ftxui/src/ftxui/component/component_vertical.cpp b/ftxui/src/ftxui/component/component_vertical.cpp
index 70d516e7..ec0141fb 100644
--- a/ftxui/src/ftxui/component/component_vertical.cpp
+++ b/ftxui/src/ftxui/component/component_vertical.cpp
@@ -6,9 +6,9 @@ namespace component {
 ComponentVertical::ComponentVertical(Delegate* delegate)
     : ComponentDirection(delegate) {}
 
-bool ComponentVertical::HandleDirection(int key) {
+bool ComponentVertical::HandleDirection(Event event) {
   // Up pressed ?
-  if (key == 65 || key == 'k') {
+  if (event == Event::ArrowUp || event == Event::Character('k')) {
     Component* previous_sibling = active_child_->PreviousSibling();
     if (previous_sibling) {
       active_child_ = previous_sibling;
@@ -17,7 +17,7 @@ bool ComponentVertical::HandleDirection(int key) {
   }
 
   // Down pressed ?
-  if (key == 66 || key == 'j') {
+  if (event == Event::ArrowDown || event == Event::Character('j')) {
     Component* next_sibling = active_child_->NextSibling();
     if (next_sibling) {
       active_child_ = next_sibling;
diff --git a/ftxui/src/ftxui/component/input.cpp b/ftxui/src/ftxui/component/input.cpp
new file mode 100644
index 00000000..3ed3addd
--- /dev/null
+++ b/ftxui/src/ftxui/component/input.cpp
@@ -0,0 +1,46 @@
+#include "ftxui/component/input.hpp"
+#include "ftxui/util/string.hpp"
+
+namespace ftxui {
+namespace component {
+
+Input::Input(Delegate* delegate): Component(delegate) {}
+Input::~Input() {}
+
+// Component implementation.
+dom::Element Input::Render() {
+  bool is_place_ho
+  std::wstring& displayed_text = content.size() ? content : placeholder;
+
+  using namespace dom;
+  if (Focused())
+    return flex(inverted(text(displayed_text)));
+  else
+    return flex(text(displayed_text));
+}
+bool Input::OnEvent(Event event) {
+  std::wstring c;
+
+  // Backspace
+  if (event == Event::Backspace) {
+    if (content.size() != 0)
+      content = content.substr(0, content.size()-1);
+    return true;
+  }
+
+  // Enter
+  if (event == Event::Return) {
+    return true;
+  }
+
+  constexpr char ESC = char(27);
+  if (event.values[0] != ESC) {
+    content += event.values[0];
+    return true;
+  }
+
+  return false;
+}
+
+}  // namespace component
+}  // namespace ftxui
diff --git a/ftxui/src/ftxui/component/menu.cpp b/ftxui/src/ftxui/component/menu.cpp
index 3d5f259e..ebc5e460 100644
--- a/ftxui/src/ftxui/component/menu.cpp
+++ b/ftxui/src/ftxui/component/menu.cpp
@@ -1,5 +1,6 @@
 #include "ftxui/component/menu.hpp"
 #include <algorithm>
+#include <iostream>
 
 namespace ftxui {
 namespace component {
@@ -24,14 +25,14 @@ dom::Element Menu::Render() {
   return vbox(std::move(elements));
 }
 
-bool Menu::Event(int key) {
+bool Menu::OnEvent(Event event) {
   if (!Focused())
     return false;
 
   int new_selected = selected;
-  if (key == 65 || key == 'k')
+  if (event == Event::ArrowUp || event == Event::Character('k'))
     new_selected--;
-  if (key == 66 || key == 'j')
+  if (event == Event::ArrowDown || event == Event::Character('j'))
     new_selected++;
   new_selected = std::max(0, std::min(int(entries.size())-1, new_selected));
 
@@ -41,7 +42,7 @@ bool Menu::Event(int key) {
     return true;
   }
 
-  if (key == 10) {
+  if (event == Event::Return) {
     on_enter();
     return true;
   }
diff --git a/ftxui/src/ftxui/component/toggle.cpp b/ftxui/src/ftxui/component/toggle.cpp
index 023ca0ee..2552affd 100644
--- a/ftxui/src/ftxui/component/toggle.cpp
+++ b/ftxui/src/ftxui/component/toggle.cpp
@@ -24,16 +24,15 @@ dom::Element Toggle::Render() {
   return hbox(std::move(children));
 }
 
-bool Toggle::Event(int key) {
-
+bool Toggle::OnEvent(Event event) {
   if (activated) {
-    if (key == 67 || key == 'l') {
+    if (event == Event::ArrowRight || event == Event::Character('l')) {
       activated = false;
       on_change();
       return true;
     }
   } else {
-    if (key == 68 || key == 'h') {
+    if (event == Event::ArrowLeft || event == Event::Character('h')) {
       activated = true;
       on_change();
       return true;
diff --git a/ftxui/src/ftxui/event.cpp b/ftxui/src/ftxui/event.cpp
new file mode 100644
index 00000000..f4fe1231
--- /dev/null
+++ b/ftxui/src/ftxui/event.cpp
@@ -0,0 +1,37 @@
+#include "ftxui/event.hpp"
+
+namespace ftxui {
+
+constexpr char ESC = char(27);
+
+// --- Character ---
+Event Event::Character(char c) {
+  return Event{c};
+}
+
+// --- Arrow ---
+Event Event::ArrowLeft{ESC, '[', 'D'};
+Event Event::ArrowRight{ESC, '[', 'C'};
+Event Event::ArrowUp{ESC, '[', 'A'};
+Event Event::ArrowDown{ESC, '[', 'B'};
+
+// --- Other ---
+Event Event::Backspace{char(127)};
+Event Event::Delete{ESC, '[', '3', '~'};
+Event Event::Escape{ESC};
+Event Event::Return{char(10)};
+
+Event Event::F1{ESC, '[', 'O', 'P'};
+Event Event::F2{ESC, '[', 'O', 'Q'};
+Event Event::F3{ESC, '[', 'O', 'R'};
+Event Event::F4{ESC, '[', 'O', 'S'};
+Event Event::F5{ESC, '[', '1', '5', '~'};
+Event Event::F6{ESC, '[', '1', '7', '~'};
+Event Event::F7{ESC, '[', '1', '8', '~'};
+Event Event::F8{ESC, '[', '1', '9', '~'};
+Event Event::F9{ESC, '[', '2', '0', '~'};
+Event Event::F10{ESC, '[', '2', '1', '~'};
+Event Event::F11{ESC, '[', '2', '1', '~'};  // Same as F10 ?
+Event Event::F12{ESC, '[', '2', '4', '~'};
+
+} // namespace ftxui
diff --git a/ftxui/src/ftxui/screen_interactive.cpp b/ftxui/src/ftxui/screen_interactive.cpp
index 7d359431..3b2d49dd 100644
--- a/ftxui/src/ftxui/screen_interactive.cpp
+++ b/ftxui/src/ftxui/screen_interactive.cpp
@@ -8,6 +8,20 @@
 
 namespace ftxui {
 
+namespace {
+  constexpr char ESC = char(27);
+
+  Event GetEvent() {
+    char v1 = char(getchar());
+    if (v1 != ESC)
+      return Event{v1};
+
+    char v2 = char(getchar());
+    char v3 = char(getchar());
+    return Event{v1,v2,v3};
+  };
+};
+
 class ScreenInteractive::Delegate : public component::Delegate {
  public:
   Delegate() : root_(this) {}
@@ -29,7 +43,7 @@ class ScreenInteractive::Delegate : public component::Delegate {
     return child;
   }
 
-  void Event(int key) { component_->Event(key); }
+  void OnEvent(Event event) { component_->OnEvent(event); }
 
 
   std::vector<component::Delegate*> children() override {
@@ -77,8 +91,7 @@ void ScreenInteractive::Loop() {
 
   Draw();
   while (!quit_) {
-    int key = getchar();
-    delegate_->Event(key);
+    delegate_->OnEvent(GetEvent());
 
     Clear();
     Draw();
diff --git a/tutorial.md b/tutorial.md
index ca41158a..ad19e5fc 100644
--- a/tutorial.md
+++ b/tutorial.md
@@ -23,6 +23,8 @@ Element bold(Element);
 Element dim(Element);
 Element inverted(Element);
 Element underlined(Element);
+Element color(Color,Element);
+Element bgcolor(Element);
 
 // --- Decorator ---
 Element hcenter(Element);
@@ -139,3 +141,5 @@ Element bold(Element);
 Element dim(Element);
 Element inverted(Element);
 Element underlined(Element);
+Element color(Element);
+Element bgcolor(Element);
-- 
GitLab