cvsimport

This commit is contained in:
Christian Neukirchen 2013-05-29 22:37:37 +02:00
commit 5515a365ba
14 changed files with 486 additions and 516 deletions

View File

@ -7,11 +7,11 @@ PREFIX= /usr/local
SRCS= calmwm.c screen.c xmalloc.c client.c menu.c \
search.c util.c xutil.c conf.c xevents.c group.c \
kbfunc.c mousefunc.c font.c parse.y
kbfunc.c mousefunc.c parse.y
OBJS= calmwm.o screen.o xmalloc.o client.o menu.o \
search.o util.o xutil.o conf.o xevents.o group.o \
kbfunc.o mousefunc.o font.o strlcpy.o strlcat.o y.tab.o \
kbfunc.o mousefunc.o strlcpy.o strlcat.o y.tab.o \
strtonum.o fgetln.o
CPPFLAGS+= `pkg-config --cflags fontconfig x11 xft xinerama xrandr`

View File

@ -144,7 +144,6 @@ dpy_init(const char *dpyname)
static void
x_setup(void)
{
struct keybinding *kb;
int i;
Cursor_default = XCreateFontCursor(X_Dpy, XC_X_cursor);
@ -155,13 +154,6 @@ x_setup(void)
for (i = 0; i < ScreenCount(X_Dpy); i++)
screen_init(i);
/*
* XXX key grabs weren't done before, since Screenq was empty,
* do them here for now (this needs changing).
*/
TAILQ_FOREACH(kb, &Conf.keybindingq, entry)
conf_grab(&Conf, kb);
}
static void
@ -181,7 +173,7 @@ x_wmerrorhandler(Display *dpy, XErrorEvent *e)
static int
x_errorhandler(Display *dpy, XErrorEvent *e)
{
#if DEBUG
#ifdef DEBUG
char msg[80], number[80], req[80];
XGetErrorText(X_Dpy, e->error_code, msg, sizeof(msg));

View File

@ -97,20 +97,16 @@ 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 bordercolor {
enum color {
CWM_COLOR_BORDER_ACTIVE,
CWM_COLOR_BORDER_INACTIVE,
CWM_COLOR_BORDER_GROUP,
CWM_COLOR_BORDER_UNGROUP,
CWM_COLOR_BORDER_MAX
CWM_COLOR_MENU_FG,
CWM_COLOR_MENU_BG,
CWM_COLOR_MENU_FONT,
CWM_COLOR_MENU_FONT_SEL,
CWM_COLOR_MAX
};
struct geom {
@ -133,6 +129,11 @@ struct winname {
};
TAILQ_HEAD(winname_q, winname);
enum wm_protocols {
_WM_DELETE_WINDOW = 0x0001,
_WM_TAKE_FOCUS = 0x0002,
};
struct client_ctx {
TAILQ_ENTRY(client_ctx) entry;
TAILQ_ENTRY(client_ctx) group_entry;
@ -159,9 +160,7 @@ struct client_ctx {
int x; /* x position */
int y; /* y position */
} ptr;
#define CLIENT_PROTO_DELETE 0x0001
#define CLIENT_PROTO_TAKEFOCUS 0x0002
int xproto;
enum wm_protocols xproto;
#define CLIENT_HIDDEN 0x0001
#define CLIENT_IGNORE 0x0002
#define CLIENT_VMAXIMIZED 0x0004
@ -222,13 +221,12 @@ struct screen_ctx {
Colormap colormap;
Window rootwin;
Window menuwin;
unsigned long color[CWM_COLOR_BORDER_MAX];
int cycling;
struct geom view; /* viewable area */
struct geom work; /* workable area, gap-applied */
struct gap gap;
struct cycle_entry_q mruq;
XftColor xftcolor[CWM_COLOR_MENU_MAX];
XftColor xftcolor[CWM_COLOR_MAX];
XftDraw *xftdraw;
XftFont *xftfont;
int xinerama_no;
@ -247,8 +245,8 @@ struct keybinding {
TAILQ_ENTRY(keybinding) entry;
void (*callback)(struct client_ctx *, union arg *);
union arg argument;
int modmask;
int keysym;
u_int modmask;
KeySym keysym;
int keycode;
#define KBFLAG_NEEDCLIENT 0x0001
int flags;
@ -259,8 +257,8 @@ TAILQ_HEAD(keybinding_q, keybinding);
struct mousebinding {
TAILQ_ENTRY(mousebinding) entry;
void (*callback)(struct client_ctx *, void *);
int modmask;
int button;
u_int modmask;
u_int button;
#define MOUSEBIND_CTX_ROOT 0x0001
#define MOUSEBIND_CTX_WIN 0x0002
int context;
@ -302,8 +300,7 @@ struct conf {
#define CONF_SNAPDIST 0
int snapdist;
struct gap gap;
char *color[CWM_COLOR_BORDER_MAX];
char *menucolor[CWM_COLOR_MENU_MAX];
char *color[CWM_COLOR_MAX];
char termpath[MAXPATHLEN];
char lockpath[MAXPATHLEN];
char known_hosts[MAXPATHLEN];
@ -343,7 +340,7 @@ void client_lower(struct client_ctx *);
void client_map(struct client_ctx *);
void client_maximize(struct client_ctx *);
void client_move(struct client_ctx *);
struct client_ctx *client_new(Window, struct screen_ctx *, int);
struct client_ctx *client_init(Window, struct screen_ctx *, int);
void client_ptrsave(struct client_ctx *);
void client_ptrwarp(struct client_ctx *);
void client_raise(struct client_ctx *);
@ -360,7 +357,6 @@ void client_warp(struct client_ctx *);
void group_alltoggle(struct screen_ctx *);
void group_autogroup(struct client_ctx *);
void group_client_delete(struct client_ctx *);
void group_cycle(struct screen_ctx *, int);
void group_hidetoggle(struct screen_ctx *, int);
void group_init(struct screen_ctx *);
@ -442,7 +438,6 @@ struct menu *menu_filter(struct screen_ctx *, struct menu_q *,
char *, char *, int,
void (*)(struct menu_q *, struct menu_q *, char *),
void (*)(struct menu *, int));
void menu_init(struct screen_ctx *);
void menuq_clear(struct menu_q *);
int parse_config(const char *, struct conf *);
@ -452,24 +447,12 @@ void conf_bindname(struct conf *, char *, char *);
void conf_clear(struct conf *);
void conf_client(struct client_ctx *);
void conf_cmd_add(struct conf *, char *, char *);
void conf_color(struct conf *, struct screen_ctx *);
void conf_font(struct conf *, struct screen_ctx *);
void conf_gap(struct conf *, struct screen_ctx *);
void conf_grab(struct conf *, struct keybinding *);
void conf_grab_mouse(struct client_ctx *);
void conf_grab_kbd(Window);
void conf_grab_mouse(Window);
void conf_init(struct conf *);
void conf_ignore(struct conf *, char *);
void conf_mousebind(struct conf *, char *, char *);
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, int);
u_int font_height(struct screen_ctx *);
void font_init(struct screen_ctx *, const char *,
const char **);
int font_width(struct screen_ctx *, const char *, int);
int conf_mousebind(struct conf *, char *, char *);
void conf_screen(struct screen_ctx *);
void xev_loop(void);
@ -477,21 +460,21 @@ void xu_btn_grab(Window, int, u_int);
void xu_btn_ungrab(Window, int, u_int);
void xu_configure(struct client_ctx *);
void xu_getatoms(void);
unsigned long xu_getcolor(struct screen_ctx *, char *);
int xu_getprop(Window, Atom, Atom, long, u_char **);
int xu_get_wm_state(Window, int *);
int xu_getstrprop(Window, Atom, char **);
void xu_key_grab(Window, int, int);
void xu_key_ungrab(Window, int, int);
void xu_key_grab(Window, u_int, KeySym);
void xu_ptr_getpos(Window, int *, int *);
int xu_ptr_grab(Window, int, Cursor);
int xu_ptr_regrab(int, Cursor);
int xu_ptr_grab(Window, u_int, Cursor);
int xu_ptr_regrab(u_int, Cursor);
void xu_ptr_setpos(Window, int, int);
void xu_ptr_ungrab(void);
void xu_sendmsg(Window, Atom, long);
void xu_sendmsg(Window, Atom, Atom);
void xu_set_wm_state(Window win, int);
void xu_xorcolor(XRenderColor, XRenderColor,
XRenderColor *);
void xu_xft_draw(struct screen_ctx *, const char *,
int, int, int);
int xu_xft_width(XftFont *, const char *, int);
void xu_xorcolor(XftColor, XftColor, XftColor *);
void xu_ewmh_net_supported(struct screen_ctx *);
void xu_ewmh_net_supported_wm_check(struct screen_ctx *);
@ -508,6 +491,11 @@ void xu_ewmh_net_desktop_names(struct screen_ctx *, char *,
int);
void xu_ewmh_net_wm_desktop(struct client_ctx *);
Atom *xu_ewmh_get_net_wm_state(struct client_ctx *, int *);
void xu_ewmh_handle_net_wm_state_msg(struct client_ctx *,
int, Atom , Atom);
void xu_ewmh_set_net_wm_state(struct client_ctx *);
void xu_ewmh_restore_net_wm_state(struct client_ctx *);
void u_exec(char *);
void u_spawn(char *);
@ -542,6 +530,7 @@ enum {
WM_PROTOCOLS,
_MOTIF_WM_HINTS,
UTF8_STRING,
WM_CHANGE_STATE,
CWMH_NITEMS
};
enum {
@ -559,8 +548,18 @@ enum {
_NET_WORKAREA,
_NET_WM_NAME,
_NET_WM_DESKTOP,
_NET_CLOSE_WINDOW,
_NET_WM_STATE,
#define _NET_WM_STATES_NITEMS 2
_NET_WM_STATE_MAXIMIZED_VERT,
_NET_WM_STATE_MAXIMIZED_HORZ,
EWMH_NITEMS
};
enum {
_NET_WM_STATE_REMOVE,
_NET_WM_STATE_ADD,
_NET_WM_STATE_TOGGLE
};
struct atom_ctx {
char *name;
Atom atom;

View File

@ -36,7 +36,7 @@ static struct client_ctx *client_mruprev(struct client_ctx *);
static void client_mtf(struct client_ctx *);
static void client_none(struct screen_ctx *);
static void client_placecalc(struct client_ctx *);
static void client_update(struct client_ctx *);
static void client_wm_protocols(struct client_ctx *);
static void client_getmwmhints(struct client_ctx *);
static int client_inbound(struct client_ctx *, int, int);
@ -55,7 +55,7 @@ client_find(Window win)
}
struct client_ctx *
client_new(Window win, struct screen_ctx *sc, int mapped)
client_init(Window win, struct screen_ctx *sc, int mapped)
{
struct client_ctx *cc;
XClassHint xch;
@ -132,7 +132,8 @@ client_new(Window win, struct screen_ctx *sc, int mapped)
xu_ewmh_net_client_list(sc);
client_update(cc);
client_wm_protocols(cc);
xu_ewmh_restore_net_wm_state(cc);
if (mapped)
group_autogroup(cc);
@ -149,13 +150,10 @@ client_delete(struct client_ctx *cc)
struct screen_ctx *sc = cc->sc;
struct winname *wn;
group_client_delete(cc);
XGrabServer(X_Dpy);
cc->state = WithdrawnState;
xu_set_wm_state(cc->win, cc->state);
XRemoveFromSaveSet(X_Dpy, cc->win);
XSync(X_Dpy, False);
XUngrabServer(X_Dpy);
@ -164,6 +162,9 @@ client_delete(struct client_ctx *cc)
xu_ewmh_net_client_list(sc);
if (cc->group != NULL)
TAILQ_REMOVE(&cc->group->clients, cc, group_entry);
if (cc == client_current())
client_none(sc);
@ -212,7 +213,7 @@ client_setactive(struct client_ctx *cc, int fg)
XInstallColormap(X_Dpy, cc->colormap);
XSetInputFocus(X_Dpy, cc->win,
RevertToPointerRoot, CurrentTime);
conf_grab_mouse(cc);
conf_grab_mouse(cc->win);
/*
* If we're in the middle of alt-tabbing, don't change
* the order please.
@ -301,6 +302,7 @@ client_maximize(struct client_ctx *cc)
resize:
client_resize(cc, 0);
xu_ewmh_set_net_wm_state(cc);
}
void
@ -341,6 +343,7 @@ client_vmaximize(struct client_ctx *cc)
resize:
client_resize(cc, 0);
xu_ewmh_set_net_wm_state(cc);
}
void
@ -381,6 +384,7 @@ client_hmaximize(struct client_ctx *cc)
resize:
client_resize(cc, 0);
xu_ewmh_set_net_wm_state(cc);
}
void
@ -389,6 +393,7 @@ client_resize(struct client_ctx *cc, int reset)
if (reset) {
cc->flags &= ~CLIENT_MAXIMIZED;
cc->bwidth = Conf.bwidth;
xu_ewmh_set_net_wm_state(cc);
}
client_draw_border(cc);
@ -480,46 +485,43 @@ client_draw_border(struct client_ctx *cc)
if (cc->active)
switch (cc->flags & CLIENT_HIGHLIGHT) {
case CLIENT_GROUP:
pixel = sc->color[CWM_COLOR_BORDER_GROUP];
pixel = sc->xftcolor[CWM_COLOR_BORDER_GROUP].pixel;
break;
case CLIENT_UNGROUP:
pixel = sc->color[CWM_COLOR_BORDER_UNGROUP];
pixel = sc->xftcolor[CWM_COLOR_BORDER_UNGROUP].pixel;
break;
default:
pixel = sc->color[CWM_COLOR_BORDER_ACTIVE];
pixel = sc->xftcolor[CWM_COLOR_BORDER_ACTIVE].pixel;
break;
}
else
pixel = sc->color[CWM_COLOR_BORDER_INACTIVE];
pixel = sc->xftcolor[CWM_COLOR_BORDER_INACTIVE].pixel;
XSetWindowBorderWidth(X_Dpy, cc->win, cc->bwidth);
XSetWindowBorder(X_Dpy, cc->win, pixel);
}
static void
client_update(struct client_ctx *cc)
client_wm_protocols(struct client_ctx *cc)
{
Atom *p;
int i;
long n;
int i, j;
if ((n = xu_getprop(cc->win, cwmh[WM_PROTOCOLS].atom,
XA_ATOM, 20L, (u_char **)&p)) <= 0)
return;
for (i = 0; i < n; i++)
if (p[i] == cwmh[WM_DELETE_WINDOW].atom)
cc->xproto |= CLIENT_PROTO_DELETE;
else if (p[i] == cwmh[WM_TAKE_FOCUS].atom)
cc->xproto |= CLIENT_PROTO_TAKEFOCUS;
XFree(p);
if (XGetWMProtocols(X_Dpy, cc->win, &p, &j)) {
for (i = 0; i < j; i++) {
if (p[i] == cwmh[WM_DELETE_WINDOW].atom)
cc->xproto |= _WM_DELETE_WINDOW;
else if (p[i] == cwmh[WM_TAKE_FOCUS].atom)
cc->xproto |= _WM_TAKE_FOCUS;
}
XFree(p);
}
}
void
client_send_delete(struct client_ctx *cc)
{
if (cc->xproto & CLIENT_PROTO_DELETE)
if (cc->xproto & _WM_DELETE_WINDOW)
xu_sendmsg(cc->win,
cwmh[WM_PROTOCOLS].atom, cwmh[WM_DELETE_WINDOW].atom);
else

178
conf.c
View File

@ -84,39 +84,63 @@ conf_ignore(struct conf *c, char *val)
TAILQ_INSERT_TAIL(&c->ignoreq, wm, entry);
}
void
conf_gap(struct conf *c, struct screen_ctx *sc)
{
sc->gap = c->gap;
}
void
conf_font(struct conf *c, struct screen_ctx *sc)
{
font_init(sc, c->font, (const char **)c->menucolor);
}
static char *menu_color_binds[CWM_COLOR_MENU_MAX] = {
static char *color_binds[CWM_COLOR_MAX] = {
"#CCCCCC", /* CWM_COLOR_BORDER_ACTIVE */
"#666666", /* CWM_COLOR_BORDER_INACTIVE */
"blue", /* CWM_COLOR_BORDER_GROUP */
"red", /* CWM_COLOR_BORDER_UNGROUP */
"black", /* CWM_COLOR_MENU_FG */
"white", /* CWM_COLOR_MENU_BG */
"black", /* CWM_COLOR_MENU_FONT */
"", /* CWM_COLOR_MENU_FONT_SEL */
};
static char *color_binds[CWM_COLOR_BORDER_MAX] = {
"#CCCCCC", /* CWM_COLOR_BORDER_ACTIVE */
"#666666", /* CWM_COLOR_BORDER_INACTIVE */
"blue", /* CWM_COLOR_BORDER_GROUP */
"red", /* CWM_COLOR_BORDER_UNGROUP */
};
void
conf_color(struct conf *c, struct screen_ctx *sc)
conf_screen(struct screen_ctx *sc)
{
int i;
int i;
XftColor xc;
for (i = 0; i < CWM_COLOR_BORDER_MAX; i++)
sc->color[i] = xu_getcolor(sc, c->color[i]);
sc->gap = Conf.gap;
sc->xftfont = XftFontOpenName(X_Dpy, sc->which, Conf.font);
if (sc->xftfont == NULL)
errx(1, "XftFontOpenName");
for (i = 0; i < CWM_COLOR_MAX; i++) {
if (*Conf.color[i] == '\0')
break;
if (XftColorAllocName(X_Dpy, sc->visual, sc->colormap,
Conf.color[i], &xc)) {
sc->xftcolor[i] = xc;
XftColorFree(X_Dpy, sc->visual, sc->colormap, &xc);
} else {
warnx("XftColorAllocName: '%s'", Conf.color[i]);
XftColorAllocName(X_Dpy, sc->visual, sc->colormap,
color_binds[i], &sc->xftcolor[i]);
}
}
if (i == CWM_COLOR_MAX)
return;
xu_xorcolor(sc->xftcolor[CWM_COLOR_MENU_BG],
sc->xftcolor[CWM_COLOR_MENU_FG], &xc);
xu_xorcolor(sc->xftcolor[CWM_COLOR_MENU_FONT], xc, &xc);
if (!XftColorAllocValue(X_Dpy, sc->visual, sc->colormap,
&xc.color, &sc->xftcolor[CWM_COLOR_MENU_FONT_SEL]))
warnx("XftColorAllocValue: '%s'", Conf.color[i]);
sc->menuwin = XCreateSimpleWindow(X_Dpy, sc->rootwin, 0, 0, 1, 1,
Conf.bwidth,
sc->xftcolor[CWM_COLOR_MENU_FG].pixel,
sc->xftcolor[CWM_COLOR_MENU_BG].pixel);
sc->xftdraw = XftDrawCreate(X_Dpy, sc->menuwin,
sc->visual, sc->colormap);
if (sc->xftdraw == NULL)
errx(1, "XftDrawCreate");
conf_grab_kbd(sc->rootwin);
}
static struct {
@ -195,7 +219,7 @@ m_binds[] = {
void
conf_init(struct conf *c)
{
int i;
u_int i;
bzero(c, sizeof(*c));
@ -218,9 +242,6 @@ conf_init(struct conf *c)
for (i = 0; i < nitems(color_binds); i++)
c->color[i] = xstrdup(color_binds[i]);
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));
@ -268,7 +289,7 @@ conf_clear(struct conf *c)
free(mb);
}
for (i = 0; i < CWM_COLOR_BORDER_MAX; i++)
for (i = 0; i < CWM_COLOR_MAX; i++)
free(c->color[i]);
free(c->font);
@ -413,37 +434,6 @@ static struct {
{.i = CWM_TILE_VERT } },
};
/*
* The following two functions are used when grabbing and ungrabbing keys for
* bindings
*/
/*
* Grab key combination on all screens and add to the global queue
*/
void
conf_grab(struct conf *c, struct keybinding *kb)
{
extern struct screen_ctx_q Screenq;
struct screen_ctx *sc;
TAILQ_FOREACH(sc, &Screenq, entry)
xu_key_grab(sc->rootwin, kb->modmask, kb->keysym);
}
/*
* Ungrab key combination from all screens and remove from global queue
*/
void
conf_ungrab(struct conf *c, struct keybinding *kb)
{
extern struct screen_ctx_q Screenq;
struct screen_ctx *sc;
TAILQ_FOREACH(sc, &Screenq, entry)
xu_key_ungrab(sc->rootwin, kb->modmask, kb->keysym);
}
static struct {
char chr;
int mask;
@ -459,7 +449,7 @@ conf_bindname(struct conf *c, char *name, char *binding)
{
struct keybinding *current_binding;
char *substring, *tmp;
int i;
u_int i;
current_binding = xcalloc(1, sizeof(*current_binding));
@ -507,7 +497,6 @@ conf_bindname(struct conf *c, char *name, char *binding)
current_binding->flags = name_to_kbfunc[i].flags;
current_binding->argument = name_to_kbfunc[i].argument;
current_binding->argtype |= ARG_INT;
conf_grab(c, current_binding);
TAILQ_INSERT_TAIL(&c->keybindingq, current_binding, entry);
return;
}
@ -516,7 +505,6 @@ conf_bindname(struct conf *c, char *name, char *binding)
current_binding->flags = 0;
current_binding->argument.c = xstrdup(binding);
current_binding->argtype |= ARG_CHAR;
conf_grab(c, current_binding);
TAILQ_INSERT_TAIL(&c->keybindingq, current_binding, entry);
}
@ -532,7 +520,6 @@ conf_unbind(struct conf *c, struct keybinding *unbind)
if ((key->keycode != 0 && key->keysym == NoSymbol &&
key->keycode == unbind->keycode) ||
key->keysym == unbind->keysym) {
conf_ungrab(c, key);
TAILQ_REMOVE(&c->keybindingq, key, entry);
if (key->argtype & ARG_CHAR)
free(key->argument.c);
@ -558,13 +545,16 @@ static struct {
{ "menu_cmd", mousefunc_menu_cmd, MOUSEBIND_CTX_ROOT },
};
void
static unsigned int mouse_btns[] = { Button1, Button2, Button3 };
int
conf_mousebind(struct conf *c, char *name, char *binding)
{
struct mousebinding *current_binding;
char *substring, *tmp;
u_int button;
const char *errstr;
int i;
u_int i;
current_binding = xcalloc(1, sizeof(*current_binding));
@ -581,16 +571,27 @@ conf_mousebind(struct conf *c, char *name, char *binding)
} else
substring = name;
current_binding->button = strtonum(substring, 1, 3, &errstr);
button = strtonum(substring, 1, 3, &errstr);
if (errstr)
warnx("number of buttons is %s: %s", errstr, substring);
warnx("button number is %s: %s", errstr, substring);
for (i = 0; i < nitems(mouse_btns); i++) {
if (button == mouse_btns[i]) {
current_binding->button = button;
break;
}
}
if (!current_binding->button || errstr) {
free(current_binding);
return (0);
}
/* We now have the correct binding, remove duplicates. */
conf_mouseunbind(c, current_binding);
if (strcmp("unmap", binding) == 0) {
free(current_binding);
return;
return (1);
}
for (i = 0; i < nitems(name_to_mousefunc); i++) {
@ -600,8 +601,10 @@ conf_mousebind(struct conf *c, char *name, char *binding)
current_binding->context = name_to_mousefunc[i].context;
current_binding->callback = name_to_mousefunc[i].handler;
TAILQ_INSERT_TAIL(&c->mousebindingq, current_binding, entry);
return;
return (1);
}
return (0);
}
static void
@ -620,33 +623,26 @@ conf_mouseunbind(struct conf *c, struct mousebinding *unbind)
}
}
/*
* Grab the mouse buttons that we need for bindings for this client
*/
void
conf_grab_mouse(struct client_ctx *cc)
conf_grab_mouse(Window win)
{
struct mousebinding *mb;
int button;
TAILQ_FOREACH(mb, &Conf.mousebindingq, entry) {
if (mb->context != MOUSEBIND_CTX_WIN)
continue;
switch(mb->button) {
case 1:
button = Button1;
break;
case 2:
button = Button2;
break;
case 3:
button = Button3;
break;
default:
warnx("strange button in mousebinding\n");
continue;
}
xu_btn_grab(cc->win, mb->modmask, button);
xu_btn_grab(win, mb->modmask, mb->button);
}
}
void
conf_grab_kbd(Window win)
{
struct keybinding *kb;
XUngrabKey(X_Dpy, AnyKey, AnyModifier, win);
TAILQ_FOREACH(kb, &Conf.keybindingq, entry)
xu_key_grab(win, kb->modmask, kb->keysym);
}

105
font.c
View File

@ -1,105 +0,0 @@
/*
* calmwm - the calm window manager
*
* Copyright (c) 2005 Marius Eriksen <marius@monkey.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* $OpenBSD$
*/
#include <sys/param.h>
#include "queue.h"
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "calmwm.h"
int
font_ascent(struct screen_ctx *sc)
{
return (sc->xftfont->ascent);
}
int
font_descent(struct screen_ctx *sc)
{
return (sc->xftfont->descent);
}
u_int
font_height(struct screen_ctx *sc)
{
return (sc->xftfont->height + 1);
}
void
font_init(struct screen_ctx *sc, const char *name, const char **color)
{
int i;
XRenderColor c;
sc->xftdraw = XftDrawCreate(X_Dpy, sc->rootwin,
sc->visual, sc->colormap);
if (sc->xftdraw == NULL)
errx(1, "XftDrawCreate");
sc->xftfont = XftFontOpenName(X_Dpy, sc->which, name);
if (sc->xftfont == NULL)
errx(1, "XftFontOpenName");
for (i = 0; i < CWM_COLOR_MENU_MAX; i++) {
if (*color[i] == '\0')
break;
if (!XftColorAllocName(X_Dpy, sc->visual, sc->colormap,
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, sc->visual, sc->colormap,
&c, &sc->xftcolor[CWM_COLOR_MENU_FONT_SEL]))
errx(1, "XftColorAllocValue");
}
int
font_width(struct screen_ctx *sc, const char *text, int len)
{
XGlyphInfo extents;
XftTextExtentsUtf8(X_Dpy, sc->xftfont, (const FcChar8*)text,
len, &extents);
return (extents.xOff);
}
void
font_draw(struct screen_ctx *sc, const char *text, int len,
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[color], sc->xftfont, x, y,
(const FcChar8*)text, len);
}

11
group.c
View File

@ -308,17 +308,6 @@ group_cycle(struct screen_ctx *sc, int flags)
group_setactive(sc, showgroup->shortcut);
}
/* called when a client is deleted */
void
group_client_delete(struct client_ctx *cc)
{
if (cc->group == NULL)
return;
TAILQ_REMOVE(&cc->group->clients, cc, group_entry);
cc->group = NULL; /* he he */
}
void
group_menu(XButtonEvent *e)
{

View File

@ -88,17 +88,16 @@ kbfunc_moveresize(struct client_ctx *cc, union arg *arg)
}
switch (flags & TYPEMASK) {
case CWM_MOVE:
cc->geom.y += my;
if (cc->geom.y + cc->geom.h < 0)
cc->geom.y = -cc->geom.h;
if (cc->geom.y > sc->view.h - 1)
cc->geom.y = sc->view.h - 1;
cc->geom.x += mx;
if (cc->geom.x + cc->geom.w < 0)
cc->geom.x = -cc->geom.w;
if (cc->geom.x > sc->view.w - 1)
cc->geom.x = sc->view.w - 1;
cc->geom.y += my;
if (cc->geom.y + cc->geom.h < 0)
cc->geom.y = -cc->geom.h;
if (cc->geom.y > sc->view.h - 1)
cc->geom.y = sc->view.h - 1;
cc->geom.x += client_snapcalc(cc->geom.x,
cc->geom.x + cc->geom.w + (cc->bwidth * 2),
@ -109,15 +108,15 @@ kbfunc_moveresize(struct client_ctx *cc, union arg *arg)
client_move(cc);
xu_ptr_getpos(cc->win, &x, &y);
cc->ptr.y = y + my;
cc->ptr.x = x + mx;
cc->ptr.y = y + my;
client_ptrwarp(cc);
break;
case CWM_RESIZE:
if ((cc->geom.h += my) < 1)
cc->geom.h = 1;
if ((cc->geom.w += mx) < 1)
cc->geom.w = 1;
if ((cc->geom.h += my) < 1)
cc->geom.h = 1;
client_resize(cc, 1);
/* Make sure the pointer stays within the window. */

135
menu.c
View File

@ -42,7 +42,7 @@ enum ctltype {
};
struct menu_ctx {
struct screen_ctx *sc;
struct screen_ctx *sc;
char searchstr[MENU_MAXENTRY + 1];
char dispstr[MENU_MAXENTRY*2 + 1];
char promptstr[MENU_MAXENTRY + 1];
@ -65,27 +65,16 @@ 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 menu_q *);
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 *,
struct menu_q *);
static void menu_draw(struct menu_ctx *, struct menu_q *,
struct menu_q *);
static void menu_draw_entry(struct menu_ctx *, struct menu_q *,
int, int);
static int menu_calc_entry(struct menu_ctx *, int, int);
static struct menu *menu_complete_path(struct menu_ctx *);
static int menu_keycode(XKeyEvent *, enum ctltype *,
char *);
void
menu_init(struct screen_ctx *sc)
{
sc->menuwin = XCreateSimpleWindow(X_Dpy, sc->rootwin, 0, 0, 1, 1,
Conf.bwidth,
sc->xftcolor[CWM_COLOR_MENU_FG].pixel,
sc->xftcolor[CWM_COLOR_MENU_BG].pixel);
}
static int menu_keycode(XKeyEvent *, enum ctltype *, char *);
struct menu *
menu_filter(struct screen_ctx *sc, struct menu_q *menuq, char *prompt,
@ -112,18 +101,13 @@ menu_filter(struct screen_ctx *sc, struct menu_q *menuq, char *prompt,
mc.sc = sc;
mc.flags = flags;
if (prompt == NULL) {
evmask = MENUMASK;
mc.promptstr[0] = '\0';
mc.list = 1;
} else {
evmask = MENUMASK | KEYMASK; /* only accept keys if prompt */
(void)snprintf(mc.promptstr, sizeof(mc.promptstr), "%s%s",
prompt, PROMPT_SCHAR);
(void)snprintf(mc.dispstr, sizeof(mc.dispstr), "%s%s%s",
mc.promptstr, mc.searchstr, PROMPT_ECHAR);
mc.width = font_width(sc, mc.dispstr, strlen(mc.dispstr));
if (prompt != NULL) {
evmask = MENUMASK | KEYMASK; /* accept keys as well */
(void)strlcpy(mc.promptstr, prompt, sizeof(mc.promptstr));
mc.hasprompt = 1;
} else {
evmask = MENUMASK;
mc.list = 1;
}
if (initial != NULL)
@ -135,8 +119,6 @@ menu_filter(struct screen_ctx *sc, struct menu_q *menuq, char *prompt,
mc.print = print;
mc.entry = mc.prev = -1;
XMoveResizeWindow(X_Dpy, sc->menuwin, mc.x, mc.y, mc.width,
font_height(sc));
XSelectInput(X_Dpy, sc->menuwin, evmask);
XMapRaised(X_Dpy, sc->menuwin);
@ -164,13 +146,13 @@ menu_filter(struct screen_ctx *sc, struct menu_q *menuq, char *prompt,
goto out;
/* FALLTHROUGH */
case Expose:
menu_draw(sc, &mc, menuq, &resultq);
menu_draw(&mc, menuq, &resultq);
break;
case MotionNotify:
menu_handle_move(&e, &mc, sc, &resultq);
menu_handle_move(&e, &mc, &resultq);
break;
case ButtonRelease:
if ((mi = menu_handle_release(&e, &mc, sc, &resultq))
if ((mi = menu_handle_release(&e, &mc, &resultq))
!= NULL)
goto out;
break;
@ -192,6 +174,7 @@ out:
xu_ptr_setpos(sc->rootwin, xsave, ysave);
xu_ptr_ungrab();
XMoveResizeWindow(X_Dpy, sc->menuwin, 0, 0, 1, 1);
XUnmapWindow(X_Dpy, sc->menuwin);
XUngrabKeyboard(X_Dpy, CurrentTime);
@ -203,7 +186,7 @@ menu_complete_path(struct menu_ctx *mc)
{
struct menu *mi, *mr;
struct menu_q menuq;
char *path = NULL;
char *path = NULL;
path = xcalloc(1, sizeof(mr->text));
mr = xcalloc(1, sizeof(*mr));
@ -348,9 +331,9 @@ menu_handle_key(XEvent *e, struct menu_ctx *mc, struct menu_q *menuq,
}
static void
menu_draw(struct screen_ctx *sc, struct menu_ctx *mc, struct menu_q *menuq,
struct menu_q *resultq)
menu_draw(struct menu_ctx *mc, struct menu_q *menuq, struct menu_q *resultq)
{
struct screen_ctx *sc = mc->sc;
struct menu *mi;
struct geom xine;
int n, xsave, ysave;
@ -371,10 +354,11 @@ menu_draw(struct screen_ctx *sc, struct menu_ctx *mc, struct menu_q *menuq,
mc->width = 0;
mc->height = 0;
if (mc->hasprompt) {
(void)snprintf(mc->dispstr, sizeof(mc->dispstr), "%s%s%s",
mc->promptstr, mc->searchstr, PROMPT_ECHAR);
mc->width = font_width(sc, mc->dispstr, strlen(mc->dispstr));
mc->height = font_height(sc);
(void)snprintf(mc->dispstr, sizeof(mc->dispstr), "%s%s%s%s",
mc->promptstr, PROMPT_SCHAR, mc->searchstr, PROMPT_ECHAR);
mc->width = xu_xft_width(sc->xftfont, mc->dispstr,
strlen(mc->dispstr));
mc->height = sc->xftfont->height + 1;
mc->num = 1;
}
@ -389,9 +373,9 @@ menu_draw(struct screen_ctx *sc, struct menu_ctx *mc, struct menu_q *menuq,
text = mi->text;
}
mc->width = MAX(mc->width, font_width(sc, text,
mc->width = MAX(mc->width, xu_xft_width(sc->xftfont, text,
MIN(strlen(text), MENU_MAXENTRY)));
mc->height += font_height(sc);
mc->height += sc->xftfont->height + 1;
mc->num++;
}
@ -424,8 +408,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,
0, font_ascent(sc));
xu_xft_draw(sc, mc->dispstr, CWM_COLOR_MENU_FONT,
0, sc->xftfont->ascent);
n = 1;
} else
n = 0;
@ -433,29 +417,29 @@ menu_draw(struct screen_ctx *sc, struct menu_ctx *mc, struct menu_q *menuq,
TAILQ_FOREACH(mi, resultq, resultentry) {
char *text = mi->print[0] != '\0' ?
mi->print : mi->text;
int y = n * font_height(sc) + font_ascent(sc) + 1;
int y = n * (sc->xftfont->height + 1) + sc->xftfont->ascent + 1;
/* Stop drawing when menu doesn't fit inside the screen. */
if (mc->y + y > xine.h)
break;
font_draw(sc, text, MIN(strlen(text), MENU_MAXENTRY),
sc->menuwin, 0, 0, y);
xu_xft_draw(sc, text, CWM_COLOR_MENU_FONT, 0, y);
n++;
}
if (mc->hasprompt && n > 1 && (mc->searchstr[0] != '\0')) {
mc->entry = 1;
menu_draw_entry(sc, mc, resultq, mc->entry, 1);
menu_draw_entry(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)
menu_draw_entry(struct menu_ctx *mc, struct menu_q *resultq,
int entry, int active)
{
struct menu *mi;
char *text;
int color, i = 0;
struct screen_ctx *sc = mc->sc;
struct menu *mi;
char *text;
int color, i = 0;
if (mc->hasprompt)
i = 1;
@ -467,44 +451,43 @@ menu_draw_entry(struct screen_ctx *sc, struct menu_ctx *mc,
return;
color = active ? CWM_COLOR_MENU_FG : CWM_COLOR_MENU_BG;
text = mi->print[0] != '\0' ? mi->print : mi->text;
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);
(sc->xftfont->height + 1) * entry, mc->width,
(sc->xftfont->height + 1) + sc->xftfont->descent);
color = active ? CWM_COLOR_MENU_FONT_SEL : CWM_COLOR_MENU_FONT;
xu_xft_draw(sc, text, color,
0, (sc->xftfont->height + 1) * entry + sc->xftfont->ascent + 1);
}
static void
menu_handle_move(XEvent *e, struct menu_ctx *mc, struct screen_ctx *sc,
struct menu_q *resultq)
menu_handle_move(XEvent *e, struct menu_ctx *mc, struct menu_q *resultq)
{
mc->prev = mc->entry;
mc->entry = menu_calc_entry(sc, mc, e->xbutton.x, e->xbutton.y);
mc->entry = menu_calc_entry(mc, e->xbutton.x, e->xbutton.y);
if (mc->prev == mc->entry)
return;
if (mc->prev != -1)
menu_draw_entry(sc, mc, resultq, mc->prev, 0);
menu_draw_entry(mc, resultq, mc->prev, 0);
if (mc->entry != -1) {
(void)xu_ptr_regrab(MENUGRABMASK, Cursor_normal);
menu_draw_entry(sc, mc, resultq, mc->entry, 1);
menu_draw_entry(mc, resultq, mc->entry, 1);
} else
(void)xu_ptr_regrab(MENUGRABMASK, Cursor_default);
if (mc->hasprompt)
menu_draw_entry(sc, mc, resultq, 1, 1);
menu_draw_entry(mc, resultq, 1, 1);
}
static struct menu *
menu_handle_release(XEvent *e, struct menu_ctx *mc, struct screen_ctx *sc,
struct menu_q *resultq)
menu_handle_release(XEvent *e, struct menu_ctx *mc, struct menu_q *resultq)
{
struct menu *mi;
int entry, i = 0;
struct menu *mi;
int entry, i = 0;
entry = menu_calc_entry(sc, mc, e->xbutton.x, e->xbutton.y);
entry = menu_calc_entry(mc, e->xbutton.x, e->xbutton.y);
if (mc->hasprompt)
i = 1;
@ -521,15 +504,17 @@ menu_handle_release(XEvent *e, struct menu_ctx *mc, struct screen_ctx *sc,
}
static int
menu_calc_entry(struct screen_ctx *sc, struct menu_ctx *mc, int x, int y)
menu_calc_entry(struct menu_ctx *mc, int x, int y)
{
int entry;
struct screen_ctx *sc = mc->sc;
int entry;
entry = y / font_height(sc);
entry = y / (sc->xftfont->height + 1);
/* in bounds? */
if (x < 0 || x > mc->width || y < 0 ||
y > font_height(sc) * mc->num || entry < 0 || entry >= mc->num)
y > (sc->xftfont->height + 1) * mc->num ||
entry < 0 || entry >= mc->num)
entry = -1;
if (mc->hasprompt && entry == 0)

View File

@ -31,14 +31,12 @@
#include "calmwm.h"
static int mousefunc_sweep_calc(struct client_ctx *, int, int, int, int);
static void mousefunc_sweep_calc(struct client_ctx *, int, int, int, int);
static void mousefunc_sweep_draw(struct client_ctx *);
static int
static void
mousefunc_sweep_calc(struct client_ctx *cc, int x, int y, int mx, int my)
{
int width = cc->geom.w, height = cc->geom.h;
cc->geom.w = abs(x - mx) - cc->bwidth;
cc->geom.h = abs(y - my) - cc->bwidth;
@ -46,32 +44,27 @@ mousefunc_sweep_calc(struct client_ctx *cc, int x, int y, int mx, int my)
cc->geom.x = x <= mx ? x : x - cc->geom.w;
cc->geom.y = y <= my ? y : y - cc->geom.h;
return (width != cc->geom.w || height != cc->geom.h);
}
static void
mousefunc_sweep_draw(struct client_ctx *cc)
{
struct screen_ctx *sc = cc->sc;
char asize[10]; /* fits "nnnnxnnnn\0" */
int width, width_size, width_name;
char asize[14]; /* fits " nnnn x nnnn \0" */
(void)snprintf(asize, sizeof(asize), "%dx%d",
(void)snprintf(asize, sizeof(asize), " %4d x %-4d ",
(cc->geom.w - cc->hint.basew) / cc->hint.incw,
(cc->geom.h - cc->hint.baseh) / cc->hint.inch);
width_size = font_width(sc, asize, strlen(asize)) + 4;
width_name = font_width(sc, cc->name, strlen(cc->name)) + 4;
width = MAX(width_size, width_name);
XReparentWindow(X_Dpy, sc->menuwin, cc->win, 0, 0);
XMoveResizeWindow(X_Dpy, sc->menuwin, 0, 0, width, font_height(sc) * 2);
XMoveResizeWindow(X_Dpy, sc->menuwin, 0, 0,
xu_xft_width(sc->xftfont, asize, strlen(asize)),
sc->xftfont->height);
XMapWindow(X_Dpy, sc->menuwin);
XClearWindow(X_Dpy, 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, 0,
width / 2 - width_size / 2, font_height(sc) + font_ascent(sc) + 1);
xu_xft_draw(sc, asize, CWM_COLOR_MENU_FONT,
0, sc->xftfont->ascent + 1);
}
void
@ -102,15 +95,14 @@ mousefunc_window_resize(struct client_ctx *cc, void *arg)
client_draw_border(cc);
break;
case MotionNotify:
if (mousefunc_sweep_calc(cc, x, y,
ev.xmotion.x_root, ev.xmotion.y_root))
/* Recompute window output */
mousefunc_sweep_draw(cc);
mousefunc_sweep_calc(cc, x, y,
ev.xmotion.x_root, ev.xmotion.y_root);
/* don't resize more than 60 times / second */
if ((ev.xmotion.time - ltime) > (1000 / 60)) {
ltime = ev.xmotion.time;
client_resize(cc, 1);
mousefunc_sweep_draw(cc);
}
break;
case ButtonRelease:

111
parse.y
View File

@ -44,18 +44,17 @@ static struct file {
char *name;
int lineno;
int errors;
} *file;
struct file *pushfile(const char *);
int popfile(void);
int yyparse(void);
int yylex(void);
int yyerror(const char *, ...);
int kw_cmp(const void *, const void *);
int lookup(char *);
int lgetc(int);
int lungetc(int);
int findeol(void);
} *file, *topfile;
struct file *pushfile(const char *);
int popfile(void);
int yyparse(void);
int yylex(void);
int yyerror(const char *, ...);
int kw_cmp(const void *, const void *);
int lookup(char *);
int lgetc(int);
int lungetc(int);
int findeol(void);
static struct conf *conf;
@ -119,12 +118,24 @@ main : FONTNAME STRING {
conf->flags |= CONF_STICKY_GROUPS;
}
| BORDERWIDTH NUMBER {
if ($2 < 0) {
yyerror("invalid borderwidth: %d", $2);
YYERROR;
}
conf->bwidth = $2;
}
| MOVEAMOUNT NUMBER {
if ($2 < 0) {
yyerror("invalid movemount: %d", $2);
YYERROR;
}
conf->mamount = $2;
}
| SNAPDIST NUMBER {
if ($2 < 0) {
yyerror("invalid snapdist: %d", $2);
YYERROR;
}
conf->snapdist = $2;
}
| COMMAND STRING string {
@ -135,10 +146,9 @@ main : FONTNAME STRING {
| AUTOGROUP NUMBER STRING {
if ($2 < 0 || $2 > 9) {
free($3);
yyerror("autogroup number out of range: %d", $2);
yyerror("invalid autogroup: %d", $2);
YYERROR;
}
conf_autogroup(conf, $2, $3);
free($3);
}
@ -152,13 +162,23 @@ main : FONTNAME STRING {
free($3);
}
| GAP NUMBER NUMBER NUMBER NUMBER {
if ($2 < 0 || $3 < 0 || $4 < 0 || $5 < 0) {
yyerror("invalid gap: %d %d %d %d",
$2, $3, $4, $5);
YYERROR;
}
conf->gap.top = $2;
conf->gap.bottom = $3;
conf->gap.left = $4;
conf->gap.right = $5;
}
| MOUSEBIND STRING string {
conf_mousebind(conf, $2, $3);
if (!conf_mousebind(conf, $2, $3)) {
yyerror("invalid mousebind: %s %s", $2, $3);
free($2);
free($3);
YYERROR;
}
free($2);
free($3);
}
@ -184,20 +204,20 @@ colors : ACTIVEBORDER STRING {
conf->color[CWM_COLOR_BORDER_UNGROUP] = $2;
}
| MENUBG STRING {
free(conf->menucolor[CWM_COLOR_MENU_BG]);
conf->menucolor[CWM_COLOR_MENU_BG] = $2;
free(conf->color[CWM_COLOR_MENU_BG]);
conf->color[CWM_COLOR_MENU_BG] = $2;
}
| MENUFG STRING {
free(conf->menucolor[CWM_COLOR_MENU_FG]);
conf->menucolor[CWM_COLOR_MENU_FG] = $2;
free(conf->color[CWM_COLOR_MENU_FG]);
conf->color[CWM_COLOR_MENU_FG] = $2;
}
| FONTCOLOR STRING {
free(conf->menucolor[CWM_COLOR_MENU_FONT]);
conf->menucolor[CWM_COLOR_MENU_FONT] = $2;
free(conf->color[CWM_COLOR_MENU_FONT]);
conf->color[CWM_COLOR_MENU_FONT] = $2;
}
| FONTSELCOLOR STRING {
free(conf->menucolor[CWM_COLOR_MENU_FONT_SEL]);
conf->menucolor[CWM_COLOR_MENU_FONT_SEL] = $2;
free(conf->color[CWM_COLOR_MENU_FONT_SEL]);
conf->color[CWM_COLOR_MENU_FONT_SEL] = $2;
}
;
%%
@ -210,7 +230,7 @@ struct keywords {
int
yyerror(const char *fmt, ...)
{
va_list ap;
va_list ap;
file->errors++;
va_start(ap, fmt);
@ -294,8 +314,9 @@ lgetc(int quotec)
if (quotec) {
if ((c = getc(file->stream)) == EOF) {
yyerror("reached end of file while parsing quoted string");
if (popfile() == EOF)
yyerror("reached end of file while parsing "
"quoted string");
if (file == topfile || popfile() == EOF)
return (EOF);
return (quotec);
}
@ -313,7 +334,7 @@ lgetc(int quotec)
}
while (c == EOF) {
if (popfile() == EOF)
if (file == topfile || popfile() == EOF)
return (EOF);
c = getc(file->stream);
}
@ -342,11 +363,13 @@ findeol(void)
int c;
parsebuf = NULL;
pushback_index = 0;
/* skip to either EOF or the first real EOL */
while (1) {
c = lgetc(0);
if (pushback_index)
c = pushback_buffer[--pushback_index];
else
c = lgetc(0);
if (c == '\n') {
file->lineno++;
break;
@ -447,9 +470,10 @@ nodigits:
#define allowed_in_string(x) \
(isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
x != '{' && x != '}' && x != '<' && x != '>' && \
x != '!' && x != '=' && x != '#' && x != ','))
x != '!' && x != '=' && x != '/' && x != '#' && \
x != ','))
if (isalnum(c) || c == ':' || c == '_' || c == '*' || c == '/') {
if (isalnum(c) || c == ':' || c == '_' || c == '*') {
do {
*p++ = c;
if ((unsigned)(p-buf) >= sizeof(buf)) {
@ -481,6 +505,7 @@ pushfile(const char *name)
nfile->name = xstrdup(name);
if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
warn("%s", nfile->name);
free(nfile->name);
free(nfile);
return (NULL);
@ -495,16 +520,15 @@ popfile(void)
{
struct file *prev;
if ((prev = TAILQ_PREV(file, files, entry)) != NULL) {
if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
prev->errors += file->errors;
TAILQ_REMOVE(&files, file, entry);
fclose(file->stream);
free(file->name);
free(file);
file = prev;
return (0);
}
return (EOF);
TAILQ_REMOVE(&files, file, entry);
fclose(file->stream);
free(file->name);
free(file);
file = prev;
return (file ? 0 : EOF);
}
int
@ -518,12 +542,12 @@ parse_config(const char *filename, struct conf *xconf)
free(conf);
return (-1);
}
topfile = file;
conf_init(conf);
yyparse();
errors = file->errors;
file->errors = 0;
popfile();
if (errors) {
@ -575,12 +599,9 @@ parse_config(const char *filename, struct conf *xconf)
(void)strlcpy(xconf->lockpath, conf->lockpath,
sizeof(xconf->lockpath));
for (i = 0; i < CWM_COLOR_BORDER_MAX; i++)
for (i = 0; i < CWM_COLOR_MAX; i++)
xconf->color[i] = conf->color[i];
for (i = 0; i < CWM_COLOR_MENU_MAX; i++)
xconf->menucolor[i] = conf->menucolor[i];
xconf->font = conf->font;
}

View File

@ -49,16 +49,13 @@ screen_init(int which)
xu_ewmh_net_supported(sc);
xu_ewmh_net_supported_wm_check(sc);
conf_gap(&Conf, sc);
conf_color(&Conf, sc);
conf_font(&Conf, sc);
conf_screen(sc);
screen_update_geometry(sc);
TAILQ_INIT(&sc->mruq);
group_init(sc);
menu_init(sc);
rootattr.cursor = Cursor_normal;
rootattr.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|
@ -76,7 +73,7 @@ screen_init(int which)
if (winattr.override_redirect ||
winattr.map_state != IsViewable)
continue;
(void)client_new(wins[i], sc, winattr.map_state != IsUnmapped);
(void)client_init(wins[i], sc, winattr.map_state != IsUnmapped);
}
XFree(wins);

View File

@ -86,7 +86,7 @@ xev_handle_maprequest(XEvent *ee)
if ((cc = client_find(e->window)) == NULL) {
XGetWindowAttributes(X_Dpy, e->window, &xattr);
cc = client_new(e->window, screen_fromroot(xattr.root), 1);
cc = client_init(e->window, screen_fromroot(xattr.root), 1);
}
if ((cc->flags & CLIENT_IGNORE) == 0)
@ -203,13 +203,12 @@ xev_handle_propertynotify(XEvent *ee)
break;
}
} else {
TAILQ_FOREACH(sc, &Screenq, entry)
if (sc->rootwin == e->window)
goto test;
return;
test:
if (e->atom == ewmh[_NET_DESKTOP_NAMES].atom)
group_update_names(sc);
TAILQ_FOREACH(sc, &Screenq, entry) {
if (sc->rootwin == e->window) {
if (e->atom == ewmh[_NET_DESKTOP_NAMES].atom)
group_update_names(sc);
}
}
}
}
@ -277,7 +276,7 @@ xev_handle_keypress(XEvent *ee)
struct client_ctx *cc = NULL, fakecc;
struct keybinding *kb;
KeySym keysym, skeysym;
int modshift;
u_int modshift;
keysym = XkbKeycodeToKeysym(X_Dpy, e->keycode, 0, 0);
skeysym = XkbKeycodeToKeysym(X_Dpy, e->keycode, 0, 1);
@ -322,7 +321,8 @@ xev_handle_keyrelease(XEvent *ee)
XKeyEvent *e = &ee->xkey;
struct screen_ctx *sc;
struct client_ctx *cc;
int i, keysym;
KeySym keysym;
u_int i;
sc = screen_fromroot(e->root);
cc = client_current();
@ -340,17 +340,29 @@ static void
xev_handle_clientmessage(XEvent *ee)
{
XClientMessageEvent *e = &ee->xclient;
Atom xa_wm_change_state;
struct client_ctx *cc;
xa_wm_change_state = XInternAtom(X_Dpy, "WM_CHANGE_STATE", False);
struct client_ctx *cc, *old_cc;
if ((cc = client_find(e->window)) == NULL)
return;
if (e->message_type == xa_wm_change_state && e->format == 32 &&
e->data.l[0] == IconicState)
if (e->message_type == cwmh[WM_CHANGE_STATE].atom &&
e->format == 32 && e->data.l[0] == IconicState)
client_hide(cc);
if (e->message_type == ewmh[_NET_CLOSE_WINDOW].atom)
client_send_delete(cc);
if (e->message_type == ewmh[_NET_ACTIVE_WINDOW].atom &&
e->format == 32) {
old_cc = client_current();
if (old_cc)
client_ptrsave(old_cc);
client_ptrwarp(cc);
}
if (e->message_type == ewmh[_NET_WM_STATE].atom &&
e->format == 32)
xu_ewmh_handle_net_wm_state_msg(cc,
e->data.l[0], e->data.l[1], e->data.l[2]);
}
static void
@ -377,15 +389,13 @@ static void
xev_handle_mappingnotify(XEvent *ee)
{
XMappingEvent *e = &ee->xmapping;
struct keybinding *kb;
TAILQ_FOREACH(kb, &Conf.keybindingq, entry)
conf_ungrab(&Conf, kb);
struct screen_ctx *sc;
XRefreshKeyboardMapping(e);
TAILQ_FOREACH(kb, &Conf.keybindingq, entry)
conf_grab(&Conf, kb);
if (e->request == MappingKeyboard) {
TAILQ_FOREACH(sc, &Screenq, entry)
conf_grab_kbd(sc->rootwin);
}
}
static void

185
xutil.c
View File

@ -33,7 +33,7 @@
static unsigned int ign_mods[] = { 0, LockMask, Mod2Mask, Mod2Mask | LockMask };
int
xu_ptr_grab(Window win, int mask, Cursor curs)
xu_ptr_grab(Window win, u_int mask, Cursor curs)
{
return (XGrabPointer(X_Dpy, win, False, mask,
GrabModeAsync, GrabModeAsync,
@ -41,7 +41,7 @@ xu_ptr_grab(Window win, int mask, Cursor curs)
}
int
xu_ptr_regrab(int mask, Cursor curs)
xu_ptr_regrab(u_int mask, Cursor curs)
{
return (XChangeActivePointerGrab(X_Dpy, mask,
curs, CurrentTime) == GrabSuccess ? 0 : -1);
@ -56,7 +56,8 @@ xu_ptr_ungrab(void)
void
xu_btn_grab(Window win, int mask, u_int btn)
{
int i;
u_int i;
for (i = 0; i < nitems(ign_mods); i++)
XGrabButton(X_Dpy, btn, (mask | ign_mods[i]), win,
False, BUTTONMASK, GrabModeAsync,
@ -66,7 +67,8 @@ xu_btn_grab(Window win, int mask, u_int btn)
void
xu_btn_ungrab(Window win, int mask, u_int btn)
{
int i;
u_int i;
for (i = 0; i < nitems(ign_mods); i++)
XUngrabButton(X_Dpy, btn, (mask | ign_mods[i]), win);
}
@ -88,10 +90,10 @@ xu_ptr_setpos(Window win, int x, int y)
}
void
xu_key_grab(Window win, int mask, int keysym)
xu_key_grab(Window win, u_int mask, KeySym keysym)
{
KeyCode code;
int i;
u_int i;
code = XKeysymToKeycode(X_Dpy, keysym);
if ((XkbKeycodeToKeysym(X_Dpy, code, 0, 0) != keysym) &&
@ -103,21 +105,6 @@ xu_key_grab(Window win, int mask, int keysym)
True, GrabModeAsync, GrabModeAsync);
}
void
xu_key_ungrab(Window win, int mask, int keysym)
{
KeyCode code;
int i;
code = XKeysymToKeycode(X_Dpy, keysym);
if ((XkbKeycodeToKeysym(X_Dpy, code, 0, 0) != keysym) &&
(XkbKeycodeToKeysym(X_Dpy, code, 0, 1) == keysym))
mask |= ShiftMask;
for (i = 0; i < nitems(ign_mods); i++)
XUngrabKey(X_Dpy, code, (mask | ign_mods[i]), win);
}
void
xu_configure(struct client_ctx *cc)
{
@ -138,19 +125,19 @@ xu_configure(struct client_ctx *cc)
}
void
xu_sendmsg(Window win, Atom atm, long val)
xu_sendmsg(Window win, Atom type, Atom atm)
{
XEvent e;
XClientMessageEvent e;
(void)memset(&e, 0, sizeof(e));
e.xclient.type = ClientMessage;
e.xclient.window = win;
e.xclient.message_type = atm;
e.xclient.format = 32;
e.xclient.data.l[0] = val;
e.xclient.data.l[1] = CurrentTime;
bzero(&e, sizeof(e));
e.type = ClientMessage;
e.window = win;
e.message_type = type;
e.format = 32;
e.data.l[0] = atm;
e.data.l[1] = CurrentTime;
XSendEvent(X_Dpy, win, False, 0, &e);
XSendEvent(X_Dpy, win, False, 0L, (XEvent *)&e);
}
int
@ -237,6 +224,7 @@ struct atom_ctx cwmh[CWMH_NITEMS] = {
{"WM_PROTOCOLS", None},
{"_MOTIF_WM_HINTS", None},
{"UTF8_STRING", None},
{"WM_CHANGE_STATE", None},
};
struct atom_ctx ewmh[EWMH_NITEMS] = {
{"_NET_SUPPORTED", None},
@ -253,12 +241,16 @@ struct atom_ctx ewmh[EWMH_NITEMS] = {
{"_NET_WORKAREA", None},
{"_NET_WM_NAME", None},
{"_NET_WM_DESKTOP", None},
{"_NET_CLOSE_WINDOW", None},
{"_NET_WM_STATE", None},
{"_NET_WM_STATE_MAXIMIZED_VERT",None},
{"_NET_WM_STATE_MAXIMIZED_HORZ",None},
};
void
xu_getatoms(void)
{
int i;
u_int i;
for (i = 0; i < nitems(cwmh); i++)
cwmh[i].atom = XInternAtom(X_Dpy, cwmh[i].name, False);
@ -271,7 +263,7 @@ void
xu_ewmh_net_supported(struct screen_ctx *sc)
{
Atom atom[EWMH_NITEMS];
int i;
u_int i;
for (i = 0; i < nitems(ewmh); i++)
atom[i] = ewmh[i].atom;
@ -416,24 +408,125 @@ xu_ewmh_net_wm_desktop(struct client_ctx *cc)
XA_CARDINAL, 32, PropModeReplace, (unsigned char *)&no, 1);
}
unsigned long
xu_getcolor(struct screen_ctx *sc, char *name)
Atom *
xu_ewmh_get_net_wm_state(struct client_ctx *cc, int *n)
{
XColor color, tmp;
Atom *state, *p = NULL;
if (!XAllocNamedColor(X_Dpy, sc->colormap, name, &color, &tmp)) {
warnx("XAllocNamedColor error: '%s'", name);
return (0);
}
if ((*n = xu_getprop(cc->win, ewmh[_NET_WM_STATE].atom, XA_ATOM, 64L,
(u_char **)&p)) <= 0)
return (NULL);
return (color.pixel);
state = xmalloc(*n * sizeof(Atom));
memcpy(state, p, *n * sizeof(Atom));
XFree((char *)p);
return (state);
}
void
xu_xorcolor(XRenderColor a, XRenderColor b, XRenderColor *r)
xu_ewmh_handle_net_wm_state_msg(struct client_ctx *cc, int action,
Atom first, Atom second)
{
r->red = a.red ^ b.red;
r->green = a.green ^ b.green;
r->blue = a.blue ^ b.blue;
r->alpha = 0xffff;
int i;
static struct handlers {
int atom;
int property;
void (*toggle)(struct client_ctx *);
} handlers[] = {
{ _NET_WM_STATE_MAXIMIZED_VERT,
CLIENT_VMAXIMIZED,
client_vmaximize },
{ _NET_WM_STATE_MAXIMIZED_HORZ,
CLIENT_HMAXIMIZED,
client_hmaximize },
};
for (i = 0; i < nitems(handlers); i++) {
if (first != ewmh[handlers[i].atom].atom &&
second != ewmh[handlers[i].atom].atom)
continue;
switch (action) {
case _NET_WM_STATE_ADD:
if ((cc->flags & handlers[i].property) == 0)
handlers[i].toggle(cc);
break;
case _NET_WM_STATE_REMOVE:
if (cc->flags & handlers[i].property)
handlers[i].toggle(cc);
break;
case _NET_WM_STATE_TOGGLE:
handlers[i].toggle(cc);
}
}
}
void
xu_ewmh_restore_net_wm_state(struct client_ctx *cc)
{
Atom *atoms;
int i, n;
atoms = xu_ewmh_get_net_wm_state(cc, &n);
for (i = 0; i < n; i++) {
if (atoms[i] == ewmh[_NET_WM_STATE_MAXIMIZED_HORZ].atom)
client_hmaximize(cc);
if (atoms[i] == ewmh[_NET_WM_STATE_MAXIMIZED_VERT].atom)
client_vmaximize(cc);
}
free(atoms);
}
void
xu_ewmh_set_net_wm_state(struct client_ctx *cc)
{
Atom *atoms, *oatoms;
int n, i, j;
oatoms = xu_ewmh_get_net_wm_state(cc, &n);
atoms = xmalloc((n + _NET_WM_STATES_NITEMS) * sizeof(Atom));
for (i = j = 0; i < n; i++) {
if (oatoms[i] != ewmh[_NET_WM_STATE_MAXIMIZED_HORZ].atom &&
oatoms[i] != ewmh[_NET_WM_STATE_MAXIMIZED_VERT].atom)
atoms[j++] = oatoms[i];
}
free(oatoms);
if (cc->flags & CLIENT_HMAXIMIZED)
atoms[j++] = ewmh[_NET_WM_STATE_MAXIMIZED_HORZ].atom;
if (cc->flags & CLIENT_VMAXIMIZED)
atoms[j++] = ewmh[_NET_WM_STATE_MAXIMIZED_VERT].atom;
if (j > 0)
XChangeProperty(X_Dpy, cc->win, ewmh[_NET_WM_STATE].atom,
XA_ATOM, 32, PropModeReplace, (unsigned char *)atoms, j);
else
XDeleteProperty(X_Dpy, cc->win, ewmh[_NET_WM_STATE].atom);
free(atoms);
}
void
xu_xorcolor(XftColor a, XftColor b, XftColor *r)
{
r->pixel = a.pixel ^ b.pixel;
r->color.red = a.color.red ^ b.color.red;
r->color.green = a.color.green ^ b.color.green;
r->color.blue = a.color.blue ^ b.color.blue;
r->color.alpha = 0xffff;
}
int
xu_xft_width(XftFont *xftfont, const char *text, int len)
{
XGlyphInfo extents;
XftTextExtentsUtf8(X_Dpy, xftfont, (const FcChar8*)text,
len, &extents);
return (extents.xOff);
}
void
xu_xft_draw(struct screen_ctx *sc, const char *text, int color, int x, int y)
{
XftDrawStringUtf8(sc->xftdraw, &sc->xftcolor[color], sc->xftfont,
x, y, (const FcChar8*)text, strlen(text));
}