*/
#include <regex>
-
+#include <ilm/ilm_control.h>
+#include <stdlib.h>
+#include "wm_client.hpp"
#include "wm_layer.hpp"
#include "json_helper.hpp"
#include "util.hpp"
+using std::string;
+using std::vector;
+using std::unordered_map;
+
+#define BG_LAYER_NAME "BackGroundLayer"
+
namespace wm
{
-using json = nlohmann::json;
+LayerState::LayerState()
+ : render_order(),
+ area2appid()
+{}
-layer::layer(nlohmann::json const &j)
+const unordered_map<string, string> LayerState::getCurrentState()
{
- this->role = j["role"];
- this->name = j["name"];
- this->layer_id = j["layer_id"];
+ return this->area2appid;
+}
- HMI_DEBUG("layer_id:%d name:%s", this->layer_id, this->name.c_str());
+const vector<unsigned> LayerState::getIviIdList()
+{
+ return this->render_order;
}
-struct result<struct layer_map> to_layer_map(nlohmann::json const &j)
+void LayerState::addLayer(unsigned layer)
{
- try
- {
- layer_map stl{};
- auto m = j["mappings"];
-
- std::transform(std::cbegin(m), std::cend(m),
- std::inserter(stl.mapping, stl.mapping.end()),
- [](nlohmann::json const &j) {
- return std::pair<int, struct layer>(
- j.value("layer_id", -1), layer(j));
- });
-
- // TODO: add sanity checks here?
- // * check for double IDs
- // * check for double names/roles
-
- stl.layers.reserve(m.size());
- std::transform(std::cbegin(stl.mapping), std::cend(stl.mapping),
- std::back_inserter(stl.layers),
- [&stl](std::pair<int, struct layer> const &k) {
- stl.roles.emplace_back(
- std::make_pair(k.second.role, k.second.layer_id));
- return unsigned(k.second.layer_id);
- });
-
- std::sort(stl.layers.begin(), stl.layers.end());
-
- for (auto i : stl.mapping)
- {
- if (i.second.name.empty())
- {
- return Err<struct layer_map>("Found mapping w/o name");
- }
- if (i.second.layer_id == -1)
- {
- return Err<struct layer_map>("Found invalid/unset IDs in mapping");
- }
- }
+ auto result = std::find(this->render_order.begin(), this->render_order.end(), layer);
+ if(result == this->render_order.end())
+ this->render_order.push_back(layer);
+}
- auto msi = j.find("main_surface");
- if (msi != j.end())
- {
- stl.main_surface_name = msi->value("surface_role", "");
- stl.main_surface = -1;
+void LayerState::removeLayer(unsigned layer)
+{
+ auto fwd_itr = std::remove_if(
+ this->render_order.begin(), this->render_order.end(),
+ [layer](unsigned elm) {
+ if(elm == layer)
+ HMI_DEBUG("remove layer %d", elm);
+ return elm == layer;
}
+ );
+ this->render_order.erase(fwd_itr, this->render_order.end());
+}
+
+bool LayerState::hasLayer(unsigned layer)
+{
+ auto itr = std::find(this->render_order.begin(), this->render_order.end(), layer);
+ return (itr != this->render_order.end()) ? true : false;
+}
+
+void LayerState::attachAppToArea(const string& app, const string& area)
+{
+ this->area2appid[area] = app;
+}
- return Ok(stl);
+void LayerState::dump()
+{
+ std::string ids, apps;
+ for(const auto& ro : this->render_order)
+ {
+ ids += std::to_string(ro);
+ ids += ",";
}
- catch (std::exception &e)
+ for(const auto& area : this->area2appid)
{
- return Err<struct layer_map>(e.what());
+ apps += area.first;
+ apps += ":";
+ apps += area.second;
+ apps += ",";
}
+ DUMP(" render order : %s", ids.c_str());
+ DUMP(" area, app : %s", apps.c_str());
}
-optional<int>
-layer_map::get_layer_id(int surface_id)
+WMLayer::WMLayer(json_object* j, unsigned wm_layer_id) : tmp_state(), state(), wm_layer_id(wm_layer_id)
{
- auto i = this->surfaces.find(surface_id);
- if (i != this->surfaces.end())
+ this->name = jh::getStringFromJson(j, "name");
+ this->role_list = jh::getStringFromJson(j, "role");
+ this->id_begin = static_cast<unsigned>(jh::getIntFromJson(j, "id_range_begin"));
+ this->id_end = static_cast<unsigned>(jh::getIntFromJson(j, "id_range_end"));
+ this->screen = jh::getIntFromJson(j, "screen"); // screen is not defined in layers.json, screen is set to 0
+
+ if (name.empty())
+ {
+ HMI_ERROR("Parse Error!!");
+ exit(1);
+ }
+ if(this->id_begin > this->id_end)
{
- return optional<int>(i->second);
+ HMI_ERROR("INVALID");
+ exit(1);
}
- return nullopt;
}
-optional<int> layer_map::get_layer_id(std::string const &role)
+unsigned WMLayer::getNewLayerID(const string& role)
{
- for (auto const &r : this->roles)
+ unsigned ret = 0;
+ if(this->name == BG_LAYER_NAME)
+ return ret;
+
+ // generate new layer id;
+ if(this->hasRole(role))
{
- auto re = std::regex(r.first);
- if (std::regex_match(role, re))
+ if(this->id_list.size() == 0)
+ {
+ ret = this->idBegin();
+ this->id_list.push_back(ret);
+ }
+ else
{
- HMI_DEBUG("role %s matches layer %d", role.c_str(), r.second);
- return optional<int>(r.second);
+ ret = this->id_list.back() + 1;
}
+ HMI_INFO("Generate new id: %d", ret);
+ }
+ else
+ {
+ return ret;
}
- HMI_DEBUG("role %s does NOT match any layer", role.c_str());
- return nullopt;
-}
-json layer::to_json() const
-{
- auto is_full = this->rect == compositor::full_rect;
+ size_t count = std::count(id_list.begin(), id_list.end(), ret);
+ if( (ret > this->idEnd()) || (count > 1))
+ {
+ HMI_NOTICE("id %d is not available then generate new id", ret);
+ ret = 0; // reset
+ for(unsigned i = this->idBegin(); i < this->idEnd(); i++)
+ {
+ auto ret_found = std::find(id_list.begin(), id_list.end(), i);
+ if(ret_found == id_list.cend())
+ {
+ HMI_INFO("set new id: %d", i);
+ ret = i;
+ break;
+ }
+ }
+ }
- json r{};
- if (is_full)
+ if(ret != 0)
{
- r = {{"type", "full"}};
+ id_list.push_back(ret);
}
else
{
- r = {{"type", "rect"},
- {"rect",
- {{"x", this->rect.x},
- {"y", this->rect.y},
- {"width", this->rect.w},
- {"height", this->rect.h}}}};
+ HMI_ERROR("failed to get New ID");
}
-
- return {
- {"name", this->name},
- {"role", this->role},
- {"layer_id", this->layer_id},
- {"area", r},
- };
+ return ret;
}
-json layer_map::to_json() const
+const string& WMLayer::layerName()
{
- json j{};
- for (auto const &i : this->mapping)
- {
- j.push_back(i.second.to_json());
- }
- return j;
+ return this->name;
}
-void layer_map::setupArea(double scaling)
+WMError WMLayer::setLayerState(const LayerState& l)
{
- compositor::rect rct;
-
- rct = this->area2size["normal.full"];
- this->area2size["normalfull"] = rct;
- this->area2size["normal"] = rct;
-
- for (auto &i : this->area2size)
- {
- i.second.x = static_cast<int>(scaling * i.second.x + 0.5);
- i.second.y = static_cast<int>(scaling * i.second.y + 0.5);
- i.second.w = static_cast<int>(scaling * i.second.w + 0.5);
- i.second.h = static_cast<int>(scaling * i.second.h + 0.5);
-
- HMI_DEBUG("area:%s size(after) : x:%d y:%d w:%d h:%d",
- i.first.c_str(), i.second.x, i.second.y, i.second.w, i.second.h);
- }
+ this->tmp_state = l;
+ return WMError::SUCCESS;
}
-compositor::rect layer_map::getAreaSize(const std::string &area)
+void WMLayer::addLayerToState(unsigned layer)
{
- return area2size[area];
+ this->tmp_state.addLayer(layer);
}
-int layer_map::loadAreaDb()
+void WMLayer::removeLayerFromState(unsigned layer)
{
- // Get afm application installed dir
- char const *afm_app_install_dir = getenv("AFM_APP_INSTALL_DIR");
- HMI_DEBUG("afm_app_install_dir:%s", afm_app_install_dir);
+ this->tmp_state.removeLayer(layer);
+}
- std::string file_name;
- if (!afm_app_install_dir)
- {
- HMI_ERROR("AFM_APP_INSTALL_DIR is not defined");
- }
- else
- {
- file_name = std::string(afm_app_install_dir) + std::string("/etc/areas.db");
- }
+bool WMLayer::hasLayerFromState(unsigned layer)
+{
+ this->tmp_state.hasLayer(layer);
+}
- // Load area.db
- json_object *json_obj;
- int ret = jh::inputJsonFilie(file_name.c_str(), &json_obj);
- if (0 > ret)
- {
- HMI_DEBUG("Could not open area.db, so use default area information");
- json_obj = json_tokener_parse(kDefaultAreaDb);
- }
- HMI_DEBUG("json_obj dump:%s", json_object_get_string(json_obj));
+void WMLayer::attachAppToArea(const string& app, const string& area)
+{
+ this->tmp_state.attachAppToArea(app, area);
+}
- // Perse areas
- HMI_DEBUG("Perse areas");
- json_object *json_cfg;
- if (!json_object_object_get_ex(json_obj, "areas", &json_cfg))
+string WMLayer::attachedApp(const string& area)
+{
+ string ret;
+ auto list = this->state.getCurrentState();
+ auto app = list.find(area);
+ if(app != list.end())
{
- HMI_ERROR("Parse Error!!");
- return -1;
+ ret = app->second;
}
+ return ret;
+}
- int len = json_object_array_length(json_cfg);
- HMI_DEBUG("json_cfg len:%d", len);
- HMI_DEBUG("json_cfg dump:%s", json_object_get_string(json_cfg));
-
- const char *area;
- for (int i = 0; i < len; i++)
- {
- json_object *json_tmp = json_object_array_get_idx(json_cfg, i);
- HMI_DEBUG("> json_tmp dump:%s", json_object_get_string(json_tmp));
-
- area = jh::getStringFromJson(json_tmp, "name");
- if (nullptr == area)
- {
- HMI_ERROR("Parse Error!!");
- return -1;
- }
- HMI_DEBUG("> area:%s", area);
-
- json_object *json_rect;
- if (!json_object_object_get_ex(json_tmp, "rect", &json_rect))
- {
- HMI_ERROR("Parse Error!!");
- return -1;
- }
- HMI_DEBUG("> json_rect dump:%s", json_object_get_string(json_rect));
+void WMLayer::appendArea(const string& area)
+{
+ this->area_list.push_back(area);
+}
- compositor::rect area_size;
- area_size.x = jh::getIntFromJson(json_rect, "x");
- area_size.y = jh::getIntFromJson(json_rect, "y");
- area_size.w = jh::getIntFromJson(json_rect, "w");
- area_size.h = jh::getIntFromJson(json_rect, "h");
+void WMLayer::appTerminated(unsigned id)
+{
+ auto fwd_itr = std::remove_if(this->id_list.begin(), this->id_list.end(),
+ [id](unsigned elm) {
+ return elm == id;
+ });
+ this->id_list.erase(fwd_itr, this->id_list.end());
+ this->tmp_state.removeLayer(id);
+ this->state.removeLayer(id);
+ ilm_layerRemove(id);
+}
- this->area2size[area] = area_size;
- }
+bool WMLayer::hasLayerID(unsigned id)
+{
+ bool ret = (id >= this->idBegin() && id <= this->idEnd());
+ if(!ret)
+ return ret;
+ auto itr = std::find(this->id_list.begin(), this->id_list.end(), id);
+ return (itr != this->id_list.end()) ? true : false;
+}
- // Check
- for (auto itr = this->area2size.begin();
- itr != this->area2size.end(); ++itr)
+bool WMLayer::hasRole(const string& role)
+{
+ auto re = std::regex(this->role_list);
+ if (std::regex_match(role, re))
{
- HMI_DEBUG("area:%s x:%d y:%d w:%d h:%d",
- itr->first.c_str(), itr->second.x, itr->second.y,
- itr->second.w, itr->second.h);
+ HMI_DEBUG("role %s matches layer %s", role.c_str(), this->name.c_str());
+ return true;
}
+ return false;
+}
- // Release json_object
- json_object_put(json_obj);
+void WMLayer::update()
+{
+ this->state = this->tmp_state;
+}
- return 0;
+void WMLayer::undo()
+{
+ this->tmp_state = this->state;
}
-const char* layer_map::kDefaultAreaDb = "{ \
- \"areas\": [ \
- { \
- \"name\": \"fullscreen\", \
- \"rect\": { \
- \"x\": 0, \
- \"y\": 0, \
- \"w\": 1080, \
- \"h\": 1920 \
- } \
- }, \
- { \
- \"name\": \"normal.full\", \
- \"rect\": { \
- \"x\": 0, \
- \"y\": 218, \
- \"w\": 1080, \
- \"h\": 1488 \
- } \
- }, \
- { \
- \"name\": \"split.main\", \
- \"rect\": { \
- \"x\": 0, \
- \"y\": 218, \
- \"w\": 1080, \
- \"h\": 744 \
- } \
- }, \
- { \
- \"name\": \"split.sub\", \
- \"rect\": { \
- \"x\": 0, \
- \"y\": 962, \
- \"w\": 1080, \
- \"h\": 744 \
- } \
- }, \
- { \
- \"name\": \"software_keyboard\", \
- \"rect\": { \
- \"x\": 0, \
- \"y\": 962, \
- \"w\": 1080, \
- \"h\": 744 \
- } \
- }, \
- { \
- \"name\": \"restriction.normal\", \
- \"rect\": { \
- \"x\": 0, \
- \"y\": 218, \
- \"w\": 1080, \
- \"h\": 1488 \
- } \
- }, \
- { \
- \"name\": \"restriction.split.main\", \
- \"rect\": { \
- \"x\": 0, \
- \"y\": 218, \
- \"w\": 1080, \
- \"h\": 744 \
- } \
- }, \
- { \
- \"name\": \"restriction.split.sub\", \
- \"rect\": { \
- \"x\": 0, \
- \"y\": 962, \
- \"w\": 1080, \
- \"h\": 744 \
- } \
- }, \
- { \
- \"name\": \"on_screen\", \
- \"rect\": { \
- \"x\": 0, \
- \"y\": 218, \
- \"w\": 1080, \
- \"h\": 1488 \
- } \
- } \
- ] \
-}";
+void WMLayer::dump()
+{
+ DUMP("===== wm layer status =====");
+ DUMP("Layer :%s on screen %d", this->name.c_str(), this->screen);
+ DUMP(" [Current]");
+ this->state.dump();
+ DUMP(" [To be]");
+ this->tmp_state.dump();
+ DUMP("===== wm layer status end =====");
+
+}
} // namespace wm