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