static const char *cvstag = "$scrotwm$";
-#define SWM_VERSION "0.7"
+#define SWM_VERSION "0.8"
#include <stdio.h>
#include <stdlib.h>
char *spawn_term[] = { "xterm", NULL };
char *spawn_screenshot[] = { "screenshot.sh", NULL, NULL };
char *spawn_lock[] = { "xlock", NULL };
+char *spawn_initscr[] = { "initscreen.sh", NULL };
char *spawn_menu[] = { "dmenu_run", "-fn", NULL, "-nb", NULL,
"-nf", NULL, "-sb", NULL, "-sf", NULL, NULL };
struct {
int horizontal_msize;
int horizontal_mwin;
+ int horizontal_stacks;
int vertical_msize;
int vertical_mwin;
+ int vertical_stacks;
} l_state;
};
#define SWM_ARG_ID_CYCLEWS_DOWN (13)
#define SWM_ARG_ID_CYCLESC_UP (14)
#define SWM_ARG_ID_CYCLESC_DOWN (15)
+#define SWM_ARG_ID_STACKINC (16)
+#define SWM_ARG_ID_STACKDEC (17)
#define SWM_ARG_ID_SS_ALL (0)
#define SWM_ARG_ID_SS_WINDOW (1)
#define SWM_ARG_ID_DONTCENTER (0)
char *class;
char *name;
unsigned long quirk;
-#define SWM_Q_FLOAT (1<<0)
-#define SWM_Q_TRANSSZ (1<<1)
+#define SWM_Q_FLOAT (1<<0) /* float this window */
+#define SWM_Q_TRANSSZ (1<<1) /* transiend window size too small */
+#define SWM_Q_ANYWHERE (1<<2) /* don't position this window */
} 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},
+ { "Gimp", "gimp", SWM_Q_FLOAT | SWM_Q_ANYWHERE},
+ { NULL, NULL, 0},
};
/* events */
struct swm_region *
root_to_region(Window root)
{
- struct swm_region *r;
+ struct swm_region *r = NULL;
Window rr, cr;
int i, x, y, wx, wy;
unsigned int mask;
break;
if (XQueryPointer(display, screens[i].root,
- &rr, &cr, &x, &y, &wx, &wy, &mask) == False) {
- /* if we can't query the pointer, grab the first region */
- r = TAILQ_FIRST(&screens[i].rl);
- } else {
- /* otherwise, choose a region based on pointer location */
- TAILQ_FOREACH(r, &screens[i].rl, entry) {
+ &rr, &cr, &x, &y, &wx, &wy, &mask) != False) {
+ /* 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))
break;
- }
-
- if (r == NULL)
- r = TAILQ_FIRST(&screens[i].rl);
}
+
+ if (r == NULL)
+ r = TAILQ_FIRST(&screens[i].rl);
+
return (r);
}
XWindowChanges wc;
struct swm_geometry win_g, r_g = *g;
struct ws_win *win, *winfocus;
- int i, j, w_inc, h_inc, w_base, h_base;
+ int i, j, s, w_inc, h_inc, w_base, h_base, stacks;
int hrh, extra, h_slice, last_h = 0;
int split, colno, winno, mwin, msize, mscale;
int remain, missing, v_slice;;
w_base = win->sh.base_width;
mwin = ws->l_state.horizontal_mwin;
mscale = ws->l_state.horizontal_msize;
+ stacks = ws->l_state.horizontal_stacks;
SWAPXY(&r_g);
} else {
w_inc = win->sh.height_inc;
w_base = win->sh.base_height;
mwin = ws->l_state.vertical_mwin;
mscale = ws->l_state.vertical_msize;
+ stacks = ws->l_state.vertical_stacks;
}
win_g = r_g;
+ if (stacks > winno - mwin)
+ stacks = winno - mwin;
+ if (stacks < 1)
+ stacks = 1;
+
h_slice = r_g.h / SWM_H_SLICE;
if (mwin && winno > mwin) {
v_slice = r_g.w / SWM_V_SLICE;
split = mwin;
colno = split;
- msize = v_slice * mscale;
+ win_g.w = v_slice * mscale;
if (w_inc > 1 && w_inc < v_slice) {
/* adjust for window's requested size increment */
}
}
- win_g.w = msize;
+ msize = win_g.w;
if (flip)
win_g.x += r_g.w - msize;
} else {
- colno = winno;
- split = 0;
+ msize = -2;
+ colno = split = winno / stacks;
+ win_g.w = ((r_g.w - (stacks * 2) + 2) / stacks);
}
hrh = r_g.h / colno;
extra = r_g.h - (colno * hrh);
win_g.h = hrh - 2;
/* stack all the tiled windows */
- i = j = 0;
+ i = j = 0, s = stacks;
TAILQ_FOREACH(win, &ws->winlist, entry) {
if (win->transient != 0 || win->floating != 0)
continue;
if (split && i == split) {
- colno = winno - split;
+ colno = (winno - mwin) / stacks;
+ if (s <= (winno - mwin) % stacks)
+ colno++;
+ split = split + colno;
hrh = (r_g.h / colno);
extra = r_g.h - (colno * hrh);
if (flip)
win_g.x = r_g.x;
else
- win_g.x += msize + 2;
- win_g.w = r_g.w - (msize + 2);
+ win_g.x += win_g.w + 2;
+ win_g.w = (r_g.w - msize - (stacks * 2)) / stacks;
+ if (s == 1)
+ win_g.w += (r_g.w - msize - (stacks * 2)) %
+ stacks;
+ s--;
j = 0;
}
win_g.h = hrh - 2;
case SWM_ARG_ID_STACKINIT:
ws->l_state.vertical_msize = SWM_V_SLICE / 2;
ws->l_state.vertical_mwin = 1;
+ ws->l_state.vertical_stacks = 1;
break;
case SWM_ARG_ID_MASTERSHRINK:
if (ws->l_state.vertical_msize > 1)
if (ws->l_state.vertical_mwin > 0)
ws->l_state.vertical_mwin--;
break;
+ case SWM_ARG_ID_STACKINC:
+ ws->l_state.vertical_stacks++;
+ break;
+ case SWM_ARG_ID_STACKDEC:
+ if (ws->l_state.vertical_stacks > 1)
+ ws->l_state.vertical_stacks--;
+ break;
default:
return;
}
case SWM_ARG_ID_STACKINIT:
ws->l_state.horizontal_mwin = 1;
ws->l_state.horizontal_msize = SWM_H_SLICE / 2;
+ ws->l_state.horizontal_stacks = 1;
break;
case SWM_ARG_ID_MASTERSHRINK:
if (ws->l_state.horizontal_msize > 1)
if (ws->l_state.horizontal_mwin > 0)
ws->l_state.horizontal_mwin--;
break;
+ case SWM_ARG_ID_STACKINC:
+ ws->l_state.horizontal_stacks++;
+ break;
+ case SWM_ARG_ID_STACKDEC:
+ if (ws->l_state.horizontal_stacks > 1)
+ ws->l_state.horizontal_stacks--;
+ break;
default:
return;
}
{ MODKEY, XK_l, stack_config, {.id = SWM_ARG_ID_MASTERGROW} },
{ MODKEY, XK_comma, stack_config, {.id = SWM_ARG_ID_MASTERADD} },
{ MODKEY, XK_period, stack_config, {.id = SWM_ARG_ID_MASTERDEL} },
+ { MODKEY | ShiftMask, XK_comma, stack_config, {.id = SWM_ARG_ID_STACKINC} },
+ { MODKEY | ShiftMask, XK_period, stack_config, {.id = SWM_ARG_ID_STACKDEC} },
{ MODKEY, XK_Return, swapwin, {.id = SWM_ARG_ID_SWAPMAIN} },
{ MODKEY, XK_j, focus, {.id = SWM_ARG_ID_FOCUSNEXT} },
{ MODKEY, XK_k, focus, {.id = SWM_ARG_ID_FOCUSPREV} },
{ MODKEY, XK_t, floating_toggle,{0} },
{ MODKEY | ShiftMask, XK_v, version, {0} },
{ MODKEY | ShiftMask, XK_Delete, spawn, {.argv = spawn_lock} },
+ { MODKEY | ShiftMask, XK_i, spawn, {.argv = spawn_initscr} },
};
void
struct swm_region *r;
long mask;
const char *errstr;
+ XWindowChanges wc;
if ((win = find_window(id)) != NULL)
return (win); /* already being managed */
}
}
+ /* alter window position if quirky */
+ if (win->quirks & SWM_Q_ANYWHERE) {
+ win->manual = 1; /* don't center the quirky windows */
+ bzero(&wc, sizeof wc);
+ mask = 0;
+ if (win->g.y < bar_height) {
+ win->g.y = wc.y = bar_height;
+ mask |= CWY;
+ }
+ if (win->g.w + win->g.x > WIDTH(r)) {
+ win->g.x = wc.x = WIDTH(win->ws->r) - win->g.w - 2;
+ mask |= CWX;
+ }
+ wc.border_width = 1;
+ mask |= CWBorderWidth;
+ XConfigureWindow(display, win->id, mask, &wc);
+ }
+
XSelectInput(display, id, EnterWindowMask | FocusChangeMask |
PropertyChangeMask | StructureNotifyMask);
set_win_state(win, NormalState);
+ /* floaters need to be mapped if they are in the current workspace */
+ if (win->floating && (ws->idx == r->ws->idx))
+ XMapRaised(display, win->id);
+
/* make new win focused */
focus_win(win);
DNPRINTF(SWM_D_MISC, "unmanage_window: %lu\n", win->id);
+ /* don't unmanage if we are switching workspaces */
ws = win->ws;
if (ws->restack)
return;
ev->value_mask |= CWY | CWHeight;
}
}
- if ((ev->value_mask & (CWX|CWY)) &&
- !(ev->value_mask & (CWWidth|CWHeight)))
+ if ((ev->value_mask & (CWX | CWY)) &&
+ !(ev->value_mask & (CWWidth | CWHeight)))
config_win(win);
XMoveResizeWindow(display, win->id,
win->g.x, win->g.y, win->g.w, win->g.h);
if (wa.override_redirect)
return;
manage_window(e->xmaprequest.window);
+
stack();
}
new_region(struct swm_screen *s, int x, int y, int w, int h)
{
struct swm_region *r, *n;
- struct workspace *ws;
+ struct workspace *ws = NULL;
int i;
DNPRINTF(SWM_D_MISC, "new region: screen[%d]:%dx%d+%d+%d\n",
(X(r) + WIDTH(r)) > x &&
Y(r) < (y + h) &&
(Y(r) + HEIGHT(r)) > y) {
- r->ws->r = NULL;
XDestroyWindow(display, r->bar_window);
TAILQ_REMOVE(&s->rl, r, entry);
TAILQ_INSERT_TAIL(&s->orl, r, entry);
ws = &s->ws[i];
break;
}
- if (ws == NULL)
- errx(1, "no free workspaces\n");
}
+ if (ws == NULL)
+ errx(1, "no free workspaces\n");
+
X(r) = x;
Y(r) = y;
WIDTH(r) = w;
XRRCrtcInfo *ci;
XRRScreenResources *sr;
int c;
+ int ncrtc = 0;
#endif /* SWM_XRR_HAS_CRTC */
struct swm_region *r;
- int ncrtc = 0;
- /* remove any old regions */
+ if (i >= ScreenCount(display))
+ errx(1, "invalid screen");
+
+ /* remove any old regions */
while ((r = TAILQ_FIRST(&screens[i].rl)) != NULL) {
r->ws->r = NULL;
XDestroyWindow(display, r->bar_window);
}
void
-screenchange(XEvent *e)
-{
+screenchange(XEvent *e) {
XRRScreenChangeNotifyEvent *xe = (XRRScreenChangeNotifyEvent *)e;
struct swm_region *r;
struct ws_win *win;
int i;
- DNPRINTF(SWM_D_EVENT, "screenchange: %d\n", xe->root);
+ DNPRINTF(SWM_D_EVENT, "screenchange: %lu\n", xe->root);
if (!XRRUpdateConfiguration(e))
return;
{
Window d1, d2, *wins = NULL;
XWindowAttributes wa;
- struct swm_region *r;
unsigned int no;
int i, j, k;
int errorbase, major, minor;
if (!XQueryTree(display, screens[i].root, &d1, &d2, &wins, &no))
continue;
+ scan_xrandr(i);
+
if (xrandr_support)
XRRSelectInput(display, screens[i].root,
RRScreenChangeNotifyMask);
- scan_xrandr(i);
-
/* attach windows to a region */
/* normal windows */
- if ((r = TAILQ_FIRST(&screens[i].rl)) == NULL)
- errx(1, "no regions on screen %d", i);
-
- for (i = 0; i < no; i++) {
- XGetWindowAttributes(display, wins[i], &wa);
- if (!XGetWindowAttributes(display, wins[i], &wa) ||
+ for (j = 0; j < no; j++) {
+ XGetWindowAttributes(display, wins[j], &wa);
+ if (!XGetWindowAttributes(display, wins[j], &wa) ||
wa.override_redirect ||
- XGetTransientForHint(display, wins[i], &d1))
+ XGetTransientForHint(display, wins[j], &d1))
continue;
if (wa.map_state == IsViewable ||
- getstate(wins[i]) == NormalState)
- manage_window(wins[i]);
+ getstate(wins[j]) == NormalState)
+ manage_window(wins[j]);
}
/* transient windows */
- for (i = 0; i < no; i++) {
- if (!XGetWindowAttributes(display, wins[i], &wa))
+ for (j = 0; j < no; j++) {
+ if (!XGetWindowAttributes(display, wins[j], &wa))
continue;
- if (XGetTransientForHint(display, wins[i], &d1) &&
- (wa.map_state == IsViewable || getstate(wins[i]) ==
+ if (XGetTransientForHint(display, wins[j], &d1) &&
+ (wa.map_state == IsViewable || getstate(wins[j]) ==
NormalState))
- manage_window(wins[i]);
+ manage_window(wins[j]);
}
if (wins) {
XFree(wins);
bar_alarm = 0;
bar_update();
}
- while(XPending(display)) {
+ while (XPending(display)) {
XNextEvent(display, &e);
if (e.type < LASTEvent) {
if (handler[e.type])
handler[e.type](&e);
else
DNPRINTF(SWM_D_EVENT,
- "unkown event: %d\n", e.type);
+ "win: %lu unknown event: %d\n",
+ e.xany.window, e.type);
} else {
switch (e.type - xrandr_eventbase) {
- case RRNotify:
case RRScreenChangeNotify:
screenchange(&e);
break;
default:
DNPRINTF(SWM_D_EVENT,
- "unkown event: %d\n", e.type);
+ "win: %lu unknown xrandr event: "
+ "%d\n", e.xany.window, e.type);
break;
}
}