From 7a5d735041a1390fffda46ef451d70859137a808 Mon Sep 17 00:00:00 2001 From: Marcus Fritzsch Date: Tue, 29 Aug 2017 13:23:43 +0200 Subject: [PATCH] app: added enddraw() and deactivate_surface() Implementation untested, not sure if this is even sensible... Signed-off-by: Marcus Fritzsch --- generate-binding-glue.py | 14 +++++++ src/app.cpp | 101 ++++++++++++++++++++++++++++++++++++++++++----- src/app.hpp | 11 +++++- 3 files changed, 115 insertions(+), 11 deletions(-) diff --git a/generate-binding-glue.py b/generate-binding-glue.py index c6fda53..66f55cf 100644 --- a/generate-binding-glue.py +++ b/generate-binding-glue.py @@ -112,12 +112,26 @@ API = { { 'name': 'drawing_name', 'type': 'char const*', 'jtype': 'string' }, ], }, + { + 'name': 'deactivate_surface', + 'args': [ + { 'name': 'drawing_name', 'type': 'char const*', 'jtype': 'string' }, + ], + }, + { + 'name': 'enddraw', + 'args': [ + { 'name': 'drawing_name', 'type': 'char const*', 'jtype': 'string' }, + ], + }, { 'name': 'list_drawing_names', }, { 'name': 'demo_activate_surface', 'args': [ { 'name': 'surfaceid', 'type': 'uint32_t', 'jtype': 'int' } ] }, + { 'name': 'demo_activate_all' }, + { 'name': 'debug_status', }, { 'name': 'debug_layers', }, { 'name': 'debug_surfaces', }, diff --git a/src/app.cpp b/src/app.cpp index 07747b9..76668cc 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -129,7 +129,8 @@ App::App(wl::display *d) layers(), pending(), name_mapping(), - id_alloc{} { + id_alloc{}, + last_active() { assert(g_app == nullptr); g_app = this; @@ -177,7 +178,7 @@ int App::init() { this->display->add_global_handler( "ivi_controller", [this](wl_registry *r, uint32_t name, uint32_t v) { - this->controller = std::make_unique(r, name, v); + this->controller = std::make_unique(r, name, v); // Init controller hooks this->controller->chooks = &this->chooks; @@ -270,6 +271,11 @@ int App::init_layout() { } void App::surface_set_layout(uint32_t surface_id) { + if (!this->controller->surface_exists(surface_id)) { + logerror("Surface %d does not exist", int(surface_id)); + return; + } + auto o_layer_id = this->layers.get_layer_id(surface_id); if (!o_layer_id) { @@ -277,11 +283,6 @@ void App::surface_set_layout(uint32_t surface_id) { return; } - if (!this->controller->surface_exists(surface_id)) { - logerror("Surface %d does not exist", int(surface_id)); - return; - } - uint32_t layer_id = o_layer_id.value(); logdebug("surface_set_layout for surface %u on layer %u", surface_id, layer_id); @@ -346,10 +347,50 @@ char const *App::activate_surface(uint32_t surface_id) { this->controller->commit_changes(); this->display->flush(); + // Current active surface is the first in last_active + this->last_active.push_front(s->id); + /// // XXX: I am not sure I even need 5 elements... + /// this->last_active.resize(std::min(int(this->last_active.size()), 5)); + + // no error return nullptr; } +char const *App::deactivate_surface(uint32_t surface_id) { + if (surface_id == this->layers.main_surface) { + return "Cannot deactivate main_surface"; + } + + if (this->last_active.empty()) { + return "Cannot deactivate surface (not active)"; + } + + // XXX: should an active surface not alsways be front() or + // front+1() of last_active?! + + // XXX: Should I really be able to deactivate a surface that is not + // front() of last_active? + auto is = std::find(this->last_active.begin(), + this->last_active.end(), + surface_id); + + if (is == this->last_active.end()) { + return "Cannot deactivate surface (not active)"; + } + + this->last_active.erase(is); + + if (! this->last_active.empty()) { + // Should be active already, shouldn't it? + this->activate_surface(this->last_active.front()); + } else { + this->activate_surface(this->layers.main_surface); + } + + return nullptr; +} + void App::add_task(char const *name, std::function &&f) { this->pending.emplace_back(std::make_pair(name, f)); } @@ -373,6 +414,8 @@ void App::execute_pending() { // | .__/|_| \___/_/\_\_|\___|\__,_| |_____| \_/ \___|_| |_|\__|___/ // |_| void App::surface_created(uint32_t surface_id) { + surface_id &= id_allocator::id_mask; + logdebug("surface_id is %u", surface_id); // We need to execute the surface setup after its creation. @@ -381,10 +424,21 @@ void App::surface_created(uint32_t surface_id) { } void App::surface_removed(uint32_t surface_id) { + surface_id &= id_allocator::id_mask; + logdebug("surface_id is %u", surface_id); this->add_task("remove surface ID", - [surface_id, this] { this->id_alloc.remove_id(surface_id); }); + [surface_id, this] { + this->id_alloc.remove_id(surface_id); + + // Also remove from last_active, if found + auto i = std::find(this->last_active.begin(), + this->last_active.end(), surface_id); + if (i != this->last_active.end()) { + this->last_active.erase(i); + } + }); } result App::request_surface(char const *drawing_name) { @@ -421,8 +475,20 @@ char const *App::activate_surface(char const *drawing_name) { if (osid) { logdebug("ativate surface with name %s and id %u", drawing_name, osid.value()); - this->activate_surface(osid.value()); - return nullptr; + return this->activate_surface(osid.value()); + } + + logerror("surface %s unknown", drawing_name); + return "Surface unknown"; +} + +char const *App::deactivate_surface(char const *drawing_name) { + auto osid = this->id_alloc.lookup(drawing_name); + + if (osid) { + logdebug("deativate surface with name %s and id %u", drawing_name, + osid.value()); + return this->deactivate_surface(osid.value()); } logerror("surface %s unknown", drawing_name); @@ -454,7 +520,22 @@ binding_api::result_type binding_api::activate_surface( return Ok(json_object_new_object()); } +binding_api::result_type binding_api::deactivate_surface(char const* drawing_name) { + logdebug("%s drawing_name %s", __func__, drawing_name); + auto r = this->app->deactivate_surface(drawing_name); + if (r != nullptr) { + return Err(r); + } + return Ok(json_object_new_object()); +} + +binding_api::result_type binding_api::enddraw(char const* drawing_name) { + logdebug("%s drawing_name %s", __func__, drawing_name); + return Err("not implemented"); +} + binding_api::result_type binding_api::list_drawing_names() { + logdebug("%s", __func__); json j = this->app->id_alloc.names; return Ok(json_tokener_parse(j.dump().c_str())); } diff --git a/src/app.hpp b/src/app.hpp index 8f30d96..ac2eca6 100644 --- a/src/app.hpp +++ b/src/app.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #include "afb_binding_api.hpp" #include "config.hpp" @@ -41,7 +42,10 @@ struct controller; namespace wm { struct id_allocator { - unsigned next = 0x0100'0000; + constexpr static unsigned id_shift = 20; + constexpr static unsigned id_mask = (1 << id_shift) - 1; + + unsigned next = 1; // Surfaces that where requested but not yet created std::unordered_map surfaces; @@ -56,6 +60,7 @@ struct id_allocator { // Insert and return a new ID unsigned generate_id(std::string const &name) { unsigned sid = this->next++; + sid <<= id_shift; this->surfaces[sid] = name; // this->pending_surfaces.insert({sid}); this->names[name] = sid; @@ -117,6 +122,8 @@ struct App { struct id_allocator id_alloc; + std::deque last_active; + explicit App(wl::display *d); ~App(); @@ -132,12 +139,14 @@ struct App { void surface_set_layout(uint32_t surface_id); char const *activate_surface(uint32_t surface_id); + char const *deactivate_surface(uint32_t surface_id); // Allocate a surface ID for this role result request_surface(char const *drawing_name); // Activate (i.e. make visible, if allowed!) a surface char const *activate_surface(char const *drawing_name); + char const *deactivate_surface(char const *drawing_name); // add tasks, executed after dispatch_events() void add_task(char const *name, std::function &&f); -- 2.16.6