cvsimport

* refs/heads/master: (28 commits)
  Use screen's saved view instead of re-querying the server.
  Slightly expand and expose verbose debugging.
  add debugging for x events
  Add a simple debug logging mechanism.
  Simplification; use asprintf where appropriate now.
  Use func attributes where appropriate.
  Fix wins comparison declaration since it's unsigned from XQueryTree().
  Generate name_to_func[] in a clean and readable fashion.
  Shrink tier[] by one after removing matchname in r1.55.
  If the requested group number is invalid, bail but don't kill cwm.
  Quick fix: exit after a failed execvp in u_spawn instead; previously we did in u_exec, but the introduction of re-exec'ing the previous invocation of cwm if 'exec_wm' failed missed the 'exec' failing path. Will likely split out as a proper fix.
  Only exec the fallback when in CWM_EXEC_WM state.
  Typo, from Julien Steinhauser.
  Convert menu-exec-wm from an abritrary exec menu, into a config-based menu from which one may configure (wm <name> <path_and_args>) (and choose) specific window managers to replace the running one. 'wm cwm cwm' is included by default.
  As done for buttonrelease, work specific un-cycling and un-highlighting actions into the keyrelease event, only performing what's actually needed for each; should result in much fewer events against keyreleases. No intended behaviour change.
  Merge group_toggle_membership_leave into the buttonrelease event and only do border work for a group/ungroup action.
  add helper function client_show to bring together like actions for unhide/raise
  Add support for re-exec'ing with SIGHUP; equivalent to the already built-in 'restart' function.
  Use poll and XNextEvent to replace XNextEvent blocking inside the x11 event handler.
  zap stray that snuck in
  ...
This commit is contained in:
okan 2018-02-06 15:05:20 +00:00
commit 63ebc0cd8b
15 changed files with 539 additions and 382 deletions

View File

@ -27,6 +27,7 @@
#include <getopt.h>
#include <limits.h>
#include <locale.h>
#include <poll.h>
#include <pwd.h>
#include <signal.h>
#include <stdio.h>
@ -46,7 +47,7 @@ volatile sig_atomic_t cwm_status;
static void sighdlr(int);
static int x_errorhandler(Display *, XErrorEvent *);
static void x_init(const char *);
static int x_init(const char *);
static void x_teardown(void);
static int x_wmerrorhandler(Display *, XErrorEvent *);
@ -55,15 +56,18 @@ main(int argc, char **argv)
{
const char *conf_file = NULL;
char *conf_path, *display_name = NULL;
int ch;
char *fallback;
int ch, xfd;
struct pollfd pfd[1];
struct passwd *pw;
if (!setlocale(LC_CTYPE, "") || !XSupportsLocale())
warnx("no locale support");
mbtowc(NULL, NULL, MB_CUR_MAX);
fallback = u_argv(argv);
Conf.wm_argv = u_argv(argv);
while ((ch = getopt(argc, argv, "c:d:")) != -1) {
while ((ch = getopt(argc, argv, "c:d:v")) != -1) {
switch (ch) {
case 'c':
conf_file = optarg;
@ -71,6 +75,9 @@ main(int argc, char **argv)
case 'd':
display_name = optarg;
break;
case 'v':
Conf.debug++;
break;
default:
usage();
}
@ -80,8 +87,11 @@ main(int argc, char **argv)
if (signal(SIGCHLD, sighdlr) == SIG_ERR)
err(1, "signal");
if (signal(SIGHUP, sighdlr) == SIG_ERR)
err(1, "signal");
if ((Conf.homedir = getenv("HOME")) == NULL || Conf.homedir[0] == '\0') {
Conf.homedir = getenv("HOME");
if ((Conf.homedir == NULL) || (Conf.homedir[0] == '\0')) {
pw = getpwuid(getuid());
if (pw != NULL && pw->pw_dir != NULL && *pw->pw_dir != '\0')
Conf.homedir = pw->pw_dir;
@ -107,7 +117,7 @@ main(int argc, char **argv)
warnx("config file %s has errors", conf_path);
free(conf_path);
x_init(display_name);
xfd = x_init(display_name);
cwm_status = CWM_RUNNING;
#ifdef __OpenBSD__
@ -115,16 +125,27 @@ main(int argc, char **argv)
err(1, "pledge");
#endif
while (cwm_status == CWM_RUNNING)
memset(&pfd, 0, sizeof(pfd));
pfd[0].fd = xfd;
pfd[0].events = POLLIN;
while (cwm_status == CWM_RUNNING) {
xev_process();
if (poll(pfd, 1, INFTIM) == -1) {
if (errno != EINTR)
warn("poll");
}
}
x_teardown();
if (cwm_status == CWM_EXEC_WM)
if (cwm_status == CWM_EXEC_WM) {
u_exec(Conf.wm_argv);
warnx("'%s' failed to start, restarting fallback", Conf.wm_argv);
u_exec(fallback);
}
return(0);
}
static void
static int
x_init(const char *dpyname)
{
int i;
@ -144,6 +165,8 @@ x_init(const char *dpyname)
for (i = 0; i < ScreenCount(X_Dpy); i++)
screen_init(i);
return ConnectionNumber(X_Dpy);
}
static void
@ -210,6 +233,9 @@ sighdlr(int sig)
(pid < 0 && errno == EINTR))
;
break;
case SIGHUP:
cwm_status = CWM_EXEC_WM;
break;
}
errno = save_errno;
@ -220,7 +246,7 @@ usage(void)
{
extern char *__progname;
(void)fprintf(stderr, "usage: %s [-c file] [-d display]\n",
(void)fprintf(stderr, "usage: %s [-v] [-c file] [-d display]\n",
__progname);
exit(1);
}

View File

@ -52,6 +52,11 @@ size_t strlcpy(char *, const char *, size_t);
#include <X11/extensions/Xrandr.h>
#include <X11/keysym.h>
#define LOG_DEBUG0(...) log_debug(0, __func__, __VA_ARGS__)
#define LOG_DEBUG1(...) log_debug(1, __func__, __VA_ARGS__)
#define LOG_DEBUG2(...) log_debug(2, __func__, __VA_ARGS__)
#define LOG_DEBUG3(...) log_debug(3, __func__, __VA_ARGS__)
#undef MIN
#undef MAX
#define MIN(x, y) ((x) < (y) ? (x) : (y))
@ -65,9 +70,9 @@ size_t strlcpy(char *, const char *, size_t);
#define BUTTONMASK (ButtonPressMask | ButtonReleaseMask)
#define MOUSEMASK (BUTTONMASK | PointerMotionMask)
#define MENUMASK (MOUSEMASK | ButtonMotionMask | ExposureMask)
#define MENUMASK (MOUSEMASK | ButtonMotionMask | KeyPressMask | \
ExposureMask)
#define MENUGRABMASK (MOUSEMASK | ButtonMotionMask | StructureNotifyMask)
#define KEYMASK (KeyPressMask | ExposureMask)
#define IGNOREMODMASK (LockMask | Mod2Mask | 0x2000)
/* direction/amount */
@ -76,7 +81,15 @@ size_t strlcpy(char *, const char *, size_t);
#define CWM_LEFT 0x0004
#define CWM_RIGHT 0x0008
#define CWM_BIGAMOUNT 0x0010
#define DIRECTIONMASK (CWM_UP | CWM_DOWN | CWM_LEFT | CWM_RIGHT)
#define CWM_UP_BIG (CWM_UP | CWM_BIGAMOUNT)
#define CWM_DOWN_BIG (CWM_DOWN | CWM_BIGAMOUNT)
#define CWM_LEFT_BIG (CWM_LEFT | CWM_BIGAMOUNT)
#define CWM_RIGHT_BIG (CWM_RIGHT | CWM_BIGAMOUNT)
#define CWM_UP_RIGHT (CWM_UP | CWM_RIGHT)
#define CWM_UP_LEFT (CWM_UP | CWM_LEFT)
#define CWM_DOWN_RIGHT (CWM_DOWN | CWM_RIGHT)
#define CWM_DOWN_LEFT (CWM_DOWN | CWM_LEFT)
#define DIRECTIONMASK (CWM_UP | CWM_DOWN | CWM_LEFT | CWM_RIGHT)
#define CWM_CYCLE_FORWARD 0x0001
#define CWM_CYCLE_REVERSE 0x0002
@ -176,6 +189,11 @@ struct client_ctx {
#define CLIENT_FULLSCREEN 0x0800
#define CLIENT_STICKY 0x1000
#define CLIENT_ACTIVE 0x2000
#define CLIENT_SKIP_PAGER 0x4000
#define CLIENT_SKIP_TASKBAR 0x8000
#define CLIENT_SKIP_CYCLE (CLIENT_HIDDEN | CLIENT_IGNORE | \
CLIENT_SKIP_TASKBAR | CLIENT_SKIP_PAGER)
#define CLIENT_HIGHLIGHT (CLIENT_GROUP | CLIENT_UNGROUP)
#define CLIENT_MAXFLAGS (CLIENT_VMAXIMIZED | CLIENT_HMAXIMIZED)
#define CLIENT_MAXIMIZED (CLIENT_VMAXIMIZED | CLIENT_HMAXIMIZED)
@ -268,14 +286,11 @@ TAILQ_HEAD(mousebind_q, bind_ctx);
struct cmd_ctx {
TAILQ_ENTRY(cmd_ctx) entry;
char *name;
char path[PATH_MAX];
char *path;
};
TAILQ_HEAD(cmd_q, cmd_ctx);
TAILQ_HEAD(wm_q, cmd_ctx);
enum menu_exec {
CWM_MENU_EXEC_EXEC,
CWM_MENU_EXEC_WM
};
#define CWM_MENU_DUMMY 0x0001
#define CWM_MENU_FILE 0x0002
#define CWM_MENU_LIST 0x0004
@ -300,6 +315,7 @@ struct conf {
struct autogroup_q autogroupq;
struct ignore_q ignoreq;
struct cmd_q cmdq;
struct wm_q wmq;
int ngroups;
int stickygroups;
int nameqlen;
@ -308,14 +324,15 @@ struct conf {
int snapdist;
struct gap gap;
char *color[CWM_COLOR_NITEMS];
char known_hosts[PATH_MAX];
char *font;
char *wmname;
Cursor cursor[CF_NITEMS];
int xrandr;
int xrandr_event_base;
char *homedir;
char *known_hosts;
char *wm_argv;
u_int32_t debug;
};
/* MWM hints */
@ -374,13 +391,15 @@ enum ewmh {
_NET_WM_DESKTOP,
_NET_CLOSE_WINDOW,
_NET_WM_STATE,
#define _NET_WM_STATES_NITEMS 7
#define _NET_WM_STATES_NITEMS 9
_NET_WM_STATE_STICKY,
_NET_WM_STATE_MAXIMIZED_VERT,
_NET_WM_STATE_MAXIMIZED_HORZ,
_NET_WM_STATE_HIDDEN,
_NET_WM_STATE_FULLSCREEN,
_NET_WM_STATE_DEMANDS_ATTENTION,
_NET_WM_STATE_SKIP_PAGER,
_NET_WM_STATE_SKIP_TASKBAR,
_CWM_WM_STATE_FREEZE,
EWMH_NITEMS
};
@ -403,7 +422,6 @@ void client_applysizehints(struct client_ctx *);
void client_config(struct client_ctx *);
struct client_ctx *client_current(void);
void client_cycle(struct screen_ctx *, int);
void client_cycle_leave(struct screen_ctx *);
void client_delete(struct client_ctx *);
void client_draw_border(struct client_ctx *);
struct client_ctx *client_find(Window);
@ -415,6 +433,7 @@ void client_lower(struct client_ctx *);
void client_map(struct client_ctx *);
void client_msg(struct client_ctx *, Atom, Time);
void client_move(struct client_ctx *);
void client_mtf(struct client_ctx *);
int client_inbound(struct client_ctx *, int, int);
struct client_ctx *client_init(Window, struct screen_ctx *, int);
void client_ptr_inbound(struct client_ctx *, int);
@ -426,12 +445,15 @@ void client_send_delete(struct client_ctx *);
void client_set_wm_state(struct client_ctx *, long);
void client_setactive(struct client_ctx *);
void client_setname(struct client_ctx *);
void client_show(struct client_ctx *);
int client_snapcalc(int, int, int, int, int);
void client_toggle_freeze(struct client_ctx *);
void client_toggle_fullscreen(struct client_ctx *);
void client_toggle_hidden(struct client_ctx *);
void client_toggle_hmaximize(struct client_ctx *);
void client_toggle_maximize(struct client_ctx *);
void client_toggle_skip_pager(struct client_ctx *);
void client_toggle_skip_taskbar(struct client_ctx *);
void client_toggle_sticky(struct client_ctx *);
void client_toggle_vmaximize(struct client_ctx *);
void client_transient(struct client_ctx *);
@ -453,8 +475,7 @@ void group_movetogroup(struct client_ctx *, int);
void group_only(struct screen_ctx *, int);
int group_restore(struct client_ctx *);
void group_show(struct group_ctx *);
void group_toggle_membership_enter(struct client_ctx *);
void group_toggle_membership_leave(struct client_ctx *);
void group_toggle_membership(struct client_ctx *);
void group_update_names(struct screen_ctx *);
void search_match_client(struct menu_q *, struct menu_q *,
@ -469,10 +490,13 @@ void search_match_cmd(struct menu_q *, struct menu_q *,
char *);
void search_match_group(struct menu_q *, struct menu_q *,
char *);
void search_match_wm(struct menu_q *, struct menu_q *,
char *);
void search_print_client(struct menu *, int);
void search_print_cmd(struct menu *, int);
void search_print_group(struct menu *, int);
void search_print_text(struct menu *, int);
void search_print_wm(struct menu *, int);
struct region_ctx *region_find(struct screen_ctx *, int, int);
struct geom screen_apply_gap(struct screen_ctx *, struct geom);
@ -512,6 +536,7 @@ void kbfunc_group_alltoggle(void *, struct cargs *);
void kbfunc_menu_client(void *, struct cargs *);
void kbfunc_menu_cmd(void *, struct cargs *);
void kbfunc_menu_group(void *, struct cargs *);
void kbfunc_menu_wm(void *, struct cargs *);
void kbfunc_menu_exec(void *, struct cargs *);
void kbfunc_menu_ssh(void *, struct cargs *);
void kbfunc_client_menu_label(void *, struct cargs *);
@ -520,12 +545,15 @@ void kbfunc_exec_lock(void *, struct cargs *);
void kbfunc_exec_term(void *, struct cargs *);
void menu_windraw(struct screen_ctx *, Window,
const char *, ...);
const char *, ...)
__attribute__((__format__ (printf, 3, 4)))
__attribute__((__nonnull__ (3)));
struct menu *menu_filter(struct screen_ctx *, struct menu_q *,
const char *, const char *, int,
void (*)(struct menu_q *, struct menu_q *, char *),
void (*)(struct menu *, int));
void menuq_add(struct menu_q *, void *, const char *, ...);
void menuq_add(struct menu_q *, void *, const char *, ...)
__attribute__((__format__ (printf, 3, 4)));
void menuq_clear(struct menu_q *);
int parse_config(const char *, struct conf *);
@ -539,7 +567,9 @@ int conf_bind_mouse(struct conf *, const char *,
const char *);
void conf_clear(struct conf *);
void conf_client(struct client_ctx *);
int conf_cmd_add(struct conf *, const char *,
void conf_cmd_add(struct conf *, const char *,
const char *);
void conf_wm_add(struct conf *, const char *,
const char *);
void conf_cursor(struct conf *);
void conf_grab_kbd(Window);
@ -581,6 +611,9 @@ void xu_ewmh_restore_net_wm_state(struct client_ctx *);
char *u_argv(char * const *);
void u_exec(char *);
void u_spawn(char *);
void log_debug(int, const char *, const char *, ...)
__attribute__((__format__ (printf, 3, 4)))
__attribute__((__nonnull__ (3)));
void *xcalloc(size_t, size_t);
void *xmalloc(size_t);

View File

@ -33,7 +33,6 @@
static struct client_ctx *client_next(struct client_ctx *);
static struct client_ctx *client_prev(struct client_ctx *);
static void client_mtf(struct client_ctx *);
static void client_placecalc(struct client_ctx *);
static void client_wm_protocols(struct client_ctx *);
static void client_mwm_hints(struct client_ctx *);
@ -104,8 +103,8 @@ client_init(Window win, struct screen_ctx *sc, int active)
if ((cc->wmh) && (cc->wmh->flags & StateHint))
client_set_wm_state(cc, cc->wmh->initial_state);
} else {
if ((active == 0) && (XQueryPointer(X_Dpy, cc->win, &rwin, &cwin,
&x, &y, &wx, &wy, &mask)) && (cwin != None))
if ((active == 0) && (XQueryPointer(X_Dpy, cc->win, &rwin,
&cwin, &x, &y, &wx, &wy, &mask)) && (cwin != None))
active = 1;
}
@ -222,7 +221,7 @@ client_setactive(struct client_ctx *cc)
client_draw_border(oldcc);
}
/* If we're in the middle of cycing, don't change the order. */
/* If we're in the middle of cycling, don't change the order. */
if (!sc->cycling)
client_mtf(cc);
@ -265,6 +264,20 @@ client_toggle_hidden(struct client_ctx *cc)
xu_ewmh_set_net_wm_state(cc);
}
void
client_toggle_skip_pager(struct client_ctx *cc)
{
cc->flags ^= CLIENT_SKIP_PAGER;
xu_ewmh_set_net_wm_state(cc);
}
void
client_toggle_skip_taskbar(struct client_ctx *cc)
{
cc->flags ^= CLIENT_SKIP_TASKBAR;
xu_ewmh_set_net_wm_state(cc);
}
void
client_toggle_sticky(struct client_ctx *cc)
{
@ -330,11 +343,6 @@ client_toggle_maximize(struct client_ctx *cc)
cc->savegeom.x = cc->geom.x;
}
/*
* pick screen that the middle of the window is on.
* that's probably more fair than if just the origin of
* a window is poking over a boundary
*/
area = screen_area(sc,
cc->geom.x + cc->geom.w / 2,
cc->geom.y + cc->geom.h / 2, CWM_GAP);
@ -522,6 +530,15 @@ client_hide(struct client_ctx *cc)
client_set_wm_state(cc, IconicState);
}
void
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)
{
@ -644,7 +661,6 @@ client_setname(struct client_ctx *cc)
wn = xmalloc(sizeof(*wn));
wn->name = newname;
TAILQ_INSERT_TAIL(&cc->nameq, wn, entry);
match:
cc->name = wn->name;
@ -666,10 +682,6 @@ client_cycle(struct screen_ctx *sc, int flags)
struct client_ctx *newcc, *oldcc, *prevcc;
int again = 1;
/* For X apps that ignore events. */
XGrabKeyboard(X_Dpy, sc->rootwin, True,
GrabModeAsync, GrabModeAsync, CurrentTime);
if (TAILQ_EMPTY(&sc->clientq))
return;
@ -688,21 +700,20 @@ client_cycle(struct screen_ctx *sc, int flags)
client_next(newcc);
/* Only cycle visible and non-ignored windows. */
if ((newcc->flags & (CLIENT_HIDDEN | CLIENT_IGNORE))
|| ((flags & CWM_CYCLE_INGROUP) &&
(newcc->gc != oldcc->gc)))
if ((newcc->flags & (CLIENT_SKIP_CYCLE)) ||
((flags & CWM_CYCLE_INGROUP) &&
(newcc->gc != oldcc->gc)))
again = 1;
/* Is oldcc the only non-hidden window? */
if (newcc == oldcc) {
if (again)
return; /* No windows visible. */
break;
}
}
/* reset when cycling mod is released. XXX I hate this hack */
/* Reset when cycling mod is released. XXX I hate this hack */
sc->cycling = 1;
client_ptrsave(oldcc);
client_raise(prevcc);
@ -714,21 +725,6 @@ client_cycle(struct screen_ctx *sc, int flags)
client_ptrwarp(newcc);
}
void
client_cycle_leave(struct screen_ctx *sc)
{
struct client_ctx *cc;
sc->cycling = 0;
if ((cc = client_current()) != NULL) {
client_mtf(cc);
cc->flags &= ~CLIENT_HIGHLIGHT;
client_draw_border(cc);
XUngrabKeyboard(X_Dpy, CurrentTime);
}
}
static struct client_ctx *
client_next(struct client_ctx *cc)
{
@ -756,17 +752,12 @@ client_placecalc(struct client_ctx *cc)
int xslack, yslack;
if (cc->hint.flags & (USPosition | PPosition)) {
int wmax, hmax;
wmax = DisplayWidth(X_Dpy, sc->which);
hmax = DisplayHeight(X_Dpy, sc->which);
if (cc->geom.x >= wmax)
cc->geom.x = wmax - cc->bwidth - 1;
if (cc->geom.x >= sc->view.w)
cc->geom.x = sc->view.w - cc->bwidth - 1;
if (cc->geom.x + cc->geom.w + cc->bwidth <= 0)
cc->geom.x = -(cc->geom.w + cc->bwidth - 1);
if (cc->geom.y >= hmax)
cc->geom.x = hmax - cc->bwidth - 1;
if (cc->geom.y >= sc->view.h)
cc->geom.x = sc->view.h - cc->bwidth - 1;
if (cc->geom.y + cc->geom.h + cc->bwidth <= 0)
cc->geom.y = -(cc->geom.h + cc->bwidth - 1);
} else {
@ -801,7 +792,7 @@ client_placecalc(struct client_ctx *cc)
}
}
static void
void
client_mtf(struct client_ctx *cc)
{
struct screen_ctx *sc = cc->sc;
@ -910,8 +901,9 @@ client_mwm_hints(struct client_ctx *cc)
{
struct mwm_hints *mwmh;
if (xu_getprop(cc->win, cwmh[_MOTIF_WM_HINTS], cwmh[_MOTIF_WM_HINTS],
MWM_HINTS_ELEMENTS, (unsigned char **)&mwmh) == MWM_HINTS_ELEMENTS) {
if (xu_getprop(cc->win, cwmh[_MOTIF_WM_HINTS],
cwmh[_MOTIF_WM_HINTS], MWM_HINTS_ELEMENTS,
(unsigned char **)&mwmh) == MWM_HINTS_ELEMENTS) {
if (mwmh->flags & MWM_FLAGS_DECORATIONS &&
!(mwmh->decorations & MWM_DECOR_ALL) &&
!(mwmh->decorations & MWM_DECOR_BORDER))

307
conf.c
View File

@ -33,7 +33,6 @@
#include "calmwm.h"
static const char *conf_bind_getmask(const char *, unsigned int *);
static void conf_cmd_remove(struct conf *, const char *);
static void conf_unbind_key(struct conf *, struct bind_ctx *);
static void conf_unbind_mouse(struct conf *, struct bind_ctx *);
@ -60,149 +59,111 @@ static const struct {
enum context context;
int flag;
} name_to_func[] = {
{ "window-menu-label", kbfunc_client_menu_label, CWM_CONTEXT_CC, 0 },
{ "window-lower", kbfunc_client_lower, CWM_CONTEXT_CC, 0 },
{ "window-raise", kbfunc_client_raise, CWM_CONTEXT_CC, 0 },
{ "window-hide", kbfunc_client_hide, CWM_CONTEXT_CC, 0 },
{ "window-delete", kbfunc_client_delete, CWM_CONTEXT_CC, 0 },
{ "window-htile", kbfunc_client_htile, CWM_CONTEXT_CC, 0 },
{ "window-vtile", kbfunc_client_vtile, CWM_CONTEXT_CC, 0 },
{ "window-stick", kbfunc_client_toggle_sticky, CWM_CONTEXT_CC, 0 },
{ "window-fullscreen", kbfunc_client_toggle_fullscreen, CWM_CONTEXT_CC, 0 },
{ "window-maximize", kbfunc_client_toggle_maximize, CWM_CONTEXT_CC, 0 },
{ "window-vmaximize", kbfunc_client_toggle_vmaximize, CWM_CONTEXT_CC, 0 },
{ "window-hmaximize", kbfunc_client_toggle_hmaximize, CWM_CONTEXT_CC, 0 },
{ "window-freeze", kbfunc_client_toggle_freeze, CWM_CONTEXT_CC, 0 },
{ "window-cycle", kbfunc_client_cycle, CWM_CONTEXT_SC,
(CWM_CYCLE_FORWARD) },
{ "window-rcycle", kbfunc_client_cycle, CWM_CONTEXT_SC,
(CWM_CYCLE_REVERSE) },
{ "window-cycle-ingroup", kbfunc_client_cycle, CWM_CONTEXT_SC,
(CWM_CYCLE_FORWARD | CWM_CYCLE_INGROUP) },
{ "window-rcycle-ingroup", kbfunc_client_cycle, CWM_CONTEXT_SC,
(CWM_CYCLE_REVERSE | CWM_CYCLE_INGROUP) },
{ "window-group", kbfunc_client_toggle_group, CWM_CONTEXT_CC, 0 },
{ "window-movetogroup-1", kbfunc_client_movetogroup, CWM_CONTEXT_CC, 1 },
{ "window-movetogroup-2", kbfunc_client_movetogroup, CWM_CONTEXT_CC, 2 },
{ "window-movetogroup-3", kbfunc_client_movetogroup, CWM_CONTEXT_CC, 3 },
{ "window-movetogroup-4", kbfunc_client_movetogroup, CWM_CONTEXT_CC, 4 },
{ "window-movetogroup-5", kbfunc_client_movetogroup, CWM_CONTEXT_CC, 5 },
{ "window-movetogroup-6", kbfunc_client_movetogroup, CWM_CONTEXT_CC, 6 },
{ "window-movetogroup-7", kbfunc_client_movetogroup, CWM_CONTEXT_CC, 7 },
{ "window-movetogroup-8", kbfunc_client_movetogroup, CWM_CONTEXT_CC, 8 },
{ "window-movetogroup-9", kbfunc_client_movetogroup, CWM_CONTEXT_CC, 9 },
#define FUNC_CC(t, h, n) \
#t, kbfunc_ ## h, CWM_CONTEXT_CC, n
#define FUNC_SC(t, h, n) \
#t, kbfunc_ ## h, CWM_CONTEXT_SC, n
{ "window-snap-up", kbfunc_client_snap, CWM_CONTEXT_CC,
(CWM_UP) },
{ "window-snap-down", kbfunc_client_snap, CWM_CONTEXT_CC,
(CWM_DOWN) },
{ "window-snap-left", kbfunc_client_snap, CWM_CONTEXT_CC,
(CWM_LEFT) },
{ "window-snap-right", kbfunc_client_snap, CWM_CONTEXT_CC,
(CWM_RIGHT) },
{ FUNC_CC(window-lower, client_lower, 0) },
{ FUNC_CC(window-raise, client_raise, 0) },
{ FUNC_CC(window-hide, client_hide, 0) },
{ FUNC_CC(window-delete, client_delete, 0) },
{ FUNC_CC(window-htile, client_htile, 0) },
{ FUNC_CC(window-vtile, client_vtile, 0) },
{ FUNC_CC(window-stick, client_toggle_sticky, 0) },
{ FUNC_CC(window-fullscreen, client_toggle_fullscreen, 0) },
{ FUNC_CC(window-maximize, client_toggle_maximize, 0) },
{ FUNC_CC(window-vmaximize, client_toggle_vmaximize, 0) },
{ FUNC_CC(window-hmaximize, client_toggle_hmaximize, 0) },
{ FUNC_CC(window-freeze, client_toggle_freeze, 0) },
{ FUNC_CC(window-group, client_toggle_group, 0) },
{ FUNC_CC(window-movetogroup-1, client_movetogroup, 1) },
{ FUNC_CC(window-movetogroup-2, client_movetogroup, 2) },
{ FUNC_CC(window-movetogroup-3, client_movetogroup, 3) },
{ FUNC_CC(window-movetogroup-4, client_movetogroup, 4) },
{ FUNC_CC(window-movetogroup-5, client_movetogroup, 5) },
{ FUNC_CC(window-movetogroup-6, client_movetogroup, 6) },
{ FUNC_CC(window-movetogroup-7, client_movetogroup, 7) },
{ FUNC_CC(window-movetogroup-8, client_movetogroup, 8) },
{ FUNC_CC(window-movetogroup-9, client_movetogroup, 9) },
{ FUNC_CC(window-snap-up, client_snap, (CWM_UP)) },
{ FUNC_CC(window-snap-down, client_snap, (CWM_DOWN)) },
{ FUNC_CC(window-snap-right, client_snap, (CWM_RIGHT)) },
{ FUNC_CC(window-snap-left, client_snap, (CWM_LEFT)) },
{ FUNC_CC(window-snap-up-right, client_snap, (CWM_UP_RIGHT)) },
{ FUNC_CC(window-snap-up-left, client_snap, (CWM_UP_LEFT)) },
{ FUNC_CC(window-snap-down-right, client_snap, (CWM_DOWN_RIGHT)) },
{ FUNC_CC(window-snap-down-left, client_snap, (CWM_DOWN_LEFT)) },
{ FUNC_CC(window-move, client_move, 0) },
{ FUNC_CC(window-move-up, client_move, (CWM_UP)) },
{ FUNC_CC(window-move-down, client_move, (CWM_DOWN)) },
{ FUNC_CC(window-move-right, client_move, (CWM_RIGHT)) },
{ FUNC_CC(window-move-left, client_move, (CWM_LEFT)) },
{ FUNC_CC(window-move-up-big, client_move, (CWM_UP_BIG)) },
{ FUNC_CC(window-move-down-big, client_move, (CWM_DOWN_BIG)) },
{ FUNC_CC(window-move-right-big, client_move, (CWM_RIGHT_BIG)) },
{ FUNC_CC(window-move-left-big, client_move, (CWM_LEFT_BIG)) },
{ FUNC_CC(window-resize, client_resize, 0) },
{ FUNC_CC(window-resize-up, client_resize, (CWM_UP)) },
{ FUNC_CC(window-resize-down, client_resize, (CWM_DOWN)) },
{ FUNC_CC(window-resize-right, client_resize, (CWM_RIGHT)) },
{ FUNC_CC(window-resize-left, client_resize, (CWM_LEFT)) },
{ FUNC_CC(window-resize-up-big, client_resize, (CWM_UP_BIG)) },
{ FUNC_CC(window-resize-down-big, client_resize, (CWM_DOWN_BIG)) },
{ FUNC_CC(window-resize-right-big, client_resize, (CWM_RIGHT_BIG)) },
{ FUNC_CC(window-resize-left-big, client_resize, (CWM_LEFT_BIG)) },
{ FUNC_CC(window-menu-label, client_menu_label, 0) },
{ "window-snap-up-right", kbfunc_client_snap, CWM_CONTEXT_CC,
(CWM_UP|CWM_RIGHT) },
{ "window-snap-up-left", kbfunc_client_snap, CWM_CONTEXT_CC,
(CWM_UP|CWM_LEFT) },
{ "window-snap-down-right", kbfunc_client_snap, CWM_CONTEXT_CC,
(CWM_DOWN|CWM_RIGHT) },
{ "window-snap-down-left", kbfunc_client_snap, CWM_CONTEXT_CC,
(CWM_DOWN|CWM_LEFT) },
{ FUNC_SC(window-cycle, client_cycle, (CWM_CYCLE_FORWARD)) },
{ FUNC_SC(window-rcycle, client_cycle, (CWM_CYCLE_REVERSE)) },
{ FUNC_SC(window-cycle-ingroup, client_cycle,
(CWM_CYCLE_FORWARD | CWM_CYCLE_INGROUP)) },
{ FUNC_SC(window-rcycle-ingroup, client_cycle,
(CWM_CYCLE_REVERSE | CWM_CYCLE_INGROUP)) },
{ "window-move", kbfunc_client_move, CWM_CONTEXT_CC, 0 },
{ "window-move-up", kbfunc_client_move, CWM_CONTEXT_CC,
(CWM_UP) },
{ "window-move-down", kbfunc_client_move, CWM_CONTEXT_CC,
(CWM_DOWN) },
{ "window-move-right", kbfunc_client_move, CWM_CONTEXT_CC,
(CWM_RIGHT) },
{ "window-move-left", kbfunc_client_move, CWM_CONTEXT_CC,
(CWM_LEFT) },
{ "window-move-up-big", kbfunc_client_move, CWM_CONTEXT_CC,
(CWM_UP | CWM_BIGAMOUNT) },
{ "window-move-down-big", kbfunc_client_move, CWM_CONTEXT_CC,
(CWM_DOWN | CWM_BIGAMOUNT) },
{ "window-move-right-big", kbfunc_client_move, CWM_CONTEXT_CC,
(CWM_RIGHT | CWM_BIGAMOUNT) },
{ "window-move-left-big", kbfunc_client_move, CWM_CONTEXT_CC,
(CWM_LEFT | CWM_BIGAMOUNT) },
{ "window-resize", kbfunc_client_resize, CWM_CONTEXT_CC, 0 },
{ "window-resize-up", kbfunc_client_resize, CWM_CONTEXT_CC,
(CWM_UP) },
{ "window-resize-down", kbfunc_client_resize, CWM_CONTEXT_CC,
(CWM_DOWN) },
{ "window-resize-right", kbfunc_client_resize, CWM_CONTEXT_CC,
(CWM_RIGHT) },
{ "window-resize-left", kbfunc_client_resize, CWM_CONTEXT_CC,
(CWM_LEFT) },
{ "window-resize-up-big", kbfunc_client_resize, CWM_CONTEXT_CC,
(CWM_UP | CWM_BIGAMOUNT) },
{ "window-resize-down-big", kbfunc_client_resize, CWM_CONTEXT_CC,
(CWM_DOWN | CWM_BIGAMOUNT) },
{ "window-resize-right-big", kbfunc_client_resize, CWM_CONTEXT_CC,
(CWM_RIGHT | CWM_BIGAMOUNT) },
{ "window-resize-left-big", kbfunc_client_resize, CWM_CONTEXT_CC,
(CWM_LEFT | CWM_BIGAMOUNT) },
{ FUNC_SC(group-cycle, group_cycle, (CWM_CYCLE_FORWARD)) },
{ FUNC_SC(group-rcycle, group_cycle, (CWM_CYCLE_REVERSE)) },
{ FUNC_SC(group-toggle-all, group_alltoggle, 0) },
{ FUNC_SC(group-toggle-1, group_toggle, 1) },
{ FUNC_SC(group-toggle-2, group_toggle, 2) },
{ FUNC_SC(group-toggle-3, group_toggle, 3) },
{ FUNC_SC(group-toggle-4, group_toggle, 4) },
{ FUNC_SC(group-toggle-5, group_toggle, 5) },
{ FUNC_SC(group-toggle-6, group_toggle, 6) },
{ FUNC_SC(group-toggle-7, group_toggle, 7) },
{ FUNC_SC(group-toggle-8, group_toggle, 8) },
{ FUNC_SC(group-toggle-9, group_toggle, 9) },
{ FUNC_SC(group-only-1, group_only, 1) },
{ FUNC_SC(group-only-2, group_only, 2) },
{ FUNC_SC(group-only-3, group_only, 3) },
{ FUNC_SC(group-only-4, group_only, 4) },
{ FUNC_SC(group-only-5, group_only, 5) },
{ FUNC_SC(group-only-6, group_only, 6) },
{ FUNC_SC(group-only-7, group_only, 7) },
{ FUNC_SC(group-only-8, group_only, 8) },
{ FUNC_SC(group-only-9, group_only, 9) },
{ "group-cycle", kbfunc_group_cycle, CWM_CONTEXT_SC,
(CWM_CYCLE_FORWARD) },
{ "group-rcycle", kbfunc_group_cycle, CWM_CONTEXT_SC,
(CWM_CYCLE_REVERSE) },
{ "group-toggle-all", kbfunc_group_alltoggle, CWM_CONTEXT_SC, 0 },
{ "group-toggle-1", kbfunc_group_toggle, CWM_CONTEXT_SC, 1 },
{ "group-toggle-2", kbfunc_group_toggle, CWM_CONTEXT_SC, 2 },
{ "group-toggle-3", kbfunc_group_toggle, CWM_CONTEXT_SC, 3 },
{ "group-toggle-4", kbfunc_group_toggle, CWM_CONTEXT_SC, 4 },
{ "group-toggle-5", kbfunc_group_toggle, CWM_CONTEXT_SC, 5 },
{ "group-toggle-6", kbfunc_group_toggle, CWM_CONTEXT_SC, 6 },
{ "group-toggle-7", kbfunc_group_toggle, CWM_CONTEXT_SC, 7 },
{ "group-toggle-8", kbfunc_group_toggle, CWM_CONTEXT_SC, 8 },
{ "group-toggle-9", kbfunc_group_toggle, CWM_CONTEXT_SC, 9 },
{ "group-only-1", kbfunc_group_only, CWM_CONTEXT_SC, 1 },
{ "group-only-2", kbfunc_group_only, CWM_CONTEXT_SC, 2 },
{ "group-only-3", kbfunc_group_only, CWM_CONTEXT_SC, 3 },
{ "group-only-4", kbfunc_group_only, CWM_CONTEXT_SC, 4 },
{ "group-only-5", kbfunc_group_only, CWM_CONTEXT_SC, 5 },
{ "group-only-6", kbfunc_group_only, CWM_CONTEXT_SC, 6 },
{ "group-only-7", kbfunc_group_only, CWM_CONTEXT_SC, 7 },
{ "group-only-8", kbfunc_group_only, CWM_CONTEXT_SC, 8 },
{ "group-only-9", kbfunc_group_only, CWM_CONTEXT_SC, 9 },
{ FUNC_SC(pointer-move-up, ptrmove, (CWM_UP)) },
{ FUNC_SC(pointer-move-down, ptrmove, (CWM_DOWN)) },
{ FUNC_SC(pointer-move-left, ptrmove, (CWM_LEFT)) },
{ FUNC_SC(pointer-move-right, ptrmove, (CWM_RIGHT)) },
{ FUNC_SC(pointer-move-up-big, ptrmove, (CWM_UP_BIG)) },
{ FUNC_SC(pointer-move-down-big, ptrmove, (CWM_DOWN_BIG)) },
{ FUNC_SC(pointer-move-left-big, ptrmove, (CWM_LEFT_BIG)) },
{ FUNC_SC(pointer-move-right-big, ptrmove, (CWM_RIGHT_BIG)) },
{ "pointer-move-up", kbfunc_ptrmove, CWM_CONTEXT_SC,
(CWM_UP) },
{ "pointer-move-down", kbfunc_ptrmove, CWM_CONTEXT_SC,
(CWM_DOWN) },
{ "pointer-move-left", kbfunc_ptrmove, CWM_CONTEXT_SC,
(CWM_LEFT) },
{ "pointer-move-right", kbfunc_ptrmove, CWM_CONTEXT_SC,
(CWM_RIGHT) },
{ "pointer-move-up-big", kbfunc_ptrmove, CWM_CONTEXT_SC,
(CWM_UP | CWM_BIGAMOUNT) },
{ "pointer-move-down-big", kbfunc_ptrmove, CWM_CONTEXT_SC,
(CWM_DOWN | CWM_BIGAMOUNT) },
{ "pointer-move-left-big", kbfunc_ptrmove, CWM_CONTEXT_SC,
(CWM_LEFT | CWM_BIGAMOUNT) },
{ "pointer-move-right-big", kbfunc_ptrmove, CWM_CONTEXT_SC,
(CWM_RIGHT | CWM_BIGAMOUNT) },
{ "menu-cmd", kbfunc_menu_cmd, CWM_CONTEXT_SC, 0 },
{ "menu-group", kbfunc_menu_group, CWM_CONTEXT_SC, 0 },
{ "menu-ssh", kbfunc_menu_ssh, CWM_CONTEXT_SC, 0 },
{ "menu-window", kbfunc_menu_client, CWM_CONTEXT_SC,
CWM_MENU_WINDOW_ALL },
{ "menu-window-hidden", kbfunc_menu_client, CWM_CONTEXT_SC,
CWM_MENU_WINDOW_HIDDEN },
{ "menu-exec", kbfunc_menu_exec, CWM_CONTEXT_SC,
CWM_MENU_EXEC_EXEC },
{ "menu-exec-wm", kbfunc_menu_exec, CWM_CONTEXT_SC,
CWM_MENU_EXEC_WM },
{ "terminal", kbfunc_exec_term, CWM_CONTEXT_SC, 0 },
{ "lock", kbfunc_exec_lock, CWM_CONTEXT_SC, 0 },
{ "restart", kbfunc_cwm_status, CWM_CONTEXT_SC, CWM_EXEC_WM },
{ "quit", kbfunc_cwm_status, CWM_CONTEXT_SC, CWM_QUIT },
{ FUNC_SC(menu-cmd, menu_cmd, 0) },
{ FUNC_SC(menu-group, menu_group, 0) },
{ FUNC_SC(menu-ssh, menu_ssh, 0) },
{ FUNC_SC(menu-window, menu_client, CWM_MENU_WINDOW_ALL) },
{ FUNC_SC(menu-window-hidden, menu_client, CWM_MENU_WINDOW_HIDDEN) },
{ FUNC_SC(menu-exec, menu_exec, 0) },
{ FUNC_SC(menu-exec-wm, menu_wm, 0) },
{ FUNC_SC(terminal, exec_term, 0) },
{ FUNC_SC(lock, exec_lock, 0) },
{ FUNC_SC(restart, cwm_status, CWM_EXEC_WM) },
{ FUNC_SC(quit, cwm_status, CWM_QUIT) },
};
static unsigned int ignore_mods[] = {
0, LockMask, Mod2Mask, Mod2Mask | LockMask
@ -298,6 +259,7 @@ conf_init(struct conf *c)
TAILQ_INIT(&c->ignoreq);
TAILQ_INIT(&c->cmdq);
TAILQ_INIT(&c->wmq);
TAILQ_INIT(&c->keybindq);
TAILQ_INIT(&c->autogroupq);
TAILQ_INIT(&c->mousebindq);
@ -314,8 +276,9 @@ conf_init(struct conf *c)
conf_cmd_add(c, "lock", "xlock");
conf_cmd_add(c, "term", "xterm");
(void)snprintf(c->known_hosts, sizeof(c->known_hosts), "%s/%s",
c->homedir, ".ssh/known_hosts");
conf_wm_add(c, "cwm", "cwm");
xasprintf(&c->known_hosts, "%s/%s", c->homedir, ".ssh/known_hosts");
c->font = xstrdup("sans-serif:pixelsize=14:bold");
c->wmname = xstrdup("CWM");
@ -327,14 +290,21 @@ conf_clear(struct conf *c)
struct autogroup *ag;
struct bind_ctx *kb, *mb;
struct winname *wn;
struct cmd_ctx *cmd;
struct cmd_ctx *cmd, *wm;
int i;
while ((cmd = TAILQ_FIRST(&c->cmdq)) != NULL) {
TAILQ_REMOVE(&c->cmdq, cmd, entry);
free(cmd->name);
free(cmd->path);
free(cmd);
}
while ((wm = TAILQ_FIRST(&c->wmq)) != NULL) {
TAILQ_REMOVE(&c->wmq, wm, entry);
free(wm->name);
free(wm->path);
free(wm);
}
while ((kb = TAILQ_FIRST(&c->keybindq)) != NULL) {
TAILQ_REMOVE(&c->keybindq, kb, entry);
free(kb);
@ -357,40 +327,49 @@ conf_clear(struct conf *c)
for (i = 0; i < CWM_COLOR_NITEMS; i++)
free(c->color[i]);
free(c->known_hosts);
free(c->font);
free(c->wmname);
}
int
void
conf_cmd_add(struct conf *c, const char *name, const char *path)
{
struct cmd_ctx *cmd;
struct cmd_ctx *cmd, *cmdtmp = NULL, *cmdnxt;
cmd = xmalloc(sizeof(*cmd));
cmd->name = xstrdup(name);
if (strlcpy(cmd->path, path, sizeof(cmd->path)) >= sizeof(cmd->path)) {
free(cmd->name);
free(cmd);
return(0);
}
conf_cmd_remove(c, name);
cmd->path = xstrdup(path);
TAILQ_INSERT_TAIL(&c->cmdq, cmd, entry);
return(1);
}
static void
conf_cmd_remove(struct conf *c, const char *name)
{
struct cmd_ctx *cmd = NULL, *cmdnxt;
TAILQ_FOREACH_SAFE(cmd, &c->cmdq, entry, cmdnxt) {
if (strcmp(cmd->name, name) == 0) {
TAILQ_REMOVE(&c->cmdq, cmd, entry);
free(cmd->name);
free(cmd);
TAILQ_FOREACH_SAFE(cmdtmp, &c->cmdq, entry, cmdnxt) {
if (strcmp(cmdtmp->name, name) == 0) {
TAILQ_REMOVE(&c->cmdq, cmdtmp, entry);
free(cmdtmp->name);
free(cmdtmp->path);
free(cmdtmp);
}
}
TAILQ_INSERT_TAIL(&c->cmdq, cmd, entry);
}
void
conf_wm_add(struct conf *c, const char *name, const char *path)
{
struct cmd_ctx *wm, *wmtmp = NULL, *wmnxt;
wm = xmalloc(sizeof(*wm));
wm->name = xstrdup(name);
wm->path = xstrdup(path);
TAILQ_FOREACH_SAFE(wmtmp, &c->cmdq, entry, wmnxt) {
if (strcmp(wmtmp->name, name) == 0) {
TAILQ_REMOVE(&c->wmq, wmtmp, entry);
free(wmtmp->name);
free(wmtmp->path);
free(wmtmp);
}
}
TAILQ_INSERT_TAIL(&c->wmq, wm, entry);
}
void
@ -720,6 +699,8 @@ static char *ewmhints[] = {
"_NET_WM_STATE_HIDDEN",
"_NET_WM_STATE_FULLSCREEN",
"_NET_WM_STATE_DEMANDS_ATTENTION",
"_NET_WM_STATE_SKIP_PAGER",
"_NET_WM_STATE_SKIP_TASKBAR",
"_CWM_WM_STATE_FREEZE",
};

16
cwm.1
View File

@ -23,6 +23,7 @@
.Sh SYNOPSIS
.\" For a program: program [-abc] file ...
.Nm cwm
.Op Fl v
.Op Fl c Ar file
.Op Fl d Ar display
.Sh DESCRIPTION
@ -47,6 +48,11 @@ however,
will continue to process the rest of the configuration file.
.It Fl d Ar display
Specify the display to use.
.It Fl v
Verbose mode.
Multiple
.Fl v
options increase the verbosity.
.El
.Pp
.Nm
@ -143,7 +149,7 @@ will be executed via the configured terminal emulator.
.It Ic CM-w
Spawn
.Dq exec WindowManager
dialog, allowing a switch to another window manager.
menu, allowing a switch to another window manager.
.It Ic CMS-r
Restart.
.It Ic CMS-q
@ -184,6 +190,14 @@ List all available items.
.It Ic [Esc]
Cancel.
.El
.Pp
.Nm
rereads its configuration file when it receives a hangup signal,
.Dv SIGHUP ,
by executing itself with the name and arguments with which it was started.
This is equivalent to the
.Ar restart
function.
.Sh SEARCH
.Nm
features the ability to search for windows by their current title,

View File

@ -245,6 +245,12 @@ A special
keyword
.Dq all
can be used to unbind all buttons.
.It Ic wm Ar name path
Every
.Ar name
entry is shown in the wm menu.
When selected, the window manager is replaced by
.Ar path .
.El
.Sh BIND FUNCTION LIST
.Bl -tag -width 23n -compact

15
group.c
View File

@ -155,7 +155,7 @@ group_movetogroup(struct client_ctx *cc, int idx)
struct group_ctx *gc;
if (idx < 0 || idx >= Conf.ngroups)
errx(1, "%s: index out of range (%d)", __func__, idx);
return;
TAILQ_FOREACH(gc, &sc->groupq, entry) {
if (gc->num == idx)
@ -170,7 +170,7 @@ group_movetogroup(struct client_ctx *cc, int idx)
}
void
group_toggle_membership_enter(struct client_ctx *cc)
group_toggle_membership(struct client_ctx *cc)
{
struct screen_ctx *sc = cc->sc;
struct group_ctx *gc = sc->group_active;
@ -186,13 +186,6 @@ group_toggle_membership_enter(struct client_ctx *cc)
client_draw_border(cc);
}
void
group_toggle_membership_leave(struct client_ctx *cc)
{
cc->flags &= ~CLIENT_HIGHLIGHT;
client_draw_border(cc);
}
int
group_holds_only_sticky(struct group_ctx *gc)
{
@ -223,7 +216,7 @@ group_hidetoggle(struct screen_ctx *sc, int idx)
struct group_ctx *gc;
if (idx < 0 || idx >= Conf.ngroups)
errx(1, "%s: index out of range (%d)", __func__, idx);
return;
TAILQ_FOREACH(gc, &sc->groupq, entry) {
if (gc->num == idx)
@ -246,7 +239,7 @@ group_only(struct screen_ctx *sc, int idx)
struct group_ctx *gc;
if (idx < 0 || idx >= Conf.ngroups)
errx(1, "%s: index out of range (%d)", __func__, idx);
return;
TAILQ_FOREACH(gc, &sc->groupq, entry) {
if (gc->num == idx)

110
kbfunc.c
View File

@ -401,7 +401,14 @@ kbfunc_client_vtile(void *ctx, struct cargs *cargs)
void
kbfunc_client_cycle(void *ctx, struct cargs *cargs)
{
client_cycle(ctx, cargs->flag);
struct screen_ctx *sc = ctx;
/* For X apps that ignore/steal events. */
if (cargs->xev == CWM_XEV_KEY)
XGrabKeyboard(X_Dpy, sc->rootwin, True,
GrabModeAsync, GrabModeAsync, CurrentTime);
client_cycle(sc, cargs->flag);
}
void
@ -409,12 +416,12 @@ kbfunc_client_toggle_group(void *ctx, struct cargs *cargs)
{
struct client_ctx *cc = ctx;
/* For X apps that steal events. */
/* For X apps that ignore/steal events. */
if (cargs->xev == CWM_XEV_KEY)
XGrabKeyboard(X_Dpy, cc->win, True,
GrabModeAsync, GrabModeAsync, CurrentTime);
group_toggle_membership_enter(cc);
group_toggle_membership(cc);
}
void
@ -454,8 +461,11 @@ kbfunc_menu_client(void *ctx, struct cargs *cargs)
struct client_ctx *cc, *old_cc;
struct menu *mi;
struct menu_q menuq;
int m = (cargs->xev == CWM_XEV_BTN);
int all = (cargs->flag & CWM_MENU_WINDOW_ALL);
int mflags = 0;
if (cargs->xev == CWM_XEV_BTN)
mflags |= CWM_MENU_LIST;
old_cc = client_current();
@ -468,15 +478,10 @@ kbfunc_menu_client(void *ctx, struct cargs *cargs)
menuq_add(&menuq, cc, NULL);
}
if ((mi = menu_filter(sc, &menuq,
(m) ? NULL : "window", NULL,
((m) ? CWM_MENU_LIST : 0),
if ((mi = menu_filter(sc, &menuq, "window", NULL, mflags,
search_match_client, search_print_client)) != NULL) {
cc = (struct client_ctx *)mi->ctx;
if (cc->flags & CLIENT_HIDDEN)
client_unhide(cc);
else
client_raise(cc);
client_show(cc);
if (old_cc)
client_ptrsave(old_cc);
client_ptrwarp(cc);
@ -492,7 +497,10 @@ kbfunc_menu_cmd(void *ctx, struct cargs *cargs)
struct cmd_ctx *cmd;
struct menu *mi;
struct menu_q menuq;
int m = (cargs->xev == CWM_XEV_BTN);
int mflags = 0;
if (cargs->xev == CWM_XEV_BTN)
mflags |= CWM_MENU_LIST;
TAILQ_INIT(&menuq);
TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {
@ -502,9 +510,7 @@ kbfunc_menu_cmd(void *ctx, struct cargs *cargs)
menuq_add(&menuq, cmd, NULL);
}
if ((mi = menu_filter(sc, &menuq,
(m) ? NULL : "application", NULL,
((m) ? CWM_MENU_LIST : 0),
if ((mi = menu_filter(sc, &menuq, "application", NULL, mflags,
search_match_cmd, search_print_cmd)) != NULL) {
cmd = (struct cmd_ctx *)mi->ctx;
u_spawn(cmd->path);
@ -520,7 +526,10 @@ kbfunc_menu_group(void *ctx, struct cargs *cargs)
struct group_ctx *gc;
struct menu *mi;
struct menu_q menuq;
int m = (cargs->xev == CWM_XEV_BTN);
int mflags = 0;
if (cargs->xev == CWM_XEV_BTN)
mflags |= CWM_MENU_LIST;
TAILQ_INIT(&menuq);
TAILQ_FOREACH(gc, &sc->groupq, entry) {
@ -529,8 +538,7 @@ kbfunc_menu_group(void *ctx, struct cargs *cargs)
menuq_add(&menuq, gc, NULL);
}
if ((mi = menu_filter(sc, &menuq,
(m) ? NULL : "group", NULL, (CWM_MENU_LIST),
if ((mi = menu_filter(sc, &menuq, "group", NULL, mflags,
search_match_group, search_print_group)) != NULL) {
gc = (struct group_ctx *)mi->ctx;
(group_holds_only_hidden(gc)) ?
@ -540,6 +548,33 @@ kbfunc_menu_group(void *ctx, struct cargs *cargs)
menuq_clear(&menuq);
}
void
kbfunc_menu_wm(void *ctx, struct cargs *cargs)
{
struct screen_ctx *sc = ctx;
struct cmd_ctx *wm;
struct menu *mi;
struct menu_q menuq;
int mflags = 0;
if (cargs->xev == CWM_XEV_BTN)
mflags |= CWM_MENU_LIST;
TAILQ_INIT(&menuq);
TAILQ_FOREACH(wm, &Conf.wmq, entry)
menuq_add(&menuq, wm, NULL);
if ((mi = menu_filter(sc, &menuq, "wm", NULL, mflags,
search_match_wm, search_print_wm)) != NULL) {
wm = (struct cmd_ctx *)mi->ctx;
free(Conf.wm_argv);
Conf.wm_argv = xstrdup(wm->path);
cwm_status = CWM_EXEC_WM;
}
menuq_clear(&menuq);
}
void
kbfunc_menu_exec(void *ctx, struct cargs *cargs)
{
@ -548,24 +583,12 @@ kbfunc_menu_exec(void *ctx, struct cargs *cargs)
char **ap, *paths[NPATHS], *path, *pathcpy;
char tpath[PATH_MAX];
struct stat sb;
const char *label;
DIR *dirp;
struct dirent *dp;
struct menu *mi;
struct menu_q menuq;
int l, i, cmd = cargs->flag;
switch (cmd) {
case CWM_MENU_EXEC_EXEC:
label = "exec";
break;
case CWM_MENU_EXEC_WM:
label = "wm";
break;
default:
errx(1, "%s: invalid cmd %d", __func__, cmd);
/* NOTREACHED */
}
int l, i;
int mflags = (CWM_MENU_DUMMY | CWM_MENU_FILE);
TAILQ_INIT(&menuq);
@ -605,24 +628,11 @@ kbfunc_menu_exec(void *ctx, struct cargs *cargs)
}
free(path);
if ((mi = menu_filter(sc, &menuq, label, NULL,
(CWM_MENU_DUMMY | CWM_MENU_FILE),
if ((mi = menu_filter(sc, &menuq, "exec", NULL, mflags,
search_match_exec, search_print_text)) != NULL) {
if (mi->text[0] == '\0')
goto out;
switch (cmd) {
case CWM_MENU_EXEC_EXEC:
u_spawn(mi->text);
break;
case CWM_MENU_EXEC_WM:
cwm_status = CWM_EXEC_WM;
free(Conf.wm_argv);
Conf.wm_argv = xstrdup(mi->text);
break;
default:
errx(1, "%s: egad, cmd changed value!", __func__);
/* NOTREACHED */
}
u_spawn(mi->text);
}
out:
if (mi != NULL && mi->dummy)
@ -644,6 +654,7 @@ kbfunc_menu_ssh(void *ctx, struct cargs *cargs)
int l;
size_t len;
ssize_t slen;
int mflags = (CWM_MENU_DUMMY);
TAILQ_FOREACH(cmd, &Conf.cmdq, entry) {
if (strcmp(cmd->name, "term") == 0)
@ -679,7 +690,7 @@ kbfunc_menu_ssh(void *ctx, struct cargs *cargs)
err(1, "%s", path);
(void)fclose(fp);
menu:
if ((mi = menu_filter(sc, &menuq, "ssh", NULL, (CWM_MENU_DUMMY),
if ((mi = menu_filter(sc, &menuq, "ssh", NULL, mflags,
search_match_text, search_print_text)) != NULL) {
if (mi->text[0] == '\0')
goto out;
@ -701,11 +712,12 @@ kbfunc_client_menu_label(void *ctx, struct cargs *cargs)
struct client_ctx *cc = ctx;
struct menu *mi;
struct menu_q menuq;
int mflags = (CWM_MENU_DUMMY);
TAILQ_INIT(&menuq);
/* dummy is set, so this will always return */
mi = menu_filter(cc->sc, &menuq, "label", cc->label, (CWM_MENU_DUMMY),
mi = menu_filter(cc->sc, &menuq, "label", cc->label, mflags,
search_match_text, search_print_text);
if (!mi->abort) {

74
menu.c
View File

@ -48,7 +48,6 @@ struct menu_ctx {
char searchstr[MENU_MAXENTRY + 1];
char dispstr[MENU_MAXENTRY*2 + 1];
char promptstr[MENU_MAXENTRY + 1];
int hasprompt;
int list;
int listing;
int changed;
@ -85,15 +84,13 @@ menu_filter(struct screen_ctx *sc, struct menu_q *menuq, const char *prompt,
struct menu *mi = NULL;
XEvent e;
Window focuswin;
int evmask, focusrevert;
int xsave, ysave, xcur, ycur;
int focusrevert, xsave, ysave, xcur, ycur;
TAILQ_INIT(&resultq);
(void)memset(&mc, 0, sizeof(mc));
xu_ptr_getpos(sc->rootwin, &xsave, &ysave);
(void)memset(&mc, 0, sizeof(mc));
mc.sc = sc;
mc.flags = flags;
mc.match = match;
@ -105,19 +102,13 @@ menu_filter(struct screen_ctx *sc, struct menu_q *menuq, const char *prompt,
if (mc.flags & CWM_MENU_LIST)
mc.list = 1;
(void)strlcpy(mc.promptstr, prompt, sizeof(mc.promptstr));
if (initial != NULL)
(void)strlcpy(mc.searchstr, initial, sizeof(mc.searchstr));
else
mc.searchstr[0] = '\0';
evmask = MENUMASK;
if (prompt != NULL) {
evmask |= KEYMASK; /* accept keys as well */
(void)strlcpy(mc.promptstr, prompt, sizeof(mc.promptstr));
mc.hasprompt = 1;
}
XSelectInput(X_Dpy, sc->menu.win, evmask);
XSelectInput(X_Dpy, sc->menu.win, MENUMASK);
XMapRaised(X_Dpy, sc->menu.win);
if (XGrabPointer(X_Dpy, sc->menu.win, False, MENUGRABMASK,
@ -137,7 +128,7 @@ menu_filter(struct screen_ctx *sc, struct menu_q *menuq, const char *prompt,
for (;;) {
mc.changed = 0;
XWindowEvent(X_Dpy, sc->menu.win, evmask, &e);
XWindowEvent(X_Dpy, sc->menu.win, MENUMASK, &e);
switch (e.type) {
case KeyPress:
@ -188,13 +179,14 @@ menu_complete_path(struct menu_ctx *mc)
struct screen_ctx *sc = mc->sc;
struct menu *mi, *mr;
struct menu_q menuq;
int mflags = (CWM_MENU_DUMMY);
mr = xcalloc(1, sizeof(*mr));
TAILQ_INIT(&menuq);
if ((mi = menu_filter(sc, &menuq, mc->searchstr, NULL,
(CWM_MENU_DUMMY), search_match_path, search_print_text)) != NULL) {
if ((mi = menu_filter(sc, &menuq, mc->searchstr, NULL, mflags,
search_match_path, search_print_text)) != NULL) {
mr->abort = mi->abort;
mr->dummy = mi->dummy;
if (mi->text[0] != '\0')
@ -343,28 +335,19 @@ menu_draw(struct menu_ctx *mc, struct menu_q *menuq, struct menu_q *resultq)
mc->listing = 0;
}
mc->num = 0;
mc->geom.w = 0;
mc->geom.h = 0;
if (mc->hasprompt) {
(void)snprintf(mc->dispstr, sizeof(mc->dispstr), "%s%s%s%s",
mc->promptstr, PROMPT_SCHAR, mc->searchstr, PROMPT_ECHAR);
XftTextExtentsUtf8(X_Dpy, sc->xftfont,
(const FcChar8*)mc->dispstr, strlen(mc->dispstr), &extents);
mc->geom.w = extents.xOff;
mc->geom.h = sc->xftfont->height + 1;
mc->num = 1;
}
(void)snprintf(mc->dispstr, sizeof(mc->dispstr), "%s%s%s%s",
mc->promptstr, PROMPT_SCHAR, mc->searchstr, PROMPT_ECHAR);
XftTextExtentsUtf8(X_Dpy, sc->xftfont,
(const FcChar8*)mc->dispstr, strlen(mc->dispstr), &extents);
mc->geom.w = extents.xOff;
mc->geom.h = sc->xftfont->height + 1;
mc->num = 1;
TAILQ_FOREACH(mi, resultq, resultentry) {
(*mc->print)(mi, mc->listing);
XftTextExtentsUtf8(X_Dpy, sc->xftfont,
(const FcChar8*)mi->print,
MIN(strlen(mi->print), MENU_MAXENTRY), &extents);
mc->geom.w = MAX(mc->geom.w, extents.xOff);
mc->geom.h += sc->xftfont->height + 1;
mc->num++;
@ -398,14 +381,11 @@ menu_draw(struct menu_ctx *mc, struct menu_q *menuq, struct menu_q *resultq)
XMoveResizeWindow(X_Dpy, sc->menu.win, mc->geom.x, mc->geom.y,
mc->geom.w, mc->geom.h);
n = 0;
if (mc->hasprompt) {
XftDrawStringUtf8(sc->menu.xftdraw,
&sc->xftcolor[CWM_COLOR_MENU_FONT], sc->xftfont,
0, sc->xftfont->ascent,
(const FcChar8*)mc->dispstr, strlen(mc->dispstr));
n++;
}
n = 1;
XftDrawStringUtf8(sc->menu.xftdraw,
&sc->xftcolor[CWM_COLOR_MENU_FONT], sc->xftfont,
0, sc->xftfont->ascent,
(const FcChar8*)mc->dispstr, strlen(mc->dispstr));
TAILQ_FOREACH(mi, resultq, resultentry) {
int y = n * (sc->xftfont->height + 1) + sc->xftfont->ascent + 1;
@ -420,7 +400,7 @@ menu_draw(struct menu_ctx *mc, struct menu_q *menuq, struct menu_q *resultq)
(const FcChar8*)mi->print, strlen(mi->print));
n++;
}
if (mc->hasprompt && n > 1)
if (n > 1)
menu_draw_entry(mc, resultq, 1, 1);
}
@ -430,10 +410,7 @@ menu_draw_entry(struct menu_ctx *mc, struct menu_q *resultq,
{
struct screen_ctx *sc = mc->sc;
struct menu *mi;
int color, i = 0;
if (mc->hasprompt)
i = 1;
int color, i = 1;
TAILQ_FOREACH(mi, resultq, resultentry)
if (entry == i++)
@ -474,13 +451,10 @@ static struct menu *
menu_handle_release(struct menu_ctx *mc, struct menu_q *resultq, int x, int y)
{
struct menu *mi;
int entry, i = 0;
int entry, i = 1;
entry = menu_calc_entry(mc, x, y);
if (mc->hasprompt)
i = 1;
TAILQ_FOREACH(mi, resultq, resultentry)
if (entry == i++)
break;
@ -506,7 +480,7 @@ menu_calc_entry(struct menu_ctx *mc, int x, int y)
entry < 0 || entry >= mc->num)
entry = -1;
if (mc->hasprompt && entry == 0)
if (entry == 0)
entry = -1;
return(entry);

19
parse.y
View File

@ -72,7 +72,7 @@ typedef struct {
%token BINDKEY UNBINDKEY BINDMOUSE UNBINDMOUSE
%token FONTNAME STICKY GAP
%token AUTOGROUP COMMAND IGNORE
%token AUTOGROUP COMMAND IGNORE WM
%token YES NO BORDERWIDTH MOVEAMOUNT
%token COLOR SNAPDIST
%token ACTIVEBORDER INACTIVEBORDER URGENCYBORDER
@ -139,12 +139,24 @@ main : FONTNAME STRING {
conf->snapdist = $2;
}
| COMMAND STRING string {
if (!conf_cmd_add(conf, $2, $3)) {
yyerror("command name/path too long");
if (strlen($3) >= PATH_MAX) {
yyerror("%s command path too long", $2);
free($2);
free($3);
YYERROR;
}
conf_cmd_add(conf, $2, $3);
free($2);
free($3);
}
| WM STRING string {
if (strlen($3) >= PATH_MAX) {
yyerror("%s wm path too long", $2);
free($2);
free($3);
YYERROR;
}
conf_wm_add(conf, $2, $3);
free($2);
free($3);
}
@ -319,6 +331,7 @@ lookup(char *s)
{ "unbind-mouse", UNBINDMOUSE},
{ "ungroupborder", UNGROUPBORDER},
{ "urgencyborder", URGENCYBORDER},
{ "wm", WM},
{ "yes", YES}
};
const struct keywords *p;

View File

@ -37,7 +37,8 @@ screen_init(int which)
struct screen_ctx *sc;
Window *wins, w0, w1, active = None;
XSetWindowAttributes rootattr;
unsigned int nwins, i;
unsigned int nwins, w;
int i;
sc = xmalloc(sizeof(*sc));
@ -77,8 +78,8 @@ screen_init(int which)
/* Deal with existing clients. */
if (XQueryTree(X_Dpy, sc->rootwin, &w0, &w1, &wins, &nwins)) {
for (i = 0; i < nwins; i++)
(void)client_init(wins[i], sc, (active == wins[i]));
for (w = 0; w < nwins; w++)
(void)client_init(wins[w], sc, (active == wins[w]));
XFree(wins);
}

View File

@ -69,15 +69,16 @@ match_substr(char *sub, char *str, int zeroidx)
void
search_match_client(struct menu_q *menuq, struct menu_q *resultq, char *search)
{
struct winname *wn;
struct menu *mi, *tierp[4], *before = NULL;
struct menu *mi, *tierp[3], *before = NULL;
struct client_ctx *cc;
struct winname *wn;
(void)memset(tierp, 0, sizeof(tierp));
TAILQ_INIT(resultq);
TAILQ_FOREACH(mi, menuq, entry) {
int tier = -1, t;
struct client_ctx *cc = (struct client_ctx *)mi->ctx;
cc = (struct client_ctx *)mi->ctx;
/* Match on label. */
if (match_substr(search, cc->label, 0))
@ -87,14 +88,14 @@ search_match_client(struct menu_q *menuq, struct menu_q *resultq, char *search)
if (tier < 0) {
TAILQ_FOREACH_REVERSE(wn, &cc->nameq, name_q, entry)
if (match_substr(search, wn->name, 0)) {
tier = 2;
tier = 1;
break;
}
}
/* Match on window resource class. */
if ((tier < 0) && match_substr(search, cc->ch.res_class, 0))
tier = 3;
tier = 2;
if (tier < 0)
continue;
@ -107,9 +108,6 @@ search_match_client(struct menu_q *menuq, struct menu_q *resultq, char *search)
if ((tier > 0) && (cc->flags & CLIENT_HIDDEN))
tier--;
if (tier >= nitems(tierp))
errx(1, "%s: invalid tier", __func__);
/*
* If you have a tierp, insert after it, and make it
* the new tierp. If you don't have a tierp, find the
@ -132,11 +130,12 @@ search_match_client(struct menu_q *menuq, struct menu_q *resultq, char *search)
void
search_match_cmd(struct menu_q *menuq, struct menu_q *resultq, char *search)
{
struct menu *mi;
struct menu *mi;
struct cmd_ctx *cmd;
TAILQ_INIT(resultq);
TAILQ_FOREACH(mi, menuq, entry) {
struct cmd_ctx *cmd = (struct cmd_ctx *)mi->ctx;
cmd = (struct cmd_ctx *)mi->ctx;
if (match_substr(search, cmd->name, 0))
TAILQ_INSERT_TAIL(resultq, mi, resultentry);
}
@ -145,12 +144,13 @@ search_match_cmd(struct menu_q *menuq, struct menu_q *resultq, char *search)
void
search_match_group(struct menu_q *menuq, struct menu_q *resultq, char *search)
{
struct menu *mi;
char *s;
struct menu *mi;
struct group_ctx *gc;
char *s;
TAILQ_INIT(resultq);
TAILQ_FOREACH(mi, menuq, entry) {
struct group_ctx *gc = (struct group_ctx *)mi->ctx;
gc = (struct group_ctx *)mi->ctx;
xasprintf(&s, "%d %s", gc->num, gc->name);
if (match_substr(search, s, 0))
TAILQ_INSERT_TAIL(resultq, mi, resultentry);
@ -162,12 +162,11 @@ static void
match_path_type(struct menu_q *resultq, char *search, int flag)
{
struct menu *mi;
char pattern[PATH_MAX];
char *pattern;
glob_t g;
int i;
(void)strlcpy(pattern, search, sizeof(pattern));
(void)strlcat(pattern, "*", sizeof(pattern));
xasprintf(&pattern, "%s*", search);
if (glob(pattern, GLOB_MARK, NULL, &g) != 0)
return;
for (i = 0; i < g.gl_pathc; i++) {
@ -178,6 +177,7 @@ match_path_type(struct menu_q *resultq, char *search, int flag)
TAILQ_INSERT_TAIL(resultq, mi, resultentry);
}
globfree(&g);
free(pattern);
}
void
@ -224,6 +224,21 @@ search_match_text(struct menu_q *menuq, struct menu_q *resultq, char *search)
}
}
void
search_match_wm(struct menu_q *menuq, struct menu_q *resultq, char *search)
{
struct menu *mi;
struct cmd_ctx *wm;
TAILQ_INIT(resultq);
TAILQ_FOREACH(mi, menuq, entry) {
wm = (struct cmd_ctx *)mi->ctx;
if ((match_substr(search, wm->name, 0)) ||
(match_substr(search, wm->path, 0)))
TAILQ_INSERT_TAIL(resultq, mi, resultentry);
}
}
void
search_print_client(struct menu *mi, int listing)
{
@ -243,7 +258,7 @@ search_print_client(struct menu *mi, int listing)
void
search_print_cmd(struct menu *mi, int listing)
{
struct cmd_ctx *cmd = (struct cmd_ctx *)mi->ctx;
struct cmd_ctx *cmd = (struct cmd_ctx *)mi->ctx;
(void)snprintf(mi->print, sizeof(mi->print), "%s", cmd->name);
}
@ -263,3 +278,12 @@ search_print_text(struct menu *mi, int listing)
{
(void)snprintf(mi->print, sizeof(mi->print), "%s", mi->text);
}
void
search_print_wm(struct menu *mi, int listing)
{
struct cmd_ctx *wm = (struct cmd_ctx *)mi->ctx;
(void)snprintf(mi->print, sizeof(mi->print), "%s [%s]",
wm->name, wm->path);
}

36
util.c
View File

@ -31,13 +31,15 @@
#include "calmwm.h"
static void log_msg(const char *, va_list);
void
u_spawn(char *argstr)
{
switch (fork()) {
case 0:
u_exec(argstr);
break;
exit(1);
case -1:
warn("fork");
default:
@ -78,7 +80,7 @@ u_exec(char *argstr)
(void)setsid();
(void)execvp(args[0], args);
err(1, "%s", s);
warn("%s", s);
}
char *
@ -104,3 +106,33 @@ u_argv(char * const *argv)
}
return(p);
}
static void
log_msg(const char *msg, va_list ap)
{
char *fmt;
if (asprintf(&fmt, "%s\n", msg) == -1) {
vfprintf(stderr, msg, ap);
fprintf(stderr, "\n");
} else {
vfprintf(stderr, fmt, ap);
free(fmt);
}
fflush(stderr);
}
void
log_debug(int level, const char *func, const char *msg, ...)
{
char *fmt;
va_list ap;
if (Conf.debug < level)
return;
va_start(ap, msg);
xasprintf(&fmt, "debug%d: %s: %s", level, func, msg);
log_msg(fmt, ap);
va_end(ap);
}

View File

@ -77,6 +77,8 @@ xev_handle_maprequest(XEvent *ee)
XMapRequestEvent *e = &ee->xmaprequest;
struct client_ctx *cc = NULL, *old_cc;
LOG_DEBUG3("window: 0x%lx", e->window);
if ((old_cc = client_current()) != NULL)
client_ptrsave(old_cc);
@ -93,6 +95,8 @@ xev_handle_unmapnotify(XEvent *ee)
XUnmapEvent *e = &ee->xunmap;
struct client_ctx *cc;
LOG_DEBUG3("window: 0x%lx", e->window);
if ((cc = client_find(e->window)) != NULL) {
if (e->send_event) {
client_set_wm_state(cc, WithdrawnState);
@ -109,6 +113,8 @@ xev_handle_destroynotify(XEvent *ee)
XDestroyWindowEvent *e = &ee->xdestroywindow;
struct client_ctx *cc;
LOG_DEBUG3("window: 0x%lx", e->window);
if ((cc = client_find(e->window)) != NULL)
client_delete(cc);
}
@ -121,6 +127,8 @@ xev_handle_configurerequest(XEvent *ee)
struct screen_ctx *sc;
XWindowChanges wc;
LOG_DEBUG3("window: 0x%lx", e->window);
if ((cc = client_find(e->window)) != NULL) {
sc = cc->sc;
@ -174,6 +182,8 @@ xev_handle_propertynotify(XEvent *ee)
struct screen_ctx *sc;
struct client_ctx *cc;
LOG_DEBUG3("window: 0x%lx", e->window);
if ((cc = client_find(e->window)) != NULL) {
switch (e->atom) {
case XA_WM_NORMAL_HINTS:
@ -209,6 +219,8 @@ xev_handle_enternotify(XEvent *ee)
XCrossingEvent *e = &ee->xcrossing;
struct client_ctx *cc;
LOG_DEBUG3("window: 0x%lx", e->window);
Last_Event_Time = e->time;
if ((cc = client_find(e->window)) != NULL)
@ -223,6 +235,8 @@ xev_handle_buttonpress(XEvent *ee)
struct screen_ctx *sc;
struct bind_ctx *mb;
LOG_DEBUG3("window: 0x%lx", e->window);
e->state &= ~IGNOREMODMASK;
TAILQ_FOREACH(mb, &Conf.mousebindq, entry) {
@ -259,9 +273,13 @@ xev_handle_buttonrelease(XEvent *ee)
XButtonEvent *e = &ee->xbutton;
struct client_ctx *cc;
LOG_DEBUG3("window: 0x%lx", ee->xbutton.window);
if ((cc = client_find(e->window)) != NULL) {
if (cc->flags & CLIENT_ACTIVE)
group_toggle_membership_leave(cc);
if (cc->flags & (CLIENT_ACTIVE | CLIENT_HIGHLIGHT)) {
cc->flags &= ~CLIENT_HIGHLIGHT;
client_draw_border(cc);
}
}
}
@ -275,6 +293,8 @@ xev_handle_keypress(XEvent *ee)
KeySym keysym, skeysym;
unsigned int modshift;
LOG_DEBUG3("window: 0x%lx", e->window);
keysym = XkbKeycodeToKeysym(X_Dpy, e->keycode, 0, 0);
skeysym = XkbKeycodeToKeysym(X_Dpy, e->keycode, 0, 1);
@ -322,16 +342,29 @@ xev_handle_keyrelease(XEvent *ee)
{
XKeyEvent *e = &ee->xkey;
struct screen_ctx *sc;
struct client_ctx *cc;
KeySym keysym;
unsigned int i;
LOG_DEBUG3("window: 0x%lx", e->window);
if ((sc = screen_find(e->root)) == NULL)
return;
keysym = XkbKeycodeToKeysym(X_Dpy, e->keycode, 0, 0);
for (i = 0; i < nitems(modkeys); i++) {
if (keysym == modkeys[i]) {
client_cycle_leave(sc);
if ((cc = client_current()) != NULL) {
if (sc->cycling) {
sc->cycling = 0;
client_mtf(cc);
}
if (cc->flags & CLIENT_HIGHLIGHT) {
cc->flags &= ~CLIENT_HIGHLIGHT;
client_draw_border(cc);
}
}
XUngrabKeyboard(X_Dpy, CurrentTime);
break;
}
}
@ -344,6 +377,8 @@ xev_handle_clientmessage(XEvent *ee)
struct client_ctx *cc, *old_cc;
struct screen_ctx *sc;
LOG_DEBUG3("window: 0x%lx", e->window);
if (e->message_type == cwmh[WM_CHANGE_STATE]) {
if ((cc = client_find(e->window)) != NULL) {
if (e->data.l[0] == IconicState)
@ -357,10 +392,7 @@ xev_handle_clientmessage(XEvent *ee)
if ((cc = client_find(e->window)) != NULL) {
if ((old_cc = client_current()) != NULL)
client_ptrsave(old_cc);
if (cc->flags & CLIENT_HIDDEN)
client_unhide(cc);
else
client_raise(cc);
client_show(cc);
client_ptrwarp(cc);
}
} else if (e->message_type == ewmh[_NET_WM_DESKTOP]) {
@ -394,6 +426,8 @@ xev_handle_randr(XEvent *ee)
struct screen_ctx *sc;
int i;
LOG_DEBUG3("new size: %d/%d", rev->width, rev->height);
i = XRRRootToScreen(X_Dpy, rev->root);
TAILQ_FOREACH(sc, &Screenq, entry) {
if (sc->which == i) {
@ -414,6 +448,8 @@ xev_handle_mappingnotify(XEvent *ee)
XMappingEvent *e = &ee->xmapping;
struct screen_ctx *sc;
LOG_DEBUG3("window: 0x%lx", e->window);
XRefreshKeyboardMapping(e);
if (e->request == MappingKeyboard) {
TAILQ_FOREACH(sc, &Screenq, entry)
@ -427,6 +463,8 @@ xev_handle_expose(XEvent *ee)
XExposeEvent *e = &ee->xexpose;
struct client_ctx *cc;
LOG_DEBUG3("window: 0x%lx", e->window);
if ((cc = client_find(e->window)) != NULL && e->count == 0)
client_draw_border(cc);
}
@ -436,9 +474,11 @@ xev_process(void)
{
XEvent e;
XNextEvent(X_Dpy, &e);
if (e.type - Conf.xrandr_event_base == RRScreenChangeNotify)
xev_handle_randr(&e);
else if (e.type < LASTEvent && xev_handlers[e.type] != NULL)
(*xev_handlers[e.type])(&e);
while (XPending(X_Dpy)) {
XNextEvent(X_Dpy, &e);
if (e.type - Conf.xrandr_event_base == RRScreenChangeNotify)
xev_handle_randr(&e);
else if (e.type < LASTEvent && xev_handlers[e.type] != NULL)
(*xev_handlers[e.type])(&e);
}
}

16
xutil.c
View File

@ -368,6 +368,12 @@ xu_ewmh_handle_net_wm_state_msg(struct client_ctx *cc, int action,
{ _NET_WM_STATE_DEMANDS_ATTENTION,
CLIENT_URGENCY,
client_urgency },
{ _NET_WM_STATE_SKIP_PAGER,
CLIENT_SKIP_PAGER,
client_toggle_skip_pager},
{ _NET_WM_STATE_SKIP_TASKBAR,
CLIENT_SKIP_TASKBAR,
client_toggle_skip_taskbar},
{ _CWM_WM_STATE_FREEZE,
CLIENT_FREEZE,
client_toggle_freeze },
@ -412,6 +418,10 @@ xu_ewmh_restore_net_wm_state(struct client_ctx *cc)
client_toggle_fullscreen(cc);
if (atoms[i] == ewmh[_NET_WM_STATE_DEMANDS_ATTENTION])
client_urgency(cc);
if (atoms[i] == ewmh[_NET_WM_STATE_SKIP_PAGER])
client_toggle_skip_pager(cc);
if (atoms[i] == ewmh[_NET_WM_STATE_SKIP_TASKBAR])
client_toggle_skip_taskbar(cc);
if (atoms[i] == ewmh[_CWM_WM_STATE_FREEZE])
client_toggle_freeze(cc);
}
@ -433,6 +443,8 @@ xu_ewmh_set_net_wm_state(struct client_ctx *cc)
oatoms[i] != ewmh[_NET_WM_STATE_HIDDEN] &&
oatoms[i] != ewmh[_NET_WM_STATE_FULLSCREEN] &&
oatoms[i] != ewmh[_NET_WM_STATE_DEMANDS_ATTENTION] &&
oatoms[i] != ewmh[_NET_WM_STATE_SKIP_PAGER] &&
oatoms[i] != ewmh[_NET_WM_STATE_SKIP_TASKBAR] &&
oatoms[i] != ewmh[_CWM_WM_STATE_FREEZE])
atoms[j++] = oatoms[i];
}
@ -451,6 +463,10 @@ xu_ewmh_set_net_wm_state(struct client_ctx *cc)
}
if (cc->flags & CLIENT_URGENCY)
atoms[j++] = ewmh[_NET_WM_STATE_DEMANDS_ATTENTION];
if (cc->flags & CLIENT_SKIP_PAGER)
atoms[j++] = ewmh[_NET_WM_STATE_SKIP_PAGER];
if (cc->flags & CLIENT_SKIP_TASKBAR)
atoms[j++] = ewmh[_NET_WM_STATE_SKIP_TASKBAR];
if (cc->flags & CLIENT_FREEZE)
atoms[j++] = ewmh[_CWM_WM_STATE_FREEZE];
if (j > 0)