wip(refactor): Improve signal and event handling
This commit is contained in:
parent
d45fd76dcd
commit
08be86fbe1
73 changed files with 2228 additions and 2251 deletions
|
@ -2,12 +2,16 @@
|
|||
|
||||
#include "common.hpp"
|
||||
#include "components/config.hpp"
|
||||
#include "components/screen.hpp"
|
||||
#include "components/types.hpp"
|
||||
#include "errors.hpp"
|
||||
#include "events/signal_emitter.hpp"
|
||||
#include "events/signal_fwd.hpp"
|
||||
#include "utils/concurrency.hpp"
|
||||
#include "utils/throttle.hpp"
|
||||
#include "x11/connection.hpp"
|
||||
#include "x11/events.hpp"
|
||||
#include "x11/tray_manager.hpp"
|
||||
#include "x11/types.hpp"
|
||||
#include "x11/window.hpp"
|
||||
|
||||
|
@ -21,20 +25,16 @@ class renderer;
|
|||
|
||||
class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::property_notify> {
|
||||
public:
|
||||
explicit bar(connection& conn, const config& config, const logger& logger, unique_ptr<screen> screen, unique_ptr<tray_manager> tray_manager);
|
||||
~bar();
|
||||
explicit bar(connection& conn, signal_emitter& emitter, const config& config, const logger& logger,
|
||||
unique_ptr<screen> screen, unique_ptr<tray_manager> tray_manager);
|
||||
|
||||
void bootstrap(bool nodraw = false);
|
||||
void bootstrap_tray();
|
||||
void activate_tray();
|
||||
~bar();
|
||||
|
||||
const bar_settings settings() const;
|
||||
|
||||
void parse(const string& data, bool force = false);
|
||||
|
||||
protected:
|
||||
void setup_monitor();
|
||||
void configure_geom();
|
||||
void restack_window();
|
||||
void reconfigure_pos();
|
||||
void reconfigure_struts();
|
||||
|
@ -47,22 +47,37 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
|
|||
|
||||
private:
|
||||
connection& m_connection;
|
||||
signal_emitter& m_sig;
|
||||
const config& m_conf;
|
||||
const logger& m_log;
|
||||
unique_ptr<screen> m_screen;
|
||||
unique_ptr<tray_manager> m_tray;
|
||||
unique_ptr<renderer> m_renderer;
|
||||
|
||||
xcb_window_t m_window;
|
||||
bar_settings m_opts;
|
||||
|
||||
string m_lastinput;
|
||||
|
||||
std::mutex m_mutex;
|
||||
|
||||
event_timer m_buttonpress{};
|
||||
event_timer m_buttonpress{0L, 5L};
|
||||
};
|
||||
|
||||
di::injector<unique_ptr<bar>> configure_bar();
|
||||
namespace {
|
||||
/**
|
||||
* Configure bar controller
|
||||
*/
|
||||
inline unique_ptr<bar> make_bar() {
|
||||
// clang-format off
|
||||
return factory_util::unique<bar>(
|
||||
make_connection(),
|
||||
make_signal_emitter(),
|
||||
make_confreader(),
|
||||
make_logger(),
|
||||
make_screen(),
|
||||
make_tray_manager());
|
||||
// clang-format on
|
||||
}
|
||||
}
|
||||
|
||||
POLYBAR_NS_END
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "common.hpp"
|
||||
#include "components/config.hpp"
|
||||
#include "components/types.hpp"
|
||||
|
@ -7,6 +9,8 @@
|
|||
|
||||
POLYBAR_NS
|
||||
|
||||
using std::map;
|
||||
|
||||
#define DEFAULT_SPACING -1
|
||||
|
||||
#ifndef BUILDER_SPACE_TOKEN
|
||||
|
@ -28,7 +32,7 @@ class builder {
|
|||
explicit builder(const bar_settings bar) : m_bar(bar) {}
|
||||
|
||||
string flush();
|
||||
void append(string text);
|
||||
void append(const string& text);
|
||||
void node(string str, bool add_space = false);
|
||||
void node(string str, int font_index, bool add_space = false);
|
||||
void node(const label_t& label, bool add_space = false);
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "common.hpp"
|
||||
#include "errors.hpp"
|
||||
#include "utils/factory.hpp"
|
||||
|
||||
POLYBAR_NS
|
||||
|
||||
|
@ -12,7 +15,7 @@ namespace command_line {
|
|||
class option;
|
||||
using choices = vector<string>;
|
||||
using options = vector<option>;
|
||||
using values = map<string, string>;
|
||||
using values = std::map<string, string>;
|
||||
|
||||
// class definition : option {{{
|
||||
|
||||
|
@ -69,13 +72,8 @@ namespace {
|
|||
/**
|
||||
* Configure injection module
|
||||
*/
|
||||
template <class T = cliparser>
|
||||
di::injector<T> configure_cliparser(string scriptname, const clioptions& opts) {
|
||||
// clang-format off
|
||||
return di::make_injector(
|
||||
di::bind<>().to("Usage: " + scriptname + " bar_name [OPTION...]"),
|
||||
di::bind<>().to(opts));
|
||||
// clang-format on
|
||||
inline unique_ptr<cliparser> make_command_line(string scriptname, const clioptions& opts) {
|
||||
return factory_util::unique<cliparser>("Usage: " + scriptname + " bar_name [OPTION...]", opts);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -268,9 +268,9 @@ namespace {
|
|||
/**
|
||||
* Configure injection module
|
||||
*/
|
||||
template <typename T = const config&>
|
||||
di::injector<T> configure_config() {
|
||||
return di::make_injector(configure_logger(), configure_xresource_manager());
|
||||
inline const config& make_confreader() {
|
||||
shared_ptr<config> instance = factory_util::singleton<config>(make_logger(), make_xresource_manager());
|
||||
return static_cast<config&>(*instance);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,11 +3,16 @@
|
|||
#include <csignal>
|
||||
|
||||
#include "common.hpp"
|
||||
#include "components/bar.hpp"
|
||||
#include "components/config.hpp"
|
||||
#include "components/eventloop.hpp"
|
||||
#include "components/ipc.hpp"
|
||||
#include "components/logger.hpp"
|
||||
#include "components/types.hpp"
|
||||
#include "config.hpp"
|
||||
#include "events/signal_emitter.hpp"
|
||||
#include "events/signal_fwd.hpp"
|
||||
#include "events/signal_receiver.hpp"
|
||||
#include "utils/command.hpp"
|
||||
#include "utils/inotify.hpp"
|
||||
#include "x11/connection.hpp"
|
||||
|
@ -18,65 +23,46 @@ POLYBAR_NS
|
|||
// fwd decl {{{
|
||||
|
||||
class bar;
|
||||
struct bar_settings;
|
||||
|
||||
// }}}
|
||||
|
||||
using watch_t = inotify_util::watch_t;
|
||||
|
||||
class controller {
|
||||
public:
|
||||
explicit controller(connection& conn, const logger& logger, const config& config, unique_ptr<eventloop> eventloop,
|
||||
unique_ptr<bar> bar, inotify_util::watch_t& confwatch)
|
||||
: m_connection(conn)
|
||||
, m_log(logger)
|
||||
, m_conf(config)
|
||||
, m_eventloop(forward<decltype(eventloop)>(eventloop))
|
||||
, m_bar(forward<decltype(bar)>(bar))
|
||||
, m_confwatch(confwatch) {}
|
||||
namespace sig_ev = signals::eventloop;
|
||||
namespace sig_ui = signals::ui;
|
||||
namespace sig_ipc = signals::ipc;
|
||||
|
||||
class controller : public signal_receiver<SIGN_PRIORITY_CONTROLLER, sig_ev::process_update, sig_ev::process_input,
|
||||
sig_ev::process_quit, sig_ui::button_press, sig_ipc::process_action, sig_ipc::process_command,
|
||||
sig_ipc::process_hook> {
|
||||
public:
|
||||
explicit controller(connection& conn, signal_emitter& emitter, const logger& logger, const config& config,
|
||||
unique_ptr<eventloop> eventloop, unique_ptr<bar> bar, unique_ptr<ipc> ipc, watch_t confwatch, bool writeback);
|
||||
~controller();
|
||||
|
||||
void bootstrap(bool writeback = false, bool dump_wmname = false);
|
||||
void setup();
|
||||
bool run();
|
||||
|
||||
const bar_settings opts() const;
|
||||
|
||||
protected:
|
||||
void install_sigmask();
|
||||
void uninstall_sigmask();
|
||||
|
||||
void install_confwatch();
|
||||
void uninstall_confwatch();
|
||||
|
||||
void wait_for_signal();
|
||||
void wait_for_xevent();
|
||||
void wait_for_eventloop();
|
||||
void wait_for_configwatch();
|
||||
|
||||
void bootstrap_modules();
|
||||
|
||||
void on_ipc_action(const ipc_action& message);
|
||||
void on_mouse_event(const string& input);
|
||||
void on_unrecognized_action(string input);
|
||||
void on_update(bool force);
|
||||
|
||||
private:
|
||||
enum class thread_role {
|
||||
EVENT_QUEUE,
|
||||
EVENT_QUEUE_X,
|
||||
IPC_LISTENER,
|
||||
CONF_LISTENER,
|
||||
};
|
||||
|
||||
bool is_thread_joinable(thread_role&& role) {
|
||||
if (m_threads.find(role) == m_threads.end()) {
|
||||
return false;
|
||||
} else {
|
||||
return m_threads[role].joinable();
|
||||
}
|
||||
}
|
||||
bool on(const sig_ev::process_update& evt);
|
||||
bool on(const sig_ev::process_input& evt);
|
||||
bool on(const sig_ev::process_quit& evt);
|
||||
bool on(const sig_ui::button_press& evt);
|
||||
bool on(const sig_ipc::process_action& evt);
|
||||
bool on(const sig_ipc::process_command& evt);
|
||||
bool on(const sig_ipc::process_hook& evt);
|
||||
|
||||
private:
|
||||
connection& m_connection;
|
||||
registry m_registry{m_connection};
|
||||
signal_emitter& m_sig;
|
||||
const logger& m_log;
|
||||
const config& m_conf;
|
||||
unique_ptr<eventloop> m_eventloop;
|
||||
|
@ -86,18 +72,37 @@ class controller {
|
|||
stateflag m_running{false};
|
||||
stateflag m_reload{false};
|
||||
stateflag m_waiting{false};
|
||||
stateflag m_trayactivated{false};
|
||||
|
||||
sigset_t m_blockmask;
|
||||
sigset_t m_waitmask;
|
||||
map<thread_role, thread> m_threads;
|
||||
vector<thread> m_threads;
|
||||
|
||||
inotify_util::watch_t& m_confwatch;
|
||||
command_util::command_t m_command;
|
||||
watch_t m_confwatch;
|
||||
command_t m_command;
|
||||
|
||||
bool m_writeback{false};
|
||||
};
|
||||
|
||||
di::injector<unique_ptr<controller>> configure_controller(watch_t& confwatch);
|
||||
namespace {
|
||||
inline unique_ptr<controller> make_controller(watch_t&& confwatch, bool enableipc = false, bool writeback = false) {
|
||||
unique_ptr<ipc> ipc;
|
||||
|
||||
if (enableipc) {
|
||||
ipc = make_ipc();
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
return factory_util::unique<controller>(
|
||||
make_connection(),
|
||||
make_signal_emitter(),
|
||||
make_logger(),
|
||||
make_confreader(),
|
||||
make_eventloop(),
|
||||
make_bar(),
|
||||
move(ipc),
|
||||
move(confwatch),
|
||||
writeback);
|
||||
// clang-format on
|
||||
}
|
||||
}
|
||||
|
||||
POLYBAR_NS_END
|
||||
|
|
|
@ -5,104 +5,107 @@
|
|||
|
||||
#include "common.hpp"
|
||||
#include "components/logger.hpp"
|
||||
#include "events/signal_emitter.hpp"
|
||||
#include "events/signal_fwd.hpp"
|
||||
#include "events/signal_receiver.hpp"
|
||||
#include "modules/meta/base.hpp"
|
||||
|
||||
POLYBAR_NS
|
||||
|
||||
using namespace signals::eventloop;
|
||||
|
||||
using module_t = unique_ptr<modules::module_interface>;
|
||||
using modulemap_t = map<alignment, vector<module_t>>;
|
||||
|
||||
enum class event_type : uint8_t {
|
||||
NONE = 0,
|
||||
UPDATE,
|
||||
CHECK,
|
||||
INPUT,
|
||||
QUIT,
|
||||
};
|
||||
|
||||
struct event {
|
||||
uint8_t type{0};
|
||||
char data[256]{'\0'};
|
||||
};
|
||||
|
||||
struct quit_event {
|
||||
const uint8_t type{static_cast<uint8_t>(event_type::QUIT)};
|
||||
bool reload{false};
|
||||
};
|
||||
|
||||
struct update_event {
|
||||
const uint8_t type{static_cast<uint8_t>(event_type::UPDATE)};
|
||||
bool force{false};
|
||||
};
|
||||
|
||||
struct input_event {
|
||||
const uint8_t type{static_cast<uint8_t>(event_type::INPUT)};
|
||||
char data[256]{'\0'};
|
||||
};
|
||||
|
||||
class eventloop {
|
||||
class eventloop : public signal_receiver<SIGN_PRIORITY_EVENTLOOP, process_quit, process_input, process_check,
|
||||
enqueue_event, enqueue_quit, enqueue_update, enqueue_input, enqueue_check> {
|
||||
public:
|
||||
/**
|
||||
* Queue type
|
||||
*/
|
||||
using entry_t = event;
|
||||
using queue_t = moodycamel::BlockingConcurrentQueue<entry_t>;
|
||||
enum class event_type : uint8_t {
|
||||
NONE = 0,
|
||||
UPDATE,
|
||||
CHECK,
|
||||
INPUT,
|
||||
QUIT,
|
||||
};
|
||||
|
||||
struct event {
|
||||
uint8_t type{static_cast<uint8_t>(event_type::NONE)};
|
||||
bool flag{false};
|
||||
};
|
||||
|
||||
struct input_data {
|
||||
char data[EVENT_SIZE];
|
||||
};
|
||||
|
||||
template <typename EventType>
|
||||
using queue_t = moodycamel::BlockingConcurrentQueue<EventType>;
|
||||
using duration_t = chrono::duration<double, std::milli>;
|
||||
|
||||
explicit eventloop(const logger& logger, const config& config);
|
||||
public:
|
||||
explicit eventloop(signal_emitter& emitter, const logger& logger, const config& config);
|
||||
~eventloop();
|
||||
|
||||
void start();
|
||||
void wait();
|
||||
void stop();
|
||||
|
||||
bool enqueue(const entry_t& entry);
|
||||
bool enqueue_delayed(const entry_t& entry);
|
||||
|
||||
void set_update_cb(callback<bool>&& cb);
|
||||
void set_input_db(callback<string>&& cb);
|
||||
bool enqueue(event&& evt);
|
||||
bool enqueue(input_data&& evt);
|
||||
|
||||
void add_module(const alignment pos, module_t&& module);
|
||||
const modulemap_t& modules() const;
|
||||
size_t module_count() const;
|
||||
|
||||
static const eventloop::entry_t& make(update_event&& event, bool force = false) {
|
||||
event.force = force;
|
||||
return reinterpret_cast<const eventloop::entry_t&>(event);
|
||||
static auto make_quit_evt(bool reload = false) {
|
||||
return event{static_cast<uint8_t>(event_type::QUIT), reload};
|
||||
}
|
||||
|
||||
static const eventloop::entry_t& make(quit_event&& event, bool reload = false) {
|
||||
event.reload = reload;
|
||||
return reinterpret_cast<const eventloop::entry_t&>(event);
|
||||
static auto make_update_evt(bool force = false) {
|
||||
return event{static_cast<uint8_t>(event_type::UPDATE), force};
|
||||
}
|
||||
|
||||
static const eventloop::entry_t& make(input_event&& event, const string& data) {
|
||||
snprintf(event.data, sizeof(event.data), "%s", data.c_str());
|
||||
return reinterpret_cast<const eventloop::entry_t&>(event);
|
||||
static auto make_input_evt() {
|
||||
return event{static_cast<uint8_t>(event_type::INPUT)};
|
||||
}
|
||||
static auto make_input_data(string&& data) {
|
||||
input_data d{};
|
||||
memcpy(d.data, &data[0], sizeof(d.data));
|
||||
return d;
|
||||
}
|
||||
static auto make_check_evt() {
|
||||
return event{static_cast<uint8_t>(event_type::CHECK)};
|
||||
}
|
||||
|
||||
protected:
|
||||
void process_inputqueue();
|
||||
void dispatch_modules();
|
||||
void dispatch_queue_worker();
|
||||
void dispatch_delayed_worker();
|
||||
|
||||
inline bool match_event(entry_t evt, event_type type);
|
||||
inline bool compare_events(entry_t evt, entry_t evt2);
|
||||
void forward_event(entry_t evt);
|
||||
inline bool compare_events(event evt, event evt2);
|
||||
inline bool compare_events(input_data data, input_data data1);
|
||||
|
||||
void on_update(const update_event& evt);
|
||||
void on_input(const input_event& evt);
|
||||
void on_check();
|
||||
void on_quit(const quit_event& evt);
|
||||
void forward_event(event evt);
|
||||
|
||||
bool on(const process_input& evt);
|
||||
bool on(const process_check& evt);
|
||||
bool on(const process_quit& evt);
|
||||
|
||||
bool on(const enqueue_event& evt);
|
||||
bool on(const enqueue_quit& evt);
|
||||
bool on(const enqueue_update& evt);
|
||||
bool on(const enqueue_input& evt);
|
||||
bool on(const enqueue_check& evt);
|
||||
|
||||
private:
|
||||
signal_emitter& m_sig;
|
||||
const logger& m_log;
|
||||
const config& m_conf;
|
||||
|
||||
/**
|
||||
* @brief Event queue
|
||||
*/
|
||||
queue_t m_queue;
|
||||
queue_t<event> m_queue;
|
||||
|
||||
/**
|
||||
* @brief Event queue
|
||||
*/
|
||||
queue_t<input_data> m_inputqueue;
|
||||
|
||||
/**
|
||||
* @brief Loaded modules
|
||||
|
@ -114,16 +117,6 @@ class eventloop {
|
|||
*/
|
||||
stateflag m_running;
|
||||
|
||||
/**
|
||||
* @brief Callback fired when receiving UPDATE events
|
||||
*/
|
||||
callback<bool> m_update_cb;
|
||||
|
||||
/**
|
||||
* @brief Callback fired for unprocessed INPUT events
|
||||
*/
|
||||
callback<string> m_unrecognized_input_cb;
|
||||
|
||||
/**
|
||||
* @brief Time to wait for subsequent events
|
||||
*/
|
||||
|
@ -133,45 +126,11 @@ class eventloop {
|
|||
* @brief Maximum amount of subsequent events to swallow within timeframe
|
||||
*/
|
||||
size_t m_swallow_limit{0};
|
||||
|
||||
/**
|
||||
* @brief Time until releasing the lock on the delayed enqueue channel
|
||||
*/
|
||||
duration_t m_delayed_time;
|
||||
|
||||
/**
|
||||
* @brief Lock used to control the condition variable
|
||||
*/
|
||||
std::mutex m_delayed_lock;
|
||||
|
||||
/**
|
||||
* @brief Condition variable used to manage notifications for delayed enqueues
|
||||
*/
|
||||
std::condition_variable m_delayed_cond;
|
||||
|
||||
/**
|
||||
* @brief Pending event on the delayed channel
|
||||
*/
|
||||
entry_t m_delayed_entry{0};
|
||||
|
||||
/**
|
||||
* @brief Queue worker thread
|
||||
*/
|
||||
thread m_queue_thread;
|
||||
|
||||
/**
|
||||
* @brief Delayed notifier thread
|
||||
*/
|
||||
thread m_delayed_thread;
|
||||
};
|
||||
|
||||
namespace {
|
||||
/**
|
||||
* Configure injection module
|
||||
*/
|
||||
template <typename T = unique_ptr<eventloop>>
|
||||
di::injector<T> configure_eventloop() {
|
||||
return di::make_injector(configure_logger(), configure_config());
|
||||
inline unique_ptr<eventloop> make_eventloop() {
|
||||
return make_unique<eventloop>(make_signal_emitter(), make_logger(), make_confreader());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
18
include/components/eventloop_fwd.hpp
Normal file
18
include/components/eventloop_fwd.hpp
Normal file
|
@ -0,0 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
POLYBAR_NS
|
||||
|
||||
enum class event_type;
|
||||
struct event;
|
||||
struct quit_event;
|
||||
struct update_event;
|
||||
struct input_event;
|
||||
|
||||
class eventloop {
|
||||
public:
|
||||
using entry_t = event;
|
||||
};
|
||||
|
||||
POLYBAR_NS_END
|
|
@ -2,8 +2,10 @@
|
|||
|
||||
#include "common.hpp"
|
||||
#include "components/logger.hpp"
|
||||
#include "events/signal_emitter.hpp"
|
||||
#include "utils/concurrency.hpp"
|
||||
#include "utils/functional.hpp"
|
||||
#include "utils/factory.hpp"
|
||||
|
||||
POLYBAR_NS
|
||||
|
||||
|
@ -12,15 +14,15 @@ POLYBAR_NS
|
|||
*/
|
||||
struct ipc_command {
|
||||
static constexpr const char* prefix{"cmd:"};
|
||||
string payload;
|
||||
char payload[EVENT_SIZE]{'\0'};
|
||||
};
|
||||
struct ipc_hook {
|
||||
static constexpr const char* prefix{"hook:"};
|
||||
string payload;
|
||||
char payload[EVENT_SIZE]{'\0'};
|
||||
};
|
||||
struct ipc_action {
|
||||
static constexpr const char* prefix{"action:"};
|
||||
string payload;
|
||||
char payload[EVENT_SIZE]{'\0'};
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -32,40 +34,28 @@ struct ipc_action {
|
|||
*/
|
||||
class ipc {
|
||||
public:
|
||||
explicit ipc(const logger& logger) : m_log(logger) {}
|
||||
explicit ipc(signal_emitter& emitter, const logger& logger) : m_sig(emitter), m_log(logger) {}
|
||||
~ipc();
|
||||
|
||||
void attach_callback(callback<const ipc_command&>&& cb);
|
||||
void attach_callback(callback<const ipc_hook&>&& cb);
|
||||
void attach_callback(callback<const ipc_action&>&& cb);
|
||||
void receive_messages();
|
||||
|
||||
protected:
|
||||
void parse(const string& payload) const;
|
||||
void delegate(const ipc_command& message) const;
|
||||
void delegate(const ipc_hook& message) const;
|
||||
void delegate(const ipc_action& message) const;
|
||||
|
||||
private:
|
||||
signal_emitter& m_sig;
|
||||
const logger& m_log;
|
||||
|
||||
vector<callback<const ipc_command&>> m_command_callbacks;
|
||||
vector<callback<const ipc_hook&>> m_hook_callbacks;
|
||||
vector<callback<const ipc_action&>> m_action_callbacks;
|
||||
|
||||
stateflag m_running{false};
|
||||
|
||||
string m_fifo;
|
||||
int m_fd;
|
||||
stateflag m_running{false};
|
||||
};
|
||||
|
||||
namespace {
|
||||
/**
|
||||
* Configure injection module
|
||||
*/
|
||||
template <typename T = unique_ptr<ipc>>
|
||||
di::injector<T> configure_ipc() {
|
||||
return di::make_injector(configure_logger());
|
||||
inline unique_ptr<ipc> make_ipc() {
|
||||
return factory_util::unique<ipc>(make_signal_emitter(), make_logger());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdio>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
#include "common.hpp"
|
||||
#include "utils/factory.hpp"
|
||||
|
||||
POLYBAR_NS
|
||||
|
||||
enum class loglevel {
|
||||
enum class loglevel : uint8_t {
|
||||
NONE = 0,
|
||||
ERROR,
|
||||
WARNING,
|
||||
|
@ -25,34 +27,26 @@ class logger {
|
|||
void verbosity(loglevel level);
|
||||
void verbosity(string level);
|
||||
|
||||
/**
|
||||
* Output a trace message
|
||||
*/
|
||||
#ifdef DEBUG_LOGGER // {{{
|
||||
template <typename... Args>
|
||||
#ifdef DEBUG_LOGGER
|
||||
void trace(string message, Args... args) const {
|
||||
output(loglevel::TRACE, message, args...);
|
||||
}
|
||||
#else
|
||||
#ifdef VERBOSE_TRACELOG
|
||||
#undef VERBOSE_TRACELOG
|
||||
#endif
|
||||
void trace(string, Args...) const {
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Output extra verbose trace message
|
||||
*/
|
||||
template <typename... Args>
|
||||
#ifdef VERBOSE_TRACELOG
|
||||
void trace_x(string message, Args... args) const {
|
||||
output(loglevel::TRACE, message, args...);
|
||||
}
|
||||
#else
|
||||
void trace_x(string, Args...) const {
|
||||
}
|
||||
template <typename... Args>
|
||||
void trace_x(Args...) const {}
|
||||
#endif
|
||||
#else
|
||||
template <typename... Args>
|
||||
void trace(Args...) const {}
|
||||
template <typename... Args>
|
||||
void trace_x(Args...) const {}
|
||||
#endif // }}}
|
||||
|
||||
/**
|
||||
* Output an info message
|
||||
|
@ -97,70 +91,56 @@ class logger {
|
|||
*/
|
||||
template <typename... Args>
|
||||
void output(loglevel level, string format, Args... values) const {
|
||||
if (level > m_level)
|
||||
if (level > m_level) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto prefix = m_prefixes.find(level)->second;
|
||||
auto suffix = m_suffixes.find(level)->second;
|
||||
|
||||
// silence the compiler
|
||||
#if defined(__clang__)
|
||||
#if defined(__clang__) // {{{
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wformat-security"
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wformat-security"
|
||||
#endif
|
||||
dprintf(m_fd, (prefix + format + suffix + "\n").c_str(), convert(values)...);
|
||||
#if defined(__clang__)
|
||||
#endif // }}}
|
||||
|
||||
dprintf(m_fd, (m_prefixes.at(level) + format + m_suffixes.at(level) + "\n").c_str(), convert(values)...);
|
||||
|
||||
#if defined(__clang__) // {{{
|
||||
#pragma clang diagnostic pop
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif // }}}
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Logger verbosity level
|
||||
*/
|
||||
loglevel m_level = loglevel::TRACE;
|
||||
loglevel m_level{loglevel::TRACE};
|
||||
|
||||
/**
|
||||
* File descriptor used when writing the log messages
|
||||
*/
|
||||
int m_fd = STDERR_FILENO;
|
||||
int m_fd{STDERR_FILENO};
|
||||
|
||||
/**
|
||||
* Loglevel specific prefixes
|
||||
*/
|
||||
// clang-format off
|
||||
map<loglevel, string> m_prefixes {
|
||||
{loglevel::TRACE, "polybar|trace "},
|
||||
{loglevel::INFO, "polybar|info "},
|
||||
{loglevel::WARNING, "polybar|warn "},
|
||||
{loglevel::ERROR, "polybar|error "},
|
||||
};
|
||||
std::map<loglevel, string> m_prefixes;
|
||||
|
||||
/**
|
||||
* Loglevel specific suffixes
|
||||
*/
|
||||
map<loglevel, string> m_suffixes {
|
||||
{loglevel::TRACE, ""},
|
||||
{loglevel::INFO, ""},
|
||||
{loglevel::WARNING, ""},
|
||||
{loglevel::ERROR, ""},
|
||||
};
|
||||
// clang-format on
|
||||
std::map<loglevel, string> m_suffixes;
|
||||
};
|
||||
|
||||
/**
|
||||
* Configure injection module
|
||||
*/
|
||||
namespace {
|
||||
/**
|
||||
* Configure injection module
|
||||
*/
|
||||
template <typename T = const logger&>
|
||||
di::injector<T> configure_logger(loglevel level = loglevel::NONE) {
|
||||
auto instance = factory_util::generic_singleton<logger>(level);
|
||||
return di::make_injector(di::bind<>().to(instance));
|
||||
inline const logger& make_logger(loglevel level = loglevel::NONE) {
|
||||
auto instance = factory_util::singleton<const logger>(level);
|
||||
return static_cast<const logger&>(*instance);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
POLYBAR_NS
|
||||
|
||||
class signal_emitter;
|
||||
class logger;
|
||||
struct bar_settings;
|
||||
enum class attribute : uint8_t;
|
||||
|
@ -17,7 +18,7 @@ DEFINE_CHILD_ERROR(unclosed_actionblocks, parser_error);
|
|||
|
||||
class parser {
|
||||
public:
|
||||
explicit parser(const logger& logger, const bar_settings& bar);
|
||||
explicit parser(signal_emitter& emitter, const logger& logger, const bar_settings& bar);
|
||||
void operator()(string data);
|
||||
void codeblock(string data);
|
||||
size_t text(string data);
|
||||
|
@ -30,6 +31,7 @@ class parser {
|
|||
string parse_action_cmd(const string& data);
|
||||
|
||||
private:
|
||||
signal_emitter& m_sig;
|
||||
const logger& m_log;
|
||||
const bar_settings& m_bar;
|
||||
vector<int> m_actions;
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "common.hpp"
|
||||
#include "components/logger.hpp"
|
||||
#include "components/types.hpp"
|
||||
#include "events/signal_emitter.hpp"
|
||||
#include "events/signal_fwd.hpp"
|
||||
#include "events/signal_receiver.hpp"
|
||||
#include "x11/connection.hpp"
|
||||
#include "x11/fonts.hpp"
|
||||
#include "x11/types.hpp"
|
||||
|
||||
POLYBAR_NS
|
||||
|
@ -10,12 +16,17 @@ class connection;
|
|||
class font_manager;
|
||||
class logger;
|
||||
|
||||
class renderer {
|
||||
using namespace signals::parser;
|
||||
|
||||
class renderer
|
||||
: public signal_receiver<SIGN_PRIORITY_RENDERER, change_background, change_foreground, change_underline,
|
||||
change_overline, change_font, change_alignment, offset_pixel, attribute_set, attribute_unset,
|
||||
attribute_toggle, action_begin, action_end, write_text_ascii, write_text_unicode, write_text_string> {
|
||||
public:
|
||||
enum class gc : uint8_t { BG, FG, OL, UL, BT, BB, BL, BR };
|
||||
|
||||
explicit renderer(connection& conn, const logger& logger, unique_ptr<font_manager> font_manager,
|
||||
const bar_settings& bar, const vector<string>& fonts);
|
||||
explicit renderer(connection& conn, signal_emitter& emitter, const logger& logger,
|
||||
unique_ptr<font_manager> font_manager, const bar_settings& bar, const vector<string>& fonts);
|
||||
~renderer();
|
||||
|
||||
xcb_window_t window() const;
|
||||
|
@ -52,6 +63,22 @@ class renderer {
|
|||
int16_t shift_content(int16_t x, const int16_t shift_x);
|
||||
int16_t shift_content(const int16_t shift_x);
|
||||
|
||||
bool on(const change_background& evt);
|
||||
bool on(const change_foreground& evt);
|
||||
bool on(const change_underline& evt);
|
||||
bool on(const change_overline& evt);
|
||||
bool on(const change_font& evt);
|
||||
bool on(const change_alignment& evt);
|
||||
bool on(const offset_pixel& evt);
|
||||
bool on(const attribute_set& evt);
|
||||
bool on(const attribute_unset& evt);
|
||||
bool on(const attribute_toggle& evt);
|
||||
bool on(const action_begin& evt);
|
||||
bool on(const action_end& evt);
|
||||
bool on(const write_text_ascii& evt);
|
||||
bool on(const write_text_unicode& evt);
|
||||
bool on(const write_text_string& evt);
|
||||
|
||||
#ifdef DEBUG_HINTS
|
||||
vector<xcb_window_t> m_debughints;
|
||||
void debug_hints();
|
||||
|
@ -65,13 +92,13 @@ class renderer {
|
|||
|
||||
private:
|
||||
connection& m_connection;
|
||||
signal_emitter& m_sig;
|
||||
const logger& m_log;
|
||||
unique_ptr<font_manager> m_fontmanager;
|
||||
|
||||
const bar_settings& m_bar;
|
||||
|
||||
xcb_rectangle_t m_rect{0, 0, 0U, 0U};
|
||||
|
||||
xcb_rectangle_t m_cleared{0, 0, 0U, 0U};
|
||||
reserve_area m_cleararea{};
|
||||
|
||||
|
@ -95,6 +122,21 @@ class renderer {
|
|||
xcb_font_t m_gcfont{XCB_NONE};
|
||||
};
|
||||
|
||||
di::injector<unique_ptr<renderer>> configure_renderer(const bar_settings& bar, const vector<string>& fonts);
|
||||
namespace {
|
||||
/**
|
||||
* Configure injection module
|
||||
*/
|
||||
inline unique_ptr<renderer> make_renderer(const bar_settings& bar, const vector<string>& fonts) {
|
||||
// clang-format off
|
||||
return factory_util::unique<renderer>(
|
||||
make_connection(),
|
||||
make_signal_emitter(),
|
||||
make_logger(),
|
||||
make_font_manager(),
|
||||
bar,
|
||||
fonts);
|
||||
// clang-format on
|
||||
}
|
||||
}
|
||||
|
||||
POLYBAR_NS_END
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include "common.hpp"
|
||||
#include "components/config.hpp"
|
||||
#include "components/logger.hpp"
|
||||
#include "components/types.hpp"
|
||||
#include "events/signal_emitter.hpp"
|
||||
#include "x11/events.hpp"
|
||||
#include "x11/window.hpp"
|
||||
|
||||
|
@ -11,10 +14,11 @@ POLYBAR_NS
|
|||
class config;
|
||||
class logger;
|
||||
class connection;
|
||||
class signal_emitter;
|
||||
|
||||
class screen : public xpp::event::sink<evt::randr_screen_change_notify> {
|
||||
public:
|
||||
explicit screen(connection& conn, const logger& logger, const config& conf);
|
||||
explicit screen(connection& conn, signal_emitter& emitter, const logger& logger, const config& conf);
|
||||
~screen();
|
||||
|
||||
struct size size() const {
|
||||
|
@ -30,6 +34,7 @@ class screen : public xpp::event::sink<evt::randr_screen_change_notify> {
|
|||
|
||||
private:
|
||||
connection& m_connection;
|
||||
signal_emitter& m_sig;
|
||||
const logger& m_log;
|
||||
const config& m_conf;
|
||||
|
||||
|
@ -37,10 +42,20 @@ class screen : public xpp::event::sink<evt::randr_screen_change_notify> {
|
|||
xcb_window_t m_proxy{XCB_NONE};
|
||||
|
||||
vector<monitor_t> m_monitors;
|
||||
struct size m_size{0U, 0U};
|
||||
struct size m_size {
|
||||
0U, 0U
|
||||
};
|
||||
bool m_sigraised{false};
|
||||
};
|
||||
|
||||
di::injector<unique_ptr<screen>> configure_screen();
|
||||
namespace {
|
||||
/**
|
||||
* Configure injection module
|
||||
*/
|
||||
inline unique_ptr<screen> make_screen() {
|
||||
return factory_util::unique<screen>(
|
||||
make_connection(), make_signal_emitter(), make_logger(), make_confreader());
|
||||
}
|
||||
}
|
||||
|
||||
POLYBAR_NS_END
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
#include "components/eventloop.hpp"
|
||||
#include "utils/functional.hpp"
|
||||
|
||||
POLYBAR_NS
|
||||
|
||||
// fwd decl {{{
|
||||
|
||||
enum class mousebtn : uint8_t;
|
||||
enum class syntaxtag : uint8_t;
|
||||
enum class alignment : uint8_t;
|
||||
enum class attribute : uint8_t;
|
||||
|
||||
// }}}
|
||||
|
||||
/**
|
||||
* @TODO: Allow multiple signal handlers
|
||||
* @TODO: Encapsulate signals
|
||||
*/
|
||||
namespace g_signals {
|
||||
/**
|
||||
* Helper used to create no-op "callbacks"
|
||||
*/
|
||||
template <typename... T>
|
||||
static callback<T...> noop = [](T...) {};
|
||||
|
||||
/**
|
||||
* Signals used to communicate with the event loop
|
||||
*/
|
||||
namespace event {
|
||||
extern callback<const eventloop::entry_t&> enqueue;
|
||||
extern callback<const eventloop::entry_t&> enqueue_delayed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals used to communicate with the bar window
|
||||
*/
|
||||
namespace bar {
|
||||
extern callback<string> action_click;
|
||||
extern callback<const bool> visibility_change;
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals used to communicate with the input parser
|
||||
*/
|
||||
namespace parser {
|
||||
extern callback<const uint32_t> background_change;
|
||||
extern callback<const uint32_t> foreground_change;
|
||||
extern callback<const uint32_t> underline_change;
|
||||
extern callback<const uint32_t> overline_change;
|
||||
extern callback<const alignment> alignment_change;
|
||||
extern callback<const attribute> attribute_set;
|
||||
extern callback<const attribute> attribute_unset;
|
||||
extern callback<const attribute> attribute_toggle;
|
||||
extern callback<const int8_t> font_change;
|
||||
extern callback<const int16_t> pixel_offset;
|
||||
extern callback<const mousebtn, const string> action_block_open;
|
||||
extern callback<const mousebtn> action_block_close;
|
||||
extern callback<const uint16_t> ascii_text_write;
|
||||
extern callback<const uint16_t> unicode_text_write;
|
||||
extern callback<const char*, const size_t> string_write;
|
||||
}
|
||||
}
|
||||
|
||||
POLYBAR_NS_END
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "common.hpp"
|
||||
#include "x11/color.hpp"
|
||||
#include "x11/randr.hpp"
|
||||
|
@ -80,8 +82,8 @@ struct action {
|
|||
|
||||
struct action_block : public action {
|
||||
alignment align{alignment::NONE};
|
||||
double start_x{0.0};
|
||||
double end_x{0.0};
|
||||
volatile double start_x{0.0};
|
||||
volatile double end_x{0.0};
|
||||
bool active{true};
|
||||
|
||||
uint16_t width() const {
|
||||
|
@ -90,6 +92,11 @@ struct action_block : public action {
|
|||
};
|
||||
|
||||
struct bar_settings {
|
||||
explicit bar_settings() = default;
|
||||
bar_settings(const bar_settings& other) = default;
|
||||
|
||||
xcb_window_t window;
|
||||
|
||||
monitor_t monitor;
|
||||
edge origin{edge::TOP};
|
||||
struct size size {
|
||||
|
@ -109,7 +116,7 @@ struct bar_settings {
|
|||
line_settings underline;
|
||||
line_settings overline;
|
||||
|
||||
map<edge, border_settings> borders;
|
||||
std::unordered_map<edge, border_settings> borders;
|
||||
|
||||
uint8_t spacing{1U};
|
||||
string separator;
|
||||
|
@ -128,13 +135,20 @@ struct bar_settings {
|
|||
rect.x = pos.x;
|
||||
rect.y = pos.y;
|
||||
}
|
||||
|
||||
rect.y += borders.at(edge::TOP).size;
|
||||
rect.height -= borders.at(edge::TOP).size;
|
||||
rect.height -= borders.at(edge::BOTTOM).size;
|
||||
rect.x += borders.at(edge::LEFT).size;
|
||||
rect.width -= borders.at(edge::LEFT).size;
|
||||
rect.width -= borders.at(edge::RIGHT).size;
|
||||
if (borders.find(edge::TOP) != borders.end()) {
|
||||
rect.y += borders.at(edge::TOP).size;
|
||||
rect.height -= borders.at(edge::TOP).size;
|
||||
}
|
||||
if (borders.find(edge::BOTTOM) != borders.end()) {
|
||||
rect.height -= borders.at(edge::BOTTOM).size;
|
||||
}
|
||||
if (borders.find(edge::LEFT) != borders.end()) {
|
||||
rect.x += borders.at(edge::LEFT).size;
|
||||
rect.width -= borders.at(edge::LEFT).size;
|
||||
}
|
||||
if (borders.find(edge::RIGHT) != borders.end()) {
|
||||
rect.width -= borders.at(edge::RIGHT).size;
|
||||
}
|
||||
return rect;
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue