From 00ee9b48ed5d69a7b4c752d648914e1afd4f41df Mon Sep 17 00:00:00 2001 From: Kazumasa Mitsunari Date: Sun, 24 Jun 2018 17:11:24 +0900 Subject: Clean: Sort functions Change-Id: I8d6b88fe75125877c8358f2062aa748885c138cf Signed-off-by: Kazumasa Mitsunari --- src/window_manager.cpp | 1450 ++++++++++++++++++++++++------------------------ src/window_manager.hpp | 15 +- 2 files changed, 731 insertions(+), 734 deletions(-) diff --git a/src/window_manager.cpp b/src/window_manager.cpp index 50e2f85..1582168 100644 --- a/src/window_manager.cpp +++ b/src/window_manager.cpp @@ -100,40 +100,6 @@ static int processTimerHandler(sd_event_source *s, uint64_t usec, void *userdata } // namespace -void WindowManager::timerHandler() -{ - unsigned req_num = g_app_list.currentRequestNumber(); - HMI_SEQ_DEBUG(req_num, "Timer expired remove Request"); - g_app_list.reqDump(); - g_app_list.removeRequest(req_num); - this->processNextRequest(); -} - -void WindowManager::removeClient(const std::string &appid) -{ - HMI_DEBUG("wm", "Remove clinet %s from list", appid.c_str()); - g_app_list.removeClient(appid); -} - -void WindowManager::exceptionProcessForTransition() -{ - unsigned req_num = g_app_list.currentRequestNumber(); - HMI_SEQ_NOTICE(req_num, "Process exception handling for request. Remove current request %d", req_num); - g_app_list.removeRequest(req_num); - HMI_SEQ_NOTICE(g_app_list.currentRequestNumber(), "Process next request if exists"); - this->processNextRequest(); -} - -bool WindowManager::subscribeEventForApp(const std::string &appid, afb_req req, const std::string &evname) -{ - if(!g_app_list.contains(appid)){ - HMI_DEBUG("wm", "Client %s is not registered", appid.c_str()); - return false; - } - auto client = g_app_list.lookUpClient(appid); - return client->subscribe(req, evname); -} - /** * WindowManager Impl */ @@ -243,174 +209,679 @@ int WindowManager::dispatch_pending_events() return -1; } -bool WindowManager::pop_pending_events() -{ - bool x{true}; - return this->pending_events.compare_exchange_strong( - x, false, std::memory_order_consume); -} - void WindowManager::set_pending_events() { this->pending_events.store(true, std::memory_order_release); } -optional WindowManager::lookup_id(char const *name) -{ - return this->id_alloc.lookup(std::string(name)); -} -optional WindowManager::lookup_name(int id) -{ - return this->id_alloc.lookup(id); -} - -/** - * init_layers() - */ -int WindowManager::init_layers() +result WindowManager::api_request_surface(char const *appid, char const *drawing_name) { - if (!this->controller) + auto lid = this->layers.get_layer_id(std::string(drawing_name)); + if (!lid) { - HMI_ERROR("wm", "ivi_controller global not available"); - return -1; + /** + * 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", drawing_name); + if (!lid) + { + return Err("Drawing name does not match any role, Fallback is disabled"); + } } - if (this->outputs.empty()) + auto rname = this->lookup_id(drawing_name); + if (!rname) { - HMI_ERROR("wm", "no output was set up!"); - return -1; + // name does not exist yet, allocate surface id... + auto id = int(this->id_alloc.generate_id(drawing_name)); + this->layers.add_surface(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("wm", "Set main_surface id to %u", id); + } + + // add client into the db + std::string appid_str(appid); + std::string role(drawing_name); + //g_app_list.addClient(appid_str, role); + g_app_list.addClient(appid_str, *lid, id, role); + + return Ok(id); } - auto &c = this->controller; + // Check currently registered drawing names if it is already there. + return Err("Surface already present"); +} - auto &o = this->outputs.front(); - auto &s = c->screens.begin()->second; - auto &layers = c->layers; +char const *WindowManager::api_request_surface(char const *appid, char const *drawing_name, + char const *ivi_id) +{ + ST(); - // 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)}; + auto lid = this->layers.get_layer_id(std::string(drawing_name)); + unsigned sid = std::stol(ivi_id); - // Clear scene - layers.clear(); + 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", drawing_name); + if (!lid) + { + return "Drawing name does not match any role, Fallback is disabled"; + } + } - // Clear screen - s->clear(); + auto rname = this->lookup_id(drawing_name); - // Quick and dirty setup of layers - for (auto const &i : this->layers.mapping) + if (rname) { - c->layer_create(i.second.layer_id, o->width, o->height); - auto &l = layers[i.second.layer_id]; - l->set_destination_rectangle(0, 0, o->width, o->height); - l->set_visibility(1); - HMI_DEBUG("wm", "Setting up layer %s (%d) for surface role match \"%s\"", - i.second.name.c_str(), i.second.layer_id, i.second.role.c_str()); + return "Surface already present"; } - // Add layers to screen - s->set_render_order(this->layers.layers); + // register pair drawing_name and ivi_id + this->id_alloc.register_name_id(drawing_name, sid); + this->layers.add_surface(sid, *lid); - this->layout_commit(); + // this surface is already created + HMI_DEBUG("wm", "surface_id is %u, layer_id is %u", sid, *lid); - this->layers.setupArea(o->width, o->height); + this->controller->layers[*lid]->add_surface(sid); + this->layout_commit(); - return 0; + return nullptr; } -void WindowManager::surface_set_layout(int surface_id, const std::string& area) +void WindowManager::api_activate_surface(char const *appid, char const *drawing_name, + char const *drawing_area, const reply_func &reply) { - if (!this->controller->surface_exists(surface_id)) + ST(); + + std::string id = appid; + std::string role = drawing_name; + std::string area = drawing_area; + Task task = Task::TASK_ALLOCATE; + unsigned req_num = 0; + WMError ret = WMError::UNKNOWN; + + ret = this->setRequest(id, role, area, task, &req_num); + + if(ret != WMError::SUCCESS) { - HMI_ERROR("wm", "Surface %d does not exist", surface_id); + HMI_ERROR("wm", errorDescription(ret)); + reply("Failed to set request"); return; } - auto o_layer_id = this->layers.get_layer_id(surface_id); - - if (!o_layer_id) + reply(nullptr); + if (req_num != g_app_list.currentRequestNumber()) { - HMI_ERROR("wm", "Surface %d is not associated with any layer!", surface_id); + // Add request, then invoked after the previous task is finished + HMI_SEQ_DEBUG(req_num, "request is accepted"); return; } - uint32_t layer_id = *o_layer_id; + /* + * Do allocate tasks + */ + ret = this->doTransition(req_num); - 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]; + if (ret != WMError::SUCCESS) + { + //this->emit_error() + HMI_SEQ_ERROR(req_num, errorDescription(ret)); + g_app_list.removeRequest(req_num); + this->processNextRequest(); + } +} - int x = rect.x; - int y = rect.y; - int w = rect.w; - int h = rect.h; +void WindowManager::api_deactivate_surface(char const *appid, char const *drawing_name, + const reply_func &reply) +{ + ST(); - // less-than-0 values refer to MAX + 1 - $VALUE - // e.g. MAX is either screen width or height - if (w < 0) + /* + * Check Phase + */ + std::string id = appid; + std::string role = drawing_name; + std::string area = ""; //drawing_area; + Task task = Task::TASK_RELEASE; + unsigned req_num = 0; + WMError ret = WMError::UNKNOWN; + + ret = this->setRequest(id, role, area, task, &req_num); + + if (ret != WMError::SUCCESS) { - w = this->controller->output_size.w + 1 + w; + HMI_ERROR("wm", errorDescription(ret)); + reply("Failed to set request"); + return; } - if (h < 0) + + reply(nullptr); + if (req_num != g_app_list.currentRequestNumber()) { - h = this->controller->output_size.h + 1 + h; + // Add request, then invoked after the previous task is finished + HMI_SEQ_DEBUG(req_num, "request is accepted"); + return; } - HMI_DEBUG("wm", "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; + /* + * Do allocate tasks + */ + ret = this->doTransition(req_num); - HMI_DEBUG("wm", "Surface %u now on layer %u with rect { %d, %d, %d, %d }", - surface_id, layer_id, x, y, w, h); + if (ret != WMError::SUCCESS) + { + //this->emit_error() + HMI_SEQ_ERROR(req_num, errorDescription(ret)); + g_app_list.removeRequest(req_num); + this->processNextRequest(); + } } -void WindowManager::layout_commit() +void WindowManager::api_enddraw(char const *appid, char const *drawing_name) +{ + std::string id = appid; + std::string role = drawing_name; + unsigned current_req = g_app_list.currentRequestNumber(); + bool result = g_app_list.setEndDrawFinished(current_req, id, role); + + if (!result) + { + HMI_ERROR("wm", "%s is not in transition state", id.c_str()); + return; + } + + if (g_app_list.endDrawFullfilled(current_req)) + { + // do task for endDraw + this->stopTimer(); + WMError ret = this->doEndDraw(current_req); + + if(ret != WMError::SUCCESS) + { + //this->emit_error(); + } + HMI_SEQ_INFO(current_req, "Finish request status: %s", errorDescription(ret)); + + g_app_list.removeRequest(current_req); + + this->processNextRequest(); + } + else + { + HMI_SEQ_INFO(current_req, "Wait other App call endDraw"); + return; + } +} + +result WindowManager::api_get_display_info() +{ + // Check controller + if (!this->controller) + { + return Err("ivi_controller global not available"); + } + + // Set display info + compositor::size o_size = this->controller->output_size; + compositor::size p_size = this->controller->physical_size; + + 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)); + + return Ok(object); +} + +result WindowManager::api_get_area_info(char const *drawing_name) +{ + HMI_DEBUG("wm", "called"); + + // Check drawing name, surface/layer id + auto const &surface_id = this->lookup_id(drawing_name); + if (!surface_id) + { + return Err("Surface does not exist"); + } + + if (!this->controller->surface_exists(*surface_id)) + { + return Err("Surface does not exist in controller!"); + } + + auto layer_id = this->layers.get_layer_id(*surface_id); + if (!layer_id) + { + return Err("Surface is not on any layer!"); + } + + auto o_state = *this->layers.get_layout_state(*surface_id); + if (o_state == nullptr) + { + return Err("Could not find layer for surface"); + } + + struct LayoutState &state = *o_state; + if ((state.main != *surface_id) && (state.sub != *surface_id)) + { + return Err("Surface is inactive"); + } + + // Set area rectangle + compositor::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)); + json_object_object_add(object, kKeyWidth, json_object_new_int(area_info.w)); + json_object_object_add(object, kKeyHeight, json_object_new_int(area_info.h)); + + return Ok(object); +} + +void WindowManager::api_ping() { this->dispatch_pending_events(); } + +void WindowManager::send_event(char const *evname, char const *label) +{ + HMI_DEBUG("wm", "%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("wm", "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("wm", "%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("wm", "afb_event_push failed: %m"); + } +} + +/** + * proxied events + */ +void WindowManager::surface_created(uint32_t surface_id) +{ + auto layer_id = this->layers.get_layer_id(surface_id); + if (!layer_id) + { + HMI_DEBUG("wm", "Newly created surfce %d is not associated with any layer!", + surface_id); + return; + } + + HMI_DEBUG("wm", "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) +{ + HMI_DEBUG("wm", "surface_id is %u", surface_id); + + g_app_list.removeSurface(surface_id); +} + +void WindowManager::removeClient(const std::string &appid) +{ + HMI_DEBUG("wm", "Remove clinet %s from list", appid.c_str()); + g_app_list.removeClient(appid); +} + +void WindowManager::exceptionProcessForTransition() +{ + unsigned req_num = g_app_list.currentRequestNumber(); + HMI_SEQ_NOTICE(req_num, "Process exception handling for request. Remove current request %d", req_num); + g_app_list.removeRequest(req_num); + HMI_SEQ_NOTICE(g_app_list.currentRequestNumber(), "Process next request if exists"); + this->processNextRequest(); +} + +bool WindowManager::subscribeEventForApp(const std::string &appid, afb_req req, const std::string &evname) +{ + if(!g_app_list.contains(appid)){ + HMI_DEBUG("wm", "Client %s is not registered", appid.c_str()); + return false; + } + auto client = g_app_list.lookUpClient(appid); + return client->subscribe(req, evname); +} + +void WindowManager::timerHandler() +{ + unsigned req_num = g_app_list.currentRequestNumber(); + HMI_SEQ_DEBUG(req_num, "Timer expired remove Request"); + g_app_list.reqDump(); + g_app_list.removeRequest(req_num); + 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 WindowManager::lookup_id(char const *name) +{ + return this->id_alloc.lookup(std::string(name)); +} +optional WindowManager::lookup_name(int id) +{ + return this->id_alloc.lookup(id); +} + +/** + * init_layers() + */ +int WindowManager::init_layers() +{ + if (!this->controller) + { + HMI_ERROR("wm", "ivi_controller global not available"); + return -1; + } + + if (this->outputs.empty()) + { + HMI_ERROR("wm", "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)}; + + // 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, o->width, o->height); + auto &l = layers[i.second.layer_id]; + l->set_destination_rectangle(0, 0, o->width, o->height); + l->set_visibility(1); + HMI_DEBUG("wm", "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(); + + this->layers.setupArea(o->width, o->height); + + return 0; +} + +void WindowManager::surface_set_layout(int surface_id, const std::string& area) +{ + if (!this->controller->surface_exists(surface_id)) + { + HMI_ERROR("wm", "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("wm", "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; + + // less-than-0 values refer to MAX + 1 - $VALUE + // e.g. MAX is either screen width or height + if (w < 0) + { + w = this->controller->output_size.w + 1 + w; + } + if (h < 0) + { + h = this->controller->output_size.h + 1 + h; + } + + HMI_DEBUG("wm", "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("wm", "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::setTimer() +void WindowManager::emit_activated(char const *label) { - HMI_SEQ_DEBUG(g_app_list.currentRequestNumber(), "Timer set activate"); - if (g_timer_ev_src == nullptr) + 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->lm_get_area_info(area, &x, &y, &w, &h); + 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, "MediaPlayer")) || + (0 == strcmp(label, "Music")) || + (0 == strcmp(label, "Navigation"))) + { + 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("wm", "Remove %s(%d) from BG layer", label, id); + this->controller->layers[999]->remove_surface(id); + + // Add to FG layer (1001) + HMI_DEBUG("wm", "Add %s(%d) to FG layer", label, id); + this->controller->layers[1001]->add_surface(id); + + for (int j : this->surface_bg) + { + HMI_DEBUG("wm", "Stored id:%d", j); + } + break; + } + } + } + // <<< FOR CES DEMO + this->layout_commit(); + + this->emit_visible(label); + this->emit_activated(label); + } +} + +void WindowManager::deactivate(int id) +{ + auto ip = this->controller->sprops.find(id); + if (ip != this->controller->sprops.end()) { - // firsttime set into sd_event - int ret = sd_event_add_time(afb_daemon_get_event_loop(), &g_timer_ev_src, - CLOCK_REALTIME, time(NULL) * (1000000UL) + kTimeOut, 1, processTimerHandler, this); - if (ret < 0) + char const *label = + this->lookup_name(id).value_or("unknown-name").c_str(); + + // FOR CES DEMO >>> + if ((0 == strcmp(label, "Radio")) || (0 == strcmp(label, "MediaPlayer")) || (0 == strcmp(label, "Music")) || (0 == strcmp(label, "Navigation"))) { - HMI_ERROR("wm", "Could't set timer"); + + // Store id + this->surface_bg.push_back(id); + + // Remove from FG layer (1001) + HMI_DEBUG("wm", "Remove %s(%d) from FG layer", label, id); + this->controller->layers[1001]->remove_surface(id); + + // Add to BG layer (999) + HMI_DEBUG("wm", "Add %s(%d) to BG layer", label, id); + this->controller->layers[999]->add_surface(id); + + for (int j : surface_bg) + { + HMI_DEBUG("wm", "Stored id:%d", j); + } } - } - else - { - // update timer limitation after second time - sd_event_source_set_time(g_timer_ev_src, time(NULL) * (1000000UL) + kTimeOut); - sd_event_source_set_enabled(g_timer_ev_src, SD_EVENT_ONESHOT); + else + { + this->controller->surfaces[id]->set_visibility(0); + } + // <<< FOR CES DEMO + + this->emit_deactivated(label); + this->emit_invisible(label); } } -void WindowManager::stopTimer() +WMError WindowManager::setRequest(const std::string& appid, const std::string &role, const std::string &area, + Task task, unsigned* req_num) { - unsigned req_num = g_app_list.currentRequestNumber(); - HMI_SEQ_DEBUG(req_num, "Timer stop"); - int rc = sd_event_source_set_enabled(g_timer_ev_src, SD_EVENT_OFF); - if (rc < 0) + if (!g_app_list.contains(appid)) { - HMI_SEQ_ERROR(req_num, "Timer stop failed"); + return WMError::NOT_REGISTERED; + } + + auto client = g_app_list.lookUpClient(appid); + + /* + * Queueing Phase + */ + unsigned current = g_app_list.currentRequestNumber(); + unsigned requested_num = g_app_list.getRequestNumber(appid); + if (requested_num != 0) + { + HMI_SEQ_INFO(requested_num, + "%s %s %s request is already queued", appid.c_str(), role.c_str(), area.c_str()); + return REQ_REJECTED; } + + WMRequest req = WMRequest(appid, role, area, task); + unsigned new_req = g_app_list.addRequest(req); + *req_num = new_req; + g_app_list.reqDump(); + + HMI_SEQ_DEBUG(current, "%s start sequence with %s, %s", appid.c_str(), role.c_str(), area.c_str()); + + return WMError::SUCCESS; } WMError WindowManager::doTransition(unsigned req_num) @@ -693,190 +1164,33 @@ WMError WindowManager::setInvisibleTask(const std::string &role, bool split) deact_main.end_draw_finished = end_draw_finished; HMI_SEQ_DEBUG(req_num, "sub surface doesn't exist"); g_app_list.setAction(req_num, deact_main); - } - if (state.sub != -1) - { - if (state.sub != *surface_id) - { - //this->deactivate(state.sub); - WMAction deact_sub; - deact_sub.role = std::move(*this->id_alloc.lookup(state.sub)); - ; - deact_sub.area = add_area; - deact_sub.appid = g_app_list.getAppID(state.sub, deact_sub.role, &found); - if (!found) - { - HMI_SEQ_DEBUG(req_num, "sub surface ddoesn't exist"); - return WMError::NOT_REGISTERED; - } - deact_sub.visible = task_visible; - deact_sub.end_draw_finished = end_draw_finished; - HMI_SEQ_DEBUG(req_num, "sub surface doesn't exist"); - g_app_list.setAction(req_num, deact_sub); - } - } - //state = LayoutState{*surface_id}; - } - } - } - return WMError::SUCCESS; -} - -const char *WindowManager::check_surface_exist(const char *drawing_name) -{ - auto const &surface_id = this->lookup_id(drawing_name); - if (!surface_id) - { - //reply("Surface does not exist"); - return "Surface does not exist"; - } - - if (!this->controller->surface_exists(*surface_id)) - { - //reply("Surface does not exist in controller!"); - return "Surface does not exist in controller!"; - } - - auto layer_id = this->layers.get_layer_id(*surface_id); - - if (!layer_id) - { - //reply("Surface is not on any layer!"); - return "Surface is not on any layer!"; - } - - auto o_state = *this->layers.get_layout_state(*surface_id); - - if (o_state == nullptr) - { - //reply("Could not find layer for surface"); - return "Could not find layer for surface"; - } - - HMI_DEBUG("wm", "surface %d is detected", *surface_id); - return nullptr; - //reply(nullptr); -} - -WMError WindowManager::setRequest(const std::string& appid, const std::string &role, const std::string &area, - Task task, unsigned* req_num) -{ - if (!g_app_list.contains(appid)) - { - return WMError::NOT_REGISTERED; - } - - auto client = g_app_list.lookUpClient(appid); - - /* - * Queueing Phase - */ - unsigned current = g_app_list.currentRequestNumber(); - unsigned requested_num = g_app_list.getRequestNumber(appid); - if (requested_num != 0) - { - HMI_SEQ_INFO(requested_num, - "%s %s %s request is already queued", appid.c_str(), role.c_str(), area.c_str()); - return REQ_REJECTED; - } - - WMRequest req = WMRequest(appid, role, area, task); - unsigned new_req = g_app_list.addRequest(req); - *req_num = new_req; - g_app_list.reqDump(); - - HMI_SEQ_DEBUG(current, "%s start sequence with %s, %s", appid.c_str(), role.c_str(), area.c_str()); - - return WMError::SUCCESS; -} - -void WindowManager::api_activate_surface(char const *appid, char const *drawing_name, - char const *drawing_area, const reply_func &reply) -{ - ST(); - - std::string id = appid; - std::string role = drawing_name; - std::string area = drawing_area; - Task task = Task::TASK_ALLOCATE; - unsigned req_num = 0; - WMError ret = WMError::UNKNOWN; - - ret = this->setRequest(id, role, area, task, &req_num); - - if(ret != WMError::SUCCESS) - { - HMI_ERROR("wm", errorDescription(ret)); - reply("Failed to set request"); - return; - } - - reply(nullptr); - if (req_num != g_app_list.currentRequestNumber()) - { - // Add request, then invoked after the previous task is finished - HMI_SEQ_DEBUG(req_num, "request is accepted"); - return; - } - - /* - * Do allocate tasks - */ - ret = this->doTransition(req_num); - - if (ret != WMError::SUCCESS) - { - //this->emit_error() - HMI_SEQ_ERROR(req_num, errorDescription(ret)); - g_app_list.removeRequest(req_num); - this->processNextRequest(); - } -} - -void WindowManager::api_deactivate_surface(char const *appid, char const *drawing_name, - const reply_func &reply) -{ - ST(); - - /* - * Check Phase - */ - std::string id = appid; - std::string role = drawing_name; - std::string area = ""; //drawing_area; - Task task = Task::TASK_RELEASE; - unsigned req_num = 0; - WMError ret = WMError::UNKNOWN; - - ret = this->setRequest(id, role, area, task, &req_num); - - if (ret != WMError::SUCCESS) - { - HMI_ERROR("wm", errorDescription(ret)); - reply("Failed to set request"); - return; - } - - reply(nullptr); - if (req_num != g_app_list.currentRequestNumber()) - { - // Add request, then invoked after the previous task is finished - HMI_SEQ_DEBUG(req_num, "request is accepted"); - return; - } - - /* - * Do allocate tasks - */ - ret = this->doTransition(req_num); - - if (ret != WMError::SUCCESS) - { - //this->emit_error() - HMI_SEQ_ERROR(req_num, errorDescription(ret)); - g_app_list.removeRequest(req_num); - this->processNextRequest(); + } + if (state.sub != -1) + { + if (state.sub != *surface_id) + { + //this->deactivate(state.sub); + WMAction deact_sub; + deact_sub.role = std::move(*this->id_alloc.lookup(state.sub)); + ; + deact_sub.area = add_area; + deact_sub.appid = g_app_list.getAppID(state.sub, deact_sub.role, &found); + if (!found) + { + HMI_SEQ_DEBUG(req_num, "sub surface ddoesn't exist"); + return WMError::NOT_REGISTERED; + } + deact_sub.visible = task_visible; + deact_sub.end_draw_finished = end_draw_finished; + HMI_SEQ_DEBUG(req_num, "sub surface doesn't exist"); + g_app_list.setAction(req_num, deact_sub); + } + } + //state = LayoutState{*surface_id}; + } + } } + return WMError::SUCCESS; } WMError WindowManager::doEndDraw(unsigned req_num) @@ -934,13 +1248,6 @@ WMError WindowManager::doEndDraw(unsigned req_num) return ret; } -WMError WindowManager::setSurfaceSize(unsigned surface, const std::string &area) -{ - this->surface_set_layout(surface, area); - - return WMError::SUCCESS; -} - WMError WindowManager::layoutChange(const WMAction &action) { if (action.visible == TaskVisible::INVISIBLE) @@ -987,6 +1294,13 @@ WMError WindowManager::visibilityChange(const WMAction &action) return WMError::SUCCESS; } +WMError WindowManager::setSurfaceSize(unsigned surface, const std::string &area) +{ + this->surface_set_layout(surface, area); + + return WMError::SUCCESS; +} + WMError WindowManager::changeCurrentState(unsigned req_num) { HMI_SEQ_DEBUG(req_num, "Change current layout state"); @@ -1015,442 +1329,132 @@ WMError WindowManager::changeCurrentState(unsigned req_num) continue; } pCurState->main = reset_state.main; - pCurState->sub = reset_state.sub; - } - - HMI_SEQ_DEBUG(req_num, "Change state"); - for (const auto &action : actions) - { - auto client = g_app_list.lookUpClient(action.appid); - auto pLayerCurState = *this->layers.get_layout_state((int)client->surfaceID(action.role)); - if (pLayerCurState == nullptr) - { - HMI_SEQ_ERROR(req_num, "Counldn't find current status"); - continue; - } - int surface = -1; - - if (action.visible != TaskVisible::INVISIBLE) - { - surface = (int)client->surfaceID(action.role); - HMI_SEQ_INFO(req_num, "Change %s surface : %d, state visible area : %s", - action.role.c_str(), surface, action.area.c_str()); - // visible == true -> layout changes - if(action.area == "normal.full" || action.area == "split.main") - { - pLayerCurState->main = surface; - } - else if (action.area == "split.sub") - { - pLayerCurState->sub = surface; - } - else - { - // normalfull - pLayerCurState->main = surface; - } - } - } - - return WMError::SUCCESS; -} - -void WindowManager::api_enddraw(char const *appid, char const *drawing_name) -{ - std::string id = appid; - std::string role = drawing_name; - unsigned current_req = g_app_list.currentRequestNumber(); - bool result = g_app_list.setEndDrawFinished(current_req, id, role); - - if (!result) - { - HMI_ERROR("wm", "%s is not in transition state", id.c_str()); - return; - } - - if (g_app_list.endDrawFullfilled(current_req)) - { - // do task for endDraw - this->stopTimer(); - WMError ret = this->doEndDraw(current_req); - - if(ret != WMError::SUCCESS) - { - //this->emit_error(); - } - HMI_SEQ_INFO(current_req, "Finish request status: %s", errorDescription(ret)); - - g_app_list.removeRequest(current_req); - - this->processNextRequest(); - } - else - { - HMI_SEQ_INFO(current_req, "Wait other App call endDraw"); - return; - } -} - -void WindowManager::processNextRequest() -{ - g_app_list.next(); - g_app_list.reqDump(); - unsigned req_num = g_app_list.currentRequestNumber(); - if (g_app_list.haveRequest()) - { - HMI_SEQ_DEBUG(req_num, "Process next request"); - WMError rc = doTransition(req_num); - if (rc != WMError::SUCCESS) - { - HMI_SEQ_ERROR(req_num, errorDescription(rc)); - } - } - else - { - HMI_SEQ_DEBUG(req_num, "Nothing Request. Waiting Request"); - } -} - -void WindowManager::api_ping() { this->dispatch_pending_events(); } - -void WindowManager::send_event(char const *evname, char const *label) -{ - HMI_DEBUG("wm", "%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("wm", "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("wm", "%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("wm", "afb_event_push failed: %m"); - } -} - -/** - * proxied events - */ -void WindowManager::surface_created(uint32_t surface_id) -{ - auto layer_id = this->layers.get_layer_id(surface_id); - if (!layer_id) - { - HMI_DEBUG("wm", "Newly created surfce %d is not associated with any layer!", - surface_id); - return; - } - - HMI_DEBUG("wm", "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) -{ - HMI_DEBUG("wm", "surface_id is %u", surface_id); - - g_app_list.removeSurface(surface_id); -} - -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->lm_get_area_info(area, &x, &y, &w, &h); - 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); } - -result WindowManager::api_request_surface(char const *appid, char const *drawing_name) -{ - auto lid = this->layers.get_layer_id(std::string(drawing_name)); - 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", drawing_name); - if (!lid) - { - return Err("Drawing name does not match any role, Fallback is disabled"); - } + pCurState->sub = reset_state.sub; } - auto rname = this->lookup_id(drawing_name); - if (!rname) + HMI_SEQ_DEBUG(req_num, "Change state"); + for (const auto &action : actions) { - // name does not exist yet, allocate surface id... - auto id = int(this->id_alloc.generate_id(drawing_name)); - this->layers.add_surface(id, *lid); - - // set the main_surface[_name] here and now - if (!this->layers.main_surface_name.empty() && - this->layers.main_surface_name == drawing_name) + auto client = g_app_list.lookUpClient(action.appid); + auto pLayerCurState = *this->layers.get_layout_state((int)client->surfaceID(action.role)); + if (pLayerCurState == nullptr) { - this->layers.main_surface = id; - HMI_DEBUG("wm", "Set main_surface id to %u", id); + HMI_SEQ_ERROR(req_num, "Counldn't find current status"); + continue; } + int surface = -1; - // add client into the db - std::string appid_str(appid); - std::string role(drawing_name); - //g_app_list.addClient(appid_str, role); - g_app_list.addClient(appid_str, *lid, id, role); - - return Ok(id); + if (action.visible != TaskVisible::INVISIBLE) + { + surface = (int)client->surfaceID(action.role); + HMI_SEQ_INFO(req_num, "Change %s surface : %d, state visible area : %s", + action.role.c_str(), surface, action.area.c_str()); + // visible == true -> layout changes + if(action.area == "normal.full" || action.area == "split.main") + { + pLayerCurState->main = surface; + } + else if (action.area == "split.sub") + { + pLayerCurState->sub = surface; + } + else + { + // normalfull + pLayerCurState->main = surface; + } + } } - // Check currently registered drawing names if it is already there. - return Err("Surface already present"); + return WMError::SUCCESS; } -char const *WindowManager::api_request_surface(char const *appid, char const *drawing_name, - char const *ivi_id) +void WindowManager::setTimer() { - ST(); - - auto lid = this->layers.get_layer_id(std::string(drawing_name)); - unsigned sid = std::stol(ivi_id); - - if (!lid) + HMI_SEQ_DEBUG(g_app_list.currentRequestNumber(), "Timer set activate"); + if (g_timer_ev_src == nullptr) { - /** - * 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", drawing_name); - if (!lid) + // firsttime set into sd_event + int ret = sd_event_add_time(afb_daemon_get_event_loop(), &g_timer_ev_src, + CLOCK_REALTIME, time(NULL) * (1000000UL) + kTimeOut, 1, processTimerHandler, this); + if (ret < 0) { - return "Drawing name does not match any role, Fallback is disabled"; + HMI_ERROR("wm", "Could't set timer"); } } - - auto rname = this->lookup_id(drawing_name); - - if (rname) + else { - return "Surface already present"; + // update timer limitation after second time + sd_event_source_set_time(g_timer_ev_src, time(NULL) * (1000000UL) + kTimeOut); + sd_event_source_set_enabled(g_timer_ev_src, SD_EVENT_ONESHOT); } - - // register pair drawing_name and ivi_id - this->id_alloc.register_name_id(drawing_name, sid); - this->layers.add_surface(sid, *lid); - - // this surface is already created - HMI_DEBUG("wm", "surface_id is %u, layer_id is %u", sid, *lid); - - this->controller->layers[*lid]->add_surface(sid); - this->layout_commit(); - - return nullptr; } -result WindowManager::api_get_display_info() +void WindowManager::stopTimer() { - // Check controller - if (!this->controller) + unsigned req_num = g_app_list.currentRequestNumber(); + HMI_SEQ_DEBUG(req_num, "Timer stop"); + int rc = sd_event_source_set_enabled(g_timer_ev_src, SD_EVENT_OFF); + if (rc < 0) { - return Err("ivi_controller global not available"); + HMI_SEQ_ERROR(req_num, "Timer stop failed"); } - - // Set display info - compositor::size o_size = this->controller->output_size; - compositor::size p_size = this->controller->physical_size; - - 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)); - - return Ok(object); } -result WindowManager::api_get_area_info(char const *drawing_name) +void WindowManager::processNextRequest() { - HMI_DEBUG("wm", "called"); + g_app_list.next(); + g_app_list.reqDump(); + unsigned req_num = g_app_list.currentRequestNumber(); + if (g_app_list.haveRequest()) + { + HMI_SEQ_DEBUG(req_num, "Process next request"); + WMError rc = doTransition(req_num); + if (rc != WMError::SUCCESS) + { + HMI_SEQ_ERROR(req_num, errorDescription(rc)); + } + } + else + { + HMI_SEQ_DEBUG(req_num, "Nothing Request. Waiting Request"); + } +} - // Check drawing name, surface/layer id +const char *WindowManager::check_surface_exist(const char *drawing_name) +{ auto const &surface_id = this->lookup_id(drawing_name); if (!surface_id) { - return Err("Surface does not exist"); + //reply("Surface does not exist"); + return "Surface does not exist"; } if (!this->controller->surface_exists(*surface_id)) { - return Err("Surface does not exist in controller!"); + //reply("Surface does not exist in controller!"); + return "Surface does not exist in controller!"; } auto layer_id = this->layers.get_layer_id(*surface_id); + if (!layer_id) { - return Err("Surface is not on any layer!"); + //reply("Surface is not on any layer!"); + return "Surface is not on any layer!"; } auto o_state = *this->layers.get_layout_state(*surface_id); - if (o_state == nullptr) - { - return Err("Could not find layer for surface"); - } - - struct LayoutState &state = *o_state; - if ((state.main != *surface_id) && (state.sub != *surface_id)) - { - return Err("Surface is inactive"); - } - - // Set area rectangle - compositor::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)); - json_object_object_add(object, kKeyWidth, json_object_new_int(area_info.w)); - json_object_object_add(object, kKeyHeight, json_object_new_int(area_info.h)); - - return Ok(object); -} -void WindowManager::activate(int id) -{ - auto ip = this->controller->sprops.find(id); - if (ip != this->controller->sprops.end()) + if (o_state == nullptr) { - 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, "MediaPlayer")) || - (0 == strcmp(label, "Music")) || - (0 == strcmp(label, "Navigation"))) - { - 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("wm", "Remove %s(%d) from BG layer", label, id); - this->controller->layers[999]->remove_surface(id); - - // Add to FG layer (1001) - HMI_DEBUG("wm", "Add %s(%d) to FG layer", label, id); - this->controller->layers[1001]->add_surface(id); - - for (int j : this->surface_bg) - { - HMI_DEBUG("wm", "Stored id:%d", j); - } - break; - } - } - } - // <<< FOR CES DEMO - this->layout_commit(); - - this->emit_visible(label); - this->emit_activated(label); + //reply("Could not find layer for surface"); + return "Could not find layer for surface"; } -} - -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, "MediaPlayer")) || (0 == strcmp(label, "Music")) || (0 == strcmp(label, "Navigation"))) - { - - // Store id - this->surface_bg.push_back(id); - - // Remove from FG layer (1001) - HMI_DEBUG("wm", "Remove %s(%d) from FG layer", label, id); - this->controller->layers[1001]->remove_surface(id); - - // Add to BG layer (999) - HMI_DEBUG("wm", "Add %s(%d) to BG layer", label, id); - this->controller->layers[999]->add_surface(id); - - for (int j : surface_bg) - { - HMI_DEBUG("wm", "Stored id:%d", j); - } - } - else - { - this->controller->surfaces[id]->set_visibility(0); - } - // <<< FOR CES DEMO - - this->emit_deactivated(label); - this->emit_invisible(label); - } + HMI_DEBUG("wm", "surface %d is detected", *surface_id); + return nullptr; + //reply(nullptr); } bool WindowManager::can_split(struct LayoutState const &state, int new_id) diff --git a/src/window_manager.hpp b/src/window_manager.hpp index 99a30e0..06967c0 100644 --- a/src/window_manager.hpp +++ b/src/window_manager.hpp @@ -201,9 +201,7 @@ class WindowManager WindowManager &operator=(WindowManager &&) = delete; int init(); - int dispatch_pending_events(); - void set_pending_events(); result api_request_surface(char const *appid, char const *drawing_name); @@ -225,21 +223,17 @@ class WindowManager void exceptionProcessForTransition(); bool subscribeEventForApp(const std::string &appid, afb_req req, const std::string &evname); // Do not use this function - //static int processTimerHandler(sd_event_source *s, uint64_t usec, void *userdata); void timerHandler(); private: + bool pop_pending_events(); optional lookup_id(char const *name); optional lookup_name(int id); - - bool pop_pending_events(); - int init_layers(); - void surface_set_layout(int surface_id, const std::string& area = ""); void layout_commit(); - // TMC WM Events to clients + // 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); @@ -249,6 +243,8 @@ class WindowManager 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); @@ -268,9 +264,6 @@ class WindowManager const char *check_surface_exist(const char *drawing_name); - void activate(int id); - void deactivate(int id); - bool can_split(struct LayoutState const &state, int new_id); private: -- cgit 1.2.3-korg