main: move most of main to app, separate ownership
[staging/windowmanager.git] / src / app.cpp
index 74f3bfa..6515978 100644 (file)
 #include "json_helper.hpp"
 #include "wayland.hpp"
 
+#include <cassert>
+
 #include <json-c/json.h>
 
 namespace wm {
 
-    App::App()
-            : api{this}, display{}, controller{}
-    {}
+    namespace {
+        App *g_app;
+    }
+
+    App::App(wl::display *d)
+            : api{this}, display{d}, controller{}, outputs()
+    {
+        assert(g_app == nullptr);
+        g_app = this;
+    }
+
+    int App::init() {
+        if (!this->display->ok()) {
+            return -1;
+        }
+
+        this->display->r.add_global_handler("wl_output", [](wl_registry *r,
+                                                            uint32_t name,
+                                                            uint32_t v) {
+            g_app->outputs.emplace_back(std::make_unique<wl::output>(r, name, v));
+        });
+
+        this->display->r.add_global_handler(
+                "ivi_controller", [](wl_registry *r, uint32_t name, uint32_t v) {
+                    g_app->controller =
+                            std::make_unique<genivi::controller>(r, name, v);
+
+                    // XXX: This protocol needs the output, so lets just add our mapping
+                    // here...
+                    g_app->controller->add_proxy_to_id_mapping(
+                            g_app->outputs.back()->proxy.get(),
+                            wl_proxy_get_id(reinterpret_cast<struct wl_proxy *>(
+                                                    g_app->outputs.back()->proxy.get())));
+                });
+
+        // First level objects
+        this->display->roundtrip();
+        // Second level objects
+        this->display->roundtrip();
+        // Third level objects
+        this->display->roundtrip();
+
+        return init_layout();
+    }
+
+    int App::dispatch_events() {
+        int ret = this->display->dispatch();
+        if (ret == -1) {
+            logerror("wl_display_dipatch() returned error %d",
+                     this->display->get_error());
+            return -1;
+        }
+        this->display->flush();
+
+        // execute pending tasks, that is layout changes etc.
+        this->controller->execute_pending();
+        this->display->roundtrip();
+
+        return 0;
+    }
+
+    //  _       _ _       _                         _    ____
+    // (_)_ __ (_) |_    | | __ _ _   _  ___  _   _| |_ / /\ \
+    // | | '_ \| | __|   | |/ _` | | | |/ _ \| | | | __| |  | |
+    // | | | | | | |_    | | (_| | |_| | (_) | |_| | |_| |  | |
+    // |_|_| |_|_|\__|___|_|\__,_|\__, |\___/ \__,_|\__| |  | |
+    //              |_____|       |___/                 \_\/_/
+    int App::init_layout() {
+        if (!this->controller) {
+            logerror("ivi_controller global not available");
+            return -1;
+        }
+
+        if (this->outputs.empty()) {
+            logerror("no output was set up!");
+            return -1;
+        }
+
+        auto &c = this->controller;
+
+        auto &o = this->outputs.front();
+        auto &s = c->screens.begin()->second;
+        auto &layers = c->layers;
+
+        // XXX: Write output dimensions to ivi controller...
+        c->output_size = genivi::size{uint32_t(o->width), uint32_t(o->height)};
+
+        // Clear scene
+        layers.clear();
+
+        // Clear screen
+        s->clear();
+
+        // Setup our dummy scene...
+        c->layer_create(100, 0, 0);   // bottom layer, anything else
+        c->layer_create(1000, 0, 0);  // top layer, mandelbrot
+
+        auto &l100 = c->layers[100];
+        auto &l1k = c->layers[1000];
+
+        // Set layers fullscreen
+        l100->set_destination_rectangle(0, 0, o->width, o->height);
+        l1k->set_destination_rectangle(0, 0, o->width, o->height);
+        l100->set_visibility(1);
+        l1k->set_visibility(1);
+
+        // Add layers to screen
+        s->set_render_order({100, 1000});
+
+        c->commit_changes();
+
+        this->display->flush();
+
+        return 0;
+    }
 
     binding_api::result_type binding_api::register_surface(uint32_t appid,
                                                           uint32_t surfid) {