X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=scrotwm.c;h=70aee79463e69f5fa3e9ce508b4c40f896ade0dd;hb=6392bc78077595ba35d63693a54ab66bb00e9077;hp=c86a6cc96c9033e12a0bd30d137c9ef409d6cc1d;hpb=a1937a73b7f51bf931a6316c669f8b51a89d796e;p=spectrwm.git diff --git a/scrotwm.c b/scrotwm.c index c86a6cc..70aee79 100644 --- a/scrotwm.c +++ b/scrotwm.c @@ -3,6 +3,7 @@ * Copyright (c) 2009 Marco Peereboom * Copyright (c) 2009 Ryan McBride * Copyright (c) 2009 Darrin Chandler + * Copyright (c) 2009 Pierre-Yves Ritschard * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -51,7 +52,7 @@ static const char *cvstag = "$scrotwm$"; -#define SWM_VERSION "0.9.1" +#define SWM_VERSION "0.9.5" #include #include @@ -107,6 +108,7 @@ static const char *cvstag = "$scrotwm$"; #define SWM_D_PROP 0x0080 #define SWM_D_CLASS 0x0100 #define SWM_D_KEY 0x0200 +#define SWM_D_QUIRK 0x0400 u_int32_t swm_debug = 0 | SWM_D_MISC @@ -119,6 +121,7 @@ u_int32_t swm_debug = 0 | SWM_D_PROP | SWM_D_CLASS | SWM_D_KEY + | SWM_D_QUIRK ; #else #define DPRINTF(x...) @@ -133,6 +136,7 @@ u_int32_t swm_debug = 0 #define SWM_PROPLEN (16) #define SWM_FUNCNAME_LEN (32) #define SWM_KEYS_LEN (255) +#define SWM_QUIRK_LEN (64) #define X(r) (r)->g.x #define Y(r) (r)->g.y #define WIDTH(r) (r)->g.w @@ -179,6 +183,8 @@ int bar_extra_running = 0; int bar_verbose = 1; int bar_height = 0; int clock_enabled = 1; +int title_name_enabled = 0; +int title_class_enabled = 0; pid_t bar_pid; GC bar_gc; XGCValues bar_gcv; @@ -317,6 +323,10 @@ void update_modkey(unsigned int); int bindmatch(const char *var, const char *name, unsigned int currmod, char *keystr, enum keyfuncid *kfid, unsigned int *mod, KeySym *ks); void setkeybinding(unsigned int mod, KeySym ks, enum keyfuncid kfid); +/* quirks */ +int quirkmatch(const char *var, const char *name, char *qstr, + char *qclass, char *qname, unsigned long *qquirk); +void setquirk(const char *class, const char *name, const int quirk); struct layout { void (*l_stack)(struct workspace *, struct swm_geometry *); @@ -408,30 +418,17 @@ union arg { /* quirks */ struct quirk { - char *class; - char *name; + char class[SWM_QUIRK_LEN]; + char name[SWM_QUIRK_LEN]; unsigned long quirk; #define SWM_Q_FLOAT (1<<0) /* float this window */ #define SWM_Q_TRANSSZ (1<<1) /* transiend window size too small */ #define SWM_Q_ANYWHERE (1<<2) /* don't position this window */ #define SWM_Q_XTERM_FONTADJ (1<<3) /* adjust xterm fonts when resizing */ #define SWM_Q_FULLSCREEN (1<<4) /* remove border */ -} quirks[] = { - { "MPlayer", "xv", SWM_Q_FLOAT | SWM_Q_FULLSCREEN }, - { "OpenOffice.org 2.4", "VCLSalFrame", SWM_Q_FLOAT }, - { "OpenOffice.org 3.0", "VCLSalFrame", SWM_Q_FLOAT }, - { "Firefox-bin", "firefox-bin", SWM_Q_TRANSSZ }, - { "Firefox", "Dialog", SWM_Q_FLOAT }, - { "Gimp", "gimp", SWM_Q_FLOAT | SWM_Q_ANYWHERE }, - { "XTerm", "xterm", SWM_Q_XTERM_FONTADJ }, - { "xine", "Xine Window", SWM_Q_FLOAT | SWM_Q_ANYWHERE }, - { "Xitk", "Xitk Combo", SWM_Q_FLOAT | SWM_Q_ANYWHERE }, - { "xine", "xine Panel", SWM_Q_FLOAT | SWM_Q_ANYWHERE }, - { "Xitk", "Xine Window", SWM_Q_FLOAT | SWM_Q_ANYWHERE }, - { "xine", "xine Video Fullscreen Window", SWM_Q_FULLSCREEN | SWM_Q_FLOAT }, - { "pcb", "pcb", SWM_Q_FLOAT }, - { NULL, NULL, 0}, }; +int quirks_size = 0, quirks_length = 0; +struct quirk *quirks = NULL; /* events */ void expose(XEvent *); @@ -574,6 +571,9 @@ conf_load(char *filename) unsigned int modkey = MODKEY, modmask; KeySym ks; enum keyfuncid kfid; + char class[SWM_QUIRK_LEN]; + char name[SWM_QUIRK_LEN]; + unsigned long quirk; DNPRINTF(SWM_D_MISC, "conf_load: filename %s\n", filename); @@ -665,6 +665,13 @@ conf_load(char *filename) goto bad; break; + case 'q': + if (!quirkmatch(var, "quirk", val, class, name, &quirk)) + setquirk(class, name, quirk); + else + goto bad; + break; + case 'r': if (!strncmp(var, "region", strlen("region"))) custom_region(val); @@ -688,6 +695,12 @@ conf_load(char *filename) case 't': if (!strncmp(var, "term_width", strlen("term_width"))) term_width = atoi(val); + else if (!strncmp(var, "title_class_enabled", + strlen("title_class_enabled"))) + title_class_enabled = atoi(val); + else if (!strncmp(var, "title_name_enabled", + strlen("title_name_enabled"))) + title_name_enabled = atoi(val); else goto bad; break; @@ -752,6 +765,8 @@ bar_update(void) char s[SWM_BAR_MAX]; char loc[SWM_BAR_MAX]; char *b; + XClassHint *xch; + Status status; if (bar_enabled == 0) return; @@ -777,10 +792,28 @@ bar_update(void) localtime_r(&tmt, &tm); strftime(s, sizeof s, "%a %b %d %R %Z %Y ", &tm); } + xch = NULL; + if ((title_name_enabled == 1 || title_class_enabled == 1) && + cur_focus != NULL) { + if ((xch = XAllocClassHint()) == NULL) + goto out; + status = XGetClassHint(display, cur_focus->id, xch); + if (status == BadWindow || status == BadAlloc) + goto out; + if (title_class_enabled) + strlcat(s, xch->res_class, sizeof s); + if (title_name_enabled && title_class_enabled) + strlcat(s, ":", sizeof s); + if (title_name_enabled) + strlcat(s, xch->res_name, sizeof s); + } +out: + if (xch) + XFree(xch); for (i = 0; i < ScreenCount(display); i++) { x = 1; TAILQ_FOREACH(r, &screens[i].rl, entry) { - snprintf(loc, sizeof loc, "%d:%d %s%s %s", + snprintf(loc, sizeof loc, "%d:%d %s %s %s", x++, r->ws->idx + 1, s, bar_ext, bar_vertext); bar_print(r, loc); } @@ -908,7 +941,8 @@ version(struct swm_region *r, union arg *args) { bar_version = !bar_version; if (bar_version) - strlcpy(bar_vertext, cvstag, sizeof bar_vertext); + snprintf(bar_vertext, sizeof bar_vertext, "Version: %s CVS: %s", + SWM_VERSION, cvstag); else strlcpy(bar_vertext, "", sizeof bar_vertext); bar_update(); @@ -1562,7 +1596,7 @@ stack_master(struct workspace *ws, struct swm_geometry *g, int rot, int flip) int w_inc = 1, h_inc, w_base = 1, h_base; int hrh, extra = 0, h_slice, last_h = 0; int split, colno, winno, mwin, msize, mscale; - int remain, missing, v_slice;; + int remain, missing, v_slice; unsigned int mask; DNPRINTF(SWM_D_STACK, "stack_master: workspace: %d\n rot=%s flip=%s", @@ -2244,6 +2278,8 @@ parsekeys(char *keystr, unsigned int currmod, unsigned int *mod, KeySym *ks) *mod |= Mod4Mask; else if (strncasecmp(name, "SHIFT", SWM_MODNAME_SIZE) == 0) *mod |= ShiftMask; + else if (strncasecmp(name, "CONTROL", SWM_MODNAME_SIZE) == 0) + *mod |= ControlMask; else { *ks = XStringToKeysym(name); XConvertCase(*ks, ks, &uks); @@ -2375,7 +2411,7 @@ setup_keys(void) setkeybinding(MODKEY, XK_j, kf_focus_next); setkeybinding(MODKEY, XK_k, kf_focus_prev); setkeybinding(MODKEY|ShiftMask, XK_j, kf_swap_next); - setkeybinding(MODKEY|ShiftMask, XK_k, kf_swap_next); + setkeybinding(MODKEY|ShiftMask, XK_k, kf_swap_prev); setkeybinding(MODKEY|ShiftMask, XK_Return, kf_spawn_term); setkeybinding(MODKEY, XK_p, kf_spawn_menu); setkeybinding(MODKEY|ShiftMask, XK_q, kf_quit); @@ -2546,6 +2582,176 @@ set_win_state(struct ws_win *win, long state) (unsigned char *)data, 2); } +const char *quirkname[] = { + "NONE", /* config string for "no value" */ + "FLOAT", + "TRANSSZ", + "ANYWHERE", + "XTERM_FONTADJ", + "FULLSCREEN", +}; + +#define SWM_Q_WS "\n| \t" +int +parsequirks(char *qstr, unsigned long *quirk) +{ + char *cp, *name; + int i; + if (quirk == NULL) + return (0); + cp = qstr; + *quirk = 0; + while ((name = strsep(&cp, SWM_Q_WS)) != NULL) { + if (cp) + cp += (long)strspn(cp, SWM_Q_WS); + for (i = 0; i < LENGTH(quirkname); i++) { + if (!strncasecmp(name, quirkname[i], SWM_QUIRK_LEN)) { + DNPRINTF(SWM_D_QUIRK, "parsequirks: %s\n", name); + if (i == 0) { + *quirk = 0; + return (1); + } + *quirk |= 1 << (i-1); + break; + } + } + if (i >= LENGTH(quirkname)) { + DNPRINTF(SWM_D_QUIRK, + "parsequirks: invalid quirk [%s]\n", name); + return (0); + } + } + return (1); +} +int +quirkmatch(const char *var, const char *name, char *qstr, char *qclass, + char *qname, unsigned long *qquirk) +{ + char *p; + int i; + char classname[SWM_QUIRK_LEN*2+1]; + DNPRINTF(SWM_D_QUIRK, "quirkmatch: in [%s]\n", var); + i = strncmp(var, name, 255); + if (qclass == NULL || qname == NULL || qquirk == NULL) + return (i); + *qquirk = 0; + *qclass = '\0'; + *qname = '\0'; + bzero(classname, LENGTH(classname)); + if (i <= 0) + return (i); + p = (char *)var + strlen(name); + if (*p++ != '[') + return (i); + i = 0; + while (isgraph(*p) && *p != ']' && i < LENGTH(classname)) + classname[i++] = *p++; + if (i >= LENGTH(classname) || *p != ']') + return (1); + if ((p = strchr(classname, ':')) == NULL || p-classname >= SWM_QUIRK_LEN) + return (1); + strlcpy(qclass, classname, p-classname+1); + strlcpy(qname, ++p, SWM_QUIRK_LEN); + for (p = qclass; *p && p-qclass < SWM_QUIRK_LEN; p++) + if (*p == '_') + *p = ' '; + for (p = qname; *p && p-qname < SWM_QUIRK_LEN; p++) + if (*p == '_') + *p = ' '; + i = (!parsequirks(qstr, qquirk)); + DNPRINTF(SWM_D_QUIRK, "quirkmatch: [%s][%s] %d\n", qclass, qname, i); + return (i); +} +void +setquirk(const char *class, const char *name, const int quirk) +{ + int i, j; + /* find existing */ + for (i = 0; i < quirks_length; i++) { + if (!strcmp(quirks[i].class, class) && + !strcmp(quirks[i].name, name)) { + if (!quirk) { + /* found: delete */ + DNPRINTF(SWM_D_QUIRK, + "setquirk: delete #%d %s:%s\n", + i, quirks[i].class, quirks[i].name); + j = quirks_length - 1; + if (i < j) + quirks[i] = quirks[j]; + quirks_length--; + return; + } else { + /* found: replace */ + DNPRINTF(SWM_D_QUIRK, + "setquirk: replace #%d %s:%s\n", + i, quirks[i].class, quirks[i].name); + strlcpy(quirks[i].class, class, + sizeof quirks->class); + strlcpy(quirks[i].name, name, + sizeof quirks->name); + quirks[i].quirk = quirk; + return; + } + } + } + if (!quirk) { + fprintf(stderr, + "error: setquirk: cannot find class/name combination"); + return; + } + /* not found: add */ + if (quirks_size == 0 || quirks == NULL) { + quirks_size = 4; + DNPRINTF(SWM_D_QUIRK, "setquirk: init list %d\n", quirks_size); + quirks = malloc((size_t)quirks_size * sizeof(struct quirk)); + if (!quirks) { + fprintf(stderr, "setquirk: malloc failed\n"); + perror(" failed"); + quit(NULL, NULL); + } + } else if (quirks_length == quirks_size) { + quirks_size *= 2; + DNPRINTF(SWM_D_QUIRK, "setquirk: grow list %d\n", quirks_size); + quirks = realloc(quirks, (size_t)quirks_size * sizeof(struct quirk)); + if (!quirks) { + fprintf(stderr, "setquirk: realloc failed\n"); + perror(" failed"); + quit(NULL, NULL); + } + } + if (quirks_length < quirks_size) { + DNPRINTF(SWM_D_QUIRK, "setquirk: add %d\n", quirks_length); + j = quirks_length++; + strlcpy(quirks[j].class, class, sizeof quirks->class); + strlcpy(quirks[j].name, name, sizeof quirks->name); + quirks[j].quirk = quirk; + } else { + fprintf(stderr, "quirks array problem?\n"); + if (!quirks) { + fprintf(stderr, "quirks array problem!\n"); + quit(NULL, NULL); + } + } +} + +void +setup_quirks(void) +{ + setquirk("MPlayer", "xv", SWM_Q_FLOAT | SWM_Q_FULLSCREEN); + setquirk("OpenOffice.org 2.4", "VCLSalFrame", SWM_Q_FLOAT); + setquirk("OpenOffice.org 3.0", "VCLSalFrame", SWM_Q_FLOAT); + setquirk("Firefox-bin", "firefox-bin", SWM_Q_TRANSSZ); + setquirk("Firefox", "Dialog", SWM_Q_FLOAT); + setquirk("Gimp", "gimp", SWM_Q_FLOAT | SWM_Q_ANYWHERE); + setquirk("XTerm", "xterm", SWM_Q_XTERM_FONTADJ); + setquirk("xine", "Xine Window", SWM_Q_FLOAT | SWM_Q_ANYWHERE); + setquirk("Xitk", "Xitk Combo", SWM_Q_FLOAT | SWM_Q_ANYWHERE); + setquirk("xine", "xine Panel", SWM_Q_FLOAT | SWM_Q_ANYWHERE); + setquirk("Xitk", "Xine Window", SWM_Q_FLOAT | SWM_Q_ANYWHERE); + setquirk("xine", "xine Video Fullscreen Window", SWM_Q_FULLSCREEN | SWM_Q_FLOAT); + setquirk("pcb", "pcb", SWM_Q_FLOAT); +} + struct ws_win * manage_window(Window id) { @@ -2631,8 +2837,7 @@ manage_window(Window id) if (XGetClassHint(display, win->id, &win->ch)) { DNPRINTF(SWM_D_CLASS, "class: %s name: %s\n", win->ch.res_class, win->ch.res_name); - for (i = 0; quirks[i].class != NULL && quirks[i].name != NULL && - quirks[i].quirk != 0; i++){ + for (i = 0; i < quirks_length; i++){ if (!strcmp(win->ch.res_class, quirks[i].class) && !strcmp(win->ch.res_name, quirks[i].name)) { DNPRINTF(SWM_D_CLASS, "found: %s name: %s\n", @@ -3317,6 +3522,7 @@ main(int argc, char *argv[]) setup_screens(); setup_keys(); + setup_quirks(); snprintf(conf, sizeof conf, "%s/.%s", pwd->pw_dir, SWM_CONF_FILE); if (stat(conf, &sb) != -1) {