xmenu now supports x resources
authorphillbush <phillbush@cock.li>
Sun, 17 May 2020 04:22:21 +0000 (01:22 -0300)
committerphillbush <phillbush@cock.li>
Sun, 17 May 2020 04:22:21 +0000 (01:22 -0300)
config.h
xmenu.1
xmenu.c

index 2dffcc7..6a37a74 100644 (file)
--- 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 (file)
--- 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 (file)
--- a/xmenu.c
+++ b/xmenu.c
@@ -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;