#endif
/* #define SWM_DEBUG */
-/* #define SWM_DEBUG */
#ifdef SWM_DEBUG
#define DPRINTF(x...) do { if (swm_debug) fprintf(stderr, x); } while(0)
#define DNPRINTF(n,x...) do { if (swm_debug & n) fprintf(stderr, x); } while(0)
#define SWM_D_MOVE 0x0010
#define SWM_D_STACK 0x0020
#define SWM_D_MOUSE 0x0040
+#define SWM_D_PROP 0x0080
+
u_int32_t swm_debug = 0
| SWM_D_MISC
| SWM_D_FOCUS
| SWM_D_MOVE
| SWM_D_STACK
+ | SWM_D_PROP
;
#else
#define DPRINTF(x...)
#define WIDTH(r) (r)->g.w
#define HEIGHT(r) (r)->g.h
+#ifndef SWM_LIB
+#define SWM_LIB "/usr/X11R6/lib/swmhack.so"
+#endif
+
+#define SWM_PROPLEN (16)
+
char **start_argv;
Atom astate;
int (*xerrorxlib)(Display *, XErrorEvent *);
int bar_pipe[2];
char bar_ext[SWM_BAR_MAX];
sig_atomic_t bar_alarm = 0;
+int bar_delay = 30;
int bar_enabled = 1;
int bar_extra = 1;
int bar_extra_running = 0;
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
goto bad;
break;
}
}
XSync(display, False);
-
- alarm(60);
+ alarm(bar_delay);
}
void
} else {
/* otherwise, choose a region based on pointer location */
TAILQ_FOREACH(r, &screens[i].rl, entry) {
- if (x > X(r) && x < X(r) + WIDTH(r) &&
- y > Y(r) && y < Y(r) + HEIGHT(r))
+ if (x >= X(r) && x <= X(r) + WIDTH(r) &&
+ y >= Y(r) && y <= Y(r) + HEIGHT(r))
break;
}
*/
if (fork() == 0) {
if (fork() == 0) {
+ char *ret;
if (display)
close(ConnectionNumber(display));
+ setenv("LD_PRELOAD", SWM_LIB, 1);
+ if (asprintf(&ret, "%d", r->ws->idx))
+ setenv("_SWM_WS", ret, 1);
+ if (asprintf(&ret, "%d", getpid()))
+ setenv("_SWM_PID", ret, 1);
setsid();
execvp(args->argv[0], args->argv);
fprintf(stderr, "execvp failed\n");
int wsid = args->id;
struct ws_win *win = cur_focus;
struct workspace *ws, *nws;
+ Atom ws_idx_atom = 0;
+ unsigned char ws_idx_str[SWM_PROPLEN];
DNPRINTF(SWM_D_MOVE, "send_to_ws: win: %lu\n", win->id);
TAILQ_INSERT_TAIL(&nws->winlist, win, entry);
win->ws = nws;
+ /* Try to update the window's workspace property */
+ ws_idx_atom = XInternAtom(display, "_SWM_WS", False);
+ if (ws_idx_atom &&
+ snprintf(ws_idx_str, SWM_PROPLEN, "%d", nws->idx) < SWM_PROPLEN) {
+ DNPRINTF(SWM_D_PROP, "setting property _SWM_WS to %s\n",
+ ws_idx_str);
+ XChangeProperty(display, win->id, ws_idx_atom, XA_STRING, 8,
+ PropModeReplace, ws_idx_str, SWM_PROPLEN);
+ }
+
if (count_win(nws, 1) == 1)
nws->focus = win;
ws->restack = 1;
}
struct ws_win *
-manage_window(Window id, struct workspace *ws)
+manage_window(Window id)
{
Window trans;
+ struct workspace *ws;
struct ws_win *win;
XClassHint ch;
+ int format;
+ unsigned long nitems, bytes;
+ Atom ws_idx_atom = 0, type;
+ unsigned char ws_idx_str[SWM_PROPLEN], *prop = NULL;
+ struct swm_region *r;
- TAILQ_FOREACH(win, &ws->winlist, entry) {
- if (win->id == id)
+ if ((win = find_window(id)) != NULL)
return (win); /* already being managed */
- }
if ((win = calloc(1, sizeof(struct ws_win))) == NULL)
errx(1, "calloc: failed to allocate memory for new window");
+ ws_idx_atom = XInternAtom(display, "_SWM_WS", False);
+ 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);
+ r = root_to_region(win->wa.root);
+ /* If the window was managed before, put it in the same workspace */
+ if (prop) {
+ int ws_idx;
+ const char *errstr;
+
+ DNPRINTF(SWM_D_PROP, "got property _SWM_WS=%s\n", prop);
+ ws_idx = strtonum(prop, 0, 9, &errstr);
+ if (errstr)
+ DNPRINTF(SWM_D_EVENT, "window idx is %s: %s",
+ errstr, prop);
+ ws = &r->s->ws[ws_idx];
+ } else
+ ws = r->ws;
+
win->id = id;
win->ws = ws;
- win->s = ws->r->s; /* this never changes */
+ win->s = r->s; /* this never changes */
TAILQ_INSERT_TAIL(&ws->winlist, win, entry);
/* make new win focused */
DNPRINTF(SWM_D_MISC, "manage_window: win %u transient %u\n",
(unsigned)win->id, win->transient);
}
- XGetWindowAttributes(display, id, &win->wa);
win->g.w = win->wa.width;
win->g.h = win->wa.height;
win->g.x = win->wa.x;
win->g.y = win->wa.y;
+
+ if (ws_idx_atom && prop == NULL &&
+ snprintf(ws_idx_str, SWM_PROPLEN, "%d", ws->idx) < SWM_PROPLEN) {
+ DNPRINTF(SWM_D_PROP, "setting property _SWM_WS to %s\n",
+ ws_idx_str);
+ XChangeProperty(display, win->id, ws_idx_atom, XA_STRING, 8,
+ PropModeReplace, ws_idx_str, SWM_PROPLEN);
+ }
+ XFree(prop);
+
/*
fprintf(stderr, "manage window: %d x %d y %d w %d h %d\n", win->id, win->g.x, win->g.y, win->g.w, win->g.h);
*/
+
/* XXX make this a table */
bzero(&ch, sizeof ch);
if (XGetClassHint(display, win->id, &ch)) {
{
XMapRequestEvent *ev = &e->xmaprequest;
XWindowAttributes wa;
- struct swm_region *r;
DNPRINTF(SWM_D_EVENT, "maprequest: window: %lu\n",
e->xmaprequest.window);
return;
if (wa.override_redirect)
return;
- r = root_to_region(wa.root);
- manage_window(e->xmaprequest.window, r->ws);
+ manage_window(e->xmaprequest.window);
stack();
}
int ncrtc = 0, w = 0;
int i, j, k;
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);
+
+
/* map physical screens */
for (i = 0; i < ScreenCount(display); i++) {
DNPRINTF(SWM_D_WS, "setup_screens: init screen %d\n", i);
else
ncrtc = sr->ncrtc;
- for (c = 0; c < ncrtc; c++) {
+ for (c = 0, ci = NULL; c < ncrtc; c++) {
ci = XRRGetCrtcInfo(display, sr, sr->crtcs[c]);
if (ci->noutput == 0)
continue;
ci->x, ci->y, ci->width, ci->height);
w++;
}
- XRRFreeCrtcInfo(ci);
+ if (ci)
+ XRRFreeCrtcInfo(ci);
XRRFreeScreenResources(sr);
#else
new_region(&screens[i], &screens[i].ws[w], 0, 0,
if (wa.map_state == IsViewable ||
getstate(wins[i]) == NormalState)
- manage_window(wins[i], r->ws);
+ manage_window(wins[i]);
}
/* transient windows */
for (i = 0; i < no; i++) {
if (XGetTransientForHint(display, wins[i], &d1) &&
(wa.map_state == IsViewable || getstate(wins[i]) ==
NormalState))
- manage_window(wins[i], r->ws);
+ manage_window(wins[i]);
}
if (wins) {
XFree(wins);