refactor(xresources): Use xcb-util-xrm
Drop the Xlib version and handle X resource lookups using xcb-util-xrm Refs #356
This commit is contained in:
parent
100c64a20c
commit
e1483c3f65
@ -72,6 +72,12 @@ option(WITH_XDAMAGE "XDAMAGE support" OFF)
|
||||
option(WITH_XSYNC "XSYNC support" OFF)
|
||||
option(WITH_XCOMPOSITE "XCOMPOSITE support" OFF)
|
||||
option(WITH_XKB "XKB support" ON)
|
||||
option(WITH_XRM "xcb-xrm support" ON)
|
||||
|
||||
if(NOT DEFINED WITH_XRM)
|
||||
pkg_check_modules(XRM QUIET xcb-xrm)
|
||||
set(WITH_XRM ${XRM_FOUND} CACHE BOOL "Enable xcb-xrm support")
|
||||
endif()
|
||||
|
||||
if(NOT DEFINED ENABLE_XRANDR_MONITORS)
|
||||
pkg_check_modules(XRANDR QUIET xrandr>=1.5.0)
|
||||
|
@ -75,3 +75,5 @@ colored_option(STATUS " XSYNC support ${WITH_XSYNC}" WITH_XSYNC "32;1" "3
|
||||
colored_option(STATUS " XCOMPOSITE support ${WITH_XCOMPOSITE}" WITH_XCOMPOSITE "32;1" "37;2")
|
||||
colored_option(STATUS " XKB support ${WITH_XKB}" WITH_XKB "32;1" "37;2")
|
||||
message(STATUS "--------------------------")
|
||||
colored_option(STATUS " xcb-util-xrm ${WITH_XCB_UTIL_XRM}" WITH_XCB_UTIL_XRM "32;1" "37;2")
|
||||
message(STATUS "--------------------------")
|
||||
|
@ -12,7 +12,7 @@ pkgbase = polybar-git
|
||||
makedepends = pkg-config
|
||||
depends = libxft
|
||||
depends = xcb-util-wm
|
||||
depends = xcb-util-image
|
||||
depends = xcb-util-xrm
|
||||
optdepends = alsa-lib: volume module support
|
||||
optdepends = libmpdclient: mpd module support
|
||||
optdepends = wireless_tools: network module support
|
||||
|
@ -8,7 +8,7 @@ pkgdesc="A fast and easy-to-use status bar"
|
||||
arch=("i686" "x86_64")
|
||||
url="https://github.com/jaagr/polybar"
|
||||
license=("MIT")
|
||||
depends=("libxft" "xcb-util-wm" "xcb-util-image")
|
||||
depends=("libxft" "xcb-util-wm" "xcb-util-xrm")
|
||||
optdepends=("alsa-lib: volume module support"
|
||||
"libmpdclient: mpd module support"
|
||||
"wireless_tools: network module support"
|
||||
|
@ -12,7 +12,7 @@ pkgbase = polybar
|
||||
makedepends = pkg-config
|
||||
depends = libxft
|
||||
depends = xcb-util-wm
|
||||
depends = xcb-util-image
|
||||
depends = xcb-util-xrm
|
||||
optdepends = alsa-lib: volume module support
|
||||
optdepends = libmpdclient: mpd module support
|
||||
optdepends = wireless_tools: network module support
|
||||
|
@ -7,7 +7,7 @@ pkgdesc="A fast and easy-to-use status bar"
|
||||
arch=("i686" "x86_64")
|
||||
url="https://github.com/jaagr/polybar"
|
||||
license=("MIT")
|
||||
depends=("libxft" "xcb-util-wm" "xcb-util-image")
|
||||
depends=("libxft" "xcb-util-wm" "xcb-util-xrm")
|
||||
optdepends=("alsa-lib: volume module support"
|
||||
"libmpdclient: mpd module support"
|
||||
"wireless_tools: network module support"
|
||||
|
@ -5,10 +5,13 @@
|
||||
#include "common.hpp"
|
||||
#include "components/logger.hpp"
|
||||
#include "errors.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "utils/env.hpp"
|
||||
#include "utils/file.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#ifdef WITH_XRM
|
||||
#include "x11/xresources.hpp"
|
||||
#endif
|
||||
|
||||
POLYBAR_NS
|
||||
|
||||
@ -23,7 +26,7 @@ class config {
|
||||
using make_type = const config&;
|
||||
static make_type make(string path = "", string bar = "");
|
||||
|
||||
explicit config(const logger& logger, const xresource_manager& xrm, string&& path = "", string&& bar = "");
|
||||
explicit config(const logger& logger, string&& path = "", string&& bar = "");
|
||||
|
||||
string filepath() const;
|
||||
string section() const;
|
||||
@ -209,11 +212,11 @@ class config {
|
||||
size_t pos;
|
||||
|
||||
if (path.compare(0, 4, "env:") == 0) {
|
||||
return dereference_env<T>(path.substr(4), fallback);
|
||||
return dereference_env<T>(path.substr(4));
|
||||
} else if (path.compare(0, 5, "xrdb:") == 0) {
|
||||
return dereference_xrdb<T>(path.substr(5), fallback);
|
||||
return dereference_xrdb<T>(path.substr(5));
|
||||
} else if (path.compare(0, 5, "file:") == 0) {
|
||||
return dereference_file<T>(path.substr(5), fallback);
|
||||
return dereference_file<T>(path.substr(5));
|
||||
} else if ((pos = path.find(".")) != string::npos) {
|
||||
return dereference_local<T>(path.substr(0, pos), path.substr(pos + 1), section);
|
||||
} else {
|
||||
@ -252,9 +255,9 @@ class config {
|
||||
* ${env:key:fallback value}
|
||||
*/
|
||||
template <typename T>
|
||||
T dereference_env(string var, const T&) const {
|
||||
T dereference_env(string var) const {
|
||||
size_t pos;
|
||||
string env_default{""};
|
||||
string env_default;
|
||||
|
||||
if ((pos = var.find(":")) != string::npos) {
|
||||
env_default = var.substr(pos + 1);
|
||||
@ -281,15 +284,37 @@ class config {
|
||||
* ${xrdb:key:fallback value}
|
||||
*/
|
||||
template <typename T>
|
||||
T dereference_xrdb(string var, const T& fallback) const {
|
||||
T dereference_xrdb(string var) const {
|
||||
size_t pos;
|
||||
|
||||
#ifndef WITH_XRM
|
||||
m_log.warn("No built-in support for xrdb (requires xcb-util-xrm). Using default value for `%s`", var);
|
||||
if ((pos = var.find(":")) != string::npos) {
|
||||
return convert<T>(m_xrm.get_string(var.substr(0, pos), var.substr(pos + 1)));
|
||||
return var.substr(pos + 1);
|
||||
}
|
||||
return fallback;
|
||||
#else
|
||||
if (!m_xrm) {
|
||||
throw application_error("xrm is not initialized");
|
||||
}
|
||||
|
||||
string str{m_xrm.get_string(var, "")};
|
||||
return str.empty() ? fallback : convert<T>(move(str));
|
||||
string fallback;
|
||||
if ((pos = var.find(":")) != string::npos) {
|
||||
fallback = var.substr(pos + 1);
|
||||
var.erase(pos);
|
||||
}
|
||||
|
||||
try {
|
||||
auto value = m_xrm->require<string>(var.c_str());
|
||||
m_log.info("Found matching X resource \"%s\" (value=%s)", var, value);
|
||||
return convert<T>(move(value));
|
||||
} catch (const xresource_error& err) {
|
||||
if (!fallback.empty()) {
|
||||
m_log.warn("%s, using defined fallback value \"%s\"", err.what(), fallback);
|
||||
return convert<T>(move(fallback));
|
||||
}
|
||||
throw value_error(sstream() << err.what() << " (no fallback set)");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
@ -297,11 +322,12 @@ class config {
|
||||
* ${file:/absolute/file/path}
|
||||
*/
|
||||
template <typename T>
|
||||
T dereference_file(string var, const T& fallback) const {
|
||||
string filename{move(var)};
|
||||
|
||||
if (file_util::exists(filename)) {
|
||||
return convert<T>(string_util::trim(file_util::contents(filename), '\n'));
|
||||
T dereference_file(string var) const {
|
||||
size_t pos;
|
||||
string fallback;
|
||||
if ((pos = var.find(":")) != string::npos) {
|
||||
fallback = var.substr(pos + 1);
|
||||
var.erase(pos);
|
||||
}
|
||||
|
||||
return fallback;
|
||||
@ -310,10 +336,12 @@ class config {
|
||||
private:
|
||||
static constexpr const char* KEY_INHERIT{"inherit"};
|
||||
const logger& m_log;
|
||||
const xresource_manager& m_xrm;
|
||||
string m_file;
|
||||
string m_barname;
|
||||
sectionmap_t m_sections{};
|
||||
#ifdef WITH_XRM
|
||||
unique_ptr<xresource_manager> m_xrm;
|
||||
#endif
|
||||
};
|
||||
|
||||
POLYBAR_NS_END
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <thread>
|
||||
|
||||
#include "common.hpp"
|
||||
#include "settings.hpp"
|
||||
|
||||
#ifndef STDOUT_FILENO
|
||||
#define STDOUT_FILENO 1
|
||||
|
@ -25,6 +25,7 @@
|
||||
#cmakedefine01 WITH_XSYNC
|
||||
#cmakedefine01 WITH_XCOMPOSITE
|
||||
#cmakedefine01 WITH_XKB
|
||||
#cmakedefine01 WITH_XRM
|
||||
|
||||
#if WITH_XRANDR
|
||||
#cmakedefine01 ENABLE_XRANDR_MONITORS
|
||||
@ -97,14 +98,15 @@ const auto print_build_info = [](bool extended = false) {
|
||||
(ENABLE_NETWORK ? '+' : '-'));
|
||||
if (extended) {
|
||||
printf("\n");
|
||||
printf("X extensions: %cxrandr (%cmonitors) %cxrender %cxdamage %cxsync %cxcomposite %cxkb\n",
|
||||
printf("X extensions: %cxrandr (%cmonitors) %cxrender %cxdamage %cxsync %cxcomposite %cxkb %cxcb-util-xrm\n",
|
||||
(WITH_XRANDR ? '+' : '-'),
|
||||
(ENABLE_XRANDR_MONITORS ? '+' : '-'),
|
||||
(WITH_XRENDER ? '+' : '-'),
|
||||
(WITH_XDAMAGE ? '+' : '-'),
|
||||
(WITH_XSYNC ? '+' : '-'),
|
||||
(WITH_XCOMPOSITE ? '+' : '-'),
|
||||
(WITH_XKB ? '+' : '-'));
|
||||
(WITH_XKB ? '+' : '-'),
|
||||
(WITH_XRM ? '+' : '-'));
|
||||
printf("\n");
|
||||
printf("Build type: @CMAKE_BUILD_TYPE@\n");
|
||||
printf("Compiler: @CMAKE_CXX_COMPILER@\n");
|
||||
|
@ -1,33 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xresource.h>
|
||||
#include "settings.hpp"
|
||||
|
||||
#if not WITH_XRM
|
||||
#error "Not built with support for xcb-xrm..."
|
||||
#endif
|
||||
|
||||
#include <xcb/xcb_xrm.h>
|
||||
|
||||
#include "common.hpp"
|
||||
#include "errors.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#include "x11/connection.hpp"
|
||||
|
||||
POLYBAR_NS
|
||||
|
||||
DEFINE_ERROR(xresource_error);
|
||||
|
||||
class xresource_manager {
|
||||
public:
|
||||
using make_type = const xresource_manager&;
|
||||
static make_type make();
|
||||
explicit xresource_manager(xcb_connection_t* conn) : m_xrm(xcb_xrm_database_from_default(conn)) {
|
||||
if (m_xrm == nullptr) {
|
||||
throw application_error("xcb_xrm_database_from_default()");
|
||||
}
|
||||
}
|
||||
|
||||
explicit xresource_manager(Display*);
|
||||
~xresource_manager();
|
||||
~xresource_manager() {
|
||||
xcb_xrm_database_free(m_xrm);
|
||||
}
|
||||
|
||||
xresource_manager(const xresource_manager& o) = delete;
|
||||
xresource_manager& operator=(const xresource_manager& o) = delete;
|
||||
operator bool() const {
|
||||
return m_xrm != nullptr;
|
||||
}
|
||||
|
||||
string get_string(string name, string fallback = "") const;
|
||||
float get_float(string name, float fallback = 0.0f) const;
|
||||
int get_int(string name, int fallback = 0) const;
|
||||
template <typename T>
|
||||
T require(const char* name) const {
|
||||
char* result{nullptr};
|
||||
if (xcb_xrm_resource_get_string(m_xrm, string_util::replace(name, "*", ".").c_str(), "String", &result) == -1) {
|
||||
throw xresource_error(sstream() << "X resource \"" << name << "\" not found");
|
||||
} else if (result == nullptr) {
|
||||
throw xresource_error(sstream() << "X resource \"" << name << "\" not found");
|
||||
}
|
||||
return convert<T>(string(result));
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T get(const char* name, const T& fallback) const {
|
||||
try {
|
||||
return convert<T>(require<T>(name));
|
||||
} catch (const xresource_error) {
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
string load_value(const string& key, const string& res_type, size_t n) const;
|
||||
template <typename T>
|
||||
T convert(string&& value) const;
|
||||
|
||||
private:
|
||||
XrmDatabase m_db;
|
||||
char* m_manager{nullptr};
|
||||
xcb_xrm_database_t* m_xrm;
|
||||
};
|
||||
|
||||
POLYBAR_NS_END
|
||||
|
@ -64,6 +64,11 @@ if(WITH_XKB)
|
||||
else()
|
||||
list(REMOVE_ITEM SOURCES x11/extensions/xkb.cpp modules/xkeyboard.cpp)
|
||||
endif()
|
||||
if(WITH_XRM)
|
||||
pkg_check_modules(XCB_UTIL_XRM REQUIRED xcb-xrm)
|
||||
set(APP_LIBRARIES ${APP_LIBRARIES} ${XCB_UTIL_XRM_LIBRARIES})
|
||||
set(APP_INCLUDE_DIRS ${APP_INCLUDE_DIRS} ${XCB_UTIL_XRM_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
string(REPLACE ";" ", " XPP_EXTENSION_LIST "${XPP_EXTENSION_LIST}")
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "utils/math.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#include "x11/color.hpp"
|
||||
#include "x11/xresources.hpp"
|
||||
|
||||
POLYBAR_NS
|
||||
|
||||
@ -15,18 +16,14 @@ POLYBAR_NS
|
||||
* Create instance
|
||||
*/
|
||||
config::make_type config::make(string path, string bar) {
|
||||
return static_cast<config::make_type>(*factory_util::singleton<std::remove_reference_t<config::make_type>>(
|
||||
logger::make(), xresource_manager::make(), move(path), move(bar)));
|
||||
return *factory_util::singleton<std::remove_reference_t<config::make_type>>(logger::make(), move(path), move(bar));
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct config object
|
||||
*/
|
||||
config::config(const logger& logger, const xresource_manager& xrm, string&& path, string&& bar)
|
||||
: m_log(logger)
|
||||
, m_xrm(forward<decltype(xrm)>(xrm))
|
||||
, m_file(forward<string>(path))
|
||||
, m_barname(forward<string>(bar)) {
|
||||
config::config(const logger& logger, string&& path, string&& bar)
|
||||
: m_log(logger), m_file(forward<string>(path)), m_barname(forward<string>(bar)) {
|
||||
if (!file_util::exists(m_file)) {
|
||||
throw application_error("Could not find config file: " + m_file);
|
||||
}
|
||||
@ -126,6 +123,14 @@ void config::parse_file() {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef WITH_XRM
|
||||
// Initialize the xresource manage if there are any xrdb refs
|
||||
// present in the configuration
|
||||
if (!m_xrm && value.find("${xrdb") != string::npos) {
|
||||
m_xrm.reset(new xresource_manager{connection::make()});
|
||||
}
|
||||
#endif
|
||||
|
||||
m_sections[section].emplace_hint(it, move(key), move(value));
|
||||
}
|
||||
}
|
||||
|
@ -1,88 +1,15 @@
|
||||
#include <X11/Xlib.h>
|
||||
#include <cstring>
|
||||
#include <utility>
|
||||
|
||||
#include "utils/factory.hpp"
|
||||
#include "x11/connection.hpp"
|
||||
#include "x11/xresources.hpp"
|
||||
|
||||
POLYBAR_NS
|
||||
|
||||
/**
|
||||
* Create instance
|
||||
*/
|
||||
xresource_manager::make_type xresource_manager::make() {
|
||||
return *factory_util::singleton<xresource_manager>(static_cast<Display*>(connection::make()));
|
||||
template <>
|
||||
string xresource_manager::convert(string&& value) const {
|
||||
return forward<string>(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct manager instance
|
||||
*/
|
||||
xresource_manager::xresource_manager(Display* dsp) {
|
||||
XrmInitialize();
|
||||
|
||||
if ((m_manager = XResourceManagerString(dsp)) != nullptr) {
|
||||
m_db = XrmGetStringDatabase(m_manager);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deconstruct instance
|
||||
*/
|
||||
xresource_manager::~xresource_manager() {
|
||||
if (m_manager != nullptr) {
|
||||
XrmDestroyDatabase(m_db);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get string value from the X resource db
|
||||
*/
|
||||
string xresource_manager::get_string(string name, string fallback) const {
|
||||
auto result = load_value(move(name), "String", 64);
|
||||
if (result.empty()) {
|
||||
return fallback;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get float value from the X resource db
|
||||
*/
|
||||
float xresource_manager::get_float(string name, float fallback) const {
|
||||
auto result = load_value(move(name), "String", 64);
|
||||
if (result.empty()) {
|
||||
return fallback;
|
||||
}
|
||||
return strtof(result.c_str(), nullptr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get integer value from the X resource db
|
||||
*/
|
||||
int xresource_manager::get_int(string name, int fallback) const {
|
||||
auto result = load_value(move(name), "String", 64);
|
||||
if (result.empty()) {
|
||||
return fallback;
|
||||
}
|
||||
return atoi(result.c_str());
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the database for given key
|
||||
*/
|
||||
string xresource_manager::load_value(const string& key, const string& res_type, size_t n) const {
|
||||
if (m_manager != nullptr) {
|
||||
char* type = nullptr;
|
||||
XrmValue ret{};
|
||||
|
||||
if (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 "";
|
||||
template <>
|
||||
double xresource_manager::convert(string&& value) const {
|
||||
return std::strtod(value.c_str(), nullptr);
|
||||
}
|
||||
|
||||
POLYBAR_NS_END
|
||||
|
Loading…
Reference in New Issue
Block a user