shod

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 5440d9166a67ff7f69efda1a9e3e3ebaa6255034
parent c2c4fca49a16ab20986e905d793aa484ca662abf
Author: Lucas de Sena <lucas@seninha.org>
Date:   Sat,  8 Apr 2023 15:12:24 -0300

use quarks for querying resources

Diffstat:
Mshod.c | 28++++++++++++++++++++++++----
Mshod.h | 45+++++++++++++++++++++++++++++++++++++++++++++
Mxdraw.c | 114++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Mxevents.c | 199++++++++++++++++++++++++++++++++++++++++++-------------------------------------
Mxutil.c | 13+++++++++++++
Mxutil.h | 1+
6 files changed, 249 insertions(+), 151 deletions(-)

diff --git a/shod.c b/shod.c @@ -183,6 +183,28 @@ initcursors(void) wm.cursors[CURSOR_PIRATE] = XCreateFontCursor(dpy, XC_pirate); } +static void +initxrm(void) +{ + static struct { + const char *class, *name; + } resourceids[NRESOURCES] = { +#define X(res, s1, s2) [res] = { .class = s1, .name = s2, }, + RESOURCES +#undef X + }; + int i; + + XrmInitialize(); + wm.application.class = XrmPermStringToQuark("Shod"); + wm.application.name = XrmPermStringToQuark("shod"); + for (i = 0; i < NRESOURCES; i++) { + wm.resources[i].class = XrmPermStringToQuark(resourceids[i].class); + wm.resources[i].name = XrmPermStringToQuark(resourceids[i].name); + } + setresources(XResourceManagerString(dpy)); +} + /* set up root window */ static void initroot(void) @@ -324,7 +346,7 @@ int main(int argc, char *argv[]) { XEvent ev; - char *filename, *wmname, *xrm; + char *filename, *wmname; if (!setlocale(LC_ALL, "") || !XSupportsLocale()) warnx("warning: no locale support"); @@ -332,9 +354,6 @@ main(int argc, char *argv[]) checkotherwm(); moninit(); xinitvisual(); - XrmInitialize(); - xrm = XResourceManagerString(dpy); - setresources(xrm); clientswa.colormap = colormap; clientswa.border_pixel = BlackPixel(dpy, screen); clientswa.background_pixel = BlackPixel(dpy, screen); @@ -364,6 +383,7 @@ main(int argc, char *argv[]) initsignal(); initcursors(); initatoms(); + initxrm(); initroot(); initdummywindows(); initdock(); diff --git a/shod.h b/shod.h @@ -27,6 +27,43 @@ } \ } +#define RESOURCES \ + /* CLASS NAME */\ + X(RES_ANY, "?", "?" )\ + X(RES_TYPE, "Type", "type" )\ + X(RES_STATE, "State", "state" )\ + X(RES_DOCK_POS, "Dockpos", "dockpos" )\ + X(RES_FACE_NAME, "FaceName", "faceName" )\ + X(RES_FOREGROUND, "Foreground", "foreground" )\ + X(RES_DOCK_BACKGROUND, "DockBackground", "dockBackground" )\ + X(RES_DOCK_BORDER, "DockBorder", "dockBorder" )\ + X(RES_ACTIVE_BG, "ActiveBackground", "activeBackground" )\ + X(RES_ACTIVE_TOP, "ActiveTopShadowColor", "activeTopShadowColor" )\ + X(RES_ACTIVE_BOT, "ActiveBottomShadowColor", "activeBottomShadowColor" )\ + X(RES_INACTIVE_BG, "InactiveBackground", "inactiveBackground" )\ + X(RES_INACTIVE_TOP, "InactiveTopShadowColor", "inactiveTopShadowColor" )\ + X(RES_INACTIVE_BOT, "InactiveBottomShadowColor", "inactiveBottomShadowColor" )\ + X(RES_URGENT_BG, "UrgentBackground", "urgentBackground" )\ + X(RES_URGENT_TOP, "UrgentTopShadowColor", "urgentTopShadowColor" )\ + X(RES_URGENT_BOT, "UrgentBottomShadowColor", "urgentBottomShadowColor" )\ + X(RES_BORDER_WIDTH, "BorderWidth", "borderWidth" )\ + X(RES_SHADOW_WIDTH, "ShadowThickness", "shadowThickness" )\ + X(RES_TITLE_WIDTH, "TitleWidth", "titleWidth" )\ + X(RES_DOCK_WIDTH, "DockWidth", "dockWidth" )\ + X(RES_DOCK_SPACE, "DockSpace", "dockSpace" )\ + X(RES_DOCK_GRAVITY, "DockGravity", "dockGravity" )\ + X(RES_NOTIFY_GAP, "NotifGap", "notifGap" )\ + X(RES_NOTIFY_GRAVITY, "NotifGravity", "notifGravity" )\ + X(RES_NDESKTOPS, "NumOfDesktops", "numOfDesktops" )\ + X(RES_SNAP_PROXIMITY, "SnapProximity", "snapProximity" ) + +enum Resource { +#define X(res, class, name) res, + RESOURCES + NRESOURCES +#undef X +}; + enum { /* border array indices */ BORDER_N, @@ -541,6 +578,14 @@ struct WM { int nclients; /* total number of container windows */ /* + * Resources + */ + struct { + XrmClass class; + XrmName name; + } application, resources[NRESOURCES]; + + /* * Xrandr information. */ int xrandr; /* whether Xrandr is being used */ diff --git a/xdraw.c b/xdraw.c @@ -784,73 +784,81 @@ cleantheme(void) XFreeGC(dpy, gc); } +static char * +queryrdb(int res) +{ + XrmClass class[] = { wm.application.class, wm.resources[res].class, NULLQUARK }; + XrmName name[] = { wm.application.name, wm.resources[res].name, NULLQUARK }; + + return getresource(xdb, class, name); +} + void setresources(char *xrm) { long n; - char *type; - XrmValue xval; + char *value; if (xrm == NULL || (xdb = XrmGetStringDatabase(xrm)) == NULL) return; - if (XrmGetResource(xdb, "shod.faceName", "*", &type, &xval) == True) - config.font = xval.addr; - if (XrmGetResource(xdb, "shod.foreground", "*", &type, &xval) == True) - config.foreground = xval.addr; - - if (XrmGetResource(xdb, "shod.dockBackground", "*", &type, &xval) == True) - config.dockcolors[COLOR_DEF] = xval.addr; - if (XrmGetResource(xdb, "shod.dockBorder", "*", &type, &xval) == True) - config.dockcolors[COLOR_ALT] = xval.addr; - - if (XrmGetResource(xdb, "shod.activeBackground", "*", &type, &xval) == True) - config.bordercolors[FOCUSED][COLOR_MID] = xval.addr; - if (XrmGetResource(xdb, "shod.activeTopShadowColor", "*", &type, &xval) == True) - config.bordercolors[FOCUSED][COLOR_LIGHT] = xval.addr; - if (XrmGetResource(xdb, "shod.activeBottomShadowColor", "*", &type, &xval) == True) - config.bordercolors[FOCUSED][COLOR_DARK] = xval.addr; - - if (XrmGetResource(xdb, "shod.inactiveBackground", "*", &type, &xval) == True) - config.bordercolors[UNFOCUSED][COLOR_MID] = xval.addr; - if (XrmGetResource(xdb, "shod.inactiveTopShadowColor", "*", &type, &xval) == True) - config.bordercolors[UNFOCUSED][COLOR_LIGHT] = xval.addr; - if (XrmGetResource(xdb, "shod.inactiveBottomShadowColor", "*", &type, &xval) == True) - config.bordercolors[UNFOCUSED][COLOR_DARK] = xval.addr; - - if (XrmGetResource(xdb, "shod.urgentBackground", "*", &type, &xval) == True) - config.bordercolors[URGENT][COLOR_MID] = xval.addr; - if (XrmGetResource(xdb, "shod.urgentTopShadowColor", "*", &type, &xval) == True) - config.bordercolors[URGENT][COLOR_LIGHT] = xval.addr; - if (XrmGetResource(xdb, "shod.urgentBottomShadowColor", "*", &type, &xval) == True) - config.bordercolors[URGENT][COLOR_DARK] = xval.addr; - - if (XrmGetResource(xdb, "shod.borderWidth", "*", &type, &xval) == True) - if ((n = strtol(xval.addr, NULL, 10)) > 0 && n < 100) + if ((value = queryrdb(RES_FACE_NAME)) != NULL) + config.font = value; + if ((value = queryrdb(RES_FOREGROUND)) != NULL) + config.foreground = value; + + if ((value = queryrdb(RES_DOCK_BACKGROUND)) != NULL) + config.dockcolors[COLOR_DEF] = value; + if ((value = queryrdb(RES_DOCK_BORDER)) != NULL) + config.dockcolors[COLOR_ALT] = value; + + if ((value = queryrdb(RES_ACTIVE_BG)) != NULL) + config.bordercolors[FOCUSED][COLOR_MID] = value; + if ((value = queryrdb(RES_ACTIVE_TOP)) != NULL) + config.bordercolors[FOCUSED][COLOR_LIGHT] = value; + if ((value = queryrdb(RES_ACTIVE_BOT)) != NULL) + config.bordercolors[FOCUSED][COLOR_DARK] = value; + + if ((value = queryrdb(RES_INACTIVE_BG)) != NULL) + config.bordercolors[UNFOCUSED][COLOR_MID] = value; + if ((value = queryrdb(RES_INACTIVE_TOP)) != NULL) + config.bordercolors[UNFOCUSED][COLOR_LIGHT] = value; + if ((value = queryrdb(RES_INACTIVE_BOT)) != NULL) + config.bordercolors[UNFOCUSED][COLOR_DARK] = value; + + if ((value = queryrdb(RES_URGENT_BG)) != NULL) + config.bordercolors[URGENT][COLOR_MID] = value; + if ((value = queryrdb(RES_URGENT_TOP)) != NULL) + config.bordercolors[URGENT][COLOR_LIGHT] = value; + if ((value = queryrdb(RES_URGENT_BOT)) != NULL) + config.bordercolors[URGENT][COLOR_DARK] = value; + + if ((value = queryrdb(RES_BORDER_WIDTH)) != NULL) + if ((n = strtol(value, NULL, 10)) > 0 && n < 100) config.borderwidth = n; - if (XrmGetResource(xdb, "shod.shadowThickness", "*", &type, &xval) == True) - if ((n = strtol(xval.addr, NULL, 10)) > 0 && n < 100) + if ((value = queryrdb(RES_SHADOW_WIDTH)) != NULL) + if ((n = strtol(value, NULL, 10)) > 0 && n < 100) config.shadowthickness = n; - if (XrmGetResource(xdb, "shod.titleWidth", "*", &type, &xval) == True) - if ((n = strtol(xval.addr, NULL, 10)) > 0 && n < 100) + if ((value = queryrdb(RES_TITLE_WIDTH)) != NULL) + if ((n = strtol(value, NULL, 10)) > 0 && n < 100) config.titlewidth = n; - if (XrmGetResource(xdb, "shod.dockWidth", "*", &type, &xval) == True) - if ((n = strtol(xval.addr, NULL, 10)) > 0) + if ((value = queryrdb(RES_DOCK_WIDTH)) != NULL) + if ((n = strtol(value, NULL, 10)) > 0) config.dockwidth = n; - if (XrmGetResource(xdb, "shod.dockSpace", "*", &type, &xval) == True) - if ((n = strtol(xval.addr, NULL, 10)) > 0) + if ((value = queryrdb(RES_DOCK_SPACE)) != NULL) + if ((n = strtol(value, NULL, 10)) > 0) config.dockspace = n; - if (XrmGetResource(xdb, "shod.dockGravity", "*", &type, &xval) == True) - config.dockgravity = xval.addr; - if (XrmGetResource(xdb, "shod.notifGap", "*", &type, &xval) == True) - if ((n = strtol(xval.addr, NULL, 10)) > 0) + if ((value = queryrdb(RES_DOCK_GRAVITY)) != NULL) + config.dockgravity = value; + if ((value = queryrdb(RES_NOTIFY_GAP)) != NULL) + if ((n = strtol(value, NULL, 10)) > 0) config.notifgap = n; - if (XrmGetResource(xdb, "shod.notifGravity", "*", &type, &xval) == True) - config.notifgravity = xval.addr; - if (XrmGetResource(xdb, "shod.numOfDesktops", "*", &type, &xval) == True) - if ((n = strtol(xval.addr, NULL, 10)) > 0 && n < 100) + if ((value = queryrdb(RES_NOTIFY_GRAVITY)) != NULL) + config.notifgravity = value; + if ((value = queryrdb(RES_NDESKTOPS)) != NULL) + if ((n = strtol(value, NULL, 10)) > 0 && n < 100) config.ndesktops = n; - if (XrmGetResource(xdb, "shod.snapProximity", "*", &type, &xval) == True) - if ((n = strtol(xval.addr, NULL, 10)) >= 0 && n < 100) + if ((value = queryrdb(RES_SNAP_PROXIMITY)) != NULL) + if ((n = strtol(value, NULL, 10)) >= 0 && n < 100) config.snap = n; } diff --git a/xevents.c b/xevents.c @@ -324,27 +324,27 @@ getstate(Window w) return result; } -/* get text property from window; return `Success` on success */ -static int -gettextprop(Window win, Atom atom, char *buf, size_t size) +static char * +gettextprop(Window win, Atom atom) { - XTextProperty tprop; + XTextProperty tprop = { .value = NULL }; int count; char **list = NULL; + char *s = NULL; - if (buf == NULL || size == 0) - return BadLength; - buf[0] = '\0'; - if (!XGetTextProperty(dpy, win, &tprop, atom) || tprop.nitems == 0) - return BadAlloc; - if (XmbTextPropertyToTextList(dpy, &tprop, &list, &count) != Success || - count < 1 || list == NULL || *list == NULL) - return BadAlloc; - strncpy(buf, *list, size - 1); - buf[size - 1] = '\0'; + if (!XGetTextProperty(dpy, win, &tprop, atom)) + goto error; + if (tprop.nitems == 0) + goto error; + if (XmbTextPropertyToTextList(dpy, &tprop, &list, &count) != Success) + goto error; + if (count < 1 || list == NULL || *list == NULL) + goto error; + s = strdup(list[0]); +error: XFreeStringList(list); XFree(tprop.value); - return Success; + return s; } /* get motif/GNUstep hints from window; return -1 on error */ @@ -376,27 +376,26 @@ getextrahints(Window win, Atom prop, unsigned long nmemb, size_t size, void *hin return ret; } +#define STRCMP(a, b) ((a) != NULL && (b) != NULL && strcmp((a), (b)) == 0) + /* get window info based on its type */ static int getwintype(Window *win_ret, Window *leader, struct Tab **tab, int *state, XRectangle *rect) { /* rules for identifying windows */ - enum { CLASS = 0, INSTANCE = 1, ROLE = 2 }; - char *rule[] = { "_", "_", "_" }; - + enum { I_APP, I_CLASS, I_INSTANCE, I_ROLE, I_RESOURCE, I_NULL, I_LAST }; + XrmClass class[I_LAST]; + XrmName name[I_LAST]; struct MwmHints mwmhints = { 0 }; struct GNUHints gnuhints = { 0 }; - XClassHint classh; + XClassHint classh = { .res_class = NULL, .res_name = NULL }; XWMHints *wmhints; - XrmValue xval; Window win; Atom prop; size_t i; long n; int type, isdockapp, pos; - char *ds; - char buf[NAMEMAXLEN]; - char role[NAMEMAXLEN]; + char *role, *value; pos = 0; win = *win_ret; @@ -405,21 +404,16 @@ getwintype(Window *win_ret, Window *leader, struct Tab **tab, int *state, XRecta type = TYPE_UNKNOWN; classh.res_class = NULL; classh.res_name = NULL; - if (gettextprop(win, atoms[WM_WINDOW_ROLE], role, NAMEMAXLEN) == Success) - rule[ROLE] = role; - if (XGetClassHint(dpy, win, &classh)) { - rule[CLASS] = classh.res_class; - rule[INSTANCE] = classh.res_name; - } - /* get window state requested by application */ *state = getwinstate(win); /* get window type (and other info) from default (hardcoded) rules */ + role = gettextprop(win, atoms[WM_WINDOW_ROLE]); + XGetClassHint(dpy, win, &classh); for (i = 0; config.rules[i].class != NULL || config.rules[i].instance != NULL || config.rules[i].role != NULL; i++) { - if ((config.rules[i].class == NULL || strcmp(config.rules[i].class, rule[CLASS]) == 0) - && (config.rules[i].instance == NULL || strcmp(config.rules[i].instance, rule[INSTANCE]) == 0) - && (config.rules[i].role == NULL || strcmp(config.rules[i].role, rule[ROLE]) == 0)) { + if ((config.rules[i].class == NULL || STRCMP(config.rules[i].class, classh.res_class)) + && (config.rules[i].instance == NULL || STRCMP(config.rules[i].instance, classh.res_name)) + && (config.rules[i].role == NULL || STRCMP(config.rules[i].role, role))) { if (config.rules[i].type != TYPE_MENU && config.rules[i].type != TYPE_DIALOG) { type = config.rules[i].type; } @@ -429,69 +423,86 @@ getwintype(Window *win_ret, Window *leader, struct Tab **tab, int *state, XRecta } } - /* get window type (and other info) from X resources */ - if (xdb != NULL) { - /* check for window type */ - (void)snprintf(buf, NAMEMAXLEN, "shod.%s.%s.%s.type", rule[CLASS], rule[INSTANCE], rule[ROLE]); - if (XrmGetResource(xdb, buf, "*", &ds, &xval) == True && xval.addr != NULL) { - if (strcasecmp(xval.addr, "DESKTOP") == 0) { - type = TYPE_DESKTOP; - } else if (strcasecmp(xval.addr, "DOCKAPP") == 0) { - type = TYPE_DOCKAPP; - } else if (strcasecmp(xval.addr, "PROMPT") == 0) { - type = TYPE_PROMPT; - } else if (strcasecmp(xval.addr, "NORMAL") == 0) { - type = TYPE_NORMAL; - } - } + /* convert strings to quarks for xrm */ + class[I_NULL] = name[I_NULL] = NULLQUARK; + class[I_APP] = wm.application.class; + name[I_APP] = wm.application.name; + if (classh.res_class != NULL) + class[I_CLASS] = name[I_CLASS] = XrmStringToQuark(classh.res_class); + else + class[I_CLASS] = name[I_CLASS] = wm.resources[RES_ANY].name; + if (classh.res_name != NULL) + class[I_INSTANCE] = name[I_INSTANCE] = XrmStringToQuark(classh.res_name); + else + class[I_INSTANCE] = name[I_INSTANCE] = wm.resources[RES_ANY].name; + if (role != NULL) + class[I_ROLE] = name[I_ROLE] = XrmStringToQuark(role); + else + class[I_ROLE] = name[I_ROLE] = wm.resources[RES_ANY].name; + free(role); + XFree(classh.res_class); + XFree(classh.res_name); - /* check for window state */ - (void)snprintf(buf, NAMEMAXLEN, "shod.%s.%s.%s.state", rule[CLASS], rule[INSTANCE], rule[ROLE]); - if (XrmGetResource(xdb, buf, "*", &ds, &xval) == True && xval.addr != NULL) { - *state = 0; - if (strcasestr(xval.addr, "above") != NULL) { - *state |= ABOVE; - } - if (strcasestr(xval.addr, "below") != NULL) { - *state |= BELOW; - } - if (strcasestr(xval.addr, "fullscreen") != NULL) { - *state |= FULLSCREEN; - } - if (strcasestr(xval.addr, "maximized") != NULL) { - *state |= MAXIMIZED; - } - if (strcasestr(xval.addr, "minimized") != NULL) { - *state |= MINIMIZED; - } - if (strcasestr(xval.addr, "shaded") != NULL) { - *state |= SHADED; - } - if (strcasestr(xval.addr, "sticky") != NULL) { - *state |= STICKY; - } - if (strcasestr(xval.addr, "extend") != NULL) { - *state |= EXTEND; - } - if (strcasestr(xval.addr, "shrunk") != NULL) { - *state |= SHRUNK; - } - if (strcasestr(xval.addr, "resized") != NULL) { - *state |= RESIZED; - } + /* get window type from X resources */ + class[I_RESOURCE] = wm.resources[RES_TYPE].class; + name[I_RESOURCE] = wm.resources[RES_TYPE].name; + if ((value = getresource(xdb, class, name)) != NULL) { + if (strcasecmp(value, "DESKTOP") == 0) { + type = TYPE_DESKTOP; + } else if (strcasecmp(value, "DOCKAPP") == 0) { + type = TYPE_DOCKAPP; + } else if (strcasecmp(value, "PROMPT") == 0) { + type = TYPE_PROMPT; + } else if (strcasecmp(value, "NORMAL") == 0) { + type = TYPE_NORMAL; } + } - /* check for dockapp position */ - (void)snprintf(buf, NAMEMAXLEN, "shod.%s.%s.%s.dockpos", rule[CLASS], rule[INSTANCE], rule[ROLE]); - if (XrmGetResource(xdb, buf, "*", &ds, &xval) == True) { - if ((n = strtol(xval.addr, NULL, 10)) >= 0 && n < INT_MAX) { - pos = n; - } + /* get window state from X resources */ + class[I_RESOURCE] = wm.resources[RES_STATE].class; + name[I_RESOURCE] = wm.resources[RES_STATE].name; + if ((value = getresource(xdb, class, name)) != NULL) { + *state = 0; + if (strcasestr(value, "above") != NULL) { + *state |= ABOVE; + } + if (strcasestr(value, "below") != NULL) { + *state |= BELOW; + } + if (strcasestr(value, "fullscreen") != NULL) { + *state |= FULLSCREEN; + } + if (strcasestr(value, "maximized") != NULL) { + *state |= MAXIMIZED; + } + if (strcasestr(value, "minimized") != NULL) { + *state |= MINIMIZED; + } + if (strcasestr(value, "shaded") != NULL) { + *state |= SHADED; + } + if (strcasestr(value, "sticky") != NULL) { + *state |= STICKY; + } + if (strcasestr(value, "extend") != NULL) { + *state |= EXTEND; + } + if (strcasestr(value, "shrunk") != NULL) { + *state |= SHRUNK; + } + if (strcasestr(value, "resized") != NULL) { + *state |= RESIZED; } } - XFree(classh.res_class); - XFree(classh.res_name); + /* get dockapp position from X resources */ + class[I_RESOURCE] = wm.resources[RES_DOCK_POS].class; + name[I_RESOURCE] = wm.resources[RES_DOCK_POS].name; + if ((value = getresource(xdb, class, name)) != NULL) { + if ((n = strtol(value, NULL, 10)) >= 0 && n < INT_MAX) { + pos = n; + } + } /* we already got the type of the window, return */ if (type != TYPE_UNKNOWN) @@ -1749,19 +1760,19 @@ static void xeventpropertynotify(XEvent *e) { XPropertyEvent *ev; - XTextProperty prop; struct Container *c; struct Object *obj; struct Tab *tab; struct Menu *menu; + char *str; ev = &e->xproperty; if (ev->window == root && ev->atom == XA_RESOURCE_MANAGER) { - if (!XGetTextProperty(dpy, root, &prop, XA_RESOURCE_MANAGER)) + if ((str = gettextprop(root, XA_RESOURCE_MANAGER)) == NULL) return; XrmDestroyDatabase(xdb); - setresources(prop.value); - XFree(prop.value); + setresources(str); + free(str); cleantheme(); inittheme(); TAILQ_FOREACH(c, &wm.focusq, entry) diff --git a/xutil.c b/xutil.c @@ -112,6 +112,19 @@ estrndup(const char *s, size_t maxlen) return p; } +char * +getresource(XrmDatabase xdb, XrmClass *class, XrmName *name) +{ + XrmRepresentation tmp; + XrmValue xval; + + if (xdb == NULL) + return NULL; + if (XrmQGetResource(xdb, name, class, &tmp, &xval)) + return xval.addr; + return NULL; +} + unsigned long getwinsprop(Window win, Atom prop, Window **wins) { diff --git a/xutil.h b/xutil.h @@ -102,3 +102,4 @@ void initatoms(void); void initatom(int atomenum); void xinit(void); void xinitvisual(void); +char *getresource(XrmDatabase xdb, XrmClass *class, XrmName *name);