Add new class
[apps/agl-service-windowmanager-2017.git] / src / window_manager.cpp
index 5b86af8..62bbbcb 100644 (file)
@@ -185,12 +185,12 @@ int WindowManager::init()
 
             // This protocol needs the output, so lets just add our mapping here...
             this->controller->add_proxy_to_id_mapping(
-                this->outputs.back()->proxy.get(),
+                this->outputs.front()->proxy.get(),
                 wl_proxy_get_id(reinterpret_cast<struct wl_proxy *>(
-                    this->outputs.back()->proxy.get())));
+                    this->outputs.front()->proxy.get())));
 
             // Create screen
-            this->controller->create_screen(this->outputs.back()->proxy.get());
+            this->controller->create_screen(this->outputs.front()->proxy.get());
 
             // Set display to controller
             this->controller->display = this->display;
@@ -238,7 +238,7 @@ result<int> WindowManager::api_request_surface(char const *appid, char const *dr
         HMI_DEBUG("wm", "%s is not registered in layers.json, then fallback as normal app", role);
         if (!lid)
         {
-            return Err<int>("Drawing name does not match any role, Fallback is disabled");
+            return Err<int>("Drawing name does not match any role, fallback is disabled");
         }
     }
 
@@ -292,7 +292,7 @@ char const *WindowManager::api_request_surface(char const *appid, char const *dr
         HMI_DEBUG("wm", "%s is not registered in layers.json, then fallback as normal app", role);
         if (!lid)
         {
-            return "Drawing name does not match any role, Fallback is disabled";
+            return "Drawing name does not match any role, fallback is disabled";
         }
     }
 
@@ -323,6 +323,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)
 {
@@ -335,6 +426,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();
+    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;
@@ -576,6 +684,8 @@ void WindowManager::send_event(char const *evname, char const *label, char const
  */
 void WindowManager::surface_created(uint32_t 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)
     {
@@ -596,6 +706,45 @@ void WindowManager::surface_removed(uint32_t surface_id)
     g_app_list.removeSurface(surface_id);
 }
 
+void WindowManager::surface_properties(unsigned surface_id, unsigned pid)
+{
+    HMI_DEBUG("wm", "get surface properties");
+
+    // search pid from surfaceID
+    json_object *response;
+    afb_service_call_sync("afm-main", "runners", nullptr, &response);
+
+    // retrieve appid from pid from application manager
+    std::string appid = "";
+    if(response == nullptr)
+    {
+        HMI_ERROR("wm", "No runners");
+    }
+    else
+    {
+        // check appid then add it to the client
+        HMI_INFO("wm", "Runners:%s", json_object_get_string(response));
+        int size = json_object_array_length(response);
+        for(int i = 0; i < size; i++)
+        {
+            json_object *j = json_object_array_get_idx(response, i);
+            const char* id = jh::getStringFromJson(j, "id");
+            int runid      = jh::getIntFromJson(j, "runid");
+            if(id && (runid > 0))
+            {
+                if(runid == pid)
+                {
+                    appid = id;
+                    break;
+                }
+            }
+        }
+    }
+    json_object_put(response);
+
+    g_app_list.addFloatingSurface(appid, surface_id, pid);
+}
+
 void WindowManager::removeClient(const std::string &appid)
 {
     HMI_DEBUG("wm", "Remove clinet %s from list", appid.c_str());
@@ -1088,7 +1237,7 @@ WMError WindowManager::startTransition(unsigned req_num)
             if (g_app_list.contains(x.appid))
             {
                 auto client = g_app_list.lookUpClient(x.appid);
-                this->deactivate(client->surfaceID(x.role));
+                this->deactivate(client->surfaceID());
             }
         }
         ret = NO_LAYOUT_CHANGE;
@@ -1100,6 +1249,15 @@ WMError WindowManager::setInvisibleTask(const std::string &role, bool split)
 {
     unsigned req_num = g_app_list.currentRequestNumber();
     HMI_SEQ_DEBUG(req_num, "set current visible app to invisible task");
+    bool found = false;
+    auto trigger = g_app_list.getRequest(req_num, &found);
+    // I don't check found == true here because this is checked in caller.
+    if(trigger.role == "homescreen")
+    {
+        HMI_SEQ_INFO(req_num, "In case of 'homescreen' visible, don't change app to invisible");
+        return WMError::SUCCESS;
+    }
+
     // This task is copied from original actiavete surface
     const char *drawing_name = this->rolenew2old[role].c_str();
     auto const &surface_id = this->lookup_id(role.c_str());
@@ -1111,7 +1269,6 @@ WMError WindowManager::setInvisibleTask(const std::string &role, bool split)
     int surface;
     TaskVisible task_visible = TaskVisible::INVISIBLE;
     bool end_draw_finished = true;
-    bool found = false;
 
     for (auto const &l : this->layers.mapping)
     {
@@ -1278,6 +1435,7 @@ WMError WindowManager::doEndDraw(unsigned req_num)
         HMI_SEQ_DEBUG(req_num, "visible %s", act.role.c_str());
         //this->lm_enddraw(act.role.c_str());
     }
+    this->layout_commit();
 
     // Change current state
     this->changeCurrentState(req_num);
@@ -1307,7 +1465,7 @@ WMError WindowManager::layoutChange(const WMAction &action)
         return WMError::SUCCESS;
     }
     auto client = g_app_list.lookUpClient(action.appid);
-    unsigned surface = client->surfaceID(action.role);
+    unsigned surface = client->surfaceID();
     if (surface == 0)
     {
         HMI_SEQ_ERROR(g_app_list.currentRequestNumber(),
@@ -1326,7 +1484,7 @@ WMError WindowManager::visibilityChange(const WMAction &action)
         return WMError::NOT_REGISTERED;
     }
     auto client = g_app_list.lookUpClient(action.appid);
-    unsigned surface = client->surfaceID(action.role);
+    unsigned surface = client->surfaceID();
     if(surface == 0)
     {
         HMI_SEQ_ERROR(g_app_list.currentRequestNumber(),
@@ -1373,7 +1531,7 @@ WMError WindowManager::changeCurrentState(unsigned req_num)
             return WMError::NOT_REGISTERED;
         }
         auto client = g_app_list.lookUpClient(action.appid);
-        auto pCurState = *this->layers.get_layout_state((int)client->surfaceID(action.role));
+        auto pCurState = *this->layers.get_layout_state((int)client->surfaceID());
         if(pCurState == nullptr)
         {
             HMI_SEQ_ERROR(req_num, "Counldn't find current status");
@@ -1387,7 +1545,7 @@ WMError WindowManager::changeCurrentState(unsigned req_num)
     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));
+        auto pLayerCurState = *this->layers.get_layout_state((int)client->surfaceID());
         if (pLayerCurState == nullptr)
         {
             HMI_SEQ_ERROR(req_num, "Counldn't find current status");
@@ -1397,7 +1555,7 @@ WMError WindowManager::changeCurrentState(unsigned req_num)
 
         if (action.visible != TaskVisible::INVISIBLE)
         {
-            surface = (int)client->surfaceID(action.role);
+            surface = (int)client->surfaceID();
             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
@@ -1447,7 +1605,6 @@ void WindowManager::emitScreenUpdated(unsigned req_num)
     {
         HMI_DEBUG("wm", "afb_event_push failed: %m");
     }
-    json_object_put(jarray);
 }
 
 void WindowManager::setTimer()
@@ -1758,12 +1915,12 @@ const char* WindowManager::kDefaultOldRoleDb = "{ \
  */
 void controller_hooks::surface_created(uint32_t surface_id)
 {
-    this->app->surface_created(surface_id);
+    this->wmgr->surface_created(surface_id);
 }
 
 void controller_hooks::surface_removed(uint32_t surface_id)
 {
-    this->app->surface_removed(surface_id);
+    this->wmgr->surface_removed(surface_id);
 }
 
 void controller_hooks::surface_visibility(uint32_t /*surface_id*/,
@@ -1775,4 +1932,9 @@ void controller_hooks::surface_destination_rectangle(uint32_t /*surface_id*/,
                                                      uint32_t /*w*/,
                                                      uint32_t /*h*/) {}
 
+void controller_hooks::surface_properties(uint32_t surface_id, uint32_t pid)
+{
+    this->wmgr->surface_properties(surface_id, pid);
+}
+
 } // namespace wm