New API: setRenderOrder
[apps/agl-service-windowmanager.git] / src / main.cpp
index 5990e99..d5adfd5 100644 (file)
 #include <algorithm>
 #include <mutex>
 #include <json.h>
-#include "../include/json.hpp"
+#include <stdlib.h>
+#include <vector>
 #include "window_manager.hpp"
 #include "json_helper.hpp"
-#include "wayland_ivi_wm.hpp"
 
 extern "C"
 {
@@ -42,10 +42,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();
 };
@@ -58,101 +58,18 @@ int afb_instance::init()
     return this->wmgr.init();
 }
 
-int display_event_callback(sd_event_source *evs, int /*fd*/, uint32_t events,
-                           void * /*data*/)
-{
-    ST();
-
-    if ((events & EPOLLHUP) != 0)
-    {
-        HMI_ERROR("wm", "The compositor hung up, dying now.");
-        delete g_afb_instance;
-        g_afb_instance = nullptr;
-        goto error;
-    }
-
-    if ((events & EPOLLIN) != 0u)
-    {
-        {
-            STN(display_read_events);
-            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
-            STN(winman_ping_api_call);
-            afb_service_call("windowmanager", "ping", json_object_new_object(),
-                            [](void *c, int st, json_object *j) {
-                                STN(winman_ping_api_call_return);
-                            },
-                            nullptr);
-        }
-    }
-
-    return 0;
-
-error:
-    sd_event_source_unref(evs);
-    if (getenv("WINMAN_EXIT_ON_HANGUP") != nullptr)
-    {
-        exit(1);
-    }
-    return -1;
-}
-
 int _binding_init()
 {
-    HMI_NOTICE("wm", "WinMan ver. %s", WINMAN_VERSION_STRING);
+    HMI_NOTICE("WinMan ver. %s", WINMAN_VERSION_STRING);
 
-    if (g_afb_instance != nullptr)
-    {
-        HMI_ERROR("wm", "Wayland context already initialized?");
-        return 0;
-    }
-
-    if (getenv("XDG_RUNTIME_DIR") == nullptr)
-    {
-        HMI_ERROR("wm", "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("wm", "Could not connect to compositor");
-                goto error;
-            }
-            HMI_ERROR("wm", "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)
     {
-        HMI_ERROR("wm", "Could not connect to compositor");
+        HMI_ERROR("Could not connect to compositor");
         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("wm", "Could not initialize afb_instance event handler: %d", -ret);
-            goto error;
-        }
-    }
-
     atexit([] { delete g_afb_instance; });
 
     return 0;
@@ -171,7 +88,7 @@ int binding_init() noexcept
     }
     catch (std::exception &e)
     {
-        HMI_ERROR("wm", "Uncaught exception in binding_init(): %s", e.what());
+        HMI_ERROR("Uncaught exception in binding_init(): %s", e.what());
     }
     return -1;
 }
@@ -183,7 +100,7 @@ static void cbRemoveClientCtxt(void *data)
     {
         return;
     }
-    HMI_DEBUG("wm", "remove app %s", ctxt->name.c_str());
+    HMI_DEBUG("remove app %s", ctxt->name.c_str());
 
     // Policy Manager does not know this app was killed,
     // so notify it by deactivate request.
@@ -203,7 +120,7 @@ static void createSecurityContext(afb_req req, const char* appid, const char* ro
         // Create Security Context at first time
         const char *new_role = g_afb_instance->wmgr.convertRoleOldToNew(role);
         WMClientCtxt *ctxt = new WMClientCtxt(appid, new_role);
-        HMI_DEBUG("wm", "create session for %s", ctxt->name.c_str());
+        HMI_DEBUG("create session for %s", ctxt->name.c_str());
         afb_req_session_set_LOA(req, 1);
         afb_req_context_set(req, ctxt, cbRemoveClientCtxt);
     }
@@ -212,9 +129,7 @@ static void createSecurityContext(afb_req req, const char* appid, const char* ro
 void windowmanager_requestsurface(afb_req req) noexcept
 {
     std::lock_guard<std::mutex> guard(binding_m);
-#ifdef ST
-    ST();
-#endif
+
     if (g_afb_instance == nullptr)
     {
         afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
@@ -230,18 +145,26 @@ void windowmanager_requestsurface(afb_req req) noexcept
             return;
         }
 
-        const char *appid = afb_req_get_application_id(req);
-        auto ret = g_afb_instance->wmgr.api_request_surface(
-            appid, a_drawing_name);
-        if (ret.is_err())
+        char *appid = afb_req_get_application_id(req);
+        if(appid)
         {
-            afb_req_fail(req, "failed", ret.unwrap_err());
-            return;
+            auto ret = g_afb_instance->wmgr.api_request_surface(
+                appid, a_drawing_name);
+            if (ret.is_err())
+            {
+                afb_req_fail(req, "failed", ret.unwrap_err());
+            }
+            else
+            {
+                createSecurityContext(req, appid, a_drawing_name);
+                afb_req_success(req, json_object_new_int(ret.unwrap()), "success");
+            }
+            free(appid);
+        }
+        else
+        {
+            afb_req_fail(req, "failed", nullptr);
         }
-
-        createSecurityContext(req, appid, a_drawing_name);
-
-        afb_req_success(req, json_object_new_int(ret.unwrap()), "success");
     }
     catch (std::exception &e)
     {
@@ -253,9 +176,7 @@ void windowmanager_requestsurface(afb_req req) noexcept
 void windowmanager_requestsurfacexdg(afb_req req) noexcept
 {
     std::lock_guard<std::mutex> guard(binding_m);
-#ifdef ST
-    ST();
-#endif
+
     if (g_afb_instance == nullptr)
     {
         afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
@@ -281,19 +202,23 @@ void windowmanager_requestsurfacexdg(afb_req req) noexcept
             return;
         }
         char const *a_ivi_id = json_object_get_string(j_ivi_id);
-        char const *appid = afb_req_get_application_id(req);
-        auto ret = g_afb_instance->wmgr.api_request_surface(
-            appid, a_drawing_name, a_ivi_id);
-
-        if (ret != nullptr)
+        char *appid = afb_req_get_application_id(req);
+        if(appid)
         {
-            afb_req_fail(req, "failed", ret);
-            return;
-        }
-
-        createSecurityContext(req, appid, a_drawing_name);
+            auto ret = g_afb_instance->wmgr.api_request_surface(
+                appid, a_drawing_name, a_ivi_id);
 
-        afb_req_success(req, NULL, "success");
+            if (ret != nullptr)
+            {
+                afb_req_fail(req, "failed", ret);
+            }
+            else
+            {
+                createSecurityContext(req, appid, a_drawing_name);
+                afb_req_success(req, NULL, "success");
+            }
+            free(appid);
+        }
     }
     catch (std::exception &e)
     {
@@ -312,8 +237,6 @@ void windowmanager_setrole(afb_req req) noexcept
     }
     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;
@@ -323,25 +246,22 @@ void windowmanager_setrole(afb_req req) noexcept
             return;
         }
         char const *a_role = json_object_get_string(j_role);
+        char *appid = afb_req_get_application_id(req);
 
-        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)
+        if(appid)
         {
-            afb_req_fail(req, "failed", "Couldn't register");
-            return;
+            auto ret = g_afb_instance->wmgr.api_set_role(appid, a_role);
+            if (!ret)
+            {
+                afb_req_fail(req, "failed", "Couldn't register");
+            }
+            else
+            {
+                createSecurityContext(req, appid, a_role);
+                afb_req_success(req, NULL, "success");
+            }
+            free(appid);
         }
-
-        createSecurityContext(req, appid, a_role);
-
-        afb_req_success(req, NULL, "success");
     }
     catch (std::exception &e)
     {
@@ -353,9 +273,7 @@ void windowmanager_setrole(afb_req req) noexcept
 void windowmanager_activatewindow(afb_req req) noexcept
 {
     std::lock_guard<std::mutex> guard(binding_m);
-#ifdef ST
-    ST();
-#endif
+
     if (g_afb_instance == nullptr)
     {
         afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
@@ -378,22 +296,26 @@ void windowmanager_activatewindow(afb_req req) noexcept
             return;
         }
 
-        g_afb_instance->wmgr.api_activate_surface(
-            afb_req_get_application_id(req),
-            a_drawing_name, a_drawing_area,
-            [&req](const char *errmsg) {
-                if (errmsg != nullptr)
-                {
-                    HMI_ERROR("wm", errmsg);
-                    afb_req_fail(req, "failed", errmsg);
-                    return;
-                }
-                afb_req_success(req, NULL, "success");
-            });
+        char* appid = afb_req_get_application_id(req);
+        if(appid)
+        {
+            g_afb_instance->wmgr.api_activate_surface(
+                appid, a_drawing_name, a_drawing_area,
+                [&req](const char *errmsg) {
+                    if (errmsg != nullptr)
+                    {
+                        HMI_ERROR(errmsg);
+                        afb_req_fail(req, "failed", errmsg);
+                        return;
+                    }
+                    afb_req_success(req, NULL, "success");
+                });
+            free(appid);
+        }
     }
     catch (std::exception &e)
     {
-        HMI_WARNING("wm", "failed: Uncaught exception while calling activatesurface: %s", e.what());
+        HMI_WARNING("failed: Uncaught exception while calling activatesurface: %s", e.what());
         g_afb_instance->wmgr.exceptionProcessForTransition();
         return;
     }
@@ -402,9 +324,7 @@ void windowmanager_activatewindow(afb_req req) noexcept
 void windowmanager_deactivatewindow(afb_req req) noexcept
 {
     std::lock_guard<std::mutex> guard(binding_m);
-#ifdef ST
-    ST();
-#endif
+
     if (g_afb_instance == nullptr)
     {
         afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
@@ -420,21 +340,26 @@ void windowmanager_deactivatewindow(afb_req req) noexcept
             return;
         }
 
-        g_afb_instance->wmgr.api_deactivate_surface(
-            afb_req_get_application_id(req), a_drawing_name,
-            [&req](const char *errmsg) {
-                if (errmsg != nullptr)
-                {
-                    HMI_ERROR("wm", errmsg);
-                    afb_req_fail(req, "failed", errmsg);
-                    return;
-                }
-                afb_req_success(req, NULL, "success");
-            });
+        char* appid = afb_req_get_application_id(req);
+        if(appid)
+        {
+            g_afb_instance->wmgr.api_deactivate_surface(
+                appid, a_drawing_name,
+                [&req](const char *errmsg) {
+                    if (errmsg != nullptr)
+                    {
+                        HMI_ERROR(errmsg);
+                        afb_req_fail(req, "failed", errmsg);
+                        return;
+                    }
+                    afb_req_success(req, NULL, "success");
+                });
+            free(appid);
+        }
     }
     catch (std::exception &e)
     {
-        HMI_WARNING("wm", "failed: Uncaught exception while calling deactivatesurface: %s", e.what());
+        HMI_WARNING("failed: Uncaught exception while calling deactivatesurface: %s", e.what());
         g_afb_instance->wmgr.exceptionProcessForTransition();
         return;
     }
@@ -443,9 +368,7 @@ void windowmanager_deactivatewindow(afb_req req) noexcept
 void windowmanager_enddraw(afb_req req) noexcept
 {
     std::lock_guard<std::mutex> guard(binding_m);
-#ifdef ST
-    ST();
-#endif
+
     if (g_afb_instance == nullptr)
     {
         afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
@@ -462,12 +385,16 @@ void windowmanager_enddraw(afb_req req) noexcept
         }
         afb_req_success(req, NULL, "success");
 
-        g_afb_instance->wmgr.api_enddraw(
-            afb_req_get_application_id(req), a_drawing_name);
+        char* appid = afb_req_get_application_id(req);
+        if(appid)
+        {
+            g_afb_instance->wmgr.api_enddraw(appid, a_drawing_name);
+            free(appid);
+        }
     }
     catch (std::exception &e)
     {
-        HMI_WARNING("wm", "failed: Uncaught exception while calling enddraw: %s", e.what());
+        HMI_WARNING("failed: Uncaught exception while calling enddraw: %s", e.what());
         g_afb_instance->wmgr.exceptionProcessForTransition();
         return;
     }
@@ -476,9 +403,7 @@ void windowmanager_enddraw(afb_req req) noexcept
 void windowmanager_getdisplayinfo_thunk(afb_req req) noexcept
 {
     std::lock_guard<std::mutex> guard(binding_m);
-#ifdef ST
-    ST();
-#endif
+
     if (g_afb_instance == nullptr)
     {
         afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
@@ -506,9 +431,7 @@ void windowmanager_getdisplayinfo_thunk(afb_req req) noexcept
 void windowmanager_getareainfo_thunk(afb_req req) noexcept
 {
     std::lock_guard<std::mutex> guard(binding_m);
-#ifdef ST
-    ST();
-#endif
+
     if (g_afb_instance == nullptr)
     {
         afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
@@ -543,12 +466,51 @@ void windowmanager_getareainfo_thunk(afb_req req) noexcept
     }
 }
 
+void windowmanager_set_render_order(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;
+    }
+
+    char* appid = afb_req_get_application_id(req);
+    if(appid)
+    {
+        json_object *jreq = afb_req_json(req);
+        json_object *j_ro; // Do not free this. binder frees jreq, then free j_ro
+        if (json_object_object_get_ex(jreq, "render_order", &j_ro))
+        {
+            int size = json_object_array_length(j_ro);
+            std::vector<std::string> ro(size);
+            for(int i = 0; i < size; i++)
+            {
+                ro[i] = json_object_get_string(json_object_array_get_idx(j_ro, i));
+            }
+
+            auto ret = g_afb_instance->wmgr.api_client_set_render_order(appid, ro);
+            if (!ret)
+            {
+                afb_req_fail(req, "failed", nullptr);
+            }
+            else
+            {
+                afb_req_success(req, nullptr, nullptr);
+            }
+        }
+        free(appid);
+    }
+    else
+    {
+        afb_req_fail(req, "failed", nullptr);
+    }
+}
+
 void windowmanager_wm_subscribe(afb_req req) noexcept
 {
     std::lock_guard<std::mutex> guard(binding_m);
-#ifdef ST
-    ST();
-#endif
+
     if (g_afb_instance == nullptr)
     {
         afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
@@ -585,10 +547,8 @@ void windowmanager_wm_subscribe(afb_req req) noexcept
 void windowmanager_list_drawing_names(afb_req req) noexcept
 {
     std::lock_guard<std::mutex> guard(binding_m);
-#ifdef ST
-    ST();
-#endif
-    if (g_afb_instance == nullptr)
+
+    /* if (g_afb_instance == nullptr)
     {
         afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
         return;
@@ -611,42 +571,29 @@ void windowmanager_list_drawing_names(afb_req req) noexcept
     {
         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);
-#ifdef ST
-    ST();
-#endif
+
     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);
-#ifdef ST
-    ST();
-#endif
-    if (g_afb_instance == nullptr)
+
+    /* if (g_afb_instance == nullptr)
     {
         afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
         return;
@@ -666,16 +613,14 @@ void windowmanager_debug_status(afb_req req) noexcept
     {
         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);
-#ifdef ST
-    ST();
-#endif
-    if (g_afb_instance == nullptr)
+
+    /* if (g_afb_instance == nullptr)
     {
         afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
         return;
@@ -691,16 +636,14 @@ void windowmanager_debug_layers(afb_req req) noexcept
     {
         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);
-#ifdef ST
-    ST();
-#endif
-    if (g_afb_instance == nullptr)
+
+    /* if (g_afb_instance == nullptr)
     {
         afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
         return;
@@ -722,15 +665,13 @@ void windowmanager_debug_surfaces(afb_req req) noexcept
     {
         afb_req_fail_f(req, "failed", "Uncaught exception while calling debug_surfaces: %s", e.what());
         return;
-    }
+    } */
 }
 
 void windowmanager_debug_terminate(afb_req req) noexcept
 {
     std::lock_guard<std::mutex> guard(binding_m);
-#ifdef ST
-    ST();
-#endif
+
     if (g_afb_instance == nullptr)
     {
         afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
@@ -756,14 +697,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},
-    {"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},
-    {"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},
+    {"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},
+    {"getDisplayInfo", windowmanager_getdisplayinfo_thunk, nullptr, nullptr, AFB_SESSION_NONE},
+    {"getAreaInfo", windowmanager_getareainfo_thunk, nullptr, nullptr, AFB_SESSION_NONE},
+    {"setRenderOrder", windowmanager_set_render_order, 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},