diff options
author | Kazumasa Mitsunari <knimitz@witz-inc.co.jp> | 2019-01-29 13:18:17 +0900 |
---|---|---|
committer | Kazumasa Mitsunari <knimitz@witz-inc.co.jp> | 2019-02-04 19:54:01 +0900 |
commit | a0fa6394c0d8b7997343d6f2a44d9c2868f4be5f (patch) | |
tree | 33dee52eb43bfbf77fafbcecbe5e96a062179853 /src | |
parent | b72e372690e677c38fa9b5ae90fb7fbe5a575c76 (diff) |
Fix top surface becomes invisible when background surface is crashed.
Fix top surface becomes invisible when surface on same layer,
such like application layer, is crashed.
To fix this issue, I refactored attaching app to layer.
Originally, window manager attached app to surface.
This patch is the backport of master branch.
Bug-AGL : SPEC-1635
Change-Id: Ie6713e669a25662e8547aa7782551ddae60c7e01
Signed-off-by: Kazumasa Mitsunari <knimitz@witz-inc.co.jp>
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 26 | ||||
-rw-r--r-- | src/applist.cpp | 36 | ||||
-rw-r--r-- | src/applist.hpp | 7 | ||||
-rw-r--r-- | src/controller_hooks.hpp | 41 | ||||
-rw-r--r-- | src/db/areas.db | 85 | ||||
-rw-r--r-- | src/db/old_roles.db | 68 | ||||
-rw-r--r-- | src/json_helper.cpp | 65 | ||||
-rw-r--r-- | src/json_helper.hpp | 3 | ||||
-rw-r--r-- | src/layers.cpp | 343 | ||||
-rw-r--r-- | src/layers.hpp | 158 | ||||
-rw-r--r-- | src/layout.cpp | 17 | ||||
-rw-r--r-- | src/layout.hpp | 41 | ||||
-rw-r--r-- | src/main.cpp | 249 | ||||
-rw-r--r-- | src/pm_wrapper.cpp | 9 | ||||
-rw-r--r-- | src/request.hpp | 6 | ||||
-rw-r--r-- | src/util.cpp | 2 | ||||
-rw-r--r-- | src/util.hpp | 29 | ||||
-rw-r--r-- | src/wayland_ivi_wm.cpp | 721 | ||||
-rw-r--r-- | src/wayland_ivi_wm.hpp | 326 | ||||
-rw-r--r-- | src/window_manager.cpp | 922 | ||||
-rw-r--r-- | src/window_manager.hpp | 115 | ||||
-rw-r--r-- | src/wm_client.cpp | 280 | ||||
-rw-r--r-- | src/wm_client.hpp | 47 | ||||
-rw-r--r-- | src/wm_layer.cpp | 260 | ||||
-rw-r--r-- | src/wm_layer.hpp | 97 | ||||
-rw-r--r-- | src/wm_layer_control.cpp | 645 | ||||
-rw-r--r-- | src/wm_layer_control.hpp | 105 |
27 files changed, 1658 insertions, 3045 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3c8da4c..5c532e2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -14,10 +14,9 @@ # limitations under the License. # -wlproto(IVI_CON ivi-wm) - include(FindPkgConfig) pkg_check_modules(AFB REQUIRED afb-daemon) +pkg_check_modules(ILM REQUIRED ilmControl ilmCommon) pkg_check_modules(SD REQUIRED libsystemd>=222) # We do not want a prefix for our module @@ -27,24 +26,22 @@ set(TARGETS_WM windowmanager-service) add_library(${TARGETS_WM} MODULE main.cpp - wayland_ivi_wm.cpp util.cpp - layout.cpp - ${IVI_CON_PROTO} json_helper.cpp + applist.cpp + request.cpp + pm_wrapper.cpp window_manager.cpp - layers.cpp wm_client.cpp wm_error.cpp - applist.cpp - request.cpp - pm_wrapper.cpp) + wm_layer.cpp + wm_layer_control.cpp) target_include_directories(${TARGETS_WM} PRIVATE ${AFB_INCLUDE_DIRS} ${SD_INCLUDE_DIRS} - ../include + ${ILM_INCLUDE_DIRS} ../src ../${PLUGIN_PM}) @@ -52,6 +49,7 @@ target_link_libraries(${TARGETS_WM} PRIVATE ${AFB_LIBRARIES} ${WLC_LIBRARIES} + ${ILM_LIBRARIES} ${SD_LIBRARIES} ${PLUGIN_PM}) @@ -71,7 +69,7 @@ endif() target_compile_options(${TARGETS_WM} PRIVATE - -Wall -Wextra -Wno-unused-parameter -Wno-comment) + -Wall -Wextra -Wno-unused-parameter -Wno-comment -Wno-missing-field-initializers) set_target_properties(${TARGETS_WM} PROPERTIES @@ -112,9 +110,9 @@ add_custom_command(TARGET ${TARGETS_WM} POST_BUILD COMMAND mkdir -p ${PROJECT_BINARY_DIR}/package/root/lib COMMAND cp -rf ${PROJECT_BINARY_DIR}/src/${TARGETS_WM}.so ${PROJECT_BINARY_DIR}/package/root/lib COMMAND mkdir -p ${PROJECT_BINARY_DIR}/package/root/etc - COMMAND cp -f ${PROJECT_SOURCE_DIR}/layers.json ${PROJECT_BINARY_DIR}/package/root/etc - COMMAND cp -f ${PROJECT_SOURCE_DIR}/src/db/old_roles.db ${PROJECT_BINARY_DIR}/package/root/etc - COMMAND cp -f ${PROJECT_SOURCE_DIR}/src/db/areas.db ${PROJECT_BINARY_DIR}/package/root/etc + COMMAND cp -f ${PROJECT_SOURCE_DIR}/conf/old_roles.db ${PROJECT_BINARY_DIR}/package/root/etc + COMMAND cp -f ${CMAKE_SOURCE_DIR}/conf/layers.json ${PROJECT_BINARY_DIR}/package/root/etc + COMMAND cp -f ${CMAKE_SOURCE_DIR}/conf/areas.json ${PROJECT_BINARY_DIR}/package/root/etc ) add_custom_target(package DEPENDS ${PROJECT_BINARY_DIR}/package/root diff --git a/src/applist.cpp b/src/applist.cpp index f0dade0..67980f1 100644 --- a/src/applist.cpp +++ b/src/applist.cpp @@ -65,7 +65,7 @@ AppList::~AppList() {} * @attention This function should be called once for the app * Caller should take care not to be called more than once. */ -void AppList::addClient(const std::string &appid, unsigned layer, unsigned surface, const std::string &role) +void AppList::addClient(const string &appid, unsigned layer, unsigned surface, const string &role) { std::lock_guard<std::mutex> lock(this->mtx); shared_ptr<WMClient> client = std::make_shared<WMClient>(appid, layer, surface, role); @@ -73,6 +73,14 @@ void AppList::addClient(const std::string &appid, unsigned layer, unsigned surfa this->clientDump(); } +void AppList::addClient(const string &appid, unsigned layer, const string &role) +{ + std::lock_guard<std::mutex> lock(this->mtx); + shared_ptr<WMClient> client = std::make_shared<WMClient>(appid, layer, role); + this->app2client[appid] = client; + this->clientDump(); +} + /** * Remove WMClient from the list * @@ -132,7 +140,14 @@ void AppList::removeSurface(unsigned surface){ */ shared_ptr<WMClient> AppList::lookUpClient(const string &appid) { - return this->app2client.at(appid); + if(this->app2client.count(appid) != 0) + { + return this->app2client.at(appid); + } + else + { + return nullptr; + } } /** @@ -154,17 +169,16 @@ int AppList::countClient() const * Returns AppID if found. * * @param unsigned[in] surfaceID - * @param string[in] role * @param bool[in,out] AppID is found or not * @return AppID * @attention If AppID is not found, param found will be false. */ -string AppList::getAppID(unsigned surface, const string& role, bool* found) const +string AppList::getAppID(unsigned surface, bool* found) const { *found = false; for (const auto &x : this->app2client) { - if(x.second->surfaceID(role) == surface){ + if(x.second->surfaceID() == surface){ *found = true; return x.second->appID(); } @@ -296,6 +310,10 @@ const vector<struct WMAction> &AppList::getActions(unsigned req_num, bool* found } } HMI_SEQ_ERROR(req_num, "Couldn't get action with the request : %d", req_num); + { + static vector<struct WMAction> empty; + return empty; + } } /** @@ -351,7 +369,7 @@ WMError AppList::setAction(unsigned req_num, const struct WMAction &action) * otherwise (visible is false) app should be invisible. Then enddraw_finished param is set to true. * This function doesn't support actions for focus yet. */ -WMError AppList::setAction(unsigned req_num, const string &appid, const string &role, const string &area, TaskVisible visible) +WMError AppList::setAction(unsigned req_num, shared_ptr<WMClient> client, const string &role, const string &area, TaskVisible visible) { std::lock_guard<std::mutex> lock(this->mtx); WMError result = WMError::FAIL; @@ -363,7 +381,7 @@ WMError AppList::setAction(unsigned req_num, const string &appid, const string & } // If visible task is not invisible, redraw is required -> true bool edraw_f = (visible != TaskVisible::INVISIBLE) ? false : true; - WMAction action{appid, role, area, visible, edraw_f}; + WMAction action{req_num, client, role, area, visible, edraw_f}; x.sync_draw_req.push_back(action); result = WMError::SUCCESS; @@ -399,7 +417,7 @@ bool AppList::setEndDrawFinished(unsigned req_num, const string &appid, const st { for (auto &y : x.sync_draw_req) { - if (y.appid == appid && y.role == role) + if (y.client->appID() == appid && y.role == role) { HMI_SEQ_INFO(req_num, "Role %s finish redraw", y.role.c_str()); y.end_draw_finished = true; @@ -514,7 +532,7 @@ void AppList::reqDump() { DUMP( "Action : (APPID :%s, ROLE :%s, AREA :%s, VISIBLE : %s, END_DRAW_FINISHED: %d)", - y.appid.c_str(), + y.client->appID().c_str(), y.role.c_str(), y.area.c_str(), (y.visible == TaskVisible::INVISIBLE) ? "invisible" : "visible", diff --git a/src/applist.hpp b/src/applist.hpp index a794b53..085504a 100644 --- a/src/applist.hpp +++ b/src/applist.hpp @@ -43,20 +43,21 @@ class AppList If the WMClient should be more flexible, I think this param should be WMClient class */ void addClient(const std::string &appid, unsigned layer, - unsigned surface,const std::string &role); + unsigned surface, const std::string &role); + void addClient(const std::string &appid, unsigned layer, const std::string &role); void removeClient(const std::string &appid); bool contains(const std::string &appid) const; int countClient() const; std::shared_ptr<WMClient> lookUpClient(const std::string &appid); void removeSurface(unsigned surface); - std::string getAppID(unsigned surface, const std::string &role, bool *found) const; + std::string getAppID(unsigned surface, bool* found) const; // TODO: remove // Request Interface unsigned currentRequestNumber() const; unsigned getRequestNumber(const std::string &appid) const; unsigned addRequest(WMRequest req); WMError setAction(unsigned req_num, const struct WMAction &action); - WMError setAction(unsigned req_num, const std::string &appid, + WMError setAction(unsigned req_num, std::shared_ptr<WMClient> client, const std::string &role, const std::string &area, TaskVisible visible); bool setEndDrawFinished(unsigned req_num, const std::string &appid, const std::string &role); bool endDrawFullfilled(unsigned req_num); diff --git a/src/controller_hooks.hpp b/src/controller_hooks.hpp deleted file mode 100644 index dd0a3aa..0000000 --- a/src/controller_hooks.hpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2017 TOYOTA MOTOR CORPORATION - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef TMCAGLWM_CONTROLLER_HOOKS_HPP -#define TMCAGLWM_CONTROLLER_HOOKS_HPP - -#include <cstdint> - -#include <functional> - -namespace wm -{ - -class WindowManager; - -struct controller_hooks -{ - WindowManager *wmgr; - - void surface_created(uint32_t surface_id); - void surface_removed(uint32_t surface_id); - void surface_visibility(uint32_t surface_id, uint32_t v); - void surface_destination_rectangle(uint32_t surface_id, uint32_t x, uint32_t y, uint32_t w, uint32_t h); -}; - -} // namespace wm - -#endif // TMCAGLWM_CONTROLLER_HOOKS_HPP diff --git a/src/db/areas.db b/src/db/areas.db deleted file mode 100644 index 03ddfe4..0000000 --- a/src/db/areas.db +++ /dev/null @@ -1,85 +0,0 @@ -{ - "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 - } - } - ] -} diff --git a/src/db/old_roles.db b/src/db/old_roles.db deleted file mode 100644 index 02a4c2d..0000000 --- a/src/db/old_roles.db +++ /dev/null @@ -1,68 +0,0 @@ -{ - "old_roles": [ - { - "name": "HomeScreen", - "new": "homescreen" - }, - { - "name": "Music", - "new": "music" - }, - { - "name": "MediaPlayer", - "new": "music" - }, - { - "name": "Video", - "new": "video" - }, - { - "name": "VideoPlayer", - "new": "video" - }, - { - "name": "WebBrowser", - "new": "browser" - }, - { - "name": "Radio", - "new": "radio" - }, - { - "name": "Phone", - "new": "phone" - }, - { - "name": "Navigation", - "new": "map" - }, - { - "name": "HVAC", - "new": "hvac" - }, - { - "name": "Settings", - "new": "settings" - }, - { - "name": "Dashboard", - "new": "dashboard" - }, - { - "name": "POI", - "new": "poi" - }, - { - "name": "Mixer", - "new": "mixer" - }, - { - "name": "Restriction", - "new": "restriction" - }, - { - "name": "^OnScreen.*", - "new": "on_screen" - } - ] -} diff --git a/src/json_helper.cpp b/src/json_helper.cpp index cf13363..72ae36a 100644 --- a/src/json_helper.cpp +++ b/src/json_helper.cpp @@ -17,66 +17,6 @@ #include "json_helper.hpp" #include "util.hpp" -json_object *to_json(compositor::surface_properties const &s) -{ - // auto j = json::object({ - auto j = json_object_new_object(); - - // {"id", s.id}, - json_object_object_add(j, "id", json_object_new_int(s.id)); - - // {"size", {{"width", s.size.w}, {"height", s.size.h}}}, - auto jsize = json_object_new_object(); - json_object_object_add(jsize, "width", json_object_new_int(s.size.w)); - json_object_object_add(jsize, "height", json_object_new_int(s.size.h)); - json_object_object_add(j, "size", jsize); - - // {"dst", - // {{"width", s.dst_rect.w}, - // {"height", s.dst_rect.h}, - // {"x", s.dst_rect.x}, - // {"y", s.dst_rect.y}}}, - auto jdst = json_object_new_object(); - json_object_object_add(jdst, "width", json_object_new_int(s.dst_rect.w)); - json_object_object_add(jdst, "height", json_object_new_int(s.dst_rect.h)); - json_object_object_add(jdst, "x", json_object_new_int(s.dst_rect.x)); - json_object_object_add(jdst, "y", json_object_new_int(s.dst_rect.y)); - json_object_object_add(j, "dst", jdst); - - // {"src", - // {{"width", s.src_rect.w}, - // {"height", s.src_rect.h}, - // {"x", s.src_rect.x}, - // {"y", s.src_rect.y}}}, - auto jsrc = json_object_new_object(); - json_object_object_add(jsrc, "width", json_object_new_int(s.src_rect.w)); - json_object_object_add(jsrc, "height", json_object_new_int(s.src_rect.h)); - json_object_object_add(jsrc, "x", json_object_new_int(s.src_rect.x)); - json_object_object_add(jsrc, "y", json_object_new_int(s.src_rect.y)); - json_object_object_add(j, "src", jsrc); - - // {"visibility", s.visibility}, - json_object_object_add( - j, "visibility", - json_object_new_boolean(static_cast<json_bool>(s.visibility == 1))); - - // {"opacity", s.opacity}, - json_object_object_add(j, "opacity", json_object_new_double(s.opacity)); - - // {"orientation", s.orientation}, - json_object_object_add(j, "orientation", json_object_new_int(s.orientation)); - - // }); - return j; -} - -json_object *to_json(compositor::screen const *s) -{ - auto o = json_object_new_object(); - json_object_object_add(o, "id", json_object_new_int(s->id)); - return o; -} - template <typename T> json_object *to_json_(T const &s) { @@ -93,11 +33,6 @@ json_object *to_json_(T const &s) return a; } -json_object *to_json(compositor::controller::props_map const &s) -{ - return to_json_(s); -} - json_object *to_json(std::vector<uint32_t> const &v) { auto a = json_object_new_array(); diff --git a/src/json_helper.hpp b/src/json_helper.hpp index 2321f8b..6ccbcc1 100644 --- a/src/json_helper.hpp +++ b/src/json_helper.hpp @@ -19,12 +19,9 @@ #include <json-c/json.h> #include <vector> -#include "wayland_ivi_wm.hpp" struct json_object; -json_object *to_json(compositor::screen const *s); -json_object *to_json(compositor::controller::props_map const &s); json_object *to_json(std::vector<uint32_t> const &v); namespace jh { diff --git a/src/layers.cpp b/src/layers.cpp deleted file mode 100644 index b79d2f6..0000000 --- a/src/layers.cpp +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Copyright (c) 2017 TOYOTA MOTOR CORPORATION - * Copyright (c) 2018 Konsulko Group - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <regex> - -#include "layers.hpp" -#include "json_helper.hpp" -#include "util.hpp" - -namespace wm -{ - -using json = nlohmann::json; - -layer::layer(nlohmann::json const &j) -{ - this->role = j["role"]; - this->name = j["name"]; - this->layer_id = j["layer_id"]; - - HMI_DEBUG("layer_id:%d name:%s", this->layer_id, this->name.c_str()); -} - -struct result<struct layer_map> to_layer_map(nlohmann::json const &j) -{ - 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 msi = j.find("main_surface"); - if (msi != j.end()) - { - stl.main_surface_name = msi->value("surface_role", ""); - stl.main_surface = -1; - } - - return Ok(stl); - } - catch (std::exception &e) - { - return Err<struct layer_map>(e.what()); - } -} - -optional<int> -layer_map::get_layer_id(int surface_id) -{ - auto i = this->surfaces.find(surface_id); - if (i != this->surfaces.end()) - { - return optional<int>(i->second); - } - return nullopt; -} - -optional<int> layer_map::get_layer_id(std::string const &role) -{ - for (auto const &r : this->roles) - { - auto re = std::regex(r.first); - if (std::regex_match(role, re)) - { - HMI_DEBUG("role %s matches layer %d", role.c_str(), r.second); - return optional<int>(r.second); - } - } - 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; - - json r{}; - if (is_full) - { - r = {{"type", "full"}}; - } - else - { - r = {{"type", "rect"}, - {"rect", - {{"x", this->rect.x}, - {"y", this->rect.y}, - {"width", this->rect.w}, - {"height", this->rect.h}}}}; - } - - return { - {"name", this->name}, - {"role", this->role}, - {"layer_id", this->layer_id}, - {"area", r}, - }; -} - -json layer_map::to_json() const -{ - json j{}; - for (auto const &i : this->mapping) - { - j.push_back(i.second.to_json()); - } - return j; -} - -void layer_map::setupArea(double scaling) -{ - 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); - } -} - -compositor::rect layer_map::getAreaSize(const std::string &area) -{ - return area2size[area]; -} - -int layer_map::loadAreaDb() -{ - HMI_DEBUG("Call"); - - std::string file_name(get_file_path("areas.db")); - - // 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)); - - // Perse areas - HMI_DEBUG("Perse areas"); - json_object *json_cfg; - if (!json_object_object_get_ex(json_obj, "areas", &json_cfg)) - { - HMI_ERROR("Parse Error!!"); - return -1; - } - - 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)); - - 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"); - - this->area2size[area] = area_size; - } - - // Check - for (auto itr = this->area2size.begin(); - itr != this->area2size.end(); ++itr) - { - 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); - } - - // Release json_object - json_object_put(json_obj); - - return 0; -} - -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 \ - } \ - } \ - ] \ -}"; - -} // namespace wm diff --git a/src/layers.hpp b/src/layers.hpp deleted file mode 100644 index 3a16985..0000000 --- a/src/layers.hpp +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2017 TOYOTA MOTOR CORPORATION - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef TMCAGLWM_LAYERS_H -#define TMCAGLWM_LAYERS_H - -#include <string> - -#include "../include/json.hpp" -#include "layout.hpp" -#include "result.hpp" -#include "wayland_ivi_wm.hpp" - -namespace wm -{ - -struct layer -{ - using json = nlohmann::json; - - // A more or less descriptive name? - std::string name = ""; - // The actual layer ID - int layer_id = -1; - // The rectangular region surfaces are allowed to draw on - // this layer. - compositor::rect rect; - // Specify a role prefix for surfaces that should be - // put on this layer. - std::string role; - - mutable struct LayoutState state; - - explicit layer(nlohmann::json const &j); - - json to_json() const; -}; - -struct layer_map -{ - using json = nlohmann::json; - - using storage_type = std::map<int, struct layer>; - using layers_type = std::vector<uint32_t>; - using role_to_layer_map = std::vector<std::pair<std::string, int>>; - using addsurf_layer_map = std::map<int, int>; - - storage_type mapping; // map surface_id to layer - layers_type layers; // the actual layer IDs we have - int main_surface; - std::string main_surface_name; - role_to_layer_map roles; - addsurf_layer_map surfaces; // additional surfaces on layers - - optional<int> get_layer_id(int surface_id); - optional<int> get_layer_id(std::string const &role); - optional<struct LayoutState *> get_layout_state(int surface_id) - { - int layer_id = *this->get_layer_id(surface_id); - auto i = this->mapping.find(layer_id); - return i == this->mapping.end() - ? nullopt - : optional<struct LayoutState *>(&i->second.state); - } - optional<struct layer> get_layer(int layer_id) - { - auto i = this->mapping.find(layer_id); - return i == this->mapping.end() ? nullopt - : optional<struct layer>(i->second); - } - - layers_type::size_type get_layers_count() const - { - return this->layers.size(); - } - - void add_surface(int surface_id, int layer_id) - { - this->surfaces[surface_id] = layer_id; - } - - void remove_surface(int surface_id) - { - this->surfaces.erase(surface_id); - } - - json to_json() const; - void setupArea(double scaling); - compositor::rect getAreaSize(const std::string &area); - int loadAreaDb(); - - private: - std::unordered_map<std::string, compositor::rect> area2size; - - static const char *kDefaultAreaDb; -}; - -struct result<struct layer_map> to_layer_map(nlohmann::json const &j); - -static const nlohmann::json default_layers_json = { - {"main_surface", { - {"surface_role", "HomeScreen"} - }}, - {"mappings", { - { - {"role", "^HomeScreen$"}, - {"name", "HomeScreen"}, - {"layer_id", 1000}, - {"area", { - {"type", "full"} - }} - }, - { - {"role", "MediaPlayer|Radio|Phone|Navigation|HVAC|Settings|Dashboard|POI|Mixer"}, - {"name", "apps"}, - {"layer_id", 1001}, - {"area", { - {"type", "rect"}, - {"rect", { - {"x", 0}, - {"y", 218}, - {"width", -1}, - {"height", -433} - }} - }} - }, - { - {"role", "^OnScreen.*"}, - {"name", "popups"}, - {"layer_id", 9999}, - {"area", { - {"type", "rect"}, - {"rect", { - {"x", 0}, - {"y", 760}, - {"width", -1}, - {"height", 400} - }} - }} - } - }} -}; -} // namespace wm - -#endif // TMCAGLWM_LAYERS_H diff --git a/src/layout.cpp b/src/layout.cpp deleted file mode 100644 index fbf2baa..0000000 --- a/src/layout.cpp +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2017 TOYOTA MOTOR CORPORATION - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "layout.hpp" diff --git a/src/layout.hpp b/src/layout.hpp deleted file mode 100644 index 3430ef3..0000000 --- a/src/layout.hpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2017 TOYOTA MOTOR CORPORATION - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef TMCAGLWM_LAYOUT_HPP -#define TMCAGLWM_LAYOUT_HPP - -namespace wm -{ - -struct LayoutState -{ - int main{-1}; - int sub{-1}; - - bool operator==(const LayoutState &b) const - { - return main == b.main && sub == b.sub; - } - - bool operator!=(const LayoutState &b) const - { - return !(*this == b); - } -}; - -} // namespace wm - -#endif // TMCAGLWM_LAYOUT_HPP diff --git a/src/main.cpp b/src/main.cpp index b652918..8808161 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,7 +20,6 @@ #include <json.h> #include "window_manager.hpp" #include "json_helper.hpp" -#include "wayland_ivi_wm.hpp" extern "C" { @@ -41,10 +40,10 @@ typedef struct WMClientCtxt struct afb_instance { - std::unique_ptr<wl::display> display; wm::WindowManager wmgr; - afb_instance() : display{new wl::display}, wmgr{this->display.get()} {} + afb_instance() : wmgr() {} + ~afb_instance() = default; int init(); }; @@ -57,78 +56,11 @@ int afb_instance::init() return this->wmgr.init(); } -int display_event_callback(sd_event_source *evs, int /*fd*/, uint32_t events, - void * /*data*/) -{ - if ((events & EPOLLHUP) != 0) - { - HMI_ERROR("The compositor hung up, dying now."); - delete g_afb_instance; - g_afb_instance = nullptr; - goto error; - } - - if ((events & EPOLLIN) != 0u) - { - { - g_afb_instance->wmgr.display->read_events(); - g_afb_instance->wmgr.set_pending_events(); - } - { - // We want do dispatch pending wayland events from within - // the API context - afb_service_call("windowmanager", "ping", json_object_new_object(), - [](void *c, int st, json_object *j) { - }, - nullptr); - } - } - - return 0; - -error: - sd_event_source_unref(evs); - if (getenv("WINMAN_EXIT_ON_HANGUP") != nullptr) - { - exit(1); - } - return -1; -} - -int _binding_init() +static int _binding_init() { HMI_NOTICE("WinMan ver. %s", WINMAN_VERSION_STRING); - if (g_afb_instance != nullptr) - { - HMI_ERROR("Wayland context already initialized?"); - return 0; - } - - if (getenv("XDG_RUNTIME_DIR") == nullptr) - { - HMI_ERROR("Environment variable XDG_RUNTIME_DIR not set"); - goto error; - } - - { - // wait until wayland compositor starts up. - int cnt = 0; - g_afb_instance = new afb_instance; - while (!g_afb_instance->display->ok()) - { - cnt++; - if (20 <= cnt) - { - HMI_ERROR("Could not connect to compositor"); - goto error; - } - HMI_ERROR("Wait to start weston ..."); - sleep(1); - delete g_afb_instance; - g_afb_instance = new afb_instance; - } - } + g_afb_instance = new afb_instance; if (g_afb_instance->init() == -1) { @@ -136,17 +68,6 @@ int _binding_init() goto error; } - { - int ret = sd_event_add_io(afb_daemon_get_event_loop(), nullptr, - g_afb_instance->display->get_fd(), EPOLLIN, - display_event_callback, g_afb_instance); - if (ret < 0) - { - HMI_ERROR("Could not initialize afb_instance event handler: %d", -ret); - goto error; - } - } - atexit([] { delete g_afb_instance; }); return 0; @@ -181,15 +102,9 @@ static void cbRemoveClientCtxt(void *data) // Policy Manager does not know this app was killed, // so notify it by deactivate request. - g_afb_instance->wmgr.api_deactivate_surface( + g_afb_instance->wmgr.api_deactivate_window( ctxt->name.c_str(), ctxt->role.c_str(), - [](const char *errmsg) { - if (errmsg != nullptr) - { - HMI_ERROR(errmsg); - return; - } - }); + [](const char *) {}); g_afb_instance->wmgr.removeClient(ctxt->name); delete ctxt; @@ -336,12 +251,12 @@ void windowmanager_activatewindow(afb_req req) noexcept char* appid = afb_req_get_application_id(req); if(appid) { - g_afb_instance->wmgr.api_activate_surface( + g_afb_instance->wmgr.api_activate_window( appid, a_drawing_name, a_drawing_area, [&req](const char *errmsg) { if (errmsg != nullptr) { - HMI_ERROR("wm", errmsg); + HMI_ERROR(errmsg); afb_req_fail(req, "failed", errmsg); return; } @@ -379,12 +294,12 @@ void windowmanager_deactivatewindow(afb_req req) noexcept char* appid = afb_req_get_application_id(req); if(appid) { - g_afb_instance->wmgr.api_deactivate_surface( + g_afb_instance->wmgr.api_deactivate_window( appid, a_drawing_name, [&req](const char *errmsg) { if (errmsg != nullptr) { - HMI_ERROR("wm", errmsg); + HMI_ERROR(errmsg); afb_req_fail(req, "failed", errmsg); return; } @@ -517,11 +432,10 @@ void windowmanager_wm_subscribe(afb_req req) noexcept afb_req_fail(req, "failed", "Need char const* argument event"); return; } - int event_type = json_object_get_int(j); - const char *event_name = g_afb_instance->wmgr.kListEventName[event_type]; - struct afb_event event = g_afb_instance->wmgr.map_afb_event[event_name]; - int ret = afb_req_subscribe(req, event); - if (ret) + wm::WindowManager::EventType event_id = (wm::WindowManager::EventType)json_object_get_int(j); + bool ret = g_afb_instance->wmgr.api_subscribe(req, event_id); + + if (!ret) { afb_req_fail(req, "failed", "Error: afb_req_subscribe()"); return; @@ -535,132 +449,19 @@ void windowmanager_wm_subscribe(afb_req req) noexcept } } -void windowmanager_list_drawing_names(afb_req req) noexcept +void windowmanager_ping(afb_req_t req) noexcept { std::lock_guard<std::mutex> guard(binding_m); - if (g_afb_instance == nullptr) - { - afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?"); - return; - } - - try - { - - nlohmann::json j = g_afb_instance->wmgr.id_alloc.name2id; - auto ret = wm::Ok(json_tokener_parse(j.dump().c_str())); - if (ret.is_err()) - { - afb_req_fail(req, "failed", ret.unwrap_err()); - return; - } - afb_req_success(req, ret.unwrap(), "success"); - } - catch (std::exception &e) - { - afb_req_fail_f(req, "failed", "Uncaught exception while calling list_drawing_names: %s", e.what()); - return; - } -} - -void windowmanager_ping(afb_req req) noexcept -{ - std::lock_guard<std::mutex> guard(binding_m); if (g_afb_instance == nullptr) { afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?"); return; } - - try + else { - - g_afb_instance->wmgr.api_ping(); - afb_req_success(req, NULL, "success"); } - catch (std::exception &e) - { - afb_req_fail_f(req, "failed", "Uncaught exception while calling ping: %s", e.what()); - return; - } -} - -void windowmanager_debug_status(afb_req req) noexcept -{ - std::lock_guard<std::mutex> guard(binding_m); - if (g_afb_instance == nullptr) - { - afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?"); - return; - } - - try - { - - json_object *jr = json_object_new_object(); - json_object_object_add(jr, "surfaces", - to_json(g_afb_instance->wmgr.controller->sprops)); - json_object_object_add(jr, "layers", to_json(g_afb_instance->wmgr.controller->lprops)); - - afb_req_success(req, jr, "success"); - } - catch (std::exception &e) - { - afb_req_fail_f(req, "failed", "Uncaught exception while calling debug_status: %s", e.what()); - return; - } -} - -void windowmanager_debug_layers(afb_req req) noexcept -{ - std::lock_guard<std::mutex> guard(binding_m); - if (g_afb_instance == nullptr) - { - afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?"); - return; - } - - try - { - auto ret = wm::Ok(json_tokener_parse(g_afb_instance->wmgr.layers.to_json().dump().c_str())); - - afb_req_success(req, ret, "success"); - } - catch (std::exception &e) - { - afb_req_fail_f(req, "failed", "Uncaught exception while calling debug_layers: %s", e.what()); - return; - } -} - -void windowmanager_debug_surfaces(afb_req req) noexcept -{ - std::lock_guard<std::mutex> guard(binding_m); - if (g_afb_instance == nullptr) - { - afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?"); - return; - } - - try - { - - auto ret = wm::Ok(to_json(g_afb_instance->wmgr.controller->sprops)); - if (ret.is_err()) - { - afb_req_fail(req, "failed", ret.unwrap_err()); - return; - } - - afb_req_success(req, ret.unwrap(), "success"); - } - catch (std::exception &e) - { - afb_req_fail_f(req, "failed", "Uncaught exception while calling debug_surfaces: %s", e.what()); - return; - } } void windowmanager_debug_terminate(afb_req req) noexcept @@ -691,19 +492,15 @@ void windowmanager_debug_terminate(afb_req req) noexcept } const struct afb_verb_v2 windowmanager_verbs[] = { - {"requestsurface", windowmanager_requestsurface, nullptr, nullptr, AFB_SESSION_NONE}, - {"requestsurfacexdg", windowmanager_requestsurfacexdg, nullptr, nullptr, AFB_SESSION_NONE}, - {"activatewindow", windowmanager_activatewindow, nullptr, nullptr, AFB_SESSION_NONE}, - {"deactivatewindow", windowmanager_deactivatewindow, nullptr, nullptr, AFB_SESSION_NONE}, - {"enddraw", windowmanager_enddraw, nullptr, nullptr, AFB_SESSION_NONE}, - {"getdisplayinfo", windowmanager_getdisplayinfo_thunk, nullptr, nullptr, AFB_SESSION_NONE}, - {"getareainfo", windowmanager_getareainfo_thunk, nullptr, nullptr, AFB_SESSION_NONE}, + {"requestSurface", windowmanager_requestsurface, nullptr, nullptr, AFB_SESSION_NONE}, + {"requestSurfaceXDG", windowmanager_requestsurfacexdg, nullptr, nullptr, AFB_SESSION_NONE}, + {"activateWindow", windowmanager_activatewindow, nullptr, nullptr, AFB_SESSION_NONE}, + {"deactivateWindow", windowmanager_deactivatewindow, nullptr, nullptr, AFB_SESSION_NONE}, + {"endDraw", windowmanager_enddraw, nullptr, nullptr, AFB_SESSION_NONE}, + {"getDisplayInfo", windowmanager_getdisplayinfo_thunk, nullptr, nullptr, AFB_SESSION_NONE}, + {"getAreaInfo", windowmanager_getareainfo_thunk, nullptr, nullptr, AFB_SESSION_NONE}, {"wm_subscribe", windowmanager_wm_subscribe, nullptr, nullptr, AFB_SESSION_NONE}, - {"list_drawing_names", windowmanager_list_drawing_names, nullptr, nullptr, AFB_SESSION_NONE}, {"ping", windowmanager_ping, nullptr, nullptr, AFB_SESSION_NONE}, - {"debug_status", windowmanager_debug_status, nullptr, nullptr, AFB_SESSION_NONE}, - {"debug_layers", windowmanager_debug_layers, nullptr, nullptr, AFB_SESSION_NONE}, - {"debug_surfaces", windowmanager_debug_surfaces, nullptr, nullptr, AFB_SESSION_NONE}, {"debug_terminate", windowmanager_debug_terminate, nullptr, nullptr, AFB_SESSION_NONE}, {}}; diff --git a/src/pm_wrapper.cpp b/src/pm_wrapper.cpp index d71e91f..8706128 100644 --- a/src/pm_wrapper.cpp +++ b/src/pm_wrapper.cpp @@ -192,7 +192,8 @@ void PMWrapper::createLayoutChangeAction(json_object *json_out, std::vector<WMAc bool end_draw_finished = false; WMAction act { - "", + 0, + nullptr, role_name, area_name, TaskVisible::VISIBLE, @@ -214,7 +215,8 @@ void PMWrapper::createLayoutChangeAction(json_object *json_out, std::vector<WMAc bool end_draw_finished = false; WMAction act { - "", + 0, + nullptr, role_name, area_name, TaskVisible::VISIBLE, @@ -238,7 +240,8 @@ void PMWrapper::createLayoutChangeAction(json_object *json_out, std::vector<WMAc bool end_draw_finished = true; WMAction act { - "", + 0, + nullptr, i_prv.first, "", TaskVisible::INVISIBLE, diff --git a/src/request.hpp b/src/request.hpp index 6b2bda1..073dd27 100644 --- a/src/request.hpp +++ b/src/request.hpp @@ -19,10 +19,13 @@ #include <string> #include <vector> +#include <memory> namespace wm { +class WMClient; + enum Task { TASK_ALLOCATE, @@ -47,7 +50,8 @@ struct WMTrigger struct WMAction { - std::string appid; + unsigned req_num; + std::shared_ptr<WMClient> client; std::string role; std::string area; TaskVisible visible; diff --git a/src/util.cpp b/src/util.cpp index 26d0ef6..9983561 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -31,7 +31,7 @@ void rectangle::fit(unsigned long to_width, unsigned long to_height) { // fit rect within (to_width x to_height) - if (to_width <= width()) { + if (to_width <= (unsigned long)width()) { // scale to fit with set_bottom(top() + (static_cast<long>(to_width) * height() / width()) - 1); set_right(left() + to_width - 1); diff --git a/src/util.hpp b/src/util.hpp index d3cab08..bf2e517 100644 --- a/src/util.hpp +++ b/src/util.hpp @@ -37,7 +37,7 @@ #define HMI_SEQ_INFO(seq_num, args,...) _HMI_SEQ_LOG(LOG_LEVEL_INFO, __FILENAME__, __FUNCTION__, __LINE__, seq_num, args, ##__VA_ARGS__) #define HMI_SEQ_DEBUG(seq_num, args,...) _HMI_SEQ_LOG(LOG_LEVEL_DEBUG, __FILENAME__, __FUNCTION__, __LINE__, seq_num, args, ##__VA_ARGS__) -#define DUMP(args, ...) _DUMP(LOG_LEVEL_DEBUG, args, ##__VA_ARGS__) +#define DUMP(args, ...) _DUMP(LOG_LEVEL_INFO, args, ##__VA_ARGS__) enum LOG_LEVEL{ LOG_LEVEL_NONE = 0, @@ -53,24 +53,15 @@ void _HMI_LOG(enum LOG_LEVEL level, const char* file, const char* func, const in void _HMI_SEQ_LOG(enum LOG_LEVEL level, const char* file, const char* func, const int line, unsigned seq_num, const char* log, ...); void _DUMP(enum LOG_LEVEL level, const char *log, ...); -/** - * @struct unique_fd - */ -struct unique_fd +struct rect { - int fd{-1}; - unique_fd() = default; - explicit unique_fd(int f) : fd{f} {} - operator int() const { return fd; } - ~unique_fd(); - unique_fd(unique_fd const &) = delete; - unique_fd &operator=(unique_fd const &) = delete; - unique_fd(unique_fd &&o) : fd(o.fd) { o.fd = -1; } - unique_fd &operator=(unique_fd &&o) - { - std::swap(this->fd, o.fd); - return *this; - } + int32_t w, h; + int32_t x, y; +}; + +struct size +{ + uint32_t w, h; }; class rectangle @@ -130,4 +121,4 @@ class rectangle // Configuration file path helper std::string get_file_path(const char *file_name, const char *log_category = "wm"); -#endif // !WM_UTIL_HPP +#endif // WM_UTIL_HPP diff --git a/src/wayland_ivi_wm.cpp b/src/wayland_ivi_wm.cpp deleted file mode 100644 index bbf745b..0000000 --- a/src/wayland_ivi_wm.cpp +++ /dev/null @@ -1,721 +0,0 @@ -/* - * Copyright (c) 2017 TOYOTA MOTOR CORPORATION - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "wayland_ivi_wm.hpp" - -/** - * namespace wl - */ -namespace wl -{ - -/** - * display - */ -display::display() - : d(std::unique_ptr<struct wl_display, void (*)(struct wl_display *)>( - wl_display_connect(nullptr), &wl_display_disconnect)), - r(d.get()) {} - -bool display::ok() const { return d && wl_display_get_error(d.get()) == 0; } - -void display::roundtrip() { wl_display_roundtrip(this->d.get()); } - -int display::dispatch() { return wl_display_dispatch(this->d.get()); } - -int display::dispatch_pending() { return wl_display_dispatch_pending(this->d.get()); } - -int display::read_events() -{ - while (wl_display_prepare_read(this->d.get()) == -1) - { - if (wl_display_dispatch_pending(this->d.get()) == -1) - { - return -1; - } - } - - if (wl_display_flush(this->d.get()) == -1) - { - return -1; - } - - if (wl_display_read_events(this->d.get()) == -1) - { - wl_display_cancel_read(this->d.get()); - } - - return 0; -} - -void display::flush() { wl_display_flush(this->d.get()); } - -int display::get_fd() const { return wl_display_get_fd(this->d.get()); } - -int display::get_error() { return wl_display_get_error(this->d.get()); } - -/** - * registry - */ -namespace -{ -void registry_global_created(void *data, struct wl_registry * /*r*/, uint32_t name, - char const *iface, uint32_t v) -{ - static_cast<struct registry *>(data)->global_created(name, iface, v); -} - -void registry_global_removed(void *data, struct wl_registry * /*r*/, - uint32_t name) -{ - static_cast<struct registry *>(data)->global_removed(name); -} - -constexpr struct wl_registry_listener registry_listener = { - registry_global_created, registry_global_removed}; -} // namespace - -registry::registry(struct wl_display *d) - : wayland_proxy(d == nullptr ? nullptr : wl_display_get_registry(d)) -{ - if (this->proxy != nullptr) - { - wl_registry_add_listener(this->proxy.get(), ®istry_listener, this); - } -} - -void registry::add_global_handler(char const *iface, binder bind) -{ - this->bindings[iface] = std::move(bind); -} - -void registry::global_created(uint32_t name, char const *iface, uint32_t v) -{ - auto b = this->bindings.find(iface); - if (b != this->bindings.end()) - { - b->second(this->proxy.get(), name, v); - } - HMI_DEBUG("wl::registry @ %p global n %u i %s v %u", this->proxy.get(), name, - iface, v); -} - -void registry::global_removed(uint32_t /*name*/) {} - -/** - * output - */ -namespace -{ -void output_geometry(void *data, struct wl_output * /*wl_output*/, int32_t x, - int32_t y, int32_t physical_width, int32_t physical_height, - int32_t subpixel, const char *make, const char *model, - int32_t transform) -{ - static_cast<struct output *>(data)->geometry( - x, y, physical_width, physical_height, subpixel, make, model, transform); -} - -void output_mode(void *data, struct wl_output * /*wl_output*/, uint32_t flags, - int32_t width, int32_t height, int32_t refresh) -{ - static_cast<struct output *>(data)->mode(flags, width, height, refresh); -} - -void output_done(void *data, struct wl_output * /*wl_output*/) -{ - static_cast<struct output *>(data)->done(); -} - -void output_scale(void *data, struct wl_output * /*wl_output*/, - int32_t factor) -{ - static_cast<struct output *>(data)->scale(factor); -} - -constexpr struct wl_output_listener output_listener = { - output_geometry, output_mode, output_done, output_scale}; -} // namespace - -output::output(struct wl_registry *r, uint32_t name, uint32_t v) - : wayland_proxy(wl_registry_bind(r, name, &wl_output_interface, v)) -{ - wl_output_add_listener(this->proxy.get(), &output_listener, this); -} - -void output::geometry(int32_t x, int32_t y, int32_t pw, int32_t ph, - int32_t subpel, char const *make, char const *model, - int32_t tx) -{ - HMI_DEBUG("wl::output %s @ %p x %i y %i w %i h %i spel %x make %s model %s tx %i", - __func__, this->proxy.get(), x, y, pw, ph, subpel, make, model, tx); - this->physical_width = pw; - this->physical_height = ph; - this->transform = tx; -} - -void output::mode(uint32_t flags, int32_t w, int32_t h, int32_t r) -{ - HMI_DEBUG("wl::output %s @ %p f %x w %i h %i r %i", __func__, - this->proxy.get(), flags, w, h, r); - if ((flags & WL_OUTPUT_MODE_CURRENT) != 0u) - { - this->width = w; - this->height = h; - this->refresh = r; - } -} - -void output::done() -{ - HMI_DEBUG("wl::output %s @ %p done", __func__, this->proxy.get()); - // Pivot and flipped - if (this->transform == WL_OUTPUT_TRANSFORM_90 || - this->transform == WL_OUTPUT_TRANSFORM_270 || - this->transform == WL_OUTPUT_TRANSFORM_FLIPPED_90 || - this->transform == WL_OUTPUT_TRANSFORM_FLIPPED_270) - { - std::swap(this->width, this->height); - std::swap(this->physical_width, this->physical_height); - } -} - -void output::scale(int32_t factor) -{ - HMI_DEBUG("wl::output %s @ %p f %i", __func__, this->proxy.get(), factor); -} -} // namespace wl - -/** - * namespace compositor - */ -namespace compositor -{ - -namespace -{ - -void surface_visibility_changed( - void *data, struct ivi_wm * /*ivi_wm*/, - uint32_t surface_id, int32_t visibility) -{ - auto c = static_cast<struct controller *>(data); - c->surface_visibility_changed(surface_id, visibility); -} - -void surface_opacity_changed(void *data, struct ivi_wm * /*ivi_wm*/, - uint32_t surface_id, wl_fixed_t opacity) -{ - auto c = static_cast<struct controller *>(data); - c->surface_opacity_changed(surface_id, float(wl_fixed_to_double(opacity))); -} - -void surface_source_rectangle_changed( - void *data, struct ivi_wm * /*ivi_wm*/, uint32_t surface_id, - int32_t x, int32_t y, int32_t width, int32_t height) -{ - auto c = static_cast<struct controller *>(data); - c->surface_source_rectangle_changed(surface_id, x, y, width, height); -} - -void surface_destination_rectangle_changed( - void *data, struct ivi_wm * /*ivi_wm*/, uint32_t surface_id, - int32_t x, int32_t y, int32_t width, int32_t height) -{ - auto c = static_cast<struct controller *>(data); - c->surface_destination_rectangle_changed(surface_id, x, y, width, height); -} - -void surface_created(void *data, struct ivi_wm * /*ivi_wm*/, - uint32_t id_surface) -{ - static_cast<struct controller *>(data)->surface_created(id_surface); -} - -void surface_destroyed( - void *data, struct ivi_wm * /*ivi_wm*/, uint32_t surface_id) -{ - auto c = static_cast<struct controller *>(data); - c->surface_destroyed(surface_id); -} - -void surface_error_detected(void *data, struct ivi_wm * /*ivi_wm*/, uint32_t object_id, - uint32_t error_code, const char *error_text) -{ - static_cast<struct controller *>(data)->surface_error_detected( - object_id, error_code, error_text); -} - -void surface_size_changed( - void *data, struct ivi_wm * /*ivi_wm*/, uint32_t surface_id, - int32_t width, int32_t height) -{ - auto c = static_cast<struct controller *>(data); - c->surface_size_changed(surface_id, width, height); -} - -void surface_stats_received(void *data, struct ivi_wm * /*ivi_wm*/, - uint32_t surface_id, uint32_t frame_count, uint32_t pid) -{ - auto c = static_cast<struct controller *>(data); - c->surface_stats_received(surface_id, frame_count, pid); -} - -void surface_added_to_layer(void *data, struct ivi_wm * /*ivi_wm*/, - uint32_t layer_id, uint32_t surface_id) -{ - auto c = static_cast<struct controller *>(data); - c->surface_added_to_layer(layer_id, surface_id); -} - -void layer_visibility_changed(void *data, struct ivi_wm * /*ivi_wm*/, - uint32_t layer_id, int32_t visibility) -{ - auto c = static_cast<struct controller *>(data); - c->layer_visibility_changed(layer_id, visibility); -} - -void layer_opacity_changed(void *data, struct ivi_wm * /*ivi_wm*/, - uint32_t layer_id, wl_fixed_t opacity) -{ - auto c = static_cast<struct controller *>(data); - c->layer_opacity_changed(layer_id, float(wl_fixed_to_double(opacity))); -} - -void layer_source_rectangle_changed( - void *data, struct ivi_wm * /*ivi_wm*/, uint32_t layer_id, - int32_t x, int32_t y, int32_t width, int32_t height) -{ - auto c = static_cast<struct controller *>(data); - c->layer_source_rectangle_changed(layer_id, x, y, width, height); -} - -void layer_destination_rectangle_changed( - void *data, struct ivi_wm * /*ivi_wm*/, uint32_t layer_id, - int32_t x, int32_t y, int32_t width, int32_t height) -{ - auto c = static_cast<struct controller *>(data); - c->layer_destination_rectangle_changed(layer_id, x, y, width, height); -} - -void layer_created(void *data, struct ivi_wm * /*ivi_wm*/, - uint32_t id_layer) -{ - static_cast<struct controller *>(data)->layer_created(id_layer); -} - -void layer_destroyed(void *data, struct ivi_wm * /*ivi_wm*/, uint32_t layer_id) -{ - auto c = static_cast<struct controller *>(data); - c->layer_destroyed(layer_id); -} - -void layer_error_detected(void *data, struct ivi_wm * /*ivi_wm*/, uint32_t object_id, - uint32_t error_code, const char *error_text) -{ - static_cast<struct controller *>(data)->layer_error_detected( - object_id, error_code, error_text); -} - -constexpr struct ivi_wm_listener listener = { - surface_visibility_changed, - layer_visibility_changed, - surface_opacity_changed, - layer_opacity_changed, - surface_source_rectangle_changed, - layer_source_rectangle_changed, - surface_destination_rectangle_changed, - layer_destination_rectangle_changed, - surface_created, - layer_created, - surface_destroyed, - layer_destroyed, - surface_error_detected, - layer_error_detected, - surface_size_changed, - surface_stats_received, - surface_added_to_layer, -}; - -void screen_created(void *data, struct ivi_wm_screen *ivi_wm_screen, uint32_t id) -{ - static_cast<struct screen *>(data)->screen_created((struct screen *)data, id); -} - -void layer_added(void *data, - struct ivi_wm_screen *ivi_wm_screen, - uint32_t layer_id) -{ - HMI_DEBUG("added layer_id:%d", layer_id); -} - -void connector_name(void *data, - struct ivi_wm_screen *ivi_wm_screen, - const char *process_name) -{ - HMI_DEBUG("process_name:%s", process_name); -} - -void screen_error(void *data, - struct ivi_wm_screen *ivi_wm_screen, - uint32_t error, - const char *message) -{ - HMI_DEBUG("screen error:%d message:%s", error, message); -} - -constexpr struct ivi_wm_screen_listener screen_listener = { - screen_created, - layer_added, - connector_name, - screen_error, -}; -} // namespace - -/** - * surface - */ -surface::surface(uint32_t i, struct controller *c) - : controller_child(c, i) -{ - this->parent->add_proxy_to_sid_mapping(this->parent->proxy.get(), i); -} - -void surface::set_visibility(uint32_t visibility) -{ - HMI_DEBUG("compositor::surface id:%d v:%d", this->id, visibility); - ivi_wm_set_surface_visibility(this->parent->proxy.get(), this->id, visibility); -} - -void surface::set_source_rectangle(int32_t x, int32_t y, - int32_t width, int32_t height) -{ - ivi_wm_set_surface_source_rectangle(this->parent->proxy.get(), this->id, - x, y, width, height); -} - -void surface::set_destination_rectangle(int32_t x, int32_t y, - int32_t width, int32_t height) -{ - ivi_wm_set_surface_destination_rectangle(this->parent->proxy.get(), this->id, - x, y, width, height); -} - -/** - * layer - */ -layer::layer(uint32_t i, struct controller *c) : layer(i, 0, 0, c) {} - -layer::layer(uint32_t i, int32_t w, int32_t h, struct controller *c) - : controller_child(c, i) -{ - this->parent->add_proxy_to_lid_mapping(this->parent->proxy.get(), i); - ivi_wm_create_layout_layer(c->proxy.get(), i, w, h); -} - -void layer::set_visibility(uint32_t visibility) -{ - ivi_wm_set_layer_visibility(this->parent->proxy.get(), this->id, visibility); -} - -void layer::set_destination_rectangle(int32_t x, int32_t y, - int32_t width, int32_t height) -{ - ivi_wm_set_layer_destination_rectangle(this->parent->proxy.get(), this->id, - x, y, width, height); -} - -void layer::add_surface(uint32_t surface_id) -{ - ivi_wm_layer_add_surface(this->parent->proxy.get(), this->id, surface_id); -} - -void layer::remove_surface(uint32_t surface_id) -{ - ivi_wm_layer_remove_surface(this->parent->proxy.get(), this->id, surface_id); -} - -/** - * screen - */ -screen::screen(uint32_t i, struct controller *c, struct wl_output *o) - : wayland_proxy(ivi_wm_create_screen(c->proxy.get(), o)), - controller_child(c, i) -{ - HMI_DEBUG("compositor::screen @ %p id %u o %p", this->proxy.get(), i, o); - - // Add listener for screen - ivi_wm_screen_add_listener(this->proxy.get(), &screen_listener, this); -} - -void screen::clear() { ivi_wm_screen_clear(this->proxy.get()); } - -void screen::screen_created(struct screen *screen, uint32_t id) -{ - HMI_DEBUG("compositor::screen @ %p screen %u (%x) @ %p", this->proxy.get(), - id, id, screen); - this->id = id; - this->parent->screens[id] = screen; -} - -void screen::set_render_order(std::vector<uint32_t> const &ro) -{ - std::size_t i; - - // Remove all layers from the screen render order - ivi_wm_screen_clear(this->proxy.get()); - - for (i = 0; i < ro.size(); i++) - { - HMI_DEBUG("compositor::screen @ %p add layer %u", this->proxy.get(), ro[i]); - // Add the layer to screen render order at nearest z-position - ivi_wm_screen_add_layer(this->proxy.get(), ro[i]); - } -} - -/** - * controller - */ -controller::controller(struct wl_registry *r, uint32_t name, uint32_t version) - : wayland_proxy( - wl_registry_bind(r, name, &ivi_wm_interface, version)), - output_size{} -{ - ivi_wm_add_listener(this->proxy.get(), &listener, this); -} - -void controller::layer_create(uint32_t id, int32_t w, int32_t h) -{ - this->layers[id] = std::make_unique<struct layer>(id, w, h, this); -} - -void controller::surface_create(uint32_t id) -{ - this->surfaces[id] = std::make_unique<struct surface>(id, this); - - // TODO: If Clipping is necessary, this process should be modified. - { - // Set surface type:IVI_WM_SURFACE_TYPE_DESKTOP) - // for resizing wayland surface when switching from split to full surface. - ivi_wm_set_surface_type(this->proxy.get(), id, IVI_WM_SURFACE_TYPE_DESKTOP); - - // Set source reactangle even if we should not need to set it - // for enable setting for destination region. - this->surfaces[id]->set_source_rectangle(0, 0, this->output_size.w, this->output_size.h); - - // Flush display - this->display->flush(); - } -} - -void controller::create_screen(struct wl_output *output) -{ - // TODO: screen id is 0 (WM manages one screen for now) - this->screen = std::make_unique<struct screen>(0, this, output); -} - -void controller::get_surface_properties(uint32_t surface_id, int param) -{ - ivi_wm_surface_get(this->proxy.get(), surface_id, param); -} - -void controller::layer_created(uint32_t id) -{ - HMI_DEBUG("compositor::controller @ %p layer %u (%x)", this->proxy.get(), id, id); - if (this->layers.find(id) != this->layers.end()) - { - HMI_DEBUG("WindowManager has created layer %u (%x) already", id, id); - } - else - { - this->layers[id] = std::make_unique<struct layer>(id, this); - } -} - -void controller::layer_error_detected(uint32_t object_id, - uint32_t error_code, const char *error_text) -{ - HMI_DEBUG("compositor::controller @ %p error o %d c %d text %s", - this->proxy.get(), object_id, error_code, error_text); -} - -void controller::surface_visibility_changed(uint32_t id, int32_t visibility) -{ - HMI_DEBUG("compositor::surface %s @ %d v %i", __func__, id, - visibility); - this->sprops[id].visibility = visibility; - this->chooks->surface_visibility(id, visibility); -} - -void controller::surface_opacity_changed(uint32_t id, float opacity) -{ - HMI_DEBUG("compositor::surface %s @ %d o %f", - __func__, id, opacity); - this->sprops[id].opacity = opacity; -} - -void controller::surface_source_rectangle_changed(uint32_t id, int32_t x, - int32_t y, int32_t width, - int32_t height) -{ - HMI_DEBUG("compositor::surface %s @ %d x %i y %i w %i h %i", __func__, - id, x, y, width, height); - this->sprops[id].src_rect = rect{width, height, x, y}; -} - -void controller::surface_destination_rectangle_changed(uint32_t id, int32_t x, - int32_t y, int32_t width, - int32_t height) -{ - HMI_DEBUG("compositor::surface %s @ %d x %i y %i w %i h %i", __func__, - id, x, y, width, height); - this->sprops[id].dst_rect = rect{width, height, x, y}; - this->chooks->surface_destination_rectangle(id, x, y, width, height); -} - -void controller::surface_size_changed(uint32_t id, int32_t width, - int32_t height) -{ - HMI_DEBUG("compositor::surface %s @ %d w %i h %i", __func__, id, - width, height); - this->sprops[id].size = size{uint32_t(width), uint32_t(height)}; - this->surfaces[id]->set_source_rectangle(0, 0, width, height); -} - -void controller::surface_added_to_layer(uint32_t layer_id, uint32_t surface_id) -{ - HMI_DEBUG("compositor::surface %s @ %d l %u", - __func__, layer_id, surface_id); -} - -void controller::surface_stats_received(uint32_t surface_id, - uint32_t frame_count, uint32_t pid) -{ - HMI_DEBUG("compositor::surface %s @ %d f %u pid %u", - __func__, surface_id, frame_count, pid); -} - -void controller::surface_created(uint32_t id) -{ - HMI_DEBUG("compositor::controller @ %p surface %u (%x)", this->proxy.get(), id, - id); - if (this->surfaces.find(id) == this->surfaces.end()) - { - this->surfaces[id] = std::make_unique<struct surface>(id, this); - this->chooks->surface_created(id); - - // Set surface type:IVI_WM_SURFACE_TYPE_DESKTOP) - // for resizing wayland surface when switching from split to full surface. - ivi_wm_set_surface_type(this->proxy.get(), id, IVI_WM_SURFACE_TYPE_DESKTOP); - - // Flush display - this->display->flush(); - } -} - -void controller::surface_destroyed(uint32_t surface_id) -{ - HMI_DEBUG("compositor::surface %s @ %d", __func__, surface_id); - this->chooks->surface_removed(surface_id); - this->sprops.erase(surface_id); - this->surfaces.erase(surface_id); -} - -void controller::surface_error_detected(uint32_t object_id, - uint32_t error_code, const char *error_text) -{ - HMI_DEBUG("compositor::controller @ %p error o %d c %d text %s", - this->proxy.get(), object_id, error_code, error_text); -} - -void controller::layer_visibility_changed(uint32_t layer_id, int32_t visibility) -{ - HMI_DEBUG("compositor::layer %s @ %d v %i", __func__, layer_id, visibility); - this->lprops[layer_id].visibility = visibility; -} - -void controller::layer_opacity_changed(uint32_t layer_id, float opacity) -{ - HMI_DEBUG("compositor::layer %s @ %d o %f", __func__, layer_id, opacity); - this->lprops[layer_id].opacity = opacity; -} - -void controller::layer_source_rectangle_changed(uint32_t layer_id, - int32_t x, int32_t y, - int32_t width, int32_t height) -{ - HMI_DEBUG("compositor::layer %s @ %d x %i y %i w %i h %i", - __func__, layer_id, x, y, width, height); - this->lprops[layer_id].src_rect = rect{width, height, x, y}; -} - -void controller::layer_destination_rectangle_changed(uint32_t layer_id, - int32_t x, int32_t y, - int32_t width, int32_t height) -{ - HMI_DEBUG("compositor::layer %s @ %d x %i y %i w %i h %i", - __func__, layer_id, x, y, width, height); - this->lprops[layer_id].dst_rect = rect{width, height, x, y}; -} - -void controller::layer_destroyed(uint32_t layer_id) -{ - HMI_DEBUG("compositor::layer %s @ %d", __func__, layer_id); - this->lprops.erase(layer_id); - this->layers.erase(layer_id); -} - -void controller::add_proxy_to_sid_mapping(struct ivi_wm *p, - uint32_t id) -{ - HMI_DEBUG("Add surface proxy mapping for %p (%u)", p, id); - this->surface_proxy_to_id[uintptr_t(p)] = id; - this->sprops[id].id = id; -} - -void controller::remove_proxy_to_sid_mapping(struct ivi_wm *p) -{ - HMI_DEBUG("Remove surface proxy mapping for %p", p); - this->surface_proxy_to_id.erase(uintptr_t(p)); -} - -void controller::add_proxy_to_lid_mapping(struct ivi_wm *p, - uint32_t id) -{ - HMI_DEBUG("Add layer proxy mapping for %p (%u)", p, id); - this->layer_proxy_to_id[uintptr_t(p)] = id; - this->lprops[id].id = id; -} - -void controller::remove_proxy_to_lid_mapping(struct ivi_wm *p) -{ - HMI_DEBUG("Remove layer proxy mapping for %p", p); - this->layer_proxy_to_id.erase(uintptr_t(p)); -} - -void controller::add_proxy_to_id_mapping(struct wl_output *p, uint32_t id) -{ - HMI_DEBUG("Add screen proxy mapping for %p (%u)", p, id); - this->screen_proxy_to_id[uintptr_t(p)] = id; -} - -void controller::remove_proxy_to_id_mapping(struct wl_output *p) -{ - HMI_DEBUG("Remove screen proxy mapping for %p", p); - this->screen_proxy_to_id.erase(uintptr_t(p)); -} - -} // namespace compositor diff --git a/src/wayland_ivi_wm.hpp b/src/wayland_ivi_wm.hpp deleted file mode 100644 index b515a06..0000000 --- a/src/wayland_ivi_wm.hpp +++ /dev/null @@ -1,326 +0,0 @@ -/* - * Copyright (c) 2017 TOYOTA MOTOR CORPORATION - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef WM_WAYLAND_HPP -#define WM_WAYLAND_HPP - -#include "controller_hooks.hpp" -#include "ivi-wm-client-protocol.h" -#include "util.hpp" - -#include <functional> -#include <memory> -#include <unordered_map> -#include <vector> - -/** - * @struct wayland_proxy - */ -template <typename ProxyT> -struct wayland_proxy -{ - std::unique_ptr<ProxyT, std::function<void(ProxyT *)>> proxy; - wayland_proxy(wayland_proxy const &) = delete; - wayland_proxy &operator=(wayland_proxy const &) = delete; - wayland_proxy(void *p) - : wayland_proxy(p, - reinterpret_cast<void (*)(ProxyT *)>(wl_proxy_destroy)) {} - wayland_proxy(void *p, std::function<void(ProxyT *)> &&p_del) - : proxy(std::unique_ptr<ProxyT, std::function<void(ProxyT *)>>( - static_cast<ProxyT *>(p), p_del)) {} -}; - -/** - * namespace wl - */ -namespace wl -{ - -/** - * @struct registry - */ -struct registry : public wayland_proxy<struct wl_registry> -{ - typedef std::function<void(struct wl_registry *, uint32_t, uint32_t)> binder; - std::unordered_map<std::string, binder> bindings; - - registry(registry const &) = delete; - registry &operator=(registry const &) = delete; - registry(struct wl_display *d); - - void add_global_handler(char const *iface, binder bind); - - // Events - void global_created(uint32_t name, char const *iface, uint32_t v); - void global_removed(uint32_t name); -}; - -/** - * @struct display - */ -struct display -{ - std::unique_ptr<struct wl_display, void (*)(struct wl_display *)> d; - struct registry r; - - display(display const &) = delete; - display &operator=(display const &) = delete; - display(); - bool ok() const; - void roundtrip(); - int dispatch(); - int dispatch_pending(); - int read_events(); - void flush(); - int get_fd() const; - int get_error(); - - // Lets just proxy this for the registry - inline void add_global_handler(char const *iface, registry::binder bind) - { - this->r.add_global_handler(iface, bind); - } -}; - -/** - * @struct output - */ -struct output : public wayland_proxy<struct wl_output> -{ - int width{}; - int height{}; - int physical_width{}; - int physical_height{}; - int refresh{}; - int transform{}; - - output(output const &) = delete; - output &operator=(output const &) = delete; - output(struct wl_registry *r, uint32_t name, uint32_t v); - - // Events - void geometry(int32_t x, int32_t y, int32_t pw, int32_t ph, int32_t subpel, - char const *make, char const *model, int32_t tx); - void mode(uint32_t flags, int32_t w, int32_t h, int32_t r); - void done(); - void scale(int32_t factor); -}; -} // namespace wl - -/** - * namespace compositor - */ -namespace compositor -{ - -struct size -{ - uint32_t w, h; -}; - -struct rect -{ - int32_t w, h; - int32_t x, y; -}; - -static const constexpr rect full_rect = rect{-1, -1, 0, 0}; - -inline bool operator==(struct rect a, struct rect b) -{ - return a.w == b.w && a.h == b.h && a.x == b.x && a.y == b.y; -} - -struct controller; - -struct controller_child -{ - struct controller *parent; - uint32_t id; - - controller_child(controller_child const &) = delete; - controller_child &operator=(controller_child const &) = delete; - controller_child(struct controller *c, uint32_t i) : parent(c), id(i) {} - virtual ~controller_child() {} -}; - -struct surface_properties -{ - uint32_t id; // let's just save an ID here too - struct rect dst_rect; - struct rect src_rect; - struct size size; - int32_t orientation; - int32_t visibility; - float opacity; -}; - -/** - * @struct surface - */ -struct surface : public controller_child -{ - surface(surface const &) = delete; - surface &operator=(surface const &) = delete; - surface(uint32_t i, struct controller *c); - - // Requests - void set_visibility(uint32_t visibility); - void set_source_rectangle(int32_t x, int32_t y, - int32_t width, int32_t height); - void set_destination_rectangle(int32_t x, int32_t y, - int32_t width, int32_t height); -}; - -/** - * @struct layer - */ -struct layer : public controller_child -{ - layer(layer const &) = delete; - layer &operator=(layer const &) = delete; - layer(uint32_t i, struct controller *c); - layer(uint32_t i, int32_t w, int32_t h, struct controller *c); - - // Requests - void set_visibility(uint32_t visibility); - void set_destination_rectangle(int32_t x, int32_t y, - int32_t width, int32_t height); - void add_surface(uint32_t surface_id); - void remove_surface(uint32_t surface_id); -}; - -/** - * @struct screen - */ -struct screen : public wayland_proxy<struct ivi_wm_screen>, - public controller_child -{ - screen(screen const &) = delete; - screen &operator=(screen const &) = delete; - screen(uint32_t i, struct controller *c, struct wl_output *o); - - void clear(); - void screen_created(struct screen *screen, uint32_t id); - void set_render_order(std::vector<uint32_t> const &ro); -}; - -/** - * @struct controller - */ -struct controller : public wayland_proxy<struct ivi_wm> -{ - // This controller is still missing ivi-input - - typedef std::unordered_map<uintptr_t, uint32_t> proxy_to_id_map_type; - typedef std::unordered_map<uint32_t, std::unique_ptr<struct surface>> - surface_map_type; - typedef std::unordered_map<uint32_t, std::unique_ptr<struct layer>> - layer_map_type; - typedef std::unordered_map<uint32_t, struct screen *> screen_map_type; - typedef std::unordered_map<uint32_t, struct surface_properties> props_map; - - // HACK: - // The order of these member is mandatory, as when objects are destroyed - // they will call their parent (that's us right here!) and remove their - // proxy-to-id mapping. I.e. the *_proxy_to_id members need to be valid - // when the surfaces/layers/screens maps are destroyed. This sucks, but - // I cannot see a better solution w/o globals or some other horrible - // call-our-parent construct. - proxy_to_id_map_type surface_proxy_to_id; - proxy_to_id_map_type layer_proxy_to_id; - proxy_to_id_map_type screen_proxy_to_id; - - props_map sprops; - props_map lprops; - - surface_map_type surfaces; - layer_map_type layers; - screen_map_type screens; - - std::unique_ptr<struct screen> screen; - - size output_size; // Display size[pixel] - size physical_size; // Display size[mm] - - // Scale for conversion CSS PX -> DP(Device Pixel) - double scale; - - wm::controller_hooks *chooks; - - struct wl::display *display; - - void add_proxy_to_sid_mapping(struct ivi_wm *p, uint32_t id); - void remove_proxy_to_sid_mapping(struct ivi_wm *p); - - void add_proxy_to_lid_mapping(struct ivi_wm *p, uint32_t id); - void remove_proxy_to_lid_mapping(struct ivi_wm *p); - - void add_proxy_to_id_mapping(struct wl_output *p, uint32_t id); - void remove_proxy_to_id_mapping(struct wl_output *p); - - bool surface_exists(uint32_t id) const - { - return this->surfaces.find(id) != this->surfaces.end(); - } - - bool layer_exists(uint32_t id) const - { - return this->layers.find(id) != this->layers.end(); - } - - controller(struct wl_registry *r, uint32_t name, uint32_t version); - - // Requests - void commit_changes() const - { - ivi_wm_commit_changes(this->proxy.get()); - } - void layer_create(uint32_t id, int32_t w, int32_t h); - void surface_create(uint32_t id); - void create_screen(struct wl_output *output); - void get_surface_properties(uint32_t surface_id, int param = 0); - - // Events - void surface_visibility_changed(uint32_t id, int32_t visibility); - void surface_opacity_changed(uint32_t id, float opacity); - void surface_source_rectangle_changed(uint32_t id, int32_t x, int32_t y, - int32_t width, int32_t height); - void surface_destination_rectangle_changed(uint32_t id, int32_t x, int32_t y, - int32_t width, int32_t height); - void surface_created(uint32_t id); - void surface_destroyed(uint32_t surface_id); - void surface_error_detected(uint32_t object_id, - uint32_t error_code, char const *error_text); - void surface_size_changed(uint32_t id, int32_t width, int32_t height); - void surface_stats_received(uint32_t surface_id, - uint32_t frame_count, uint32_t pid); - void surface_added_to_layer(uint32_t layer_id, uint32_t surface_id); - - void layer_visibility_changed(uint32_t layer_id, int32_t visibility); - void layer_opacity_changed(uint32_t layer_id, float opacity); - void layer_source_rectangle_changed(uint32_t layer_id, int32_t x, int32_t y, - int32_t width, int32_t height); - void layer_destination_rectangle_changed(uint32_t layer_id, int32_t x, int32_t y, - int32_t width, int32_t height); - void layer_created(uint32_t id); - void layer_destroyed(uint32_t layer_id); - void layer_error_detected(uint32_t object_id, - uint32_t error_code, char const *error_text); -}; -} // namespace compositor - -#endif // !WM_WAYLAND_HPP diff --git a/src/window_manager.cpp b/src/window_manager.cpp index c70e820..965c60d 100644 --- a/src/window_manager.cpp +++ b/src/window_manager.cpp @@ -20,7 +20,6 @@ #include "window_manager.hpp" #include "json_helper.hpp" -#include "util.hpp" #include "applist.hpp" extern "C" @@ -28,6 +27,10 @@ extern "C" #include <systemd/sd-event.h> } +using std::string; +using std::vector; +using std::unordered_map; + namespace wm { @@ -55,6 +58,16 @@ const char kKeyHeightMm[] = "height_mm"; const char kKeyScale[] = "scale"; const char kKeyIds[] = "ids"; +static const vector<string> kListEventName{ + "active", + "inactive", + "visible", + "invisible", + "syncDraw", + "flushDraw", + "screenUpdated", + "error"}; + static sd_event_source *g_timer_ev_src = nullptr; static AppList g_app_list; static WindowManager *g_context; @@ -62,39 +75,6 @@ static WindowManager *g_context; namespace { -using nlohmann::json; - -result<json> file_to_json(char const *filename) -{ - json j; - std::ifstream i(filename); - if (i.fail()) - { - HMI_DEBUG("Could not open config file, so use default layer information"); - j = default_layers_json; - } - else - { - i >> j; - } - - return Ok(j); -} - -struct result<layer_map> load_layer_map(char const *filename) -{ - HMI_DEBUG("loading IDs from %s", filename); - - auto j = file_to_json(filename); - if (j.is_err()) - { - return Err<layer_map>(j.unwrap_err()); - } - json jids = j.unwrap(); - - return to_layer_map(jids); -} - static int processTimerHandler(sd_event_source *s, uint64_t usec, void *userdata) { HMI_NOTICE("Time out occurs because the client replys endDraw slow, so revert the request"); @@ -102,7 +82,7 @@ static int processTimerHandler(sd_event_source *s, uint64_t usec, void *userdata return 0; } -static void onStateTransitioned(std::vector<WMAction> actions) +static void onStateTransitioned(vector<WMAction> actions) { g_context->startTransitionWrapper(actions); } @@ -116,47 +96,33 @@ static void onError() /** * WindowManager Impl */ -WindowManager::WindowManager(wl::display *d) - : chooks{this}, - display{d}, - controller{}, - outputs(), - layers(), - id_alloc{}, - pending_events(false) +WindowManager::WindowManager() + : id_alloc{} { - std::string path(get_file_path("layers.json")); - - try + const char *path = getenv("AFM_APP_INSTALL_DIR"); + if (!path) { - { - auto l = load_layer_map(path.c_str()); - if (l.is_ok()) - { - this->layers = l.unwrap(); - } - else - { - HMI_ERROR("%s", l.err().value()); - } - } - } - catch (std::exception &e) - { - HMI_ERROR("Loading of configuration failed: %s", e.what()); + HMI_ERROR("AFM_APP_INSTALL_DIR is not defined"); } + string root = path; + + this->lc = std::make_shared<LayerControl>(root); + + HMI_DEBUG("Layer Controller initialized"); } int WindowManager::init() { - if (!this->display->ok()) - { - return -1; - } + LayerControlCallbacks lmcb; + lmcb.surfaceCreated = [&](unsigned pid, unsigned surface){ + this->surface_created(surface); + }; + lmcb.surfaceDestroyed = [&](unsigned surface){ + this->surface_removed(surface); + }; - if (this->layers.mapping.empty()) + if(this->lc->init(lmcb) != WMError::SUCCESS) { - HMI_ERROR("No surface -> layer mapping loaded"); return -1; } @@ -174,107 +140,66 @@ int WindowManager::init() // Register callback to PolicyManager this->pmw.registerCallback(onStateTransitioned, onError); - // Make afb event - for (int i = Event_Val_Min; i <= Event_Val_Max; i++) + // Make afb event for subscriber + for (int i = Event_ScreenUpdated; i < Event_Error; i++) { - map_afb_event[kListEventName[i]] = afb_daemon_make_event(kListEventName[i]); + map_afb_event[kListEventName[i]] = afb_daemon_make_event(kListEventName[i].c_str()); } - this->display->add_global_handler( - "wl_output", [this](wl_registry *r, uint32_t name, uint32_t v) { - this->outputs.emplace_back(std::make_unique<wl::output>(r, name, v)); - }); - - this->display->add_global_handler( - "ivi_wm", [this](wl_registry *r, uint32_t name, uint32_t v) { - this->controller = - std::make_unique<struct compositor::controller>(r, name, v); - - // Init controller hooks - this->controller->chooks = &this->chooks; - - // This protocol needs the output, so lets just add our mapping here... - if(!this->outputs.empty()) { - // FIXME : Work around to avoid signal 11. Window Manager can't handle hotplug. - this->controller->add_proxy_to_id_mapping( - this->outputs.front()->proxy.get(), - wl_proxy_get_id(reinterpret_cast<struct wl_proxy *>( - this->outputs.front()->proxy.get()))); - - // Create screen - this->controller->create_screen(this->outputs.front()->proxy.get()); - } - else { - HMI_WARNING("wm", "No output object. Window Manager can't handle screen"); - } - - // Set display to controller - this->controller->display = this->display; - }); + const struct rect css_bg = this->lc->getAreaSize("fullscreen"); + Screen screen = this->lc->getScreenInfo(); + rectangle dp_bg(screen.width(), screen.height()); - // First level objects - this->display->roundtrip(); - // Second level objects - this->display->roundtrip(); - // Third level objects - this->display->roundtrip(); - - return init_layers(); -} + dp_bg.set_aspect(static_cast<double>(css_bg.w) / css_bg.h); + dp_bg.fit(screen.width(), screen.height()); + dp_bg.center(screen.width(), screen.height()); + HMI_DEBUG("SCALING: CSS BG(%dx%d) -> DDP %dx%d,(%dx%d)", + css_bg.w, css_bg.h, dp_bg.left(), dp_bg.top(), dp_bg.width(), dp_bg.height()); -int WindowManager::dispatch_pending_events() -{ - if (this->pop_pending_events()) - { - this->display->dispatch_pending(); - return 0; - } - return -1; -} + double scale = static_cast<double>(dp_bg.height()) / css_bg.h; + this->lc->setupArea(dp_bg, scale); -void WindowManager::set_pending_events() -{ - this->pending_events.store(true, std::memory_order_release); + return 0; } result<int> WindowManager::api_request_surface(char const *appid, char const *drawing_name) { // TODO: application requests by old role, // so convert role old to new - const char *role = this->convertRoleOldToNew(drawing_name); + const char *new_role = this->convertRoleOldToNew(drawing_name); - auto lid = this->layers.get_layer_id(std::string(role)); - if (!lid) + string str_id = appid; + string role = new_role; + unsigned lid = 0; + + if(!g_app_list.contains(str_id)) { - /** - * register drawing_name as fallback and make it displayed. - */ - lid = this->layers.get_layer_id(std::string("fallback")); - HMI_DEBUG("%s is not registered in layers.json, then fallback as normal app", role); - if (!lid) + lid = this->lc->getNewLayerID(role); + if (lid == 0) { - return Err<int>("Drawing name does not match any role, fallback is disabled"); + // register drawing_name as fallback and make it displayed. + lid = this->lc->getNewLayerID(string("fallback")); + HMI_DEBUG("%s is not registered in layers.json, then fallback as normal app", role.c_str()); + if (lid == 0) + { + return Err<int>("Designated role does not match any role, fallback is disabled"); + } } + this->lc->createNewLayer(lid); + // add client into the db + g_app_list.addClient(str_id, lid, drawing_name); } - auto rname = this->lookup_id(role); + // generate surface ID for ivi-shell application + auto rname = this->id_alloc.lookup(role); if (!rname) { // name does not exist yet, allocate surface id... auto id = int(this->id_alloc.generate_id(role)); - this->layers.add_surface(id, *lid); + this->tmp_surface2app[id] = {str_id, lid}; - // set the main_surface[_name] here and now - if (!this->layers.main_surface_name.empty() && - this->layers.main_surface_name == drawing_name) - { - this->layers.main_surface = id; - HMI_DEBUG("Set main_surface id to %u", id); - } - - // add client into the db - std::string appid_str(appid); - g_app_list.addClient(appid_str, *lid, id, std::string(role)); + auto client = g_app_list.lookUpClient(str_id); + client->registerSurface(id); // Set role map of (new, old) this->rolenew2old[role] = std::string(drawing_name); @@ -291,25 +216,45 @@ char const *WindowManager::api_request_surface(char const *appid, char const *dr { // TODO: application requests by old role, // so convert role old to new - const char *role = this->convertRoleOldToNew(drawing_name); + const char *new_role = this->convertRoleOldToNew(drawing_name); + + string str_id = appid; + string role = new_role; - auto lid = this->layers.get_layer_id(std::string(role)); unsigned sid = std::stol(ivi_id); + HMI_DEBUG("This API(requestSurfaceXDG) is for XDG Application using runXDG"); + /* + * IVI-shell doesn't send surface_size event via ivi-wm protocol + * if the application is using XDG surface. + * So WM has to set surface size with original size here + */ + WMError ret = this->lc->setXDGSurfaceOriginSize(sid); + if(ret != SUCCESS) + { + HMI_ERROR("%s", errorDescription(ret)); + HMI_WARNING("The main user of this API is runXDG"); + return "fail"; + } - if (!lid) + if(!g_app_list.contains(str_id)) { - /** - * register drawing_name as fallback and make it displayed. - */ - lid = this->layers.get_layer_id(std::string("fallback")); - HMI_DEBUG("%s is not registered in layers.json, then fallback as normal app", role); - if (!lid) + unsigned l_id = this->lc->getNewLayerID(role); + if (l_id == 0) { - return "Drawing name does not match any role, fallback is disabled"; + // register drawing_name as fallback and make it displayed. + l_id = this->lc->getNewLayerID("fallback"); + HMI_DEBUG("%s is not registered in layers.json, then fallback as normal app", role.c_str()); + if (l_id == 0) + { + return "Designated role does not match any role, fallback is disabled"; + } } + this->lc->createNewLayer(l_id); + // add client into the db + g_app_list.addClient(str_id, l_id, drawing_name); } - auto rname = this->lookup_id(role); + auto rname = this->id_alloc.lookup(role); if (rname) { @@ -318,17 +263,9 @@ char const *WindowManager::api_request_surface(char const *appid, char const *dr // register pair drawing_name and ivi_id this->id_alloc.register_name_id(role, sid); - this->layers.add_surface(sid, *lid); - - // this surface is already created - HMI_DEBUG("surface_id is %u, layer_id is %u", sid, *lid); - - this->controller->layers[*lid]->add_surface(sid); - this->layout_commit(); - // add client into the db - std::string appid_str(appid); - g_app_list.addClient(appid_str, *lid, sid, std::string(role)); + auto client = g_app_list.lookUpClient(str_id); + client->addSurface(sid); // Set role map of (new, old) this->rolenew2old[role] = std::string(drawing_name); @@ -336,16 +273,24 @@ char const *WindowManager::api_request_surface(char const *appid, char const *dr return nullptr; } -void WindowManager::api_activate_surface(char const *appid, char const *drawing_name, +void WindowManager::api_activate_window(char const *appid, char const *drawing_name, char const *drawing_area, const reply_func &reply) { // TODO: application requests by old role, // so convert role old to new const char *c_role = this->convertRoleOldToNew(drawing_name); - std::string id = appid; - std::string role = c_role; - std::string area = drawing_area; + string id = appid; + string role = c_role; + string area = drawing_area; + + if(!g_app_list.contains(id)) + { + reply("app doesn't request 'requestSurface' or 'setRole' yet"); + return; + } + auto client = g_app_list.lookUpClient(id); + Task task = Task::TASK_ALLOCATE; unsigned req_num = 0; WMError ret = WMError::UNKNOWN; @@ -367,10 +312,8 @@ void WindowManager::api_activate_surface(char const *appid, char const *drawing_ return; } - /* - * Do allocate tasks - */ - ret = this->doTransition(req_num); + // Do allocate tasks + ret = this->checkPolicy(req_num); if (ret != WMError::SUCCESS) { @@ -381,19 +324,16 @@ void WindowManager::api_activate_surface(char const *appid, char const *drawing_ } } -void WindowManager::api_deactivate_surface(char const *appid, char const *drawing_name, +void WindowManager::api_deactivate_window(char const *appid, char const *drawing_name, const reply_func &reply) { // TODO: application requests by old role, // so convert role old to new const char *c_role = this->convertRoleOldToNew(drawing_name); - - /* - * Check Phase - */ - std::string id = appid; - std::string role = c_role; - std::string area = ""; //drawing_area; + // Check Phase + string id = appid; + string role = c_role; + string area = ""; //drawing_area; Task task = Task::TASK_RELEASE; unsigned req_num = 0; WMError ret = WMError::UNKNOWN; @@ -415,10 +355,8 @@ void WindowManager::api_deactivate_surface(char const *appid, char const *drawin return; } - /* - * Do allocate tasks - */ - ret = this->doTransition(req_num); + // Do allocate tasks + ret = this->checkPolicy(req_num); if (ret != WMError::SUCCESS) { @@ -435,8 +373,8 @@ void WindowManager::api_enddraw(char const *appid, char const *drawing_name) // so convert role old to new const char *c_role = this->convertRoleOldToNew(drawing_name); - std::string id = appid; - std::string role = c_role; + string id = appid; + string role = c_role; unsigned current_req = g_app_list.currentRequestNumber(); bool result = g_app_list.setEndDrawFinished(current_req, id, role); @@ -458,6 +396,7 @@ void WindowManager::api_enddraw(char const *appid, char const *drawing_name) // Undo state of PolicyManager this->pmw.undoState(); + this->lc->undoUpdate(); } this->emitScreenUpdated(current_req); HMI_SEQ_INFO(current_req, "Finish request status: %s", errorDescription(ret)); @@ -473,23 +412,50 @@ void WindowManager::api_enddraw(char const *appid, char const *drawing_name) } } -result<json_object *> WindowManager::api_get_display_info() +bool WindowManager::api_subscribe(afb_req_t req, EventType event_id) { - if (!this->display->ok()) + bool ret = false; + char* appid = afb_req_get_application_id(req); + if(event_id < Event_Val_Min || event_id > Event_Val_Max) { - return Err<json_object *>("Wayland compositor is not available"); + HMI_ERROR("not defined in Window Manager", event_id); + return ret; } + HMI_INFO("%s subscribe %s : %d", appid, kListEventName[event_id].c_str(), event_id); + if(event_id == Event_ScreenUpdated) + { + // Event_ScreenUpdated should be emitted to subscriber + afb_event_t event = this->map_afb_event[kListEventName[event_id]]; + int rc = afb_req_subscribe(req, event); + if(rc == 0) + { + ret = true; + } + } + else if(appid) + { + string id = appid; + free(appid); + auto client = g_app_list.lookUpClient(id); + if(client != nullptr) + { + ret = client->subscribe(req, kListEventName[event_id]); + } + } + return ret; +} - // Set display info - compositor::size o_size = this->controller->output_size; - compositor::size p_size = this->controller->physical_size; +result<json_object *> WindowManager::api_get_display_info() +{ + Screen screen = this->lc->getScreenInfo(); json_object *object = json_object_new_object(); - json_object_object_add(object, kKeyWidthPixel, json_object_new_int(o_size.w)); - json_object_object_add(object, kKeyHeightPixel, json_object_new_int(o_size.h)); - json_object_object_add(object, kKeyWidthMm, json_object_new_int(p_size.w)); - json_object_object_add(object, kKeyHeightMm, json_object_new_int(p_size.h)); - json_object_object_add(object, kKeyScale, json_object_new_double(this->controller->scale)); + json_object_object_add(object, kKeyWidthPixel, json_object_new_int(screen.width())); + json_object_object_add(object, kKeyHeightPixel, json_object_new_int(screen.height())); + // TODO: set size + json_object_object_add(object, kKeyWidthMm, json_object_new_int(0)); + json_object_object_add(object, kKeyHeightMm, json_object_new_int(0)); + json_object_object_add(object, kKeyScale, json_object_new_double(this->lc->scale())); return Ok<json_object *>(object); } @@ -500,28 +466,18 @@ result<json_object *> WindowManager::api_get_area_info(char const *drawing_name) // TODO: application requests by old role, // so convert role old to new - const char *role = this->convertRoleOldToNew(drawing_name); + const char *c_role = this->convertRoleOldToNew(drawing_name); + string role = c_role; // Check drawing name, surface/layer id - auto const &surface_id = this->lookup_id(role); + auto const &surface_id = this->id_alloc.lookup(role); if (!surface_id) { return Err<json_object *>("Surface does not exist"); } - if (!this->controller->surface_exists(*surface_id)) - { - return Err<json_object *>("Surface does not exist in controller!"); - } - - auto layer_id = this->layers.get_layer_id(*surface_id); - if (!layer_id) - { - return Err<json_object *>("Surface is not on any layer!"); - } - // Set area rectangle - compositor::rect area_info = this->area_info[*surface_id]; + struct rect area_info = this->area_info[*surface_id]; json_object *object = json_object_new_object(); json_object_object_add(object, kKeyX, json_object_new_int(area_info.x)); json_object_object_add(object, kKeyY, json_object_new_int(area_info.y)); @@ -531,78 +487,41 @@ result<json_object *> WindowManager::api_get_area_info(char const *drawing_name) return Ok<json_object *>(object); } -void WindowManager::api_ping() { this->dispatch_pending_events(); } - -void WindowManager::send_event(char const *evname, char const *label) -{ - HMI_DEBUG("%s: %s(%s)", __func__, evname, label); - - json_object *j = json_object_new_object(); - json_object_object_add(j, kKeyDrawingName, json_object_new_string(label)); - - int ret = afb_event_push(this->map_afb_event[evname], j); - if (ret != 0) - { - HMI_DEBUG("afb_event_push failed: %m"); - } -} - -void WindowManager::send_event(char const *evname, char const *label, char const *area, - int x, int y, int w, int h) -{ - HMI_DEBUG("%s: %s(%s, %s) x:%d y:%d w:%d h:%d", - __func__, evname, label, area, x, y, w, h); - - json_object *j_rect = json_object_new_object(); - json_object_object_add(j_rect, kKeyX, json_object_new_int(x)); - json_object_object_add(j_rect, kKeyY, json_object_new_int(y)); - json_object_object_add(j_rect, kKeyWidth, json_object_new_int(w)); - json_object_object_add(j_rect, kKeyHeight, json_object_new_int(h)); - - json_object *j = json_object_new_object(); - json_object_object_add(j, kKeyDrawingName, json_object_new_string(label)); - json_object_object_add(j, kKeyDrawingArea, json_object_new_string(area)); - json_object_object_add(j, kKeyDrawingRect, j_rect); - - int ret = afb_event_push(this->map_afb_event[evname], j); - if (ret != 0) - { - HMI_DEBUG("afb_event_push failed: %m"); - } -} - /** * proxied events */ -void WindowManager::surface_created(uint32_t surface_id) +void WindowManager::surface_created(unsigned surface_id) { - this->controller->get_surface_properties(surface_id, IVI_WM_PARAM_SIZE); - - auto layer_id = this->layers.get_layer_id(surface_id); - if (!layer_id) + // requestSurface + if(this->tmp_surface2app.count(surface_id) != 0) { - HMI_DEBUG("Newly created surfce %d is not associated with any layer!", - surface_id); - return; + string appid = this->tmp_surface2app[surface_id].appid; + auto client = g_app_list.lookUpClient(appid); + if(client != nullptr) + { + WMError ret = client->addSurface(surface_id); + HMI_INFO("Add surface %d to \"%s\"", surface_id, appid.c_str()); + if(ret != WMError::SUCCESS) + { + HMI_ERROR("Failed to add surface to client %s", client->appID().c_str()); + } + } + this->tmp_surface2app.erase(surface_id); } - - HMI_DEBUG("surface_id is %u, layer_id is %u", surface_id, *layer_id); - - this->controller->layers[*layer_id]->add_surface(surface_id); - this->layout_commit(); } -void WindowManager::surface_removed(uint32_t surface_id) +void WindowManager::surface_removed(unsigned surface_id) { HMI_DEBUG("Delete surface_id %u", surface_id); this->id_alloc.remove_id(surface_id); - this->layers.remove_surface(surface_id); g_app_list.removeSurface(surface_id); } -void WindowManager::removeClient(const std::string &appid) +void WindowManager::removeClient(const string &appid) { HMI_DEBUG("Remove clinet %s from list", appid.c_str()); + auto client = g_app_list.lookUpClient(appid); + this->lc->appTerminated(client); g_app_list.removeClient(appid); } @@ -624,7 +543,7 @@ void WindowManager::timerHandler() this->processNextRequest(); } -void WindowManager::startTransitionWrapper(std::vector<WMAction> &actions) +void WindowManager::startTransitionWrapper(vector<WMAction> &actions) { WMError ret; unsigned req_num = g_app_list.currentRequestNumber(); @@ -648,12 +567,12 @@ void WindowManager::startTransitionWrapper(std::vector<WMAction> &actions) if ("" != act.role) { bool found; - auto const &surface_id = this->lookup_id(act.role.c_str()); + auto const &surface_id = this->id_alloc.lookup(act.role); if(surface_id == nullopt) { goto proc_remove_request; } - std::string appid = g_app_list.getAppID(*surface_id, act.role, &found); + string appid = g_app_list.getAppID(*surface_id, &found); if (!found) { if (TaskVisible::INVISIBLE == act.visible) @@ -668,7 +587,9 @@ void WindowManager::startTransitionWrapper(std::vector<WMAction> &actions) goto error; } } - act.appid = appid; + auto client = g_app_list.lookUpClient(appid); + act.req_num = req_num; + act.client = client; } ret = g_app_list.setAction(req_num, act); @@ -716,287 +637,7 @@ void WindowManager::processError(WMError error) this->processNextRequest(); } -/* - ******* Private Functions ******* - */ - -bool WindowManager::pop_pending_events() -{ - bool x{true}; - return this->pending_events.compare_exchange_strong( - x, false, std::memory_order_consume); -} - -optional<int> WindowManager::lookup_id(char const *name) -{ - return this->id_alloc.lookup(std::string(name)); -} -optional<std::string> WindowManager::lookup_name(int id) -{ - return this->id_alloc.lookup(id); -} - -/** - * init_layers() - */ -int WindowManager::init_layers() -{ - if (!this->controller) - { - HMI_ERROR("ivi_controller global not available"); - return -1; - } - - if (this->outputs.empty()) - { - HMI_ERROR("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; - - // Write output dimensions to ivi controller... - c->output_size = compositor::size{uint32_t(o->width), uint32_t(o->height)}; - c->physical_size = compositor::size{uint32_t(o->physical_width), - uint32_t(o->physical_height)}; - - - HMI_DEBUG("SCALING: screen (%dx%d), physical (%dx%d)", - o->width, o->height, o->physical_width, o->physical_height); - - this->layers.loadAreaDb(); - - const compositor::rect css_bg = this->layers.getAreaSize("fullscreen"); - rectangle dp_bg(o->width, o->height); - - dp_bg.set_aspect(static_cast<double>(css_bg.w) / css_bg.h); - dp_bg.fit(o->width, o->height); - dp_bg.center(o->width, o->height); - HMI_DEBUG("SCALING: CSS BG(%dx%d) -> DDP %dx%d,(%dx%d)", - css_bg.w, css_bg.h, dp_bg.left(), dp_bg.top(), dp_bg.width(), dp_bg.height()); - - // Clear scene - layers.clear(); - - // Clear screen - s->clear(); - - // Quick and dirty setup of layers - for (auto const &i : this->layers.mapping) - { - c->layer_create(i.second.layer_id, dp_bg.width(), dp_bg.height()); - auto &l = layers[i.second.layer_id]; - l->set_destination_rectangle(dp_bg.left(), dp_bg.top(), dp_bg.width(), dp_bg.height()); - l->set_visibility(1); - HMI_DEBUG("Setting up layer %s (%d) for surface role match \"%s\"", - i.second.name.c_str(), i.second.layer_id, i.second.role.c_str()); - } - - // Add layers to screen - s->set_render_order(this->layers.layers); - - this->layout_commit(); - - c->scale = static_cast<double>(dp_bg.height()) / css_bg.h; - this->layers.setupArea(c->scale); - - return 0; -} - -void WindowManager::surface_set_layout(int surface_id, const std::string& area) -{ - if (!this->controller->surface_exists(surface_id)) - { - HMI_ERROR("Surface %d does not exist", surface_id); - return; - } - - auto o_layer_id = this->layers.get_layer_id(surface_id); - - if (!o_layer_id) - { - HMI_ERROR("Surface %d is not associated with any layer!", surface_id); - return; - } - - uint32_t layer_id = *o_layer_id; - - auto const &layer = this->layers.get_layer(layer_id); - auto rect = this->layers.getAreaSize(area); - HMI_SEQ_DEBUG(g_app_list.currentRequestNumber(), "%s : x:%d y:%d w:%d h:%d", area.c_str(), - rect.x, rect.y, rect.w, rect.h); - auto &s = this->controller->surfaces[surface_id]; - - int x = rect.x; - int y = rect.y; - int w = rect.w; - int h = rect.h; - - HMI_DEBUG("surface_set_layout for surface %u on layer %u", surface_id, - layer_id); - - // set destination to the display rectangle - s->set_destination_rectangle(x, y, w, h); - - // update area information - this->area_info[surface_id].x = x; - this->area_info[surface_id].y = y; - this->area_info[surface_id].w = w; - this->area_info[surface_id].h = h; - - HMI_DEBUG("Surface %u now on layer %u with rect { %d, %d, %d, %d }", - surface_id, layer_id, x, y, w, h); -} - -void WindowManager::layout_commit() -{ - this->controller->commit_changes(); - this->display->flush(); -} - -void WindowManager::emit_activated(char const *label) -{ - this->send_event(kListEventName[Event_Active], label); -} - -void WindowManager::emit_deactivated(char const *label) -{ - this->send_event(kListEventName[Event_Inactive], label); -} - -void WindowManager::emit_syncdraw(char const *label, char const *area, int x, int y, int w, int h) -{ - this->send_event(kListEventName[Event_SyncDraw], label, area, x, y, w, h); -} - -void WindowManager::emit_syncdraw(const std::string &role, const std::string &area) -{ - compositor::rect rect = this->layers.getAreaSize(area); - this->send_event(kListEventName[Event_SyncDraw], - role.c_str(), area.c_str(), rect.x, rect.y, rect.w, rect.h); -} - -void WindowManager::emit_flushdraw(char const *label) -{ - this->send_event(kListEventName[Event_FlushDraw], label); -} - -void WindowManager::emit_visible(char const *label, bool is_visible) -{ - this->send_event(is_visible ? kListEventName[Event_Visible] : kListEventName[Event_Invisible], label); -} - -void WindowManager::emit_invisible(char const *label) -{ - return emit_visible(label, false); -} - -void WindowManager::emit_visible(char const *label) { return emit_visible(label, true); } - -void WindowManager::activate(int id) -{ - auto ip = this->controller->sprops.find(id); - if (ip != this->controller->sprops.end()) - { - this->controller->surfaces[id]->set_visibility(1); - char const *label = - this->lookup_name(id).value_or("unknown-name").c_str(); - - // FOR CES DEMO >>> - if ((0 == strcmp(label, "radio")) || - (0 == strcmp(label, "music")) || - (0 == strcmp(label, "video")) || - (0 == strcmp(label, "map"))) - { - for (auto i = surface_bg.begin(); i != surface_bg.end(); ++i) - { - if (id == *i) - { - // Remove id - this->surface_bg.erase(i); - - // Remove from BG layer (999) - HMI_DEBUG("Remove %s(%d) from BG layer", label, id); - this->controller->layers[999]->remove_surface(id); - - // Add to FG layer (1001) - HMI_DEBUG("Add %s(%d) to FG layer", label, id); - this->controller->layers[1001]->add_surface(id); - - for (int j : this->surface_bg) - { - HMI_DEBUG("Stored id:%d", j); - } - break; - } - } - } - // <<< FOR CES DEMO - - this->layout_commit(); - - // TODO: application requests by old role, - // so convert role new to old for emitting event - const char* old_role = this->rolenew2old[label].c_str(); - - this->emit_visible(old_role); - this->emit_activated(old_role); - } -} - -void WindowManager::deactivate(int id) -{ - auto ip = this->controller->sprops.find(id); - if (ip != this->controller->sprops.end()) - { - char const *label = - this->lookup_name(id).value_or("unknown-name").c_str(); - - // FOR CES DEMO >>> - if ((0 == strcmp(label, "radio")) || - (0 == strcmp(label, "music")) || - (0 == strcmp(label, "video")) || - (0 == strcmp(label, "map"))) - { - - // Store id - this->surface_bg.push_back(id); - - // Remove from FG layer (1001) - HMI_DEBUG("Remove %s(%d) from FG layer", label, id); - this->controller->layers[1001]->remove_surface(id); - - // Add to BG layer (999) - HMI_DEBUG("Add %s(%d) to BG layer", label, id); - this->controller->layers[999]->add_surface(id); - - for (int j : surface_bg) - { - HMI_DEBUG("Stored id:%d", j); - } - } - else - { - this->controller->surfaces[id]->set_visibility(0); - } - // <<< FOR CES DEMO - - this->layout_commit(); - - // TODO: application requests by old role, - // so convert role new to old for emitting event - const char* old_role = this->rolenew2old[label].c_str(); - - this->emit_deactivated(old_role); - this->emit_invisible(old_role); - } -} - -WMError WindowManager::setRequest(const std::string& appid, const std::string &role, const std::string &area, +WMError WindowManager::setRequest(const string& appid, const string &role, const string &area, Task task, unsigned* req_num) { if (!g_app_list.contains(appid)) @@ -1028,13 +669,6 @@ WMError WindowManager::setRequest(const std::string& appid, const std::string &r return WMError::SUCCESS; } -WMError WindowManager::doTransition(unsigned req_num) -{ - HMI_SEQ_DEBUG(req_num, "check policy"); - WMError ret = this->checkPolicy(req_num); - return ret; -} - WMError WindowManager::checkPolicy(unsigned req_num) { /* @@ -1049,18 +683,7 @@ WMError WindowManager::checkPolicy(unsigned req_num) ret = WMError::NO_ENTRY; return ret; } - std::string req_area = trigger.area; - - if (trigger.task == Task::TASK_ALLOCATE) - { - const char *msg = this->check_surface_exist(trigger.role.c_str()); - - if (msg) - { - HMI_SEQ_ERROR(req_num, msg); - return ret; - } - } + string req_area = trigger.area; // Input event data to PolicyManager if (0 > this->pmw.setInputEventData(trigger.task, trigger.role, trigger.area)) @@ -1097,20 +720,14 @@ WMError WindowManager::startTransition(unsigned req_num) return ret; } + g_app_list.reqDump(); for (const auto &action : actions) { if (action.visible == TaskVisible::VISIBLE) { sync_draw_happen = true; - - // TODO: application requests by old role, - // so convert role new to old for emitting event - std::string old_role = this->rolenew2old[action.role]; - - this->emit_syncdraw(old_role, action.area); - /* TODO: emit event for app not subscriber - if(g_app_list.contains(y.appid)) - g_app_list.lookUpClient(y.appid)->emit_syncdraw(y.role, y.area); */ + struct rect r = this->lc->getAreaSize(action.area); + action.client->emitSyncDraw(action.area, r); } } @@ -1124,12 +741,11 @@ WMError WindowManager::startTransition(unsigned req_num) // Make it deactivate here for (const auto &x : actions) { - if (g_app_list.contains(x.appid)) - { - auto client = g_app_list.lookUpClient(x.appid); - this->deactivate(client->surfaceID(x.role)); - } + this->lc->visibilityChange(x); + x.client->emitActive(false); + x.client->emitVisible(false); } + this->lc->renderLayers(); ret = WMError::NO_LAYOUT_CHANGE; } return ret; @@ -1155,17 +771,18 @@ WMError WindowManager::doEndDraw(unsigned req_num) if(act.visible != TaskVisible::NO_CHANGE) { // layout change - if(!g_app_list.contains(act.appid)){ - ret = WMError::NOT_REGISTERED; - } - ret = this->layoutChange(act); + ret = this->lc->layoutChange(act); if(ret != WMError::SUCCESS) { HMI_SEQ_WARNING(req_num, "Failed to manipulate surfaces while state change : %s", errorDescription(ret)); return ret; } - ret = this->visibilityChange(act); + ret = this->lc->visibilityChange(act); + + act.client->emitActive((act.visible == VISIBLE)); + act.client->emitVisible((act.visible == VISIBLE)); + if (ret != WMError::SUCCESS) { HMI_SEQ_WARNING(req_num, @@ -1173,10 +790,9 @@ WMError WindowManager::doEndDraw(unsigned req_num) return ret; } HMI_SEQ_DEBUG(req_num, "visible %s", act.role.c_str()); - //this->lm_enddraw(act.role.c_str()); } } - this->layout_commit(); + this->lc->renderLayers(); HMI_SEQ_INFO(req_num, "emit flushDraw"); @@ -1184,76 +800,26 @@ WMError WindowManager::doEndDraw(unsigned req_num) { if(act_flush.visible == TaskVisible::VISIBLE) { - // TODO: application requests by old role, - // so convert role new to old for emitting event - std::string old_role = this->rolenew2old[act_flush.role]; - - this->emit_flushdraw(old_role.c_str()); + act_flush.client->emitFlushDraw(); } } return ret; } -WMError WindowManager::layoutChange(const WMAction &action) -{ - if (action.visible == TaskVisible::INVISIBLE) - { - // Visibility is not change -> no redraw is required - return WMError::SUCCESS; - } - auto client = g_app_list.lookUpClient(action.appid); - unsigned surface = client->surfaceID(action.role); - if (surface == 0) - { - HMI_SEQ_ERROR(g_app_list.currentRequestNumber(), - "client doesn't have surface with role(%s)", action.role.c_str()); - return WMError::NOT_REGISTERED; - } - // Layout Manager - WMError ret = this->setSurfaceSize(surface, action.area); - return ret; -} - -WMError WindowManager::visibilityChange(const WMAction &action) -{ - HMI_SEQ_DEBUG(g_app_list.currentRequestNumber(), "Change visibility"); - if(!g_app_list.contains(action.appid)){ - return WMError::NOT_REGISTERED; - } - auto client = g_app_list.lookUpClient(action.appid); - unsigned surface = client->surfaceID(action.role); - if(surface == 0) - { - HMI_SEQ_ERROR(g_app_list.currentRequestNumber(), - "client doesn't have surface with role(%s)", action.role.c_str()); - return WMError::NOT_REGISTERED; - } - - if (action.visible != TaskVisible::INVISIBLE) - { - this->activate(surface); // Layout Manager task - } - else - { - this->deactivate(surface); // Layout Manager task - } - return WMError::SUCCESS; -} - -WMError WindowManager::setSurfaceSize(unsigned surface, const std::string &area) -{ - this->surface_set_layout(surface, area); - - return WMError::SUCCESS; -} - void WindowManager::emitScreenUpdated(unsigned req_num) { // Get visible apps HMI_SEQ_DEBUG(req_num, "emit screen updated"); bool found = false; auto actions = g_app_list.getActions(req_num, &found); + if (!found) + { + HMI_SEQ_ERROR(req_num, + "Window Manager bug :%s : Action is not set", + errorDescription(WMError::NO_ENTRY)); + return; + } // create json object json_object *j = json_object_new_object(); @@ -1263,7 +829,7 @@ void WindowManager::emitScreenUpdated(unsigned req_num) { if(action.visible != TaskVisible::INVISIBLE) { - json_object_array_add(jarray, json_object_new_string(action.appid.c_str())); + json_object_array_add(jarray, json_object_new_string(action.client->appID().c_str())); } } json_object_object_add(j, kKeyIds, jarray); @@ -1271,7 +837,7 @@ void WindowManager::emitScreenUpdated(unsigned req_num) int ret = afb_event_push( this->map_afb_event[kListEventName[Event_ScreenUpdated]], j); - if (ret != 0) + if (ret < 0) { HMI_DEBUG("afb_event_push failed: %m"); } @@ -1323,7 +889,7 @@ void WindowManager::processNextRequest() if (g_app_list.haveRequest()) { HMI_SEQ_DEBUG(req_num, "Process next request"); - WMError rc = doTransition(req_num); + WMError rc = checkPolicy(req_num); if (rc != WMError::SUCCESS) { HMI_SEQ_ERROR(req_num, errorDescription(rc)); @@ -1422,30 +988,6 @@ int WindowManager::loadOldRoleDb() return 0; } -const char *WindowManager::check_surface_exist(const char *drawing_name) -{ - auto const &surface_id = this->lookup_id(drawing_name); - if (!surface_id) - { - return "Surface does not exist"; - } - - if (!this->controller->surface_exists(*surface_id)) - { - return "Surface does not exist in controller!"; - } - - auto layer_id = this->layers.get_layer_id(*surface_id); - - if (!layer_id) - { - return "Surface is not on any layer!"; - } - - HMI_DEBUG("surface %d is detected", *surface_id); - return nullptr; -} - const char* WindowManager::kDefaultOldRoleDb = "{ \ \"old_roles\": [ \ { \ @@ -1515,26 +1057,4 @@ const char* WindowManager::kDefaultOldRoleDb = "{ \ ] \ }"; -/** - * controller_hooks - */ -void controller_hooks::surface_created(uint32_t surface_id) -{ - this->wmgr->surface_created(surface_id); -} - -void controller_hooks::surface_removed(uint32_t surface_id) -{ - this->wmgr->surface_removed(surface_id); -} - -void controller_hooks::surface_visibility(uint32_t /*surface_id*/, - uint32_t /*v*/) {} - -void controller_hooks::surface_destination_rectangle(uint32_t /*surface_id*/, - uint32_t /*x*/, - uint32_t /*y*/, - uint32_t /*w*/, - uint32_t /*h*/) {} - } // namespace wm diff --git a/src/window_manager.hpp b/src/window_manager.hpp index 72c875a..ccec302 100644 --- a/src/window_manager.hpp +++ b/src/window_manager.hpp @@ -22,14 +22,12 @@ #include <memory> #include <unordered_map> #include <experimental/optional> -#include "util.hpp" -#include "controller_hooks.hpp" -#include "layers.hpp" -#include "layout.hpp" -#include "wayland_ivi_wm.hpp" +#include "result.hpp" #include "pm_wrapper.hpp" +#include "util.hpp" #include "request.hpp" #include "wm_error.hpp" +#include "wm_layer_control.hpp" extern "C" { #include <afb/afb-binding.h> @@ -37,16 +35,6 @@ extern "C" struct json_object; -namespace wl -{ -struct display; -} - -namespace compositor -{ -struct controller; -} - namespace wm { @@ -77,7 +65,6 @@ extern const char kKeyIds[]; struct id_allocator { unsigned next = 1; - // Surfaces that where requested but not yet created std::unordered_map<unsigned, std::string> id2name; std::unordered_map<std::string, unsigned> name2id; @@ -142,10 +129,17 @@ struct id_allocator } }; +struct TmpClient +{ + std::string appid; + unsigned layer; +}; + + class WindowManager { public: - typedef std::unordered_map<uint32_t, struct compositor::rect> rect_map; + typedef std::unordered_map<uint32_t, struct rect> rect_map; typedef std::function<void(const char *err_msg)> reply_func; enum EventType @@ -168,42 +162,7 @@ class WindowManager Event_Val_Max = Event_Error, }; - const std::vector<const char *> kListEventName{ - "active", - "inactive", - "visible", - "invisible", - "syncDraw", - "flushDraw", - "screenUpdated", - "error"}; - - struct controller_hooks chooks; - - // This is the one thing, we do not own. - struct wl::display *display; - - std::unique_ptr<struct compositor::controller> controller; - std::vector<std::unique_ptr<struct wl::output>> outputs; - - // track current layouts separately - layer_map layers; - - // ID allocation and proxy methods for lookup - struct id_allocator id_alloc; - - // Set by AFB API when wayland events need to be dispatched - std::atomic<bool> pending_events; - - std::map<const char *, struct afb_event> map_afb_event; - - // Surface are info (x, y, w, h) - rect_map area_info; - - // FOR CES DEMO - std::vector<int> surface_bg; - - explicit WindowManager(wl::display *d); + explicit WindowManager(); ~WindowManager() = default; WindowManager(WindowManager const &) = delete; @@ -212,23 +171,19 @@ class WindowManager WindowManager &operator=(WindowManager &&) = delete; int init(); - int dispatch_pending_events(); - void set_pending_events(); result<int> api_request_surface(char const *appid, char const *role); char const *api_request_surface(char const *appid, char const *role, char const *ivi_id); - void api_activate_surface(char const *appid, char const *role, char const *drawing_area, const reply_func &reply); - void api_deactivate_surface(char const *appid, char const *role, const reply_func &reply); + void api_activate_window(char const *appid, char const *role, char const *drawing_area, const reply_func &reply); + void api_deactivate_window(char const *appid, char const *role, const reply_func &reply); void api_enddraw(char const *appid, char const *role); + bool api_subscribe(afb_req_t req, EventType event_id); result<json_object *> api_get_display_info(); result<json_object *> api_get_area_info(char const *role); - void api_ping(); - void send_event(char const *evname, char const *label); - void send_event(char const *evname, char const *label, char const *area, int x, int y, int w, int h); // Events from the compositor we are interested in - void surface_created(uint32_t surface_id); - void surface_removed(uint32_t surface_id); + void surface_created(unsigned surface_id); + void surface_removed(unsigned surface_id); void removeClient(const std::string &appid); void exceptionProcessForTransition(); @@ -240,52 +195,32 @@ class WindowManager void processError(WMError error); private: - bool pop_pending_events(); - optional<int> lookup_id(char const *name); - optional<std::string> lookup_name(int id); - int init_layers(); - void surface_set_layout(int surface_id, const std::string& area = ""); - void layout_commit(); - - // WM Events to clients - void emit_activated(char const *label); - void emit_deactivated(char const *label); - void emit_syncdraw(char const *label, char const *area, int x, int y, int w, int h); - void emit_syncdraw(const std::string &role, const std::string &area); - void emit_flushdraw(char const *label); - void emit_visible(char const *label, bool is_visible); - void emit_invisible(char const *label); - void emit_visible(char const *label); - - void activate(int id); - void deactivate(int id); WMError setRequest(const std::string &appid, const std::string &role, const std::string &area, Task task, unsigned *req_num); - WMError doTransition(unsigned sequence_number); WMError checkPolicy(unsigned req_num); WMError startTransition(unsigned req_num); WMError doEndDraw(unsigned req_num); - WMError layoutChange(const WMAction &action); - WMError visibilityChange(const WMAction &action); - WMError setSurfaceSize(unsigned surface, const std::string& area); void emitScreenUpdated(unsigned req_num); void setTimer(); void stopTimer(); void processNextRequest(); - int loadOldRoleDb(); - - const char *check_surface_exist(const char *role); - private: - std::unordered_map<std::string, struct compositor::rect> area2size; + std::map<std::string, afb_event_t> map_afb_event; + std::unordered_map<std::string, struct rect> area2size; + std::shared_ptr<LayerControl> lc; std::unordered_map<std::string, std::string> roleold2new; std::unordered_map<std::string, std::string> rolenew2old; PMWrapper pmw; + rect_map area_info; + struct id_allocator id_alloc; + // ID allocation and proxy methods for lookup + std::unordered_map<unsigned, struct TmpClient> tmp_surface2app; + int loadOldRoleDb(); static const char* kDefaultOldRoleDb; }; diff --git a/src/wm_client.cpp b/src/wm_client.cpp index 2e12a69..da7e626 100644 --- a/src/wm_client.cpp +++ b/src/wm_client.cpp @@ -16,7 +16,7 @@ #include <json-c/json.h> #include "wm_client.hpp" -#include "util.hpp" +#include <ilm/ilm_control.h> #define INVALID_SURFACE_ID 0 @@ -26,19 +26,34 @@ using std::vector; namespace wm { -static const vector<string> kWMEvents = { - // Private event for applications - "syncDraw", "flushDraw", "visible", "invisible", "active", "inactive", "error"}; -static const vector<string> kErrorDescription = { - "unknown-error"}; - +static const char kActive[] = "active"; +static const char kInactive[] = "inactive"; +static const char kVisible[] = "visible"; +static const char kInvisible[] = "invisible"; +static const char kSyncDraw[] = "syncDraw"; +static const char kFlushDraw[] = "flushDraw"; static const char kKeyDrawingName[] = "drawing_name"; +static const char kKeyDrawingArea[] = "drawing_area"; +static const char kKeyRole[] = "role"; +static const char kKeyArea[] = "area"; static const char kKeyrole[] = "role"; static const char kKeyError[] = "error"; -static const char kKeyErrorDesc[] = "kErrorDescription"; +static const char kKeyErrorDesc[] = "errorDescription"; +static const char kKeyX[] = "x"; +static const char kKeyY[] = "y"; +static const char kKeyWidth[] = "width"; +static const char kKeyHeight[] = "height"; +static const char kKeyDrawingRect[] = "drawing-rect"; + +static const vector<string> kWMEvents = { + // Private event for applications + kActive, kInactive, + kVisible, kInvisible, + kSyncDraw, kFlushDraw, + kKeyError}; WMClient::WMClient(const string &appid, unsigned layer, unsigned surface, const string &role) - : id(appid), layer(layer), + : id(appid), layer(layer), is_source_set(false), role2surface(0) { role2surface[role] = surface; @@ -47,17 +62,18 @@ WMClient::WMClient(const string &appid, unsigned layer, unsigned surface, const #if GTEST_ENABLED string ev = x; #else - afb_event ev = afb_daemon_make_event(x.c_str()); + afb_event_t ev = afb_daemon_make_event(x.c_str()); #endif - event2list[x] = ev; + evname2afb_event[x] = ev; } } WMClient::WMClient(const string &appid, const string &role) : id(appid), layer(0), + is_source_set(false), role2surface(0), - event2list(0) + evname2afb_event(0) { role2surface[role] = INVALID_SURFACE_ID; for (auto x : kWMEvents) @@ -65,14 +81,29 @@ WMClient::WMClient(const string &appid, const string &role) #if GTEST_ENABLED string ev = x; #else - afb_event ev = afb_daemon_make_event(x.c_str()); + afb_event_t ev = afb_daemon_make_event(x.c_str()); #endif - event2list[x] = ev; + evname2afb_event[x] = ev; } } -WMClient::~WMClient() +WMClient::WMClient(const string &appid, unsigned layer, const string &role) + : id(appid), + layer(layer), + main_role(role), + role2surface(0), + evname2afb_event(0) { + role2surface[role] = INVALID_SURFACE_ID; + for (auto x : kWMEvents) + { +#if GTEST_ENABLED + string ev = x; +#else + afb_event_t ev = afb_daemon_make_event(x.c_str()); +#endif + evname2afb_event[x] = ev; + } } string WMClient::appID() const @@ -80,108 +111,70 @@ string WMClient::appID() const return this->id; } -unsigned WMClient::surfaceID(const string &role) const +string WMClient::role() const { - if (0 == this->role2surface.count(role)) - { - return INVALID_SURFACE_ID; - } - return this->role2surface.at(role); + return this->main_role; } -std::string WMClient::role(unsigned surface) const +unsigned WMClient::layerID() const { - for(const auto& x : this->role2surface) - { - if(x.second == surface) - { - return x.first; - } - } - return std::string(""); + return this->layer; } -unsigned WMClient::layerID() const +unsigned WMClient::surfaceID() const { - return this->layer; + return this->surface; } -/** - * Set layerID the client belongs to - * - * This function set layerID the client belongs to. - * But this function may not used because the layer should be fixed at constructor. - * So this function will be used to change layer by some reasons. - * - * @param unsigned[in] layerID - * @return None - * @attention WMClient can't have multiple layer - */ -void WMClient::registerLayer(unsigned layer) +void WMClient::registerSurface(unsigned surface) { - this->layer = layer; + this->surface = surface; } /** - * Add the pair of role and surface to the client + * Add surface to the client * - * This function set the pair of role and surface to the client. - * This function is used for the client which has multi surfaces. - * If the model and relationship for role and surface(layer) - * is changed, this function will be changed - * Current Window Manager doesn't use this function. + * This function add main surface to the client(ivi_layer). * * @param string[in] role - * @param unsigned[in] surface - * @return true + * @return WMError */ -bool WMClient::addSurface(const string &role, unsigned surface) +WMError WMClient::addSurface(unsigned surface) { - HMI_DEBUG("Add role %s with surface %d", role.c_str(), surface); - if (0 != this->role2surface.count(role)) + this->surface = surface; + ilmErrorTypes err = ilm_layerAddSurface(this->layer, surface); + + if(err == ILM_SUCCESS) { - HMI_NOTICE("override surfaceID %d with %d", this->role2surface[role], surface); + err = ilm_commitChanges(); } - this->role2surface[role] = surface; - return true; + return (err == ILM_SUCCESS) ? WMError::SUCCESS : WMError::FAIL; } -bool WMClient::removeSurfaceIfExist(unsigned surface) +void WMClient::setSurfaceSizeCorrectly() { - bool ret = false; - for (auto &x : this->role2surface) - { - if (surface == x.second) - { - HMI_INFO("Remove surface from client %s: role %s, surface: %d", - this->id.c_str(), x.first.c_str(), x.second); - this->role2surface.erase(x.first); - ret = true; - break; - } - } - return ret; + this->is_source_set = true; +} + +bool WMClient::isSourceSizeSet() +{ + return this->is_source_set; } -bool WMClient::removeRole(const string &role) +bool WMClient::removeSurfaceIfExist(unsigned surface) { bool ret = false; - if (this->role2surface.count(role) != 0) + if(surface == this->surface) { - this->role2surface.erase(role); + this->surface = INVALID_SURFACE_ID; ret = true; } return ret; } -#if GTEST_ENABLED -bool WMClient::subscribe(afb_req req, const string &evname) +bool WMClient::subscribe(afb_req_t req, const string &evname) { - if(evname != kKeyError){ - HMI_DEBUG("error is only enabeled for now"); - return false; - } - int ret = afb_req_subscribe(req, this->event2list[evname]); + int ret = afb_req_subscribe(req, this->evname2afb_event[evname]); if (ret) { HMI_DEBUG("Failed to subscribe %s", evname.c_str()); @@ -190,24 +183,129 @@ bool WMClient::subscribe(afb_req req, const string &evname) return true; } -void WMClient::emitError(WM_CLIENT_ERROR_EVENT ev) +void WMClient::emitVisible(bool visible) +{ + // error check + bool allow_send = false; + if(visible) + { + allow_send = afb_event_is_valid(this->evname2afb_event[kVisible]); + } + else + { + allow_send = afb_event_is_valid(this->evname2afb_event[kInvisible]); + } + if(allow_send) + { + json_object* j = json_object_new_object(); + json_object_object_add(j, kKeyRole, json_object_new_string(this->role().c_str())); + json_object_object_add(j, kKeyDrawingName, json_object_new_string(this->role().c_str())); + + if(visible) + { + afb_event_push(this->evname2afb_event[kVisible], j); + } + else + { + afb_event_push(this->evname2afb_event[kInvisible], j); + } + } + else + { + HMI_ERROR("Failed to send %s", __func__); + } +} + +void WMClient::emitActive(bool active) +{ + // error check + bool allow_send = false; + if(active) + { + allow_send = afb_event_is_valid(this->evname2afb_event[kActive]); + } + else + { + allow_send = afb_event_is_valid(this->evname2afb_event[kInactive]); + } + if(allow_send) + { + json_object* j = json_object_new_object(); + json_object_object_add(j, kKeyRole, json_object_new_string(this->role().c_str())); + json_object_object_add(j, kKeyDrawingName, json_object_new_string(this->role().c_str())); + + if(active) + { + afb_event_push(this->evname2afb_event[kActive], j); + } + else + { + afb_event_push(this->evname2afb_event[kInactive], j); + } + } + else + { + HMI_ERROR("Failed to send %s", __func__); + } +} + +void WMClient::emitSyncDraw(const string& area, struct rect& r) +{ + HMI_NOTICE("trace"); + if(afb_event_is_valid(this->evname2afb_event[kSyncDraw])) + { + json_object *j_rect = json_object_new_object(); + json_object_object_add(j_rect, kKeyX, json_object_new_int(r.x)); + json_object_object_add(j_rect, kKeyY, json_object_new_int(r.y)); + json_object_object_add(j_rect, kKeyWidth, json_object_new_int(r.w)); + json_object_object_add(j_rect, kKeyHeight, json_object_new_int(r.h)); + + json_object* j = json_object_new_object(); + json_object_object_add(j, kKeyRole, json_object_new_string(this->role().c_str())); + json_object_object_add(j, kKeyDrawingName, json_object_new_string(this->role().c_str())); + json_object_object_add(j, kKeyDrawingArea, json_object_new_string(area.c_str())); + json_object_object_add(j, kKeyArea, json_object_new_string(this->role().c_str())); + + json_object_object_add(j, kKeyDrawingRect, j_rect); + afb_event_push(this->evname2afb_event[kSyncDraw], j); + } + else + { + HMI_ERROR("Failed to send %s", __func__); + } +} + +void WMClient::emitFlushDraw() +{ + if(afb_event_is_valid(this->evname2afb_event[kFlushDraw])) + { + json_object* j = json_object_new_object(); + json_object_object_add(j, kKeyRole, json_object_new_string(this->role().c_str())); + json_object_object_add(j, kKeyDrawingName, json_object_new_string(this->role().c_str())); + afb_event_push(this->evname2afb_event[kFlushDraw], nullptr); + } + else + { + HMI_ERROR("Failed to send %s", __func__); + } +} + +void WMClient::emitError(WMError error) { - if (!afb_event_is_valid(this->event2list[kKeyError])){ + if (!afb_event_is_valid(this->evname2afb_event[kKeyError])){ HMI_ERROR("event err is not valid"); return; } json_object *j = json_object_new_object(); - json_object_object_add(j, kKeyError, json_object_new_int(ev)); - json_object_object_add(j, kKeyErrorDesc, json_object_new_string(kErrorDescription[ev].c_str())); - HMI_DEBUG("error: %d, description:%s", ev, kErrorDescription[ev].c_str()); - - int ret = afb_event_push(this->event2list[kKeyError], j); + json_object_object_add(j, kKeyError, json_object_new_int(error)); + json_object_object_add(j, kKeyErrorDesc, json_object_new_string(errorDescription(error))); + HMI_DEBUG("error: %d, description:%s", error, errorDescription(error)); + int ret = afb_event_push(this->evname2afb_event[kKeyError], j); if (ret != 0) { HMI_DEBUG("afb_event_push failed: %m"); } } -#endif void WMClient::dumpInfo() { diff --git a/src/wm_client.hpp b/src/wm_client.hpp index 259d504..3ffa786 100644 --- a/src/wm_client.hpp +++ b/src/wm_client.hpp @@ -20,21 +20,17 @@ #include <vector> #include <string> #include <unordered_map> +#include "util.hpp" +#include "wm_error.hpp" extern "C" { -#define AFB_BINDING_VERSION 2 #include <afb/afb-binding.h> } namespace wm { -enum WM_CLIENT_ERROR_EVENT -{ - UNKNOWN_ERROR -}; - class WMClient { public: @@ -42,35 +38,48 @@ class WMClient WMClient(const std::string &appid, unsigned layer, unsigned surface, const std::string &role); WMClient(const std::string &appid, const std::string &role); - virtual ~WMClient(); + WMClient(const std::string &appid, unsigned layer, const std::string &role); + WMClient(const std::string &appid, unsigned layer, + const std::string& layer_name, unsigned surface, const std::string &role); + ~WMClient() = default; std::string appID() const; - unsigned surfaceID(const std::string &role) const; + std::string role() const; unsigned layerID() const; - std::string role(unsigned surface) const; - void registerLayer(unsigned layer); - bool addSurface(const std::string& role, unsigned surface); + unsigned surfaceID() const; + void registerSurface(unsigned surface); + std::string area() const {return this->app_area;}; + void setArea(const std::string area) {this->app_area = area;} + WMError addSurface(unsigned surface); + bool isSourceSizeSet(); + void setSurfaceSizeCorrectly(); bool removeSurfaceIfExist(unsigned surface); - bool removeRole(const std::string& role); -#if GTEST_ENABLED - bool subscribe(afb_req req, const std::string &event_name); - void emitError(WM_CLIENT_ERROR_EVENT ev); -#endif + bool subscribe(afb_req_t req, const std::string &event_name); + void emitActive(bool active); + void emitVisible(bool visible); + void emitSyncDraw(const std::string& area, struct rect& r); + void emitFlushDraw(); + void emitError(WMError error); void dumpInfo(); private: std::string id; unsigned layer; + bool is_source_set; + std::string main_role; + std::string app_area; + unsigned surface; // currently, main application has only one surface. + //std::vector<std::string> role_list; std::unordered_map<std::string, unsigned> role2surface; #if GTEST_ENABLED // This is for unit test. afb_make_event occurs sig11 if call not in afb-binding - std::unordered_map<std::string, std::string> event2list; + std::unordered_map<std::string, std::string> evname2afb_event; #else - std::unordered_map<std::string, struct afb_event> event2list; + std::unordered_map<std::string, afb_event_t> evname2afb_event; #endif }; } // namespace wm -#endif
\ No newline at end of file +#endif diff --git a/src/wm_layer.cpp b/src/wm_layer.cpp new file mode 100644 index 0000000..66fb0a2 --- /dev/null +++ b/src/wm_layer.cpp @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2017 TOYOTA MOTOR CORPORATION + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#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 +{ + +LayerState::LayerState() + : render_order(), + area2appid() +{} + +const unordered_map<string, string> LayerState::getCurrentState() +{ + return this->area2appid; +} + +const vector<unsigned> LayerState::getIviIdList() +{ + return this->render_order; +} + +void LayerState::addLayer(unsigned layer) +{ + 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); +} + +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()); +} + +void LayerState::attachAppToArea(const string& app, const string& area) +{ + this->area2appid[area] = app; +} + +void LayerState::dump() +{ + std::string ids, apps; + for(const auto& ro : this->render_order) + { + ids += std::to_string(ro); + ids += ","; + } + for(const auto& area : this->area2appid) + { + apps += area.first; + apps += ":"; + apps += area.second; + apps += ","; + } + DUMP(" render order : %s", ids.c_str()); + DUMP(" area, app : %s", apps.c_str()); +} + +WMLayer::WMLayer(json_object* j, unsigned wm_layer_id) : tmp_state(), state(), wm_layer_id(wm_layer_id) +{ + 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")); + + if (name.empty()) + { + HMI_ERROR("Parse Error!!"); + exit(1); + } + if(this->id_begin > this->id_end) + { + HMI_ERROR("INVALID"); + exit(1); + } +} + +unsigned WMLayer::getNewLayerID(const string& role) +{ + unsigned ret = 0; + if(this->name == BG_LAYER_NAME) + return ret; + + // generate new layer id; + if(this->hasRole(role)) + { + if(this->id_list.size() == 0) + { + ret = this->idBegin(); + this->id_list.push_back(ret); + } + else + { + ret = this->id_list.back() + 1; + } + HMI_INFO("Generate new id: %d", ret); + } + else + { + return ret; + } + + 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; + } + } + } + + if(ret != 0) + { + id_list.push_back(ret); + } + else + { + HMI_ERROR("failed to get New ID"); + } + return ret; +} + +const string& WMLayer::layerName() +{ + return this->name; +} + +WMError WMLayer::setLayerState(const LayerState& l) +{ + this->tmp_state = l; + return WMError::SUCCESS; +} + +void WMLayer::addLayerToState(unsigned layer) +{ + this->tmp_state.addLayer(layer); +} + +void WMLayer::removeLayerFromState(unsigned layer) +{ + this->tmp_state.removeLayer(layer); +} + +void WMLayer::attachAppToArea(const string& app, const string& area) +{ + this->tmp_state.attachAppToArea(app, area); +} + +string WMLayer::attachedApp(const string& area) +{ + string ret; + auto list = this->state.getCurrentState(); + auto app = list.find(area); + if(app != list.end()) + { + ret = app->second; + } + return ret; +} + +void WMLayer::appendArea(const string& area) +{ + this->area_list.push_back(area); +} + +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); +} + +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; +} + +bool WMLayer::hasRole(const string& role) +{ + auto re = std::regex(this->role_list); + if (std::regex_match(role, re)) + { + HMI_DEBUG("role %s matches layer %s", role.c_str(), this->name.c_str()); + return true; + } + return false; +} + +void WMLayer::update() +{ + this->state = this->tmp_state; +} + +void WMLayer::undo() +{ + this->tmp_state = this->state; +} + +void WMLayer::dump() +{ + DUMP("===== wm layer status ====="); + DUMP("Layer :%s", this->name.c_str()); + this->tmp_state.dump(); + this->state.dump(); + DUMP("===== wm layer status end ====="); + +} + +} // namespace wm diff --git a/src/wm_layer.hpp b/src/wm_layer.hpp new file mode 100644 index 0000000..97cf8a8 --- /dev/null +++ b/src/wm_layer.hpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2017 TOYOTA MOTOR CORPORATION + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef WM_LAYER_HPP +#define WM_LAYER_HPP + +#include <string> +#include <vector> +#include <unordered_map> +#include <memory> +#include "wm_error.hpp" + +struct json_object; + +namespace wm +{ + +class WMClient; +class LayerState +{ + public: + LayerState(); + ~LayerState() = default; + const std::unordered_map<std::string, std::string> getCurrentState(); + const std::vector<unsigned> getIviIdList(); + void addLayer(unsigned layer); + void removeLayer(unsigned layer); + void attachAppToArea(const std::string& app, const std::string& area); + + // Debug + void dump(); + + private: + std::vector<unsigned> render_order; + std::unordered_map<std::string, std::string> area2appid; +}; + +class WMLayer +{ + public: + explicit WMLayer(json_object* j, unsigned wm_layer_id); + ~WMLayer() = default; + + // Status & Setting API + unsigned getNewLayerID(const std::string& role); + unsigned idBegin() { return this->id_begin; } + unsigned idEnd() { return this->id_end; } + unsigned getWMLayerID() { return this->wm_layer_id; } + const std::string& layerName(); + void appendArea(const std::string& area); + LayerState& getLayerState() { return tmp_state; } + WMError setLayerState(const LayerState& l); + bool hasLayerID(unsigned id); + bool hasRole(const std::string& role); + + // Manipulation + void addLayerToState(unsigned layer); + void removeLayerFromState(unsigned layer); + void attachAppToArea(const std::string& app, const std::string& area); + std::string attachedApp(const std::string& area); + void update(); + void undo(); + + // Event + void appTerminated(unsigned layer); + + // Debug + void dump(); + + private: + LayerState tmp_state; + LayerState state; + unsigned wm_layer_id; + std::string name = ""; // Layer name + std::string role_list; + std::vector<std::string> area_list; + std::vector<unsigned> id_list; + unsigned id_begin; + unsigned id_end; +}; + +} // namespace wm + +#endif // WM_LAYER_HPP diff --git a/src/wm_layer_control.cpp b/src/wm_layer_control.cpp new file mode 100644 index 0000000..65d8c30 --- /dev/null +++ b/src/wm_layer_control.cpp @@ -0,0 +1,645 @@ +/* + * Copyright (c) 2017 TOYOTA MOTOR CORPORATION + * Copyright (c) 2018 Konsulko Group + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include <assert.h> +#include <unistd.h> +#include "wm_layer_control.hpp" +#include "wm_layer.hpp" +#include "wm_client.hpp" +#include "request.hpp" +#include "json_helper.hpp" + +#define LC_AREA_FILE "areas.json" +#define LC_LAYER_SETTING_FILE "layers.json" +#define LC_DEFAULT_AREA "fullscreen" +#define BACK_GROUND_LAYER "BackGroundLayer" + +using std::string; +using std::vector; +using std::shared_ptr; + +namespace wm { + +LayerControl* g_lc_ctxt; + +static void createCallback_static(ilmObjectType object, + t_ilm_uint id, + t_ilm_bool created, + void* data) +{ + static_cast<LayerControl*>(data)->dispatchCreateEvent(object, id, created); +} + +static void surfaceCallback_static(t_ilm_surface surface, + struct ilmSurfaceProperties* surface_prop, + t_ilm_notification_mask mask) +{ + g_lc_ctxt->dispatchSurfacePropChangeEvent(surface, surface_prop, mask); +} + +static void layerCallback_static(t_ilm_layer layer, + struct ilmLayerProperties* layer_prop, + t_ilm_notification_mask mask) +{ + g_lc_ctxt->dispatchLayerPropChangeEvent(layer, layer_prop, mask); +} + +LayerControl::LayerControl(const std::string& root) +{ + string area_path(get_file_path(LC_AREA_FILE, root.c_str())); + string layer_path(get_file_path(LC_LAYER_SETTING_FILE, root.c_str())); + // load layers.setting.json + WMError ret = this->loadLayerSetting(layer_path); + assert(ret == WMError::SUCCESS); + // load areas.json + ret = this->loadAreaDb(area_path); + assert(ret == WMError::SUCCESS); +} + +WMError LayerControl::init(const LayerControlCallbacks& cb) +{ + HMI_DEBUG("Initialize of ilm library and display"); + t_ilm_uint num = 0; + t_ilm_uint *ids; + int cnt = 0; + ilmErrorTypes rc = ilm_init(); + + while (rc != ILM_SUCCESS) + { + cnt++; + if (20 <= cnt) + { + HMI_ERROR("Could not connect to compositor"); + goto lc_init_error; + } + HMI_ERROR("Wait to start weston ..."); + sleep(1); + rc = ilm_init(); + } + if(rc != ILM_SUCCESS) goto lc_init_error; + + // Get current screen setting + rc = ilm_getScreenIDs(&num, &ids); + + if(rc != ILM_SUCCESS) goto lc_init_error; + + for(unsigned i = 0; i < num; i++) + { + HMI_INFO("get screen: %d", ids[i]); + } + // Currently, 0 is only available + this->screenID = ids[0]; + + rc = ilm_getPropertiesOfScreen(this->screenID, &this->screen_prop); + + if(rc != ILM_SUCCESS) goto lc_init_error; + + // Register Callback to Window Manager and from ILM + this->cb = cb; + ilm_registerNotification(createCallback_static, this); + + return WMError::SUCCESS; + +lc_init_error: + HMI_ERROR("Failed to initialize. Terminate WM"); + + return WMError::FAIL; +} + +void LayerControl::createNewLayer(unsigned id) +{ + HMI_INFO("create new ID :%d", id); + struct rect rct = this->area2size[LC_DEFAULT_AREA]; + ilm_layerCreateWithDimension(&id, rct.w, rct.h); + //ilm_layerSetSourceRectangle(id, rct.x, rct.y, rct.w, rct.h); + ilm_layerSetDestinationRectangle(id, this->offset_x, this->offset_y, rct.w, rct.h); + ilm_layerSetOpacity(id, 1.0); + ilm_layerSetVisibility(id, ILM_FALSE); + ilm_commitChanges(); + auto wm_layer = getWMLayer(id); + wm_layer->addLayerToState(id); + this->renderLayers(); +} + +unsigned LayerControl::getNewLayerID(const string& role) +{ + unsigned ret = 0; + for(const auto& l: this->wm_layers) + { + ret = l->getNewLayerID(role); + if(ret != 0) + { + unsigned wmlid = l->getWMLayerID(); + this->lid2wmlid[ret] = wmlid; + break; + } + } + return ret; +} + +shared_ptr<WMLayer> LayerControl::getWMLayer(unsigned layer) +{ + unsigned wm_lid = this->lid2wmlid[layer]; + return this->wm_layers[wm_lid]; +} + +std::shared_ptr<WMLayer> LayerControl::getWMLayer(std::string layer_name) +{ + for(auto &l : this->wm_layers) + { + if(l->layerName() == layer_name) + { + return l; + } + } + return nullptr; +} + +struct rect LayerControl::getAreaSize(const std::string& area) +{ + return area2size[area]; +} + +void LayerControl::setupArea(const rectangle& base_rct, double scaling) +{ + this->scaling = scaling; + this->offset_x = base_rct.left(); + this->offset_y = base_rct.top(); + + 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); + } +} + +Screen LayerControl::getScreenInfo() +{ + return Screen(this->screen_prop.screenWidth, this->screen_prop.screenHeight); +} + +double LayerControl::scale() +{ + return this->scaling; +} + +WMError LayerControl::renderLayers() +{ + HMI_INFO("Commit change"); + WMError rc = WMError::SUCCESS; + + // Check the number of layers + vector<unsigned> ivi_l_ids; + for(auto& l : this->wm_layers) + { + auto state = l->getLayerState(); + HMI_DEBUG("layer %s", l->layerName().c_str()); + for(const auto& id : state.getIviIdList()) + { + HMI_DEBUG("Add %d", id); + ivi_l_ids.push_back(id); + } + } + + // Create render order + t_ilm_layer* id_array = new t_ilm_layer[ivi_l_ids.size()]; + if(id_array == nullptr) + { + HMI_WARNING("short memory"); + this->undoUpdate(); + return WMError::FAIL; + } + int count = 0; + for(const auto& i : ivi_l_ids) + { + id_array[count] = i; + ++count; + } + + // Display + ilmErrorTypes ret = ilm_displaySetRenderOrder(this->screenID, id_array, ivi_l_ids.size()); + if(ret != ILM_SUCCESS) + { + this->undoUpdate(); + rc = WMError::FAIL; + } + else + { + for(auto& l : this->wm_layers) + { + l->update(); + } + } + ilm_commitChanges(); + delete id_array; + return rc; +} + +WMError LayerControl::setXDGSurfaceOriginSize(unsigned surface) +{ + WMError ret = WMError::NOT_REGISTERED; + ilmSurfaceProperties prop; + ilmErrorTypes rc = ilm_getPropertiesOfSurface(surface, &prop); + if(rc == ILM_SUCCESS) + { + HMI_INFO("xdg surface info %d, %d", prop.origSourceWidth, prop.origSourceHeight); + ilm_surfaceSetSourceRectangle(surface, 0, 0, prop.origSourceWidth, prop.origSourceHeight); + ret = WMError::SUCCESS; + } + return ret; +} + + +void LayerControl::undoUpdate() +{ + for(auto& l : this->wm_layers) + { + l->undo(); + } +} + +WMError LayerControl::loadLayerSetting(const string &path) +{ + HMI_DEBUG("loading WMLayer(Application Containers) Setting from %s", path.c_str()); + + json_object *json_obj, *json_cfg; + int ret = jh::inputJsonFilie(path.c_str(), &json_obj); + if (0 > ret) + { + HMI_ERROR("Could not open %s", path.c_str()); + return WMError::FAIL; + } + HMI_INFO("json_obj dump:%s", json_object_get_string(json_obj)); + + if (!json_object_object_get_ex(json_obj, "mappings", &json_cfg)) + { + HMI_ERROR("Parse Error!!"); + return WMError::FAIL; + } + + int len = json_object_array_length(json_cfg); + HMI_DEBUG("json_cfg len:%d", len); + + 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)); + + this->wm_layers.emplace_back(std::make_shared<WMLayer>(json_tmp, i)); + } + json_object_put(json_obj); + + return WMError::SUCCESS; +} + +WMError LayerControl::loadAreaDb(const std::string& path) +{ + // Load area.db + json_object *json_obj; + int ret = jh::inputJsonFilie(path.c_str(), &json_obj); + if (0 > ret) + { + HMI_ERROR("Could not open %s", path.c_str()); + return WMError::FAIL; + } + HMI_INFO("json_obj dump:%s", json_object_get_string(json_obj)); + + // Perse areas + json_object *json_cfg; + if (!json_object_object_get_ex(json_obj, "areas", &json_cfg)) + { + HMI_ERROR("Parse Error!!"); + return WMError::FAIL; + } + + int len = json_object_array_length(json_cfg); + HMI_DEBUG("json_cfg len:%d", len); + + 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 WMError::FAIL; + } + 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 WMError::FAIL; + } + HMI_DEBUG("> json_rect dump:%s", json_object_get_string(json_rect)); + + struct 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"); + + this->area2size[area] = area_size; + } + + // Check + for (const auto& itr : this->area2size) + { + 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); + } + + // Release json_object + json_object_put(json_obj); + + return WMError::SUCCESS; +} + +WMError LayerControl::layoutChange(const WMAction& action) +{ + if (action.visible == TaskVisible::INVISIBLE) + { + // Visibility is not change -> no redraw is required + return WMError::SUCCESS; + } + if(action.client == nullptr) + { + HMI_SEQ_ERROR(action.req_num, "client may vanish"); + return WMError::NOT_REGISTERED; + } + unsigned layer = action.client->layerID(); + unsigned surface = action.client->surfaceID(); + + auto rect = this->getAreaSize(action.area); + HMI_SEQ_INFO(action.req_num, "Set layout %d, %d, %d, %d",rect.x, rect.y, rect.w, rect.h); + + // Sometimes, ivi_wm_surface_size signal doesn't reach window manager, + // then, Window Manager set set source size = 0. + if(!action.client->isSourceSizeSet()) + { + ilmSurfaceProperties sp; + ilm_getPropertiesOfSurface(surface, &sp); + if((sp.origSourceHeight != sp.sourceHeight) || (sp.origSourceWidth != sp.sourceWidth)) + { + HMI_SEQ_NOTICE(action.req_num, "set source size w:%d h%d", sp.origSourceWidth, sp.origSourceHeight); + ilm_surfaceSetSourceRectangle(surface, 0, 0, sp.origSourceWidth, sp.origSourceHeight); + ilm_commitChanges(); + action.client->setSurfaceSizeCorrectly(); + } + } + + ilm_surfaceSetDestinationRectangle(surface, rect.x, rect.y, rect.w, rect.h); + ilm_commitChanges(); + action.client->setArea(action.area); + for(auto &wm_layer: this->wm_layers) + { + // Store the state who is assigned to the area + if(wm_layer->hasLayerID(layer)) + { + wm_layer->attachAppToArea(action.client->appID(), action.area); + /* TODO: manipulate state directly + LayerState ls = wm_layer->getLayerState(); + ls.seattachAppToAreatArea(action.client->appID(), action.area); + wm_layer->dump(); */ + } + } + + return WMError::SUCCESS; +} + +WMError LayerControl::visibilityChange(const WMAction& action) +{ + WMError ret = WMError::FAIL; + if(action.client == nullptr) + { + HMI_SEQ_ERROR(action.req_num, "client may vanish"); + return WMError::NOT_REGISTERED; + } + + if (action.visible == TaskVisible::VISIBLE) + { + ret = this->makeVisible(action.client); + } + else if (action.visible == TaskVisible::INVISIBLE) + { + ret = this->makeInvisible(action.client); + } + ilm_commitChanges(); + return ret; +} + +void LayerControl::appTerminated(const shared_ptr<WMClient> client) +{ + for(auto& l : this->wm_layers) + { + if(l->hasLayerID(client->layerID())) + { + l->appTerminated(client->layerID()); + } + } +} + +void LayerControl::dispatchCreateEvent(ilmObjectType object, unsigned id, bool created) +{ + if (ILM_SURFACE == object) + { + if (created) + { + ilmSurfaceProperties sp; + ilmErrorTypes rc; + rc = ilm_getPropertiesOfSurface(id, &sp); + if(rc != ILM_SUCCESS) + { + HMI_ERROR("Failed to get surface %d property due to %d", id, ilm_getError()); + return; + } + this->cb.surfaceCreated(sp.creatorPid, id); + ilm_surfaceAddNotification(id, surfaceCallback_static); + ilm_surfaceSetVisibility(id, ILM_TRUE); + ilm_surfaceSetType(id, ILM_SURFACETYPE_DESKTOP); + } + else + { + this->cb.surfaceDestroyed(id); + } + } + if (ILM_LAYER == object) + { + if(created) + { + ilm_layerAddNotification(id, layerCallback_static); + } + else + { + // Ignore here. Nothing to do currently. + // Process of application dead is handled by Window Manager + // from binder notification + } + } +} + +void LayerControl::dispatchSurfacePropChangeEvent(unsigned id, + struct ilmSurfaceProperties* sprop, + t_ilm_notification_mask mask) +{ + /* + ILM_NOTIFICATION_CONTENT_AVAILABLE & ILM_NOTIFICATION_CONTENT_REMOVED + are not handled here, handled in create/destroy event + */ + if (ILM_NOTIFICATION_VISIBILITY & mask) + { + HMI_DEBUG("surface %d turns visibility %d", id, sprop->visibility); + } + if (ILM_NOTIFICATION_OPACITY & mask) + { + HMI_DEBUG("surface %d turns opacity %f", id, sprop->opacity); + } + if (ILM_NOTIFICATION_SOURCE_RECT & mask) + { + HMI_DEBUG("surface %d source rect changes", id); + } + if (ILM_NOTIFICATION_DEST_RECT & mask) + { + HMI_DEBUG("surface %d dest rect changes", id); + } + if (ILM_NOTIFICATION_CONFIGURED & mask) + { + HMI_DEBUG("surface %d size %d, %d, %d, %d", id, + sprop->sourceX, sprop->sourceY, sprop->origSourceWidth, sprop->origSourceHeight); + ilm_surfaceSetSourceRectangle(id, 0, 0, sprop->origSourceWidth, sprop->origSourceHeight); + } +} + +void LayerControl::dispatchLayerPropChangeEvent(unsigned id, + struct ilmLayerProperties* lprop, + t_ilm_notification_mask mask) +{ + if (ILM_NOTIFICATION_VISIBILITY & mask) + { + HMI_DEBUG("layer %d turns visibility %d", id, lprop->visibility); + } + if (ILM_NOTIFICATION_OPACITY & mask) + { + HMI_DEBUG("layer %d turns opacity %f", id, lprop->opacity); + } + if (ILM_NOTIFICATION_SOURCE_RECT & mask) + { + HMI_DEBUG("layer %d source rect changes", id); + } + if (ILM_NOTIFICATION_DEST_RECT & mask) + { + HMI_DEBUG("layer %d dest rect changes", id); + } +} + +WMError LayerControl::makeVisible(const shared_ptr<WMClient> client) +{ + WMError ret = WMError::SUCCESS; + // Don't check here wheher client is nullptr or not + unsigned layer = client->layerID(); + + this->moveForeGround(client); + + ilm_layerSetVisibility(layer, ILM_TRUE); + + return ret; +} + +WMError LayerControl::makeInvisible(const shared_ptr<WMClient> client) +{ + WMError ret = WMError::SUCCESS; + // Don't check here the client is not nullptr + unsigned layer = client->layerID(); + + bool mv_ok = this->moveBackGround(client); + + if(!mv_ok) + { + HMI_INFO("make invisible client %s", client->appID().c_str()); + ilm_layerSetVisibility(layer, ILM_FALSE); + } + + return ret; +} + +bool LayerControl::moveBackGround(const shared_ptr<WMClient> client) +{ + bool ret = false; + + // Move background from foreground layer + auto bg = this->getWMLayer(BACK_GROUND_LAYER); + if(bg != nullptr) + { + HMI_DEBUG("client %s role %s", client->appID().c_str(), client->role().c_str()); + unsigned layer = client->layerID(); + if(bg->hasRole(client->role())) + { + HMI_INFO("%s go to background", client->appID().c_str()); + bg->addLayerToState(layer); + auto wm_layer = this->getWMLayer(layer); + wm_layer->removeLayerFromState(layer); + /* TODO: manipulate state directly + LayerState bg_ls = bg->getLayerState(); + bg_ls.addLayer(layer); + LayerState ls = wm_layer->getLayerState(); + ls.removeLayer(layer); */ + bg->dump(); + wm_layer->dump(); + ret = true; + } + } + return ret; +} + +bool LayerControl::moveForeGround(const shared_ptr<WMClient> client) +{ + bool ret = false; + + // Move foreground from foreground layer + auto bg = this->getWMLayer(BACK_GROUND_LAYER); + if(bg != nullptr) + { + if(bg->hasRole(client->role())) + { + unsigned layer = client->layerID(); + HMI_INFO("%s go to foreground", client->appID().c_str()); + bg->removeLayerFromState(layer); + auto wm_layer = this->getWMLayer(layer); + wm_layer->addLayerToState(layer); + /* TODO: manipulate state directly + LayerState bg_ls = bg->getLayerState(); + bg_ls.removeLayer(layer); + LayerState ls = wm_layer->getLayerState(); + ls.addLayer(layer); */ + bg->dump(); + wm_layer->dump(); + ret = true; + } + } + return ret; +} + +} // namespace wm diff --git a/src/wm_layer_control.hpp b/src/wm_layer_control.hpp new file mode 100644 index 0000000..25d71fd --- /dev/null +++ b/src/wm_layer_control.hpp @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2017 TOYOTA MOTOR CORPORATION + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <string> +#include <memory> +#include <vector> +#include <unordered_map> +#include <functional> +#include <ilm/ilm_control.h> +#include "wm_error.hpp" +#include "util.hpp" + +namespace wm { + +class Screen { + public: + Screen(unsigned w, unsigned h) : _width(w), _height(h){} + unsigned width() { return _width; } + unsigned height() { return _height; } + private: + unsigned _width; + unsigned _height; + unsigned _pysical_width = 0; + unsigned _pysical_height = 0; +}; + +class LayerControlCallbacks { + public: + LayerControlCallbacks() {}; + ~LayerControlCallbacks() = default; + LayerControlCallbacks(const LayerControlCallbacks &obj) = default; + + // callback functions + std::function<void(unsigned, unsigned)> surfaceCreated; + std::function<void(unsigned)> surfaceDestroyed; + /* + std::function<void(unsigned)> layerCreated; + std::function<void(unsigned)> layerDestroyed; + */ +}; + +class WMLayer; +class LayerState; +class WMAction; +class WMClient; + +class LayerControl +{ + public: + explicit LayerControl(const std::string& root); + ~LayerControl() = default; + WMError init(const LayerControlCallbacks& cb); + void createNewLayer(unsigned id); + unsigned getNewLayerID(const std::string& role); + std::shared_ptr<WMLayer> getWMLayer(unsigned layer); + std::shared_ptr<WMLayer> getWMLayer(std::string layer_name); + struct rect getAreaSize(const std::string& area); + void setupArea(const rectangle& base_rct, double scaling); + Screen getScreenInfo(); + double scale(); + WMError renderLayers(); + WMError setXDGSurfaceOriginSize(unsigned surface); + void undoUpdate(); + WMError layoutChange(const WMAction& action); + WMError visibilityChange(const WMAction &action); + void appTerminated(const std::shared_ptr<WMClient> client); + + // Don't use this function. + void dispatchCreateEvent(ilmObjectType object, unsigned id, bool created); + void dispatchSurfacePropChangeEvent(unsigned id, struct ilmSurfaceProperties*, t_ilm_notification_mask); + void dispatchLayerPropChangeEvent(unsigned id, struct ilmLayerProperties*, t_ilm_notification_mask); + + private: + WMError makeVisible(const std::shared_ptr<WMClient> client); + WMError makeInvisible(const std::shared_ptr<WMClient> client); + bool moveForeGround(const std::shared_ptr<WMClient> client); + bool moveBackGround(const std::shared_ptr<WMClient> client); + WMError loadLayerSetting(const std::string& path); + WMError loadAreaDb(const std::string& path); + + std::vector<std::shared_ptr<WMLayer>> wm_layers; + std::unordered_map<unsigned, unsigned> lid2wmlid; + std::unordered_map<std::string, struct rect> area2size; + unsigned screenID; + struct ilmScreenProperties screen_prop; + double scaling; + int offset_x; + int offset_y; + LayerControlCallbacks cb; +}; + +} // namespace wm
\ No newline at end of file |