From 8afd5b71df03785aaab71132dc3791cdcf2f813a Mon Sep 17 00:00:00 2001
From: Patrick Ziegler
Date: Mon, 27 Sep 2021 17:35:45 +0200
Subject: [PATCH] Integrate bar taskqueue into eventloop (#2510)
* Remove DEBUG_SHADED
Was disabled by default AND behind an #if 0
* Make TimerHandle expose more libuv functions
* Prepare for moving double clicks into eventloop
* Make eventloop available to bar
* Remove bar mutex
Everything in the bar is now in the same thread
* Move double-click handling to eventloop
* Extract double click deferred function into method
* Stop throttling clicks
* Increase double click interval to 400 and add option
double-click-interval in the bar section
Closes #1441
* Implement dimming using timer handles
* Remove taskqueue
* Remove unused dependencies
* Cleanup & Comments
---
CHANGELOG.md | 11 +-
cmake/05-summary.cmake | 1 -
include/components/bar.hpp | 31 ++--
include/components/controller.hpp | 10 +-
include/components/eventloop.hpp | 19 ++-
include/components/taskqueue.hpp | 62 --------
include/components/types.hpp | 21 ++-
include/events/signal.hpp | 9 --
include/events/signal_fwd.hpp | 3 -
include/settings.hpp.cmake | 1 -
src/CMakeLists.txt | 1 -
src/components/bar.cpp | 256 +++++++-----------------------
src/components/controller.cpp | 46 +++---
src/components/eventloop.cpp | 18 ++-
src/components/renderer.cpp | 19 ---
src/components/taskqueue.cpp | 109 -------------
src/main.cpp | 3 +-
src/utils/env.cpp | 7 +-
18 files changed, 156 insertions(+), 471 deletions(-)
delete mode 100644 include/components/taskqueue.hpp
delete mode 100644 src/components/taskqueue.cpp
diff --git a/CHANGELOG.md b/CHANGELOG.md
index eab17012..6aa79782 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -59,10 +59,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
triggers if they happen directly after one another, leading to only a single
bar update.
+### Removed
+- `DEBUG_SHADED` cmake variable and its associated functionality.
+
### Added
- `drawtypes/ramp`: Add support for ramp weights.
([1750](https://github.com/polybar/polybar/issues/1750))
-- `internal/memory`: New tokens `%used%`, `%free%`, `%total%`, `%swap_total%`,
+- `internal/memory`: New tokens `%used%`, `%free%`, `%total%`, `%swap_total%`,
`%swap_free%`, and `%swap_used%` that automatically switch between MiB and GiB
when below or above 1GiB.
([`2472`](https://github.com/polybar/polybar/issues/2472))
@@ -114,6 +117,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
([`#2427`](https://github.com/polybar/polybar/issues/2427))
- `custom/ipc`: `send` action to send arbitrary strings to be displayed in the module.
([`#2455`](https://github.com/polybar/polybar/issues/2455))
+- Added `double-click-interval` setting to the bar section to control the time
+ interval in which a double-click is recognized. Defaults to 400 (ms)
+ ([`#1441`](https://github.com/polybar/polybar/issues/1441))
### Changed
- We rewrote polybar's main event loop. This shouldn't change any behavior for
@@ -130,6 +136,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `internal/network`:
- Increased precision for upload and download speeds: 0 decimal places for
KB/s (as before), 1 for MB/s and 2 for GB/s.
+- Clicks arriving in close succession, no longer get dropped. Before polybar
+ would drop any click that arrived within 5ms of the previous one.
+- Increased the double click interval from 150ms to 400ms.
### Fixed
- Trailing space after the layout label when indicators are empty and made sure right amount
diff --git a/cmake/05-summary.cmake b/cmake/05-summary.cmake
index c992d285..c15f3674 100644
--- a/cmake/05-summary.cmake
+++ b/cmake/05-summary.cmake
@@ -55,6 +55,5 @@ if (BUILD_LIBPOLY)
colored_option(" Trace logging (verbose)" DEBUG_LOGGER_VERBOSE)
colored_option(" Draw clickable areas" DEBUG_HINTS)
colored_option(" Print fc-match details" DEBUG_FONTCONFIG)
- colored_option(" Enable window shading" DEBUG_SHADED)
endif()
endif()
diff --git a/include/components/bar.hpp b/include/components/bar.hpp
index 101e6c87..63d8d472 100644
--- a/include/components/bar.hpp
+++ b/include/components/bar.hpp
@@ -5,6 +5,7 @@
#include
#include "common.hpp"
+#include "components/eventloop.hpp"
#include "components/types.hpp"
#include "errors.hpp"
#include "events/signal_fwd.hpp"
@@ -23,7 +24,6 @@ class connection;
class logger;
class renderer;
class screen;
-class taskqueue;
class tray_manager;
namespace tags {
@@ -55,8 +55,7 @@ inline double geom_format_to_pixels(std::string str, double max) {
class bar : public xpp::event::sink,
- public signal_receiver {
public:
using make_type = unique_ptr;
- static make_type make(bool only_initialize_values = false);
+ static make_type make(eventloop&, bool only_initialize_values = false);
- explicit bar(connection&, signal_emitter&, const config&, const logger&, unique_ptr&&,
+ explicit bar(connection&, signal_emitter&, const config&, const logger&, eventloop&, unique_ptr&&,
unique_ptr&&, unique_ptr&&, unique_ptr&&,
- unique_ptr&&, bool only_initialize_values);
+ bool only_initialize_values);
~bar();
const bar_settings settings() const;
@@ -90,6 +89,8 @@ class bar : public xpp::event::sink m_screen;
unique_ptr m_tray;
unique_ptr m_renderer;
unique_ptr m_dispatch;
unique_ptr m_action_ctxt;
- unique_ptr m_taskqueue;
bar_settings m_opts{};
string m_lastinput{};
- std::mutex m_mutex{};
- std::atomic m_dblclicks{false};
+ bool m_dblclicks{false};
- mousebtn m_buttonpress_btn{mousebtn::NONE};
- int m_buttonpress_pos{0};
#if WITH_XCURSOR
int m_motion_pos{0};
#endif
- event_timer m_buttonpress{0L, 5L};
- event_timer m_doubleclick{0L, 150L};
-
- double m_anim_step{0.0};
+ TimerHandle_t m_leftclick_timer{m_loop.timer_handle(nullptr)};
+ TimerHandle_t m_middleclick_timer{m_loop.timer_handle(nullptr)};
+ TimerHandle_t m_rightclick_timer{m_loop.timer_handle(nullptr)};
+ TimerHandle_t m_dim_timer{m_loop.timer_handle(nullptr)};
bool m_visible{true};
};
diff --git a/include/components/controller.hpp b/include/components/controller.hpp
index 5f016b38..4d8555a3 100644
--- a/include/components/controller.hpp
+++ b/include/components/controller.hpp
@@ -2,7 +2,6 @@
#include
#include
-#include
#include "common.hpp"
#include "components/eventloop.hpp"
@@ -42,7 +41,7 @@ class controller : public signal_receiver;
static make_type make(unique_ptr&& ipc);
- explicit controller(connection&, signal_emitter&, const logger&, const config&, unique_ptr&&, unique_ptr&&);
+ explicit controller(connection&, signal_emitter&, const logger&, const config&, unique_ptr&&);
~controller();
bool run(bool writeback, string snapshot_dst, bool confwatch);
@@ -98,15 +97,14 @@ class controller : public signal_receiver m_loop;
unique_ptr m_bar;
unique_ptr m_ipc;
- std::unique_ptr eloop;
-
/**
- * Once this is set to true, 'eloop' and any uv handles can be used.
+ * Once this is set to true, 'm_loop' and any uv handles can be used.
*/
- std::atomic_bool m_eloop_ready{false};
+ std::atomic_bool m_loop_ready{false};
/**
* \brief Async handle to notify the eventloop
diff --git a/include/components/eventloop.hpp b/include/components/eventloop.hpp
index 4798a3e1..26f030be 100644
--- a/include/components/eventloop.hpp
+++ b/include/components/eventloop.hpp
@@ -45,11 +45,19 @@ struct UVHandleGeneric {
}
void close() {
- if (handle && !uv_is_closing((uv_handle_t*)handle)) {
+ if (!is_closing()) {
uv_close((uv_handle_t*)handle, close_callback);
}
}
+ bool is_closing() {
+ return !handle || uv_is_closing((uv_handle_t*)handle);
+ }
+
+ bool is_active() {
+ return uv_is_active((uv_handle_t*)handle) != 0;
+ }
+
void cleanup_resources() {
if (handle) {
delete handle;
@@ -109,7 +117,8 @@ struct PipeHandle : public UVHandleGeneric {
TimerHandle(uv_loop_t* loop, function fun);
- void start(uint64_t timeout, uint64_t repeat);
+ void start(uint64_t timeout, uint64_t repeat, function new_cb = function(nullptr));
+ void stop();
};
struct AsyncHandle : public UVHandle {
@@ -121,8 +130,8 @@ using SignalHandle_t = std::unique_ptr;
using PollHandle_t = std::unique_ptr;
using FSEventHandle_t = std::unique_ptr;
using PipeHandle_t = std::unique_ptr;
-using TimerHandle_t = std::unique_ptr;
-// shared_ptr because we need a reference outside to call send
+// shared_ptr because we also return the pointer in order to call methods on it
+using TimerHandle_t = std::shared_ptr;
using AsyncHandle_t = std::shared_ptr;
class eventloop {
@@ -136,7 +145,7 @@ class eventloop {
void fs_event_handle(const string& path, function fun, function err_cb);
void pipe_handle(
const string& path, function fun, function eof_cb, function err_cb);
- void timer_handle(uint64_t timeout, uint64_t repeat, function fun);
+ TimerHandle_t timer_handle(function fun);
AsyncHandle_t async_handle(function fun);
protected:
diff --git a/include/components/taskqueue.hpp b/include/components/taskqueue.hpp
deleted file mode 100644
index d693b637..00000000
--- a/include/components/taskqueue.hpp
+++ /dev/null
@@ -1,62 +0,0 @@
-#pragma once
-
-#include
-#include
-#include
-#include
-#include
-
-#include "common.hpp"
-#include "utils/mixins.hpp"
-
-POLYBAR_NS
-
-namespace chrono = std::chrono;
-using namespace std::chrono_literals;
-
-class taskqueue : non_copyable_mixin {
- public:
- struct deferred {
- using clock = chrono::high_resolution_clock;
- using duration = chrono::milliseconds;
- using timepoint = chrono::time_point;
- using callback = function;
-
- explicit deferred(string id, timepoint now, duration wait, callback fn, size_t count)
- : id(move(id)), func(move(fn)), now(move(now)), wait(move(wait)), count(move(count)) {}
-
- const string id;
- const callback func;
- timepoint now;
- duration wait;
- size_t count;
- };
-
- public:
- using make_type = unique_ptr;
- static make_type make();
-
- explicit taskqueue();
- ~taskqueue();
-
- void defer(
- string id, deferred::duration ms, deferred::callback fn, deferred::duration offset = 0ms, size_t count = 1);
- void defer_unique(
- string id, deferred::duration ms, deferred::callback fn, deferred::duration offset = 0ms, size_t count = 1);
-
- bool exist(const string& id);
- bool purge(const string& id);
-
- protected:
- void tick();
-
- private:
- std::thread m_thread;
- std::mutex m_lock{};
- std::condition_variable m_hold;
- std::atomic_bool m_active{true};
-
- vector> m_deferred;
-};
-
-POLYBAR_NS_END
diff --git a/include/components/types.hpp b/include/components/types.hpp
index 0ec11440..01c9d72a 100644
--- a/include/components/types.hpp
+++ b/include/components/types.hpp
@@ -46,6 +46,19 @@ enum class mousebtn {
BTN_COUNT,
};
+static inline mousebtn mousebtn_get_double(mousebtn btn) {
+ switch (btn) {
+ case mousebtn::LEFT:
+ return mousebtn::DOUBLE_LEFT;
+ case mousebtn::MIDDLE:
+ return mousebtn::DOUBLE_MIDDLE;
+ case mousebtn::RIGHT:
+ return mousebtn::DOUBLE_RIGHT;
+ default:
+ return mousebtn::NONE;
+ }
+}
+
enum class strut {
LEFT = 0,
RIGHT,
@@ -146,6 +159,8 @@ struct bar_settings {
bool override_redirect{false};
+ int double_click_interval{400};
+
string cursor{};
string cursor_click{};
string cursor_scroll{};
@@ -155,12 +170,6 @@ struct bar_settings {
bool dimmed{false};
double dimvalue{1.0};
- bool shaded{false};
- struct size shade_size {
- 1U, 1U
- };
- position shade_pos{1U, 1U};
-
const xcb_rectangle_t inner_area(bool abspos = false) const {
xcb_rectangle_t rect = this->outer_area(abspos);
diff --git a/include/events/signal.hpp b/include/events/signal.hpp
index c9a4f694..1a823d72 100644
--- a/include/events/signal.hpp
+++ b/include/events/signal.hpp
@@ -80,9 +80,6 @@ namespace signals {
struct changed : public detail::base_signal {
using base_type::base_type;
};
- struct tick : public detail::base_signal {
- using base_type::base_type;
- };
struct button_press : public detail::value_signal {
using base_type::base_type;
};
@@ -95,12 +92,6 @@ namespace signals {
struct dim_window : public detail::value_signal {
using base_type::base_type;
};
- struct shade_window : public detail::base_signal {
- using base_type::base_type;
- };
- struct unshade_window : public detail::base_signal {
- using base_type::base_type;
- };
struct request_snapshot : public detail::value_signal {
using base_type::base_type;
};
diff --git a/include/events/signal_fwd.hpp b/include/events/signal_fwd.hpp
index ff51e8f4..376683a0 100644
--- a/include/events/signal_fwd.hpp
+++ b/include/events/signal_fwd.hpp
@@ -27,13 +27,10 @@ namespace signals {
} // namespace ipc
namespace ui {
struct changed;
- struct tick;
struct button_press;
struct cursor_change;
struct visibility_change;
struct dim_window;
- struct shade_window;
- struct unshade_window;
struct request_snapshot;
struct update_background;
struct update_geometry;
diff --git a/include/settings.hpp.cmake b/include/settings.hpp.cmake
index 776b38eb..d1016db8 100644
--- a/include/settings.hpp.cmake
+++ b/include/settings.hpp.cmake
@@ -41,7 +41,6 @@ extern const char* const APP_VERSION;
#cmakedefine DEBUG_LOGGER_VERBOSE
#cmakedefine DEBUG_HINTS
#cmakedefine DEBUG_WHITESPACE
-#cmakedefine DEBUG_SHADED
#cmakedefine DEBUG_FONTCONFIG
#endif
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 250287d3..31f08d19 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -66,7 +66,6 @@ if(BUILD_LIBPOLY)
${src_dir}/components/logger.cpp
${src_dir}/components/renderer.cpp
${src_dir}/components/screen.cpp
- ${src_dir}/components/taskqueue.cpp
${src_dir}/components/eventloop.cpp
${src_dir}/drawtypes/animation.cpp
diff --git a/src/components/bar.cpp b/src/components/bar.cpp
index 3c096efa..7a95f668 100644
--- a/src/components/bar.cpp
+++ b/src/components/bar.cpp
@@ -5,7 +5,6 @@
#include "components/config.hpp"
#include "components/renderer.hpp"
#include "components/screen.hpp"
-#include "components/taskqueue.hpp"
#include "components/types.hpp"
#include "drawtypes/label.hpp"
#include "events/signal.hpp"
@@ -37,7 +36,7 @@ using namespace signals::ui;
/**
* Create instance
*/
-bar::make_type bar::make(bool only_initialize_values) {
+bar::make_type bar::make(eventloop& loop, bool only_initialize_values) {
auto action_ctxt = make_unique();
// clang-format off
@@ -46,11 +45,11 @@ bar::make_type bar::make(bool only_initialize_values) {
signal_emitter::make(),
config::make(),
logger::make(),
+ loop,
screen::make(),
tray_manager::make(),
tags::dispatch::make(*action_ctxt),
std::move(action_ctxt),
- taskqueue::make(),
only_initialize_values);
// clang-format on
}
@@ -60,18 +59,18 @@ bar::make_type bar::make(bool only_initialize_values) {
*
* TODO: Break out all tray handling
*/
-bar::bar(connection& conn, signal_emitter& emitter, const config& config, const logger& logger,
+bar::bar(connection& conn, signal_emitter& emitter, const config& config, const logger& logger, eventloop& loop,
unique_ptr&& screen, unique_ptr&& tray_manager, unique_ptr&& dispatch,
- unique_ptr&& action_ctxt, unique_ptr&& taskqueue, bool only_initialize_values)
+ unique_ptr&& action_ctxt, bool only_initialize_values)
: m_connection(conn)
, m_sig(emitter)
, m_conf(config)
, m_log(logger)
+ , m_loop(loop)
, m_screen(forward(screen))
, m_tray(forward(tray_manager))
, m_dispatch(forward(dispatch))
- , m_action_ctxt(forward(action_ctxt))
- , m_taskqueue(forward(taskqueue)) {
+ , m_action_ctxt(forward(action_ctxt)) {
string bs{m_conf.section()};
// Get available RandR outputs
@@ -179,6 +178,8 @@ bar::bar(connection& conn, signal_emitter& emitter, const config& config, const
m_opts.module_margin.left = m_conf.get(bs, "module-margin-left", margin);
m_opts.module_margin.right = m_conf.get(bs, "module-margin-right", margin);
+ m_opts.double_click_interval = m_conf.get(bs, "double-click-interval", m_opts.double_click_interval);
+
if (only_initialize_values) {
return;
}
@@ -308,7 +309,6 @@ bar::bar(connection& conn, signal_emitter& emitter, const config& config, const
* Cleanup signal handlers and destroy the bar window
*/
bar::~bar() {
- std::lock_guard guard(m_mutex);
m_connection.detach_sink(this, SINK_PRIORITY_BAR);
m_sig.detach(this);
}
@@ -327,12 +327,6 @@ const bar_settings bar::settings() const {
* \param force Unless true, do not parse unchanged data
*/
void bar::parse(string&& data, bool force) {
- if (!m_mutex.try_lock()) {
- return;
- }
-
- std::lock_guard guard(m_mutex, std::adopt_lock);
-
bool unchanged = data == m_lastinput;
m_lastinput = data;
@@ -341,8 +335,6 @@ void bar::parse(string&& data, bool force) {
m_log.trace("bar: Force update");
} else if (!m_visible) {
return m_log.trace("bar: Ignoring update (invisible)");
- } else if (m_opts.shaded) {
- return m_log.trace("bar: Ignoring update (shaded)");
} else if (unchanged) {
return m_log.trace("bar: Ignoring update (unchanged)");
}
@@ -575,6 +567,25 @@ void bar::broadcast_visibility() {
}
}
+void bar::trigger_click(mousebtn btn, int pos) {
+ tags::action_t action = m_action_ctxt->has_action(btn, pos);
+
+ if (action != tags::NO_ACTION) {
+ m_log.trace("Found matching input area");
+ m_sig.emit(button_press{m_action_ctxt->get_action(action)});
+ return;
+ }
+
+ for (auto&& action : m_opts.actions) {
+ if (action.button == btn && !action.command.empty()) {
+ m_log.trace("Found matching fallback handler");
+ m_sig.emit(button_press{string{action.command}});
+ return;
+ }
+ }
+ m_log.info("No matching input area found (btn=%i)", static_cast(btn));
+}
+
/**
* Event handler for XCB_DESTROY_NOTIFY events
*/
@@ -601,21 +612,13 @@ void bar::handle(const evt::destroy_notify& evt) {
* _NET_WM_WINDOW_OPACITY atom value
*/
void bar::handle(const evt::enter_notify&) {
-#if 0
-#ifdef DEBUG_SHADED
- if (m_opts.origin == edge::TOP) {
- m_taskqueue->defer_unique("window-hover", 25ms, [&](size_t) { m_sig.emit(signals::ui::unshade_window{}); });
- return;
- }
-#endif
-#endif
if (m_opts.dimmed) {
- m_taskqueue->defer_unique("window-dim", 25ms, [&](size_t) {
+ m_dim_timer->start(25, 0, [this]() {
m_opts.dimmed = false;
m_sig.emit(dim_window{1.0});
});
- } else if (m_taskqueue->exist("window-dim")) {
- m_taskqueue->purge("window-dim");
+ } else if (m_dim_timer->is_active()) {
+ m_dim_timer->stop();
}
}
@@ -626,19 +629,14 @@ void bar::handle(const evt::enter_notify&) {
* _NET_WM_WINDOW_OPACITY atom value
*/
void bar::handle(const evt::leave_notify&) {
-#if 0
-#ifdef DEBUG_SHADED
- if (m_opts.origin == edge::TOP) {
- m_taskqueue->defer_unique("window-hover", 25ms, [&](size_t) { m_sig.emit(signals::ui::shade_window{}); });
- return;
- }
-#endif
-#endif
- if (!m_opts.dimmed) {
- m_taskqueue->defer_unique("window-dim", 3s, [&](size_t) {
- m_opts.dimmed = true;
- m_sig.emit(dim_window{double(m_opts.dimvalue)});
- });
+ // Only trigger dimming, if the dim-value is not fully opaque.
+ if (m_opts.dimvalue < 1.0) {
+ if (!m_opts.dimmed) {
+ m_dim_timer->start(3000, 0, [this]() {
+ m_opts.dimmed = true;
+ m_sig.emit(dim_window{double(m_opts.dimvalue)});
+ });
+ }
}
}
@@ -648,12 +646,6 @@ void bar::handle(const evt::leave_notify&) {
* Used to change the cursor depending on the module
*/
void bar::handle(const evt::motion_notify& evt) {
- if (!m_mutex.try_lock()) {
- return;
- }
-
- std::lock_guard guard(m_mutex, std::adopt_lock);
-
m_log.trace("bar: Detected motion: %i at pos(%i, %i)", evt->detail, evt->event_x, evt->event_y);
#if WITH_XCURSOR
m_motion_pos = evt->event_x;
@@ -735,63 +727,37 @@ void bar::handle(const evt::motion_notify& evt) {
* Used to map mouse clicks to bar actions
*/
void bar::handle(const evt::button_press& evt) {
- if (!m_mutex.try_lock()) {
- return;
- }
-
- std::lock_guard guard(m_mutex, std::adopt_lock);
-
- if (m_buttonpress.deny(evt->time)) {
- return m_log.trace_x("bar: Ignoring button press (throttled)...");
- }
-
m_log.trace("bar: Received button press: %i at pos(%i, %i)", evt->detail, evt->event_x, evt->event_y);
- m_buttonpress_btn = static_cast(evt->detail);
- m_buttonpress_pos = evt->event_x;
+ mousebtn btn = static_cast(evt->detail);
+ int pos = evt->event_x;
- const auto deferred_fn = [&](size_t) {
- tags::action_t action = m_action_ctxt->has_action(m_buttonpress_btn, m_buttonpress_pos);
-
- if (action != tags::NO_ACTION) {
- m_log.trace("Found matching input area");
- m_sig.emit(button_press{m_action_ctxt->get_action(action)});
- return;
- }
-
- for (auto&& action : m_opts.actions) {
- if (action.button == m_buttonpress_btn && !action.command.empty()) {
- m_log.trace("Found matching fallback handler");
- m_sig.emit(button_press{string{action.command}});
- return;
- }
- }
- m_log.info("No matching input area found (btn=%i)", static_cast(m_buttonpress_btn));
- };
-
- const auto check_double = [&](string&& id, mousebtn&& btn) {
- if (!m_taskqueue->exist(id)) {
- m_doubleclick.event = evt->time;
- m_taskqueue->defer(id, taskqueue::deferred::duration{m_doubleclick.offset}, deferred_fn);
- } else if (m_doubleclick.deny(evt->time)) {
- m_doubleclick.event = 0;
- m_buttonpress_btn = btn;
- m_taskqueue->defer_unique(id, 0ms, deferred_fn);
+ /*
+ * For possible double-clicks we need to delay the triggering of the click by
+ * the configured interval and if in that time another click arrives, we
+ * need to trigger a double click.
+ */
+ const auto check_double = [this](TimerHandle_t handle, mousebtn btn, int pos) {
+ if (!handle->is_active()) {
+ handle->start(m_opts.double_click_interval, 0, [=]() { trigger_click(btn, pos); });
+ } else {
+ handle->stop();
+ trigger_click(mousebtn_get_double(btn), pos);
}
};
// If there are no double click handlers defined we can
// just by-pass the click timer handling
if (!m_dblclicks) {
- deferred_fn(0);
- } else if (evt->detail == static_cast(mousebtn::LEFT)) {
- check_double("buttonpress-left", mousebtn::DOUBLE_LEFT);
- } else if (evt->detail == static_cast(mousebtn::MIDDLE)) {
- check_double("buttonpress-middle", mousebtn::DOUBLE_MIDDLE);
- } else if (evt->detail == static_cast(mousebtn::RIGHT)) {
- check_double("buttonpress-right", mousebtn::DOUBLE_RIGHT);
+ trigger_click(btn, pos);
+ } else if (btn == mousebtn::LEFT) {
+ check_double(m_leftclick_timer, btn, pos);
+ } else if (btn == mousebtn::MIDDLE) {
+ check_double(m_middleclick_timer, btn, pos);
+ } else if (btn == mousebtn::RIGHT) {
+ check_double(m_rightclick_timer, btn, pos);
} else {
- deferred_fn(0);
+ trigger_click(btn, pos);
}
}
@@ -876,110 +842,6 @@ void bar::start() {
broadcast_visibility();
}
-bool bar::on(const signals::ui::unshade_window&) {
- m_opts.shaded = false;
- m_opts.shade_size.w = m_opts.size.w;
- m_opts.shade_size.h = m_opts.size.h;
- m_opts.shade_pos.x = m_opts.pos.x;
- m_opts.shade_pos.y = m_opts.pos.y;
-
- double distance{static_cast(m_opts.shade_size.h - m_connection.get_geometry(m_opts.window)->height)};
- double steptime{25.0 / 2.0};
- m_anim_step = distance / steptime / 2.0;
-
- m_taskqueue->defer_unique(
- "window-shade", 25ms,
- [&](size_t remaining) {
- if (!m_opts.shaded) {
- m_sig.emit(signals::ui::tick{});
- }
- if (!remaining) {
- m_renderer->flush();
- }
- if (m_opts.dimmed) {
- m_opts.dimmed = false;
- m_sig.emit(dim_window{1.0});
- }
- },
- taskqueue::deferred::duration{25ms}, 10U);
-
- return true;
-}
-
-bool bar::on(const signals::ui::shade_window&) {
- taskqueue::deferred::duration offset{2000ms};
-
- if (!m_opts.shaded && m_opts.shade_size.h != m_opts.size.h) {
- offset = taskqueue::deferred::duration{25ms};
- }
-
- m_opts.shaded = true;
- m_opts.shade_size.h = 5;
- m_opts.shade_size.w = m_opts.size.w;
- m_opts.shade_pos.x = m_opts.pos.x;
- m_opts.shade_pos.y = m_opts.pos.y;
-
- if (m_opts.origin == edge::BOTTOM) {
- m_opts.shade_pos.y = m_opts.pos.y + m_opts.size.h - m_opts.shade_size.h;
- }
-
- double distance{static_cast(m_connection.get_geometry(m_opts.window)->height - m_opts.shade_size.h)};
- double steptime{25.0 / 2.0};
- m_anim_step = distance / steptime / 2.0;
-
- m_taskqueue->defer_unique(
- "window-shade", 25ms,
- [&](size_t remaining) {
- if (m_opts.shaded) {
- m_sig.emit(signals::ui::tick{});
- }
- if (!remaining) {
- m_renderer->flush();
- }
- if (!m_opts.dimmed) {
- m_opts.dimmed = true;
- m_sig.emit(dim_window{double{m_opts.dimvalue}});
- }
- },
- move(offset), 10U);
-
- return true;
-}
-
-bool bar::on(const signals::ui::tick&) {
- auto geom = m_connection.get_geometry(m_opts.window);
- if (geom->y == m_opts.shade_pos.y && geom->height == m_opts.shade_size.h) {
- return false;
- }
-
- unsigned int mask{0};
- unsigned int values[7]{0};
- xcb_params_configure_window_t params{};
-
- if (m_opts.shade_size.h > geom->height) {
- XCB_AUX_ADD_PARAM(&mask, ¶ms, height, static_cast(geom->height + m_anim_step));
- params.height = std::max(1U, std::min(params.height, static_cast(m_opts.shade_size.h)));
- } else if (m_opts.shade_size.h < geom->height) {
- XCB_AUX_ADD_PARAM(&mask, ¶ms, height, static_cast(geom->height - m_anim_step));
- params.height = std::max(1U, std::max(params.height, static_cast(m_opts.shade_size.h)));
- }
-
- if (m_opts.shade_pos.y > geom->y) {
- XCB_AUX_ADD_PARAM(&mask, ¶ms, y, static_cast(geom->y + m_anim_step));
- params.y = std::min(params.y, static_cast(m_opts.shade_pos.y));
- } else if (m_opts.shade_pos.y < geom->y) {
- XCB_AUX_ADD_PARAM(&mask, ¶ms, y, static_cast(geom->y - m_anim_step));
- params.y = std::max(params.y, static_cast(m_opts.shade_pos.y));
- }
-
- connection::pack_values(mask, ¶ms, values);
-
- m_connection.configure_window(m_opts.window, mask, values);
- m_connection.flush();
-
- return false;
-}
-
bool bar::on(const signals::ui::dim_window& sig) {
m_opts.dimmed = sig.cast() != 1.0;
ewmh_util::set_wm_window_opacity(m_opts.window, sig.cast() * 0xFFFFFFFF);
diff --git a/src/components/controller.cpp b/src/components/controller.cpp
index 85bca3b2..392daa4b 100644
--- a/src/components/controller.cpp
+++ b/src/components/controller.cpp
@@ -31,20 +31,21 @@ POLYBAR_NS
* Build controller instance
*/
controller::make_type controller::make(unique_ptr&& ipc) {
- return std::make_unique(connection::make(), signal_emitter::make(), logger::make(), config::make(),
- bar::make(), forward(ipc));
+ return std::make_unique(
+ connection::make(), signal_emitter::make(), logger::make(), config::make(), forward(ipc));
}
/**
* Construct controller
*/
-controller::controller(connection& conn, signal_emitter& emitter, const logger& logger, const config& config,
- unique_ptr&& bar, unique_ptr&& ipc)
+controller::controller(
+ connection& conn, signal_emitter& emitter, const logger& logger, const config& config, unique_ptr&& ipc)
: m_connection(conn)
, m_sig(emitter)
, m_log(logger)
, m_conf(config)
- , m_bar(forward(bar))
+ , m_loop(make_unique())
+ , m_bar(bar::make(*m_loop))
, m_ipc(forward(ipc)) {
m_conf.ignore_key("settings", "throttle-input-for");
m_conf.ignore_key("settings", "throttle-output");
@@ -152,14 +153,14 @@ void controller::trigger_update(bool force) {
}
void controller::trigger_notification() {
- if (m_eloop_ready) {
+ if (m_loop_ready) {
m_notifier->send();
}
}
void controller::stop(bool reload) {
update_reload(reload);
- eloop->stop();
+ m_loop->stop();
}
void controller::conn_cb(uv_poll_event) {
@@ -210,7 +211,7 @@ void controller::notifier_handler() {
if (data.quit) {
update_reload(data.reload);
- eloop->stop();
+ m_loop->stop();
return;
}
@@ -234,29 +235,23 @@ void controller::screenshot_handler() {
void controller::read_events(bool confwatch) {
m_log.info("Entering event loop (thread-id=%lu)", this_thread::get_id());
- if (!m_writeback) {
- m_bar->start();
- }
-
try {
- eloop = std::make_unique();
-
- eloop->poll_handle(
+ m_loop->poll_handle(
UV_READABLE, m_connection.get_file_descriptor(), [this](uv_poll_event events) { conn_cb(events); },
[](int status) { throw runtime_error("libuv error while polling X connection: "s + uv_strerror(status)); });
for (auto s : {SIGINT, SIGQUIT, SIGTERM, SIGUSR1, SIGALRM}) {
- eloop->signal_handle(s, [this](int signum) { signal_handler(signum); });
+ m_loop->signal_handle(s, [this](int signum) { signal_handler(signum); });
}
if (confwatch) {
- eloop->fs_event_handle(
+ m_loop->fs_event_handle(
m_conf.filepath(), [this](const char* path, uv_fs_event events) { confwatch_handler(path, events); },
[this](int err) { m_log.err("libuv error while watching config file for changes: %s", uv_strerror(err)); });
}
if (m_ipc) {
- eloop->pipe_handle(
+ m_loop->pipe_handle(
m_ipc->get_path(), [this](const string payload) { m_ipc->receive_data(payload); },
[this]() { m_ipc->receive_eof(); },
[this](int err) { m_log.err("libuv error while listening to IPC channel: %s", uv_strerror(err)); });
@@ -264,19 +259,23 @@ void controller::read_events(bool confwatch) {
if (!m_snapshot_dst.empty()) {
// Trigger a single screenshot after 3 seconds
- eloop->timer_handle(3000, 0, [this]() { screenshot_handler(); });
+ m_loop->timer_handle([this]() { screenshot_handler(); })->start(3000, 0);
}
- m_notifier = eloop->async_handle([this]() { notifier_handler(); });
+ m_notifier = m_loop->async_handle([this]() { notifier_handler(); });
- m_eloop_ready.store(true);
+ m_loop_ready = true;
+
+ if (!m_writeback) {
+ m_bar->start();
+ }
/*
* Immediately trigger and update so that the bar displays something.
*/
trigger_update(true);
- eloop->run();
+ m_loop->run();
} catch (const exception& err) {
m_log.err("Fatal Error in eventloop: %s", err.what());
stop(false);
@@ -284,7 +283,8 @@ void controller::read_events(bool confwatch) {
m_log.info("Eventloop finished");
- eloop.reset();
+ m_loop_ready = false;
+ m_loop.reset();
}
/**
diff --git a/src/components/eventloop.cpp b/src/components/eventloop.cpp
index cca21ebb..66947c52 100644
--- a/src/components/eventloop.cpp
+++ b/src/components/eventloop.cpp
@@ -141,7 +141,7 @@ void PipeHandle::read_cb(ssize_t nread, const uv_buf_t* buf) {
*
* We reuse the memory for the underlying uv handle
*/
- if (!uv_is_closing((uv_handle_t*)handle)) {
+ if (!is_closing()) {
uv_close((uv_handle_t*)handle, [](uv_handle_t* handle) {
PipeHandle* This = static_cast(handle->data);
UV(uv_pipe_init, This->loop(), This->handle, false);
@@ -158,9 +158,17 @@ TimerHandle::TimerHandle(uv_loop_t* loop, function fun) : UVHandle(f
UV(uv_timer_init, loop, handle);
}
-void TimerHandle::start(uint64_t timeout, uint64_t repeat) {
+void TimerHandle::start(uint64_t timeout, uint64_t repeat, function new_cb) {
+ if (new_cb) {
+ this->func = new_cb;
+ }
+
UV(uv_timer_start, handle, callback, timeout, repeat);
}
+
+void TimerHandle::stop() {
+ UV(uv_timer_stop, handle);
+}
// }}}
// AsyncHandle {{{
@@ -243,9 +251,9 @@ void eventloop::pipe_handle(
m_pipe_handles.back()->start();
}
-void eventloop::timer_handle(uint64_t timeout, uint64_t repeat, function fun) {
- m_timer_handles.emplace_back(std::make_unique(get(), fun));
- m_timer_handles.back()->start(timeout, repeat);
+TimerHandle_t eventloop::timer_handle(function fun) {
+ m_timer_handles.emplace_back(std::make_shared(get(), fun));
+ return m_timer_handles.back();
}
AsyncHandle_t eventloop::async_handle(function fun) {
diff --git a/src/components/renderer.cpp b/src/components/renderer.cpp
index 2a668e47..c79e5e74 100644
--- a/src/components/renderer.cpp
+++ b/src/components/renderer.cpp
@@ -381,25 +381,6 @@ void renderer::flush() {
highlight_clickable_areas();
-#if 0
-#ifdef DEBUG_SHADED
- if (m_bar.shaded && m_bar.origin == edge::TOP) {
- m_log.trace_x(
- "renderer: copy pixmap (shaded=1, geom=%dx%d+%d+%d)", m_rect.width, m_rect.height, m_rect.x, m_rect.y);
- auto geom = m_connection.get_geometry(m_window);
- auto x1 = 0;
- auto y1 = m_rect.height - m_bar.shade_size.h - m_rect.y - geom->height;
- auto x2 = m_rect.x;
- auto y2 = m_rect.y;
- auto w = m_rect.width;
- auto h = m_rect.height - m_bar.shade_size.h + geom->height;
- m_connection.copy_area(m_pixmap, m_window, m_gcontext, x1, y1, x2, y2, w, h);
- m_connection.flush();
- return;
- }
-#endif
-#endif
-
m_surface->flush();
m_connection.copy_area(m_pixmap, m_window, m_gcontext, 0, 0, 0, 0, m_bar.size.w, m_bar.size.h);
m_connection.flush();
diff --git a/src/components/taskqueue.cpp b/src/components/taskqueue.cpp
deleted file mode 100644
index b0ba3bbe..00000000
--- a/src/components/taskqueue.cpp
+++ /dev/null
@@ -1,109 +0,0 @@
-#include "components/taskqueue.hpp"
-
-#include
-
-POLYBAR_NS
-
-taskqueue::make_type taskqueue::make() {
- return std::make_unique();
-}
-
-taskqueue::taskqueue() {
- m_thread = std::thread([&] {
- while (m_active) {
- std::unique_lock guard(m_lock);
-
- if (m_deferred.empty()) {
- m_hold.wait(guard);
- } else {
- auto now = deferred::clock::now();
- auto wait = m_deferred.front()->now + m_deferred.front()->wait;
- for (auto&& task : m_deferred) {
- auto when = task->now + task->wait;
- if (when < wait) {
- wait = move(when);
- }
- }
- if (wait > now) {
- m_hold.wait_for(guard, wait - now);
- }
- }
- if (!m_deferred.empty()) {
- guard.unlock();
- tick();
- }
- }
- });
-}
-
-taskqueue::~taskqueue() {
- if (m_active && m_thread.joinable()) {
- m_active = false;
- m_hold.notify_all();
- m_thread.join();
- }
-}
-
-void taskqueue::defer(
- string id, deferred::duration ms, deferred::callback fn, deferred::duration offset, size_t count) {
- std::unique_lock guard(m_lock);
- deferred::timepoint now{chrono::time_point_cast(deferred::clock::now() + move(offset))};
- m_deferred.emplace_back(make_unique(move(id), move(now), move(ms), move(fn), move(count)));
- guard.unlock();
- m_hold.notify_one();
-}
-
-void taskqueue::defer_unique(
- string id, deferred::duration ms, deferred::callback fn, deferred::duration offset, size_t count) {
- purge(id);
- std::unique_lock guard(m_lock);
- deferred::timepoint now{chrono::time_point_cast(deferred::clock::now() + move(offset))};
- m_deferred.emplace_back(make_unique(move(id), move(now), move(ms), move(fn), move(count)));
- guard.unlock();
- m_hold.notify_one();
-}
-
-void taskqueue::tick() {
- if (!m_lock.try_lock()) {
- return;
- }
- std::unique_lock guard(m_lock, std::adopt_lock);
- auto now = chrono::time_point_cast(deferred::clock::now());
- vector> cbs;
- for (auto it = m_deferred.rbegin(); it != m_deferred.rend(); ++it) {
- auto& task = *it;
- if (task->now + task->wait > now) {
- continue;
- } else if (task->count--) {
- cbs.emplace_back(make_pair(task->func, task->count));
- task->now = now;
- } else {
- m_deferred.erase(std::remove_if(m_deferred.begin(), m_deferred.end(),
- [&](const unique_ptr& d) { return d == task; }),
- m_deferred.end());
- }
- }
- guard.unlock();
- for (auto&& p : cbs) {
- p.first(p.second);
- }
-}
-
-bool taskqueue::purge(const string& id) {
- std::lock_guard guard(m_lock);
- return m_deferred.erase(std::remove_if(m_deferred.begin(), m_deferred.end(),
- [id](const unique_ptr& d) { return d->id == id; }),
- m_deferred.end()) == m_deferred.end();
-}
-
-bool taskqueue::exist(const string& id) {
- std::lock_guard guard(m_lock);
- for (const auto& task : m_deferred) {
- if (task->id == id) {
- return true;
- }
- }
- return false;
-}
-
-POLYBAR_NS_END
diff --git a/src/main.cpp b/src/main.cpp
index 5320dd75..f0d8ddb2 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -127,7 +127,8 @@ int main(int argc, char** argv) {
return EXIT_SUCCESS;
}
if (cli->has("print-wmname")) {
- printf("%s\n", bar::make(true)->settings().wmname.c_str());
+ eventloop loop{};
+ printf("%s\n", bar::make(loop, true)->settings().wmname.c_str());
return EXIT_SUCCESS;
}
diff --git a/src/utils/env.cpp b/src/utils/env.cpp
index 575ffb42..b28ce768 100644
--- a/src/utils/env.cpp
+++ b/src/utils/env.cpp
@@ -1,10 +1,9 @@
+#include "utils/env.hpp"
+
#include
#include
-#include
#include
-#include "utils/env.hpp"
-
POLYBAR_NS
namespace env_util {
@@ -17,6 +16,6 @@ namespace env_util {
const char* value{std::getenv(var.c_str())};
return value != nullptr ? value : move(fallback);
}
-}
+} // namespace env_util
POLYBAR_NS_END