changeset 82:ee850a6ab89e

Client: namespace and hierarchy
author David Demelier <markand@malikania.fr>
date Sun, 22 Jan 2017 11:07:36 +0100
parents 301599387b40
children d458af0b7748
files client/main.cpp examples/animation/main.cpp examples/font/main.cpp examples/image/main.cpp examples/js-animation/main.cpp examples/js-font/main.cpp examples/js-image/main.cpp examples/js-sprite/main.cpp examples/sprite/main.cpp libclient-js/malikania/js_animation.cpp libclient-js/malikania/js_animation.hpp libclient-js/malikania/js_animator.cpp libclient-js/malikania/js_animator.hpp libclient-js/malikania/js_client_resources_loader.cpp libclient-js/malikania/js_client_resources_loader.hpp libclient-js/malikania/js_color.cpp libclient-js/malikania/js_color.hpp libclient-js/malikania/js_font.cpp libclient-js/malikania/js_font.hpp libclient-js/malikania/js_image.cpp libclient-js/malikania/js_image.hpp libclient-js/malikania/js_line.cpp libclient-js/malikania/js_line.hpp libclient-js/malikania/js_point.cpp libclient-js/malikania/js_point.hpp libclient-js/malikania/js_rectangle.cpp libclient-js/malikania/js_rectangle.hpp libclient-js/malikania/js_size.cpp libclient-js/malikania/js_size.hpp libclient-js/malikania/js_sprite.cpp libclient-js/malikania/js_sprite.hpp libclient-js/malikania/js_window.cpp libclient-js/malikania/js_window.hpp libclient/CMakeLists.txt libclient/malikania/animation.hpp libclient/malikania/animator.cpp libclient/malikania/animator.hpp libclient/malikania/backend/sdl/font_backend.cpp libclient/malikania/backend/sdl/font_backend.hpp libclient/malikania/backend/sdl/image_backend.cpp libclient/malikania/backend/sdl/image_backend.hpp libclient/malikania/backend/sdl/window_backend.cpp libclient/malikania/backend/sdl/window_backend.hpp libclient/malikania/button.cpp libclient/malikania/button.hpp libclient/malikania/client/animation.hpp libclient/malikania/client/animator.cpp libclient/malikania/client/animator.hpp libclient/malikania/client/backend/sdl/font_backend.cpp libclient/malikania/client/backend/sdl/font_backend.hpp libclient/malikania/client/backend/sdl/image_backend.cpp libclient/malikania/client/backend/sdl/image_backend.hpp libclient/malikania/client/backend/sdl/window_backend.cpp libclient/malikania/client/backend/sdl/window_backend.hpp libclient/malikania/client/button.cpp libclient/malikania/client/button.hpp libclient/malikania/client/color.cpp libclient/malikania/client/color.hpp libclient/malikania/client/font.cpp libclient/malikania/client/font.hpp libclient/malikania/client/frame.cpp libclient/malikania/client/frame.hpp libclient/malikania/client/grid_layout.cpp libclient/malikania/client/grid_layout.hpp libclient/malikania/client/image.cpp libclient/malikania/client/image.hpp libclient/malikania/client/key.hpp libclient/malikania/client/label.cpp libclient/malikania/client/label.hpp libclient/malikania/client/layout.hpp libclient/malikania/client/line.hpp libclient/malikania/client/loader.cpp libclient/malikania/client/loader.hpp libclient/malikania/client/mouse.hpp libclient/malikania/client/point.hpp libclient/malikania/client/rectangle.hpp libclient/malikania/client/size.hpp libclient/malikania/client/sprite.cpp libclient/malikania/client/sprite.hpp libclient/malikania/client/theme.cpp libclient/malikania/client/theme.hpp libclient/malikania/client/unique_layout.cpp libclient/malikania/client/unique_layout.hpp libclient/malikania/client/widget.cpp libclient/malikania/client/widget.hpp libclient/malikania/client/window.cpp libclient/malikania/client/window.hpp libclient/malikania/client_resources_loader.cpp libclient/malikania/client_resources_loader.hpp libclient/malikania/color.cpp libclient/malikania/color.hpp libclient/malikania/font.cpp libclient/malikania/font.hpp libclient/malikania/frame.cpp libclient/malikania/frame.hpp libclient/malikania/grid_layout.cpp libclient/malikania/grid_layout.hpp libclient/malikania/image.cpp libclient/malikania/image.hpp libclient/malikania/key.hpp libclient/malikania/label.cpp libclient/malikania/label.hpp libclient/malikania/layout.hpp libclient/malikania/line.hpp libclient/malikania/mouse.hpp libclient/malikania/point.hpp libclient/malikania/rectangle.hpp libclient/malikania/size.hpp libclient/malikania/sprite.cpp libclient/malikania/sprite.hpp libclient/malikania/theme.cpp libclient/malikania/theme.hpp libclient/malikania/unique_layout.cpp libclient/malikania/unique_layout.hpp libclient/malikania/widget.cpp libclient/malikania/widget.hpp libclient/malikania/window.cpp libclient/malikania/window.hpp tests/libclient/color/main.cpp tests/libclient/line/main.cpp tests/libclient/point/main.cpp tests/libclient/rectangle/main.cpp tests/libclient/size/main.cpp
diffstat 123 files changed, 5545 insertions(+), 5369 deletions(-) [+]
line wrap: on
line diff
--- a/client/main.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/client/main.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -21,21 +21,21 @@
 #include <chrono>
 #include <thread>
 
-#include "malikania/button.hpp"
-#include "malikania/color.hpp"
-#include "malikania/frame.hpp"
-#include "malikania/label.hpp"
-#include "malikania/point.hpp"
-#include "malikania/unique_layout.hpp"
-#include "malikania/window.hpp"
+#include <malikania/client/button.hpp>
+#include <malikania/client/color.hpp>
+#include <malikania/client/frame.hpp>
+#include <malikania/client/label.hpp>
+#include <malikania/client/point.hpp>
+#include <malikania/client/unique_layout.hpp>
+#include <malikania/client/window.hpp>
 
 int main()
 {
-    mlk::window win;
+    mlk::client::window win;
 
-    auto f = std::make_shared<mlk::frame>();
-    auto w = std::make_shared<mlk::label>("Malikania");
-    auto l = std::make_shared<mlk::unique_layout>(w);
+    auto f = std::make_shared<mlk::client::frame>();
+    auto w = std::make_shared<mlk::client::label>("Malikania");
+    auto l = std::make_shared<mlk::client::unique_layout>(w);
 
     f->move({50, 50});
     f->set_layout(l);
--- a/examples/animation/main.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/examples/animation/main.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -20,29 +20,29 @@
 #include <thread>
 #include <exception>
 
-#include <malikania/animation.hpp>
-#include <malikania/animator.hpp>
-#include <malikania/client_resources_loader.hpp>
+#include <malikania/client/animation.hpp>
+#include <malikania/client/animator.hpp>
+#include <malikania/client/loader.hpp>
+#include <malikania/client/window.hpp>
 #include <malikania/locator.hpp>
-#include <malikania/window.hpp>
 
 int main()
 {
     boost::timer::cpu_timer timer;
 
     try {
-        mlk::window win(400, 400);
         mlk::directory_locator locator(SOURCE_DIRECTORY);
-        mlk::client_resources_loader loader(locator);
-        mlk::animation animation = loader.load_animation("animations/margins.json");
-        mlk::animator animator(animation);
+        mlk::client::window win(400, 400);
+        mlk::client::loader loader(locator);
+        mlk::client::animation animation = loader.load_animation("animations/margins.json");
+        mlk::client::animator animator(animation);
 
         auto x = (400 / 2) - (animation.sprite().cell().width() / 2);
         auto y = (400 / 2) - (animation.sprite().cell().height() / 2);
 
         while (timer.elapsed().wall / 1000000LL < 8000) {
             win.clear();
-            animator.draw(win, mlk::point(x, y));
+            animator.draw(win, mlk::client::point(x, y));
             animator.update();
             win.present();
         }
--- a/examples/font/main.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/examples/font/main.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -19,86 +19,86 @@
 #include <chrono>
 #include <thread>
 
-#include <malikania/client_resources_loader.hpp>
-#include <malikania/color.hpp>
-#include <malikania/font.hpp>
+#include <malikania/client/loader.hpp>
+#include <malikania/client/color.hpp>
+#include <malikania/client/font.hpp>
+#include <malikania/client/point.hpp>
+#include <malikania/client/window.hpp>
 #include <malikania/locator.hpp>
-#include <malikania/point.hpp>
-#include <malikania/window.hpp>
 
 using namespace std::chrono_literals;
 
-void topleft(mlk::window& window, mlk::font& font)
+void topleft(mlk::client::window& window, mlk::client::font& font)
 {
-    window.set_drawing_color(mlk::color("black"));
+    window.set_drawing_color(mlk::client::color("black"));
     window.clear();
-    window.set_drawing_color(mlk::color("white"));
-    window.draw_text("top left", font, mlk::point(10, 10));
+    window.set_drawing_color(mlk::client::color("white"));
+    window.draw_text("top left", font, mlk::client::point(10, 10));
     window.present();
 
     std::this_thread::sleep_for(1s);
 }
 
-void topright(mlk::window& window, mlk::font& font)
+void topright(mlk::client::window& window, mlk::client::font& font)
 {
     auto dim = font.clip("top right");
 
-    window.set_drawing_color(mlk::color("black"));
+    window.set_drawing_color(mlk::client::color("black"));
     window.clear();
-    window.set_drawing_color(mlk::color("white"));
-    window.draw_text("top right", font, mlk::point(400 - dim.width() - 10, 10));
+    window.set_drawing_color(mlk::client::color("white"));
+    window.draw_text("top right", font, mlk::client::point(400 - dim.width() - 10, 10));
     window.present();
 
     std::this_thread::sleep_for(1s);
 }
 
-void bottomleft(mlk::window& window, mlk::font& font)
+void bottomleft(mlk::client::window& window, mlk::client::font& font)
 {
     auto dim = font.clip("bottom left");
 
-    window.set_drawing_color(mlk::color("black"));
+    window.set_drawing_color(mlk::client::color("black"));
     window.clear();
-    window.set_drawing_color(mlk::color("white"));
-    window.draw_text("bottom left", font, mlk::point(10, 400 - dim.height() - 10));
+    window.set_drawing_color(mlk::client::color("white"));
+    window.draw_text("bottom left", font, mlk::client::point(10, 400 - dim.height() - 10));
     window.present();
 
     std::this_thread::sleep_for(1s);
 }
 
-void bottomright(mlk::window& window, mlk::font& font)
+void bottomright(mlk::client::window& window, mlk::client::font& font)
 {
     auto dim = font.clip("bottom right");
 
-    window.set_drawing_color(mlk::color("black"));
+    window.set_drawing_color(mlk::client::color("black"));
     window.clear();
-    window.set_drawing_color(mlk::color("white"));
-    window.draw_text("bottom right", font, mlk::point(400 - dim.width() - 10, 400 - dim.height() - 10));
+    window.set_drawing_color(mlk::client::color("white"));
+    window.draw_text("bottom right", font, mlk::client::point(400 - dim.width() - 10, 400 - dim.height() - 10));
     window.present();
 
     std::this_thread::sleep_for(1s);
 }
 
-void center(mlk::window& window, mlk::font& font)
+void center(mlk::client::window& window, mlk::client::font& font)
 {
     auto dim = font.clip("center");
 
-    window.set_drawing_color(mlk::color("black"));
+    window.set_drawing_color(mlk::client::color("black"));
     window.clear();
-    window.set_drawing_color(mlk::color("white"));
-    window.draw_text("center", font, mlk::point(200 - (dim.width() / 2), 200 - (dim.height() -2)));
+    window.set_drawing_color(mlk::client::color("white"));
+    window.draw_text("center", font, mlk::client::point(200 - (dim.width() / 2), 200 - (dim.height() -2)));
     window.present();
 
     std::this_thread::sleep_for(1s);
 }
 
-void center2(mlk::window& window, mlk::font& font)
+void center2(mlk::client::window& window, mlk::client::font& font)
 {
     auto dim = font.clip("The world is Malikania.");
 
-    window.set_drawing_color(mlk::color("black"));
+    window.set_drawing_color(mlk::client::color("black"));
     window.clear();
-    window.set_drawing_color(mlk::color("white"));
-    window.draw_text("The world is Malikania.", font, mlk::point(200 - (dim.width() / 2), 200 - (dim.height() -2)));
+    window.set_drawing_color(mlk::client::color("white"));
+    window.draw_text("The world is Malikania.", font, mlk::client::point(200 - (dim.width() / 2), 200 - (dim.height() -2)));
     window.present();
 
     std::this_thread::sleep_for(3s);
@@ -107,10 +107,10 @@
 int main()
 {
     try {
-        mlk::window window(400, 400);
+        mlk::client::window window(400, 400);
         mlk::directory_locator locator(SOURCE_DIRECTORY);
-        mlk::client_resources_loader loader(locator);
-        mlk::font font = loader.load_font("DejaVuSans.ttf", 10);
+        mlk::client::loader loader(locator);
+        mlk::client::font font = loader.load_font("DejaVuSans.ttf", 10);
 
         topleft(window, font);
         topright(window, font);
--- a/examples/image/main.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/examples/image/main.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -19,14 +19,14 @@
 #include <chrono>
 #include <thread>
 
-#include <malikania/client_resources_loader.hpp>
-#include <malikania/image.hpp>
+#include <malikania/client/loader.hpp>
+#include <malikania/client/image.hpp>
+#include <malikania/client/window.hpp>
 #include <malikania/locator.hpp>
-#include <malikania/window.hpp>
 
 using namespace std::chrono_literals;
 
-void draw(mlk::window& window, mlk::client_resources_loader& loader)
+void draw(mlk::client::window& window, mlk::client::loader& loader)
 {
     try {
         auto image = loader.load_image("images/smiley.png");
@@ -34,7 +34,7 @@
         auto y = (400 / 2) - (image.size().height() / 2);
 
         window.clear();
-        image.draw(window, mlk::point(x, y));
+        image.draw(window, mlk::client::point(x, y));
         window.present();
 
         std::this_thread::sleep_for(3s);
@@ -47,9 +47,9 @@
 int main()
 {
     try {
-        mlk::window window(400, 400);
+        mlk::client::window window(400, 400);
         mlk::directory_locator locator(SOURCE_DIRECTORY);
-        mlk::client_resources_loader loader(locator);
+        mlk::client::loader loader(locator);
 
         draw(window, loader);
     } catch (const std::exception& ex) {
--- a/examples/js-animation/main.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/examples/js-animation/main.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -31,7 +31,7 @@
 {
     try {
         mlk::directory_locator locator(SOURCE_DIRECTORY);
-        mlk::client_resources_loader loader(locator);
+        mlk::client::loader loader(locator);
         dukx_context m_ctx;
 
         duk_push_object(m_ctx);
--- a/examples/js-font/main.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/examples/js-font/main.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -51,7 +51,7 @@
 {
     try {
         mlk::directory_locator locator(SOURCE_DIRECTORY);
-        mlk::client_resources_loader loader(locator);
+        mlk::client::loader loader(locator);
         dukx_context ctx;
 
         duk_push_object(ctx);
--- a/examples/js-image/main.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/examples/js-image/main.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -66,7 +66,7 @@
 {
     try {
         mlk::directory_locator locator(SOURCE_DIRECTORY);
-        mlk::client_resources_loader loader(locator);
+        mlk::client::loader loader(locator);
         dukx_context ctx;
 
         duk_push_object(ctx);
--- a/examples/js-sprite/main.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/examples/js-sprite/main.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -59,7 +59,7 @@
 {
     try {
         mlk::directory_locator locator(SOURCE_DIRECTORY);
-        mlk::client_resources_loader loader(locator);
+        mlk::client::loader loader(locator);
         dukx_context ctx;
 
         duk_push_object(ctx);
--- a/examples/sprite/main.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/examples/sprite/main.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -20,14 +20,14 @@
 #include <thread>
 #include <exception>
 
-#include <malikania/client_resources_loader.hpp>
+#include <malikania/client/loader.hpp>
+#include <malikania/client/sprite.hpp>
+#include <malikania/client/window.hpp>
 #include <malikania/locator.hpp>
-#include <malikania/sprite.hpp>
-#include <malikania/window.hpp>
 
 using namespace std::chrono_literals;
 
-void draw(mlk::window& window, mlk::client_resources_loader& loader)
+void draw(mlk::client::window& window, mlk::client::loader& loader)
 {
     auto sprite = loader.load_sprite("sprites/margins.json");
     auto total = sprite.rows() * sprite.columns();
@@ -36,7 +36,7 @@
 
     for (unsigned c = 0; c < total; ++c) {
         window.clear();
-        sprite.draw(window, c, mlk::point(x, y));
+        sprite.draw(window, c, mlk::client::point(x, y));
         window.present();
 
         std::this_thread::sleep_for(1s);
@@ -47,8 +47,8 @@
 {
     try {
         mlk::directory_locator locator(SOURCE_DIRECTORY);
-        mlk::client_resources_loader loader(locator);
-        mlk::window window(400, 400);
+        mlk::client::loader loader(locator);
+        mlk::client::window window(400, 400);
 
         draw(window, loader);
     } catch (const std::exception& ex) {
--- a/libclient-js/malikania/js_animation.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/libclient-js/malikania/js_animation.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -38,7 +38,7 @@
         auto anim = loader.load_animation(duk_require_string(ctx, 0));
 
         duk_push_this(ctx);
-        duk_push_pointer(ctx, new animation(std::move(anim)));
+        duk_push_pointer(ctx, new client::animation(std::move(anim)));
         duk_put_prop_string(ctx, -2, signature.c_str());
         duk_pop(ctx);
     } catch (const std::exception &ex) {
@@ -51,7 +51,7 @@
 duk_ret_t destructor(duk_context* ctx)
 {
     duk_get_prop_string(ctx, 0, signature.c_str());
-    delete static_cast<animation *>(duk_to_pointer(ctx, -1));
+    delete static_cast<client::animation *>(duk_to_pointer(ctx, -1));
     duk_pop(ctx);
     duk_del_prop_string(ctx, 0, signature.c_str());
 
@@ -60,19 +60,19 @@
 
 } // !namespace
 
-void dukx_new_animation(duk_context* ctx, animation& anim)
+void dukx_new_animation(duk_context* ctx, client::animation& anim)
 {
     assert(ctx);
 
     dukx_stack_assert sa(ctx);
 
     duk_push_this(ctx);
-    duk_push_pointer(ctx, new animation(std::move(anim)));
+    duk_push_pointer(ctx, new client::animation(std::move(anim)));
     duk_put_prop_string(ctx, -2, signature.c_str());
     duk_pop(ctx);
 }
 
-animation& dukx_require_animation(duk_context* ctx, duk_idx_t index)
+client::animation& dukx_require_animation(duk_context* ctx, duk_idx_t index)
 {
     assert(ctx);
 
@@ -86,7 +86,7 @@
         duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an animation object");
     }
 
-    return *static_cast<animation*>(ptr);
+    return *static_cast<client::animation*>(ptr);
 }
 
 void dukx_load_animation(duk_context* ctx)
--- a/libclient-js/malikania/js_animation.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/libclient-js/malikania/js_animation.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -19,10 +19,9 @@
 #ifndef MALIKANIA_JS_ANIMATION_HPP
 #define MALIKANIA_JS_ANIMATION_HPP
 
+#include <malikania/client/animation.hpp>
 #include <malikania/duktape.hpp>
 
-#include "animation.hpp"
-
 namespace mlk {
 
 #if 0
@@ -45,7 +44,7 @@
  * \param index the value index
  * \return the Animation object
  */
-animation& dukx_require_animation(duk_context* ctx, duk_idx_t index);
+client::animation& dukx_require_animation(duk_context* ctx, duk_idx_t index);
 
 /**
  * Load the animation module into the context.
--- a/libclient-js/malikania/js_animator.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/libclient-js/malikania/js_animator.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -30,7 +30,7 @@
 
 const std::string signature("\xff""\xff""malikania-animator-ptr");
 
-animator& self(duk_context* ctx)
+client::animator& self(duk_context* ctx)
 {
     dukx_stack_assert sa(ctx);
 
@@ -43,7 +43,7 @@
         duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an animator object");
     }
 
-    return *static_cast<animator*>(ptr);
+    return *static_cast<client::animator*>(ptr);
 }
 
 duk_ret_t constructor(duk_context *ctx)
@@ -53,7 +53,7 @@
     }
 
     duk_push_this(ctx);
-    duk_push_pointer(ctx, new animator(dukx_require_animation(ctx, 0)));
+    duk_push_pointer(ctx, new client::animator(dukx_require_animation(ctx, 0)));
     duk_put_prop_string(ctx, -2, signature.c_str());
 
     // Be sure animation get not collected before.
@@ -67,7 +67,7 @@
 duk_ret_t destructor(duk_context *ctx)
 {
     duk_get_prop_string(ctx, 0, signature.c_str());
-    delete static_cast<animator *>(duk_to_pointer(ctx, -1));
+    delete static_cast<client::animator *>(duk_to_pointer(ctx, -1));
     duk_pop(ctx);
     duk_del_prop_string(ctx, 0, signature.c_str());
 
@@ -116,7 +116,7 @@
 
 #endif
 
-animator& dukx_require_animator(duk_context* ctx, duk_idx_t index)
+client::animator& dukx_require_animator(duk_context* ctx, duk_idx_t index)
 {
     assert(ctx);
 
@@ -130,7 +130,7 @@
         duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an animator object");
     }
 
-    return *static_cast<animator*>(ptr);
+    return *static_cast<client::animator*>(ptr);
 }
 
 void dukx_load_animator(duk_context* ctx)
--- a/libclient-js/malikania/js_animator.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/libclient-js/malikania/js_animator.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -19,8 +19,8 @@
 #ifndef MALIKANIA_JS_ANIMATOR_HPP
 #define MALIKANIA_JS_ANIMATOR_HPP
 
-#include "animator.hpp"
-#include "duktape.hpp"
+#include <malikania/client/animator.hpp>
+#include <malikania/duktape.hpp>
 
 namespace mlk {
 
@@ -46,7 +46,7 @@
  * \param index the value index
  * \return the animator
  */
-animator& dukx_require_animator(duk_context* ctx, duk_idx_t index);
+client::animator& dukx_require_animator(duk_context* ctx, duk_idx_t index);
 
 void dukx_load_animator(duk_context* ctx);
 
--- a/libclient-js/malikania/js_client_resources_loader.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/libclient-js/malikania/js_client_resources_loader.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -29,7 +29,7 @@
 
 } // !namespace
 
-void dukx_put_client_loader(duk_context* ctx, client_resources_loader& loader)
+void dukx_put_client_loader(duk_context* ctx, client::loader& loader)
 {
     assert(ctx);
 
@@ -42,17 +42,17 @@
     duk_put_global_string(ctx, variable.c_str());
 }
 
-client_resources_loader& dukx_get_client_loader(duk_context* ctx)
+client::loader& dukx_get_client_loader(duk_context* ctx)
 {
     assert(ctx);
 
     dukx_stack_assert sa(ctx);
 
     duk_get_global_string(ctx, variable.c_str());
-    auto ptr = static_cast<client_resources_loader*>(duk_to_pointer(ctx, -1));
+    auto ptr = static_cast<client::loader*>(duk_to_pointer(ctx, -1));
     duk_pop(ctx);
 
-    return *static_cast<client_resources_loader*>(ptr);
+    return *static_cast<client::loader*>(ptr);
 }
 
 } // !mlk
--- a/libclient-js/malikania/js_client_resources_loader.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/libclient-js/malikania/js_client_resources_loader.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -19,14 +19,15 @@
 #ifndef MALIKANIA_JS_CLIENT_RESOURCES_LOADER_H
 #define MALIKANIA_JS_CLIENT_RESOURCES_LOADER_H
 
-#include "client_resources_loader.hpp"
+#include <malikania/client/loader.hpp>
+
 #include "duktape.hpp"
 
 namespace mlk {
 
-void dukx_put_client_loader(duk_context* ctx, client_resources_loader&);
+void dukx_put_client_loader(duk_context* ctx, mlk::client::loader&);
 
-client_resources_loader& dukx_get_client_loader(duk_context* ctx);
+mlk::client::loader& dukx_get_client_loader(duk_context* ctx);
 
 } // !mlk
 
--- a/libclient-js/malikania/js_color.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/libclient-js/malikania/js_color.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -38,14 +38,14 @@
     return static_cast<std::uint8_t>(value);
 }
 
-color parse_string(duk_context* ctx, duk_idx_t index, bool required)
+client::color parse_string(duk_context* ctx, duk_idx_t index, bool required)
 {
     assert(duk_is_string(ctx, index));
 
-    color ret;
+    client::color ret;
 
     try {
-        ret = color(duk_get_string(ctx, index));
+        ret = client::color(duk_get_string(ctx, index));
     } catch (const std::exception &ex) {
         if (required) {
             duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
@@ -55,7 +55,7 @@
     return ret;
 }
 
-color parse_object(duk_context* ctx, duk_idx_t index, bool required)
+client::color parse_object(duk_context* ctx, duk_idx_t index, bool required)
 {
     assert(duk_is_object(ctx, index));
 
@@ -76,7 +76,7 @@
     auto alpha = duk_is_number(ctx, -1) ? duk_to_int(ctx, -1) : 255;
     duk_pop(ctx);
 
-    return color(
+    return client::color(
         require("red"),
         require("green"),
         require("blue"),
@@ -84,7 +84,7 @@
     );
 }
 
-color parse(duk_context* ctx, duk_idx_t index, bool required, color ret = {})
+client::color parse(duk_context* ctx, duk_idx_t index, bool required, client::color ret = {})
 {
     switch (duk_get_type(ctx, index)) {
     case DUK_TYPE_STRING:
@@ -106,7 +106,7 @@
 
 duk_ret_t constructor(duk_context* ctx)
 {
-    color obj;
+    client::color obj;
 
     /*
      * The constructor allows an additional signature that takes 4 number
@@ -116,7 +116,7 @@
         // Alpha is optional.
         auto alpha = duk_is_number(ctx, 3) ? duk_to_int(ctx, 3) : 255;
 
-        obj = color(
+        obj = client::color(
             clamp_component(ctx, duk_require_int(ctx, 0), true),
             clamp_component(ctx, duk_require_int(ctx, 1), true),
             clamp_component(ctx, duk_require_int(ctx, 2), true),
@@ -144,22 +144,22 @@
 
 } //! namespace
 
-color dukx_get_color(duk_context* ctx, duk_idx_t index)
+client::color dukx_get_color(duk_context* ctx, duk_idx_t index)
 {
     return parse(ctx, index, false);
 }
 
-color dukx_require_color(duk_context* ctx, duk_idx_t index)
+client::color dukx_require_color(duk_context* ctx, duk_idx_t index)
 {
     return parse(ctx, index, true);
 }
 
-color dukx_optional_color(duk_context* ctx, duk_idx_t index, color def)
+client::color dukx_optional_color(duk_context* ctx, duk_idx_t index, client::color def)
 {
     return parse(ctx, index, false, std::move(def));
 }
 
-void dukx_push_color(duk_context* ctx, const color& color)
+void dukx_push_color(duk_context* ctx, const client::color& color)
 {
     dukx_stack_assert sa(ctx, 1);
 
@@ -167,7 +167,7 @@
     dukx_put_color(ctx, color);
 }
 
-void dukx_put_color(duk_context* ctx, const color &color)
+void dukx_put_color(duk_context* ctx, const client::color &color)
 {
     assert(duk_is_object(ctx, -1));
 
--- a/libclient-js/malikania/js_color.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/libclient-js/malikania/js_color.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -37,8 +37,8 @@
  * It can also takes strings like "#rrggbbaa" and SVG names.
  */
 
-#include "color.hpp"
-#include "duktape.hpp"
+#include <malikania/client/color.hpp>
+#include <malikania/duktape.hpp>
 
 namespace mlk {
 
@@ -50,7 +50,7 @@
  * \param ctx the context
  * \param index the index
  */
-color dukx_get_color(duk_context* ctx, duk_idx_t index);
+client::color dukx_get_color(duk_context* ctx, duk_idx_t index);
 
 /**
  * Require a color.
@@ -60,7 +60,7 @@
  * \param ctx the context
  * \param index the index
  */
-color dukx_require_color(duk_context* ctx, duk_idx_t index);
+client::color dukx_require_color(duk_context* ctx, duk_idx_t index);
 
 /**
  * Like get, but return the default value only if the value at the given
@@ -70,7 +70,7 @@
  * \param index the index
  * \param def the default value
  */
-color dukx_optional_color(duk_context* ctx, duk_idx_t index, color def);
+client::color dukx_optional_color(duk_context* ctx, duk_idx_t index, client::color def);
 
 /**
  * Push the color as object.
@@ -78,7 +78,7 @@
  * \param ctx the context
  * \param color the color
  */
-void dukx_push_color(duk_context* ctx, const color& color);
+void dukx_push_color(duk_context* ctx, const client::color& color);
 
 /**
  * Put the color properties into the object at the top of the stack.
@@ -87,7 +87,7 @@
  * \param ctx the context
  * \param color the color
  */
-void dukx_put_color(duk_context* ctx, const color& color);
+void dukx_put_color(duk_context* ctx, const client::color& color);
 
 void dukx_load_color(duk_context* ctx);
 
--- a/libclient-js/malikania/js_font.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/libclient-js/malikania/js_font.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -28,7 +28,7 @@
 
 const std::string signature("\xff""\xff""malikania-font-ptr");
 
-font& self(duk_context* ctx)
+client::font& self(duk_context* ctx)
 {
     dukx_stack_assert sa(ctx);
 
@@ -41,7 +41,7 @@
         duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a font object");
     }
 
-    return *static_cast<font*>(ptr);
+    return *static_cast<client::font*>(ptr);
 }
 
 duk_ret_t constructor(duk_context* ctx)
@@ -62,7 +62,7 @@
         }
 
         duk_push_this(ctx);
-        duk_push_pointer(ctx, new font(loader.load_font(id, static_cast<unsigned>(size))));
+        duk_push_pointer(ctx, new client::font(loader.load_font(id, static_cast<unsigned>(size))));
         duk_put_prop_string(ctx, -2, signature.c_str());
         duk_pop(ctx);
     } catch (const std::exception &ex) {
@@ -107,7 +107,7 @@
 
 #endif
 
-font& dukx_require_font(duk_context* ctx, duk_idx_t index)
+client::font& dukx_require_font(duk_context* ctx, duk_idx_t index)
 {
     assert(ctx);
 
@@ -121,7 +121,7 @@
         duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a font object");
     }
 
-    return *static_cast<font*>(ptr);
+    return *static_cast<client::font*>(ptr);
 }
 
 void dukx_load_font(duk_context* ctx)
--- a/libclient-js/malikania/js_font.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/libclient-js/malikania/js_font.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -19,8 +19,8 @@
 #ifndef MALIKANIA_JS_FONT_HPP
 #define MALIKANIA_JS_FONT_HPP
 
-#include "duktape.hpp"
-#include "font.hpp"
+#include <malikania/client/font.hpp>
+#include <malikania/duktape.hpp>
 
 namespace mlk {
 
@@ -28,7 +28,7 @@
 void dukx_new_font(duk_context *ctx, Font *font);
 #endif
 
-font& dukx_require_font(duk_context* ctx, duk_idx_t index);
+client::font& dukx_require_font(duk_context* ctx, duk_idx_t index);
 
 void dukx_load_font(duk_context* ctx);
 
--- a/libclient-js/malikania/js_image.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/libclient-js/malikania/js_image.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -29,7 +29,7 @@
 
 const std::string signature("\xff""\xff""malikania-image-ptr");
 
-image& self(duk_context* ctx)
+client::image& self(duk_context* ctx)
 {
     dukx_stack_assert sa(ctx);
 
@@ -42,7 +42,7 @@
         duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an Animator object");
     }
 
-    return *static_cast<image *>(ptr);
+    return *static_cast<client::image *>(ptr);
 }
 
 duk_ret_t size(duk_context* ctx)
@@ -86,7 +86,7 @@
         auto& loader = dukx_get_client_loader(ctx);
 
         duk_push_this(ctx);
-        duk_push_pointer(ctx, new image(loader.load_image(duk_require_string(ctx, 0))));
+        duk_push_pointer(ctx, new client::image(loader.load_image(duk_require_string(ctx, 0))));
         duk_put_prop_string(ctx, -2, signature.c_str());
         duk_push_string(ctx, "size");
         duk_push_c_function(ctx, size, 0);
@@ -106,7 +106,7 @@
 
 } // !namespace
 
-void dukx_new_image(duk_context* ctx, image *image)
+void dukx_new_image(duk_context* ctx, client::image *image)
 {
     assert(ctx);
     assert(image);
--- a/libclient-js/malikania/js_image.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/libclient-js/malikania/js_image.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -19,8 +19,8 @@
 #ifndef MALIKANIA_JS_IMAGE_HPP
 #define MALIKANIA_JS_IMAGE_HPP
 
-#include "duktape.hpp"
-#include "image.hpp"
+#include <malikania/client/image.hpp>
+#include <malikania/duktape.hpp>
 
 namespace mlk {
 
--- a/libclient-js/malikania/js_line.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/libclient-js/malikania/js_line.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -26,10 +26,10 @@
 
 duk_ret_t constructor(duk_context* ctx)
 {
-    line obj;
+    client::line obj;
 
     if (duk_get_top(ctx) == 4) {
-        obj = line(
+        obj = client::line(
             duk_get_int(ctx, 0),
             duk_get_int(ctx, 1),
             duk_get_int(ctx, 2),
@@ -56,7 +56,7 @@
 
 } // !namespace
 
-line dukx_get_line(duk_context* ctx, duk_idx_t index)
+client::line dukx_get_line(duk_context* ctx, duk_idx_t index)
 {
     auto get = [&] (auto name) {
         dukx_stack_assert sa(ctx);
@@ -68,10 +68,10 @@
         return v;
     };
 
-    return line(get("x1"), get("y1"), get("x2"), get("y2"));
+    return client::line(get("x1"), get("y1"), get("x2"), get("y2"));
 }
 
-line dukx_require_line(duk_context* ctx, duk_idx_t index)
+client::line dukx_require_line(duk_context* ctx, duk_idx_t index)
 {
     auto get = [&] (auto prop) {
         if (!duk_has_prop_string(ctx, index, prop)) {
@@ -92,15 +92,15 @@
         return value;
     };
 
-    return line(get("x1"), get("y1"), get("x2"), get("y2"));
+    return client::line(get("x1"), get("y1"), get("x2"), get("y2"));
 }
 
-line dukx_optional_line(duk_context* ctx, duk_idx_t index, line def)
+client::line dukx_optional_line(duk_context* ctx, duk_idx_t index, client::line def)
 {
     return duk_is_object(ctx, index) ? dukx_get_line(ctx, index) : def;
 }
 
-void dukx_push_line(duk_context* ctx, const line& line)
+void dukx_push_line(duk_context* ctx, const client::line& line)
 {
     dukx_stack_assert sa(ctx, 1);
 
@@ -108,7 +108,7 @@
     dukx_put_line(ctx, line);
 }
 
-void dukx_put_line(duk_context* ctx, const line& line)
+void dukx_put_line(duk_context* ctx, const client::line& line)
 {
     assert(duk_is_object(ctx, -1));
 
--- a/libclient-js/malikania/js_line.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/libclient-js/malikania/js_line.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -35,8 +35,8 @@
  * ````
  */
 
-#include "duktape.hpp"
-#include "line.hpp"
+#include <malikania/duktape.hpp>
+#include <malikania/client/line.hpp>
 
 namespace mlk {
 
@@ -47,7 +47,7 @@
  * \param index the index
  * \return the line
  */
-line dukx_get_line(duk_context* ctx, duk_idx_t index);
+client::line dukx_get_line(duk_context* ctx, duk_idx_t index);
 
 /**
  * Require a line.
@@ -58,7 +58,7 @@
  * \param index the index
  * \return the line
  */
-line dukx_require_line(duk_context* ctx, duk_idx_t index);
+client::line dukx_require_line(duk_context* ctx, duk_idx_t index);
 
 /**
  * Like get but return def if the value at the given index is not an object.
@@ -68,7 +68,7 @@
  * \param def the default value
  * \return the line
  */
-line dukx_optional_line(duk_context* ctx, duk_idx_t index, line def);
+client::line dukx_optional_line(duk_context* ctx, duk_idx_t index, client::line def);
 
 /**
  * Push the line as object.
@@ -76,7 +76,7 @@
  * \param ctx the context
  * \param line the line
  */
-void dukx_push_line(duk_context* ctx, const line &line);
+void dukx_push_line(duk_context* ctx, const client::line &line);
 
 /**
  * Put the line properties into the object at the top of the stack.
@@ -84,7 +84,7 @@
  * \param ctx the context
  * \param line the line
  */
-void dukx_put_line(duk_context* ctx, const line &line);
+void dukx_put_line(duk_context* ctx, const client::line &line);
 
 void dukx_load_line(duk_context* ctx);
 
--- a/libclient-js/malikania/js_point.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/libclient-js/malikania/js_point.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -24,7 +24,7 @@
 
 namespace {
 
-point parse(duk_context* ctx, duk_idx_t index, bool required, point ret = {})
+client::point parse(duk_context* ctx, duk_idx_t index, bool required, client::point ret = {})
 {
     dukx_stack_assert sa(ctx);
 
@@ -46,7 +46,7 @@
         y = duk_to_int(ctx, -1);
         duk_pop(ctx);
 
-        ret = point(x, y);
+        ret = client::point(x, y);
     } else if (required) {
         duk_error(ctx, DUK_ERR_TYPE_ERROR, "point object expected");
     }
@@ -56,10 +56,10 @@
 
 duk_ret_t constructor(duk_context* ctx)
 {
-    point obj;
+    client::point obj;
 
     if (duk_get_top(ctx) == 2) {
-        obj = point(duk_require_int(ctx, 0), duk_require_int(ctx, 1));
+        obj = client::point(duk_require_int(ctx, 0), duk_require_int(ctx, 1));
     } else if (duk_get_top(ctx) == 1) {
         obj = parse(ctx, 0, true);
     }
@@ -82,22 +82,22 @@
 
 } // !namespace
 
-point dukx_get_point(duk_context* ctx, duk_idx_t index)
+client::point dukx_get_point(duk_context* ctx, duk_idx_t index)
 {
     return parse(ctx, index, false);
 }
 
-point dukx_require_point(duk_context* ctx, duk_idx_t index)
+client::point dukx_require_point(duk_context* ctx, duk_idx_t index)
 {
     return parse(ctx, index, true);
 }
 
-point dukx_optional_point(duk_context* ctx, duk_idx_t index, point def)
+client::point dukx_optional_point(duk_context* ctx, duk_idx_t index, client::point def)
 {
     return parse(ctx, index, false, std::move(def));
 }
 
-void dukx_push_point(duk_context* ctx, const point &point)
+void dukx_push_point(duk_context* ctx, const client::point &point)
 {
     dukx_stack_assert sa(ctx, 1);
 
@@ -105,7 +105,7 @@
     dukx_put_point(ctx, point);
 }
 
-void dukx_put_point(duk_context* ctx, const point& point)
+void dukx_put_point(duk_context* ctx, const client::point& point)
 {
     assert(duk_is_object(ctx, -1));
 
--- a/libclient-js/malikania/js_point.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/libclient-js/malikania/js_point.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * js_point.hpp -- point description (JavaScript binding)
+ * js_client::point.hpp -- client::point description (JavaScript binding)
  *
  * Copyright (c) 2013-2017 Malikania Authors
  *
@@ -19,18 +19,18 @@
 #ifndef MALIKANIA_JS_POINT_HPP
 #define MALIKANIA_JS_POINT_HPP
 
-#include "duktape.hpp"
-#include "point.hpp"
+#include <malikania/client/point.hpp>
+#include <malikania/duktape.hpp>
 
 namespace mlk {
 
-point dukx_require_point(duk_context* ctx, duk_idx_t index);
+client::point dukx_require_point(duk_context* ctx, duk_idx_t index);
 
-point dukx_get_point(duk_context* ctx, duk_idx_t index);
+client::point dukx_get_point(duk_context* ctx, duk_idx_t index);
 
-void dukx_push_point(duk_context* ctx, const point& point);
+void dukx_push_point(duk_context* ctx, const client::point& point);
 
-void dukx_put_point(duk_context* ctx, const point& point);
+void dukx_put_point(duk_context* ctx, const client::point& point);
 
 void dukx_load_point(duk_context* ctx);
 
--- a/libclient-js/malikania/js_rectangle.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/libclient-js/malikania/js_rectangle.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -37,7 +37,7 @@
     return static_cast<unsigned>(value);
 }
 
-rectangle parse(duk_context* ctx, duk_idx_t index, bool required, rectangle rect = {})
+client::rectangle parse(duk_context* ctx, duk_idx_t index, bool required, client::rectangle rect = {})
 {
     dukx_stack_assert sa(ctx);
 
@@ -61,7 +61,7 @@
             return value;
         };
 
-        rect = rectangle(get("x"), get("y"),
+        rect = client::rectangle(get("x"), get("y"),
             clamp(ctx, get("width"), required), clamp(ctx, get("height"), required));
     } else if (required) {
         duk_error(ctx, DUK_ERR_TYPE_ERROR, "rectangle object expected");
@@ -72,10 +72,10 @@
 
 duk_ret_t constructor(duk_context* ctx)
 {
-    rectangle rect;
+    client::rectangle rect;
 
     if (duk_get_top(ctx) == 4) {
-        rect = rectangle(
+        rect = client::rectangle(
             duk_require_int(ctx, 0),
             duk_require_int(ctx, 1),
             clamp(ctx, duk_require_int(ctx, 2), true),
@@ -103,22 +103,22 @@
 
 } // !namespace
 
-rectangle dukx_get_rect(duk_context* ctx, duk_idx_t index)
+client::rectangle dukx_get_rect(duk_context* ctx, duk_idx_t index)
 {
     return parse(ctx, index, false);
 }
 
-rectangle dukx_require_rect(duk_context* ctx, duk_idx_t index)
+client::rectangle dukx_require_rect(duk_context* ctx, duk_idx_t index)
 {
     return parse(ctx, index, true);
 }
 
-rectangle dukx_optional_rect(duk_context* ctx, duk_idx_t index, rectangle def)
+client::rectangle dukx_optional_rect(duk_context* ctx, duk_idx_t index, client::rectangle def)
 {
     return parse(ctx, index, false, std::move(def));
 }
 
-void dukx_push_rect(duk_context* ctx, const rectangle& rect)
+void dukx_push_rect(duk_context* ctx, const client::rectangle& rect)
 {
     dukx_stack_assert sa(ctx, 1);
 
@@ -126,7 +126,7 @@
     dukx_put_rect(ctx, rect);
 }
 
-void dukx_put_rect(duk_context* ctx, const rectangle& rect)
+void dukx_put_rect(duk_context* ctx, const client::rectangle& rect)
 {
     assert(duk_is_object(ctx, -1));
 
--- a/libclient-js/malikania/js_rectangle.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/libclient-js/malikania/js_rectangle.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -35,8 +35,8 @@
  * ````
  */
 
-#include "duktape.hpp"
-#include "rectangle.hpp"
+#include <malikania/client/rectangle.hpp>
+#include <malikania/duktape.hpp>
 
 namespace mlk {
 
@@ -49,7 +49,7 @@
  * \param index the value index
  * \return the rectangle
  */
-rectangle dukx_get_rect(duk_context* ctx, duk_idx_t index);
+client::rectangle dukx_get_rect(duk_context* ctx, duk_idx_t index);
 
 /**
  * Require a rectangle.
@@ -60,7 +60,7 @@
  * \param index the index
  * \return the rectangle
  */
-rectangle dukx_require_rect(duk_context* ctx, duk_idx_t index);
+client::rectangle dukx_require_rect(duk_context* ctx, duk_idx_t index);
 
 /**
  * Like get but return the default value if the value at the given index is not an object or invalid
@@ -70,7 +70,7 @@
  * \param def the default value
  * \return the rectangle
  */
-rectangle dukx_optional_rect(duk_context* ctx, duk_idx_t index, rectangle def);
+client::rectangle dukx_optional_rect(duk_context* ctx, duk_idx_t index, client::rectangle def);
 
 /**
  * Push the rectangle as object.
@@ -78,7 +78,7 @@
  * \param ctx the context
  * \param rect the rectangle
  */
-void dukx_push_rect(duk_context* ctx, const rectangle &rect);
+void dukx_push_rect(duk_context* ctx, const client::rectangle &rect);
 
 /**
  * Put the rectangle properties into the object at the top of the stack.
@@ -86,7 +86,7 @@
  * \param ctx the context
  * \param rect the rectangle
  */
-void dukx_put_rect(duk_context* ctx, const rectangle& rect);
+void dukx_put_rect(duk_context* ctx, const client::rectangle& rect);
 
 void dukx_load_rect(duk_context* ctx);
 
--- a/libclient-js/malikania/js_size.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/libclient-js/malikania/js_size.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -24,7 +24,7 @@
 
 namespace {
 
-size parse(duk_context* ctx, duk_idx_t index, bool required, size ret = {})
+client::size parse(duk_context* ctx, duk_idx_t index, bool required, client::size ret = {})
 {
     dukx_stack_assert sa(ctx);
 
@@ -52,7 +52,7 @@
             duk_error(ctx, DUK_ERR_RANGE_ERROR, "height can not be negative");
         }
 
-        ret = size(width, height);
+        ret = client::size(width, height);
     } else if (required) {
         duk_error(ctx, DUK_ERR_TYPE_ERROR, "size object expected");
     }
@@ -62,7 +62,7 @@
 
 duk_ret_t constructor(duk_context* ctx)
 {
-    size obj;
+    client::size obj;
 
     if (duk_get_top(ctx) == 2) {
         int width;
@@ -75,7 +75,7 @@
             duk_error(ctx, DUK_ERR_RANGE_ERROR, "argument #1 can not be negative");
         }
 
-        obj = size(static_cast<unsigned>(width), static_cast<unsigned>(height));
+        obj = client::size(static_cast<unsigned>(width), static_cast<unsigned>(height));
     } else if (duk_get_top(ctx) == 1) {
         obj = parse(ctx, 0, true);
     }
@@ -98,22 +98,22 @@
 
 } // !namespace
 
-size dukx_get_size(duk_context* ctx, duk_idx_t index)
+client::size dukx_get_size(duk_context* ctx, duk_idx_t index)
 {
     return parse(ctx, index, false);
 }
 
-size dukx_require_size(duk_context* ctx, duk_idx_t index)
+client::size dukx_require_size(duk_context* ctx, duk_idx_t index)
 {
     return parse(ctx, index, true);
 }
 
-size dukx_optional_size(duk_context* ctx, duk_idx_t index, size def)
+client::size dukx_optional_size(duk_context* ctx, duk_idx_t index, client::size def)
 {
     return parse(ctx, index, false, std::move(def));
 }
 
-void dukx_push_size(duk_context* ctx, const size& size)
+void dukx_push_size(duk_context* ctx, const client::size& size)
 {
     dukx_stack_assert sa(ctx, 1);
 
@@ -121,7 +121,7 @@
     dukx_put_size(ctx, size);
 }
 
-void dukx_put_size(duk_context* ctx, const size& size)
+void dukx_put_size(duk_context* ctx, const client::size& size)
 {
     assert(duk_is_object(ctx, -1));
 
--- a/libclient-js/malikania/js_size.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/libclient-js/malikania/js_size.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -33,8 +33,8 @@
  * ````
  */
 
-#include "duktape.hpp"
-#include "size.hpp"
+#include <malikania/duktape.hpp>
+#include <malikania/client/size.hpp>
 
 namespace mlk {
 
@@ -47,7 +47,7 @@
  * \param index the value index
  * \return the size
  */
-size dukx_get_size(duk_context* ctx, duk_idx_t index);
+client::size dukx_get_size(duk_context* ctx, duk_idx_t index);
 
 /**
  * Require a size
@@ -58,7 +58,7 @@
  * \param index the index
  * \return the size
  */
-size dukx_require_size(duk_context* ctx, duk_idx_t index);
+client::size dukx_require_size(duk_context* ctx, duk_idx_t index);
 
 /**
  * Like get but return the default value if the value at the given index is not an object.
@@ -68,7 +68,7 @@
  * \param def the default value
  * \return the size
  */
-size dukx_optional_size(duk_context* ctx, duk_idx_t index, size def);
+client::size dukx_optional_size(duk_context* ctx, duk_idx_t index, client::size def);
 
 /**
  * Push the size as object.
@@ -76,7 +76,7 @@
  * \param ctx the context
  * \param size the size
  */
-void dukx_push_size(duk_context* ctx, const size& size);
+void dukx_push_size(duk_context* ctx, const client::size& size);
 
 /**
  * Put the size properties into the object at the top of the stack.
@@ -84,7 +84,7 @@
  * \param ctx the context
  * \param size the size
  */
-void dukx_put_size(duk_context* ctx, const size& size);
+void dukx_put_size(duk_context* ctx, const client::size& size);
 
 void dukx_load_size(duk_context* ctx);
 
--- a/libclient-js/malikania/js_sprite.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/libclient-js/malikania/js_sprite.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -28,7 +28,7 @@
 
 const std::string signature("\xff""\xff""malikania-sprite-ptr");
 
-sprite& self(duk_context *ctx)
+client::sprite& self(duk_context *ctx)
 {
     dukx_stack_assert sa(ctx);
 
@@ -41,7 +41,7 @@
         duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a sprite object");
     }
 
-    return *static_cast<sprite*>(ptr);
+    return *static_cast<client::sprite*>(ptr);
 }
 
 duk_ret_t cell(duk_context* ctx)
@@ -90,7 +90,7 @@
         auto sp = loader.load_sprite(duk_require_string(ctx, 0));
 
         duk_push_this(ctx);
-        duk_push_pointer(ctx, new sprite(std::move(sp)));
+        duk_push_pointer(ctx, new client::sprite(std::move(sp)));
         duk_put_prop_string(ctx, -2, signature.c_str());
 
         // Cell.
--- a/libclient-js/malikania/js_sprite.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/libclient-js/malikania/js_sprite.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -19,8 +19,8 @@
 #ifndef MALIKANIA_JS_SPRITE_HPP
 #define MALIKANIA_JS_SPRITE_HPP
 
-#include "duktape.hpp"
-#include "sprite.hpp"
+#include <malikania/duktape.hpp>
+#include <malikania/client/sprite.hpp>
 
 namespace mlk {
 
--- a/libclient-js/malikania/js_window.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/libclient-js/malikania/js_window.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -32,7 +32,7 @@
 const std::string signature("\xff""\xff""malikania-window-ptr");
 const std::string prototype("\xff""\xff""malikania-window-prototype");
 
-window& self(duk_context* ctx)
+client::window& self(duk_context* ctx)
 {
     dukx_stack_assert sa(ctx);
 
@@ -45,7 +45,7 @@
         duk_error(ctx, DUK_ERR_TYPE_ERROR, "not an Window object");
     }
 
-    return *static_cast<window*>(ptr);
+    return *static_cast<client::window*>(ptr);
 }
 
 duk_ret_t constructor(duk_context* ctx)
@@ -59,7 +59,7 @@
     // TODO: add parameters.
     try {
         duk_push_this(ctx);
-        duk_push_pointer(ctx, new window);
+        duk_push_pointer(ctx, new client::window);
         duk_put_prop_string(ctx, -2, signature.c_str());
         duk_pop(ctx);
     } catch (const std::exception &ex) {
@@ -179,7 +179,7 @@
         if (!rect.is_null()) {
             win.draw_text(text, font, rect);
         } else {
-            win.draw_text(text, font, point{rect.x(), rect.y()});
+            win.draw_text(text, font, client::point{rect.x(), rect.y()});
         }
     } catch (const std::exception &ex) {
         duk_error(ctx, DUK_ERR_ERROR, "%s", ex.what());
@@ -257,7 +257,7 @@
 
 #endif
 
-window& dukx_require_window(duk_context* ctx, duk_idx_t index)
+client::window& dukx_require_window(duk_context* ctx, duk_idx_t index)
 {
     assert(ctx);
 
@@ -271,7 +271,7 @@
         duk_error(ctx, DUK_ERR_TYPE_ERROR, "not a Window object");
     }
 
-    return *static_cast<window*>(ptr);
+    return *static_cast<client::window*>(ptr);
 }
 
 void dukx_load_window(duk_context* ctx)
--- a/libclient-js/malikania/js_window.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/libclient-js/malikania/js_window.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -19,12 +19,12 @@
 #ifndef MALIKANIA_JS_WINDOW_HPP
 #define MALIKANIA_JS_WINDOW_HPP
 
-#include "duktape.hpp"
-#include "window.hpp"
+#include <malikania/client/window.hpp>
+#include <malikania/duktape.hpp>
 
 namespace mlk {
 
-window& dukx_require_window(duk_context* ctx, duk_idx_t index);
+client::window& dukx_require_window(duk_context* ctx, duk_idx_t index);
 
 void dukx_load_window(duk_context* ctx);
 
--- a/libclient/CMakeLists.txt	Sun Jan 22 10:11:17 2017 +0100
+++ b/libclient/CMakeLists.txt	Sun Jan 22 11:07:36 2017 +0100
@@ -20,51 +20,50 @@
 
 set(
     HEADERS
-    ${libmlk-client_SOURCE_DIR}/malikania/animation.hpp
-    ${libmlk-client_SOURCE_DIR}/malikania/animator.hpp
-    ${libmlk-client_SOURCE_DIR}/malikania/button.hpp
-    ${libmlk-client_SOURCE_DIR}/malikania/color.hpp
-    ${libmlk-client_SOURCE_DIR}/malikania/font.hpp
-    ${libmlk-client_SOURCE_DIR}/malikania/frame.hpp
-#    ${libmlk-client_SOURCE_DIR}/malikania/grid_layout.hpp
-    ${libmlk-client_SOURCE_DIR}/malikania/image.hpp
-    ${libmlk-client_SOURCE_DIR}/malikania/key.hpp
-    ${libmlk-client_SOURCE_DIR}/malikania/label.hpp
-    ${libmlk-client_SOURCE_DIR}/malikania/layout.hpp
-    ${libmlk-client_SOURCE_DIR}/malikania/line.hpp
-    ${libmlk-client_SOURCE_DIR}/malikania/mouse.hpp
-    ${libmlk-client_SOURCE_DIR}/malikania/point.hpp
-    ${libmlk-client_SOURCE_DIR}/malikania/rectangle.hpp
-    ${libmlk-client_SOURCE_DIR}/malikania/size.hpp
-    ${libmlk-client_SOURCE_DIR}/malikania/sprite.hpp
-    ${libmlk-client_SOURCE_DIR}/malikania/theme.hpp
-    ${libmlk-client_SOURCE_DIR}/malikania/unique_layout.hpp
-    ${libmlk-client_SOURCE_DIR}/malikania/widget.hpp
-    ${libmlk-client_SOURCE_DIR}/malikania/window.hpp
-    ${libmlk-client_SOURCE_DIR}/malikania/${WITH_BACKEND_DIR}/font_backend.hpp
-    ${libmlk-client_SOURCE_DIR}/malikania/${WITH_BACKEND_DIR}/image_backend.hpp
-    ${libmlk-client_SOURCE_DIR}/malikania/${WITH_BACKEND_DIR}/window_backend.hpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/animation.hpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/animator.hpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/button.hpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/color.hpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/font.hpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/frame.hpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/image.hpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/key.hpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/label.hpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/layout.hpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/line.hpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/loader.hpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/mouse.hpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/point.hpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/rectangle.hpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/size.hpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/sprite.hpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/theme.hpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/unique_layout.hpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/widget.hpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/window.hpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/${WITH_BACKEND_DIR}/font_backend.hpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/${WITH_BACKEND_DIR}/image_backend.hpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/${WITH_BACKEND_DIR}/window_backend.hpp
 )
 
 set(
     SOURCES
-    ${libmlk-client_SOURCE_DIR}/malikania/animator.cpp
-    ${libmlk-client_SOURCE_DIR}/malikania/button.cpp
-    ${libmlk-client_SOURCE_DIR}/malikania/client_resources_loader.cpp
-    ${libmlk-client_SOURCE_DIR}/malikania/color.cpp
-    ${libmlk-client_SOURCE_DIR}/malikania/font.cpp
-    ${libmlk-client_SOURCE_DIR}/malikania/frame.cpp
-#    ${libmlk-client_SOURCE_DIR}/malikania/grid_layout.cpp
-    ${libmlk-client_SOURCE_DIR}/malikania/image.cpp
-    ${libmlk-client_SOURCE_DIR}/malikania/label.cpp
-    ${libmlk-client_SOURCE_DIR}/malikania/sprite.cpp
-    ${libmlk-client_SOURCE_DIR}/malikania/theme.cpp
-    ${libmlk-client_SOURCE_DIR}/malikania/unique_layout.cpp
-    ${libmlk-client_SOURCE_DIR}/malikania/widget.cpp
-    ${libmlk-client_SOURCE_DIR}/malikania/window.cpp
-    ${libmlk-client_SOURCE_DIR}/malikania/${WITH_BACKEND_DIR}/font_backend.cpp
-    ${libmlk-client_SOURCE_DIR}/malikania/${WITH_BACKEND_DIR}/image_backend.cpp
-    ${libmlk-client_SOURCE_DIR}/malikania/${WITH_BACKEND_DIR}/window_backend.cpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/animator.cpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/button.cpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/loader.cpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/color.cpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/font.cpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/frame.cpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/image.cpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/label.cpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/sprite.cpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/theme.cpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/unique_layout.cpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/widget.cpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/window.cpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/${WITH_BACKEND_DIR}/font_backend.cpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/${WITH_BACKEND_DIR}/image_backend.cpp
+    ${libmlk-client_SOURCE_DIR}/malikania/client/${WITH_BACKEND_DIR}/window_backend.cpp
 )
 
 if (WITH_BACKEND MATCHES "SDL")
@@ -93,8 +92,10 @@
     TARGET libmlk-client
     SOURCES ${HEADERS} ${SOURCES}
     ASSETS ${libmlk-client_SOURCE_DIR}/assets/dejavu_sans.ttf
+    PRIVATE_INCLUDES
+        $<BUILD_INTERFACE:${libmlk-client_SOURCE_DIR}/malikania/client>
     PUBLIC_INCLUDES
-        $<BUILD_INTERFACE:${libmlk-client_SOURCE_DIR}/malikania/${WITH_BACKEND_DIR}>
+        $<BUILD_INTERFACE:${libmlk-client_SOURCE_DIR}/malikania/client/${WITH_BACKEND_DIR}>
         $<BUILD_INTERFACE:${libmlk-client_SOURCE_DIR}/malikania>
         ${INCLUDES}
     LIBRARIES libmlk-common ${LIBRARIES}
--- a/libclient/malikania/animation.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,153 +0,0 @@
-/*
- * animation.hpp -- animation description
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_ANIMATION_HPP
-#define MALIKANIA_ANIMATION_HPP
-
-/**
- * \file animation.hpp
- * \brief Describe an animation.
- */
-
-#include <cassert>
-#include <cstdint>
-#include <memory>
-#include <vector>
-
-#include "sprite.hpp"
-
-namespace mlk {
-
-class window;
-
-/**
- * \brief Animation frame description.
- *
- * A frame is a duration before switching to the next sprite cell. It is
- * currently implemented as a class for future usage.
- */
-class animation_frame {
-private:
-    std::uint16_t m_delay;
-
-public:
-    /**
-     * Construct a frame.
-     *
-     * \param delay the optional delay
-     */
-    inline animation_frame(std::uint16_t delay = 100) noexcept
-        : m_delay(delay)
-    {
-    }
-
-    /**
-     * Get the the delay.
-     *
-     * \return the delay
-     */
-    inline std::uint16_t delay() const noexcept
-    {
-        return m_delay;
-    }
-};
-
-/**
- * \brief List of frames.
- */
-using animation_frames = std::vector<animation_frame>;
-
-/**
- * \brief Animation description.
- *
- * An animation is a sprite with a set of frames containing a delay for showing
- * all sprites in a specific amount of time.
- *
- * Because an animation contains an image, a state (time, current cell) it must
- * be constructed with an animator object so the user is able to use the same
- * animation on different parts of the screen without having to duplicate
- * resources.
- *
- * \see Animator
- */
-class animation {
-private:
-    mlk::sprite m_sprite;
-    mlk::animation_frames m_frames;
-
-public:
-    /**
-     * Create an animation.
-     *
-     * \param sprite the sprite image
-     * \param frames the frames to show
-     */
-    inline animation(mlk::sprite sprite, animation_frames frames) noexcept
-        : m_sprite(std::move(sprite))
-        , m_frames(std::move(frames))
-    {
-    }
-
-    /**
-     * Get the underlying sprite.
-     *
-     * \return the sprite
-     */
-    inline const mlk::sprite& sprite() const noexcept
-    {
-        return m_sprite;
-    }
-
-    /**
-     * Overloaded function.
-     *
-     * \return the sprite
-     */
-    inline mlk::sprite& sprite() noexcept
-    {
-        return m_sprite;
-    }
-
-    /**
-     * Get the frames.
-     *
-     * \return the frames
-     */
-    inline const animation_frames& frames() const noexcept
-    {
-        return m_frames;
-    }
-
-    /**
-     * Access a frame.
-     *
-     * \pre index < number of frames
-     * \param index the index
-     * \return the frame
-     */
-    inline const animation_frame& operator[](unsigned index) const noexcept
-    {
-        assert(index < m_frames.size());
-
-        return m_frames[index];
-    }
-};
-
-} // !mlk
-
-#endif // !MALIKANIA_ANIMATION_HPP
--- a/libclient/malikania/animator.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * animator.cpp -- animation drawing object
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "animation.hpp"
-#include "animator.hpp"
-
-namespace mlk {
-
-animator::animator(animation& animation) noexcept
-    : m_animation(animation)
-{
-}
-
-void animator::update() noexcept
-{
-    auto total = m_animation.sprite().rows() * m_animation.sprite().columns();
-
-    if (m_current >= total) {
-        return;
-    }
-
-    if (m_timer.elapsed().wall / 1000000LL >= m_animation[m_current].delay()) {
-        m_current ++;
-        m_timer.start();
-    }
-}
-
-void animator::draw(window& window, const point& point)
-{
-    if (m_current >= m_animation.sprite().rows() * m_animation.sprite().columns()) {
-        return;
-    }
-
-    m_animation.sprite().draw(window, m_current, point);
-}
-
-} // !mlk
--- a/libclient/malikania/animator.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * animator.hpp -- animation drawing object
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_ANIMATOR_HPP
-#define MALIKANIA_ANIMATOR_HPP
-
-#include <boost/timer/timer.hpp>
-
-/**
- * \file animator.hpp
- * \brief Draw animations.
- */
-
-namespace mlk {
-
-class animation;
-class point;
-class window;
-
-/**
- * \brief Object for drawing animations.
- *
- * The animator contains an animation and a state.
- */
-class animator {
-private:
-    boost::timer::cpu_timer m_timer;
-    animation& m_animation;
-    unsigned m_current{0};
-
-public:
-    /**
-     * Construct an animator.
-     *
-     * \pre animation must not be null
-     * \param animation the animation
-     */
-    animator(animation& animation) noexcept;
-
-    /**
-     * Update the animator state.
-     *
-     * This function should be called in the main loop to update the cell to
-     * draw before calling draw().
-     */
-    void update() noexcept;
-
-    /**
-     * Draw the animation.
-     *
-     * \param window the window
-     * \param position the position in the window
-     */
-    void draw(window& window, const point& position);
-};
-
-} // !mlk
-
-#endif // !MALIKANIA_ANIMATOR_HPP
--- a/libclient/malikania/backend/sdl/font_backend.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,57 +0,0 @@
-/*
- * font_backend.cpp -- font object (SDL2 implementation)
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <malikania/backend/sdl/sdl_util.hpp>
-
-#include <malikania/size.hpp>
-#include <malikania/font.hpp>
-
-#include "font_backend.hpp"
-
-using namespace std::string_literals;
-
-namespace mlk {
-
-font::backend_impl::backend_impl(std::string data, unsigned size)
-    : m_font(nullptr, nullptr)
-{
-    auto rw = SDLx_RWFromBinary(std::move(data));
-
-    if (rw == nullptr) {
-        throw std::runtime_error(SDL_GetError());
-    }
-
-    m_font = {TTF_OpenFontRW(rw, true, size), TTF_CloseFont};
-
-    if (m_font == nullptr) {
-        throw std::runtime_error(TTF_GetError());
-    }
-}
-
-size font::backend_impl::clip(const mlk::font&, const std::string& text) const
-{
-    int width, height;
-
-    if (TTF_SizeUTF8(m_font.get(), text.c_str(), &width, &height) != 0) {
-        throw std::runtime_error(SDL_GetError());
-    }
-
-    return mlk::size(static_cast<unsigned>(width), static_cast<unsigned>(height));
-}
-
-} // !mlk
--- a/libclient/malikania/backend/sdl/font_backend.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * font_backend.hpp -- font object (SDL2 implementation)
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_FONT_BACKEND_HPP
-#define MALIKANIA_FONT_BACKEND_HPP
-
-#include <memory>
-
-#include <SDL.h>
-#include <SDL_ttf.h>
-
-#include <malikania/font.hpp>
-
-namespace mlk {
-
-class font;
-class size;
-
-class font::backend_impl {
-private:
-    std::unique_ptr<TTF_Font, void (*)(TTF_Font*)> m_font;
-
-public:
-    backend_impl(std::string data, unsigned size);
-
-    inline TTF_Font* font() noexcept
-    {
-        return m_font.get();
-    }
-
-    mlk::size clip(const mlk::font& self, const std::string& text) const;
-};
-
-} // !mlk
-
-#endif // !MALIKANIA_FONT_BACKEND_HPP
--- a/libclient/malikania/backend/sdl/image_backend.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,119 +0,0 @@
-/*
- * image_backend.cpp -- image object (SDL2 implementation)
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <SDL_image.h>
-
-#include <malikania/backend/sdl/sdl_util.hpp>
-
-#include "image_backend.hpp"
-#include "window_backend.hpp"
-
-using namespace std::string_literals;
-
-namespace mlk {
-
-void image::backend_impl::create_texture(window& window)
-{
-    m_texture = {
-        SDL_CreateTextureFromSurface(window.backend().renderer(), m_surface.get()),
-        SDL_DestroyTexture
-    };
-
-    if (m_texture == nullptr) {
-        throw std::runtime_error(SDL_GetError());
-    }
-}
-
-image::backend_impl::backend_impl(image&, std::string data)
-    : m_surface(nullptr, nullptr)
-    , m_texture(nullptr, nullptr)
-{
-    auto rw = SDLx_RWFromBinary(std::move(data));
-
-    if (rw == nullptr) {
-        throw std::runtime_error(SDL_GetError());
-    }
-
-    m_surface = {IMG_Load_RW(rw, true), SDL_FreeSurface};
-
-    if (!m_surface) {
-        throw std::runtime_error(SDL_GetError());
-    }
-
-    m_size = mlk::size(
-        static_cast<unsigned>(m_surface->w),
-        static_cast<unsigned>(m_surface->h)
-    );
-}
-
-void image::backend_impl::draw(window& window, const point& point)
-{
-    /*
-     * Create texture at this step so the image constructor does not need the
-     * window.
-     */
-    if (!m_texture) {
-        create_texture(window);
-    }
-
-    SDL_Rect target;
-
-    target.x = static_cast<int>(point.x());
-    target.y = static_cast<int>(point.y());
-    target.w = static_cast<int>(m_size.width());
-    target.h = static_cast<int>(m_size.height());
-
-    if (SDL_RenderCopy(window.backend().renderer(), m_texture.get(), nullptr, &target) < 0) {
-        throw std::runtime_error(SDL_GetError());
-    }
-}
-
-void image::backend_impl::draw(window& window, const rectangle& source, const rectangle& target)
-{
-    if (!m_texture) {
-        create_texture(window);
-    }
-
-    SDL_Rect sr, st;
-
-    sr.x = source.x();
-    sr.y = source.y();
-    sr.w = static_cast<int>(source.width());
-    sr.h = static_cast<int>(source.height());
-
-    st.x = target.x();
-    st.y = target.y();
-    st.w = static_cast<int>(target.width());
-    st.h = static_cast<int>(target.height());
-
-    // Readjust .w, .h if null.
-    if (source.is_null()) {
-        sr.w = static_cast<int>(m_size.width());
-        sr.h = static_cast<int>(m_size.height());
-    }
-    if (target.is_null()) {
-        st.w = static_cast<int>(m_size.width());
-        st.h = static_cast<int>(m_size.height());
-    }
-
-    if (SDL_RenderCopy(window.backend().renderer(), m_texture.get(), &sr, &st) < 0) {
-        throw std::runtime_error(SDL_GetError());
-    }
-}
-
-} // !mlk
--- a/libclient/malikania/backend/sdl/image_backend.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,65 +0,0 @@
-/*
- * image_backend.hpp -- image object (SDL2 implementation)
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_IMAGE_BACKEND_HPP
-#define MALIKANIA_IMAGE_BACKEND_HPP
-
-#include <memory>
-
-#include <SDL.h>
-
-#include <malikania/size.hpp>
-#include <malikania/image.hpp>
-
-namespace mlk {
-
-class image;
-class point;
-class rectangle;
-class window;
-
-class image::backend_impl {
-private:
-    std::unique_ptr<SDL_Surface, void (*)(SDL_Surface *)> m_surface;
-    std::unique_ptr<SDL_Texture, void (*)(SDL_Texture *)> m_texture;
-
-    mlk::size m_size;
-
-    void create_texture(window& window);
-
-public:
-    backend_impl(image& self, std::string data);
-
-    inline SDL_Texture* texture() noexcept
-    {
-        return m_texture.get();
-    }
-
-    inline const mlk::size& size() const noexcept
-    {
-        return m_size;
-    }
-
-    void draw(window& window, const point& position);
-
-    void draw(window& window, const rectangle& source, const rectangle& target);
-};
-
-} // !mlk
-
-#endif // !MALIKANIA_IMAGE_BACKEND_HPP
--- a/libclient/malikania/backend/sdl/window_backend.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,640 +0,0 @@
-/*
- * window_backend.cpp -- window object (SDL2 implementation)
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <cassert>
-#include <stdexcept>
-#include <unordered_map>
-
-#include <SDL.h>
-#include <SDL_ttf.h>
-
-#include <malikania/color.hpp>
-#include <malikania/key.hpp>
-#include <malikania/line.hpp>
-#include <malikania/point.hpp>
-#include <malikania/rectangle.hpp>
-
-#include "font_backend.hpp"
-#include "window_backend.hpp"
-#include "window.hpp"
-
-namespace mlk {
-
-namespace {
-
-/*
- * conversion maps
- * ------------------------------------------------------------------
- *
- * There is a difference between scancode and key codes. The scancode is the
- * key located on the keyboard which is always the same, the key code is the
- * translated to the user layout.
- *
- * For example, on azerty, hitting the 'a' key makes a key code of 'a' but a
- * scancode of 'q'.
- *
- *   - scancodes_map        : convert SDL scancode do key
- *   - keycodes_map         : convert SDL key code to key
- *   - modifiers_map        : convert masks
- *   - button_map           : convert SDL mouse buttons
- */
-
-const std::unordered_map<SDL_Keycode, key> scancodes_map{
-    { SDL_SCANCODE_A,               key::a                      },
-    { SDL_SCANCODE_B,               key::b                      },
-    { SDL_SCANCODE_C,               key::c                      },
-    { SDL_SCANCODE_D,               key::d                      },
-    { SDL_SCANCODE_E,               key::e                      },
-    { SDL_SCANCODE_F,               key::f                      },
-    { SDL_SCANCODE_G,               key::g                      },
-    { SDL_SCANCODE_H,               key::h                      },
-    { SDL_SCANCODE_I,               key::i                      },
-    { SDL_SCANCODE_J,               key::j                      },
-    { SDL_SCANCODE_K,               key::k                      },
-    { SDL_SCANCODE_L,               key::l                      },
-    { SDL_SCANCODE_M,               key::m                      },
-    { SDL_SCANCODE_N,               key::n                      },
-    { SDL_SCANCODE_O,               key::o                      },
-    { SDL_SCANCODE_P,               key::p                      },
-    { SDL_SCANCODE_Q,               key::q                      },
-    { SDL_SCANCODE_R,               key::r                      },
-    { SDL_SCANCODE_S,               key::s                      },
-    { SDL_SCANCODE_T,               key::t                      },
-    { SDL_SCANCODE_U,               key::u                      },
-    { SDL_SCANCODE_V,               key::v                      },
-    { SDL_SCANCODE_W,               key::w                      },
-    { SDL_SCANCODE_X,               key::x                      },
-    { SDL_SCANCODE_Y,               key::y                      },
-    { SDL_SCANCODE_Z,               key::z                      },
-    { SDL_SCANCODE_1,               key::one                    },
-    { SDL_SCANCODE_2,               key::two                    },
-    { SDL_SCANCODE_3,               key::three                  },
-    { SDL_SCANCODE_4,               key::four                   },
-    { SDL_SCANCODE_5,               key::five                   },
-    { SDL_SCANCODE_6,               key::six                    },
-    { SDL_SCANCODE_7,               key::seven                  },
-    { SDL_SCANCODE_8,               key::eight                  },
-    { SDL_SCANCODE_9,               key::nine                   },
-    { SDL_SCANCODE_0,               key::zero                   },
-    { SDL_SCANCODE_RETURN,          key::enter                  },
-    { SDL_SCANCODE_ESCAPE,          key::escape                 },
-    { SDL_SCANCODE_BACKSPACE,       key::backspace              },
-    { SDL_SCANCODE_TAB,             key::tab                    },
-    { SDL_SCANCODE_SPACE,           key::space                  },
-    { SDL_SCANCODE_MINUS,           key::minus                  },
-    { SDL_SCANCODE_EQUALS,          key::equals                 },
-    { SDL_SCANCODE_LEFTBRACKET,     key::left_bracket           },
-    { SDL_SCANCODE_RIGHTBRACKET,    key::right_bracket          },
-    { SDL_SCANCODE_BACKSLASH,       key::backslash              },
-    { SDL_SCANCODE_NONUSHASH,       key::hash                   },
-    { SDL_SCANCODE_SEMICOLON,       key::semicolon              },
-    { SDL_SCANCODE_APOSTROPHE,      key::apostrophe             },
-    { SDL_SCANCODE_GRAVE,           key::grave                  },
-    { SDL_SCANCODE_COMMA,           key::comma                  },
-    { SDL_SCANCODE_PERIOD,          key::period                 },
-    { SDL_SCANCODE_SLASH,           key::slash                  },
-    { SDL_SCANCODE_CAPSLOCK,        key::caps_lock              },
-    { SDL_SCANCODE_F1,              key::f1                     },
-    { SDL_SCANCODE_F2,              key::f2                     },
-    { SDL_SCANCODE_F3,              key::f3                     },
-    { SDL_SCANCODE_F4,              key::f4                     },
-    { SDL_SCANCODE_F5,              key::f5                     },
-    { SDL_SCANCODE_F6,              key::f6                     },
-    { SDL_SCANCODE_F7,              key::f7                     },
-    { SDL_SCANCODE_F8,              key::f8                     },
-    { SDL_SCANCODE_F9,              key::f9                     },
-    { SDL_SCANCODE_F10,             key::f10                    },
-    { SDL_SCANCODE_F11,             key::f11                    },
-    { SDL_SCANCODE_F12,             key::f12                    },
-    { SDL_SCANCODE_F13,             key::f13                    },
-    { SDL_SCANCODE_F14,             key::f14                    },
-    { SDL_SCANCODE_F15,             key::f15                    },
-    { SDL_SCANCODE_F16,             key::f16                    },
-    { SDL_SCANCODE_F17,             key::f17                    },
-    { SDL_SCANCODE_F18,             key::f18                    },
-    { SDL_SCANCODE_F19,             key::f19                    },
-    { SDL_SCANCODE_F20,             key::f20                    },
-    { SDL_SCANCODE_F21,             key::f21                    },
-    { SDL_SCANCODE_F22,             key::f22                    },
-    { SDL_SCANCODE_F23,             key::f23                    },
-    { SDL_SCANCODE_F24,             key::f24                    },
-    { SDL_SCANCODE_PRINTSCREEN,     key::print_screen           },
-    { SDL_SCANCODE_SCROLLLOCK,      key::scroll_lock            },
-    { SDL_SCANCODE_PAUSE,           key::pause                  },
-    { SDL_SCANCODE_INSERT,          key::insert                 },
-    { SDL_SCANCODE_HOME,            key::home                   },
-    { SDL_SCANCODE_PAGEUP,          key::page_up                },
-    { SDL_SCANCODE_PAGEDOWN,        key::page_down              },
-    { SDL_SCANCODE_DELETE,          key::del                    },
-    { SDL_SCANCODE_END,             key::end                    },
-    { SDL_SCANCODE_RIGHT,           key::right                  },
-    { SDL_SCANCODE_LEFT,            key::left                   },
-    { SDL_SCANCODE_DOWN,            key::down                   },
-    { SDL_SCANCODE_UP,              key::up                     },
-    { SDL_SCANCODE_KP_DIVIDE,       key::kp_divide              },
-    { SDL_SCANCODE_KP_MULTIPLY,     key::kp_multiply            },
-    { SDL_SCANCODE_KP_MINUS,        key::kp_minus               },
-    { SDL_SCANCODE_KP_PLUS,         key::kp_plus                },
-    { SDL_SCANCODE_KP_ENTER,        key::kp_enter               },
-    { SDL_SCANCODE_KP_1,            key::kp_one                 },
-    { SDL_SCANCODE_KP_2,            key::kp_two                 },
-    { SDL_SCANCODE_KP_3,            key::kp_three               },
-    { SDL_SCANCODE_KP_4,            key::kp_four                },
-    { SDL_SCANCODE_KP_5,            key::kp_five                },
-    { SDL_SCANCODE_KP_6,            key::kp_six                 },
-    { SDL_SCANCODE_KP_7,            key::kp_seven               },
-    { SDL_SCANCODE_KP_8,            key::kp_eight               },
-    { SDL_SCANCODE_KP_9,            key::kp_nine                },
-    { SDL_SCANCODE_KP_0,            key::kp_zero                },
-    { SDL_SCANCODE_MUTE,            key::mute                   },
-    { SDL_SCANCODE_VOLUMEUP,        key::volume_up              },
-    { SDL_SCANCODE_VOLUMEDOWN,      key::volume_down            },
-    { SDL_SCANCODE_LCTRL,           key::left_control           },
-    { SDL_SCANCODE_LALT,            key::left_alt               },
-    { SDL_SCANCODE_LSHIFT,          key::left_shift             },
-    { SDL_SCANCODE_LGUI,            key::left_super             },
-    { SDL_SCANCODE_RCTRL,           key::right_control          },
-    { SDL_SCANCODE_RALT,            key::right_alt              },
-    { SDL_SCANCODE_RSHIFT,          key::right_shift            },
-    { SDL_SCANCODE_RGUI,            key::right_super            }
-};
-
-const std::unordered_map<SDL_Keycode, key> keycodes_map{
-    { SDLK_RETURN,                  key::enter                  },
-    { SDLK_ESCAPE,                  key::escape                 },
-    { SDLK_BACKSPACE,               key::backspace              },
-    { SDLK_TAB,                     key::tab                    },
-    { SDLK_SPACE,                   key::space                  },
-    { SDLK_EXCLAIM,                 key::exclaim                },
-    { SDLK_QUOTEDBL,                key::double_quote           },
-    { SDLK_HASH,                    key::hash                   },
-    { SDLK_PERCENT,                 key::percent                },
-    { SDLK_DOLLAR,                  key::dollar                 },
-    { SDLK_AMPERSAND,               key::ampersand              },
-    { SDLK_QUOTE,                   key::quote                  },
-    { SDLK_LEFTPAREN,               key::left_parenthese        },
-    { SDLK_RIGHTPAREN,              key::right_parenthese       },
-    { SDLK_ASTERISK,                key::asterisk               },
-    { SDLK_PLUS,                    key::plus                   },
-    { SDLK_COMMA,                   key::comma                  },
-    { SDLK_MINUS,                   key::minus                  },
-    { SDLK_PERIOD,                  key::period                 },
-    { SDLK_SLASH,                   key::slash                  },
-    { SDLK_0,                       key::zero                   },
-    { SDLK_1,                       key::one                    },
-    { SDLK_2,                       key::two                    },
-    { SDLK_3,                       key::three                  },
-    { SDLK_4,                       key::four                   },
-    { SDLK_5,                       key::five                   },
-    { SDLK_6,                       key::six                    },
-    { SDLK_7,                       key::seven                  },
-    { SDLK_8,                       key::eight                  },
-    { SDLK_9,                       key::nine                   },
-    { SDLK_COLON,                   key::colon                  },
-    { SDLK_SEMICOLON,               key::semicolon              },
-    { SDLK_LESS,                    key::less                   },
-    { SDLK_EQUALS,                  key::equals                 },
-    { SDLK_GREATER,                 key::greater                },
-    { SDLK_QUESTION,                key::question               },
-    { SDLK_AT,                      key::at                     },
-    { SDLK_LEFTBRACKET,             key::left_bracket           },
-    { SDLK_BACKSLASH,               key::backslash              },
-    { SDLK_RIGHTBRACKET,            key::right_bracket          },
-    { SDLK_CARET,                   key::caret                  },
-    { SDLK_UNDERSCORE,              key::underscore             },
-    { SDLK_BACKQUOTE,               key::back_quote             },
-    { SDLK_a,                       key::a                      },
-    { SDLK_b,                       key::b                      },
-    { SDLK_c,                       key::c                      },
-    { SDLK_d,                       key::d                      },
-    { SDLK_e,                       key::e                      },
-    { SDLK_f,                       key::f                      },
-    { SDLK_g,                       key::g                      },
-    { SDLK_h,                       key::h                      },
-    { SDLK_i,                       key::i                      },
-    { SDLK_j,                       key::j                      },
-    { SDLK_k,                       key::k                      },
-    { SDLK_l,                       key::l                      },
-    { SDLK_m,                       key::m                      },
-    { SDLK_n,                       key::n                      },
-    { SDLK_o,                       key::o                      },
-    { SDLK_p,                       key::p                      },
-    { SDLK_q,                       key::q                      },
-    { SDLK_r,                       key::r                      },
-    { SDLK_s,                       key::s                      },
-    { SDLK_t,                       key::t                      },
-    { SDLK_u,                       key::u                      },
-    { SDLK_v,                       key::v                      },
-    { SDLK_w,                       key::w                      },
-    { SDLK_x,                       key::x                      },
-    { SDLK_y,                       key::y                      },
-    { SDLK_z,                       key::z                      },
-    { SDLK_CAPSLOCK,                key::caps_lock              },
-    { SDLK_F1,                      key::f1                     },
-    { SDLK_F2,                      key::f2                     },
-    { SDLK_F3,                      key::f3                     },
-    { SDLK_F4,                      key::f4                     },
-    { SDLK_F5,                      key::f5                     },
-    { SDLK_F6,                      key::f6                     },
-    { SDLK_F7,                      key::f7                     },
-    { SDLK_F8,                      key::f8                     },
-    { SDLK_F9,                      key::f9                     },
-    { SDLK_F10,                     key::f10                    },
-    { SDLK_F11,                     key::f11                    },
-    { SDLK_F12,                     key::f12                    },
-    { SDLK_F13,                     key::f13                    },
-    { SDLK_F14,                     key::f14                    },
-    { SDLK_F15,                     key::f15                    },
-    { SDLK_F16,                     key::f16                    },
-    { SDLK_F17,                     key::f17                    },
-    { SDLK_F18,                     key::f18                    },
-    { SDLK_F19,                     key::f19                    },
-    { SDLK_F20,                     key::f20                    },
-    { SDLK_F21,                     key::f21                    },
-    { SDLK_F22,                     key::f22                    },
-    { SDLK_F23,                     key::f23                    },
-    { SDLK_F24,                     key::f24                    },
-    { SDLK_PRINTSCREEN,             key::print_screen           },
-    { SDLK_SCROLLLOCK,              key::scroll_lock            },
-    { SDLK_PAUSE,                   key::pause                  },
-    { SDLK_INSERT,                  key::insert                 },
-    { SDLK_HOME,                    key::home                   },
-    { SDLK_PAGEUP,                  key::page_up                },
-    { SDLK_PAGEDOWN,                key::page_down              },
-    { SDLK_DELETE,                  key::del                    },
-    { SDLK_END,                     key::end                    },
-    { SDLK_RIGHT,                   key::right                  },
-    { SDLK_LEFT,                    key::left                   },
-    { SDLK_DOWN,                    key::down                   },
-    { SDLK_UP,                      key::up                     },
-    { SDLK_KP_DIVIDE,               key::kp_divide              },
-    { SDLK_KP_MULTIPLY,             key::kp_multiply            },
-    { SDLK_KP_MINUS,                key::kp_minus               },
-    { SDLK_KP_PLUS,                 key::kp_plus                },
-    { SDLK_KP_ENTER,                key::kp_enter               },
-    { SDLK_KP_1,                    key::kp_one                 },
-    { SDLK_KP_2,                    key::kp_two                 },
-    { SDLK_KP_3,                    key::kp_three               },
-    { SDLK_KP_4,                    key::kp_four                },
-    { SDLK_KP_5,                    key::kp_five                },
-    { SDLK_KP_6,                    key::kp_six                 },
-    { SDLK_KP_7,                    key::kp_seven               },
-    { SDLK_KP_8,                    key::kp_eight               },
-    { SDLK_KP_9,                    key::kp_nine                },
-    { SDLK_KP_0,                    key::kp_zero                },
-    { SDLK_MUTE,                    key::mute                   },
-    { SDLK_VOLUMEUP,                key::volume_up              },
-    { SDLK_VOLUMEDOWN,              key::volume_down            },
-    { SDLK_LCTRL,                   key::left_control           },
-    { SDLK_LALT,                    key::left_alt               },
-    { SDLK_LSHIFT,                  key::left_shift             },
-    { SDLK_LGUI,                    key::left_super             },
-    { SDLK_RCTRL,                   key::right_control          },
-    { SDLK_RALT,                    key::right_alt              },
-    { SDLK_RSHIFT,                  key::right_shift            },
-    { SDLK_RGUI,                    key::right_super            }
-};
-
-const std::unordered_map<SDL_Keymod, mod> modifiers_map{
-    { KMOD_LCTRL,                   mod::left_control           },
-    { KMOD_LALT,                    mod::left_alt               },
-    { KMOD_LSHIFT,                  mod::left_shift             },
-    { KMOD_LGUI,                    mod::left_super             },
-    { KMOD_RCTRL,                   mod::right_control          },
-    { KMOD_RALT,                    mod::right_alt              },
-    { KMOD_RSHIFT,                  mod::right_shift            },
-    { KMOD_RGUI,                    mod::right_super            },
-    { KMOD_NUM,                     mod::num_lock               },
-    { KMOD_CAPS,                    mod::caps_lock              }
-};
-
-const std::unordered_map<Uint32, mouse> button_map{
-    { SDL_BUTTON_LEFT,      mouse::left     },
-    { SDL_BUTTON_RIGHT,     mouse::right    },
-    { SDL_BUTTON_MIDDLE,    mouse::middle   }
-};
-
-} // !namespace
-
-void window::backend_impl::handle_key(window& self, const SDL_Event& ev)
-{
-    assert(ev.type == SDL_KEYDOWN || ev.type == SDL_KEYUP);
-
-    // Key and scan code.
-    auto kc = keycodes_map.find(ev.key.keysym.sym);
-    auto sc = scancodes_map.find(ev.key.keysym.scancode);
-
-    if (kc == keycodes_map.end() || sc == scancodes_map.end()) {
-        return;
-    }
-
-    key_event kev{kc->second, sc->second, mod::none};
-
-    // Modifier is a mask.
-    for (const auto& pair : modifiers_map) {
-        if (ev.key.keysym.mod & pair.first) {
-            kev.modifiers |= pair.second;
-        }
-    }
-
-    if (ev.type == SDL_KEYDOWN) {
-        self.handle_key_down(kev);
-    } else {
-        self.handle_key_up(kev);
-    }
-}
-
-void window::backend_impl::handle_mouse(window& self, const SDL_Event& ev)
-{
-    assert(ev.type == SDL_MOUSEBUTTONDOWN || ev.type == SDL_MOUSEBUTTONUP);
-
-    auto which = button_map.find(ev.button.button);
-
-    if (which == button_map.end()) {
-        return;
-    }
-
-    mouse_click_event mev{
-        which->second,
-        point(ev.button.x, ev.button.y)
-    };
-
-    if (ev.type == SDL_MOUSEBUTTONDOWN) {
-        self.handle_mouse_down(mev);
-    } else {
-        self.handle_mouse_up(mev);
-    }
-}
-
-void window::backend_impl::handle_mouse_wheel(window& self, const SDL_Event& ev)
-{
-    assert(ev.type == SDL_MOUSEWHEEL);
-
-    mouse_wheel_event wev{{ev.wheel.x, ev.wheel.y}};
-
-    self.handle_mouse_wheel(wev);
-}
-
-window::backend_impl::backend_impl(window&, unsigned width, unsigned height, const std::string& title)
-    : m_window(nullptr, nullptr)
-    , m_renderer(nullptr, nullptr)
-{
-    SDL_SetMainReady();
-    SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
-
-    m_window = {
-        SDL_CreateWindow(
-            title.c_str(),
-            SDL_WINDOWPOS_UNDEFINED,
-            SDL_WINDOWPOS_UNDEFINED,
-            width, height,
-            SDL_WINDOW_OPENGL
-        ),
-        SDL_DestroyWindow
-    };
-
-    if (m_window == nullptr) {
-        throw std::runtime_error(SDL_GetError());
-    }
-
-    // Create renderer.
-    m_renderer = {
-        SDL_CreateRenderer(m_window.get(), -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
-        SDL_DestroyRenderer
-    };
-
-    if (m_renderer == nullptr) {
-        throw std::runtime_error(SDL_GetError());
-    }
-    if (TTF_Init() == -1) {
-        throw std::runtime_error(TTF_GetError());
-    }
-}
-
-void window::backend_impl::clear()
-{
-    SDL_RenderClear(m_renderer.get());
-}
-
-void window::backend_impl::present()
-{
-    SDL_RenderPresent(m_renderer.get());
-}
-
-#if 0
-
-// TODO: see later if it's really needed
-
-Size window::backend_impl::resolution()
-{
-    SDL_DisplayMode current;
-    int width = 0;
-    int height = 0;
-    for (int i = 0; i < SDL_GetNumVideoDisplays(); i++) {
-        int error = SDL_GetCurrentDisplayMode(i, &current);
-        if (error == 0) {
-            // Get the last one
-            // TODO test with only one display mode, but we have to test with more than that
-            width = current.w;
-            height = current.hpp;
-        } else {
-            throw std::runtime_error("Could not get display mode for video display" + std::string(SDL_GetError()));
-        }
-    }
-
-    return Size((unsigned)width, (unsigned)height);
-}
-
-#endif
-
-color window::backend_impl::drawing_color() const
-{
-    SDL_Color color;
-
-    if (SDL_GetRenderDrawColor(m_renderer.get(), &color.r, &color.g, &color.b, &color.a) < 0) {
-        throw std::runtime_error(SDL_GetError());
-    }
-
-    return {color.r, color.g, color.b, color.a};
-}
-
-void window::backend_impl::set_drawing_color(const color& color)
-{
-    if (SDL_SetRenderDrawColor(m_renderer.get(), color.red(), color.green(), color.blue(), color.alpha()) < 0) {
-        throw std::runtime_error(SDL_GetError());
-    }
-}
-
-void window::backend_impl::draw_line(const line& line)
-{
-    if (SDL_RenderDrawLine(m_renderer.get(), line.x1(), line.y1(), line.x2(), line.y2()) != 0) {
-        throw std::runtime_error(SDL_GetError());
-    }
-}
-
-void window::backend_impl::draw_lines(const std::vector<point>& points)
-{
-    std::vector<SDL_Point> sdlpoints(points.size());
-
-    for (unsigned i = 0; i < points.size(); ++i) {
-        sdlpoints[i] = {points[i].x(), points[i].y()};
-    }
-
-    if (SDL_RenderDrawLines(m_renderer.get(), sdlpoints.data(), sdlpoints.size()) < 0) {
-        throw std::runtime_error(SDL_GetError());
-    }
-}
-
-void window::backend_impl::draw_point(const point& point)
-{
-    if (SDL_RenderDrawPoint(m_renderer.get(), point.x(), point.y()) != 0) {
-        throw std::runtime_error(SDL_GetError());
-    }
-}
-
-void window::backend_impl::draw_points(const std::vector<point>& points)
-{
-    std::vector<SDL_Point> sdlpoints(points.size());
-
-    for (unsigned i = 0; i < points.size(); ++i) {
-        sdlpoints[i] = {points[i].x(), points[i].y()};
-    }
-
-    if (SDL_RenderDrawPoints(m_renderer.get(), sdlpoints.data(), sdlpoints.size()) != 0) {
-        throw std::runtime_error(SDL_GetError());
-    }
-}
-
-void window::backend_impl::draw_rectangle(const rectangle& rectangle)
-{
-    SDL_Rect rect{
-        rectangle.x(),
-        rectangle.y(),
-        static_cast<int>(rectangle.width()),
-        static_cast<int>(rectangle.height())
-    };
-
-    if (SDL_RenderDrawRect(m_renderer.get(), &rect) < 0) {
-        throw std::runtime_error(SDL_GetError());
-    }
-}
-
-void window::backend_impl::draw_rectangles(const std::vector<rectangle>& rectangles)
-{
-    std::vector<SDL_Rect> sdlrects(rectangles.size());
-
-    for (unsigned i = 0; i < rectangles.size(); ++i) {
-        sdlrects[i] = {
-            rectangles[i].x(),
-            rectangles[i].y(),
-            static_cast<int>(rectangles[i].width()),
-            static_cast<int>(rectangles[i].height())
-        };
-    }
-
-    if (SDL_RenderDrawRects(m_renderer.get(), sdlrects.data(), sdlrects.size()) != 0) {
-        throw std::runtime_error(SDL_GetError());
-    }
-}
-
-void window::backend_impl::fill_rectangle(const rectangle& rectangle)
-{
-    SDL_Rect rect{
-        rectangle.x(),
-        rectangle.y(),
-        static_cast<int>(rectangle.width()),
-        static_cast<int>(rectangle.height())
-    };
-
-    if (SDL_RenderFillRect(m_renderer.get(), &rect) < 0) {
-        throw std::runtime_error(SDL_GetError());
-    }
-}
-
-void window::backend_impl::fill_rectangles(const std::vector<rectangle>& rectangles)
-{
-    std::vector<SDL_Rect> sdlrects(rectangles.size());
-
-    for (unsigned i = 0; i < rectangles.size(); ++i) {
-        sdlrects[i] = {
-            rectangles[i].x(),
-            rectangles[i].y(),
-            static_cast<int>(rectangles[i].width()),
-            static_cast<int>(rectangles[i].height())
-        };
-    }
-
-    if (SDL_RenderFillRects(m_renderer.get(), sdlrects.data(), sdlrects.size()) != 0) {
-        throw std::runtime_error(SDL_GetError());
-    }
-}
-
-void window::backend_impl::draw_text(const std::string& text, font& font, const rectangle& rectangle)
-{
-    SDL_Color color = {0, 0, 0, 255};
-    SDL_Surface* message = TTF_RenderUTF8_Blended(font.backend().font(), text.c_str(), color);
-    SDL_Texture* texture = SDL_CreateTextureFromSurface(m_renderer.get(), message);
-    SDL_Rect rect = {rectangle.x(), rectangle.y(), (int)rectangle.width(), (int)rectangle.height()};
-    SDL_RenderCopy(m_renderer.get(), texture, nullptr, &rect);
-    SDL_FreeSurface(message);
-    SDL_DestroyTexture(texture);
-}
-
-void window::backend_impl::draw_text(const std::string &text, font& font, const point& point)
-{
-    SDL_Color color = {0, 0, 0, 0};
-    SDL_GetRenderDrawColor(m_renderer.get(), &color.r, &color.g, &color.b, &color.a);
-    SDL_Surface* message = TTF_RenderUTF8_Blended(font.backend().font(), text.c_str(), color);
-    SDL_Texture* texture = SDL_CreateTextureFromSurface(m_renderer.get(), message);
-    SDL_Rect rect = {point.x(), point.y(), message->w, message->h};
-    SDL_RenderCopy(m_renderer.get(), texture, nullptr, &rect);
-    SDL_FreeSurface(message);
-    SDL_DestroyTexture(texture);
-}
-
-void window::backend_impl::close()
-{
-}
-
-void window::backend_impl::poll(window& self)
-{
-    SDL_Event event;
-
-    while (SDL_PollEvent(&event)) {
-        switch (event.type) {
-        case SDL_KEYUP:
-        case SDL_KEYDOWN:
-            handle_key(self, event);
-            break;
-        case SDL_MOUSEBUTTONDOWN:
-        case SDL_MOUSEBUTTONUP:
-            handle_mouse(self, event);
-            break;
-        case SDL_MOUSEWHEEL:
-            handle_mouse_wheel(self, event);
-            break;
-        case SDL_QUIT:
-            self.handle_quit();
-            break;
-        default:
-            break;
-        }
-    }
-}
-
-} // !mlk
--- a/libclient/malikania/backend/sdl/window_backend.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/*
- * window_backend.hpp -- window object (SDL2 implementation)
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_WINDOW_BACKEND_HPP
-#define MALIKANIA_WINDOW_BACKEND_HPP
-
-#include <memory>
-#include <vector>
-
-#include <SDL.h>
-
-#include <malikania/window.hpp>
-
-namespace mlk {
-
-class window::backend_impl {
-private:
-    std::unique_ptr<SDL_Window, void (*)(SDL_Window *)> m_window;
-    std::unique_ptr<SDL_Renderer, void (*)(SDL_Renderer *)> m_renderer;
-
-    void handle_key(window&, const SDL_Event&);
-    void handle_mouse(window&, const SDL_Event&);
-    void handle_mouse_wheel(window&, const SDL_Event&);
-
-public:
-    backend_impl(window& self, unsigned width, unsigned height, const std::string& title);
-
-    inline SDL_Renderer* renderer() noexcept
-    {
-        return m_renderer.get();
-    }
-
-    void close();
-
-    void clear();
-
-    void present();
-
-    color drawing_color() const;
-
-    void set_drawing_color(const color& color);
-
-    void draw_line(const line& line);
-
-    void draw_lines(const std::vector<point>& points);
-
-    void draw_point(const point& point);
-
-    void draw_points(const std::vector<point>& points);
-
-    void draw_rectangle(const rectangle& rect);
-
-    void draw_rectangles(const std::vector<rectangle>& rects);
-
-    void fill_rectangle(const rectangle& rect);
-
-    void fill_rectangles(const std::vector<rectangle>& rects);
-
-    void draw_text(const std::string& text, font& font, const rectangle& rectangle);
-
-    void draw_text(const std::string& text, font& font, const point& point);
-
-    void poll(window &self);
-};
-
-} // !mlk
-
-#endif // !MALIKANIA_WINDOW_BACKEND_HPP
--- a/libclient/malikania/button.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * button.cpp -- GUI button element
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "button.hpp"
-#include "theme.hpp"
-#include "window.hpp"
-
-namespace mlk {
-
-button::button(std::string text)
-    : m_text(std::move(text))
-{
-}
-
-void button::handle_mouse_down(const mouse_click_event& ev)
-{
-    if (ev.button == mouse::left) {
-        on_clicked();
-    }
-}
-
-void button::draw(window& w, const rectangle& rect)
-{
-    w.theme().draw_button(w, *this, rect);
-}
-
-mlk::size button::size(window& w) const noexcept
-{
-    return w.theme().size_button(*this);
-}
-
-} // !mlk
--- a/libclient/malikania/button.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * button.hpp -- GUI button element
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_CLIENT_BUTTON_HPP
-#define MALIKANIA_CLIENT_BUTTON_HPP
-
-/**
- * \file button.hpp
- * \brief GUI button element.
- */
-
-#include <boost/signals2.hpp>
-
-#include <string>
-
-#include "widget.hpp"
-
-namespace mlk {
-
-/**
- * \brief Basic button element.
- */
-class button : public widget {
-public:
-    boost::signals2::signal<void()> on_clicked;
-    boost::signals2::signal<void()> on_released;
-
-private:
-    std::string m_text;
-
-public:
-    /**
-     * Default constructor with optional text.
-     *
-     * \param text the text
-     */
-    button(std::string text = "");
-
-    /**
-     * Get the button text.
-     *
-     * \return the text
-     */
-    inline const std::string& text() const noexcept
-    {
-        return m_text;
-    }
-
-    /**
-     * Set the button text.
-     *
-     * \param text the text
-     */
-    inline void set_text(std::string text) noexcept
-    {
-        m_text = std::move(text);
-    }
-
-    /**
-     * \copydoc widget::handle_mouse_down
-     */
-    void handle_mouse_down(const mouse_click_event& ev) override;
-
-    /**
-     * Bring back other functions.
-     */
-    using widget::draw;
-
-    /**
-     * \copydoc widget::draw
-     */
-    void draw(window& w, const rectangle& rect) override;
-
-    /**
-     * \copydoc widget::size
-     */
-    mlk::size size(window& w) const noexcept override;
-};
-
-} // !mlk
-
-#endif // !MALIKANIA_CLIENT_BUTTON_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/animation.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,157 @@
+/*
+ * animation.hpp -- animation description
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_ANIMATION_HPP
+#define MALIKANIA_ANIMATION_HPP
+
+/**
+ * \file animation.hpp
+ * \brief Describe an animation.
+ */
+
+#include <cassert>
+#include <cstdint>
+#include <memory>
+#include <vector>
+
+#include "sprite.hpp"
+
+namespace mlk {
+
+namespace client {
+
+class window;
+
+/**
+ * \brief Animation frame description.
+ *
+ * A frame is a duration before switching to the next sprite cell. It is
+ * currently implemented as a class for future usage.
+ */
+class animation_frame {
+private:
+    std::uint16_t m_delay;
+
+public:
+    /**
+     * Construct a frame.
+     *
+     * \param delay the optional delay
+     */
+    inline animation_frame(std::uint16_t delay = 100) noexcept
+        : m_delay(delay)
+    {
+    }
+
+    /**
+     * Get the the delay.
+     *
+     * \return the delay
+     */
+    inline std::uint16_t delay() const noexcept
+    {
+        return m_delay;
+    }
+};
+
+/**
+ * \brief List of frames.
+ */
+using animation_frames = std::vector<animation_frame>;
+
+/**
+ * \brief Animation description.
+ *
+ * An animation is a sprite with a set of frames containing a delay for showing
+ * all sprites in a specific amount of time.
+ *
+ * Because an animation contains an image, a state (time, current cell) it must
+ * be constructed with an animator object so the user is able to use the same
+ * animation on different parts of the screen without having to duplicate
+ * resources.
+ *
+ * \see Animator
+ */
+class animation {
+private:
+    mlk::client::sprite m_sprite;
+    mlk::client::animation_frames m_frames;
+
+public:
+    /**
+     * Create an animation.
+     *
+     * \param sprite the sprite image
+     * \param frames the frames to show
+     */
+    inline animation(mlk::client::sprite sprite, animation_frames frames) noexcept
+        : m_sprite(std::move(sprite))
+        , m_frames(std::move(frames))
+    {
+    }
+
+    /**
+     * Get the underlying sprite.
+     *
+     * \return the sprite
+     */
+    inline const mlk::client::sprite& sprite() const noexcept
+    {
+        return m_sprite;
+    }
+
+    /**
+     * Overloaded function.
+     *
+     * \return the sprite
+     */
+    inline mlk::client::sprite& sprite() noexcept
+    {
+        return m_sprite;
+    }
+
+    /**
+     * Get the frames.
+     *
+     * \return the frames
+     */
+    inline const animation_frames& frames() const noexcept
+    {
+        return m_frames;
+    }
+
+    /**
+     * Access a frame.
+     *
+     * \pre index < number of frames
+     * \param index the index
+     * \return the frame
+     */
+    inline const animation_frame& operator[](unsigned index) const noexcept
+    {
+        assert(index < m_frames.size());
+
+        return m_frames[index];
+    }
+};
+
+} // !client
+
+} // !mlk
+
+#endif // !MALIKANIA_ANIMATION_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/animator.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,56 @@
+/*
+ * animator.cpp -- animation drawing object
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "animation.hpp"
+#include "animator.hpp"
+
+namespace mlk {
+
+namespace client {
+
+animator::animator(animation& animation) noexcept
+    : m_animation(animation)
+{
+}
+
+void animator::update() noexcept
+{
+    auto total = m_animation.sprite().rows() * m_animation.sprite().columns();
+
+    if (m_current >= total) {
+        return;
+    }
+
+    if (m_timer.elapsed().wall / 1000000LL >= m_animation[m_current].delay()) {
+        m_current ++;
+        m_timer.start();
+    }
+}
+
+void animator::draw(window& window, const point& point)
+{
+    if (m_current >= m_animation.sprite().rows() * m_animation.sprite().columns()) {
+        return;
+    }
+
+    m_animation.sprite().draw(window, m_current, point);
+}
+
+} // !client
+
+} // !mlk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/animator.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,78 @@
+/*
+ * animator.hpp -- animation drawing object
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_ANIMATOR_HPP
+#define MALIKANIA_ANIMATOR_HPP
+
+#include <boost/timer/timer.hpp>
+
+/**
+ * \file animator.hpp
+ * \brief Draw animations.
+ */
+
+namespace mlk {
+
+namespace client {
+
+class animation;
+class point;
+class window;
+
+/**
+ * \brief Object for drawing animations.
+ *
+ * The animator contains an animation and a state.
+ */
+class animator {
+private:
+    boost::timer::cpu_timer m_timer;
+    animation& m_animation;
+    unsigned m_current{0};
+
+public:
+    /**
+     * Construct an animator.
+     *
+     * \pre animation must not be null
+     * \param animation the animation
+     */
+    animator(animation& animation) noexcept;
+
+    /**
+     * Update the animator state.
+     *
+     * This function should be called in the main loop to update the cell to
+     * draw before calling draw().
+     */
+    void update() noexcept;
+
+    /**
+     * Draw the animation.
+     *
+     * \param window the window
+     * \param position the position in the window
+     */
+    void draw(window& window, const point& position);
+};
+
+} // !client
+
+} // !mlk
+
+#endif // !MALIKANIA_ANIMATOR_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/backend/sdl/font_backend.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,60 @@
+/*
+ * font_backend.cpp -- font object (SDL2 implementation)
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <malikania/backend/sdl/sdl_util.hpp>
+
+#include "size.hpp"
+#include "font.hpp"
+#include "font_backend.hpp"
+
+using namespace std::string_literals;
+
+namespace mlk {
+
+namespace client {
+
+font::backend_impl::backend_impl(std::string data, unsigned size)
+    : m_font(nullptr, nullptr)
+{
+    auto rw = SDLx_RWFromBinary(std::move(data));
+
+    if (rw == nullptr) {
+        throw std::runtime_error(SDL_GetError());
+    }
+
+    m_font = {TTF_OpenFontRW(rw, true, size), TTF_CloseFont};
+
+    if (m_font == nullptr) {
+        throw std::runtime_error(TTF_GetError());
+    }
+}
+
+size font::backend_impl::clip(const mlk::client::font&, const std::string& text) const
+{
+    int width, height;
+
+    if (TTF_SizeUTF8(m_font.get(), text.c_str(), &width, &height) != 0) {
+        throw std::runtime_error(SDL_GetError());
+    }
+
+    return mlk::client::size(static_cast<unsigned>(width), static_cast<unsigned>(height));
+}
+
+} // !client
+
+} // !mlk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/backend/sdl/font_backend.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,55 @@
+/*
+ * font_backend.hpp -- font object (SDL2 implementation)
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_FONT_BACKEND_HPP
+#define MALIKANIA_FONT_BACKEND_HPP
+
+#include <memory>
+
+#include <SDL.h>
+#include <SDL_ttf.h>
+
+#include "font.hpp"
+
+namespace mlk {
+
+namespace client {
+
+class font;
+class size;
+
+class font::backend_impl {
+private:
+    std::unique_ptr<TTF_Font, void (*)(TTF_Font*)> m_font;
+
+public:
+    backend_impl(std::string data, unsigned size);
+
+    inline TTF_Font* font() noexcept
+    {
+        return m_font.get();
+    }
+
+    mlk::client::size clip(const mlk::client::font& self, const std::string& text) const;
+};
+
+} // !client
+
+} // !mlk
+
+#endif // !MALIKANIA_FONT_BACKEND_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/backend/sdl/image_backend.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,123 @@
+/*
+ * image_backend.cpp -- image object (SDL2 implementation)
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <SDL_image.h>
+
+#include <malikania/backend/sdl/sdl_util.hpp>
+
+#include "image_backend.hpp"
+#include "window_backend.hpp"
+
+using namespace std::string_literals;
+
+namespace mlk {
+
+namespace client {
+
+void image::backend_impl::create_texture(window& window)
+{
+    m_texture = {
+        SDL_CreateTextureFromSurface(window.backend().renderer(), m_surface.get()),
+        SDL_DestroyTexture
+    };
+
+    if (m_texture == nullptr) {
+        throw std::runtime_error(SDL_GetError());
+    }
+}
+
+image::backend_impl::backend_impl(image&, std::string data)
+    : m_surface(nullptr, nullptr)
+    , m_texture(nullptr, nullptr)
+{
+    auto rw = SDLx_RWFromBinary(std::move(data));
+
+    if (rw == nullptr) {
+        throw std::runtime_error(SDL_GetError());
+    }
+
+    m_surface = {IMG_Load_RW(rw, true), SDL_FreeSurface};
+
+    if (!m_surface) {
+        throw std::runtime_error(SDL_GetError());
+    }
+
+    m_size = mlk::client::size(
+        static_cast<unsigned>(m_surface->w),
+        static_cast<unsigned>(m_surface->h)
+    );
+}
+
+void image::backend_impl::draw(window& window, const point& point)
+{
+    /*
+     * Create texture at this step so the image constructor does not need the
+     * window.
+     */
+    if (!m_texture) {
+        create_texture(window);
+    }
+
+    SDL_Rect target;
+
+    target.x = static_cast<int>(point.x());
+    target.y = static_cast<int>(point.y());
+    target.w = static_cast<int>(m_size.width());
+    target.h = static_cast<int>(m_size.height());
+
+    if (SDL_RenderCopy(window.backend().renderer(), m_texture.get(), nullptr, &target) < 0) {
+        throw std::runtime_error(SDL_GetError());
+    }
+}
+
+void image::backend_impl::draw(window& window, const rectangle& source, const rectangle& target)
+{
+    if (!m_texture) {
+        create_texture(window);
+    }
+
+    SDL_Rect sr, st;
+
+    sr.x = source.x();
+    sr.y = source.y();
+    sr.w = static_cast<int>(source.width());
+    sr.h = static_cast<int>(source.height());
+
+    st.x = target.x();
+    st.y = target.y();
+    st.w = static_cast<int>(target.width());
+    st.h = static_cast<int>(target.height());
+
+    // Readjust .w, .h if null.
+    if (source.is_null()) {
+        sr.w = static_cast<int>(m_size.width());
+        sr.h = static_cast<int>(m_size.height());
+    }
+    if (target.is_null()) {
+        st.w = static_cast<int>(m_size.width());
+        st.h = static_cast<int>(m_size.height());
+    }
+
+    if (SDL_RenderCopy(window.backend().renderer(), m_texture.get(), &sr, &st) < 0) {
+        throw std::runtime_error(SDL_GetError());
+    }
+}
+
+} // !client
+
+} // !mlk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/backend/sdl/image_backend.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,69 @@
+/*
+ * image_backend.hpp -- image object (SDL2 implementation)
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_IMAGE_BACKEND_HPP
+#define MALIKANIA_IMAGE_BACKEND_HPP
+
+#include <memory>
+
+#include <SDL.h>
+
+#include "size.hpp"
+#include "image.hpp"
+
+namespace mlk {
+
+namespace client {
+
+class image;
+class point;
+class rectangle;
+class window;
+
+class image::backend_impl {
+private:
+    std::unique_ptr<SDL_Surface, void (*)(SDL_Surface *)> m_surface;
+    std::unique_ptr<SDL_Texture, void (*)(SDL_Texture *)> m_texture;
+
+    mlk::client::size m_size;
+
+    void create_texture(window& window);
+
+public:
+    backend_impl(image& self, std::string data);
+
+    inline SDL_Texture* texture() noexcept
+    {
+        return m_texture.get();
+    }
+
+    inline const mlk::client::size& size() const noexcept
+    {
+        return m_size;
+    }
+
+    void draw(window& window, const point& position);
+
+    void draw(window& window, const rectangle& source, const rectangle& target);
+};
+
+} // !client
+
+} // !mlk
+
+#endif // !MALIKANIA_IMAGE_BACKEND_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/backend/sdl/window_backend.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,643 @@
+/*
+ * window_backend.cpp -- window object (SDL2 implementation)
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <cassert>
+#include <stdexcept>
+#include <unordered_map>
+
+#include <SDL.h>
+#include <SDL_ttf.h>
+
+#include "color.hpp"
+#include "font_backend.hpp"
+#include "key.hpp"
+#include "line.hpp"
+#include "point.hpp"
+#include "rectangle.hpp"
+#include "window_backend.hpp"
+#include "window.hpp"
+
+namespace mlk {
+
+namespace client {
+
+namespace {
+
+/*
+ * conversion maps
+ * ------------------------------------------------------------------
+ *
+ * There is a difference between scancode and key codes. The scancode is the
+ * key located on the keyboard which is always the same, the key code is the
+ * translated to the user layout.
+ *
+ * For example, on azerty, hitting the 'a' key makes a key code of 'a' but a
+ * scancode of 'q'.
+ *
+ *   - scancodes_map        : convert SDL scancode do key
+ *   - keycodes_map         : convert SDL key code to key
+ *   - modifiers_map        : convert masks
+ *   - button_map           : convert SDL mouse buttons
+ */
+
+const std::unordered_map<SDL_Keycode, key> scancodes_map{
+    { SDL_SCANCODE_A,               key::a                      },
+    { SDL_SCANCODE_B,               key::b                      },
+    { SDL_SCANCODE_C,               key::c                      },
+    { SDL_SCANCODE_D,               key::d                      },
+    { SDL_SCANCODE_E,               key::e                      },
+    { SDL_SCANCODE_F,               key::f                      },
+    { SDL_SCANCODE_G,               key::g                      },
+    { SDL_SCANCODE_H,               key::h                      },
+    { SDL_SCANCODE_I,               key::i                      },
+    { SDL_SCANCODE_J,               key::j                      },
+    { SDL_SCANCODE_K,               key::k                      },
+    { SDL_SCANCODE_L,               key::l                      },
+    { SDL_SCANCODE_M,               key::m                      },
+    { SDL_SCANCODE_N,               key::n                      },
+    { SDL_SCANCODE_O,               key::o                      },
+    { SDL_SCANCODE_P,               key::p                      },
+    { SDL_SCANCODE_Q,               key::q                      },
+    { SDL_SCANCODE_R,               key::r                      },
+    { SDL_SCANCODE_S,               key::s                      },
+    { SDL_SCANCODE_T,               key::t                      },
+    { SDL_SCANCODE_U,               key::u                      },
+    { SDL_SCANCODE_V,               key::v                      },
+    { SDL_SCANCODE_W,               key::w                      },
+    { SDL_SCANCODE_X,               key::x                      },
+    { SDL_SCANCODE_Y,               key::y                      },
+    { SDL_SCANCODE_Z,               key::z                      },
+    { SDL_SCANCODE_1,               key::one                    },
+    { SDL_SCANCODE_2,               key::two                    },
+    { SDL_SCANCODE_3,               key::three                  },
+    { SDL_SCANCODE_4,               key::four                   },
+    { SDL_SCANCODE_5,               key::five                   },
+    { SDL_SCANCODE_6,               key::six                    },
+    { SDL_SCANCODE_7,               key::seven                  },
+    { SDL_SCANCODE_8,               key::eight                  },
+    { SDL_SCANCODE_9,               key::nine                   },
+    { SDL_SCANCODE_0,               key::zero                   },
+    { SDL_SCANCODE_RETURN,          key::enter                  },
+    { SDL_SCANCODE_ESCAPE,          key::escape                 },
+    { SDL_SCANCODE_BACKSPACE,       key::backspace              },
+    { SDL_SCANCODE_TAB,             key::tab                    },
+    { SDL_SCANCODE_SPACE,           key::space                  },
+    { SDL_SCANCODE_MINUS,           key::minus                  },
+    { SDL_SCANCODE_EQUALS,          key::equals                 },
+    { SDL_SCANCODE_LEFTBRACKET,     key::left_bracket           },
+    { SDL_SCANCODE_RIGHTBRACKET,    key::right_bracket          },
+    { SDL_SCANCODE_BACKSLASH,       key::backslash              },
+    { SDL_SCANCODE_NONUSHASH,       key::hash                   },
+    { SDL_SCANCODE_SEMICOLON,       key::semicolon              },
+    { SDL_SCANCODE_APOSTROPHE,      key::apostrophe             },
+    { SDL_SCANCODE_GRAVE,           key::grave                  },
+    { SDL_SCANCODE_COMMA,           key::comma                  },
+    { SDL_SCANCODE_PERIOD,          key::period                 },
+    { SDL_SCANCODE_SLASH,           key::slash                  },
+    { SDL_SCANCODE_CAPSLOCK,        key::caps_lock              },
+    { SDL_SCANCODE_F1,              key::f1                     },
+    { SDL_SCANCODE_F2,              key::f2                     },
+    { SDL_SCANCODE_F3,              key::f3                     },
+    { SDL_SCANCODE_F4,              key::f4                     },
+    { SDL_SCANCODE_F5,              key::f5                     },
+    { SDL_SCANCODE_F6,              key::f6                     },
+    { SDL_SCANCODE_F7,              key::f7                     },
+    { SDL_SCANCODE_F8,              key::f8                     },
+    { SDL_SCANCODE_F9,              key::f9                     },
+    { SDL_SCANCODE_F10,             key::f10                    },
+    { SDL_SCANCODE_F11,             key::f11                    },
+    { SDL_SCANCODE_F12,             key::f12                    },
+    { SDL_SCANCODE_F13,             key::f13                    },
+    { SDL_SCANCODE_F14,             key::f14                    },
+    { SDL_SCANCODE_F15,             key::f15                    },
+    { SDL_SCANCODE_F16,             key::f16                    },
+    { SDL_SCANCODE_F17,             key::f17                    },
+    { SDL_SCANCODE_F18,             key::f18                    },
+    { SDL_SCANCODE_F19,             key::f19                    },
+    { SDL_SCANCODE_F20,             key::f20                    },
+    { SDL_SCANCODE_F21,             key::f21                    },
+    { SDL_SCANCODE_F22,             key::f22                    },
+    { SDL_SCANCODE_F23,             key::f23                    },
+    { SDL_SCANCODE_F24,             key::f24                    },
+    { SDL_SCANCODE_PRINTSCREEN,     key::print_screen           },
+    { SDL_SCANCODE_SCROLLLOCK,      key::scroll_lock            },
+    { SDL_SCANCODE_PAUSE,           key::pause                  },
+    { SDL_SCANCODE_INSERT,          key::insert                 },
+    { SDL_SCANCODE_HOME,            key::home                   },
+    { SDL_SCANCODE_PAGEUP,          key::page_up                },
+    { SDL_SCANCODE_PAGEDOWN,        key::page_down              },
+    { SDL_SCANCODE_DELETE,          key::del                    },
+    { SDL_SCANCODE_END,             key::end                    },
+    { SDL_SCANCODE_RIGHT,           key::right                  },
+    { SDL_SCANCODE_LEFT,            key::left                   },
+    { SDL_SCANCODE_DOWN,            key::down                   },
+    { SDL_SCANCODE_UP,              key::up                     },
+    { SDL_SCANCODE_KP_DIVIDE,       key::kp_divide              },
+    { SDL_SCANCODE_KP_MULTIPLY,     key::kp_multiply            },
+    { SDL_SCANCODE_KP_MINUS,        key::kp_minus               },
+    { SDL_SCANCODE_KP_PLUS,         key::kp_plus                },
+    { SDL_SCANCODE_KP_ENTER,        key::kp_enter               },
+    { SDL_SCANCODE_KP_1,            key::kp_one                 },
+    { SDL_SCANCODE_KP_2,            key::kp_two                 },
+    { SDL_SCANCODE_KP_3,            key::kp_three               },
+    { SDL_SCANCODE_KP_4,            key::kp_four                },
+    { SDL_SCANCODE_KP_5,            key::kp_five                },
+    { SDL_SCANCODE_KP_6,            key::kp_six                 },
+    { SDL_SCANCODE_KP_7,            key::kp_seven               },
+    { SDL_SCANCODE_KP_8,            key::kp_eight               },
+    { SDL_SCANCODE_KP_9,            key::kp_nine                },
+    { SDL_SCANCODE_KP_0,            key::kp_zero                },
+    { SDL_SCANCODE_MUTE,            key::mute                   },
+    { SDL_SCANCODE_VOLUMEUP,        key::volume_up              },
+    { SDL_SCANCODE_VOLUMEDOWN,      key::volume_down            },
+    { SDL_SCANCODE_LCTRL,           key::left_control           },
+    { SDL_SCANCODE_LALT,            key::left_alt               },
+    { SDL_SCANCODE_LSHIFT,          key::left_shift             },
+    { SDL_SCANCODE_LGUI,            key::left_super             },
+    { SDL_SCANCODE_RCTRL,           key::right_control          },
+    { SDL_SCANCODE_RALT,            key::right_alt              },
+    { SDL_SCANCODE_RSHIFT,          key::right_shift            },
+    { SDL_SCANCODE_RGUI,            key::right_super            }
+};
+
+const std::unordered_map<SDL_Keycode, key> keycodes_map{
+    { SDLK_RETURN,                  key::enter                  },
+    { SDLK_ESCAPE,                  key::escape                 },
+    { SDLK_BACKSPACE,               key::backspace              },
+    { SDLK_TAB,                     key::tab                    },
+    { SDLK_SPACE,                   key::space                  },
+    { SDLK_EXCLAIM,                 key::exclaim                },
+    { SDLK_QUOTEDBL,                key::double_quote           },
+    { SDLK_HASH,                    key::hash                   },
+    { SDLK_PERCENT,                 key::percent                },
+    { SDLK_DOLLAR,                  key::dollar                 },
+    { SDLK_AMPERSAND,               key::ampersand              },
+    { SDLK_QUOTE,                   key::quote                  },
+    { SDLK_LEFTPAREN,               key::left_parenthese        },
+    { SDLK_RIGHTPAREN,              key::right_parenthese       },
+    { SDLK_ASTERISK,                key::asterisk               },
+    { SDLK_PLUS,                    key::plus                   },
+    { SDLK_COMMA,                   key::comma                  },
+    { SDLK_MINUS,                   key::minus                  },
+    { SDLK_PERIOD,                  key::period                 },
+    { SDLK_SLASH,                   key::slash                  },
+    { SDLK_0,                       key::zero                   },
+    { SDLK_1,                       key::one                    },
+    { SDLK_2,                       key::two                    },
+    { SDLK_3,                       key::three                  },
+    { SDLK_4,                       key::four                   },
+    { SDLK_5,                       key::five                   },
+    { SDLK_6,                       key::six                    },
+    { SDLK_7,                       key::seven                  },
+    { SDLK_8,                       key::eight                  },
+    { SDLK_9,                       key::nine                   },
+    { SDLK_COLON,                   key::colon                  },
+    { SDLK_SEMICOLON,               key::semicolon              },
+    { SDLK_LESS,                    key::less                   },
+    { SDLK_EQUALS,                  key::equals                 },
+    { SDLK_GREATER,                 key::greater                },
+    { SDLK_QUESTION,                key::question               },
+    { SDLK_AT,                      key::at                     },
+    { SDLK_LEFTBRACKET,             key::left_bracket           },
+    { SDLK_BACKSLASH,               key::backslash              },
+    { SDLK_RIGHTBRACKET,            key::right_bracket          },
+    { SDLK_CARET,                   key::caret                  },
+    { SDLK_UNDERSCORE,              key::underscore             },
+    { SDLK_BACKQUOTE,               key::back_quote             },
+    { SDLK_a,                       key::a                      },
+    { SDLK_b,                       key::b                      },
+    { SDLK_c,                       key::c                      },
+    { SDLK_d,                       key::d                      },
+    { SDLK_e,                       key::e                      },
+    { SDLK_f,                       key::f                      },
+    { SDLK_g,                       key::g                      },
+    { SDLK_h,                       key::h                      },
+    { SDLK_i,                       key::i                      },
+    { SDLK_j,                       key::j                      },
+    { SDLK_k,                       key::k                      },
+    { SDLK_l,                       key::l                      },
+    { SDLK_m,                       key::m                      },
+    { SDLK_n,                       key::n                      },
+    { SDLK_o,                       key::o                      },
+    { SDLK_p,                       key::p                      },
+    { SDLK_q,                       key::q                      },
+    { SDLK_r,                       key::r                      },
+    { SDLK_s,                       key::s                      },
+    { SDLK_t,                       key::t                      },
+    { SDLK_u,                       key::u                      },
+    { SDLK_v,                       key::v                      },
+    { SDLK_w,                       key::w                      },
+    { SDLK_x,                       key::x                      },
+    { SDLK_y,                       key::y                      },
+    { SDLK_z,                       key::z                      },
+    { SDLK_CAPSLOCK,                key::caps_lock              },
+    { SDLK_F1,                      key::f1                     },
+    { SDLK_F2,                      key::f2                     },
+    { SDLK_F3,                      key::f3                     },
+    { SDLK_F4,                      key::f4                     },
+    { SDLK_F5,                      key::f5                     },
+    { SDLK_F6,                      key::f6                     },
+    { SDLK_F7,                      key::f7                     },
+    { SDLK_F8,                      key::f8                     },
+    { SDLK_F9,                      key::f9                     },
+    { SDLK_F10,                     key::f10                    },
+    { SDLK_F11,                     key::f11                    },
+    { SDLK_F12,                     key::f12                    },
+    { SDLK_F13,                     key::f13                    },
+    { SDLK_F14,                     key::f14                    },
+    { SDLK_F15,                     key::f15                    },
+    { SDLK_F16,                     key::f16                    },
+    { SDLK_F17,                     key::f17                    },
+    { SDLK_F18,                     key::f18                    },
+    { SDLK_F19,                     key::f19                    },
+    { SDLK_F20,                     key::f20                    },
+    { SDLK_F21,                     key::f21                    },
+    { SDLK_F22,                     key::f22                    },
+    { SDLK_F23,                     key::f23                    },
+    { SDLK_F24,                     key::f24                    },
+    { SDLK_PRINTSCREEN,             key::print_screen           },
+    { SDLK_SCROLLLOCK,              key::scroll_lock            },
+    { SDLK_PAUSE,                   key::pause                  },
+    { SDLK_INSERT,                  key::insert                 },
+    { SDLK_HOME,                    key::home                   },
+    { SDLK_PAGEUP,                  key::page_up                },
+    { SDLK_PAGEDOWN,                key::page_down              },
+    { SDLK_DELETE,                  key::del                    },
+    { SDLK_END,                     key::end                    },
+    { SDLK_RIGHT,                   key::right                  },
+    { SDLK_LEFT,                    key::left                   },
+    { SDLK_DOWN,                    key::down                   },
+    { SDLK_UP,                      key::up                     },
+    { SDLK_KP_DIVIDE,               key::kp_divide              },
+    { SDLK_KP_MULTIPLY,             key::kp_multiply            },
+    { SDLK_KP_MINUS,                key::kp_minus               },
+    { SDLK_KP_PLUS,                 key::kp_plus                },
+    { SDLK_KP_ENTER,                key::kp_enter               },
+    { SDLK_KP_1,                    key::kp_one                 },
+    { SDLK_KP_2,                    key::kp_two                 },
+    { SDLK_KP_3,                    key::kp_three               },
+    { SDLK_KP_4,                    key::kp_four                },
+    { SDLK_KP_5,                    key::kp_five                },
+    { SDLK_KP_6,                    key::kp_six                 },
+    { SDLK_KP_7,                    key::kp_seven               },
+    { SDLK_KP_8,                    key::kp_eight               },
+    { SDLK_KP_9,                    key::kp_nine                },
+    { SDLK_KP_0,                    key::kp_zero                },
+    { SDLK_MUTE,                    key::mute                   },
+    { SDLK_VOLUMEUP,                key::volume_up              },
+    { SDLK_VOLUMEDOWN,              key::volume_down            },
+    { SDLK_LCTRL,                   key::left_control           },
+    { SDLK_LALT,                    key::left_alt               },
+    { SDLK_LSHIFT,                  key::left_shift             },
+    { SDLK_LGUI,                    key::left_super             },
+    { SDLK_RCTRL,                   key::right_control          },
+    { SDLK_RALT,                    key::right_alt              },
+    { SDLK_RSHIFT,                  key::right_shift            },
+    { SDLK_RGUI,                    key::right_super            }
+};
+
+const std::unordered_map<SDL_Keymod, mod> modifiers_map{
+    { KMOD_LCTRL,                   mod::left_control           },
+    { KMOD_LALT,                    mod::left_alt               },
+    { KMOD_LSHIFT,                  mod::left_shift             },
+    { KMOD_LGUI,                    mod::left_super             },
+    { KMOD_RCTRL,                   mod::right_control          },
+    { KMOD_RALT,                    mod::right_alt              },
+    { KMOD_RSHIFT,                  mod::right_shift            },
+    { KMOD_RGUI,                    mod::right_super            },
+    { KMOD_NUM,                     mod::num_lock               },
+    { KMOD_CAPS,                    mod::caps_lock              }
+};
+
+const std::unordered_map<Uint32, mouse> button_map{
+    { SDL_BUTTON_LEFT,      mouse::left     },
+    { SDL_BUTTON_RIGHT,     mouse::right    },
+    { SDL_BUTTON_MIDDLE,    mouse::middle   }
+};
+
+} // !namespace
+
+void window::backend_impl::handle_key(window& self, const SDL_Event& ev)
+{
+    assert(ev.type == SDL_KEYDOWN || ev.type == SDL_KEYUP);
+
+    // Key and scan code.
+    auto kc = keycodes_map.find(ev.key.keysym.sym);
+    auto sc = scancodes_map.find(ev.key.keysym.scancode);
+
+    if (kc == keycodes_map.end() || sc == scancodes_map.end()) {
+        return;
+    }
+
+    key_event kev{kc->second, sc->second, mod::none};
+
+    // Modifier is a mask.
+    for (const auto& pair : modifiers_map) {
+        if (ev.key.keysym.mod & pair.first) {
+            kev.modifiers |= pair.second;
+        }
+    }
+
+    if (ev.type == SDL_KEYDOWN) {
+        self.handle_key_down(kev);
+    } else {
+        self.handle_key_up(kev);
+    }
+}
+
+void window::backend_impl::handle_mouse(window& self, const SDL_Event& ev)
+{
+    assert(ev.type == SDL_MOUSEBUTTONDOWN || ev.type == SDL_MOUSEBUTTONUP);
+
+    auto which = button_map.find(ev.button.button);
+
+    if (which == button_map.end()) {
+        return;
+    }
+
+    mouse_click_event mev{
+        which->second,
+        point(ev.button.x, ev.button.y)
+    };
+
+    if (ev.type == SDL_MOUSEBUTTONDOWN) {
+        self.handle_mouse_down(mev);
+    } else {
+        self.handle_mouse_up(mev);
+    }
+}
+
+void window::backend_impl::handle_mouse_wheel(window& self, const SDL_Event& ev)
+{
+    assert(ev.type == SDL_MOUSEWHEEL);
+
+    mouse_wheel_event wev{{ev.wheel.x, ev.wheel.y}};
+
+    self.handle_mouse_wheel(wev);
+}
+
+window::backend_impl::backend_impl(window&, unsigned width, unsigned height, const std::string& title)
+    : m_window(nullptr, nullptr)
+    , m_renderer(nullptr, nullptr)
+{
+    SDL_SetMainReady();
+    SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO);
+
+    m_window = {
+        SDL_CreateWindow(
+            title.c_str(),
+            SDL_WINDOWPOS_UNDEFINED,
+            SDL_WINDOWPOS_UNDEFINED,
+            width, height,
+            SDL_WINDOW_OPENGL
+        ),
+        SDL_DestroyWindow
+    };
+
+    if (m_window == nullptr) {
+        throw std::runtime_error(SDL_GetError());
+    }
+
+    // Create renderer.
+    m_renderer = {
+        SDL_CreateRenderer(m_window.get(), -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC),
+        SDL_DestroyRenderer
+    };
+
+    if (m_renderer == nullptr) {
+        throw std::runtime_error(SDL_GetError());
+    }
+    if (TTF_Init() == -1) {
+        throw std::runtime_error(TTF_GetError());
+    }
+}
+
+void window::backend_impl::clear()
+{
+    SDL_RenderClear(m_renderer.get());
+}
+
+void window::backend_impl::present()
+{
+    SDL_RenderPresent(m_renderer.get());
+}
+
+#if 0
+
+// TODO: see later if it's really needed
+
+Size window::backend_impl::resolution()
+{
+    SDL_DisplayMode current;
+    int width = 0;
+    int height = 0;
+    for (int i = 0; i < SDL_GetNumVideoDisplays(); i++) {
+        int error = SDL_GetCurrentDisplayMode(i, &current);
+        if (error == 0) {
+            // Get the last one
+            // TODO test with only one display mode, but we have to test with more than that
+            width = current.w;
+            height = current.hpp;
+        } else {
+            throw std::runtime_error("Could not get display mode for video display" + std::string(SDL_GetError()));
+        }
+    }
+
+    return Size((unsigned)width, (unsigned)height);
+}
+
+#endif
+
+color window::backend_impl::drawing_color() const
+{
+    SDL_Color color;
+
+    if (SDL_GetRenderDrawColor(m_renderer.get(), &color.r, &color.g, &color.b, &color.a) < 0) {
+        throw std::runtime_error(SDL_GetError());
+    }
+
+    return {color.r, color.g, color.b, color.a};
+}
+
+void window::backend_impl::set_drawing_color(const color& color)
+{
+    if (SDL_SetRenderDrawColor(m_renderer.get(), color.red(), color.green(), color.blue(), color.alpha()) < 0) {
+        throw std::runtime_error(SDL_GetError());
+    }
+}
+
+void window::backend_impl::draw_line(const line& line)
+{
+    if (SDL_RenderDrawLine(m_renderer.get(), line.x1(), line.y1(), line.x2(), line.y2()) != 0) {
+        throw std::runtime_error(SDL_GetError());
+    }
+}
+
+void window::backend_impl::draw_lines(const std::vector<point>& points)
+{
+    std::vector<SDL_Point> sdlpoints(points.size());
+
+    for (unsigned i = 0; i < points.size(); ++i) {
+        sdlpoints[i] = {points[i].x(), points[i].y()};
+    }
+
+    if (SDL_RenderDrawLines(m_renderer.get(), sdlpoints.data(), sdlpoints.size()) < 0) {
+        throw std::runtime_error(SDL_GetError());
+    }
+}
+
+void window::backend_impl::draw_point(const point& point)
+{
+    if (SDL_RenderDrawPoint(m_renderer.get(), point.x(), point.y()) != 0) {
+        throw std::runtime_error(SDL_GetError());
+    }
+}
+
+void window::backend_impl::draw_points(const std::vector<point>& points)
+{
+    std::vector<SDL_Point> sdlpoints(points.size());
+
+    for (unsigned i = 0; i < points.size(); ++i) {
+        sdlpoints[i] = {points[i].x(), points[i].y()};
+    }
+
+    if (SDL_RenderDrawPoints(m_renderer.get(), sdlpoints.data(), sdlpoints.size()) != 0) {
+        throw std::runtime_error(SDL_GetError());
+    }
+}
+
+void window::backend_impl::draw_rectangle(const rectangle& rectangle)
+{
+    SDL_Rect rect{
+        rectangle.x(),
+        rectangle.y(),
+        static_cast<int>(rectangle.width()),
+        static_cast<int>(rectangle.height())
+    };
+
+    if (SDL_RenderDrawRect(m_renderer.get(), &rect) < 0) {
+        throw std::runtime_error(SDL_GetError());
+    }
+}
+
+void window::backend_impl::draw_rectangles(const std::vector<rectangle>& rectangles)
+{
+    std::vector<SDL_Rect> sdlrects(rectangles.size());
+
+    for (unsigned i = 0; i < rectangles.size(); ++i) {
+        sdlrects[i] = {
+            rectangles[i].x(),
+            rectangles[i].y(),
+            static_cast<int>(rectangles[i].width()),
+            static_cast<int>(rectangles[i].height())
+        };
+    }
+
+    if (SDL_RenderDrawRects(m_renderer.get(), sdlrects.data(), sdlrects.size()) != 0) {
+        throw std::runtime_error(SDL_GetError());
+    }
+}
+
+void window::backend_impl::fill_rectangle(const rectangle& rectangle)
+{
+    SDL_Rect rect{
+        rectangle.x(),
+        rectangle.y(),
+        static_cast<int>(rectangle.width()),
+        static_cast<int>(rectangle.height())
+    };
+
+    if (SDL_RenderFillRect(m_renderer.get(), &rect) < 0) {
+        throw std::runtime_error(SDL_GetError());
+    }
+}
+
+void window::backend_impl::fill_rectangles(const std::vector<rectangle>& rectangles)
+{
+    std::vector<SDL_Rect> sdlrects(rectangles.size());
+
+    for (unsigned i = 0; i < rectangles.size(); ++i) {
+        sdlrects[i] = {
+            rectangles[i].x(),
+            rectangles[i].y(),
+            static_cast<int>(rectangles[i].width()),
+            static_cast<int>(rectangles[i].height())
+        };
+    }
+
+    if (SDL_RenderFillRects(m_renderer.get(), sdlrects.data(), sdlrects.size()) != 0) {
+        throw std::runtime_error(SDL_GetError());
+    }
+}
+
+void window::backend_impl::draw_text(const std::string& text, font& font, const rectangle& rectangle)
+{
+    SDL_Color color = {0, 0, 0, 255};
+    SDL_Surface* message = TTF_RenderUTF8_Blended(font.backend().font(), text.c_str(), color);
+    SDL_Texture* texture = SDL_CreateTextureFromSurface(m_renderer.get(), message);
+    SDL_Rect rect = {rectangle.x(), rectangle.y(), (int)rectangle.width(), (int)rectangle.height()};
+    SDL_RenderCopy(m_renderer.get(), texture, nullptr, &rect);
+    SDL_FreeSurface(message);
+    SDL_DestroyTexture(texture);
+}
+
+void window::backend_impl::draw_text(const std::string &text, font& font, const point& point)
+{
+    SDL_Color color = {0, 0, 0, 0};
+    SDL_GetRenderDrawColor(m_renderer.get(), &color.r, &color.g, &color.b, &color.a);
+    SDL_Surface* message = TTF_RenderUTF8_Blended(font.backend().font(), text.c_str(), color);
+    SDL_Texture* texture = SDL_CreateTextureFromSurface(m_renderer.get(), message);
+    SDL_Rect rect = {point.x(), point.y(), message->w, message->h};
+    SDL_RenderCopy(m_renderer.get(), texture, nullptr, &rect);
+    SDL_FreeSurface(message);
+    SDL_DestroyTexture(texture);
+}
+
+void window::backend_impl::close()
+{
+}
+
+void window::backend_impl::poll(window& self)
+{
+    SDL_Event event;
+
+    while (SDL_PollEvent(&event)) {
+        switch (event.type) {
+        case SDL_KEYUP:
+        case SDL_KEYDOWN:
+            handle_key(self, event);
+            break;
+        case SDL_MOUSEBUTTONDOWN:
+        case SDL_MOUSEBUTTONUP:
+            handle_mouse(self, event);
+            break;
+        case SDL_MOUSEWHEEL:
+            handle_mouse_wheel(self, event);
+            break;
+        case SDL_QUIT:
+            self.handle_quit();
+            break;
+        default:
+            break;
+        }
+    }
+}
+
+} // !client
+
+} // !mlk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/backend/sdl/window_backend.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,87 @@
+/*
+ * window_backend.hpp -- window object (SDL2 implementation)
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_WINDOW_BACKEND_HPP
+#define MALIKANIA_WINDOW_BACKEND_HPP
+
+#include <memory>
+#include <vector>
+
+#include <SDL.h>
+
+#include "window.hpp"
+
+namespace mlk {
+
+namespace client {
+
+class window::backend_impl {
+private:
+    std::unique_ptr<SDL_Window, void (*)(SDL_Window *)> m_window;
+    std::unique_ptr<SDL_Renderer, void (*)(SDL_Renderer *)> m_renderer;
+
+    void handle_key(window&, const SDL_Event&);
+    void handle_mouse(window&, const SDL_Event&);
+    void handle_mouse_wheel(window&, const SDL_Event&);
+
+public:
+    backend_impl(window& self, unsigned width, unsigned height, const std::string& title);
+
+    inline SDL_Renderer* renderer() noexcept
+    {
+        return m_renderer.get();
+    }
+
+    void close();
+
+    void clear();
+
+    void present();
+
+    color drawing_color() const;
+
+    void set_drawing_color(const color& color);
+
+    void draw_line(const line& line);
+
+    void draw_lines(const std::vector<point>& points);
+
+    void draw_point(const point& point);
+
+    void draw_points(const std::vector<point>& points);
+
+    void draw_rectangle(const rectangle& rect);
+
+    void draw_rectangles(const std::vector<rectangle>& rects);
+
+    void fill_rectangle(const rectangle& rect);
+
+    void fill_rectangles(const std::vector<rectangle>& rects);
+
+    void draw_text(const std::string& text, font& font, const rectangle& rectangle);
+
+    void draw_text(const std::string& text, font& font, const point& point);
+
+    void poll(window &self);
+};
+
+} // !client
+
+} // !mlk
+
+#endif // !MALIKANIA_WINDOW_BACKEND_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/button.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,51 @@
+/*
+ * button.cpp -- GUI button element
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "button.hpp"
+#include "theme.hpp"
+#include "window.hpp"
+
+namespace mlk {
+
+namespace client {
+
+button::button(std::string text)
+    : m_text(std::move(text))
+{
+}
+
+void button::handle_mouse_down(const mouse_click_event& ev)
+{
+    if (ev.button == mouse::left) {
+        on_clicked();
+    }
+}
+
+void button::draw(window& w, const rectangle& rect)
+{
+    w.theme().draw_button(w, *this, rect);
+}
+
+mlk::client::size button::size(window& w) const noexcept
+{
+    return w.theme().size_button(*this);
+}
+
+} // !client
+
+} // !mlk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/button.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,101 @@
+/*
+ * button.hpp -- GUI button element
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_CLIENT_BUTTON_HPP
+#define MALIKANIA_CLIENT_BUTTON_HPP
+
+/**
+ * \file button.hpp
+ * \brief GUI button element.
+ */
+
+#include <boost/signals2.hpp>
+
+#include <string>
+
+#include "widget.hpp"
+
+namespace mlk {
+
+namespace client {
+
+/**
+ * \brief Basic button element.
+ */
+class button : public widget {
+public:
+    boost::signals2::signal<void()> on_clicked;
+    boost::signals2::signal<void()> on_released;
+
+private:
+    std::string m_text;
+
+public:
+    /**
+     * Default constructor with optional text.
+     *
+     * \param text the text
+     */
+    button(std::string text = "");
+
+    /**
+     * Get the button text.
+     *
+     * \return the text
+     */
+    inline const std::string& text() const noexcept
+    {
+        return m_text;
+    }
+
+    /**
+     * Set the button text.
+     *
+     * \param text the text
+     */
+    inline void set_text(std::string text) noexcept
+    {
+        m_text = std::move(text);
+    }
+
+    /**
+     * \copydoc widget::handle_mouse_down
+     */
+    void handle_mouse_down(const mouse_click_event& ev) override;
+
+    /**
+     * Bring back other functions.
+     */
+    using widget::draw;
+
+    /**
+     * \copydoc widget::draw
+     */
+    void draw(window& w, const rectangle& rect) override;
+
+    /**
+     * \copydoc widget::size
+     */
+    mlk::client::size size(window& w) const noexcept override;
+};
+
+} // !client
+
+} // !mlk
+
+#endif // !MALIKANIA_CLIENT_BUTTON_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/color.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,241 @@
+/*
+ * color.cpp -- color description
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <cctype>
+#include <locale>
+#include <unordered_map>
+
+#include "color.hpp"
+
+namespace mlk {
+
+namespace client {
+
+namespace {
+
+constexpr unsigned rgb(std::uint8_t r, std::uint8_t g, std::uint8_t b) noexcept
+{
+    return (0xff000000 | (r << 16) | (g << 8) | b);
+}
+
+/*
+ * Convert hexadecimal value to the correct number.
+ */
+std::uint8_t value(char digit)
+{
+    if (std::isdigit(digit, {})) {
+        return digit - '0';
+    }
+    if ((digit = std::toupper(digit, {})) < 'A' || digit > 'F') {
+        throw std::invalid_argument("invalid hexadecimal value: " + std::to_string(digit));
+    }
+
+    return digit - 55;
+}
+
+inline std::uint8_t value(char digit1, char digit2)
+{
+    return ((value(digit1) << 4) & 0xf0) | value(digit2);
+}
+
+const std::unordered_map<std::string, std::uint32_t> colors{
+    { "aliceblue",              rgb(240, 248, 255)  },
+    { "antiquewhite",           rgb(250, 235, 215)  },
+    { "aqua",                   rgb( 0, 255, 255)   },
+    { "aquamarine",             rgb(127, 255, 212)  },
+    { "azure",                  rgb(240, 255, 255)  },
+    { "beige",                  rgb(245, 245, 220)  },
+    { "bisque",                 rgb(255, 228, 196)  },
+    { "black",                  rgb( 0, 0, 0)       },
+    { "blanchedalmond",         rgb(255, 235, 205)  },
+    { "blue",                   rgb( 0, 0, 255)     },
+    { "blueviolet",             rgb(138, 43, 226)   },
+    { "brown",                  rgb(165, 42, 42)    },
+    { "burlywood",              rgb(222, 184, 135)  },
+    { "cadetblue",              rgb( 95, 158, 160)  },
+    { "chartreuse",             rgb(127, 255, 0)    },
+    { "chocolate",              rgb(210, 105, 30)   },
+    { "coral",                  rgb(255, 127, 80)   },
+    { "cornflowerblue",         rgb(100, 149, 237)  },
+    { "cornsilk",               rgb(255, 248, 220)  },
+    { "crimson",                rgb(220, 20, 60)    },
+    { "cyan",                   rgb( 0, 255, 255)   },
+    { "darkblue",               rgb( 0, 0, 139)     },
+    { "darkcyan",               rgb( 0, 139, 139)   },
+    { "darkgoldenrod",          rgb(184, 134, 11)   },
+    { "darkgray",               rgb(169, 169, 169)  },
+    { "darkgreen",              rgb( 0, 100, 0)     },
+    { "darkgrey",               rgb(169, 169, 169)  },
+    { "darkkhaki",              rgb(189, 183, 107)  },
+    { "darkmagenta",            rgb(139, 0, 139)    },
+    { "darkolivegreen",         rgb( 85, 107, 47)   },
+    { "darkorange",             rgb(255, 140, 0)    },
+    { "darkorchid",             rgb(153, 50, 204)   },
+    { "darkred",                rgb(139, 0, 0)      },
+    { "darksalmon",             rgb(233, 150, 122)  },
+    { "darkseagreen",           rgb(143, 188, 143)  },
+    { "darkslateblue",          rgb( 72, 61, 139)   },
+    { "darkslategray",          rgb( 47, 79, 79)    },
+    { "darkslategrey",          rgb( 47, 79, 79)    },
+    { "darkturquoise",          rgb( 0, 206, 209)   },
+    { "darkviolet",             rgb(148, 0, 211)    },
+    { "deeppink",               rgb(255, 20, 147)   },
+    { "deepskyblue",            rgb( 0, 191, 255)   },
+    { "dimgray",                rgb(105, 105, 105)  },
+    { "dimgrey",                rgb(105, 105, 105)  },
+    { "dodgerblue",             rgb( 30, 144, 255)  },
+    { "firebrick",              rgb(178, 34, 34)    },
+    { "floralwhite",            rgb(255, 250, 240)  },
+    { "forestgreen",            rgb( 34, 139, 34)   },
+    { "fuchsia",                rgb(255, 0, 255)    },
+    { "gainsboro",              rgb(220, 220, 220)  },
+    { "ghostwhite",             rgb(248, 248, 255)  },
+    { "gold",                   rgb(255, 215, 0)    },
+    { "goldenrod",              rgb(218, 165, 32)   },
+    { "gray",                   rgb(128, 128, 128)  },
+    { "green",                  rgb( 0, 128, 0)     },
+    { "greenyellow",            rgb(173, 255, 47)   },
+    { "grey",                   rgb(128, 128, 128)  },
+    { "honeydew",               rgb(240, 255, 240)  },
+    { "hotpink",                rgb(255, 105, 180)  },
+    { "indianred",              rgb(205, 92, 92)    },
+    { "indigo",                 rgb( 75, 0, 130)    },
+    { "ivory",                  rgb(255, 255, 240)  },
+    { "khaki",                  rgb(240, 230, 140)  },
+    { "lavender",               rgb(230, 230, 250)  },
+    { "lavenderblush",          rgb(255, 240, 245)  },
+    { "lawngreen",              rgb(124, 252, 0)    },
+    { "lemonchiffon",           rgb(255, 250, 205)  },
+    { "lightblue",              rgb(173, 216, 230)  },
+    { "lightcoral",             rgb(240, 128, 128)  },
+    { "lightcyan",              rgb(224, 255, 255)  },
+    { "lightgoldenrodyellow",   rgb(250, 250, 210)  },
+    { "lightgray",              rgb(211, 211, 211)  },
+    { "lightgreen",             rgb(144, 238, 144)  },
+    { "lightgrey",              rgb(211, 211, 211)  },
+    { "lightpink",              rgb(255, 182, 193)  },
+    { "lightsalmon",            rgb(255, 160, 122)  },
+    { "lightseagreen",          rgb( 32, 178, 170)  },
+    { "lightskyblue",           rgb(135, 206, 250)  },
+    { "lightslategray",         rgb(119, 136, 153)  },
+    { "lightslategrey",         rgb(119, 136, 153)  },
+    { "lightsteelblue",         rgb(176, 196, 222)  },
+    { "lightyellow",            rgb(255, 255, 224)  },
+    { "lime",                   rgb( 0, 255, 0)     },
+    { "limegreen",              rgb( 50, 205, 50)   },
+    { "linen",                  rgb(250, 240, 230)  },
+    { "magenta",                rgb(255, 0, 255)    },
+    { "maroon",                 rgb(128, 0, 0)      },
+    { "mediumaquamarine",       rgb(102, 205, 170)  },
+    { "mediumblue",             rgb( 0, 0, 205)     },
+    { "mediumorchid",           rgb(186, 85, 211)   },
+    { "mediumpurple",           rgb(147, 112, 219)  },
+    { "mediumseagreen",         rgb( 60, 179, 113)  },
+    { "mediumslateblue",        rgb(123, 104, 238)  },
+    { "mediumspringgreen",      rgb( 0, 250, 154)   },
+    { "mediumturquoise",        rgb( 72, 209, 204)  },
+    { "mediumvioletred",        rgb(199, 21, 133)   },
+    { "midnightblue",           rgb( 25, 25, 112)   },
+    { "mintcream",              rgb(245, 255, 250)  },
+    { "mistyrose",              rgb(255, 228, 225)  },
+    { "moccasin",               rgb(255, 228, 181)  },
+    { "navajowhite",            rgb(255, 222, 173)  },
+    { "navy",                   rgb( 0, 0, 128)     },
+    { "oldlace",                rgb(253, 245, 230)  },
+    { "olive",                  rgb(128, 128, 0)    },
+    { "olivedrab",              rgb(107, 142, 35)   },
+    { "orange",                 rgb(255, 165, 0)    },
+    { "orangered",              rgb(255, 69, 0)     },
+    { "orchid",                 rgb(218, 112, 214)  },
+    { "palegoldenrod",          rgb(238, 232, 170)  },
+    { "palegreen",              rgb(152, 251, 152)  },
+    { "paleturquoise",          rgb(175, 238, 238)  },
+    { "palevioletred",          rgb(219, 112, 147)  },
+    { "papayawhip",             rgb(255, 239, 213)  },
+    { "peachpuff",              rgb(255, 218, 185)  },
+    { "peru",                   rgb(205, 133, 63)   },
+    { "pink",                   rgb(255, 192, 203)  },
+    { "plum",                   rgb(221, 160, 221)  },
+    { "powderblue",             rgb(176, 224, 230)  },
+    { "purple",                 rgb(128, 0, 128)    },
+    { "red",                    rgb(255, 0, 0)      },
+    { "rosybrown",              rgb(188, 143, 143)  },
+    { "royalblue",              rgb( 65, 105, 225)  },
+    { "saddlebrown",            rgb(139, 69, 19)    },
+    { "salmon",                 rgb(250, 128, 114)  },
+    { "sandybrown",             rgb(244, 164, 96)   },
+    { "seagreen",               rgb( 46, 139, 87)   },
+    { "seashell",               rgb(255, 245, 238)  },
+    { "sienna",                 rgb(160, 82, 45)    },
+    { "silver",                 rgb(192, 192, 192)  },
+    { "skyblue",                rgb(135, 206, 235)  },
+    { "slateblue",              rgb(106, 90, 205)   },
+    { "slategray",              rgb(112, 128, 144)  },
+    { "slategrey",              rgb(112, 128, 144)  },
+    { "snow",                   rgb(255, 250, 250)  },
+    { "springgreen",            rgb( 0, 255, 127)   },
+    { "steelblue",              rgb( 70, 130, 180)  },
+    { "tan",                    rgb(210, 180, 140)  },
+    { "teal",                   rgb( 0, 128, 128)   },
+    { "thistle",                rgb(216, 191, 216)  },
+    { "tomato",                 rgb(255, 99, 71)    },
+    { "transparent",            0                   },
+    { "turquoise",              rgb( 64, 224, 208)  },
+    { "violet",                 rgb(238, 130, 238)  },
+    { "wheat",                  rgb(245, 222, 179)  },
+    { "white",                  rgb(255, 255, 255)  },
+    { "whitesmoke",             rgb(245, 245, 245)  },
+    { "yellow",                 rgb(255, 255, 0)    },
+    { "yellowgreen",            rgb(154, 205, 50)   }
+};
+
+} // !namespace
+
+color::color(const std::string& name)
+{
+    if (!name.empty()) {
+        // Parse #rrggbb or #rgb.
+        if (name[0] == '#') {
+            if (name.length() == 7) {
+                m_red   = value(name[1], name[2]);
+                m_green = value(name[3], name[4]);
+                m_blue  = value(name[5], name[6]);
+            } else if (name.length() == 4) {
+                m_red   = value(name[1], name[1]);
+                m_green = value(name[2], name[2]);
+                m_blue  = value(name[3], name[3]);
+            } else {
+                throw std::invalid_argument("invalid format");
+            }
+        } else {
+            // Name lookup.
+            auto it = colors.find(name);
+
+            if (it == colors.end()) {
+                throw std::invalid_argument(name + " is not a valid color");
+            }
+
+            // Assign the color to *this.
+            *this = it->second;
+        }
+    }
+}
+
+} // !client
+
+} // !mlk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/color.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,134 @@
+/*
+ * color.hpp -- color description
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_COLOR_HPP
+#define MALIKANIA_COLOR_HPP
+
+/**
+ * \file color.hpp
+ * \brief Colors.
+ */
+
+#include <cstdint>
+#include <string>
+
+namespace mlk {
+
+namespace client {
+
+/**
+ * \brief color description
+ */
+class color {
+private:
+    std::uint8_t m_red{0};
+    std::uint8_t m_green{0};
+    std::uint8_t m_blue{0};
+    std::uint8_t m_alpha{255};
+
+public:
+    /**
+     * Default color to black.
+     */
+    inline color() noexcept = default;
+
+    /**
+     * Constructor with all fields.
+     *
+     * \param red the red value
+     * \param green the green value
+     * \param blue the blue value
+     * \param alpha the alpha value
+     */
+    inline color(std::uint8_t red, std::uint8_t green, std::uint8_t blue, std::uint8_t alpha) noexcept
+        : m_red(red)
+        , m_green(green)
+        , m_blue(blue)
+        , m_alpha(alpha)
+    {
+    }
+
+    /**
+     * Constructor with an hexadecimal value.
+     *
+     * \param hex the color
+     */
+    inline color(std::uint32_t hex) noexcept
+        : m_red((hex >> 16) & 0xff)
+        , m_green((hex >> 8) & 0xff)
+        , m_blue(hex & 0xff)
+        , m_alpha((hex >> 24) & 0xff)
+    {
+    }
+
+    /**
+     * Construct a color from #rrggbb or name.
+     *
+     * See the SVG this [list](http://www.december.com/html/spec/colorsvg.html) for supported names.
+     *
+     * \param name the color name
+     * \throw std::invalid_argument if the color does not exist or is invalid
+     */
+    color(const std::string& name);
+
+    /**
+     * Get the red value.
+     *
+     * \return the value
+     */
+    inline std::uint8_t red() const noexcept
+    {
+        return m_red;
+    }
+
+    /**
+     * Get the green value.
+     *
+     * \return the value
+     */
+    inline std::uint8_t green() const noexcept
+    {
+        return m_green;
+    }
+
+    /**
+     * Get the blue value.
+     *
+     * \return the value
+     */
+    inline std::uint8_t blue() const noexcept
+    {
+        return m_blue;
+    }
+
+    /**
+     * Get the alpha value.
+     *
+     * \return the value
+     */
+    inline std::uint8_t alpha() const noexcept
+    {
+        return m_alpha;
+    }
+};
+
+} // !client
+
+} // !mlk
+
+#endif // !MALIKANIA_COLOR_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/font.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,44 @@
+/*
+ * font.cpp -- font object
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "font_backend.hpp"
+
+namespace mlk {
+
+namespace client {
+
+font::font(std::string data, unsigned size)
+    : m_backend(std::make_unique<backend_impl>(std::move(data), size))
+    , m_size(size)
+{
+}
+
+font::font(font&& other) noexcept = default;
+
+font::~font() noexcept = default;
+
+size font::clip(const std::string& text) const
+{
+    return m_backend->clip(*this, text);
+}
+
+font& font::operator=(font&& other) noexcept = default;
+
+} // !client
+
+} // !mlk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/font.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,118 @@
+/*
+ * font.hpp -- font object
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_FONT_HPP
+#define MALIKANIA_FONT_HPP
+
+/**
+ * \file font.hpp
+ * \brief fonts.
+ */
+
+#include <memory>
+#include <string>
+
+#include "size.hpp"
+
+namespace mlk {
+
+namespace client {
+
+/**
+ * \brief font object.
+ */
+class font {
+private:
+    class backend_impl;
+
+    std::unique_ptr<backend_impl> m_backend;
+    unsigned m_size;
+
+public:
+    /**
+     * Construct a font from binary data.
+     *
+     * \param data the raw data
+     * \param size the size
+     */
+    font(std::string data, unsigned size);
+
+    /**
+     * Default move constructor.
+     *
+     * \param other the other font
+     */
+    font(font&& other) noexcept;
+
+    /**
+     * Default destructor.
+     */
+    virtual ~font() noexcept;
+
+    /**
+     * Get the font size.
+     *
+     * \return the font size
+     */
+    inline unsigned size() const noexcept
+    {
+        return m_size;
+    }
+
+    /**
+     * Get the underlying backend.
+     *
+     * \return the backend
+     */
+    inline const backend_impl& backend() const noexcept
+    {
+        return *m_backend;
+    }
+
+    /**
+     * Overloaded function.
+     *
+     * \return the backend
+     */
+    inline backend_impl& backend() noexcept
+    {
+        return *m_backend;
+    }
+
+    /**
+     * Get the clipping size required to draw the given text.
+     *
+     * \param text the text to clip
+     * \return the required size
+     */
+    mlk::client::size clip(const std::string& text) const;
+
+    /**
+     * Default move assignment operator.
+     *
+     * \param other the other font
+     * \return this
+     */
+    font& operator=(font&& other) noexcept;
+};
+
+} // !client
+
+} // !mlk
+
+#endif // MALIKANIA_FONT_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/frame.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,49 @@
+/*
+ * frame.cpp -- top level GUI frame
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "layout.hpp"
+#include "frame.hpp"
+#include "point.hpp"
+#include "rectangle.hpp"
+#include "theme.hpp"
+#include "window.hpp"
+
+namespace mlk {
+
+namespace client {
+
+mlk::client::size frame::size(window &win)
+{
+    return m_layout ? m_layout->size(win) : mlk::client::size();
+}
+
+void frame::draw(window& win)
+{
+    if (m_layout) {
+        win.theme().draw_frame(win, *this);
+    }
+}
+
+void frame::move(point pos)
+{
+    m_position = std::move(pos);
+}
+
+} // !client
+
+} // !mlk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/frame.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,178 @@
+/*
+ * frame.hpp -- top level GUI frame
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_CLIENT_FRAME_HPP
+#define MALIKANIA_CLIENT_FRAME_HPP
+
+/**
+ * \file frame.hpp
+ * \brief Top level GUI frame.
+ */
+
+#include <memory>
+
+#include "point.hpp"
+#include "size.hpp"
+
+namespace mlk {
+
+namespace client {
+
+class layout;
+class point;
+class window;
+
+/**
+ * \brief Top level GUI frame.
+ */
+class frame {
+private:
+    std::shared_ptr<mlk::client::layout> m_layout;
+    mlk::client::point m_position;
+    mlk::client::size m_padding{10, 10};
+
+public:
+    /**
+     * Create a frame with an optional layout.
+     *
+     * \param layout the optional layout
+     */
+    inline frame(std::shared_ptr<mlk::client::layout> layout = nullptr) noexcept
+        : m_layout(std::move(layout))
+    {
+    }
+
+    /**
+     * Virtual destructor defaulted.
+     */
+    virtual ~frame() = default;
+
+    /**
+     * Get the current layout.
+     *
+     * return the layout
+     */
+    inline const std::shared_ptr<mlk::client::layout>& layout() const noexcept
+    {
+        return m_layout;
+    }
+
+    /**
+     * Overloaded function.
+     *
+     * \return the layout
+     */
+    inline std::shared_ptr<mlk::client::layout>& layout() noexcept
+    {
+        return m_layout;
+    }
+
+    /**
+     * Change the current frame layout.
+     *
+     * \param layout the new layout (may be null)
+     */
+    inline void set_layout(std::shared_ptr<mlk::client::layout> layout) noexcept
+    {
+        m_layout = std::move(layout);
+    }
+
+    /**
+     * Get the current frame position.
+     *
+     * \return the frame position
+     */
+    inline const point& position() const noexcept
+    {
+        return m_position;
+    }
+
+    /**
+     * Overloaded function.
+     *
+     * \return the position
+     */
+    inline point& position() noexcept
+    {
+        return m_position;
+    }
+
+    /**
+     * Get the frame padding.
+     *
+     * \return the frame padding
+     */
+    inline const mlk::client::size& padding() const noexcept
+    {
+        return m_padding;
+    }
+
+    /**
+     * Overloaded function.
+     *
+     * \return the padding
+     */
+    inline mlk::client::size& padding() noexcept
+    {
+        return m_padding;
+    }
+
+    /**
+     * Set the frame padding.
+     *
+     * \param padding the padding
+     */
+    inline void set_padding(mlk::client::size padding) noexcept
+    {
+        m_padding = std::move(padding);
+    }
+
+    /**
+     * Compute the total frame size.
+     *
+     * If no layout is attached, the frame returns a null size. Otherwise, the
+     * default implementation returns `layout()->size()`.
+     *
+     * \param win the window
+     * \return the size required to draw this frame
+     */
+    virtual mlk::client::size size(window& win);
+
+    /**
+     * Draw the frame and its content.
+     *
+     * If no layout is attached, the function is a no-op. Otherwise the default
+     * implementation calls `win.theme().draw_frame(*this)`.
+     *
+     * \param win the window
+     */
+    virtual void draw(window& win);
+
+    /**
+     * Move the frame to somewhere else.
+     *
+     * \param pos the new position
+     */
+    virtual void move(point pos);
+};
+
+} // !client
+
+} // !mlk
+
+#endif // !MALIKANIA_CLIENT_FRAME_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/grid_layout.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,112 @@
+/*
+ * grid_layout.cpp -- basic grid layout
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <algorithm>
+#include <numeric>
+
+#include "grid_layout.hpp"
+#include "size.hpp"
+#include "widget.hpp"
+
+namespace mlk {
+
+unsigned grid_layout::index(unsigned r, unsigned c) const noexcept
+{
+    return r * m_cols + c;
+}
+
+void grid_layout::update_rsize(window& win) noexcept
+{
+    for (unsigned r = 0; r < m_rows; ++r) {
+        m_min_rsize[r] = 0;
+
+        for (unsigned c = 0; c < m_cols; ++c) {
+            auto idx = index(r, c);
+
+            if (!m_widgets[idx]) {
+                continue;
+            }
+
+            auto size = m_widgets[index(r, c)]->size(win);
+
+            if (size.height() > m_min_rsize[r]) {
+                m_min_rsize[r] = size.height();
+            }
+        }
+    }
+}
+
+void grid_layout::update_csize(window& win) noexcept
+{
+    for (unsigned c = 0; c < m_cols; ++c) {
+        m_min_csize[c] = 0;
+
+        for (unsigned r = 0; r < m_rows; ++r) {
+            auto idx = index(r, c);
+
+            if (!m_widgets[idx]) {
+                continue;
+            }
+
+            auto size = m_widgets[index(r, c)]->size(win);
+
+            if (size.width() > m_min_csize[c]) {
+                m_min_csize[c] = size.width();
+            }
+        }
+    }
+}
+
+grid_layout::grid_layout(unsigned rows, unsigned columns)
+    : m_rows(rows)
+    , m_cols(columns)
+{
+    m_widgets.resize(rows * columns);
+    m_min_rsize.resize(rows);
+    m_min_csize.resize(columns);
+}
+
+void grid_layout::add_widget(unsigned r, unsigned c, std::shared_ptr<widget> w)
+{
+    m_widgets[index(r, c)] = std::move(w);
+}
+
+void grid_layout::remove_widget(unsigned r, unsigned c)
+{
+    m_widgets[index(r, c)] = nullptr;
+}
+
+void grid_layout::remove_widget(std::shared_ptr<widget> w)
+{
+    m_widgets.erase(std::remove(m_widgets.begin(), m_widgets.end(), w), m_widgets.end());
+}
+
+mlk::size grid_layout::size(window& win) const noexcept
+{
+    return {
+        std::accumulate(m_min_csize.begin(), m_min_csize.end(), 0) + (m_rows * 10),
+        std::accumulate(m_min_rsize.begin(), m_min_rsize.end(), 0) + (m_cols * 10)
+    };
+}
+
+void grid_layout::draw(window &win, const rectangle &dst)
+{
+
+}
+
+} // !mlk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/grid_layout.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,70 @@
+/*
+ * grid_layout.hpp -- basic grid layout
+ *
+ * Copyright (c) 2013-2016 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_CLIENT_GRID_LAYOUT_HPP
+#define MALIKANIA_CLIENT_GRID_LAYOUT_HPP
+
+#include <memory>
+#include <vector>
+
+#include "layout.hpp"
+
+namespace mlk {
+
+class widget;
+
+class grid_layout : public layout {
+private:
+    // Dimensions.
+    unsigned m_rows;
+    unsigned m_cols;
+
+    // Widgets.
+    std::vector<std::shared_ptr<widget>> m_widgets;
+
+    /*
+     * Track maximum size by rows/columns to determine the minimum whole
+     * layout size.
+     *
+     * It's only used in draw() but kept as member variables to avoid useless
+     * reallocation on each frame.
+     */
+    std::vector<unsigned> m_min_rsize;
+    std::vector<unsigned> m_min_csize;
+
+    unsigned index(unsigned, unsigned) const noexcept;
+    void update_rsize(window&) noexcept;
+    void update_csize(window&) noexcept;
+
+public:
+    grid_layout(unsigned rows, unsigned columns);
+
+    void add_widget(unsigned r, unsigned c, std::shared_ptr<widget> w);
+
+    void remove_widget(unsigned r, unsigned c);
+
+    void remove_widget(std::shared_ptr<widget> w);
+
+    mlk::size size(window& win) const noexcept override;
+
+    void draw(window& win, const rectangle& dst) override;
+};
+
+} // !mlk
+
+#endif // !MALIKANIA_CLIENT_GRID_LAYOUT_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/image.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,53 @@
+/*
+ * image.cpp -- image object
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "image_backend.hpp"
+
+namespace mlk {
+
+namespace client {
+
+image::image(std::string data)
+    : m_backend(new backend_impl(*this, std::move(data)))
+{
+}
+
+image::image(image&&) noexcept = default;
+
+image::~image() noexcept = default;
+
+const mlk::client::size& image::size() const noexcept
+{
+    return m_backend->size();
+}
+
+void image::draw(window& window, const point& position)
+{
+    m_backend->draw(window, position);
+}
+
+void image::draw(window& window, const rectangle& source, const rectangle& target)
+{
+    m_backend->draw(window, source, target);
+}
+
+image& image::operator=(image&&) noexcept = default;
+
+} // !client
+
+} // !mlk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/image.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,127 @@
+/*
+ * image.hpp -- image object
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_IMAGE_HPP
+#define MALIKANIA_IMAGE_HPP
+
+/**
+ * \file image.hpp
+ * \brief Images.
+ */
+
+#include <memory>
+#include <string>
+
+#include "point.hpp"
+#include "rectangle.hpp"
+#include "size.hpp"
+
+namespace mlk {
+
+namespace client {
+
+class window;
+
+/**
+ * \brief Image object.
+ */
+class image {
+private:
+    class backend_impl;
+
+    std::unique_ptr<backend_impl> m_backend;
+
+public:
+    /**
+     * Construct an image from the binary data.
+     *
+     * \param window the window
+     * \param data the data
+     */
+    image(std::string data);
+
+    /**
+     * Default move constructor.
+     *
+     * \param other the other image
+     */
+    image(image&& other) noexcept;
+
+    /**
+     * Default destructor.
+     */
+    ~image() noexcept;
+
+    /**
+     * Overloaded function.
+     *
+     * \return the backend
+     */
+    inline class backend_impl& backend() noexcept
+    {
+        return *m_backend;
+    }
+
+    /**
+     * Get the underlying backend.
+     *
+     * \return the backend
+     */
+    inline const backend_impl& backend() const noexcept
+    {
+        return *m_backend;
+    }
+
+    /**
+     * Get the image size.
+     *
+     * \return the size
+     */
+    const mlk::client::size& size() const noexcept;
+
+    /**
+     * Draw the image to the window.
+     *
+     * \param window the window
+     * \param position the position
+     */
+    void draw(window& window, const point& position = {0, 0});
+
+    /**
+     * Overloaded function.
+     *
+     * \param window the window
+     * \param source the source to clip
+     * \param target the target destination
+     */
+    void draw(window& window, const rectangle& source, const rectangle& target);
+
+    /**
+     * Default move assignment operator.
+     *
+     * \param other the other image
+     * \return this
+     */
+    image& operator=(image&& image) noexcept;
+};
+
+} // !client
+
+} // !mlk
+
+#endif // !MALIKANIA_IMAGE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/key.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,248 @@
+/*
+ * key.hpp -- key definitions
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_CLIENT_KEY_HPP
+#define MALIKANIA_CLIENT_KEY_HPP
+
+namespace mlk {
+
+namespace client {
+
+/**
+ * \brief Describe keyboard modifiers
+ *
+ * This enumeration is a satisfied the Bitmask concept.
+ */
+enum class mod {
+    none            = 0,                //!< no modifiers
+    left_control    = (1 << 1),         //!< left control
+    left_alt        = (1 << 2),         //!< left alt
+    left_shift      = (1 << 3),         //!< left shift
+    left_super      = (1 << 4),         //!< left logo
+    right_control   = (1 << 5),         //!< right control
+    right_alt       = (1 << 6),         //!< right alt
+    right_shift     = (1 << 7),         //!< right shift
+    right_super     = (1 << 8),         //!< right logo
+    num_lock        = (1 << 9),         //!< num lock is on
+    caps_lock       = (1 << 10),        //!< caps lock is on
+    control         = left_control |    //!< left or right control
+                      right_control,
+    shift           = left_shift |      //!< left or right shift
+                      right_shift,
+    alt             = left_alt |        //!< left or right alt
+                      right_alt,
+    super           = left_super |      //!< left or right super
+                      right_super
+};
+
+/**
+ * \cond ENUM_HIDDEN_SYMBOLS
+ */
+
+inline mod operator^(mod v1, mod v2) noexcept
+{
+    return static_cast<mod>(static_cast<unsigned>(v1) ^ static_cast<unsigned>(v2));
+}
+
+inline mod operator&(mod v1, mod v2) noexcept
+{
+    return static_cast<mod>(static_cast<unsigned>(v1)&  static_cast<unsigned>(v2));
+}
+
+inline mod operator|(mod v1, mod v2) noexcept
+{
+    return static_cast<mod>(static_cast<unsigned>(v1) | static_cast<unsigned>(v2));
+}
+
+inline mod operator~(mod v) noexcept
+{
+    return static_cast<mod>(~static_cast<unsigned>(v));
+}
+
+inline mod& operator|=(mod& v1, mod v2) noexcept
+{
+    v1 = static_cast<mod>(static_cast<unsigned>(v1) | static_cast<unsigned>(v2));
+
+    return v1;
+}
+
+inline mod& operator&=(mod& v1, mod v2) noexcept
+{
+    v1 = static_cast<mod>(static_cast<unsigned>(v1)&  static_cast<unsigned>(v2));
+
+    return v1;
+}
+
+inline mod& operator^=(mod& v1, mod v2) noexcept
+{
+    v1 = static_cast<mod>(static_cast<unsigned>(v1) ^ static_cast<unsigned>(v2));
+
+    return v1;
+}
+
+/**
+ * \endcond
+ */
+
+/**
+ * \brief Key description.
+ */
+enum class key {
+    unknown,
+    a,
+    b,
+    c,
+    d,
+    e,
+    f,
+    g,
+    h,
+    i,
+    j,
+    k,
+    l,
+    m,
+    n,
+    o,
+    p,
+    q,
+    r,
+    s,
+    t,
+    u,
+    v,
+    w,
+    x,
+    y,
+    z,
+    exclaim,
+    double_quote,
+    percent,
+    dollar,
+    ampersand,
+    left_parenthese,
+    right_parenthese,
+    asterisk,
+    plus,
+    colon,
+    less,
+    greater,
+    question,
+    at,
+    caret,
+    underscore,
+    back_quote,
+    quote,
+    one,
+    two,
+    three,
+    four,
+    five,
+    six,
+    seven,
+    eight,
+    nine,
+    zero,
+    enter,
+    escape,
+    backspace,
+    tab,
+    space,
+    minus,
+    equals,
+    left_bracket,
+    right_bracket,
+    backslash,
+    hash,
+    semicolon,
+    apostrophe,
+    grave,
+    comma,
+    period,
+    slash,
+    caps_lock,
+    f1,
+    f2,
+    f3,
+    f4,
+    f5,
+    f6,
+    f7,
+    f8,
+    f9,
+    f10,
+    f11,
+    f12,
+    f13,
+    f14,
+    f15,
+    f16,
+    f17,
+    f18,
+    f19,
+    f20,
+    f21,
+    f22,
+    f23,
+    f24,
+    print_screen,
+    scroll_lock,
+    pause,
+    insert,
+    home,
+    page_up,
+    page_down,
+    del,
+    end,
+    right,
+    left,
+    down,
+    up,
+    kp_divide,
+    kp_multiply,
+    kp_minus,
+    kp_plus,
+    kp_enter,
+    kp_one,
+    kp_two,
+    kp_three,
+    kp_four,
+    kp_five,
+    kp_six,
+    kp_seven,
+    kp_eight,
+    kp_nine,
+    kp_zero,
+    mute,
+    volume_up,
+    volume_down,
+    left_control,
+    left_alt,
+    left_shift,
+    left_super,
+    right_control,
+    right_alt,
+    right_shift,
+    right_super
+};
+
+} // !client
+
+} // !mlk
+
+#endif // !MALIKANIA_CLIENT_KEY_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/label.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,45 @@
+/*
+ * label.cpp -- GUI label element
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "label.hpp"
+#include "size.hpp"
+#include "theme.hpp"
+#include "window.hpp"
+
+namespace mlk {
+
+namespace client {
+
+label::label(std::string text) noexcept
+    : m_text(std::move(text))
+{
+}
+
+void label::draw(window& w, const rectangle& rect)
+{
+    w.theme().draw_label(w, *this, rect);
+}
+
+mlk::client::size label::size(window& w) const noexcept
+{
+    return w.theme().size_label(*this);
+}
+
+} // !client
+
+} // !mlk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/label.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,97 @@
+/*
+ * label.hpp -- GUI label element
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_CLIENT_LABEL_HPP
+#define MALIKANIA_CLIENT_LABEL_HPP
+
+/**
+ * \file label.hp
+ * \brief GUI label element.
+ */
+
+#include <string>
+
+#include "widget.hpp"
+
+namespace mlk {
+
+namespace client {
+
+/**
+ * \brief Basic label for displaying test.
+ */
+class label : public widget {
+private:
+    std::string m_text;
+
+public:
+    /**
+     * Create a label with an optional text.
+     *
+     * \param text the text
+     */
+    label(std::string text = "") noexcept;
+
+    /**
+     * Get the text.
+     *
+     * \return the label text
+     */
+    inline const std::string& text() const noexcept
+    {
+        return m_text;
+    }
+
+    /**
+     * Overloaded function.
+     *
+     * \return the text
+     */
+    inline std::string& text() noexcept
+    {
+        return m_text;
+    }
+
+    /**
+     * Set the label text.
+     *
+     * \param text the text
+     */
+    inline void set_text(std::string text) noexcept
+    {
+        m_text = std::move(text);
+    }
+
+    using widget::draw;
+
+    /**
+     * \copydoc widget::draw
+     */
+    void draw(window& w, const rectangle& rect) override;
+
+    /**
+     * \copydoc widget::size
+     */
+    mlk::client::size size(window& w) const noexcept override;
+};
+
+} // !client
+
+} // !mlk
+
+#endif // !MALIKANIA_CLIENT_LABEL_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/layout.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,81 @@
+/*
+ * layout.hpp -- generic layout manager inside a frame
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_CLIENT_LAYOUT_HPP
+#define MALIKANIA_CLIENT_LAYOUT_HPP
+
+/**
+ * \brief Generic layout manager inside a frame.
+ */
+
+namespace mlk {
+
+namespace client {
+
+class mouse_click_event;
+class rectangle;
+class size;
+class window;
+
+/**
+ * \brief Manages the widgets inside a frame.
+ *
+ * Layouts are responsible of positioning the widgets inside a frame. They
+ * handle their positions and dispatch events if applicable.
+ *
+ * \see grid_layout
+ */
+class layout {
+public:
+    /**
+     * Virtual destructor defaulted.
+     */
+    virtual ~layout() noexcept = default;
+
+    /**
+     * Handle mouse down.
+     *
+     * \param ev the mouse event
+     */
+    virtual void handle_mouse_down(const mouse_click_event& ev) = 0;
+
+    /**
+     * Handle mouse up.
+     *
+     * \param ev the event
+     */
+    virtual void handle_mouse_up(const mouse_click_event& ev) = 0;
+
+    /**
+     * Return the required minimum size to draw the whole layout.
+     */
+    virtual mlk::client::size size(window& win) const = 0;
+
+    /**
+     * Draw the layout content at the given position.
+     *
+     * \param win the window
+     */
+    virtual void draw(window& win, const rectangle& dst) = 0;
+};
+
+} // !client
+
+} // !mlk
+
+#endif // !MALIKANIA_CLIENT_LAYOUT_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/line.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,129 @@
+/*
+ * line.hpp -- line description
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_LINE_HPP
+#define MALIKANIA_LINE_HPP
+
+/**
+ * \file line.hpp
+ * \brief line description.
+ */
+
+namespace mlk {
+
+namespace client {
+
+/**
+ * \brief line description.
+ *
+ * A line has an origin (x, y) and a destination (x, y).
+ */
+class line {
+private:
+    int m_x1;
+    int m_y1;
+    int m_x2;
+    int m_y2;
+
+public:
+    /**
+     * Construct a line.
+     *
+     * \param x1 the first x
+     * \param y1 the first y
+     * \param x2 the second x
+     * \param y2 the second y
+     */
+    inline line(int x1 = 0, int y1 = 0, int x2 = 0, int y2 = 0) noexcept
+        : m_x1(x1)
+        , m_y1(y1)
+        , m_x2(x2)
+        , m_y2(y2)
+    {
+    }
+
+    /**
+     * Get the first x.
+     *
+     * \return the x1
+     */
+    inline int x1() const noexcept
+    {
+        return m_x1;
+    }
+
+    /**
+     * Get the first y.
+     *
+     * \return the y1
+     */
+    inline int y1() const noexcept
+    {
+        return m_y1;
+    }
+
+    /**
+     * Get the second x.
+     *
+     * \return the x2
+     */
+    inline int x2() const noexcept
+    {
+        return m_x2;
+    }
+
+    /**
+     * Get the second y.
+     *
+     * \return the y2
+     */
+    inline int y2() const noexcept
+    {
+        return m_y2;
+    }
+};
+
+/**
+ * Compare equality.
+ *
+ * \param l1 the first line
+ * \param l2 the second line
+ * \return true if they equal
+ */
+inline bool operator==(const line& l1, const line& l2) noexcept
+{
+    return l1.x1() == l2.x1() && l1.x2() == l2.x2() && l1.y1() == l2.y1() && l1.y2() == l2.y2();
+}
+
+/**
+ * Compare equality.
+ *
+ * \param l1 the first line
+ * \param l2 the second line
+ * \return false if they equal
+ */
+inline bool operator!=(const line& l1, const line& l2) noexcept
+{
+    return !(l1 == l2);
+}
+
+} // !client
+
+} // !mlk
+
+#endif // !MALIKANIA_LINE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/loader.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,142 @@
+/*
+ * client_resources_loader.cpp -- load shared resources files for the client
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <boost/format.hpp>
+
+#include <cassert>
+
+#include "animation.hpp"
+#include "loader.hpp"
+#include "size.hpp"
+#include "sprite.hpp"
+#include "util.hpp"
+
+using boost::str;
+using boost::format;
+
+using mlk::util::json::invalid;
+
+namespace mlk {
+
+namespace client {
+
+size loader::require_size(const std::string& id,
+                          const nlohmann::json& object,
+                          const std::string& property) const
+{
+    assert(object.is_object());
+
+    auto it = object.find(property);
+
+    if (it == object.end() || !it->is_array()) {
+        throw std::runtime_error(str(format("%s: missing '%' property (array expected)") % id % property));
+    }
+    if (it->size() != 2) {
+        throw std::runtime_error(str(format("%s: property '%s' muve have two values") % id % property));
+    }
+    if (!(*it)[0].is_number_integer() || !(*it)[1].is_number_integer()) {
+        throw std::runtime_error(str(format("%s: property '%s' must contains two ints")));
+    }
+
+    return size((*it)[0].get<int>(), (*it)[1].get<int>());
+}
+
+size loader::get_size(const std::string&,
+                      const nlohmann::json& object,
+                      const std::string& key) const noexcept
+{
+    assert(object.is_object());
+
+    auto it = object.find(key);
+
+    if (it == object.end() || !it->is_array() || it->size() != 2 ||
+        !(*it)[0].is_number_integer() || !(*it)[1].is_number_integer()) {
+        return size();
+    }
+
+    return size((*it)[0].get<int>(), (*it)[1].get<int>());
+}
+
+font loader::load_font(const std::string& id, unsigned size)
+{
+    return font(locator().read(id), size);
+}
+
+image loader::load_image(const std::string& id)
+{
+    return image(locator().read(id));
+}
+
+sprite loader::load_sprite(const std::string& id)
+{
+    auto value = nlohmann::json::parse(locator().read(id));
+
+    if (!value.is_object()) {
+        throw std::runtime_error(id + ": not a JSON object");
+    }
+
+    return sprite(
+        load_image(require_string(id, value, "image")),
+        require_size(id, value, "cell"),
+        get_size(id, value, "size"),
+        get_size(id, value, "space"),
+        get_size(id, value, "margin")
+    );
+}
+
+animation loader::load_animation(const std::string& id)
+{
+    auto value = nlohmann::json::parse(locator().read(id));
+
+    if (!value.is_object()) {
+        throw std::runtime_error("not a JSON object");
+    }
+
+    auto sprite = load_sprite(require_string(id, value, "sprite"));
+
+    // Load all frames.
+    auto property = value["frames"];
+
+    if (!property.is_array()) {
+        throw invalid(id, nlohmann::json::value_t::array);
+    }
+
+    animation_frames frames;
+    int index = 0;
+
+    for (auto it = property.begin(); it != property.end(); ++it) {
+        if (!it->is_object()) {
+            throw std::runtime_error(id + ": frame " + std::to_string(index) + ": not a JSON object");
+        }
+
+        auto delay = it->find("delay");
+
+        if (delay == it->end() || !delay->is_number_integer()) {
+            throw std::runtime_error(id + ": frame " + std::to_string(index) +
+                ": missing 'delay' property (int expected)");
+        }
+
+        frames.emplace_back(delay->get<int>());
+    }
+
+    return animation(std::move(sprite), std::move(frames));
+}
+
+} // !client
+
+} // !mlk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/loader.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,129 @@
+/*
+ * client_resources_loader.hpp -- load shared resources files for the client
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_CLIENT_RESOURCES_LOADER_HPP
+#define MALIKANIA_CLIENT_RESOURCES_LOADER_HPP
+
+/*
+ * \file client_resources_loader.hpp
+ * \brief Load client assets.
+ */
+
+#include <malikania/loader.hpp>
+
+#include "animation.hpp"
+#include "font.hpp"
+#include "image.hpp"
+#include "size.hpp"
+#include "sprite.hpp"
+
+namespace mlk {
+
+namespace client {
+
+/**
+ * \brief Load client resources.
+ */
+class loader : public mlk::loader {
+protected:
+    /**
+     * Require a size object from an object property.
+     *
+     * The size is an array of two integers (e.g. [ 1, 2 ]).
+     *
+     * \pre object.is_object()
+     * \param id the resource id
+     * \param object the object
+     * \param property the property
+     * \return the size
+     * \throw std::runtime_error if the property is not a size
+     */
+    size require_size(const std::string& id,
+                      const nlohmann::json& object,
+                      const std::string& property) const;
+
+    /**
+     * Get a size object or a default one if not present or invalid.
+     *
+     * \pre object.is_object()
+     * \param id the resource id
+     * \param object the object
+     * \param property the property
+     * \return the size or default one
+     */
+    size get_size(const std::string& id,
+                  const nlohmann::json& object,
+                  const std::string& property) const noexcept;
+
+public:
+    /**
+     * Client resources loader constructor.
+     *
+     * The window is required because some of the resources require it.
+     *
+     * \param window the window
+     * \param locator the resources locator
+     */
+    inline loader(mlk::locator& locator)
+        : mlk::loader(locator)
+    {
+    }
+
+    /**
+     * Load a font.
+     *
+     * \param id the resource id
+     * \param size the desired size
+     * \return the font
+     * \throw std::runtime_error on errors
+     */
+    virtual font load_font(const std::string& id, unsigned size);
+
+    /**
+     * Load an image.
+     *
+     * \param id the resource id
+     * \return the image
+     * \throw std::runtime_error on errors
+     */
+    virtual image load_image(const std::string& id);
+
+    /**
+     * Load a sprite.
+     *
+     * \param id the resource id
+     * \return the sprite
+     * \throw std::runtime_error on errors
+     */
+    virtual sprite load_sprite(const std::string& id);
+
+    /**
+     * Load an animation.
+     *
+     * \param id the resource id
+     * \return the animation
+     * \throw std::runtime_error on errors
+     */
+    virtual animation load_animation(const std::string& id);
+};
+
+} // !client
+
+} // !mlk
+
+#endif // !MALIKANIA_CLIENT_RESOURCES_LOADER_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/mouse.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,45 @@
+/*
+ * mouse.hpp -- mouse definitions
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_CLIENT_MOUSE_HPP
+#define MALIKANIA_CLIENT_MOUSE_HPP
+
+/**
+ * \file mouse.hpp
+ * \brief Mouse definitions.
+ */
+
+namespace mlk {
+
+namespace client {
+
+/**
+ * \brief Describe mouse button
+ */
+enum class mouse {
+    none,                           //!< no buttons are pressed
+    left,                           //!< left click is pressed
+    right,                          //!< right click is pressed
+    middle                          //!< middle click is pressed
+};
+
+} // !client
+
+} // !mlk
+
+#endif // !MALIKANIA_CLIENT_MOUSE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/point.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,101 @@
+/*
+ * point.hpp -- point description
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_POINT_HPP
+#define MALIKANIA_POINT_HPP
+
+/**
+ * \file point.hpp
+ * \brief point description.
+ */
+
+namespace mlk {
+
+namespace client {
+
+/**
+ * \brief point coordinate.
+ */
+class point {
+private:
+    int m_x;
+    int m_y;
+
+public:
+    /**
+     * Construct a point.
+     *
+     * \param x the x
+     * \param y the y
+     */
+    inline point(int x = 0, int y = 0) noexcept
+        : m_x(x)
+        , m_y(y)
+    {
+    }
+
+    /**
+     * Get the x position.
+     *
+     * \return the x
+     */
+    inline int x() const noexcept
+    {
+        return m_x;
+    }
+
+    /**
+     * Get the y position.
+     *
+     * \return the y
+     */
+    inline int y() const noexcept
+    {
+        return m_y;
+    }
+};
+
+/**
+ * Compare equality.
+ *
+ * \param p1 the first point
+ * \param p2 the second point
+ * \return true if they equal
+ */
+inline bool operator==(const point& p1, const point& p2) noexcept
+{
+    return p1.x() == p2.x() && p1.y() == p2.y();
+}
+
+/**
+ * Compare equality.
+ *
+ * \param p1 the first point
+ * \param p2 the second point
+ * \return false if they equal
+ */
+inline bool operator!=(const point& p1, const point& p2) noexcept
+{
+    return !(p1 == p2);
+}
+
+} // !client
+
+} // !mlk
+
+#endif // !MALIKANIA_POINT_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/rectangle.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,142 @@
+/*
+ * rectangle.hpp -- rectangle description
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_RECTANGLE_HPP
+#define MALIKANIA_RECTANGLE_HPP
+
+/**
+ * \file rectangle.hpp
+ * \brief rectangle description.
+ */
+
+namespace mlk {
+
+namespace client {
+
+/**
+ * \brief rectangle description.
+ *
+ * A rectangle has coordinates (x, y) and dimensions (width, height).
+ *
+ * They are commonly used for clipping images into the window.
+ */
+class rectangle {
+private:
+    int m_x;
+    int m_y;
+    unsigned m_width;
+    unsigned m_height;
+
+public:
+    /**
+     * Construct a rectangle.
+     *
+     * \param x the x position
+     * \param y the y position
+     * \param width the width
+     * \param height the height
+     */
+    inline rectangle(int x = 0, int y = 0, unsigned width = 0, unsigned height = 0) noexcept
+        : m_x(x)
+        , m_y(y)
+        , m_width(width)
+        , m_height(height)
+    {
+    }
+
+    /**
+     * Get the x position.
+     *
+     * \return the x position
+     */
+    inline int x() const noexcept
+    {
+        return m_x;
+    }
+
+    /**
+     * Get the y position.
+     *
+     * \return the y position
+     */
+    inline int y() const noexcept
+    {
+        return m_y;
+    }
+
+    /**
+     * Get the rectangle width.
+     *
+     * \return the width
+     */
+    inline unsigned width() const noexcept
+    {
+        return m_width;
+    }
+
+    /**
+     * Get the rectangle height.
+     *
+     * \return the height
+     */
+    inline unsigned height() const noexcept
+    {
+        return m_height;
+    }
+
+    /**
+     * Check if the rectangle has null dimensions.
+     *
+     * \return true if weight and height are 0
+     */
+    inline bool is_null() const noexcept
+    {
+        return m_width == 0 && m_height == 0;
+    }
+};
+
+/**
+ * Compare equality.
+ *
+ * \param r1 the first rectangle
+ * \param r2 the second rectangle
+ * \return true if they equal
+ */
+inline bool operator==(const rectangle& r1, const rectangle& r2) noexcept
+{
+    return r1.x() == r2.x() && r1.y() == r2.y() &&
+           r1.width() == r2.width() && r1.height() == r2.height();
+}
+
+/**
+ * Compare equality.
+ *
+ * \param r1 the first rectangle
+ * \param r2 the second rectangle
+ * \return false if they equal
+ */
+inline bool operator!=(const rectangle& r1, const rectangle& r2) noexcept
+{
+    return !(r1 == r2);
+}
+
+} // !client
+
+} // !mlk
+
+#endif // !MALIKANIA_RECTANGLE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/size.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,106 @@
+/*
+ * size.hpp -- size description
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_SIZE_HPP
+#define MALIKANIA_SIZE_HPP
+
+namespace mlk {
+
+namespace client {
+
+/**
+ * \brief size description.
+ */
+class size {
+private:
+    unsigned m_width;
+    unsigned m_height;
+
+public:
+    /**
+     * Constructor.
+     *
+     * \param width the size width
+     * \param height the size height
+     */
+    inline size(unsigned width = 0, unsigned height = 0) noexcept
+        : m_width(width)
+        , m_height(height)
+    {
+    }
+
+    /**
+     * Get the width.
+     *
+     * \return the width
+     */
+    inline unsigned width() const noexcept
+    {
+        return m_width;
+    }
+
+    /**
+     * Get the height.
+     *
+     * \return the height
+     */
+    inline unsigned height() const noexcept
+    {
+        return m_height;
+    }
+
+    /**
+     * Check if the size is 0, 0.
+     *
+     * \return true if height and width are 0
+     */
+    inline bool is_null() const noexcept
+    {
+        return m_height == 0 && m_width == 0;
+    }
+};
+
+/**
+ * Compare equality.
+ *
+ * \param s1 the first size
+ * \param s2 the second size
+ * \return true if they equal
+ */
+inline bool operator==(const size& s1, const size& s2) noexcept
+{
+    return s1.width() == s2.width() && s1.height() == s2.height();
+}
+
+/**
+ * Compare equality.
+ *
+ * \param s1 the first size
+ * \param s2 the second size
+ * \return false if they equal
+ */
+inline bool operator!=(const size& s1, const size& s2) noexcept
+{
+    return !(s1 == s2);
+}
+
+} // !client
+
+} // !mlk
+
+#endif // !MALIKANIA_SIZE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/sprite.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,71 @@
+/*
+ * sprite.cpp -- image sprite
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <cassert>
+
+#include "sprite.hpp"
+
+namespace mlk {
+
+namespace client {
+
+sprite::sprite(mlk::client::image image,
+               mlk::client::size cell,
+               mlk::client::size size,
+               mlk::client::size space,
+               mlk::client::size margin) noexcept
+    : m_image(std::move(image))
+    , m_cell(std::move(cell))
+    , m_margin(std::move(margin))
+    , m_space(std::move(space))
+    , m_size(std::move(size))
+{
+    assert(m_cell.width() > 0);
+    assert(m_cell.height() > 0);
+
+    // If size is not specified, take from image.
+    if (m_size.is_null()) {
+        m_size = m_image.size();
+    }
+
+    // Compute number of cells.
+    m_rows = (m_size.height() - (margin.height() * 2) + m_space.height()) / (m_cell.height() + m_space.height());
+    m_columns = (m_size.width() - (m_margin.width() * 2) + m_space.width()) / (m_cell.width() + m_space.width());
+}
+
+void sprite::draw(window& window, unsigned cell, const point& point)
+{
+    assert(cell < m_rows * m_columns);
+
+    // Compute index in the grid.
+    unsigned hindex = (cell % m_columns);
+    unsigned vindex = (cell / m_columns);
+
+    // Compute the pixel boundaries.
+    int x = m_margin.width() + (hindex * m_space.width()) + (hindex * m_cell.width());
+    int y = m_margin.height() + (vindex * m_space.height()) + (vindex * m_cell.height());
+
+    rectangle source(x, y, m_cell.width(), m_cell.height());
+    rectangle target(point.x(), point.y(), m_cell.width(), m_cell.height());
+
+    m_image.draw(window, source, target);
+}
+
+} // !client
+
+} // !mlk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/sprite.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,149 @@
+/*
+ * sprite.hpp -- image sprite
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_SPRITE_HPP
+#define MALIKANIA_SPRITE_HPP
+
+/**
+ * \file sprite.hpp
+ * \brief Sprite description.
+ */
+
+#include "image.hpp"
+
+namespace mlk {
+
+namespace client {
+
+/**
+ * \brief A Sprite is an image divided into cells.
+ */
+class sprite {
+private:
+    mlk::client::image m_image;
+    mlk::client::size m_cell;
+    mlk::client::size m_margin;
+    mlk::client::size m_space;
+    mlk::client::size m_size;
+
+    unsigned m_rows;
+    unsigned m_columns;
+
+public:
+    /**
+     * Construct a sprite.
+     *
+     * \pre cell must not have height or width null
+     * \param image the image to use
+     * \param cell size of cell in the image
+     * \param margin the optional space from borders
+     * \param space the optional space between cells
+     * \param size the sprite size (if 0, taken from the image)
+     */
+    sprite(mlk::client::image image,
+           mlk::client::size cell,
+           mlk::client::size margin = { 0, 0 },
+           mlk::client::size space = { 0, 0 },
+           mlk::client::size size = { 0, 0 }) noexcept;
+
+    /**
+     * Get the underlying image.
+     *
+     * \return the image
+     */
+    inline const mlk::client::image& image() const noexcept
+    {
+        return m_image;
+    }
+
+    /**
+     * Overloaded function.
+     *
+     * \return the image
+     */
+    inline mlk::client::image& image() noexcept
+    {
+        return m_image;
+    }
+
+    /**
+     * Get the cell size.
+     *
+     * \return the cell size
+     */
+    inline const size& cell() const noexcept
+    {
+        return m_cell;
+    }
+
+    /**
+     * Get the margin size.
+     *
+     * \return the margin size
+     */
+    inline const size& margin() noexcept
+    {
+        return m_margin;
+    }
+
+    /**
+     * Get the space size.
+     *
+     * \return the space size
+     */
+    inline const size& space() const noexcept
+    {
+        return m_space;
+    }
+
+    /**
+     * Get the number of rows in the grid.
+     *
+     * \return the number of rows
+     */
+    inline unsigned rows() const noexcept
+    {
+        return m_rows;
+    }
+
+    /**
+     * Get the number of columns in the grid.
+     *
+     * \return the number of columns
+     */
+    inline unsigned columns() const noexcept
+    {
+        return m_columns;
+    }
+
+    /**
+     * Draw the sprite into the window at the specified position.
+     *
+     * \pre cell < rows() * columns()
+     * \param window the window
+     * \param cell the cell index
+     * \param position the position in the window
+     */
+    void draw(window& window, unsigned cell, const point& position);
+};
+
+} // !client
+
+} // !mlk
+
+#endif // !MALIKANIA_SPRITE_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/theme.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,120 @@
+/*
+ * theme.cpp -- theming support for gui elements
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "button.hpp"
+#include "color.hpp"
+#include "frame.hpp"
+#include "label.hpp"
+#include "layout.hpp"
+#include "point.hpp"
+#include "rectangle.hpp"
+#include "theme.hpp"
+#include "window.hpp"
+
+namespace mlk {
+
+namespace client {
+
+namespace {
+
+#include <dejavu_sans.cpp>
+
+} // !namespace
+
+theme::theme()
+    : m_font(std::string(dejavu_sans, sizeof (dejavu_sans)), 10)
+    , m_background_color(228, 228, 228, 255)
+    , m_border_color(102, 102, 102, 255)
+    , m_text_color(50, 50, 50, 255)
+    , m_frame_padding(10, 10)
+{
+}
+
+size theme::size_button(const button &b)
+{
+    auto clip = m_font.clip(b.text());
+
+    return {
+        clip.width() + 12,
+        clip.height() + 12
+    };
+}
+
+size theme::size_label(const label& l)
+{
+    return m_font.clip(l.text());
+}
+
+void theme::draw_frame(window& win, const frame &f)
+{
+    auto layout_size = f.layout()->size(win);
+    auto frame_pos = f.position();
+
+    // Frame border.
+    win.set_drawing_color(m_border_color);
+    win.draw_rectangle({
+        frame_pos.x(),
+        frame_pos.y(),
+        layout_size.width() + m_frame_padding.width() * 2 + 2,
+        layout_size.height() + m_frame_padding.height() * 2 + 2
+    });
+
+    // Frame content.
+    win.set_drawing_color(m_background_color);
+    win.fill_rectangle({
+        frame_pos.x() + 1,
+        frame_pos.y() + 1,
+        layout_size.width() + m_frame_padding.width() * 2,
+        layout_size.height() + m_frame_padding.height() * 2
+    });
+
+    // Layout.
+    f.layout()->draw(win, mlk::client::rectangle(
+        frame_pos.x() + m_frame_padding.width() + 1,
+        frame_pos.y() + m_frame_padding.height() + 1,
+        layout_size.width(),
+        layout_size.height()
+    ));
+}
+
+void theme::draw_button(window& w, const button& b, const rectangle& rect)
+{
+    auto size = size_button(b);
+
+    // Border.
+    w.set_drawing_color(m_border_color);
+    w.draw_rectangle({rect.x(), rect.y(), size.width(), size.height()});
+
+    // Box content.
+    w.set_drawing_color(m_background_color);
+    w.fill_rectangle({rect.x() + 1, rect.y() + 1, size.width() - 2, size.height() - 2});
+
+    // Text.
+    w.set_drawing_color(m_text_color);
+    w.draw_text(b.text(), m_font, point{rect.x() + 5, rect.y() + 5});
+}
+
+void theme::draw_label(window& w, const label& label, const rectangle& rect)
+{
+    w.set_drawing_color(m_text_color);
+    w.draw_text(label.text(), m_font, mlk::client::point(rect.x(), rect.y()));
+}
+
+} // !client
+
+} // !mlk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/theme.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,125 @@
+/*
+ * theme.hpp -- theming support for gui elements
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_CLIENT_THEME_HPP
+#define MALIKANIA_CLIENT_THEME_HPP
+
+/**
+ * \file theme.hpp
+ * \brief Theming support for gui elements.
+ */
+
+#include "color.hpp"
+#include "font.hpp"
+#include "size.hpp"
+
+namespace mlk {
+
+namespace client {
+
+class button;
+class frame;
+class label;
+class rectangle;
+class point;
+class window;
+
+/**
+ * \brief Reimplement this class to provide your own theme.
+ */
+class theme {
+private:
+    font m_font;
+    color m_background_color;
+    color m_border_color;
+    color m_text_color;
+    size m_frame_padding;
+
+public:
+    /**
+     * Default constructor.
+     */
+    theme();
+
+    /**
+     * Virtual destructor defaulted.
+     */
+    virtual ~theme() noexcept = default;
+
+    inline const color& background_color() const noexcept
+    {
+        return m_background_color;
+    }
+
+    inline const color& border_color() const noexcept
+    {
+        return m_border_color;
+    }
+
+    inline const color& text_color() const noexcept
+    {
+        return m_text_color;
+    }
+
+    /**
+     * Get the required bounding rectangle size for this button.
+     *
+     * \param b the button
+     * \return the size
+     */
+    virtual size size_button(const button& b);
+
+    /**
+     * Get the required bouding rectangle size for this label.
+     *
+     * \param l the label
+     * \return the size
+     */
+    virtual size size_label(const label& l);
+
+    /**
+     * Draw the frame.
+     *
+     * \param w the main window
+     * \param f the frame
+     */
+    virtual void draw_frame(window& w, const frame& f);
+
+    /**
+     * Draw a button.
+     *
+     * \param w the main window
+     * \param b the button
+     */
+    virtual void draw_button(window& w, const button& b, const rectangle& rect);
+
+    /**
+     * Draw a label.
+     *
+     * \param w the main window
+     * \param l the label
+     * \param rect the bounding rectangle.
+     */
+    virtual void draw_label(window& w, const label& l, const rectangle& rect);
+};
+
+} // !client
+
+} // !mlk
+
+#endif // !MALIKANIA_CLIENT_THEME_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/unique_layout.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,60 @@
+/*
+ * unique_layout.cpp -- basic layout with one widget
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "size.hpp"
+#include "unique_layout.hpp"
+#include "widget.hpp"
+
+namespace mlk {
+
+namespace client {
+
+unique_layout::unique_layout(std::shared_ptr<mlk::client::widget> widget) noexcept
+    : m_widget(std::move(widget))
+{
+}
+
+void unique_layout::handle_mouse_down(const mouse_click_event& ev)
+{
+    if (m_widget) {
+        m_widget->handle_mouse_down(ev);
+    }
+}
+
+void unique_layout::handle_mouse_up(const mouse_click_event& ev)
+{
+    if (m_widget) {
+        m_widget->handle_mouse_up(ev);
+    }
+}
+
+mlk::client::size unique_layout::size(window& win) const
+{
+    return m_widget ? m_widget->size(win) : mlk::client::size();
+}
+
+void unique_layout::draw(window& win, const rectangle& dst)
+{
+    if (m_widget) {
+        m_widget->draw(win, dst);
+    }
+}
+
+} // !client
+
+} // !mlk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/unique_layout.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,107 @@
+/*
+ * unique_layout.hpp -- basic layout with one widget
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_CLIENT_UNIQUE_LAYOUT_HPP
+#define MALIKANIA_CLIENT_UNIQUE_LAYOUT_HPP
+
+/**
+ * \file unique_layout.hpp
+ * \brief Basic layout with one widget.
+ */
+
+#include <memory>
+
+#include "layout.hpp"
+
+namespace mlk {
+
+namespace client {
+
+class widget;
+
+/**
+ * \brief Simple layout that consists of one widget.
+ */
+class unique_layout : public layout {
+private:
+    std::shared_ptr<mlk::client::widget> m_widget;
+
+public:
+    /**
+     * Constructor with optional widget.
+     *
+     * \param widget the widget
+     */
+    unique_layout(std::shared_ptr<mlk::client::widget> w = nullptr) noexcept;
+
+    /**
+     * Get the handled widget.
+     *
+     * \return the widget
+     */
+    inline const std::shared_ptr<mlk::client::widget>& widget() const noexcept
+    {
+        return m_widget;
+    }
+
+    /**
+     * Overloaded function.
+     *
+     * \return the widget
+     */
+    inline std::shared_ptr<mlk::client::widget>& widget() noexcept
+    {
+        return m_widget;
+    }
+
+    /**
+     * Replace the current widget with this one.
+     *
+     * \param widget the widget
+     */
+    inline void set_widget(std::shared_ptr<mlk::client::widget> widget) noexcept
+    {
+        m_widget = std::move(widget);
+    }
+
+    /**
+     * \copydoc layout::handle_mouse_down
+     */
+    void handle_mouse_down(const mouse_click_event& ev) override;
+
+    /**
+     * \copydoc layout::handle_mouse_up
+     */
+    void handle_mouse_up(const mouse_click_event& ev) override;
+
+    /**
+     * \copydoc layout::size
+     */
+    mlk::client::size size(window& win) const override;
+
+    /**
+     * \copydoc layout::draw
+     */
+    void draw(window& win, const rectangle& dst) override;
+};
+
+} // !client
+
+} // !mlk
+
+#endif // !MALIKANIA_CLIENT_UNIQUE_LAYOUT_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/widget.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,57 @@
+/*
+ * widget.cpp -- basic abstract widget for GUI
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "point.hpp"
+#include "rectangle.hpp"
+#include "size.hpp"
+#include "widget.hpp"
+
+namespace mlk {
+
+namespace client {
+
+void widget::handle_key_down(const key_event&)
+{
+}
+
+void widget::handle_key_up(const key_event&)
+{
+}
+
+void widget::handle_mouse_down(const mouse_click_event&)
+{
+}
+
+void widget::handle_mouse_up(const mouse_click_event&)
+{
+}
+
+void widget::draw(window& w, const point& pos)
+{
+    mlk::client::size sz = size(w);
+    mlk::client::rectangle rect{
+        pos.x(), pos.y(),
+        sz.width(), sz.height()
+    };
+
+    draw(w, rect);
+}
+
+} // !client
+
+} // !mlk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/widget.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,107 @@
+/*
+ * widget.hpp -- basic abstract widget for GUI
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_CLIENT_WIDGET_HPP
+#define MALIKANIA_CLIENT_WIDGET_HPP
+
+/**
+ * \file widget.hpp
+ * \brief Basic abstract widget for GUI
+ */
+
+namespace mlk {
+
+namespace client {
+
+class key_event;
+class mouse_click_event;
+class point;
+class rectangle;
+class size;
+class window;
+
+/**
+ * \brief Abstract widget
+ */
+class widget {
+public:
+    /**
+     * Default destructor.
+     */
+    virtual ~widget() noexcept = default;
+
+    /**
+     * Handle a key down.
+     *
+     * \param ev the event
+     */
+    virtual void handle_key_down(const key_event& ev);
+
+    /**
+     * Handle a key up.
+     *
+     * \param ev the event
+     */
+    virtual void handle_key_up(const key_event& ev);
+
+    /**
+     * Handle mouse down event.
+     *
+     * \param ev the event
+     */
+    virtual void handle_mouse_down(const mouse_click_event& ev);
+
+    /**
+     * Handle a mouse up event.
+     *
+     * \param ev the event
+     */
+    virtual void handle_mouse_up(const mouse_click_event& ev);
+
+    /**
+     * Draw the widget at the specified position.
+     *
+     * Basic GUI elements will use the window theme to render themselves.
+     *
+     * \param w the window
+     */
+    virtual void draw(window& w, const rectangle& rect) = 0;
+
+    /**
+     * Helper to draw the whole widget at the given position.
+     *
+     * Effectively call draw with a rectangle overload.
+     *
+     * \param w the window
+     * \param pos the position
+     */
+    virtual void draw(window& w, const point& pos);
+
+    /**
+     * Get the required size to draw that widget.
+     *
+     * \return the widget size
+     */
+    virtual mlk::client::size size(window& w) const noexcept = 0;
+};
+
+} // !client
+
+} // !mlk
+
+#endif // !MALIKANIA_CLIENT_WIDGET_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/window.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,180 @@
+/*
+ * window.cpp -- main window and basic drawing
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <iostream>
+#include <stdexcept>
+
+#include "color.hpp"
+#include "frame.hpp"
+#include "layout.hpp"
+#include "theme.hpp"
+#include "widget.hpp"
+#include "window_backend.hpp"
+
+namespace mlk {
+
+namespace client {
+
+bool window::is_frame_bound(frame& f, const point& ev_pos) noexcept
+{
+    auto frame_size = f.size(*this);
+    auto frame_padding = f.padding();
+    auto frame_pos = f.position();
+
+    return ev_pos.x() >= frame_pos.x() + static_cast<int>(frame_padding.width()) &&
+           ev_pos.y() >= frame_pos.y() + static_cast<int>(frame_padding.height()) &&
+           ev_pos.x() <= frame_pos.x() + static_cast<int>(frame_padding.width()  + frame_size.width()) &&
+           ev_pos.y() <= frame_pos.y() + static_cast<int>(frame_padding.height() + frame_size.height());
+}
+
+window::window(unsigned width, unsigned height, const std::string& title)
+    : m_backend(std::make_unique<backend_impl>(*this, width, height, title))
+    , m_theme(std::make_unique<mlk::client::theme>())
+{
+}
+
+window::window(window&&) noexcept = default;
+
+window::~window() noexcept = default;
+
+void window::clear()
+{
+    m_backend->clear();
+}
+
+void window::present()
+{
+    m_backend->present();
+}
+
+void window::close() noexcept
+{
+    m_is_open = false;
+    m_backend->close();
+}
+
+color window::drawing_color() const
+{
+    return m_backend->drawing_color();
+}
+
+void window::set_drawing_color(const color& color)
+{
+    m_backend->set_drawing_color(color);
+}
+
+void window::draw_line(const line& line)
+{
+    m_backend->draw_line(line);
+}
+
+void window::draw_lines(const std::vector<point>& points)
+{
+    m_backend->draw_lines(points);
+}
+
+void window::draw_point(const point& point)
+{
+    m_backend->draw_point(point);
+}
+
+void window::draw_points(const std::vector<point>& points)
+{
+    m_backend->draw_points(points);
+}
+
+void window::draw_rectangle(const rectangle& rectangle)
+{
+    m_backend->draw_rectangle(rectangle);
+}
+
+void window::draw_rectangles(const std::vector<rectangle>& rectangles)
+{
+    m_backend->draw_rectangles(rectangles);
+}
+
+void window::draw_frames()
+{
+    for (const auto& f : m_frames) {
+        f->draw(*this);
+    }
+}
+
+void window::fill_rectangle(const rectangle& rectangle)
+{
+    m_backend->fill_rectangle(rectangle);
+}
+
+void window::fill_rectangles(const std::vector<rectangle>& rectangles)
+{
+    m_backend->fill_rectangles(rectangles);
+}
+
+void window::draw_text(const std::string& text, font& font, const rectangle& rectangle)
+{
+    m_backend->draw_text(text, font, rectangle);
+}
+
+void window::draw_text(const std::string& text, font& font, const point& point)
+{
+    m_backend->draw_text(text, font, point);
+}
+
+void window::poll()
+{
+    m_backend->poll(*this);
+}
+
+void window::handle_key_down(const key_event&)
+{
+}
+
+void window::handle_key_up(const key_event&)
+{
+}
+
+void window::handle_mouse_down(const mouse_click_event& ev)
+{
+    for (const auto& f : m_frames) {
+        if (is_frame_bound(*f, ev.pos)) {
+            f->layout()->handle_mouse_down({
+                ev.button,
+                point(ev.pos.x() - f->position().x(), ev.pos.y() - f->position().y())
+            });
+        }
+    }
+}
+
+void window::handle_mouse_up(const mouse_click_event&)
+{
+}
+
+void window::handle_mouse_wheel(const mouse_wheel_event&)
+{
+}
+
+void window::handle_quit()
+{
+    m_is_open = false;
+}
+
+window& window::operator=(window&&) noexcept = default;
+
+} // !client
+
+} // !mlk
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libclient/malikania/client/window.hpp	Sun Jan 22 11:07:36 2017 +0100
@@ -0,0 +1,354 @@
+/*
+ * window.hpp -- main window and basic drawing
+ *
+ * Copyright (c) 2013-2017 Malikania Authors
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef MALIKANIA_WINDOW_HPP
+#define MALIKANIA_WINDOW_HPP
+
+/**
+ * \file window.hpp
+ * \brief Window and drawing.
+ */
+
+#include <functional>
+#include <memory>
+#include <vector>
+#include <string>
+#include <unordered_set>
+
+#include "key.hpp"
+#include "mouse.hpp"
+#include "point.hpp"
+
+namespace mlk {
+
+namespace client {
+
+class color;
+class frame;
+class line;
+class font;
+class rectangle;
+class theme;
+
+/**
+ * \brief Describe key event.
+ */
+class key_event {
+public:
+    mlk::client::key key{key::unknown};         //!< layout-dependant key
+    mlk::client::key scancode{key::unknown};    //!< physical key
+    mlk::client::mod modifiers{mod::none};      //!< optional modifiers
+};
+
+/**
+ * \brief Describe mouse click event.
+ */
+class mouse_click_event {
+public:
+    mouse button{mouse::none};          //!< which mouse button
+    point pos;                          //!< current mouse position
+};
+
+/**
+ * \brief Describe a mouse motion event.
+ */
+class mouse_motion_event {
+public:
+    point pos;                          //!< current mouse position
+};
+
+/**
+ * \brief Describe mouse wheel (up/down) event.
+ */
+class mouse_wheel_event {
+public:
+    point pos;                          //!< current mouse position
+};
+
+/**
+ * \brief Main window class and drawing.
+ */
+class window {
+private:
+    class backend_impl;
+
+    std::unique_ptr<backend_impl> m_backend;
+    std::unique_ptr<mlk::client::theme> m_theme;
+    std::unordered_set<std::shared_ptr<frame>> m_frames;
+
+    bool m_is_open{true};
+
+    bool is_frame_bound(frame&, const point&) noexcept;
+
+public:
+    /**
+     * Create a window.
+     *
+     * \param width the initial width
+     * \param height the initial height
+     * \param title the optional title
+     * \throw std::runtime_error on errors
+     */
+    window(unsigned width = 640,
+           unsigned height = 480,
+           const std::string& title = "Malikania Engine");
+
+    /**
+     * Move constructor defaulted.
+     */
+    window(window&&) noexcept;
+
+    /**
+     * Virtual destructor defaulted.
+     */
+    virtual ~window() noexcept;
+
+    /**
+     * Tells if the window is open.
+     *
+     * \return true if open
+     */
+    inline bool is_open() const noexcept
+    {
+        return m_is_open;
+    }
+
+    /**
+     * Get the underlying backend.
+     *
+     * \return the backend
+     */
+    inline const backend_impl& backend() const noexcept
+    {
+        return *m_backend;
+    }
+
+    /**
+     * Overloaded function.
+     *
+     * \return the backend
+     */
+    inline backend_impl& backend() noexcept
+    {
+        return *m_backend;
+    }
+
+    void add_frame(std::shared_ptr<mlk::client::frame> frame)
+    {
+        m_frames.insert(std::move(frame));
+    }
+
+    void remove_frame(std::shared_ptr<mlk::client::frame> frame)
+    {
+        m_frames.erase(frame);
+    }
+
+    /**
+     * Get the current theme.
+     *
+     * \return the theme
+     */
+    inline const mlk::client::theme& theme() const noexcept
+    {
+        return *m_theme;
+    }
+
+    /**
+     * Overloaded function.
+     *
+     * \return the theme
+     */
+    inline mlk::client::theme& theme() noexcept
+    {
+        return *m_theme;
+    }
+
+    /**
+     * Clear the window content with the current drawing color.
+     */
+    void clear();
+
+    /**
+     * Render the content of the window to the screen.
+     */
+    void present();
+
+    /**
+     * Close the window.
+     */
+    void close() noexcept;
+
+    /**
+     * Get the current drawing color.
+     *
+     * \return the color
+     */
+    color drawing_color() const;
+
+    /**
+     * Set the drawing color.
+     *
+     * \param color the color
+     */
+    void set_drawing_color(const color& color);
+
+    /**
+     * Draw a line.
+     *
+     * \param line the line
+     */
+    void draw_line(const line& line);
+
+    /**
+     * Draw a several lines.
+     *
+     * \param the lines vertices
+     */
+    void draw_lines(const std::vector<point>& points);
+
+    /**
+     * Draw a point.
+     *
+     * \param point the point
+     */
+    void draw_point(const point& point);
+
+    /**
+     * Draw a list of points.
+     *
+     * \param points the points
+     */
+    void draw_points(const std::vector<point>& points);
+
+    /**
+     * Draw a rectangle (only borders).
+     *
+     * \param rect the rectangle
+     * \see fillRectangle
+     */
+    void draw_rectangle(const rectangle& rect);
+
+    /**
+     * Draw a list of rectangles.
+     *
+     * \param rects the rectangles
+     * \see fillRectangles
+     */
+    void draw_rectangles(const std::vector<rectangle>& rects);
+
+    /**
+     * Draw internal GUI frames.
+     */
+    void draw_frames();
+
+    /**
+     * Fill the given rectangle with the current color.
+     *
+     * \param rect the rectangle
+     * \see drawRectangle
+     */
+    void fill_rectangle(const rectangle& rect);
+
+    /**
+     * Fill the list of rectangles with the current color.
+     *
+     * \param rects the list of rectangles
+     * \see drawRectangles
+     */
+    void fill_rectangles(const std::vector<rectangle>& rects);
+
+    /**
+     * Draw some text.
+     *
+     * This function may stretch the text texture.
+     *
+     * \param text the text (UTF-8)
+     * \param font the font
+     * \param rectangle the rectangle target
+     */
+    void draw_text(const std::string& text, font& font, const rectangle& rectangle);
+
+    /**
+     * Overloaded function.
+     *
+     * Draw the text at the given position.
+     *
+     * \param text the text (UTF-8)
+     * \param font the font
+     * \param point the text position
+     */
+    void draw_text(const std::string& text, font& font, const point& point);
+
+    /**
+     * Poll all pending events and call appropriate functions.
+     */
+    void poll();
+
+    /**
+     * Key down event.
+     *
+     * \param ev the event
+     */
+    virtual void handle_key_down(const key_event& ev);
+
+    /**
+     * Key released event.
+     *
+     * \param ev the event
+     */
+    virtual void handle_key_up(const key_event& ev);
+
+    /**
+     * Mouse click event.
+     *
+     * \param ev the event
+     */
+    virtual void handle_mouse_down(const mouse_click_event& ev);
+
+    /**
+     * Mouse click release event.
+     *
+     * \param ev the event
+     */
+    virtual void handle_mouse_up(const mouse_click_event& ev);
+
+    /**
+     * Mouse wheel event.
+     *
+     * \param ev the event
+     */
+    virtual void handle_mouse_wheel(const mouse_wheel_event& ev);
+
+    /**
+     * Quit request.
+     */
+    virtual void handle_quit();
+
+    /**
+     * Move assigment operator defaulted.
+     *
+     * \return this
+     */
+    window& operator=(window&&) noexcept;
+};
+
+} // !client
+
+} // !mlk
+
+#endif // !MALIKANIA_WINDOW_HPP
--- a/libclient/malikania/client_resources_loader.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,138 +0,0 @@
-/*
- * client_resources_loader.cpp -- load shared resources files for the client
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <boost/format.hpp>
-
-#include <cassert>
-
-#include "animation.hpp"
-#include "client_resources_loader.hpp"
-#include "size.hpp"
-#include "sprite.hpp"
-#include "util.hpp"
-
-using boost::str;
-using boost::format;
-
-using mlk::util::json::invalid;
-
-namespace mlk {
-
-size client_resources_loader::require_size(const std::string& id,
-                                           const nlohmann::json& object,
-                                           const std::string& property) const
-{
-    assert(object.is_object());
-
-    auto it = object.find(property);
-
-    if (it == object.end() || !it->is_array()) {
-        throw std::runtime_error(str(format("%s: missing '%' property (array expected)") % id % property));
-    }
-    if (it->size() != 2) {
-        throw std::runtime_error(str(format("%s: property '%s' muve have two values") % id % property));
-    }
-    if (!(*it)[0].is_number_integer() || !(*it)[1].is_number_integer()) {
-        throw std::runtime_error(str(format("%s: property '%s' must contains two ints")));
-    }
-
-    return size((*it)[0].get<int>(), (*it)[1].get<int>());
-}
-
-size client_resources_loader::get_size(const std::string&,
-                                       const nlohmann::json& object,
-                                       const std::string& key) const noexcept
-{
-    assert(object.is_object());
-
-    auto it = object.find(key);
-
-    if (it == object.end() || !it->is_array() || it->size() != 2 ||
-        !(*it)[0].is_number_integer() || !(*it)[1].is_number_integer()) {
-        return size();
-    }
-
-    return size((*it)[0].get<int>(), (*it)[1].get<int>());
-}
-
-font client_resources_loader::load_font(const std::string& id, unsigned size)
-{
-    return font(locator().read(id), size);
-}
-
-image client_resources_loader::load_image(const std::string& id)
-{
-    return image(locator().read(id));
-}
-
-sprite client_resources_loader::load_sprite(const std::string& id)
-{
-    auto value = nlohmann::json::parse(locator().read(id));
-
-    if (!value.is_object()) {
-        throw std::runtime_error(id + ": not a JSON object");
-    }
-
-    return sprite(
-        load_image(require_string(id, value, "image")),
-        require_size(id, value, "cell"),
-        get_size(id, value, "size"),
-        get_size(id, value, "space"),
-        get_size(id, value, "margin")
-    );
-}
-
-animation client_resources_loader::load_animation(const std::string& id)
-{
-    auto value = nlohmann::json::parse(locator().read(id));
-
-    if (!value.is_object()) {
-        throw std::runtime_error("not a JSON object");
-    }
-
-    auto sprite = load_sprite(require_string(id, value, "sprite"));
-
-    // Load all frames.
-    auto property = value["frames"];
-
-    if (!property.is_array()) {
-        throw invalid(id, nlohmann::json::value_t::array);
-    }
-
-    animation_frames frames;
-    int index = 0;
-
-    for (auto it = property.begin(); it != property.end(); ++it) {
-        if (!it->is_object()) {
-            throw std::runtime_error(id + ": frame " + std::to_string(index) + ": not a JSON object");
-        }
-
-        auto delay = it->find("delay");
-
-        if (delay == it->end() || !delay->is_number_integer()) {
-            throw std::runtime_error(id + ": frame " + std::to_string(index) +
-                ": missing 'delay' property (int expected)");
-        }
-
-        frames.emplace_back(delay->get<int>());
-    }
-
-    return animation(std::move(sprite), std::move(frames));
-}
-
-} // !mlk
--- a/libclient/malikania/client_resources_loader.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-/*
- * client_resources_loader.hpp -- load shared resources files for the client
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_CLIENT_RESOURCES_LOADER_HPP
-#define MALIKANIA_CLIENT_RESOURCES_LOADER_HPP
-
-/*
- * \file client_resources_loader.hpp
- * \brief Load client assets.
- */
-
-#include <malikania/loader.hpp>
-
-#include "animation.hpp"
-#include "font.hpp"
-#include "image.hpp"
-#include "size.hpp"
-#include "sprite.hpp"
-
-namespace mlk {
-
-/**
- * \brief Load client resources.
- */
-class client_resources_loader : public loader {
-protected:
-    /**
-     * Require a size object from an object property.
-     *
-     * The size is an array of two integers (e.g. [ 1, 2 ]).
-     *
-     * \pre object.is_object()
-     * \param id the resource id
-     * \param object the object
-     * \param property the property
-     * \return the size
-     * \throw std::runtime_error if the property is not a size
-     */
-    size require_size(const std::string& id,
-                      const nlohmann::json& object,
-                      const std::string& property) const;
-
-    /**
-     * Get a size object or a default one if not present or invalid.
-     *
-     * \pre object.is_object()
-     * \param id the resource id
-     * \param object the object
-     * \param property the property
-     * \return the size or default one
-     */
-    size get_size(const std::string& id,
-                  const nlohmann::json& object,
-                  const std::string& property) const noexcept;
-
-public:
-    /**
-     * Client resources loader constructor.
-     *
-     * The window is required because some of the resources require it.
-     *
-     * \param window the window
-     * \param locator the resources locator
-     */
-    inline client_resources_loader(mlk::locator& locator)
-        : loader(locator)
-    {
-    }
-
-    /**
-     * Load a font.
-     *
-     * \param id the resource id
-     * \param size the desired size
-     * \return the font
-     * \throw std::runtime_error on errors
-     */
-    virtual font load_font(const std::string& id, unsigned size);
-
-    /**
-     * Load an image.
-     *
-     * \param id the resource id
-     * \return the image
-     * \throw std::runtime_error on errors
-     */
-    virtual image load_image(const std::string& id);
-
-    /**
-     * Load a sprite.
-     *
-     * \param id the resource id
-     * \return the sprite
-     * \throw std::runtime_error on errors
-     */
-    virtual sprite load_sprite(const std::string& id);
-
-    /**
-     * Load an animation.
-     *
-     * \param id the resource id
-     * \return the animation
-     * \throw std::runtime_error on errors
-     */
-    virtual animation load_animation(const std::string& id);
-};
-
-} // !mlk
-
-#endif // !MALIKANIA_CLIENT_RESOURCES_LOADER_HPP
--- a/libclient/malikania/color.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,237 +0,0 @@
-/*
- * color.cpp -- color description
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <cctype>
-#include <locale>
-#include <unordered_map>
-
-#include "color.hpp"
-
-namespace mlk {
-
-namespace {
-
-constexpr unsigned rgb(std::uint8_t r, std::uint8_t g, std::uint8_t b) noexcept
-{
-    return (0xff000000 | (r << 16) | (g << 8) | b);
-}
-
-/*
- * Convert hexadecimal value to the correct number.
- */
-std::uint8_t value(char digit)
-{
-    if (std::isdigit(digit, {})) {
-        return digit - '0';
-    }
-    if ((digit = std::toupper(digit, {})) < 'A' || digit > 'F') {
-        throw std::invalid_argument("invalid hexadecimal value: " + std::to_string(digit));
-    }
-
-    return digit - 55;
-}
-
-inline std::uint8_t value(char digit1, char digit2)
-{
-    return ((value(digit1) << 4) & 0xf0) | value(digit2);
-}
-
-const std::unordered_map<std::string, std::uint32_t> colors{
-    { "aliceblue",              rgb(240, 248, 255)  },
-    { "antiquewhite",           rgb(250, 235, 215)  },
-    { "aqua",                   rgb( 0, 255, 255)   },
-    { "aquamarine",             rgb(127, 255, 212)  },
-    { "azure",                  rgb(240, 255, 255)  },
-    { "beige",                  rgb(245, 245, 220)  },
-    { "bisque",                 rgb(255, 228, 196)  },
-    { "black",                  rgb( 0, 0, 0)       },
-    { "blanchedalmond",         rgb(255, 235, 205)  },
-    { "blue",                   rgb( 0, 0, 255)     },
-    { "blueviolet",             rgb(138, 43, 226)   },
-    { "brown",                  rgb(165, 42, 42)    },
-    { "burlywood",              rgb(222, 184, 135)  },
-    { "cadetblue",              rgb( 95, 158, 160)  },
-    { "chartreuse",             rgb(127, 255, 0)    },
-    { "chocolate",              rgb(210, 105, 30)   },
-    { "coral",                  rgb(255, 127, 80)   },
-    { "cornflowerblue",         rgb(100, 149, 237)  },
-    { "cornsilk",               rgb(255, 248, 220)  },
-    { "crimson",                rgb(220, 20, 60)    },
-    { "cyan",                   rgb( 0, 255, 255)   },
-    { "darkblue",               rgb( 0, 0, 139)     },
-    { "darkcyan",               rgb( 0, 139, 139)   },
-    { "darkgoldenrod",          rgb(184, 134, 11)   },
-    { "darkgray",               rgb(169, 169, 169)  },
-    { "darkgreen",              rgb( 0, 100, 0)     },
-    { "darkgrey",               rgb(169, 169, 169)  },
-    { "darkkhaki",              rgb(189, 183, 107)  },
-    { "darkmagenta",            rgb(139, 0, 139)    },
-    { "darkolivegreen",         rgb( 85, 107, 47)   },
-    { "darkorange",             rgb(255, 140, 0)    },
-    { "darkorchid",             rgb(153, 50, 204)   },
-    { "darkred",                rgb(139, 0, 0)      },
-    { "darksalmon",             rgb(233, 150, 122)  },
-    { "darkseagreen",           rgb(143, 188, 143)  },
-    { "darkslateblue",          rgb( 72, 61, 139)   },
-    { "darkslategray",          rgb( 47, 79, 79)    },
-    { "darkslategrey",          rgb( 47, 79, 79)    },
-    { "darkturquoise",          rgb( 0, 206, 209)   },
-    { "darkviolet",             rgb(148, 0, 211)    },
-    { "deeppink",               rgb(255, 20, 147)   },
-    { "deepskyblue",            rgb( 0, 191, 255)   },
-    { "dimgray",                rgb(105, 105, 105)  },
-    { "dimgrey",                rgb(105, 105, 105)  },
-    { "dodgerblue",             rgb( 30, 144, 255)  },
-    { "firebrick",              rgb(178, 34, 34)    },
-    { "floralwhite",            rgb(255, 250, 240)  },
-    { "forestgreen",            rgb( 34, 139, 34)   },
-    { "fuchsia",                rgb(255, 0, 255)    },
-    { "gainsboro",              rgb(220, 220, 220)  },
-    { "ghostwhite",             rgb(248, 248, 255)  },
-    { "gold",                   rgb(255, 215, 0)    },
-    { "goldenrod",              rgb(218, 165, 32)   },
-    { "gray",                   rgb(128, 128, 128)  },
-    { "green",                  rgb( 0, 128, 0)     },
-    { "greenyellow",            rgb(173, 255, 47)   },
-    { "grey",                   rgb(128, 128, 128)  },
-    { "honeydew",               rgb(240, 255, 240)  },
-    { "hotpink",                rgb(255, 105, 180)  },
-    { "indianred",              rgb(205, 92, 92)    },
-    { "indigo",                 rgb( 75, 0, 130)    },
-    { "ivory",                  rgb(255, 255, 240)  },
-    { "khaki",                  rgb(240, 230, 140)  },
-    { "lavender",               rgb(230, 230, 250)  },
-    { "lavenderblush",          rgb(255, 240, 245)  },
-    { "lawngreen",              rgb(124, 252, 0)    },
-    { "lemonchiffon",           rgb(255, 250, 205)  },
-    { "lightblue",              rgb(173, 216, 230)  },
-    { "lightcoral",             rgb(240, 128, 128)  },
-    { "lightcyan",              rgb(224, 255, 255)  },
-    { "lightgoldenrodyellow",   rgb(250, 250, 210)  },
-    { "lightgray",              rgb(211, 211, 211)  },
-    { "lightgreen",             rgb(144, 238, 144)  },
-    { "lightgrey",              rgb(211, 211, 211)  },
-    { "lightpink",              rgb(255, 182, 193)  },
-    { "lightsalmon",            rgb(255, 160, 122)  },
-    { "lightseagreen",          rgb( 32, 178, 170)  },
-    { "lightskyblue",           rgb(135, 206, 250)  },
-    { "lightslategray",         rgb(119, 136, 153)  },
-    { "lightslategrey",         rgb(119, 136, 153)  },
-    { "lightsteelblue",         rgb(176, 196, 222)  },
-    { "lightyellow",            rgb(255, 255, 224)  },
-    { "lime",                   rgb( 0, 255, 0)     },
-    { "limegreen",              rgb( 50, 205, 50)   },
-    { "linen",                  rgb(250, 240, 230)  },
-    { "magenta",                rgb(255, 0, 255)    },
-    { "maroon",                 rgb(128, 0, 0)      },
-    { "mediumaquamarine",       rgb(102, 205, 170)  },
-    { "mediumblue",             rgb( 0, 0, 205)     },
-    { "mediumorchid",           rgb(186, 85, 211)   },
-    { "mediumpurple",           rgb(147, 112, 219)  },
-    { "mediumseagreen",         rgb( 60, 179, 113)  },
-    { "mediumslateblue",        rgb(123, 104, 238)  },
-    { "mediumspringgreen",      rgb( 0, 250, 154)   },
-    { "mediumturquoise",        rgb( 72, 209, 204)  },
-    { "mediumvioletred",        rgb(199, 21, 133)   },
-    { "midnightblue",           rgb( 25, 25, 112)   },
-    { "mintcream",              rgb(245, 255, 250)  },
-    { "mistyrose",              rgb(255, 228, 225)  },
-    { "moccasin",               rgb(255, 228, 181)  },
-    { "navajowhite",            rgb(255, 222, 173)  },
-    { "navy",                   rgb( 0, 0, 128)     },
-    { "oldlace",                rgb(253, 245, 230)  },
-    { "olive",                  rgb(128, 128, 0)    },
-    { "olivedrab",              rgb(107, 142, 35)   },
-    { "orange",                 rgb(255, 165, 0)    },
-    { "orangered",              rgb(255, 69, 0)     },
-    { "orchid",                 rgb(218, 112, 214)  },
-    { "palegoldenrod",          rgb(238, 232, 170)  },
-    { "palegreen",              rgb(152, 251, 152)  },
-    { "paleturquoise",          rgb(175, 238, 238)  },
-    { "palevioletred",          rgb(219, 112, 147)  },
-    { "papayawhip",             rgb(255, 239, 213)  },
-    { "peachpuff",              rgb(255, 218, 185)  },
-    { "peru",                   rgb(205, 133, 63)   },
-    { "pink",                   rgb(255, 192, 203)  },
-    { "plum",                   rgb(221, 160, 221)  },
-    { "powderblue",             rgb(176, 224, 230)  },
-    { "purple",                 rgb(128, 0, 128)    },
-    { "red",                    rgb(255, 0, 0)      },
-    { "rosybrown",              rgb(188, 143, 143)  },
-    { "royalblue",              rgb( 65, 105, 225)  },
-    { "saddlebrown",            rgb(139, 69, 19)    },
-    { "salmon",                 rgb(250, 128, 114)  },
-    { "sandybrown",             rgb(244, 164, 96)   },
-    { "seagreen",               rgb( 46, 139, 87)   },
-    { "seashell",               rgb(255, 245, 238)  },
-    { "sienna",                 rgb(160, 82, 45)    },
-    { "silver",                 rgb(192, 192, 192)  },
-    { "skyblue",                rgb(135, 206, 235)  },
-    { "slateblue",              rgb(106, 90, 205)   },
-    { "slategray",              rgb(112, 128, 144)  },
-    { "slategrey",              rgb(112, 128, 144)  },
-    { "snow",                   rgb(255, 250, 250)  },
-    { "springgreen",            rgb( 0, 255, 127)   },
-    { "steelblue",              rgb( 70, 130, 180)  },
-    { "tan",                    rgb(210, 180, 140)  },
-    { "teal",                   rgb( 0, 128, 128)   },
-    { "thistle",                rgb(216, 191, 216)  },
-    { "tomato",                 rgb(255, 99, 71)    },
-    { "transparent",            0                   },
-    { "turquoise",              rgb( 64, 224, 208)  },
-    { "violet",                 rgb(238, 130, 238)  },
-    { "wheat",                  rgb(245, 222, 179)  },
-    { "white",                  rgb(255, 255, 255)  },
-    { "whitesmoke",             rgb(245, 245, 245)  },
-    { "yellow",                 rgb(255, 255, 0)    },
-    { "yellowgreen",            rgb(154, 205, 50)   }
-};
-
-} // !namespace
-
-color::color(const std::string& name)
-{
-    if (!name.empty()) {
-        // Parse #rrggbb or #rgb.
-        if (name[0] == '#') {
-            if (name.length() == 7) {
-                m_red   = value(name[1], name[2]);
-                m_green = value(name[3], name[4]);
-                m_blue  = value(name[5], name[6]);
-            } else if (name.length() == 4) {
-                m_red   = value(name[1], name[1]);
-                m_green = value(name[2], name[2]);
-                m_blue  = value(name[3], name[3]);
-            } else {
-                throw std::invalid_argument("invalid format");
-            }
-        } else {
-            // Name lookup.
-            auto it = colors.find(name);
-
-            if (it == colors.end()) {
-                throw std::invalid_argument(name + " is not a valid color");
-            }
-
-            // Assign the color to *this.
-            *this = it->second;
-        }
-    }
-}
-
-} // !mlk
--- a/libclient/malikania/color.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-/*
- * color.hpp -- color description
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_COLOR_HPP
-#define MALIKANIA_COLOR_HPP
-
-/**
- * \file color.hpp
- * \brief Colors.
- */
-
-#include <cstdint>
-#include <string>
-
-namespace mlk {
-
-/**
- * \brief color description
- */
-class color {
-private:
-    std::uint8_t m_red{0};
-    std::uint8_t m_green{0};
-    std::uint8_t m_blue{0};
-    std::uint8_t m_alpha{255};
-
-public:
-    /**
-     * Default color to black.
-     */
-    inline color() noexcept = default;
-
-    /**
-     * Constructor with all fields.
-     *
-     * \param red the red value
-     * \param green the green value
-     * \param blue the blue value
-     * \param alpha the alpha value
-     */
-    inline color(std::uint8_t red, std::uint8_t green, std::uint8_t blue, std::uint8_t alpha) noexcept
-        : m_red(red)
-        , m_green(green)
-        , m_blue(blue)
-        , m_alpha(alpha)
-    {
-    }
-
-    /**
-     * Constructor with an hexadecimal value.
-     *
-     * \param hex the color
-     */
-    inline color(std::uint32_t hex) noexcept
-        : m_red((hex >> 16) & 0xff)
-        , m_green((hex >> 8) & 0xff)
-        , m_blue(hex & 0xff)
-        , m_alpha((hex >> 24) & 0xff)
-    {
-    }
-
-    /**
-     * Construct a color from #rrggbb or name.
-     *
-     * See the SVG this [list](http://www.december.com/html/spec/colorsvg.html) for supported names.
-     *
-     * \param name the color name
-     * \throw std::invalid_argument if the color does not exist or is invalid
-     */
-    color(const std::string& name);
-
-    /**
-     * Get the red value.
-     *
-     * \return the value
-     */
-    inline std::uint8_t red() const noexcept
-    {
-        return m_red;
-    }
-
-    /**
-     * Get the green value.
-     *
-     * \return the value
-     */
-    inline std::uint8_t green() const noexcept
-    {
-        return m_green;
-    }
-
-    /**
-     * Get the blue value.
-     *
-     * \return the value
-     */
-    inline std::uint8_t blue() const noexcept
-    {
-        return m_blue;
-    }
-
-    /**
-     * Get the alpha value.
-     *
-     * \return the value
-     */
-    inline std::uint8_t alpha() const noexcept
-    {
-        return m_alpha;
-    }
-};
-
-} // !mlk
-
-#endif // !MALIKANIA_COLOR_HPP
--- a/libclient/malikania/font.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-/*
- * font.cpp -- font object
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "font_backend.hpp"
-
-namespace mlk {
-
-font::font(std::string data, unsigned size)
-    : m_backend(std::make_unique<backend_impl>(std::move(data), size))
-    , m_size(size)
-{
-}
-
-font::font(font&& other) noexcept = default;
-
-font::~font() noexcept = default;
-
-size font::clip(const std::string& text) const
-{
-    return m_backend->clip(*this, text);
-}
-
-font& font::operator=(font&& other) noexcept = default;
-
-} // !mlk
--- a/libclient/malikania/font.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,114 +0,0 @@
-/*
- * font.hpp -- font object
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_FONT_HPP
-#define MALIKANIA_FONT_HPP
-
-/**
- * \file font.hpp
- * \brief fonts.
- */
-
-#include <memory>
-#include <string>
-
-#include "size.hpp"
-
-namespace mlk {
-
-/**
- * \brief font object.
- */
-class font {
-private:
-    class backend_impl;
-
-    std::unique_ptr<backend_impl> m_backend;
-    unsigned m_size;
-
-public:
-    /**
-     * Construct a font from binary data.
-     *
-     * \param data the raw data
-     * \param size the size
-     */
-    font(std::string data, unsigned size);
-
-    /**
-     * Default move constructor.
-     *
-     * \param other the other font
-     */
-    font(font&& other) noexcept;
-
-    /**
-     * Default destructor.
-     */
-    virtual ~font() noexcept;
-
-    /**
-     * Get the font size.
-     *
-     * \return the font size
-     */
-    inline unsigned size() const noexcept
-    {
-        return m_size;
-    }
-
-    /**
-     * Get the underlying backend.
-     *
-     * \return the backend
-     */
-    inline const backend_impl& backend() const noexcept
-    {
-        return *m_backend;
-    }
-
-    /**
-     * Overloaded function.
-     *
-     * \return the backend
-     */
-    inline backend_impl& backend() noexcept
-    {
-        return *m_backend;
-    }
-
-    /**
-     * Get the clipping size required to draw the given text.
-     *
-     * \param text the text to clip
-     * \return the required size
-     */
-    mlk::size clip(const std::string& text) const;
-
-    /**
-     * Default move assignment operator.
-     *
-     * \param other the other font
-     * \return this
-     */
-    font& operator=(font&& other) noexcept;
-};
-
-} // !mlk
-
-#endif // MALIKANIA_FONT_HPP
--- a/libclient/malikania/frame.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * frame.cpp -- top level GUI frame
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "layout.hpp"
-#include "frame.hpp"
-#include "point.hpp"
-#include "rectangle.hpp"
-#include "theme.hpp"
-#include "window.hpp"
-
-namespace mlk {
-
-mlk::size frame::size(window &win)
-{
-    return m_layout ? m_layout->size(win) : mlk::size();
-}
-
-void frame::draw(window& win)
-{
-    if (m_layout) {
-        win.theme().draw_frame(win, *this);
-    }
-}
-
-void frame::move(point pos)
-{
-    m_position = std::move(pos);
-}
-
-} // !mlk
--- a/libclient/malikania/frame.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,174 +0,0 @@
-/*
- * frame.hpp -- top level GUI frame
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_CLIENT_FRAME_HPP
-#define MALIKANIA_CLIENT_FRAME_HPP
-
-/**
- * \file frame.hpp
- * \brief Top level GUI frame.
- */
-
-#include <memory>
-
-#include "point.hpp"
-#include "size.hpp"
-
-namespace mlk {
-
-class layout;
-class point;
-class window;
-
-/**
- * \brief Top level GUI frame.
- */
-class frame {
-private:
-    std::shared_ptr<mlk::layout> m_layout;
-    mlk::point m_position;
-    mlk::size m_padding{10, 10};
-
-public:
-    /**
-     * Create a frame with an optional layout.
-     *
-     * \param layout the optional layout
-     */
-    inline frame(std::shared_ptr<mlk::layout> layout = nullptr) noexcept
-        : m_layout(std::move(layout))
-    {
-    }
-
-    /**
-     * Virtual destructor defaulted.
-     */
-    virtual ~frame() = default;
-
-    /**
-     * Get the current layout.
-     *
-     * return the layout
-     */
-    inline const std::shared_ptr<mlk::layout>& layout() const noexcept
-    {
-        return m_layout;
-    }
-
-    /**
-     * Overloaded function.
-     *
-     * \return the layout
-     */
-    inline std::shared_ptr<mlk::layout>& layout() noexcept
-    {
-        return m_layout;
-    }
-
-    /**
-     * Change the current frame layout.
-     *
-     * \param layout the new layout (may be null)
-     */
-    inline void set_layout(std::shared_ptr<mlk::layout> layout) noexcept
-    {
-        m_layout = std::move(layout);
-    }
-
-    /**
-     * Get the current frame position.
-     *
-     * \return the frame position
-     */
-    inline const point& position() const noexcept
-    {
-        return m_position;
-    }
-
-    /**
-     * Overloaded function.
-     *
-     * \return the position
-     */
-    inline point& position() noexcept
-    {
-        return m_position;
-    }
-
-    /**
-     * Get the frame padding.
-     *
-     * \return the frame padding
-     */
-    inline const mlk::size& padding() const noexcept
-    {
-        return m_padding;
-    }
-
-    /**
-     * Overloaded function.
-     *
-     * \return the padding
-     */
-    inline mlk::size& padding() noexcept
-    {
-        return m_padding;
-    }
-
-    /**
-     * Set the frame padding.
-     *
-     * \param padding the padding
-     */
-    inline void set_padding(mlk::size padding) noexcept
-    {
-        m_padding = std::move(padding);
-    }
-
-    /**
-     * Compute the total frame size.
-     *
-     * If no layout is attached, the frame returns a null size. Otherwise, the
-     * default implementation returns `layout()->size()`.
-     *
-     * \param win the window
-     * \return the size required to draw this frame
-     */
-    virtual mlk::size size(window& win);
-
-    /**
-     * Draw the frame and its content.
-     *
-     * If no layout is attached, the function is a no-op. Otherwise the default
-     * implementation calls `win.theme().draw_frame(*this)`.
-     *
-     * \param win the window
-     */
-    virtual void draw(window& win);
-
-    /**
-     * Move the frame to somewhere else.
-     *
-     * \param pos the new position
-     */
-    virtual void move(point pos);
-};
-
-} // !mlk
-
-#endif // !MALIKANIA_CLIENT_FRAME_HPP
--- a/libclient/malikania/grid_layout.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * grid_layout.cpp -- basic grid layout
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <algorithm>
-#include <numeric>
-
-#include "grid_layout.hpp"
-#include "size.hpp"
-#include "widget.hpp"
-
-namespace mlk {
-
-unsigned grid_layout::index(unsigned r, unsigned c) const noexcept
-{
-    return r * m_cols + c;
-}
-
-void grid_layout::update_rsize(window& win) noexcept
-{
-    for (unsigned r = 0; r < m_rows; ++r) {
-        m_min_rsize[r] = 0;
-
-        for (unsigned c = 0; c < m_cols; ++c) {
-            auto idx = index(r, c);
-
-            if (!m_widgets[idx]) {
-                continue;
-            }
-
-            auto size = m_widgets[index(r, c)]->size(win);
-
-            if (size.height() > m_min_rsize[r]) {
-                m_min_rsize[r] = size.height();
-            }
-        }
-    }
-}
-
-void grid_layout::update_csize(window& win) noexcept
-{
-    for (unsigned c = 0; c < m_cols; ++c) {
-        m_min_csize[c] = 0;
-
-        for (unsigned r = 0; r < m_rows; ++r) {
-            auto idx = index(r, c);
-
-            if (!m_widgets[idx]) {
-                continue;
-            }
-
-            auto size = m_widgets[index(r, c)]->size(win);
-
-            if (size.width() > m_min_csize[c]) {
-                m_min_csize[c] = size.width();
-            }
-        }
-    }
-}
-
-grid_layout::grid_layout(unsigned rows, unsigned columns)
-    : m_rows(rows)
-    , m_cols(columns)
-{
-    m_widgets.resize(rows * columns);
-    m_min_rsize.resize(rows);
-    m_min_csize.resize(columns);
-}
-
-void grid_layout::add_widget(unsigned r, unsigned c, std::shared_ptr<widget> w)
-{
-    m_widgets[index(r, c)] = std::move(w);
-}
-
-void grid_layout::remove_widget(unsigned r, unsigned c)
-{
-    m_widgets[index(r, c)] = nullptr;
-}
-
-void grid_layout::remove_widget(std::shared_ptr<widget> w)
-{
-    m_widgets.erase(std::remove(m_widgets.begin(), m_widgets.end(), w), m_widgets.end());
-}
-
-mlk::size grid_layout::size(window& win) const noexcept
-{
-    return {
-        std::accumulate(m_min_csize.begin(), m_min_csize.end(), 0) + (m_rows * 10),
-        std::accumulate(m_min_rsize.begin(), m_min_rsize.end(), 0) + (m_cols * 10)
-    };
-}
-
-void grid_layout::draw(window &win, const rectangle &dst)
-{
-
-}
-
-} // !mlk
--- a/libclient/malikania/grid_layout.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +0,0 @@
-/*
- * grid_layout.hpp -- basic grid layout
- *
- * Copyright (c) 2013-2016 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_CLIENT_GRID_LAYOUT_HPP
-#define MALIKANIA_CLIENT_GRID_LAYOUT_HPP
-
-#include <memory>
-#include <vector>
-
-#include "layout.hpp"
-
-namespace mlk {
-
-class widget;
-
-class grid_layout : public layout {
-private:
-    // Dimensions.
-    unsigned m_rows;
-    unsigned m_cols;
-
-    // Widgets.
-    std::vector<std::shared_ptr<widget>> m_widgets;
-
-    /*
-     * Track maximum size by rows/columns to determine the minimum whole
-     * layout size.
-     *
-     * It's only used in draw() but kept as member variables to avoid useless
-     * reallocation on each frame.
-     */
-    std::vector<unsigned> m_min_rsize;
-    std::vector<unsigned> m_min_csize;
-
-    unsigned index(unsigned, unsigned) const noexcept;
-    void update_rsize(window&) noexcept;
-    void update_csize(window&) noexcept;
-
-public:
-    grid_layout(unsigned rows, unsigned columns);
-
-    void add_widget(unsigned r, unsigned c, std::shared_ptr<widget> w);
-
-    void remove_widget(unsigned r, unsigned c);
-
-    void remove_widget(std::shared_ptr<widget> w);
-
-    mlk::size size(window& win) const noexcept override;
-
-    void draw(window& win, const rectangle& dst) override;
-};
-
-} // !mlk
-
-#endif // !MALIKANIA_CLIENT_GRID_LAYOUT_HPP
--- a/libclient/malikania/image.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,49 +0,0 @@
-/*
- * image.cpp -- image object
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "image_backend.hpp"
-
-namespace mlk {
-
-image::image(std::string data)
-    : m_backend(new backend_impl(*this, std::move(data)))
-{
-}
-
-image::image(image&&) noexcept = default;
-
-image::~image() noexcept = default;
-
-const mlk::size& image::size() const noexcept
-{
-    return m_backend->size();
-}
-
-void image::draw(window& window, const point& position)
-{
-    m_backend->draw(window, position);
-}
-
-void image::draw(window& window, const rectangle& source, const rectangle& target)
-{
-    m_backend->draw(window, source, target);
-}
-
-image& image::operator=(image&&) noexcept = default;
-
-} // !mlk
--- a/libclient/malikania/image.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,123 +0,0 @@
-/*
- * image.hpp -- image object
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_IMAGE_HPP
-#define MALIKANIA_IMAGE_HPP
-
-/**
- * \file image.hpp
- * \brief Images.
- */
-
-#include <memory>
-#include <string>
-
-#include "point.hpp"
-#include "rectangle.hpp"
-#include "size.hpp"
-
-namespace mlk {
-
-class window;
-
-/**
- * \brief Image object.
- */
-class image {
-private:
-    class backend_impl;
-
-    std::unique_ptr<backend_impl> m_backend;
-
-public:
-    /**
-     * Construct an image from the binary data.
-     *
-     * \param window the window
-     * \param data the data
-     */
-    image(std::string data);
-
-    /**
-     * Default move constructor.
-     *
-     * \param other the other image
-     */
-    image(image&& other) noexcept;
-
-    /**
-     * Default destructor.
-     */
-    ~image() noexcept;
-
-    /**
-     * Overloaded function.
-     *
-     * \return the backend
-     */
-    inline class backend_impl& backend() noexcept
-    {
-        return *m_backend;
-    }
-
-    /**
-     * Get the underlying backend.
-     *
-     * \return the backend
-     */
-    inline const backend_impl& backend() const noexcept
-    {
-        return *m_backend;
-    }
-
-    /**
-     * Get the image size.
-     *
-     * \return the size
-     */
-    const mlk::size& size() const noexcept;
-
-    /**
-     * Draw the image to the window.
-     *
-     * \param window the window
-     * \param position the position
-     */
-    void draw(window& window, const point& position = {0, 0});
-
-    /**
-     * Overloaded function.
-     *
-     * \param window the window
-     * \param source the source to clip
-     * \param target the target destination
-     */
-    void draw(window& window, const rectangle& source, const rectangle& target);
-
-    /**
-     * Default move assignment operator.
-     *
-     * \param other the other image
-     * \return this
-     */
-    image& operator=(image&& image) noexcept;
-};
-
-} // !mlk
-
-#endif // !MALIKANIA_IMAGE_HPP
--- a/libclient/malikania/key.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,244 +0,0 @@
-/*
- * key.hpp -- key definitions
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_CLIENT_KEY_HPP
-#define MALIKANIA_CLIENT_KEY_HPP
-
-namespace mlk {
-
-/**
- * \brief Describe keyboard modifiers
- *
- * This enumeration is a satisfied the Bitmask concept.
- */
-enum class mod {
-    none            = 0,                //!< no modifiers
-    left_control    = (1 << 1),         //!< left control
-    left_alt        = (1 << 2),         //!< left alt
-    left_shift      = (1 << 3),         //!< left shift
-    left_super      = (1 << 4),         //!< left logo
-    right_control   = (1 << 5),         //!< right control
-    right_alt       = (1 << 6),         //!< right alt
-    right_shift     = (1 << 7),         //!< right shift
-    right_super     = (1 << 8),         //!< right logo
-    num_lock        = (1 << 9),         //!< num lock is on
-    caps_lock       = (1 << 10),        //!< caps lock is on
-    control         = left_control |    //!< left or right control
-                      right_control,
-    shift           = left_shift |      //!< left or right shift
-                      right_shift,
-    alt             = left_alt |        //!< left or right alt
-                      right_alt,
-    super           = left_super |      //!< left or right super
-                      right_super
-};
-
-/**
- * \cond ENUM_HIDDEN_SYMBOLS
- */
-
-inline mod operator^(mod v1, mod v2) noexcept
-{
-    return static_cast<mod>(static_cast<unsigned>(v1) ^ static_cast<unsigned>(v2));
-}
-
-inline mod operator&(mod v1, mod v2) noexcept
-{
-    return static_cast<mod>(static_cast<unsigned>(v1)&  static_cast<unsigned>(v2));
-}
-
-inline mod operator|(mod v1, mod v2) noexcept
-{
-    return static_cast<mod>(static_cast<unsigned>(v1) | static_cast<unsigned>(v2));
-}
-
-inline mod operator~(mod v) noexcept
-{
-    return static_cast<mod>(~static_cast<unsigned>(v));
-}
-
-inline mod& operator|=(mod& v1, mod v2) noexcept
-{
-    v1 = static_cast<mod>(static_cast<unsigned>(v1) | static_cast<unsigned>(v2));
-
-    return v1;
-}
-
-inline mod& operator&=(mod& v1, mod v2) noexcept
-{
-    v1 = static_cast<mod>(static_cast<unsigned>(v1)&  static_cast<unsigned>(v2));
-
-    return v1;
-}
-
-inline mod& operator^=(mod& v1, mod v2) noexcept
-{
-    v1 = static_cast<mod>(static_cast<unsigned>(v1) ^ static_cast<unsigned>(v2));
-
-    return v1;
-}
-
-/**
- * \endcond
- */
-
-/**
- * \brief Key description.
- */
-enum class key {
-    unknown,
-    a,
-    b,
-    c,
-    d,
-    e,
-    f,
-    g,
-    h,
-    i,
-    j,
-    k,
-    l,
-    m,
-    n,
-    o,
-    p,
-    q,
-    r,
-    s,
-    t,
-    u,
-    v,
-    w,
-    x,
-    y,
-    z,
-    exclaim,
-    double_quote,
-    percent,
-    dollar,
-    ampersand,
-    left_parenthese,
-    right_parenthese,
-    asterisk,
-    plus,
-    colon,
-    less,
-    greater,
-    question,
-    at,
-    caret,
-    underscore,
-    back_quote,
-    quote,
-    one,
-    two,
-    three,
-    four,
-    five,
-    six,
-    seven,
-    eight,
-    nine,
-    zero,
-    enter,
-    escape,
-    backspace,
-    tab,
-    space,
-    minus,
-    equals,
-    left_bracket,
-    right_bracket,
-    backslash,
-    hash,
-    semicolon,
-    apostrophe,
-    grave,
-    comma,
-    period,
-    slash,
-    caps_lock,
-    f1,
-    f2,
-    f3,
-    f4,
-    f5,
-    f6,
-    f7,
-    f8,
-    f9,
-    f10,
-    f11,
-    f12,
-    f13,
-    f14,
-    f15,
-    f16,
-    f17,
-    f18,
-    f19,
-    f20,
-    f21,
-    f22,
-    f23,
-    f24,
-    print_screen,
-    scroll_lock,
-    pause,
-    insert,
-    home,
-    page_up,
-    page_down,
-    del,
-    end,
-    right,
-    left,
-    down,
-    up,
-    kp_divide,
-    kp_multiply,
-    kp_minus,
-    kp_plus,
-    kp_enter,
-    kp_one,
-    kp_two,
-    kp_three,
-    kp_four,
-    kp_five,
-    kp_six,
-    kp_seven,
-    kp_eight,
-    kp_nine,
-    kp_zero,
-    mute,
-    volume_up,
-    volume_down,
-    left_control,
-    left_alt,
-    left_shift,
-    left_super,
-    right_control,
-    right_alt,
-    right_shift,
-    right_super
-};
-
-} // !mlk
-
-#endif // !MALIKANIA_CLIENT_KEY_HPP
--- a/libclient/malikania/label.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * label.cpp -- GUI label element
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "label.hpp"
-#include "size.hpp"
-#include "theme.hpp"
-#include "window.hpp"
-
-namespace mlk {
-
-label::label(std::string text) noexcept
-    : m_text(std::move(text))
-{
-}
-
-void label::draw(window& w, const rectangle& rect)
-{
-    w.theme().draw_label(w, *this, rect);
-}
-
-mlk::size label::size(window& w) const noexcept
-{
-    return w.theme().size_label(*this);
-}
-
-} // !mlk
--- a/libclient/malikania/label.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * label.hpp -- GUI label element
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_CLIENT_LABEL_HPP
-#define MALIKANIA_CLIENT_LABEL_HPP
-
-/**
- * \file label.hp
- * \brief GUI label element.
- */
-
-#include <string>
-
-#include "widget.hpp"
-
-namespace mlk {
-
-/**
- * \brief Basic label for displaying test.
- */
-class label : public widget {
-private:
-    std::string m_text;
-
-public:
-    /**
-     * Create a label with an optional text.
-     *
-     * \param text the text
-     */
-    label(std::string text = "") noexcept;
-
-    /**
-     * Get the text.
-     *
-     * \return the label text
-     */
-    inline const std::string& text() const noexcept
-    {
-        return m_text;
-    }
-
-    /**
-     * Overloaded function.
-     *
-     * \return the text
-     */
-    inline std::string& text() noexcept
-    {
-        return m_text;
-    }
-
-    /**
-     * Set the label text.
-     *
-     * \param text the text
-     */
-    inline void set_text(std::string text) noexcept
-    {
-        m_text = std::move(text);
-    }
-
-    using widget::draw;
-
-    /**
-     * \copydoc widget::draw
-     */
-    void draw(window& w, const rectangle& rect) override;
-
-    /**
-     * \copydoc widget::size
-     */
-    mlk::size size(window& w) const noexcept override;
-};
-
-} // !mlk
-
-#endif // !MALIKANIA_CLIENT_LABEL_HPP
--- a/libclient/malikania/layout.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,77 +0,0 @@
-/*
- * layout.hpp -- generic layout manager inside a frame
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_CLIENT_LAYOUT_HPP
-#define MALIKANIA_CLIENT_LAYOUT_HPP
-
-/**
- * \brief Generic layout manager inside a frame.
- */
-
-namespace mlk {
-
-class mouse_click_event;
-class rectangle;
-class size;
-class window;
-
-/**
- * \brief Manages the widgets inside a frame.
- *
- * Layouts are responsible of positioning the widgets inside a frame. They
- * handle their positions and dispatch events if applicable.
- *
- * \see grid_layout
- */
-class layout {
-public:
-    /**
-     * Virtual destructor defaulted.
-     */
-    virtual ~layout() noexcept = default;
-
-    /**
-     * Handle mouse down.
-     *
-     * \param ev the mouse event
-     */
-    virtual void handle_mouse_down(const mouse_click_event& ev) = 0;
-
-    /**
-     * Handle mouse up.
-     *
-     * \param ev the event
-     */
-    virtual void handle_mouse_up(const mouse_click_event& ev) = 0;
-
-    /**
-     * Return the required minimum size to draw the whole layout.
-     */
-    virtual mlk::size size(window& win) const = 0;
-
-    /**
-     * Draw the layout content at the given position.
-     *
-     * \param win the window
-     */
-    virtual void draw(window& win, const rectangle& dst) = 0;
-};
-
-} // !mlk
-
-#endif // !MALIKANIA_CLIENT_LAYOUT_HPP
--- a/libclient/malikania/line.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-/*
- * line.hpp -- line description
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_LINE_HPP
-#define MALIKANIA_LINE_HPP
-
-/**
- * \file line.hpp
- * \brief line description.
- */
-
-namespace mlk {
-
-/**
- * \brief line description.
- *
- * A line has an origin (x, y) and a destination (x, y).
- */
-class line {
-private:
-    int m_x1;
-    int m_y1;
-    int m_x2;
-    int m_y2;
-
-public:
-    /**
-     * Construct a line.
-     *
-     * \param x1 the first x
-     * \param y1 the first y
-     * \param x2 the second x
-     * \param y2 the second y
-     */
-    inline line(int x1 = 0, int y1 = 0, int x2 = 0, int y2 = 0) noexcept
-        : m_x1(x1)
-        , m_y1(y1)
-        , m_x2(x2)
-        , m_y2(y2)
-    {
-    }
-
-    /**
-     * Get the first x.
-     *
-     * \return the x1
-     */
-    inline int x1() const noexcept
-    {
-        return m_x1;
-    }
-
-    /**
-     * Get the first y.
-     *
-     * \return the y1
-     */
-    inline int y1() const noexcept
-    {
-        return m_y1;
-    }
-
-    /**
-     * Get the second x.
-     *
-     * \return the x2
-     */
-    inline int x2() const noexcept
-    {
-        return m_x2;
-    }
-
-    /**
-     * Get the second y.
-     *
-     * \return the y2
-     */
-    inline int y2() const noexcept
-    {
-        return m_y2;
-    }
-};
-
-/**
- * Compare equality.
- *
- * \param l1 the first line
- * \param l2 the second line
- * \return true if they equal
- */
-inline bool operator==(const line& l1, const line& l2) noexcept
-{
-    return l1.x1() == l2.x1() && l1.x2() == l2.x2() && l1.y1() == l2.y1() && l1.y2() == l2.y2();
-}
-
-/**
- * Compare equality.
- *
- * \param l1 the first line
- * \param l2 the second line
- * \return false if they equal
- */
-inline bool operator!=(const line& l1, const line& l2) noexcept
-{
-    return !(l1 == l2);
-}
-
-} // !mlk
-
-#endif // !MALIKANIA_LINE_HPP
--- a/libclient/malikania/mouse.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-/*
- * mouse.hpp -- mouse definitions
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_CLIENT_MOUSE_HPP
-#define MALIKANIA_CLIENT_MOUSE_HPP
-
-/**
- * \file mouse.hpp
- * \brief Mouse definitions.
- */
-
-namespace mlk {
-
-/**
- * \brief Describe mouse button
- */
-enum class mouse {
-    none,                           //!< no buttons are pressed
-    left,                           //!< left click is pressed
-    right,                          //!< right click is pressed
-    middle                          //!< middle click is pressed
-};
-
-} // !mlk
-
-#endif // !MALIKANIA_CLIENT_MOUSE_HPP
--- a/libclient/malikania/point.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * point.hpp -- point description
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_POINT_HPP
-#define MALIKANIA_POINT_HPP
-
-/**
- * \file point.hpp
- * \brief point description.
- */
-
-namespace mlk {
-
-/**
- * \brief point coordinate.
- */
-class point {
-private:
-    int m_x;
-    int m_y;
-
-public:
-    /**
-     * Construct a point.
-     *
-     * \param x the x
-     * \param y the y
-     */
-    inline point(int x = 0, int y = 0) noexcept
-        : m_x(x)
-        , m_y(y)
-    {
-    }
-
-    /**
-     * Get the x position.
-     *
-     * \return the x
-     */
-    inline int x() const noexcept
-    {
-        return m_x;
-    }
-
-    /**
-     * Get the y position.
-     *
-     * \return the y
-     */
-    inline int y() const noexcept
-    {
-        return m_y;
-    }
-};
-
-/**
- * Compare equality.
- *
- * \param p1 the first point
- * \param p2 the second point
- * \return true if they equal
- */
-inline bool operator==(const point& p1, const point& p2) noexcept
-{
-    return p1.x() == p2.x() && p1.y() == p2.y();
-}
-
-/**
- * Compare equality.
- *
- * \param p1 the first point
- * \param p2 the second point
- * \return false if they equal
- */
-inline bool operator!=(const point& p1, const point& p2) noexcept
-{
-    return !(p1 == p2);
-}
-
-} // !mlk
-
-#endif // !MALIKANIA_POINT_HPP
--- a/libclient/malikania/rectangle.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,138 +0,0 @@
-/*
- * rectangle.hpp -- rectangle description
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_RECTANGLE_HPP
-#define MALIKANIA_RECTANGLE_HPP
-
-/**
- * \file rectangle.hpp
- * \brief rectangle description.
- */
-
-namespace mlk {
-
-/**
- * \brief rectangle description.
- *
- * A rectangle has coordinates (x, y) and dimensions (width, height).
- *
- * They are commonly used for clipping images into the window.
- */
-class rectangle {
-private:
-    int m_x;
-    int m_y;
-    unsigned m_width;
-    unsigned m_height;
-
-public:
-    /**
-     * Construct a rectangle.
-     *
-     * \param x the x position
-     * \param y the y position
-     * \param width the width
-     * \param height the height
-     */
-    inline rectangle(int x = 0, int y = 0, unsigned width = 0, unsigned height = 0) noexcept
-        : m_x(x)
-        , m_y(y)
-        , m_width(width)
-        , m_height(height)
-    {
-    }
-
-    /**
-     * Get the x position.
-     *
-     * \return the x position
-     */
-    inline int x() const noexcept
-    {
-        return m_x;
-    }
-
-    /**
-     * Get the y position.
-     *
-     * \return the y position
-     */
-    inline int y() const noexcept
-    {
-        return m_y;
-    }
-
-    /**
-     * Get the rectangle width.
-     *
-     * \return the width
-     */
-    inline unsigned width() const noexcept
-    {
-        return m_width;
-    }
-
-    /**
-     * Get the rectangle height.
-     *
-     * \return the height
-     */
-    inline unsigned height() const noexcept
-    {
-        return m_height;
-    }
-
-    /**
-     * Check if the rectangle has null dimensions.
-     *
-     * \return true if weight and height are 0
-     */
-    inline bool is_null() const noexcept
-    {
-        return m_width == 0 && m_height == 0;
-    }
-};
-
-/**
- * Compare equality.
- *
- * \param r1 the first rectangle
- * \param r2 the second rectangle
- * \return true if they equal
- */
-inline bool operator==(const rectangle& r1, const rectangle& r2) noexcept
-{
-    return r1.x() == r2.x() && r1.y() == r2.y() &&
-           r1.width() == r2.width() && r1.height() == r2.height();
-}
-
-/**
- * Compare equality.
- *
- * \param r1 the first rectangle
- * \param r2 the second rectangle
- * \return false if they equal
- */
-inline bool operator!=(const rectangle& r1, const rectangle& r2) noexcept
-{
-    return !(r1 == r2);
-}
-
-} // !mlk
-
-#endif // !MALIKANIA_RECTANGLE_HPP
--- a/libclient/malikania/size.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,102 +0,0 @@
-/*
- * size.hpp -- size description
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_SIZE_HPP
-#define MALIKANIA_SIZE_HPP
-
-namespace mlk {
-
-/**
- * \brief size description.
- */
-class size {
-private:
-    unsigned m_width;
-    unsigned m_height;
-
-public:
-    /**
-     * Constructor.
-     *
-     * \param width the size width
-     * \param height the size height
-     */
-    inline size(unsigned width = 0, unsigned height = 0) noexcept
-        : m_width(width)
-        , m_height(height)
-    {
-    }
-
-    /**
-     * Get the width.
-     *
-     * \return the width
-     */
-    inline unsigned width() const noexcept
-    {
-        return m_width;
-    }
-
-    /**
-     * Get the height.
-     *
-     * \return the height
-     */
-    inline unsigned height() const noexcept
-    {
-        return m_height;
-    }
-
-    /**
-     * Check if the size is 0, 0.
-     *
-     * \return true if height and width are 0
-     */
-    inline bool is_null() const noexcept
-    {
-        return m_height == 0 && m_width == 0;
-    }
-};
-
-/**
- * Compare equality.
- *
- * \param s1 the first size
- * \param s2 the second size
- * \return true if they equal
- */
-inline bool operator==(const size& s1, const size& s2) noexcept
-{
-    return s1.width() == s2.width() && s1.height() == s2.height();
-}
-
-/**
- * Compare equality.
- *
- * \param s1 the first size
- * \param s2 the second size
- * \return false if they equal
- */
-inline bool operator!=(const size& s1, const size& s2) noexcept
-{
-    return !(s1 == s2);
-}
-
-} // !mlk
-
-#endif // !MALIKANIA_SIZE_HPP
--- a/libclient/malikania/sprite.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,67 +0,0 @@
-/*
- * sprite.cpp -- image sprite
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <cassert>
-
-#include "sprite.hpp"
-
-namespace mlk {
-
-sprite::sprite(mlk::image image,
-               mlk::size cell,
-               mlk::size size,
-               mlk::size space,
-               mlk::size margin) noexcept
-    : m_image(std::move(image))
-    , m_cell(std::move(cell))
-    , m_margin(std::move(margin))
-    , m_space(std::move(space))
-    , m_size(std::move(size))
-{
-    assert(m_cell.width() > 0);
-    assert(m_cell.height() > 0);
-
-    // If size is not specified, take from image.
-    if (m_size.is_null()) {
-        m_size = m_image.size();
-    }
-
-    // Compute number of cells.
-    m_rows = (m_size.height() - (margin.height() * 2) + m_space.height()) / (m_cell.height() + m_space.height());
-    m_columns = (m_size.width() - (m_margin.width() * 2) + m_space.width()) / (m_cell.width() + m_space.width());
-}
-
-void sprite::draw(window& window, unsigned cell, const point& point)
-{
-    assert(cell < m_rows * m_columns);
-
-    // Compute index in the grid.
-    unsigned hindex = (cell % m_columns);
-    unsigned vindex = (cell / m_columns);
-
-    // Compute the pixel boundaries.
-    int x = m_margin.width() + (hindex * m_space.width()) + (hindex * m_cell.width());
-    int y = m_margin.height() + (vindex * m_space.height()) + (vindex * m_cell.height());
-
-    rectangle source(x, y, m_cell.width(), m_cell.height());
-    rectangle target(point.x(), point.y(), m_cell.width(), m_cell.height());
-
-    m_image.draw(window, source, target);
-}
-
-} // !mlk
--- a/libclient/malikania/sprite.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,144 +0,0 @@
-/*
- * sprite.hpp -- image sprite
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_SPRITE_HPP
-#define MALIKANIA_SPRITE_HPP
-
-/**
- * \file sprite.hpp
- * \brief Sprite description.
- */
-
-#include "image.hpp"
-
-namespace mlk {
-
-/**
- * \brief A Sprite is an image divided into cells.
- */
-class sprite {
-private:
-    mlk::image m_image;
-    mlk::size m_cell;
-    mlk::size m_margin;
-    mlk::size m_space;
-    mlk::size m_size;
-    unsigned m_rows;
-    unsigned m_columns;
-
-public:
-    /**
-     * Construct a sprite.
-     *
-     * \pre cell must not have height or width null
-     * \param image the image to use
-     * \param cell size of cell in the image
-     * \param margin the optional space from borders
-     * \param space the optional space between cells
-     * \param size the sprite size (if 0, taken from the image)
-     */
-    sprite(mlk::image image,
-           mlk::size cell,
-           mlk::size margin = { 0, 0 },
-           mlk::size space = { 0, 0 },
-           mlk::size size = { 0, 0 }) noexcept;
-
-    /**
-     * Get the underlying image.
-     *
-     * \return the image
-     */
-    inline const mlk::image& image() const noexcept
-    {
-        return m_image;
-    }
-
-    /**
-     * Overloaded function.
-     *
-     * \return the image
-     */
-    inline mlk::image& image() noexcept
-    {
-        return m_image;
-    }
-
-    /**
-     * Get the cell size.
-     *
-     * \return the cell size
-     */
-    inline const size& cell() const noexcept
-    {
-        return m_cell;
-    }
-
-    /**
-     * Get the margin size.
-     *
-     * \return the margin size
-     */
-    inline const size& margin() noexcept
-    {
-        return m_margin;
-    }
-
-    /**
-     * Get the space size.
-     *
-     * \return the space size
-     */
-    inline const size& space() const noexcept
-    {
-        return m_space;
-    }
-
-    /**
-     * Get the number of rows in the grid.
-     *
-     * \return the number of rows
-     */
-    inline unsigned rows() const noexcept
-    {
-        return m_rows;
-    }
-
-    /**
-     * Get the number of columns in the grid.
-     *
-     * \return the number of columns
-     */
-    inline unsigned columns() const noexcept
-    {
-        return m_columns;
-    }
-
-    /**
-     * Draw the sprite into the window at the specified position.
-     *
-     * \pre cell < rows() * columns()
-     * \param window the window
-     * \param cell the cell index
-     * \param position the position in the window
-     */
-    void draw(window& window, unsigned cell, const point& position);
-};
-
-} // !mlk
-
-#endif // !MALIKANIA_SPRITE_HPP
--- a/libclient/malikania/theme.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-/*
- * theme.cpp -- theming support for gui elements
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "button.hpp"
-#include "color.hpp"
-#include "frame.hpp"
-#include "label.hpp"
-#include "layout.hpp"
-#include "point.hpp"
-#include "rectangle.hpp"
-#include "theme.hpp"
-#include "window.hpp"
-
-namespace mlk {
-
-namespace {
-
-#include <dejavu_sans.cpp>
-
-} // !namespace
-
-theme::theme()
-    : m_font(std::string(dejavu_sans, sizeof (dejavu_sans)), 10)
-    , m_background_color(228, 228, 228, 255)
-    , m_border_color(102, 102, 102, 255)
-    , m_text_color(50, 50, 50, 255)
-    , m_frame_padding(10, 10)
-{
-}
-
-size theme::size_button(const button &b)
-{
-    auto clip = m_font.clip(b.text());
-
-    return {
-        clip.width() + 12,
-        clip.height() + 12
-    };
-}
-
-size theme::size_label(const label& l)
-{
-    return m_font.clip(l.text());
-}
-
-void theme::draw_frame(window& win, const frame &f)
-{
-    auto layout_size = f.layout()->size(win);
-    auto frame_pos = f.position();
-
-    // Frame border.
-    win.set_drawing_color(m_border_color);
-    win.draw_rectangle({
-        frame_pos.x(),
-        frame_pos.y(),
-        layout_size.width() + m_frame_padding.width() * 2 + 2,
-        layout_size.height() + m_frame_padding.height() * 2 + 2
-    });
-
-    // Frame content.
-    win.set_drawing_color(m_background_color);
-    win.fill_rectangle({
-        frame_pos.x() + 1,
-        frame_pos.y() + 1,
-        layout_size.width() + m_frame_padding.width() * 2,
-        layout_size.height() + m_frame_padding.height() * 2
-    });
-
-    // Layout.
-    f.layout()->draw(win, mlk::rectangle(
-        frame_pos.x() + m_frame_padding.width() + 1,
-        frame_pos.y() + m_frame_padding.height() + 1,
-        layout_size.width(),
-        layout_size.height()
-    ));
-}
-
-void theme::draw_button(window& w, const button& b, const rectangle& rect)
-{
-    auto size = size_button(b);
-
-    // Border.
-    w.set_drawing_color(m_border_color);
-    w.draw_rectangle({rect.x(), rect.y(), size.width(), size.height()});
-
-    // Box content.
-    w.set_drawing_color(m_background_color);
-    w.fill_rectangle({rect.x() + 1, rect.y() + 1, size.width() - 2, size.height() - 2});
-
-    // Text.
-    w.set_drawing_color(m_text_color);
-    w.draw_text(b.text(), m_font, point{rect.x() + 5, rect.y() + 5});
-}
-
-void theme::draw_label(window& w, const label& label, const rectangle& rect)
-{
-    w.set_drawing_color(m_text_color);
-    w.draw_text(label.text(), m_font, mlk::point(rect.x(), rect.y()));
-}
-
-} // !mlk
--- a/libclient/malikania/theme.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,121 +0,0 @@
-/*
- * theme.hpp -- theming support for gui elements
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_CLIENT_THEME_HPP
-#define MALIKANIA_CLIENT_THEME_HPP
-
-/**
- * \file theme.hpp
- * \brief Theming support for gui elements.
- */
-
-#include "color.hpp"
-#include "font.hpp"
-#include "size.hpp"
-
-namespace mlk {
-
-class button;
-class frame;
-class label;
-class rectangle;
-class point;
-class window;
-
-/**
- * \brief Reimplement this class to provide your own theme.
- */
-class theme {
-private:
-    font m_font;
-    color m_background_color;
-    color m_border_color;
-    color m_text_color;
-    size m_frame_padding;
-
-public:
-    /**
-     * Default constructor.
-     */
-    theme();
-
-    /**
-     * Virtual destructor defaulted.
-     */
-    virtual ~theme() noexcept = default;
-
-    inline const color& background_color() const noexcept
-    {
-        return m_background_color;
-    }
-
-    inline const color& border_color() const noexcept
-    {
-        return m_border_color;
-    }
-
-    inline const color& text_color() const noexcept
-    {
-        return m_text_color;
-    }
-
-    /**
-     * Get the required bounding rectangle size for this button.
-     *
-     * \param b the button
-     * \return the size
-     */
-    virtual size size_button(const button& b);
-
-    /**
-     * Get the required bouding rectangle size for this label.
-     *
-     * \param l the label
-     * \return the size
-     */
-    virtual size size_label(const label& l);
-
-    /**
-     * Draw the frame.
-     *
-     * \param w the main window
-     * \param f the frame
-     */
-    virtual void draw_frame(window& w, const frame& f);
-
-    /**
-     * Draw a button.
-     *
-     * \param w the main window
-     * \param b the button
-     */
-    virtual void draw_button(window& w, const button& b, const rectangle& rect);
-
-    /**
-     * Draw a label.
-     *
-     * \param w the main window
-     * \param l the label
-     * \param rect the bounding rectangle.
-     */
-    virtual void draw_label(window& w, const label& l, const rectangle& rect);
-};
-
-} // !mlk
-
-#endif // !MALIKANIA_CLIENT_THEME_HPP
--- a/libclient/malikania/unique_layout.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,56 +0,0 @@
-/*
- * unique_layout.cpp -- basic layout with one widget
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "size.hpp"
-#include "unique_layout.hpp"
-#include "widget.hpp"
-
-namespace mlk {
-
-unique_layout::unique_layout(std::shared_ptr<mlk::widget> widget) noexcept
-    : m_widget(std::move(widget))
-{
-}
-
-void unique_layout::handle_mouse_down(const mouse_click_event& ev)
-{
-    if (m_widget) {
-        m_widget->handle_mouse_down(ev);
-    }
-}
-
-void unique_layout::handle_mouse_up(const mouse_click_event& ev)
-{
-    if (m_widget) {
-        m_widget->handle_mouse_up(ev);
-    }
-}
-
-mlk::size unique_layout::size(window& win) const
-{
-    return m_widget ? m_widget->size(win) : mlk::size();
-}
-
-void unique_layout::draw(window& win, const rectangle& dst)
-{
-    if (m_widget) {
-        m_widget->draw(win, dst);
-    }
-}
-
-} // !mlk
--- a/libclient/malikania/unique_layout.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/*
- * unique_layout.hpp -- basic layout with one widget
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_CLIENT_UNIQUE_LAYOUT_HPP
-#define MALIKANIA_CLIENT_UNIQUE_LAYOUT_HPP
-
-/**
- * \file unique_layout.hpp
- * \brief Basic layout with one widget.
- */
-
-#include <memory>
-
-#include "layout.hpp"
-
-namespace mlk {
-
-class widget;
-
-/**
- * \brief Simple layout that consists of one widget.
- */
-class unique_layout : public layout {
-private:
-    std::shared_ptr<mlk::widget> m_widget;
-
-public:
-    /**
-     * Constructor with optional widget.
-     *
-     * \param widget the widget
-     */
-    unique_layout(std::shared_ptr<mlk::widget> w = nullptr) noexcept;
-
-    /**
-     * Get the handled widget.
-     *
-     * \return the widget
-     */
-    inline const std::shared_ptr<mlk::widget>& widget() const noexcept
-    {
-        return m_widget;
-    }
-
-    /**
-     * Overloaded function.
-     *
-     * \return the widget
-     */
-    inline std::shared_ptr<mlk::widget>& widget() noexcept
-    {
-        return m_widget;
-    }
-
-    /**
-     * Replace the current widget with this one.
-     *
-     * \param widget the widget
-     */
-    inline void set_widget(std::shared_ptr<mlk::widget> widget) noexcept
-    {
-        m_widget = std::move(widget);
-    }
-
-    /**
-     * \copydoc layout::handle_mouse_down
-     */
-    void handle_mouse_down(const mouse_click_event& ev) override;
-
-    /**
-     * \copydoc layout::handle_mouse_up
-     */
-    void handle_mouse_up(const mouse_click_event& ev) override;
-
-    /**
-     * \copydoc layout::size
-     */
-    mlk::size size(window& win) const override;
-
-    /**
-     * \copydoc layout::draw
-     */
-    void draw(window& win, const rectangle& dst) override;
-};
-
-} // !mlk
-
-#endif // !MALIKANIA_CLIENT_UNIQUE_LAYOUT_HPP
--- a/libclient/malikania/widget.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,53 +0,0 @@
-/*
- * widget.cpp -- basic abstract widget for GUI
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include "point.hpp"
-#include "rectangle.hpp"
-#include "size.hpp"
-#include "widget.hpp"
-
-namespace mlk {
-
-void widget::handle_key_down(const key_event&)
-{
-}
-
-void widget::handle_key_up(const key_event&)
-{
-}
-
-void widget::handle_mouse_down(const mouse_click_event&)
-{
-}
-
-void widget::handle_mouse_up(const mouse_click_event&)
-{
-}
-
-void widget::draw(window& w, const point& pos)
-{
-    mlk::size sz = size(w);
-    mlk::rectangle rect{
-        pos.x(), pos.y(),
-        sz.width(), sz.height()
-    };
-
-    draw(w, rect);
-}
-
-} // !mlk
--- a/libclient/malikania/widget.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,103 +0,0 @@
-/*
- * widget.hpp -- basic abstract widget for GUI
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_CLIENT_WIDGET_HPP
-#define MALIKANIA_CLIENT_WIDGET_HPP
-
-/**
- * \file widget.hpp
- * \brief Basic abstract widget for GUI
- */
-
-namespace mlk {
-
-class key_event;
-class mouse_click_event;
-class point;
-class rectangle;
-class size;
-class window;
-
-/**
- * \brief Abstract widget
- */
-class widget {
-public:
-    /**
-     * Default destructor.
-     */
-    virtual ~widget() noexcept = default;
-
-    /**
-     * Handle a key down.
-     *
-     * \param ev the event
-     */
-    virtual void handle_key_down(const key_event& ev);
-
-    /**
-     * Handle a key up.
-     *
-     * \param ev the event
-     */
-    virtual void handle_key_up(const key_event& ev);
-
-    /**
-     * Handle mouse down event.
-     *
-     * \param ev the event
-     */
-    virtual void handle_mouse_down(const mouse_click_event& ev);
-
-    /**
-     * Handle a mouse up event.
-     *
-     * \param ev the event
-     */
-    virtual void handle_mouse_up(const mouse_click_event& ev);
-
-    /**
-     * Draw the widget at the specified position.
-     *
-     * Basic GUI elements will use the window theme to render themselves.
-     *
-     * \param w the window
-     */
-    virtual void draw(window& w, const rectangle& rect) = 0;
-
-    /**
-     * Helper to draw the whole widget at the given position.
-     *
-     * Effectively call draw with a rectangle overload.
-     *
-     * \param w the window
-     * \param pos the position
-     */
-    virtual void draw(window& w, const point& pos);
-
-    /**
-     * Get the required size to draw that widget.
-     *
-     * \return the widget size
-     */
-    virtual mlk::size size(window& w) const noexcept = 0;
-};
-
-} // !mlk
-
-#endif // !MALIKANIA_CLIENT_WIDGET_HPP
--- a/libclient/malikania/window.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,176 +0,0 @@
-/*
- * window.cpp -- main window and basic drawing
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <iostream>
-#include <stdexcept>
-
-#include "color.hpp"
-#include "frame.hpp"
-#include "layout.hpp"
-#include "theme.hpp"
-#include "widget.hpp"
-#include "window_backend.hpp"
-
-namespace mlk {
-
-bool window::is_frame_bound(frame& f, const point& ev_pos) noexcept
-{
-    auto frame_size = f.size(*this);
-    auto frame_padding = f.padding();
-    auto frame_pos = f.position();
-
-    return ev_pos.x() >= frame_pos.x() + static_cast<int>(frame_padding.width()) &&
-           ev_pos.y() >= frame_pos.y() + static_cast<int>(frame_padding.height()) &&
-           ev_pos.x() <= frame_pos.x() + static_cast<int>(frame_padding.width()  + frame_size.width()) &&
-           ev_pos.y() <= frame_pos.y() + static_cast<int>(frame_padding.height() + frame_size.height());
-}
-
-window::window(unsigned width, unsigned height, const std::string& title)
-    : m_backend(std::make_unique<backend_impl>(*this, width, height, title))
-    , m_theme(std::make_unique<mlk::theme>())
-{
-}
-
-window::window(window&&) noexcept = default;
-
-window::~window() noexcept = default;
-
-void window::clear()
-{
-    m_backend->clear();
-}
-
-void window::present()
-{
-    m_backend->present();
-}
-
-void window::close() noexcept
-{
-    m_is_open = false;
-    m_backend->close();
-}
-
-color window::drawing_color() const
-{
-    return m_backend->drawing_color();
-}
-
-void window::set_drawing_color(const color& color)
-{
-    m_backend->set_drawing_color(color);
-}
-
-void window::draw_line(const line& line)
-{
-    m_backend->draw_line(line);
-}
-
-void window::draw_lines(const std::vector<point>& points)
-{
-    m_backend->draw_lines(points);
-}
-
-void window::draw_point(const point& point)
-{
-    m_backend->draw_point(point);
-}
-
-void window::draw_points(const std::vector<point>& points)
-{
-    m_backend->draw_points(points);
-}
-
-void window::draw_rectangle(const rectangle& rectangle)
-{
-    m_backend->draw_rectangle(rectangle);
-}
-
-void window::draw_rectangles(const std::vector<rectangle>& rectangles)
-{
-    m_backend->draw_rectangles(rectangles);
-}
-
-void window::draw_frames()
-{
-    for (const auto& f : m_frames) {
-        f->draw(*this);
-    }
-}
-
-void window::fill_rectangle(const rectangle& rectangle)
-{
-    m_backend->fill_rectangle(rectangle);
-}
-
-void window::fill_rectangles(const std::vector<rectangle>& rectangles)
-{
-    m_backend->fill_rectangles(rectangles);
-}
-
-void window::draw_text(const std::string& text, font& font, const rectangle& rectangle)
-{
-    m_backend->draw_text(text, font, rectangle);
-}
-
-void window::draw_text(const std::string& text, font& font, const point& point)
-{
-    m_backend->draw_text(text, font, point);
-}
-
-void window::poll()
-{
-    m_backend->poll(*this);
-}
-
-void window::handle_key_down(const key_event&)
-{
-}
-
-void window::handle_key_up(const key_event&)
-{
-}
-
-void window::handle_mouse_down(const mouse_click_event& ev)
-{
-    for (const auto& f : m_frames) {
-        if (is_frame_bound(*f, ev.pos)) {
-            f->layout()->handle_mouse_down({
-                ev.button,
-                point(ev.pos.x() - f->position().x(), ev.pos.y() - f->position().y())
-            });
-        }
-    }
-}
-
-void window::handle_mouse_up(const mouse_click_event&)
-{
-}
-
-void window::handle_mouse_wheel(const mouse_wheel_event&)
-{
-}
-
-void window::handle_quit()
-{
-    m_is_open = false;
-}
-
-window& window::operator=(window&&) noexcept = default;
-
-} // !mlk
--- a/libclient/malikania/window.hpp	Sun Jan 22 10:11:17 2017 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,350 +0,0 @@
-/*
- * window.hpp -- main window and basic drawing
- *
- * Copyright (c) 2013-2017 Malikania Authors
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#ifndef MALIKANIA_WINDOW_HPP
-#define MALIKANIA_WINDOW_HPP
-
-/**
- * \file window.hpp
- * \brief Window and drawing.
- */
-
-#include <functional>
-#include <memory>
-#include <vector>
-#include <string>
-#include <unordered_set>
-
-#include "key.hpp"
-#include "mouse.hpp"
-#include "point.hpp"
-
-namespace mlk {
-
-class color;
-class frame;
-class line;
-class font;
-class rectangle;
-class theme;
-
-/**
- * \brief Describe key event.
- */
-class key_event {
-public:
-    mlk::key key{key::unknown};         //!< layout-dependant key
-    mlk::key scancode{key::unknown};    //!< physical key
-    mlk::mod modifiers{mod::none};      //!< optional modifiers
-};
-
-/**
- * \brief Describe mouse click event.
- */
-class mouse_click_event {
-public:
-    mouse button{mouse::none};          //!< which mouse button
-    point pos;                          //!< current mouse position
-};
-
-/**
- * \brief Describe a mouse motion event.
- */
-class mouse_motion_event {
-public:
-    point pos;                          //!< current mouse position
-};
-
-/**
- * \brief Describe mouse wheel (up/down) event.
- */
-class mouse_wheel_event {
-public:
-    point pos;                          //!< current mouse position
-};
-
-/**
- * \brief Main window class and drawing.
- */
-class window {
-private:
-    class backend_impl;
-
-    std::unique_ptr<backend_impl> m_backend;
-    std::unique_ptr<mlk::theme> m_theme;
-    std::unordered_set<std::shared_ptr<frame>> m_frames;
-
-    bool m_is_open{true};
-
-    bool is_frame_bound(frame&, const point&) noexcept;
-
-public:
-    /**
-     * Create a window.
-     *
-     * \param width the initial width
-     * \param height the initial height
-     * \param title the optional title
-     * \throw std::runtime_error on errors
-     */
-    window(unsigned width = 640,
-           unsigned height = 480,
-           const std::string& title = "Malikania Engine");
-
-    /**
-     * Move constructor defaulted.
-     */
-    window(window&&) noexcept;
-
-    /**
-     * Virtual destructor defaulted.
-     */
-    virtual ~window() noexcept;
-
-    /**
-     * Tells if the window is open.
-     *
-     * \return true if open
-     */
-    inline bool is_open() const noexcept
-    {
-        return m_is_open;
-    }
-
-    /**
-     * Get the underlying backend.
-     *
-     * \return the backend
-     */
-    inline const backend_impl& backend() const noexcept
-    {
-        return *m_backend;
-    }
-
-    /**
-     * Overloaded function.
-     *
-     * \return the backend
-     */
-    inline backend_impl& backend() noexcept
-    {
-        return *m_backend;
-    }
-
-    void add_frame(std::shared_ptr<mlk::frame> frame)
-    {
-        m_frames.insert(std::move(frame));
-    }
-
-    void remove_frame(std::shared_ptr<mlk::frame> frame)
-    {
-        m_frames.erase(frame);
-    }
-
-    /**
-     * Get the current theme.
-     *
-     * \return the theme
-     */
-    inline const mlk::theme& theme() const noexcept
-    {
-        return *m_theme;
-    }
-
-    /**
-     * Overloaded function.
-     *
-     * \return the theme
-     */
-    inline mlk::theme& theme() noexcept
-    {
-        return *m_theme;
-    }
-
-    /**
-     * Clear the window content with the current drawing color.
-     */
-    void clear();
-
-    /**
-     * Render the content of the window to the screen.
-     */
-    void present();
-
-    /**
-     * Close the window.
-     */
-    void close() noexcept;
-
-    /**
-     * Get the current drawing color.
-     *
-     * \return the color
-     */
-    color drawing_color() const;
-
-    /**
-     * Set the drawing color.
-     *
-     * \param color the color
-     */
-    void set_drawing_color(const color& color);
-
-    /**
-     * Draw a line.
-     *
-     * \param line the line
-     */
-    void draw_line(const line& line);
-
-    /**
-     * Draw a several lines.
-     *
-     * \param the lines vertices
-     */
-    void draw_lines(const std::vector<point>& points);
-
-    /**
-     * Draw a point.
-     *
-     * \param point the point
-     */
-    void draw_point(const point& point);
-
-    /**
-     * Draw a list of points.
-     *
-     * \param points the points
-     */
-    void draw_points(const std::vector<point>& points);
-
-    /**
-     * Draw a rectangle (only borders).
-     *
-     * \param rect the rectangle
-     * \see fillRectangle
-     */
-    void draw_rectangle(const rectangle& rect);
-
-    /**
-     * Draw a list of rectangles.
-     *
-     * \param rects the rectangles
-     * \see fillRectangles
-     */
-    void draw_rectangles(const std::vector<rectangle>& rects);
-
-    /**
-     * Draw internal GUI frames.
-     */
-    void draw_frames();
-
-    /**
-     * Fill the given rectangle with the current color.
-     *
-     * \param rect the rectangle
-     * \see drawRectangle
-     */
-    void fill_rectangle(const rectangle& rect);
-
-    /**
-     * Fill the list of rectangles with the current color.
-     *
-     * \param rects the list of rectangles
-     * \see drawRectangles
-     */
-    void fill_rectangles(const std::vector<rectangle>& rects);
-
-    /**
-     * Draw some text.
-     *
-     * This function may stretch the text texture.
-     *
-     * \param text the text (UTF-8)
-     * \param font the font
-     * \param rectangle the rectangle target
-     */
-    void draw_text(const std::string& text, font& font, const rectangle& rectangle);
-
-    /**
-     * Overloaded function.
-     *
-     * Draw the text at the given position.
-     *
-     * \param text the text (UTF-8)
-     * \param font the font
-     * \param point the text position
-     */
-    void draw_text(const std::string& text, font& font, const point& point);
-
-    /**
-     * Poll all pending events and call appropriate functions.
-     */
-    void poll();
-
-    /**
-     * Key down event.
-     *
-     * \param ev the event
-     */
-    virtual void handle_key_down(const key_event& ev);
-
-    /**
-     * Key released event.
-     *
-     * \param ev the event
-     */
-    virtual void handle_key_up(const key_event& ev);
-
-    /**
-     * Mouse click event.
-     *
-     * \param ev the event
-     */
-    virtual void handle_mouse_down(const mouse_click_event& ev);
-
-    /**
-     * Mouse click release event.
-     *
-     * \param ev the event
-     */
-    virtual void handle_mouse_up(const mouse_click_event& ev);
-
-    /**
-     * Mouse wheel event.
-     *
-     * \param ev the event
-     */
-    virtual void handle_mouse_wheel(const mouse_wheel_event& ev);
-
-    /**
-     * Quit request.
-     */
-    virtual void handle_quit();
-
-    /**
-     * Move assigment operator defaulted.
-     *
-     * \return this
-     */
-    window& operator=(window&&) noexcept;
-};
-
-} // !mlk
-
-#endif // !MALIKANIA_WINDOW_HPP
--- a/tests/libclient/color/main.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/tests/libclient/color/main.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * main.cpp -- test mlk::color
+ * main.cpp -- test mlk::client::color
  *
  * Copyright (c) 2013-2017 Malikania Authors
  *
@@ -19,7 +19,7 @@
 #define BOOST_TEST_MODULE "Color"
 #include <boost/test/unit_test.hpp>
 
-#include <malikania/color.hpp>
+#include <malikania/client/color.hpp>
 
 /*
  * Separate arguments.
@@ -30,7 +30,7 @@
 
 BOOST_AUTO_TEST_CASE(black)
 {
-    mlk::color c;
+    mlk::client::color c;
 
     BOOST_REQUIRE_EQUAL(0, c.red());
     BOOST_REQUIRE_EQUAL(0, c.green());
@@ -40,7 +40,7 @@
 
 BOOST_AUTO_TEST_CASE(white)
 {
-    mlk::color c{255, 255, 255, 255};
+    mlk::client::color c{255, 255, 255, 255};
 
     BOOST_REQUIRE_EQUAL(255, c.red());
     BOOST_REQUIRE_EQUAL(255, c.green());
@@ -50,7 +50,7 @@
 
 BOOST_AUTO_TEST_CASE(red)
 {
-    mlk::color c{255, 0, 0, 255};
+    mlk::client::color c{255, 0, 0, 255};
 
     BOOST_REQUIRE_EQUAL(255, c.red());
     BOOST_REQUIRE_EQUAL(0, c.green());
@@ -60,7 +60,7 @@
 
 BOOST_AUTO_TEST_CASE(green)
 {
-    mlk::color c{0, 255, 0, 255};
+    mlk::client::color c{0, 255, 0, 255};
 
     BOOST_REQUIRE_EQUAL(0, c.red());
     BOOST_REQUIRE_EQUAL(255, c.green());
@@ -70,7 +70,7 @@
 
 BOOST_AUTO_TEST_CASE(blue)
 {
-    mlk::color c{0, 0, 255, 255};
+    mlk::client::color c{0, 0, 255, 255};
 
     BOOST_REQUIRE_EQUAL(0, c.red());
     BOOST_REQUIRE_EQUAL(0, c.green());
@@ -89,7 +89,7 @@
 
 BOOST_AUTO_TEST_CASE(black)
 {
-    mlk::color c{0xff000000};
+    mlk::client::color c{0xff000000};
 
     BOOST_REQUIRE_EQUAL(0, c.red());
     BOOST_REQUIRE_EQUAL(0, c.green());
@@ -99,7 +99,7 @@
 
 BOOST_AUTO_TEST_CASE(white)
 {
-    mlk::color c{0xffffffff};
+    mlk::client::color c{0xffffffff};
 
     BOOST_REQUIRE_EQUAL(255, c.red());
     BOOST_REQUIRE_EQUAL(255, c.green());
@@ -109,7 +109,7 @@
 
 BOOST_AUTO_TEST_CASE(red)
 {
-    mlk::color c{0xffff0000};
+    mlk::client::color c{0xffff0000};
 
     BOOST_REQUIRE_EQUAL(255, c.red());
     BOOST_REQUIRE_EQUAL(0, c.green());
@@ -119,7 +119,7 @@
 
 BOOST_AUTO_TEST_CASE(green)
 {
-    mlk::color c{0xff00ff00};
+    mlk::client::color c{0xff00ff00};
 
     BOOST_REQUIRE_EQUAL(0, c.red());
     BOOST_REQUIRE_EQUAL(255, c.green());
@@ -129,7 +129,7 @@
 
 BOOST_AUTO_TEST_CASE(blue)
 {
-    mlk::color c{0xff0000ff};
+    mlk::client::color c{0xff0000ff};
 
     BOOST_REQUIRE_EQUAL(0, c.red());
     BOOST_REQUIRE_EQUAL(0, c.green());
@@ -150,7 +150,7 @@
 
 BOOST_AUTO_TEST_CASE(black)
 {
-    mlk::color c{"black"};
+    mlk::client::color c{"black"};
 
     BOOST_REQUIRE_EQUAL(0, c.red());
     BOOST_REQUIRE_EQUAL(0, c.green());
@@ -160,7 +160,7 @@
 
 BOOST_AUTO_TEST_CASE(white)
 {
-    mlk::color c{"white"};
+    mlk::client::color c{"white"};
 
     BOOST_REQUIRE_EQUAL(255, c.red());
     BOOST_REQUIRE_EQUAL(255, c.green());
@@ -170,7 +170,7 @@
 
 BOOST_AUTO_TEST_CASE(red)
 {
-    mlk::color c{"red"};
+    mlk::client::color c{"red"};
 
     BOOST_REQUIRE_EQUAL(255, c.red());
     BOOST_REQUIRE_EQUAL(0, c.green());
@@ -180,7 +180,7 @@
 
 BOOST_AUTO_TEST_CASE(green)
 {
-    mlk::color c{"green"};
+    mlk::client::color c{"green"};
 
     BOOST_REQUIRE_EQUAL(0, c.red());
     BOOST_REQUIRE_EQUAL(128, c.green());
@@ -190,7 +190,7 @@
 
 BOOST_AUTO_TEST_CASE(blue)
 {
-    mlk::color c{"blue"};
+    mlk::client::color c{"blue"};
 
     BOOST_REQUIRE_EQUAL(0, c.red());
     BOOST_REQUIRE_EQUAL(0, c.green());
@@ -200,7 +200,7 @@
 
 BOOST_AUTO_TEST_CASE(wrong)
 {
-    BOOST_REQUIRE_THROW(mlk::color c{"does not exist"}, std::exception);
+    BOOST_REQUIRE_THROW(mlk::client::color c{"does not exist"}, std::exception);
 }
 
 BOOST_AUTO_TEST_SUITE_END()
@@ -216,7 +216,7 @@
 
 BOOST_AUTO_TEST_CASE(black)
 {
-    mlk::color c{"#000000"};
+    mlk::client::color c{"#000000"};
 
     BOOST_REQUIRE_EQUAL(0, c.red());
     BOOST_REQUIRE_EQUAL(0, c.green());
@@ -226,7 +226,7 @@
 
 BOOST_AUTO_TEST_CASE(white)
 {
-    mlk::color c{"#ffffff"};
+    mlk::client::color c{"#ffffff"};
 
     BOOST_REQUIRE_EQUAL(255, c.red());
     BOOST_REQUIRE_EQUAL(255, c.green());
@@ -236,7 +236,7 @@
 
 BOOST_AUTO_TEST_CASE(red)
 {
-    mlk::color c{"#ff0000"};
+    mlk::client::color c{"#ff0000"};
 
     BOOST_REQUIRE_EQUAL(255, c.red());
     BOOST_REQUIRE_EQUAL(0, c.green());
@@ -246,7 +246,7 @@
 
 BOOST_AUTO_TEST_CASE(green)
 {
-    mlk::color c{"#00ff00"};
+    mlk::client::color c{"#00ff00"};
 
     BOOST_REQUIRE_EQUAL(0, c.red());
     BOOST_REQUIRE_EQUAL(255, c.green());
@@ -256,7 +256,7 @@
 
 BOOST_AUTO_TEST_CASE(blue)
 {
-    mlk::color c{"#0000ff"};
+    mlk::client::color c{"#0000ff"};
 
     BOOST_REQUIRE_EQUAL(0, c.red());
     BOOST_REQUIRE_EQUAL(0, c.green());
@@ -266,7 +266,7 @@
 
 BOOST_AUTO_TEST_CASE(wrong)
 {
-    BOOST_REQUIRE_THROW(mlk::color c{"#ghijkl"}, std::exception);
+    BOOST_REQUIRE_THROW(mlk::client::color c{"#ghijkl"}, std::exception);
 }
 
 BOOST_AUTO_TEST_SUITE_END()
@@ -282,7 +282,7 @@
 
 BOOST_AUTO_TEST_CASE(black)
 {
-    mlk::color c{"#000"};
+    mlk::client::color c{"#000"};
 
     BOOST_REQUIRE_EQUAL(0, c.red());
     BOOST_REQUIRE_EQUAL(0, c.green());
@@ -292,7 +292,7 @@
 
 BOOST_AUTO_TEST_CASE(white)
 {
-    mlk::color c{"#fff"};
+    mlk::client::color c{"#fff"};
 
     BOOST_REQUIRE_EQUAL(255, c.red());
     BOOST_REQUIRE_EQUAL(255, c.green());
@@ -302,7 +302,7 @@
 
 BOOST_AUTO_TEST_CASE(red)
 {
-    mlk::color c{"#f00"};
+    mlk::client::color c{"#f00"};
 
     BOOST_REQUIRE_EQUAL(255, c.red());
     BOOST_REQUIRE_EQUAL(0, c.green());
@@ -312,7 +312,7 @@
 
 BOOST_AUTO_TEST_CASE(green)
 {
-    mlk::color c{"#0f0"};
+    mlk::client::color c{"#0f0"};
 
     BOOST_REQUIRE_EQUAL(0, c.red());
     BOOST_REQUIRE_EQUAL(255, c.green());
@@ -322,7 +322,7 @@
 
 BOOST_AUTO_TEST_CASE(blue)
 {
-    mlk::color c{"#00f"};
+    mlk::client::color c{"#00f"};
 
     BOOST_REQUIRE_EQUAL(0, c.red());
     BOOST_REQUIRE_EQUAL(0, c.green());
@@ -332,7 +332,7 @@
 
 BOOST_AUTO_TEST_CASE(combination)
 {
-    mlk::color c{"#123"};
+    mlk::client::color c{"#123"};
 
     BOOST_REQUIRE_EQUAL(17, c.red());
     BOOST_REQUIRE_EQUAL(34, c.green());
@@ -342,7 +342,7 @@
 
 BOOST_AUTO_TEST_CASE(wrong)
 {
-    BOOST_REQUIRE_THROW(mlk::color c{"#ghi"}, std::exception);
+    BOOST_REQUIRE_THROW(mlk::client::color c{"#ghi"}, std::exception);
 }
 
 BOOST_AUTO_TEST_SUITE_END()
--- a/tests/libclient/line/main.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/tests/libclient/line/main.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * main.cpp -- test mlk::line
+ * main.cpp -- test mlk::client::line
  *
  * Copyright (c) 2013-2017 Malikania Authors
  *
@@ -19,10 +19,12 @@
 #define BOOST_TEST_MODULE "Line"
 #include <boost/test/unit_test.hpp>
 
-#include <malikania/line.hpp>
+#include <malikania/client/line.hpp>
 
 namespace mlk {
 
+namespace client {
+
 std::ostream& operator<<(std::ostream& out, const line& line)
 {
     out << "{";
@@ -33,11 +35,13 @@
     return out;
 }
 
+} // !client
+
 } // !mlk
 
 BOOST_AUTO_TEST_CASE(none)
 {
-    mlk::line line;
+    mlk::client::line line;
 
     BOOST_REQUIRE_EQUAL(0, line.x1());
     BOOST_REQUIRE_EQUAL(0, line.y1());
@@ -47,7 +51,7 @@
 
 BOOST_AUTO_TEST_CASE(standard)
 {
-    mlk::line line(10, 20, 30, 40);
+    mlk::client::line line(10, 20, 30, 40);
 
     BOOST_REQUIRE_EQUAL(10, line.x1());
     BOOST_REQUIRE_EQUAL(20, line.y1());
@@ -57,23 +61,23 @@
 
 BOOST_AUTO_TEST_CASE(operator_eq)
 {
-    mlk::line line1, line2;
+    mlk::client::line line1, line2;
 
     BOOST_REQUIRE_EQUAL(line1, line2);
 }
 
 BOOST_AUTO_TEST_CASE(operator_eq1)
 {
-    mlk::line line1(10, 20, 30, 40);
-    mlk::line line2(10, 20, 30, 40);
+    mlk::client::line line1(10, 20, 30, 40);
+    mlk::client::line line2(10, 20, 30, 40);
 
     BOOST_REQUIRE_EQUAL(line1, line2);
 }
 
 BOOST_AUTO_TEST_CASE(operator_neq)
 {
-    BOOST_REQUIRE_NE(mlk::line(10), mlk::line(20));
-    BOOST_REQUIRE_NE(mlk::line(10, 10), mlk::line(10, 20));
-    BOOST_REQUIRE_NE(mlk::line(10, 10, 10), mlk::line(10, 10, 20));
-    BOOST_REQUIRE_NE(mlk::line(10, 10, 10, 10), mlk::line(10, 10, 10, 20));
+    BOOST_REQUIRE_NE(mlk::client::line(10), mlk::client::line(20));
+    BOOST_REQUIRE_NE(mlk::client::line(10, 10), mlk::client::line(10, 20));
+    BOOST_REQUIRE_NE(mlk::client::line(10, 10, 10), mlk::client::line(10, 10, 20));
+    BOOST_REQUIRE_NE(mlk::client::line(10, 10, 10, 10), mlk::client::line(10, 10, 10, 20));
 }
--- a/tests/libclient/point/main.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/tests/libclient/point/main.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * main.cpp -- test mlk::point
+ * main.cpp -- test mlk::client::point
  *
  * Copyright (c) 2013-2017 Malikania Authors
  *
@@ -19,10 +19,12 @@
 #define BOOST_TEST_MODULE "Point"
 #include <boost/test/unit_test.hpp>
 
-#include <malikania/point.hpp>
+#include <malikania/client/point.hpp>
 
 namespace mlk {
 
+namespace client {
+
 std::ostream& operator<<(std::ostream& out, const point& point)
 {
     out << "{" << point.x() << ", " << point.y() << "}";
@@ -30,11 +32,13 @@
     return out;
 }
 
+} // !client
+
 } // !mlk
 
 BOOST_AUTO_TEST_CASE(none)
 {
-    mlk::point point;
+    mlk::client::point point;
 
     BOOST_REQUIRE_EQUAL(0, point.x());
     BOOST_REQUIRE_EQUAL(0, point.y());
@@ -42,7 +46,7 @@
 
 BOOST_AUTO_TEST_CASE(standard)
 {
-    mlk::point point(10, 20);
+    mlk::client::point point(10, 20);
 
     BOOST_REQUIRE_EQUAL(10, point.x());
     BOOST_REQUIRE_EQUAL(20, point.y());
@@ -50,21 +54,21 @@
 
 BOOST_AUTO_TEST_CASE(operator_eq)
 {
-    mlk::point point1, point2;
+    mlk::client::point point1, point2;
 
     BOOST_REQUIRE_EQUAL(point1, point2);
 }
 
 BOOST_AUTO_TEST_CASE(operator_eq1)
 {
-    mlk::point point1(10, 20);
-    mlk::point point2(10, 20);
+    mlk::client::point point1(10, 20);
+    mlk::client::point point2(10, 20);
 
     BOOST_REQUIRE_EQUAL(point1, point2);
 }
 
 BOOST_AUTO_TEST_CASE(operator_neq)
 {
-    BOOST_REQUIRE_NE(mlk::point(10), mlk::point(20));
-    BOOST_REQUIRE_NE(mlk::point(10, 10), mlk::point(10, 20));
+    BOOST_REQUIRE_NE(mlk::client::point(10), mlk::client::point(20));
+    BOOST_REQUIRE_NE(mlk::client::point(10, 10), mlk::client::point(10, 20));
 }
--- a/tests/libclient/rectangle/main.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/tests/libclient/rectangle/main.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * main.cpp -- test mlk::rectangle
+ * main.cpp -- test mlk::client::rectangle
  *
  * Copyright (c) 2013-2017 Malikania Authors
  *
@@ -19,10 +19,12 @@
 #define BOOST_TEST_MODULE "Rectangle"
 #include <boost/test/unit_test.hpp>
 
-#include <malikania/rectangle.hpp>
+#include <malikania/client/rectangle.hpp>
 
 namespace mlk {
 
+namespace client {
+
 std::ostream& operator<<(std::ostream& out, const rectangle& rectangle)
 {
     out << "{";
@@ -33,11 +35,13 @@
     return out;
 }
 
+} // !client
+
 } // !mlk
 
 BOOST_AUTO_TEST_CASE(none)
 {
-    mlk::rectangle rectangle;
+    mlk::client::rectangle rectangle;
 
     BOOST_REQUIRE_EQUAL(0, rectangle.x());
     BOOST_REQUIRE_EQUAL(0, rectangle.y());
@@ -47,15 +51,15 @@
 
 BOOST_AUTO_TEST_CASE(null)
 {
-    BOOST_REQUIRE(mlk::rectangle().is_null());
-    BOOST_REQUIRE(!mlk::rectangle(0, 0, 10, 0).is_null());
-    BOOST_REQUIRE(!mlk::rectangle(0, 0, 0, 10).is_null());
-    BOOST_REQUIRE(!mlk::rectangle(0, 0, 10, 10).is_null());
+    BOOST_REQUIRE(mlk::client::rectangle().is_null());
+    BOOST_REQUIRE(!mlk::client::rectangle(0, 0, 10, 0).is_null());
+    BOOST_REQUIRE(!mlk::client::rectangle(0, 0, 0, 10).is_null());
+    BOOST_REQUIRE(!mlk::client::rectangle(0, 0, 10, 10).is_null());
 }
 
 BOOST_AUTO_TEST_CASE(standard)
 {
-    mlk::rectangle rectangle(10, 20, 30, 40);
+    mlk::client::rectangle rectangle(10, 20, 30, 40);
 
     BOOST_REQUIRE_EQUAL(10, rectangle.x());
     BOOST_REQUIRE_EQUAL(20, rectangle.y());
@@ -65,23 +69,23 @@
 
 BOOST_AUTO_TEST_CASE(operator_eq)
 {
-    mlk::rectangle rectangle1, rectangle2;
+    mlk::client::rectangle rectangle1, rectangle2;
 
     BOOST_REQUIRE_EQUAL(rectangle1, rectangle2);
 }
 
 BOOST_AUTO_TEST_CASE(operator_eq1)
 {
-    mlk::rectangle rectangle1(10, 20, 30, 40);
-    mlk::rectangle rectangle2(10, 20, 30, 40);
+    mlk::client::rectangle rectangle1(10, 20, 30, 40);
+    mlk::client::rectangle rectangle2(10, 20, 30, 40);
 
     BOOST_REQUIRE_EQUAL(rectangle1, rectangle2);
 }
 
 BOOST_AUTO_TEST_CASE(operator_neq)
 {
-    BOOST_REQUIRE_NE(mlk::rectangle(10), mlk::rectangle(20));
-    BOOST_REQUIRE_NE(mlk::rectangle(10, 10), mlk::rectangle(10, 20));
-    BOOST_REQUIRE_NE(mlk::rectangle(10, 10, 10), mlk::rectangle(10, 10, 20));
-    BOOST_REQUIRE_NE(mlk::rectangle(10, 10, 10, 10), mlk::rectangle(10, 10, 10, 20));
+    BOOST_REQUIRE_NE(mlk::client::rectangle(10), mlk::client::rectangle(20));
+    BOOST_REQUIRE_NE(mlk::client::rectangle(10, 10), mlk::client::rectangle(10, 20));
+    BOOST_REQUIRE_NE(mlk::client::rectangle(10, 10, 10), mlk::client::rectangle(10, 10, 20));
+    BOOST_REQUIRE_NE(mlk::client::rectangle(10, 10, 10, 10), mlk::client::rectangle(10, 10, 10, 20));
 }
--- a/tests/libclient/size/main.cpp	Sun Jan 22 10:11:17 2017 +0100
+++ b/tests/libclient/size/main.cpp	Sun Jan 22 11:07:36 2017 +0100
@@ -1,5 +1,5 @@
 /*
- * main.cpp -- test mlk::size
+ * main.cpp -- test mlk::client::size
  *
  * Copyright (c) 2013-2017 Malikania Authors
  *
@@ -19,10 +19,12 @@
 #define BOOST_TEST_MODULE "Size"
 #include <boost/test/unit_test.hpp>
 
-#include <malikania/size.hpp>
+#include <malikania/client/size.hpp>
 
 namespace mlk {
 
+namespace client {
+
 std::ostream& operator<<(std::ostream& out, const size& size)
 {
     out << "{" << size.width() << ", " << size.height() << "}";
@@ -30,11 +32,13 @@
     return out;
 }
 
+} // !client
+
 } // !mlk
 
 BOOST_AUTO_TEST_CASE(none)
 {
-    mlk::size size;
+    mlk::client::size size;
 
     BOOST_REQUIRE_EQUAL(0U, size.width());
     BOOST_REQUIRE_EQUAL(0U, size.height());
@@ -42,14 +46,14 @@
 
 BOOST_AUTO_TEST_CASE(null)
 {
-    BOOST_REQUIRE(mlk::size().is_null());
-    BOOST_REQUIRE(!mlk::size(0, 10).is_null());
-    BOOST_REQUIRE(!mlk::size(10, 0).is_null());
+    BOOST_REQUIRE(mlk::client::size().is_null());
+    BOOST_REQUIRE(!mlk::client::size(0, 10).is_null());
+    BOOST_REQUIRE(!mlk::client::size(10, 0).is_null());
 }
 
 BOOST_AUTO_TEST_CASE(standard)
 {
-    mlk::size size(10, 20);
+    mlk::client::size size(10, 20);
 
     BOOST_REQUIRE_EQUAL(10U, size.width());
     BOOST_REQUIRE_EQUAL(20U, size.height());
@@ -57,21 +61,21 @@
 
 BOOST_AUTO_TEST_CASE(operator_eq)
 {
-    mlk::size size1, size2;
+    mlk::client::size size1, size2;
 
     BOOST_REQUIRE_EQUAL(size1, size2);
 }
 
 BOOST_AUTO_TEST_CASE(operator_eq_1)
 {
-    mlk::size size1(10, 20);
-    mlk::size size2(10, 20);
+    mlk::client::size size1(10, 20);
+    mlk::client::size size2(10, 20);
 
     BOOST_REQUIRE_EQUAL(size1, size2);
 }
 
 BOOST_AUTO_TEST_CASE(operator_neq)
 {
-    BOOST_REQUIRE_NE(mlk::size(10), mlk::size(20));
-    BOOST_REQUIRE_NE(mlk::size(10, 10), mlk::size(10, 20));
+    BOOST_REQUIRE_NE(mlk::client::size(10), mlk::client::size(20));
+    BOOST_REQUIRE_NE(mlk::client::size(10, 10), mlk::client::size(10, 20));
 }