added the -i option
authorphillbush <phillbush@cock.li>
Thu, 16 Jul 2020 01:57:59 +0000 (22:57 -0300)
committerphillbush <phillbush@cock.li>
Thu, 16 Jul 2020 01:57:59 +0000 (22:57 -0300)
Widths and x positions no more depend on item->h.

config.h
xmenu.1
xmenu.c
xmenu.h

index 27e9c11..d6a8807 100644 (file)
--- a/config.h
+++ b/config.h
@@ -17,12 +17,18 @@ static struct Config config = {
        .separator_pixels = 3,      /* space around separator */
        .gap_pixels = 0,            /* gap between menus */
 
        .separator_pixels = 3,      /* space around separator */
        .gap_pixels = 0,            /* gap between menus */
 
-       /* the variables below cannot be set by X resources */
+       /*
+        * The variables below cannot be set by X resources.
+        * Their values must be less than .height_pixels.
+        */
 
        /* geometry of the right-pointing isoceles triangle for submenus */
        .triangle_width = 3,
        .triangle_height = 7,
 
 
        /* geometry of the right-pointing isoceles triangle for submenus */
        .triangle_width = 3,
        .triangle_height = 7,
 
-       /* padding of the area around the icon */
-       .iconpadding = 4,
+       /* the icon size is equal to .height_pixels - .iconpadding * 2 */
+       .iconpadding = 2,
+
+       /* area around the icon, the triangle and the separator */
+       .horzpadding = 8,
 };
 };
diff --git a/xmenu.1 b/xmenu.1
index 470b251..73a95f6 100644 (file)
--- a/xmenu.1
+++ b/xmenu.1
@@ -3,7 +3,7 @@
 xmenu \- menu utility for X
 .SH SYNOPSIS
 .B xmenu
 xmenu \- menu utility for X
 .SH SYNOPSIS
 .B xmenu
-.RB [ \-w ]
+.RB [ \-iw ]
 .RI [ title ]
 .SH DESCRIPTION
 .B xmenu
 .RI [ title ]
 .SH DESCRIPTION
 .B xmenu
@@ -14,9 +14,19 @@ and outputs the item selected to stdout.
 .PP
 The options are as follows:
 .TP
 .PP
 The options are as follows:
 .TP
+.B -i
+Disable icons.
+.B xmenu
+allocates a space at the left side of the menu for the icons;
+if there is no icon, then this space will be blank.
+Setting the
+.B -i
+option removes this space, making the menu narrower.
+.TP
 .B -w
 Asks the window manager to draw a border around the menus.
 .B -w
 Asks the window manager to draw a border around the menus.
-This option may be buggy in some window managers, specially tiled ones.
+This option may be buggy in some window managers,
+specially tiled ones that do not respect window hints.
 .PP
 Each item read from stdin has the following format:
 .IP
 .PP
 Each item read from stdin has the following format:
 .IP
diff --git a/xmenu.c b/xmenu.c
index 92b1581..af0f801 100644 (file)
--- a/xmenu.c
+++ b/xmenu.c
@@ -21,7 +21,7 @@
 static void ealloccolor(const char *s, XftColor *color);
 static void initresources(void);
 static void initdc(void);
 static void ealloccolor(const char *s, XftColor *color);
 static void initresources(void);
 static void initdc(void);
-static void initscreengeom(void);
+static void initconfig(void);
 static void initatoms(void);
 
 /* structure builders, and their helper routines */
 static void initatoms(void);
 
 /* structure builders, and their helper routines */
@@ -31,10 +31,10 @@ static struct Menu *buildmenutree(unsigned level, const char *label, const char
 static struct Menu *parsestdin(void);
 
 /* image loader */
 static struct Menu *parsestdin(void);
 
 /* image loader */
-static Imlib_Image loadicon(const char *file, int size);
+static Imlib_Image loadicon(const char *file);
 
 /* structure setters, and their helper routines */
 
 /* structure setters, and their helper routines */
-static void setupmenusize(struct Menu *menu);
+static void setupitems(struct Menu *menu);
 static void setupmenupos(struct Menu *menu);
 static void setupmenu(struct Menu *menu, XClassHint *classh);
 
 static void setupmenupos(struct Menu *menu);
 static void setupmenu(struct Menu *menu, XClassHint *classh);
 
@@ -79,6 +79,7 @@ static Atom netatom[NetLast];
 
 /* flags */
 static int wflag = 0;   /* whether to let the window manager control XMenu */
 
 /* flags */
 static int wflag = 0;   /* whether to let the window manager control XMenu */
+static int iflag = 0;   /* whether to disable icons */
 
 /* include config variable */
 #include "config.h"
 
 /* include config variable */
 #include "config.h"
@@ -96,8 +97,11 @@ main(int argc, char *argv[])
        XClassHint classh;
        int ch;
 
        XClassHint classh;
        int ch;
 
-       while ((ch = getopt(argc, argv, "w")) != -1) {
+       while ((ch = getopt(argc, argv, "iw")) != -1) {
                switch (ch) {
                switch (ch) {
+               case 'i':
+                       iflag = 1;
+                       break;
                case 'w':
                        wflag = 1;
                        break;
                case 'w':
                        wflag = 1;
                        break;
@@ -121,16 +125,18 @@ main(int argc, char *argv[])
        colormap = DefaultColormap(dpy, screen);
 
        /* imlib2 stuff */
        colormap = DefaultColormap(dpy, screen);
 
        /* imlib2 stuff */
-       imlib_set_cache_size(2048 * 1024);
-       imlib_context_set_dither(1);
-       imlib_context_set_display(dpy);
-       imlib_context_set_visual(visual);
-       imlib_context_set_colormap(colormap);
+       if (!iflag) {
+               imlib_set_cache_size(2048 * 1024);
+               imlib_context_set_dither(1);
+               imlib_context_set_display(dpy);
+               imlib_context_set_visual(visual);
+               imlib_context_set_colormap(colormap);
+       }
 
        /* initializers */
        initresources();
        initdc();
 
        /* initializers */
        initresources();
        initdc();
-       initscreengeom();
+       initconfig();
        initatoms();
 
        /* set window class */
        initatoms();
 
        /* set window class */
@@ -239,9 +245,9 @@ initdc(void)
        dc.gc = XCreateGC(dpy, rootwin, 0, NULL);
 }
 
        dc.gc = XCreateGC(dpy, rootwin, 0, NULL);
 }
 
-/* calculate screen geometry */
+/* calculate configuration values that are not set manually */
 static void
 static void
-initscreengeom(void)
+initconfig(void)
 {
        Window dw;   /* dummy variable */
        int di;      /* dummy variable */
 {
        Window dw;   /* dummy variable */
        int di;      /* dummy variable */
@@ -250,6 +256,7 @@ initscreengeom(void)
        XQueryPointer(dpy, rootwin, &dw, &dw, &config.cursx, &config.cursy, &di, &di, &du);
        config.screenw = DisplayWidth(dpy, screen);
        config.screenh = DisplayHeight(dpy, screen);
        XQueryPointer(dpy, rootwin, &dw, &dw, &config.cursx, &config.cursy, &di, &di, &du);
        config.screenw = DisplayWidth(dpy, screen);
        config.screenh = DisplayHeight(dpy, screen);
+       config.iconsize = config.height_pixels - config.iconpadding * 2;
 }
 
 /* intern atoms */
 }
 
 /* intern atoms */
@@ -441,7 +448,7 @@ parsestdin(void)
 
 /* load and scale icon */
 static Imlib_Image
 
 /* load and scale icon */
 static Imlib_Image
-loadicon(const char *file, int size)
+loadicon(const char *file)
 {
        Imlib_Image icon;
        int width;
 {
        Imlib_Image icon;
        int width;
@@ -458,18 +465,20 @@ loadicon(const char *file, int size)
        height = imlib_image_get_height();
        imgsize = MIN(width, height);
 
        height = imlib_image_get_height();
        imgsize = MIN(width, height);
 
-       icon = imlib_create_cropped_scaled_image(0, 0, imgsize, imgsize, size, size);
+       icon = imlib_create_cropped_scaled_image(0, 0, imgsize, imgsize,
+                                                config.iconsize,
+                                                config.iconsize);
 
        return icon;
 }
 
 
        return icon;
 }
 
-/* setup the size of a menu and the position of its items */
+/* setup the height, width and icon of the items of a menu */
 static void
 static void
-setupmenusize(struct Menu *menu)
+setupitems(struct Menu *menu)
 {
        XGlyphInfo ext;
        struct Item *item;
 {
        XGlyphInfo ext;
        struct Item *item;
-       int labelwidth;
+       int itemwidth;
 
        menu->w = config.width_pixels;
        for (item = menu->list; item != NULL; item = item->next) {
 
        menu->w = config.width_pixels;
        for (item = menu->list; item != NULL; item = item->next) {
@@ -485,13 +494,25 @@ setupmenusize(struct Menu *menu)
                XftTextExtentsUtf8(dpy, dc.font, (XftChar8 *)item->label,
                                   item->labellen, &ext);
 
                XftTextExtentsUtf8(dpy, dc.font, (XftChar8 *)item->label,
                                   item->labellen, &ext);
 
-               /* set menu width */
-               labelwidth = ext.xOff + item->h * 2;
-               menu->w = MAX(menu->w, labelwidth);
+               /*
+                * set menu width
+                *
+                * the item width depends on the size of its label (ext.xOff),
+                * and it is only used to calculate the width of the menu (which
+                * is equal to the width of the largest item).
+                *
+                * the horizontal padding appears 4 times through the width of a
+                * item: before and after its icon, and before and after its triangle
+                * if the iflag is set (icons are disabled) then the horizontal
+                * padding appears before the label and around the triangle.
+                */
+               itemwidth = ext.xOff + config.triangle_width + config.horzpadding * 3;
+               itemwidth += (iflag) ? 0 : config.iconsize + config.horzpadding;
+               menu->w = MAX(menu->w, itemwidth);
 
                /* create icon */
 
                /* create icon */
-               if (item->file != NULL)
-                       item->icon = loadicon(item->file, item->h - config.iconpadding * 2);
+               if (item->file != NULL && !iflag)
+                       item->icon = loadicon(item->file);
        }
 }
 
        }
 }
 
@@ -539,7 +560,7 @@ setupmenu(struct Menu *menu, XClassHint *classh)
        XTextProperty wintitle;
 
        /* setup size and position of menus */
        XTextProperty wintitle;
 
        /* setup size and position of menus */
-       setupmenusize(menu);
+       setupitems(menu);
        setupmenupos(menu);
 
        /* update menu geometry */
        setupmenupos(menu);
 
        /* update menu geometry */
@@ -685,7 +706,8 @@ drawseparator(struct Menu *menu, struct Item *item)
        y = item->y + item->h/2;
 
        XSetForeground(dpy, dc.gc, dc.separator.pixel);
        y = item->y + item->h/2;
 
        XSetForeground(dpy, dc.gc, dc.separator.pixel);
-       XDrawLine(dpy, menu->pixmap, dc.gc, 0, y, menu->w, y);
+       XDrawLine(dpy, menu->pixmap, dc.gc, config.horzpadding, y,
+                 menu->w - config.horzpadding, y);
 }
 
 /* draw regular item */
 }
 
 /* draw regular item */
@@ -694,7 +716,8 @@ drawitem(struct Menu *menu, struct Item *item, XftColor *color)
 {
        int x, y;
 
 {
        int x, y;
 
-       x = item->h;
+       x = config.horzpadding;
+       x += (iflag) ? 0 : config.horzpadding + config.iconsize;
        y = item->y + (item->h + dc.font->ascent) / 2;
        XSetForeground(dpy, dc.gc, color[ColorFG].pixel);
        XftDrawStringUtf8(menu->draw, &color[ColorFG], dc.font,
        y = item->y + (item->h + dc.font->ascent) / 2;
        XSetForeground(dpy, dc.gc, color[ColorFG].pixel);
        XftDrawStringUtf8(menu->draw, &color[ColorFG], dc.font,
@@ -702,7 +725,7 @@ drawitem(struct Menu *menu, struct Item *item, XftColor *color)
 
        /* draw triangle, if item contains a submenu */
        if (item->submenu != NULL) {
 
        /* draw triangle, if item contains a submenu */
        if (item->submenu != NULL) {
-               x = menu->w - (item->h + config.triangle_width + 1) / 2;
+               x = menu->w - config.triangle_width - config.horzpadding;
                y = item->y + (item->h - config.triangle_height + 1) / 2;
 
                XPoint triangle[] = {
                y = item->y + (item->h - config.triangle_height + 1) / 2;
 
                XPoint triangle[] = {
@@ -717,8 +740,8 @@ drawitem(struct Menu *menu, struct Item *item, XftColor *color)
        }
 
        /* draw icon */
        }
 
        /* draw icon */
-       if (item->file != NULL) {
-               x = config.iconpadding;
+       if (item->icon != NULL) {
+               x = config.horzpadding;
                y = item->y + config.iconpadding;
                imlib_context_set_drawable(menu->pixmap);
                imlib_context_set_image(item->icon);
                y = item->y + config.iconpadding;
                imlib_context_set_drawable(menu->pixmap);
                imlib_context_set_image(item->icon);
@@ -997,6 +1020,6 @@ cleanup(void)
 static void
 usage(void)
 {
 static void
 usage(void)
 {
-       (void)fprintf(stderr, "usage: xmenu [-w] [title]\n");
+       (void)fprintf(stderr, "usage: xmenu [-iw] [title]\n");
        exit(1);
 }
        exit(1);
 }
diff --git a/xmenu.h b/xmenu.h
index 11fd29f..b636114 100644 (file)
--- a/xmenu.h
+++ b/xmenu.h
@@ -36,6 +36,9 @@ struct Config {
        int triangle_height;
 
        int iconpadding;
        int triangle_height;
 
        int iconpadding;
+       int horzpadding;
+
+       int iconsize;
 
        int cursx, cursy;           /* cursor position */
        int screenw, screenh;       /* screen width and height */
 
        int cursx, cursy;           /* cursor position */
        int screenw, screenh;       /* screen width and height */