Add unified Xresources theme engine, Default.xth export, and xthemes manager plugin
This commit is contained in:
@@ -236,10 +236,12 @@ int runFilesApp(int argc, char** argv) {
|
||||
Visual* visual = DefaultVisual(dpy, screen);
|
||||
Colormap cmap = DefaultColormap(dpy, screen);
|
||||
|
||||
ThemeSpec initSpec = loadThemeSpec(dpy, screen);
|
||||
|
||||
XSetWindowAttributes swa {};
|
||||
swa.override_redirect = True;
|
||||
swa.background_pixel = 0x222222;
|
||||
swa.border_pixel = 0x005577;
|
||||
swa.background_pixel = initSpec.bgMain;
|
||||
swa.border_pixel = initSpec.selBg;
|
||||
swa.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask |
|
||||
VisibilityChangeMask | StructureNotifyMask;
|
||||
|
||||
@@ -261,38 +263,19 @@ int runFilesApp(int argc, char** argv) {
|
||||
GC gc = XCreateGC(dpy, pix, 0, nullptr);
|
||||
XftDraw* xftDraw = XftDrawCreate(dpy, pix, visual, cmap);
|
||||
|
||||
PangoFontMap* fontMap = pango_xft_get_font_map(dpy, screen);
|
||||
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 colOrange = allocColor("#e67e22");
|
||||
XftColor colRed = allocColor("#e74c3c");
|
||||
PluginTheme pt;
|
||||
pt.init(dpy, screen, visual, cmap, win);
|
||||
auto& layoutMain = pt.layoutMain;
|
||||
auto& layoutSmall = pt.layoutSmall;
|
||||
auto& layoutIcon = pt.layoutIcon;
|
||||
auto& colWhite = pt.colWhite;
|
||||
auto& colLight = pt.colLight;
|
||||
auto& colMuted = pt.colMuted;
|
||||
auto& colYellow = pt.colYellow;
|
||||
auto& colGreen = pt.colGreen;
|
||||
auto& colBlue = pt.colBlue;
|
||||
auto& colOrange = pt.colOrange;
|
||||
auto& colRed = pt.colRed;
|
||||
|
||||
const char* homeEnv = std::getenv("HOME");
|
||||
std::string homeDir = (homeEnv && homeEnv[0]) ? homeEnv : "/home/user";
|
||||
@@ -599,9 +582,9 @@ int runFilesApp(int argc, char** argv) {
|
||||
const std::string& centerLabel,
|
||||
const std::string& rightLabel) {
|
||||
const int barY = kWinHeight - 26;
|
||||
XSetForeground(dpy, gc, 0x141414);
|
||||
XSetForeground(dpy, gc, pt.spec.bgFooter);
|
||||
XFillRectangle(dpy, pix, gc, 0, barY, kWinWidth, 26);
|
||||
XSetForeground(dpy, gc, 0x2d2d2d);
|
||||
XSetForeground(dpy, gc, pt.spec.divider);
|
||||
XDrawLine(dpy, pix, gc, 0, barY, kWinWidth, barY);
|
||||
|
||||
drawPango(layoutMain, &colBlue, 6, barY, 26, leftLabel);
|
||||
@@ -624,14 +607,15 @@ int runFilesApp(int argc, char** argv) {
|
||||
|
||||
auto drawUI = [&]() {
|
||||
if (!visible) return;
|
||||
pt.checkAndReload();
|
||||
|
||||
XSetForeground(dpy, gc, 0x222222);
|
||||
XSetForeground(dpy, gc, pt.spec.bgMain);
|
||||
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, kWinHeight);
|
||||
|
||||
if (mode == ViewMode::Browser) {
|
||||
XSetForeground(dpy, gc, 0x161616);
|
||||
XSetForeground(dpy, gc, pt.spec.bgHeader);
|
||||
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, 38);
|
||||
XSetForeground(dpy, gc, 0x333333);
|
||||
XSetForeground(dpy, gc, pt.spec.border);
|
||||
XDrawLine(dpy, pix, gc, 0, 37, kWinWidth, 37);
|
||||
|
||||
if (searchQuery.empty()) {
|
||||
@@ -681,12 +665,13 @@ int runFilesApp(int argc, char** argv) {
|
||||
bool isSel = (idx == selected);
|
||||
|
||||
if (isSel) {
|
||||
XSetForeground(dpy, gc, 0x005577);
|
||||
XSetForeground(dpy, gc, pt.spec.selBg);
|
||||
XFillRectangle(dpy, pix, gc, 0, ry, kWinWidth, rowH - 1);
|
||||
XSetForeground(dpy, gc, 0x0088bb);
|
||||
XSetForeground(dpy, gc, pt.spec.accentAlt);
|
||||
XDrawLine(dpy, pix, gc, 0, ry, kWinWidth, ry);
|
||||
} else {
|
||||
XSetForeground(dpy, gc, (i % 2 == 0) ? 0x222222 : 0x1d1d1d);
|
||||
XSetForeground(dpy, gc,
|
||||
(i % 2 == 0) ? pt.spec.bgAltEven : pt.spec.bgAltOdd);
|
||||
XFillRectangle(dpy, pix, gc, 0, ry, kWinWidth, rowH - 1);
|
||||
}
|
||||
|
||||
@@ -738,7 +723,7 @@ int runFilesApp(int argc, char** argv) {
|
||||
searchQuery.empty() ? "Close" : "Clear");
|
||||
|
||||
} else if (mode == ViewMode::Actions) {
|
||||
XSetForeground(dpy, gc, 0x161616);
|
||||
XSetForeground(dpy, gc, pt.spec.bgHeader);
|
||||
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, 34);
|
||||
drawPango(layoutIcon, &colBlue, 6, 0, 34, kIconList);
|
||||
drawPango(layoutMain, &colWhite, 28, 0, 34, "File Actions", 200);
|
||||
@@ -755,7 +740,7 @@ int runFilesApp(int argc, char** argv) {
|
||||
if (idx >= static_cast<int>(actionsList.size())) break;
|
||||
int ry = listY + i * rowH;
|
||||
bool isSel = (idx == actionSelected);
|
||||
XSetForeground(dpy, gc, isSel ? 0x005577 : 0x222222);
|
||||
XSetForeground(dpy, gc, isSel ? pt.spec.selBg : pt.spec.bgMain);
|
||||
XFillRectangle(dpy, pix, gc, 0, ry, kWinWidth, rowH - 1);
|
||||
drawPango(layoutIcon, isSel ? &colYellow : &colBlue, 8, ry, rowH,
|
||||
actionsList[idx].icon);
|
||||
@@ -765,7 +750,7 @@ int runFilesApp(int argc, char** argv) {
|
||||
drawSoftkeyBar("Select", "Select", "Back");
|
||||
|
||||
} else if (mode == ViewMode::TextView) {
|
||||
XSetForeground(dpy, gc, 0x161616);
|
||||
XSetForeground(dpy, gc, pt.spec.bgHeader);
|
||||
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, 32);
|
||||
drawPango(layoutIcon, &colBlue, 6, 0, 32, kIconFileText);
|
||||
drawPango(layoutMain, &colWhite, 28, 0, 32, viewingFileName, 150);
|
||||
@@ -791,7 +776,7 @@ int runFilesApp(int argc, char** argv) {
|
||||
drawSoftkeyBar("Edit", "Down", "Back");
|
||||
|
||||
} else if (mode == ViewMode::ImageView) {
|
||||
XSetForeground(dpy, gc, 0x161616);
|
||||
XSetForeground(dpy, gc, pt.spec.bgHeader);
|
||||
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, 36);
|
||||
drawPango(layoutIcon, &colGreen, 6, 1, 18, kIconImage);
|
||||
drawPango(layoutMain, &colWhite, 28, 0, 20, viewingFileName, 145);
|
||||
@@ -807,7 +792,7 @@ int runFilesApp(int argc, char** argv) {
|
||||
|
||||
} else if (mode == ViewMode::PropsView && !filteredItems.empty()) {
|
||||
const auto& it = filteredItems[selected];
|
||||
XSetForeground(dpy, gc, 0x161616);
|
||||
XSetForeground(dpy, gc, pt.spec.bgHeader);
|
||||
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, 34);
|
||||
drawPango(layoutIcon, &colBlue, 6, 0, 34, kIconInfo);
|
||||
drawPango(layoutMain, &colWhite, 28, 0, 34, "Properties", 200);
|
||||
@@ -838,7 +823,7 @@ int runFilesApp(int argc, char** argv) {
|
||||
drawSoftkeyBar("Back", "Back", "Back");
|
||||
|
||||
} else if (mode == ViewMode::InputModal) {
|
||||
XSetForeground(dpy, gc, 0x161616);
|
||||
XSetForeground(dpy, gc, pt.spec.bgHeader);
|
||||
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, 36);
|
||||
drawPango(layoutIcon, &colBlue, 6, 0, 36, kIconEdit);
|
||||
drawPango(layoutMain, &colWhite, 28, 0, 36, inputTitle, 145);
|
||||
@@ -849,9 +834,9 @@ int runFilesApp(int argc, char** argv) {
|
||||
else if (caseMode == TextCaseMode::Num) mBadge = "[123]";
|
||||
drawPango(layoutSmall, &colYellow, kWinWidth - 46, 0, 36, mBadge);
|
||||
|
||||
XSetForeground(dpy, gc, 0x182630);
|
||||
XSetForeground(dpy, gc, pt.spec.bgInputFocus);
|
||||
XFillRectangle(dpy, pix, gc, 10, 74, kWinWidth - 20, 38);
|
||||
XSetForeground(dpy, gc, 0x0088bb);
|
||||
XSetForeground(dpy, gc, pt.spec.accentAlt);
|
||||
XDrawRectangle(dpy, pix, gc, 10, 74, kWinWidth - 21, 37);
|
||||
drawPango(layoutMain, &colWhite, 16, 74, 38, inputValue + "|",
|
||||
kWinWidth - 32);
|
||||
@@ -863,7 +848,7 @@ int runFilesApp(int argc, char** argv) {
|
||||
|
||||
} else if (mode == ViewMode::ConfirmDelete && !filteredItems.empty()) {
|
||||
const auto& it = filteredItems[selected];
|
||||
XSetForeground(dpy, gc, 0x161616);
|
||||
XSetForeground(dpy, gc, pt.spec.bgHeader);
|
||||
XFillRectangle(dpy, pix, gc, 0, 0, kWinWidth, 36);
|
||||
drawPango(layoutIcon, &colRed, 8, 0, 36, kIconTrash);
|
||||
drawPango(layoutMain, &colWhite, 30, 0, 36, "Delete Item?", 200);
|
||||
@@ -878,8 +863,10 @@ int runFilesApp(int argc, char** argv) {
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
int ry = 164 + i * 40;
|
||||
bool isSel = (confirmSelected == i);
|
||||
XSetForeground(dpy, gc,
|
||||
isSel ? (i == 1 ? 0x922b21 : 0x005577) : 0x2a2a2a);
|
||||
XSetForeground(
|
||||
dpy, gc,
|
||||
isSel ? (i == 1 ? pt.spec.dangerBg : pt.spec.selBg)
|
||||
: pt.spec.bgButton);
|
||||
XFillRectangle(dpy, pix, gc, 16, ry, kWinWidth - 32, 34);
|
||||
drawPango(layoutMain, &colWhite, 28, ry, 34,
|
||||
i == 0 ? "No, Keep Item" : "Yes, Delete", 184);
|
||||
@@ -889,9 +876,9 @@ int runFilesApp(int argc, char** argv) {
|
||||
|
||||
int64_t tNow = nowMs();
|
||||
if (!statusBanner.empty() && tNow < statusBannerUntilMs) {
|
||||
XSetForeground(dpy, gc, 0x102535);
|
||||
XSetForeground(dpy, gc, pt.spec.bgToast);
|
||||
XFillRectangle(dpy, pix, gc, 8, kWinHeight - 58, kWinWidth - 16, 28);
|
||||
XSetForeground(dpy, gc, 0x5dade2);
|
||||
XSetForeground(dpy, gc, pt.spec.info);
|
||||
XDrawRectangle(dpy, pix, gc, 8, kWinHeight - 58, kWinWidth - 17, 27);
|
||||
drawPango(layoutSmall, &colWhite, 14, kWinHeight - 58, 28, statusBanner,
|
||||
kWinWidth - 28);
|
||||
@@ -1151,6 +1138,9 @@ int runFilesApp(int argc, char** argv) {
|
||||
for (const auto& cmd : readFifoLines(fifoFd)) {
|
||||
if (cmd == "NOP") {
|
||||
continue;
|
||||
} else if (cmd == "RELOAD_THEME") {
|
||||
pt.reload();
|
||||
if (visible) drawUI();
|
||||
} else if (cmd == "CLOSE") {
|
||||
hideWindow();
|
||||
} else if (cmd == "OPEN") {
|
||||
@@ -1384,7 +1374,10 @@ int runFilesApp(int argc, char** argv) {
|
||||
int pr = ::poll(pfds, nfds, timeoutMs);
|
||||
if (pr > 0 && fifoIdx >= 0 && (pfds[fifoIdx].revents & POLLIN)) {
|
||||
for (const auto& cmd : readFifoLines(fifoFd)) {
|
||||
if (cmd == "CLOSE") {
|
||||
if (cmd == "RELOAD_THEME") {
|
||||
pt.reload();
|
||||
if (visible) drawUI();
|
||||
} else if (cmd == "CLOSE") {
|
||||
hideWindow();
|
||||
} else if (cmd == "OPEN") {
|
||||
showWindow("");
|
||||
|
||||
Reference in New Issue
Block a user