cvsimport

* refs/heads/master: (23 commits)
  Check the atom type on propertynotify before iterating.
  use screen_find() for xrandr crtc changes
  Find the managed screen from the parent window for client_current().
  Print window id in hex; while here, remove unnecessary newline.
  Similar to keypress event, fetch the screen from the event root window in the buttonpress handler; bail if we don't manage the screen. Allows us to find the current client based on the screen/event root.
  extend verbose logging for key/button events
  [keypress event] turns out we've been checking the wrong window for a matching client thus always falling back to client_current(); while the current client is problaby right in most cases, use event's subwindow (not window) to find the client. Bail early if this event came to us from a screen we don't manage. This is result of us grabing all keybindings off the root window instead of selectively.
  add parans for readibility
  Teach client_current() to use a screen to find the current client instead of iterating over all (fallback if no screen provided for now). Initially convert trivial uses of client_current().
  check cc->gc directly
  zip extra lines
  gc clientq inside groups, instead use the better maintained one per-screen
  shuffle deck chairs: rename group actions to match intent for clarity
  same thing as screen_find()
  Separate out the menu window from the client resize/move geom window; in each case, create and destroy on-demand. Isolate more menu specific code.
  fix a few misplaced (and misnamed) ewmh root window functions
  _NET_WORKAREA needs ngroups, so screen_update_geometry() needs to come after conf_group().
  simplify xftcolor config
  Tie group number and name together during config.
  Move the group index (desktop number) check to the only 2 callers that require checking due to ewmh.
  ...
This commit is contained in:
okan 2019-03-11 15:25:46 +00:00
commit 85d88f3304
11 changed files with 321 additions and 285 deletions

View File

@ -55,7 +55,7 @@ main(int argc, char **argv)
{ {
char *display_name = NULL; char *display_name = NULL;
char *fallback; char *fallback;
int ch, xfd; int ch, xfd, nflag = 0;
struct pollfd pfd[1]; struct pollfd pfd[1];
if (!setlocale(LC_CTYPE, "") || !XSupportsLocale()) if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
@ -66,7 +66,7 @@ main(int argc, char **argv)
fallback = u_argv(argv); fallback = u_argv(argv);
Conf.wm_argv = u_argv(argv); Conf.wm_argv = u_argv(argv);
while ((ch = getopt(argc, argv, "c:d:v")) != -1) { while ((ch = getopt(argc, argv, "c:d:nv")) != -1) {
switch (ch) { switch (ch) {
case 'c': case 'c':
free(Conf.conf_file); free(Conf.conf_file);
@ -75,6 +75,9 @@ main(int argc, char **argv)
case 'd': case 'd':
display_name = optarg; display_name = optarg;
break; break;
case 'n':
nflag = 1;
break;
case 'v': case 'v':
Conf.debug++; Conf.debug++;
break; break;
@ -90,8 +93,13 @@ main(int argc, char **argv)
if (signal(SIGHUP, sighdlr) == SIG_ERR) if (signal(SIGHUP, sighdlr) == SIG_ERR)
err(1, "signal"); err(1, "signal");
if (parse_config(Conf.conf_file, &Conf) == -1) if (parse_config(Conf.conf_file, &Conf) == -1) {
warnx("error parsing config file"); warnx("error parsing config file");
if (nflag)
return 1;
}
if (nflag)
return 0;
xfd = x_init(display_name); xfd = x_init(display_name);
cwm_status = CWM_RUNNING; cwm_status = CWM_RUNNING;
@ -159,8 +167,6 @@ x_teardown(void)
DefaultColormap(X_Dpy, sc->which), DefaultColormap(X_Dpy, sc->which),
&sc->xftcolor[i]); &sc->xftcolor[i]);
XftFontClose(X_Dpy, sc->xftfont); XftFontClose(X_Dpy, sc->xftfont);
XftDrawDestroy(sc->menu.xftdraw);
XDestroyWindow(X_Dpy, sc->menu.win);
XUngrabKey(X_Dpy, AnyKey, AnyModifier, sc->rootwin); XUngrabKey(X_Dpy, AnyKey, AnyModifier, sc->rootwin);
} }
XUngrabPointer(X_Dpy, CurrentTime); XUngrabPointer(X_Dpy, CurrentTime);
@ -221,7 +227,7 @@ usage(void)
{ {
extern char *__progname; extern char *__progname;
(void)fprintf(stderr, "usage: %s [-v] [-c file] [-d display]\n", (void)fprintf(stderr, "usage: %s [-nv] [-c file] [-d display]\n",
__progname); __progname);
exit(1); exit(1);
} }

View File

@ -68,9 +68,6 @@ size_t strlcpy(char *, const char *, size_t);
#define BUTTONMASK (ButtonPressMask | ButtonReleaseMask) #define BUTTONMASK (ButtonPressMask | ButtonReleaseMask)
#define MOUSEMASK (BUTTONMASK | PointerMotionMask) #define MOUSEMASK (BUTTONMASK | PointerMotionMask)
#define MENUMASK (MOUSEMASK | ButtonMotionMask | KeyPressMask | \
ExposureMask)
#define MENUGRABMASK (MOUSEMASK | ButtonMotionMask | StructureNotifyMask)
#define IGNOREMODMASK (LockMask | Mod2Mask | 0x2000) #define IGNOREMODMASK (LockMask | Mod2Mask | 0x2000)
/* direction/amount */ /* direction/amount */
@ -145,7 +142,6 @@ TAILQ_HEAD(ignore_q, winname);
struct client_ctx { struct client_ctx {
TAILQ_ENTRY(client_ctx) entry; TAILQ_ENTRY(client_ctx) entry;
TAILQ_ENTRY(client_ctx) group_entry;
struct screen_ctx *sc; struct screen_ctx *sc;
struct group_ctx *gc; struct group_ctx *gc;
Window win; Window win;
@ -211,7 +207,6 @@ struct group_ctx {
struct screen_ctx *sc; struct screen_ctx *sc;
char *name; char *name;
int num; int num;
struct client_q clientq;
}; };
TAILQ_HEAD(group_q, group_ctx); TAILQ_HEAD(group_q, group_ctx);
@ -250,7 +245,7 @@ struct screen_ctx {
struct { struct {
Window win; Window win;
XftDraw *xftdraw; XftDraw *xftdraw;
} menu; } prop;
XftColor xftcolor[CWM_COLOR_NITEMS]; XftColor xftcolor[CWM_COLOR_NITEMS];
XftFont *xftfont; XftFont *xftfont;
}; };
@ -420,7 +415,7 @@ void usage(void);
void client_applysizehints(struct client_ctx *); void client_applysizehints(struct client_ctx *);
void client_config(struct client_ctx *); void client_config(struct client_ctx *);
struct client_ctx *client_current(void); struct client_ctx *client_current(struct screen_ctx *);
void client_cycle(struct screen_ctx *, int); void client_cycle(struct screen_ctx *, int);
void client_remove(struct client_ctx *); void client_remove(struct client_ctx *);
void client_draw_border(struct client_ctx *); void client_draw_border(struct client_ctx *);
@ -456,25 +451,24 @@ void client_toggle_skip_taskbar(struct client_ctx *);
void client_toggle_sticky(struct client_ctx *); void client_toggle_sticky(struct client_ctx *);
void client_toggle_vmaximize(struct client_ctx *); void client_toggle_vmaximize(struct client_ctx *);
void client_transient(struct client_ctx *); void client_transient(struct client_ctx *);
void client_unhide(struct client_ctx *);
void client_urgency(struct client_ctx *); void client_urgency(struct client_ctx *);
void client_vtile(struct client_ctx *); void client_vtile(struct client_ctx *);
void client_wm_hints(struct client_ctx *); void client_wm_hints(struct client_ctx *);
void group_alltoggle(struct screen_ctx *);
void group_assign(struct group_ctx *, struct client_ctx *); void group_assign(struct group_ctx *, struct client_ctx *);
int group_autogroup(struct client_ctx *); int group_autogroup(struct client_ctx *);
void group_cycle(struct screen_ctx *, int); void group_cycle(struct screen_ctx *, int);
void group_hide(struct group_ctx *); void group_hide(struct group_ctx *);
void group_hidetoggle(struct screen_ctx *, int);
int group_holds_only_hidden(struct group_ctx *); int group_holds_only_hidden(struct group_ctx *);
int group_holds_only_sticky(struct group_ctx *); int group_holds_only_sticky(struct group_ctx *);
void group_init(struct screen_ctx *, int); void group_init(struct screen_ctx *, int, const char *);
void group_movetogroup(struct client_ctx *, int); void group_movetogroup(struct client_ctx *, int);
void group_only(struct screen_ctx *, int); void group_only(struct screen_ctx *, int);
void group_close(struct screen_ctx *, int); void group_close(struct screen_ctx *, int);
int group_restore(struct client_ctx *); int group_restore(struct client_ctx *);
void group_show(struct group_ctx *); void group_show(struct group_ctx *);
void group_toggle(struct screen_ctx *, int);
void group_toggle_all(struct screen_ctx *);
void group_toggle_membership(struct client_ctx *); void group_toggle_membership(struct client_ctx *);
void group_update_names(struct screen_ctx *); void group_update_names(struct screen_ctx *);
@ -506,6 +500,12 @@ void screen_init(int);
void screen_update_geometry(struct screen_ctx *); void screen_update_geometry(struct screen_ctx *);
void screen_updatestackingorder(struct screen_ctx *); void screen_updatestackingorder(struct screen_ctx *);
void screen_assert_clients_within(struct screen_ctx *); void screen_assert_clients_within(struct screen_ctx *);
void screen_prop_win_create(struct screen_ctx *, Window);
void screen_prop_win_destroy(struct screen_ctx *);
void screen_prop_win_draw(struct screen_ctx *,
const char *, ...)
__attribute__((__format__ (printf, 2, 3)))
__attribute__((__nonnull__ (2)));
void kbfunc_cwm_status(void *, struct cargs *); void kbfunc_cwm_status(void *, struct cargs *);
void kbfunc_ptrmove(void *, struct cargs *); void kbfunc_ptrmove(void *, struct cargs *);
@ -532,7 +532,7 @@ void kbfunc_group_toggle(void *, struct cargs *);
void kbfunc_group_only(void *, struct cargs *); void kbfunc_group_only(void *, struct cargs *);
void kbfunc_group_close(void *, struct cargs *); void kbfunc_group_close(void *, struct cargs *);
void kbfunc_group_cycle(void *, struct cargs *); void kbfunc_group_cycle(void *, struct cargs *);
void kbfunc_group_alltoggle(void *, struct cargs *); void kbfunc_group_toggle_all(void *, struct cargs *);
void kbfunc_menu_client(void *, struct cargs *); void kbfunc_menu_client(void *, struct cargs *);
void kbfunc_menu_cmd(void *, struct cargs *); void kbfunc_menu_cmd(void *, struct cargs *);
void kbfunc_menu_group(void *, struct cargs *); void kbfunc_menu_group(void *, struct cargs *);
@ -544,10 +544,6 @@ void kbfunc_exec_cmd(void *, struct cargs *);
void kbfunc_exec_lock(void *, struct cargs *); void kbfunc_exec_lock(void *, struct cargs *);
void kbfunc_exec_term(void *, struct cargs *); void kbfunc_exec_term(void *, struct cargs *);
void menu_windraw(struct screen_ctx *, Window,
const char *, ...)
__attribute__((__format__ (printf, 3, 4)))
__attribute__((__nonnull__ (3)));
struct menu *menu_filter(struct screen_ctx *, struct menu_q *, struct menu *menu_filter(struct screen_ctx *, struct menu_q *,
const char *, const char *, int, const char *, const char *, int,
void (*)(struct menu_q *, struct menu_q *, char *), void (*)(struct menu_q *, struct menu_q *, char *),
@ -577,6 +573,7 @@ void conf_grab_mouse(Window);
void conf_init(struct conf *); void conf_init(struct conf *);
void conf_ignore(struct conf *, const char *); void conf_ignore(struct conf *, const char *);
void conf_screen(struct screen_ctx *); void conf_screen(struct screen_ctx *);
void conf_group(struct screen_ctx *);
void xev_process(void); void xev_process(void);
@ -589,13 +586,13 @@ void xu_xorcolor(XftColor, XftColor, XftColor *);
void xu_ewmh_net_supported(struct screen_ctx *); void xu_ewmh_net_supported(struct screen_ctx *);
void xu_ewmh_net_supported_wm_check(struct screen_ctx *); void xu_ewmh_net_supported_wm_check(struct screen_ctx *);
void xu_ewmh_net_desktop_geometry(struct screen_ctx *); void xu_ewmh_net_desktop_geometry(struct screen_ctx *);
void xu_ewmh_net_desktop_viewport(struct screen_ctx *);
void xu_ewmh_net_workarea(struct screen_ctx *); void xu_ewmh_net_workarea(struct screen_ctx *);
void xu_ewmh_net_client_list(struct screen_ctx *); void xu_ewmh_net_client_list(struct screen_ctx *);
void xu_ewmh_net_client_list_stacking(struct screen_ctx *); void xu_ewmh_net_client_list_stacking(struct screen_ctx *);
void xu_ewmh_net_active_window(struct screen_ctx *, Window); void xu_ewmh_net_active_window(struct screen_ctx *, Window);
Window xu_ewmh_get_net_active_window(struct screen_ctx *); Window xu_ewmh_get_net_active_window(struct screen_ctx *);
void xu_ewmh_net_wm_desktop_viewport(struct screen_ctx *); void xu_ewmh_net_number_of_desktops(struct screen_ctx *);
void xu_ewmh_net_wm_number_of_desktops(struct screen_ctx *);
void xu_ewmh_net_showing_desktop(struct screen_ctx *); void xu_ewmh_net_showing_desktop(struct screen_ctx *);
void xu_ewmh_net_virtual_roots(struct screen_ctx *); void xu_ewmh_net_virtual_roots(struct screen_ctx *);
void xu_ewmh_net_current_desktop(struct screen_ctx *); void xu_ewmh_net_current_desktop(struct screen_ctx *);

View File

@ -128,7 +128,7 @@ client_init(Window win, struct screen_ctx *sc, int active)
if (client_get_wm_state(cc) == IconicState) if (client_get_wm_state(cc) == IconicState)
client_hide(cc); client_hide(cc);
else else
client_unhide(cc); client_show(cc);
if (mapped) { if (mapped) {
if (cc->gc) { if (cc->gc) {
@ -183,9 +183,6 @@ client_remove(struct client_ctx *cc)
if (cc->flags & CLIENT_ACTIVE) if (cc->flags & CLIENT_ACTIVE)
xu_ewmh_net_active_window(sc, None); xu_ewmh_net_active_window(sc, None);
if (cc->gc != NULL)
TAILQ_REMOVE(&cc->gc->clientq, cc, group_entry);
while ((wn = TAILQ_FIRST(&cc->nameq)) != NULL) { while ((wn = TAILQ_FIRST(&cc->nameq)) != NULL) {
TAILQ_REMOVE(&cc->nameq, wn, entry); TAILQ_REMOVE(&cc->nameq, wn, entry);
free(wn->name); free(wn->name);
@ -221,7 +218,7 @@ client_setactive(struct client_ctx *cc)
if (cc->flags & CLIENT_WM_TAKE_FOCUS) if (cc->flags & CLIENT_WM_TAKE_FOCUS)
client_msg(cc, cwmh[WM_TAKE_FOCUS], Last_Event_Time); client_msg(cc, cwmh[WM_TAKE_FOCUS], Last_Event_Time);
if ((oldcc = client_current()) != NULL) { if ((oldcc = client_current(sc)) != NULL) {
oldcc->flags &= ~CLIENT_ACTIVE; oldcc->flags &= ~CLIENT_ACTIVE;
client_draw_border(oldcc); client_draw_border(oldcc);
} }
@ -238,16 +235,23 @@ client_setactive(struct client_ctx *cc)
} }
struct client_ctx * struct client_ctx *
client_current(void) client_current(struct screen_ctx *sc)
{ {
struct screen_ctx *sc; struct screen_ctx *_sc;
struct client_ctx *cc; struct client_ctx *cc;
TAILQ_FOREACH(sc, &Screenq, entry) { if (sc) {
TAILQ_FOREACH(cc, &sc->clientq, entry) { TAILQ_FOREACH(cc, &sc->clientq, entry) {
if (cc->flags & CLIENT_ACTIVE) if (cc->flags & CLIENT_ACTIVE)
return(cc); return(cc);
} }
} else {
TAILQ_FOREACH(_sc, &Screenq, entry) {
TAILQ_FOREACH(cc, &_sc->clientq, entry) {
if (cc->flags & CLIENT_ACTIVE)
return(cc);
}
}
} }
return(NULL); return(NULL);
} }
@ -527,25 +531,16 @@ client_hide(struct client_ctx *cc)
{ {
XUnmapWindow(X_Dpy, cc->win); XUnmapWindow(X_Dpy, cc->win);
if (cc->flags & CLIENT_ACTIVE) if (cc->flags & CLIENT_ACTIVE) {
cc->flags &= ~CLIENT_ACTIVE;
xu_ewmh_net_active_window(cc->sc, None); xu_ewmh_net_active_window(cc->sc, None);
}
cc->flags &= ~CLIENT_ACTIVE;
cc->flags |= CLIENT_HIDDEN; cc->flags |= CLIENT_HIDDEN;
client_set_wm_state(cc, IconicState); client_set_wm_state(cc, IconicState);
} }
void void
client_show(struct client_ctx *cc) client_show(struct client_ctx *cc)
{
if (cc->flags & CLIENT_HIDDEN)
client_unhide(cc);
else
client_raise(cc);
}
void
client_unhide(struct client_ctx *cc)
{ {
XMapRaised(X_Dpy, cc->win); XMapRaised(X_Dpy, cc->win);
@ -691,7 +686,7 @@ client_cycle(struct screen_ctx *sc, int flags)
return; return;
prevcc = TAILQ_FIRST(&sc->clientq); prevcc = TAILQ_FIRST(&sc->clientq);
oldcc = client_current(); oldcc = client_current(sc);
if (oldcc == NULL) if (oldcc == NULL)
oldcc = (flags & CWM_CYCLE_REVERSE) ? oldcc = (flags & CWM_CYCLE_REVERSE) ?
TAILQ_LAST(&sc->clientq, client_q) : TAILQ_LAST(&sc->clientq, client_q) :
@ -972,12 +967,11 @@ void
client_htile(struct client_ctx *cc) client_htile(struct client_ctx *cc)
{ {
struct client_ctx *ci; struct client_ctx *ci;
struct group_ctx *gc = cc->gc;
struct screen_ctx *sc = cc->sc; struct screen_ctx *sc = cc->sc;
struct geom area; struct geom area;
int i, n, mh, x, w, h; int i, n, mh, x, w, h;
if (!gc) if (!cc->gc)
return; return;
i = n = 0; i = n = 0;
@ -985,7 +979,9 @@ client_htile(struct client_ctx *cc)
cc->geom.x + cc->geom.w / 2, cc->geom.x + cc->geom.w / 2,
cc->geom.y + cc->geom.h / 2, CWM_GAP); cc->geom.y + cc->geom.h / 2, CWM_GAP);
TAILQ_FOREACH(ci, &gc->clientq, group_entry) { TAILQ_FOREACH(ci, &sc->clientq, entry) {
if (ci->gc != cc->gc)
continue;
if (ci->flags & CLIENT_HIDDEN || if (ci->flags & CLIENT_HIDDEN ||
ci->flags & CLIENT_IGNORE || (ci == cc) || ci->flags & CLIENT_IGNORE || (ci == cc) ||
ci->geom.x < area.x || ci->geom.x < area.x ||
@ -1014,7 +1010,9 @@ client_htile(struct client_ctx *cc)
x = area.x; x = area.x;
w = area.w / n; w = area.w / n;
h = area.h - mh; h = area.h - mh;
TAILQ_FOREACH(ci, &gc->clientq, group_entry) { TAILQ_FOREACH(ci, &sc->clientq, entry) {
if (ci->gc != cc->gc)
continue;
if (ci->flags & CLIENT_HIDDEN || if (ci->flags & CLIENT_HIDDEN ||
ci->flags & CLIENT_IGNORE || (ci == cc) || ci->flags & CLIENT_IGNORE || (ci == cc) ||
ci->geom.x < area.x || ci->geom.x < area.x ||
@ -1040,12 +1038,11 @@ void
client_vtile(struct client_ctx *cc) client_vtile(struct client_ctx *cc)
{ {
struct client_ctx *ci; struct client_ctx *ci;
struct group_ctx *gc = cc->gc;
struct screen_ctx *sc = cc->sc; struct screen_ctx *sc = cc->sc;
struct geom area; struct geom area;
int i, n, mw, y, w, h; int i, n, mw, y, w, h;
if (!gc) if (!cc->gc)
return; return;
i = n = 0; i = n = 0;
@ -1053,7 +1050,9 @@ client_vtile(struct client_ctx *cc)
cc->geom.x + cc->geom.w / 2, cc->geom.x + cc->geom.w / 2,
cc->geom.y + cc->geom.h / 2, CWM_GAP); cc->geom.y + cc->geom.h / 2, CWM_GAP);
TAILQ_FOREACH(ci, &gc->clientq, group_entry) { TAILQ_FOREACH(ci, &sc->clientq, entry) {
if (ci->gc != cc->gc)
continue;
if (ci->flags & CLIENT_HIDDEN || if (ci->flags & CLIENT_HIDDEN ||
ci->flags & CLIENT_IGNORE || (ci == cc) || ci->flags & CLIENT_IGNORE || (ci == cc) ||
ci->geom.x < area.x || ci->geom.x < area.x ||
@ -1082,7 +1081,9 @@ client_vtile(struct client_ctx *cc)
y = area.y; y = area.y;
h = area.h / n; h = area.h / n;
w = area.w - mw; w = area.w - mw;
TAILQ_FOREACH(ci, &gc->clientq, group_entry) { TAILQ_FOREACH(ci, &sc->clientq, entry) {
if (ci->gc != cc->gc)
continue;
if (ci->flags & CLIENT_HIDDEN || if (ci->flags & CLIENT_HIDDEN ||
ci->flags & CLIENT_IGNORE || (ci == cc) || ci->flags & CLIENT_IGNORE || (ci == cc) ||
ci->geom.x < area.x || ci->geom.x < area.x ||

47
conf.c
View File

@ -36,6 +36,21 @@ static const char *conf_bind_getmask(const char *, unsigned int *);
static void conf_unbind_key(struct conf *, struct bind_ctx *); static void conf_unbind_key(struct conf *, struct bind_ctx *);
static void conf_unbind_mouse(struct conf *, struct bind_ctx *); static void conf_unbind_mouse(struct conf *, struct bind_ctx *);
static const struct {
int num;
const char *name;
} group_binds[] = {
{ 0, "nogroup" },
{ 1, "one" },
{ 2, "two" },
{ 3, "three" },
{ 4, "four" },
{ 5, "five" },
{ 6, "six" },
{ 7, "seven" },
{ 8, "eight" },
{ 9, "nine" },
};
static int cursor_binds[] = { static int cursor_binds[] = {
XC_left_ptr, /* CF_NORMAL */ XC_left_ptr, /* CF_NORMAL */
XC_fleur, /* CF_MOVE */ XC_fleur, /* CF_MOVE */
@ -124,7 +139,7 @@ static const struct {
{ FUNC_SC(group-cycle, group_cycle, (CWM_CYCLE_FORWARD)) }, { FUNC_SC(group-cycle, group_cycle, (CWM_CYCLE_FORWARD)) },
{ FUNC_SC(group-rcycle, group_cycle, (CWM_CYCLE_REVERSE)) }, { FUNC_SC(group-rcycle, group_cycle, (CWM_CYCLE_REVERSE)) },
{ FUNC_SC(group-toggle-all, group_alltoggle, 0) }, { FUNC_SC(group-toggle-all, group_toggle_all, 0) },
{ FUNC_SC(group-toggle-1, group_toggle, 1) }, { FUNC_SC(group-toggle-1, group_toggle, 1) },
{ FUNC_SC(group-toggle-2, group_toggle, 2) }, { FUNC_SC(group-toggle-2, group_toggle, 2) },
{ FUNC_SC(group-toggle-3, group_toggle, 3) }, { FUNC_SC(group-toggle-3, group_toggle, 3) },
@ -266,7 +281,7 @@ conf_init(struct conf *c)
c->bwidth = 1; c->bwidth = 1;
c->mamount = 1; c->mamount = 1;
c->snapdist = 0; c->snapdist = 0;
c->ngroups = 10; c->ngroups = 0;
c->nameqlen = 5; c->nameqlen = 5;
TAILQ_INIT(&c->ignoreq); TAILQ_INIT(&c->ignoreq);
@ -478,30 +493,28 @@ conf_screen(struct screen_ctx *sc)
warnx("XftColorAllocValue: %s", Conf.color[i]); warnx("XftColorAllocValue: %s", Conf.color[i]);
break; break;
} }
if (XftColorAllocName(X_Dpy, sc->visual, sc->colormap, if (!XftColorAllocName(X_Dpy, sc->visual, sc->colormap,
Conf.color[i], &xc)) { Conf.color[i], &sc->xftcolor[i])) {
sc->xftcolor[i] = xc;
XftColorFree(X_Dpy, sc->visual, sc->colormap, &xc);
} else {
warnx("XftColorAllocName: %s", Conf.color[i]); warnx("XftColorAllocName: %s", Conf.color[i]);
XftColorAllocName(X_Dpy, sc->visual, sc->colormap, XftColorAllocName(X_Dpy, sc->visual, sc->colormap,
color_binds[i], &sc->xftcolor[i]); color_binds[i], &sc->xftcolor[i]);
} }
} }
sc->menu.win = 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->menu.xftdraw = XftDrawCreate(X_Dpy, sc->menu.win,
sc->visual, sc->colormap);
if (sc->menu.xftdraw == NULL)
errx(1, "%s: XftDrawCreate", __func__);
conf_grab_kbd(sc->rootwin); conf_grab_kbd(sc->rootwin);
} }
void
conf_group(struct screen_ctx *sc)
{
unsigned int i;
for (i = 0; i < nitems(group_binds); i++) {
group_init(sc, group_binds[i].num, group_binds[i].name);
Conf.ngroups++;
}
}
static const char * static const char *
conf_bind_getmask(const char *name, unsigned int *mask) conf_bind_getmask(const char *name, unsigned int *mask)
{ {

5
cwm.1
View File

@ -23,7 +23,7 @@
.Sh SYNOPSIS .Sh SYNOPSIS
.\" For a program: program [-abc] file ... .\" For a program: program [-abc] file ...
.Nm cwm .Nm cwm
.Op Fl v .Op Fl nv
.Op Fl c Ar file .Op Fl c Ar file
.Op Fl d Ar display .Op Fl d Ar display
.Sh DESCRIPTION .Sh DESCRIPTION
@ -48,6 +48,9 @@ however,
will continue to process the rest of the configuration file. will continue to process the rest of the configuration file.
.It Fl d Ar display .It Fl d Ar display
Specify the display to use. Specify the display to use.
.It Fl n
Configtest mode.
Only check the configuration file for validity.
.It Fl v .It Fl v
Verbose mode. Verbose mode.
Multiple Multiple

154
group.c
View File

@ -37,37 +37,30 @@ static struct group_ctx *group_prev(struct group_ctx *);
static void group_restack(struct group_ctx *); static void group_restack(struct group_ctx *);
static void group_setactive(struct group_ctx *); static void group_setactive(struct group_ctx *);
const char *num_to_name[] = {
"nogroup", "one", "two", "three", "four", "five", "six",
"seven", "eight", "nine"
};
void void
group_assign(struct group_ctx *gc, struct client_ctx *cc) group_assign(struct group_ctx *gc, struct client_ctx *cc)
{ {
if (cc->gc != NULL)
TAILQ_REMOVE(&cc->gc->clientq, cc, group_entry);
if ((gc != NULL) && (gc->num == 0)) if ((gc != NULL) && (gc->num == 0))
gc = NULL; gc = NULL;
cc->gc = gc; cc->gc = gc;
if (cc->gc != NULL)
TAILQ_INSERT_TAIL(&gc->clientq, cc, group_entry);
xu_ewmh_net_wm_desktop(cc); xu_ewmh_net_wm_desktop(cc);
} }
void void
group_hide(struct group_ctx *gc) group_hide(struct group_ctx *gc)
{ {
struct screen_ctx *sc = gc->sc;
struct client_ctx *cc; struct client_ctx *cc;
screen_updatestackingorder(gc->sc); screen_updatestackingorder(gc->sc);
TAILQ_FOREACH(cc, &gc->clientq, group_entry) { TAILQ_FOREACH(cc, &sc->clientq, entry) {
if (!(cc->flags & CLIENT_STICKY)) if (cc->gc != gc)
continue;
if (!(cc->flags & CLIENT_STICKY) &&
!(cc->flags & CLIENT_HIDDEN))
client_hide(cc); client_hide(cc);
} }
} }
@ -75,13 +68,16 @@ group_hide(struct group_ctx *gc)
void void
group_show(struct group_ctx *gc) group_show(struct group_ctx *gc)
{ {
struct screen_ctx *sc = gc->sc;
struct client_ctx *cc; struct client_ctx *cc;
TAILQ_FOREACH(cc, &gc->clientq, group_entry) { TAILQ_FOREACH(cc, &sc->clientq, entry) {
if (!(cc->flags & CLIENT_STICKY)) if (cc->gc != gc)
client_unhide(cc); continue;
if (!(cc->flags & CLIENT_STICKY) &&
(cc->flags & CLIENT_HIDDEN))
client_show(cc);
} }
group_restack(gc); group_restack(gc);
group_setactive(gc); group_setactive(gc);
} }
@ -89,19 +85,24 @@ group_show(struct group_ctx *gc)
static void static void
group_restack(struct group_ctx *gc) group_restack(struct group_ctx *gc)
{ {
struct screen_ctx *sc = gc->sc;
struct client_ctx *cc; struct client_ctx *cc;
Window *winlist; Window *winlist;
int i, lastempty = -1; int i, lastempty = -1;
int nwins = 0, highstack = 0; int nwins = 0, highstack = 0;
TAILQ_FOREACH(cc, &gc->clientq, group_entry) { TAILQ_FOREACH(cc, &sc->clientq, entry) {
if (cc->gc != gc)
continue;
if (cc->stackingorder > highstack) if (cc->stackingorder > highstack)
highstack = cc->stackingorder; highstack = cc->stackingorder;
} }
winlist = xreallocarray(NULL, (highstack + 1), sizeof(*winlist)); winlist = xreallocarray(NULL, (highstack + 1), sizeof(*winlist));
/* Invert the stacking order for XRestackWindows(). */ /* Invert the stacking order for XRestackWindows(). */
TAILQ_FOREACH(cc, &gc->clientq, group_entry) { TAILQ_FOREACH(cc, &sc->clientq, entry) {
if (cc->gc != gc)
continue;
winlist[highstack - cc->stackingorder] = cc->win; winlist[highstack - cc->stackingorder] = cc->win;
nwins++; nwins++;
} }
@ -122,16 +123,14 @@ group_restack(struct group_ctx *gc)
} }
void void
group_init(struct screen_ctx *sc, int num) group_init(struct screen_ctx *sc, int num, const char *name)
{ {
struct group_ctx *gc; struct group_ctx *gc;
gc = xmalloc(sizeof(*gc)); gc = xmalloc(sizeof(*gc));
gc->sc = sc; gc->sc = sc;
gc->name = xstrdup(num_to_name[num]); gc->name = xstrdup(name);
gc->num = num; gc->num = num;
TAILQ_INIT(&gc->clientq);
TAILQ_INSERT_TAIL(&sc->groupq, gc, entry); TAILQ_INSERT_TAIL(&sc->groupq, gc, entry);
if (num == 1) if (num == 1)
@ -154,19 +153,15 @@ group_movetogroup(struct client_ctx *cc, int idx)
struct screen_ctx *sc = cc->sc; struct screen_ctx *sc = cc->sc;
struct group_ctx *gc; struct group_ctx *gc;
if (idx < 0 || idx >= Conf.ngroups)
return;
TAILQ_FOREACH(gc, &sc->groupq, entry) { TAILQ_FOREACH(gc, &sc->groupq, entry) {
if (gc->num == idx) if (gc->num == idx) {
break; if (cc->gc == gc)
return;
if (gc->num != 0 && group_holds_only_hidden(gc))
client_hide(cc);
group_assign(gc, cc);
}
} }
if (cc->gc == gc)
return;
if (gc->num != 0 && group_holds_only_hidden(gc))
client_hide(cc);
group_assign(gc, cc);
} }
void void
@ -175,23 +170,25 @@ group_toggle_membership(struct client_ctx *cc)
struct screen_ctx *sc = cc->sc; struct screen_ctx *sc = cc->sc;
struct group_ctx *gc = sc->group_active; struct group_ctx *gc = sc->group_active;
if (gc == cc->gc) { if (cc->gc == gc) {
group_assign(NULL, cc); group_assign(NULL, cc);
cc->flags |= CLIENT_UNGROUP; cc->flags |= CLIENT_UNGROUP;
} else { } else {
group_assign(gc, cc); group_assign(gc, cc);
cc->flags |= CLIENT_GROUP; cc->flags |= CLIENT_GROUP;
} }
client_draw_border(cc); client_draw_border(cc);
} }
int int
group_holds_only_sticky(struct group_ctx *gc) group_holds_only_sticky(struct group_ctx *gc)
{ {
struct screen_ctx *sc = gc->sc;
struct client_ctx *cc; struct client_ctx *cc;
TAILQ_FOREACH(cc, &gc->clientq, group_entry) { TAILQ_FOREACH(cc, &sc->clientq, entry) {
if (cc->gc != gc)
continue;
if (!(cc->flags & CLIENT_STICKY)) if (!(cc->flags & CLIENT_STICKY))
return(0); return(0);
} }
@ -201,46 +198,23 @@ group_holds_only_sticky(struct group_ctx *gc)
int int
group_holds_only_hidden(struct group_ctx *gc) group_holds_only_hidden(struct group_ctx *gc)
{ {
struct screen_ctx *sc = gc->sc;
struct client_ctx *cc; struct client_ctx *cc;
TAILQ_FOREACH(cc, &gc->clientq, group_entry) { TAILQ_FOREACH(cc, &sc->clientq, entry) {
if (cc->gc != gc)
continue;
if (!(cc->flags & (CLIENT_HIDDEN | CLIENT_STICKY))) if (!(cc->flags & (CLIENT_HIDDEN | CLIENT_STICKY)))
return(0); return(0);
} }
return(1); return(1);
} }
void
group_hidetoggle(struct screen_ctx *sc, int idx)
{
struct group_ctx *gc;
if (idx < 0 || idx >= Conf.ngroups)
return;
TAILQ_FOREACH(gc, &sc->groupq, entry) {
if (gc->num == idx)
break;
}
if (group_holds_only_hidden(gc))
group_show(gc);
else {
group_hide(gc);
/* make clients stick to empty group */
if (TAILQ_EMPTY(&gc->clientq))
group_setactive(gc);
}
}
void void
group_only(struct screen_ctx *sc, int idx) group_only(struct screen_ctx *sc, int idx)
{ {
struct group_ctx *gc; struct group_ctx *gc;
if (idx < 0 || idx >= Conf.ngroups)
return;
TAILQ_FOREACH(gc, &sc->groupq, entry) { TAILQ_FOREACH(gc, &sc->groupq, entry) {
if (gc->num == idx) if (gc->num == idx)
group_show(gc); group_show(gc);
@ -249,19 +223,48 @@ group_only(struct screen_ctx *sc, int idx)
} }
} }
void
group_toggle(struct screen_ctx *sc, int idx)
{
struct group_ctx *gc;
TAILQ_FOREACH(gc, &sc->groupq, entry) {
if (gc->num == idx) {
if (group_holds_only_hidden(gc))
group_show(gc);
else
group_hide(gc);
}
}
}
void
group_toggle_all(struct screen_ctx *sc)
{
struct group_ctx *gc;
TAILQ_FOREACH(gc, &sc->groupq, entry) {
if (sc->hideall)
group_show(gc);
else
group_hide(gc);
}
sc->hideall = !sc->hideall;
}
void void
group_close(struct screen_ctx *sc, int idx) group_close(struct screen_ctx *sc, int idx)
{ {
struct group_ctx *gc; struct group_ctx *gc;
struct client_ctx *cc; struct client_ctx *cc;
if (idx < 0 || idx >= Conf.ngroups)
return;
TAILQ_FOREACH(gc, &sc->groupq, entry) { TAILQ_FOREACH(gc, &sc->groupq, entry) {
if (gc->num == idx) { if (gc->num == idx) {
TAILQ_FOREACH(cc, &gc->clientq, group_entry) TAILQ_FOREACH(cc, &sc->clientq, entry) {
if (cc->gc != gc)
continue;
client_close(cc); client_close(cc);
}
} }
} }
} }
@ -286,7 +289,6 @@ group_cycle(struct screen_ctx *sc, int flags)
else if (!group_holds_only_hidden(newgc)) else if (!group_holds_only_hidden(newgc))
group_hide(newgc); group_hide(newgc);
} }
if (showgroup == NULL) if (showgroup == NULL)
return; return;
@ -318,20 +320,6 @@ group_prev(struct group_ctx *gc)
newgc : TAILQ_LAST(&sc->groupq, group_q)); newgc : TAILQ_LAST(&sc->groupq, group_q));
} }
void
group_alltoggle(struct screen_ctx *sc)
{
struct group_ctx *gc;
TAILQ_FOREACH(gc, &sc->groupq, entry) {
if (sc->hideall)
group_show(gc);
else
group_hide(gc);
}
sc->hideall = !sc->hideall;
}
int int
group_restore(struct client_ctx *cc) group_restore(struct client_ctx *cc)
{ {

View File

@ -169,8 +169,8 @@ kbfunc_client_move_mb(void *ctx, struct cargs *cargs)
CurrentTime) != GrabSuccess) CurrentTime) != GrabSuccess)
return; return;
menu_windraw(sc, cc->win, "%4d, %-4d", cc->geom.x, cc->geom.y); screen_prop_win_create(sc, cc->win);
screen_prop_win_draw(sc, "%+5d%+5d", cc->geom.x, cc->geom.y);
while (move) { while (move) {
XMaskEvent(X_Dpy, MOUSEMASK, &ev); XMaskEvent(X_Dpy, MOUSEMASK, &ev);
switch (ev.type) { switch (ev.type) {
@ -193,8 +193,8 @@ kbfunc_client_move_mb(void *ctx, struct cargs *cargs)
cc->geom.y + cc->geom.h + (cc->bwidth * 2), cc->geom.y + cc->geom.h + (cc->bwidth * 2),
area.y, area.y + area.h, sc->snapdist); area.y, area.y + area.h, sc->snapdist);
client_move(cc); client_move(cc);
menu_windraw(sc, cc->win, screen_prop_win_draw(sc,
"%4d, %-4d", cc->geom.x, cc->geom.y); "%+5d%+5d", cc->geom.x, cc->geom.y);
break; break;
case ButtonRelease: case ButtonRelease:
move = 0; move = 0;
@ -203,8 +203,7 @@ kbfunc_client_move_mb(void *ctx, struct cargs *cargs)
} }
if (ltime) if (ltime)
client_move(cc); client_move(cc);
XUnmapWindow(X_Dpy, sc->menu.win); screen_prop_win_destroy(sc);
XReparentWindow(X_Dpy, sc->menu.win, sc->rootwin, 0, 0);
XUngrabPointer(X_Dpy, CurrentTime); XUngrabPointer(X_Dpy, CurrentTime);
} }
@ -258,7 +257,8 @@ kbfunc_client_resize_mb(void *ctx, struct cargs *cargs)
CurrentTime) != GrabSuccess) CurrentTime) != GrabSuccess)
return; return;
menu_windraw(sc, cc->win, "%4d x %-4d", cc->dim.w, cc->dim.h); screen_prop_win_create(sc, cc->win);
screen_prop_win_draw(sc, "%4d x %-4d", cc->dim.w, cc->dim.h);
while (resize) { while (resize) {
XMaskEvent(X_Dpy, MOUSEMASK, &ev); XMaskEvent(X_Dpy, MOUSEMASK, &ev);
switch (ev.type) { switch (ev.type) {
@ -272,7 +272,7 @@ kbfunc_client_resize_mb(void *ctx, struct cargs *cargs)
cc->geom.h = ev.xmotion.y; cc->geom.h = ev.xmotion.y;
client_applysizehints(cc); client_applysizehints(cc);
client_resize(cc, 1); client_resize(cc, 1);
menu_windraw(sc, cc->win, screen_prop_win_draw(sc,
"%4d x %-4d", cc->dim.w, cc->dim.h); "%4d x %-4d", cc->dim.w, cc->dim.h);
break; break;
case ButtonRelease: case ButtonRelease:
@ -282,8 +282,7 @@ kbfunc_client_resize_mb(void *ctx, struct cargs *cargs)
} }
if (ltime) if (ltime)
client_resize(cc, 1); client_resize(cc, 1);
XUnmapWindow(X_Dpy, sc->menu.win); screen_prop_win_destroy(sc);
XReparentWindow(X_Dpy, sc->menu.win, sc->rootwin, 0, 0);
XUngrabPointer(X_Dpy, CurrentTime); XUngrabPointer(X_Dpy, CurrentTime);
/* Make sure the pointer stays within the window. */ /* Make sure the pointer stays within the window. */
@ -431,18 +430,24 @@ kbfunc_client_movetogroup(void *ctx, struct cargs *cargs)
group_movetogroup(ctx, cargs->flag); group_movetogroup(ctx, cargs->flag);
} }
void
kbfunc_group_toggle(void *ctx, struct cargs *cargs)
{
group_hidetoggle(ctx, cargs->flag);
}
void void
kbfunc_group_only(void *ctx, struct cargs *cargs) kbfunc_group_only(void *ctx, struct cargs *cargs)
{ {
group_only(ctx, cargs->flag); group_only(ctx, cargs->flag);
} }
void
kbfunc_group_toggle(void *ctx, struct cargs *cargs)
{
group_toggle(ctx, cargs->flag);
}
void
kbfunc_group_toggle_all(void *ctx, struct cargs *cargs)
{
group_toggle_all(ctx);
}
void void
kbfunc_group_close(void *ctx, struct cargs *cargs) kbfunc_group_close(void *ctx, struct cargs *cargs)
{ {
@ -455,12 +460,6 @@ kbfunc_group_cycle(void *ctx, struct cargs *cargs)
group_cycle(ctx, cargs->flag); group_cycle(ctx, cargs->flag);
} }
void
kbfunc_group_alltoggle(void *ctx, struct cargs *cargs)
{
group_alltoggle(ctx);
}
void void
kbfunc_menu_client(void *ctx, struct cargs *cargs) kbfunc_menu_client(void *ctx, struct cargs *cargs)
{ {
@ -474,7 +473,7 @@ kbfunc_menu_client(void *ctx, struct cargs *cargs)
if (cargs->xev == CWM_XEV_BTN) if (cargs->xev == CWM_XEV_BTN)
mflags |= CWM_MENU_LIST; mflags |= CWM_MENU_LIST;
old_cc = client_current(); old_cc = client_current(sc);
TAILQ_INIT(&menuq); TAILQ_INIT(&menuq);
TAILQ_FOREACH(cc, &sc->clientq, entry) { TAILQ_FOREACH(cc, &sc->clientq, entry) {

82
menu.c
View File

@ -37,6 +37,10 @@
#define PROMPT_SCHAR "\xc2\xbb" #define PROMPT_SCHAR "\xc2\xbb"
#define PROMPT_ECHAR "\xc2\xab" #define PROMPT_ECHAR "\xc2\xab"
#define MENUMASK (MOUSEMASK | ButtonMotionMask | KeyPressMask | \
ExposureMask)
#define MENUGRABMASK (MOUSEMASK | ButtonMotionMask | StructureNotifyMask)
enum ctltype { enum ctltype {
CTL_NONE = -1, CTL_NONE = -1,
CTL_ERASEONE = 0, CTL_WIPE, CTL_UP, CTL_DOWN, CTL_RETURN, CTL_ERASEONE = 0, CTL_WIPE, CTL_UP, CTL_DOWN, CTL_RETURN,
@ -45,6 +49,9 @@ enum ctltype {
struct menu_ctx { struct menu_ctx {
struct screen_ctx *sc; struct screen_ctx *sc;
Window win;
XftDraw *xftdraw;
struct geom geom;
char searchstr[MENU_MAXENTRY + 1]; char searchstr[MENU_MAXENTRY + 1];
char dispstr[MENU_MAXENTRY*2 + 1]; char dispstr[MENU_MAXENTRY*2 + 1];
char promptstr[MENU_MAXENTRY + 1]; char promptstr[MENU_MAXENTRY + 1];
@ -55,7 +62,6 @@ struct menu_ctx {
int entry; int entry;
int num; int num;
int flags; int flags;
struct geom geom;
void (*match)(struct menu_q *, struct menu_q *, char *); void (*match)(struct menu_q *, struct menu_q *, char *);
void (*print)(struct menu *, int); void (*print)(struct menu *, int);
}; };
@ -108,27 +114,34 @@ menu_filter(struct screen_ctx *sc, struct menu_q *menuq, const char *prompt,
else else
mc.searchstr[0] = '\0'; mc.searchstr[0] = '\0';
XSelectInput(X_Dpy, sc->menu.win, MENUMASK); mc.win = XCreateSimpleWindow(X_Dpy, sc->rootwin, 0, 0, 1, 1,
XMapRaised(X_Dpy, sc->menu.win); Conf.bwidth,
sc->xftcolor[CWM_COLOR_MENU_FG].pixel,
sc->xftcolor[CWM_COLOR_MENU_BG].pixel);
mc.xftdraw = XftDrawCreate(X_Dpy, mc.win,
sc->visual, sc->colormap);
if (XGrabPointer(X_Dpy, sc->menu.win, False, MENUGRABMASK, XSelectInput(X_Dpy, mc.win, MENUMASK);
XMapRaised(X_Dpy, mc.win);
if (XGrabPointer(X_Dpy, mc.win, False, MENUGRABMASK,
GrabModeAsync, GrabModeAsync, None, Conf.cursor[CF_QUESTION], GrabModeAsync, GrabModeAsync, None, Conf.cursor[CF_QUESTION],
CurrentTime) != GrabSuccess) { CurrentTime) != GrabSuccess) {
XUnmapWindow(X_Dpy, sc->menu.win); XftDrawDestroy(mc.xftdraw);
return(NULL); XDestroyWindow(X_Dpy, mc.win);
} }
XGetInputFocus(X_Dpy, &focuswin, &focusrevert); XGetInputFocus(X_Dpy, &focuswin, &focusrevert);
XSetInputFocus(X_Dpy, sc->menu.win, RevertToPointerRoot, CurrentTime); XSetInputFocus(X_Dpy, mc.win, RevertToPointerRoot, CurrentTime);
/* make sure keybindings don't remove keys from the menu stream */ /* make sure keybindings don't remove keys from the menu stream */
XGrabKeyboard(X_Dpy, sc->menu.win, True, XGrabKeyboard(X_Dpy, mc.win, True,
GrabModeAsync, GrabModeAsync, CurrentTime); GrabModeAsync, GrabModeAsync, CurrentTime);
for (;;) { for (;;) {
mc.changed = 0; mc.changed = 0;
XWindowEvent(X_Dpy, sc->menu.win, MENUMASK, &e); XWindowEvent(X_Dpy, mc.win, MENUMASK, &e);
switch (e.type) { switch (e.type) {
case KeyPress: case KeyPress:
@ -159,16 +172,16 @@ out:
mi = NULL; mi = NULL;
} }
XSelectInput(X_Dpy, sc->menu.win, NoEventMask); XftDrawDestroy(mc.xftdraw);
XDestroyWindow(X_Dpy, mc.win);
XSetInputFocus(X_Dpy, focuswin, focusrevert, CurrentTime); XSetInputFocus(X_Dpy, focuswin, focusrevert, CurrentTime);
/* restore if user didn't move */ /* restore if user didn't move */
xu_ptr_getpos(sc->rootwin, &xcur, &ycur); xu_ptr_getpos(sc->rootwin, &xcur, &ycur);
if (xcur == mc.geom.x && ycur == mc.geom.y) if (xcur == mc.geom.x && ycur == mc.geom.y)
xu_ptr_setpos(sc->rootwin, xsave, ysave); xu_ptr_setpos(sc->rootwin, xsave, ysave);
XUngrabPointer(X_Dpy, CurrentTime);
XMoveResizeWindow(X_Dpy, sc->menu.win, 0, 0, 1, 1); XUngrabPointer(X_Dpy, CurrentTime);
XUnmapWindow(X_Dpy, sc->menu.win);
XUngrabKeyboard(X_Dpy, CurrentTime); XUngrabKeyboard(X_Dpy, CurrentTime);
return(mi); return(mi);
@ -378,12 +391,12 @@ menu_draw(struct menu_ctx *mc, struct menu_q *menuq, struct menu_q *resultq)
if (mc->geom.x != xsave || mc->geom.y != ysave) if (mc->geom.x != xsave || mc->geom.y != ysave)
xu_ptr_setpos(sc->rootwin, mc->geom.x, mc->geom.y); xu_ptr_setpos(sc->rootwin, mc->geom.x, mc->geom.y);
XClearWindow(X_Dpy, sc->menu.win); XClearWindow(X_Dpy, mc->win);
XMoveResizeWindow(X_Dpy, sc->menu.win, mc->geom.x, mc->geom.y, XMoveResizeWindow(X_Dpy, mc->win, mc->geom.x, mc->geom.y,
mc->geom.w, mc->geom.h); mc->geom.w, mc->geom.h);
n = 1; n = 1;
XftDrawStringUtf8(sc->menu.xftdraw, XftDrawStringUtf8(mc->xftdraw,
&sc->xftcolor[CWM_COLOR_MENU_FONT], sc->xftfont, &sc->xftcolor[CWM_COLOR_MENU_FONT], sc->xftfont,
0, sc->xftfont->ascent, 0, sc->xftfont->ascent,
(const FcChar8*)mc->dispstr, strlen(mc->dispstr)); (const FcChar8*)mc->dispstr, strlen(mc->dispstr));
@ -395,7 +408,7 @@ menu_draw(struct menu_ctx *mc, struct menu_q *menuq, struct menu_q *resultq)
if (mc->geom.y + y > area.h) if (mc->geom.y + y > area.h)
break; break;
XftDrawStringUtf8(sc->menu.xftdraw, XftDrawStringUtf8(mc->xftdraw,
&sc->xftcolor[CWM_COLOR_MENU_FONT], sc->xftfont, &sc->xftcolor[CWM_COLOR_MENU_FONT], sc->xftfont,
0, y, 0, y,
(const FcChar8*)mi->print, strlen(mi->print)); (const FcChar8*)mi->print, strlen(mi->print));
@ -420,11 +433,11 @@ menu_draw_entry(struct menu_ctx *mc, struct menu_q *resultq,
return; return;
color = (active) ? CWM_COLOR_MENU_FG : CWM_COLOR_MENU_BG; color = (active) ? CWM_COLOR_MENU_FG : CWM_COLOR_MENU_BG;
XftDrawRect(sc->menu.xftdraw, &sc->xftcolor[color], 0, XftDrawRect(mc->xftdraw, &sc->xftcolor[color], 0,
(sc->xftfont->height + 1) * entry, mc->geom.w, (sc->xftfont->height + 1) * entry, mc->geom.w,
(sc->xftfont->height + 1) + sc->xftfont->descent); (sc->xftfont->height + 1) + sc->xftfont->descent);
color = (active) ? CWM_COLOR_MENU_FONT_SEL : CWM_COLOR_MENU_FONT; color = (active) ? CWM_COLOR_MENU_FONT_SEL : CWM_COLOR_MENU_FONT;
XftDrawStringUtf8(sc->menu.xftdraw, XftDrawStringUtf8(mc->xftdraw,
&sc->xftcolor[color], sc->xftfont, &sc->xftcolor[color], sc->xftfont,
0, (sc->xftfont->height + 1) * entry + sc->xftfont->ascent + 1, 0, (sc->xftfont->height + 1) * entry + sc->xftfont->ascent + 1,
(const FcChar8*)mi->print, strlen(mi->print)); (const FcChar8*)mi->print, strlen(mi->print));
@ -604,34 +617,3 @@ menuq_clear(struct menu_q *mq)
free(mi); free(mi);
} }
} }
void
menu_windraw(struct screen_ctx *sc, Window win, const char *fmt, ...)
{
va_list ap;
int i;
char *text;
XGlyphInfo extents;
va_start(ap, fmt);
i = vasprintf(&text, fmt, ap);
va_end(ap);
if (i < 0 || text == NULL)
err(1, "vasprintf");
XftTextExtentsUtf8(X_Dpy, sc->xftfont, (const FcChar8*)text,
strlen(text), &extents);
XReparentWindow(X_Dpy, sc->menu.win, win, 0, 0);
XMoveResizeWindow(X_Dpy, sc->menu.win, 0, 0,
extents.xOff, sc->xftfont->height);
XMapWindow(X_Dpy, sc->menu.win);
XClearWindow(X_Dpy, sc->menu.win);
XftDrawStringUtf8(sc->menu.xftdraw, &sc->xftcolor[CWM_COLOR_MENU_FONT],
sc->xftfont, 0, sc->xftfont->ascent + 1,
(const FcChar8*)text, strlen(text));
free(text);
}

View File

@ -24,6 +24,7 @@
#include <err.h> #include <err.h>
#include <errno.h> #include <errno.h>
#include <limits.h> #include <limits.h>
#include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -40,7 +41,6 @@ screen_init(int which)
Window *wins, w0, w1, active = None; Window *wins, w0, w1, active = None;
XSetWindowAttributes rootattr; XSetWindowAttributes rootattr;
unsigned int nwins, w; unsigned int nwins, w;
int i;
sc = xmalloc(sizeof(*sc)); sc = xmalloc(sizeof(*sc));
@ -60,14 +60,11 @@ screen_init(int which)
xu_ewmh_net_supported(sc); xu_ewmh_net_supported(sc);
xu_ewmh_net_supported_wm_check(sc); xu_ewmh_net_supported_wm_check(sc);
conf_group(sc);
screen_update_geometry(sc); screen_update_geometry(sc);
for (i = 0; i < Conf.ngroups; i++)
group_init(sc, i);
xu_ewmh_net_desktop_names(sc); xu_ewmh_net_desktop_names(sc);
xu_ewmh_net_wm_desktop_viewport(sc); xu_ewmh_net_number_of_desktops(sc);
xu_ewmh_net_wm_number_of_desktops(sc);
xu_ewmh_net_showing_desktop(sc); xu_ewmh_net_showing_desktop(sc);
xu_ewmh_net_virtual_roots(sc); xu_ewmh_net_virtual_roots(sc);
active = xu_ewmh_get_net_active_window(sc); active = xu_ewmh_get_net_active_window(sc);
@ -106,7 +103,7 @@ screen_find(Window win)
if (sc->rootwin == win) if (sc->rootwin == win)
return(sc); return(sc);
} }
warnx("%s: failure win 0x%lu\n", __func__, win); warnx("%s: failure win 0x%lx", __func__, win);
return(NULL); return(NULL);
} }
@ -217,6 +214,7 @@ screen_update_geometry(struct screen_ctx *sc)
} }
xu_ewmh_net_desktop_geometry(sc); xu_ewmh_net_desktop_geometry(sc);
xu_ewmh_net_desktop_viewport(sc);
xu_ewmh_net_workarea(sc); xu_ewmh_net_workarea(sc);
} }
@ -253,3 +251,47 @@ screen_assert_clients_within(struct screen_ctx *sc)
} }
} }
} }
void
screen_prop_win_create(struct screen_ctx *sc, Window win)
{
sc->prop.win = XCreateSimpleWindow(X_Dpy, win, 0, 0, 1, 1, 0,
sc->xftcolor[CWM_COLOR_MENU_BG].pixel,
sc->xftcolor[CWM_COLOR_MENU_BG].pixel);
sc->prop.xftdraw = XftDrawCreate(X_Dpy, sc->prop.win,
sc->visual, sc->colormap);
XMapWindow(X_Dpy, sc->prop.win);
}
void
screen_prop_win_destroy(struct screen_ctx *sc)
{
XftDrawDestroy(sc->prop.xftdraw);
XDestroyWindow(X_Dpy, sc->prop.win);
}
void
screen_prop_win_draw(struct screen_ctx *sc, const char *fmt, ...)
{
va_list ap;
int i;
char *text;
XGlyphInfo extents;
va_start(ap, fmt);
i = vasprintf(&text, fmt, ap);
va_end(ap);
if (i < 0 || text == NULL)
err(1, "vasprintf");
XftTextExtentsUtf8(X_Dpy, sc->xftfont, (const FcChar8*)text,
strlen(text), &extents);
XResizeWindow(X_Dpy, sc->prop.win, extents.xOff, sc->xftfont->height);
XClearWindow(X_Dpy, sc->prop.win);
XftDrawStringUtf8(sc->prop.xftdraw, &sc->xftcolor[CWM_COLOR_MENU_FONT],
sc->xftfont, 0, sc->xftfont->ascent + 1,
(const FcChar8*)text, strlen(text));
free(text);
}

View File

@ -75,11 +75,15 @@ static void
xev_handle_maprequest(XEvent *ee) xev_handle_maprequest(XEvent *ee)
{ {
XMapRequestEvent *e = &ee->xmaprequest; XMapRequestEvent *e = &ee->xmaprequest;
struct client_ctx *cc = NULL, *old_cc; struct screen_ctx *sc;
struct client_ctx *cc, *old_cc;
LOG_DEBUG3("window: 0x%lx", e->window); LOG_DEBUG3("parent: 0x%lx window: 0x%lx", e->parent, e->window);
if ((old_cc = client_current()) != NULL) if ((sc = screen_find(e->parent)) == NULL)
return;
if ((old_cc = client_current(sc)) != NULL)
client_ptrsave(old_cc); client_ptrsave(old_cc);
if ((cc = client_find(e->window)) == NULL) if ((cc = client_find(e->window)) == NULL)
@ -207,11 +211,9 @@ xev_handle_propertynotify(XEvent *ee)
break; break;
} }
} else { } else {
TAILQ_FOREACH(sc, &Screenq, entry) { if (e->atom == ewmh[_NET_DESKTOP_NAMES]) {
if (sc->rootwin == e->window) { if ((sc = screen_find(e->window)) != NULL)
if (e->atom == ewmh[_NET_DESKTOP_NAMES]) xu_ewmh_net_desktop_names(sc);
xu_ewmh_net_desktop_names(sc);
}
} }
} }
} }
@ -238,7 +240,11 @@ xev_handle_buttonpress(XEvent *ee)
struct screen_ctx *sc; struct screen_ctx *sc;
struct bind_ctx *mb; struct bind_ctx *mb;
LOG_DEBUG3("window: 0x%lx", e->window); LOG_DEBUG3("root: 0x%lx window: 0x%lx subwindow: 0x%lx",
e->root, e->window, e->subwindow);
if ((sc = screen_find(e->root)) == NULL)
return;
e->state &= ~IGNOREMODMASK; e->state &= ~IGNOREMODMASK;
@ -246,22 +252,17 @@ xev_handle_buttonpress(XEvent *ee)
if (e->button == mb->press.button && e->state == mb->modmask) if (e->button == mb->press.button && e->state == mb->modmask)
break; break;
} }
if (mb == NULL) if (mb == NULL)
return; return;
mb->cargs->xev = CWM_XEV_BTN; mb->cargs->xev = CWM_XEV_BTN;
switch (mb->context) { switch (mb->context) {
case CWM_CONTEXT_CC: case CWM_CONTEXT_CC:
if (((cc = client_find(e->window)) == NULL) && if (((cc = client_find(e->window)) == NULL) &&
(cc = client_current()) == NULL) ((cc = client_current(sc)) == NULL))
return; return;
(*mb->callback)(cc, mb->cargs); (*mb->callback)(cc, mb->cargs);
break; break;
case CWM_CONTEXT_SC: case CWM_CONTEXT_SC:
if (e->window != e->root)
return;
if ((sc = screen_find(e->window)) == NULL)
return;
(*mb->callback)(sc, mb->cargs); (*mb->callback)(sc, mb->cargs);
break; break;
case CWM_CONTEXT_NONE: case CWM_CONTEXT_NONE:
@ -276,7 +277,8 @@ xev_handle_buttonrelease(XEvent *ee)
XButtonEvent *e = &ee->xbutton; XButtonEvent *e = &ee->xbutton;
struct client_ctx *cc; struct client_ctx *cc;
LOG_DEBUG3("window: 0x%lx", ee->xbutton.window); LOG_DEBUG3("root: 0x%lx window: 0x%lx subwindow: 0x%lx",
e->root, e->window, e->subwindow);
if ((cc = client_find(e->window)) != NULL) { if ((cc = client_find(e->window)) != NULL) {
if (cc->flags & (CLIENT_ACTIVE | CLIENT_HIGHLIGHT)) { if (cc->flags & (CLIENT_ACTIVE | CLIENT_HIGHLIGHT)) {
@ -296,7 +298,11 @@ xev_handle_keypress(XEvent *ee)
KeySym keysym, skeysym; KeySym keysym, skeysym;
unsigned int modshift; unsigned int modshift;
LOG_DEBUG3("window: 0x%lx", e->window); LOG_DEBUG3("root: 0x%lx window: 0x%lx subwindow: 0x%lx",
e->root, e->window, e->subwindow);
if ((sc = screen_find(e->root)) == NULL)
return;
keysym = XkbKeycodeToKeysym(X_Dpy, e->keycode, 0, 0); keysym = XkbKeycodeToKeysym(X_Dpy, e->keycode, 0, 0);
skeysym = XkbKeycodeToKeysym(X_Dpy, e->keycode, 0, 1); skeysym = XkbKeycodeToKeysym(X_Dpy, e->keycode, 0, 1);
@ -315,20 +321,17 @@ xev_handle_keypress(XEvent *ee)
if (kb->press.keysym == ((modshift == 0) ? keysym : skeysym)) if (kb->press.keysym == ((modshift == 0) ? keysym : skeysym))
break; break;
} }
if (kb == NULL) if (kb == NULL)
return; return;
kb->cargs->xev = CWM_XEV_KEY; kb->cargs->xev = CWM_XEV_KEY;
switch (kb->context) { switch (kb->context) {
case CWM_CONTEXT_CC: case CWM_CONTEXT_CC:
if (((cc = client_find(e->window)) == NULL) && if (((cc = client_find(e->subwindow)) == NULL) &&
(cc = client_current()) == NULL) ((cc = client_current(sc)) == NULL))
return; return;
(*kb->callback)(cc, kb->cargs); (*kb->callback)(cc, kb->cargs);
break; break;
case CWM_CONTEXT_SC: case CWM_CONTEXT_SC:
if ((sc = screen_find(e->window)) == NULL)
return;
(*kb->callback)(sc, kb->cargs); (*kb->callback)(sc, kb->cargs);
break; break;
case CWM_CONTEXT_NONE: case CWM_CONTEXT_NONE:
@ -349,7 +352,8 @@ xev_handle_keyrelease(XEvent *ee)
KeySym keysym; KeySym keysym;
unsigned int i; unsigned int i;
LOG_DEBUG3("window: 0x%lx", e->window); LOG_DEBUG3("root: 0x%lx window: 0x%lx subwindow: 0x%lx",
e->root, e->window, e->subwindow);
if ((sc = screen_find(e->root)) == NULL) if ((sc = screen_find(e->root)) == NULL)
return; return;
@ -357,7 +361,7 @@ xev_handle_keyrelease(XEvent *ee)
keysym = XkbKeycodeToKeysym(X_Dpy, e->keycode, 0, 0); keysym = XkbKeycodeToKeysym(X_Dpy, e->keycode, 0, 0);
for (i = 0; i < nitems(modkeys); i++) { for (i = 0; i < nitems(modkeys); i++) {
if (keysym == modkeys[i]) { if (keysym == modkeys[i]) {
if ((cc = client_current()) != NULL) { if ((cc = client_current(sc)) != NULL) {
if (sc->cycling) { if (sc->cycling) {
sc->cycling = 0; sc->cycling = 0;
client_mtf(cc); client_mtf(cc);
@ -393,7 +397,7 @@ xev_handle_clientmessage(XEvent *ee)
} }
} else if (e->message_type == ewmh[_NET_ACTIVE_WINDOW]) { } else if (e->message_type == ewmh[_NET_ACTIVE_WINDOW]) {
if ((cc = client_find(e->window)) != NULL) { if ((cc = client_find(e->window)) != NULL) {
if ((old_cc = client_current()) != NULL) if ((old_cc = client_current(NULL)) != NULL)
client_ptrsave(old_cc); client_ptrsave(old_cc);
client_show(cc); client_show(cc);
client_ptrwarp(cc); client_ptrwarp(cc);
@ -408,7 +412,9 @@ xev_handle_clientmessage(XEvent *ee)
if (e->data.l[0] == (unsigned long)-1) if (e->data.l[0] == (unsigned long)-1)
group_movetogroup(cc, 0); group_movetogroup(cc, 0);
else else
group_movetogroup(cc, e->data.l[0]); if (e->data.l[0] >= 0 &&
e->data.l[0] < Conf.ngroups)
group_movetogroup(cc, e->data.l[0]);
} }
} else if (e->message_type == ewmh[_NET_WM_STATE]) { } else if (e->message_type == ewmh[_NET_WM_STATE]) {
if ((cc = client_find(e->window)) != NULL) { if ((cc = client_find(e->window)) != NULL) {
@ -417,7 +423,9 @@ xev_handle_clientmessage(XEvent *ee)
} }
} else if (e->message_type == ewmh[_NET_CURRENT_DESKTOP]) { } else if (e->message_type == ewmh[_NET_CURRENT_DESKTOP]) {
if ((sc = screen_find(e->window)) != NULL) { if ((sc = screen_find(e->window)) != NULL) {
group_only(sc, e->data.l[0]); if (e->data.l[0] >= 0 &&
e->data.l[0] < Conf.ngroups)
group_only(sc, e->data.l[0]);
} }
} }
} }
@ -425,20 +433,17 @@ xev_handle_clientmessage(XEvent *ee)
static void static void
xev_handle_randr(XEvent *ee) xev_handle_randr(XEvent *ee)
{ {
XRRScreenChangeNotifyEvent *rev = (XRRScreenChangeNotifyEvent *)ee; XRRScreenChangeNotifyEvent *e = (XRRScreenChangeNotifyEvent *)ee;
struct screen_ctx *sc; struct screen_ctx *sc;
int i;
LOG_DEBUG3("new size: %d/%d", rev->width, rev->height); LOG_DEBUG3("size: %d/%d", e->width, e->height);
i = XRRRootToScreen(X_Dpy, rev->root); if ((sc = screen_find(e->root)) == NULL)
TAILQ_FOREACH(sc, &Screenq, entry) { return;
if (sc->which == i) {
XRRUpdateConfiguration(ee); XRRUpdateConfiguration(ee);
screen_update_geometry(sc); screen_update_geometry(sc);
screen_assert_clients_within(sc); screen_assert_clients_within(sc);
}
}
} }
/* /*
@ -479,9 +484,9 @@ xev_process(void)
while (XPending(X_Dpy)) { while (XPending(X_Dpy)) {
XNextEvent(X_Dpy, &e); XNextEvent(X_Dpy, &e);
if (e.type - Conf.xrandr_event_base == RRScreenChangeNotify) if ((e.type - Conf.xrandr_event_base) == RRScreenChangeNotify)
xev_handle_randr(&e); xev_handle_randr(&e);
else if (e.type < LASTEvent && xev_handlers[e.type] != NULL) else if ((e.type < LASTEvent) && (xev_handlers[e.type] != NULL))
(*xev_handlers[e.type])(&e); (*xev_handlers[e.type])(&e);
} }
} }

22
xutil.c
View File

@ -128,6 +128,16 @@ xu_ewmh_net_desktop_geometry(struct screen_ctx *sc)
XA_CARDINAL, 32, PropModeReplace, (unsigned char *)geom , 2); XA_CARDINAL, 32, PropModeReplace, (unsigned char *)geom , 2);
} }
void
xu_ewmh_net_desktop_viewport(struct screen_ctx *sc)
{
long viewports[2] = {0, 0};
/* We don't support large desktops, so this is (0, 0). */
XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_DESKTOP_VIEWPORT],
XA_CARDINAL, 32, PropModeReplace, (unsigned char *)viewports, 2);
}
void void
xu_ewmh_net_workarea(struct screen_ctx *sc) xu_ewmh_net_workarea(struct screen_ctx *sc)
{ {
@ -212,17 +222,7 @@ xu_ewmh_get_net_active_window(struct screen_ctx *sc)
} }
void void
xu_ewmh_net_wm_desktop_viewport(struct screen_ctx *sc) xu_ewmh_net_number_of_desktops(struct screen_ctx *sc)
{
long viewports[2] = {0, 0};
/* We don't support large desktops, so this is (0, 0). */
XChangeProperty(X_Dpy, sc->rootwin, ewmh[_NET_DESKTOP_VIEWPORT],
XA_CARDINAL, 32, PropModeReplace, (unsigned char *)viewports, 2);
}
void
xu_ewmh_net_wm_number_of_desktops(struct screen_ctx *sc)
{ {
long ndesks = Conf.ngroups; long ndesks = Conf.ngroups;