From a76ebd191a65aeebc692ba1fb9be4b69631d92ce Mon Sep 17 00:00:00 2001 From: Kris Maglione Date: Fri, 23 May 2008 11:32:01 -0400 Subject: [PATCH] See diff. --- cmd/wmii/Makefile | 1 + cmd/wmii/column.c | 3 +- cmd/wmii/dat.h | 7 + cmd/wmii/fns.h | 4 +- cmd/wmii/layout.c | 519 ++++++++++++++++++++++++++++++++++++++++++++++ cmd/wmii/mouse.c | 511 +-------------------------------------------- 6 files changed, 534 insertions(+), 511 deletions(-) create mode 100644 cmd/wmii/layout.c diff --git a/cmd/wmii/Makefile b/cmd/wmii/Makefile index 44f22b5a..42c20aca 100644 --- a/cmd/wmii/Makefile +++ b/cmd/wmii/Makefile @@ -23,6 +23,7 @@ OBJ = area \ fs \ geom \ key \ + layout \ main \ map \ message \ diff --git a/cmd/wmii/column.c b/cmd/wmii/column.c index f1aee439..e4b3ea62 100644 --- a/cmd/wmii/column.c +++ b/cmd/wmii/column.c @@ -396,7 +396,8 @@ column_scale(Area *a) { } } - column_squeeze(a); + if(def.incmode == ISqueeze) + column_squeeze(a); column_settle(a); } diff --git a/cmd/wmii/dat.h b/cmd/wmii/dat.h index e753629e..2ec13e90 100644 --- a/cmd/wmii/dat.h +++ b/cmd/wmii/dat.h @@ -31,6 +31,12 @@ enum { CRight = 1<<2, }; +enum IncMode { + ISqueeze, + IShow, + IIgnore, +}; + enum { GInvert = 1<<0, }; @@ -304,6 +310,7 @@ EXTERN struct { uint border; uint snap; int colmode; + int incmode; } def; enum { diff --git a/cmd/wmii/fns.h b/cmd/wmii/fns.h index 3244057a..f5a3299d 100644 --- a/cmd/wmii/fns.h +++ b/cmd/wmii/fns.h @@ -202,10 +202,12 @@ bool setdebug(int); void vdebug(int, const char*, va_list); /* mouse.c */ +void grab_button(XWindow, uint button, ulong mod); void mouse_movegrabbox(Client*); void mouse_resize(Client*, Align); void mouse_resizecol(Divide*); -void grab_button(XWindow, uint button, ulong mod); +bool readmotion(Point*); +int readmouse(Point*, uint*); Align snap_rect(Rectangle *rects, int num, Rectangle *current, Align *mask, int snapw); /* printevent.c */ diff --git a/cmd/wmii/layout.c b/cmd/wmii/layout.c new file mode 100644 index 00000000..f6a79cd5 --- /dev/null +++ b/cmd/wmii/layout.c @@ -0,0 +1,519 @@ +/* Copyright ©2006-2008 Kris Maglione + * See LICENSE file for license details. + */ +#include "dat.h" +#include "fns.h" + +/* Here be dragons. */ + +enum { + ButtonMask = + ButtonPressMask | ButtonReleaseMask, + MouseMask = + ButtonMask | PointerMotionMask +}; + +static Handlers handlers; + +enum { OHoriz, OVert }; +typedef struct Framewin Framewin; +struct Framewin { + /* Todo... give these better names. */ + Window* w; + Rectangle grabbox; + Rectangle fprev_r; + Frame* fprev; + Frame* f; + Area* ra; + Point pt; + int orientation; + int xy; +}; + +static Rectangle +framerect(Framewin *f) { + Rectangle r; + Point p; + + r.min = ZP; + if(f->orientation == OHoriz) { + r.max.x = f->xy; + r.max.y = f->grabbox.max.y + f->grabbox.min.y; + r = rectsubpt(r, Pt(0, Dy(r)/2)); + }else { + r.max.x = f->grabbox.max.x + f->grabbox.min.x; + r.max.y = f->xy; + r = rectsubpt(r, Pt(Dx(r)/2, 0)); + } + r = rectaddpt(r, f->pt); + + /* Keep onscreen */ + p = ZP; + p.x -= min(0, r.min.x); + p.x -= max(0, r.max.x - screen->r.max.x); + p.y -= max(0, r.max.y - screen->brect.min.y - Dy(r)/2); + return rectaddpt(r, p); +} + +static void +frameadjust(Framewin *f, Point pt, int orientation, int xy) { + f->orientation = orientation; + f->xy = xy; + f->pt = pt; +} + +static Framewin* +framewin(Frame *f, Point pt, int orientation, int n) { + WinAttr wa; + Framewin *fw; + + fw = emallocz(sizeof *fw); + wa.override_redirect = true; + wa.event_mask = ExposureMask; + fw->w = createwindow(&scr.root, Rect(0, 0, 1, 1), + scr.depth, InputOutput, + &wa, CWEventMask); + fw->w->aux = fw; + sethandler(fw->w, &handlers); + + fw->f = f; + fw->grabbox = f->grabbox; + frameadjust(fw, pt, orientation, n); + reshapewin(fw->w, framerect(fw)); + + mapwin(fw->w); + raisewin(fw->w); + + return fw; +} + +static void +framedestroy(Framewin *f) { + destroywindow(f->w); + free(f); +} + +static void +expose_event(Window *w, XExposeEvent *e) { + Rectangle r; + Framewin *f; + Image *buf; + CTuple *c; + + USED(e); + + f = w->aux; + c = &def.focuscolor; + buf = screen->ibuf; + + r = rectsubpt(w->r, w->r.min); + fill(buf, r, c->bg); + border(buf, r, 1, c->border); + border(buf, f->grabbox, 1, c->border); + border(buf, insetrect(f->grabbox, -f->grabbox.min.x), 1, c->border); + + copyimage(w, r, buf, ZP); +} + +static Handlers handlers = { + .expose = expose_event, +}; + +static int +_vsnap(Framewin *f, int y) { + if(abs(f->xy - y) < Dy(f->w->r)) { + f->xy = y; + return 1; + } + return 0; +} + +static void +vplace(Framewin *fw, Point pt) { + Rectangle r; + Frame *f; + Area *a; + View *v; + int hr; + + v = screen->sel; + + for(a = v->area->next; a->next; a = a->next) + if(pt.x < a->r.max.x) + break; + fw->ra = a; + + pt.x = a->r.min.x; + frameadjust(fw, pt, OHoriz, Dx(a->r)); + + r = fw->w->r; + hr = Dy(r)/2; + fw->xy = pt.y; + + if(a->frame == nil) + goto done; + + for(f = a->frame; f->anext; f = f->anext) + if(f->r.max.y > pt.y) + break; + + if(!f->collapsed) { + fw->fprev = f; + fw->fprev_r = f->r; + + if(f == fw->f) { + fw->fprev = f->aprev; + fw->fprev_r.min.y = pt.y - hr; + //if(_vsnap(fw, f->r.min.y+hr)) + goto done; + } + + if(_vsnap(fw, f->r.max.y - hr)) { + if(f == fw->f->aprev) + fw->xy = pt.y; + else { + fw->fprev_r.min.y = f->r.max.y - labelh(def.font); + goto done; + } + } + if(_vsnap(fw, f->r.min.y+Dy(r)+hr)) { + fw->fprev_r.min.y = f->r.min.y + labelh(def.font); + goto done; + } + if(f->aprev == nil || f->aprev->collapsed) + _vsnap(fw, f->r.min.y); + else if(_vsnap(fw, f->r.min.y-hr)) + fw->fprev = f->aprev; + + fw->fprev_r.min.y = pt.y - hr; + if(fw->fprev && fw->fprev->anext == fw->f) + fw->fprev_r.max = fw->f->r.max; + goto done; + } + + if(pt.y < f->r.min.y + hr) { + pt.y = f->r.min.y; + if(f->aprev && !f->aprev->collapsed) + pt.y -= hr; + }else { + pt.y = f->r.max.y; + if(f->anext == fw->f) + pt.y += hr; + } + +done: + pt.x = a->r.min.x; + pt.y = fw->xy; + frameadjust(fw, pt, OHoriz, Dx(a->r)); + reshapewin(fw->w, framerect(fw)); +} + +static void +hplace(Framewin *fw, Point pt) { + Area *a; + View *v; + int minw; + + v = screen->sel; + minw = Dx(v->r)/NCOL; + + for(a = v->area->next; a->next; a = a->next) + if(pt.x < a->r.max.x) + break; + + fw->ra = nil; + if(abs(pt.x - a->r.min.x) < minw/2) { + pt.x = a->r.min.x; + fw->ra = a->prev; + } + else if(abs(pt.x - a->r.max.x) < minw/2) { + pt.x = a->r.max.x; + fw->ra = a; + } + + pt.y = a->r.min.y; + frameadjust(fw, pt, OVert, Dy(a->r)); + reshapewin(fw->w, framerect(fw)); +} + +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; +} + +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, +}; + +/* Trampoline to allow properly tail recursive move/resize routines. + * We could probably get away with plain tail calls, but I don't + * like the idea. + */ +static void +trampoline(int fn, Frame *f) { + + while(fn > 0) { + f->collapsed = false; + fn = tramp[fn](f); + } + ungrabpointer(); + + warppointer(grabboxcenter(f)); +} + +void +mouse_movegrabbox(Client *c) { + Frame *f; + int incmode; + + f = c->sel; + incmode = def.incmode; + def.incmode = IShow; + view_update(f->view); + if(f->area->floating) + trampoline(TFloat, f); + else + trampoline(THCol, f); + def.incmode = incmode; + view_update(f->view); +} + +static 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, at least clearer, 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->colr.min.y = f->colr.min.y; + frame_resize(fnext, fnext->colr); + } + else if(fprev) { + if(fw->fprev == fprev->aprev) { + fw->fprev = fprev->aprev; + fprev->colr = f->r; + }else + fprev->colr.max.y = f->r.max.y; + frame_resize(fprev, fprev->colr); + } + } + + column_insert(fw->ra, f, fw->fprev); + + r = fw->fprev_r; + if(f->aprev) { + f->aprev->colr.max.y = r.min.y; + frame_resize(f->aprev, f->aprev->colr); + }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; + + Dprint(DGeneric, "fw->fprev: %C fprev: %C f: %C f->r: %R fprev_r: %R\n", + (fw->fprev?fw->fprev->client:nil), (fprev?fprev->client:nil), + f->client, f->r, fw->fprev_r); + f->colr = fw->fprev_r; + frame_resize(f, f->colr); + + if(!a->frame && !a->floating) + area_destroy(a); + goto done; + case ButtonPress: + if(button == 2) + ret = TVCol; + else if(button == 3) + ret = TFloat; + else + continue; + goto done; + } +done: + framedestroy(fw); + return ret; +} + +static 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); + } + goto done; + } + +done: + framedestroy(fw); + destroywindow(cwin); + return ret; +} + +static int +tfloat(Frame *f) { + Rectangle *rects; + Rectangle frect, origin; + Point pt, pt1; + Client *c; + Align align; + uint nrect, button; + int ret; + + c = f->client; + if(!f->area->floating) { + if(f->anext) + f->anext->colr.min.y = f->colr.min.y; + else if(f->aprev) + f->aprev->colr.max.y = f->colr.max.y; + 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; +label: + for(;;pt1=pt) + switch (readmouse(&pt, &button)) { + default: goto label; /* shut up ken */ + case MotionNotify: + casmotion: + origin = rectaddpt(origin, subpt(pt, pt1)); + origin = constrain(origin); + frect = origin; + + align = Center; + 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; +} + diff --git a/cmd/wmii/mouse.c b/cmd/wmii/mouse.c index fcfed4a9..72f911e1 100644 --- a/cmd/wmii/mouse.c +++ b/cmd/wmii/mouse.c @@ -13,229 +13,6 @@ enum { ButtonMask | PointerMotionMask }; -static Handlers handlers; - -enum { OHoriz, OVert }; -typedef struct Framewin Framewin; -struct Framewin { - /* Todo... give these better names. */ - Window* w; - Rectangle grabbox; - Rectangle fprev_r; - Frame* fprev; - Frame* f; - Area* ra; - Point pt; - int orientation; - int xy; -}; - -static Rectangle -framerect(Framewin *f) { - Rectangle r; - Point p; - - r.min = ZP; - if(f->orientation == OHoriz) { - r.max.x = f->xy; - r.max.y = f->grabbox.max.y + f->grabbox.min.y; - r = rectsubpt(r, Pt(0, Dy(r)/2)); - }else { - r.max.x = f->grabbox.max.x + f->grabbox.min.x; - r.max.y = f->xy; - r = rectsubpt(r, Pt(Dx(r)/2, 0)); - } - r = rectaddpt(r, f->pt); - - /* Keep onscreen */ - p = ZP; - p.x -= min(0, r.min.x); - p.x -= max(0, r.max.x - screen->r.max.x); - p.y -= max(0, r.max.y - screen->brect.min.y - Dy(r)/2); - return rectaddpt(r, p); -} - -static void -frameadjust(Framewin *f, Point pt, int orientation, int xy) { - f->orientation = orientation; - f->xy = xy; - f->pt = pt; -} - -static Framewin* -framewin(Frame *f, Point pt, int orientation, int n) { - WinAttr wa; - Framewin *fw; - - fw = emallocz(sizeof *fw); - wa.override_redirect = true; - wa.event_mask = ExposureMask; - fw->w = createwindow(&scr.root, Rect(0, 0, 1, 1), - scr.depth, InputOutput, - &wa, CWEventMask); - fw->w->aux = fw; - sethandler(fw->w, &handlers); - - fw->f = f; - fw->grabbox = f->grabbox; - frameadjust(fw, pt, orientation, n); - reshapewin(fw->w, framerect(fw)); - - mapwin(fw->w); - raisewin(fw->w); - - return fw; -} - -static void -framedestroy(Framewin *f) { - destroywindow(f->w); - free(f); -} - -static void -expose_event(Window *w, XExposeEvent *e) { - Rectangle r; - Framewin *f; - Image *buf; - CTuple *c; - - USED(e); - - f = w->aux; - c = &def.focuscolor; - buf = screen->ibuf; - - r = rectsubpt(w->r, w->r.min); - fill(buf, r, c->bg); - border(buf, r, 1, c->border); - border(buf, f->grabbox, 1, c->border); - border(buf, insetrect(f->grabbox, -f->grabbox.min.x), 1, c->border); - - copyimage(w, r, buf, ZP); -} - -static Handlers handlers = { - .expose = expose_event, -}; - -static int -_vsnap(Framewin *f, int y) { - if(abs(f->xy - y) < Dy(f->w->r)) { - f->xy = y; - return 1; - } - return 0; -} - -static void -vplace(Framewin *fw, Point pt) { - Rectangle r; - Frame *f; - Area *a; - View *v; - int hr; - - v = screen->sel; - - for(a = v->area->next; a->next; a = a->next) - if(pt.x < a->r.max.x) - break; - fw->ra = a; - - pt.x = a->r.min.x; - frameadjust(fw, pt, OHoriz, Dx(a->r)); - - r = fw->w->r; - hr = Dy(r)/2; - fw->xy = pt.y; - - if(a->frame == nil) - goto done; - - for(f = a->frame; f->anext; f = f->anext) - if(f->r.max.y > pt.y) - break; - - if(!f->collapsed) { - fw->fprev = f; - fw->fprev_r = f->r; - - if(f == fw->f) { - fw->fprev = f->aprev; - fw->fprev_r.min.y = pt.y - hr; - //if(_vsnap(fw, f->r.min.y+hr)) - goto done; - } - - if(_vsnap(fw, f->r.max.y - hr)) { - if(f == fw->f->aprev) - fw->xy = pt.y; - else { - fw->fprev_r.min.y = f->r.max.y - labelh(def.font); - goto done; - } - } - if(_vsnap(fw, f->r.min.y+Dy(r)+hr)) { - fw->fprev_r.min.y = f->r.min.y + labelh(def.font); - goto done; - } - if(f->aprev == nil || f->aprev->collapsed) - _vsnap(fw, f->r.min.y); - else if(_vsnap(fw, f->r.min.y-hr)) - fw->fprev = f->aprev; - - fw->fprev_r.min.y = pt.y - hr; - if(fw->fprev && fw->fprev->anext == fw->f) - fw->fprev_r.max = fw->f->r.max; - goto done; - } - - if(pt.y < f->r.min.y + hr) { - pt.y = f->r.min.y; - if(f->aprev && !f->aprev->collapsed) - pt.y -= hr; - }else { - pt.y = f->r.max.y; - if(f->anext == fw->f) - pt.y += hr; - } - -done: - pt.x = a->r.min.x; - pt.y = fw->xy; - frameadjust(fw, pt, OHoriz, Dx(a->r)); - reshapewin(fw->w, framerect(fw)); -} - -static void -hplace(Framewin *fw, Point pt) { - Area *a; - View *v; - int minw; - - v = screen->sel; - minw = Dx(v->r)/NCOL; - - for(a = v->area->next; a->next; a = a->next) - if(pt.x < a->r.max.x) - break; - - fw->ra = nil; - if(abs(pt.x - a->r.min.x) < minw/2) { - pt.x = a->r.min.x; - fw->ra = a->prev; - } - else if(abs(pt.x - a->r.max.x) < minw/2) { - pt.x = a->r.max.x; - fw->ra = a; - } - - pt.y = a->r.min.y; - frameadjust(fw, pt, OVert, Dy(a->r)); - reshapewin(fw->w, framerect(fw)); -} - static Window* gethsep(Rectangle r) { Window *w; @@ -352,22 +129,7 @@ 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 clear. - pt = addpt(pt, divpt(subpt(f->grabbox.max, - f->grabbox.min), - Pt(2, 2))) - */ -} - -static int +int readmouse(Point *p, uint *button) { XEvent ev; @@ -390,7 +152,7 @@ readmouse(Point *p, uint *button) { } } -static bool +bool readmotion(Point *p) { uint button; @@ -658,275 +420,6 @@ 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, -}; - -/* Trampoline to allow properly tail recursive move/resize routines. - * We could probably get away with plain tail calls, but I don't - * like the idea. - */ -static void -trampoline(int fn, Frame *f) { - - while(fn > 0) { - f->collapsed = false; - fn = tramp[fn](f); - } - ungrabpointer(); - - warppointer(grabboxcenter(f)); -} - -# if 1 -void -mouse_movegrabbox(Client *c) { - Frame *f; - - f = c->sel; - for(Area *a=f->view->area->next; a; a=a->next) - column_frob(a); - if(f->area->floating) - trampoline(TFloat, f); - else - trampoline(THCol, f); -} -# endif - -static 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, at least clearer, 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->colr.min.y = f->colr.min.y; - frame_resize(fnext, fnext->colr); - } - else if(fprev) { - if(fw->fprev == fprev->aprev) { - fw->fprev = fprev->aprev; - fprev->colr = f->r; - }else - fprev->colr.max.y = f->r.max.y; - frame_resize(fprev, fprev->colr); - } - } - - column_insert(fw->ra, f, fw->fprev); - - r = fw->fprev_r; - if(f->aprev) { - f->aprev->colr.max.y = r.min.y; - frame_resize(f->aprev, f->aprev->colr); - }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; - - Dprint(DGeneric, "fw->fprev: %C fprev: %C f: %C f->r: %R fprev_r: %R\n", - (fw->fprev?fw->fprev->client:nil), (fprev?fprev->client:nil), - f->client, f->r, fw->fprev_r); - f->colr = fw->fprev_r; - frame_resize(f, f->colr); - - 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; -} - -static 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; -} - -static int -tfloat(Frame *f) { - Rectangle *rects; - Rectangle frect, origin; - Point pt, pt1; - Client *c; - Align align; - 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; -label: - for(;;pt1=pt) - switch (readmouse(&pt, &button)) { - default: goto label; /* shut up ken */ - case MotionNotify: - casmotion: - origin = rectaddpt(origin, subpt(pt, pt1)); - origin = constrain(origin); - frect = origin; - - align = Center; - 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 - static void _grab(XWindow w, uint button, ulong mod) { XGrabButton(display, button, mod, w, false, ButtonMask,