Hello again, this patch adds the possibility to specify colors for the menu and its font in the cwmrc(5), this time without breaking subpixel hinting. Please note that the syntax is not the same as last time, see the manpage for details.
I've tested this with a variety of different colors over the course of a few days (on amd64). Apart from the colors there's only one additional change in behaviour: The first entry in the ``exec program'' dialog is always highlighted, even when selected with the mouse. Index: calmwm.h =================================================================== RCS file: /cvs/xenocara/app/cwm/calmwm.h,v retrieving revision 1.98 diff -u calmwm.h --- calmwm.h 27 Aug 2009 01:38:08 -0000 1.98 +++ calmwm.h 11 Sep 2009 13:01:57 -0000 @@ -47,6 +47,8 @@ CWM_COLOR_BORDER_UNGROUP, CWM_COLOR_FG_MENU, CWM_COLOR_BG_MENU, + CWM_COLOR_FG_FONT, + CWM_COLOR_BG_FONT, CWM_COLOR_MAX }; @@ -77,7 +79,8 @@ struct cycle_entry_q mruq; XftDraw *xftdraw; - XftColor xftcolor; + XftColor xftcolorfg; + XftColor xftcolorbg; int xinerama_no; XineramaScreenInfo *xinerama; @@ -275,6 +278,8 @@ #define CONF_COLOR_UNGROUPBORDER "red" #define CONF_COLOR_MENUFG "black" #define CONF_COLOR_MENUBG "white" +#define CONF_COLOR_FONTFG "white" +#define CONF_COLOR_FONTBG "black" struct color color[CWM_COLOR_MAX]; char termpath[MAXPATHLEN]; @@ -484,12 +489,13 @@ void font_init(struct screen_ctx *); int font_width(const char *, int); void font_draw(struct screen_ctx *, const char *, int, - Drawable, int, int); + Drawable, int, int, int); XftFont *font_make(struct screen_ctx *, const char *); #define font_ascent() Conf.DefaultFont->ascent #define font_descent() Conf.DefaultFont->descent #define font_height() Conf.FontHeight +#define font_baseline() (font_ascent() + 1) /* Externs */ Index: conf.c =================================================================== RCS file: /cvs/xenocara/app/cwm/conf.c,v retrieving revision 1.70 diff -u conf.c --- conf.c 25 Aug 2009 12:05:11 -0000 1.70 +++ conf.c 11 Sep 2009 13:01:58 -0000 @@ -74,14 +74,20 @@ for (i = 0; i < CWM_COLOR_MAX; i++) { xu_freecolor(sc, sc->color[i].pixel); sc->color[i].pixel = xu_getcolor(sc, c->color[i].name); + + xfree(sc->color[i].name); + sc->color[i].name = xstrdup(c->color[i].name); } } void conf_reload(struct conf *c) { + struct screen_ctx *sc; struct client_ctx *cc; + sc = screen_current(); + if (parse_config(c->conf_path, c) == -1) { warnx("config file %s has errors, not reloading", c->conf_path); return; @@ -91,6 +97,17 @@ TAILQ_FOREACH(cc, &Clientq, entry) client_draw_border(cc); conf_font(c); + + XDestroyWindow(X_Dpy, sc->menuwin); + XFreeGC(X_Dpy, sc->gc); + menu_init(sc); + + XftDrawDestroy(sc->xftdraw); + XftColorFree(X_Dpy, DefaultVisual(X_Dpy, sc->which), + DefaultColormap(X_Dpy, sc->which), &sc->xftcolorfg); + XftColorFree(X_Dpy, DefaultVisual(X_Dpy, sc->which), + DefaultColormap(X_Dpy, sc->which), &sc->xftcolorbg); + font_init(sc); } static struct { @@ -202,6 +219,10 @@ xstrdup(CONF_COLOR_MENUFG); c->color[CWM_COLOR_BG_MENU].name = xstrdup(CONF_COLOR_MENUBG); + c->color[CWM_COLOR_FG_FONT].name = + xstrdup(CONF_COLOR_FONTFG); + c->color[CWM_COLOR_BG_FONT].name = + xstrdup(CONF_COLOR_FONTBG); c->DefaultFontName = xstrdup(DEFAULTFONTNAME); } Index: cwmrc.5 =================================================================== RCS file: /cvs/xenocara/app/cwm/cwmrc.5,v retrieving revision 1.28 diff -u cwmrc.5 --- cwmrc.5 24 Aug 2009 23:54:41 -0000 1.28 +++ cwmrc.5 11 Sep 2009 13:01:58 -0000 @@ -96,6 +96,14 @@ .It Ic color ungroupborder Ar color Set the color of the border while ungrouping a window. .Pp +.It Ic color primary Ar foreground background +Set the primary colors of the menus. These are for example used for the not +selected entries in the application menu. +.Pp +.It Ic color secondary Ar foreground background +Set the secondary colors of the menus. These are for example used to highlight +the currently selected entry in the application menu. +.Pp .It Ic command Ar name path Every .Ar name Index: font.c =================================================================== RCS file: /cvs/xenocara/app/cwm/font.c,v retrieving revision 1.9 diff -u font.c --- font.c 17 May 2009 23:40:57 -0000 1.9 +++ font.c 11 Sep 2009 13:01:58 -0000 @@ -28,8 +28,14 @@ errx(1, "XftDrawCreate"); if (!XftColorAllocName(X_Dpy, DefaultVisual(X_Dpy, sc->which), - DefaultColormap(X_Dpy, sc->which), "black", &sc->xftcolor)) + DefaultColormap(X_Dpy, sc->which), + sc->color[CWM_COLOR_FG_FONT].name, &sc->xftcolorfg)) errx(1, "XftColorAllocName"); + + if (!XftColorAllocName(X_Dpy, DefaultVisual(X_Dpy, sc->which), + DefaultColormap(X_Dpy, sc->which), + sc->color[CWM_COLOR_BG_FONT].name, &sc->xftcolorbg)) + errx(1, "XftColorAllocName"); } int @@ -45,12 +51,12 @@ void font_draw(struct screen_ctx *sc, const char *text, int len, - Drawable d, int x, int y) + Drawable d, int x, int y, int fg) { XftDrawChange(sc->xftdraw, d); /* Really needs to be UTF8'd. */ - XftDrawString8(sc->xftdraw, &sc->xftcolor, Conf.DefaultFont, x, y, - (const FcChar8*)text, len); + XftDrawString8(sc->xftdraw, fg ? &sc->xftcolorfg : &sc->xftcolorbg, + Conf.DefaultFont, x, y, (const FcChar8*)text, len); } XftFont * Index: menu.c =================================================================== RCS file: /cvs/xenocara/app/cwm/menu.c,v retrieving revision 1.13 diff -u menu.c --- menu.c 5 Sep 2009 14:10:11 -0000 1.13 +++ menu.c 11 Sep 2009 13:01:58 -0000 @@ -42,7 +42,7 @@ 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 *, @@ -59,10 +59,9 @@ sc->color[CWM_COLOR_BG_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.foreground = sc->color[CWM_COLOR_FG_MENU].pixel; gv.background = sc->color[CWM_COLOR_BG_MENU].pixel; - gv.function = GXxor; + gv.function = GXcopy; sc->gc = XCreateGC(X_Dpy, sc->menuwin, GCForeground|GCBackground|GCFunction, &gv); @@ -146,7 +145,7 @@ 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)) @@ -264,6 +263,7 @@ { struct menu *mi; int n, dy, xsave, ysave; + char *text; if (mc->list) { if (TAILQ_EMPTY(resultq) && mc->list) { @@ -289,8 +289,6 @@ } TAILQ_FOREACH(mi, resultq, resultentry) { - char *text; - if (mc->print != NULL) { (*mc->print)(mi, mc->listing); text = mi->print; @@ -326,42 +324,86 @@ if (mc->hasprompt) { font_draw(sc, mc->dispstr, strlen(mc->dispstr), sc->menuwin, - 0, font_ascent() + 1); + 0, font_baseline(), 0); n = 1; } else n = 0; TAILQ_FOREACH(mi, resultq, resultentry) { - char *text = mi->print[0] != '\0' ? + text = mi->print[0] != '\0' ? mi->print : mi->text; font_draw(sc, text, MIN(strlen(text), MENU_MAXENTRY), - sc->menuwin, 0, n*font_height() + font_ascent() + 1); + sc->menuwin, 0, n * font_height() + font_baseline(), 0); n++; } - if (mc->hasprompt && n > 1) + if (mc->hasprompt && n > 1) { + mi = TAILQ_FIRST(resultq); + text = mi->print[0] != '\0' ? mi->print : mi->text; + XFillRectangle(X_Dpy, sc->menuwin, sc->gc, 0, font_height(), mc->width, font_height()); + font_draw(sc, text, MIN(strlen(text), MENU_MAXENTRY), + sc->menuwin, 0, font_height() + font_baseline(), 1); + } - if (mc->noresult) + if (mc->noresult) { XFillRectangle(X_Dpy, sc->menuwin, sc->gc, 0, 0, mc->width, font_height()); + font_draw(sc, mc->dispstr, strlen(mc->dispstr), + sc->menuwin, 0, font_baseline(), 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) { + struct menu *mi = NULL; + int i; + char *prevtext = NULL; + char *entrytext = NULL; + mc->prev = mc->entry; mc->entry = menu_calc_entry(sc, mc, e->xbutton.x, e->xbutton.y); - if (mc->prev != -1) - XFillRectangle(X_Dpy, sc->menuwin, sc->gc, 0, - font_height() * mc->prev, mc->width, font_height()); + i = 0; + if (mc->hasprompt) + i = 1; + + TAILQ_FOREACH(mi, resultq, resultentry) { + if ((mc->prev != -1 && prevtext == NULL) || + (mc->entry != -1 && entrytext == NULL)) { + if (i == mc->prev) + prevtext = mi->print[0] != '\0' ? + mi->print : mi->text; + if (i == mc->entry) + entrytext = mi->print[0] != '\0' ? + mi->print : mi->text; + } else + break; + + i++; + } + + /* The previous entry has been selected with the mouse. */ + if (mc->prev != -1 && !(mc->hasprompt && mc->prev == 1)) { + XClearArea(X_Dpy, sc->menuwin, 0, + font_height() * mc->prev, mc->width, font_height(), 0); + font_draw(sc, prevtext, MIN(strlen(prevtext), MENU_MAXENTRY), + sc->menuwin, 0, mc->prev * font_height() + font_baseline(), + 0); + } + if (mc->entry != -1) { xu_ptr_regrab(MenuGrabMask, Cursor_select); + XFillRectangle(X_Dpy, sc->menuwin, sc->gc, 0, font_height() * mc->entry, mc->width, font_height()); + font_draw(sc, entrytext, MIN(strlen(entrytext), MENU_MAXENTRY), + sc->menuwin, 0, mc->entry * font_height() + font_baseline(), + 1); } else xu_ptr_regrab(MenuGrabMask, Cursor_default); } Index: mousefunc.c =================================================================== RCS file: /cvs/xenocara/app/cwm/mousefunc.c,v retrieving revision 1.15 diff -u mousefunc.c --- mousefunc.c 27 Aug 2009 01:38:08 -0000 1.15 +++ mousefunc.c 11 Sep 2009 13:01:58 -0000 @@ -62,9 +62,9 @@ XReparentWindow(X_Dpy, sc->menuwin, cc->win, 0, 0); XClearWindow(X_Dpy, sc->menuwin); font_draw(sc, cc->name, strlen(cc->name), sc->menuwin, - 2, font_ascent() + 1); + 2, font_baseline(), 0); font_draw(sc, asize, strlen(asize), sc->menuwin, - width / 2 - width_size / 2, height + font_ascent() + 1); + width / 2 - width_size / 2, height + font_baseline(), 0); } void Index: parse.y =================================================================== RCS file: /cvs/xenocara/app/cwm/parse.y,v retrieving revision 1.21 diff -u parse.y --- parse.y 20 Jun 2009 00:22:39 -0000 1.21 +++ parse.y 11 Sep 2009 13:01:58 -0000 @@ -70,6 +70,7 @@ %token COLOR %token ACTIVEBORDER INACTIVEBORDER %token GROUPBORDER UNGROUPBORDER +%token PRIMARY SECONDARY %token ERROR %token <v.string> STRING %token <v.number> NUMBER @@ -194,6 +195,18 @@ free(conf->color[CWM_COLOR_BORDER_UNGROUP].name); conf->color[CWM_COLOR_BORDER_UNGROUP].name = $2; } + | PRIMARY STRING STRING { + free(conf->color[CWM_COLOR_BG_FONT].name); + free(conf->color[CWM_COLOR_BG_MENU].name); + conf->color[CWM_COLOR_BG_FONT].name = $2; + conf->color[CWM_COLOR_BG_MENU].name = $3; + } + | SECONDARY STRING STRING { + free(conf->color[CWM_COLOR_FG_FONT].name); + free(conf->color[CWM_COLOR_FG_MENU].name); + conf->color[CWM_COLOR_FG_FONT].name = $2; + conf->color[CWM_COLOR_FG_MENU].name = $3; + } ; %% @@ -241,6 +254,8 @@ { "mousebind", MOUSEBIND}, { "moveamount", MOVEAMOUNT}, { "no", NO}, + { "primary", PRIMARY}, + { "secondary", SECONDARY}, { "sticky", STICKY}, { "ungroupborder", UNGROUPBORDER}, { "yes", YES} -- Simon Nicolussi, <simon.nicolu...@student.uibk.ac.at> http://homepage.uibk.ac.at/~csag9583/