aboutsummaryrefslogtreecommitdiffstats
path: root/grab.c
diff options
context:
space:
mode:
authoroga2008-01-14 15:21:10 +0000
committeroga2008-01-14 15:21:10 +0000
commit923c9f8936be6a656e3f9b6607c69a820b411330 (patch)
treea6af6b773f95cc8f4d00ade3cc49f812cb873cdd /grab.c
parent13d8a3a4a43bbca611050d5fd8dca3871225b8fb (diff)
downloadcwm-923c9f8936be6a656e3f9b6607c69a820b411330.tar.gz
Rewrite most of grab_menu in grab.c (it was partly 9wm code).
This should work functionally the same, with a few simplifications. Changes: - we don't care if you're holding another button when you release the menu key if you don't want to select anything, move off the menu. - remove the hysteresis from the menu selection (before you had to move more than three pixels onto a new menu entry before it selected it) - simplify a lot of the selection code - kill dead code. - do what the XXX comment said and cache the screensize (i may tweak this later). As far as I can tell, the only code remaining from 9wm is the list of fonts in calmwm.c. Others appear to concur. ok marc@, looked over and tested by a few others. Reminders from okan@.
Diffstat (limited to 'grab.c')
-rw-r--r--grab.c336
1 files changed, 84 insertions, 252 deletions
diff --git a/grab.c b/grab.c
index d6a7f22..ac8e2a9 100644
--- a/grab.c
+++ b/grab.c
@@ -15,14 +15,14 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: grab.c,v 1.6 2008/01/11 16:06:44 oga Exp $
+ * $Id: grab.c,v 1.7 2008/01/14 15:21:10 oga Exp $
*/
#include "headers.h"
#include "calmwm.h"
-int _sweepcalc(struct client_ctx *, int, int, int, int);
-int _nobuttons(XButtonEvent *);
+static int _sweepcalc(struct client_ctx *, int, int, int, int);
+static int menu_calc_entry(int, int, int, int, int);
#define ADJUST_HEIGHT(cc, dy) ((cc->geom.height - cc->geom.min_dy)/ dy)
#define ADJUST_WIDTH(cc, dx) ((cc->geom.width - cc->geom.min_dx)/ dx)
@@ -144,205 +144,113 @@ grab_drag(struct client_ctx *cc)
/* NOTREACHED */
}
-/*
- * Adapted from 9wm.
- */
-
-/* XXX - this REALLY needs to be cleaned up. */
-
#define MenuMask (ButtonMask|ButtonMotionMask|ExposureMask)
#define MenuGrabMask (ButtonMask|ButtonMotionMask|StructureNotifyMask)
#define AllButtonMask (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)
-#ifdef notyet
-struct client_ctx *
-grab_menu_getcc(struct menu_q *menuq, int off)
-{
- int where = 0;
- struct menu *mi;
-
- TAILQ_FOREACH(mi, menuq, entry)
- if (off == where++)
- return mi->ctx;
- return (NULL);
-}
-#endif
-
void *
grab_menu(XButtonEvent *e, struct menu_q *menuq)
{
struct screen_ctx *sc;
struct menu *mi;
- XEvent ev;
- int i, n, cur = 0, old, wide, high, status, drawn, warp;
- int x, y, dx, dy, xmax, ymax;
- int tx, ty;
+ XEvent event;
struct fontdesc *font = DefaultFont;
+ int x, y, width, height, tothigh, i, no, entry, prev;
+ int fx, fy;
+
+ no = i = width = 0;
if ((sc = screen_fromroot(e->root)) == NULL || e->window == sc->menuwin)
return (NULL);
- dx = 0;
- i = 0;
TAILQ_FOREACH(mi, menuq, entry) {
- wide = font_width(font, mi->text, strlen(mi->text)) + 4;
- if (wide > dx)
- dx = wide;
- if (mi->lasthit)
- cur = i;
- i++;
+ i = font_width(font, mi->text, strlen(mi->text)) + 4;
+ if (i > width)
+ width = i;
+ no++;
}
- n = i;
-
- wide = dx;
- high = font_ascent(font) + font_descent(font) + 1;
- dy = n*high;
- x = e->x - wide/2;
- y = e->y - cur*high - high/2;
- warp = 0;
- /* XXX - cache these in sc. */
- xmax = DisplayWidth(X_Dpy, sc->which);
- ymax = DisplayHeight(X_Dpy, sc->which);
- if (x < 0) {
- e->x -= x;
- x = 0;
- warp++;
+ if (!sc->maxinitialised) {
+ sc->xmax = DisplayWidth(X_Dpy, sc->which);
+ sc->ymax = DisplayHeight(X_Dpy, sc->which);
}
- if (x+wide >= xmax) {
- e->x -= x+wide-xmax;
- x = xmax-wide;
- warp++;
- }
- if (y < 0) {
- e->y -= y;
+
+ height = font_ascent(font) + font_descent(font) + 1;
+ tothigh = height * no;
+
+ x = e->x - width/2;
+ y = e->y - height/2;
+
+ /* does it fit on the screen? */
+ if (x < 0)
+ x = 0;
+ else if (x+width >= sc->xmax)
+ x = sc->xmax - width;
+
+ if (y < 0)
y = 0;
- warp++;
- }
- if (y+dy >= ymax) {
- e->y -= y+dy-ymax;
- y = ymax-dy;
- warp++;
- }
- if (warp)
- xu_ptr_setpos(e->root, e->x, e->y);
+ else if (y+tothigh >= sc->ymax)
+ y = sc->ymax - tothigh;
- XMoveResizeWindow(X_Dpy, sc->menuwin, x, y, dx, dy);
+ xu_ptr_setpos(e->root, x + width/2, y + height/2);
+
+ XMoveResizeWindow(X_Dpy, sc->menuwin, x, y, width, tothigh);
XSelectInput(X_Dpy, sc->menuwin, MenuMask);
XMapRaised(X_Dpy, sc->menuwin);
- status = xu_ptr_grab(sc->menuwin, MenuGrabMask, Cursor_select);
- if (status < 0) {
+
+ if (xu_ptr_grab(sc->menuwin, MenuGrabMask, Cursor_select) < 0) {
XUnmapWindow(X_Dpy, sc->menuwin);
return (NULL);
}
- drawn = 0;
-
-#ifdef notyet
- if (e->button == Button1) {
- struct client_ctx *cc;
- cc = grab_menu_getcc(menuq, cur);
- if (cc != NULL) {
- client_unhide(cc);
- XRaiseWindow(X_Dpy, sc->menuwin);
- }
- }
-#endif
+
+ entry = prev = -1;
for (;;) {
- XMaskEvent(X_Dpy, MenuMask, &ev);
- switch (ev.type) {
- default:
- warnx("menuhit: unknown ev.type %d\n", ev.type);
- break;
- case ButtonPress:
+ XMaskEvent(X_Dpy, MenuMask, &event);
+ switch (event.type) {
+ case Expose:
+ XClearWindow(X_Dpy, sc->menuwin);
+ i = 0;
+ TAILQ_FOREACH(mi, menuq, entry) {
+ fx = (width - font_width(font, mi->text,
+ strlen(mi->text)))/2;
+ fy = height*i + font_ascent(font) + 1;
+ font_draw(font, mi->text, strlen(mi->text),
+ sc->menuwin, fx, fy);
+ i++;
+ }
+ if (entry != -1)
+ XFillRectangle(X_Dpy, sc->menuwin, sc->hlgc,
+ 0, entry*height, width, height);
+ case MotionNotify:
+ prev = entry;
+ entry = menu_calc_entry(event.xbutton.x,
+ event.xbutton.y, width, height, no);
+ if (prev != -1)
+ XFillRectangle(X_Dpy, sc->menuwin, sc->hlgc,
+ 0, height*prev, width, height);
+ if (entry != -1) {
+ xu_ptr_regrab(MenuGrabMask, Cursor_select);
+ XFillRectangle(X_Dpy, sc->menuwin, sc->hlgc,
+ 0, height*entry, width, height);
+ } else
+ xu_ptr_regrab(MenuGrabMask, Cursor_default);
break;
case ButtonRelease:
- if (ev.xbutton.button != e->button)
+ if (event.xbutton.button != e->button)
break;
- x = ev.xbutton.x;
- y = ev.xbutton.y;
- i = y/high;
- if (cur >= 0 && y >= cur*high-3 && y < (cur+1)*high+3)
- i = cur;
- if (x < 0 || x > wide || y < -3)
- i = -1;
- else if (i < 0 || i >= n)
- i = -1;
-/* else */
-/* m->lasthit = i; */
- if (!_nobuttons(&ev.xbutton))
- i = -1;
-
- /* XXX */
- /* ungrab(&ev.xbutton); */
+ entry = menu_calc_entry(event.xbutton.x,
+ event.xbutton.y, width, height, no);
xu_ptr_ungrab();
XUnmapWindow(X_Dpy, sc->menuwin);
- n = 0;
+
+ i = 0;
TAILQ_FOREACH(mi, menuq, entry)
- if (i == n++)
+ if (entry == i++)
break;
-
return (mi);
- case MotionNotify:
- if (!drawn)
- break;
- x = ev.xbutton.x;
- y = ev.xbutton.y;
- old = cur;
- cur = y/high;
- if (old >= 0 && y >= old*high-3 && y < (old+1)*high+3)
- cur = old;
- if (x < 0 || x > wide || y < -3)
- cur = -1;
- else if (cur < 0 || cur >= n)
- cur = -1;
- if (cur == old)
- break;
- if (old >= 0 && old < n) {
-#ifdef notyet
- if (e->button == Button1) {
- struct client_ctx *cc;
- cc = grab_menu_getcc(menuq, old);
- if (cc != NULL)
- client_hide(cc);
- }
-#endif
- XFillRectangle(X_Dpy, sc->menuwin,
- sc->hlgc, 0, old*high, wide, high);
- }
- if (cur >= 0 && cur < n) {
-#ifdef notyet
- if (e->button == Button1) {
- struct client_ctx *cc;
- cc = grab_menu_getcc(menuq, cur);
- if (cc != NULL) {
- client_unhide(cc);
- XRaiseWindow(X_Dpy,
- sc->menuwin);
- }
- }
-#endif
- xu_ptr_regrab(MenuGrabMask, Cursor_select);
- XFillRectangle(X_Dpy, sc->menuwin,
- sc->hlgc, 0, cur*high, wide, high);
- } else
- xu_ptr_regrab(MenuGrabMask, Cursor_default);
+ default:
break;
- case Expose:
- XClearWindow(X_Dpy, sc->menuwin);
- i = 0;
- TAILQ_FOREACH(mi, menuq, entry) {
- tx = (wide - font_width(font, mi->text,
- strlen(mi->text)))/2;
- ty = i*high + font_ascent(font) + 1;
- font_draw(font, mi->text, strlen(mi->text),
- sc->menuwin, tx, ty);
- i++;
- }
- if (cur >= 0 && cur < n)
- XFillRectangle(X_Dpy, sc->menuwin,
- sc->hlgc, 0, cur*high, wide, high);
- drawn = 1;
}
}
}
@@ -447,86 +355,7 @@ grab_label(struct client_ctx *cc)
XUnmapWindow(X_Dpy, sc->searchwin);
}
-#define ExecMask (KeyPressMask|ExposureMask)
-
-void
-grab_exec(void)
-{
- int x, y, dx, dy, fontheight, focusrevert, len;
- char cmdstr[MAXPATHLEN];
- char dispstr[MAXPATHLEN + sizeof("exec>") - 1];
- char chr, str[2];
- enum ctltype ctl;
- struct fontdesc *font = DefaultFont;
- struct screen_ctx *sc = screen_current();
- XEvent e;
- Window focuswin;
-
- cmdstr[0] = '\0';
-
- xu_ptr_getpos(sc->rootwin, &x, &y);
-
- dy = fontheight = font_ascent(font) + font_descent(font) + 1;
- dx = font_width(font, "exec>", 5);
-
- XMoveResizeWindow(X_Dpy, sc->searchwin, x, y, dx, dy);
- XSelectInput(X_Dpy, sc->searchwin, ExecMask);
- XMapRaised(X_Dpy, sc->searchwin);
-
- XGetInputFocus(X_Dpy, &focuswin, &focusrevert);
- XSetInputFocus(X_Dpy, sc->searchwin,
- RevertToPointerRoot, CurrentTime);
-
- for (;;) {
- XMaskEvent(X_Dpy, ExecMask, &e);
-
- switch (e.type) {
- case KeyPress:
- if (input_keycodetrans(e.xkey.keycode, e.xkey.state,
- &ctl, &chr, 0) < 0)
- continue;
-
- switch (ctl) {
- case CTL_ERASEONE:
- if ((len = strlen(cmdstr)) > 0)
- cmdstr[len - 1] = '\0';
- break;
- case CTL_RETURN:
- if (strlen(cmdstr) > 0)
- u_spawn(cmdstr);
- goto out;
- break;
- case CTL_ABORT:
- goto out;
- default:
- break;
- }
-
- if (chr != '\0') {
- str[0] = chr;
- str[1] = '\0';
- strlcat(cmdstr, str, sizeof(cmdstr));
- }
- case Expose:
- snprintf(dispstr, sizeof(dispstr), "exec>%s", cmdstr);
-
- dx = font_width(font, dispstr, strlen(dispstr));
- dy = fontheight;
-
- XClearWindow(X_Dpy, sc->searchwin);
- XResizeWindow(X_Dpy, sc->searchwin, dx, dy);
-
- font_draw(font, dispstr, strlen(dispstr),
- sc->searchwin, 0, font_ascent(font) + 1);
- break;
- }
- }
- out:
- XSetInputFocus(X_Dpy, focuswin, focusrevert, CurrentTime);
- XUnmapWindow(X_Dpy, sc->searchwin);
-}
-
-int
+static int
_sweepcalc(struct client_ctx *cc, int x0, int y0, int motionx, int motiony)
{
int width, height;
@@ -560,12 +389,15 @@ _sweepcalc(struct client_ctx *cc, int x0, int y0, int motionx, int motiony)
return (width != cc->geom.width || height != cc->geom.height);
}
-/* XXX */
-int
-_nobuttons(XButtonEvent *e) /* Einstuerzende */
+static int
+menu_calc_entry(int x, int y, int width, int height, int noentries)
{
- int state;
+ int entry = y/height;
+
+ /* in bounds? */
+ if (x < 0 || x > width || y < 0 || y > height*noentries ||
+ entry < 0 || entry >= noentries)
+ entry = -1;
- state = (e->state & AllButtonMask);
- return (e->type == ButtonRelease) && (state & (state - 1)) == 0;
+ return entry;
}