#include <unistd.h>
+#include <signal.h>
#include <sys/poll.h>
+#include <sys/signalfd.h>
-struct conn {
+#include <algorithm>
+
+struct connection {
std::vector<std::unique_ptr<wl::output>> outputs;
std::unique_ptr<genivi::controller> c;
};
-namespace {
-// _ _ _ ____
-// ___| |__ ___ ___| | __ _____ _____ _ __ | |_ ___ / /\ \
-// / __| '_ \ / _ \/ __| |/ / / _ \ \ / / _ \ '_ \| __/ __| | | |
-// | (__| | | | __/ (__| < | __/\ V / __/ | | | |_\__ \ | | |
-// \___|_| |_|\___|\___|_|\_\___\___| \_/ \___|_| |_|\__|___/ | | |
-// |_____| \_\/_/
-int check_events(struct wl::display &d, struct conn &c, int fd) {
- struct pollfd pfd[2] = {{.fd = d.get_fd(), .events = POLLIN, .revents = 0},
- {.fd = fd, .events = POLLIN, .revents = 0}};
-
- d.flush();
-
- if (poll(pfd, fd != -1 ? 2 : 1, -1) != -1 && errno != EINTR) {
- int ret = 0;
-
- if ((pfd[0].revents & POLLIN) != 0) {
- ret = d.dispatch();
- }
-
- if (ret == -1) {
- return ret;
- }
-
- if (fd != -1 && ((pfd[1].revents & POLLIN) != 0)) {
- char buf[256];
-
- // read all there is ...
- while (read(pfd[1].fd, buf, sizeof(buf)) == sizeof(buf)) {
- ;
- }
+// _ _ ____ _ _
+// ___| |_ _ __ _ _ ___| |_ | _ \ ___ | | | ___ _ __
+// / __| __| '__| | | |/ __| __| | |_) / _ \| | |/ _ \ '__|
+// \__ \ |_| | | |_| | (__| |_ | __/ (_) | | | __/ |
+// |___/\__|_| \__,_|\___|\__| |_| \___/|_|_|\___|_|
+//
+struct Poller {
+ std::vector<std::function<int(int)>> handlers;
+ std::vector<struct pollfd> pfds;
+
+ Poller() = default;
+ void add_fd(int fd, std::function<int(int)> handler);
+ int check_events();
+};
- // Display current status
- if (!c.c->surfaces.empty()) {
- puts("Surfaces:");
- for (auto const &i : c.c->surfaces) {
- auto const &r = i.second->dst_rect;
- auto const &s = i.second->size;
- printf("%d [%ux%u] (%ux%u@%dx%d), ", i.first, s.w, s.h, r.w, r.h,
- r.x, r.y);
- }
- puts("\b\b ");
- }
+void Poller::add_fd(int fd, std::function<int(int)> handler) {
+ pfds.emplace_back(pollfd{.fd = fd, .events = POLLIN, .revents = 0});
+ handlers.emplace_back(std::move(handler));
+}
- if (!c.c->layers.empty()) {
- puts("Layers:");
- for (auto const &i : c.c->layers) {
- auto const &r = i.second->dst_rect;
- auto const &s = i.second->size;
- printf("%d [%ux%u] (%ux%u@%dx%d), ", i.first, s.w, s.h, r.w, r.h,
- r.x, r.y);
+int Poller::check_events() {
+ int ret = 0;
+ if ((ret = poll(this->pfds.data(), this->pfds.size(), -1)) != -1 &&
+ errno != EINTR) {
+ for (unsigned i = 0; i < pfds.size(); i++) {
+ if (pfds[i].revents & POLLIN) {
+ if (handlers[i](pfds[i].fd) == -1) {
+ return -1;
}
- puts("\b\b ");
+ pfds[i].revents = 0;
+ pfds[i].events = POLLIN;
}
}
}
-
- return 0;
+ return ret;
}
+struct unique_fd {
+ int fd {-1};
+ unique_fd() = default;
+ explicit unique_fd(int f) : fd{f} {}
+ operator int() const { return fd; }
+ ~unique_fd() {
+ if (this->fd != -1)
+ close(this->fd);
+ }
+ unique_fd(unique_fd const &) = delete;
+ unique_fd &operator=(unique_fd const &) = delete;
+ unique_fd(unique_fd &&o) : fd(o.fd) { o.fd = -1; }
+ unique_fd &operator=(unique_fd &&o) {
+ std::swap(this->fd, o.fd);
+ return *this;
+ }
+};
+
+
+namespace {
// _ _ _ _ _ ____
// (_)_ __ (_) |_ | | __ _ _ _ ___ _ _| |_ / /\ \
// | | '_ \| | __| | |/ _` | | | |/ _ \| | | | __| | | |
// | | | | | | |_ | | (_| | |_| | (_) | |_| | |_| | | |
// |_|_| |_|_|\__|___|_|\__,_|\__, |\___/ \__,_|\__| | | |
// |_____| |___/ \_\/_/
-void init_layout(struct conn &c) {
+char const *init_layout(struct connection &c) {
+ if (!c.c) {
+ return "ivi_controller global not available";
+ }
+
+ if (c.outputs.empty()) {
+ return "no output was set up!";
+ }
+
auto &o = c.outputs.front();
auto &s = c.c->screens.begin()->second;
auto &layers = c.c->layers;
c.c->commit_changes();
// Note: this does not flush the display!
+
+ return nullptr;
}
} // namespace
fatal("Could not connect to compositor");
}
- struct conn c {};
+ struct connection c {};
+
+ d.r.add_global_handler(
+ "wl_output", [&c](wl_registry *r, uint32_t name, uint32_t v) {
+ c.outputs.emplace_back(std::make_unique<wl::output>(r, name, v));
+ });
d.r.add_global_handler(
"ivi_controller", [&c](wl_registry *r, uint32_t name, uint32_t v) {
c.c = std::make_unique<genivi::controller>(r, name, v);
- });
- d.r.add_global_handler(
- "wl_output", [&c](wl_registry *r, uint32_t name, uint32_t v) {
- c.outputs.emplace_back(std::make_unique<wl::output>(r, name, v));
+ // XXX: This protocol needs the output, so lets just add our mapping here...
+ c.c->add_proxy_to_id_mapping(c.outputs.back()->proxy.get(),
+ wl_proxy_get_id(
+ reinterpret_cast<struct wl_proxy *>(
+ c.outputs.back()->proxy.get())));
});
// First level objects
// Third level objects
d.roundtrip();
- if (!c.c) {
- fatal("ivi_controller global not available");
+ if (char const *e = init_layout(c)) {
+ fatal("Could not init layout: %s", e);
}
- if (c.outputs.empty()) {
- fatal("no output was set up!");
- }
-
- init_layout(c);
+ struct Poller p{};
+ p.add_fd(STDIN_FILENO, [&c](int fd) {
+ int buf;
+ ssize_t ret;
+ ret = read(fd, &buf, sizeof(buf));
+ c.c->debug_dump_current_status();
+ return ret == 0 ? -1 : 0;
+ });
+
+ p.add_fd(d.get_fd(), [&d](int fd) {
+ return d.dispatch();
+ });
+
+ sigset_t sset{};
+ sigemptyset(&sset);
+ sigaddset(&sset, SIGINT);
+ sigaddset(&sset, SIGTERM);
+
+ auto sfd = unique_fd(signalfd(-1, &sset, SFD_NONBLOCK | SFD_CLOEXEC));
+ sigprocmask(SIG_BLOCK, &sset, NULL);
+ p.add_fd(sfd.fd, [](int fd) {
+ struct signalfd_siginfo si;
+ while (read(fd, &si, sizeof(si)) == sizeof(si)) {
+ lognotice("Received signal %u", si.ssi_signo);
+ }
+ return -1;
+ });
- while (check_events(d, c, STDIN_FILENO) != -1) {
+ while ((d.flush(), p.check_events()) != -1) {
c.c->execute_pending();
- d.flush();
}
+ c.c->commit_changes();
d.roundtrip();
return 0;