replace qt event loop with epoll
This commit is contained in:
parent
dfae73b1c5
commit
31c09e24d6
132
src/main.cpp
132
src/main.cpp
@ -5,6 +5,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <sys/epoll.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/signalfd.h>
|
#include <sys/signalfd.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@ -14,10 +15,10 @@
|
|||||||
#include <list>
|
#include <list>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <QGuiApplication>
|
|
||||||
#include <QSocketNotifier>
|
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
#include <wayland-cursor.h>
|
#include <wayland-cursor.h>
|
||||||
|
#include <QGuiApplication>
|
||||||
|
#include <QString>
|
||||||
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
|
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
|
||||||
#include "xdg-shell-client-protocol.h"
|
#include "xdg-shell-client-protocol.h"
|
||||||
#include "net-tapesoftware-dwl-wm-unstable-v1-client-protocol.h"
|
#include "net-tapesoftware-dwl-wm-unstable-v1-client-protocol.h"
|
||||||
@ -44,10 +45,11 @@ struct Seat {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static void waylandFlush();
|
static void waylandFlush();
|
||||||
static void waylandWriteReady();
|
|
||||||
static void requireGlobal(const void *p, const char *name);
|
static void requireGlobal(const void *p, const char *name);
|
||||||
static void setupStatusFifo();
|
static void setupStatusFifo();
|
||||||
static void onStatus();
|
static void onStatus();
|
||||||
|
[[noreturn]] static void diesys(const char *why);
|
||||||
|
[[noreturn]] static void die(const char *why);
|
||||||
static void cleanup();
|
static void cleanup();
|
||||||
|
|
||||||
wl_display *display;
|
wl_display *display;
|
||||||
@ -65,9 +67,10 @@ static std::list<Monitor> monitors;
|
|||||||
static std::list<Seat> seats;
|
static std::list<Seat> seats;
|
||||||
static QString lastStatus;
|
static QString lastStatus;
|
||||||
static std::string statusFifoName;
|
static std::string statusFifoName;
|
||||||
|
static int epoll {-1};
|
||||||
|
static int displayFd {-1};
|
||||||
static int statusFifoFd {-1};
|
static int statusFifoFd {-1};
|
||||||
static int statusFifoWriter {-1};
|
static int statusFifoWriter {-1};
|
||||||
static QSocketNotifier *displayWriteNotifier;
|
|
||||||
static bool quitting {false};
|
static bool quitting {false};
|
||||||
|
|
||||||
void view(Monitor &m, const Arg &arg)
|
void view(Monitor &m, const Arg &arg)
|
||||||
@ -245,28 +248,27 @@ static void setupStatusFifo()
|
|||||||
auto result = mkfifo(path.c_str(), 0666);
|
auto result = mkfifo(path.c_str(), 0666);
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
auto fd = open(path.c_str(), O_CLOEXEC | O_NONBLOCK | O_RDONLY);
|
auto fd = open(path.c_str(), O_CLOEXEC | O_NONBLOCK | O_RDONLY);
|
||||||
if (fd == -1) {
|
if (fd < 0) {
|
||||||
perror("open status fifo reader");
|
diesys("open status fifo reader");
|
||||||
cleanup();
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
statusFifoName = path;
|
statusFifoName = path;
|
||||||
statusFifoFd = fd;
|
statusFifoFd = fd;
|
||||||
|
|
||||||
fd = open(path.c_str(), O_CLOEXEC | O_WRONLY);
|
fd = open(path.c_str(), O_CLOEXEC | O_WRONLY);
|
||||||
if (fd == -1) {
|
if (fd < 0) {
|
||||||
perror("open status fifo writer");
|
diesys("open status fifo writer");
|
||||||
cleanup();
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
statusFifoWriter = fd;
|
statusFifoWriter = fd;
|
||||||
|
|
||||||
auto statusNotifier = new QSocketNotifier(statusFifoFd, QSocketNotifier::Read);
|
epoll_event ev = {0};
|
||||||
statusNotifier->setEnabled(true);
|
ev.events = EPOLLIN;
|
||||||
QObject::connect(statusNotifier, &QSocketNotifier::activated, onStatus);
|
ev.data.fd = statusFifoFd;
|
||||||
|
if (epoll_ctl(epoll, EPOLL_CTL_ADD, statusFifoFd, &ev) < 0) {
|
||||||
|
diesys("epoll_ctl add status fifo");
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
} else if (errno != EEXIST) {
|
} else if (errno != EEXIST) {
|
||||||
perror("mkfifo");
|
diesys("mkfifo");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -341,52 +343,87 @@ int main(int argc, char **argv)
|
|||||||
sigaddset(&blockedsigs, SIGTERM);
|
sigaddset(&blockedsigs, SIGTERM);
|
||||||
sigprocmask(SIG_BLOCK, &blockedsigs, nullptr);
|
sigprocmask(SIG_BLOCK, &blockedsigs, nullptr);
|
||||||
|
|
||||||
QGuiApplication app(argc, argv);
|
QGuiApplication app {argc, argv};
|
||||||
QCoreApplication::setOrganizationName("tape software");
|
|
||||||
QCoreApplication::setOrganizationDomain("tapesoftware.net");
|
|
||||||
QCoreApplication::setApplicationName("somebar");
|
|
||||||
|
|
||||||
|
epoll_event epollEv = {0};
|
||||||
|
std::array<epoll_event, 5> epollEvents;
|
||||||
|
epoll = epoll_create1(EPOLL_CLOEXEC);
|
||||||
|
if (epoll < 0) {
|
||||||
|
diesys("epoll_create1");
|
||||||
|
}
|
||||||
int sfd = signalfd(-1, &blockedsigs, SFD_CLOEXEC | SFD_NONBLOCK);
|
int sfd = signalfd(-1, &blockedsigs, SFD_CLOEXEC | SFD_NONBLOCK);
|
||||||
if (sfd < 0) {
|
if (sfd < 0) {
|
||||||
perror("signalfd");
|
diesys("signalfd");
|
||||||
cleanup();
|
}
|
||||||
exit(1);
|
epollEv.events = EPOLLIN;
|
||||||
|
epollEv.data.fd = sfd;
|
||||||
|
if (epoll_ctl(epoll, EPOLL_CTL_ADD, sfd, &epollEv) < 0) {
|
||||||
|
diesys("epoll_ctl add signalfd");
|
||||||
}
|
}
|
||||||
QSocketNotifier signalNotifier {sfd, QSocketNotifier::Read};
|
|
||||||
QObject::connect(&signalNotifier, &QSocketNotifier::activated, []() { quitting = true; });
|
|
||||||
|
|
||||||
display = wl_display_connect(NULL);
|
display = wl_display_connect(nullptr);
|
||||||
if (!display) {
|
if (!display) {
|
||||||
fprintf(stderr, "Failed to connect to Wayland display\n");
|
die("Failed to connect to Wayland display");
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
displayFd = wl_display_get_fd(display);
|
||||||
|
|
||||||
auto registry = wl_display_get_registry(display);
|
auto registry = wl_display_get_registry(display);
|
||||||
wl_registry_add_listener(registry, ®istry_listener, nullptr);
|
wl_registry_add_listener(registry, ®istry_listener, nullptr);
|
||||||
wl_display_roundtrip(display);
|
wl_display_roundtrip(display);
|
||||||
onReady();
|
onReady();
|
||||||
|
|
||||||
QSocketNotifier displayReadNotifier(wl_display_get_fd(display), QSocketNotifier::Read);
|
epollEv.events = EPOLLIN;
|
||||||
displayReadNotifier.setEnabled(true);
|
epollEv.data.fd = displayFd;
|
||||||
QObject::connect(&displayReadNotifier, &QSocketNotifier::activated, [=]() {
|
if (epoll_ctl(epoll, EPOLL_CTL_ADD, displayFd, &epollEv) < 0) {
|
||||||
auto res = wl_display_dispatch(display);
|
diesys("epoll_ctl add wayland_display");
|
||||||
if (res < 0) {
|
|
||||||
perror("wl_display_dispatch");
|
|
||||||
cleanup();
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
displayWriteNotifier = new QSocketNotifier(wl_display_get_fd(display), QSocketNotifier::Write);
|
|
||||||
displayWriteNotifier->setEnabled(false);
|
|
||||||
QObject::connect(displayWriteNotifier, &QSocketNotifier::activated, waylandWriteReady);
|
|
||||||
|
|
||||||
while (!quitting) {
|
while (!quitting) {
|
||||||
waylandFlush();
|
waylandFlush();
|
||||||
app.processEvents(QEventLoop::WaitForMoreEvents);
|
auto res = epoll_wait(epoll, epollEvents.data(), epollEvents.size(), -1);
|
||||||
|
if (res < 0) {
|
||||||
|
if (errno != EINTR) {
|
||||||
|
diesys("epoll_wait");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (auto i=0; i<res; i++) {
|
||||||
|
auto &ev = epollEvents[i];
|
||||||
|
if (ev.data.fd == displayFd) {
|
||||||
|
if (ev.events & EPOLLIN) {
|
||||||
|
if (wl_display_dispatch(display) < 0) {
|
||||||
|
die("wl_display_dispatch");
|
||||||
|
}
|
||||||
|
} if (ev.events & EPOLLOUT) {
|
||||||
|
epollEv.events = EPOLLIN;
|
||||||
|
epollEv.data.fd = displayFd;
|
||||||
|
if (epoll_ctl(epoll, EPOLL_CTL_MOD, displayFd, &epollEv) < 0) {
|
||||||
|
diesys("epoll_ctl");
|
||||||
|
}
|
||||||
|
waylandFlush();
|
||||||
|
}
|
||||||
|
} else if (ev.data.fd == statusFifoFd) {
|
||||||
|
onStatus();
|
||||||
|
} else if (ev.data.fd == sfd) {
|
||||||
|
quitting = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
cleanup();
|
cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void die(const char *why) {
|
||||||
|
fprintf(stderr, "%s\n", why);
|
||||||
|
cleanup();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void diesys(const char *why) {
|
||||||
|
perror(why);
|
||||||
|
cleanup();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
void cleanup() {
|
void cleanup() {
|
||||||
if (!statusFifoName.empty()) {
|
if (!statusFifoName.empty()) {
|
||||||
unlink(statusFifoName.c_str());
|
unlink(statusFifoName.c_str());
|
||||||
@ -397,14 +434,15 @@ void waylandFlush()
|
|||||||
{
|
{
|
||||||
wl_display_dispatch_pending(display);
|
wl_display_dispatch_pending(display);
|
||||||
if (wl_display_flush(display) < 0 && errno == EAGAIN) {
|
if (wl_display_flush(display) < 0 && errno == EAGAIN) {
|
||||||
displayWriteNotifier->setEnabled(true);
|
epoll_event ev = {0};
|
||||||
|
ev.events = EPOLLIN | EPOLLOUT;
|
||||||
|
ev.data.fd = displayFd;
|
||||||
|
if (epoll_ctl(epoll, EPOLL_CTL_MOD, displayFd, &ev) < 0) {
|
||||||
|
diesys("epoll_ctl");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static void waylandWriteReady()
|
|
||||||
{
|
|
||||||
displayWriteNotifier->setEnabled(false);
|
|
||||||
waylandFlush();
|
|
||||||
}
|
|
||||||
static void requireGlobal(const void *p, const char *name)
|
static void requireGlobal(const void *p, const char *name)
|
||||||
{
|
{
|
||||||
if (p) return;
|
if (p) return;
|
||||||
|
Loading…
Reference in New Issue
Block a user