summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--calmwm.c5
-rw-r--r--calmwm.h20
-rw-r--r--conf.c17
-rw-r--r--cwmrc.55
-rw-r--r--font.c34
-rw-r--r--menu.c77
-rw-r--r--mousefunc.c4
-rw-r--r--parse.y23
-rw-r--r--xutil.c9
9 files changed, 131 insertions, 63 deletions
diff --git a/calmwm.c b/calmwm.c
index 97a25b1..c699751 100644
--- a/calmwm.c
+++ b/calmwm.c
@@ -147,11 +147,6 @@ x_setup(void)
 static void
 x_teardown(void)
 {
-	struct screen_ctx	*sc;
-
-	TAILQ_FOREACH(sc, &Screenq, entry)
-		XFreeGC(X_Dpy, sc->gc);
-
 	XCloseDisplay(X_Dpy);
 }
 
diff --git a/calmwm.h b/calmwm.h
index 38c3fee..bd0dbd7 100644
--- a/calmwm.h
+++ b/calmwm.h
@@ -84,14 +84,19 @@ union arg {
 	int	 i;
 };
 
+enum menucolor {
+	CWM_COLOR_MENU_FG,
+	CWM_COLOR_MENU_BG,
+	CWM_COLOR_MENU_FONT,
+	CWM_COLOR_MENU_FONT_SEL,
+	CWM_COLOR_MENU_MAX
+};
+
 enum cwmcolor {
 	CWM_COLOR_BORDER_ACTIVE,
 	CWM_COLOR_BORDER_INACTIVE,
 	CWM_COLOR_BORDER_GROUP,
 	CWM_COLOR_BORDER_UNGROUP,
-	CWM_COLOR_FG_MENU,
-	CWM_COLOR_BG_MENU,
-	CWM_COLOR_FONT,
 	CWM_COLOR_MAX
 };
 
@@ -208,13 +213,12 @@ struct screen_ctx {
 	Window			 rootwin;
 	Window			 menuwin;
 	struct color		 color[CWM_COLOR_MAX];
-	GC			 gc;
 	int			 cycling;
 	struct geom		 view; /* viewable area */
 	struct geom		 work; /* workable area, gap-applied */
 	struct gap		 gap;
 	struct cycle_entry_q	 mruq;
-	XftColor		 xftcolor;
+	XftColor		 xftcolor[CWM_COLOR_MENU_MAX];
 	XftDraw			*xftdraw;
 	XftFont			*font;
 	int			 xinerama_no;
@@ -289,6 +293,7 @@ struct conf {
 	int			 snapdist;
 	struct gap		 gap;
 	struct color		 color[CWM_COLOR_MAX];
+	char		 	*menucolor[CWM_COLOR_MENU_MAX];
 	char			 termpath[MAXPATHLEN];
 	char			 lockpath[MAXPATHLEN];
 #define	CONF_FONT			"sans-serif:pixelsize=14:bold"
@@ -445,10 +450,10 @@ void			 conf_ungrab(struct conf *, struct keybinding *);
 int			 font_ascent(struct screen_ctx *);
 int			 font_descent(struct screen_ctx *);
 void			 font_draw(struct screen_ctx *, const char *, int,
-			     Drawable, int, int);
+			     Drawable, int, int, int);
 u_int			 font_height(struct screen_ctx *);
 void			 font_init(struct screen_ctx *, const char *,
-			     const char *);
+			     const char **);
 int			 font_width(struct screen_ctx *, const char *, int);
 
 void			 xev_loop(void);
@@ -486,6 +491,7 @@ void			 xu_ewmh_net_desktop_names(struct screen_ctx *, char *, int);
 
 void			 xu_ewmh_net_wm_desktop(struct client_ctx *);
 
+void 			 xu_xorcolor(XRenderColor, XRenderColor, XRenderColor *);
 
 void			 u_exec(char *);
 void			 u_spawn(char *);
diff --git a/conf.c b/conf.c
index 2fe7363..a42be91 100644
--- a/conf.c
+++ b/conf.c
@@ -62,17 +62,21 @@ conf_gap(struct conf *c, struct screen_ctx *sc)
 void
 conf_font(struct conf *c, struct screen_ctx *sc)
 {
-	font_init(sc, c->font, c->color[CWM_COLOR_FONT].name);
+	font_init(sc, c->font, (const char**)c->menucolor);
 }
 
-static struct color color_binds[] = {
+static char *menu_color_binds[CWM_COLOR_MENU_MAX] = {
+	"black",  /* CWM_COLOR_MENU_FG */
+	"white",  /* CWM_COLOR_MENU_BG */
+	"black",  /* CWM_COLOR_MENU_FONT */
+	"",  	  /* CWM_COLOR_MENU_FONT_SEL */
+};
+
+static struct color color_binds[CWM_COLOR_MAX] = {
 	{ "#CCCCCC",	0 }, /* CWM_COLOR_BORDER_ACTIVE */
 	{ "#666666",	0 }, /* CWM_COLOR_BORDER_INACTIVE */
 	{ "blue",	0 }, /* CWM_COLOR_BORDER_GROUP */
 	{ "red",	0 }, /* CWM_COLOR_BORDER_UNGROUP */
-	{ "black",	0 }, /* CWM_COLOR_FG_MENU */
-	{ "white",	0 }, /* CWM_COLOR_BG_MENU */
-	{ "black",	0 }, /* CWM_COLOR_FONT */
 };
 
 void
@@ -182,6 +186,9 @@ conf_init(struct conf *c)
 	for (i = 0; i < nitems(color_binds); i++)
 		c->color[i].name = xstrdup(color_binds[i].name);
 
+	for (i = 0; i < nitems(menu_color_binds); i++)
+		c->menucolor[i] = xstrdup(menu_color_binds[i]);
+
 	/* Default term/lock */
 	(void)strlcpy(c->termpath, "xterm", sizeof(c->termpath));
 	(void)strlcpy(c->lockpath, "xlock", sizeof(c->lockpath));
diff --git a/cwmrc.5 b/cwmrc.5
index 4e17dbd..c8ea841 100644
--- a/cwmrc.5
+++ b/cwmrc.5
@@ -14,7 +14,7 @@
 .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 .\"
-.Dd $Mdocdate: November 7 2012 $
+.Dd $Mdocdate: November 29 2012 $
 .Dt CWMRC 5
 .Os
 .Sh NAME
@@ -112,6 +112,9 @@ Set the color of the active border.
 .It Ic color font Ar color
 Set menu font color.
 .Pp
+.It Ic color selfont Ar color
+Set font color for selected menu item.
+.Pp
 .It Ic color groupborder Ar color
 Set the color of the border while grouping a window.
 .Pp
diff --git a/font.c b/font.c
index 0e1c144..cbd5b56 100644
--- a/font.c
+++ b/font.c
@@ -49,20 +49,37 @@ font_height(struct screen_ctx *sc)
 }
 
 void
-font_init(struct screen_ctx *sc, const char *name, const char *color)
+font_init(struct screen_ctx *sc, const char *name, const char **color)
 {
+	int i;
+	XRenderColor c;
+
 	sc->xftdraw = XftDrawCreate(X_Dpy, sc->rootwin,
 	    DefaultVisual(X_Dpy, sc->which), DefaultColormap(X_Dpy, sc->which));
 	if (sc->xftdraw == NULL)
 		errx(1, "XftDrawCreate");
 
-	if (!XftColorAllocName(X_Dpy, DefaultVisual(X_Dpy, sc->which),
-	    DefaultColormap(X_Dpy, sc->which), color, &sc->xftcolor))
-		errx(1, "XftColorAllocName");
-
 	sc->font = XftFontOpenName(X_Dpy, sc->which, name);
 	if (sc->font == NULL)
 		errx(1, "XftFontOpenName");
+	for(i = 0; i < CWM_COLOR_MENU_MAX; i++) {
+		if (*color[i] == '\0')
+			break;
+		if (!XftColorAllocName(X_Dpy, DefaultVisual(X_Dpy, sc->which),
+			DefaultColormap(X_Dpy, sc->which), color[i],
+		       	&sc->xftcolor[i]))
+			errx(1, "XftColorAllocName");
+	}
+	if (i == CWM_COLOR_MENU_MAX)
+		return;
+
+	xu_xorcolor(sc->xftcolor[CWM_COLOR_MENU_BG].color,
+			sc->xftcolor[CWM_COLOR_MENU_FG].color, &c);
+	xu_xorcolor(sc->xftcolor[CWM_COLOR_MENU_FONT].color, c, &c);
+	if (!XftColorAllocValue(X_Dpy, DefaultVisual(X_Dpy, sc->which),
+				DefaultColormap(X_Dpy, sc->which), &c,
+				&sc->xftcolor[CWM_COLOR_MENU_FONT_SEL]))
+		errx(1, "XftColorAllocValue");
 }
 
 int
@@ -78,9 +95,12 @@ font_width(struct screen_ctx *sc, const char *text, int len)
 
 void
 font_draw(struct screen_ctx *sc, const char *text, int len,
-    Drawable d, int x, int y)
+    Drawable d, int active, int x, int y)
 {
+	int color;
+
+	color = active ? CWM_COLOR_MENU_FONT_SEL : CWM_COLOR_MENU_FONT;
 	XftDrawChange(sc->xftdraw, d);
-	XftDrawStringUtf8(sc->xftdraw, &sc->xftcolor, sc->font, x, y,
+	XftDrawStringUtf8(sc->xftdraw, &sc->xftcolor[color], sc->font, x, y,
 	    (const FcChar8*)text, len);
 }
diff --git a/menu.c b/menu.c
index e2b6e0e..8a0ce26 100644
--- a/menu.c
+++ b/menu.c
@@ -65,11 +65,13 @@ struct menu_ctx {
 static struct menu	*menu_handle_key(XEvent *, struct menu_ctx *,
 			     struct menu_q *, struct menu_q *);
 static void		 menu_handle_move(XEvent *, struct menu_ctx *,
-			     struct screen_ctx *);
+			     struct screen_ctx *, struct menu_q *);
 static struct menu	*menu_handle_release(XEvent *, struct menu_ctx *,
 			     struct screen_ctx *, struct menu_q *);
 static void		 menu_draw(struct screen_ctx *, struct menu_ctx *,
 			     struct menu_q *, struct menu_q *);
+static void 		 menu_draw_entry(struct screen_ctx *, struct menu_ctx *,
+			     struct menu_q *, int, int);
 static int		 menu_calc_entry(struct screen_ctx *, struct menu_ctx *,
 			     int, int);
 static int		 menu_keycode(XKeyEvent *, enum ctltype *,
@@ -78,20 +80,10 @@ static int		 menu_keycode(XKeyEvent *, enum ctltype *,
 void
 menu_init(struct screen_ctx *sc)
 {
-	XGCValues	 gv;
-
 	sc->menuwin = XCreateSimpleWindow(X_Dpy, sc->rootwin, 0, 0, 1, 1,
 	    Conf.bwidth,
-	    sc->color[CWM_COLOR_FG_MENU].pixel,
-	    sc->color[CWM_COLOR_BG_MENU].pixel);
-
-	gv.foreground =
-	    sc->color[CWM_COLOR_FG_MENU].pixel^sc->color[CWM_COLOR_BG_MENU].pixel;
-	gv.background = sc->color[CWM_COLOR_BG_MENU].pixel;
-	gv.function = GXxor;
-
-	sc->gc = XCreateGC(X_Dpy, sc->menuwin,
-	    GCForeground|GCBackground|GCFunction, &gv);
+	    sc->xftcolor[CWM_COLOR_MENU_FG].pixel,
+	    sc->xftcolor[CWM_COLOR_MENU_BG].pixel);
 }
 
 struct menu *
@@ -174,7 +166,7 @@ menu_filter(struct screen_ctx *sc, struct menu_q *menuq, char *prompt,
 			menu_draw(sc, &mc, menuq, &resultq);
 			break;
 		case MotionNotify:
-			menu_handle_move(&e, &mc, sc);
+			menu_handle_move(&e, &mc, sc, &resultq);
 			break;
 		case ButtonRelease:
 			if ((mi = menu_handle_release(&e, &mc, sc, &resultq))
@@ -442,8 +434,8 @@ menu_draw(struct screen_ctx *sc, struct menu_ctx *mc, struct menu_q *menuq,
 	    mc->width, mc->height);
 
 	if (mc->hasprompt) {
-		font_draw(sc, mc->dispstr, strlen(mc->dispstr), sc->menuwin,
-		    0, font_ascent(sc) + 1);
+		font_draw(sc, mc->dispstr, strlen(mc->dispstr), sc->menuwin, 0,
+		    0, font_ascent(sc));
 		n = 1;
 	} else
 		n = 0;
@@ -458,34 +450,61 @@ menu_draw(struct screen_ctx *sc, struct menu_ctx *mc, struct menu_q *menuq,
 			break;
 
 		font_draw(sc, text, MIN(strlen(text), MENU_MAXENTRY),
-		    sc->menuwin, 0, y);
+		    sc->menuwin, 0, 0, y);
 		n++;
 	}
+	if (mc->hasprompt && n > 1 && (mc->searchstr[0] != '\0')) {
+		mc->entry = 1;
+		menu_draw_entry(sc, mc, resultq, mc->entry, 1);
+	}
+}
+
+static void
+menu_draw_entry(struct screen_ctx *sc, struct menu_ctx *mc,
+    struct menu_q *resultq, int entry, int active)
+{
+	struct menu	*mi;
+	char 		*text;
+	int		 color, i = 0;
 
-	if (mc->hasprompt && n > 1 && (mc->searchstr[0] != '\0'))
-		XFillRectangle(X_Dpy, sc->menuwin, sc->gc,
-		    0, font_height(sc), mc->width, font_height(sc));
+	if (mc->hasprompt)
+		i = 1;
+
+	TAILQ_FOREACH(mi, resultq, resultentry)
+		if (entry == i++)
+			break;
 
-	if (mc->noresult)
-		XFillRectangle(X_Dpy, sc->menuwin, sc->gc,
-		    0, 0, mc->width, font_height(sc));
+	if (mi == NULL)
+		return;
+	color = active ? CWM_COLOR_MENU_FG : CWM_COLOR_MENU_BG;
+	text = mi->print[0] != '\0' ?
+		    mi->print : mi->text;
+	XftDrawRect(sc->xftdraw, &sc->xftcolor[color], 0,
+			font_height(sc) * entry, mc->width,
+			font_height(sc) + font_descent(sc));
+	font_draw(sc, text, strlen(text), sc->menuwin, active,
+			0, font_height(sc) * entry + font_ascent(sc) + 1);
 }
 
 static void
-menu_handle_move(XEvent *e, struct menu_ctx *mc, struct screen_ctx *sc)
+menu_handle_move(XEvent *e, struct menu_ctx *mc, struct screen_ctx *sc,
+    struct menu_q *resultq)
 {
 	mc->prev = mc->entry;
 	mc->entry = menu_calc_entry(sc, mc, e->xbutton.x, e->xbutton.y);
 
+	if (mc->prev == mc->entry)
+		return;
+
 	if (mc->prev != -1)
-		XFillRectangle(X_Dpy, sc->menuwin, sc->gc, 0,
-		    font_height(sc) * mc->prev, mc->width, font_height(sc));
+		menu_draw_entry(sc, mc, resultq, mc->prev, 0);
 	if (mc->entry != -1) {
 		(void)xu_ptr_regrab(MENUGRABMASK, Cursor_normal);
-		XFillRectangle(X_Dpy, sc->menuwin, sc->gc, 0,
-		    font_height(sc) * mc->entry, mc->width, font_height(sc));
+		menu_draw_entry(sc, mc, resultq, mc->entry, 1);
 	} else
 		(void)xu_ptr_regrab(MENUGRABMASK, Cursor_default);
+	if (mc->hasprompt)
+		menu_draw_entry(sc, mc, resultq, 1, 1);
 }
 
 static struct menu *
@@ -519,7 +538,7 @@ menu_calc_entry(struct screen_ctx *sc, struct menu_ctx *mc, int x, int y)
 	entry = y / font_height(sc);
 
 	/* in bounds? */
-	if (x <= 0 || x > mc->width || y <= 0 ||
+	if (x < 0 || x > mc->width || y < 0 ||
 	    y > font_height(sc) * mc->num || entry < 0 || entry >= mc->num)
 		entry = -1;
 
diff --git a/mousefunc.c b/mousefunc.c
index d61adca..a342b8e 100644
--- a/mousefunc.c
+++ b/mousefunc.c
@@ -68,9 +68,9 @@ mousefunc_sweep_draw(struct client_ctx *cc)
 	XMoveResizeWindow(X_Dpy, sc->menuwin, 0, 0, width, font_height(sc) * 2);
 	XMapWindow(X_Dpy, sc->menuwin);
 	XClearWindow(X_Dpy, sc->menuwin);
-	font_draw(sc, cc->name, strlen(cc->name), sc->menuwin,
+	font_draw(sc, cc->name, strlen(cc->name), sc->menuwin, 0,
 	    2, font_ascent(sc) + 1);
-	font_draw(sc, asize, strlen(asize), sc->menuwin,
+	font_draw(sc, asize, strlen(asize), sc->menuwin, 0,
 	    width / 2 - width_size / 2, font_height(sc) + font_ascent(sc) + 1);
 }
 
diff --git a/parse.y b/parse.y
index c89c038..b36ee26 100644
--- a/parse.y
+++ b/parse.y
@@ -73,7 +73,8 @@ typedef struct {
 %token	COLOR SNAPDIST
 %token	ACTIVEBORDER INACTIVEBORDER
 %token	GROUPBORDER UNGROUPBORDER
-%token	MENUBG MENUFG FONTCOLOR
+%token	MENUBG MENUFG
+%token	FONTCOLOR FONTSELCOLOR
 %token	ERROR
 %token	<v.string>		STRING
 %token	<v.number>		NUMBER
@@ -186,16 +187,20 @@ colors		: ACTIVEBORDER STRING {
 			conf->color[CWM_COLOR_BORDER_UNGROUP].name = $2;
 		}
 		| MENUBG STRING {
-			free(conf->color[CWM_COLOR_BG_MENU].name);
-			conf->color[CWM_COLOR_BG_MENU].name = $2;
+			free(conf->menucolor[CWM_COLOR_MENU_BG]);
+			conf->menucolor[CWM_COLOR_MENU_BG] = $2;
 		}
 		| MENUFG STRING {
-			free(conf->color[CWM_COLOR_FG_MENU].name);
-			conf->color[CWM_COLOR_FG_MENU].name = $2;
+			free(conf->menucolor[CWM_COLOR_MENU_FG]);
+			conf->menucolor[CWM_COLOR_MENU_FG] = $2;
 		}
 		| FONTCOLOR STRING {
-			free(conf->color[CWM_COLOR_FONT].name);
-			conf->color[CWM_COLOR_FONT].name = $2;
+			free(conf->menucolor[CWM_COLOR_MENU_FONT]);
+			conf->menucolor[CWM_COLOR_MENU_FONT] = $2;
+		}
+		| FONTSELCOLOR STRING {
+			free(conf->menucolor[CWM_COLOR_MENU_FONT_SEL]);
+			conf->menucolor[CWM_COLOR_MENU_FONT_SEL] = $2;
 		}
 		;
 %%
@@ -247,6 +252,7 @@ lookup(char *s)
 		{ "mousebind",		MOUSEBIND},
 		{ "moveamount",		MOVEAMOUNT},
 		{ "no",			NO},
+		{ "selfont", 		FONTSELCOLOR},
 		{ "snapdist",		SNAPDIST},
 		{ "sticky",		STICKY},
 		{ "ungroupborder",	UNGROUPBORDER},
@@ -575,6 +581,9 @@ parse_config(const char *filename, struct conf *xconf)
 		for (i = 0; i < CWM_COLOR_MAX; i++)
 			xconf->color[i].name = conf->color[i].name;
 
+		for (i = 0; i < CWM_COLOR_MENU_MAX; i++)
+			xconf->menucolor[i]= conf->menucolor[i];
+
 		xconf->font = conf->font;
 	}
 
diff --git a/xutil.c b/xutil.c
index 9c80dfe..6e80379 100644
--- a/xutil.c
+++ b/xutil.c
@@ -430,3 +430,12 @@ xu_getcolor(struct screen_ctx *sc, char *name)
 
 	return (color.pixel);
 }
+
+void
+xu_xorcolor(XRenderColor a, XRenderColor b, XRenderColor *r)
+{
+	r->red = a.red ^ b.red;
+	r->green = a.green ^ b.green;
+	r->blue = a.blue ^ b.blue;
+	r->alpha = 0xffff;
+}