wmii

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

commit cc6103ca998daa2b90670c8d737c3d3d3fd97bce
parent ba3b4bd5a2b8a6903d75b40acb98873ac6632183
Author: Kris Maglione <jg@suckless.org>
Date:   Wed, 23 Jan 2008 00:13:33 -0500

Ameliorate the mouse.c rat's nest.

Diffstat:
cmd/wmii/fns.h | 3++-
cmd/wmii/frame.c | 8++++----
cmd/wmii/mouse.c | 650++++++++++++++++++++++++++++++++++++++++---------------------------------------
cmd/wmii/x11.c | 11+++++++++++
include/x11.h | 1+
5 files changed, 351 insertions(+), 322 deletions(-)

diff --git a/cmd/wmii/fns.h b/cmd/wmii/fns.h @@ -185,7 +185,8 @@ bool setdebug(int); void vdebug(int, const char*, va_list); /* mouse.c */ -void mouse_resize(Client*, bool opaque, Align); +void mouse_movegrabbox(Client*); +void mouse_resize(Client*, Align); void mouse_resizecol(Divide*); void grab_button(XWindow, uint button, ulong mod); Align snap_rect(Rectangle *rects, int num, Rectangle *current, Align *mask, int snapw); diff --git a/cmd/wmii/frame.c b/cmd/wmii/frame.c @@ -154,7 +154,7 @@ bdown_event(Window *w, XButtonEvent *e) { switch(e->button) { case Button1: focus(c, false); - mouse_resize(c, false, Center); + mouse_resize(c, Center); break; case Button2: frame_restack(f, nil); @@ -163,7 +163,7 @@ bdown_event(Window *w, XButtonEvent *e) { break; case Button3: focus(c, false); - mouse_resize(c, false, quadrant(f->r, Pt(e->x_root, e->y_root))); + mouse_resize(c, quadrant(f->r, Pt(e->x_root, e->y_root))); break; default: XAllowEvents(display, ReplayPointer, e->time); @@ -178,10 +178,10 @@ bdown_event(Window *w, XButtonEvent *e) { view_restack(f->view); } if(rect_haspoint_p(Pt(e->x, e->y), f->grabbox)) - mouse_resize(c, true, Center); + mouse_movegrabbox(c); else if(f->area->floating) if(!e->subwindow && !rect_haspoint_p(Pt(e->x, e->y), f->titlebar)) - mouse_resize(c, false, quadrant(f->r, Pt(e->x_root, e->y_root))); + mouse_resize(c, quadrant(f->r, Pt(e->x_root, e->y_root))); if(f->client != selclient()) focus(c, false); diff --git a/cmd/wmii/mouse.c b/cmd/wmii/mouse.c @@ -46,7 +46,7 @@ framerect(Framewin *f) { r = rectsubpt(r, Pt(Dx(r)/2, 0)); } r = rectaddpt(r, f->pt); - + /* Keep onscreen */ p = ZP; p.x -= min(0, r.min.x); @@ -68,9 +68,11 @@ framewin(Frame *f, Point pt, int orientation, int n) { Framewin *fw; fw = emallocz(sizeof *fw); - wa.override_redirect = True; + 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 = createwindow(&scr.root, Rect(0, 0, 1, 1), + scr.depth, InputOutput, + &wa, CWEventMask); fw->w->aux = fw; sethandler(fw->w, &handlers); @@ -226,15 +228,168 @@ hplace(Framewin *fw, Point pt) { reshapewin(fw->w, framerect(fw)); } +static Window* +gethsep(Rectangle r) { + Window *w; + WinAttr wa; + + wa.background_pixel = def.normcolor.border; + w = createwindow(&scr.root, r, scr.depth, InputOutput, &wa, CWBackPixel); + mapwin(w); + raisewin(w); + return w; +} + +static void +rect_morph(Rectangle *r, Point d, Align *mask) { + int n; + + if(*mask & North) + r->min.y += d.y; + if(*mask & West) + r->min.x += d.x; + if(*mask & South) + r->max.y += d.y; + if(*mask & East) + r->max.x += d.x; + + if(r->min.x > r->max.x) { + n = r->min.x; + r->min.x = r->max.x; + r->max.x = n; + *mask ^= East|West; + } + if(r->min.y > r->max.y) { + n = r->min.y; + r->min.y = r->max.y; + r->max.y = n; + *mask ^= North|South; + } +} + +static int +snap_hline(Rectangle *rects, int nrect, int dy, Rectangle *r, int y) { + Rectangle *rp; + int i, ty; + + for(i=0; i < nrect; i++) { + rp = &rects[i]; + if((rp->min.x <= r->max.x) && (rp->max.x >= r->min.x)) { + ty = rp->min.y; + if(abs(ty - y) <= abs(dy)) + dy = ty - y; + + ty = rp->max.y; + if(abs(ty - y) <= abs(dy)) + dy = ty - y; + } + } + return dy; +} + +static int +snap_vline(Rectangle *rects, int nrect, int dx, Rectangle *r, int x) { + Rectangle *rp; + int i, tx; + + for(i=0; i < nrect; i++) { + rp = &rects[i]; + if((rp->min.y <= r->max.y) && (rp->max.y >= r->min.y)) { + tx = rp->min.x; + if(abs(tx - x) <= abs(dx)) + dx = tx - x; + + tx = rp->max.x; + if(abs(tx - x) <= abs(dx)) + dx = tx - x; + } + } + return dx; +} + +/* Returns a gravity for increment handling. It's normally the opposite of the mask + * (the directions that we're resizing in), unless a snap occurs, in which case, it's the + * direction of the snap. + */ +Align +snap_rect(Rectangle *rects, int num, Rectangle *r, Align *mask, int snap) { + Align ret; + Point d; + + d.x = snap+1; + d.y = snap+1; + + if(*mask&North) + d.y = snap_hline(rects, num, d.y, r, r->min.y); + if(*mask&South) + d.y = snap_hline(rects, num, d.y, r, r->max.y); + + if(*mask&East) + d.x = snap_vline(rects, num, d.x, r, r->max.x); + if(*mask&West) + d.x = snap_vline(rects, num, d.x, r, r->min.x); + + ret = Center; + if(abs(d.x) <= snap) + ret ^= East|West; + else + d.x = 0; + + if(abs(d.y) <= snap) + ret ^= North|South; + else + d.y = 0; + + rect_morph(r, d, mask); + return ret ^ *mask; +} + +static int +readmouse(Point *p, uint *button) { + XEvent ev; + + for(;;) { + XMaskEvent(display, MouseMask|ExposureMask, &ev); + switch(ev.type) { + case Expose: + dispatch_event(&ev); + default: + continue; + case ButtonPress: + case ButtonRelease: + *button = ev.xbutton.button; + case MotionNotify: + p->x = ev.xmotion.x_root; + p->y = ev.xmotion.y_root; + break; + } + return ev.type; + } +} + +static bool +readmotion(Point *p) { + uint button; + + for(;;) + switch(readmouse(p, &button)) { + case MotionNotify: + return true; + case ButtonRelease: + return false; + } +} + static void do_managed_move(Client *c) { Rectangle r; WinAttr wa; - XEvent ev; Framewin *fw; Window *cwin; Frame *f, *fprev, *fnext; + Area *a; Point pt, pt2; + uint button; int y; focus(c, false); @@ -256,108 +411,90 @@ horiz: ungrabpointer(); if(!grabpointer(&scr.root, nil, cursor[CurIcon], MouseMask)) goto done; + warppointer(pt); vplace(fw, pt); - for(;;) { - XMaskEvent(display, MouseMask | ExposureMask, &ev); - switch (ev.type) { - default: - break; - case Expose: - dispatch_event(&ev); - break; + for(;;) + switch (readmouse(&pt, &button)) { case MotionNotify: - pt.x = ev.xmotion.x_root; - pt.y = ev.xmotion.y_root; - vplace(fw, pt); break; case ButtonRelease: - switch(ev.xbutton.button) { - case 1: + if(button != 1) + continue; /* TODO: Fix... Tangled, broken mess. */ - 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); + 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 - r.min.y = f->area->r.min.y; + fprev->r.max.y = f->r.max.y; + frame_resize(fprev, fprev->r); + } - if(f->anext) - r.max.y = f->anext->r.min.y; - else - r.max.y = f->area->r.max.y; + column_insert(fw->ra, f, fw->fprev); - frame_resize(f, fw->fprev_r); + 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; - view_arrange(f->view); - goto done; - } - break; + 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: - switch(ev.xbutton.button) { - case 2: + if(button == 2) goto vert; - } - break; + continue; } - } vert: y = pt.y; ungrabpointer(); if(!grabpointer(&scr.root, cwin, cursor[CurIcon], MouseMask)) goto done; hplace(fw, pt); - for(;;) { - XMaskEvent(display, MouseMask | ExposureMask, &ev); - switch (ev.type) { - default: - break; - case Expose: - dispatch_event(&ev); - break; + for(;;) + switch (readmouse(&pt, &button)) { case MotionNotify: - pt.x = ev.xmotion.x_root; - pt.y = ev.xmotion.y_root; - hplace(fw, pt); - break; - case ButtonRelease: - switch(ev.xbutton.button) { - case 1: - 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; - case 2: + continue; + case ButtonPress: + if(button == 2) { pt.y = y; goto horiz; } - break; + 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); @@ -369,22 +506,9 @@ done: warppointer(pt); } -static Window* -gethsep(Rectangle r) { - Window *w; - WinAttr wa; - - wa.background_pixel = def.normcolor.border; - w = createwindow(&scr.root, r, scr.depth, InputOutput, &wa, CWBackPixel); - mapwin(w); - raisewin(w); - return w; -} - static void mouse_resizecolframe(Frame *f, Align align) { WinAttr wa; - XEvent ev; Window *cwin, *hwin; Divide *d; View *v; @@ -458,53 +582,40 @@ mouse_resizecolframe(Frame *f, Align align) { pt.y = ((align&North) ? f->r.min.y : f->r.max.y); warppointer(pt); - for(;;) { - XMaskEvent(display, MouseMask | ExposureMask, &ev); - switch (ev.type) { - default: - break; - case Expose: - dispatch_event(&ev); - break; - case MotionNotify: - pt.x = ev.xmotion.x_root; - pt.y = ev.xmotion.y_root; + while(readmotion(&pt)) { + if(align&West) + r.min.x = pt.x; + else + r.max.x = pt.x; + r.min.y = ((align&South) ? pt.y : pt.y-1); + r.max.y = r.min.y+2; - if(align&West) - r.min.x = pt.x; - else - r.max.x = pt.x; - r.min.y = ((align&South) ? pt.y : pt.y-1); - r.max.y = r.min.y+2; + div_set(d, pt.x); + reshapewin(hwin, r); + } - div_set(d, pt.x); - reshapewin(hwin, r); - break; - case ButtonRelease: - r = f->r; - if(align&West) - r.min.x = pt.x; - else - r.max.x = pt.x; - if(align&North) - r.min.y = pt.y; - else - r.max.y = pt.y; - column_resizeframe(f, r); + r = f->r; + if(align&West) + r.min.x = pt.x; + else + r.max.x = pt.x; + if(align&North) + r.min.y = pt.y; + else + r.max.y = pt.y; + column_resizeframe(f, r); + + /* XXX: Magic number... */ + if(align&West) + pt.x = f->r.min.x + 4; + else + pt.x = f->r.max.x - 4; + if(align&North) + pt.y = f->r.min.y + 4; + else + pt.y = f->r.max.y - 4; + warppointer(pt); - /* XXX: Magic number... */ - if(align&West) - pt.x = f->r.min.x + 4; - else - pt.x = f->r.max.x - 4; - if(align&North) - pt.y = f->r.min.y + 4; - else - pt.y = f->r.max.y - 4; - warppointer(pt); - goto done; - } - } done: ungrabpointer(); destroywindow(cwin); @@ -514,7 +625,6 @@ done: void mouse_resizecol(Divide *d) { WinAttr wa; - XEvent ev; Window *cwin; Divide *dp; View *v; @@ -546,150 +656,71 @@ mouse_resizecol(Divide *d) { if(!grabpointer(&scr.root, cwin, cursor[CurNone], MouseMask)) goto done; - for(;;) { - XMaskEvent(display, MouseMask | ExposureMask, &ev); - switch (ev.type) { - default: - break; - case Expose: - dispatch_event(&ev); - break; - case MotionNotify: - pt.x = ev.xmotion.x_root; + while(readmotion(&pt)) div_set(d, pt.x); - break; - case ButtonRelease: - column_resize(a, pt.x - a->r.min.x); - goto done; - } - } + + column_resize(a, pt.x - a->r.min.x); + done: ungrabpointer(); destroywindow(cwin); } -static void -rect_morph(Rectangle *r, Point d, Align *mask) { - int n; - - if(*mask & North) - r->min.y += d.y; - if(*mask & West) - r->min.x += d.x; - if(*mask & South) - r->max.y += d.y; - if(*mask & East) - r->max.x += d.x; +void +mouse_movegrabbox(Client *c) { + Rectangle *rects; + Rectangle frect, origin; + Point pt, pt1; + Frame *f; + Align align, grav; + uint nrect; - if(r->min.x > r->max.x) { - n = r->min.x; - r->min.x = r->max.x; - r->max.x = n; - *mask ^= East|West; - } - if(r->min.y > r->max.y) { - n = r->min.y; - r->min.y = r->max.y; - r->max.y = n; - *mask ^= North|South; + f = c->sel; + if(!f->area->floating) { + do_managed_move(c); + return; } -} -static int -snap_hline(Rectangle *rects, int nrect, int dy, Rectangle *r, int y) { - Rectangle *rp; - int i, ty; - - for(i=0; i < nrect; i++) { - rp = &rects[i]; - if((rp->min.x <= r->max.x) && (rp->max.x >= r->min.x)) { - ty = rp->min.y; - if(abs(ty - y) <= abs(dy)) - dy = ty - y; + if(!grabpointer(c->framewin, nil, cursor[CurMove], MouseMask)) + return; - ty = rp->max.y; - if(abs(ty - y) <= abs(dy)) - dy = ty - y; - } - } - return dy; -} + rects = view_rects(f->view, &nrect, f); + origin = f->r; + frect = f->r; -static int -snap_vline(Rectangle *rects, int nrect, int dx, Rectangle *r, int x) { - Rectangle *rp; - int i, tx; + pt1 = querypointer(&scr.root); + for(; readmotion(&pt); pt1=pt) { + origin = rectaddpt(origin, subpt(pt, pt1)); + origin = constrain(origin); + frect = origin; - for(i=0; i < nrect; i++) { - rp = &rects[i]; - if((rp->min.y <= r->max.y) && (rp->max.y >= r->min.y)) { - tx = rp->min.x; - if(abs(tx - x) <= abs(dx)) - dx = tx - x; + align = Center; + grav = snap_rect(rects, nrect, &frect, &align, def.snap); - tx = rp->max.x; - if(abs(tx - x) <= abs(dx)) - dx = tx - x; - } + frect = frame_hints(f, frect, Center); + frect = constrain(frect); + client_resize(c, frect); } - return dx; -} - -/* Returns a gravity for increment handling. It's normally the opposite of the mask - * (the directions that we're resizing in), unless a snap occurs, in which case, it's the - * direction of the snap. - */ -Align -snap_rect(Rectangle *rects, int num, Rectangle *r, Align *mask, int snap) { - Align ret; - Point d; - - d.x = snap+1; - d.y = snap+1; - - if(*mask&North) - d.y = snap_hline(rects, num, d.y, r, r->min.y); - if(*mask&South) - d.y = snap_hline(rects, num, d.y, r, r->max.y); - - if(*mask&East) - d.x = snap_vline(rects, num, d.x, r, r->max.x); - if(*mask&West) - d.x = snap_vline(rects, num, d.x, r, r->min.x); - - ret = Center; - if(abs(d.x) <= snap) - ret ^= East|West; - else - d.x = 0; - - if(abs(d.y) <= snap) - ret ^= North|South; - else - d.y = 0; + client_resize(c, frect); - rect_morph(r, d, mask); - return ret ^ *mask; + free(rects); + ungrabpointer(); } -/* Grumble... Messy... TODO: Rewrite. */ void -mouse_resize(Client *c, bool grabbox, Align align) { - XEvent ev; +mouse_resize(Client *c, Align align) { Rectangle *rects; Rectangle frect, origin; Align grav; Cursor cur; Point d, pt, hr; float rx, ry, hrx, hry; - uint num; + uint nrect; Frame *f; f = c->sel; - if(f->client->fullscreen) return; - if(!f->area->floating) { if(align==Center) do_managed_move(c); @@ -698,30 +729,28 @@ mouse_resize(Client *c, bool grabbox, Align align) { return; } - origin = f->r; - frect = f->r; - rects = view_rects(f->area->view, &num, c->frame); - cur = quad_cursor(align); - if((align==Center) && !grabbox) + if(align == Center) cur = cursor[CurSizing]; - pt = querypointer(c->framewin); - rx = (float)pt.x / Dx(frect); - ry = (float)pt.y /Dy(frect); - if(!grabpointer(c->framewin, nil, cur, MouseMask)) return; - pt = querypointer(&scr.root); + origin = f->r; + frect = f->r; + rects = view_rects(f->area->view, &nrect, c->frame); - hr = subpt(frect.max, frect.min); - hr = divpt(hr, Pt(2, 2)); + pt = querypointer(c->framewin); + rx = (float)pt.x / Dx(frect); + ry = (float)pt.y / Dy(frect); + + pt = querypointer(&scr.root); SET(hrx); SET(hry); - if(align != Center) { + hr = subpt(frect.max, frect.min); + hr = divpt(hr, Pt(2, 2)); d = hr; if(align&North) d.y -= hr.y; if(align&South) d.y += hr.y; @@ -730,12 +759,15 @@ mouse_resize(Client *c, bool grabbox, Align align) { pt = addpt(d, f->r.min); warppointer(pt); - } - else if(!grabbox) { - hrx = (double)(Dx(screen->r) + Dx(frect) - 2 * labelh(def.font)) - / Dx(screen->r); - hry = (double)(Dy(screen->r) + Dy(frect) - 3 * labelh(def.font)) - / Dy(screen->r); + }else { + hrx = (double)(Dx(screen->r) + + Dx(frect) + - 2 * labelh(def.font)) + / Dx(screen->r); + hry = (double)(Dy(screen->r) + + Dy(frect) + - 3 * labelh(def.font)) + / Dy(screen->r); pt.x = frect.max.x - labelh(def.font); pt.y = frect.max.y - labelh(def.font); @@ -743,67 +775,51 @@ mouse_resize(Client *c, bool grabbox, Align align) { d.y = pt.y / hry; warppointer(d); - flushevents(PointerMotionMask, False); } + sync(); + flushevents(PointerMotionMask, false); - for(;;) { - XMaskEvent(display, MouseMask | ExposureMask, &ev); - switch (ev.type) { - default: - break; - case Expose: - dispatch_event(&ev); - break; - case MotionNotify: - d.x = ev.xmotion.x_root; - d.y = ev.xmotion.y_root; + while(readmotion(&d)) { + if(align == Center) { + d.x = (d.x * hrx) - pt.x; + d.y = (d.y * hry) - pt.y; + }else + d = subpt(d, pt); + pt = addpt(pt, d); - if(align == Center && !grabbox) { - d.x = (d.x * hrx) - pt.x; - d.y = (d.y * hry) - pt.y; - }else - d = subpt(d, pt); - pt = addpt(pt, d); + rect_morph(&origin, d, &align); + origin = constrain(origin); + frect = origin; - rect_morph(&origin, d, &align); - origin = constrain(origin); - frect = origin; + grav = snap_rect(rects, nrect, &frect, &align, def.snap); - grav = snap_rect(rects, num, &frect, &align, def.snap); + frect = frame_hints(f, frect, grav); + frect = constrain(frect); - frect = frame_hints(f, frect, grav); - frect = constrain(frect); + client_resize(c, frect); + } - //reshapewin(c->framewin, frect); - client_resize(c, frect); - break; - case ButtonRelease: - client_resize(c, frect); - - if(!grabbox) { - pt = translate(c->framewin, &scr.root, - Pt(Dx(frect)*rx, Dy(frect)*ry)); - if(pt.y > screen->brect.min.y) - pt.y = screen->brect.min.y - 1; - warppointer(pt); - } + pt = addpt(c->framewin->r.min, + Pt(Dx(frect) * rx, + Dy(frect) * ry)); + if(pt.y > f->view->r.max.y) + pt.y = f->view->r.max.y - 1; + warppointer(pt); - free(rects); - ungrabpointer(); - return; - } - } + free(rects); + ungrabpointer(); } /* Doesn't belong here */ void grab_button(XWindow w, uint button, ulong mod) { - XGrabButton(display, button, mod, w, False, ButtonMask, + XGrabButton(display, button, mod, w, false, ButtonMask, GrabModeSync, GrabModeSync, None, None); if((mod != AnyModifier) && (numlock_mask != 0)) { - XGrabButton(display, button, mod | numlock_mask, w, False, ButtonMask, + XGrabButton(display, button, mod | numlock_mask, w, false, ButtonMask, GrabModeSync, GrabModeAsync, None, None); - XGrabButton(display, button, mod | numlock_mask | LockMask, w, False, + XGrabButton(display, button, mod | numlock_mask | LockMask, w, false, ButtonMask, GrabModeSync, GrabModeAsync, None, None); } } + diff --git a/cmd/wmii/x11.c b/cmd/wmii/x11.c @@ -106,6 +106,17 @@ rectsubpt(Rectangle r, Point p) { return r; } +Rectangle +rectsetorigin(Rectangle r, Point p) { + Rectangle ret; + + ret.min.x = p.x; + ret.min.y = p.y; + ret.max.x = p.x + Dx(r); + ret.max.y = p.y + Dy(r); + return ret; +} + /* Formatters */ static int Afmt(Fmt *f) { diff --git a/include/x11.h b/include/x11.h @@ -239,6 +239,7 @@ XRectangle XRect(Rectangle); Rectangle gravitate(Rectangle dst, Rectangle src, Point grav); Rectangle insetrect(Rectangle, int); Rectangle rectaddpt(Rectangle, Point); +Rectangle rectsetorigin(Rectangle, Point); Rectangle rectsubpt(Rectangle, Point); Handlers* sethandler(Window*, Handlers*); Rectangle sizehint(WinHints*, Rectangle);