From f644b8bc229efaa87ac1d441918496e7e24cf29c Mon Sep 17 00:00:00 2001 From: phillbush Date: Sun, 17 May 2020 01:22:21 -0300 Subject: [PATCH] xmenu now supports x resources --- config.h | 22 ++++++------ xmenu.1 | 38 +++++++++++++++++++++ xmenu.c | 101 ++++++++++++++++++++++++++++++++++++++++--------------- 3 files changed, 123 insertions(+), 38 deletions(-) diff --git a/config.h b/config.h index 2dffcc7..6a37a74 100644 --- a/config.h +++ b/config.h @@ -1,11 +1,11 @@ -#define FONT "-*-*-medium-*-*-*-14-*-*-*-*-*-*-*" -#define UNPRESSEDBG "#FFFFFF" -#define UNPRESSEDFG "#2E3436" -#define PRESSEDBG "#3584E4" -#define PRESSEDFG "#FFFFFF" -#define DECORATIONBG "#CDC7C2" -#define DECORATIONFG "#E6E6E6" -#define ITEMW 130 -#define ITEMB 4 -#define BORDER 1 -#define SEPARATOR 1 +static const char *font = "-*-*-medium-*-*-*-14-*-*-*-*-*-*-*"; +static const char *background = "#FFFFFF"; +static const char *foreground = "#2E3436"; +static const char *selbackground = "#3584E4"; +static const char *selforeground = "#FFFFFF"; +static const char *separator = "#CDC7C2"; +static const char *border = "#E6E6E6"; +static int width = 130; +static int itemborder = 4; +static int menuborder = 1; +static int separatorsize = 1; diff --git a/xmenu.1 b/xmenu.1 index 0e01c44..de61a9e 100644 --- a/xmenu.1 +++ b/xmenu.1 @@ -37,6 +37,44 @@ separating the item above from the item below. The command is the string that will be output after selecting the item. .IP The newline terminates the item specification. +.SH RESOURCES +.B +xmenu +understands the following X resources. +.TP +.B xmenu.font +The font in which the labels should be drawn. +.TP +.B xmenu.background +The background color of non-selected itens in the menu. +.TP +.B xmenu.foreground +The color of the label text of non-selected itens in the menu. +.TP +.B xmenu.selbackground +The background color of selected itens in the menu. +.TP +.B xmenu.selforeground +The color of the label text of selected itens in the menu. +.TP +.B xmenu.border +The color of the border around the menu. +.TP +.B xmenu.separator +The color of the separator between itens in the menu. +.TP +.B xmenu.width +The minimum width, in pixels, of the items in the menu. +.TP +.B xmenu.itemborder +The size in pixels of the border around the label text in items in the menu. +.TP +.B xmenu.menuborder +The size in pixels of the border around the menu. +.TP +.B xmenu.separatorsize +The size in pixels of the item separator. + .SH EXAMPLES The following is an script exemplifying the use .BR xmenu . diff --git a/xmenu.c b/xmenu.c index 41303cc..0afaaa9 100644 --- a/xmenu.c +++ b/xmenu.c @@ -5,6 +5,7 @@ #include #include #include +#include /* macros */ #define LEN(x) (sizeof (x) / sizeof (x[0])) @@ -16,8 +17,8 @@ enum {ColorFG, ColorBG, ColorLast}; /* draw context structure */ struct DC { - unsigned long unpressed[ColorLast]; - unsigned long pressed[ColorLast]; + unsigned long normal[ColorLast]; + unsigned long selected[ColorLast]; unsigned long decoration[ColorLast]; Drawable d; @@ -66,6 +67,7 @@ struct Menu { /* function declarations */ static unsigned long getcolor(const char *s); +static void getresources(void); static void setupdc(void); static void setupgeom(void); static void setupgrab(void); @@ -128,6 +130,7 @@ main(int argc, char *argv[]) colormap = DefaultColormap(dpy, screen); /* setup */ + getresources(); setupdc(); setupgeom(); setupgrab(); @@ -151,6 +154,52 @@ main(int argc, char *argv[]) return 0; } +/* read xrdb for configuration options */ +static void +getresources(void) +{ + char *xrm; + long n; + + XrmInitialize(); + if ((xrm = XResourceManagerString(dpy))) { + char *type; + XrmDatabase xdb; + XrmValue xval; + + xdb = XrmGetStringDatabase(xrm); + + if (XrmGetResource(xdb, "xmenu.menuborder", "*", &type, &xval) == True) + if ((n = strtol(xval.addr, NULL, 10)) > 0) + menuborder = n; + if (XrmGetResource(xdb, "xmenu.separatorsize", "*", &type, &xval) == True) + if ((n = strtol(xval.addr, NULL, 10)) > 0) + separatorsize = n; + if (XrmGetResource(xdb, "xmenu.itemborder", "*", &type, &xval) == True) + if ((n = strtol(xval.addr, NULL, 10)) > 0) + itemborder = n; + if (XrmGetResource(xdb, "xmenu.width", "*", &type, &xval) == True) + if ((n = strtol(xval.addr, NULL, 10)) > 0) + width = n; + if (XrmGetResource(xdb, "xmenu.background", "*", &type, &xval) == True) + background = strdup(xval.addr); + if (XrmGetResource(xdb, "xmenu.foreground", "*", &type, &xval) == True) + foreground = strdup(xval.addr); + if (XrmGetResource(xdb, "xmenu.selbackground", "*", &type, &xval) == True) + selbackground = strdup(xval.addr); + if (XrmGetResource(xdb, "xmenu.selforeground", "*", &type, &xval) == True) + selforeground = strdup(xval.addr); + if (XrmGetResource(xdb, "xmenu.separator", "*", &type, &xval) == True) + separator = strdup(xval.addr); + if (XrmGetResource(xdb, "xmenu.border", "*", &type, &xval) == True) + border = strdup(xval.addr); + if (XrmGetResource(xdb, "xmenu.font", "*", &type, &xval) == True) + font = strdup(xval.addr); + + XrmDestroyDatabase(xdb); + } +} + /* get color from color string */ static unsigned long getcolor(const char *s) @@ -167,15 +216,15 @@ static void setupdc(void) { /* get color pixels */ - dc.unpressed[ColorBG] = getcolor(UNPRESSEDBG); - dc.unpressed[ColorFG] = getcolor(UNPRESSEDFG); - dc.pressed[ColorBG] = getcolor(PRESSEDBG); - dc.pressed[ColorFG] = getcolor(PRESSEDFG); - dc.decoration[ColorBG] = getcolor(DECORATIONBG); - dc.decoration[ColorFG] = getcolor(DECORATIONFG); + dc.normal[ColorBG] = getcolor(background); + dc.normal[ColorFG] = getcolor(foreground); + dc.selected[ColorBG] = getcolor(selbackground); + dc.selected[ColorFG] = getcolor(selforeground); + dc.decoration[ColorBG] = getcolor(separator); + dc.decoration[ColorFG] = getcolor(border); /* try to get font */ - if ((dc.font = XLoadQueryFont(dpy, FONT)) == NULL) + if ((dc.font = XLoadQueryFont(dpy, font)) == NULL) errx(1, "cannot load font"); dc.fonth = dc.font->ascent + dc.font->descent; @@ -188,11 +237,11 @@ setupdc(void) static void setupgeom(void) { - geom.itemb = ITEMB; - geom.itemh = dc.fonth + ITEMB * 2; - geom.itemw = ITEMW; - geom.border = BORDER; - geom.separator = SEPARATOR; + geom.itemb = itemborder; + geom.itemh = dc.fonth + itemborder * 2; + geom.itemw = width; + geom.border = menuborder; + geom.separator = separatorsize; } /* grab pointer */ @@ -396,10 +445,10 @@ calcmenu(struct Menu *menu) for (item = menu->parent->list; item->submenu != menu; item = item->next) ; - if (screengeom.screenw - (menu->parent->x + menu->parent->w) >= menu->w) - menu->x = menu->parent->x + menu->parent->w; - else if (menu->parent->x > menu->w) - menu->x = menu->parent->x - menu->w; + if (screengeom.screenw - (menu->parent->x + menu->parent->w + geom.border) >= menu->w) + menu->x = menu->parent->x + menu->parent->w + geom.border; + else if (menu->parent->x > menu->w + geom.border) + menu->x = menu->parent->x - menu->w - geom.border; if (screengeom.screenh - (item->y + menu->parent->y) > menu->h) menu->y = item->y + menu->parent->y; @@ -522,12 +571,14 @@ drawmenu(void) int labelx, labely; /* determine item color */ - if (item->label == NULL) - color = dc.decoration; - else if (item == menu->selected) - color = dc.pressed; + if (item == menu->selected) + color = dc.selected; else - color = dc.unpressed; + color = dc.normal; + + /* continue if item is a separator */ + if (item->label == NULL) + continue; /* draw item box */ XSetForeground(dpy, dc.gc, color[ColorBG]); @@ -536,10 +587,6 @@ drawmenu(void) XFillRectangle(dpy, menu->pixmap, dc.gc, 0, item->y, menu->w, item->h); - /* continue if item is a separator */ - if (item->label == NULL) - continue; - /* draw item label */ labelx = 0 + dc.fonth; labely = item->y + dc.fonth + geom.itemb;