From 741a9924776e40293b91eff00ec91d5a72f5da7f Mon Sep 17 00:00:00 2001 From: Kazumasa Mitsunari Date: Mon, 20 Aug 2018 14:44:55 +0900 Subject: Add setRole Change-Id: I6ddf6e1b3b3667493c5a0dd68047d1b72c8b0da9 Signed-off-by: Kazumasa Mitsunari --- src/applist.cpp | 83 ++++++++++++++++++++++++++++++++++++- src/applist.hpp | 17 ++++++++ src/main.cpp | 57 ++++++++++++++++++++++---- src/window_manager.cpp | 108 +++++++++++++++++++++++++++++++++++++++++++++++++ src/window_manager.hpp | 1 + src/wm_client.cpp | 16 +++----- src/wm_client.hpp | 8 ++-- 7 files changed, 269 insertions(+), 21 deletions(-) diff --git a/src/applist.cpp b/src/applist.cpp index a5ae9f0..fe9832f 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 lock(this->mtx); shared_ptr client = std::make_shared(appid, layer, surface, role); @@ -172,6 +172,76 @@ string AppList::getAppID(unsigned surface, const string& role, bool* found) cons return string(""); } +WMError AppList::popFloatingSurface(unsigned pid, unsigned *surface) +{ + WMError ret = WMError::NO_ENTRY; + + auto fwd_itr = std::remove_if(this->floating_surfaces.begin(), this->floating_surfaces.end(), + [pid, surface, &ret](FloatingSurface x) { + if(pid == x.pid){ + *surface = x.surface_id; + ret = WMError::SUCCESS; + return true; + } + else{ + return false; + } + }); + if (fwd_itr != this->floating_surfaces.cend()) + { + HMI_INFO("wm", "pop floating surface: %d", *surface); + } + this->floating_surfaces.erase(fwd_itr, this->floating_surfaces.end()); + return ret; +} + +// =================== Floating(Temporary) surface/client API =================== + +WMError AppList::popFloatingSurface(const string &appid, unsigned *surface) +{ + HMI_ERROR("wm", "This function is not implemented"); + return WMError::SUCCESS; +} + +void AppList::addFloatingClient(const string &appid, unsigned layer, const string &role) +{ +} + +void AppList::addFloatingSurface(const string &appid, unsigned surface, unsigned pid) +{ + struct FloatingSurface fsurface{appid, surface, pid}; + this->floating_surfaces.push_back(fsurface); + this->dumpFloatingSurfaces(); +} + +void AppList::removeFloatingSurface(unsigned surface) +{ + this->dumpFloatingSurfaces(); + auto fwd_itr = std::remove_if( + this->floating_surfaces.begin(), this->floating_surfaces.end(), + [surface](FloatingSurface x) { + return x.surface_id == surface; + }); + if(fwd_itr != this->floating_surfaces.cend()){ + HMI_INFO("wm", "remove floating surface: %d", surface); + } + this->floating_surfaces.erase(fwd_itr, this->floating_surfaces.end()); +} + +WMError AppList::appendRole(const string &id, const string &role, unsigned surface) +{ + WMError wm_err = WMError::NO_ENTRY; + HMI_ERROR("wm", "This function is disabled"); + /* if (this->contains(id)) + { + auto x = this->lookUpClient(id); + x->addSurface(role, surface); + wm_err = WMError::SUCCESS; + } */ + return wm_err; +} + + // =================== Request Date container API =================== /** @@ -523,4 +593,15 @@ void AppList::reqDump() } DUMP("======= req dump end ====="); } + +void AppList::dumpFloatingSurfaces() +{ + DUMP("======= floating surface dump ====="); + for (const auto &x : this->floating_surfaces) + { + DUMP("surface : %d, pid : %d", x.surface_id, x.pid); + } + DUMP("======= floating surface dump end =====\n"); +} + } // namespace wm diff --git a/src/applist.hpp b/src/applist.hpp index a794b53..fef4d65 100644 --- a/src/applist.hpp +++ b/src/applist.hpp @@ -31,6 +31,13 @@ namespace wm /* using std::experimental::nullopt; using std::experimental::optional; */ +struct FloatingSurface +{ + std::string appid; + unsigned surface_id; + unsigned pid; +}; + class AppList { public: @@ -50,6 +57,14 @@ class AppList std::shared_ptr lookUpClient(const std::string &appid); void removeSurface(unsigned surface); std::string getAppID(unsigned surface, const std::string &role, bool *found) const; + WMError appendRole(const std::string &appid, const std::string &role, unsigned surface); + + // Floating surface + void addFloatingClient(const std::string &appid, unsigned layer, const std::string &role); + void addFloatingSurface(const std::string &appid, unsigned surface, unsigned pid); + WMError popFloatingSurface(unsigned pid, unsigned *surface); + WMError popFloatingSurface(const std::string &appid, unsigned *surface); + void removeFloatingSurface(unsigned surface); // Request Interface unsigned currentRequestNumber() const; @@ -69,12 +84,14 @@ class AppList void clientDump(); void reqDump(); + void dumpFloatingSurfaces(); private: std::vector req_list; std::unordered_map> app2client; unsigned current_req; std::mutex mtx; + std::vector floating_surfaces; }; } // namespace wm diff --git a/src/main.cpp b/src/main.cpp index 0447f86..5990e99 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -189,13 +189,7 @@ static void cbRemoveClientCtxt(void *data) // so notify it by deactivate request. g_afb_instance->wmgr.api_deactivate_surface( ctxt->name.c_str(), ctxt->role.c_str(), - [](const char *errmsg) { - if (errmsg != nullptr) - { - HMI_ERROR("wm", errmsg); - return; - } - }); + [](const char *) {}); g_afb_instance->wmgr.removeClient(ctxt->name); delete ctxt; @@ -308,6 +302,54 @@ void windowmanager_requestsurfacexdg(afb_req req) noexcept } } +void windowmanager_setrole(afb_req req) noexcept +{ + std::lock_guard guard(binding_m); + if (g_afb_instance == nullptr) + { + afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?"); + return; + } + try + { + unsigned pid = 0; + char const *appid = afb_req_get_application_id(req); + json_object *jreq = afb_req_json(req); + + json_object *j_role = nullptr; + if (!json_object_object_get_ex(jreq, "role", &j_role)) + { + afb_req_fail(req, "failed", "Need char const* argument role"); + return; + } + char const *a_role = json_object_get_string(j_role); + + json_object *j_pid = nullptr; + if (json_object_object_get_ex(jreq, "pid", &j_pid)) + { + HMI_DEBUG("wm", "PID is set"); + char const *a_pid = json_object_get_string(j_pid); + pid = std::stol(a_pid); + } + + auto ret = g_afb_instance->wmgr.api_set_role(appid, a_role, pid); + if (!ret) + { + afb_req_fail(req, "failed", "Couldn't register"); + return; + } + + createSecurityContext(req, appid, a_role); + + afb_req_success(req, NULL, "success"); + } + catch (std::exception &e) + { + afb_req_fail_f(req, "failed", "Uncaught exception while calling requestsurfacexdg: %s", e.what()); + return; + } +} + void windowmanager_activatewindow(afb_req req) noexcept { std::lock_guard guard(binding_m); @@ -716,6 +758,7 @@ 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}, + {"setrole", windowmanager_setrole, 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}, diff --git a/src/window_manager.cpp b/src/window_manager.cpp index 2f8e3e9..6045eaa 100644 --- a/src/window_manager.cpp +++ b/src/window_manager.cpp @@ -340,6 +340,97 @@ char const *WindowManager::api_request_surface(char const *appid, char const *dr return nullptr; } +/** + * This function is substitute of requestSurface + * If surface creation is faster than application request of this function, + * WM will bind surfaceID with application and role. + * If surface creation is slower than application request of thie function, + * WM will put Client into pending list. + * + * Note : + * Application can request with pid but this is temporary solution for now. + * This will be removed. + * */ +bool WindowManager::api_set_role(char const *appid, char const *drawing_name, unsigned pid){ + std::string id = appid; + std::string role = drawing_name; + unsigned surface = 0; + WMError wm_err = WMError::UNKNOWN; + bool ret = false; + + // get layer ID which role should be in + auto lid = this->layers.get_layer_id(role); + if (!lid) + { + /** + * register drawing_name as fallback and make it displayed. + */ + lid = this->layers.get_layer_id(std::string("fallback")); + HMI_DEBUG("wm", "%s is not registered in layers.json, then fallback as normal app", role.c_str()); + if (!lid) + { + HMI_ERROR("wm", "Drawing name does not match any role, fallback is disabled"); + return ret; + } + } + + if(0 != pid){ + // search floating surfaceID from pid if pid is designated. + // It is not good that application request with its pid + wm_err = g_app_list.popFloatingSurface(pid, &surface); + } + else{ + // get floating surface with appid. If WM queries appid from pid, + // WM can bind surface and role with appid(not implemented yet) + //wm_err = g_app_list.popFloatingSurface(id); + } + if(wm_err != WMError::SUCCESS){ + HMI_ERROR("wm", "No floating surface for app: %s", id.c_str()); + g_app_list.addFloatingClient(id, *lid, role); + HMI_NOTICE("wm", "%s : Waiting for surface creation", id.c_str()); + return ret; + } + + ret = true; + if (g_app_list.contains(id)) + { + HMI_INFO("wm", "Add role: %s with surface: %d. Client %s has multi surfaces.", + role.c_str(), surface, id.c_str()); + wm_err = g_app_list.appendRole(id, role, surface); + if(wm_err != WMError::SUCCESS){ + HMI_INFO("wm", errorDescription(wm_err)); + } + } + else{ + HMI_INFO("wm", "Create new client: %s, surface: %d into layer: %d with role: %s", + id.c_str(), surface, *lid, role.c_str()); + g_app_list.addClient(id, *lid, surface, role); + } + + // register pair drawing_name and ivi_id + this->id_alloc.register_name_id(role.c_str(), surface); + this->layers.add_surface(surface, *lid); + + // this surface is already created + HMI_DEBUG("wm", "surface_id is %u, layer_id is %u", surface, *lid); + + const auto &o_layer = this->layers.get_layer(*lid); + auto rect = o_layer.value().rect; + if(rect.w < 0) + { + rect.w = this->controller->output_size.w + 1 + rect.w; + } + if(rect.h < 0) + { + rect.h = this->controller->output_size.h + 1 + rect.h; + } + + this->controller->layers[*lid]->add_surface(surface); + this->layout_commit(); + + return ret; +} + void WindowManager::api_activate_surface(char const *appid, char const *drawing_name, char const *drawing_area, const reply_func &reply) { @@ -352,6 +443,23 @@ void WindowManager::api_activate_surface(char const *appid, char const *drawing_ std::string id = appid; std::string role = c_role; std::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); + + unsigned srfc = client->surfaceID(role); + if(srfc == 0) + { + HMI_ERROR("wm", "role sould be set with surface"); + reply("role sould be set with surface"); + return; + } + g_app_list.removeFloatingSurface(client->surfaceID()); + Task task = Task::TASK_ALLOCATE; unsigned req_num = 0; WMError ret = WMError::UNKNOWN; diff --git a/src/window_manager.hpp b/src/window_manager.hpp index 3ad9cc7..aa1b4cc 100644 --- a/src/window_manager.hpp +++ b/src/window_manager.hpp @@ -212,6 +212,7 @@ class WindowManager result api_request_surface(char const *appid, char const *role); char const *api_request_surface(char const *appid, char const *role, char const *ivi_id); + bool api_set_role(char const *appid, char const *role, unsigned pid); 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_enddraw(char const *appid, char const *role); diff --git a/src/wm_client.cpp b/src/wm_client.cpp index 79922fa..47d0c2d 100644 --- a/src/wm_client.cpp +++ b/src/wm_client.cpp @@ -49,7 +49,7 @@ WMClient::WMClient(const string &appid, unsigned layer, unsigned surface, const #else afb_event ev = afb_daemon_make_event(x.c_str()); #endif - event2list[x] = ev; + evname2afb_event[x] = ev; } } @@ -57,7 +57,7 @@ WMClient::WMClient(const string &appid, const string &role) : id(appid), layer(0), role2surface(0), - event2list(0) + evname2afb_event(0) { role2surface[role] = INVALID_SURFACE_ID; for (auto x : kWMEvents) @@ -67,14 +67,10 @@ WMClient::WMClient(const string &appid, const string &role) #else afb_event ev = afb_daemon_make_event(x.c_str()); #endif - event2list[x] = ev; + evname2afb_event[x] = ev; } } -WMClient::~WMClient() -{ -} - string WMClient::appID() const { return this->id; @@ -196,7 +192,7 @@ bool WMClient::subscribe(afb_req req, const string &evname) HMI_DEBUG("wm", "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("wm", "Failed to subscribe %s", evname.c_str()); @@ -207,7 +203,7 @@ bool WMClient::subscribe(afb_req req, const string &evname) void WMClient::emitError(WM_CLIENT_ERROR_EVENT ev) { - if (!afb_event_is_valid(this->event2list[kKeyError])){ + if (!afb_event_is_valid(this->evname2afb_event[kKeyError])){ HMI_ERROR("wm", "event err is not valid"); return; } @@ -216,7 +212,7 @@ void WMClient::emitError(WM_CLIENT_ERROR_EVENT ev) json_object_object_add(j, kKeyErrorDesc, json_object_new_string(kErrorDescription[ev].c_str())); HMI_DEBUG("wm", "error: %d, description:%s", ev, kErrorDescription[ev].c_str()); - int ret = afb_event_push(this->event2list[kKeyError], j); + int ret = afb_event_push(this->evname2afb_event[kKeyError], j); if (ret != 0) { HMI_DEBUG("wm", "afb_event_push failed: %m"); diff --git a/src/wm_client.hpp b/src/wm_client.hpp index 0268807..0b5abe1 100644 --- a/src/wm_client.hpp +++ b/src/wm_client.hpp @@ -42,7 +42,7 @@ 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() = default; std::string appID() const; unsigned surfaceID(const std::string &role) const; @@ -50,6 +50,7 @@ class WMClient const std::string& getWMLayerName(); unsigned surfaceID() const; std::vector renderOrder() const; + std::string role(unsigned surface) const; const std::vector &roles() const; void setRole(const std::string& role); void registerLayer(unsigned layer); @@ -73,11 +74,12 @@ class WMClient std::vector role_list; std::vector surface_render_order; std::unordered_map service2surfaces; + std::unordered_map role2surface; #if GTEST_ENABLED // This is for unit test. afb_make_event occurs sig11 if call not in afb-binding - std::unordered_map event2list; + std::unordered_map evname2afb_event; #else - std::unordered_map event2list; + std::unordered_map evname2afb_event; #endif }; } // namespace wm -- cgit 1.2.3-korg