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
+32 -40
View File
@@ -101,33 +101,19 @@ int calllog_run_main(int argc, char** argv) {
PangoContext* pangoCtx = pango_font_map_create_context(fontMap);
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");
XftColor colRed = allocColor("#e74c3c");
PluginTheme theme;
theme.load(dpy, screen, visual, cmap, layoutMain, layoutSmall, layoutIcon,
nullptr, 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;
XftColor& colRed = theme.colRed;
ContactBook book;
std::vector<CallLogItem> allLogs;
@@ -208,10 +194,10 @@ int calllog_run_main(int argc, char** argv) {
const char* kTabLabels[4] = {"All", "Missed", "In", "Out"};
auto render = [&]() {
XSetForeground(dpy, gc, 0x222222);
XSetForeground(dpy, gc, theme.spec.bgMain);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, kWinHeight);
XSetForeground(dpy, gc, 0x1c1c1c);
XSetForeground(dpy, gc, theme.spec.bgHeader);
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, kHeaderH);
for (int t = 0; t < 4; ++t) {
@@ -219,9 +205,9 @@ int calllog_run_main(int argc, char** argv) {
int tw = ((t + 1) * kWinWidth) / 4 - tx;
bool active = (t == filterTab);
if (active) {
XSetForeground(dpy, gc, 0x005577);
XSetForeground(dpy, gc, theme.spec.selBg);
XFillRectangle(dpy, pix, gc, tx, 0, tw, kHeaderH - 2);
XSetForeground(dpy, gc, 0xf4d03f);
XSetForeground(dpy, gc, theme.spec.accent);
XFillRectangle(dpy, pix, gc, tx, kHeaderH - 3, tw, 3);
}
std::string lbl(kTabLabels[t]);
@@ -230,7 +216,7 @@ int calllog_run_main(int argc, char** argv) {
tx + (tw - lw) / 2, 0, kHeaderH - 2, lbl);
}
XSetForeground(dpy, gc, 0x444444);
XSetForeground(dpy, gc, theme.spec.border);
XFillRectangle(dpy, pix, gc, 0, kHeaderH - 1, kWinWidth, 1);
if (filtered.empty()) {
@@ -259,11 +245,11 @@ int calllog_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);
}
@@ -313,15 +299,15 @@ int calllog_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);
drawPango(layoutMain, &colLight, 6, sbY + 1, kSoftbarH - 1, "Dialer");
@@ -348,6 +334,9 @@ int calllog_run_main(int argc, char** argv) {
auto showWindow = [&]() {
closeOtherPlugins("calllog");
bool themeChanged = theme.checkAndReload(
dpy, screen, visual, cmap, layoutMain, layoutSmall, layoutIcon,
nullptr, win);
if (!visible) {
openStartMs = nowMs();
startupIgnoreUntilMs = openStartMs + 90;
@@ -356,7 +345,9 @@ int calllog_run_main(int argc, char** argv) {
softkeyDeadlineMs = 0;
visible = true;
XMapRaised(dpy, win);
XCopyArea(dpy, pix, win, gc, 0, 0, kWinWidth, kWinHeight, 0, 0);
if (!themeChanged) {
XCopyArea(dpy, pix, win, gc, 0, 0, kWinWidth, kWinHeight, 0, 0);
}
for (int i = 0; i < 20; ++i) {
if (XGrabKeyboard(dpy, win, True, GrabModeAsync, GrabModeAsync, CurrentTime) ==
GrabSuccess) {
@@ -364,7 +355,7 @@ int calllog_run_main(int argc, char** argv) {
}
usleep(2000);
}
if (reloadLogsIfNeeded() || filterTab != 0 || selected != 0) {
if (reloadLogsIfNeeded() || themeChanged || filterTab != 0 || selected != 0) {
filterTab = 0;
selected = 0;
applyFilter();
@@ -373,7 +364,7 @@ int calllog_run_main(int argc, char** argv) {
XFlush(dpy);
writeIntFile(activePidPath, static_cast<int>(::getpid()));
} else {
if (reloadLogsIfNeeded()) {
if (reloadLogsIfNeeded() || themeChanged) {
render();
}
}
@@ -428,6 +419,10 @@ int calllog_run_main(int argc, char** argv) {
hideWindow(false);
} else if (cmd.rfind("OPEN", 0) == 0) {
showWindow();
} else if (cmd == "RELOAD_THEME") {
theme.load(dpy, screen, visual, cmap, layoutMain, layoutSmall,
layoutIcon, nullptr, win);
render();
}
}
@@ -614,9 +609,6 @@ int calllog_run_main(int argc, char** argv) {
::unlink(getPluginFifoPath("calllog").c_str());
::unlink(daemonPidPath.c_str());
pango_font_description_free(descIcon);
pango_font_description_free(descSmall);
pango_font_description_free(descMain);
g_object_unref(layoutIcon);
g_object_unref(layoutSmall);
g_object_unref(layoutMain);