#include <sys/wait.h>
#include <X11/cursorfont.h>
#include <X11/keysym.h>
+#include <X11/XF86keysym.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/Xproto.h>
#define WIDTH(X) ((X)->w + 2 * (X)->bw)
#define HEIGHT(X) ((X)->h + 2 * (X)->bw)
#define TAGMASK ((1 << LENGTH(tags)) - 1)
-#define TEXTW(X) (drw_font_getexts_width(drw->font, X, strlen(X)) + drw->font->h)
+#define TEXTW_NOPAD(X) drw_font_getexts_width(drw->font, X, strlen(X))
+#define TEXTW(X) (TEXTW_NOPAD(X) + drw->font->h)
/* enums */
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
NetWMWindowTypeDialog, NetClientList, NetSupportingWMCheck, NetLast }; /* EWMH atoms */
enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */
enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
- ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
+ ClkClientWin, ClkRootWin, ClkAnywhere, ClkLast }; /* clicks */
typedef union {
int i;
static void setup(void);
static void showhide(Client *c);
static void sigchld(int unused);
+static void kbspawn(const Arg *arg);
static void spawn(const Arg *arg);
static void tag(const Arg *arg);
static void tagmon(const Arg *arg);
static int xerrorstart(Display *dpy, XErrorEvent *ee);
static void zoom(const Arg *arg);
-/* variables */
+// variables
+static Bool key_buffering = False;
static const char broken[] = "broken";
static char stext[256];
static int screen;
-static int sw, sh; /* X display screen geometry width, height */
-static int bh, blw = 0; /* bar geometry */
+static int sw, sh; // X display screen geometry width, height
+static int bh; // bar height
static int (*xerrorxlib)(Display *, XErrorEvent *);
static unsigned int numlockmask = 0;
static void (*handler[LASTEvent]) (XEvent *) = {
&& (!r->instance || strstr(instance, r->instance)))
{
c->isfloating = r->isfloating;
+ if(r->isfloating) {
+ c->x = -1; c->y = -2; // secret code for centered
+ }
c->tags |= r->tags;
c->screen_hog = r->screen_hog;
for(m = mons; m && m->num != r->monitor; m = m->next);
void
buttonpress(XEvent *e) {
- unsigned int i, x, click;
+ unsigned int i, click;
Arg arg = {0};
Client *c;
Monitor *m;
XButtonPressedEvent *ev = &e->xbutton;
+ Bool called = False;
+
+ for(i = 0; i < LENGTH(buttons); i++) {
+ if(buttons[i].click == ClkAnywhere && buttons[i].button == ev->button
+ && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) {
+ buttons[i].func(&buttons[i].arg);
+ called = True;
+ }
+ }
+ if (called) {
+ return;
+ }
click = ClkRootWin;
/* focus monitor if necessary */
focus(NULL);
}
if(ev->window == selmon->barwin) {
- i = x = 0;
- do
- x += TEXTW(tags[i]);
- while(ev->x >= x && ++i < LENGTH(tags));
- if(i < LENGTH(tags)) {
- click = ClkTagBar;
- arg.ui = 1 << i;
- }
- else if(ev->x < x + blw)
- click = ClkLtSymbol;
- else if(ev->x > selmon->ww - TEXTW(stext))
- click = ClkStatusText;
- else
- click = ClkWinTitle;
- }
- else if((c = wintoclient(ev->window))) {
+ return;
+ } else if((c = wintoclient(ev->window))) {
focus(c);
click = ClkClientWin;
}
- for(i = 0; i < LENGTH(buttons); i++)
+ for(i = 0; i < LENGTH(buttons); i++) {
if(click == buttons[i].click && buttons[i].func && buttons[i].button == ev->button
- && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state))
- buttons[i].func(click == ClkTagBar && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg);
+ && CLEANMASK(buttons[i].mask) == CLEANMASK(ev->state)) {
+ if (click == ClkTagBar && buttons[i].arg.i == 0) {
+ buttons[i].func(&arg);
+ } else {
+ buttons[i].func(&buttons[i].arg);
+ }
+ }
+ }
}
void
drw_resize(drw, sw, bh);
updatebars();
for(m = mons; m; m = m->next)
- XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh);
+ XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww * m->mfact, bh);
focus(NULL);
arrange(NULL);
}
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)
+ 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) {
}
x = 0;
for(i = 0; i < LENGTH(tags); i++) {
- w = TEXTW(tags[i]);
+ w = TEXTW_NOPAD(tags[i]);
drw_setscheme(drw, m->tagset[m->seltags] & 1 << i ? &scheme[SchemeSel] : &scheme[SchemeNorm]);
- drw_text(drw, x, 0, w, bh, tags[i], urg & 1 << i);
- drw_rect(drw, x, 0, w, bh, m == selmon && selmon->sel && selmon->sel->tags & 1 << i,
- occ & 1 << i, urg & 1 << i);
+ drw_text_nopad(drw, x, 0, w, bh, tags[i], urg & 1 << i);
x += w;
}
- w = blw = TEXTW(m->ltsymbol);
- drw_setscheme(drw, &scheme[SchemeNorm]);
- drw_text(drw, x, 0, w, bh, m->ltsymbol, 0);
- x += w;
xx = x;
if(m == selmon) { /* status is only drawn on selected monitor */
w = TEXTW(stext);
- x = m->ww - w;
+ x = m->ww * m->mfact - w;
if(x < xx) {
x = xx;
- w = m->ww - xx;
+ w = m->ww* m->mfact - xx;
}
drw_text(drw, x, 0, w, bh, stext, 0);
}
drw_setscheme(drw, m == selmon ? &scheme[SchemeSel] : &scheme[SchemeNorm]);
drw_text(drw, x, 0, w, bh, m->sel->name, 0);
drw_rect(drw, x, 0, w, bh, m->sel->isfixed, m->sel->isfloating, 0);
- }
- else {
+ } else {
drw_setscheme(drw, &scheme[SchemeNorm]);
drw_text(drw, x, 0, w, bh, NULL, 0);
}
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
if(focused) {
for(i = 0; i < LENGTH(buttons); i++)
- if(buttons[i].click == ClkClientWin)
+ if(buttons[i].click == ClkClientWin || buttons[i].click == ClkAnywhere)
for(j = 0; j < LENGTH(modifiers); j++)
XGrabButton(dpy, buttons[i].button,
buttons[i].mask | modifiers[j],
c->win, False, BUTTONMASK,
GrabModeAsync, GrabModeSync, None, None);
- }
- else
+ } else {
XGrabButton(dpy, AnyButton, AnyModifier, c->win, False,
BUTTONMASK, GrabModeAsync, GrabModeSync, None, None);
+ }
}
}
void
grabkeys(void) {
updatenumlockmask();
+ //XUngrabKey(dpy, AnyKey, AnyModifier, root);
{
unsigned int i, j;
unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };
if((code = XKeysymToKeycode(dpy, keys[i].keysym)))
for(j = 0; j < LENGTH(modifiers); j++)
XGrabKey(dpy, code, keys[i].mod | modifiers[j], root,
- True, GrabModeAsync, GrabModeAsync);
+ True, GrabModeAsync,
+ keys[i].func == kbspawn ? GrabModeSync : GrabModeAsync);
}
}
ev = &e->xkey;
keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0);
- for(i = 0; i < LENGTH(keys); i++)
+ for(i = 0; i < LENGTH(keys); i++) {
if(keysym == keys[i].keysym
&& CLEANMASK(keys[i].mod) == CLEANMASK(ev->state)
- && keys[i].func)
+ && keys[i].func) {
keys[i].func(&(keys[i].arg));
+ }
+ }
}
void
applyrules(c);
}
/* geometry */
- c->x = c->oldx = wa->x;
- c->y = c->oldy = wa->y;
+ if(c->x == -1 && c->y == -2) { // secret code for centered
+ c->x = c->oldx = (c->mon->ww - wa->width) / 2;
+ c->y = c->oldy = (c->mon->wh - wa->height) / 2;
+ } else {
+ c->x = c->oldx = wa->x;
+ c->y = c->oldy = wa->y;
+ }
c->w = c->oldw = wa->width;
c->h = c->oldh = wa->height;
c->oldbw = wa->border_width;
arrange(c->mon);
XMapWindow(dpy, c->win);
focus(c);
+ if(key_buffering) {
+ key_buffering = False;
+ XAllowEvents(dpy, AsyncKeyboard, CurrentTime);
+ }
}
void
mappingnotify(XEvent *e) {
XMappingEvent *ev = &e->xmapping;
+ // fprintf(stderr, "MapNotify\n");
XRefreshKeyboardMapping(ev);
if(ev->request == MappingKeyboard)
static XWindowAttributes wa;
XMapRequestEvent *ev = &e->xmaprequest;
+ // fprintf(stderr, "MapRequest\n");
if(!XGetWindowAttributes(dpy, ev->window, &wa))
return;
- if(wa.override_redirect)
+ if(wa.override_redirect) {
return;
+ }
if(!wintoclient(ev->window))
manage(ev->window, &wa);
}
XEvent ev;
/* main event loop */
XSync(dpy, False);
- while(running && !XNextEvent(dpy, &ev))
- if(handler[ev.type])
+ while(running && !XNextEvent(dpy, &ev)) {
+ if(handler[ev.type]) {
+ // fprintf(stderr, "handling event type %i\n", ev.type);
handler[ev.type](&ev); /* call handler */
+ } else {
+ // fprintf(stderr, "evt type %i\n", ev.type);
+ }
+ }
}
void
}
void
+kbspawn(const Arg *arg) {
+ key_buffering = True;
+ spawn(arg);
+}
+
+void
spawn(const Arg *arg) {
int tag = 0, i;
- if(arg->v == termcmd) {
+ if(arg->v == termcmd || arg->v == runcmd) {
for(i = 0; i < 32; ++i) {
if(selmon->tagset[selmon->seltags] & (1 << i)) {
tag = i;
}
}
WORKSPACE_NUMBER[17] = workspace_numbers_str[tag][0];
- WORKSPACE_NUMBER[18] = workspace_numbers_str[tag][1];
+ WORKSPACE_NUMBER[18] = workspace_numbers_str[tag][1]; // 2nd digit or null
}
if(arg->v == dmenucmd)
dmenumon[0] = '0' + selmon->num;
}
}
-#define TAB_HEIGHT 19
-#define TAB_PAD 7
+#define GUTTER_PX 4
+#define TAB_HEIGHT (bh / 2 - GUTTER_PX)
+#define TAB_PAD GUTTER_PX
void
jason_layout(Monitor *m) {
} else {
mw = m->ww;
}
- right_width = m->ww - mw;
+ right_width = m->ww - mw - GUTTER_PX;
tab_count = &(tab_counts[0]);
- tab_top = m->wy - (m->wh - (2 * (TAB_HEIGHT + TAB_PAD))) + TAB_HEIGHT;
+ tab_top = m->my - m->wh + TAB_HEIGHT;
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, 0);
} else {
if (c == vis_slave) {
- resize(c, m->wx + mw, m->wy + TAB_HEIGHT + TAB_PAD, right_width, m->wh - 2 * (TAB_HEIGHT + TAB_PAD), False, base);
+ resize(c,
+ m->wx + mw + GUTTER_PX,
+ m->my + TAB_HEIGHT + TAB_PAD,
+ right_width,
+ m->wh,
+ False,
+ base
+ );
tab_count = &(tab_counts[1]);
- tab_top = m->wy + m->wh - TAB_HEIGHT;
+ tab_top = m->my + m->mh - TAB_HEIGHT;
cur_tab = 0;
} 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 + right_width * cur_tab / (*tab_count), tab_top, right_width, m->wh - 2 * (TAB_HEIGHT + TAB_PAD), False, base);
+ resize(c,
+ m->wx + mw + GUTTER_PX + right_width * cur_tab / (*tab_count),
+ tab_top,
+ right_width,
+ m->wh,
+ False,
+ base
+ );
cur_tab += 1;
}
}
for(m = mons; m; m = m->next) {
if (m->barwin)
continue;
- m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen),
+ m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww * m->mfact, bh, 0, DefaultDepth(dpy, screen),
CopyFromParent, DefaultVisual(dpy, screen),
CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa);
XChangeProperty(dpy, root, netatom[NetSupportingWMCheck], XA_WINDOW, 32,