glue: renamed output files to better represent their actual purpose
[staging/windowmanager.git] / src / main.cpp
1 #include "json_helper.hpp"
2 #include "util.hpp"
3 #include "wayland.hpp"
4 #include "app.hpp"
5
6 #include <algorithm>
7 #include <json.h>
8
9 extern "C" {
10 #include <afb/afb-binding.h>
11 #include <systemd/sd-event.h>
12 }
13
14 namespace {
15 struct afb_instance {
16    std::unique_ptr<wl::display> display;
17    wm::App app;
18
19    afb_instance() : display{new wl::display}, app{this->display.get()} {}
20
21    int init();
22 };
23
24 struct afb_instance *g_afb_instance;
25
26 int afb_instance::init() {
27    if (!this->display->ok()) {
28       return -1;
29    }
30
31    return this->app.init();
32 }
33
34 int display_event_callback(sd_event_source *evs, int fd, uint32_t events,
35                            void *data) {
36    if ((events & EPOLLHUP) != 0) {
37       logerror("The compositor hung up, dying now.");
38       delete g_afb_instance;
39       g_afb_instance = nullptr;
40       goto error;
41    }
42
43    if (events & EPOLLIN) {
44        if (g_afb_instance->app.dispatch_events() == -1) {
45           goto error;
46        }
47    }
48
49    return 0;
50
51 error:
52    sd_event_source_unref(evs);
53    return -1;
54 }
55
56 //  _     _           _ _                 _       _ _    ____
57 // | |__ (_)_ __   __| (_)_ __   __ _    (_)_ __ (_) |_ / /\ \
58 // | '_ \| | '_ \ / _` | | '_ \ / _` |   | | '_ \| | __| |  | |
59 // | |_) | | | | | (_| | | | | | (_| |   | | | | | | |_| |  | |
60 // |_.__/|_|_| |_|\__,_|_|_| |_|\__, |___|_|_| |_|_|\__| |  | |
61 //                              |___/_____|             \_\/_/
62 int binding_init_() {
63    lognotice("WinMan ver. %s", WINMAN_VERSION_STRING);
64
65    if (g_afb_instance != nullptr) {
66       logerror("Wayland context already initialized?");
67       return 0;
68    }
69
70    if (getenv("XDG_RUNTIME_DIR") == nullptr) {
71       logerror("Environment variable XDG_RUNTIME_DIR not set");
72       goto error;
73    }
74
75    g_afb_instance = new afb_instance;
76    if (g_afb_instance->init() == -1) {
77       logerror("Could not connect to compositor");
78       goto error;
79    }
80
81    {
82       int ret = sd_event_add_io(afb_daemon_get_event_loop(), nullptr,
83                                 g_afb_instance->display->get_fd(), EPOLLIN,
84                                 display_event_callback, g_afb_instance);
85       if (ret < 0) {
86          logerror("Could not initialize afb_instance event handler: %d", -ret);
87          goto error;
88       }
89    }
90
91    atexit([] { delete g_afb_instance; });
92
93    return 0;
94
95 error:
96    delete g_afb_instance;
97    g_afb_instance = nullptr;
98    return -1;
99 }
100
101 int binding_init() noexcept {
102    try {
103       return binding_init_();
104    } catch (std::exception &e) {
105       logerror("Uncaught exception in binding_init(): %s", e.what());
106    }
107    return -1;
108 }
109
110 } // namespace
111
112 #include "afb_binding_glue.inl"
113
114 extern "C" const struct afb_binding_v2 afbBindingV2 = {
115    "winman", NULL, NULL, winman_verbs, NULL, binding_init, NULL, 1};