Use uv timer for delayed screenshot

This commit is contained in:
patrick96 2021-09-11 15:14:17 +02:00 committed by Patrick Ziegler
parent 6ac5b7ebdd
commit e3cb94ef88
7 changed files with 36 additions and 74 deletions

View File

@ -55,8 +55,8 @@ inline double geom_format_to_pixels(std::string str, double max) {
class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::property_notify, evt::enter_notify, class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::property_notify, evt::enter_notify,
evt::leave_notify, evt::motion_notify, evt::destroy_notify, evt::client_message, evt::configure_notify>, evt::leave_notify, evt::motion_notify, evt::destroy_notify, evt::client_message, evt::configure_notify>,
public signal_receiver<SIGN_PRIORITY_BAR, signals::eventqueue::start, signals::ui::tick, public signal_receiver<SIGN_PRIORITY_BAR, signals::ui::tick, signals::ui::shade_window,
signals::ui::shade_window, signals::ui::unshade_window, signals::ui::dim_window signals::ui::unshade_window, signals::ui::dim_window
#if WITH_XCURSOR #if WITH_XCURSOR
, ,
signals::ui::cursor_change signals::ui::cursor_change
@ -73,6 +73,8 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
const bar_settings settings() const; const bar_settings settings() const;
void start();
void parse(string&& data, bool force = false); void parse(string&& data, bool force = false);
void hide(); void hide();
@ -98,7 +100,6 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
void handle(const evt::property_notify& evt) override; void handle(const evt::property_notify& evt) override;
void handle(const evt::configure_notify& evt) override; void handle(const evt::configure_notify& evt) override;
bool on(const signals::eventqueue::start&) override;
bool on(const signals::ui::unshade_window&) override; bool on(const signals::ui::unshade_window&) override;
bool on(const signals::ui::shade_window&) override; bool on(const signals::ui::shade_window&) override;
bool on(const signals::ui::tick&) override; bool on(const signals::ui::tick&) override;

View File

@ -35,11 +35,10 @@ using modulemap_t = std::map<alignment, vector<module_t>>;
// }}} // }}}
class controller class controller : public signal_receiver<SIGN_PRIORITY_CONTROLLER, signals::eventqueue::exit_reload,
: public signal_receiver<SIGN_PRIORITY_CONTROLLER, signals::eventqueue::exit_reload, signals::eventqueue::notify_change, signals::eventqueue::notify_forcechange,
signals::eventqueue::notify_change, signals::eventqueue::notify_forcechange, signals::eventqueue::check_state, signals::eventqueue::check_state, signals::ipc::action, signals::ipc::command,
signals::ipc::action, signals::ipc::command, signals::ipc::hook, signals::ui::ready, signals::ipc::hook, signals::ui::button_press, signals::ui::update_background> {
signals::ui::button_press, signals::ui::update_background> {
public: public:
using make_type = unique_ptr<controller>; using make_type = unique_ptr<controller>;
static make_type make(unique_ptr<ipc>&& ipc); static make_type make(unique_ptr<ipc>&& ipc);
@ -61,6 +60,7 @@ class controller
void ipc_cb(string buf); void ipc_cb(string buf);
void confwatch_handler(const char* fname, int events, int status); void confwatch_handler(const char* fname, int events, int status);
void notifier_handler(); void notifier_handler();
void screenshot_handler();
protected: protected:
void read_events(bool confwatch); void read_events(bool confwatch);
@ -71,7 +71,6 @@ class controller
bool on(const signals::eventqueue::notify_forcechange& evt) override; bool on(const signals::eventqueue::notify_forcechange& evt) override;
bool on(const signals::eventqueue::exit_reload& evt) override; bool on(const signals::eventqueue::exit_reload& evt) override;
bool on(const signals::eventqueue::check_state& evt) override; bool on(const signals::eventqueue::check_state& evt) override;
bool on(const signals::ui::ready& evt) override;
bool on(const signals::ui::button_press& evt) override; bool on(const signals::ui::button_press& evt) override;
bool on(const signals::ipc::action& evt) override; bool on(const signals::ipc::action& evt) override;
bool on(const signals::ipc::command& evt) override; bool on(const signals::ipc::command& evt) override;
@ -121,25 +120,10 @@ class controller
*/ */
modulemap_t m_blocks; modulemap_t m_blocks;
/**
* \brief Maximum number of subsequent events to swallow
*/
size_t m_swallow_limit{5U};
/**
* \brief Time to wait for subsequent events
*/
std::chrono::milliseconds m_swallow_update{10};
/** /**
* \brief Input data * \brief Input data
*/ */
string m_inputdata; string m_inputdata;
/**
* \brief Misc threads
*/
vector<std::thread> m_threads;
}; };
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -50,9 +50,6 @@ namespace signals {
} // namespace detail } // namespace detail
namespace eventqueue { namespace eventqueue {
struct start : public detail::base_signal<start> {
using base_type::base_type;
};
struct exit_reload : public detail::base_signal<exit_reload> { struct exit_reload : public detail::base_signal<exit_reload> {
using base_type::base_type; using base_type::base_type;
}; };
@ -80,9 +77,6 @@ namespace signals {
} // namespace ipc } // namespace ipc
namespace ui { namespace ui {
struct ready : public detail::base_signal<ready> {
using base_type::base_type;
};
struct changed : public detail::base_signal<changed> { struct changed : public detail::base_signal<changed> {
using base_type::base_type; using base_type::base_type;
}; };

View File

@ -15,7 +15,6 @@ namespace signals {
} }
namespace eventqueue { namespace eventqueue {
struct start;
struct exit_reload; struct exit_reload;
struct notify_change; struct notify_change;
struct notify_forcechange; struct notify_forcechange;
@ -27,7 +26,6 @@ namespace signals {
struct action; struct action;
} // namespace ipc } // namespace ipc
namespace ui { namespace ui {
struct ready;
struct changed; struct changed;
struct tick; struct tick;
struct button_press; struct button_press;

View File

@ -839,7 +839,7 @@ void bar::handle(const evt::configure_notify&) {
m_sig.emit(signals::ui::update_geometry{}); m_sig.emit(signals::ui::update_geometry{});
} }
bool bar::on(const signals::eventqueue::start&) { void bar::start() {
m_log.trace("bar: Create renderer"); m_log.trace("bar: Create renderer");
m_renderer = renderer::make(m_opts, *m_action_ctxt); m_renderer = renderer::make(m_opts, *m_action_ctxt);
m_opts.window = m_renderer->window(); m_opts.window = m_renderer->window();
@ -871,15 +871,10 @@ bool bar::on(const signals::eventqueue::start&) {
m_renderer->begin(m_opts.inner_area()); m_renderer->begin(m_opts.inner_area());
m_renderer->end(); m_renderer->end();
m_sig.emit(signals::ui::ready{});
// TODO: tray manager could run this internally on ready event
m_log.trace("bar: Setup tray manager"); m_log.trace("bar: Setup tray manager");
m_tray->setup(static_cast<const bar_settings&>(m_opts)); m_tray->setup(static_cast<const bar_settings&>(m_opts));
broadcast_visibility(); broadcast_visibility();
return true;
} }
bool bar::on(const signals::ui::unshade_window&) { bool bar::on(const signals::ui::unshade_window&) {

View File

@ -61,8 +61,8 @@ controller::controller(connection& conn, signal_emitter& emitter, const logger&
} }
// TODO deprecate both // TODO deprecate both
m_swallow_limit = m_conf.deprecated("settings", "eventqueue-swallow", "throttle-output", m_swallow_limit); m_conf.deprecated("settings", "eventqueue-swallow", "throttle-output", 0);
m_swallow_update = m_conf.deprecated("settings", "eventqueue-swallow-time", "throttle-output-for", m_swallow_update); m_conf.deprecated("settings", "eventqueue-swallow-time", "throttle-output-for", 0);
m_log.trace("controller: Setup user-defined modules"); m_log.trace("controller: Setup user-defined modules");
size_t created_modules{0}; size_t created_modules{0};
@ -88,13 +88,6 @@ controller::~controller() {
auto cleanup_ms = time_util::measure([&module] { module->stop(); }); auto cleanup_ms = time_util::measure([&module] { module->stop(); });
m_log.info("Deconstruction of %s took %lu ms.", module_name, cleanup_ms); m_log.info("Deconstruction of %s took %lu ms.", module_name, cleanup_ms);
} }
m_log.trace("controller: Joining threads");
for (auto&& t : m_threads) {
if (t.joinable()) {
t.join();
}
}
} }
/** /**
@ -274,6 +267,15 @@ static void notifier_cb_wrapper(uv_async_t* handle) {
static_cast<controller*>(handle->data)->notifier_handler(); static_cast<controller*>(handle->data)->notifier_handler();
} }
void controller::screenshot_handler() {
m_sig.emit(signals::ui::request_snapshot{move(m_snapshot_dst)});
trigger_update(true);
}
static void screenshot_cb_wrapper(uv_timer_t* handle) {
static_cast<controller*>(handle->data)->screenshot_handler();
}
/** /**
* Read events from configured file descriptors * Read events from configured file descriptors
*/ */
@ -281,15 +283,13 @@ void controller::read_events(bool confwatch) {
m_log.info("Entering event loop (thread-id=%lu)", this_thread::get_id()); m_log.info("Entering event loop (thread-id=%lu)", this_thread::get_id());
if (!m_writeback) { if (!m_writeback) {
m_sig.emit(signals::eventqueue::start{}); m_bar->start();
} else {
// bypass the start eventqueue signal
m_sig.emit(signals::ui::ready{});
} }
process_update(true); process_update(true);
auto ipc_handle = std::unique_ptr<uv_pipe_t>(nullptr); auto ipc_handle = std::unique_ptr<uv_pipe_t>(nullptr);
auto screenshot_timer_handle = std::unique_ptr<uv_timer_t>(nullptr);
try { try {
eloop = std::make_unique<eventloop>(); eloop = std::make_unique<eventloop>();
@ -309,16 +309,24 @@ void controller::read_events(bool confwatch) {
if (m_ipc) { if (m_ipc) {
ipc_handle = std::make_unique<uv_pipe_t>(); ipc_handle = std::make_unique<uv_pipe_t>();
uv_pipe_init(loop, ipc_handle.get(), false); UV(uv_pipe_init, loop, ipc_handle.get(), false);
ipc_handle->data = this; ipc_handle->data = this;
uv_pipe_open(ipc_handle.get(), m_ipc->get_file_descriptor()); UV(uv_pipe_open, ipc_handle.get(), m_ipc->get_file_descriptor());
uv_read_start((uv_stream_t*)ipc_handle.get(), ipc_alloc_cb, ipc_read_cb_wrapper); UV(uv_read_start, (uv_stream_t*)ipc_handle.get(), ipc_alloc_cb, ipc_read_cb_wrapper);
} }
m_notifier = std::make_unique<uv_async_t>(); m_notifier = std::make_unique<uv_async_t>();
uv_async_init(loop, m_notifier.get(), notifier_cb_wrapper); UV(uv_async_init, loop, m_notifier.get(), notifier_cb_wrapper);
m_notifier->data = this; m_notifier->data = this;
if (!m_snapshot_dst.empty()) {
screenshot_timer_handle = std::make_unique<uv_timer_t>();
UV(uv_timer_init, loop, screenshot_timer_handle.get());
screenshot_timer_handle->data = this;
// Trigger a screenshot after 3 seconds
UV(uv_timer_start, screenshot_timer_handle.get(), screenshot_cb_wrapper, 3000, 0);
}
eloop->run(); eloop->run();
} catch (const exception& err) { } catch (const exception& err) {
m_log.err("Fatal Error in eventloop: %s", err.what()); m_log.err("Fatal Error in eventloop: %s", err.what());
@ -698,24 +706,6 @@ bool controller::on(const signals::eventqueue::check_state&) {
return true; return true;
} }
/**
* Process ui ready event
*/
bool controller::on(const signals::ui::ready&) {
trigger_update(true);
if (!m_snapshot_dst.empty()) {
m_threads.emplace_back(thread([&] {
this_thread::sleep_for(3s);
m_sig.emit(signals::ui::request_snapshot{move(m_snapshot_dst)});
trigger_update(true);
}));
}
// let the event bubble
return false;
}
/** /**
* Process ui button press event * Process ui button press event
*/ */

View File

@ -408,7 +408,7 @@ void renderer::flush() {
if (!m_snapshot_dst.empty()) { if (!m_snapshot_dst.empty()) {
try { try {
m_surface->write_png(m_snapshot_dst); m_surface->write_png(m_snapshot_dst);
m_log.info("Successfully wrote %s", m_snapshot_dst); m_log.notice("Successfully wrote %s", m_snapshot_dst);
} catch (const exception& err) { } catch (const exception& err) {
m_log.err("Failed to write snapshot (err: %s)", err.what()); m_log.err("Failed to write snapshot (err: %s)", err.what());
} }