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-*-*-*-*-*-*-*" static const char *font = "-*-*-medium-*-*-*-14-*-*-*-*-*-*-*";
#define UNPRESSEDBG "#FFFFFF" static const char *background = "#FFFFFF";
#define UNPRESSEDFG "#2E3436" static const char *foreground = "#2E3436";
#define PRESSEDBG "#3584E4" static const char *selbackground = "#3584E4";
#define PRESSEDFG "#FFFFFF" static const char *selforeground = "#FFFFFF";
#define DECORATIONBG "#CDC7C2" static const char *separator = "#CDC7C2";
#define DECORATIONFG "#E6E6E6" static const char *border = "#E6E6E6";
#define ITEMW 130 static int width = 130;
#define ITEMB 4 static int itemborder = 4;
#define BORDER 1 static int menuborder = 1;
#define SEPARATOR 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. The command is the string that will be output after selecting the item.
.IP .IP
The newline terminates the item specification. 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 .SH EXAMPLES
The following is an script exemplifying the use The following is an script exemplifying the use
.BR xmenu . .BR xmenu .

101
xmenu.c
View File

@ -5,6 +5,7 @@
#include <unistd.h> #include <unistd.h>
#include <X11/Xlib.h> #include <X11/Xlib.h>
#include <X11/Xutil.h> #include <X11/Xutil.h>
#include <X11/Xresource.h>
/* macros */ /* macros */
#define LEN(x) (sizeof (x) / sizeof (x[0])) #define LEN(x) (sizeof (x) / sizeof (x[0]))
@ -16,8 +17,8 @@ enum {ColorFG, ColorBG, ColorLast};
/* draw context structure */ /* draw context structure */
struct DC { struct DC {
unsigned long unpressed[ColorLast]; unsigned long normal[ColorLast];
unsigned long pressed[ColorLast]; unsigned long selected[ColorLast];
unsigned long decoration[ColorLast]; unsigned long decoration[ColorLast];
Drawable d; Drawable d;
@ -66,6 +67,7 @@ struct Menu {
/* function declarations */ /* function declarations */
static unsigned long getcolor(const char *s); static unsigned long getcolor(const char *s);
static void getresources(void);
static void setupdc(void); static void setupdc(void);
static void setupgeom(void); static void setupgeom(void);
static void setupgrab(void); static void setupgrab(void);
@ -128,6 +130,7 @@ main(int argc, char *argv[])
colormap = DefaultColormap(dpy, screen); colormap = DefaultColormap(dpy, screen);
/* setup */ /* setup */
getresources();
setupdc(); setupdc();
setupgeom(); setupgeom();
setupgrab(); setupgrab();
@ -151,6 +154,52 @@ main(int argc, char *argv[])
return 0; 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 */ /* get color from color string */
static unsigned long static unsigned long
getcolor(const char *s) getcolor(const char *s)
@ -167,15 +216,15 @@ static void
setupdc(void) setupdc(void)
{ {
/* get color pixels */ /* get color pixels */
dc.unpressed[ColorBG] = getcolor(UNPRESSEDBG); dc.normal[ColorBG] = getcolor(background);
dc.unpressed[ColorFG] = getcolor(UNPRESSEDFG); dc.normal[ColorFG] = getcolor(foreground);
dc.pressed[ColorBG] = getcolor(PRESSEDBG); dc.selected[ColorBG] = getcolor(selbackground);
dc.pressed[ColorFG] = getcolor(PRESSEDFG); dc.selected[ColorFG] = getcolor(selforeground);
dc.decoration[ColorBG] = getcolor(DECORATIONBG); dc.decoration[ColorBG] = getcolor(separator);
dc.decoration[ColorFG] = getcolor(DECORATIONFG); dc.decoration[ColorFG] = getcolor(border);
/* try to get font */ /* try to get font */
if ((dc.font = XLoadQueryFont(dpy, FONT)) == NULL) if ((dc.font = XLoadQueryFont(dpy, font)) == NULL)
errx(1, "cannot load font"); errx(1, "cannot load font");
dc.fonth = dc.font->ascent + dc.font->descent; dc.fonth = dc.font->ascent + dc.font->descent;
@ -188,11 +237,11 @@ setupdc(void)
static void static void
setupgeom(void) setupgeom(void)
{ {
geom.itemb = ITEMB; geom.itemb = itemborder;
geom.itemh = dc.fonth + ITEMB * 2; geom.itemh = dc.fonth + itemborder * 2;
geom.itemw = ITEMW; geom.itemw = width;
geom.border = BORDER; geom.border = menuborder;
geom.separator = SEPARATOR; geom.separator = separatorsize;
} }
/* grab pointer */ /* grab pointer */
@ -396,10 +445,10 @@ calcmenu(struct Menu *menu)
for (item = menu->parent->list; item->submenu != menu; item = item->next) for (item = menu->parent->list; item->submenu != menu; item = item->next)
; ;
if (screengeom.screenw - (menu->parent->x + menu->parent->w) >= menu->w) if (screengeom.screenw - (menu->parent->x + menu->parent->w + geom.border) >= menu->w)
menu->x = menu->parent->x + menu->parent->w; menu->x = menu->parent->x + menu->parent->w + geom.border;
else if (menu->parent->x > menu->w) else if (menu->parent->x > menu->w + geom.border)
menu->x = menu->parent->x - menu->w; menu->x = menu->parent->x - menu->w - geom.border;
if (screengeom.screenh - (item->y + menu->parent->y) > menu->h) if (screengeom.screenh - (item->y + menu->parent->y) > menu->h)
menu->y = item->y + menu->parent->y; menu->y = item->y + menu->parent->y;
@ -522,12 +571,14 @@ drawmenu(void)
int labelx, labely; int labelx, labely;
/* determine item color */ /* determine item color */
if (item->label == NULL) if (item == menu->selected)
color = dc.decoration; color = dc.selected;
else if (item == menu->selected)
color = dc.pressed;
else else
color = dc.unpressed; color = dc.normal;
/* continue if item is a separator */
if (item->label == NULL)
continue;
/* draw item box */ /* draw item box */
XSetForeground(dpy, dc.gc, color[ColorBG]); XSetForeground(dpy, dc.gc, color[ColorBG]);
@ -536,10 +587,6 @@ drawmenu(void)
XFillRectangle(dpy, menu->pixmap, dc.gc, 0, item->y, XFillRectangle(dpy, menu->pixmap, dc.gc, 0, item->y,
menu->w, item->h); menu->w, item->h);
/* continue if item is a separator */
if (item->label == NULL)
continue;
/* draw item label */ /* draw item label */
labelx = 0 + dc.fonth; labelx = 0 + dc.fonth;
labely = item->y + dc.fonth + geom.itemb; labely = item->y + dc.fonth + geom.itemb;