diff --git a/include/components/eventloop.hpp b/include/components/eventloop.hpp index 1a3610aa..7c1908e2 100644 --- a/include/components/eventloop.hpp +++ b/include/components/eventloop.hpp @@ -390,12 +390,27 @@ namespace eventloop { cb_connect connect_callback; }; + class PrepareHandle : public Handle { + public: + using Handle::Handle; + using cb = cb_void; + + void init(); + void start(cb user_cb); + + private: + static void connect_cb(uv_connect_t* req, int status); + + cb callback; + }; + class loop : public non_copyable_mixin, public non_movable_mixin { public: loop(); ~loop(); void run(); void stop(); + uint64_t now() const; template H& handle(Args... args) { @@ -404,13 +419,12 @@ namespace eventloop { return ptr->leak(std::move(ptr)); } - protected: uv_loop_t* get() const; private: std::unique_ptr m_loop{nullptr}; }; -} // namespace eventloop +} // namespace eventloop POLYBAR_NS_END diff --git a/lib/xpp b/lib/xpp index 7a9960bb..343dc77d 160000 --- a/lib/xpp +++ b/lib/xpp @@ -1 +1 @@ -Subproject commit 7a9960bbb912f0ed66929c978aaeb1c30acf4bfd +Subproject commit 343dc77d50bedab3c84b6e7cab70e1af2309eb0e diff --git a/src/components/controller.cpp b/src/components/controller.cpp index ba00ef1a..9fff6adb 100644 --- a/src/components/controller.cpp +++ b/src/components/controller.cpp @@ -171,7 +171,7 @@ void controller::conn_cb() { } shared_ptr evt{}; - while ((evt = shared_ptr(xcb_poll_for_event(m_connection), free)) != nullptr) { + while ((evt = m_connection.poll_for_event()) != nullptr) { try { m_connection.dispatch_event(evt); } catch (xpp::connection_error& err) { @@ -247,14 +247,25 @@ void controller::read_events(bool confwatch) { m_log.info("Entering event loop (thread-id=%lu)", this_thread::get_id()); try { - auto& poll_handle = m_loop.handle(m_connection.get_file_descriptor()); - poll_handle.start( + auto& x_poll_handle = m_loop.handle(m_connection.get_file_descriptor()); + x_poll_handle.start( UV_READABLE, [this](const auto&) { conn_cb(); }, [this](const auto& e) { m_log.err("libuv error while polling X connection: "s + uv_strerror(e.status)); stop(false); }); + auto& x_prepare_handle = m_loop.handle(); + x_prepare_handle.start([this]() { + /* + * We have to also handle events in the prepare handle (which runs right + * before polling for IO) to process any already queued X events which + * wouldn't trigger the uv_poll handle. + */ + conn_cb(); + m_connection.flush(); + }); + for (auto s : {SIGINT, SIGQUIT, SIGTERM, SIGUSR1, SIGALRM}) { auto& signal_handle = m_loop.handle(); signal_handle.start(s, [this](const auto& e) { signal_handler(e.signum); }); diff --git a/src/components/eventloop.cpp b/src/components/eventloop.cpp index 623e3994..e48f7029 100644 --- a/src/components/eventloop.cpp +++ b/src/components/eventloop.cpp @@ -38,6 +38,9 @@ namespace eventloop { case UV_NAMED_PIPE: static_cast(handle->data)->close(); break; + case UV_PREPARE: + static_cast(handle->data)->close(); + break; default: assert(false); } @@ -157,6 +160,17 @@ namespace eventloop { } // }}} + // PrepareHandle {{{ + void PrepareHandle::init() { + UV(uv_prepare_init, loop(), get()); + } + + void PrepareHandle::start(cb user_cb) { + this->callback = user_cb; + UV(uv_prepare_start, get(), void_event_cb<&PrepareHandle::callback>); + } + // }}} + // eventloop {{{ static void close_walk_cb(uv_handle_t* handle, void*) { if (!uv_is_closing(handle)) { @@ -201,11 +215,15 @@ namespace eventloop { uv_stop(m_loop.get()); } + uint64_t loop::now() const { + return uv_now(m_loop.get()); + } + uv_loop_t* loop::get() const { return m_loop.get(); } // }}} -} // namespace eventloop +} // namespace eventloop POLYBAR_NS_END