#endif /* XINERAMA */
/* macros */
-#define D if(1)
#define BUTTONMASK (ButtonPressMask|ButtonReleaseMask)
#define CLEANMASK(mask) (mask & ~(numlockmask|LockMask))
#define INRECT(X,Y,RX,RY,RW,RH) ((X) >= (RX) && (X) < (RX) + (RW) && (Y) >= (RY) && (Y) < (RY) + (RH))
/* enums */
enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */
enum { ColBorder, ColFG, ColBG, ColLast }; /* color */
-enum { NetSupported, NetWMName, NetLast }; /* EWMH atoms */
+enum { NetSupported, NetWMName, NetWMState,
+ NetWMFullscreen, NetLast }; /* EWMH atoms */
enum { WMProtocols, WMDelete, WMState, WMLast }; /* default atoms */
enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle,
ClkClientWin, ClkRootWin, ClkLast }; /* clicks */
char name[256];
float mina, maxa;
int x, y, w, h;
+ int oldx, oldy, oldw, oldh;
int basew, baseh, incw, inch, maxw, maxh, minw, minh;
int bw, oldbw;
unsigned int tags;
- Bool isfixed, isfloating, isurgent;
+ Bool isfixed, isfloating, isurgent, oldstate;
Client *next;
Client *snext;
Monitor *mon;
static void cleanup(void);
static void cleanupmon(Monitor *mon);
static void clearurgent(Client *c);
+static void clientmessage(XEvent *e);
static void configure(Client *c);
static void configurenotify(XEvent *e);
static void configurerequest(XEvent *e);
static void propertynotify(XEvent *e);
static void quit(const Arg *arg);
static void resize(Client *c, int x, int y, int w, int h, Bool interact);
+static void resizeclient(Client *c, int x, int y, int w, int h);
static void resizemouse(const Arg *arg);
static void restack(Monitor *m);
static void run(void);
static void togglefloating(const Arg *arg);
static void toggletag(const Arg *arg);
static void toggleview(const Arg *arg);
-static void unfocus(Client *c);
+static void unfocus(Client *c, Bool setfocus);
static void unmanage(Client *c, Bool destroyed);
static void unmapnotify(XEvent *e);
static Bool updategeom(void);
static unsigned int numlockmask = 0;
static void (*handler[LASTEvent]) (XEvent *) = {
[ButtonPress] = buttonpress,
+ [ClientMessage] = clientmessage,
[ConfigureRequest] = configurerequest,
[ConfigureNotify] = configurenotify,
[DestroyNotify] = destroynotify,
click = ClkRootWin;
/* focus monitor if necessary */
if((m = wintomon(ev->window)) && m != selmon) {
- unfocus(selmon->sel);
+ unfocus(selmon->sel, True);
selmon = m;
focus(NULL);
}
void
enternotify(XEvent *e) {
- Client *c;
Monitor *m;
XCrossingEvent *ev = &e->xcrossing;
if((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root)
return;
if((m = wintomon(ev->window)) && m != selmon) {
- unfocus(selmon->sel);
+ unfocus(selmon->sel, True);
selmon = m;
}
- if((c = wintoclient(ev->window)))
- focus(c);
- else
- focus(NULL);
+ focus(wintoclient(ev->window));
}
void
focus(Client *c) {
if(!c || !ISVISIBLE(c))
for(c = selmon->stack; c && !ISVISIBLE(c); c = c->snext);
-/* if(selmon->sel)
- unfocus(selmon->sel);*/
+ /* was if(selmon->sel) */
+ if(selmon->sel && selmon->sel != c)
+ unfocus(selmon->sel, False);
if(c) {
if(c->mon != selmon)
selmon = c->mon;
if(!mons->next)
return;
- m = dirtomon(arg->i);
- unfocus(selmon->sel);
+ if((m = dirtomon(arg->i)) == selmon)
+ return;
+ unfocus(selmon->sel, True);
selmon = m;
focus(NULL);
}
long
getstate(Window w) {
- int format, status;
+ int format;
long result = -1;
unsigned char *p = NULL;
unsigned long n, extra;
Atom real;
- status = XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState],
- &real, &format, &n, &extra, (unsigned char **)&p);
- if(status != Success)
+ if(XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState],
+ &real, &format, &n, &extra, (unsigned char **)&p) != Success)
return -1;
if(n != 0)
result = *p;
applyrules(c);
}
/* geometry */
- c->x = wa->x + c->mon->wx;
- c->y = wa->y + c->mon->wy;
- c->w = wa->width;
- c->h = wa->height;
+ c->x = c->oldx = wa->x + c->mon->wx;
+ c->y = c->oldy = wa->y + c->mon->wy;
+ c->w = c->oldw = wa->width;
+ c->h = c->oldh = wa->height;
c->oldbw = wa->border_width;
if(c->w == c->mon->mw && c->h == c->mon->mh) {
+ c->isfloating = 1;
c->x = c->mon->mx;
c->y = c->mon->my;
c->bw = 0;
XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
grabbuttons(c, False);
if(!c->isfloating)
- c->isfloating = trans != None || c->isfixed;
+ c->isfloating = c->oldstate = trans != None || c->isfixed;
if(c->isfloating)
XRaiseWindow(dpy, c->win);
attach(c);
}
}
+void
+clientmessage(XEvent *e) {
+ XClientMessageEvent *cme = &e->xclient;
+ Client *c;
+
+ if((c = wintoclient(cme->window))
+ && (cme->message_type == netatom[NetWMState] && cme->data.l[1] == netatom[NetWMFullscreen]))
+ {
+ if(cme->data.l[0]) {
+ XChangeProperty(dpy, cme->window, netatom[NetWMState], XA_ATOM, 32,
+ PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1);
+ c->oldstate = c->isfloating;
+ c->oldbw = c->bw;
+ c->bw = 0;
+ c->isfloating = 1;
+ resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh);
+ XRaiseWindow(dpy, c->win);
+ }
+ else {
+ XChangeProperty(dpy, cme->window, netatom[NetWMState], XA_ATOM, 32,
+ PropModeReplace, (unsigned char*)0, 0);
+ c->isfloating = c->oldstate;
+ c->bw = c->oldbw;
+ c->x = c->oldx;
+ c->y = c->oldy;
+ c->w = c->oldw;
+ c->h = c->oldh;
+ resizeclient(c, c->x, c->y, c->w, c->h);
+ arrange(c->mon);
+ }
+ }
+}
+
void
quit(const Arg *arg) {
running = False;
void
resize(Client *c, int x, int y, int w, int h, Bool interact) {
+ if(applysizehints(c, &x, &y, &w, &h, interact))
+ resizeclient(c, x, y, w, h);
+}
+
+void
+resizeclient(Client *c, int x, int y, int w, int h) {
XWindowChanges wc;
- if(applysizehints(c, &x, &y, &w, &h, interact)) {
- c->x = wc.x = x;
- c->y = wc.y = y;
- c->w = wc.width = w;
- c->h = wc.height = h;
- wc.border_width = c->bw;
- XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
- configure(c);
- XSync(dpy, False);
- }
+ c->oldx = c->x; c->x = wc.x = x;
+ c->oldy = c->y; c->y = wc.y = y;
+ c->oldw = c->w; c->w = wc.width = w;
+ c->oldh = c->h; c->h = wc.height = h;
+ wc.border_width = c->bw;
+ XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
+ configure(c);
+ XSync(dpy, False);
}
void
void
run(void) {
XEvent ev;
- static const char *evname[LASTEvent] = {
- [ButtonPress] = "buttonpress",
- [ConfigureRequest] = "configurerequest",
- [ConfigureNotify] = "configurenotify",
- [DestroyNotify] = "destroynotify",
- [EnterNotify] = "enternotify",
- [Expose] = "expose",
- [FocusIn] = "focusin",
- [KeyPress] = "keypress",
- [MappingNotify] = "mappingnotify",
- [MapRequest] = "maprequest",
- [PropertyNotify] = "propertynotify",
- [UnmapNotify] = "unmapnotify"
- };
/* main event loop */
XSync(dpy, False);
while(running && !XNextEvent(dpy, &ev)) {
- D fprintf(stderr, "run event %s\n", evname[ev.type]);
if(handler[ev.type])
handler[ev.type](&ev); /* call handler */
}
sendmon(Client *c, Monitor *m) {
if(c->mon == m)
return;
- unfocus(c);
+ unfocus(c, True);
detach(c);
detachstack(c);
c->mon = m;
wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False);
netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
+ netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False);
+ netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False);
/* init cursors */
cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
}
void
-unfocus(Client *c) {
+unfocus(Client *c, Bool setfocus) {
if(!c)
return;
grabbuttons(c, False);
XSetWindowBorder(dpy, c->win, dc.norm[ColBorder]);
- XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
+ if(setfocus)
+ XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
}
void
XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn);
XineramaScreenInfo *unique = NULL;
- info = XineramaQueryScreens(dpy, &nn);
for(n = 0, m = mons; m; m = m->next, n++);
/* only consider unique geometries as separate screens */
if(!(unique = (XineramaScreenInfo *)malloc(sizeof(XineramaScreenInfo) * nn)))
int
main(int argc, char *argv[]) {
if(argc == 2 && !strcmp("-v", argv[1]))
- die("dwm-"VERSION", © 2006-2009 dwm engineers, see LICENSE for details\n");
+ die("dwm-"VERSION", © 2006-2010 dwm engineers, see LICENSE for details\n");
else if(argc != 1)
die("usage: dwm [-v]\n");
if(!setlocale(LC_CTYPE, "") || !XSupportsLocale())