struct swm_region {
TAILQ_ENTRY(swm_region) entry;
struct swm_geometry g;
- Window bar_window;
struct workspace *ws; /* current workspace on this region */
struct swm_screen *s; /* screen idx */
+ Window bar_window;
};
TAILQ_HEAD(swm_region_list, swm_region);
int floating;
int transient;
int manual;
+ unsigned long quirks;
struct workspace *ws; /* always valid */
struct swm_screen *s; /* always valid, never changes */
XWindowAttributes wa;
char *name;
unsigned long quirk;
#define SWM_Q_FLOAT (1<<0)
+#define SWM_Q_TRANSSZ (1<<1)
} quirks[] = {
{ "MPlayer", "xv", SWM_Q_FLOAT },
{ "OpenOffice.org 2.4", "VCLSalFrame", SWM_Q_FLOAT },
+ { "OpenOffice.org 3.0", "VCLSalFrame", SWM_Q_FLOAT },
+ { "Firefox-bin", "firefox-bin", SWM_Q_TRANSSZ},
{ NULL, NULL, 0},
};
i, ScreenCount(display));
}
+void new_region(struct swm_screen *, struct workspace *,
+ int, int, int, int);
+
+void
+custom_region(char *val)
+{
+ unsigned int sidx, x, y, w, h;
+
+ if (sscanf(val, "screen[%u]:%ux%u+%u+%u", &sidx, &w, &h, &x, &y) != 5)
+ errx(1, "invalid custom region, "
+ "should be 'screen[<n>]:<n>x<n>+<n>+<n>\n");
+ if (sidx < 1 || sidx > ScreenCount(display))
+ errx(1, "invalid screen index: %d out of bounds (maximum %d)\n",
+ sidx, ScreenCount(display));
+ sidx--;
+
+ if (w < 1 || h < 1)
+ errx(1, "region %ux%u+%u+%u too small\n", w, h, x, y);
+
+ if (x < 0 || x > DisplayWidth(display, sidx) ||
+ y < 0 || y > DisplayHeight(display, sidx) ||
+ w + x > DisplayWidth(display, sidx) ||
+ h + y > DisplayHeight(display, sidx))
+ errx(1, "region %ux%u+%u+%u not within screen boundaries "
+ "(%ux%u)\n", w, h, x, y,
+ DisplayWidth(display, sidx), DisplayHeight(display, sidx));
+
+ new_region(&screens[sidx], NULL, x, y, w, h);
+}
+
int
varmatch(char *var, char *name, int *index)
{
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);
old_ws = this_r->ws;
new_ws = &this_r->s->ws[wsid];
- DNPRINTF(SWM_D_WS, "switchws screen %d region %dx%d+%d+%d: "
+ DNPRINTF(SWM_D_WS, "switchws screen[%d]:%dx%d+%d+%d: "
"%d -> %d\n", r->s->idx, WIDTH(r), HEIGHT(r), X(r), Y(r),
old_ws->idx, wsid);
struct swm_screen *s = r->s;
DNPRINTF(SWM_D_WS, "cyclews id %d "
- "in screen %d region %dx%d+%d+%d ws %d\n", args->id,
+ "in screen[%d]:%dx%d+%d+%d ws %d\n", args->id,
r->s->idx, WIDTH(r), HEIGHT(r), X(r), Y(r), r->ws->idx);
a.id = r->ws->idx;
bzero(&wc, sizeof wc);
mask = CWX | CWY | CWBorderWidth | CWWidth | CWHeight;
wc.border_width = 1;
- if (win->transient) {
+ if (win->transient && (win->quirks & SWM_Q_TRANSSZ)) {
win->g.w = (double)WIDTH(r) * dialog_ratio;
win->g.h = (double)HEIGHT(r) * dialog_ratio;
}
mask = CWX | CWY | CWWidth | CWHeight | CWBorderWidth;
XConfigureWindow(display, win->id, mask, &wc);
XMapRaised(display, win->id);
- /*
- fprintf(stderr, "vertical_stack: win %d x %d y %d w %d h %d bw %d\n", win->id, win->g.x, win->g.y, win->g.w , win->g.h, wc.border_width);
- */
last_h = win_g.h;
i++;
XEvent ev;
Time time = 0;
- DNPRINTF(SWM_D_MOUSE, "resize: win %d floating %d trans %d\n",
+ DNPRINTF(SWM_D_MOUSE, "resize: win %lu floating %d trans %d\n",
win->id, win->floating, win->transient);
if (!(win->transient != 0 || win->floating != 0))
Time time = 0;
int restack = 0;
- DNPRINTF(SWM_D_MOUSE, "move: win %d floating %d trans %d\n",
+ DNPRINTF(SWM_D_MOUSE, "move: win %lu floating %d trans %d\n",
win->id, win->floating, win->transient);
if (win->floating == 0) {
}
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);
- */
-
if (XGetClassHint(display, win->id, &win->ch)) {
DNPRINTF(SWM_D_CLASS, "class: %s name: %s\n",
win->ch.res_class, win->ch.res_name);
win->ch.res_class, win->ch.res_name);
if (quirks[i].quirk & SWM_Q_FLOAT)
win->floating = 1;
+ win->quirks = quirks[i].quirk;
}
}
}
}
void
+unmanage_window(struct ws_win *win)
+{
+ if (win == NULL)
+ return;
+
+ DNPRINTF(SWM_D_MISC, "unmanage_window: %lu\n", win->id);
+
+ TAILQ_REMOVE(&win->ws->winlist, win, entry);
+ set_win_state(win, WithdrawnState);
+ if (win->ch.res_class)
+ XFree(win->ch.res_class);
+ if (win->ch.res_name)
+ XFree(win->ch.res_name);
+ free(win);
+}
+
+void
configurerequest(XEvent *e)
{
XConfigureRequestEvent *ev = &e->xconfigurerequest;
if (new) {
DNPRINTF(SWM_D_EVENT, "configurerequest: new window: %lu\n",
ev->window);
- /*
- fprintf(stderr, "configurerequest: new window: %lu x %d y %d w %d h %d bw %d s %d sm %d\n",
- ev->window, ev->x, ev->y, ev->width, ev->height, ev->border_width, ev->above, ev->detail);
- */
bzero(&wc, sizeof wc);
wc.x = ev->x;
wc.y = ev->y;
wc.stack_mode = ev->detail;
XConfigureWindow(display, ev->window, ev->value_mask, &wc);
} else {
- /*
- fprintf(stderr, "configurerequest: change window: %lu\n",
- ev->window);
- */
DNPRINTF(SWM_D_EVENT, "configurerequest: change window: %lu\n",
ev->window);
if (win->floating) {
unfocus_all();
} else
focus_win(ws->focus);
- TAILQ_REMOVE(&ws->winlist, win, entry);
- set_win_state(win, WithdrawnState);
- if (win->ch.res_class)
- XFree(win->ch.res_class);
- if (win->ch.res_name)
- XFree(win->ch.res_name);
- free(win);
+ unmanage_window(win);
stack();
}
}
void
unmapnotify(XEvent *e)
{
+ XDestroyWindowEvent *ev = &e->xdestroywindow;
+ struct ws_win *win;
+
DNPRINTF(SWM_D_EVENT, "unmapnotify: window: %lu\n", e->xunmap.window);
+
+ if ((win = find_window(ev->window)) != NULL)
+ if (win->transient)
+ unmanage_window(win);
}
void
}
void
+remove_region(struct swm_region *r)
+{
+ struct swm_screen *s = r->s;
+ struct ws_win *win;
+
+ DNPRINTF(SWM_D_MISC, "removing region: screen[%d]:%dx%d+%d+%d\n",
+ s->idx, WIDTH(r), HEIGHT(r), X(r), Y(r));
+
+ TAILQ_FOREACH(win, &r->ws->winlist, entry)
+ XUnmapWindow(display, win->id);
+ r->ws->r = NULL;
+
+ XDestroyWindow(display, r->bar_window);
+ TAILQ_REMOVE(&s->rl, r, entry);
+ free(r);
+}
+
+void
new_region(struct swm_screen *s, struct workspace *ws,
int x, int y, int w, int h)
{
- struct swm_region *r;
+ struct swm_region *r, *n;
+ int i;
+
+ DNPRINTF(SWM_D_MISC, "new region: screen[%d]:%dx%d+%d+%d\n",
+ s->idx, w, h, x, y);
+
+ /* remove any conflicting regions */
+ n = TAILQ_FIRST(&s->rl);
+ while (n) {
+ r = n;
+ n = TAILQ_NEXT(r, entry);
+ if (X(r) < (x + w) &&
+ (X(r) + WIDTH(r)) > x &&
+ Y(r) < (y + h) &&
+ (Y(r) + HEIGHT(r)) > y) {
+ if (ws == NULL)
+ ws = r->ws;
+ remove_region(r);
+ }
+ }
+
+ /* pick an appropriate workspace */
+ if (ws == NULL) {
+ for (i = 0; i < SWM_WS_MAX; i++)
+ if (s->ws[i].r == NULL) {
+ ws = &s->ws[i];
+ break;
+ }
- DNPRINTF(SWM_D_MISC, "new region on screen %d: %dx%d (%d, %d)\n",
- s->idx, x, y, w, h);
+ if (ws == NULL)
+ errx(1, "no free regions\n");
+ }
if ((r = calloc(1, sizeof(struct swm_region))) == NULL)
errx(1, "calloc: failed to allocate memory for screen");