clang-tidy the place up
[staging/windowmanager.git] / src / main.cpp
1 #include "util.h"
2 #include "wayland.hpp"
3
4 #include <unistd.h>
5
6 #include <cstdlib>
7
8 #include <sys/poll.h>
9
10 struct conn {
11    std::vector<std::unique_ptr<wl::output>> outputs;
12    std::unique_ptr<genivi::controller> c;
13 };
14
15 namespace {
16 //       _               _                            _        ____
17 //   ___| |__   ___  ___| | __    _____   _____ _ __ | |_ ___ / /\ \
18 //  / __| '_ \ / _ \/ __| |/ /   / _ \ \ / / _ \ '_ \| __/ __| |  | |
19 // | (__| | | |  __/ (__|   <   |  __/\ V /  __/ | | | |_\__ \ |  | |
20 //  \___|_| |_|\___|\___|_|\_\___\___| \_/ \___|_| |_|\__|___/ |  | |
21 //                          |_____|                           \_\/_/
22 int check_events(struct wl::display &d, struct conn &c, int fd) {
23    struct pollfd pfd[2] = {{.fd = d.get_fd(), .events = POLLIN, .revents = 0},
24                            {.fd = fd, .events = POLLIN, .revents = 0}};
25
26    d.flush();
27
28    if (poll(pfd, fd != -1 ? 2 : 1, -1) != -1 && errno != EINTR) {
29       int ret = 0;
30
31       if ((pfd[0].revents & POLLIN) != 0) {
32          ret = d.dispatch();
33       }
34
35       if (ret == -1) {
36          return ret;
37       }
38
39       if (fd != -1 && ((pfd[1].revents & POLLIN) != 0)) {
40          char buf[256];
41
42          // read all there is ...
43          while (read(pfd[1].fd, buf, sizeof(buf)) == sizeof(buf)) {
44             ;
45          }
46
47          // Display current status
48          if (!c.c->surfaces.empty()) {
49             puts("Surfaces:");
50             for (auto const &i : c.c->surfaces) {
51                auto const &r = i.second->dst_rect;
52                auto const &s = i.second->size;
53                printf("%d [%ux%u] (%ux%u@%dx%d), ", i.first, s.w, s.h, r.w, r.h,
54                       r.x, r.y);
55             }
56             puts("\b\b ");
57          }
58
59          if (!c.c->layers.empty()) {
60             puts("Layers:");
61             for (auto const &i : c.c->layers) {
62                auto const &r = i.second->dst_rect;
63                auto const &s = i.second->size;
64                printf("%d [%ux%u] (%ux%u@%dx%d), ", i.first, s.w, s.h, r.w, r.h,
65                       r.x, r.y);
66             }
67             puts("\b\b ");
68          }
69       }
70    }
71
72    return 0;
73 }
74
75 //  _       _ _       _                         _    ____
76 // (_)_ __ (_) |_    | | __ _ _   _  ___  _   _| |_ / /\ \
77 // | | '_ \| | __|   | |/ _` | | | |/ _ \| | | | __| |  | |
78 // | | | | | | |_    | | (_| | |_| | (_) | |_| | |_| |  | |
79 // |_|_| |_|_|\__|___|_|\__,_|\__, |\___/ \__,_|\__| |  | |
80 //              |_____|       |___/                 \_\/_/
81 void init_layout(struct conn &c) {
82    auto &o = c.outputs.front();
83    auto &s = c.c->screens.begin()->second;
84    auto &layers = c.c->layers;
85
86    // XXX: Write output dimensions to ivi controller...
87    c.c->output_size = genivi::size{uint32_t(o->width), uint32_t(o->height)};
88
89    // Clear scene
90    layers.clear();
91
92    // Clear screen
93    s->clear();
94
95    // Setup our dummy scene...
96    c.c->layer_create(100, 0, 0);   // bottom layer, anything else
97    c.c->layer_create(1000, 0, 0);  // top layer, mandelbrot
98
99    auto &l100 = c.c->layers[100];
100    auto &l1k = c.c->layers[1000];
101
102    // Set layers fullscreen
103    l100->set_destination_rectangle(0, 0, o->width, o->height);
104    l1k->set_destination_rectangle(0, 0, o->width, o->height);
105    l100->set_visibility(1);
106    l1k->set_visibility(1);
107
108    // Add layers to screen
109    s->set_render_order({100, 1000});
110
111    c.c->commit_changes();
112    // Note: this does not flush the display!
113 }
114 }  // namespace
115
116 //                  _        ____
117 //  _ __ ___   __ _(_)_ __  / /\ \
118 // | '_ ` _ \ / _` | | '_ \| |  | |
119 // | | | | | | (_| | | | | | |  | |
120 // |_| |_| |_|\__,_|_|_| |_| |  | |
121 //                          \_\/_/
122 int main(int /*argc*/, char ** /*argv*/) {
123    lognotice("WinMan ver. %s", WINMAN_VERSION_STRING);
124
125    if (getenv("XDG_RUNTIME_DIR") == nullptr) {
126       fatal("Environment variable XDG_RUNTIME_DIR not set");
127    }
128
129    struct wl::display d {};
130    if (!d.ok()) {
131       fatal("Could not connect to compositor");
132    }
133
134    struct conn c {};
135
136    d.r.add_global_handler(
137       "ivi_controller", [&c](wl_registry *r, uint32_t name, uint32_t v) {
138          c.c = std::make_unique<genivi::controller>(r, name, v);
139       });
140
141    d.r.add_global_handler(
142       "wl_output", [&c](wl_registry *r, uint32_t name, uint32_t v) {
143          c.outputs.emplace_back(std::make_unique<wl::output>(r, name, v));
144       });
145
146    // First level objects
147    d.roundtrip();
148    // Second level objects
149    d.roundtrip();
150    // Third level objects
151    d.roundtrip();
152
153    if (!c.c) {
154       fatal("ivi_controller global not available");
155    }
156
157    if (c.outputs.empty()) {
158       fatal("no output was set up!");
159    }
160
161    init_layout(c);
162
163    while (check_events(d, c, STDIN_FILENO) != -1) {
164       c.c->execute_pending();
165       d.flush();
166    }
167
168    d.roundtrip();
169
170    return 0;
171 }