Browse Source

implemented restack behavior (floats are on top in tiled mode)

Anselm R.Garbe 19 năm trước cách đây
mục cha
commit
d4b7a9a373
6 tập tin đã thay đổi với 81 bổ sung34 xóa
  1. 8 18
      client.c
  2. 2 2
      dwm.1
  3. 2 1
      dwm.h
  4. 6 3
      event.c
  5. 54 10
      tag.c
  6. 9 0
      util.c

+ 8 - 18
client.c

@@ -59,8 +59,6 @@ focus(Client *c)
 		drawtitle(old);
 	drawtitle(c);
 	XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
-	XSync(dpy, False);
-	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
 }
 
 void
@@ -77,8 +75,8 @@ focusnext(Arg *arg)
 	if(!(c = getnext(sel->next)))
 		c = getnext(clients);
 	if(c) {
-		higher(c);
 		focus(c);
+		restack();
 	}
 }
 
@@ -98,8 +96,8 @@ focusprev(Arg *arg)
 		c = getprev(c);
 	}
 	if(c) {
-		higher(c);
 		focus(c);
+		restack();
 	}
 }
 
@@ -180,13 +178,6 @@ gravitate(Client *c, Bool invert)
 	c->y += dy;
 }
 
-void
-higher(Client *c)
-{
-	XRaiseWindow(dpy, c->win);
-	XRaiseWindow(dpy, c->title);
-}
-
 void
 killclient(Arg *arg)
 {
@@ -271,13 +262,12 @@ manage(Window w, XWindowAttributes *wa)
 			|| (c->maxw && c->minw &&
 				c->maxw == c->minw && c->maxh == c->minh);
 	settitle(c);
-	arrange(NULL);
 
-	/* mapping the window now prevents flicker */
-	XMapRaised(dpy, c->win);
-	XMapRaised(dpy, c->title);
+	XMapWindow(dpy, c->win);
+	XMapWindow(dpy, c->title);
 	if(isvisible(c))
 		focus(c);
+	arrange(NULL);
 }
 
 void
@@ -410,7 +400,7 @@ togglemax(Arg *arg)
 		sel->w = sw - 2;
 		sel->h = sh - 2 - bh;
 
-		higher(sel);
+		restack();
 		resize(sel, arrange == dofloat, TopLeft);
 
 		sel->x = ox;
@@ -446,9 +436,9 @@ unmanage(Client *c)
 	XSync(dpy, False);
 	XSetErrorHandler(xerror);
 	XUngrabServer(dpy);
-	arrange(NULL);
 	if(sel)
 		focus(sel);
+	arrange(NULL);
 }
 
 void
@@ -474,6 +464,6 @@ zoom(Arg *arg)
 	clients->prev = sel;
 	sel->next = clients;
 	clients = sel;
-	arrange(NULL);
 	focus(sel);
+	arrange(NULL);
 }

+ 2 - 2
dwm.1

@@ -36,11 +36,11 @@ prints version information to standard output, then exits.
 .B Standard input
 is read and displayed in the status text area.
 .TP
-.B Button[1,3]
+.B Button[1,2]
 click on a tag label focuses that
 .B tag.
 .TP
-.B Button2
+.B Button3
 click on a tag label toggles that
 .B tag.
 .SS Keyboard commands

+ 2 - 1
dwm.h

@@ -89,7 +89,6 @@ extern void focusprev(Arg *arg);
 extern Client *getclient(Window w);
 extern Client *getctitle(Window w);
 extern void gravitate(Client *c, Bool invert);
-extern void higher(Client *c);
 extern void killclient(Arg *arg);
 extern void manage(Window w, XWindowAttributes *wa);
 extern void resize(Client *c, Bool sizehints, Corner sticky);
@@ -125,6 +124,7 @@ extern Bool isvisible(Client *c);
 extern Client *getnext(Client *c);
 extern Client *getprev(Client *c);
 extern void replacetag(Arg *arg);
+extern void restack();
 extern void settags(Client *c);
 extern void togglemode(Arg *arg);
 extern void view(Arg *arg);
@@ -133,4 +133,5 @@ extern void toggleview(Arg *arg);
 /* util.c */
 extern void *emallocz(unsigned int size);
 extern void eprint(const char *errstr, ...);
+extern void *erealloc(void *ptr, unsigned int size);
 extern void spawn(Arg *arg);

+ 6 - 3
event.c

@@ -118,21 +118,24 @@ buttonpress(XEvent *e)
 		}
 	}
 	else if((c = getclient(ev->window))) {
-		higher(c);
 		focus(c);
 		switch(ev->button) {
 		default:
 			break;
 		case Button1:
-			if(!c->ismax && (arrange == dofloat || c->isfloat))
+			if(!c->ismax && (arrange == dofloat || c->isfloat)) {
+				restack(c);
 				movemouse(c);
+			}
 			break;
 		case Button2:
 			zoom(NULL);
 			break;
 		case Button3:
-			if(!c->ismax && (arrange == dofloat || c->isfloat))
+			if(!c->ismax && (arrange == dofloat || c->isfloat)) {
+				restack(c);
 				resizemouse(c);
+			}
 			break;
 		}
 	}

+ 54 - 10
tag.c

@@ -58,18 +58,17 @@ dofloat(Arg *arg)
 			ban(c);
 	}
 	if((sel = getnext(clients))) {
-		higher(sel);
 		focus(sel);
+		restack();
 	}
 	else
 		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
-	drawall();
 }
 
 void
 dotile(Arg *arg)
 {
-	int n, i, w, h;
+	int h, i, n, w;
 	Client *c;
 
 	w = sw - mw;
@@ -86,7 +85,6 @@ dotile(Arg *arg)
 		c->ismax = False;
 		if(isvisible(c)) {
 			if(c->isfloat) {
-				higher(c);
 				resize(c, True, TopLeft);
 				continue;
 			}
@@ -123,13 +121,11 @@ dotile(Arg *arg)
 		else
 			ban(c);
 	}
-	if((sel = getnext(clients))) {
-		higher(sel);
+	if((sel = getnext(clients)))
 		focus(sel);
-	}
 	else
 		XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime);
-	drawall();
+	restack();
 }
 
 Client *
@@ -199,6 +195,56 @@ replacetag(Arg *arg)
 	appendtag(arg);
 }
 
+void
+restack()
+{
+	static unsigned int nwins = 0;
+	static Window *wins = NULL;
+	unsigned int f, fi, m, mi, n;
+	Client *c;
+	XEvent ev;
+
+	for(f = 0, m = 0, c = clients; c; c = c->next)
+		if(isvisible(c)) {
+			if(c->isfloat || arrange == dofloat)
+				f++;
+			else
+				m++;
+		}
+
+	n = 2 * (f + m);
+	if(nwins < n) {
+		nwins = n;
+		wins = erealloc(wins, nwins * sizeof(Window));
+	}
+
+	fi = 0;
+	mi = 2 * f;
+	if(sel->isfloat || arrange == dofloat) {
+		wins[fi++] = sel->title;
+		wins[fi++] = sel->win;
+	}
+	else {
+		wins[mi++] = sel->title;
+		wins[mi++] = sel->win;
+	}
+	for(c = clients; c; c = c->next)
+		if(isvisible(c) && c != sel) {
+			if(c->isfloat || arrange == dofloat) {
+				wins[fi++] = c->title;
+				wins[fi++] = c->win;
+			}
+			else {
+				wins[mi++] = c->title;
+				wins[mi++] = c->win;
+			}
+		}
+	XRestackWindows(dpy, wins, n);
+	drawall();
+	XSync(dpy, False);
+	while(XCheckMaskEvent(dpy, EnterWindowMask, &ev));
+}
+
 void
 settags(Client *c)
 {
@@ -248,7 +294,6 @@ view(Arg *arg)
 		seltag[i] = False;
 	seltag[arg->i] = True;
 	arrange(NULL);
-	drawall();
 }
 
 void
@@ -261,5 +306,4 @@ toggleview(Arg *arg)
 	if(i == ntags)
 		seltag[arg->i] = True; /* cannot toggle last view */
 	arrange(NULL);
-	drawall();
 }

+ 9 - 0
util.c

@@ -40,6 +40,15 @@ eprint(const char *errstr, ...)
 	exit(EXIT_FAILURE);
 }
 
+void *
+erealloc(void *ptr, unsigned int size)
+{
+	void *res = realloc(ptr, size);
+	if(!res)
+		bad_malloc(size);
+	return res;
+}
+
 void
 spawn(Arg *arg)
 {