refactor: Use plain std::function callbacks

Replace fastdelegate with plain std::function's because
of incomplete clang support
This commit is contained in:
Michael Carlberg 2016-10-25 01:51:55 +02:00
parent 6b9d162981
commit bcf9249dc7
7 changed files with 133 additions and 118 deletions

View File

@ -46,19 +46,22 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
*/
~bar() {
std::lock_guard<threading_util::spin_lock> lck(m_lock);
g_signals::parser::alignment_change.disconnect(this, &bar::on_alignment_change);
g_signals::parser::attribute_set.disconnect(this, &bar::on_attribute_set);
g_signals::parser::attribute_unset.disconnect(this, &bar::on_attribute_unset);
g_signals::parser::attribute_toggle.disconnect(this, &bar::on_attribute_toggle);
g_signals::parser::action_block_open.disconnect(this, &bar::on_action_block_open);
g_signals::parser::action_block_close.disconnect(this, &bar::on_action_block_close);
g_signals::parser::color_change.disconnect(this, &bar::on_color_change);
g_signals::parser::font_change.disconnect(this, &bar::on_font_change);
g_signals::parser::pixel_offset.disconnect(this, &bar::on_pixel_offset);
g_signals::parser::ascii_text_write.disconnect(this, &bar::draw_character);
g_signals::parser::unicode_text_write.disconnect(this, &bar::draw_character);
if (m_tray.align != alignment::NONE)
g_signals::tray::report_slotcount.disconnect(this, &bar::on_tray_report);
// Disconnect signal handlers {{{
g_signals::parser::alignment_change = nullptr;
g_signals::parser::attribute_set = nullptr;
g_signals::parser::attribute_unset = nullptr;
g_signals::parser::attribute_toggle = nullptr;
g_signals::parser::action_block_open = nullptr;
g_signals::parser::action_block_close = nullptr;
g_signals::parser::color_change = nullptr;
g_signals::parser::font_change = nullptr;
g_signals::parser::pixel_offset = nullptr;
g_signals::parser::ascii_text_write = nullptr;
g_signals::parser::unicode_text_write = nullptr;
g_signals::tray::report_slotcount = nullptr;
// }}}
if (m_sinkattached)
m_connection.detach_sink(this, 1);
m_window.destroy();
@ -444,20 +447,22 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
// }}}
// Connect signal handlers {{{
g_signals::parser::alignment_change.connect(this, &bar::on_alignment_change);
g_signals::parser::attribute_set.connect(this, &bar::on_attribute_set);
g_signals::parser::attribute_unset.connect(this, &bar::on_attribute_unset);
g_signals::parser::attribute_toggle.connect(this, &bar::on_attribute_toggle);
g_signals::parser::action_block_open.connect(this, &bar::on_action_block_open);
g_signals::parser::action_block_close.connect(this, &bar::on_action_block_close);
g_signals::parser::color_change.connect(this, &bar::on_color_change);
g_signals::parser::font_change.connect(this, &bar::on_font_change);
g_signals::parser::pixel_offset.connect(this, &bar::on_pixel_offset);
g_signals::parser::ascii_text_write.connect(this, &bar::draw_character);
g_signals::parser::unicode_text_write.connect(this, &bar::draw_character);
// clang-format off
g_signals::parser::alignment_change = bind(&bar::on_alignment_change, this, std::placeholders::_1);
g_signals::parser::attribute_set = bind(&bar::on_attribute_set, this, std::placeholders::_1);
g_signals::parser::attribute_unset = bind(&bar::on_attribute_unset, this, std::placeholders::_1);
g_signals::parser::attribute_toggle = bind(&bar::on_attribute_toggle, this, std::placeholders::_1);
g_signals::parser::action_block_open = bind(&bar::on_action_block_open, this, std::placeholders::_1, std::placeholders::_2);
g_signals::parser::action_block_close = bind(&bar::on_action_block_close, this, std::placeholders::_1);
g_signals::parser::color_change = bind(&bar::on_color_change, this, std::placeholders::_1, std::placeholders::_2);
g_signals::parser::font_change = bind(&bar::on_font_change, this, std::placeholders::_1);
g_signals::parser::pixel_offset = bind(&bar::on_pixel_offset, this, std::placeholders::_1);
g_signals::parser::ascii_text_write = bind(&bar::draw_character, this, std::placeholders::_1);
g_signals::parser::unicode_text_write = bind(&bar::draw_character, this, std::placeholders::_1);
// clang-format on
if (m_tray.align != alignment::NONE)
g_signals::tray::report_slotcount.connect(this, &bar::on_tray_report);
g_signals::tray::report_slotcount = bind(&bar::on_tray_report, this, std::placeholders::_1);
// }}}
@ -535,11 +540,9 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
m_pixmap, m_window, m_gcontexts.at(gc::BR), 0, 0, 0, 0, m_bar.width, m_bar.height);
#if DEBUG and DRAW_CLICKABLE_AREA_HINTS
map<alignment, int> hint_num{
{ {alignment::LEFT, 0},
{alignment::CENTER, 0},
{alignment::RIGHT, 0},
}};
map<alignment, int> hint_num{{
{alignment::LEFT, 0}, {alignment::CENTER, 0}, {alignment::RIGHT, 0},
}};
#endif
for (auto&& action : m_actions) {
@ -625,8 +628,8 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
m_log.trace("action.start_x = %i", action.start_x);
m_log.trace("action.end_x = %i", action.end_x);
if (!g_signals::bar::action_click.empty())
g_signals::bar::action_click.emit(action.command);
if (g_signals::bar::action_click)
g_signals::bar::action_click(action.command);
else
m_log.warn("No signal handler's connected to 'action_click'");
@ -663,19 +666,19 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
*/
void handle(const evt::property_notify& evt) { // {{{
if (evt->window == m_window && evt->atom == WM_STATE) {
if (g_signals::bar::visibility_change.empty()) {
if (!g_signals::bar::visibility_change)
return;
}
try {
auto attr = m_connection.get_window_attributes(m_window);
if (attr->map_state == XCB_MAP_STATE_VIEWABLE)
g_signals::bar::visibility_change.emit(true);
g_signals::bar::visibility_change(true);
else if (attr->map_state == XCB_MAP_STATE_UNVIEWABLE)
g_signals::bar::visibility_change.emit(false);
g_signals::bar::visibility_change(false);
else if (attr->map_state == XCB_MAP_STATE_UNMAPPED)
g_signals::bar::visibility_change.emit(false);
g_signals::bar::visibility_change(false);
else
g_signals::bar::visibility_change.emit(true);
g_signals::bar::visibility_change(true);
} catch (const std::exception& err) {
m_log.warn("Failed to emit bar window's visibility change event");
}

View File

@ -87,7 +87,7 @@ class controller {
}
m_log.trace("controller: Deconstruct bar instance");
g_signals::bar::action_click.clear();
g_signals::bar::action_click = nullptr;
m_bar.reset();
m_log.trace("controller: Interrupt X event loop");
@ -159,7 +159,7 @@ class controller {
std::cout << m_bar->settings().wmname << std::endl;
return;
} else if (!to_stdout) {
g_signals::bar::action_click.connect(this, &controller::on_module_click);
g_signals::bar::action_click = bind(&controller::on_module_click, this, std::placeholders::_1);
}
} catch (const std::exception& err) {
throw application_error("Failed to setup bar renderer: " + string{err.what()});
@ -411,8 +411,8 @@ class controller {
auto& module = modules.back();
module->set_writer(delegate::MakeDelegate(this, &controller::on_module_update));
module->set_terminator(delegate::MakeDelegate(this, &controller::on_module_stop));
module->set_writer(bind(&controller::on_module_update, this, std::placeholders::_1));
module->set_terminator(bind(&controller::on_module_stop, this, std::placeholders::_1));
module_count++;
}

View File

@ -80,11 +80,13 @@ class logger {
* Output a trace message
*/
template <typename... Args>
void trace(string message, Args... args) const {
#ifdef DEBUG
void trace(string message, Args... args) const {
output(loglevel::TRACE, message, args...);
#endif
}
#else
void trace(string, Args...) const {}
#endif
/**
* Output an info message

View File

@ -1,10 +1,8 @@
#pragma once
#include <fastdelegate/fastdelegate.hpp>
#include "common.hpp"
#include "components/types.hpp"
#include "components/signals.hpp"
#include "components/types.hpp"
#include "utils/math.hpp"
#include "utils/string.hpp"
@ -63,69 +61,69 @@ class parser {
switch (tag) {
case 'B':
// Ignore tag if it occurs again later in the same block
if (data.find(" B") == string::npos && !g_signals::parser::color_change.empty())
g_signals::parser::color_change.emit(gc::BG, parse_color(value, m_bar.background));
if (data.find(" B") == string::npos && g_signals::parser::color_change)
g_signals::parser::color_change(gc::BG, parse_color(value, m_bar.background));
break;
case 'F':
// Ignore tag if it occurs again later in the same block
if (data.find(" F") == string::npos && !g_signals::parser::color_change.empty())
g_signals::parser::color_change.emit(gc::FG, parse_color(value, m_bar.foreground));
if (data.find(" F") == string::npos && g_signals::parser::color_change)
g_signals::parser::color_change(gc::FG, parse_color(value, m_bar.foreground));
break;
case 'U':
// Ignore tag if it occurs again later in the same block
if (data.find(" U") == string::npos && !g_signals::parser::color_change.empty()) {
g_signals::parser::color_change.emit(gc::UL, parse_color(value, m_bar.linecolor));
g_signals::parser::color_change.emit(gc::OL, parse_color(value, m_bar.linecolor));
if (data.find(" U") == string::npos && g_signals::parser::color_change) {
g_signals::parser::color_change(gc::UL, parse_color(value, m_bar.linecolor));
g_signals::parser::color_change(gc::OL, parse_color(value, m_bar.linecolor));
}
break;
case 'R':
if (!g_signals::parser::color_change.empty()) {
g_signals::parser::color_change.emit(gc::BG, m_bar.foreground);
g_signals::parser::color_change.emit(gc::FG, m_bar.background);
if (g_signals::parser::color_change) {
g_signals::parser::color_change(gc::BG, m_bar.foreground);
g_signals::parser::color_change(gc::FG, m_bar.background);
}
break;
case 'T':
if (data.find(" T") == string::npos && !g_signals::parser::font_change.empty())
g_signals::parser::font_change.emit(parse_fontindex(value));
if (data.find(" T") == string::npos && g_signals::parser::font_change)
g_signals::parser::font_change(parse_fontindex(value));
break;
case 'O':
if (!g_signals::parser::pixel_offset.empty())
g_signals::parser::pixel_offset.emit(std::atoi(value.c_str()));
if (g_signals::parser::pixel_offset)
g_signals::parser::pixel_offset(std::atoi(value.c_str()));
break;
case 'l':
if (!g_signals::parser::alignment_change.empty())
g_signals::parser::alignment_change.emit(alignment::LEFT);
if (g_signals::parser::alignment_change)
g_signals::parser::alignment_change(alignment::LEFT);
break;
case 'c':
if (!g_signals::parser::alignment_change.empty())
g_signals::parser::alignment_change.emit(alignment::CENTER);
if (g_signals::parser::alignment_change)
g_signals::parser::alignment_change(alignment::CENTER);
break;
case 'r':
if (!g_signals::parser::alignment_change.empty())
g_signals::parser::alignment_change.emit(alignment::RIGHT);
if (g_signals::parser::alignment_change)
g_signals::parser::alignment_change(alignment::RIGHT);
break;
case '+':
if (!g_signals::parser::attribute_set.empty())
g_signals::parser::attribute_set.emit(parse_attr(value[0]));
if (g_signals::parser::attribute_set)
g_signals::parser::attribute_set(parse_attr(value[0]));
break;
case '-':
if (!g_signals::parser::attribute_unset.empty())
g_signals::parser::attribute_unset.emit(parse_attr(value[0]));
if (g_signals::parser::attribute_unset)
g_signals::parser::attribute_unset(parse_attr(value[0]));
break;
case '!':
if (!g_signals::parser::attribute_toggle.empty())
g_signals::parser::attribute_toggle.emit(parse_attr(value[0]));
if (g_signals::parser::attribute_toggle)
g_signals::parser::attribute_toggle(parse_attr(value[0]));
break;
case 'A':
@ -134,16 +132,16 @@ class parser {
mousebtn btn = parse_action_btn(data);
m_actions.push_back(static_cast<int>(btn));
if (!g_signals::parser::action_block_open.empty())
g_signals::parser::action_block_open.emit(btn, value);
if (g_signals::parser::action_block_open)
g_signals::parser::action_block_open(btn, value);
// make sure we strip the correct length (btn+wrapping colons)
if (data[0] != ':')
value += "0";
value += "::";
} else if (!m_actions.empty()) {
if (!g_signals::parser::action_block_close.empty())
g_signals::parser::action_block_close.emit(parse_action_btn(data));
if (g_signals::parser::action_block_close)
g_signals::parser::action_block_close(parse_action_btn(data));
m_actions.pop_back();
}
break;
@ -170,31 +168,39 @@ class parser {
// size_t n = 0;
// while (sequence[n] != '\0' && static_cast<uint8_t>(sequence[n]) < 0x80 && ++n <= next_tag)
// ;
// g_signals::parser::ascii_text_write.emit(data.substr(0, n));
// if (g_signals::parser::ascii_text_write)
// g_signals::parser::ascii_text_write(data.substr(0, n));
// return data.length();
// }
if (utf[0] < 0x80) {
g_signals::parser::ascii_text_write.emit(utf[0]);
if (g_signals::parser::ascii_text_write)
g_signals::parser::ascii_text_write(utf[0]);
return 1;
} else if ((utf[0] & 0xe0) == 0xc0) { // 2 byte utf-8 sequence
g_signals::parser::unicode_text_write.emit((utf[0] & 0x1f) << 6 | (utf[1] & 0x3f));
if (g_signals::parser::unicode_text_write)
g_signals::parser::unicode_text_write((utf[0] & 0x1f) << 6 | (utf[1] & 0x3f));
return 2;
} else if ((utf[0] & 0xf0) == 0xe0) { // 3 byte utf-8 sequence
g_signals::parser::unicode_text_write.emit(
(utf[0] & 0xf) << 12 | (utf[1] & 0x3f) << 6 | (utf[2] & 0x3f));
if (g_signals::parser::unicode_text_write)
g_signals::parser::unicode_text_write(
(utf[0] & 0xf) << 12 | (utf[1] & 0x3f) << 6 | (utf[2] & 0x3f));
return 3;
} else if ((utf[0] & 0xf8) == 0xf0) { // 4 byte utf-8 sequence
g_signals::parser::unicode_text_write.emit(0xfffd);
if (g_signals::parser::unicode_text_write)
g_signals::parser::unicode_text_write(0xfffd);
return 4;
} else if ((utf[0] & 0xfc) == 0xf8) { // 5 byte utf-8 sequence
g_signals::parser::unicode_text_write.emit(0xfffd);
if (g_signals::parser::unicode_text_write)
g_signals::parser::unicode_text_write(0xfffd);
return 5;
} else if ((utf[0] & 0xfe) == 0xfc) { // 6 byte utf-8 sequence
g_signals::parser::unicode_text_write.emit(0xfffd);
if (g_signals::parser::unicode_text_write)
g_signals::parser::unicode_text_write(0xfffd);
return 6;
} else { // invalid utf-8 sequence
g_signals::parser::ascii_text_write.emit(utf[0]);
if (g_signals::parser::ascii_text_write)
g_signals::parser::ascii_text_write(utf[0]);
return 1;
}
} // }}}

View File

@ -1,43 +1,44 @@
#pragma once
#include <fastdelegate/fastdelegate.hpp>
#include "common.hpp"
#include "components/types.hpp"
LEMONBUDDY_NS
/**
* @TODO: Allow multiple signal handlers
*/
namespace g_signals {
/**
* Signals used to communicate with the bar window
*/
namespace bar {
static delegate::Signal1<string> action_click;
static delegate::Signal1<bool> visibility_change;
static function<void(string)> action_click;
static function<void(bool)> visibility_change;
}
/**
* Signals used to communicate with the input parser
*/
namespace parser {
static delegate::Signal1<alignment> alignment_change;
static delegate::Signal1<attribute> attribute_set;
static delegate::Signal1<attribute> attribute_unset;
static delegate::Signal1<attribute> attribute_toggle;
static delegate::Signal2<mousebtn, string> action_block_open;
static delegate::Signal1<mousebtn> action_block_close;
static delegate::Signal2<gc, color> color_change;
static delegate::Signal1<int> font_change;
static delegate::Signal1<int> pixel_offset;
static delegate::Signal1<uint16_t> ascii_text_write;
static delegate::Signal1<uint16_t> unicode_text_write;
static function<void(alignment)> alignment_change;
static function<void(attribute)> attribute_set;
static function<void(attribute)> attribute_unset;
static function<void(attribute)> attribute_toggle;
static function<void(mousebtn, string)> action_block_open;
static function<void(mousebtn)> action_block_close;
static function<void(gc, color)> color_change;
static function<void(int)> font_change;
static function<void(int)> pixel_offset;
static function<void(uint16_t)> ascii_text_write;
static function<void(uint16_t)> unicode_text_write;
}
/**
* Signals used to communicate with the tray manager
*/
namespace tray {
static delegate::Signal1<uint16_t> report_slotcount;
static function<void(uint16_t)> report_slotcount;
}
}

View File

@ -147,7 +147,8 @@ class traymanager
// Listen for visibility change events on the bar window
if (!m_restacked) {
g_signals::bar::visibility_change.connect(this, &traymanager::bar_visibility_change);
g_signals::bar::visibility_change =
bind(&traymanager::bar_visibility_change, this, std::placeholders::_1);
}
// Attempt to get control of the systray selection then
@ -193,7 +194,8 @@ class traymanager
}
if (!m_restacked) {
g_signals::bar::visibility_change.disconnect(this, &traymanager::bar_visibility_change);
g_signals::bar::visibility_change =
bind(&traymanager::bar_visibility_change, this, std::placeholders::_1);
}
// Dismiss all clients by reparenting them to the root window
@ -238,8 +240,8 @@ class traymanager
}
}
if (!g_signals::tray::report_slotcount.empty())
g_signals::tray::report_slotcount.emit(mapped_clients);
if (g_signals::tray::report_slotcount)
g_signals::tray::report_slotcount(mapped_clients);
if (!width && m_mapped) {
m_connection.unmap_window(m_tray);
@ -540,7 +542,7 @@ class traymanager
void handle(const evt::expose& evt) {
if (!m_activated || m_clients.empty())
return;
m_logger.trace("tray: Received expose event");
m_logger.trace("tray: Received expose event for %s", m_connection.id(evt->window));
reconfigure();
}
@ -550,7 +552,7 @@ class traymanager
void handle(const evt::visibility_notify& evt) {
if (!m_activated || m_clients.empty())
return;
m_logger.trace("tray: Received visibility_notify");
m_logger.trace("tray: Received visibility_notify for %s", m_connection.id(evt->window));
reconfigure();
}

View File

@ -2,7 +2,6 @@
#include <algorithm>
#include <condition_variable>
#include <fastdelegate/fastdelegate.hpp>
#include <mutex>
#include "common.hpp"
@ -158,8 +157,8 @@ namespace modules {
virtual bool handle_event(string cmd) = 0;
virtual bool receive_events() const = 0;
virtual void set_writer(delegate::Delegate1<string>&& fn) = 0;
virtual void set_terminator(delegate::Delegate1<string>&& fn) = 0;
virtual void set_writer(std::function<void(string)>&& fn) = 0;
virtual void set_terminator(std::function<void(string)>&& fn) = 0;
};
// }}}
@ -197,11 +196,11 @@ namespace modules {
m_log.trace("%s: Done cleaning up", name());
}
void set_writer(delegate::Delegate1<string>&& fn) {
void set_writer(std::function<void(string)>&& fn) {
m_writer = forward<decltype(fn)>(fn);
}
void set_terminator(delegate::Delegate1<string>&& fn) {
void set_terminator(std::function<void(string)>&& fn) {
m_terminator = forward<decltype(fn)>(fn);
}
@ -261,11 +260,13 @@ namespace modules {
void broadcast() {
if (!enabled())
return;
else if (!m_writer)
m_log.warn("%s: No attach writer, ignoring broadcast...", name());
m_cache = CAST_MOD(Impl)->get_output();
m_writer(name());
if (m_writer)
m_writer(name());
else
m_log.warn("%s: No handler, ignoring broadcast...", name());
}
void idle() {}
@ -318,8 +319,8 @@ namespace modules {
}
protected:
delegate::Delegate1<string> m_writer;
delegate::Delegate1<string> m_terminator;
function<void(string)> m_writer;
function<void(string)> m_terminator;
threading_util::spin_lock m_updatelock;
// std::timed_mutex m_mutex;