From f427515b412094b7feb09838793ce2e48118839d Mon Sep 17 00:00:00 2001 From: Kazumasa Mitsunari Date: Tue, 14 Aug 2018 15:00:06 +0900 Subject: Introduce simple API Originally, API of libwindowmanager uses json_object type as parameters. This causes useless coding and mistakes such as double free with json_object_put accidentally. So this patch introduces simple API not using json_object as parameters. Bug-AGL: SPEC-1582 Bug-AGL: SPEC-1565 Change-Id: Id0a8e74739f0c73d294843c5ce154d0a36dd9279 Signed-off-by: Kazumasa Mitsunari --- src/libwindowmanager.cpp | 364 +++++++++++++++++++++++++++++++++++++++-------- src/libwindowmanager.h | 68 ++++++++- 2 files changed, 372 insertions(+), 60 deletions(-) diff --git a/src/libwindowmanager.cpp b/src/libwindowmanager.cpp index 19cef6e..515fea1 100644 --- a/src/libwindowmanager.cpp +++ b/src/libwindowmanager.cpp @@ -17,52 +17,38 @@ #include "libwindowmanager.h" #include "hmi-debug.h" -#include -#include -#include -#include -#include -#include - #include #include #include #include #include - #include - -#include - #include extern "C" { #include #include +#include } #define UNUSED(x) (void)(x) +namespace { + /* Key for json obejct */ + static const char g_kKeyDrawingName[] = "drawing_name"; + static const char g_kKeyDrawingArea[] = "drawing_area"; + static const char g_kKeyDrawingRect[] = "drawing_rect"; + static const char g_kKeyResponse[] = "response"; +} + /** * @class LibWindowmanager::Impl */ class LibWindowmanager::Impl { - friend class LibWindowmanager; - - const std::vector kListEventName{ - std::string("active"), - std::string("inactive"), - std::string("visible"), - std::string("invisible"), - std::string("syncDraw"), - std::string("flushDraw"), - std::string("screenUpdated"), - std::string("error") - }; + public: - /* Key for json obejct */ - const char *kKeyDrawingName = "drawing_name"; - const char *kKeyDrawingArea = "drawing_area"; + Impl(); + ~Impl(); // This is the LibWindowmanager interface impl int init(int port, char const *token); @@ -76,11 +62,16 @@ class LibWindowmanager::Impl { int getDisplayInfo(json_object *object); int getAreaInfo(json_object *in_obj, json_object *out_obj); + struct Screen getScreenInfo() {return this->_screen;}; void set_event_handler(enum EventType et, handler_fun func); + void setEventHandler(const WMHandler &wmh); - Impl(); - ~Impl(); + int api_call(const char *verb, json_object *object, + const std::function &onReply); + void event(char const *et, json_object *object); +private: + int runEventLoop(); struct afb_wsj1 *wsj1; struct sd_event *loop; @@ -89,18 +80,23 @@ class LibWindowmanager::Impl { std::map handlers; std::queue> handler_queue; - int api_call(const char *verb, json_object *object, - const std::function &onReply); + const std::vector kListEventName{ + std::string("active"), + std::string("inactive"), + std::string("visible"), + std::string("invisible"), + std::string("syncDraw"), + std::string("flushDraw"), + std::string("screenUpdated"), + std::string("error") + }; -public: - void event(char const *et, json_object *object); -private: - int runEventLoop(); + struct Screen _screen; + WMHandler _wmh; }; namespace { -constexpr const int token_maxlen = 20; constexpr const char *const wmAPI = "windowmanager"; #define CONCAT_(X, Y) X##Y @@ -139,16 +135,16 @@ void onCall(void *closure, const char *api, const char *verb, /* called when wsj1 receives an event */ void onEvent(void *closure, const char *event, afb_wsj1_msg *msg) { TRACE(); - // check API name in event if (0 != strncmp(wmAPI, event, strlen(wmAPI))) { HMI_ERROR("libwm", "Unknown event: %s", event); return; } - json_object *val; - if (json_object_object_get_ex(afb_wsj1_msg_object_j(msg), "data", &val)) { - reinterpret_cast(closure)->event(event, val); + json_object *j, *val; + j = afb_wsj1_msg_object_j(msg); + if (json_object_object_get_ex(j, "data", &val)) { + static_cast(closure)->event(event, val); } else { HMI_ERROR("libwm", "Not found key \"data\""); @@ -172,7 +168,11 @@ constexpr struct afb_wsj1_itf itf = { /** * @class LibWindowmanager::Impl::Impl */ -LibWindowmanager::Impl::Impl() : wsj1{}, loop{}, labels(), handlers() { TRACE(); } +LibWindowmanager::Impl::Impl() + : wsj1{}, loop{}, labels(), handlers(), + _screen{0,0,0,0,0.0}, + _wmh() +{} LibWindowmanager::Impl::~Impl() { TRACE(); @@ -240,11 +240,11 @@ int LibWindowmanager::Impl::requestSurface(json_object *object) { json_object *val; const char *tmp_label; - if (json_object_object_get_ex(object, this->kKeyDrawingName, &val)) { + if (json_object_object_get_ex(object, g_kKeyDrawingName, &val)) { tmp_label = json_object_get_string(val); } else { - HMI_DEBUG("libwm", "Not found key \"%s\"", this->kKeyDrawingName); + HMI_DEBUG("libwm", "Not found key \"%s\"", g_kKeyDrawingName); return -EINVAL; } @@ -268,7 +268,7 @@ int LibWindowmanager::Impl::requestSurface(json_object *object) { this->api_call("RequestSurface", object, [&rc](bool ok, json_object *j) { if (ok) { json_object *val; - if (json_object_object_get_ex(j, "response", &val)) { + if (json_object_object_get_ex(j, g_kKeyResponse, &val)) { rc = json_object_get_int(val); } else { @@ -297,11 +297,11 @@ int LibWindowmanager::Impl::requestSurfaceXDG(json_object *object) { json_object *val; const char *tmp_label; - if (json_object_object_get_ex(object, this->kKeyDrawingName, &val)) { + if (json_object_object_get_ex(object, g_kKeyDrawingName, &val)) { tmp_label = json_object_get_string(val); } else { - HMI_DEBUG("libwm", "Not found key \"%s\"", this->kKeyDrawingName); + HMI_DEBUG("libwm", "Not found key \"%s\"", g_kKeyDrawingName); return -EINVAL; } @@ -399,7 +399,7 @@ int LibWindowmanager::Impl::getDisplayInfo(json_object *object) { [&rc, &w_px, &h_px, &w_mm, &h_mm, &scale](bool ok, json_object *j) { if (ok) { json_object *val; - if (json_object_object_get_ex(j, "response", &val)) { + if (json_object_object_get_ex(j, g_kKeyResponse, &val)) { HMI_DEBUG("libwm", "responce:%s", json_object_get_string(val)); json_object *j_w_px = nullptr; @@ -463,11 +463,17 @@ int LibWindowmanager::Impl::getDisplayInfo(json_object *object) { } if (0 == rc) { - json_object_object_add(object, "width_pixel", json_object_new_int(w_px)); - json_object_object_add(object, "height_pixel", json_object_new_int(h_px)); - json_object_object_add(object, "width_mm", json_object_new_int(w_mm)); - json_object_object_add(object, "height_mm", json_object_new_int(h_mm)); - json_object_object_add(object, "scale", json_object_new_double(scale)); + json_object_object_add(object, "width_pixel", json_object_new_int(w_px)); + json_object_object_add(object, "height_pixel", json_object_new_int(h_px)); + json_object_object_add(object, "width_mm", json_object_new_int(w_mm)); + json_object_object_add(object, "height_mm", json_object_new_int(h_mm)); + json_object_object_add(object, "scale", json_object_new_double(scale)); + this->_screen = Screen{ + static_cast(w_px), + static_cast(h_px), + static_cast(w_mm), + static_cast(h_mm), + scale}; } return rc; @@ -496,7 +502,7 @@ int LibWindowmanager::Impl::getAreaInfo(json_object *in_obj, json_object *out_ob if (ok) { json_object *val; HMI_DEBUG("libwm", "j:%s", json_object_get_string(j)); - if (json_object_object_get_ex(j, "response", &val)) { + if (json_object_object_get_ex(j, g_kKeyResponse, &val)) { json_object *j_x = nullptr; if (!json_object_object_get_ex(val, "x", &j_x)) { HMI_DEBUG("libwm", "Not found key \"x\""); @@ -682,6 +688,80 @@ int LibWindowmanager::Impl::api_call( return rc; } +void LibWindowmanager::Impl::setEventHandler(const WMHandler &wmh) +{ + // Subscribe + const char* ev = "event"; + if(wmh.on_visible != nullptr) { + struct json_object* j = json_object_new_object(); + json_object_object_add(j, ev, json_object_new_int(Event_Visible)); + struct json_object* j_i = json_object_new_object(); + json_object_object_add(j_i, ev, json_object_new_int(Event_Invisible)); + + int ret = afb_wsj1_call_j(this->wsj1, wmAPI, "wm_subscribe", j, _on_reply_static, this); + if (0 > ret) { + HMI_ERROR("libwm", "Failed to subscribe event visible"); + } + ret = afb_wsj1_call_j(this->wsj1, wmAPI, "wm_subscribe", j_i, _on_reply_static, this); + if (0 > ret) { + HMI_ERROR("libwm", "Failed to subscribe event"); + } + } + + if(wmh.on_active != nullptr) { + struct json_object* j = json_object_new_object(); + json_object_object_add(j, ev, json_object_new_int(Event_Active)); + struct json_object* j_i = json_object_new_object(); + json_object_object_add(j_i, ev, json_object_new_int(Event_Inactive)); + + int ret = afb_wsj1_call_j(this->wsj1, wmAPI, "wm_subscribe", j, _on_reply_static, this); + if (0 > ret) { + HMI_ERROR("libwm", "Failed to subscribe event active"); + } + ret = afb_wsj1_call_j(this->wsj1, wmAPI, "wm_subscribe", j_i, _on_reply_static, this); + if (0 > ret) { + HMI_ERROR("libwm", "Failed to subscribe event"); + } + } + + if(wmh.on_sync_draw != nullptr) { + struct json_object* j = json_object_new_object(); + json_object_object_add(j, ev, json_object_new_int(Event_SyncDraw)); + + int ret = afb_wsj1_call_j(this->wsj1, wmAPI, "wm_subscribe", j, _on_reply_static, this); + if (0 > ret) { + HMI_ERROR("libwm", "Failed to subscribe event active"); + } + } + + if(wmh.on_flush_draw != nullptr) { + struct json_object* j = json_object_new_object(); + json_object_object_add(j, ev, json_object_new_int(Event_FlushDraw)); + + int ret = afb_wsj1_call_j(this->wsj1, wmAPI, "wm_subscribe", j, _on_reply_static, this); + if (0 > ret) { + HMI_ERROR("libwm", "Failed to subscribe event active"); + } + } + + if(wmh.on_screen_updated != nullptr) { + struct json_object* j = json_object_new_object(); + json_object_object_add(j, ev, json_object_new_int(Event_ScreenUpdated)); + + int ret = afb_wsj1_call_j(this->wsj1, wmAPI, "wm_subscribe", j, _on_reply_static, this); + if (0 > ret) { + HMI_ERROR("libwm", "Failed to subscribe event active"); + } + } + + // Register + this->_wmh.on_visible = wmh.on_visible; + this->_wmh.on_active = wmh.on_active; + this->_wmh.on_sync_draw = wmh.on_sync_draw; + this->_wmh.on_flush_draw = wmh.on_flush_draw; + this->_wmh.on_screen_updated = wmh.on_screen_updated; +} + void LibWindowmanager::Impl::event(char const *et, json_object *object) { TRACE(); auto oet = make_event_type(et); @@ -689,12 +769,81 @@ void LibWindowmanager::Impl::event(char const *et, json_object *object) { HMI_ERROR("libwm", "Unknown event type string '%s'", et); return; } + json_object *j_val; + std::string role = ""; + bool emit = false; + if(json_object_object_get_ex(object, g_kKeyDrawingName, &j_val)) { + role = json_object_get_string(j_val); + } + if (this->labels.find(role) != this->labels.end()){ + emit = true; + } + + switch(oet.second) { + case Event_Active : + case Event_Inactive : { + bool active = ((oet.second == Event_Active) ? true : false); + if(!emit) break; + if(this->_wmh.on_active) { + return this->_wmh.on_active(role.c_str(), active); + } + break; + } + case Event_Visible : + case Event_Invisible : { + bool visible = ((oet.second == Event_Visible) ? true : false); + if(!emit) break; + if(this->_wmh.on_visible) { + return this->_wmh.on_visible(role.c_str(), visible); + } + break; + } + case Event_SyncDraw : + if(this->_wmh.on_sync_draw && emit) { + json_object_object_get_ex(object, g_kKeyDrawingArea, &j_val); + const char* area = json_object_get_string(j_val); + json_object *j_rect; + json_object_object_get_ex(object, g_kKeyDrawingRect, &j_rect); + json_object_object_get_ex(j_rect, "x", &j_val); + int x = json_object_get_int(j_val); + json_object_object_get_ex(j_rect, "y", &j_val); + int y = json_object_get_int(j_val); + json_object_object_get_ex(j_rect, "width", &j_val); + int w = json_object_get_int(j_val); + json_object_object_get_ex(j_rect, "height", &j_val); + int h = json_object_get_int(j_val); + Rect rect(x, y, w, h); + return this->_wmh.on_sync_draw(role.c_str(), area, rect); + } + break; + case Event_FlushDraw : + if(this->_wmh.on_flush_draw && emit) { + return this->_wmh.on_flush_draw(role.c_str()); + } + break; + case Event_ScreenUpdated : + if(this->_wmh.on_screen_updated) { + // emit this case + json_object_object_get_ex(object, "ids", &j_val); + int len = json_object_array_length(j_val); + std::vector id_list; + for(int i = 0; i < len; i++) + { + std::string elem = json_object_get_string(json_object_array_get_idx(j_val, i)); + id_list.push_back(elem); + } + return this->_wmh.on_screen_updated(id_list); + } + break; + default : + break; + } auto i = this->handlers.find(oet.second); if (i != this->handlers.end()) { json_object *val; const char *label; - if (json_object_object_get_ex(object, this->kKeyDrawingName, &val)) { + if (json_object_object_get_ex(object, g_kKeyDrawingName, &val)) { label = json_object_get_string(val); } else { @@ -721,7 +870,7 @@ int LibWindowmanager::Impl::runEventLoop() { int ret = pthread_create(&thread_id, NULL, event_loop_run, this->loop); if(ret != 0) { - printf("Cannot run eventloop due to error:%d", errno); + HMI_ERROR("libwm", "Cannot run eventloop due to error:%d", errno); return -1; } else @@ -729,7 +878,7 @@ int LibWindowmanager::Impl::runEventLoop() { } else { - printf("Connecting is not established yet"); + HMI_ERROR("libwm", "Connecting is not established yet"); return -1; } } @@ -738,25 +887,74 @@ int LibWindowmanager::Impl::runEventLoop() { * @class LibWindowmanager */ int LibWindowmanager::init(int port, char const *token) { - return this->d->init(port, token); + int ret = this->d->init(port, token); + if(ret == 0) { + json_object* j = json_object_new_object(); + ret = this->getDisplayInfo(j); // return 0 if success + json_object_put(j); + } + return ret; +} + +int LibWindowmanager::init(int port, const std::string &token) { + int ret = this->d->init(port, token.c_str()); + if(ret == 0) { + json_object* j = json_object_new_object(); + ret = this->getDisplayInfo(j); // return 0 if success + json_object_put(j); + } + return ret; } int LibWindowmanager::requestSurface(json_object *object) { return this->d->requestSurface(object); } +int LibWindowmanager::requestSurface(const char *role) { + json_object* object = json_object_new_object(); + json_object_object_add(object, kKeyDrawingName, json_object_new_string(role)); + return this->d->requestSurface(object); +} + int LibWindowmanager::requestSurfaceXDG(json_object *object) { return this->d->requestSurfaceXDG(object); } +int LibWindowmanager::requestSurfaceXDG(const char* role, unsigned ivi_id) { + json_object* object = json_object_new_object(); + json_object_object_add(object, kKeyDrawingName, json_object_new_string(role)); + json_object_object_add(object, kKeyIviId, json_object_new_int(ivi_id)); + return this->d->requestSurfaceXDG(object); +} + int LibWindowmanager::activateWindow(json_object *object) { return this->d->activateWindow(object); } +int LibWindowmanager::activateWindow(const char* role, const char* area) { + json_object* object = json_object_new_object(); + json_object_object_add(object, kKeyDrawingName, json_object_new_string(role)); + json_object_object_add(object, kKeyDrawingArea, json_object_new_string(area)); + return this->d->activateWindow(object); +} + +int LibWindowmanager::activateWindow(const char* role) { + json_object* object = json_object_new_object(); + json_object_object_add(object, kKeyDrawingName, json_object_new_string(role)); + json_object_object_add(object, kKeyDrawingArea, json_object_new_string(kDefaultArea.c_str())); + return this->d->activateWindow(object); +} + int LibWindowmanager::deactivateWindow(json_object *object) { return this->d->deactivateWindow(object); } +int LibWindowmanager::deactivateWindow(const char* role) { + json_object* object = json_object_new_object(); + json_object_object_add(object, kKeyDrawingName, json_object_new_string(role)); + return this->d->deactivateWindow(nullptr); +} + // This API is deprecated, please use new API int LibWindowmanager::activateSurface(json_object *object) { return this->activateWindow(object); @@ -771,6 +969,12 @@ int LibWindowmanager::endDraw(json_object *object) { return this->d->endDraw(object); } +int LibWindowmanager::endDraw(const char* role) { + json_object* object = json_object_new_object(); + json_object_object_add(object, kKeyDrawingName, json_object_new_string(role)); + return this->d->endDraw(object); +} + int LibWindowmanager::getDisplayInfo(json_object *object) { return this->d->getDisplayInfo(object); } @@ -779,6 +983,37 @@ int LibWindowmanager::getAreaInfo(json_object *in_obj, json_object *out_obj) { return this->d->getAreaInfo(in_obj, out_obj); } +int LibWindowmanager::getAreaInfo(const char *role, Rect *out_rect) { + json_object *object = json_object_new_object(); + json_object *out = json_object_new_object(); + json_object_object_add(object, this->kKeyDrawingName, json_object_new_string(role)); + int ret = this->d->getAreaInfo(object, out); + + out_rect->set_left(0); + out_rect->set_top(0); + out_rect->set_width(0); + out_rect->set_height(0); + + if(!ret) { + json_object *j_val; + json_object *j_rect; + json_object_object_get_ex(out, kKeyDrawingRect, &j_rect); + if (json_object_object_get_ex(j_rect, "x", &j_val)) { + out_rect->set_left(json_object_get_int(j_val)); + } + if (json_object_object_get_ex(j_rect, "y", &j_val)) { + out_rect->set_top(json_object_get_int(j_val)); + } + if (json_object_object_get_ex(j_rect, "width", &j_val)) { + out_rect->set_width(json_object_get_int(j_val)); + } + if (json_object_object_get_ex(j_rect, "height", &j_val)) { + out_rect->set_height(json_object_get_int(j_val)); + } + } + return ret; +} + int LibWindowmanager::getAreaInfo(const char *label, json_object *out_obj) { json_object *object = json_object_new_object(); json_object_object_add(object, this->kKeyDrawingName, json_object_new_string(label)); @@ -789,6 +1024,23 @@ void LibWindowmanager::set_event_handler(enum EventType et, handler_fun f) { return this->d->set_event_handler(et, std::move(f)); } +struct Screen LibWindowmanager::getScreenInfo() { + return this->d->getScreenInfo(); +} + +void LibWindowmanager::setEventHandler(const WMHandler &wml) +{ + return this->d->setEventHandler(wml); +} + LibWindowmanager::LibWindowmanager() : d(new Impl) {} LibWindowmanager::~LibWindowmanager() { delete d; } + +WMHandler::WMHandler() + : on_visible(nullptr), + on_active(nullptr), + on_sync_draw(nullptr), + on_flush_draw(nullptr), + on_screen_updated(nullptr) +{} diff --git a/src/libwindowmanager.h b/src/libwindowmanager.h index 60a3dab..cc65136 100644 --- a/src/libwindowmanager.h +++ b/src/libwindowmanager.h @@ -18,8 +18,58 @@ #define LIBWINDOWMANAGER_H #include +#include +#include #include +class Rect { + public: + Rect() : _x(0), _y(0),_w(0), _h(0) {} + Rect(unsigned x, unsigned y, unsigned w, unsigned h) + : _x(x), _y(y),_w(w), _h(h) {} + ~Rect() = default; + unsigned left() const { return _x;} + unsigned top() const { return _y;} + unsigned width() const { return _w;} + unsigned height() const { return _h;} + void set_left (unsigned int x) { _x = x; } + void set_top (unsigned int y) { _y = y; } + void set_width (unsigned int w) { _w = w; } + void set_height(unsigned int h) { _h = h; } + private: + unsigned _x; + unsigned _y; + unsigned _w; + unsigned _h; +}; + +struct Screen +{ + unsigned long width_dp; + unsigned long height_dp; + unsigned long width_mm; + unsigned long height_mm; + double scale = 1.0; +}; + +class WMHandler { + public: + WMHandler(); + ~WMHandler() = default; + + using visible_handler = std::function; + using active_handler = std::function; + using sync_draw_handler = std::function; + using flush_draw_handler= std::function; + using screen_updated_handler = std::function&)>; + + visible_handler on_visible; + active_handler on_active; + sync_draw_handler on_sync_draw; + flush_draw_handler on_flush_draw; + screen_updated_handler on_screen_updated; +}; + class LibWindowmanager { public: LibWindowmanager(); @@ -31,6 +81,7 @@ public: using handler_fun = std::function; /* DrawingArea name (usage: {layout}.{area}) */ + const std::string kDefaultArea = "normal.full"; const std::string kStrLayoutNormal = "normal"; const std::string kStrLayoutSplit = "split"; const std::string kStrAreaFull = "full"; @@ -61,8 +112,20 @@ public: }; int init(int port, char const *token); + int init(int port, const std::string &token); // WM API + int requestSurface(const char* role); + int requestSurfaceXDG(const char* role, unsigned ivi_id); + int activateWindow(const char* role, const char* area); + int activateWindow(const char* role); + int deactivateWindow(const char* role); + int endDraw(const char* role); + struct Screen getScreenInfo(); + int getAreaInfo(const char* role, Rect *out_rect); + void setEventHandler(const WMHandler& wmh); + + // Backward Compatible API int requestSurface(json_object *object); int requestSurfaceXDG(json_object *object); int activateWindow(json_object *object); @@ -70,16 +133,13 @@ public: int endDraw(json_object *object); int getDisplayInfo(json_object *object); int getAreaInfo(json_object *in_obj, json_object *out_obj); - int getAreaInfo(const char *label, json_object *out_obj); - void set_event_handler(enum EventType et, handler_fun f); - struct Impl; - // These APIs are deprecated, please use new API THIS_FUNCTION_IS_DEPRECATED(int activateSurface(json_object *object)); THIS_FUNCTION_IS_DEPRECATED(int deactivateSurface(json_object *object)); + class Impl; private: Impl *const d; -- cgit 1.2.3-korg