non-trivial menu drawing rewrite, moving to Xft and solving various

font/color drawing issues; from Alexander Polakov
This commit is contained in:
okan 2012-12-17 02:28:45 +00:00
parent 5fd3540f40
commit 52982ae188
9 changed files with 142 additions and 74 deletions

View File

@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: calmwm.c,v 1.69 2012/11/29 16:50:03 okan Exp $
* $OpenBSD: calmwm.c,v 1.70 2012/12/17 02:28:45 okan Exp $
*/
#include <sys/param.h>
@ -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);
}

View File

@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: calmwm.h,v 1.163 2012/11/29 03:54:46 okan Exp $
* $OpenBSD: calmwm.h,v 1.164 2012/12/17 02:28:45 okan Exp $
*/
#ifndef _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 *);

View File

@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: conf.c,v 1.110 2012/11/28 14:14:44 okan Exp $
* $OpenBSD: conf.c,v 1.111 2012/12/17 02:28:45 okan Exp $
*/
#include <sys/param.h>
@ -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));

View File

@ -1,4 +1,4 @@
.\" $OpenBSD: cwmrc.5,v 1.49 2012/11/29 04:25:49 okan Exp $
.\" $OpenBSD: cwmrc.5,v 1.50 2012/12/17 02:28:45 okan Exp $
.\"
.\" Copyright (c) 2004,2005 Marius Aamodt Eriksen <marius@monkey.org>
.\"
@ -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 29 2012 $
.Dd $Mdocdate: December 17 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

View File

@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: font.c,v 1.20 2012/11/28 14:14:44 okan Exp $
* $OpenBSD: font.c,v 1.21 2012/12/17 02:28:45 okan Exp $
*/
#include <sys/param.h>
@ -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);
}

View File

@ -16,7 +16,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: menu.c,v 1.45 2012/11/14 21:12:24 okan Exp $
* $OpenBSD: menu.c,v 1.46 2012/12/17 02:28:45 okan Exp $
*/
#include <sys/param.h>
@ -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'))
XFillRectangle(X_Dpy, sc->menuwin, sc->gc,
0, font_height(sc), mc->width, font_height(sc));
if (mc->noresult)
XFillRectangle(X_Dpy, sc->menuwin, sc->gc,
0, 0, mc->width, font_height(sc));
if (mc->hasprompt && n > 1 && (mc->searchstr[0] != '\0')) {
mc->entry = 1;
menu_draw_entry(sc, mc, resultq, mc->entry, 1);
}
}
static void
menu_handle_move(XEvent *e, struct menu_ctx *mc, struct screen_ctx *sc)
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)
i = 1;
TAILQ_FOREACH(mi, resultq, resultentry)
if (entry == i++)
break;
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,
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;

View File

@ -16,7 +16,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: mousefunc.c,v 1.40 2012/11/09 03:52:02 okan Exp $
* $OpenBSD: mousefunc.c,v 1.41 2012/12/17 02:28:45 okan Exp $
*/
#include <sys/param.h>
@ -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);
}

View File

@ -1,4 +1,4 @@
/* $OpenBSD: parse.y,v 1.34 2012/10/31 22:06:24 okan Exp $ */
/* $OpenBSD: parse.y,v 1.35 2012/12/17 02:28:45 okan Exp $ */
/*
* Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
@ -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;
}

View File

@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD: xutil.c,v 1.49 2012/11/09 03:52:02 okan Exp $
* $OpenBSD: xutil.c,v 1.50 2012/12/17 02:28:45 okan Exp $
*/
#include <sys/param.h>
@ -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;
}