X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;f=scrotwm.c;h=045bc531e82951857917b57e8e72b2cdf6371936;hb=0717d488f834b24b66509d2d4729049cf0498890;hp=c86a6cc96c9033e12a0bd30d137c9ef409d6cc1d;hpb=a1937a73b7f51bf931a6316c669f8b51a89d796e;p=spectrwm.git diff --git a/scrotwm.c b/scrotwm.c index c86a6cc..045bc53 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 @@ -161,6 +165,7 @@ int cycle_empty = 0; int cycle_visible = 0; int term_width = 0; int font_adjusted = 0; +unsigned int mod_key = MODKEY; /* dialog windows */ double dialog_ratio = .6; @@ -179,6 +184,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; @@ -312,11 +319,6 @@ void max_stack(struct workspace *, struct swm_geometry *); void grabbuttons(struct ws_win *, int); void new_region(struct swm_screen *, int, int, int, int); -void update_modkey(unsigned int); -/* user functions / key binding */ -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); struct layout { void (*l_stack)(struct workspace *, struct swm_geometry *); @@ -416,22 +418,9 @@ struct quirk { #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 *); @@ -535,176 +524,6 @@ custom_region(char *val) new_region(&screens[sidx], x, y, w, h); } -int -varmatch(char *var, char *name, int *index) -{ - char *p, buf[5]; - int i; - - i = strncmp(var, name, 255); - if (index == NULL) - return (i); - - *index = -1; - if (i <= 0) - return (i); - p = var + strlen(name); - if (*p++ != '[') - return (i); - bzero(buf, sizeof buf); - i = 0; - while (isdigit(*p) && i < sizeof buf) - buf[i++] = *p++; - if (i == 0 || i >= sizeof buf || *p != ']') - return (1); - *index = strtonum(buf, 0, 99, NULL); - return (0); -} - -/* conf file stuff */ -#define SWM_CONF_WS "\n= \t" -#define SWM_CONF_FILE "scrotwm.conf" -int -conf_load(char *filename) -{ - FILE *config; - char *line, *cp, *var, *val; - size_t len, lineno = 0; - int i, sc; - unsigned int modkey = MODKEY, modmask; - KeySym ks; - enum keyfuncid kfid; - - DNPRINTF(SWM_D_MISC, "conf_load: filename %s\n", filename); - - if (filename == NULL) - return (1); - - if ((config = fopen(filename, "r")) == NULL) - return (1); - - for (sc = ScreenCount(display);;) { - if ((line = fparseln(config, &len, &lineno, NULL, 0)) == NULL) - if (feof(config)) - break; - cp = line; - cp += (long)strspn(cp, SWM_CONF_WS); - if (cp[0] == '\0') { - /* empty line */ - free(line); - continue; - } - if ((var = strsep(&cp, SWM_CONF_WS)) == NULL || cp == NULL) - break; - cp += (long)strspn(cp, SWM_CONF_WS); - if ((val = strsep(&cp, SWM_CONF_WS)) == NULL) - break; - - DNPRINTF(SWM_D_MISC, "conf_load: %s=%s\n",var ,val); - switch (var[0]) { - case 'b': - if (!strncmp(var, "bar_enabled", strlen("bar_enabled"))) - bar_enabled = atoi(val); - else if (!varmatch(var, "bar_border", &i)) - setscreencolor(val, i, SWM_S_COLOR_BAR_BORDER); - else if (!varmatch(var, "bar_color", &i)) - setscreencolor(val, i, SWM_S_COLOR_BAR); - else if (!varmatch(var, "bar_font_color", &i)) - setscreencolor(val, i, SWM_S_COLOR_BAR_FONT); - else if (!strncmp(var, "bar_font", strlen("bar_font"))) - asprintf(&bar_fonts[0], "%s", val); - else if (!strncmp(var, "bar_action", strlen("bar_action"))) - asprintf(&bar_argv[0], "%s", val); - else if (!strncmp(var, "bar_delay", strlen("bar_delay"))) - bar_delay = atoi(val); - else if (!bindmatch(var, "bind", modkey, val, - &kfid, &modmask, &ks)) - setkeybinding(modmask, ks, kfid); - else - goto bad; - break; - - case 'c': - if (!strncmp(var, "clock_enabled", strlen("clock_enabled"))) - clock_enabled = atoi(val); - else if (!varmatch(var, "color_focus", &i)) - setscreencolor(val, i, SWM_S_COLOR_FOCUS); - else if (!varmatch(var, "color_unfocus", &i)) - setscreencolor(val, i, SWM_S_COLOR_UNFOCUS); - else if (!strncmp(var, "cycle_empty", strlen("cycle_empty"))) - cycle_visible = atoi(val); - else if (!strncmp(var, "cycle_visible", strlen("cycle_visible"))) - cycle_visible = atoi(val); - else - goto bad; - break; - - case 'd': - if (!strncmp(var, "dialog_ratio", - strlen("dialog_ratio"))) { - dialog_ratio = atof(val); - if (dialog_ratio > 1.0 || dialog_ratio <= .3) - dialog_ratio = .6; - } else - goto bad; - break; - - case 'm': - if (!strncmp(var, "modkey", strlen("modkey"))) { - modkey = MODKEY; - if (!strncmp(val, "Mod2", strlen("Mod2"))) - modkey = Mod2Mask; - else if (!strncmp(val, "Mod3", strlen("Mod3"))) - modkey = Mod3Mask; - else if (!strncmp(val, "Mod4", strlen("Mod4"))) - modkey = Mod4Mask; - else - modkey = Mod1Mask; - update_modkey(modkey); - } else - goto bad; - break; - - case 'r': - if (!strncmp(var, "region", strlen("region"))) - custom_region(val); - else - goto bad; - break; - - case 's': - if (!strncmp(var, "spawn_term", strlen("spawn_term"))) - asprintf(&spawn_term[0], "%s", val); - else if (!strncmp(var, "screenshot_enabled", - strlen("screenshot_enabled"))) - ss_enabled = atoi(val); - else if (!strncmp(var, "screenshot_app", - strlen("screenshot_app"))) - asprintf(&spawn_screenshot[0], "%s", val); - else - goto bad; - break; - - case 't': - if (!strncmp(var, "term_width", strlen("term_width"))) - term_width = atoi(val); - else - goto bad; - break; - - default: - goto bad; - } - free(line); - } - - fclose(config); - return (0); - -bad: - errx(1, "invalid conf file entry: %s=%s", var, val); -} - void socket_setnonblock(int fd) { @@ -747,11 +566,13 @@ bar_update(void) time_t tmt; struct tm tm; struct swm_region *r; - int i, x; + int i, x, do_class, do_name; size_t len; char s[SWM_BAR_MAX]; char loc[SWM_BAR_MAX]; char *b; + XClassHint *xch; + Status status; if (bar_enabled == 0) return; @@ -777,10 +598,30 @@ 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; + do_class = (title_class_enabled && xch->res_class != NULL); + do_name = (title_name_enabled && xch->res_name != NULL); + if (do_class) + strlcat(s, xch->res_class, sizeof s); + if (do_class && do_name) + strlcat(s, ":", sizeof s); + if (do_name) + 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 +749,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 +1404,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", @@ -2205,6 +2047,7 @@ update_modkey(unsigned int mod) { int i; + mod_key = mod; for (i = 0; i < keys_length; i++) if (keys[i].mod & ShiftMask) keys[i].mod = mod | ShiftMask; @@ -2244,6 +2087,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); @@ -2257,41 +2102,6 @@ parsekeys(char *keystr, unsigned int currmod, unsigned int *mod, KeySym *ks) } return (1); } -int -bindmatch(const char *var, const char *name, unsigned int currmod, char *keystr, - enum keyfuncid *kfid, unsigned int *mod, KeySym *ks) -{ - char *p; - int i; - char funcname[SWM_FUNCNAME_LEN]; - i = strncmp(var, name, 255); - if (kfid == NULL || mod == NULL || ks == NULL) - return (i); - *kfid = kf_invalid; - *mod = 0; - *ks = NoSymbol; - bzero(funcname, LENGTH(funcname)); - if (i <= 0) - return (i); - p = (char *)var + strlen(name); - if (*p++ != '[') - return (i); - i = 0; - while (isgraph(*p) && *p != ']' && i < LENGTH(funcname)) - funcname[i++] = *p++; - if (i >= LENGTH(funcname) || *p != ']') - return (1); - if (i == 0) - return (!parsekeys(keystr, currmod, mod, ks)); - for (*kfid = 0; *kfid < kf_invalid; (*kfid)++) { - if (strncasecmp(funcname, keyfuncs[*kfid].name, - SWM_FUNCNAME_LEN) == 0) { - return (!parsekeys(keystr, currmod, mod, ks)); - } - - } - return (1); -} void setkeybinding(unsigned int mod, KeySym ks, enum keyfuncid kfid) { @@ -2360,6 +2170,24 @@ setkeybinding(unsigned int mod, KeySym ks, enum keyfuncid kfid) } } } +int +setconfbinding(char *selector, char *value, int flags) +{ + enum keyfuncid kfid; + unsigned int mod; + KeySym ks; + for (kfid = 0; kfid < kf_invalid; (kfid)++) { + if (strncasecmp(selector, keyfuncs[kfid].name, + SWM_FUNCNAME_LEN) == 0) { + if (parsekeys(value, mod_key, &mod, &ks)) + setkeybinding(mod, ks, kfid); + else + return (0); + } + + } + return (1); +} void setup_keys(void) { @@ -2375,7 +2203,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 +2374,362 @@ 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", +}; + +/* SWM_Q_WS: retain '|' for back compat for now (2009-08-11) */ +#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); +} +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); + free(quirks[i].class); + free(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); + free(quirks[i].class); + free(quirks[i].name); + quirks[i].class = strdup(class); + quirks[i].name = strdup(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++; + quirks[j].class = strdup(class); + quirks[j].name = strdup(name); + quirks[j].quirk = quirk; + } else { + fprintf(stderr, "quirks array problem?\n"); + if (!quirks) { + fprintf(stderr, "quirks array problem!\n"); + quit(NULL, NULL); + } + } +} +int +setconfquirk(char *selector, char *value, int flags) +{ + char *cp, *class, *name; + int retval; + unsigned long quirks; + if (selector == NULL) + return (0); + if ((cp = strchr(selector, ':')) == NULL) + return (0); + *cp = '\0'; + class = selector; + name = cp + 1; + if ((retval = parsequirks(value, &quirks))) + setquirk(class, name, quirks); + return (retval); +} + +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); +} + +/* conf file stuff */ +#define SWM_CONF_FILE "scrotwm.conf" + +enum { SWM_S_BAR_DELAY, SWM_S_BAR_ENABLED, SWM_S_CLOCK_ENABLED, + SWM_S_CYCLE_EMPTY, SWM_S_CYCLE_VISIBLE, SWM_S_SS_ENABLED, + SWM_S_TERM_WIDTH, SWM_S_TITLE_CLASS_ENABLED, SWM_S_TITLE_NAME_ENABLED, + SWM_S_BAR_FONT, SWM_S_BAR_ACTION, SWM_S_SPAWN_TERM, SWM_S_SS_APP, + SWM_S_DIALOG_RATIO }; + +int +setconfvalue(char *selector, char *value, int flags) +{ + switch (flags) { + case SWM_S_BAR_DELAY: + bar_delay = atoi(value); + break; + case SWM_S_BAR_ENABLED: + bar_enabled = atoi(value); + break; + case SWM_S_CLOCK_ENABLED: + clock_enabled = atoi(value); + break; + case SWM_S_CYCLE_EMPTY: + cycle_empty = atoi(value); + break; + case SWM_S_CYCLE_VISIBLE: + cycle_visible = atoi(value); + break; + case SWM_S_SS_ENABLED: + ss_enabled = atoi(value); + break; + case SWM_S_TERM_WIDTH: + term_width = atoi(value); + break; + case SWM_S_TITLE_CLASS_ENABLED: + title_class_enabled = atoi(value); + break; + case SWM_S_TITLE_NAME_ENABLED: + title_name_enabled = atoi(value); + break; + case SWM_S_BAR_FONT: + bar_fonts[0] = strdup(value); + break; + case SWM_S_BAR_ACTION: + bar_argv[0] = strdup(value); + break; + case SWM_S_SPAWN_TERM: + spawn_term[0] = strdup(value); + break; + case SWM_S_SS_APP: + spawn_screenshot[0] = strdup(value); + break; + case SWM_S_DIALOG_RATIO: + dialog_ratio = atof(value); + if (dialog_ratio > 1.0 || dialog_ratio <= .3) + dialog_ratio = .6; + break; + default: + return (0); + } + return (1); +} + +int +setconfmodkey(char *selector, char *value, int flags) +{ + if (!strncasecmp(value, "Mod1", strlen("Mod1"))) + update_modkey(Mod1Mask); + else if (!strncasecmp(value, "Mod2", strlen("Mod2"))) + update_modkey(Mod2Mask); + else if (!strncasecmp(value, "Mod3", strlen("Mod3"))) + update_modkey(Mod3Mask); + else if (!strncasecmp(value, "Mod4", strlen("Mod4"))) + update_modkey(Mod4Mask); + else + return (0); + return (1); +} + +int +setconfcolor(char *selector, char *value, int flags) +{ + setscreencolor(value, ((selector == NULL)?-1:atoi(selector)), flags); + return (1); +} + +int +setconfregion(char *selector, char *value, int flags) +{ + custom_region(value); + return (1); +} + +/* config options */ +struct config_option { + char *optname; + int (*func)(char*, char*, int); + int funcflags; +}; +struct config_option configopt[] = { + { "bar_enabled", setconfvalue, SWM_S_BAR_ENABLED }, + { "bar_border", setconfcolor, SWM_S_COLOR_BAR_BORDER }, + { "bar_color", setconfcolor, SWM_S_COLOR_BAR }, + { "bar_font_color", setconfcolor, SWM_S_COLOR_BAR_FONT }, + { "bar_font", setconfvalue, SWM_S_BAR_FONT }, + { "bar_action", setconfvalue, SWM_S_BAR_ACTION }, + { "bar_delay", setconfvalue, SWM_S_BAR_DELAY }, + { "bind", setconfbinding, 0 }, + { "clock_enabled", setconfvalue, SWM_S_CLOCK_ENABLED }, + { "color_focus", setconfcolor, SWM_S_COLOR_FOCUS }, + { "color_unfocus", setconfcolor, SWM_S_COLOR_UNFOCUS }, + { "cycle_empty", setconfvalue, SWM_S_CYCLE_EMPTY }, + { "cycle_visible", setconfvalue, SWM_S_CYCLE_VISIBLE }, + { "dialog_ratio", setconfvalue, SWM_S_DIALOG_RATIO }, + { "modkey", setconfmodkey, 0 }, + { "quirk", setconfquirk, 0 }, + { "region", setconfregion, 0 }, + { "spawn_term", setconfvalue, SWM_S_SPAWN_TERM }, + { "screenshot_enabled", setconfvalue, SWM_S_SS_ENABLED }, + { "screenshot_app", setconfvalue, SWM_S_SS_APP }, + { "term_width", setconfvalue, SWM_S_TERM_WIDTH }, + { "title_class_enabled", setconfvalue, SWM_S_TITLE_CLASS_ENABLED }, + { "title_name_enabled", setconfvalue, SWM_S_TITLE_NAME_ENABLED } +}; + + +int +conf_load(char *filename) +{ + FILE *config; + char *line, *cp, *optsub, *optval; + size_t linelen, lineno = 0; + int wordlen, i, optind; + struct config_option *opt; + if (filename == NULL) + return (0); + if ((config = fopen(filename, "r")) == NULL) + return (0); + while (!feof(config)) { + if ((line = fparseln(config, &linelen, &lineno, NULL, 0)) + == NULL) { + if (ferror(config)) + err(1, "%s", filename); + else + continue; + } + cp = line; + cp += strspn(cp, " \t\n"); /* eat whitespace */ + if (cp[0] == '\0') { + /* empty line */ + free(line); + continue; + } + /* get config option */ + wordlen = strcspn(cp, "=[ \t\n"); + if (!wordlen) { + warnx("%s: line %zd: no option found", + filename, lineno); + return (0); + } + optind = -1; + for (i = 0; i < LENGTH(configopt); i++) { + opt = &configopt[i]; + if (!strncasecmp(cp, opt->optname, wordlen) && + strlen(opt->optname) == wordlen) { + optind = i; + break; + } + } + if (optind == -1) { + warnx("%s: line %zd: unknown option %.*s", + filename, lineno, wordlen, cp); + return (0); + } + cp += wordlen; + cp += strspn(cp, " \t\n"); /* eat whitespace */ + /* get [selector] if any */ + optsub = NULL; + if (*cp == '[') { + cp++; + wordlen = strcspn(cp, "]"); + if (!wordlen) { + warnx("%s: line %zd: syntax error", + filename, lineno); + return (0); + } + asprintf(&optsub, "%.*s", wordlen, cp); + cp += wordlen; + cp += strspn(cp, "] \t\n"); /* eat trailing */ + } + cp += strspn(cp, "= \t\n"); /* eat trailing */ + /* get RHS value */ + optval = strdup(cp); + /* call function to deal with it all */ + if (!configopt[optind].func(optsub, optval, + configopt[optind].funcflags)) + errx(1, "%s: line %zd: invalid data for %s", + filename, lineno, configopt[optind].optname); + free(optval); + free(optsub); + free(line); + } + return (1); +} + struct ws_win * manage_window(Window id) { @@ -2631,8 +2815,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 +3500,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) {