mirror of
https://github.com/polybar/polybar.git
synced 2024-11-11 13:50:56 -05:00
113 lines
2.7 KiB
C++
113 lines
2.7 KiB
C++
|
#pragma once
|
||
|
|
||
|
#include "common.hpp"
|
||
|
#include "events/signal_receiver.hpp"
|
||
|
#include "utils/factory.hpp"
|
||
|
#include "utils/mixins.hpp"
|
||
|
|
||
|
POLYBAR_NS
|
||
|
|
||
|
/**
|
||
|
* @brief Holds all signal receivers attached to the emitter
|
||
|
*/
|
||
|
extern signal_receivers_t g_signal_receivers;
|
||
|
|
||
|
/**
|
||
|
* Wrapper used to delegate emitted signals
|
||
|
* to attached signal receivers
|
||
|
*/
|
||
|
class signal_emitter {
|
||
|
public:
|
||
|
explicit signal_emitter() = default;
|
||
|
virtual ~signal_emitter() {}
|
||
|
|
||
|
template <typename Signal>
|
||
|
bool emit(const Signal& sig) {
|
||
|
try {
|
||
|
for (auto&& item : g_signal_receivers.at(id<Signal>())) {
|
||
|
if (item.second->on(sig)) {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
} catch (...) {
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
template <typename Signal, typename Next, typename... Signals>
|
||
|
bool emit(const Signal& sig) const {
|
||
|
return emit<Signal>(sig) || emit<Next, Signals...>(sig);
|
||
|
}
|
||
|
|
||
|
template <uint8_t Priority, typename Signal, typename... Signals>
|
||
|
void attach(signal_receiver<Priority, Signal, Signals...>* s) {
|
||
|
attach<signal_receiver<Priority, Signal, Signals...>, Signal, Signals...>(s);
|
||
|
}
|
||
|
|
||
|
template <uint8_t Priority, typename Signal, typename... Signals>
|
||
|
void detach(signal_receiver<Priority, Signal, Signals...>* s) {
|
||
|
detach<signal_receiver<Priority, Signal, Signals...>, Signal, Signals...>(s);
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
template <typename Signal>
|
||
|
uint8_t id() const {
|
||
|
return Signal::id();
|
||
|
}
|
||
|
|
||
|
template <typename Receiver, typename Signal>
|
||
|
void attach(Receiver* s) {
|
||
|
attach(s, id<Signal>());
|
||
|
}
|
||
|
|
||
|
template <typename Receiver, typename Signal, typename Next, typename... Signals>
|
||
|
void attach(Receiver* s) {
|
||
|
attach(s, id<Signal>());
|
||
|
attach<Receiver, Next, Signals...>(s);
|
||
|
}
|
||
|
|
||
|
void attach(signal_receiver_interface* s, uint8_t id) {
|
||
|
g_signal_receivers[id].emplace(s->priority(), s);
|
||
|
}
|
||
|
|
||
|
template <typename Receiver, typename Signal>
|
||
|
void detach(Receiver* s) {
|
||
|
detach(s, id<Signal>());
|
||
|
}
|
||
|
|
||
|
template <typename Receiver, typename Signal, typename Next, typename... Signals>
|
||
|
void detach(Receiver* s) {
|
||
|
detach(s, id<Signal>());
|
||
|
detach<Receiver, Next, Signals...>(s);
|
||
|
}
|
||
|
|
||
|
void detach(signal_receiver_interface* d, uint8_t id) {
|
||
|
try {
|
||
|
auto& prio_map = g_signal_receivers.at(id);
|
||
|
const auto& prio_sink_pair = prio_map.equal_range(d->priority());
|
||
|
|
||
|
for (auto it = prio_sink_pair.first; it != prio_sink_pair.second;) {
|
||
|
if (d == it->second) {
|
||
|
it = prio_map.erase(it);
|
||
|
} else {
|
||
|
++it;
|
||
|
}
|
||
|
}
|
||
|
} catch (...) {
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
namespace {
|
||
|
/**
|
||
|
* Configure injection module
|
||
|
*/
|
||
|
inline signal_emitter& make_signal_emitter() {
|
||
|
auto instance = factory_util::singleton<signal_emitter>();
|
||
|
return static_cast<signal_emitter&>(*instance);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
POLYBAR_NS_END
|