Implement surface names
[staging/windowmanager.git] / src / app.cpp
index db0a5e3..c38a7f4 100644 (file)
@@ -31,6 +31,7 @@
 #include <bits/signum.h>
 #include <csignal>
 #include <fstream>
+#include <algorithm>
 #include <json.hpp>
 
 namespace wm {
@@ -44,8 +45,7 @@ struct wm::area area_from_json(json const &j) {
    return wm::area{
       j["name"],
       {
-         j["width"], j["height"],
-         j["x"], j["y"],
+         j["width"], j["height"], j["x"], j["y"],
       },
       j["zorder"],
    };
@@ -126,7 +126,11 @@ App::App(wl::display *d)
      outputs(),
      config(),
      layouts(),
-     layers() {
+     layers(),
+     pending(),
+     name_mapping(),
+     id_alloc{}
+{
    assert(g_app == nullptr);
    g_app = this;
 
@@ -280,8 +284,10 @@ void App::surface_set_layout(uint32_t surface_id) {
    }
 
    uint32_t layer_id = o_layer_id.value();
+   logdebug("surface_set_layout for surface %u on layer %u", surface_id, layer_id);
 
-   auto rect = this->layers.get_layer_rect(surface_id).value();
+   auto const &layer = this->layers.get_layer(layer_id);
+   auto rect = layer.value().rect;
    auto &s = this->controller->surfaces[surface_id];
 
    int x = rect.x;
@@ -305,7 +311,7 @@ void App::surface_set_layout(uint32_t surface_id) {
 
    // XXX: visibility should be determined independently of our
    //      layer + geometry setup.
-   s->set_visibility(1);
+   s->set_visibility(surface_id == (unsigned)this->layers.main_surface ? 1 : 0);
    this->controller->layers[layer_id]->add_surface(s.get());
 
    logdebug("Surface %u now on layer %u with rect { %d, %d, %d, %d }",
@@ -317,7 +323,7 @@ char const *App::activate_surface(uint32_t surface_id) {
       return "Surface does not exist";
    }
 
-   // This shouild involve a policy check, but as we do not (yet) have
+   // This should involve a policy check, but as we do not (yet) have
    // such a thing, we will just switch to this surface.
    // XXX: input focus missing!!1
 
@@ -376,24 +382,81 @@ void App::surface_removed(uint32_t surface_id) {
    logdebug("surface_id is %u", surface_id);
 }
 
+result<int> App::request_surface(char const *drawing_name) {
+   auto lid = this->layers.get_layer_id(std::string(drawing_name));
+   if (!lid) {
+      // XXX: to we need to put these applications on the App layer?
+      return Err<int>("Drawing name does not match any role");
+   }
+
+   auto rname = this->id_alloc[drawing_name];
+   if (! rname) {
+      // name does not exist yet, allocate surface id...
+      // XXX: how to allocate surface IDs?
+      // * allocate by running a counter for each layer?
+      // * allocate IDs globally, i.e. do not have layers contain
+      //   ID ranges (only define the surfaces on the layer by
+      //   role?)
+      auto id = int(this->id_alloc(drawing_name));
+      this->layers.add_surface(id, lid.value());
+
+      // XXX: setup the main_surface id if we registered HomeScreen
+      // XXX: you should fix this!
+      if (!this->layers.main_surface_name.empty() &&
+           this->layers.main_surface_name == drawing_name) {
+         this->layers.main_surface = id;
+         this->activate_surface(id);
+         logdebug("Set main_surface id to %u", id);
+      }
+
+      return Ok<int>(id);
+   }
+
+   // Check currently registered drawing names if it is already there.
+   return Err<int>("Surface already present");
+}
+
+char const* App::activate_surface(char const *drawing_name) {
+   auto osid = this->id_alloc[drawing_name];
+
+   if (osid) {
+      logdebug("ativate surface with name %s and id %u", drawing_name, osid.value());
+      this->activate_surface(osid.value());
+      return nullptr;
+   }
+
+   logerror("surface %s unknown", drawing_name);
+   return "Surface unknown";
+}
+
 //  _     _           _ _                            _   _                 _
 // | |__ (_)_ __   __| (_)_ __   __ _     __ _ _ __ (_) (_)_ __ ___  _ __ | |
 // | '_ \| | '_ \ / _` | | '_ \ / _` |   / _` | '_ \| | | | '_ ` _ \| '_ \| |
 // | |_) | | | | | (_| | | | | | (_| |  | (_| | |_) | | | | | | | | | |_) | |
 // |_.__/|_|_| |_|\__,_|_|_| |_|\__, |___\__,_| .__/|_| |_|_| |_| |_| .__/|_|
 //                              |___/_____|   |_|                   |_|
-binding_api::result_type binding_api::register_surface(uint32_t appid,
-                                                       uint32_t surfid) {
-   logdebug("%s appid %u surfid %u", __func__, appid, surfid);
-   if (appid > 0xff) {
-      return Err<json_object *>("invalid appid");
+binding_api::result_type binding_api::request_surface(
+   char const *drawing_name) {
+   auto r = this->app->request_surface(drawing_name);
+   if (r.is_err()) {
+      return Err<json_object*>(r.unwrap_err());
    }
+   return Ok(json_object_new_int(r.unwrap()));
+}
 
-   if (surfid > 0xffff) {
-      return Err<json_object *>("invalid surfaceid");
+binding_api::result_type binding_api::activate_surface(
+   char const *drawing_name) {
+   logdebug("%s drawing_name %s", __func__, drawing_name);
+   auto r = this->app->activate_surface(drawing_name);
+   if (r) {
+      return Err<json_object *>(r);
    }
+   return Ok(json_object_new_object());
+}
 
-   return Ok(json_object_new_int((appid << 16) + surfid));
+binding_api::result_type binding_api::list_drawing_names() {
+   json j = this->app->id_alloc.names;
+   return Ok(json_tokener_parse(j.dump().c_str()));
 }
 
 binding_api::result_type binding_api::debug_layers() {