diff options
author | okan <okan> | 2018-02-06 15:05:20 +0000 |
---|---|---|
committer | okan <okan> | 2018-02-06 15:05:20 +0000 |
commit | 63ebc0cd8b65300104929d3463fed431996f4374 (patch) | |
tree | f547800ff23c62896ad849d2148ec7adf3f08f0d | |
parent | a0774f4777a4a94ea4bbc867c16cde3167075f80 (diff) | |
parent | f3211427c16b755db20bc71ce4074e9fb9aae8af (diff) | |
download | cwm-63ebc0cd8b65300104929d3463fed431996f4374.tar.gz cwm-63ebc0cd8b65300104929d3463fed431996f4374.tar.xz cwm-63ebc0cd8b65300104929d3463fed431996f4374.zip |
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 ...
-rw-r--r-- | calmwm.c | 44 | ||||
-rw-r--r-- | calmwm.h | 65 | ||||
-rw-r--r-- | client.c | 84 | ||||
-rw-r--r-- | conf.c | 311 | ||||
-rw-r--r-- | cwm.1 | 16 | ||||
-rw-r--r-- | cwmrc.5 | 6 | ||||
-rw-r--r-- | group.c | 15 | ||||
-rw-r--r-- | kbfunc.c | 110 | ||||
-rw-r--r-- | menu.c | 74 | ||||
-rw-r--r-- | parse.y | 19 | ||||
-rw-r--r-- | screen.c | 7 | ||||
-rw-r--r-- | search.c | 58 | ||||
-rw-r--r-- | util.c | 36 | ||||
-rw-r--r-- | xevents.c | 64 | ||||
-rw-r--r-- | xutil.c | 16 |
15 files changed, 541 insertions, 384 deletions
diff --git a/calmwm.c b/calmwm.c index c3943c4..51b6a87 100644 --- a/calmwm.c +++ b/calmwm.c @@ -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); } diff --git a/calmwm.h b/calmwm.h index 26d8189..7cf30c4 100644 --- a/calmwm.h +++ b/calmwm.h @@ -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); diff --git a/client.c b/client.c index 6a66847..ed8e914 100644 --- a/client.c +++ b/client.c @@ -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); @@ -266,6 +265,20 @@ client_toggle_hidden(struct client_ctx *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) { cc->flags ^= CLIENT_STICKY; @@ -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); @@ -523,6 +531,15 @@ client_hide(struct client_ctx *cc) } 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) { XMapRaised(X_Dpy, cc->win); @@ -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)) diff --git a/conf.c b/conf.c index 0234f48..0c2ce13 100644 --- a/conf.c +++ b/conf.c @@ -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 }, - - { "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) }, - - { "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) }, - - { "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) }, - - { "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 }, - - { "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 }, - +#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 + + { 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) }, + + { 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)) }, + + { 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) }, + + { 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)) }, + + { 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); + cmd->path = xstrdup(path); + + 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); + } } - conf_cmd_remove(c, name); - TAILQ_INSERT_TAIL(&c->cmdq, cmd, entry); - return(1); } -static void -conf_cmd_remove(struct conf *c, const char *name) +void +conf_wm_add(struct conf *c, const char *name, const char *path) { - 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); + 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", }; diff --git a/cwm.1 b/cwm.1 index d81b223..bf6c573 100644 --- a/cwm.1 +++ b/cwm.1 @@ -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, diff --git a/cwmrc.5 b/cwmrc.5 index 6851faa..2e16850 100644 --- a/cwmrc.5 +++ b/cwmrc.5 @@ -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 diff --git a/group.c b/group.c index 722afcb..124f778 100644 --- a/group.c +++ b/group.c @@ -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) diff --git a/kbfunc.c b/kbfunc.c index e2a125b..b6fb13e 100644 --- a/kbfunc.c +++ b/kbfunc.c @@ -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)) ? @@ -541,6 +549,33 @@ kbfunc_menu_group(void *ctx, struct cargs *cargs) } 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) { #define NPATHS 256 @@ -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) { diff --git a/menu.c b/menu.c index d3db032..9323463 100644 --- a/menu.c +++ b/menu.c @@ -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); diff --git a/parse.y b/parse.y index ba99e0a..1db92c0 100644 --- a/parse.y +++ b/parse.y @@ -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; diff --git a/screen.c b/screen.c index 4e2767b..526dcea 100644 --- a/screen.c +++ b/screen.c @@ -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); } diff --git a/search.c b/search.c index 68c064e..06a08b7 100644 --- a/search.c +++ b/search.c @@ -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 @@ -225,6 +225,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) { struct client_ctx *cc = (struct client_ctx *)mi->ctx; @@ -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); +} diff --git a/util.c b/util.c index 7b8e4c8..9119cc2 100644 --- a/util.c +++ b/util.c @@ -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); +} diff --git a/xevents.c b/xevents.c index 560cbb4..6518dc0 100644 --- a/xevents.c +++ b/xevents.c @@ -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); + } } diff --git a/xutil.c b/xutil.c index 2a851df..1b604c7 100644 --- a/xutil.c +++ b/xutil.c @@ -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) |