#pragma once #include #include #include #include #include #include "common.hpp" #include "components/types.hpp" #include "errors.hpp" #include "utils/concurrency.hpp" #include "utils/functional.hpp" #include "utils/inotify.hpp" #include "utils/string.hpp" POLYBAR_NS namespace chrono = std::chrono; using namespace std::chrono_literals; using std::map; #define DEFAULT_FORMAT "format" #define CONST_MOD(name) static_cast(*this) #define CAST_MOD(name) static_cast(this) // fwd decl {{{ namespace drawtypes { class ramp; using ramp_t = shared_ptr; class progressbar; using progressbar_t = shared_ptr; class animation; using animation_t = shared_ptr; class iconset; using iconset_t = shared_ptr; } // namespace drawtypes class builder; class config; class logger; class signal_emitter; // }}} namespace modules { using namespace drawtypes; DEFINE_ERROR(module_error); DEFINE_CHILD_ERROR(undefined_format, module_error); DEFINE_CHILD_ERROR(undefined_format_tag, module_error); // class definition : module_format {{{ struct module_format { string value{}; vector tags{}; label_t prefix{}; label_t suffix{}; rgba fg{}; rgba bg{}; rgba ul{}; rgba ol{}; size_t ulsize{0}; size_t olsize{0}; size_t spacing{0}; size_t padding{0}; size_t margin{0}; int offset{0}; int font{0}; string decorate(builder* builder, string output); }; // }}} // class definition : module_formatter {{{ class module_formatter { public: explicit module_formatter(const config& conf, string modname) : m_conf(conf), m_modname(modname) {} void add(string name, string fallback, vector&& tags, vector&& whitelist = {}); void add_optional(string name, vector&& tags, vector&& whitelist = {}); bool has(const string& tag, const string& format_name); bool has(const string& tag); bool has_format(const string& format_name); shared_ptr get(const string& format_name); protected: void add_value(string&& name, string&& value, vector&& tags, vector&& whitelist); const config& m_conf; string m_modname; map> m_formats; }; // }}} // class definition : module_interface {{{ struct module_interface { public: virtual ~module_interface() {} /** * The type users have to specify in the module section `type` key */ virtual string type() const = 0; /** * Module name w/o 'module/' prefix */ virtual string name_raw() const = 0; virtual string name() const = 0; virtual bool running() const = 0; /** * Handle action, possibly with data attached * * Any implementation is free to ignore the data, if the action does not * require additional data. * * \returns true if the action is supported and false otherwise */ virtual bool input(const string& action, const string& data) = 0; virtual void start() = 0; virtual void stop() = 0; virtual void halt(string error_message) = 0; virtual string contents() = 0; }; // }}} // class definition : module {{{ template class module : public module_interface { public: module(const bar_settings bar, string name); ~module() noexcept; string type() const; string name_raw() const; string name() const; bool running() const; void stop(); void halt(string error_message); void teardown(); string contents(); bool input(const string& action, const string& data); protected: void broadcast(); void idle(); void sleep(chrono::duration duration); template void sleep_until(chrono::time_point point); void wakeup(); string get_format() const; string get_output(); protected: signal_emitter& m_sig; const bar_settings m_bar; const logger& m_log; const config& m_conf; mutex m_buildlock; mutex m_updatelock; mutex m_sleeplock; std::condition_variable m_sleephandler; const string m_name; const string m_name_raw; unique_ptr m_builder; unique_ptr m_formatter; vector m_threads; thread m_mainthread; bool m_handle_events{true}; private: atomic m_enabled{true}; atomic m_changed{true}; string m_cache; }; // }}} } // namespace modules POLYBAR_NS_END