refactor: Defer buttonpress using taskqueue

This commit is contained in:
Michael Carlberg 2016-12-20 13:03:46 +01:00
parent b8ff0da693
commit 8ef8900ca2
4 changed files with 68 additions and 25 deletions

View File

@ -19,6 +19,7 @@ class parser;
class renderer; class renderer;
class screen; class screen;
class signal_emitter; class signal_emitter;
class taskqueue;
class tray_manager; class tray_manager;
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,
@ -27,9 +28,9 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
using make_type = unique_ptr<bar>; using make_type = unique_ptr<bar>;
static make_type make(); static make_type make();
explicit bar(connection& conn, signal_emitter& emitter, const config& config, const logger& logger, explicit bar(connection&, signal_emitter&, const config&, const logger&, unique_ptr<screen>&&,
unique_ptr<screen>&& screen, unique_ptr<tray_manager>&& tray_manager, unique_ptr<parser>&& parser); unique_ptr<tray_manager>&&, unique_ptr<parser>&&, unique_ptr<taskqueue>&&);
virtual ~bar(); ~bar();
void parse(string&& data) const; void parse(string&& data) const;
void parse(const string& data, bool force = false); void parse(const string& data, bool force = false);
@ -60,14 +61,18 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
unique_ptr<tray_manager> m_tray{}; unique_ptr<tray_manager> m_tray{};
unique_ptr<renderer> m_renderer{}; unique_ptr<renderer> m_renderer{};
unique_ptr<parser> m_parser{}; unique_ptr<parser> m_parser{};
unique_ptr<taskqueue> m_taskqueue;
bar_settings m_opts{}; bar_settings m_opts{};
string m_lastinput{}; string m_lastinput{};
std::mutex m_mutex{}; std::mutex m_mutex{};
mousebtn m_buttonpress_btn{mousebtn::NONE};
int16_t m_buttonpress_pos{0};
event_timer m_buttonpress{0L, 5L}; event_timer m_buttonpress{0L, 5L};
event_timer m_doubleclick{0L, 150L};
}; };
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -33,7 +33,17 @@ enum class syntaxtag : uint8_t {
u, // underline color u, // underline color
}; };
enum class mousebtn : uint8_t { NONE = 0U, LEFT, MIDDLE, RIGHT, SCROLL_UP, SCROLL_DOWN }; enum class mousebtn : uint8_t {
NONE = 0U,
LEFT,
MIDDLE,
RIGHT,
SCROLL_UP,
SCROLL_DOWN,
DOUBLE_LEFT,
DOUBLE_MIDDLE,
DOUBLE_RIGHT
};
enum class strut : uint16_t { enum class strut : uint16_t {
LEFT = 0U, LEFT = 0U,

View File

@ -7,6 +7,7 @@
#include "components/parser.hpp" #include "components/parser.hpp"
#include "components/renderer.hpp" #include "components/renderer.hpp"
#include "components/screen.hpp" #include "components/screen.hpp"
#include "components/taskqueue.hpp"
#include "events/signal.hpp" #include "events/signal.hpp"
#include "events/signal_emitter.hpp" #include "events/signal_emitter.hpp"
#include "utils/bspwm.hpp" #include "utils/bspwm.hpp"
@ -42,7 +43,8 @@ bar::make_type bar::make() {
logger::make(), logger::make(),
screen::make(), screen::make(),
tray_manager::make(), tray_manager::make(),
parser::make()); parser::make(),
taskqueue::make());
// clang-format on // clang-format on
} }
@ -52,14 +54,16 @@ bar::make_type bar::make() {
* TODO: Break out all tray handling * 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,
unique_ptr<screen>&& screen, unique_ptr<tray_manager>&& tray_manager, unique_ptr<parser>&& parser) unique_ptr<screen>&& screen, unique_ptr<tray_manager>&& tray_manager, unique_ptr<parser>&& parser,
unique_ptr<taskqueue>&& taskqueue)
: m_connection(conn) : m_connection(conn)
, m_sig(emitter) , m_sig(emitter)
, m_conf(config) , m_conf(config)
, m_log(logger) , m_log(logger)
, m_screen(forward<decltype(screen)>(screen)) , m_screen(forward<decltype(screen)>(screen))
, m_tray(forward<decltype(tray_manager)>(tray_manager)) , m_tray(forward<decltype(tray_manager)>(tray_manager))
, m_parser(forward<decltype(parser)>(parser)) { , m_parser(forward<decltype(parser)>(parser))
, m_taskqueue(forward<decltype(taskqueue)>(taskqueue)) {
string bs{m_conf.section()}; string bs{m_conf.section()};
// Get available RandR outputs // Get available RandR outputs
@ -150,6 +154,9 @@ bar::bar(connection& conn, signal_emitter& emitter, const config& config, const
actions.emplace_back(action{mousebtn::RIGHT, m_conf.get<string>(bs, "click-right", "")}); actions.emplace_back(action{mousebtn::RIGHT, m_conf.get<string>(bs, "click-right", "")});
actions.emplace_back(action{mousebtn::SCROLL_UP, m_conf.get<string>(bs, "scroll-up", "")}); actions.emplace_back(action{mousebtn::SCROLL_UP, m_conf.get<string>(bs, "scroll-up", "")});
actions.emplace_back(action{mousebtn::SCROLL_DOWN, m_conf.get<string>(bs, "scroll-down", "")}); actions.emplace_back(action{mousebtn::SCROLL_DOWN, m_conf.get<string>(bs, "scroll-down", "")});
actions.emplace_back(action{mousebtn::DOUBLE_LEFT, m_conf.get<string>(bs, "double-click-left", "")});
actions.emplace_back(action{mousebtn::DOUBLE_MIDDLE, m_conf.get<string>(bs, "double-click-middle", "")});
actions.emplace_back(action{mousebtn::DOUBLE_RIGHT, m_conf.get<string>(bs, "double-click-right", "")});
for (auto&& act : actions) { for (auto&& act : actions) {
if (!act.command.empty()) { if (!act.command.empty()) {
@ -507,25 +514,48 @@ void bar::handle(const evt::button_press& evt) {
} }
m_log.trace("bar: Received button press: %i at pos(%i, %i)", evt->detail, evt->event_x, evt->event_y); m_log.trace("bar: Received button press: %i at pos(%i, %i)", evt->detail, evt->event_x, evt->event_y);
mousebtn button{static_cast<mousebtn>(evt->detail)};
m_buttonpress_btn = static_cast<mousebtn>(evt->detail);
m_buttonpress_pos = evt->event_x;
const auto deferred_fn = [&] {
for (auto&& action : m_renderer->get_actions()) { for (auto&& action : m_renderer->get_actions()) {
if (!action.active && action.button == button && action.test(evt->event_x)) { if (action.button == m_buttonpress_btn && !action.active && action.test(m_buttonpress_pos)) {
m_log.trace("Found matching input area"); m_log.trace("Found matching input area");
m_sig.emit(button_press{string{action.command}}); m_sig.emit(button_press{string{action.command}});
return; return;
} }
} }
for (auto&& action : m_opts.actions) { for (auto&& action : m_opts.actions) {
if (action.button == button && !action.command.empty()) { if (action.button == m_buttonpress_btn && !action.command.empty()) {
m_log.trace("Triggering fallback click handler: %s", action.command); m_log.trace("Found matching fallback handler");
m_sig.emit(button_press{string{action.command}}); m_sig.emit(button_press{string{action.command}});
return; return;
} }
} }
m_log.warn("No matching input area found (btn=%i)", static_cast<uint8_t>(m_buttonpress_btn));
};
m_log.warn("No matching input area found"); const auto check_double = [&](const xcb_timestamp_t& timestamp, string&& id, mousebtn&& btn) {
if (!m_taskqueue->has_deferred(string{id})) {
m_doubleclick.event = move(timestamp);
m_taskqueue->defer_unique(string{id}, chrono::milliseconds{m_doubleclick.offset}, deferred_fn);
} else if (m_doubleclick.deny(evt->time)) {
m_doubleclick.event = 0;
m_buttonpress_btn = forward<decltype(btn)>(btn);
m_taskqueue->defer_unique(string{id}, 0ms, deferred_fn);
}
};
if (evt->detail == static_cast<uint8_t>(mousebtn::LEFT)) {
check_double(evt->time, "buttonpress-left", mousebtn::LEFT);
} else if (evt->detail == static_cast<uint8_t>(mousebtn::MIDDLE)) {
check_double(evt->time, "buttonpress-middle", mousebtn::MIDDLE);
} else if (evt->detail == static_cast<uint8_t>(mousebtn::RIGHT)) {
check_double(evt->time, "buttonpress-right", mousebtn::RIGHT);
} else {
deferred_fn();
}
} }
/** /**

View File

@ -134,8 +134,6 @@ namespace modules {
current_group = 0; current_group = 0;
} }
printf("%zu\n", current_group);
xkb_util::switch_layout(m_connection, XCB_XKB_ID_USE_CORE_KBD, current_group); xkb_util::switch_layout(m_connection, XCB_XKB_ID_USE_CORE_KBD, current_group);
m_keyboard->current(current_group); m_keyboard->current(current_group);
m_connection.flush(); m_connection.flush();