xmenu now supports x resources

This commit is contained in:
phillbush 2020-05-17 01:22:21 -03:00
parent dddba407f4
commit f644b8bc22
3 changed files with 123 additions and 38 deletions

View File

@ -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;

38
xmenu.1
View File

@ -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 .

101
xmenu.c
View File

@ -5,6 +5,7 @@
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xresource.h>
/* 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;