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