Add unified Xresources theme engine, Default.xth export, and xthemes manager plugin

This commit is contained in:
Luxferre
2026-10-21 20:36:27 +03:00
parent f615c6ddbe
commit a31595070c
60 changed files with 3692 additions and 419 deletions
+27 -42
View File
@@ -106,37 +106,19 @@ int dialer_run_main(int argc, char** argv) {
PangoContext* pangoCtx = pango_font_map_create_context(fontMap);
PangoLayout* layoutNum = pango_layout_new(pangoCtx);
PangoFontDescription* descNum =
pango_font_description_from_string("Fira Code, DejaVuSansM Nerd Font Bold 18px");
pango_layout_set_font_description(layoutNum, descNum);
PangoLayout* layoutMain = pango_layout_new(pangoCtx);
PangoFontDescription* descMain =
pango_font_description_from_string("Fira Code, DejaVuSansM Nerd Font 15px");
pango_layout_set_font_description(layoutMain, descMain);
PangoLayout* layoutSmall = pango_layout_new(pangoCtx);
PangoFontDescription* descSmall =
pango_font_description_from_string("Fira Code, DejaVuSansM Nerd Font 12px");
pango_layout_set_font_description(layoutSmall, descSmall);
PangoLayout* layoutIcon = pango_layout_new(pangoCtx);
PangoFontDescription* descIcon =
pango_font_description_from_string("DejaVuSansM Nerd Font, Fira Code 16px");
pango_layout_set_font_description(layoutIcon, descIcon);
auto allocColor = [&](const char* hex) {
XftColor col{};
XftColorAllocName(dpy, visual, cmap, hex, &col);
return col;
};
XftColor colWhite = allocColor("#ffffff");
XftColor colLight = allocColor("#dddddd");
XftColor colMuted = allocColor("#999999");
XftColor colYellow = allocColor("#f4d03f");
XftColor colGreen = allocColor("#2ecc71");
XftColor colBlue = allocColor("#5dade2");
PluginTheme theme;
theme.load(dpy, screen, visual, cmap, layoutMain, layoutSmall, layoutIcon,
layoutNum, win);
XftColor& colWhite = theme.colWhite;
XftColor& colLight = theme.colLight;
XftColor& colMuted = theme.colMuted;
XftColor& colYellow = theme.colYellow;
XftColor& colGreen = theme.colGreen;
XftColor& colBlue = theme.colBlue;
ContactBook book;
std::vector<ContactEntry> allContacts;
@@ -241,17 +223,17 @@ int dialer_run_main(int argc, char** argv) {
constexpr int kVisibleRows = 5;
auto render = [&]() {
XSetForeground(dpy, gc, 0x222222);
XSetForeground(dpy, gc, theme.spec.bgMain);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, kWinHeight);
bool topSel = (selected < 0);
XSetForeground(dpy, gc, topSel ? 0x1b3b4b : 0x1c1c1c);
XSetForeground(dpy, gc, topSel ? theme.spec.bgInputFocus : theme.spec.bgHeader);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, kHeaderH);
if (topSel) {
XSetForeground(dpy, gc, 0xf4d03f);
XSetForeground(dpy, gc, theme.spec.accent);
XFillRectangle(dpy, pix, gc, 0, 0, 4, kHeaderH);
}
XSetForeground(dpy, gc, topSel ? 0x005577 : 0x444444);
XSetForeground(dpy, gc, topSel ? theme.spec.selBg : theme.spec.border);
XFillRectangle(dpy, pix, gc, 0, kHeaderH - 2, kWinWidth, 2);
drawPango(layoutIcon, &colGreen, 10, 4, 30, kIconPhone);
@@ -315,11 +297,11 @@ int dialer_run_main(int argc, char** argv) {
bool isSel = (idx == selected);
XSetForeground(dpy, gc,
isSel ? 0x005577 : ((i % 2 == 0) ? 0x282828 : 0x2e2e2e));
isSel ? theme.spec.selBg : ((i % 2 == 0) ? theme.spec.bgAltEven : theme.spec.bgAltOdd));
XFillRectangle(dpy, pix, gc, 0, ry, kWinWidth, rowH);
if (isSel) {
XSetForeground(dpy, gc, 0xf4d03f);
XSetForeground(dpy, gc, theme.spec.accent);
XFillRectangle(dpy, pix, gc, 0, ry, 4, rowH);
}
@@ -345,15 +327,15 @@ int dialer_run_main(int argc, char** argv) {
int sbH = std::max(16, (kListH * kVisibleRows) / total);
int sbY = kListY +
((kListH - sbH) * scrollOffset) / (total - kVisibleRows);
XSetForeground(dpy, gc, 0x666666);
XSetForeground(dpy, gc, theme.spec.divider);
XFillRectangle(dpy, pix, gc, kWinWidth - 3, sbY, 3, sbH);
}
}
int sbY = kWinHeight - kSoftbarH;
XSetForeground(dpy, gc, 0x181818);
XSetForeground(dpy, gc, theme.spec.bgFooter);
XFillRectangle(dpy, pix, gc, 0, sbY, kWinWidth, kSoftbarH);
XSetForeground(dpy, gc, 0x444444);
XSetForeground(dpy, gc, theme.spec.border);
XFillRectangle(dpy, pix, gc, 0, sbY, kWinWidth, 1);
std::string leftLabel = number.empty() ? "Call Log" : "+Sign";
@@ -387,6 +369,9 @@ int dialer_run_main(int argc, char** argv) {
auto showWindow = [&](const std::string& arg) {
closeOtherPlugins("dialer");
bool themeChanged = theme.checkAndReload(
dpy, screen, visual, cmap, layoutMain, layoutSmall, layoutIcon,
layoutNum, win);
std::string cleanArg = normalizePhone(arg);
if (!visible) {
openStartMs = nowMs();
@@ -398,7 +383,7 @@ int dialer_run_main(int argc, char** argv) {
zeroPressMs = zeroHeld ? openStartMs : 0;
visible = true;
XMapRaised(dpy, win);
if (cleanArg.empty()) {
if (cleanArg.empty() && !themeChanged) {
XCopyArea(dpy, pix, win, gc, 0, 0, kWinWidth, kWinHeight, 0, 0);
}
for (int i = 0; i < 20; ++i) {
@@ -409,7 +394,7 @@ int dialer_run_main(int argc, char** argv) {
usleep(2000);
}
bool reloaded = reloadContactsIfNeeded();
if (!cleanArg.empty() || reloaded || number != cleanArg) {
if (!cleanArg.empty() || reloaded || themeChanged || number != cleanArg) {
number = cleanArg;
selected = number.empty() ? (allContacts.empty() ? -1 : 0) : -1;
updateFilter();
@@ -494,6 +479,10 @@ int dialer_run_main(int argc, char** argv) {
showWindow("");
} else if (cmd.rfind("OPEN ", 0) == 0) {
showWindow(cmd.substr(5));
} else if (cmd == "RELOAD_THEME") {
theme.load(dpy, screen, visual, cmap, layoutMain, layoutSmall,
layoutIcon, layoutNum, win);
render();
}
}
@@ -723,10 +712,6 @@ int dialer_run_main(int argc, char** argv) {
::unlink(getPluginFifoPath("dialer").c_str());
::unlink(daemonPidPath.c_str());
pango_font_description_free(descIcon);
pango_font_description_free(descSmall);
pango_font_description_free(descMain);
pango_font_description_free(descNum);
g_object_unref(layoutIcon);
g_object_unref(layoutSmall);
g_object_unref(layoutMain);