mirror of
https://github.com/leahneukirchen/cwm.git
synced 2023-08-10 21:13:12 +03:00
Make menu_filter handle mouse movement too. This enables the keyboard
search dialogues to be manipulated with the mouse, too. It also allows me to shrink the codebase further by killing grab_menu(). One known issue with highlighting the first entry in a search dialogue, that'll be fixed soonish. ok okan@, tested by Edd Barrett and todd@.
This commit is contained in:
parent
1e46ba72f7
commit
779cf04f05
6
calmwm.c
6
calmwm.c
@ -202,10 +202,6 @@ x_setupscreen(struct screen_ctx *sc, u_int which)
|
|||||||
GCForeground|GCBackground|GCFunction|
|
GCForeground|GCBackground|GCFunction|
|
||||||
GCLineWidth|GCSubwindowMode, &gv);
|
GCLineWidth|GCSubwindowMode, &gv);
|
||||||
|
|
||||||
sc->hlgc = XCreateGC(X_Dpy, sc->rootwin,
|
|
||||||
GCForeground|GCBackground|GCFunction|
|
|
||||||
GCLineWidth|GCSubwindowMode, &gv);
|
|
||||||
|
|
||||||
font_init(sc);
|
font_init(sc);
|
||||||
DefaultFont = font_getx(sc, Conf.DefaultFontName);
|
DefaultFont = font_getx(sc, Conf.DefaultFontName);
|
||||||
sc->fontheight = font_ascent(DefaultFont) +
|
sc->fontheight = font_ascent(DefaultFont) +
|
||||||
@ -218,7 +214,7 @@ x_setupscreen(struct screen_ctx *sc, u_int which)
|
|||||||
TAILQ_INIT(&sc->mruq);
|
TAILQ_INIT(&sc->mruq);
|
||||||
|
|
||||||
/* Initialize menu window. */
|
/* Initialize menu window. */
|
||||||
grab_menuinit(sc);
|
menu_init(sc);
|
||||||
|
|
||||||
/* Deal with existing clients. */
|
/* Deal with existing clients. */
|
||||||
XQueryTree(X_Dpy, sc->rootwin, &w0, &w1, &wins, &nwins);
|
XQueryTree(X_Dpy, sc->rootwin, &w0, &w1, &wins, &nwins);
|
||||||
|
5
calmwm.h
5
calmwm.h
@ -65,7 +65,7 @@ struct screen_ctx {
|
|||||||
whitecolor, blackcolor;
|
whitecolor, blackcolor;
|
||||||
char *display;
|
char *display;
|
||||||
unsigned long blackpixl, whitepixl, redpixl, bluepixl, cyanpixl;
|
unsigned long blackpixl, whitepixl, redpixl, bluepixl, cyanpixl;
|
||||||
GC gc, hlgc;
|
GC gc;
|
||||||
|
|
||||||
Pixmap gray, blue, red;
|
Pixmap gray, blue, red;
|
||||||
|
|
||||||
@ -356,6 +356,7 @@ void client_do_shape(struct client_ctx *);
|
|||||||
struct menu *menu_filter(struct menu_q *, char *, char *, int,
|
struct menu *menu_filter(struct menu_q *, char *, char *, int,
|
||||||
void (*)(struct menu_q *, struct menu_q *, char *),
|
void (*)(struct menu_q *, struct menu_q *, char *),
|
||||||
void (*)(struct menu *, int));
|
void (*)(struct menu *, int));
|
||||||
|
void menu_init(struct screen_ctx *);
|
||||||
|
|
||||||
void xev_handle_maprequest(struct xevent *, XEvent *);
|
void xev_handle_maprequest(struct xevent *, XEvent *);
|
||||||
void xev_handle_unmapnotify(struct xevent *, XEvent *);
|
void xev_handle_unmapnotify(struct xevent *, XEvent *);
|
||||||
@ -405,8 +406,6 @@ void u_exec(char *);
|
|||||||
|
|
||||||
void grab_sweep(struct client_ctx *);
|
void grab_sweep(struct client_ctx *);
|
||||||
void grab_drag(struct client_ctx *);
|
void 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_label(struct client_ctx *);
|
||||||
|
|
||||||
void xfree(void *);
|
void xfree(void *);
|
||||||
|
111
grab.c
111
grab.c
@ -145,117 +145,6 @@ grab_drag(struct client_ctx *cc)
|
|||||||
/* NOTREACHED */
|
/* NOTREACHED */
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MenuMask (ButtonMask|ButtonMotionMask|ExposureMask)
|
|
||||||
#define MenuGrabMask (ButtonMask|ButtonMotionMask|StructureNotifyMask)
|
|
||||||
#define AllButtonMask (Button1Mask|Button2Mask|Button3Mask|Button4Mask|Button5Mask)
|
|
||||||
|
|
||||||
void *
|
|
||||||
grab_menu(XButtonEvent *e, struct menu_q *menuq)
|
|
||||||
{
|
|
||||||
struct screen_ctx *sc;
|
|
||||||
struct menu *mi;
|
|
||||||
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);
|
|
||||||
|
|
||||||
TAILQ_FOREACH(mi, menuq, entry) {
|
|
||||||
i = font_width(font, mi->text, strlen(mi->text)) + 4;
|
|
||||||
if (i > width)
|
|
||||||
width = i;
|
|
||||||
no++;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
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);
|
|
||||||
|
|
||||||
if (xu_ptr_grab(sc->menuwin, MenuGrabMask, Cursor_select) < 0) {
|
|
||||||
XUnmapWindow(X_Dpy, sc->menuwin);
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
entry = prev = -1;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
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++;
|
|
||||||
}
|
|
||||||
/* FALLTHROUGH */
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
grab_menuinit(struct screen_ctx *sc)
|
|
||||||
{
|
|
||||||
sc->menuwin = XCreateSimpleWindow(X_Dpy, sc->rootwin, 0, 0,
|
|
||||||
1, 1, 1, sc->blackpixl, sc->whitepixl);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
_sweepcalc(struct client_ctx *cc, int x0, int y0, int motionx, int motiony)
|
_sweepcalc(struct client_ctx *cc, int x0, int y0, int motionx, int motiony)
|
||||||
{
|
{
|
||||||
|
2
group.c
2
group.c
@ -273,7 +273,7 @@ group_menu(XButtonEvent *e)
|
|||||||
if (TAILQ_EMPTY(&menuq))
|
if (TAILQ_EMPTY(&menuq))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mi = (struct menu *)grab_menu(e, &menuq);
|
mi = menu_filter(&menuq, NULL, NULL, 0, NULL, NULL);
|
||||||
|
|
||||||
if (mi == NULL || mi->ctx == NULL)
|
if (mi == NULL || mi->ctx == NULL)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
171
menu.c
171
menu.c
@ -18,25 +18,49 @@
|
|||||||
#include "headers.h"
|
#include "headers.h"
|
||||||
#include "calmwm.h"
|
#include "calmwm.h"
|
||||||
|
|
||||||
#define KeyMask (KeyPressMask|ExposureMask)
|
#define KeyMask (KeyPressMask|ExposureMask)
|
||||||
|
#define MenuMask (ButtonMask|ButtonMotionMask|ExposureMask| \
|
||||||
|
PointerMotionMask)
|
||||||
|
#define MenuGrabMask (ButtonMask|ButtonMotionMask|StructureNotifyMask|\
|
||||||
|
PointerMotionMask)
|
||||||
|
#define PROMPT_SCHAR '»'
|
||||||
|
#define PROMPT_ECHAR '«'
|
||||||
|
|
||||||
struct menu_ctx {
|
struct menu_ctx {
|
||||||
char searchstr[MENU_MAXENTRY + 1];
|
char searchstr[MENU_MAXENTRY + 1];
|
||||||
char dispstr[MENU_MAXENTRY*2 + 1];
|
char dispstr[MENU_MAXENTRY*2 + 1];
|
||||||
char promptstr[MENU_MAXENTRY + 1];
|
char promptstr[MENU_MAXENTRY + 1];
|
||||||
|
int hasprompt;
|
||||||
int list;
|
int list;
|
||||||
int listing;
|
int listing;
|
||||||
int changed;
|
int changed;
|
||||||
int noresult;
|
int noresult;
|
||||||
|
int prev;
|
||||||
|
int entry;
|
||||||
|
int width;
|
||||||
|
int num;
|
||||||
int x;
|
int x;
|
||||||
int y; /* location */
|
int y;
|
||||||
void (*match)(struct menu_q *, struct menu_q *, char *);
|
void (*match)(struct menu_q *, struct menu_q *, char *);
|
||||||
void (*print)(struct menu *, int);
|
void (*print)(struct menu *, int);
|
||||||
};
|
};
|
||||||
static struct menu *menu_handle_key(XEvent *, struct menu_ctx *,
|
static struct menu *menu_handle_key(XEvent *, struct menu_ctx *,
|
||||||
struct menu_q *, struct menu_q *);
|
struct menu_q *, struct menu_q *);
|
||||||
|
static void menu_handle_move(XEvent *, struct menu_ctx *,
|
||||||
|
struct screen_ctx *);
|
||||||
|
struct menu *menu_handle_release(XEvent *, struct menu_ctx *,
|
||||||
|
struct screen_ctx *, struct menu_q *);
|
||||||
static void menu_draw(struct screen_ctx *, struct menu_ctx *,
|
static void menu_draw(struct screen_ctx *, struct menu_ctx *,
|
||||||
struct menu_q *, struct menu_q *);
|
struct menu_q *, struct menu_q *);
|
||||||
|
static int menu_calc_entry(struct screen_ctx *, struct menu_ctx *,
|
||||||
|
int, int);
|
||||||
|
|
||||||
|
void
|
||||||
|
menu_init(struct screen_ctx *sc)
|
||||||
|
{
|
||||||
|
sc->menuwin = XCreateSimpleWindow(X_Dpy, sc->rootwin, 0, 0,
|
||||||
|
1, 1, 1, sc->blackpixl, sc->whitepixl);
|
||||||
|
}
|
||||||
|
|
||||||
struct menu *
|
struct menu *
|
||||||
menu_filter(struct menu_q *menuq, char *prompt, char *initial, int dummy,
|
menu_filter(struct menu_q *menuq, char *prompt, char *initial, int dummy,
|
||||||
@ -49,8 +73,7 @@ menu_filter(struct menu_q *menuq, char *prompt, char *initial, int dummy,
|
|||||||
struct menu *mi = NULL;
|
struct menu *mi = NULL;
|
||||||
XEvent e;
|
XEvent e;
|
||||||
Window focuswin;
|
Window focuswin;
|
||||||
int dx, dy, focusrevert;
|
int Mask, focusrevert;
|
||||||
char endchar = '«';
|
|
||||||
struct fontdesc *font = DefaultFont;
|
struct fontdesc *font = DefaultFont;
|
||||||
|
|
||||||
TAILQ_INIT(&resultq);
|
TAILQ_INIT(&resultq);
|
||||||
@ -59,8 +82,19 @@ menu_filter(struct menu_q *menuq, char *prompt, char *initial, int dummy,
|
|||||||
|
|
||||||
xu_ptr_getpos(sc->rootwin, &mc.x, &mc.y);
|
xu_ptr_getpos(sc->rootwin, &mc.x, &mc.y);
|
||||||
|
|
||||||
if (prompt == NULL)
|
if (prompt == NULL) {
|
||||||
prompt = "search";
|
Mask = MenuMask;
|
||||||
|
mc.promptstr[0] = '\0';
|
||||||
|
mc.list = 1;
|
||||||
|
} else {
|
||||||
|
Mask = MenuMask | KeyMask; /* only accept keys if prompt */
|
||||||
|
snprintf(mc.promptstr, sizeof(mc.promptstr), "%s%c", prompt,
|
||||||
|
PROMPT_SCHAR);
|
||||||
|
snprintf(mc.dispstr, sizeof(mc.dispstr), "%s%s%c", mc.promptstr,
|
||||||
|
mc.searchstr, PROMPT_ECHAR);
|
||||||
|
mc.width = font_width(font, mc.dispstr, strlen(mc.dispstr));
|
||||||
|
mc.hasprompt = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (initial != NULL)
|
if (initial != NULL)
|
||||||
strlcpy(mc.searchstr, initial, sizeof(mc.searchstr));
|
strlcpy(mc.searchstr, initial, sizeof(mc.searchstr));
|
||||||
@ -69,18 +103,14 @@ menu_filter(struct menu_q *menuq, char *prompt, char *initial, int dummy,
|
|||||||
|
|
||||||
mc.match = match;
|
mc.match = match;
|
||||||
mc.print = print;
|
mc.print = print;
|
||||||
|
mc.entry = mc.prev = -1;
|
||||||
|
|
||||||
snprintf(mc.promptstr, sizeof(mc.promptstr), "%s»", prompt);
|
XMoveResizeWindow(X_Dpy, sc->menuwin, mc.x, mc.y, mc.width,
|
||||||
snprintf(mc.dispstr, sizeof(mc.dispstr), "%s%s%c", mc.promptstr,
|
sc->fontheight);
|
||||||
mc.searchstr, endchar);
|
XSelectInput(X_Dpy, sc->menuwin, Mask);
|
||||||
dx = font_width(font, mc.dispstr, strlen(mc.dispstr));
|
|
||||||
dy = sc->fontheight;
|
|
||||||
|
|
||||||
XMoveResizeWindow(X_Dpy, sc->menuwin, mc.x, mc.y, dx, dy);
|
|
||||||
XSelectInput(X_Dpy, sc->menuwin, KeyMask);
|
|
||||||
XMapRaised(X_Dpy, sc->menuwin);
|
XMapRaised(X_Dpy, sc->menuwin);
|
||||||
|
|
||||||
if (xu_ptr_grab(sc->menuwin, 0, Cursor_question) < 0) {
|
if (xu_ptr_grab(sc->menuwin, MenuGrabMask, Cursor_question) < 0) {
|
||||||
XUnmapWindow(X_Dpy, sc->menuwin);
|
XUnmapWindow(X_Dpy, sc->menuwin);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
@ -91,9 +121,11 @@ menu_filter(struct menu_q *menuq, char *prompt, char *initial, int dummy,
|
|||||||
for (;;) {
|
for (;;) {
|
||||||
mc.changed = 0;
|
mc.changed = 0;
|
||||||
|
|
||||||
XWindowEvent(X_Dpy, sc->menuwin, KeyMask, &e);
|
XWindowEvent(X_Dpy, sc->menuwin, Mask, &e);
|
||||||
|
|
||||||
switch (e.type) {
|
switch (e.type) {
|
||||||
|
default:
|
||||||
|
break;
|
||||||
case KeyPress:
|
case KeyPress:
|
||||||
if ((mi = menu_handle_key(&e, &mc, menuq, &resultq))
|
if ((mi = menu_handle_key(&e, &mc, menuq, &resultq))
|
||||||
!= NULL)
|
!= NULL)
|
||||||
@ -102,6 +134,14 @@ menu_filter(struct menu_q *menuq, char *prompt, char *initial, int dummy,
|
|||||||
case Expose:
|
case Expose:
|
||||||
menu_draw(sc, &mc, menuq, &resultq);
|
menu_draw(sc, &mc, menuq, &resultq);
|
||||||
break;
|
break;
|
||||||
|
case MotionNotify:
|
||||||
|
menu_handle_move(&e, &mc, sc);
|
||||||
|
break;
|
||||||
|
case ButtonRelease:
|
||||||
|
if ((mi = menu_handle_release(&e, &mc, sc, &resultq))
|
||||||
|
!= NULL)
|
||||||
|
goto out;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out:
|
out:
|
||||||
@ -211,9 +251,8 @@ menu_draw(struct screen_ctx *sc, struct menu_ctx *mc, struct menu_q *menuq,
|
|||||||
struct menu_q *resultq)
|
struct menu_q *resultq)
|
||||||
{
|
{
|
||||||
struct menu *mi;
|
struct menu *mi;
|
||||||
char endchar = '«';
|
|
||||||
int n = 0;
|
int n = 0;
|
||||||
int dx, dy;
|
int dy;
|
||||||
int xsave, ysave;
|
int xsave, ysave;
|
||||||
int warp;
|
int warp;
|
||||||
struct fontdesc *font = DefaultFont;
|
struct fontdesc *font = DefaultFont;
|
||||||
@ -230,10 +269,16 @@ menu_draw(struct screen_ctx *sc, struct menu_ctx *mc, struct menu_q *menuq,
|
|||||||
mc->listing = 0;
|
mc->listing = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(mc->dispstr, sizeof(mc->dispstr), "%s%s%c",
|
mc->num = 0;
|
||||||
mc->promptstr, mc->searchstr, endchar);
|
mc->width = 0;
|
||||||
dx = font_width(font, mc->dispstr, strlen(mc->dispstr));
|
dy = 0;
|
||||||
dy = sc->fontheight;
|
if (mc->hasprompt) {
|
||||||
|
snprintf(mc->dispstr, sizeof(mc->dispstr), "%s%s%c",
|
||||||
|
mc->promptstr, mc->searchstr, PROMPT_ECHAR);
|
||||||
|
mc->width = font_width(font, mc->dispstr, strlen(mc->dispstr));
|
||||||
|
dy = sc->fontheight;
|
||||||
|
mc->num = 1;
|
||||||
|
}
|
||||||
|
|
||||||
TAILQ_FOREACH(mi, resultq, resultentry) {
|
TAILQ_FOREACH(mi, resultq, resultentry) {
|
||||||
char *text;
|
char *text;
|
||||||
@ -246,17 +291,18 @@ menu_draw(struct screen_ctx *sc, struct menu_ctx *mc, struct menu_q *menuq,
|
|||||||
text = mi->text;
|
text = mi->text;
|
||||||
}
|
}
|
||||||
|
|
||||||
dx = MAX(dx, font_width(font, text,
|
mc->width = MAX(mc->width, font_width(font, text,
|
||||||
MIN(strlen(text), MENU_MAXENTRY)));
|
MIN(strlen(text), MENU_MAXENTRY)));
|
||||||
dy += sc->fontheight;
|
dy += sc->fontheight;
|
||||||
|
mc->num++;
|
||||||
}
|
}
|
||||||
|
|
||||||
xsave = mc->x;
|
xsave = mc->x;
|
||||||
ysave = mc->y;
|
ysave = mc->y;
|
||||||
if (mc->x < 0)
|
if (mc->x < 0)
|
||||||
mc->x = 0;
|
mc->x = 0;
|
||||||
else if (mc->x + dx >= sc->xmax)
|
else if (mc->x + mc->width >= sc->xmax)
|
||||||
mc->x = sc->xmax - dx;
|
mc->x = sc->xmax - mc->width;
|
||||||
|
|
||||||
if (mc->y + dy >= sc->ymax)
|
if (mc->y + dy >= sc->ymax)
|
||||||
mc->y = sc->ymax - dy;
|
mc->y = sc->ymax - dy;
|
||||||
@ -268,12 +314,15 @@ menu_draw(struct screen_ctx *sc, struct menu_ctx *mc, struct menu_q *menuq,
|
|||||||
xu_ptr_setpos(sc->rootwin, mc->x, mc->y);
|
xu_ptr_setpos(sc->rootwin, mc->x, mc->y);
|
||||||
|
|
||||||
XClearWindow(X_Dpy, sc->menuwin);
|
XClearWindow(X_Dpy, sc->menuwin);
|
||||||
XMoveResizeWindow(X_Dpy, sc->menuwin, mc->x, mc->y, dx, dy);
|
XMoveResizeWindow(X_Dpy, sc->menuwin, mc->x, mc->y, mc->width, dy);
|
||||||
|
|
||||||
font_draw(font, mc->dispstr, strlen(mc->dispstr), sc->menuwin,
|
if (mc->hasprompt) {
|
||||||
0, font_ascent(font) + 1);
|
font_draw(font, mc->dispstr, strlen(mc->dispstr), sc->menuwin,
|
||||||
|
0, font_ascent(font) + 1);
|
||||||
|
n = 1;
|
||||||
|
} else
|
||||||
|
n = 0;
|
||||||
|
|
||||||
n = 1;
|
|
||||||
TAILQ_FOREACH(mi, resultq, resultentry) {
|
TAILQ_FOREACH(mi, resultq, resultentry) {
|
||||||
char *text = mi->print[0] != '\0' ?
|
char *text = mi->print[0] != '\0' ?
|
||||||
mi->print : mi->text;
|
mi->print : mi->text;
|
||||||
@ -285,12 +334,68 @@ menu_draw(struct screen_ctx *sc, struct menu_ctx *mc, struct menu_q *menuq,
|
|||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (n > 1)
|
if (mc->hasprompt && n > 1)
|
||||||
XFillRectangle(X_Dpy, sc->menuwin, sc->gc,
|
XFillRectangle(X_Dpy, sc->menuwin, sc->gc,
|
||||||
0, sc->fontheight, dx, sc->fontheight);
|
0, sc->fontheight, mc->width, sc->fontheight);
|
||||||
|
|
||||||
if (mc->noresult)
|
if (mc->noresult)
|
||||||
XFillRectangle(X_Dpy, sc->menuwin, sc->gc,
|
XFillRectangle(X_Dpy, sc->menuwin, sc->gc,
|
||||||
0, 0, dx, sc->fontheight);
|
0, 0, mc->width, sc->fontheight);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
menu_handle_move(XEvent *e, struct menu_ctx *mc, struct screen_ctx *sc)
|
||||||
|
{
|
||||||
|
mc->prev = mc->entry;
|
||||||
|
mc->entry = menu_calc_entry(sc, mc, e->xbutton.x, e->xbutton.y);
|
||||||
|
|
||||||
|
if (mc->prev != -1)
|
||||||
|
XFillRectangle(X_Dpy, sc->menuwin, sc->gc, 0,
|
||||||
|
sc->fontheight * mc->prev, mc->width, sc->fontheight);
|
||||||
|
if (mc->entry != -1) {
|
||||||
|
xu_ptr_regrab(MenuGrabMask, Cursor_select);
|
||||||
|
XFillRectangle(X_Dpy, sc->menuwin, sc->gc, 0,
|
||||||
|
sc->fontheight * mc->entry, mc->width, sc->fontheight);
|
||||||
|
} else
|
||||||
|
xu_ptr_regrab(MenuGrabMask, Cursor_default);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct menu *
|
||||||
|
menu_handle_release(XEvent *e, struct menu_ctx *mc, struct screen_ctx *sc,
|
||||||
|
struct menu_q *resultq)
|
||||||
|
{
|
||||||
|
struct menu *mi;
|
||||||
|
int entry, i = 0;
|
||||||
|
|
||||||
|
entry = menu_calc_entry(sc, mc, e->xbutton.x, e->xbutton.y);
|
||||||
|
xu_ptr_ungrab();
|
||||||
|
|
||||||
|
if (mc->hasprompt)
|
||||||
|
i = 1;
|
||||||
|
|
||||||
|
TAILQ_FOREACH(mi, resultq, resultentry)
|
||||||
|
if (entry == i++)
|
||||||
|
break;
|
||||||
|
if (mi == NULL) {
|
||||||
|
XMALLOC(mi, struct menu);
|
||||||
|
mi->text[0] = '\0';
|
||||||
|
mi->dummy = 1;
|
||||||
|
}
|
||||||
|
return (mi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
menu_calc_entry(struct screen_ctx *sc, struct menu_ctx *mc, int x, int y)
|
||||||
|
{
|
||||||
|
int entry = y / sc->fontheight;
|
||||||
|
|
||||||
|
/* in bounds? */
|
||||||
|
if (x < 0 || x > mc->width || y < 0 || y > sc->fontheight*mc->num ||
|
||||||
|
entry < 0 || entry >= mc->num)
|
||||||
|
entry = -1;
|
||||||
|
|
||||||
|
if (mc->hasprompt && entry == 0)
|
||||||
|
entry = -1;
|
||||||
|
|
||||||
|
return (entry);
|
||||||
}
|
}
|
||||||
|
@ -290,7 +290,7 @@ xev_handle_buttonpress(struct xevent *xev, XEvent *ee)
|
|||||||
if (TAILQ_EMPTY(&menuq))
|
if (TAILQ_EMPTY(&menuq))
|
||||||
goto out;
|
goto out;
|
||||||
|
|
||||||
mi = (struct menu *)grab_menu(e, &menuq);
|
mi = menu_filter(&menuq, NULL, NULL, 0, NULL, NULL);
|
||||||
if (mi == NULL)
|
if (mi == NULL)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user