mirror of https://github.com/0intro/wmii
Fix column scaling a bit.
This commit is contained in:
parent
5bb7a777a8
commit
443c6cbe66
137
cmd/wmii/_util.c
137
cmd/wmii/_util.c
|
@ -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. */
|
||||
|
@ -32,6 +36,139 @@ 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) {
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
n = getprop_ulong(&c->w, "_MOTIF_WM_HINTS", "_MOTIF_WM_HINTS",
|
||||
0L, &ret, 3L);
|
||||
|
||||
/* FIXME: Should somehow handle all frames. */
|
||||
/* FIXME: Should somehow handle all frames of a client. */
|
||||
if(c->sel)
|
||||
r = client_grav(c, ZR);
|
||||
|
||||
|
|
|
@ -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--;
|
||||
}
|
||||
if(f->collapsed) {
|
||||
if(i < 0) {
|
||||
f->collapsed = false;
|
||||
area_moveto(f->view->area, f);
|
||||
continue;
|
||||
}
|
||||
i--;
|
||||
}
|
||||
i--;
|
||||
}else {
|
||||
if(j < 0 && (f != a->sel))
|
||||
f->collapsed = true;
|
||||
j--;
|
||||
}
|
||||
/* 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; 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;
|
||||
}
|
||||
}
|
||||
for(f=a->frame; f && surplus > 0; f=f->anext) {
|
||||
|
||||
/* 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;
|
||||
|
|
|
@ -189,7 +189,7 @@ struct Frame {
|
|||
int column;
|
||||
ushort id;
|
||||
bool collapsed;
|
||||
float ratio;
|
||||
int dy;
|
||||
Rectangle r;
|
||||
Rectangle colr;
|
||||
Rectangle floatr;
|
||||
|
|
|
@ -225,12 +225,17 @@ void view_update_all(void);
|
|||
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 */
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
@ -212,36 +210,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];
|
||||
|
|
Loading…
Reference in New Issue