[hackers] [wmii] Fix column scaling a bit.

From: Kris Maglione <jg_AT_suckless.org>
Date: Sat Feb 09 19:23:43 2008

changeset: 2285:c1ab6fdb7fca
tag: tip
user: Kris Maglione <jg_AT_suckless.org>
date: Sat Feb 09 13:23:27 2008 -0500
summary: Fix column scaling a bit.

diff -r d3e408d9c6db -r c1ab6fdb7fca cmd/wmii/_util.c
--- a/cmd/wmii/_util.c Fri Feb 08 21:39:25 2008 -0500
+++ b/cmd/wmii/_util.c Sat Feb 09 13:23:27 2008 -0500
@@ -2,6 +2,10 @@
  * See LICENSE file for license details.
  */
 #include "dat.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+#include <unistd.h>
 #include "fns.h"
 
 /* Blech. */
@@ -31,6 +35,139 @@ VECTOR(long, long, l)
 VECTOR(long, long, l)
 VECTOR(Rectangle, rect, r)
 VECTOR(void*, ptr, p)
+
+int
+doublefork(void) {
+ pid_t pid;
+ int status;
+
+ switch(pid=fork()) {
+ case -1:
+ fatal("Can't fork(): %r");
+ case 0:
+ switch(pid=fork()) {
+ case -1:
+ fatal("Can't fork(): %r");
+ case 0:
+ return 0;
+ default:
+ exit(0);
+ }
+ default:
+ waitpid(pid, &status, 0);
+ return pid;
+ }
+ /* NOTREACHED */
+}
+
+void
+closeexec(int fd) {
+ if(fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
+ fatal("can't set %d close on exec: %r", fd);
+}
+
+int
+spawn3(int fd[3], const char *file, char *argv[]) {
+ /* Some ideas from Russ Cox's libthread port. */
+ int p[2];
+ int pid;
+ int _errno;
+
+ if(pipe(p) < 0)
+ return -1;
+ closeexec(p[1]);
+
+ switch(pid = doublefork()) {
+ case 0:
+ dup2(fd[0], 0);
+ dup2(fd[1], 1);
+ dup2(fd[2], 2);
+
+ execvp(file, argv);
+ write(p[1], &errno, sizeof _errno);
+ exit(1);
+ break;
+ default:
+ close(p[1]);
+ if(read(p[0], &_errno, sizeof _errno) == sizeof _errno)
+ pid = -1;
+ close(p[0]);
+ break;
+ case -1: /* can't happen */
+ break;
+ }
+
+ close(fd[0]);
+ /* These could fail if any of these was also a previous fd. */
+ close(fd[1]);
+ close(fd[2]);
+ return pid;
+}
+
+int
+spawn3l(int fd[3], const char *file, ...) {
+ va_list ap;
+ char **argv;
+ int i, n;
+
+ va_start(ap, file);
+ for(n=0; va_arg(ap, char*); n++)
+ ;
+ va_end(ap);
+
+ argv = emalloc((n+1) * sizeof *argv);
+ va_start(ap, file);
+ for(i=0; i <= n; i++)
+ argv[i] = va_arg(ap, char*);
+ va_end(ap);
+
+ return spawn3(fd, file, argv);
+}
+
+void
+backtrace(void) {
+ char *proc, *spid;
+ int fd[3], p[2], q[2];
+ int pid, status, n;
+
+ proc = sxprint("/proc/%d/file", getpid());
+ spid = sxprint("%d", getpid());
+ switch(pid = fork()) {
+ case -1:
+ return;
+ case 0:
+ break;
+ default:
+ waitpid(pid, &status, 0);
+ return;
+ }
+
+ if(pipe(p) < 0 || pipe(q) < 0)
+ exit(0);
+ closeexec(p[1]);
+ closeexec(q[0]);
+
+ fd[0] = p[0];
+ fd[1] = q[1];
+ fd[2] = open("/dev/null", O_WRONLY);
+ if(spawn3l(fd, "gdb", "gdb", "-batch", "-x", "/dev/fd/0", proc, spid, nil) < 0)
+ exit(1);
+
+ fprint(p[1], "bt full\n");
+ fprint(p[1], "detach\n");
+ close(p[1]);
+
+ /* Why? Because gdb freezes waiting for user input
+ * if its stdout is a tty.
+ */
+ /* It'd be nice to make this a /debug file at some point,
+ * anyway.
+ */
+ while((n = read(q[0], buffer, sizeof buffer)) > 0)
+ write(2, buffer, n);
+ exit(0);
+
+}
 
 void
 reinit(Regex *r, char *regx) {
diff -r d3e408d9c6db -r c1ab6fdb7fca cmd/wmii/area.c
--- a/cmd/wmii/area.c Fri Feb 08 21:39:25 2008 -0500
+++ b/cmd/wmii/area.c Sat Feb 09 13:23:27 2008 -0500
@@ -191,8 +191,11 @@ area_attach(Area *a, Frame *f) {
 
         view_arrange(a->view);
 
- if(a->frame)
- assert(a->sel);
+ if(a->frame && a->sel == nil) {
+ fprint(2, "a->sel == nil\n");
+ backtrace();
+ a->sel = a->frame;
+ }
 }
 
 void
diff -r d3e408d9c6db -r c1ab6fdb7fca cmd/wmii/client.c
--- a/cmd/wmii/client.c Fri Feb 08 21:39:25 2008 -0500
+++ b/cmd/wmii/client.c Sat Feb 09 13:23:27 2008 -0500
@@ -263,6 +263,7 @@ client_destroy(Client *c) {
 
         ewmh_destroyclient(c);
         group_remove(c);
+ client_seturgent(c, false, UrgClient);
         event("DestroyClient %C\n", c);
 
         flushenterevents();
@@ -692,17 +693,19 @@ updatemwm(Client *c) {
         int n;
 
         /* To quote Metacity, or KWin quoting Metacity:
+ *
          * We support MWM hints deemed non-stupid
+ *
          * Our definition of non-stupid is a bit less lenient than
          * theirs, though. In fact, we don't really even support the
          * idea of supporting the hints that we support, but apps
          * like xmms (which noone should use) break if we don't.
          */
 
- n = getprop_long(&c->w, "_MOTIF_WM_HINTS", "_MOTIF_WM_HINTS",
- 0L, (long**)&ret, 3L);
-
- /* FIXME: Should somehow handle all frames. */
+ n = getprop_ulong(&c->w, "_MOTIF_WM_HINTS", "_MOTIF_WM_HINTS",
+ 0L, &ret, 3L);
+
+ /* FIXME: Should somehow handle all frames of a client. */
         if(c->sel)
                 r = client_grav(c, ZR);
 
diff -r d3e408d9c6db -r c1ab6fdb7fca cmd/wmii/column.c
--- a/cmd/wmii/column.c Fri Feb 08 21:39:25 2008 -0500
+++ b/cmd/wmii/column.c Sat Feb 09 13:23:27 2008 -0500
@@ -142,18 +142,20 @@ column_scale(Area *a) {
         uint minh, yoff, dy;
         uint ncol, nuncol;
         uint colh, uncolh;
- int surplus, i, j;
+ int surplus, osurplus, i, j;
 
         if(!a->frame)
                 return;
 
+ /* The minimum heights of collapsed and uncollpsed frames.
+ */
         minh = labelh(def.font);
         colh = labelh(def.font);
- uncolh = minh + colh +1;
-
+ uncolh = minh + colh + 1;
+
+ /* Count collapsed and uncollapsed frames. */
         ncol = 0;
         nuncol = 0;
- dy = 0;
         for(f=a->frame; f; f=f->anext) {
                 frame_resize(f, f->r);
                 if(f->collapsed)
@@ -162,11 +164,13 @@ column_scale(Area *a) {
                         nuncol++;
         }
 
- surplus = Dy(a->r) - (ncol * colh) - (nuncol * uncolh);
+ surplus = Dy(a->r)
+ - (ncol * colh)
+ - (nuncol * uncolh);
 
         /* Collapse until there is room */
         if(surplus < 0) {
- i = ceil((float)(-surplus) / (uncolh - colh));
+ i = ceil(-1.F * surplus / (uncolh - colh));
                 if(i >= nuncol)
                         i = nuncol - 1;
                 nuncol -= i;
@@ -175,74 +179,94 @@ column_scale(Area *a) {
         }
         /* Push to the floating layer until there is room */
         if(surplus < 0) {
- i = ceil((float)(-surplus)/colh);
+ i = ceil(-1.F * surplus / colh);
                 if(i > ncol)
                         i = ncol;
                 ncol -= i;
- /* surplus += i * colh; */
- }
-
+ surplus += i * colh;
+ }
+
+ /* Decide which to collapse and which to float. */
         j = nuncol - 1;
         i = ncol - 1;
- /* Decide which to collapse, float */
         for(fp=&a->frame; *fp;) {
                 f = *fp;
- if(f == a->sel)
- i++, j++;
- if(f->collapsed) {
- if(i < 0 && (f != a->sel)) {
- f->collapsed = false;
- area_moveto(f->view->area, f);
- continue;
+ if(f != a->sel) {
+ if(!f->collapsed) {
+ if(j < 0)
+ f->collapsed = true;
+ j--;
                         }
- i--;
- }else {
- if(j < 0 && (f != a->sel))
- f->collapsed = true;
- j--;
+ if(f->collapsed) {
+ if(i < 0) {
+ f->collapsed = false;
+ area_moveto(f->view->area, f);
+ continue;
+ }
+ i--;
+ }
                 }
                 /* Doesn't change if we 'continue' */
                 fp = &f->anext;
         }
 
- surplus = 0;
+ /* Make some adjustments. */
+ surplus = Dy(a->r);
         for(f=a->frame; f; f=f->anext) {
                 f->r = rectsubpt(f->r, f->r.min);
- f->crect = rectsubpt(f->crect, f->crect.min);
                 f->r.max.x = Dx(a->r);
 
                 if(f->collapsed) {
+ surplus -= colh;
+ f->dy = 0;
                         f->r.max.y = colh;
                 }else {
+ surplus -= uncolh;
+ f->dy = Dy(f->r);
                         f->r.max.y = uncolh;
- dy += Dy(f->crect);
                 }
- surplus += Dy(f->r);
- }
- for(f = a->frame; f; f = f->anext)
- f->ratio = (float)Dy(f->crect)/dy;
-
- j = 0;
- surplus = Dy(a->r) - surplus;
- while(surplus > 0 && surplus != j) {
- j = surplus;
+ }
+
+ /* Distribute the surplus.
+ * When a frame doesn't accept its allocation, don't try to
+ * allocate to it again. Keep going until we have no more
+ * surplus, or no more frames will accept it.
+ */
+ osurplus = 0;
+ while(surplus > 0 && surplus != osurplus) {
+ osurplus = surplus;
                 dy = 0;
- for(f=a->frame; f; f=f->anext) {
- if(!f->collapsed)
- f->r.max.y += f->ratio * surplus;
- frame_resize(f, f->r);
- dy += Dy(f->r);
- }
- surplus = Dy(a->r) - dy;
- }
- for(f=a->frame; f && surplus > 0; f=f->anext) {
+ for(f=a->frame; f; f=f->anext)
+ if(f->dy)
+ dy += f->dy;
+ for(f=a->frame; f; f=f->anext)
+ if(f->dy) {
+ i = Dy(f->r);
+ f->r.max.y += ((float)f->dy / dy) * osurplus;
+
+ frame_resize(f, f->r);
+
+ f->r.max.y = Dy(f->crect) + labelh(def.font) + 1;
+ surplus -= Dy(f->r) - i;
+ f->dy = Dy(f->r);
+
+ if(Dy(f->r) == i)
+ f->dy = 0;
+ }
+ }
+
+ /* Now, try to give each frame, in turn, the entirety of the
+ * surplus that we have left. A single frame might be able
+ * to fill its increment gap with all of what's left, but
+ * not with its fair share.
+ */
+ for(f=a->frame; f && surplus > 0; f=f->anext)
                 if(!f->collapsed) {
                         dy = Dy(f->r);
                         f->r.max.y += surplus;
                         frame_resize(f, f->r);
                         f->r.max.y = Dy(f->crect) + labelh(def.font) + 1;
                         surplus -= Dy(f->r) - dy;
- }
         }
 
         if(surplus < 0) {
@@ -250,11 +274,15 @@ column_scale(Area *a) {
                 surplus = 0;
         }
 
+ /* Adjust the y coordnates of each frame. */
         yoff = a->r.min.y;
         i = nuncol;
         for(f=a->frame; f; f=f->anext) {
- f->r = rectaddpt(f->r, Pt(a->r.min.x, yoff));
-
+ f->r = rectaddpt(f->r,
+ Pt(a->r.min.x, yoff));
+ /* Give each frame an equal portion of the surplus,
+ * whether it wants it or not.
+ */
                 if(!f->collapsed) {
                         i--;
                         f->r.max.y += surplus / nuncol;
diff -r d3e408d9c6db -r c1ab6fdb7fca cmd/wmii/dat.h
--- a/cmd/wmii/dat.h Fri Feb 08 21:39:25 2008 -0500
+++ b/cmd/wmii/dat.h Sat Feb 09 13:23:27 2008 -0500
@@ -189,7 +189,7 @@ struct Frame {
         int column;
         ushort id;
         bool collapsed;
- float ratio;
+ int dy;
         Rectangle r;
         Rectangle colr;
         Rectangle floatr;
diff -r d3e408d9c6db -r c1ab6fdb7fca cmd/wmii/fns.h
--- a/cmd/wmii/fns.h Fri Feb 08 21:39:25 2008 -0500
+++ b/cmd/wmii/fns.h Sat Feb 09 13:23:27 2008 -0500
@@ -225,12 +225,17 @@ void view_update_rect(View*);
 void view_update_rect(View*);
 Rectangle* view_rects(View*, uint *num, Frame *ignore);
 
-/* util.c */
+/* _util.c */
+void backtrace(void);
+void closeexec(int);
 char** comm(int, char**, char**);
+int doublefork(void);
 void grep(char**, Reprog*, int);
 char* join(char**, char*);
 void refree(Regex*);
 void reinit(Regex*, char*);
+int spawn3(int[3], const char*, char*[]);
+int spawn3l(int[3], const char*, ...);
 void uniq(char**);
 
 /* utf.c */
diff -r d3e408d9c6db -r c1ab6fdb7fca cmd/wmii/frame.c
--- a/cmd/wmii/frame.c Fri Feb 08 21:39:25 2008 -0500
+++ b/cmd/wmii/frame.c Sat Feb 09 13:23:27 2008 -0500
@@ -246,7 +246,6 @@ Handlers framehandler = {
         .motion = motion_event,
 };
 
-/* These must die!!! */
 Rectangle
 frame_rect2client(Client *c, Rectangle r, bool floating) {
 
@@ -301,8 +300,12 @@ frame_resize(Frame *f, Rectangle r) {
         Rectangle fr, cr;
         int collapsed, dx;
 
- if(Dx(r) <= 0 || Dy(r) <= 0)
- die("Frame rect: %R\n", r);
+ if(Dx(r) <= 0 || Dy(r) <= 0) {
+ fprint(2, "Frame rect: %R\n", r);
+ backtrace();
+ r.max.x = min(r.min.x+1, r.max.x);
+ r.max.y = min(r.min.y+1, r.max.y);
+ }
 
         c = f->client;
         if(c->fullscreen) {
diff -r d3e408d9c6db -r c1ab6fdb7fca cmd/wmii/main.c
--- a/cmd/wmii/main.c Fri Feb 08 21:39:25 2008 -0500
+++ b/cmd/wmii/main.c Sat Feb 09 13:23:27 2008 -0500
@@ -7,12 +7,10 @@
 #include <X11/Xproto.h>
 #include <X11/cursorfont.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <locale.h>
 #include <pwd.h>
 #include <signal.h>
 #include <sys/stat.h>
-#include <sys/wait.h>
 #include <unistd.h>
 #include "fns.h"
 
@@ -213,36 +211,6 @@ cleanup_handler(int signal) {
 }
 
 static void
-closeexec(int fd) {
- if(fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
- fatal("can't set %d close on exec: %r", fd);
-}
-
-static int
-doublefork(void) {
- pid_t pid;
- int status;
-
- switch(pid=fork()) {
- case -1:
- fatal("Can't fork(): %r");
- case 0:
- switch(pid=fork()) {
- case -1:
- fatal("Can't fork(): %r");
- case 0:
- return 0;
- default:
- exit(0);
- }
- default:
- waitpid(pid, &status, 0);
- return pid;
- }
- /* NOTREACHED */
-}
-
-static void
 init_traps(void) {
         char buf[1];
         int fd[2];
Received on Sat Feb 09 2008 - 19:23:43 UTC

This archive was generated by hypermail 2.2.0 : Sun Jul 13 2008 - 15:59:20 UTC