Compare commits

..

37 Commits
3.1 ... 3.4

Author SHA1 Message Date
9ed5de00b6 removed debug flags 2007-02-07 12:37:21 +01:00
28ffff801b replaced getproto with a saner function, now old-school artifacts of WM times in the early 90s completely disappeared, no punned pointer warning anymore ;) 2007-02-07 12:37:06 +01:00
44ef3f5a07 yet another fix 2007-02-06 15:29:19 +01:00
dafbd0dcb0 simplification 2007-02-06 15:28:25 +01:00
2ddc78720a implemented aspect ratio support of windows 2007-02-06 15:22:13 +01:00
7ece30ebc0 made some changes more concistent 2007-02-05 11:19:46 +01:00
3d48f33025 got rid of LD (inspired by JGs patch to wmii) 2007-02-05 11:09:53 +01:00
19fd903d40 applied apm's patch proposal, getting rid of XDrawLines 2007-02-05 11:05:16 +01:00
5732e471ae Added tag 3.3 for changeset 0f91934037b0 2007-02-01 08:23:00 +01:00
042297b27b applied Sander's drop_bh patch 2007-01-31 20:08:55 +01:00
a5cb80b86c handling WM_STATE seems to make DnD in gtk/qt apps working, well let's handle this in dwm as well 2007-01-28 20:29:41 +01:00
7e98db251e regarding to http://plan9.bell-labs.com/sources/contrib/rsc/man.ps the BUGS section should appear after SEE ALSO section. 2007-01-26 12:41:15 +01:00
bced9077f9 renamed CAVEATS into BUGS 2007-01-26 12:31:57 +01:00
82fed986f9 Added tag 3.2.2 for changeset d3876aa79292 2007-01-25 10:05:02 +01:00
2c1db7ed35 prepared yet another hotfix release 2007-01-25 09:59:48 +01:00
ea4827a578 Added tag 3.2.1 for changeset f2cabc83a18f 2007-01-24 17:25:37 +01:00
55be4d6137 hotfix release 3.2.1 2007-01-24 17:25:30 +01:00
1f18466409 applied offscreen appearance hotfix 2007-01-24 17:24:55 +01:00
b65a1e3379 Added tag 3.2 for changeset 4ce65f61f01b 2007-01-24 12:12:29 +01:00
87836d79ef renamed activescreen into selscreen 2007-01-23 17:12:15 +01:00
c8a12a0852 implemented Sanders remarks 2007-01-23 13:10:35 +01:00
71b84c2114 small changes 2007-01-23 12:29:17 +01:00
edb2660a2e removed a blank line 2007-01-23 12:04:22 +01:00
17ec726b49 this version should also work with cornercases (like unmanage during !issel, etc.) 2007-01-23 12:00:49 +01:00
373b11de11 I think this is the best solution of multihead support 2007-01-23 11:49:16 +01:00
04a2b74529 darker border 2007-01-22 16:02:37 +01:00
fcd98308ba this variant is known to work, but focus() is ugly - we need in general a better way to handle multihead, this issel-stuff looks awkward (maybe it might be a good idea to set sel to NULL but to introduce a Client *revert which is set if a screen is unfocused, have to think about it further). 2007-01-22 10:35:58 +01:00
b233089815 applied Sanders all5.patch (thanks for your weekend session, Sander!) 2007-01-22 10:22:58 +01:00
201c56f6d3 leavenotify also don't needs the check 2007-01-19 15:05:07 +01:00
1e051d71f5 deciding for focus(NULL); 2007-01-19 15:01:51 +01:00
ddc79603f9 replaced XSetBorder.../focus() 2007-01-19 14:38:09 +01:00
dee5ea2335 yet another multihead fix by Christof Musik 2007-01-19 14:36:25 +01:00
b1c9f5f144 I prefer BORDERPX=1 2007-01-19 08:05:39 +01:00
a542bdf658 personally I prefer 2px borders 2007-01-18 11:46:39 +01:00
96e1b25c8c applied a modified version of Christof Musik's multihead patch (though this is not sure if it works in all cases, have to wait for an ACK by Christof) 2007-01-18 11:11:40 +01:00
caf5a16271 moved BORDERPX to config.*.h 2007-01-17 12:36:29 +01:00
936e11fd54 Added tag 3.1 for changeset e1c8bef05e6e 2007-01-16 11:41:56 +01:00
12 changed files with 171 additions and 146 deletions

View File

@ -30,3 +30,8 @@ c7f84f23ec5aef29988dcdc4ec22a7352ee8f58e 2.5.1
107719a9ce3bd0c79f9f1f626596eb338a276561 2.8
3a5910fac3ccb522a98aeeba7af7008530b25092 2.9
76b58d21ea98257c05565a3b9c850b9b26a32968 3.0
e1c8bef05e6e48df4f26471ea0712aa43ab9d949 3.1
4ce65f61f01b055fa6c2901c6d2527ef741aa4bf 3.2
f2cabc83a18f9b5b548159329ddd4dee904fa31f 3.2.1
d3876aa792923f9a95f7ad0c7f0134533404df35 3.2.2
0f91934037b04221ff5d1ba3a6c39c1ff26e3661 3.3

View File

@ -13,7 +13,6 @@ options:
@echo "CFLAGS = ${CFLAGS}"
@echo "LDFLAGS = ${LDFLAGS}"
@echo "CC = ${CC}"
@echo "LD = ${LD}"
.c.o:
@echo CC $<
@ -26,8 +25,8 @@ config.h:
@cp config.default.h $@
dwm: ${OBJ}
@echo LD $@
@${LD} -o $@ ${OBJ} ${LDFLAGS}
@echo CC -o $@
@${CC} -o $@ ${OBJ} ${LDFLAGS}
@strip $@
clean:

150
client.c
View File

@ -7,7 +7,7 @@
#include <X11/Xatom.h>
#include <X11/Xutil.h>
/* static functions */
/* static */
static void
detachstack(Client *c) {
@ -53,12 +53,19 @@ grabbuttons(Client *c, Bool focused) {
GrabModeAsync, GrabModeSync, None, None);
}
static void
setclientstate(Client *c, long state) {
long data[] = {state, None};
XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32,
PropModeReplace, (unsigned char *)data, 2);
}
static int
xerrordummy(Display *dsply, XErrorEvent *ee) {
return 0;
}
/* extern functions */
/* extern */
void
configure(Client *c) {
@ -79,31 +86,28 @@ configure(Client *c) {
void
focus(Client *c) {
Client *old;
if(!issel || (c && !isvisible(c)))
if(c && !isvisible(c))
return;
if(!sel)
sel = c;
else if(sel != c) {
old = sel;
sel = c;
if(old) {
grabbuttons(old, False);
XSetWindowBorder(dpy, old->win, dc.norm[ColBorder]);
}
if(sel && sel != c) {
grabbuttons(sel, False);
XSetWindowBorder(dpy, sel->win, dc.norm[ColBorder]);
}
if(c) {
detachstack(c);
c->snext = stack;
stack = c;
grabbuttons(c, True);
}
sel = c;
drawstatus();
if(!selscreen)
return;
if(c) {
XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]);
XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
}
else
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
drawstatus();
}
Client *
@ -116,11 +120,26 @@ getclient(Window w) {
return NULL;
}
Bool
isprotodel(Client *c) {
int i, n;
Atom *protocols;
Bool ret = False;
if(XGetWMProtocols(dpy, c->win, &protocols, &n)) {
for(i = 0; !ret && i < n; i++)
if(protocols[i] == wmatom[WMDelete])
ret = True;
XFree(protocols);
}
return ret;
}
void
killclient(Arg *arg) {
if(!sel)
return;
if(sel->proto & PROTODELWIN)
if(isprotodel(sel))
sendevent(sel->win, wmatom[WMProtocols], wmatom[WMDelete]);
else
XKillClient(dpy, sel->win);
@ -134,25 +153,32 @@ manage(Window w, XWindowAttributes *wa) {
c = emallocz(sizeof(Client));
c->tags = emallocz(ntags * sizeof(Bool));
c->win = w;
c->border = 0;
c->x = wa->x;
c->y = wa->y;
c->w = wa->width;
c->h = wa->height;
updatesizehints(c);
if(c->x + c->w + 2 * BORDERPX > sw)
c->x = sw - c->w - 2 * BORDERPX;
if(c->x < sx)
if(c->w == sw && c->h == sh) {
c->border = 0;
c->x = sx;
if(c->y + c->h + 2 * BORDERPX > sh)
c->y = sh - c->h - 2 * BORDERPX;
if(c->h != sh && c->y < bh)
c->y = bh;
c->proto = getproto(c->win);
c->y = sy;
}
else {
c->border = BORDERPX;
if(c->x + c->w + 2 * c->border > wax + waw)
c->x = wax + waw - c->w - 2 * c->border;
if(c->y + c->h + 2 * c->border > way + wah)
c->y = way + wah - c->h - 2 * c->border;
if(c->x < wax)
c->x = wax;
if(c->y < way)
c->y = way;
}
updatesizehints(c);
XSelectInput(dpy, c->win,
StructureNotifyMask | PropertyChangeMask | EnterWindowMask);
XGetTransientForHint(dpy, c->win, &trans);
grabbuttons(c, False);
XSetWindowBorder(dpy, c->win, dc.norm[ColBorder]);
updatetitle(c);
settags(c, getclient(trans));
if(!c->isfloat)
@ -164,22 +190,20 @@ manage(Window w, XWindowAttributes *wa) {
stack = clients = c;
XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
XMapWindow(dpy, c->win);
setclientstate(c, NormalState);
if(isvisible(c))
focus(c);
arrange();
}
void
resize(Client *c, Bool sizehints, Corner sticky) {
int bottom = c->y + c->h;
int right = c->x + c->w;
resize(Client *c, Bool sizehints) {
float actual, dx, dy, max, min;
XWindowChanges wc;
if(c->w <= 0 || c->h <= 0)
return;
if(sizehints) {
if(c->incw)
c->w -= (c->w - c->basew) % c->incw;
if(c->inch)
c->h -= (c->h - c->baseh) % c->inch;
if(c->minw && c->w < c->minw)
c->w = c->minw;
if(c->minh && c->h < c->minh)
@ -188,28 +212,51 @@ resize(Client *c, Bool sizehints, Corner sticky) {
c->w = c->maxw;
if(c->maxh && c->h > c->maxh)
c->h = c->maxh;
/* inspired by algorithm from fluxbox */
if(c->minay > 0 && c->maxay && (c->h - c->baseh) > 0) {
dx = (float)(c->w - c->basew);
dy = (float)(c->h - c->baseh);
min = (float)(c->minax) / (float)(c->minay);
max = (float)(c->maxax) / (float)(c->maxay);
actual = dx / dy;
if(max > 0 && min > 0 && actual > 0) {
if(actual < min) {
dy = (dx * min + dy) / (min * min + 1);
dx = dy * min;
c->w = (int)dx + c->basew;
c->h = (int)dy + c->baseh;
}
else if(actual > max) {
dy = (dx * min + dy) / (max * max + 1);
dx = dy * min;
c->w = (int)dx + c->basew;
c->h = (int)dy + c->baseh;
}
}
}
if(c->incw)
c->w -= (c->w - c->basew) % c->incw;
if(c->inch)
c->h -= (c->h - c->baseh) % c->inch;
}
if(sticky == TopRight || sticky == BotRight)
c->x = right - c->w;
if(sticky == BotLeft || sticky == BotRight)
c->y = bottom - c->h;
if(c->w == sw && c->h == sh)
c->border = 0;
else
c->border = BORDERPX;
/* offscreen appearance fixes */
if(c->x + c->w < sx)
c->x = sx;
if(c->y + c->h < bh)
c->y = bh;
if(c->x > sw)
c->x = sw - c->w;
c->x = sw - c->w - 2 * c->border;
if(c->y > sh)
c->y = sh - c->h;
c->y = sh - c->h - 2 * c->border;
if(c->x + c->w + 2 * c->border < sx)
c->x = sx;
if(c->y + c->h + 2 * c->border < sy)
c->y = sy;
wc.x = c->x;
wc.y = c->y;
wc.width = c->w;
wc.height = c->h;
if(c->w == sw && c->h == sh)
wc.border_width = 0;
else
wc.border_width = BORDERPX;
wc.border_width = c->border;
XConfigureWindow(dpy, c->win, CWX | CWY | CWWidth | CWHeight | CWBorderWidth, &wc);
configure(c);
XSync(dpy, False);
@ -247,6 +294,14 @@ updatesizehints(Client *c) {
}
else
c->minw = c->minh = 0;
if(c->flags & PAspect) {
c->minax = size.min_aspect.x;
c->minay = size.min_aspect.y;
c->maxax = size.max_aspect.x;
c->maxay = size.max_aspect.y;
}
else
c->minax = c->minay = c->maxax = c->maxay = 0;
c->isfixed = (c->maxw && c->minw && c->maxh && c->minh &&
c->maxw == c->minw && c->maxh == c->minh);
}
@ -291,6 +346,7 @@ unmanage(Client *c) {
focus(nc);
}
XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
setclientstate(c, WithdrawnState);
free(c->tags);
free(c);
XSync(dpy, False);

View File

@ -5,6 +5,7 @@
#define TAGS \
const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL };
#define BORDERPX 1
#define DEFMODE dotile /* dofloat */
#define FLOATSYMBOL "><>"
#define TILESYMBOL "[]="
@ -13,7 +14,7 @@ const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL };
#define NORMBORDERCOLOR "#333"
#define NORMBGCOLOR "#222"
#define NORMFGCOLOR "#ccc"
#define SELBORDERCOLOR "#9cf"
#define SELBORDERCOLOR "#69c"
#define SELBGCOLOR "#555"
#define SELFGCOLOR "#fff"

View File

@ -5,6 +5,7 @@
#define TAGS \
const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9", NULL };
#define BORDERPX 1
#define DEFMODE dotile /* dofloat */
#define FLOATSYMBOL "><>"
#define TILESYMBOL "[]="

View File

@ -1,5 +1,5 @@
# dwm version
VERSION = 3.1
VERSION = 3.4
# Customize below to fit your system
@ -27,4 +27,3 @@ LDFLAGS = ${LIBS}
# compiler and linker
CC = cc
LD = ${CC}

18
draw.c
View File

@ -35,7 +35,6 @@ drawtext(const char *text, unsigned long col[ColLast], Bool filledsquare, Bool e
unsigned int len, olen;
XGCValues gcv;
XRectangle r = { dc.x, dc.y, dc.w, dc.h };
XPoint pt[5];
XSetForeground(dpy, dc.gc, col[ColBG]);
XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
@ -74,24 +73,15 @@ drawtext(const char *text, unsigned long col[ColLast], Bool filledsquare, Bool e
XDrawString(dpy, dc.drawable, dc.gc, x, y, buf, len);
}
x = (h + 2) / 4;
r.x = dc.x + 1;
r.y = dc.y + 1;
if(filledsquare) {
r.x = dc.x + 1;
r.y = dc.y + 1;
r.width = r.height = x + 1;
XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1);
}
else if(emptysquare) {
pt[0].x = dc.x + 1;
pt[0].y = dc.y + 1;
pt[1].x = x;
pt[1].y = 0;
pt[2].x = 0;
pt[2].y = x;
pt[3].x = -x;
pt[3].y = 0;
pt[4].x = 0;
pt[4].y = -x;
XDrawLines(dpy, dc.drawable, dc.gc, pt, 5, CoordModePrevious);
r.width = r.height = x;
XDrawRectangles(dpy, dc.drawable, dc.gc, &r, 1);
}
}

8
dwm.1
View File

@ -25,7 +25,7 @@ window are indicated with a filled square in the top left corner. The tags
which are applied to one or more windows are indicated with an empty square in
the top left corner.
.P
dwm draws a 1-pixel border around windows to indicate the focus state.
dwm draws a small border around windows to indicate the focus state.
.SH OPTIONS
.TP
.B \-v
@ -131,7 +131,9 @@ Resize current window while dragging (floating mode only).
.SH CUSTOMIZATION
dwm is customized by creating a custom config.h and (re)compiling the source
code. This keeps it fast, secure and simple.
.SH CAVEATS
.SH SEE ALSO
.BR dmenu (1)
.SH BUGS
The status bar may display
.BR "EOF"
when dwm has been started by an X session manager like
@ -145,5 +147,3 @@ you can use JDK 1.4 (which doesn't contain the XToolkit/XAWT backend) or you
can set the following environment variable (to use the older Motif
backend instead):
.BR AWT_TOOLKIT=MToolkit .
.SH SEE ALSO
.BR dmenu (1)

19
dwm.h
View File

@ -36,19 +36,12 @@
/* mask shorthands, used in event.c and client.c */
#define BUTTONMASK (ButtonPressMask | ButtonReleaseMask)
/* other stuff used in different places */
#define BORDERPX 1
#define PROTODELWIN 1
enum { NetSupported, NetWMName, NetLast }; /* EWMH atoms */
enum { WMProtocols, WMDelete, WMLast }; /* default atoms */
enum { WMProtocols, WMDelete, WMState, WMLast }; /* default atoms */
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
enum { ColBorder, ColFG, ColBG, ColLast }; /* color */
typedef enum {
TopLeft, TopRight, BotLeft, BotRight
} Corner; /* window corners */
typedef union {
const char *cmd;
int i;
@ -74,13 +67,13 @@ typedef struct {
typedef struct Client Client;
struct Client {
char name[256];
int proto;
int x, y, w, h;
int rx, ry, rw, rh; /* revert geometry */
int basew, baseh, incw, inch, maxw, maxh, minw, minh;
int minax, minay, maxax, maxay;
long flags;
unsigned int border;
Bool isfloat, isfixed, ismax;
Bool isfixed, isfloat, ismax;
Bool *tags;
Client *next;
Client *prev;
@ -98,7 +91,7 @@ extern unsigned int ntags, numlockmask; /* number of tags, dynamic lock mask */
extern void (*handler[LASTEvent])(XEvent *); /* event handler */
extern void (*arrange)(void); /* arrange function, indicates mode */
extern Atom wmatom[WMLast], netatom[NetLast];
extern Bool running, issel, *seltag; /* seltag is array of Bool */
extern Bool running, selscreen, *seltag; /* seltag is array of Bool */
extern Client *clients, *sel, *stack; /* global client list and stack */
extern Cursor cursor[CurLast];
extern DC dc; /* global draw context */
@ -109,9 +102,10 @@ extern Window root, barwin;
extern void configure(Client *c); /* send synthetic configure event */
extern void focus(Client *c); /* focus c, c may be NULL */
extern Client *getclient(Window w); /* return client of w */
extern Bool isprotodel(Client *c); /* returns True if c->win supports wmatom[WMDelete] */
extern void killclient(Arg *arg); /* kill c nicely */
extern void manage(Window w, XWindowAttributes *wa); /* manage new client */
extern void resize(Client *c, Bool sizehints, Corner sticky); /* resize c*/
extern void resize(Client *c, Bool sizehints); /* resize c*/
extern void updatesizehints(Client *c); /* update the size hint variables of c */
extern void updatetitle(Client *c); /* update the name of c */
extern void unmanage(Client *c); /* destroy c */
@ -127,7 +121,6 @@ extern void grabkeys(void); /* grab all keys defined in config.h */
extern void procevent(void); /* process pending X events */
/* main.c */
extern int getproto(Window w); /* return protocol mask of WMProtocols property of w */
extern void quit(Arg *arg); /* quit dwm nicely */
extern void sendevent(Window w, Atom a, long value); /* send synthetic event to w */
extern int xerror(Display *dsply, XErrorEvent *ee); /* dwm's X error handler */

62
event.c
View File

@ -35,14 +35,16 @@ movemouse(Client *c) {
c->ismax = False;
XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui);
for(;;) {
XMaskEvent(dpy, MOUSEMASK | ExposureMask, &ev);
XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask, &ev);
switch (ev.type) {
case ButtonRelease:
resize(c, True, TopLeft);
resize(c, True);
XUngrabPointer(dpy, CurrentTime);
return;
case ConfigureRequest:
case Expose:
handler[Expose](&ev);
case MapRequest:
handler[ev.type](&ev);
break;
case MotionNotify:
XSync(dpy, False);
@ -50,13 +52,13 @@ movemouse(Client *c) {
c->y = ocy + (ev.xmotion.y - y1);
if(abs(wax + c->x) < SNAP)
c->x = wax;
else if(abs((wax + waw) - (c->x + c->w)) < SNAP)
c->x = wax + waw - c->w - 2 * BORDERPX;
else if(abs((wax + waw) - (c->x + c->w + 2 * c->border)) < SNAP)
c->x = wax + waw - c->w - 2 * c->border;
if(abs(way - c->y) < SNAP)
c->y = way;
else if(abs((way + wah) - (c->y + c->h)) < SNAP)
c->y = way + wah - c->h - 2 * BORDERPX;
resize(c, False, TopLeft);
else if(abs((way + wah) - (c->y + c->h + 2 * c->border)) < SNAP)
c->y = way + wah - c->h - 2 * c->border;
resize(c, False);
break;
}
}
@ -66,7 +68,6 @@ static void
resizemouse(Client *c) {
int ocx, ocy;
int nw, nh;
Corner sticky;
XEvent ev;
ocx = c->x;
@ -75,30 +76,26 @@ resizemouse(Client *c) {
None, cursor[CurResize], CurrentTime) != GrabSuccess)
return;
c->ismax = False;
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w, c->h);
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->border - 1, c->h + c->border - 1);
for(;;) {
XMaskEvent(dpy, MOUSEMASK | ExposureMask, &ev);
XMaskEvent(dpy, MOUSEMASK | ExposureMask | SubstructureRedirectMask , &ev);
switch(ev.type) {
case ButtonRelease:
resize(c, True, TopLeft);
resize(c, True);
XUngrabPointer(dpy, CurrentTime);
return;
case ConfigureRequest:
case Expose:
handler[Expose](&ev);
case MapRequest:
handler[ev.type](&ev);
break;
case MotionNotify:
XSync(dpy, False);
if((nw = abs(ocx - ev.xmotion.x)))
c->w = nw;
if((nh = abs(ocy - ev.xmotion.y)))
c->h = nh;
c->x = (ocx <= ev.xmotion.x) ? ocx : ocx - c->w;
c->y = (ocy <= ev.xmotion.y) ? ocy : ocy - c->h;
if(ocx <= ev.xmotion.x)
sticky = (ocy <= ev.xmotion.y) ? TopLeft : BotLeft;
else
sticky = (ocy <= ev.xmotion.y) ? TopRight : BotRight;
resize(c, True, sticky);
nw = ev.xmotion.x - ocx - 2 * c->border + 1;
c->w = nw > 0 ? nw : 1;
nh = ev.xmotion.y - ocy - 2 * c->border + 1;
c->h = nh > 0 ? nh : 1;
resize(c, True);
break;
}
}
@ -194,7 +191,7 @@ configurerequest(XEvent *e) {
configure(c);
XSync(dpy, False);
if(c->isfloat) {
resize(c, False, TopLeft);
resize(c, False);
if(!isvisible(c))
XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
}
@ -233,8 +230,9 @@ enternotify(XEvent *e) {
if((c = getclient(ev->window)) && isvisible(c))
focus(c);
else if(ev->window == root) {
issel = True;
XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
selscreen = True;
for(c = stack; c && !isvisible(c); c = c->snext);
focus(c);
}
}
@ -270,8 +268,10 @@ static void
leavenotify(XEvent *e) {
XCrossingEvent *ev = &e->xcrossing;
if((ev->window == root) && !ev->same_screen)
issel = False;
if((ev->window == root) && !ev->same_screen) {
selscreen = False;
focus(NULL);
}
}
static void
@ -308,10 +308,6 @@ propertynotify(XEvent *e) {
if(ev->state == PropertyDelete)
return; /* ignore */
if((c = getclient(ev->window))) {
if(ev->atom == wmatom[WMProtocols]) {
c->proto = getproto(c->win);
return;
}
switch (ev->atom) {
default: break;
case XA_WM_TRANSIENT_FOR:

25
main.c
View File

@ -23,7 +23,7 @@ int bh, bmw, screen, sx, sy, sw, sh, wax, way, waw, wah;
unsigned int master, nmaster, ntags, numlockmask;
Atom wmatom[WMLast], netatom[NetLast];
Bool running = True;
Bool issel = True;
Bool selscreen = True;
Client *clients = NULL;
Client *sel = NULL;
Client *stack = NULL;
@ -41,7 +41,7 @@ static void
cleanup(void) {
close(STDIN_FILENO);
while(stack) {
resize(stack, True, TopLeft);
resize(stack, True);
unmanage(stack);
}
if(dc.font.set)
@ -92,6 +92,7 @@ setup(void) {
/* init atoms */
wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False);
netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
@ -156,7 +157,7 @@ setup(void) {
dc.gc = XCreateGC(dpy, root, 0, 0);
XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
/* multihead support */
issel = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask);
selscreen = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask);
}
/*
@ -171,24 +172,6 @@ xerrorstart(Display *dsply, XErrorEvent *ee) {
/* extern */
int
getproto(Window w) {
int i, format, protos, status;
unsigned long extra, res;
Atom *protocols, real;
protos = 0;
status = XGetWindowProperty(dpy, w, wmatom[WMProtocols], 0L, 20L, False,
XA_ATOM, &real, &format, &res, &extra, (unsigned char **)&protocols);
if(status != Success || protocols == 0)
return protos;
for(i = 0; i < res; i++)
if(protocols[i] == wmatom[WMDelete])
protos |= PROTODELWIN;
free(protocols);
return protos;
}
void
sendevent(Window w, Atom a, long value) {
XEvent e;

18
view.c
View File

@ -31,7 +31,7 @@ togglemax(Client *c) {
c->w = c->rw;
c->h = c->rh;
}
resize(c, True, TopLeft);
resize(c, True);
while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
}
@ -56,7 +56,7 @@ dofloat(void) {
for(c = clients; c; c = c->next) {
if(isvisible(c)) {
resize(c, True, TopLeft);
resize(c, True);
}
else
XMoveWindow(dpy, c->win, c->x + 2 * sw, c->y);
@ -84,7 +84,7 @@ dotile(void) {
for(i = 0, c = clients; c; c = c->next)
if(isvisible(c)) {
if(c->isfloat) {
resize(c, True, TopLeft);
resize(c, True);
continue;
}
c->ismax = False;
@ -98,14 +98,14 @@ dotile(void) {
else { /* tile window */
c->x += mw;
c->w = tw - 2 * BORDERPX;
if(th > bh) {
if(th > 2 * BORDERPX) {
c->y += (i - nmaster) * th;
c->h = th - 2 * BORDERPX;
}
else /* fallback if th < bh */
else /* fallback if th <= 2 * BORDERPX */
c->h = wah - 2 * BORDERPX;
}
resize(c, False, TopLeft);
resize(c, False);
i++;
}
else
@ -149,7 +149,8 @@ focusprev(Arg *arg) {
void
incnmaster(Arg *arg) {
if((arrange == dofloat) || (nmaster + arg->i < 1) || (wah / (nmaster + arg->i) < bh))
if((arrange == dofloat) || (nmaster + arg->i < 1)
|| (wah / (nmaster + arg->i) <= 2 * BORDERPX))
return;
nmaster += arg->i;
if(sel)
@ -173,7 +174,8 @@ resizemaster(Arg *arg) {
if(arg->i == 0)
master = MASTER;
else {
if(master + arg->i > 950 || master + arg->i < 50)
if(waw * (master + arg->i) / 1000 >= waw - 2 * BORDERPX
|| waw * (master + arg->i) / 1000 <= 2 * BORDERPX)
return;
master += arg->i;
}