Merge pull request #4960 from keepo-dot/feature/8bit-hex-support

feat(client): add support for 8-bit hex color codes in CSS
This commit is contained in:
Alexis Rouillard
2026-03-31 09:54:24 +02:00
committed by GitHub
4 changed files with 91 additions and 11 deletions

View File

@@ -0,0 +1,17 @@
#pragma once
#include <string>
/**
* Result of transforming 8-bit hex codes to rgba().
*/
struct TransformResult {
std::string css;
bool was_transformed;
};
/**
* Reads a CSS file, searches for 8-bit hex codes (#RRGGBBAA),
* and transforms them into GTK-compatible rgba() syntax.
*/
TransformResult transform_8bit_to_hex(const std::string& file_path);

View File

@@ -185,7 +185,8 @@ src_files = files(
'src/util/gtk_icon.cpp', 'src/util/gtk_icon.cpp',
'src/util/icon_loader.cpp', 'src/util/icon_loader.cpp',
'src/util/regex_collection.cpp', 'src/util/regex_collection.cpp',
'src/util/css_reload_helper.cpp' 'src/util/css_reload_helper.cpp',
'src/util/transform_8bit_to_rgba.cpp'
) )
man_files = files( man_files = files(

View File

@@ -10,6 +10,7 @@
#include "idle-inhibit-unstable-v1-client-protocol.h" #include "idle-inhibit-unstable-v1-client-protocol.h"
#include "util/clara.hpp" #include "util/clara.hpp"
#include "util/format.hpp" #include "util/format.hpp"
#include "util/hex_checker.hpp"
waybar::Client* waybar::Client::inst() { waybar::Client* waybar::Client::inst() {
static auto* c = new Client(); static auto* c = new Client();
@@ -22,18 +23,15 @@ void waybar::Client::handleGlobal(void* data, struct wl_registry* registry, uint
if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0 && if (strcmp(interface, zxdg_output_manager_v1_interface.name) == 0 &&
version >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION) { version >= ZXDG_OUTPUT_V1_NAME_SINCE_VERSION) {
if (client->xdg_output_manager != nullptr) { if (client->xdg_output_manager != nullptr) {
zxdg_output_manager_v1_destroy(client->xdg_output_manager); zxdg_output_manager_v1_destroy(client->xdg_output_manager);
client->xdg_output_manager = nullptr; client->xdg_output_manager = nullptr;
} }
client->xdg_output_manager = static_cast<struct zxdg_output_manager_v1*>( client->xdg_output_manager = static_cast<struct zxdg_output_manager_v1*>(wl_registry_bind(
wl_registry_bind(registry, name, &zxdg_output_manager_v1_interface, registry, name, &zxdg_output_manager_v1_interface, ZXDG_OUTPUT_V1_NAME_SINCE_VERSION));
ZXDG_OUTPUT_V1_NAME_SINCE_VERSION));
} else if (strcmp(interface, zwp_idle_inhibit_manager_v1_interface.name) == 0) { } else if (strcmp(interface, zwp_idle_inhibit_manager_v1_interface.name) == 0) {
if (client->idle_inhibit_manager != nullptr) { if (client->idle_inhibit_manager != nullptr) {
zwp_idle_inhibit_manager_v1_destroy(client->idle_inhibit_manager); zwp_idle_inhibit_manager_v1_destroy(client->idle_inhibit_manager);
client->idle_inhibit_manager = nullptr; client->idle_inhibit_manager = nullptr;
@@ -209,11 +207,15 @@ auto waybar::Client::setupCss(const std::string& css_file) -> void {
} }
css_provider_ = Gtk::CssProvider::create(); css_provider_ = Gtk::CssProvider::create();
auto [modified_css, was_transformed] = transform_8bit_to_hex(css_file);
if (was_transformed) {
css_provider_->load_from_data(modified_css);
} else {
if (!css_provider_->load_from_path(css_file)) { if (!css_provider_->load_from_path(css_file)) {
css_provider_.reset(); css_provider_.reset();
throw std::runtime_error("Can't open style file"); throw std::runtime_error("Can't open style file");
} }
}
Gtk::StyleContext::add_provider_for_screen(screen, css_provider_, Gtk::StyleContext::add_provider_for_screen(screen, css_provider_,
GTK_STYLE_PROVIDER_PRIORITY_USER); GTK_STYLE_PROVIDER_PRIORITY_USER);
} }

View File

@@ -0,0 +1,60 @@
#include <filesystem>
#include <fstream>
#include <iomanip>
#include <regex>
#include <sstream>
namespace fs = std::filesystem;
struct TransformResult {
std::string css;
bool was_transformed;
};
TransformResult transform_8bit_to_hex(const std::string& file_path) {
std::ifstream f(file_path, std::ios::in | std::ios::binary);
const auto size = fs::file_size(file_path);
std::string result(size, '\0');
if (!f.is_open() || !f.good()) {
throw std::runtime_error("Cannot open file: " + file_path);
}
if (size == 0) {
return {.css = result, .was_transformed = false};
}
f.read(result.data(), size);
static std::regex pattern(
R"(\#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2}))");
std::string final_output;
auto it = std::sregex_iterator(result.begin(), result.end(), pattern);
auto eof = std::sregex_iterator();
if (it == eof) {
return {.css = result, .was_transformed = false};
}
std::smatch match;
while (it != eof) {
match = *it;
final_output += match.prefix().str();
int r = stoi(match[1].str(), nullptr, 16);
int g = stoi(match[2].str(), nullptr, 16);
int b = stoi(match[3].str(), nullptr, 16);
double a = (stoi(match[4].str(), nullptr, 16) / 255.0);
std::stringstream ss;
ss << "rgba(" << r << "," << g << "," << b << "," << std::fixed << std::setprecision(2) << a
<< ")";
final_output += ss.str();
++it;
}
final_output += match.suffix().str();
return {.css = final_output, .was_transformed = true};
}