2 * Copyright (c) 2017 TOYOTA MOTOR CORPORATION
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
21 #include "window_manager.hpp"
22 #include "json_helper.hpp"
26 #include <afb/afb-binding.h>
27 #include <systemd/sd-event.h>
30 typedef struct WMClientCtxt
34 WMClientCtxt(const char *appName, const char* appRole)
43 wm::WindowManager wmgr;
45 afb_instance() : wmgr() {}
46 ~afb_instance() = default;
51 struct afb_instance *g_afb_instance;
54 int afb_instance::init()
56 return this->wmgr.init();
61 HMI_NOTICE("WinMan ver. %s", WINMAN_VERSION_STRING);
63 g_afb_instance = new afb_instance;
65 if (g_afb_instance->init() == -1)
67 HMI_ERROR("Could not connect to compositor");
71 atexit([] { delete g_afb_instance; });
76 delete g_afb_instance;
77 g_afb_instance = nullptr;
81 int binding_init() noexcept
85 return _binding_init();
87 catch (std::exception &e)
89 HMI_ERROR("Uncaught exception in binding_init(): %s", e.what());
94 static void cbRemoveClientCtxt(void *data)
96 WMClientCtxt *ctxt = (WMClientCtxt *)data;
101 HMI_DEBUG("remove app %s", ctxt->name.c_str());
103 // Policy Manager does not know this app was killed,
104 // so notify it by deactivate request.
105 g_afb_instance->wmgr.api_deactivate_window(
106 ctxt->name.c_str(), ctxt->role.c_str(),
107 [](const char *) {});
109 g_afb_instance->wmgr.removeClient(ctxt->name);
113 static void createSecurityContext(afb_req req, const char* appid, const char* role)
115 WMClientCtxt *ctxt = (WMClientCtxt *)afb_req_context_get(req);
118 // Create Security Context at first time
119 const char *new_role = g_afb_instance->wmgr.convertRoleOldToNew(role);
120 WMClientCtxt *ctxt = new WMClientCtxt(appid, new_role);
121 HMI_DEBUG("create session for %s", ctxt->name.c_str());
122 afb_req_session_set_LOA(req, 1);
123 afb_req_context_set(req, ctxt, cbRemoveClientCtxt);
127 void windowmanager_requestsurface(afb_req req) noexcept
129 std::lock_guard<std::mutex> guard(binding_m);
130 if (g_afb_instance == nullptr)
132 afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
138 const char *a_drawing_name = afb_req_value(req, "drawing_name");
141 afb_req_fail(req, "failed", "Need char const* argument drawing_name");
145 char *appid = afb_req_get_application_id(req);
148 auto ret = g_afb_instance->wmgr.api_request_surface(
149 appid, a_drawing_name);
152 afb_req_fail(req, "failed", ret.unwrap_err());
156 createSecurityContext(req, appid, a_drawing_name);
157 afb_req_success(req, json_object_new_int(ret.unwrap()), "success");
163 afb_req_fail(req, "failed", nullptr);
166 catch (std::exception &e)
168 afb_req_fail_f(req, "failed", "Uncaught exception while calling requestsurface: %s", e.what());
173 void windowmanager_requestsurfacexdg(afb_req req) noexcept
175 std::lock_guard<std::mutex> guard(binding_m);
176 if (g_afb_instance == nullptr)
178 afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
184 json_object *jreq = afb_req_json(req);
186 json_object *j_drawing_name = nullptr;
187 if (!json_object_object_get_ex(jreq, "drawing_name", &j_drawing_name))
189 afb_req_fail(req, "failed", "Need char const* argument drawing_name");
192 char const *a_drawing_name = json_object_get_string(j_drawing_name);
194 json_object *j_ivi_id = nullptr;
195 if (!json_object_object_get_ex(jreq, "ivi_id", &j_ivi_id))
197 afb_req_fail(req, "failed", "Need char const* argument ivi_id");
200 char const *a_ivi_id = json_object_get_string(j_ivi_id);
201 char *appid = afb_req_get_application_id(req);
204 auto ret = g_afb_instance->wmgr.api_request_surface(
205 appid, a_drawing_name, a_ivi_id);
209 afb_req_fail(req, "failed", ret);
213 createSecurityContext(req, appid, a_drawing_name);
214 afb_req_success(req, NULL, "success");
219 catch (std::exception &e)
221 afb_req_fail_f(req, "failed", "Uncaught exception while calling requestsurfacexdg: %s", e.what());
226 void windowmanager_activatewindow(afb_req req) noexcept
228 std::lock_guard<std::mutex> guard(binding_m);
229 if (g_afb_instance == nullptr)
231 afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
237 const char *a_drawing_name = afb_req_value(req, "drawing_name");
240 afb_req_fail(req, "failed", "Need char const* argument drawing_name");
244 const char *a_drawing_area = afb_req_value(req, "drawing_area");
247 afb_req_fail(req, "failed", "Need char const* argument drawing_area");
251 char* appid = afb_req_get_application_id(req);
254 g_afb_instance->wmgr.api_activate_window(
255 appid, a_drawing_name, a_drawing_area,
256 [&req](const char *errmsg) {
257 if (errmsg != nullptr)
260 afb_req_fail(req, "failed", errmsg);
263 afb_req_success(req, NULL, "success");
268 catch (std::exception &e)
270 HMI_WARNING("failed: Uncaught exception while calling activatesurface: %s", e.what());
271 g_afb_instance->wmgr.exceptionProcessForTransition();
276 void windowmanager_deactivatewindow(afb_req req) noexcept
278 std::lock_guard<std::mutex> guard(binding_m);
279 if (g_afb_instance == nullptr)
281 afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
287 const char *a_drawing_name = afb_req_value(req, "drawing_name");
290 afb_req_fail(req, "failed", "Need char const* argument drawing_name");
294 char* appid = afb_req_get_application_id(req);
297 g_afb_instance->wmgr.api_deactivate_window(
298 appid, a_drawing_name,
299 [&req](const char *errmsg) {
300 if (errmsg != nullptr)
303 afb_req_fail(req, "failed", errmsg);
306 afb_req_success(req, NULL, "success");
311 catch (std::exception &e)
313 HMI_WARNING("failed: Uncaught exception while calling deactivatesurface: %s", e.what());
314 g_afb_instance->wmgr.exceptionProcessForTransition();
319 void windowmanager_enddraw(afb_req req) noexcept
321 std::lock_guard<std::mutex> guard(binding_m);
322 if (g_afb_instance == nullptr)
324 afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
330 const char *a_drawing_name = afb_req_value(req, "drawing_name");
333 afb_req_fail(req, "failed", "Need char const* argument drawing_name");
336 afb_req_success(req, NULL, "success");
338 char* appid = afb_req_get_application_id(req);
341 g_afb_instance->wmgr.api_enddraw(appid, a_drawing_name);
345 catch (std::exception &e)
347 HMI_WARNING("failed: Uncaught exception while calling enddraw: %s", e.what());
348 g_afb_instance->wmgr.exceptionProcessForTransition();
353 void windowmanager_getdisplayinfo_thunk(afb_req req) noexcept
355 std::lock_guard<std::mutex> guard(binding_m);
356 if (g_afb_instance == nullptr)
358 afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
364 auto ret = g_afb_instance->wmgr.api_get_display_info();
367 afb_req_fail(req, "failed", ret.unwrap_err());
371 afb_req_success(req, ret.unwrap(), "success");
373 catch (std::exception &e)
375 afb_req_fail_f(req, "failed", "Uncaught exception while calling getdisplayinfo: %s", e.what());
380 void windowmanager_getareainfo_thunk(afb_req req) noexcept
382 std::lock_guard<std::mutex> guard(binding_m);
383 if (g_afb_instance == nullptr)
385 afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
391 json_object *jreq = afb_req_json(req);
393 json_object *j_drawing_name = nullptr;
394 if (!json_object_object_get_ex(jreq, "drawing_name", &j_drawing_name))
396 afb_req_fail(req, "failed", "Need char const* argument drawing_name");
399 char const *a_drawing_name = json_object_get_string(j_drawing_name);
401 auto ret = g_afb_instance->wmgr.api_get_area_info(a_drawing_name);
404 afb_req_fail(req, "failed", ret.unwrap_err());
408 afb_req_success(req, ret.unwrap(), "success");
410 catch (std::exception &e)
412 afb_req_fail_f(req, "failed", "Uncaught exception while calling getareainfo: %s", e.what());
417 void windowmanager_wm_subscribe(afb_req req) noexcept
419 std::lock_guard<std::mutex> guard(binding_m);
420 if (g_afb_instance == nullptr)
422 afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
428 json_object *jreq = afb_req_json(req);
429 json_object *j = nullptr;
430 if (!json_object_object_get_ex(jreq, "event", &j))
432 afb_req_fail(req, "failed", "Need char const* argument event");
435 int event_id = json_object_get_int(j);
436 int ret = g_afb_instance->wmgr.api_subscribe(req, event_id);
440 afb_req_fail(req, "failed", "Error: afb_req_subscribe()");
443 afb_req_success(req, NULL, "success");
445 catch (std::exception &e)
447 afb_req_fail_f(req, "failed", "Uncaught exception while calling wm_subscribe: %s", e.what());
452 void windowmanager_ping(afb_req req) noexcept
454 std::lock_guard<std::mutex> guard(binding_m);
456 if (g_afb_instance == nullptr)
458 afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
463 afb_req_success(req, NULL, "success");
467 void windowmanager_debug_terminate(afb_req req) noexcept
469 std::lock_guard<std::mutex> guard(binding_m);
470 if (g_afb_instance == nullptr)
472 afb_req_fail(req, "failed", "Binding not initialized, did the compositor die?");
479 if (getenv("WINMAN_DEBUG_TERMINATE") != nullptr)
481 raise(SIGKILL); // afb-daemon kills it's pgroup using TERM, which
482 // doesn't play well with perf
485 afb_req_success(req, NULL, "success");
487 catch (std::exception &e)
489 afb_req_fail_f(req, "failed", "Uncaught exception while calling debug_terminate: %s", e.what());
494 const struct afb_verb_v2 windowmanager_verbs[] = {
495 {"requestSurface", windowmanager_requestsurface, nullptr, nullptr, AFB_SESSION_NONE},
496 {"requestSurfaceXDG", windowmanager_requestsurfacexdg, nullptr, nullptr, AFB_SESSION_NONE},
497 {"activateWindow", windowmanager_activatewindow, nullptr, nullptr, AFB_SESSION_NONE},
498 {"deactivateWindow", windowmanager_deactivatewindow, nullptr, nullptr, AFB_SESSION_NONE},
499 {"endDraw", windowmanager_enddraw, nullptr, nullptr, AFB_SESSION_NONE},
500 {"getDisplayInfo", windowmanager_getdisplayinfo_thunk, nullptr, nullptr, AFB_SESSION_NONE},
501 {"getAreaInfo", windowmanager_getareainfo_thunk, nullptr, nullptr, AFB_SESSION_NONE},
502 {"wm_subscribe", windowmanager_wm_subscribe, nullptr, nullptr, AFB_SESSION_NONE},
503 {"ping", windowmanager_ping, nullptr, nullptr, AFB_SESSION_NONE},
504 {"debug_terminate", windowmanager_debug_terminate, nullptr, nullptr, AFB_SESSION_NONE},
507 extern "C" const struct afb_binding_v2 afbBindingV2 = {
508 "windowmanager", nullptr, nullptr, windowmanager_verbs, nullptr, binding_init, nullptr, 0};