added the -i option

Widths and x positions no more depend on item->h.
This commit is contained in:
phillbush 2020-07-15 22:57:59 -03:00
parent 92e7609bcd
commit 71b4db9241
4 changed files with 76 additions and 34 deletions

View File

@ -17,12 +17,18 @@ static struct Config config = {
.separator_pixels = 3, /* space around separator */ .separator_pixels = 3, /* space around separator */
.gap_pixels = 0, /* gap between menus */ .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 */ /* geometry of the right-pointing isoceles triangle for submenus */
.triangle_width = 3, .triangle_width = 3,
.triangle_height = 7, .triangle_height = 7,
/* padding of the area around the icon */ /* the icon size is equal to .height_pixels - .iconpadding * 2 */
.iconpadding = 4, .iconpadding = 2,
/* area around the icon, the triangle and the separator */
.horzpadding = 8,
}; };

14
xmenu.1
View File

@ -3,7 +3,7 @@
xmenu \- menu utility for X xmenu \- menu utility for X
.SH SYNOPSIS .SH SYNOPSIS
.B xmenu .B xmenu
.RB [ \-w ] .RB [ \-iw ]
.RI [ title ] .RI [ title ]
.SH DESCRIPTION .SH DESCRIPTION
.B xmenu .B xmenu
@ -14,9 +14,19 @@ and outputs the item selected to stdout.
.PP .PP
The options are as follows: The options are as follows:
.TP .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 .B -w
Asks the window manager to draw a border around the menus. 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 .PP
Each item read from stdin has the following format: Each item read from stdin has the following format:
.IP .IP

71
xmenu.c
View File

@ -21,7 +21,7 @@
static void ealloccolor(const char *s, XftColor *color); static void ealloccolor(const char *s, XftColor *color);
static void initresources(void); static void initresources(void);
static void initdc(void); static void initdc(void);
static void initscreengeom(void); static void initconfig(void);
static void initatoms(void); static void initatoms(void);
/* structure builders, and their helper routines */ /* 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); static struct Menu *parsestdin(void);
/* image loader */ /* 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 setupmenupos(struct Menu *menu);
static void setupmenu(struct Menu *menu, XClassHint *classh); static void setupmenu(struct Menu *menu, XClassHint *classh);
@ -79,6 +79,7 @@ static Atom netatom[NetLast];
/* flags */ /* flags */
static int wflag = 0; /* whether to let the window manager control XMenu */ 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 variable */
#include "config.h" #include "config.h"
@ -96,8 +97,11 @@ main(int argc, char *argv[])
XClassHint classh; XClassHint classh;
int ch; 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': case 'w':
wflag = 1; wflag = 1;
break; break;
@ -121,16 +125,18 @@ main(int argc, char *argv[])
colormap = DefaultColormap(dpy, screen); colormap = DefaultColormap(dpy, screen);
/* imlib2 stuff */ /* imlib2 stuff */
if (!iflag) {
imlib_set_cache_size(2048 * 1024); imlib_set_cache_size(2048 * 1024);
imlib_context_set_dither(1); imlib_context_set_dither(1);
imlib_context_set_display(dpy); imlib_context_set_display(dpy);
imlib_context_set_visual(visual); imlib_context_set_visual(visual);
imlib_context_set_colormap(colormap); imlib_context_set_colormap(colormap);
}
/* initializers */ /* initializers */
initresources(); initresources();
initdc(); initdc();
initscreengeom(); initconfig();
initatoms(); initatoms();
/* set window class */ /* 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 */ Window dw; /* dummy variable */
int di; /* dummy variable */ int di; /* dummy variable */
@ -250,6 +256,7 @@ initscreengeom(void)
XQueryPointer(dpy, rootwin, &dw, &dw, &config.cursx, &config.cursy, &di, &di, &du); XQueryPointer(dpy, rootwin, &dw, &dw, &config.cursx, &config.cursy, &di, &di, &du);
config.screenw = DisplayWidth(dpy, screen); config.screenw = DisplayWidth(dpy, screen);
config.screenh = DisplayHeight(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 */ /* load and scale icon */
static Imlib_Image static Imlib_Image
loadicon(const char *file, int size) loadicon(const char *file)
{ {
Imlib_Image icon; Imlib_Image icon;
int width; int width;
@ -458,18 +465,20 @@ loadicon(const char *file, int size)
height = imlib_image_get_height(); height = imlib_image_get_height();
imgsize = MIN(width, 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; XGlyphInfo ext;
struct Item *item; struct Item *item;
int labelwidth; int itemwidth;
menu->w = config.width_pixels; menu->w = config.width_pixels;
for (item = menu->list; item != NULL; item = item->next) { for (item = menu->list; item != NULL; item = item->next) {
@ -485,13 +494,25 @@ setupmenusize(struct Menu *menu)
XftTextExtentsUtf8(dpy, dc.font, (XftChar8 *)item->label, XftTextExtentsUtf8(dpy, dc.font, (XftChar8 *)item->label,
item->labellen, &ext); item->labellen, &ext);
/* set menu width */ /*
labelwidth = ext.xOff + item->h * 2; * set menu width
menu->w = MAX(menu->w, labelwidth); *
* 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) if (item->file != NULL && !iflag)
item->icon = loadicon(item->file, item->h - config.iconpadding * 2); item->icon = loadicon(item->file);
} }
} }
@ -539,7 +560,7 @@ setupmenu(struct Menu *menu, XClassHint *classh)
XTextProperty wintitle; XTextProperty wintitle;
/* setup size and position of menus */ /* setup size and position of menus */
setupmenusize(menu); setupitems(menu);
setupmenupos(menu); setupmenupos(menu);
/* update menu geometry */ /* update menu geometry */
@ -685,7 +706,8 @@ drawseparator(struct Menu *menu, struct Item *item)
y = item->y + item->h/2; y = item->y + item->h/2;
XSetForeground(dpy, dc.gc, dc.separator.pixel); 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; y = item->y + (item->h + dc.font->ascent) / 2;
XSetForeground(dpy, dc.gc, color[ColorFG].pixel); XSetForeground(dpy, dc.gc, color[ColorFG].pixel);
XftDrawStringUtf8(menu->draw, &color[ColorFG], dc.font, 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 */ /* draw triangle, if item contains a submenu */
if (item->submenu != NULL) { 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; y = item->y + (item->h - config.triangle_height + 1) / 2;
XPoint triangle[] = { XPoint triangle[] = {
@ -717,8 +740,8 @@ drawitem(struct Menu *menu, struct Item *item, XftColor *color)
} }
/* draw icon */ /* draw icon */
if (item->file != NULL) { if (item->icon != NULL) {
x = config.iconpadding; x = config.horzpadding;
y = item->y + config.iconpadding; y = item->y + config.iconpadding;
imlib_context_set_drawable(menu->pixmap); imlib_context_set_drawable(menu->pixmap);
imlib_context_set_image(item->icon); imlib_context_set_image(item->icon);
@ -997,6 +1020,6 @@ cleanup(void)
static void static void
usage(void) usage(void)
{ {
(void)fprintf(stderr, "usage: xmenu [-w] [title]\n"); (void)fprintf(stderr, "usage: xmenu [-iw] [title]\n");
exit(1); exit(1);
} }

View File

@ -36,6 +36,9 @@ struct Config {
int triangle_height; int triangle_height;
int iconpadding; int iconpadding;
int horzpadding;
int iconsize;
int cursx, cursy; /* cursor position */ int cursx, cursy; /* cursor position */
int screenw, screenh; /* screen width and height */ int screenw, screenh; /* screen width and height */