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/

Reply via email to