Adding icons patch
This commit is contained in:
		
							
								
								
									
										315
									
								
								patches/icons.diff
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										315
									
								
								patches/icons.diff
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,315 @@
 | 
			
		||||
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
 | 
			
		||||
		Reference in New Issue
	
	Block a user