mirror of
https://github.com/0intro/wmii
synced 2024-11-22 05:42:05 +03:00
See diff.
This commit is contained in:
parent
33b0d89da3
commit
a76ebd191a
@ -23,6 +23,7 @@ OBJ = area \
|
||||
fs \
|
||||
geom \
|
||||
key \
|
||||
layout \
|
||||
main \
|
||||
map \
|
||||
message \
|
||||
|
@ -396,7 +396,8 @@ column_scale(Area *a) {
|
||||
}
|
||||
}
|
||||
|
||||
column_squeeze(a);
|
||||
if(def.incmode == ISqueeze)
|
||||
column_squeeze(a);
|
||||
column_settle(a);
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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 */
|
||||
|
519
cmd/wmii/layout.c
Normal file
519
cmd/wmii/layout.c
Normal file
@ -0,0 +1,519 @@
|
||||
/* Copyright ©2006-2008 Kris Maglione <fbsdaemon@gmail.com>
|
||||
* 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;
|
||||
}
|
||||
|
511
cmd/wmii/mouse.c
511
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,
|
||||
|
Loading…
Reference in New Issue
Block a user