diff options
-rw-r--r-- | calmwm.c | 2 | ||||
-rw-r--r-- | calmwm.h | 50 | ||||
-rw-r--r-- | client.c | 20 | ||||
-rw-r--r-- | conf.c | 11 | ||||
-rw-r--r-- | cwm.1 | 4 | ||||
-rw-r--r-- | cwmrc.5 | 6 | ||||
-rw-r--r-- | group.c | 3 | ||||
-rw-r--r-- | kbfunc.c | 25 | ||||
-rw-r--r-- | menu.c | 25 | ||||
-rw-r--r-- | parse.y | 49 | ||||
-rw-r--r-- | screen.c | 1 | ||||
-rw-r--r-- | xutil.c | 4 |
12 files changed, 136 insertions, 64 deletions
diff --git a/calmwm.c b/calmwm.c index af1effb..f81a2f6 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 9ae2afe..60e59f6 100644 --- a/calmwm.h +++ b/calmwm.h @@ -67,6 +67,7 @@ #define CWM_CYCLE_FORWARD 0x0001 #define CWM_CYCLE_REVERSE 0x0002 #define CWM_CYCLE_INGROUP 0x0004 +#define CWM_CYCLE_INCLASS 0x0008 enum cwm_status { CWM_QUIT, @@ -214,6 +215,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 { @@ -308,30 +310,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 { @@ -501,6 +512,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 *); @@ -574,7 +586,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 cfdd048..e09a71d 100644 --- a/client.c +++ b/client.c @@ -336,6 +336,7 @@ client_toggle_fullscreen(struct client_ctx *cc) resize: client_resize(cc, 0); xu_ewmh_set_net_wm_state(cc); + client_ptr_inbound(cc, 1); } void @@ -376,6 +377,7 @@ client_toggle_maximize(struct client_ctx *cc) resize: client_resize(cc, 0); xu_ewmh_set_net_wm_state(cc); + client_ptr_inbound(cc, 1); } void @@ -408,6 +410,7 @@ client_toggle_vmaximize(struct client_ctx *cc) resize: client_resize(cc, 0); xu_ewmh_set_net_wm_state(cc); + client_ptr_inbound(cc, 1); } void @@ -440,6 +443,7 @@ client_toggle_hmaximize(struct client_ctx *cc) resize: client_resize(cc, 0); xu_ewmh_set_net_wm_state(cc); + client_ptr_inbound(cc, 1); } void @@ -592,7 +596,7 @@ client_draw_border(struct client_ctx *cc) pixel = sc->xftcolor[CWM_COLOR_BORDER_URGENCY].pixel; XSetWindowBorderWidth(X_Dpy, cc->win, (unsigned int)cc->bwidth); - XSetWindowBorder(X_Dpy, cc->win, pixel); + XSetWindowBorder(X_Dpy, cc->win, pixel | (0xffu << 24)); } static void @@ -633,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; @@ -845,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 a3026cf..39f0406 100644 --- a/conf.c +++ b/conf.c @@ -136,9 +136,14 @@ static const struct { (CWM_CYCLE_FORWARD | CWM_CYCLE_INGROUP)) }, { FUNC_SC(window-rcycle-ingroup, client_cycle, (CWM_CYCLE_REVERSE | CWM_CYCLE_INGROUP)) }, + { FUNC_SC(window-cycle-inclass, client_cycle, + (CWM_CYCLE_FORWARD | CWM_CYCLE_INCLASS)) }, + { FUNC_SC(window-rcycle-inclass, client_cycle, + (CWM_CYCLE_REVERSE | CWM_CYCLE_INCLASS)) }, { 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) }, @@ -219,6 +224,8 @@ static const struct { { "C-slash", "menu-cmd" }, { "M-Tab", "window-cycle" }, { "MS-Tab", "window-rcycle" }, + { "M-grave", "window-cycle-inclass" }, + { "MS-grave", "window-rcycle-inclass" }, { "CM-n", "window-menu-label" }, { "CM-x", "window-close" }, { "CM-a", "group-toggle-all" }, @@ -647,7 +654,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 +676,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/cwm.1 b/cwm.1 index e0a892e..d70d856 100644 --- a/cwm.1 +++ b/cwm.1 @@ -102,6 +102,10 @@ Label current window. Cycle through currently visible windows. .It Ic MS-Tab Reverse cycle through currently visible windows. +.It Ic M-grave +Cycle through currently visible windows of the same window class. +.It Ic MS-grave +Reverse cycle through currently visible windows of the same window class. .It Ic CM-x Close current window. .It Ic CM-[n] diff --git a/cwmrc.5 b/cwmrc.5 index ab70d25..7d5f1f8 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 @@ -293,6 +295,10 @@ Reverse cycle through windows. Forward cycle through windows in current group. .It window-rcycle-ingroup Reverse cycle through windows in current group. +.It window-cycle-inclass +Forward cycle through windows of the current window class. +.It window-rcycle-inclass +Reverse cycle through windows of the current window class. .It window-close Close current window. .It window-hide diff --git a/group.c b/group.c index de55211..3246936 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 cbccc56..d858b7b 100644 --- a/kbfunc.c +++ b/kbfunc.c @@ -430,7 +430,9 @@ kbfunc_client_cycle(void *ctx, struct cargs *cargs) /* Only cycle visible and non-ignored windows. */ if ((newcc->flags & (CLIENT_SKIP_CYCLE)) || ((flags & CWM_CYCLE_INGROUP) && - (newcc->gc != oldcc->gc))) + (newcc->gc != oldcc->gc)) || + ((flags & CWM_CYCLE_INCLASS) && + strcmp(newcc->res_class, oldcc->res_class) != 0)) again = 1; /* Is oldcc the only non-hidden window? */ @@ -450,7 +452,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 @@ -479,6 +490,14 @@ kbfunc_group_only(void *ctx, struct cargs *cargs) } 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) { group_toggle(ctx, cargs->flag); @@ -660,7 +679,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/menu.c b/menu.c index 43b5de8..2279f12 100644 --- a/menu.c +++ b/menu.c @@ -355,7 +355,7 @@ menu_draw(struct menu_ctx *mc, struct menu_q *menuq, struct menu_q *resultq) 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->geom.h = sc->xftfont->ascent + sc->xftfont->descent; mc->num = 1; TAILQ_FOREACH(mi, resultq, resultentry) { @@ -364,7 +364,7 @@ menu_draw(struct menu_ctx *mc, struct menu_q *menuq, struct menu_q *resultq) (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->geom.h += sc->xftfont->ascent + sc->xftfont->descent; mc->num++; } @@ -403,15 +403,15 @@ menu_draw(struct menu_ctx *mc, struct menu_q *menuq, struct menu_q *resultq) (const FcChar8*)mc->dispstr, strlen(mc->dispstr)); TAILQ_FOREACH(mi, resultq, resultentry) { - int y = n * (sc->xftfont->height + 1) + sc->xftfont->ascent + 1; + int y = n * (sc->xftfont->ascent + sc->xftfont->descent); /* Stop drawing when menu doesn't fit inside the screen. */ - if (mc->geom.y + y > area.h) + if (mc->geom.y + y >= area.h) break; XftDrawStringUtf8(mc->xftdraw, &sc->xftcolor[CWM_COLOR_MENU_FONT], sc->xftfont, - 0, y, + 0, y + sc->xftfont->ascent, (const FcChar8*)mi->print, strlen(mi->print)); n++; } @@ -425,7 +425,7 @@ menu_draw_entry(struct menu_ctx *mc, struct menu_q *resultq, { struct screen_ctx *sc = mc->sc; struct menu *mi; - int color, i = 1; + int color, i = 1, y; TAILQ_FOREACH(mi, resultq, resultentry) if (entry == i++) @@ -433,14 +433,13 @@ menu_draw_entry(struct menu_ctx *mc, struct menu_q *resultq, if (mi == NULL) return; + y = entry * (sc->xftfont->ascent + sc->xftfont->descent); color = (active) ? CWM_COLOR_MENU_FG : CWM_COLOR_MENU_BG; - XftDrawRect(mc->xftdraw, &sc->xftcolor[color], 0, - (sc->xftfont->height + 1) * entry, mc->geom.w, - (sc->xftfont->height + 1) + sc->xftfont->descent); + XftDrawRect(mc->xftdraw, &sc->xftcolor[color], 0, y, + mc->geom.w, sc->xftfont->ascent + sc->xftfont->descent); color = (active) ? CWM_COLOR_MENU_FONT_SEL : CWM_COLOR_MENU_FONT; XftDrawStringUtf8(mc->xftdraw, - &sc->xftcolor[color], sc->xftfont, - 0, (sc->xftfont->height + 1) * entry + sc->xftfont->ascent + 1, + &sc->xftcolor[color], sc->xftfont, 0, y + sc->xftfont->ascent, (const FcChar8*)mi->print, strlen(mi->print)); } @@ -487,11 +486,11 @@ menu_calc_entry(struct menu_ctx *mc, int x, int y) struct screen_ctx *sc = mc->sc; int entry; - entry = y / (sc->xftfont->height + 1); + entry = y / (sc->xftfont->ascent + sc->xftfont->descent); /* in bounds? */ if (x < 0 || x > mc->geom.w || y < 0 || - y > (sc->xftfont->height + 1) * mc->num || + y > (sc->xftfont->ascent + sc->xftfont->descent) * mc->num || entry < 0 || entry >= mc->num) entry = -1; diff --git a/parse.y b/parse.y index 0138fdb..a451da5 100644 --- a/parse.y +++ b/parse.y @@ -81,7 +81,7 @@ typedef struct { %token <v.string> STRING %token <v.number> NUMBER %type <v.number> yesno -%type <v.string> string +%type <v.string> string numberstring %% grammar : /* empty */ @@ -104,6 +104,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; } ; @@ -209,7 +220,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); @@ -219,7 +230,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); @@ -227,7 +238,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); @@ -237,7 +248,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); @@ -361,9 +372,9 @@ lookup(char *s) #define MAXPUSHBACK 128 -u_char *parsebuf; +char *parsebuf; int parseindex; -u_char pushback_buffer[MAXPUSHBACK]; +char pushback_buffer[MAXPUSHBACK]; int pushback_index = 0; int @@ -374,7 +385,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; @@ -383,7 +394,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) { @@ -424,10 +435,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 @@ -440,7 +451,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') { @@ -456,8 +467,8 @@ findeol(void) int yylex(void) { - u_char buf[8096]; - u_char *p; + char buf[8096]; + char *p; int quotec, next, c; int token; @@ -514,7 +525,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()); } @@ -537,8 +548,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); } @@ -553,7 +564,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 373ff71..e880e97 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); diff --git a/xutil.c b/xutil.c index 37af7db..230a2c5 100644 --- a/xutil.c +++ b/xutil.c @@ -73,8 +73,10 @@ xu_get_strprop(Window win, Atom atm, char **text) { *text = NULL; XGetTextProperty(X_Dpy, win, &prop, atm); - if (!prop.nitems) + if (!prop.nitems) { + XFree(prop.value); return 0; + } if (Xutf8TextPropertyToTextList(X_Dpy, &prop, &list, &nitems) == Success && nitems > 0 && *list) { |