aboutsummaryrefslogtreecommitdiffstats
path: root/src/main.cpp
blob: 5eb211cb41b7d4a976e7d55cc3ae2780d2d45816 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include "app.hpp"
#include "json_helper.hpp"
#include "util.hpp"
#include "wayland.hpp"

#include <algorithm>
#include <json.h>

extern "C" {
#include <afb/afb-binding.h>
#include <systemd/sd-event.h>
}

namespace {
struct afb_instance {
   std::unique_ptr<wl::display> display;
   wm::App app;

   afb_instance() : display{new wl::display}, app{this->display.get()} {}

   int init();
};

struct afb_instance *g_afb_instance;

int afb_instance::init() {
   if (!this->display->ok()) {
      return -1;
   }

   return this->app.init();
}

int display_event_callback(sd_event_source *evs, int /*fd*/, uint32_t events,
                           void * /*data*/) {
   if ((events & EPOLLHUP) != 0) {
      logerror("The compositor hung up, dying now.");
      delete g_afb_instance;
      g_afb_instance = nullptr;
      goto error;
   }

   if ((events & EPOLLIN) != 0u) {
      if (g_afb_instance->app.dispatch_events() == -1) {
         goto error;
      }
   }

   return 0;

error:
   sd_event_source_unref(evs);
   return -1;
}

//  _     _           _ _                 _       _ _    ____
// | |__ (_)_ __   __| (_)_ __   __ _    (_)_ __ (_) |_ / /\ \
// | '_ \| | '_ \ / _` | | '_ \ / _` |   | | '_ \| | __| |  | |
// | |_) | | | | | (_| | | | | | (_| |   | | | | | | |_| |  | |
// |_.__/|_|_| |_|\__,_|_|_| |_|\__, |___|_|_| |_|_|\__| |  | |
//                              |___/_____|             \_\/_/
int binding_init_() {
   lognotice("WinMan ver. %s", WINMAN_VERSION_STRING);

   if (g_afb_instance != nullptr) {
      logerror("Wayland context already initialized?");
      return 0;
   }

   if (getenv("XDG_RUNTIME_DIR") == nullptr) {
      logerror("Environment variable XDG_RUNTIME_DIR not set");
      goto error;
   }

   g_afb_instance = new afb_instance;
   if (g_afb_instance->init() == -1) {
      logerror("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) {
         logerror("Could not initialize afb_instance event handler: %d", -ret);
         goto error;
      }
   }

   atexit([] { delete g_afb_instance; });

   return 0;

error:
   delete g_afb_instance;
   g_afb_instance = nullptr;
   return -1;
}

int binding_init() noexcept {
   try {
      return binding_init_();
   } catch (std::exception &e) {
      logerror("Uncaught exception in binding_init(): %s", e.what());
   }
   return -1;
}

}  // namespace

#include "afb_binding_glue.inl"

extern "C" const struct afb_binding_v2 afbBindingV2 = {
   "winman", nullptr, nullptr, winman_verbs, nullptr, binding_init, nullptr, 1};