wmii

git clone git://oldgit.suckless.org/wmii/
Log | Files | Refs | README | LICENSE

commit 46948c279dbe6fc57167835ccaafb373cdf1f2c8
parent cc6103ca998daa2b90670c8d737c3d3d3fd97bce
Author: Kris Maglione <jg@suckless.org>
Date:   Wed, 23 Jan 2008 21:45:30 -0500

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

Diffstat:
TODO | 3++-
cmd/wmii/area.c | 1-
cmd/wmii/float.c | 1+
cmd/wmii/frame.c | 2++
cmd/wmii/mouse.c | 446+++++++++++++++++++++++++++++++++++++++++++++++++------------------------------
cmd/wmii/x11.c | 3+++
config.mk | 3+++
libwmii_hack/Makefile | 1+
mk/gcc.mk | 2+-
mk/hdr.mk | 7++++---
mk/so.mk | 4++--
11 files changed, 294 insertions(+), 179 deletions(-)

diff --git a/TODO b/TODO @@ -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. diff --git a/cmd/wmii/area.c b/cmd/wmii/area.c @@ -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; diff --git a/cmd/wmii/float.c b/cmd/wmii/float.c @@ -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) diff --git a/cmd/wmii/frame.c b/cmd/wmii/frame.c @@ -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; } diff --git a/cmd/wmii/mouse.c b/cmd/wmii/mouse.c @@ -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; @@ -381,132 +396,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; Window *cwin, *hwin; @@ -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); @@ -667,47 +557,6 @@ done: } 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; Rectangle frect, origin; @@ -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) { diff --git a/cmd/wmii/x11.c b/cmd/wmii/x11.c @@ -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; diff --git a/config.mk b/config.mk @@ -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) diff --git a/libwmii_hack/Makefile b/libwmii_hack/Makefile @@ -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 diff --git a/mk/gcc.mk b/mk/gcc.mk @@ -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) diff --git a/mk/hdr.mk b/mk/hdr.mk @@ -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 diff --git a/mk/so.mk b/mk/so.mk @@ -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)