From 7b5a1d5df307a1721946688ac1be98026f64afcc Mon Sep 17 00:00:00 2001 From: Marco Peereboom Date: Wed, 22 Jun 2011 17:53:25 +0000 Subject: [PATCH 01/16] realloc cleanup from akfaew@jasminek.net tsk tsk dwc --- scrotwm.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/scrotwm.c b/scrotwm.c index 92ea40d..54503c6 100644 --- a/scrotwm.c +++ b/scrotwm.c @@ -3835,8 +3835,9 @@ setconfspawn(char *selector, char *value, int flags) cp += (long)strspn(cp, " \t"); if (strlen(word) > 0) { prog->argc++; - prog->argv = realloc(prog->argv, - prog->argc * sizeof(char *)); + if ((prog->argv = realloc(prog->argv, + prog->argc * sizeof(char *))) == NULL) + err(1, "setconfspawn: realloc"); if ((prog->argv[prog->argc - 1] = strdup(word)) == NULL) err(1, "setconfspawn: strdup"); } @@ -3983,7 +3984,7 @@ setkeybinding(unsigned int mod, KeySym ks, enum keyfuncid kfid, keys_size = 4; DNPRINTF(SWM_D_KEY, "setkeybinding: init list %d\n", keys_size); keys = malloc((size_t)keys_size * sizeof(struct key)); - if (!keys) { + if (keys == NULL) { fprintf(stderr, "malloc failed\n"); perror(" failed"); quit(NULL, NULL); @@ -3992,7 +3993,7 @@ setkeybinding(unsigned int mod, KeySym ks, enum keyfuncid kfid, keys_size *= 2; DNPRINTF(SWM_D_KEY, "setkeybinding: grow list %d\n", keys_size); keys = realloc(keys, (size_t)keys_size * sizeof(struct key)); - if (!keys) { + if (keys == NULL) { fprintf(stderr, "realloc failed\n"); perror(" failed"); quit(NULL, NULL); @@ -4008,7 +4009,7 @@ setkeybinding(unsigned int mod, KeySym ks, enum keyfuncid kfid, keys[j].spawn_name = strdupsafe(spawn_name); } else { fprintf(stderr, "keys array problem?\n"); - if (!keys) { + if (keys == NULL) { fprintf(stderr, "keys array problem\n"); quit(NULL, NULL); } @@ -4286,7 +4287,7 @@ setquirk(const char *class, const char *name, const int quirk) 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) { + if (quirks == NULL) { fprintf(stderr, "setquirk: malloc failed\n"); perror(" failed"); quit(NULL, NULL); @@ -4296,7 +4297,7 @@ setquirk(const char *class, const char *name, const int quirk) DNPRINTF(SWM_D_QUIRK, "setquirk: grow list %d\n", quirks_size); quirks = realloc(quirks, (size_t)quirks_size * sizeof(struct quirk)); - if (!quirks) { + if (quirks == NULL) { fprintf(stderr, "setquirk: realloc failed\n"); perror(" failed"); quit(NULL, NULL); @@ -4310,7 +4311,7 @@ setquirk(const char *class, const char *name, const int quirk) quirks[j].quirk = quirk; } else { fprintf(stderr, "quirks array problem?\n"); - if (!quirks) { + if (quirks == NULL) { fprintf(stderr, "quirks array problem!\n"); quit(NULL, NULL); } @@ -5881,6 +5882,8 @@ main(int argc, char *argv[]) if (cfile) conf_load(cfile); + custom_region("screen[1]:1280x1009+0+15"); + setup_ewmh(); /* set some values to work around bad programs */ workaround(); -- 1.7.10.4 From 871b3ea10a0299603aa5a05dae1011bc5dad415a Mon Sep 17 00:00:00 2001 From: Marco Peereboom Date: Wed, 22 Jun 2011 18:41:27 +0000 Subject: [PATCH 02/16] argh delete some stupid debug poop --- scrotwm.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/scrotwm.c b/scrotwm.c index 54503c6..5b00d29 100644 --- a/scrotwm.c +++ b/scrotwm.c @@ -5882,8 +5882,6 @@ main(int argc, char *argv[]) if (cfile) conf_load(cfile); - custom_region("screen[1]:1280x1009+0+15"); - setup_ewmh(); /* set some values to work around bad programs */ workaround(); -- 1.7.10.4 From e5d2c4266c0414aca0f06f8d65aef1d13142c8a2 Mon Sep 17 00:00:00 2001 From: Marco Peereboom Date: Thu, 23 Jun 2011 02:15:53 +0000 Subject: [PATCH 03/16] Add autorun to launch apps in workspaces and INITIAL start time and not at restart time. Currently it doesn't support arguments so you need a wrapper script for complicated stuff. sorry mcbride this can not be done using .xinitrc due to several chickens and eggs that are in the wrong order. This is FS#1 --- scrotwm.c | 143 +++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 126 insertions(+), 17 deletions(-) diff --git a/scrotwm.c b/scrotwm.c index 5b00d29..2a9550b 100644 --- a/scrotwm.c +++ b/scrotwm.c @@ -292,6 +292,15 @@ struct ws_win { }; TAILQ_HEAD(ws_win_list, ws_win); +/* pid goo */ +struct pid_e { + TAILQ_ENTRY(pid_e) entry; + long pid; + int ws; +}; +TAILQ_HEAD(pid_list, pid_e); +struct pid_list pidlist = TAILQ_HEAD_INITIALIZER(pidlist); + /* layout handlers */ void stack(void); void vertical_config(struct workspace *, int); @@ -1047,6 +1056,21 @@ sighdlr(int sig) errno = saved_errno; } +struct pid_e * +find_pid(long pid) +{ + struct pid_e *p = NULL; + + DNPRINTF(SWM_D_MISC, "find_pid: %lu\n", pid); + + TAILQ_FOREACH(p, &pidlist, entry) { + if (p->pid == pid) + return (p); + } + + return (NULL); +} + unsigned long name_to_color(char *colorname) { @@ -1687,7 +1711,7 @@ find_window(Window id) } void -spawn(struct swm_region *r, union arg *args, int close_fd) +spawn(int ws_idx, union arg *args, int close_fd) { int fd; char *ret = NULL; @@ -1699,7 +1723,7 @@ spawn(struct swm_region *r, union arg *args, int close_fd) setenv("LD_PRELOAD", SWM_LIB, 1); - if (asprintf(&ret, "%d", r->ws->idx) == -1) { + if (asprintf(&ret, "%d", ws_idx) == -1) { perror("_SWM_WS"); _exit(1); } @@ -1747,10 +1771,11 @@ spawnterm(struct swm_region *r, union arg *args) { DNPRINTF(SWM_D_MISC, "spawnterm\n"); - if (term_width) - setenv("_SWM_XTERM_FONTADJ", "", 1); - if (fork() == 0) - spawn(r, args, 1); + if (fork() == 0) { + if (term_width) + setenv("_SWM_XTERM_FONTADJ", "", 1); + spawn(r->ws->idx, args, 1); + } } void @@ -3678,7 +3703,7 @@ spawn_custom(struct swm_region *r, union arg *args, char *spawn_name) return; a.argv = real_args; if (fork() == 0) - spawn(r, &a, 1); + spawn(r->ws->idx, &a, 1); for (i = 0; i < spawn_argc; i++) free(real_args[i]); @@ -3714,7 +3739,7 @@ spawn_select(struct swm_region *r, union arg *args, char *spawn_name, int *pid) errx(1, "dup2"); close(select_list_pipe[1]); close(select_resp_pipe[0]); - spawn(r, &a, 0); + spawn(r->ws->idx, &a, 0); break; default: /* parent */ close(select_list_pipe[0]); @@ -4491,6 +4516,56 @@ setconfregion(char *selector, char *value, int flags) return (0); } +int +setautorun(char *selector, char *value, int flags) +{ + int ws_id; + char s[1024]; + union arg a; + char *real_args[] = { NULL, NULL }; + long pid; + struct pid_e *p; + + if (getenv("SWM_STARTED")) + return (0); + + bzero(s, sizeof s); + if (sscanf(value, "ws[%d]:%1023s", &ws_id, s) != 2) + errx(1, "invalid autorun entry, should be 'ws:command'\n"); + ws_id--; + if (ws_id < 0 || ws_id >= SWM_WS_MAX) + errx(1, "invalid workspace %d\n", ws_id + 1); + + /* + * This is a little intricate + * + * If the pid already exists we simply reuse it because it means it was + * used before AND not claimed by manage_window. We get away with + * altering it in the parent after INSERT because this can not be a race + */ + real_args[0] = s; + a.argv = real_args; /* XXX this sucks and should have args for real */ + if ((pid = fork()) == 0) { + spawn(ws_id, &a, 1); + /* NOTREACHED */ + _exit(1); + } + + /* parent */ + p = find_pid(pid); + if (p == NULL) { + p = calloc(1, sizeof *p); + if (p == NULL) + return (1); + TAILQ_INSERT_TAIL(&pidlist, p, entry); + } + + p->pid = pid; + p->ws = ws_id; + + return (0); +} + /* config options */ struct config_option { char *optname; @@ -4501,7 +4576,7 @@ struct config_option configopt[] = { { "bar_enabled", setconfvalue, SWM_S_BAR_ENABLED }, { "bar_at_bottom", setconfvalue, SWM_S_BAR_AT_BOTTOM }, { "bar_border", setconfcolor, SWM_S_COLOR_BAR_BORDER }, - { "bar_border_width", setconfvalue, SWM_S_BAR_BORDER_WIDTH }, + { "bar_border_width", setconfvalue, SWM_S_BAR_BORDER_WIDTH }, { "bar_color", setconfcolor, SWM_S_COLOR_BAR }, { "bar_font_color", setconfcolor, SWM_S_COLOR_BAR_FONT }, { "bar_font", setconfvalue, SWM_S_BAR_FONT }, @@ -4527,9 +4602,10 @@ struct config_option configopt[] = { { "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 }, - { "focus_mode", setconfvalue, SWM_S_FOCUS_MODE }, - { "disable_border", setconfvalue, SWM_S_DISABLE_BORDER }, - { "border_width", setconfvalue, SWM_S_BORDER_WIDTH }, + { "focus_mode", setconfvalue, SWM_S_FOCUS_MODE }, + { "disable_border", setconfvalue, SWM_S_DISABLE_BORDER }, + { "border_width", setconfvalue, SWM_S_BORDER_WIDTH }, + { "autorun", setautorun, 0 }, }; @@ -4678,6 +4754,29 @@ set_child_transient(struct ws_win *win, Window *trans) XFree(wmh); } +long +window_get_pid(Window win) +{ + Atom actual_type_return; + int actual_format_return = 0; + unsigned long nitems_return = 0; + unsigned long bytes_after_return = 0; + long *pid = 0; + long ret = 0; + + if (XGetWindowProperty(display, win, + XInternAtom(display, "_NET_WM_PID", False), 0, 1, False, + XA_CARDINAL, &actual_type_return, &actual_format_return, + &nitems_return, &bytes_after_return, + (unsigned char**)(void*)&pid) != Success) + return (0); + + ret = pid[0]; + XFree(pid); + + return (ret); +} + struct ws_win * manage_window(Window id) { @@ -4693,6 +4792,7 @@ manage_window(Window id) long mask; const char *errstr; XWindowChanges wc; + struct pid_e *p; if ((win = find_window(id)) != NULL) return (win); /* already being managed */ @@ -4717,11 +4817,15 @@ manage_window(Window id) win->id = id; + /* see if we need to override the workspace */ + p = find_pid(window_get_pid(id)); + /* Get all the window data in one shot */ ws_idx_atom = XInternAtom(display, "_SWM_WS", False); - if (ws_idx_atom) + if (ws_idx_atom) { XGetWindowProperty(display, id, ws_idx_atom, 0, SWM_PROPLEN, False, XA_STRING, &type, &format, &nitems, &bytes, &prop); + } XGetWindowAttributes(display, id, &win->wa); XGetWMNormalHints(display, id, &win->sh, &mask); win->hints = XGetWMHints(display, id); @@ -4753,7 +4857,12 @@ manage_window(Window id) * transient, * put it in the same workspace */ r = root_to_region(win->wa.root); - if (prop && win->transient == 0) { + if (p) { + ws = &r->s->ws[p->ws]; + TAILQ_REMOVE(&pidlist, p, entry); + free(p); + p = NULL; + } else if (prop && win->transient == 0) { DNPRINTF(SWM_D_PROP, "got property _SWM_WS=%s\n", prop); ws_idx = strtonum(prop, 0, 9, &errstr); if (errstr) { @@ -5702,14 +5811,11 @@ setup_screens(void) int i, j, k; int errorbase, major, minor; struct workspace *ws; - int ws_idx_atom; if ((screens = calloc(ScreenCount(display), sizeof(struct swm_screen))) == NULL) errx(1, "calloc: screens"); - ws_idx_atom = XInternAtom(display, "_SWM_WS", False); - /* initial Xrandr setup */ xrandr_support = XRRQueryExtension(display, &xrandr_eventbase, &errorbase); @@ -5889,6 +5995,9 @@ main(int argc, char *argv[]) /* grab existing windows (before we build the bars) */ grab_windows(); + if (getenv("SWM_STARTED") == NULL) + setenv("SWM_STARTED", "YES", 1); + /* setup all bars */ for (i = 0; i < ScreenCount(display); i++) TAILQ_FOREACH(r, &screens[i].rl, entry) { -- 1.7.10.4 From d4b314be4c52b7c1de2ad3bc84937fd4455bca50 Mon Sep 17 00:00:00 2001 From: Marco Peereboom Date: Thu, 23 Jun 2011 02:22:18 +0000 Subject: [PATCH 04/16] document autorun --- scrotwm.1 | 6 ++++++ scrotwm.conf | 3 +++ 2 files changed, 9 insertions(+) diff --git a/scrotwm.1 b/scrotwm.1 index 25762da..39c7a41 100644 --- a/scrotwm.1 +++ b/scrotwm.1 @@ -79,6 +79,12 @@ Enabling or disabling an option is done by using 1 or 0 respectively. The file supports the following keywords: .Pp .Bl -tag -width "title_class_enabledXXX" -offset indent -compact +.It Cm autorun +Launch an application in a specified workspace at start-of-day. +Currently this option does not support arguments so if those are required one +must use a wrapper script. +Defined in the format ws[]:application, e.g. ws[2]:xterm launches and +xterm in workspace 2 .It Cm color_focus Border color of the currently focussed window. .It Cm color_unfocus diff --git a/scrotwm.conf b/scrotwm.conf index ede67d9..e0eb51e 100644 --- a/scrotwm.conf +++ b/scrotwm.conf @@ -41,6 +41,9 @@ dialog_ratio = 0.6 # region = screen[1]:1280x1024+0+0 # region = screen[1]:1280x1024+1280+0 +# Launch applications in a workspace of choice +# autorun = ws[1]:xterm + # mod key, (windows key is Mod4) (apple key on OSX is Mod2) # modkey = Mod1 -- 1.7.10.4 From 8cc48b14f9a97003819c9b3ca086a7a746b34fe2 Mon Sep 17 00:00:00 2001 From: Marco Peereboom Date: Thu, 23 Jun 2011 03:05:04 +0000 Subject: [PATCH 05/16] add scrotwm.desktop --- release.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release.sh b/release.sh index 98ec09a..d2048eb 100644 --- a/release.sh +++ b/release.sh @@ -4,7 +4,7 @@ PREFIX=scrotwm- DIRS="lib linux osx" -FILES="Makefile baraction.sh initscreen.sh screenshot.sh scrotwm.1 scrotwm_es.1 scrotwm_it.1 scrotwm_pt.1 scrotwm_ru.1 scrotwm.c scrotwm.conf linux/Makefile linux/linux.c linux/util.h lib/Makefile lib/shlib_version lib/swm_hack.c osx/Makefile osx/osx.h osx/osx.c" +FILES="Makefile baraction.sh initscreen.sh screenshot.sh scrotwm.1 scrotwm_es.1 scrotwm_it.1 scrotwm_pt.1 scrotwm_ru.1 scrotwm.c scrotwm.conf linux/Makefile linux/linux.c linux/util.h linux/scrotwm.desktop lib/Makefile lib/shlib_version lib/swm_hack.c osx/Makefile osx/osx.h osx/osx.c" if [ -z "$1" ]; then echo "usage: release.sh " -- 1.7.10.4 From 5f8a010ab295ed72a1f432a3c47fe804dc87e76d Mon Sep 17 00:00:00 2001 From: Marco Peereboom Date: Thu, 23 Jun 2011 03:05:19 +0000 Subject: [PATCH 06/16] bump version --- scrotwm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scrotwm.c b/scrotwm.c index 2a9550b..2d10ceb 100644 --- a/scrotwm.c +++ b/scrotwm.c @@ -54,7 +54,7 @@ static const char *cvstag = "$scrotwm$"; -#define SWM_VERSION "0.9.30" +#define SWM_VERSION "0.9.31" #include #include -- 1.7.10.4 From 948314b98e7b6eccd9e2b99294190101b043c909 Mon Sep 17 00:00:00 2001 From: Marco Peereboom Date: Thu, 23 Jun 2011 11:37:16 +0000 Subject: [PATCH 07/16] fix crash on apps that dont play nice with NET_WM_PID. --- scrotwm.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/scrotwm.c b/scrotwm.c index 2d10ceb..499ee6d 100644 --- a/scrotwm.c +++ b/scrotwm.c @@ -1063,6 +1063,9 @@ find_pid(long pid) DNPRINTF(SWM_D_MISC, "find_pid: %lu\n", pid); + if (pid == 0) + return (NULL); + TAILQ_FOREACH(p, &pidlist, entry) { if (p->pid == pid) return (p); @@ -4761,7 +4764,7 @@ window_get_pid(Window win) int actual_format_return = 0; unsigned long nitems_return = 0; unsigned long bytes_after_return = 0; - long *pid = 0; + long *pid = NULL; long ret = 0; if (XGetWindowProperty(display, win, @@ -4770,8 +4773,12 @@ window_get_pid(Window win) &nitems_return, &bytes_after_return, (unsigned char**)(void*)&pid) != Success) return (0); + if (actual_type_return != XA_CARDINAL) + return (0); + if (pid == NULL) + return (0); - ret = pid[0]; + ret = *pid; XFree(pid); return (ret); -- 1.7.10.4 From f5c5fd74a8223aee7f49ece1db020d7495296047 Mon Sep 17 00:00:00 2001 From: Marco Peereboom Date: Thu, 23 Jun 2011 12:13:19 +0000 Subject: [PATCH 08/16] work around apps that dont set _NET_WM_PID and roll new version number --- scrotwm.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/scrotwm.c b/scrotwm.c index 499ee6d..4e9ecfd 100644 --- a/scrotwm.c +++ b/scrotwm.c @@ -54,7 +54,7 @@ static const char *cvstag = "$scrotwm$"; -#define SWM_VERSION "0.9.31" +#define SWM_VERSION "0.9.32" #include #include @@ -4766,22 +4766,41 @@ window_get_pid(Window win) unsigned long bytes_after_return = 0; long *pid = NULL; long ret = 0; + const char *errstr; + unsigned char *prop = NULL; if (XGetWindowProperty(display, win, XInternAtom(display, "_NET_WM_PID", False), 0, 1, False, XA_CARDINAL, &actual_type_return, &actual_format_return, &nitems_return, &bytes_after_return, (unsigned char**)(void*)&pid) != Success) - return (0); + goto tryharder; if (actual_type_return != XA_CARDINAL) - return (0); + goto tryharder; if (pid == NULL) - return (0); + goto tryharder; ret = *pid; XFree(pid); return (ret); + +tryharder: + if (XGetWindowProperty(display, win, + XInternAtom(display, "_SWM_PID", False), 0, SWM_PROPLEN, False, + XA_STRING, &actual_type_return, &actual_format_return, + &nitems_return, &bytes_after_return, &prop) != Success) + return (0); + if (actual_type_return != XA_STRING) + return (0); + if (prop == NULL) + return (0); + + ret = strtonum(prop, 0, UINT_MAX, &errstr); + /* ignore error because strtonum returns 0 anyway */ + XFree(prop); + + return (ret); } struct ws_win * -- 1.7.10.4 From c2adf746f6c01b3d919f9505c67bc7526f39e3db Mon Sep 17 00:00:00 2001 From: Marco Peereboom Date: Thu, 23 Jun 2011 16:31:54 +0000 Subject: [PATCH 09/16] add arguments to autorun, from akfaew@jasminek.net --- scrotwm.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/scrotwm.c b/scrotwm.c index 4e9ecfd..2ce3b49 100644 --- a/scrotwm.c +++ b/scrotwm.c @@ -4524,8 +4524,9 @@ setautorun(char *selector, char *value, int flags) { int ws_id; char s[1024]; + char *ap, *sp = s; union arg a; - char *real_args[] = { NULL, NULL }; + int argc = 0; long pid; struct pid_e *p; @@ -4533,7 +4534,7 @@ setautorun(char *selector, char *value, int flags) return (0); bzero(s, sizeof s); - if (sscanf(value, "ws[%d]:%1023s", &ws_id, s) != 2) + if (sscanf(value, "ws[%d]:%1023c", &ws_id, s) != 2) errx(1, "invalid autorun entry, should be 'ws:command'\n"); ws_id--; if (ws_id < 0 || ws_id >= SWM_WS_MAX) @@ -4546,13 +4547,27 @@ setautorun(char *selector, char *value, int flags) * used before AND not claimed by manage_window. We get away with * altering it in the parent after INSERT because this can not be a race */ - real_args[0] = s; - a.argv = real_args; /* XXX this sucks and should have args for real */ + a.argv = NULL; + while ((ap = strsep(&sp, " \t")) != NULL) { + if (*ap == '\0') + continue; + DNPRINTF(SWM_D_SPAWN, "setautorun: arg [%s]\n", ap); + argc++; + if ((a.argv = realloc(a.argv, argc * sizeof(char *))) == NULL) + err(1, "setautorun: realloc"); + a.argv[argc - 1] = ap; + } + + if ((a.argv = realloc(a.argv, (argc + 1) * sizeof(char *))) == NULL) + err(1, "setautorun: realloc"); + a.argv[argc] = NULL; + if ((pid = fork()) == 0) { spawn(ws_id, &a, 1); /* NOTREACHED */ _exit(1); } + free(a.argv); /* parent */ p = find_pid(pid); -- 1.7.10.4 From 86d17a103836ff75bb8cf2db7241c05245c95950 Mon Sep 17 00:00:00 2001 From: Marco Peereboom Date: Thu, 23 Jun 2011 16:34:00 +0000 Subject: [PATCH 10/16] remove args constraint and add an example of args in conf file --- scrotwm.1 | 2 -- scrotwm.conf | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/scrotwm.1 b/scrotwm.1 index 39c7a41..2e5df00 100644 --- a/scrotwm.1 +++ b/scrotwm.1 @@ -81,8 +81,6 @@ The file supports the following keywords: .Bl -tag -width "title_class_enabledXXX" -offset indent -compact .It Cm autorun Launch an application in a specified workspace at start-of-day. -Currently this option does not support arguments so if those are required one -must use a wrapper script. Defined in the format ws[]:application, e.g. ws[2]:xterm launches and xterm in workspace 2 .It Cm color_focus diff --git a/scrotwm.conf b/scrotwm.conf index e0eb51e..e5164e6 100644 --- a/scrotwm.conf +++ b/scrotwm.conf @@ -43,6 +43,7 @@ dialog_ratio = 0.6 # Launch applications in a workspace of choice # autorun = ws[1]:xterm +# autorun = ws[2]:xxxterm http://www.openbsd.org # mod key, (windows key is Mod4) (apple key on OSX is Mod2) # modkey = Mod1 -- 1.7.10.4 From 2a8d7bafe32519fac1ca81604a625199f21b3ad4 Mon Sep 17 00:00:00 2001 From: Marco Peereboom Date: Thu, 23 Jun 2011 17:52:39 +0000 Subject: [PATCH 11/16] add initial stack mode at start-of-day. this really could use some percentage value to size the master area. --- scrotwm.1 | 10 ++++++++++ scrotwm.c | 49 +++++++++++++++++++++++++++++++++++++++++++------ scrotwm.conf | 5 +++++ 3 files changed, 58 insertions(+), 6 deletions(-) diff --git a/scrotwm.1 b/scrotwm.1 index 2e5df00..9640322 100644 --- a/scrotwm.1 +++ b/scrotwm.1 @@ -120,6 +120,16 @@ so a custom clock could be used in the bar_action script. Some applications have dialogue windows that are too small to be useful. This ratio is the screen size to what they will be resized. For example, 0.6 is 60% of the physical screen size. +.It Cm layout +select layout to use at start-of-day. +Defined in the format ws[]:, e.g. ws[2]:horizontal sets worskspace +2 to the horizontal stack mode. +This setting is not retained at restart. +Possible values are +.Pa vertical , +.Pa horizontal +and +.Pa fullscreen . .It Cm region Allocates a custom region, removing any autodetected regions which occupy the same space on the screen. diff --git a/scrotwm.c b/scrotwm.c index 2ce3b49..a1f1c0a 100644 --- a/scrotwm.c +++ b/scrotwm.c @@ -332,8 +332,10 @@ struct layout { { NULL, NULL, 0, NULL }, }; -/* position of max_stack mode in the layouts array */ -#define SWM_MAX_STACK 2 +/* position of max_stack mode in the layouts array, index into layouts! */ +#define SWM_V_STACK (0) +#define SWM_H_STACK (1) +#define SWM_MAX_STACK (2) #define SWM_H_SLICE (32) #define SWM_V_SLICE (32) @@ -4535,10 +4537,10 @@ setautorun(char *selector, char *value, int flags) bzero(s, sizeof s); if (sscanf(value, "ws[%d]:%1023c", &ws_id, s) != 2) - errx(1, "invalid autorun entry, should be 'ws:command'\n"); + errx(1, "invalid autorun entry, should be 'ws[]:command'\n"); ws_id--; if (ws_id < 0 || ws_id >= SWM_WS_MAX) - errx(1, "invalid workspace %d\n", ws_id + 1); + errx(1, "autorun: invalid workspace %d\n", ws_id + 1); /* * This is a little intricate @@ -4584,11 +4586,45 @@ setautorun(char *selector, char *value, int flags) return (0); } +int +setlayout(char *selector, char *value, int flags) +{ + int ws_id, st, i; + char s[1024]; + struct workspace *ws; + + if (getenv("SWM_STARTED")) + return (0); + + bzero(s, sizeof s); + if (sscanf(value, "ws[%d]:%1023c", &ws_id, s) != 2) + errx(1, "invalid layout entry, should be 'ws[]:'\n"); + ws_id--; + if (ws_id < 0 || ws_id >= SWM_WS_MAX) + errx(1, "layout: invalid workspace %d\n", ws_id + 1); + + if (!strcasecmp(s, "vertical")) + st = SWM_V_STACK; + else if (!strcasecmp(s, "horizontal")) + st = SWM_H_STACK; + else if (!strcasecmp(s, "fullscreen")) + st = SWM_MAX_STACK; + else + errx(1, "invalid layout entry, should be 'ws[]:'\n"); + + for (i = 0; i < ScreenCount(display); i++) { + ws = (struct workspace *)&screens[i].ws; + ws[ws_id].cur_layout = &layouts[st]; + } + + return (0); +} + /* config options */ struct config_option { char *optname; - int (*func)(char*, char*, int); - int funcflags; + int (*func)(char*, char*, int); + int funcflags; }; struct config_option configopt[] = { { "bar_enabled", setconfvalue, SWM_S_BAR_ENABLED }, @@ -4624,6 +4660,7 @@ struct config_option configopt[] = { { "disable_border", setconfvalue, SWM_S_DISABLE_BORDER }, { "border_width", setconfvalue, SWM_S_BORDER_WIDTH }, { "autorun", setautorun, 0 }, + { "layout", setlayout, 0 }, }; diff --git a/scrotwm.conf b/scrotwm.conf index e5164e6..09741b5 100644 --- a/scrotwm.conf +++ b/scrotwm.conf @@ -45,6 +45,11 @@ dialog_ratio = 0.6 # autorun = ws[1]:xterm # autorun = ws[2]:xxxterm http://www.openbsd.org +# workspace layout +# layout = ws[1]:vertical +# layout = ws[2]:horizontal +# layout = ws[3]:fullscreen + # mod key, (windows key is Mod4) (apple key on OSX is Mod2) # modkey = Mod1 -- 1.7.10.4 From 014589e60503fee99276da4252258e553d62b055 Mon Sep 17 00:00:00 2001 From: Marco Peereboom Date: Thu, 23 Jun 2011 18:56:39 +0000 Subject: [PATCH 12/16] Make layout fancier by adding master_grow, master_shrink, master_add, master_del, stack_inc and stack_del to the format string. --- scrotwm.1 | 24 ++++++++++++++++++++---- scrotwm.c | 29 +++++++++++++++++++++++++++-- scrotwm.conf | 6 +++--- 3 files changed, 50 insertions(+), 9 deletions(-) diff --git a/scrotwm.1 b/scrotwm.1 index 9640322..07a3c25 100644 --- a/scrotwm.1 +++ b/scrotwm.1 @@ -122,14 +122,30 @@ This ratio is the screen size to what they will be resized. For example, 0.6 is 60% of the physical screen size. .It Cm layout select layout to use at start-of-day. -Defined in the format ws[]:, e.g. ws[2]:horizontal sets worskspace -2 to the horizontal stack mode. -This setting is not retained at restart. -Possible values are +Defined in the format ws[idx]:master_grow:master_add:stack_inc:layout, e.g. +ws[2]:-4:0:1:horizontal sets worskspace 2 to the horizontal stack mode and +shrinks the master area by 4 ticks and adds one window to the stack. +Possible layout values are .Pa vertical , .Pa horizontal and .Pa fullscreen . +.Pp +See +.Pa master_grow , +.Pa master_shrink , +.Pa master_add , +.Pa master_del , +.Pa stack_inc , +and +.Pa stack_del +for more information. +Note that the stacking options are complicated and have side-effects. +One should familiarize oneself with these commands before experimenting with the +.Pa layout +option. +.Pp +This setting is not retained at restart. .It Cm region Allocates a custom region, removing any autodetected regions which occupy the same space on the screen. diff --git a/scrotwm.c b/scrotwm.c index a1f1c0a..3b7bfce 100644 --- a/scrotwm.c +++ b/scrotwm.c @@ -4589,7 +4589,7 @@ setautorun(char *selector, char *value, int flags) int setlayout(char *selector, char *value, int flags) { - int ws_id, st, i; + int ws_id, st, i, x, mg, ma, si; char s[1024]; struct workspace *ws; @@ -4597,7 +4597,8 @@ setlayout(char *selector, char *value, int flags) return (0); bzero(s, sizeof s); - if (sscanf(value, "ws[%d]:%1023c", &ws_id, s) != 2) + if (sscanf(value, "ws[%d]:%d:%d:%d:%1023c", + &ws_id, &mg, &ma, &si, s) != 5) errx(1, "invalid layout entry, should be 'ws[]:'\n"); ws_id--; if (ws_id < 0 || ws_id >= SWM_WS_MAX) @@ -4615,6 +4616,30 @@ setlayout(char *selector, char *value, int flags) for (i = 0; i < ScreenCount(display); i++) { ws = (struct workspace *)&screens[i].ws; ws[ws_id].cur_layout = &layouts[st]; + if (st == SWM_MAX_STACK) + continue; + + /* master grow */ + for (x = 0; x < abs(mg); x++) { + ws[ws_id].cur_layout->l_config(&ws[ws_id], + mg >= 0 ? SWM_ARG_ID_MASTERGROW : + SWM_ARG_ID_MASTERSHRINK); + stack(); + } + /* master add */ + for (x = 0; x < abs(ma); x++) { + ws[ws_id].cur_layout->l_config(&ws[ws_id], + ma >= 0 ? SWM_ARG_ID_MASTERADD : + SWM_ARG_ID_MASTERDEL); + stack(); + } + /* stack inc */ + for (x = 0; x < abs(si); x++) { + ws[ws_id].cur_layout->l_config(&ws[ws_id], + si >= 0 ? SWM_ARG_ID_STACKINC : + SWM_ARG_ID_STACKDEC); + stack(); + } } return (0); diff --git a/scrotwm.conf b/scrotwm.conf index 09741b5..f10abc5 100644 --- a/scrotwm.conf +++ b/scrotwm.conf @@ -46,9 +46,9 @@ dialog_ratio = 0.6 # autorun = ws[2]:xxxterm http://www.openbsd.org # workspace layout -# layout = ws[1]:vertical -# layout = ws[2]:horizontal -# layout = ws[3]:fullscreen +# layout = ws[1]:4:0:0:vertical +# layout = ws[2]:0:0:0:horizontal +# layout = ws[3]:0:0:0:fullscreen # mod key, (windows key is Mod4) (apple key on OSX is Mod2) # modkey = Mod1 -- 1.7.10.4 From cbd90e50cdc4b29792a3b6a3d965d031afa9ac57 Mon Sep 17 00:00:00 2001 From: Marco Peereboom Date: Fri, 24 Jun 2011 16:53:40 +0000 Subject: [PATCH 13/16] bring back old tiling behavior where floating windows stay always on top. Add key stroke to toggle this behavior per workspace and add it to the layout entry in the configuration file. While here add iconify and uniconify key bindings in config file. requested by many. --- scrotwm.1 | 4 ++++ scrotwm.c | 37 ++++++++++++++++++++++++++++++------- scrotwm.conf | 9 ++++++--- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/scrotwm.1 b/scrotwm.1 index 07a3c25..90d4d20 100644 --- a/scrotwm.1 +++ b/scrotwm.1 @@ -390,6 +390,8 @@ initscr iconify .It Cm M-S-w uniconify +.It Cm M-S-r +toggle always_raised .El .Pp The action names and descriptions are listed below: @@ -495,6 +497,8 @@ above) Minimize (unmap) currently focused window. .It Cm uniconify Maximize (map) window returned by dmenu selection. +.It Cm always_raise +When set tiled windows are allowed to obscure floating windows. .El .Pp Custom bindings in the configuration file are specified as follows: diff --git a/scrotwm.c b/scrotwm.c index 3b7bfce..10806c9 100644 --- a/scrotwm.c +++ b/scrotwm.c @@ -343,6 +343,7 @@ struct layout { /* define work spaces */ struct workspace { int idx; /* workspace index */ + int always_raise; /* raise windows on focus */ struct layout *cur_layout; /* current layout handlers */ struct ws_win *focus; /* may be NULL */ struct ws_win *focus_prev; /* may be NULL */ @@ -1959,11 +1960,11 @@ focus_win(struct ws_win *win) if (win->java == 0) XSetInputFocus(display, win->id, RevertToParent, CurrentTime); - XMapRaised(display, win->id); grabbuttons(win, 1); XSetWindowBorder(display, win->id, win->ws->r->s->c[SWM_S_COLOR_FOCUS].color); - if (win->ws->cur_layout->flags & SWM_L_MAPONFOCUS) + if (win->ws->cur_layout->flags & SWM_L_MAPONFOCUS || + win->ws->always_raise) XMapRaised(display, win->id); XChangeProperty(display, win->s->root, @@ -3002,6 +3003,19 @@ send_to_ws(struct swm_region *r, union arg *args) } void +raise_toggle(struct swm_region *r, union arg *args) +{ + if (r && r->ws == NULL) + return; + + r->ws->always_raise = !r->ws->always_raise; + + /* bring floaters back to top */ + if (r->ws->always_raise == 0) + stack(); +} + +void iconify(struct swm_region *r, union arg *args) { union arg a; @@ -3486,6 +3500,7 @@ enum keyfuncid { kf_spawn_custom, kf_iconify, kf_uniconify, + kf_raise_toggle, kf_dumpwins, /* MUST BE LAST */ kf_invalid }; @@ -3562,6 +3577,7 @@ struct keyfunc { { "spawn_custom", dummykeyfunc, {0} }, { "iconify", iconify, {0} }, { "uniconify", uniconify, {0} }, + { "raise_toggle", raise_toggle, {0} }, { "dumpwins", dumpwins, {0} }, /* MUST BE LAST */ { "invalid key func", NULL, {0} }, }; @@ -4153,6 +4169,7 @@ setup_keys(void) setkeybinding(MODKEY|ShiftMask, XK_i, kf_spawn_custom, "initscr"); setkeybinding(MODKEY, XK_w, kf_iconify, NULL); setkeybinding(MODKEY|ShiftMask, XK_w, kf_uniconify, NULL); + setkeybinding(MODKEY|ShiftMask, XK_r, kf_raise_toggle,NULL); #ifdef SWM_DEBUG setkeybinding(MODKEY|ShiftMask, XK_d, kf_dumpwins, NULL); #endif @@ -4589,7 +4606,7 @@ setautorun(char *selector, char *value, int flags) int setlayout(char *selector, char *value, int flags) { - int ws_id, st, i, x, mg, ma, si; + int ws_id, st, i, x, mg, ma, si, raise; char s[1024]; struct workspace *ws; @@ -4597,9 +4614,11 @@ setlayout(char *selector, char *value, int flags) return (0); bzero(s, sizeof s); - if (sscanf(value, "ws[%d]:%d:%d:%d:%1023c", - &ws_id, &mg, &ma, &si, s) != 5) - errx(1, "invalid layout entry, should be 'ws[]:'\n"); + if (sscanf(value, "ws[%d]:%d:%d:%d:%d:%1023c", + &ws_id, &mg, &ma, &si, &raise, s) != 6) + errx(1, "invalid layout entry, should be 'ws[]:" + "::::" + "'\n"); ws_id--; if (ws_id < 0 || ws_id >= SWM_WS_MAX) errx(1, "layout: invalid workspace %d\n", ws_id + 1); @@ -4611,11 +4630,15 @@ setlayout(char *selector, char *value, int flags) else if (!strcasecmp(s, "fullscreen")) st = SWM_MAX_STACK; else - errx(1, "invalid layout entry, should be 'ws[]:'\n"); + errx(1, "invalid layout entry, should be 'ws[]:" + "::::" + "'\n"); for (i = 0; i < ScreenCount(display); i++) { ws = (struct workspace *)&screens[i].ws; ws[ws_id].cur_layout = &layouts[st]; + + ws[ws_id].always_raise = raise; if (st == SWM_MAX_STACK) continue; diff --git a/scrotwm.conf b/scrotwm.conf index f10abc5..daca5c3 100644 --- a/scrotwm.conf +++ b/scrotwm.conf @@ -46,9 +46,9 @@ dialog_ratio = 0.6 # autorun = ws[2]:xxxterm http://www.openbsd.org # workspace layout -# layout = ws[1]:4:0:0:vertical -# layout = ws[2]:0:0:0:horizontal -# layout = ws[3]:0:0:0:fullscreen +# layout = ws[1]:4:0:0:0:vertical +# layout = ws[2]:0:0:0:0:horizontal +# layout = ws[3]:0:0:0:0:fullscreen # mod key, (windows key is Mod4) (apple key on OSX is Mod2) # modkey = Mod1 @@ -108,6 +108,9 @@ dialog_ratio = 0.6 #bind[version] = MOD+Shift+v #bind[lock] = MOD+Shift+Delete #bind[initscr] = MOD+Shift+i +#bind[iconify] = MOD+w +#bind[uniconify] = MOD+Shift+w +#bind[raise_toggle] = MOD+Shift+r # quirks # remove with: quirk[class:name] = NONE -- 1.7.10.4 From bbbb9f12ac31e8137e454f2db1902c0e2623db10 Mon Sep 17 00:00:00 2001 From: Marco Peereboom Date: Fri, 24 Jun 2011 17:01:43 +0000 Subject: [PATCH 14/16] add more verbiage to layout --- scrotwm.1 | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/scrotwm.1 b/scrotwm.1 index 90d4d20..5ef311e 100644 --- a/scrotwm.1 +++ b/scrotwm.1 @@ -122,10 +122,12 @@ This ratio is the screen size to what they will be resized. For example, 0.6 is 60% of the physical screen size. .It Cm layout select layout to use at start-of-day. -Defined in the format ws[idx]:master_grow:master_add:stack_inc:layout, e.g. -ws[2]:-4:0:1:horizontal sets worskspace 2 to the horizontal stack mode and -shrinks the master area by 4 ticks and adds one window to the stack. -Possible layout values are +Defined in the format +ws[idx]:master_grow:master_add:stack_inc:layout:always_raise:stack_mode, e.g. +ws[2]:-4:0:1:0:horizontal sets worskspace 2 to the horizontal stack mode and +shrinks the master area by 4 ticks and adds one window to the stack, while +maintaining default floating window behavior. +Possible stack_mode values are .Pa vertical , .Pa horizontal and @@ -137,8 +139,9 @@ See .Pa master_add , .Pa master_del , .Pa stack_inc , +.Pa stack_del , and -.Pa stack_del +.Pa always_raise for more information. Note that the stacking options are complicated and have side-effects. One should familiarize oneself with these commands before experimenting with the -- 1.7.10.4 From 48c0f7f55a3f10abac4a03969d069b4e2bdbee5b Mon Sep 17 00:00:00 2001 From: Marco Peereboom Date: Tue, 28 Jun 2011 12:28:47 +0000 Subject: [PATCH 15/16] Add comment and link to man page. Turns out a lot of people don't know there is one. I guess we can thank the Linux howto mentality for that... --- scrotwm.conf | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scrotwm.conf b/scrotwm.conf index daca5c3..c3c3d97 100644 --- a/scrotwm.conf +++ b/scrotwm.conf @@ -1,6 +1,10 @@ # $scrotwm$ -# + +# PLEASE READ THE MAN PAGE BEFORE EDITING THIS FILE! +# http://opensource.conformal.com/cgi-bin/man-cgi?scrotwm + # colors for focussed and unfocussed window borders +# NOTE: all colors in this file are in hex! see XQueryColor for examples color_focus = red color_unfocus = rgb:88/88/88 -- 1.7.10.4 From 27eedb2351b9592c77a7ee5ea0d2430385e8c3b7 Mon Sep 17 00:00:00 2001 From: Marco Peereboom Date: Tue, 28 Jun 2011 12:41:07 +0000 Subject: [PATCH 16/16] Update authors --- scrotwm.1 | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/scrotwm.1 b/scrotwm.1 index 5ef311e..c963216 100644 --- a/scrotwm.1 +++ b/scrotwm.1 @@ -612,7 +612,7 @@ quirk[Firefox:Navigator] = FLOAT .Sh SIGNALS Sending .Nm -a HUP signal will retstart it. +a HUP signal will restart it. .Sh FILES .Bl -tag -width "/etc/scrotwm.confXXX" -compact .It Pa ~/.scrotwm.conf @@ -627,13 +627,17 @@ global settings. was inspired by xmonad & dwm. .Sh AUTHORS .An -nosplit -.Pp .Nm -was written by -.An Marco Peereboom Aq marco@peereboom.us , -.An Ryan Thomas McBride Aq mcbride@countersiege.com -and -.An Darrin Chandler Aq dwchandler@stilyagin.com . +was written by: +.Pp +.Bl -tag -width "Ryan Thomas McBride Aq mcbride@countersiege.com " -offset indent -compact +.It Cm Marco Peereboom Aq marco@peereboom.us +.It Cm Ryan Thomas McBride Aq mcbride@countersiege.com +.It Cm Darrin Chandler Aq dwchandler@stilyagin.com +.It Cm Pierre-Yves Ritschard Aq pyr@spootnik.org +.It Cm Tuukka Kataja Aq stuge@xor.fi +.It Cm Jason L. Wright Aq jason@thought.net +.El .Sh BUGS Currently the menu, invoked with .Cm M-p , -- 1.7.10.4