diff --git a/calmwm.c b/calmwm.c index ea017e1..39f53d8 100644 --- a/calmwm.c +++ b/calmwm.c @@ -94,7 +94,7 @@ main(int argc, char **argv) signal(SIGINT, sighdlr) == SIG_ERR || signal(SIGTERM, sighdlr) == SIG_ERR) err(1, "signal"); - + if (parse_config(Conf.conf_file, &Conf) == -1) { warnx("error parsing config file"); if (nflag) diff --git a/calmwm.h b/calmwm.h index 95e3c8d..b3992c3 100644 --- a/calmwm.h +++ b/calmwm.h @@ -235,6 +235,7 @@ struct screen_ctx { struct region_q regionq; struct group_q groupq; struct group_ctx *group_active; + struct group_ctx *group_last; Colormap colormap; Visual *visual; struct { @@ -329,30 +330,39 @@ struct conf { /* MWM hints */ struct mwm_hints { -#define MWM_HINTS_ELEMENTS 3L -#define MWM_FLAGS_STATUS (1<<3) +#define MWM_HINTS_ELEMENTS 5L -#define MWM_FLAGS_FUNCTIONS (1<<0) -#define MWM_FLAGS_DECORATIONS (1<<1) -#define MWM_FLAGS_INPUT_MODE (1<<2) +#define MWM_HINTS_FUNCTIONS (1L << 0) +#define MWM_HINTS_DECORATIONS (1L << 1) +#define MWM_HINTS_INPUT_MODE (1L << 2) +#define MWM_HINTS_STATUS (1L << 3) unsigned long flags; -#define MWM_FUNCS_ALL (1<<0) -#define MWM_FUNCS_RESIZE (1<<1) -#define MWM_FUNCS_MOVE (1<<2) -#define MWM_FUNCS_MINIMIZE (1<<3) -#define MWM_FUNCS_MAXIMIZE (1<<4) -#define MWM_FUNCS_CLOSE (1<<5) +#define MWM_FUNC_ALL (1L << 0) +#define MWM_FUNC_RESIZE (1L << 1) +#define MWM_FUNC_MOVE (1L << 2) +#define MWM_FUNC_MINIMIZE (1L << 3) +#define MWM_FUNC_MAXIMIZE (1L << 4) +#define MWM_FUNC_CLOSE (1L << 5) unsigned long functions; -#define MWM_DECOR_ALL (1<<0) -#define MWM_DECOR_BORDER (1<<1) -#define MWM_DECOR_RESIZE_HANDLE (1<<2) -#define MWM_DECOR_TITLEBAR (1<<3) -#define MWM_DECOR_MENU (1<<4) -#define MWM_DECOR_MINIMIZE (1<<5) -#define MWM_DECOR_MAXIMIZE (1<<6) +#define MWM_DECOR_ALL (1L << 0) +#define MWM_DECOR_BORDER (1L << 1) +#define MWM_DECOR_RESIZEH (1L << 2) +#define MWM_DECOR_TITLE (1L << 3) +#define MWM_DECOR_MENU (1L << 4) +#define MWM_DECOR_MINIMIZE (1L << 5) +#define MWM_DECOR_MAXIMIZE (1L << 6) unsigned long decorations; + +#define MWM_INPUT_MODELESS 0 +#define MWM_INPUT_PRIMARY_APPLICATION_MODAL 1 +#define MWM_INPUT_SYSTEM_MODAL 2 +#define MWM_INPUT_FULL_APPLICATION_MODAL 3 + long inputMode; + +#define MWM_TEAROFF_WINDOW (1L << 0) + unsigned long status; }; enum cwmh { @@ -524,6 +534,7 @@ void kbfunc_client_toggle_group(void *, struct cargs *); void kbfunc_client_movetogroup(void *, struct cargs *); void kbfunc_group_toggle(void *, struct cargs *); void kbfunc_group_only(void *, struct cargs *); +void kbfunc_group_last(void *, struct cargs *); void kbfunc_group_close(void *, struct cargs *); void kbfunc_group_cycle(void *, struct cargs *); void kbfunc_group_toggle_all(void *, struct cargs *); @@ -597,7 +608,7 @@ int xu_ewmh_get_net_wm_desktop(struct client_ctx *, long *); void xu_ewmh_set_net_wm_desktop(struct client_ctx *); Atom *xu_ewmh_get_net_wm_state(struct client_ctx *, int *); void xu_ewmh_handle_net_wm_state_msg(struct client_ctx *, - int, Atom , Atom); + int, Atom, Atom); void xu_ewmh_set_net_wm_state(struct client_ctx *); void xu_ewmh_restore_net_wm_state(struct client_ctx *); diff --git a/client.c b/client.c index f9262f8..59bc7b0 100644 --- a/client.c +++ b/client.c @@ -637,7 +637,7 @@ void client_wm_hints(struct client_ctx *cc) { XWMHints *wmh; - + if ((wmh = XGetWMHints(X_Dpy, cc->win)) != NULL) { if ((wmh->flags & InputHint) && (wmh->input)) cc->flags |= CLIENT_INPUT; @@ -849,13 +849,15 @@ client_mwm_hints(struct client_ctx *cc) if (xu_get_prop(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)) + (unsigned char **)&mwmh) <= 0) + return; + + if ((mwmh->flags & MWM_HINTS_DECORATIONS) && + !(mwmh->decorations & MWM_DECOR_ALL)) { + if (!(mwmh->decorations & MWM_DECOR_BORDER)) cc->bwidth = 0; - XFree(mwmh); } + XFree(mwmh); } void diff --git a/conf.c b/conf.c index 53ca295..7d3ae6e 100644 --- a/conf.c +++ b/conf.c @@ -139,6 +139,7 @@ static const struct { { FUNC_SC(group-cycle, group_cycle, (CWM_CYCLE_FORWARD)) }, { FUNC_SC(group-rcycle, group_cycle, (CWM_CYCLE_REVERSE)) }, + { FUNC_SC(group-last, group_last, 0) }, { FUNC_SC(group-toggle-all, group_toggle_all, 0) }, { FUNC_SC(group-toggle-1, group_toggle, 1) }, { FUNC_SC(group-toggle-2, group_toggle, 2) }, @@ -647,7 +648,7 @@ conf_unbind_mouse(struct conf *c, struct bind_ctx *unbind) struct bind_ctx *mb = NULL, *mbnxt; TAILQ_FOREACH_SAFE(mb, &c->mousebindq, entry, mbnxt) { - if ((unbind == NULL) || + if ((unbind == NULL) || ((mb->modmask == unbind->modmask) && (mb->press.button == unbind->press.button))) { TAILQ_REMOVE(&c->mousebindq, mb, entry); @@ -669,6 +670,8 @@ conf_grab_kbd(Window win) TAILQ_FOREACH(kb, &Conf.keybindq, entry) { kc = XKeysymToKeycode(X_Dpy, kb->press.keysym); + if (kc == 0) + continue; if ((XkbKeycodeToKeysym(X_Dpy, kc, 0, 0) != kb->press.keysym) && (XkbKeycodeToKeysym(X_Dpy, kc, 0, 1) == kb->press.keysym)) kb->modmask |= ShiftMask; diff --git a/cwmrc.5 b/cwmrc.5 index ab70d25..7075288 100644 --- a/cwmrc.5 +++ b/cwmrc.5 @@ -273,6 +273,8 @@ menu. Toggle visibility of group n, where n is 1-9. .It group-only-[n] Show only group n, where n is 1-9, hiding other groups. +.It group-last +Show only the previously active group. .It group-close-[n] Close all windows in group n, where n is 1-9. .It group-toggle-all diff --git a/group.c b/group.c index 59eae73..af4c759 100644 --- a/group.c +++ b/group.c @@ -215,6 +215,9 @@ group_only(struct screen_ctx *sc, int idx) { struct group_ctx *gc; + if (sc->group_last != sc->group_active) + sc->group_last = sc->group_active; + TAILQ_FOREACH(gc, &sc->groupq, entry) { if (gc->num == idx) group_show(gc); diff --git a/kbfunc.c b/kbfunc.c index 2d5d1ce..ed1d7cb 100644 --- a/kbfunc.c +++ b/kbfunc.c @@ -453,7 +453,16 @@ kbfunc_client_cycle(void *ctx, struct cargs *cargs) newcc->ptr.x = newcc->geom.w / 2; newcc->ptr.y = newcc->geom.h / 2; } - client_ptr_warp(newcc); + + /* When no client is active, warp pointer to last active. */ + if (oldcc->flags & (CLIENT_ACTIVE)) + client_ptr_warp(newcc); + else if (oldcc->flags & (CLIENT_SKIP_CYCLE)) + client_ptr_warp(newcc); + else { + client_raise(oldcc); + client_ptr_warp(oldcc); + } } void @@ -481,6 +490,14 @@ kbfunc_group_only(void *ctx, struct cargs *cargs) group_only(ctx, cargs->flag); } +void +kbfunc_group_last(void *ctx, struct cargs *cargs) +{ + struct screen_ctx *sc = ctx; + + group_only(ctx, sc->group_last->num); +} + void kbfunc_group_toggle(void *ctx, struct cargs *cargs) { @@ -663,7 +680,7 @@ kbfunc_menu_exec(void *ctx, struct cargs *cargs) /* lstat(2) in case d_type isn't supported. */ if (lstat(tpath, &sb) == -1) continue; - if (!S_ISREG(sb.st_mode) && + if (!S_ISREG(sb.st_mode) && !S_ISLNK(sb.st_mode)) continue; } diff --git a/parse.y b/parse.y index 383b2dd..d0407a7 100644 --- a/parse.y +++ b/parse.y @@ -83,7 +83,7 @@ typedef struct { %token STRING %token NUMBER %type yesno -%type string +%type string numberstring %% grammar : /* empty */ @@ -106,6 +106,17 @@ string : string STRING { | STRING ; +numberstring : NUMBER { + char *s; + if (asprintf(&s, "%lld", $1) == -1) { + yyerror("string: asprintf"); + YYERROR; + } + $$ = s; + } + | STRING + ; + yesno : YES { $$ = 1; } | NO { $$ = 0; } ; @@ -211,7 +222,7 @@ main : FONTNAME STRING { conf->gap.left = $4; conf->gap.right = $5; } - | BINDKEY STRING string { + | BINDKEY numberstring string { if (!conf_bind_key(conf, $2, $3)) { yyerror("invalid bind-key: %s %s", $2, $3); free($2); @@ -221,7 +232,7 @@ main : FONTNAME STRING { free($2); free($3); } - | UNBINDKEY STRING { + | UNBINDKEY numberstring { if (!conf_bind_key(conf, $2, NULL)) { yyerror("invalid unbind-key: %s", $2); free($2); @@ -229,7 +240,7 @@ main : FONTNAME STRING { } free($2); } - | BINDMOUSE STRING string { + | BINDMOUSE numberstring string { if (!conf_bind_mouse(conf, $2, $3)) { yyerror("invalid bind-mouse: %s %s", $2, $3); free($2); @@ -239,7 +250,7 @@ main : FONTNAME STRING { free($2); free($3); } - | UNBINDMOUSE STRING { + | UNBINDMOUSE numberstring { if (!conf_bind_mouse(conf, $2, NULL)) { yyerror("invalid unbind-mouse: %s", $2); free($2); @@ -376,7 +387,7 @@ lgetc(int quotec) if (parsebuf) { /* Read character from the parsebuffer instead of input. */ if (parseindex >= 0) { - c = parsebuf[parseindex++]; + c = (unsigned char)parsebuf[parseindex++]; if (c != '\0') return (c); parsebuf = NULL; @@ -385,7 +396,7 @@ lgetc(int quotec) } if (pushback_index) - return (pushback_buffer[--pushback_index]); + return ((unsigned char)pushback_buffer[--pushback_index]); if (quotec) { if ((c = getc(file->stream)) == EOF) { @@ -426,10 +437,10 @@ lungetc(int c) if (parseindex >= 0) return (c); } - if (pushback_index < MAXPUSHBACK-1) - return (pushback_buffer[pushback_index++] = c); - else + if (pushback_index + 1 >= MAXPUSHBACK) return (EOF); + pushback_buffer[pushback_index++] = c; + return (c); } int @@ -442,7 +453,7 @@ findeol(void) /* skip to either EOF or the first real EOL */ while (1) { if (pushback_index) - c = pushback_buffer[--pushback_index]; + c = (unsigned char)pushback_buffer[--pushback_index]; else c = lgetc(0); if (c == '\n') { @@ -516,7 +527,7 @@ yylex(void) if (c == '-' || isdigit(c)) { do { *p++ = c; - if ((unsigned)(p-buf) >= sizeof(buf)) { + if ((size_t)(p-buf) >= sizeof(buf)) { yyerror("string too long"); return (findeol()); } @@ -539,8 +550,8 @@ yylex(void) } else { nodigits: while (p > buf + 1) - lungetc(*--p); - c = *--p; + lungetc((unsigned char)*--p); + c = (unsigned char)*--p; if (c == '-') return (c); } @@ -555,7 +566,7 @@ nodigits: if (isalnum(c) || c == ':' || c == '_' || c == '*' || c == '/') { do { *p++ = c; - if ((unsigned)(p-buf) >= sizeof(buf)) { + if ((size_t)(p-buf) >= sizeof(buf)) { yyerror("string too long"); return (findeol()); } diff --git a/screen.c b/screen.c index 59b6eff..8e4df53 100644 --- a/screen.c +++ b/screen.c @@ -60,6 +60,7 @@ screen_init(int which) xu_ewmh_net_supported_wm_check(sc); conf_group(sc); + sc->group_last = sc->group_active; screen_update_geometry(sc); xu_ewmh_net_desktop_names(sc);