2021-02-20 20:26:45 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <uv.h>
|
|
|
|
|
2021-03-10 23:09:06 +00:00
|
|
|
#include <stdexcept>
|
|
|
|
|
2021-02-20 20:26:45 +00:00
|
|
|
#include "common.hpp"
|
|
|
|
|
|
|
|
POLYBAR_NS
|
|
|
|
|
2021-03-10 23:09:06 +00:00
|
|
|
/**
|
|
|
|
* Runs any libuv function with an integer error code return value and throws an
|
|
|
|
* exception on error.
|
|
|
|
*/
|
|
|
|
#define UV(fun, ...) \
|
|
|
|
int res = fun(__VA_ARGS__); \
|
|
|
|
if (res < 0) { \
|
|
|
|
throw std::runtime_error("libuv error for '" #fun "': "s + uv_strerror(res)); \
|
|
|
|
}
|
|
|
|
|
2021-03-01 23:00:24 +00:00
|
|
|
template <class H, class... Args>
|
|
|
|
struct cb_helper {
|
|
|
|
std::function<void(Args...)> func;
|
|
|
|
|
|
|
|
static void callback(H* context, Args... args) {
|
|
|
|
const auto unpackedThis = static_cast<const cb_helper*>(context->data);
|
|
|
|
return unpackedThis->func(std::forward<Args>(args)...);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-03-10 23:36:03 +00:00
|
|
|
template <typename H, typename... Args>
|
|
|
|
struct UVHandle {
|
|
|
|
UVHandle(std::function<void(Args...)> fun) {
|
|
|
|
handle = std::make_unique<H>();
|
|
|
|
cb = cb_helper<H, Args...>{fun};
|
2021-03-01 23:00:24 +00:00
|
|
|
handle->data = &cb;
|
2021-03-10 23:36:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<H> handle;
|
|
|
|
cb_helper<H, Args...> cb;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct SignalHandle : public UVHandle<uv_signal_t, int> {
|
|
|
|
SignalHandle(uv_loop_t* loop, std::function<void(int)> fun) : UVHandle(fun) {
|
|
|
|
UV(uv_signal_init, loop, handle.get());
|
2021-03-01 23:00:24 +00:00
|
|
|
};
|
2021-03-10 23:36:03 +00:00
|
|
|
};
|
2021-03-01 23:00:24 +00:00
|
|
|
|
2021-03-10 23:36:03 +00:00
|
|
|
struct PollHandle : public UVHandle<uv_poll_t, int, int> {
|
|
|
|
// TODO wrap callback and handle negative status
|
|
|
|
PollHandle(uv_loop_t* loop, int fd, std::function<void(int, int)> fun) : UVHandle(fun) {
|
|
|
|
UV(uv_poll_init, loop, handle.get(), fd);
|
|
|
|
};
|
2021-03-01 23:00:24 +00:00
|
|
|
};
|
|
|
|
|
2021-02-20 20:26:45 +00:00
|
|
|
class eventloop {
|
|
|
|
public:
|
|
|
|
eventloop();
|
|
|
|
~eventloop();
|
|
|
|
|
|
|
|
void run();
|
|
|
|
|
|
|
|
void stop();
|
|
|
|
|
|
|
|
/**
|
2021-03-01 23:00:24 +00:00
|
|
|
* TODO make protected
|
2021-02-20 20:26:45 +00:00
|
|
|
*/
|
|
|
|
uv_loop_t* get() const {
|
|
|
|
return m_loop.get();
|
|
|
|
}
|
|
|
|
|
2021-03-01 23:00:24 +00:00
|
|
|
void signal_handler(int signum, std::function<void(int)> fun) {
|
|
|
|
auto handle = std::make_unique<SignalHandle>(get(), fun);
|
2021-03-10 23:09:06 +00:00
|
|
|
UV(uv_signal_start, handle->handle.get(), &handle->cb.callback, signum);
|
2021-03-01 23:00:24 +00:00
|
|
|
m_sig_handles.push_back(std::move(handle));
|
|
|
|
}
|
|
|
|
|
2021-03-10 23:36:03 +00:00
|
|
|
void poll_handler(int events, int fd, std::function<void(int, int)> fun) {
|
|
|
|
auto handle = std::make_unique<PollHandle>(get(), fd, fun);
|
|
|
|
UV(uv_poll_start, handle->handle.get(), events, &handle->cb.callback);
|
|
|
|
m_poll_handles.push_back(std::move(handle));
|
|
|
|
}
|
|
|
|
|
2021-03-01 23:00:24 +00:00
|
|
|
protected:
|
|
|
|
template <typename H, typename T, typename... Args, void (T::*F)(Args...)>
|
|
|
|
static void generic_cb(H* handle, Args&&... args) {
|
|
|
|
(static_cast<T*>(handle->data).*F)(std::forward<Args>(args)...);
|
|
|
|
}
|
|
|
|
|
2021-02-20 20:26:45 +00:00
|
|
|
private:
|
|
|
|
std::unique_ptr<uv_loop_t> m_loop{nullptr};
|
2021-03-01 23:00:24 +00:00
|
|
|
|
|
|
|
vector<std::unique_ptr<SignalHandle>> m_sig_handles;
|
2021-03-10 23:36:03 +00:00
|
|
|
vector<std::unique_ptr<PollHandle>> m_poll_handles;
|
2021-02-20 20:26:45 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
POLYBAR_NS_END
|