Experimental code to float/unfloat with the mouse. Fix (hopefully) .so build on Darwin.

This commit is contained in:
Kris Maglione 2008-01-23 21:45:30 -05:00
parent cc6103ca99
commit 46948c279d
11 changed files with 294 additions and 179 deletions

3
TODO
View File

@ -6,8 +6,9 @@ BUGS
* dosbox won't grab the mouse
4.0
* Opaque managed moves. I know I've argued against it, but it may be doable.
* Regex-based tag strings
* Resizable managed area
* Grow and shrink ctl commands
* New dmenu, with real cursor.
* New dmenu, with real cursor; snarfable.

View File

@ -156,7 +156,6 @@ area_moveto(Area *to, Frame *f) {
assert(to->view == f->view);
from = f->area;
if(to->floating != from->floating) {
/* XXX: This must be changed. */
tr = f->revert;

View File

@ -13,6 +13,7 @@ float_attach(Area *a, Frame *f) {
f->client->floating = true;
float_placeframe(f);
assert(a->sel != f);
frame_insert(f, a->sel);
if(a->sel == nil)

View File

@ -71,9 +71,11 @@ frame_insert(Frame *f, Frame *pos) {
a = f->area;
if(pos) {
assert(pos != f);
f->aprev = pos;
f->anext = pos->anext;
}else {
assert(f->area->frame != f);
f->anext = f->area->frame;
f->area->frame = f;
}

View File

@ -344,6 +344,21 @@ snap_rect(Rectangle *rects, int num, Rectangle *r, Align *mask, int snap) {
return ret ^ *mask;
}
static Point
grabboxcenter(Frame *f) {
Point p;
p = addpt(f->r.min, f->grabbox.min);
p.x += Dx(f->grabbox)/2;
p.y += Dy(f->grabbox)/2;
return p;
/* Pretty, but not concise.
pt = addpt(pt, divpt(subpt(f->grabbox.max,
f->grabbox.min),
Pt(2, 2)))
*/
}
static int
readmouse(Point *p, uint *button) {
XEvent ev;
@ -380,132 +395,6 @@ readmotion(Point *p) {
}
}
static void
do_managed_move(Client *c) {
Rectangle r;
WinAttr wa;
Framewin *fw;
Window *cwin;
Frame *f, *fprev, *fnext;
Area *a;
Point pt, pt2;
uint button;
int y;
focus(c, false);
f = c->sel;
pt = querypointer(&scr.root);
pt2.x = f->area->r.min.x;
pt2.y = pt.y;
fw = framewin(f, pt2, OHoriz, Dx(f->area->r));
r = screen->r;
r.min.y += fw->grabbox.min.y + Dy(fw->grabbox)/2;
r.max.y = r.min.y + 1;
cwin = createwindow(&scr.root, r, 0, InputOnly, &wa, 0);
mapwin(cwin);
horiz:
ungrabpointer();
if(!grabpointer(&scr.root, nil, cursor[CurIcon], MouseMask))
goto done;
warppointer(pt);
vplace(fw, pt);
for(;;)
switch (readmouse(&pt, &button)) {
case MotionNotify:
vplace(fw, pt);
break;
case ButtonRelease:
if(button != 1)
continue;
/* TODO: Fix... Tangled, broken mess. */
fprev = f->aprev;
fnext = f->anext;
a = f->area;
column_remove(f);
if(fnext
&& (!fprev || (fw->fprev != fprev)
&& (fw->fprev != fprev->aprev))) {
fnext->r.min.y = f->r.min.y;
frame_resize(fnext, fnext->r);
}
else if(fprev) {
if(fw->fprev == fprev->aprev) {
fw->fprev = fprev->aprev;
fprev->r = f->r;
}else
fprev->r.max.y = f->r.max.y;
frame_resize(fprev, fprev->r);
}
column_insert(fw->ra, f, fw->fprev);
r = fw->fprev_r;
if(f->aprev) {
f->aprev->r.max.y = r.min.y;
frame_resize(f->aprev, f->aprev->r);
}else
r.min.y = f->area->r.min.y;
if(f->anext)
r.max.y = f->anext->r.min.y;
else
r.max.y = f->area->r.max.y;
frame_resize(f, fw->fprev_r);
if(!a->frame)
area_destroy(a);
view_arrange(f->view);
goto done;
case ButtonPress:
if(button == 2)
goto vert;
continue;
}
vert:
y = pt.y;
ungrabpointer();
if(!grabpointer(&scr.root, cwin, cursor[CurIcon], MouseMask))
goto done;
hplace(fw, pt);
for(;;)
switch (readmouse(&pt, &button)) {
case MotionNotify:
hplace(fw, pt);
continue;
case ButtonPress:
if(button == 2) {
pt.y = y;
goto horiz;
}
continue;
case ButtonRelease:
if(button != 1)
continue;
if(fw->ra) {
fw->ra = column_new(f->view, fw->ra, 0);
area_moveto(fw->ra, f);
view_arrange(f->view); /* I hate this. */
}
goto done;
}
done:
ungrabpointer();
framedestroy(fw);
destroywindow(cwin);
pt = addpt(f->r.min, f->grabbox.min);
pt.x += Dx(f->grabbox)/2;
pt.y += Dy(f->grabbox)/2;
warppointer(pt);
}
static void
mouse_resizecolframe(Frame *f, Align align) {
WinAttr wa;
@ -520,8 +409,9 @@ mouse_resizecolframe(Frame *f, Align align) {
assert((align&(North|South)) != (North|South));
v = screen->sel;
for(a = v->area->next, d = divs; a; a = a->next, d = d->next)
if(a == f->area) break;
d = divs;
for(a=v->area->next; a != f->area; a=a->next)
d = d->next;
if(align&East)
d = d->next;
@ -657,7 +547,7 @@ mouse_resizecol(Divide *d) {
goto done;
while(readmotion(&pt))
div_set(d, pt.x);
div_set(d, pt.x);
column_resize(a, pt.x - a->r.min.x);
@ -666,47 +556,6 @@ done:
destroywindow(cwin);
}
void
mouse_movegrabbox(Client *c) {
Rectangle *rects;
Rectangle frect, origin;
Point pt, pt1;
Frame *f;
Align align, grav;
uint nrect;
f = c->sel;
if(!f->area->floating) {
do_managed_move(c);
return;
}
if(!grabpointer(c->framewin, nil, cursor[CurMove], MouseMask))
return;
rects = view_rects(f->view, &nrect, f);
origin = f->r;
frect = f->r;
pt1 = querypointer(&scr.root);
for(; readmotion(&pt); pt1=pt) {
origin = rectaddpt(origin, subpt(pt, pt1));
origin = constrain(origin);
frect = origin;
align = Center;
grav = snap_rect(rects, nrect, &frect, &align, def.snap);
frect = frame_hints(f, frect, Center);
frect = constrain(frect);
client_resize(c, frect);
}
client_resize(c, frect);
free(rects);
ungrabpointer();
}
void
mouse_resize(Client *c, Align align) {
Rectangle *rects;
@ -723,7 +572,7 @@ mouse_resize(Client *c, Align align) {
return;
if(!f->area->floating) {
if(align==Center)
do_managed_move(c);
mouse_movegrabbox(c);
else
mouse_resizecolframe(f, align);
return;
@ -810,6 +659,261 @@ mouse_resize(Client *c, Align align) {
ungrabpointer();
}
#if 1
static int tvcol(Frame*);
static int thcol(Frame*);
static int tfloat(Frame*);
enum {
TDone,
TVCol,
THCol,
TFloat,
};
static int (*tramp[])(Frame*) = {
0,
tvcol,
thcol,
tfloat,
};
static void
trampoline(int fn, Frame *f) {
while(fn > 0)
fn = tramp[fn](f);
ungrabpointer();
warppointer(grabboxcenter(f));
}
# if 1
void
mouse_movegrabbox(Client *c) {
Frame *f;
f = c->sel;
if(f->area->floating)
trampoline(TFloat, f);
else
trampoline(THCol, f);
}
# endif
int
thcol(Frame *f) {
Framewin *fw;
Frame *fprev, *fnext;
Area *a;
Rectangle r;
Point pt, pt2;
uint button;
int ret;
focus(f->client, false);
pt = querypointer(&scr.root);
pt2.x = f->area->r.min.x;
pt2.y = pt.y;
fw = framewin(f, pt2, OHoriz, Dx(f->area->r));
ret = TDone;
if(!grabpointer(&scr.root, nil, cursor[CurIcon], MouseMask))
goto done;
warppointer(pt);
vplace(fw, pt);
for(;;)
switch (readmouse(&pt, &button)) {
case MotionNotify:
vplace(fw, pt);
break;
case ButtonRelease:
if(button != 1)
continue;
/* TODO: Fix... I think that this should be
* simpler, and should be elsewhere. But the
* expected behavior turns out to be more
* complex than one would suspect. The
* simpler algorithms tend not to do what
* you want.
*/
a = f->area;
if(a->floating)
area_detach(f);
else {
fprev = f->aprev;
fnext = f->anext;
column_remove(f);
if(fnext
&& (!fprev || (fw->fprev != fprev)
&& (fw->fprev != fprev->aprev))) {
fnext->r.min.y = f->r.min.y;
frame_resize(fnext, fnext->r);
}
else if(fprev) {
if(fw->fprev == fprev->aprev) {
fw->fprev = fprev->aprev;
fprev->r = f->r;
}else
fprev->r.max.y = f->r.max.y;
frame_resize(fprev, fprev->r);
}
}
column_insert(fw->ra, f, fw->fprev);
r = fw->fprev_r;
if(f->aprev) {
f->aprev->r.max.y = r.min.y;
frame_resize(f->aprev, f->aprev->r);
}else
r.min.y = f->area->r.min.y;
if(f->anext)
r.max.y = f->anext->r.min.y;
else
r.max.y = f->area->r.max.y;
frame_resize(f, fw->fprev_r);
if(!a->frame && !a->floating)
area_destroy(a);
view_arrange(f->view);
goto done;
case ButtonPress:
if(button == 2)
ret = TVCol;
else if(button == 3)
ret = TFloat;
else
continue;
goto done;
}
done:
framedestroy(fw);
return ret;
}
int
tvcol(Frame *f) {
Framewin *fw;
Window *cwin;
WinAttr wa;
Rectangle r;
Point pt, pt2;
uint button;
int ret;
focus(f->client, false);
pt = querypointer(&scr.root);
pt2.x = pt.x;
pt2.y = f->area->r.min.y;
fw = framewin(f, pt2, OVert, Dy(f->view->r));
r = f->view->r;
r.min.y += fw->grabbox.min.y + Dy(fw->grabbox)/2;
r.max.y = r.min.y + 1;
cwin = createwindow(&scr.root, r, 0, InputOnly, &wa, 0);
mapwin(cwin);
ret = TDone;
if(!grabpointer(&scr.root, cwin, cursor[CurIcon], MouseMask))
goto done;
hplace(fw, pt);
for(;;)
switch (readmouse(&pt, &button)) {
case MotionNotify:
hplace(fw, pt);
continue;
case ButtonPress:
if(button == 2)
ret = THCol;
else if(button == 3)
ret = TFloat;
else
continue;
goto done;
case ButtonRelease:
if(button != 1)
continue;
if(fw->ra) {
fw->ra = column_new(f->view, fw->ra, 0);
area_moveto(fw->ra, f);
view_arrange(f->view); /* I hate this. */
}
goto done;
}
done:
framedestroy(fw);
destroywindow(cwin);
return ret;
}
int
tfloat(Frame *f) {
Rectangle *rects;
Rectangle frect, origin;
Point pt, pt1;
Client *c;
Align align, grav;
uint nrect, button;
int ret;
c = f->client;
if(!f->area->floating)
area_moveto(f->view->area, f);
map_frame(f->client);
focus(f->client, false);
ret = TDone;
if(!grabpointer(c->framewin, nil, cursor[CurMove], MouseMask))
return TDone;
rects = view_rects(f->view, &nrect, f);
origin = f->r;
frect = f->r;
pt = querypointer(&scr.root);
pt1 = grabboxcenter(f);
goto casmotion;
for(;;pt1=pt)
switch (readmouse(&pt, &button)) {
case MotionNotify:
casmotion:
origin = rectaddpt(origin, subpt(pt, pt1));
origin = constrain(origin);
frect = origin;
align = Center;
grav = snap_rect(rects, nrect, &frect, &align, def.snap);
frect = frame_hints(f, frect, Center);
frect = constrain(frect);
client_resize(c, frect);
continue;
case ButtonRelease:
if(button != 1)
continue;
goto done;
case ButtonPress:
if(button != 3)
continue;
unmap_frame(f->client);
ret = THCol;
goto done;
}
done:
free(rects);
return ret;
}
#endif
/* Doesn't belong here */
void
grab_button(XWindow w, uint button, ulong mod) {

View File

@ -460,6 +460,9 @@ drawstring(Image *dst, Font *font,
case East:
x = r.max.x - (w + (font->height / 2));
break;
case Center:
x = r.min.x + (Dx(r) - w) / 2;
break;
default:
x = r.min.x + (font->height / 2);
break;

View File

@ -17,6 +17,7 @@ include $(ROOT)/mk/gcc.mk
CFLAGS += $(DEBUGCFLAGS) -O0
LDFLAGS += -g $(LIBS)
SOLDFLAGS += $(LDFLAGS)
SHARED = -shared -Wl,-soname=$(SONAME)
STATIC = -static
# Compiler, Linker. Linker should usually *not* be ld.
@ -39,6 +40,8 @@ LIBIXP = $(LIBDIR)/libixp.a
#LIBICONV = -liconv
# +Darwin
#STATIC = # Darwin doesn't like static linking
#SHARED = -dynamiclib
#SOEXT = dylib
# Solaris
#CFLAGS = -fast $(INCS)

View File

@ -4,6 +4,7 @@ include ${ROOT}/mk/hdr.mk
hack.o hack.o_pic: util.c x11.c hack.h x11.h
CFLAGS += $(INCX11)
SOLDFLAGS += $(LIBX11)
TARG = libwmii_hack
OBJ = hack

View File

@ -11,6 +11,7 @@ CFLAGS += \
-std=c99 \
-pedantic \
-pipe \
-fno-strict-aliasing \
-Wall \
-Wimplicit \
-Wmissing-prototypes \
@ -25,5 +26,4 @@ CFLAGS += \
-Wtrigraphs
MKDEP = cpp -M
SOCFLAGS += -fPIC
SOLDFLAGS += -shared -soname $(SONAME)

View File

@ -1,5 +1,5 @@
.SILENT:
.SUFFIXES: .O .o .o_pic .c .sh .rc .so .awk .1 .depend .install .uninstall .clean
.SUFFIXES: .O .o .o_pic .c .sh .rc .so .dylib .awk .1 .depend .install .uninstall .clean
all:
.c.depend:
@ -44,7 +44,7 @@ all:
echo INSTALL $$($(CLEANNAME) $(BASE)$<)
cp -f $< $(LIBDIR)/$<
chmod 0644 $(LIBDIR)/$<
.a.uninstall .so.uninstall:
.a.uninstall .$(SOEXT).uninstall:
echo UNINSTALL $$($(CLEANNAME) $(BASE)$<)
rm -f $(LIBDIR)/$<
@ -81,8 +81,9 @@ EXCFLAGS = -I$$(echo $(INCPATH)|sed 's/:/ -I/g') -D_XOPEN_SOURCE=600
COMPILE= CC="$(CC)" CFLAGS="$(EXCFLAGS) $(CFLAGS)" $(ROOT)/util/compile
COMPILEPIC= CC="$(CC)" CFLAGS="$(EXCFLAGS) $(CFLAGS) $(SOCFLAGS)" $(ROOT)/util/compile
LINK= LD="$(LD)" LDFLAGS="$(LDFLAGS)" $(ROOT)/util/link
LINKSO= LD="$(LD)" LDFLAGS="$(SOLDFLAGS)" $(ROOT)/util/link
LINKSO= LD="$(LD)" LDFLAGS="$(SOLDFLAGS) $(SHARED)" $(ROOT)/util/link
CLEANNAME=$(ROOT)/util/cleanname
SOEXT=so
include $(ROOT)/config.mk

View File

@ -1,6 +1,6 @@
SOPTARG = $(ROOT)/lib/$(TARG)
SO = $(SOPTARG).so
SONAME = $(TARG).so
SO = $(SOPTARG).$(SOEXT)
SONAME = $(TARG).$(SOEXT)
OFILES_PIC = ${OBJ:=.o_pic}
all: $(HFILES) $(SO)