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