int basew, baseh, incw, inch, maxw, maxh, minw, minh;
int bw, oldbw;
unsigned int tags;
- Bool isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen;
+ Bool isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen, screen_hog;
Client *next;
Client *snext;
Monitor *mon;
const char *title;
unsigned int tags;
Bool isfloating;
+ Bool screen_hog;
int monitor;
} Rule;
static Bool applysizehints(Client *c, int *x, int *y, int *w, int *h, Bool interact);
static void arrange(Monitor *m);
static void arrangemon(Monitor *m);
+static void attach_as_master(Client *c);
static void attach(Client *c);
static void attachstack(Client *c);
static void buttonpress(XEvent *e);
static void motionnotify(XEvent *e);
static void movemouse(const Arg *arg);
static Client *nexttiled(Client *c);
+static Client *nextvisible(Client *c);
static void pop(Client *);
static void propertynotify(XEvent *e);
static void quit(const Arg *arg);
static void spawn(const Arg *arg);
static void tag(const Arg *arg);
static void tagmon(const Arg *arg);
+static void jason_layout(Monitor *);
static void tile(Monitor *);
static void togglebar(const Arg *arg);
static void togglefloating(const Arg *arg);
// unfocused windows get transparent (feature)
static const unsigned long unfocused_opacity[] = { 0xbfffffff };
+static const unsigned long invisible_opacity[] = { 0x00000000 };
static void window_set_opaque(Client *c);
static void window_set_translucent(Client *c);
+static void window_set_invisible(Client *c);
void
window_set_opaque(Client *c) {
- XChangeProperty(dpy, c->win, netatom[NetWMWindowOpacity], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)unfocused_opacity, 1);
+ XDeleteProperty(dpy, c->win, netatom[NetWMWindowOpacity]);
}
void
window_set_translucent(Client *c) {
- XDeleteProperty(dpy, c->win, netatom[NetWMWindowOpacity]);
+ XChangeProperty(dpy, c->win, netatom[NetWMWindowOpacity], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)unfocused_opacity, 1);
+}
+void
+window_set_invisible(Client *c) {
+ XChangeProperty(dpy, c->win, netatom[NetWMWindowOpacity], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)invisible_opacity, 1);
}
XClassHint ch = { NULL, NULL };
/* rule matching */
- c->isfloating = c->tags = 0;
+ c->isfloating = c->tags = c->screen_hog = 0;
XGetClassHint(dpy, c->win, &ch);
class = ch.res_class ? ch.res_class : broken;
instance = ch.res_name ? ch.res_name : broken;
for(i = 0; i < LENGTH(rules); i++) {
r = &rules[i];
- if((!r->title || strstr(c->name, r->title))
+ if((!r->title || c->name == strstr(c->name, r->title))
&& (!r->class || strstr(class, r->class))
&& (!r->instance || strstr(instance, r->instance)))
{
c->isfloating = r->isfloating;
c->tags |= r->tags;
+ c->screen_hog = r->screen_hog;
for(m = mons; m && m->num != r->monitor; m = m->next);
if(m)
c->mon = m;
}
void
-attach(Client *c) {
+attach_as_master(Client *c) {
c->next = c->mon->clients;
c->mon->clients = c;
}
+void
+attach(Client *c) {
+ if (c->mon->sel) {
+ c->next = c->mon->sel->next;
+ c->mon->sel->next = c;
+ } else {
+ attach_as_master(c);
+ }
+}
void
attachstack(Client *c) {
|| (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen)));
}
else if(cme->message_type == netatom[NetActiveWindow]) {
+ return;
if(!ISVISIBLE(c)) {
c->mon->seltags ^= 1;
c->mon->tagset[c->mon->seltags] = c->tags;
*tc = c->next;
}
+// NOTE: the stack is for z-order and most-recently-focused
+// only mon->clients determines position in visible layout
void
detachstack(Client *c) {
- Client **tc, *t;
-
- for(tc = &c->mon->stack; *tc && *tc != c; tc = &(*tc)->snext);
- *tc = c->snext;
-
+ Client *prev = NULL, *next_sel = NULL, *i;
+ for(i = c->mon->stack; i && i != c; i = i->snext) {
+ prev = i;
+ }
if(c == c->mon->sel) {
- for(t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext);
- c->mon->sel = t;
+ // find last visible window before c
+ // WARNING if you detach() before detachstack() this will select last visible window
+ for(i = nextvisible(c->mon->clients); i && i != c; i = nextvisible(i->next))
+ next_sel = i;
+ // failing that, find first visible window (besides c)
+ if (!next_sel)
+ for(i = nextvisible(c->mon->clients); i && i == c; i = nextvisible(i->next));
+ if (i != c)
+ next_sel = i;
+ c->mon->sel = next_sel;
+ }
+ if (prev) {
+ prev->snext = c->snext;
+ } else {
+ c->mon->stack = c->snext;
}
}
/* was if(selmon->sel) */
if(selmon->sel && selmon->sel != c)
unfocus(selmon->sel, False);
- if(selmon->sel && c!=selmon->sel && c && (!root || (selmon->sel->win!=root && c->win!=root)) )
- window_set_opaque(selmon->sel);
- if(c && c!=selmon->sel && (!root || (c->win!=root)) )
- window_set_translucent(c);
if(c) {
if(c->mon != selmon)
selmon = c->mon;
}
selmon->sel = c;
drawbars();
- if(c)
- window_set_translucent(c);
+ if(c && (!root || (c->win!=root)) )
+ window_set_opaque(c);
}
void
c->mon->sel = c;
arrange(c->mon);
XMapWindow(dpy, c->win);
- focus(NULL);
+ focus(c);
}
void
return c;
}
+Client *
+nextvisible(Client *c) {
+ for(; c && !ISVISIBLE(c); c = c->next);
+ return c;
+}
+
void
pop(Client *c) {
detach(c);
- attach(c);
+ attach_as_master(c);
focus(c);
arrange(c->mon);
}
if(c->mon == m)
return;
unfocus(c, True);
- detach(c);
detachstack(c);
+ detach(c);
c->mon = m;
c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */
attach(c);
void
spawn(const Arg *arg) {
+ int tag = 0, i;
+ if(arg->v == termcmd) {
+ for(i = 0; i < 32; ++i) {
+ if(selmon->tagset[selmon->seltags] & (1 << i)) {
+ tag = i;
+ break;
+ }
+ }
+ _SWM_WS[8] = swm_tags[tag][0];
+ _SWM_WS[9] = swm_tags[tag][1];
+ }
if(arg->v == dmenucmd)
dmenumon[0] = '0' + selmon->num;
if(fork() == 0) {
if(n > m->nmaster)
mw = m->nmaster ? m->ww * m->mfact : 0;
- else
- mw = m->ww;
+ else {
+ c = nexttiled(m->clients);
+ if (c && !c->screen_hog)
+ mw = m->ww * m->mfact;
+ else
+ mw = m->ww;
+ }
for(i = my = ty = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++)
if(i < m->nmaster) {
h = (m->wh - my) / (MIN(n, m->nmaster) - i);
}
void
+jason_layout(Monitor *m) {
+ unsigned int i, n, mw;
+ Client *c, *vis_slave;
+
+ for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++);
+ if(n == 0) {
+ return;
+ }
+
+ c = nexttiled(m->clients);
+ if (c == m->sel) {
+ // if master is selected, show first slave
+ vis_slave = nexttiled(c->next);
+ } else {
+ vis_slave = m->sel;
+ }
+ if(n > 1 || (n == 1 && !c->screen_hog)) {
+ mw = m->ww * m->mfact;
+ } else {
+ // one of these:
+ // * zero tiled windows
+ // * one tiled window that's not a screen hog
+ // * miltiple tiled windows
+ mw = m->ww;
+ }
+ for (i = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), i++) {
+ if (i == 0) {
+ resize(c, m->wx, m->wy, mw, m->wh, False);
+ } else {
+ if (c == vis_slave) {
+ resize(c, m->wx + mw, m->wy, m->ww - mw, m->wh, False);
+ } else {
+ // this function does not get called when focus changes
+ // resize(c, m->wx + m->ww, m->wy, m->ww - mw, m->wh, False);
+ resize(c, m->wx + mw, m->wy, m->ww - mw, m->wh, False);
+ }
+ }
+ }
+}
+
+void
togglebar(const Arg *arg) {
selmon->showbar = !selmon->showbar;
updatebarpos(selmon);
void
unfocus(Client *c, Bool setfocus) {
+ Client *w;
if(!c)
return;
+ if(!root || c->win!=root) {
+ w = nexttiled(c->mon->clients);
+ if (!w) {
+ // no tiled windows
+ window_set_translucent(c);
+ } else if (w == c) {
+ // master
+ window_set_translucent(c);
+ } else {
+ w = nexttiled(w->next);
+ if (!w) {
+ // c must not be tiled
+ window_set_translucent(c);
+ } else {
+ if (w == c) { // first slave
+ window_set_translucent(c);
+ } else {
+ window_set_invisible(c);
+ window_set_translucent(w);
+ }
+ }
+ }
+ }
grabbuttons(c, False);
XSetWindowBorder(dpy, c->win, scheme[SchemeNorm].border->rgb);
if(setfocus) {
XWindowChanges wc;
/* The server grab construct avoids race conditions. */
- detach(c);
detachstack(c);
+ detach(c);
if(!destroyed) {
wc.border_width = c->oldbw;
XGrabServer(dpy);
XUngrabServer(dpy);
}
free(c);
- focus(NULL);
+ focus(selmon ? selmon->sel : NULL);
updateclientlist();
arrange(m);
}