Add unified Xresources theme engine, Default.xth export, and xthemes manager plugin
This commit is contained in:
@@ -107,6 +107,10 @@ static Clr *scheme[SchemeLast];
|
||||
|
||||
static char *colors[SchemeLast][2];
|
||||
static const char *fonts[3] = { NULL, NULL, NULL };
|
||||
static char xres_font_main[256] = "";
|
||||
static char xres_font_icon[256] = "";
|
||||
static time_t last_xres_mtime = 0;
|
||||
static long last_xres_nsec = 0;
|
||||
|
||||
#include "config.h"
|
||||
|
||||
@@ -151,11 +155,14 @@ static const char *ICON_ZMI = "\xf3\xb0\x9b\xad";
|
||||
static const char *ICON_ZMO = "\xf3\xb0\x9b\xac";
|
||||
static const char *ICON_A2X = "\xe2\x87\x84";
|
||||
static const char *ICON_KBD = "\xef\x84\x9c";
|
||||
static const char *ICON_THM = "\xf3\xb0\x8f\x98";
|
||||
|
||||
static void drawmenu(void);
|
||||
static void show_menu(void);
|
||||
static void hide_menu(void);
|
||||
static void open_builtin_menu(const char *menu_name, int keep_idx);
|
||||
static void load_dmenu_xresources(void);
|
||||
static void reload_dmenu_theme(void);
|
||||
|
||||
static char *
|
||||
cistrstr(const char *s, const char *sub)
|
||||
@@ -1711,6 +1718,9 @@ open_builtin_menu(const char *menu_name, int keep_idx)
|
||||
snprintf(label, sizeof(label), "%s Camera", ICON_CAM);
|
||||
add_menu_item(label, "@plugin:camera", 0);
|
||||
|
||||
snprintf(label, sizeof(label), "%s Themes", ICON_THM);
|
||||
add_menu_item(label, "@plugin:themes", 0);
|
||||
|
||||
char bl_buf[32] = "";
|
||||
if (read_first_line("/sys/class/leds/white:torch/brightness", bl_buf, sizeof(bl_buf)) ||
|
||||
read_first_line("/sys/class/leds/white:flash/brightness", bl_buf, sizeof(bl_buf))) {
|
||||
@@ -1742,6 +1752,8 @@ open_builtin_menu(const char *menu_name, int keep_idx)
|
||||
} else if (strcmp(menu_name, "applications") == 0) {
|
||||
reset_session_defaults(1, "Apps");
|
||||
append_active_call_entries();
|
||||
snprintf(label, sizeof(label), "%s Themes", ICON_THM);
|
||||
add_menu_item(label, "@plugin:themes", 0);
|
||||
load_cache_or_hook("sxmo_apps.cache", "sxmo_hook_apps.sh");
|
||||
snprintf(label, sizeof(label), "%s System Menu", ICON_MNU);
|
||||
add_menu_item(label, "@menu:sys", 1);
|
||||
@@ -1776,6 +1788,8 @@ open_builtin_menu(const char *menu_name, int keep_idx)
|
||||
home = "/home/user";
|
||||
char pbuf[256];
|
||||
|
||||
snprintf(label, sizeof(label), "%s Themes", ICON_THM);
|
||||
add_menu_item(label, "@plugin:themes", 0);
|
||||
snprintf(label, sizeof(label), "%s Brightness", ICON_ARU);
|
||||
add_menu_item(label, "@toggle:bright_up", 1);
|
||||
snprintf(label, sizeof(label), "%s Brightness", ICON_ARD);
|
||||
@@ -1942,6 +1956,7 @@ close_other_active_plugins(void)
|
||||
{ "xsms.pid", "/tmp/dwm_plugin_sms.fifo" },
|
||||
{ "xfiles.pid", "/tmp/dwm_plugin_files.fifo" },
|
||||
{ "xcamera.pid", "/tmp/dwm_plugin_camera.fifo" },
|
||||
{ "xthemes.pid", "/tmp/dwm_plugin_themes.fifo" },
|
||||
};
|
||||
const char *rdir = getenv("XDG_RUNTIME_DIR");
|
||||
const char *base = (rdir && rdir[0]) ? rdir : "/run/user/10000";
|
||||
@@ -1960,12 +1975,185 @@ close_other_active_plugins(void)
|
||||
}
|
||||
}
|
||||
|
||||
static const char *
|
||||
dmenu_xrm_lookup(XrmDatabase xdb, const char *k1, const char *k2, const char *k3)
|
||||
{
|
||||
char *type = NULL;
|
||||
XrmValue xval;
|
||||
|
||||
if (k1 && XrmGetResource(xdb, k1, "*", &type, &xval) && xval.addr && xval.addr[0])
|
||||
return xval.addr;
|
||||
if (k2 && XrmGetResource(xdb, k2, "*", &type, &xval) && xval.addr && xval.addr[0])
|
||||
return xval.addr;
|
||||
if (k3 && XrmGetResource(xdb, k3, "*", &type, &xval) && xval.addr && xval.addr[0])
|
||||
return xval.addr;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
dmenu_set_color(int scm, int col, const char *val)
|
||||
{
|
||||
if (!val || !val[0])
|
||||
return;
|
||||
free(colors[scm][col]);
|
||||
colors[scm][col] = strdup(val);
|
||||
}
|
||||
|
||||
static void
|
||||
load_dmenu_xresources(void)
|
||||
{
|
||||
XrmInitialize();
|
||||
|
||||
const char *home = getenv("HOME");
|
||||
char path[512];
|
||||
snprintf(path, sizeof(path), "%s/.Xresources", (home && home[0]) ? home : "/home/user");
|
||||
struct stat st;
|
||||
if (stat(path, &st) == 0) {
|
||||
last_xres_mtime = st.st_mtim.tv_sec;
|
||||
last_xres_nsec = st.st_mtim.tv_nsec;
|
||||
}
|
||||
|
||||
XrmDatabase xdb = XrmGetFileDatabase(path);
|
||||
Atom actual_type = None;
|
||||
int actual_format = 0;
|
||||
unsigned long nitems = 0, bytes_after = 0;
|
||||
unsigned char *prop = NULL;
|
||||
|
||||
if (!xdb && XGetWindowProperty(dpy, root, XA_RESOURCE_MANAGER, 0L, 65536L, False,
|
||||
XA_STRING, &actual_type, &actual_format,
|
||||
&nitems, &bytes_after, &prop) == Success && prop) {
|
||||
if (actual_type == XA_STRING && actual_format == 8 && nitems > 0)
|
||||
xdb = XrmGetStringDatabase((const char *)prop);
|
||||
XFree(prop);
|
||||
}
|
||||
if (!xdb) {
|
||||
char *xrm = XResourceManagerString(dpy);
|
||||
if (xrm)
|
||||
xdb = XrmGetStringDatabase(xrm);
|
||||
}
|
||||
|
||||
if (xdb) {
|
||||
const char *ff = dmenu_xrm_lookup(xdb, "theme.fontFace", NULL, NULL);
|
||||
const char *icf = dmenu_xrm_lookup(xdb, "theme.iconFontFace", NULL, NULL);
|
||||
const char *bsz = dmenu_xrm_lookup(xdb, "theme.baseFontSize", NULL, NULL);
|
||||
const char *dmf = dmenu_xrm_lookup(xdb, "dmenu.font", NULL, NULL);
|
||||
|
||||
if (ff || bsz) {
|
||||
int base_sz = bsz ? atoi(bsz) : 15;
|
||||
if (base_sz < 8 || base_sz > 32)
|
||||
base_sz = 15;
|
||||
int large_sz = (base_sz * 18 + 7) / 15;
|
||||
snprintf(xres_font_main, sizeof(xres_font_main),
|
||||
"%s:pixelsize=%d:style=Regular:antialias=true:autohint=true",
|
||||
ff ? ff : "Fira Code", large_sz);
|
||||
snprintf(xres_font_icon, sizeof(xres_font_icon),
|
||||
"%s:pixelsize=%d:style=Regular:antialias=true:autohint=true",
|
||||
icf ? icf : "DejaVuSansM Nerd Font", large_sz);
|
||||
fonts[0] = xres_font_main;
|
||||
fonts[1] = xres_font_icon;
|
||||
} else if (dmf) {
|
||||
snprintf(xres_font_main, sizeof(xres_font_main), "%s", dmf);
|
||||
fonts[0] = xres_font_main;
|
||||
fonts[1] = defaultfonts[1];
|
||||
}
|
||||
|
||||
dmenu_set_color(SchemeNorm, ColBg,
|
||||
dmenu_xrm_lookup(xdb, "theme.bgHeader", "theme.bgMain", "dmenu.background"));
|
||||
dmenu_set_color(SchemeNorm, ColFg,
|
||||
dmenu_xrm_lookup(xdb, "theme.fgBright", "theme.fgMain", "dmenu.foreground"));
|
||||
|
||||
dmenu_set_color(SchemeSel, ColBg,
|
||||
dmenu_xrm_lookup(xdb, "theme.selBg", "dmenu.selbackground", NULL));
|
||||
dmenu_set_color(SchemeSel, ColFg,
|
||||
dmenu_xrm_lookup(xdb, "theme.selFg", "dmenu.selforeground", NULL));
|
||||
|
||||
dmenu_set_color(SchemeOut, ColBg,
|
||||
dmenu_xrm_lookup(xdb, "theme.bgSearch", "dmenu.outbackground", "theme.bgInputFocus"));
|
||||
dmenu_set_color(SchemeOut, ColFg,
|
||||
dmenu_xrm_lookup(xdb, "theme.fgBright", "dmenu.outforeground", "theme.fgMain"));
|
||||
|
||||
dmenu_set_color(SchemeNormHighlight, ColBg,
|
||||
dmenu_xrm_lookup(xdb, "theme.bgHeader", "theme.bgMain", "dmenu.background"));
|
||||
dmenu_set_color(SchemeNormHighlight, ColFg,
|
||||
dmenu_xrm_lookup(xdb, "theme.highlight", "theme.accent", "dmenu.normhlforeground"));
|
||||
|
||||
dmenu_set_color(SchemeSelHighlight, ColBg,
|
||||
dmenu_xrm_lookup(xdb, "theme.selBg", "dmenu.selbackground", NULL));
|
||||
dmenu_set_color(SchemeSelHighlight, ColFg,
|
||||
dmenu_xrm_lookup(xdb, "theme.highlight", "theme.accent", "dmenu.selhlforeground"));
|
||||
|
||||
XrmDestroyDatabase(xdb);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
reload_dmenu_theme(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
load_dmenu_xresources();
|
||||
for (i = 0; i < SchemeLast; ++i) {
|
||||
if (!colors[i][ColBg])
|
||||
colors[i][ColBg] = strdup(defaultcolors[i][ColBg]);
|
||||
if (!colors[i][ColFg])
|
||||
colors[i][ColFg] = strdup(defaultcolors[i][ColFg]);
|
||||
}
|
||||
|
||||
if (drw->fonts) {
|
||||
drw_fontset_free(drw->fonts);
|
||||
drw->fonts = NULL;
|
||||
}
|
||||
if (!fonts[0]) {
|
||||
fonts[0] = defaultfonts[0];
|
||||
fonts[1] = defaultfonts[1];
|
||||
}
|
||||
if (!drw_fontset_create(drw, fonts, 2))
|
||||
drw_fontset_create(drw, defaultfonts, 2);
|
||||
|
||||
lrpad = drw->fonts->h / 2;
|
||||
bh = drw->fonts->h + 2;
|
||||
bh = MAX(bh, (int)lineheight);
|
||||
default_lines = MAX(1, (avail_h_cached / (int)bh) - 1);
|
||||
|
||||
for (i = 0; i < SchemeLast; i++) {
|
||||
free(scheme[i]);
|
||||
scheme[i] = drw_scm_create(drw, (const char **)colors[i], 2);
|
||||
}
|
||||
for (i = 0; i < SchemeLast; ++i) {
|
||||
free(colors[i][ColFg]);
|
||||
free(colors[i][ColBg]);
|
||||
colors[i][ColFg] = NULL;
|
||||
colors[i][ColBg] = NULL;
|
||||
}
|
||||
|
||||
if (win) {
|
||||
XSetWindowBackground(dpy, win, scheme[SchemeNorm][ColBg].pixel);
|
||||
XSetWindowBorder(dpy, win, scheme[SchemeSel][ColBg].pixel);
|
||||
}
|
||||
if (menu_active)
|
||||
drawmenu();
|
||||
}
|
||||
|
||||
static void
|
||||
check_dmenu_xres_changed(void)
|
||||
{
|
||||
const char *home = getenv("HOME");
|
||||
char path[512];
|
||||
snprintf(path, sizeof(path), "%s/.Xresources", (home && home[0]) ? home : "/home/user");
|
||||
struct stat st;
|
||||
if (stat(path, &st) == 0) {
|
||||
if (st.st_mtim.tv_sec != last_xres_mtime || st.st_mtim.tv_nsec != last_xres_nsec)
|
||||
reload_dmenu_theme();
|
||||
}
|
||||
}
|
||||
static void
|
||||
show_menu(void)
|
||||
{
|
||||
const int bar_h = 24;
|
||||
int target_y;
|
||||
|
||||
check_dmenu_xres_changed();
|
||||
|
||||
promptw = (prompt && *prompt) ? TEXTW(prompt) - lrpad / 4 : 0;
|
||||
if (lines > 0) {
|
||||
lines = default_lines;
|
||||
@@ -2242,6 +2430,8 @@ handle_fifo_commands(int fifo_fd)
|
||||
if (strcmp(line, "CLOSE") == 0) {
|
||||
if (menu_active)
|
||||
cancel_session();
|
||||
} else if (strcmp(line, "RELOAD_THEME") == 0) {
|
||||
reload_dmenu_theme();
|
||||
} else if (strcmp(line, "OPEN") == 0) {
|
||||
if (active_client_fd >= 0)
|
||||
finish_client_session(1, NULL);
|
||||
@@ -2469,6 +2659,8 @@ setup(int map_immediately)
|
||||
for (j = 0; j < SchemeLast; ++j) {
|
||||
free(colors[j][ColFg]);
|
||||
free(colors[j][ColBg]);
|
||||
colors[j][ColFg] = NULL;
|
||||
colors[j][ColBg] = NULL;
|
||||
}
|
||||
|
||||
clip = XInternAtom(dpy, "CLIPBOARD", False);
|
||||
@@ -2789,6 +2981,8 @@ dmenu_run_main(int argc, char *argv[])
|
||||
die("could not get embedding window attributes: 0x%lx", parentwin);
|
||||
drw = drw_create(dpy, screen, root, wa.width, wa.height);
|
||||
|
||||
load_dmenu_xresources();
|
||||
|
||||
if (!fonts[0]) {
|
||||
fonts[0] = defaultfonts[0];
|
||||
fonts[1] = defaultfonts[1];
|
||||
|
||||
Reference in New Issue
Block a user