aboutsummaryrefslogtreecommitdiffstats
path: root/src/main.cpp
blob: 794d9af1cfab6049ed205a493881a89add510d58 (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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#include "util.h"

#include "ivi-controller-client-protocol.h"

#include <stdlib.h>
#include <string.h>

#include <wayland-client.h>

#include <map>
#include <memory>
#include <string>
#include <vector>

struct ivi_surface;
struct ivi_layer;

struct conn {
   wl_display *d;
   wl_registry *r;
   ivi_controller *c;
   std::vector<std::unique_ptr<wl_output, void (*)(wl_output *)>> outputs;
   std::map<uint32_t, std::unique_ptr<ivi_layer>> layers;
   std::map<uint32_t, std::unique_ptr<ivi_surface>> surfaces;

   ~conn();
};

struct ivi_surface {
   ivi_controller_surface *controller;
   uint32_t id;
   conn *con;
   ivi_surface(ivi_controller_surface *c, uint32_t i, conn *co)
      : controller(c), id(i), con(co) {}
   ~ivi_surface() { ivi_controller_surface_destroy(this->controller, 1); }
};

struct ivi_layer {
   ivi_controller_layer *controller;
   uint32_t id;
   conn *con;
   ivi_layer(ivi_controller_layer *c, uint32_t i, conn *co)
      : controller(c), id(i), con(co) {}
   ~ivi_layer() { ivi_controller_layer_destroy(this->controller, 1); }
};

conn::~conn() {
   this->layers.clear();
   this->surfaces.clear();
   ivi_controller_destroy(this->c);
   this->outputs.clear();
   wl_registry_destroy(this->r);
   wl_display_disconnect(this->d);
}

static ivi_controller_surface_listener cs_listener = {};

static ivi_controller_layer_listener cl_listener = {};

static void c_screen(void *data, struct ivi_controller *ivi_controller,
                     uint32_t id_screen, struct ivi_controller_screen *screen) {
   lognotice("ivi_controller @ %p screen %u (%x) @ %p", ivi_controller,
             id_screen, id_screen, screen);
}

static void c_layer(void *data, struct ivi_controller *ivi_controller,
                    uint32_t id_layer) {
   lognotice("ivi_controller @ %p layer %u (%x)", ivi_controller, id_layer,
             id_layer);
   auto c = static_cast<conn *>(data);
   auto i = std::make_unique<ivi_layer>(
      ivi_controller_layer_create(c->c, id_layer, 0, 0), id_layer, c);
   ivi_controller_layer_add_listener(i->controller, &cl_listener, i.get());
   c->layers[id_layer] = std::move(i);
}

static void c_surface(void *data, struct ivi_controller *ivi_controller,
                      uint32_t id_surface) {
   lognotice("ivi_controller @ %p surface %u (%x)", ivi_controller, id_surface,
             id_surface);
   auto c = static_cast<conn *>(data);
   auto i = std::make_unique<ivi_surface>(
      ivi_controller_surface_create(c->c, id_surface), id_surface, c);
   ivi_controller_surface_add_listener(i->controller, &cs_listener, i.get());
   c->surfaces[id_surface] = std::move(i);
}

static void c_error(void *data, struct ivi_controller *ivi_controller,
                    int32_t object_id, int32_t object_type, int32_t error_code,
                    const char *error_text) {
   lognotice("ivi_controller @ %p error o %i t %i c %i text %s", ivi_controller,
             object_id, object_type, error_code, error_text);
}

static struct ivi_controller_listener c_listener = {c_screen, c_layer,
                                                    c_surface, c_error};

static void o_geometry(void *data, struct wl_output *wl_output, int32_t x,
                       int32_t y, int32_t physical_width,
                       int32_t physical_height, int32_t subpixel,
                       const char *make, const char *model, int32_t transform) {
   lognotice("output @ %p x %i y %i w %i h %i spel %x make %s model %s tx %i",
             wl_output, x, y, physical_width, physical_height, subpixel, make,
             model, transform);
}

static void o_mode(void *data, struct wl_output *wl_output, uint32_t flags,
                   int32_t width, int32_t height, int32_t refresh) {
   lognotice("output @ %p mode f %x w %i h %i r %i", wl_output, flags, width,
             height, refresh);
}

static void o_done(void *data, struct wl_output *wl_output) {
   lognotice("output @ %p done");
}

static void o_scale(void *data, struct wl_output *wl_output, int32_t factor) {
   lognotice("output @ %p scale %i", wl_output, factor);
}

static struct wl_output_listener o_listener = {o_geometry, o_mode, o_done,
                                               o_scale};

static void r_global(void *data, struct wl_registry *r, uint32_t name,
                     char const *iface, uint32_t v) {
   struct conn *c = static_cast<conn *>(data);

   if (strcmp(iface, "ivi_controller") == 0) {
      c->c = static_cast<ivi_controller *>(
         wl_registry_bind(r, name, &ivi_controller_interface, v));
      ivi_controller_add_listener(c->c, &c_listener, c);
   } else if (strcmp(iface, "wl_output") == 0) {
      auto o = static_cast<wl_output *>(
         wl_registry_bind(r, name, &wl_output_interface, v));
      c->outputs.emplace_back(std::unique_ptr<wl_output, void (*)(wl_output *)>(
         o, wl_output_destroy));
      wl_output_add_listener(o, &o_listener, c);
   } else {
      lognotice("registry @ %p global n %u i %s v %u", r, name, iface, v);
   }
}

static void r_global_remove(void *data, struct wl_registry *r, uint32_t name) {}

static struct wl_registry_listener r_listener = {r_global, r_global_remove};

int main(int argc, char **argv) {
   lognotice("WinMan ver. %s", WINMAN_VERSION_STRING);

   if (!getenv("XDG_RUNTIME_DIR"))
      fatal("Environment variable XDG_RUNTIME_DIR not set");

   struct conn c = {};

   c.d = wl_display_connect(NULL);
   if (!c.d)
      fatal("Could not connect to compositor");
   c.r = wl_display_get_registry(c.d);
   wl_registry_add_listener(c.r, &r_listener, &c);

   // First level objects
   wl_display_roundtrip(c.d);
   // Second level objects
   wl_display_roundtrip(c.d);

   if (!c.c)
      fatal("ivi_controller global not available");

   // main loop

   return 0;
}