mirror of
https://github.com/leahneukirchen/cwm.git
synced 2023-08-10 21:13:12 +03:00
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@.
This commit is contained in:
parent
e5cabb0f43
commit
1eed217b1c
6
calmwm.c
6
calmwm.c
@ -50,7 +50,6 @@ static char gray_bits[] = {0x02, 0x01};
|
||||
/* List borrowed from 9wm/rio */
|
||||
char *tryfonts[] = {
|
||||
"9x15bold",
|
||||
"blit",
|
||||
"*-lucidatypewriter-bold-*-14-*-75-*",
|
||||
"*-lucidatypewriter-medium-*-12-*-75-*",
|
||||
"fixed",
|
||||
@ -161,9 +160,7 @@ x_setup(char *display_name)
|
||||
Cursor_resize = XCreateFontCursor(X_Dpy, XC_bottom_right_corner);
|
||||
/* (used to be) XCreateFontCursor(X_Dpy, XC_hand1); */
|
||||
Cursor_select = XCreateFontCursor(X_Dpy, XC_hand1);
|
||||
/* Cursor_select = cursor_bigarrow(Curscreen); */
|
||||
Cursor_default = XCreateFontCursor(X_Dpy, XC_X_cursor);
|
||||
/* Cursor_default = cursor_bigarrow(Curscreen); */
|
||||
Cursor_question = XCreateFontCursor(X_Dpy, XC_question_arrow);
|
||||
}
|
||||
|
||||
@ -288,9 +285,6 @@ x_setupscreen(struct screen_ctx *sc, u_int which)
|
||||
rootattr.event_mask = ChildMask|PropertyChangeMask|EnterWindowMask|
|
||||
LeaveWindowMask|ColormapChangeMask|ButtonMask;
|
||||
|
||||
/* Set the root cursor to a nice obnoxious arrow :-) */
|
||||
/* rootattr.cursor = cursor_bigarrow(sc); */
|
||||
|
||||
XChangeWindowAttributes(X_Dpy, sc->rootwin,
|
||||
/* CWCursor| */CWEventMask, &rootattr);
|
||||
|
||||
|
6
calmwm.h
6
calmwm.h
@ -79,6 +79,10 @@ struct screen_ctx {
|
||||
|
||||
int altpersist;
|
||||
|
||||
int maxinitialised;
|
||||
int xmax;
|
||||
int ymax;
|
||||
|
||||
FILE *notifier;
|
||||
|
||||
struct cycle_entry_q mruq;
|
||||
@ -276,7 +280,6 @@ struct menu {
|
||||
char text[MENU_MAXENTRY + 1];
|
||||
char print[MENU_MAXENTRY + 1];
|
||||
void *ctx;
|
||||
short lasthit;
|
||||
short dummy;
|
||||
};
|
||||
|
||||
@ -399,7 +402,6 @@ int grab_drag(struct client_ctx *);
|
||||
void grab_menuinit(struct screen_ctx *);
|
||||
void *grab_menu(XButtonEvent *, struct menu_q *);
|
||||
void grab_label(struct client_ctx *);
|
||||
void grab_exec(void);
|
||||
|
||||
void xfree(void *);
|
||||
void *xmalloc(size_t);
|
||||
|
334
grab.c
334
grab.c
@ -21,8 +21,8 @@
|
||||
#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;
|
||||
if (!sc->maxinitialised) {
|
||||
sc->xmax = DisplayWidth(X_Dpy, sc->which);
|
||||
sc->ymax = DisplayHeight(X_Dpy, sc->which);
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
warp++;
|
||||
}
|
||||
if (x+wide >= xmax) {
|
||||
e->x -= x+wide-xmax;
|
||||
x = xmax-wide;
|
||||
warp++;
|
||||
}
|
||||
if (y < 0) {
|
||||
e->y -= y;
|
||||
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 (x+width >= sc->xmax)
|
||||
x = sc->xmax - width;
|
||||
|
||||
XMoveResizeWindow(X_Dpy, sc->menuwin, x, y, dx, dy);
|
||||
if (y < 0)
|
||||
y = 0;
|
||||
else if (y+tothigh >= sc->ymax)
|
||||
y = sc->ymax - tothigh;
|
||||
|
||||
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:
|
||||
break;
|
||||
case ButtonRelease:
|
||||
if (ev.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); */
|
||||
xu_ptr_ungrab();
|
||||
XUnmapWindow(X_Dpy, sc->menuwin);
|
||||
n = 0;
|
||||
TAILQ_FOREACH(mi, menuq, entry)
|
||||
if (i == n++)
|
||||
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);
|
||||
break;
|
||||
XMaskEvent(X_Dpy, MenuMask, &event);
|
||||
switch (event.type) {
|
||||
case Expose:
|
||||
XClearWindow(X_Dpy, sc->menuwin);
|
||||
i = 0;
|
||||
TAILQ_FOREACH(mi, menuq, entry) {
|
||||
tx = (wide - font_width(font, mi->text,
|
||||
fx = (width - font_width(font, mi->text,
|
||||
strlen(mi->text)))/2;
|
||||
ty = i*high + font_ascent(font) + 1;
|
||||
fy = height*i + font_ascent(font) + 1;
|
||||
font_draw(font, mi->text, strlen(mi->text),
|
||||
sc->menuwin, tx, ty);
|
||||
sc->menuwin, fx, fy);
|
||||
i++;
|
||||
}
|
||||
if (cur >= 0 && cur < n)
|
||||
XFillRectangle(X_Dpy, sc->menuwin,
|
||||
sc->hlgc, 0, cur*high, wide, high);
|
||||
drawn = 1;
|
||||
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 (event.xbutton.button != e->button)
|
||||
break;
|
||||
entry = menu_calc_entry(event.xbutton.x,
|
||||
event.xbutton.y, width, height, no);
|
||||
xu_ptr_ungrab();
|
||||
XUnmapWindow(X_Dpy, sc->menuwin);
|
||||
|
||||
i = 0;
|
||||
TAILQ_FOREACH(mi, menuq, entry)
|
||||
if (entry == i++)
|
||||
break;
|
||||
return (mi);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
|
||||
state = (e->state & AllButtonMask);
|
||||
return (e->type == ButtonRelease) && (state & (state - 1)) == 0;
|
||||
/* in bounds? */
|
||||
if (x < 0 || x > width || y < 0 || y > height*noentries ||
|
||||
entry < 0 || entry >= noentries)
|
||||
entry = -1;
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user