+// _ ___ _
+// ___| | __ _ ___ ___ |_ _|_ __ ___ _ __ | |
+// / __| |/ _` / __/ __| | || '_ ` _ \| '_ \| |
+// | (__| | (_| \__ \__ \ | || | | | | | |_) | |
+// \___|_|\__,_|___/___/ |___|_| |_| |_| .__/|_|
+// |_|
+class AFBClient::Impl {
+ friend class AFBClient;
+
+ // This is the AFBClient interface impl
+ int init(int port, char const *token);
+ int dispatch();
+
+ // WM API
+ int requestSurface(const char *label);
+ int activateSurface(const char *label);
+ int deactivateSurface(const char *label);
+ int endDraw(const char *label);
+
+ void set_event_handler(enum EventType et, handler_fun func);
+
+ Impl();
+ ~Impl();
+
+ struct afb_wsj1 *wsj1;
+ struct sd_event *loop;
+
+ std::set<std::string> labels;
+ std::map<EventType, handler_fun> handlers;
+
+ int api_call(const char *verb, json_object *object,
+ const std::function<void(bool, json_object *)> &onReply);
+ void dispatch_internal();
+
+public:
+ void event(char const *et, char const *label);
+};
+
+namespace {
+
+constexpr const int token_maxlen = 20;
+constexpr const char *const wmAPI = "winman";
+
+#ifdef NDEBUG
+#define TRACE()
+#define TRACEN(N)
+#else
+#define CONCAT_(X, Y) X##Y
+#define CONCAT(X, Y) CONCAT_(X, Y)
+
+#define TRACE() \
+ ScopeTrace __attribute__((unused)) CONCAT(trace_scope_, __LINE__)(__func__)
+#define TRACEN(N) \
+ ScopeTrace __attribute__((unused)) CONCAT(named_trace_scope_, __LINE__)(#N)
+
+struct ScopeTrace {
+ thread_local static int indent;
+ char const *f{};
+ explicit ScopeTrace(char const *func) : f(func) {
+ fprintf(stderr, "%*s%s -->\n", 2 * indent++, "", this->f);
+ }
+ ~ScopeTrace() { fprintf(stderr, "%*s%s <--\n", 2 * --indent, "", this->f); }
+};
+thread_local int ScopeTrace::indent = 0;
+#endif
+
+/* called when wsj1 receives a method invocation */
+void onCall(void *closure, const char *api, const char *verb,
+ struct afb_wsj1_msg *msg) {
+ TRACE();
+ UNUSED(closure);
+ UNUSED(verb);
+ UNUSED(api);
+ UNUSED(msg);
+}
+
+/* called when wsj1 receives an event */
+void onEvent(void *closure, const char *event, afb_wsj1_msg *msg) {
+ TRACE();
+ reinterpret_cast<AFBClient::Impl *>(closure)->event(
+ event, json_object_get_string(
+ json_object_object_get(afb_wsj1_msg_object_j(msg), "data")));
+}