JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
implemented better fullscreen handling, please test
[dwm.git] / dwm.c
diff --git a/dwm.c b/dwm.c
index fedf069..670afbe 100644 (file)
--- a/dwm.c
+++ b/dwm.c
@@ -84,10 +84,11 @@ struct Client {
        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;
@@ -202,6 +203,7 @@ static Monitor *ptrtomon(int x, int y);
 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);
@@ -222,7 +224,7 @@ static void togglebar(const Arg *arg);
 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);
@@ -426,7 +428,7 @@ buttonpress(XEvent *e) {
        click = ClkRootWin;
        /* focus monitor if necessary */
        if((m = wintomon(ev->window)) && m != selmon) {
-               unfocus(selmon->sel);
+               unfocus(selmon->sel, True);
                selmon = m;
                focus(NULL);
        }
@@ -795,7 +797,7 @@ enternotify(XEvent *e) {
        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)))
@@ -817,8 +819,9 @@ 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;
@@ -852,7 +855,7 @@ focusmon(const Arg *arg) {
                return;
        if((m = dirtomon(arg->i)) == selmon)
                return;
-       unfocus(selmon->sel);
+       unfocus(selmon->sel, True);
        selmon = m;
        focus(NULL);
 }
@@ -904,15 +907,14 @@ getrootptr(int *x, int *y) {
 
 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;
@@ -1113,12 +1115,13 @@ manage(Window w, XWindowAttributes *wa) {
                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;
@@ -1142,7 +1145,7 @@ manage(Window w, XWindowAttributes *wa) {
        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);
@@ -1297,14 +1300,33 @@ propertynotify(XEvent *e) {
 void
 clientmessage(XEvent *e) {
        XClientMessageEvent *cme = &e->xclient;
+       Client *c;
 
-       if(cme->message_type == netatom[NetWMState] && cme->data.l[1] == netatom[NetWMFullscreen]) {
-               if(cme->data.l[0])
+       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);
-               else
+                       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);
+               }
        }
 }
 
@@ -1315,18 +1337,22 @@ quit(const Arg *arg) {
 
 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
@@ -1444,7 +1470,7 @@ void
 sendmon(Client *c, Monitor *m) {
        if(c->mon == m)
                return;
-       unfocus(c);
+       unfocus(c, True);
        detach(c);
        detachstack(c);
        c->mon = m;
@@ -1681,12 +1707,13 @@ toggleview(const Arg *arg) {
 }
 
 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