|
- diff --git a/config.h b/config.h
- index a3e4f95..ca7c903 100644
- --- a/config.h
- +++ b/config.h
- @@ -18,3 +18,6 @@ static int separator_pixels = 3; /* space around separator */
- /* geometry of the right-pointing isoceles triangle for submenus */
- static const int triangle_width = 3;
- static const int triangle_height = 7;
- +
- +/* sum of padding around both sides of the image */
- +static const int imgpadding = 8;
- diff --git a/config.mk b/config.mk
- index f86aa34..0ffc8c5 100644
- --- a/config.mk
- +++ b/config.mk
- @@ -14,8 +14,8 @@ FREETYPELIB = -lfontconfig -lXft
- #FREETYPEINC = $(X11INC)/freetype2
-
- # includes and libs
- -INCS = -I${X11INC} -I${FREETYPEINC}
- -LIBS = -L${X11LIB} -L${FREETYPELIB} -lX11
- +INCS = -I/usr/local/include -I${X11INC} -I${FREETYPEINC}
- +LIBS = -L/usr/local/lib -L${X11LIB} -L${FREETYPELIB} -lX11 -lImlib2
-
- # flags
- CPPFLAGS =
- diff --git a/xmenu.1 b/xmenu.1
- index d114668..5201032 100644
- --- a/xmenu.1
- +++ b/xmenu.1
- @@ -13,17 +13,21 @@ and outputs the item selected to stdout.
- Each item read from stdin has the following format:
- .IP
- .EX
- -ITEM := [TABS] [LABEL [TABS OUTPUT]] NEWLINE
- +ITEM := [TABS] [[IMAGE TABS] LABEL [TABS OUTPUT]] NEWLINE
- .EE
- .PP
- That means that each item is composed by
- -tabs, followed by a label, followed by more tabs, followed by an output,
- +tabs, followed by an optional image specification, followed by tabs
- +followed by a label, followed by more tabs, followed by an output,
- and ended by a newline. Brackets group optional elements.
- .IP
- The initial tabs indicate the menu hierarchy:
- items indented with a tab is shown in a submenu of the preceding item not indented.
- An item without initial tabs is a top-level item.
- .IP
- +The image is a string of the form "IMG:/path/to/image.png".
- +It specifies a image to be shown as icon at the left of the entry.
- +.IP
- The label is the string that will be shown as a item in the menu.
- An item without label is considered a separator and is drawn as a thin line in the menu
- separating the item above from the item below.
- @@ -104,14 +108,14 @@ creating a command to be run by the shell.
-
- cat <<EOF | xmenu | sh &
- Applications
- - Web Browser firefox
- - Image editor gimp
- -Terminal (xterm) xterm
- -Terminal (urxvt) urxvt
- -Terminal (st) st
- + IMG:./web.png Web Browser firefox
- + Image editor gimp
- +Terminal (xterm) xterm
- +Terminal (urxvt) urxvt
- +Terminal (st) st
-
- -Shutdown poweroff
- -Reboot reboot
- +Shutdown poweroff
- +Reboot reboot
- EOF
- .EE
- .PP
- diff --git a/xmenu.c b/xmenu.c
- index abab13d..d70c6b8 100644
- --- a/xmenu.c
- +++ b/xmenu.c
- @@ -8,6 +8,7 @@
- #include <X11/Xresource.h>
- #include <X11/XKBlib.h>
- #include <X11/Xft/Xft.h>
- +#include <Imlib2.h>
-
- #define PROGNAME "xmenu"
- #define ITEMPREV 0
- @@ -45,12 +46,14 @@ struct Geometry {
- struct Item {
- char *label; /* string to be drawed on menu */
- char *output; /* string to be outputed when item is clicked */
- + char *file; /* filename of the image */
- int y; /* item y position relative to menu */
- int h; /* item height */
- size_t labellen; /* strlen(label) */
- struct Item *prev; /* previous item */
- struct Item *next; /* next item */
- struct Menu *submenu; /* submenu spawned by clicking on item */
- + Imlib_Image image;
- };
-
- /* menu structure */
- @@ -71,9 +74,9 @@ static void getresources(void);
- static void getcolor(const char *s, XftColor *color);
- static void setupdc(void);
- static void calcgeom(struct Geometry *geom);
- -static struct Item *allocitem(const char *label, const char *output);
- +static struct Item *allocitem(const char *label, const char *output, char *file);
- static struct Menu *allocmenu(struct Menu *parent, struct Item *list, unsigned level);
- -static struct Menu *buildmenutree(unsigned level, const char *label, const char *output);
- +static struct Menu *buildmenutree(unsigned level, const char *label, const char *output, char *file);
- static struct Menu *parsestdin(void);
- static void calcmenu(struct Geometry *geom, struct Menu *menu);
- static void grabpointer(void);
- @@ -129,6 +132,13 @@ main(int argc, char *argv[])
- rootwin = RootWindow(dpy, screen);
- 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);
- +
- /* setup */
- getresources();
- setupdc();
- @@ -247,7 +257,7 @@ calcgeom(struct Geometry *geom)
-
- /* allocate an item */
- static struct Item *
- -allocitem(const char *label, const char *output)
- +allocitem(const char *label, const char *output, char *file)
- {
- struct Item *item;
-
- @@ -266,6 +276,12 @@ allocitem(const char *label, const char *output)
- err(1, "strdup");
- }
- }
- + if (file == NULL) {
- + item->file = NULL;
- + } else {
- + if ((item->file = strdup(file)) == NULL)
- + err(1, "strdup");
- + }
- item->y = 0;
- item->h = 0;
- if (item->label == NULL)
- @@ -274,6 +290,7 @@ allocitem(const char *label, const char *output)
- item->labellen = strlen(item->label);
- item->next = NULL;
- item->submenu = NULL;
- + item->image = NULL;
-
- return item;
- }
- @@ -314,7 +331,7 @@ allocmenu(struct Menu *parent, struct Item *list, unsigned level)
-
- /* build the menu tree */
- static struct Menu *
- -buildmenutree(unsigned level, const char *label, const char *output)
- +buildmenutree(unsigned level, const char *label, const char *output, char *file)
- {
- static struct Menu *prevmenu = NULL; /* menu the previous item was added to */
- static struct Menu *rootmenu = NULL; /* menu to be returned */
- @@ -324,7 +341,7 @@ buildmenutree(unsigned level, const char *label, const char *output)
- unsigned i;
-
- /* create the item */
- - curritem = allocitem(label, output);
- + curritem = allocitem(label, output, file);
-
- /* put the item in the menu tree */
- if (prevmenu == NULL) { /* there is no menu yet */
- @@ -377,7 +394,7 @@ parsestdin(void)
- {
- struct Menu *rootmenu;
- char *s, buf[BUFSIZ];
- - char *label, *output;
- + char *file, *label, *output;
- unsigned level = 0;
-
- rootmenu = NULL;
- @@ -390,6 +407,13 @@ parsestdin(void)
- s = level + buf;
- label = strtok(s, "\t\n");
-
- + /* get the filename */
- + file = NULL;
- + if (label != NULL && strncmp(label, "IMG:", 4) == 0) {
- + file = label + 4;
- + label = strtok(NULL, "\t\n");
- + }
- +
- /* get the output */
- output = strtok(NULL, "\n");
- if (output == NULL) {
- @@ -399,12 +423,36 @@ parsestdin(void)
- output++;
- }
-
- - rootmenu = buildmenutree(level, label, output);
- + rootmenu = buildmenutree(level, label, output, file);
- }
-
- return rootmenu;
- }
-
- +/* load and scale image */
- +static Imlib_Image
- +loadimage(const char *file, int size)
- +{
- + Imlib_Image image;
- + int width;
- + int height;
- + int imgsize;
- +
- + image = imlib_load_image(file);
- + if (image == NULL)
- + errx(1, "cannot load image %s", file);
- +
- + imlib_context_set_image(image);
- +
- + width = imlib_image_get_width();
- + height = imlib_image_get_height();
- + imgsize = MIN(width, height);
- +
- + image = imlib_create_cropped_scaled_image(0, 0, imgsize, imgsize, size, size);
- +
- + return image;
- +}
- +
- /* recursivelly calculate menu geometry and set window hints */
- static void
- calcmenu(struct Geometry *geom, struct Menu *menu)
- @@ -430,8 +478,12 @@ calcmenu(struct Geometry *geom, struct Menu *menu)
-
- XftTextExtentsUtf8(dpy, dc.font, (XftChar8 *)item->label,
- item->labellen, &ext);
- - labelwidth = ext.xOff + dc.font->height * 2;
- + labelwidth = ext.xOff + dc.font->height * 2 + imgpadding;
- menu->w = MAX(menu->w, labelwidth);
- +
- + /* create image */
- + if (item->file != NULL)
- + item->image = loadimage(item->file, dc.font->height);
- }
-
- /* calculate menu's x and y positions */
- @@ -621,7 +673,7 @@ drawitem(struct Menu *menu, struct Item *item, XftColor *color)
- {
- int x, y;
-
- - x = dc.font->height;
- + x = dc.font->height + imgpadding;
- y = item->y + item->h/2 + dc.font->ascent/2 - 1;
- XSetForeground(dpy, dc.gc, color[ColorFG].pixel);
- XftDrawStringUtf8(menu->draw, &color[ColorFG], dc.font,
- @@ -629,8 +681,8 @@ drawitem(struct Menu *menu, struct Item *item, XftColor *color)
-
- /* draw triangle, if item contains a submenu */
- if (item->submenu != NULL) {
- - x = menu->w - dc.font->height/2 - triangle_width/2;
- - y = item->y + item->h/2 - triangle_height/2 - 1;
- + x = menu->w - (dc.font->height - triangle_width) / 2;
- + y = item->y + (item->h - triangle_height) / 2;
-
- XPoint triangle[] = {
- {x, y},
- @@ -642,6 +694,15 @@ drawitem(struct Menu *menu, struct Item *item, XftColor *color)
- XFillPolygon(dpy, menu->pixmap, dc.gc, triangle, LEN(triangle),
- Convex, CoordModeOrigin);
- }
- +
- + /* draw image */
- + if (item->file != NULL) {
- + x = imgpadding / 2;
- + y = item->y + (item->h - dc.font->height) / 2;
- + imlib_context_set_drawable(menu->pixmap);
- + imlib_context_set_image(item->image);
- + imlib_render_image_on_drawable(x, y);
- + }
- }
-
- /* draw items of the current menu and of its ancestors */
- @@ -831,6 +892,13 @@ freemenu(struct Menu *menu)
- if (tmp->label != tmp->output)
- free(tmp->label);
- free(tmp->output);
- + if (tmp->file != NULL) {
- + free(tmp->file);
- + if (item->image != NULL) {
- + imlib_context_set_image(item->image);
- + imlib_free_image();
- + }
- + }
- free(tmp);
- }
-
- diff --git a/xmenu.sh b/xmenu.sh
- index abd9a41..db08041 100755
- --- a/xmenu.sh
- +++ b/xmenu.sh
- @@ -2,7 +2,7 @@
-
- cat <<EOF | xmenu | sh &
- Applications
- - Web Browser firefox
- + IMG:./web.png Web Browser firefox
- Image editor gimp
- Terminal (xterm) xterm
- Terminal (urxvt) urxvt
|