feat(client): add support for 8-bit hex color codes in CSS
This allows users to use #RRGGBBAA format in their style.css. The client now detects 8-bit hex codes, transforms them into GTK-compatible rgba() syntax, and loads the modified data into the CSS provider. - Added utility to detect 8-bit hex patterns. - Added transformation logic to convert hex alpha to decimal. - Intercepted CSS loading in Client::setupCss to handle the conversion.
This commit is contained in:
17
include/util/hex_checker.hpp
Normal file
17
include/util/hex_checker.hpp
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a CSS file, searches for 8-bit hex codes (#RRGGBBAA),
|
||||||
|
* and returns true if found, or false if not found.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool has_8bit_hex(std::string file_path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a CSS file, searches for 8-bit hex codes (#RRGGBBAA),
|
||||||
|
* and transforms them into GTK-compatible rgba() syntax.
|
||||||
|
*/
|
||||||
|
|
||||||
|
std::string transform_8bit_to_hex(std::string file_path);
|
||||||
@@ -185,7 +185,9 @@ 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/has_8bit_hex.cpp',
|
||||||
|
'src/util/transform_8bit_to_rgba.cpp'
|
||||||
)
|
)
|
||||||
|
|
||||||
man_files = files(
|
man_files = files(
|
||||||
|
|||||||
@@ -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,21 +23,18 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
client->idle_inhibit_manager = static_cast<struct zwp_idle_inhibit_manager_v1*>(
|
client->idle_inhibit_manager = static_cast<struct zwp_idle_inhibit_manager_v1*>(
|
||||||
@@ -209,11 +207,15 @@ auto waybar::Client::setupCss(const std::string& css_file) -> void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
css_provider_ = Gtk::CssProvider::create();
|
css_provider_ = Gtk::CssProvider::create();
|
||||||
if (!css_provider_->load_from_path(css_file)) {
|
if (has_8bit_hex(css_file)) {
|
||||||
css_provider_.reset();
|
std::string modified_css = transform_8bit_to_hex(css_file);
|
||||||
throw std::runtime_error("Can't open style file");
|
css_provider_->load_from_data(modified_css);
|
||||||
|
} else {
|
||||||
|
if (!css_provider_->load_from_path(css_file)) {
|
||||||
|
css_provider_.reset();
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
|
|||||||
15
src/util/has_8bit_hex.cpp
Normal file
15
src/util/has_8bit_hex.cpp
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
|
bool has_8bit_hex(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');
|
||||||
|
f.read(result.data(), size);
|
||||||
|
std::regex pattern(
|
||||||
|
R"((?:\#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})))");
|
||||||
|
return std::regex_search(result, pattern);
|
||||||
|
}
|
||||||
41
src/util/transform_8bit_to_rgba.cpp
Normal file
41
src/util/transform_8bit_to_rgba.cpp
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <regex>
|
||||||
|
#include <sstream>
|
||||||
|
namespace fs = std::filesystem;
|
||||||
|
std::string transform_8bit_to_hex(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');
|
||||||
|
f.read(result.data(), size);
|
||||||
|
|
||||||
|
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();
|
||||||
|
std::smatch match = *it;
|
||||||
|
|
||||||
|
while (it != eof) {
|
||||||
|
|
||||||
|
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 final_output;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user