aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoroga2008-05-21 14:11:19 +0000
committeroga2008-05-21 14:11:19 +0000
commit70508fca2af57f5b3b025a45f7b5a6a66e31d4cb (patch)
tree2f68ba9395dbae3a11e6d2401bc09b62e09783ad
parentc4a8f44931713f32f250264ca00520aae30fc0e3 (diff)
downloadcwm-70508fca2af57f5b3b025a45f7b5a6a66e31d4cb.tar.gz
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@.
Diffstat (limited to '')
-rw-r--r--calmwm.c8
-rw-r--r--calmwm.h7
-rw-r--r--grab.c113
-rw-r--r--group.c4
-rw-r--r--menu.c169
-rw-r--r--xevents.c4
6 files changed, 147 insertions, 158 deletions
diff --git a/calmwm.c b/calmwm.c
index 79b62ea..3a0f18c 100644
--- a/calmwm.c
+++ b/calmwm.c
@@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: calmwm.c,v 1.19 2008/05/20 14:50:51 oga Exp $
+ * $Id: calmwm.c,v 1.20 2008/05/21 14:11:19 oga Exp $
*/
#include "headers.h"
@@ -202,10 +202,6 @@ x_setupscreen(struct screen_ctx *sc, u_int which)
GCForeground|GCBackground|GCFunction|
GCLineWidth|GCSubwindowMode, &gv);
- sc->hlgc = XCreateGC(X_Dpy, sc->rootwin,
- GCForeground|GCBackground|GCFunction|
- GCLineWidth|GCSubwindowMode, &gv);
-
font_init(sc);
DefaultFont = font_getx(sc, Conf.DefaultFontName);
sc->fontheight = font_ascent(DefaultFont) +
@@ -218,7 +214,7 @@ x_setupscreen(struct screen_ctx *sc, u_int which)
TAILQ_INIT(&sc->mruq);
/* Initialize menu window. */
- grab_menuinit(sc);
+ menu_init(sc);
/* Deal with existing clients. */
XQueryTree(X_Dpy, sc->rootwin, &w0, &w1, &wins, &nwins);
diff --git a/calmwm.h b/calmwm.h
index 3c9cb3c..5a2af4a 100644
--- a/calmwm.h
+++ b/calmwm.h
@@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: calmwm.h,v 1.49 2008/05/20 14:50:51 oga Exp $
+ * $Id: calmwm.h,v 1.50 2008/05/21 14:11:19 oga Exp $
*/
#ifndef _CALMWM_H_
@@ -65,7 +65,7 @@ struct screen_ctx {
whitecolor, blackcolor;
char *display;
unsigned long blackpixl, whitepixl, redpixl, bluepixl, cyanpixl;
- GC gc, hlgc;
+ GC gc;
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,
void (*)(struct menu_q *, struct menu_q *, char *),
void (*)(struct menu *, int));
+void menu_init(struct screen_ctx *);
void xev_handle_maprequest(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_drag(struct client_ctx *);
-void grab_menuinit(struct screen_ctx *);
-void *grab_menu(XButtonEvent *, struct menu_q *);
void grab_label(struct client_ctx *);
void xfree(void *);
diff --git a/grab.c b/grab.c
index d4abc87..3aa7ff3 100644
--- a/grab.c
+++ b/grab.c
@@ -15,7 +15,7 @@
* 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.13 2008/05/20 14:50:51 oga Exp $
+ * $Id: grab.c,v 1.14 2008/05/21 14:11:19 oga Exp $
*/
#include "headers.h"
@@ -145,117 +145,6 @@ grab_drag(struct client_ctx *cc)
/* 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
_sweepcalc(struct client_ctx *cc, int x0, int y0, int motionx, int motiony)
{
diff --git a/group.c b/group.c
index 294d7f7..1be7cd1 100644
--- a/group.c
+++ b/group.c
@@ -16,7 +16,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: group.c,v 1.16 2008/05/19 17:13:55 oga Exp $
+ * $Id: group.c,v 1.17 2008/05/21 14:11:19 oga Exp $
*/
#include "headers.h"
@@ -273,7 +273,7 @@ group_menu(XButtonEvent *e)
if (TAILQ_EMPTY(&menuq))
return;
- mi = (struct menu *)grab_menu(e, &menuq);
+ mi = menu_filter(&menuq, NULL, NULL, 0, NULL, NULL);
if (mi == NULL || mi->ctx == NULL)
goto cleanup;
diff --git a/menu.c b/menu.c
index a022f84..b3a77cf 100644
--- a/menu.c
+++ b/menu.c
@@ -18,25 +18,49 @@
#include "headers.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 {
char searchstr[MENU_MAXENTRY + 1];
char dispstr[MENU_MAXENTRY*2 + 1];
char promptstr[MENU_MAXENTRY + 1];
+ int hasprompt;
int list;
int listing;
int changed;
int noresult;
+ int prev;
+ int entry;
+ int width;
+ int num;
int x;
- int y; /* location */
+ int y;
void (*match)(struct menu_q *, struct menu_q *, char *);
void (*print)(struct menu *, int);
};
static struct menu *menu_handle_key(XEvent *, struct menu_ctx *,
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 *,
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 *
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;
XEvent e;
Window focuswin;
- int dx, dy, focusrevert;
- char endchar = '«';
+ int Mask, focusrevert;
struct fontdesc *font = DefaultFont;
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);
- if (prompt == NULL)
- prompt = "search";
+ if (prompt == NULL) {
+ 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)
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.print = print;
+ mc.entry = mc.prev = -1;
- snprintf(mc.promptstr, sizeof(mc.promptstr), "%s»", prompt);
- snprintf(mc.dispstr, sizeof(mc.dispstr), "%s%s%c", mc.promptstr,
- mc.searchstr, endchar);
- 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);
+ XMoveResizeWindow(X_Dpy, sc->menuwin, mc.x, mc.y, mc.width,
+ sc->fontheight);
+ XSelectInput(X_Dpy, sc->menuwin, Mask);
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);
return (NULL);
}
@@ -91,9 +121,11 @@ menu_filter(struct menu_q *menuq, char *prompt, char *initial, int dummy,
for (;;) {
mc.changed = 0;
- XWindowEvent(X_Dpy, sc->menuwin, KeyMask, &e);
+ XWindowEvent(X_Dpy, sc->menuwin, Mask, &e);
switch (e.type) {
+ default:
+ break;
case KeyPress:
if ((mi = menu_handle_key(&e, &mc, menuq, &resultq))
!= NULL)
@@ -102,6 +134,14 @@ menu_filter(struct menu_q *menuq, char *prompt, char *initial, int dummy,
case Expose:
menu_draw(sc, &mc, menuq, &resultq);
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:
@@ -211,9 +251,8 @@ menu_draw(struct screen_ctx *sc, struct menu_ctx *mc, struct menu_q *menuq,
struct menu_q *resultq)
{
struct menu *mi;
- char endchar = '«';
int n = 0;
- int dx, dy;
+ int dy;
int xsave, ysave;
int warp;
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;
}
- snprintf(mc->dispstr, sizeof(mc->dispstr), "%s%s%c",
- mc->promptstr, mc->searchstr, endchar);
- dx = font_width(font, mc->dispstr, strlen(mc->dispstr));
- dy = sc->fontheight;
+ mc->num = 0;
+ mc->width = 0;
+ dy = 0;
+ 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) {
char *text;
@@ -246,17 +291,18 @@ menu_draw(struct screen_ctx *sc, struct menu_ctx *mc, struct menu_q *menuq,
text = mi->text;
}
- dx = MAX(dx, font_width(font, text,
+ mc->width = MAX(mc->width, font_width(font, text,
MIN(strlen(text), MENU_MAXENTRY)));
dy += sc->fontheight;
+ mc->num++;
}
xsave = mc->x;
ysave = mc->y;
if (mc->x < 0)
mc->x = 0;
- else if (mc->x + dx >= sc->xmax)
- mc->x = sc->xmax - dx;
+ else if (mc->x + mc->width >= sc->xmax)
+ mc->x = sc->xmax - mc->width;
if (mc->y + dy >= sc->ymax)
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);
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,
- 0, font_ascent(font) + 1);
+ if (mc->hasprompt) {
+ 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) {
char *text = mi->print[0] != '\0' ?
mi->print : mi->text;
@@ -285,12 +334,68 @@ menu_draw(struct screen_ctx *sc, struct menu_ctx *mc, struct menu_q *menuq,
n++;
}
- if (n > 1)
+ if (mc->hasprompt && n > 1)
XFillRectangle(X_Dpy, sc->menuwin, sc->gc,
- 0, sc->fontheight, dx, sc->fontheight);
+ 0, sc->fontheight, mc->width, sc->fontheight);
if (mc->noresult)
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);
}
diff --git a/xevents.c b/xevents.c
index c0e53d0..5721543 100644
--- a/xevents.c
+++ b/xevents.c
@@ -15,7 +15,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
- * $Id: xevents.c,v 1.15 2008/05/19 12:56:58 okan Exp $
+ * $Id: xevents.c,v 1.16 2008/05/21 14:11:19 oga Exp $
*/
/*
@@ -290,7 +290,7 @@ xev_handle_buttonpress(struct xevent *xev, XEvent *ee)
if (TAILQ_EMPTY(&menuq))
goto out;
- mi = (struct menu *)grab_menu(e, &menuq);
+ mi = menu_filter(&menuq, NULL, NULL, 0, NULL, NULL);
if (mi == NULL)
goto cleanup;