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:
Michael Carlberg 2017-01-20 02:25:54 +01:00
parent 100c64a20c
commit e1483c3f65
13 changed files with 130 additions and 123 deletions

View File

@ -72,6 +72,12 @@ option(WITH_XDAMAGE "XDAMAGE support" OFF)
option(WITH_XSYNC "XSYNC support" OFF) option(WITH_XSYNC "XSYNC support" OFF)
option(WITH_XCOMPOSITE "XCOMPOSITE support" OFF) option(WITH_XCOMPOSITE "XCOMPOSITE support" OFF)
option(WITH_XKB "XKB support" ON) 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) if(NOT DEFINED ENABLE_XRANDR_MONITORS)
pkg_check_modules(XRANDR QUIET xrandr>=1.5.0) pkg_check_modules(XRANDR QUIET xrandr>=1.5.0)

View File

@ -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 " XCOMPOSITE support ${WITH_XCOMPOSITE}" WITH_XCOMPOSITE "32;1" "37;2")
colored_option(STATUS " XKB support ${WITH_XKB}" WITH_XKB "32;1" "37;2") colored_option(STATUS " XKB support ${WITH_XKB}" WITH_XKB "32;1" "37;2")
message(STATUS "--------------------------") message(STATUS "--------------------------")
colored_option(STATUS " xcb-util-xrm ${WITH_XCB_UTIL_XRM}" WITH_XCB_UTIL_XRM "32;1" "37;2")
message(STATUS "--------------------------")

View File

@ -12,7 +12,7 @@ pkgbase = polybar-git
makedepends = pkg-config makedepends = pkg-config
depends = libxft depends = libxft
depends = xcb-util-wm depends = xcb-util-wm
depends = xcb-util-image depends = xcb-util-xrm
optdepends = alsa-lib: volume module support optdepends = alsa-lib: volume module support
optdepends = libmpdclient: mpd module support optdepends = libmpdclient: mpd module support
optdepends = wireless_tools: network module support optdepends = wireless_tools: network module support

View File

@ -8,7 +8,7 @@ pkgdesc="A fast and easy-to-use status bar"
arch=("i686" "x86_64") arch=("i686" "x86_64")
url="https://github.com/jaagr/polybar" url="https://github.com/jaagr/polybar"
license=("MIT") license=("MIT")
depends=("libxft" "xcb-util-wm" "xcb-util-image") depends=("libxft" "xcb-util-wm" "xcb-util-xrm")
optdepends=("alsa-lib: volume module support" optdepends=("alsa-lib: volume module support"
"libmpdclient: mpd module support" "libmpdclient: mpd module support"
"wireless_tools: network module support" "wireless_tools: network module support"

View File

@ -12,7 +12,7 @@ pkgbase = polybar
makedepends = pkg-config makedepends = pkg-config
depends = libxft depends = libxft
depends = xcb-util-wm depends = xcb-util-wm
depends = xcb-util-image depends = xcb-util-xrm
optdepends = alsa-lib: volume module support optdepends = alsa-lib: volume module support
optdepends = libmpdclient: mpd module support optdepends = libmpdclient: mpd module support
optdepends = wireless_tools: network module support optdepends = wireless_tools: network module support

View File

@ -7,7 +7,7 @@ pkgdesc="A fast and easy-to-use status bar"
arch=("i686" "x86_64") arch=("i686" "x86_64")
url="https://github.com/jaagr/polybar" url="https://github.com/jaagr/polybar"
license=("MIT") license=("MIT")
depends=("libxft" "xcb-util-wm" "xcb-util-image") depends=("libxft" "xcb-util-wm" "xcb-util-xrm")
optdepends=("alsa-lib: volume module support" optdepends=("alsa-lib: volume module support"
"libmpdclient: mpd module support" "libmpdclient: mpd module support"
"wireless_tools: network module support" "wireless_tools: network module support"

View File

@ -5,10 +5,13 @@
#include "common.hpp" #include "common.hpp"
#include "components/logger.hpp" #include "components/logger.hpp"
#include "errors.hpp" #include "errors.hpp"
#include "settings.hpp"
#include "utils/env.hpp" #include "utils/env.hpp"
#include "utils/file.hpp" #include "utils/file.hpp"
#include "utils/string.hpp" #include "utils/string.hpp"
#ifdef WITH_XRM
#include "x11/xresources.hpp" #include "x11/xresources.hpp"
#endif
POLYBAR_NS POLYBAR_NS
@ -23,7 +26,7 @@ class config {
using make_type = const config&; using make_type = const config&;
static make_type make(string path = "", string bar = ""); 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 filepath() const;
string section() const; string section() const;
@ -209,11 +212,11 @@ class config {
size_t pos; size_t pos;
if (path.compare(0, 4, "env:") == 0) { 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) { } 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) { } 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) { } else if ((pos = path.find(".")) != string::npos) {
return dereference_local<T>(path.substr(0, pos), path.substr(pos + 1), section); return dereference_local<T>(path.substr(0, pos), path.substr(pos + 1), section);
} else { } else {
@ -252,9 +255,9 @@ class config {
* ${env:key:fallback value} * ${env:key:fallback value}
*/ */
template <typename T> template <typename T>
T dereference_env(string var, const T&) const { T dereference_env(string var) const {
size_t pos; size_t pos;
string env_default{""}; string env_default;
if ((pos = var.find(":")) != string::npos) { if ((pos = var.find(":")) != string::npos) {
env_default = var.substr(pos + 1); env_default = var.substr(pos + 1);
@ -281,15 +284,37 @@ class config {
* ${xrdb:key:fallback value} * ${xrdb:key:fallback value}
*/ */
template <typename T> template <typename T>
T dereference_xrdb(string var, const T& fallback) const { T dereference_xrdb(string var) const {
size_t pos; 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) { 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, "")}; string fallback;
return str.empty() ? fallback : convert<T>(move(str)); 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} * ${file:/absolute/file/path}
*/ */
template <typename T> template <typename T>
T dereference_file(string var, const T& fallback) const { T dereference_file(string var) const {
string filename{move(var)}; size_t pos;
string fallback;
if (file_util::exists(filename)) { if ((pos = var.find(":")) != string::npos) {
return convert<T>(string_util::trim(file_util::contents(filename), '\n')); fallback = var.substr(pos + 1);
var.erase(pos);
} }
return fallback; return fallback;
@ -310,10 +336,12 @@ class config {
private: private:
static constexpr const char* KEY_INHERIT{"inherit"}; static constexpr const char* KEY_INHERIT{"inherit"};
const logger& m_log; const logger& m_log;
const xresource_manager& m_xrm;
string m_file; string m_file;
string m_barname; string m_barname;
sectionmap_t m_sections{}; sectionmap_t m_sections{};
#ifdef WITH_XRM
unique_ptr<xresource_manager> m_xrm;
#endif
}; };
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -6,6 +6,7 @@
#include <thread> #include <thread>
#include "common.hpp" #include "common.hpp"
#include "settings.hpp"
#ifndef STDOUT_FILENO #ifndef STDOUT_FILENO
#define STDOUT_FILENO 1 #define STDOUT_FILENO 1

View File

@ -25,6 +25,7 @@
#cmakedefine01 WITH_XSYNC #cmakedefine01 WITH_XSYNC
#cmakedefine01 WITH_XCOMPOSITE #cmakedefine01 WITH_XCOMPOSITE
#cmakedefine01 WITH_XKB #cmakedefine01 WITH_XKB
#cmakedefine01 WITH_XRM
#if WITH_XRANDR #if WITH_XRANDR
#cmakedefine01 ENABLE_XRANDR_MONITORS #cmakedefine01 ENABLE_XRANDR_MONITORS
@ -97,14 +98,15 @@ const auto print_build_info = [](bool extended = false) {
(ENABLE_NETWORK ? '+' : '-')); (ENABLE_NETWORK ? '+' : '-'));
if (extended) { if (extended) {
printf("\n"); 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 ? '+' : '-'), (WITH_XRANDR ? '+' : '-'),
(ENABLE_XRANDR_MONITORS ? '+' : '-'), (ENABLE_XRANDR_MONITORS ? '+' : '-'),
(WITH_XRENDER ? '+' : '-'), (WITH_XRENDER ? '+' : '-'),
(WITH_XDAMAGE ? '+' : '-'), (WITH_XDAMAGE ? '+' : '-'),
(WITH_XSYNC ? '+' : '-'), (WITH_XSYNC ? '+' : '-'),
(WITH_XCOMPOSITE ? '+' : '-'), (WITH_XCOMPOSITE ? '+' : '-'),
(WITH_XKB ? '+' : '-')); (WITH_XKB ? '+' : '-'),
(WITH_XRM ? '+' : '-'));
printf("\n"); printf("\n");
printf("Build type: @CMAKE_BUILD_TYPE@\n"); printf("Build type: @CMAKE_BUILD_TYPE@\n");
printf("Compiler: @CMAKE_CXX_COMPILER@\n"); printf("Compiler: @CMAKE_CXX_COMPILER@\n");

View File

@ -1,33 +1,64 @@
#pragma once #pragma once
#include <X11/X.h> #include "settings.hpp"
#include <X11/Xresource.h>
#if not WITH_XRM
#error "Not built with support for xcb-xrm..."
#endif
#include <xcb/xcb_xrm.h>
#include "common.hpp" #include "common.hpp"
#include "errors.hpp"
#include "utils/string.hpp"
#include "x11/connection.hpp"
POLYBAR_NS POLYBAR_NS
DEFINE_ERROR(xresource_error);
class xresource_manager { class xresource_manager {
public: public:
using make_type = const xresource_manager&; explicit xresource_manager(xcb_connection_t* conn) : m_xrm(xcb_xrm_database_from_default(conn)) {
static make_type make(); 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; operator bool() const {
xresource_manager& operator=(const xresource_manager& o) = delete; return m_xrm != nullptr;
}
string get_string(string name, string fallback = "") const; template <typename T>
float get_float(string name, float fallback = 0.0f) const; T require(const char* name) const {
int get_int(string name, int fallback = 0) 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: protected:
string load_value(const string& key, const string& res_type, size_t n) const; template <typename T>
T convert(string&& value) const;
private: private:
XrmDatabase m_db; xcb_xrm_database_t* m_xrm;
char* m_manager{nullptr};
}; };
POLYBAR_NS_END POLYBAR_NS_END

View File

@ -64,6 +64,11 @@ if(WITH_XKB)
else() else()
list(REMOVE_ITEM SOURCES x11/extensions/xkb.cpp modules/xkeyboard.cpp) list(REMOVE_ITEM SOURCES x11/extensions/xkb.cpp modules/xkeyboard.cpp)
endif() 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}") string(REPLACE ";" ", " XPP_EXTENSION_LIST "${XPP_EXTENSION_LIST}")

View File

@ -8,6 +8,7 @@
#include "utils/math.hpp" #include "utils/math.hpp"
#include "utils/string.hpp" #include "utils/string.hpp"
#include "x11/color.hpp" #include "x11/color.hpp"
#include "x11/xresources.hpp"
POLYBAR_NS POLYBAR_NS
@ -15,18 +16,14 @@ POLYBAR_NS
* Create instance * Create instance
*/ */
config::make_type config::make(string path, string bar) { 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>>( return *factory_util::singleton<std::remove_reference_t<config::make_type>>(logger::make(), move(path), move(bar));
logger::make(), xresource_manager::make(), move(path), move(bar)));
} }
/** /**
* Construct config object * Construct config object
*/ */
config::config(const logger& logger, const xresource_manager& xrm, string&& path, string&& bar) config::config(const logger& logger, string&& path, string&& bar)
: m_log(logger) : m_log(logger), m_file(forward<string>(path)), m_barname(forward<string>(bar)) {
, m_xrm(forward<decltype(xrm)>(xrm))
, m_file(forward<string>(path))
, m_barname(forward<string>(bar)) {
if (!file_util::exists(m_file)) { if (!file_util::exists(m_file)) {
throw application_error("Could not find config file: " + 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)); m_sections[section].emplace_hint(it, move(key), move(value));
} }
} }

View File

@ -1,88 +1,15 @@
#include <X11/Xlib.h>
#include <cstring>
#include <utility>
#include "utils/factory.hpp"
#include "x11/connection.hpp"
#include "x11/xresources.hpp" #include "x11/xresources.hpp"
POLYBAR_NS POLYBAR_NS
/** template <>
* Create instance string xresource_manager::convert(string&& value) const {
*/ return forward<string>(value);
xresource_manager::make_type xresource_manager::make() {
return *factory_util::singleton<xresource_manager>(static_cast<Display*>(connection::make()));
} }
/** template <>
* Construct manager instance double xresource_manager::convert(string&& value) const {
*/ return std::strtod(value.c_str(), nullptr);
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 "";
} }
POLYBAR_NS_END POLYBAR_NS_END