From e3cb94ef8869b075ab3c2e4af8851a87b24028ad Mon Sep 17 00:00:00 2001
From: patrick96 <p.ziegler96@gmail.com>
Date: Sat, 11 Sep 2021 15:14:17 +0200
Subject: [PATCH] Use uv timer for delayed screenshot

---
 include/components/bar.hpp        |  7 ++--
 include/components/controller.hpp | 26 +++-----------
 include/events/signal.hpp         |  6 ----
 include/events/signal_fwd.hpp     |  2 --
 src/components/bar.cpp            |  7 +---
 src/components/controller.cpp     | 60 +++++++++++++------------------
 src/components/renderer.cpp       |  2 +-
 7 files changed, 36 insertions(+), 74 deletions(-)

diff --git a/include/components/bar.hpp b/include/components/bar.hpp
index 886992e0..101e6c87 100644
--- a/include/components/bar.hpp
+++ b/include/components/bar.hpp
@@ -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,
                 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,
-                signals::ui::shade_window, signals::ui::unshade_window, signals::ui::dim_window
+            public signal_receiver<SIGN_PRIORITY_BAR, signals::ui::tick, signals::ui::shade_window,
+                signals::ui::unshade_window, signals::ui::dim_window
 #if WITH_XCURSOR
                 ,
                 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;
 
+  void start();
+
   void parse(string&& data, bool force = false);
 
   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::configure_notify& evt) override;
 
-  bool on(const signals::eventqueue::start&) override;
   bool on(const signals::ui::unshade_window&) override;
   bool on(const signals::ui::shade_window&) override;
   bool on(const signals::ui::tick&) override;
diff --git a/include/components/controller.hpp b/include/components/controller.hpp
index 6444843c..646f1057 100644
--- a/include/components/controller.hpp
+++ b/include/components/controller.hpp
@@ -35,11 +35,10 @@ using modulemap_t = std::map<alignment, vector<module_t>>;
 
 // }}}
 
-class controller
-    : public signal_receiver<SIGN_PRIORITY_CONTROLLER, signals::eventqueue::exit_reload,
-          signals::eventqueue::notify_change, signals::eventqueue::notify_forcechange, signals::eventqueue::check_state,
-          signals::ipc::action, signals::ipc::command, signals::ipc::hook, signals::ui::ready,
-          signals::ui::button_press, signals::ui::update_background> {
+class controller : public signal_receiver<SIGN_PRIORITY_CONTROLLER, signals::eventqueue::exit_reload,
+                       signals::eventqueue::notify_change, signals::eventqueue::notify_forcechange,
+                       signals::eventqueue::check_state, signals::ipc::action, signals::ipc::command,
+                       signals::ipc::hook, signals::ui::button_press, signals::ui::update_background> {
  public:
   using make_type = unique_ptr<controller>;
   static make_type make(unique_ptr<ipc>&& ipc);
@@ -61,6 +60,7 @@ class controller
   void ipc_cb(string buf);
   void confwatch_handler(const char* fname, int events, int status);
   void notifier_handler();
+  void screenshot_handler();
 
  protected:
   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::exit_reload& 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::ipc::action& evt) override;
   bool on(const signals::ipc::command& evt) override;
@@ -121,25 +120,10 @@ class controller
    */
   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
    */
   string m_inputdata;
-
-  /**
-   * \brief Misc threads
-   */
-  vector<std::thread> m_threads;
 };
 
 POLYBAR_NS_END
diff --git a/include/events/signal.hpp b/include/events/signal.hpp
index fca684d4..c9a4f694 100644
--- a/include/events/signal.hpp
+++ b/include/events/signal.hpp
@@ -50,9 +50,6 @@ namespace signals {
   }  // namespace detail
 
   namespace eventqueue {
-    struct start : public detail::base_signal<start> {
-      using base_type::base_type;
-    };
     struct exit_reload : public detail::base_signal<exit_reload> {
       using base_type::base_type;
     };
@@ -80,9 +77,6 @@ namespace signals {
   }  // namespace ipc
 
   namespace ui {
-    struct ready : public detail::base_signal<ready> {
-      using base_type::base_type;
-    };
     struct changed : public detail::base_signal<changed> {
       using base_type::base_type;
     };
diff --git a/include/events/signal_fwd.hpp b/include/events/signal_fwd.hpp
index c182a21f..ff51e8f4 100644
--- a/include/events/signal_fwd.hpp
+++ b/include/events/signal_fwd.hpp
@@ -15,7 +15,6 @@ namespace signals {
   }
 
   namespace eventqueue {
-    struct start;
     struct exit_reload;
     struct notify_change;
     struct notify_forcechange;
@@ -27,7 +26,6 @@ namespace signals {
     struct action;
   }  // namespace ipc
   namespace ui {
-    struct ready;
     struct changed;
     struct tick;
     struct button_press;
diff --git a/src/components/bar.cpp b/src/components/bar.cpp
index 3abe7e43..a33a9736 100644
--- a/src/components/bar.cpp
+++ b/src/components/bar.cpp
@@ -839,7 +839,7 @@ void bar::handle(const evt::configure_notify&) {
   m_sig.emit(signals::ui::update_geometry{});
 }
 
-bool bar::on(const signals::eventqueue::start&) {
+void bar::start() {
   m_log.trace("bar: Create renderer");
   m_renderer = renderer::make(m_opts, *m_action_ctxt);
   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->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_tray->setup(static_cast<const bar_settings&>(m_opts));
 
   broadcast_visibility();
-
-  return true;
 }
 
 bool bar::on(const signals::ui::unshade_window&) {
diff --git a/src/components/controller.cpp b/src/components/controller.cpp
index 7da87b40..074cdf96 100644
--- a/src/components/controller.cpp
+++ b/src/components/controller.cpp
@@ -61,8 +61,8 @@ controller::controller(connection& conn, signal_emitter& emitter, const logger&
   }
 
   // TODO deprecate both
-  m_swallow_limit = m_conf.deprecated("settings", "eventqueue-swallow", "throttle-output", m_swallow_limit);
-  m_swallow_update = m_conf.deprecated("settings", "eventqueue-swallow-time", "throttle-output-for", m_swallow_update);
+  m_conf.deprecated("settings", "eventqueue-swallow", "throttle-output", 0);
+  m_conf.deprecated("settings", "eventqueue-swallow-time", "throttle-output-for", 0);
 
   m_log.trace("controller: Setup user-defined modules");
   size_t created_modules{0};
@@ -88,13 +88,6 @@ controller::~controller() {
     auto cleanup_ms = time_util::measure([&module] { module->stop(); });
     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();
 }
 
+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
  */
@@ -281,15 +283,13 @@ void controller::read_events(bool confwatch) {
   m_log.info("Entering event loop (thread-id=%lu)", this_thread::get_id());
 
   if (!m_writeback) {
-    m_sig.emit(signals::eventqueue::start{});
-  } else {
-    // bypass the start eventqueue signal
-    m_sig.emit(signals::ui::ready{});
+    m_bar->start();
   }
 
   process_update(true);
 
   auto ipc_handle = std::unique_ptr<uv_pipe_t>(nullptr);
+  auto screenshot_timer_handle = std::unique_ptr<uv_timer_t>(nullptr);
 
   try {
     eloop = std::make_unique<eventloop>();
@@ -309,16 +309,24 @@ void controller::read_events(bool confwatch) {
 
     if (m_ipc) {
       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;
-      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_pipe_open, ipc_handle.get(), m_ipc->get_file_descriptor());
+      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>();
-    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;
 
+    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();
   } catch (const exception& err) {
     m_log.err("Fatal Error in eventloop: %s", err.what());
@@ -698,24 +706,6 @@ bool controller::on(const signals::eventqueue::check_state&) {
   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
  */
diff --git a/src/components/renderer.cpp b/src/components/renderer.cpp
index 6f10b127..34daad5a 100644
--- a/src/components/renderer.cpp
+++ b/src/components/renderer.cpp
@@ -408,7 +408,7 @@ void renderer::flush() {
   if (!m_snapshot_dst.empty()) {
     try {
       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) {
       m_log.err("Failed to write snapshot (err: %s)", err.what());
     }