static const char *cvstag =
"$scrotwm$";
-#define SWM_VERSION "0.9.30"
+#define SWM_VERSION "0.9.32"
#include <stdio.h>
#include <stdlib.h>
{ 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)
/* 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 */
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);
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,
}
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;
kf_spawn_custom,
kf_iconify,
kf_uniconify,
+ kf_raise_toggle,
kf_dumpwins, /* MUST BE LAST */
kf_invalid
};
{ "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} },
};
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
{
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;
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");
+ if (sscanf(value, "ws[%d]:%1023c", &ws_id, s) != 2)
+ errx(1, "invalid autorun entry, should be 'ws[<idx>]: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
* 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);
return (0);
}
+int
+setlayout(char *selector, char *value, int flags)
+{
+ int ws_id, st, i, x, mg, ma, si, raise;
+ char s[1024];
+ struct workspace *ws;
+
+ if (getenv("SWM_STARTED"))
+ return (0);
+
+ bzero(s, sizeof s);
+ 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[<idx>]:"
+ "<master_grow>:<master_add>:<stack_inc>:<always_raise>:"
+ "<type>'\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[<idx>]:"
+ "<master_grow>:<master_add>:<stack_inc>:<always_raise>:"
+ "<type>'\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;
+
+ /* 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);
+}
+
/* 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 },
{ "disable_border", setconfvalue, SWM_S_DISABLE_BORDER },
{ "border_width", setconfvalue, SWM_S_BORDER_WIDTH },
{ "autorun", setautorun, 0 },
+ { "layout", setlayout, 0 },
};
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;
+ 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)
+ goto tryharder;
+ if (pid == NULL)
+ goto tryharder;
- ret = pid[0];
+ 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 *