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