diff --git a/CMakeLists.txt b/CMakeLists.txt index a67fb858..ef150348 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,11 +88,12 @@ find_package(Boost REQUIRED) find_package(Threads REQUIRED) find_package(Freetype REQUIRED Freetype2) find_package(PkgConfig) -find_package(X11 REQUIRED COMPONENTS Xft) +find_package(X11 REQUIRED COMPONENTS Xft Xutil) find_package(X11_XCB REQUIRED) pkg_check_modules(FONTCONFIG REQUIRED fontconfig) +link_libraries(${X11_X11_LIB}) link_libraries(${X11_Xft_LIB}) link_libraries(${X11_XCB_LIB}) link_libraries(${BOOST_LIBRARIES}) diff --git a/include/components/config.hpp b/include/components/config.hpp index e4181920..c9b30439 100644 --- a/include/components/config.hpp +++ b/include/components/config.hpp @@ -6,6 +6,7 @@ #include "common.hpp" #include "components/logger.hpp" +#include "components/x11/xresources.hpp" #include "utils/file.hpp" #include "utils/string.hpp" @@ -24,7 +25,8 @@ class config { /** * Construct config */ - explicit config(const logger& logger) : m_logger(logger) {} + explicit config(const logger& logger, const xresource_manager& xrm) + : m_logger(logger), m_xrm(xrm) {} /** * Load configuration and validate bar section @@ -181,13 +183,17 @@ class config { */ template static di::injector configure() { - return di::make_injector(logger::configure()); + return di::make_injector(logger::configure(), xresource_manager::configure()); } protected: /** * Find value of a config parameter defined as a reference * variable using ${section.param} or ${env:VAR} + * ${self.key} may be used to reference the current bar section + * + * @deprecated: ${BAR.key} has been replaced with ${self.key} + * but the former is kept to avoid breaking current configs */ template T dereference_var(string ref_section, string ref_key, string var, const T ref_val) const { @@ -205,12 +211,25 @@ class config { return ref_val; } + if (path.find("xrdb:") == 0) { + if (std::is_same()) + return boost::lexical_cast(m_xrm.get_string(path.substr(5))); + else if (std::is_same()) + return boost::lexical_cast(m_xrm.get_float(path.substr(5))); + else if (std::is_same()) + return boost::lexical_cast(m_xrm.get_int(path.substr(5))); + } + auto ref_path = build_path(ref_section, ref_key); if ((n = path.find(".")) == string::npos) throw value_error("Invalid reference defined at [" + ref_path + "]"); - auto section = string_util::replace(path.substr(0, n), "BAR", bar_section()); + auto section = path.substr(0, n); + + section = string_util::replace(section, "BAR", bar_section()); + section = string_util::replace(section, "self", bar_section()); + auto key = path.substr(n + 1, path.length() - n - 1); auto val = m_ptree.get_optional(build_path(section, key)); @@ -224,6 +243,7 @@ class config { private: const logger& m_logger; + const xresource_manager& m_xrm; ptree m_ptree; string m_file; string m_current_bar; diff --git a/include/components/x11/xlib.hpp b/include/components/x11/xlib.hpp index bf73f963..1b49e075 100644 --- a/include/components/x11/xlib.hpp +++ b/include/components/x11/xlib.hpp @@ -3,7 +3,6 @@ #include #include "common.hpp" -#include "components/x11/xutils.hpp" LEMONBUDDY_NS diff --git a/include/components/x11/xresources.hpp b/include/components/x11/xresources.hpp new file mode 100644 index 00000000..47e44b04 --- /dev/null +++ b/include/components/x11/xresources.hpp @@ -0,0 +1,66 @@ +#pragma once + +#include +#include + +#include "common.hpp" +#include "components/x11/xlib.hpp" + +LEMONBUDDY_NS + +class xresource_manager { + public: + explicit xresource_manager() { + XrmInitialize(); + + if (xlib::get_display() == nullptr) + return; + if ((m_manager = XResourceManagerString(xlib::get_display())) == nullptr) + return; + if ((m_db = XrmGetStringDatabase(m_manager)) == nullptr) + return; + } + + /** + * Configure injection module + */ + template + static di::injector configure() { + auto instance = factory::generic_singleton(); + return di::make_injector(di::bind<>().to(instance)); + } + + string get_string(string name) const { + return load_value(name, "String", 64); + } + + float get_float(string name) const { + return std::strtof(load_value(name, "String", 64).c_str(), 0); + } + + int get_int(string name) const { + return std::atoi(load_value(name, "String", 64).c_str()); + } + + protected: + string load_value(string key, string res_type, size_t n) const { + if (m_manager == nullptr) + return ""; + + char* type = nullptr; + XrmValue ret; + XrmGetResource(m_db, key.c_str(), res_type.c_str(), &type, &ret); + + if (ret.addr != nullptr && !std::strncmp(res_type.c_str(), type, n)) { + return {ret.addr}; + } + + return ""; + } + + private: + char* m_manager = nullptr; + XrmDatabase m_db; +}; + +LEMONBUDDY_NS_END