refactor: Move all event handling to the controller

This commit is contained in:
Michael Carlberg 2016-12-20 05:05:43 +01:00
parent 8ed4de1dda
commit a89c4ef2dd
47 changed files with 1146 additions and 1436 deletions

View file

@ -1,41 +1,41 @@
#pragma once
#include <mutex>
#include "common.hpp"
#include "components/renderer.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"
POLYBAR_NS
// fwd
class screen;
class tray_manager;
class connection;
class logger;
class parser;
class renderer;
class screen;
class signal_emitter;
class tray_manager;
class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::property_notify, evt::enter_notify, evt::leave_notify, evt::destroy_notify, evt::client_message> {
class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::property_notify, evt::enter_notify,
evt::leave_notify, evt::destroy_notify, evt::client_message> {
public:
using make_type = unique_ptr<bar>;
static make_type make();
explicit bar(connection& conn, signal_emitter& emitter, const config& config, const logger& logger,
unique_ptr<screen> screen, unique_ptr<tray_manager> tray_manager);
unique_ptr<screen>&& screen, unique_ptr<tray_manager>&& tray_manager, unique_ptr<parser>&& parser);
virtual ~bar();
~bar();
void parse(string&& data) const;
void parse(const string& data, bool force = false);
const bar_settings settings() const;
void parse(const string& data, bool force = false);
protected:
void restack_window();
void reconfigure_pos();
@ -57,10 +57,11 @@ class bar : public xpp::event::sink<evt::button_press, evt::expose, evt::propert
const config& m_conf;
const logger& m_log;
unique_ptr<screen> m_screen;
unique_ptr<tray_manager> m_tray;
unique_ptr<renderer> m_renderer;
unique_ptr<tray_manager> m_tray{};
unique_ptr<renderer> m_renderer{};
unique_ptr<parser> m_parser{};
bar_settings m_opts;
bar_settings m_opts{};
string m_lastinput{};

View file

@ -13,7 +13,6 @@ POLYBAR_NS
#define GET_CONFIG_VALUE(section, var, name) var = m_conf.get<decltype(var)>(section, name, var)
#define REQ_CONFIG_VALUE(section, var, name) var = m_conf.get<decltype(var)>(section, name)
#define DEPR_CONFIG_VALUE(section, var, old, name) var = m_conf.deprecated<decltype(var)>(section, old, name, var)
DEFINE_ERROR(value_error);
DEFINE_ERROR(key_error);

View file

@ -1,70 +1,69 @@
#pragma once
#include <csignal>
#include <moodycamel/blockingconcurrentqueue.h>
#include "common.hpp"
#include "components/bar.hpp"
#include "components/ipc.hpp"
#include "components/types.hpp"
#include "config.hpp"
#include "events/signal_emitter.hpp"
#include "events/signal_fwd.hpp"
#include "events/signal_receiver.hpp"
#include "events/types.hpp"
#include "x11/types.hpp"
POLYBAR_NS
// fwd decl {{{
enum class alignment : uint8_t;
class bar;
class command;
class config;
class connection;
class eventloop;
class inotify_watch;
class ipc;
class logger;
struct bar_settings;
namespace inotify_util {
class inotify_watch;
using watch_t = unique_ptr<inotify_watch>;
class signal_emitter;
namespace modules {
struct module_interface;
}
namespace command_util {
class command;
}
using command = command_util::command;
using command_t = unique_ptr<command>;
using module_t = unique_ptr<modules::module_interface>;
using modulemap_t = std::map<alignment, vector<module_t>>;
// }}}
using watch_t = inotify_util::watch_t;
namespace chrono = std::chrono;
using namespace std::chrono_literals;
namespace sig_ev = signals::eventloop;
namespace sig_ev = signals::eventqueue;
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> {
sig_ev::process_quit, sig_ev::process_check, sig_ipc::process_action, sig_ipc::process_command,
sig_ipc::process_hook, sig_ui::button_press> {
public:
using make_type = unique_ptr<controller>;
static make_type make(string&& path_confwatch, bool enable_ipc = false, bool writeback = false);
static make_type make(unique_ptr<ipc>&& ipc, unique_ptr<inotify_watch>&& config_watch);
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);
explicit controller(connection&, signal_emitter&, const logger&, const config&, unique_ptr<bar>&&, unique_ptr<ipc>&&,
unique_ptr<inotify_watch>&&);
~controller();
void setup();
bool run();
bool run(bool writeback = false);
const bar_settings opts() const;
bool enqueue(event&& evt);
bool enqueue(string&& input_data);
protected:
void wait_for_signal();
void wait_for_xevent();
void wait_for_eventloop();
void wait_for_configwatch();
void read_events();
void process_eventqueue();
void process_inputdata();
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_ev::process_check& 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);
@ -75,21 +74,51 @@ class controller : public signal_receiver<SIGN_PRIORITY_CONTROLLER, sig_ev::proc
signal_emitter& m_sig;
const logger& m_log;
const config& m_conf;
unique_ptr<eventloop> m_eventloop;
unique_ptr<bar> m_bar;
unique_ptr<ipc> m_ipc;
unique_ptr<inotify_watch> m_confwatch;
unique_ptr<command> m_command;
stateflag m_running{false};
stateflag m_reload{false};
stateflag m_waiting{false};
sigset_t m_waitmask{};
vector<thread> m_threads;
watch_t m_confwatch;
command_t m_command;
/**
* @brief Controls weather the output gets printed to stdout
*/
bool m_writeback{false};
/**
* @brief Internal event queue
*/
using queue_t = moodycamel::BlockingConcurrentQueue<event>;
queue_t m_queue;
/**
* @brief Loaded modules
*/
modulemap_t m_modules;
/**
* @brief Maximum number of subsequent events to swallow
*/
size_t m_swallow_limit{5U};
/**
* @brief Time to wait for subsequent events
*/
chrono::milliseconds m_swallow_update{10ms};
/**
* @brief Time to throttle input events
*/
chrono::milliseconds m_swallow_input{30ms};
/**
* @brief Time of last handled input event
*/
chrono::time_point<chrono::system_clock, chrono::milliseconds> m_lastinput;
/**
* @brief Input data
*/
string m_inputdata;
};
POLYBAR_NS_END

View file

@ -1,141 +0,0 @@
#pragma once
#include <moodycamel/blockingconcurrentqueue.h>
#include <chrono>
#include <condition_variable>
#include <mutex>
#include <thread>
#include "common.hpp"
#include "events/signal_emitter.hpp"
#include "events/signal_fwd.hpp"
#include "events/signal_receiver.hpp"
#include "utils/concurrency.hpp"
POLYBAR_NS
// fwd
namespace modules {
struct module_interface;
}
enum class alignment : uint8_t;
class config;
class logger;
using namespace signals::eventloop;
using module_t = unique_ptr<modules::module_interface>;
using modulemap_t = std::map<alignment, vector<module_t>>;
namespace chrono = std::chrono;
using namespace std::chrono_literals;
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:
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};
};
template <typename EventType>
using queue_t = moodycamel::BlockingConcurrentQueue<EventType>;
public:
using make_type = unique_ptr<eventloop>;
static make_type make();
explicit eventloop(signal_emitter& emitter, const logger& logger, const config& config);
~eventloop();
void start();
void stop();
bool enqueue(event&& evt);
bool enqueue(string&& input_data);
void add_module(const alignment pos, module_t&& module);
const modulemap_t& modules() const;
size_t module_count() const;
static event make_quit_evt(bool reload = false);
static event make_update_evt(bool force = false);
static event make_input_evt();
static event make_check_evt();
protected:
void dispatch_modules();
void handle_inputdata();
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<event> m_queue;
/**
* @brief Loaded modules
*/
modulemap_t m_modules;
/**
* @brief Flag to indicate current run state
*/
stateflag m_running{};
/**
* @brief Time to wait for subsequent events
*/
chrono::milliseconds m_swallow_update{10ms};
/**
* @brief Maximum amount of subsequent events to swallow within timeframe
*/
size_t m_swallow_limit{5U};
/**
* @brief Time to throttle input events
*/
chrono::milliseconds m_swallow_input{30ms};
/**
* @brief Time of last handled input event
*/
chrono::time_point<chrono::system_clock, chrono::milliseconds> m_lastinput;
/**
* @brief Mutex used to guard input data
*/
std::mutex m_inputlock{};
/**
* @brief Input data
*/
string m_inputdata;
};
POLYBAR_NS_END

View file

@ -5,6 +5,7 @@
#include "events/signal_emitter.hpp"
#include "utils/concurrency.hpp"
#include "utils/functional.hpp"
#include "utils/file.hpp"
POLYBAR_NS
@ -36,20 +37,18 @@ class ipc {
using make_type = unique_ptr<ipc>;
static make_type make();
explicit ipc(signal_emitter& emitter, const logger& logger) : m_sig(emitter), m_log(logger) {}
explicit ipc(signal_emitter& emitter, const logger& logger);
~ipc();
void receive_messages();
protected:
void parse(const string& payload) const;
void receive_message();
int get_file_descriptor() const;
private:
signal_emitter& m_sig;
const logger& m_log;
string m_fifo{};
int m_fd{0};
stateflag m_running{false};
string m_path{};
shared_ptr<file_descriptor> m_fd{};
};
POLYBAR_NS_END

View file

@ -6,9 +6,9 @@
POLYBAR_NS
class signal_emitter;
struct bar_settings;
enum class attribute : uint8_t;
enum class mousebtn : uint8_t;
struct bar_settings;
DEFINE_ERROR(parser_error);
DEFINE_CHILD_ERROR(unrecognized_token, parser_error);
@ -21,12 +21,15 @@ class parser {
uint16_t data[128]{0U};
size_t length{0};
};
using make_type = unique_ptr<parser>;
static make_type make();
explicit parser(signal_emitter& emitter, const bar_settings& bar);
void operator()(string data);
public:
explicit parser(signal_emitter& emitter);
void parse(const bar_settings& bar, string data);
protected:
void codeblock(string&& data);
void codeblock(string&& data, const bar_settings& bar);
size_t text(string&& data);
uint32_t parse_color(const string& s, uint32_t fallback = 0);
@ -37,8 +40,8 @@ class parser {
private:
signal_emitter& m_sig;
const bar_settings& m_bar;
vector<int> m_actions;
unique_ptr<parser> m_parser;
};
POLYBAR_NS_END