allow fitering spot menus
This commit is contained in:
5
event.c
5
event.c
@@ -131,11 +131,10 @@ void key_press(XEvent *ev)
|
|||||||
unsigned int state = e->state & ~(LockMask|NumlockMask);
|
unsigned int state = e->state & ~(LockMask|NumlockMask);
|
||||||
while (XCheckTypedEvent(display, KeyPress, ev));
|
while (XCheckTypedEvent(display, KeyPress, ev));
|
||||||
|
|
||||||
int i, j; Monitor *m;
|
if (menu && menu->mb && menu->mb->window == e->window)
|
||||||
for_monitors(i, m) for_spots(j) if (menu && menu->mb && menu->mb->window == e->window)
|
|
||||||
{
|
{
|
||||||
int rc = menubox_keypress(menu->mb, ev);
|
int rc = menubox_keypress(menu->mb, ev);
|
||||||
menubox_draw(menu->mb);
|
menu_update();
|
||||||
|
|
||||||
if (rc == -2)
|
if (rc == -2)
|
||||||
menu_close();
|
menu_close();
|
||||||
|
|||||||
10
menu.c
10
menu.c
@@ -29,7 +29,6 @@ void menu_update()
|
|||||||
if (menu->mb)
|
if (menu->mb)
|
||||||
{
|
{
|
||||||
menubox_draw(menu->mb);
|
menubox_draw(menu->mb);
|
||||||
menubox_show(menu->mb);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,12 +54,17 @@ void menu_select()
|
|||||||
if (menu->mb)
|
if (menu->mb)
|
||||||
{
|
{
|
||||||
id = menubox_get_id(menu->mb);
|
id = menubox_get_id(menu->mb);
|
||||||
if ((c = window_build_client(menu->items[id].window)) && c)
|
if (id >= 0 && (c = window_build_client(menu->items[id].window)) && c)
|
||||||
{
|
{
|
||||||
if (c->manage)
|
if (c->manage)
|
||||||
client_activate(c);
|
client_activate(c);
|
||||||
client_free(c);
|
client_free(c);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
if (strlen(menu->mb->input->text))
|
||||||
|
{
|
||||||
|
exec_cmd(menu->mb->input->text);
|
||||||
|
}
|
||||||
menu_close();
|
menu_close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,7 +120,7 @@ void menu_create(int spot, int mon)
|
|||||||
menubox_moveresize(mb, x, y, w, h);
|
menubox_moveresize(mb, x, y, w, h);
|
||||||
|
|
||||||
menubox_key_down(mb);
|
menubox_key_down(mb);
|
||||||
menubox_draw(mb);
|
|
||||||
menubox_show(mb);
|
menubox_show(mb);
|
||||||
|
menubox_draw(mb);
|
||||||
menubox_grab(mb);
|
menubox_grab(mb);
|
||||||
}
|
}
|
||||||
111
menubox.c
111
menubox.c
@@ -26,7 +26,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||||||
|
|
||||||
#define MB_AUTOHEIGHT 1<<0
|
#define MB_AUTOHEIGHT 1<<0
|
||||||
#define MB_AUTOWIDTH 1<<1
|
#define MB_AUTOWIDTH 1<<1
|
||||||
#define MB_SELECTABLE 1<<2
|
|
||||||
#define MB_MINWIDTH 1<<3
|
#define MB_MINWIDTH 1<<3
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -37,8 +36,8 @@ typedef struct {
|
|||||||
unsigned int box_count, box_active;
|
unsigned int box_count, box_active;
|
||||||
Textbox **boxes;
|
Textbox **boxes;
|
||||||
int *ids;
|
int *ids;
|
||||||
XIM xim;
|
int *show;
|
||||||
XIC xic;
|
Textbox *input;
|
||||||
} Menubox;
|
} Menubox;
|
||||||
|
|
||||||
void menubox_moveresize(Menubox*, short, short, short, short);
|
void menubox_moveresize(Menubox*, short, short, short, short);
|
||||||
@@ -49,6 +48,7 @@ Menubox* menubox_create(Window parent, unsigned long flags, short x, short y, sh
|
|||||||
Menubox *mb = calloc(1, sizeof(Menubox));
|
Menubox *mb = calloc(1, sizeof(Menubox));
|
||||||
mb->boxes = (Textbox**) calloc(1, sizeof(Textbox));
|
mb->boxes = (Textbox**) calloc(1, sizeof(Textbox));
|
||||||
mb->ids = (int*) calloc(1, sizeof(int));
|
mb->ids = (int*) calloc(1, sizeof(int));
|
||||||
|
mb->show = (int*) calloc(1, sizeof(int));
|
||||||
|
|
||||||
mb->flags = flags;
|
mb->flags = flags;
|
||||||
mb->parent = parent;
|
mb->parent = parent;
|
||||||
@@ -68,18 +68,12 @@ Menubox* menubox_create(Window parent, unsigned long flags, short x, short y, sh
|
|||||||
mb->window = XCreateSimpleWindow(display, mb->parent, mb->x, mb->y, mb->w, mb->h, 0, None, cp);
|
mb->window = XCreateSimpleWindow(display, mb->parent, mb->x, mb->y, mb->w, mb->h, 0, None, cp);
|
||||||
|
|
||||||
// calc line height
|
// calc line height
|
||||||
Textbox *lb = textbox_create(mb->window, TB_AUTOHEIGHT, 0, 0, 0, 0, mb->font, mb->fg_blur, mb->bg_blur, "a", NULL);
|
mb->input = textbox_create(mb->window, TB_AUTOHEIGHT|TB_EDITABLE, mb->padding, mb->padding, mb->w, 0, mb->font, mb->fg_blur, mb->bg_blur, "", "> ");
|
||||||
mb->line_height = lb->h; textbox_free(lb);
|
mb->line_height = mb->input->h;
|
||||||
|
|
||||||
// auto height/width modes get handled here
|
// auto height/width modes get handled here
|
||||||
menubox_moveresize(mb, mb->x, mb->y, mb->w, mb->h);
|
menubox_moveresize(mb, mb->x, mb->y, mb->w, mb->h);
|
||||||
|
|
||||||
if (MB_SELECTABLE)
|
|
||||||
{
|
|
||||||
mb->xim = XOpenIM(display, NULL, NULL, NULL);
|
|
||||||
mb->xic = XCreateIC(mb->xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, XNClientWindow, mb->window, XNFocusWindow, mb->window, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
return mb;
|
return mb;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +82,7 @@ void menubox_moveresize(Menubox *mb, short x, short y, short w, short h)
|
|||||||
int ow = w;
|
int ow = w;
|
||||||
|
|
||||||
if (mb->flags & MB_AUTOHEIGHT)
|
if (mb->flags & MB_AUTOHEIGHT)
|
||||||
h = mb->box_count * mb->line_height + (mb->padding*2);
|
h = (mb->box_count+1) * mb->line_height + (mb->padding*2);
|
||||||
|
|
||||||
if (mb->flags & MB_AUTOWIDTH)
|
if (mb->flags & MB_AUTOWIDTH)
|
||||||
{
|
{
|
||||||
@@ -115,9 +109,14 @@ void menubox_add(Menubox *mb, int id, char *text)
|
|||||||
|
|
||||||
mb->boxes = (Textbox**) realloc(mb->boxes, sizeof(Textbox) * mb->box_count);
|
mb->boxes = (Textbox**) realloc(mb->boxes, sizeof(Textbox) * mb->box_count);
|
||||||
mb->ids = (int*) realloc(mb->ids, sizeof(int) * mb->box_count);
|
mb->ids = (int*) realloc(mb->ids, sizeof(int) * mb->box_count);
|
||||||
|
mb->show = (int*) realloc(mb->show, sizeof(int) * mb->box_count);
|
||||||
|
|
||||||
mb->boxes[slot] = textbox_create(mb->window, TB_AUTOHEIGHT|TB_AUTOWIDTH, mb->padding, mb->line_height*slot+mb->padding, mb->w-(mb->padding*2), 0, mb->font, mb->fg_blur, mb->bg_blur, text, NULL);
|
mb->boxes[slot] = textbox_create(mb->window, TB_AUTOHEIGHT|TB_AUTOWIDTH,
|
||||||
|
mb->padding, mb->line_height*(slot+1)+mb->padding, mb->w-(mb->padding*2), 0,
|
||||||
|
mb->font, mb->fg_blur, mb->bg_blur, text, NULL);
|
||||||
|
|
||||||
mb->ids[slot] = id;
|
mb->ids[slot] = id;
|
||||||
|
mb->show[slot] = 1;
|
||||||
|
|
||||||
if (mb->flags & (MB_AUTOWIDTH|MB_AUTOHEIGHT))
|
if (mb->flags & (MB_AUTOWIDTH|MB_AUTOHEIGHT))
|
||||||
menubox_moveresize(mb, mb->x, mb->y, mb->w, mb->h);
|
menubox_moveresize(mb, mb->x, mb->y, mb->w, mb->h);
|
||||||
@@ -125,7 +124,7 @@ void menubox_add(Menubox *mb, int id, char *text)
|
|||||||
|
|
||||||
int menubox_get_id(Menubox *mb)
|
int menubox_get_id(Menubox *mb)
|
||||||
{
|
{
|
||||||
return mb->ids[mb->box_active];
|
return mb->show[mb->box_active] ? mb->ids[mb->box_active]: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void menubox_grab(Menubox *mb)
|
void menubox_grab(Menubox *mb)
|
||||||
@@ -140,17 +139,29 @@ void menubox_grab(Menubox *mb)
|
|||||||
|
|
||||||
void menubox_draw(Menubox *mb)
|
void menubox_draw(Menubox *mb)
|
||||||
{
|
{
|
||||||
for (uint i = 0; i < mb->box_count; i++)
|
textbox_draw(mb->input);
|
||||||
|
int filter = strlen(mb->input->text) > 0;
|
||||||
|
|
||||||
|
for (uint i = 0, n = 0; i < mb->box_count; i++)
|
||||||
{
|
{
|
||||||
textbox_font(mb->boxes[i], mb->font, mb->box_active == i ? mb->fg_focus: mb->fg_blur, mb->box_active == i ? mb->bg_focus: mb->bg_blur);
|
if (!filter || mb->show[i])
|
||||||
textbox_draw(mb->boxes[i]);
|
{
|
||||||
|
textbox_font(mb->boxes[i], mb->font, mb->box_active == i ? mb->fg_focus: mb->fg_blur, mb->box_active == i ? mb->bg_focus: mb->bg_blur);
|
||||||
|
textbox_moveresize(mb->boxes[i], mb->padding, mb->line_height*(n+1)+mb->padding, mb->w-(mb->padding*2), 0);
|
||||||
|
textbox_show(mb->boxes[i]);
|
||||||
|
textbox_draw(mb->boxes[i]);
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
textbox_hide(mb->boxes[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void menubox_show(Menubox *mb)
|
void menubox_show(Menubox *mb)
|
||||||
{
|
{
|
||||||
for (uint i = 0; i < mb->box_count; i++)
|
textbox_show(mb->input);
|
||||||
textbox_show(mb->boxes[i]);
|
|
||||||
XMapWindow(display, mb->window);
|
XMapWindow(display, mb->window);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,17 +176,36 @@ void menubox_free(Menubox *mb)
|
|||||||
textbox_free(mb->boxes[i]);
|
textbox_free(mb->boxes[i]);
|
||||||
free(mb->boxes);
|
free(mb->boxes);
|
||||||
free(mb->ids);
|
free(mb->ids);
|
||||||
|
free(mb->show);
|
||||||
if (mb->flags & MB_SELECTABLE)
|
textbox_free(mb->input);
|
||||||
{
|
|
||||||
XDestroyIC(mb->xic);
|
|
||||||
XCloseIM(mb->xim);
|
|
||||||
}
|
|
||||||
|
|
||||||
XDestroyWindow(display, mb->window);
|
XDestroyWindow(display, mb->window);
|
||||||
free(mb);
|
free(mb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void menubox_filter(Menubox *mb)
|
||||||
|
{
|
||||||
|
int filter = strlen(mb->input->text) > 0;
|
||||||
|
char *pattern = strdup(mb->input->text);
|
||||||
|
for (char *p = pattern; *p; *p = tolower(*p), p++);
|
||||||
|
|
||||||
|
for (int i = 0; i < mb->box_count; i++)
|
||||||
|
{
|
||||||
|
char *subject = strdup(mb->boxes[i]->text);
|
||||||
|
for (char *p = subject; *p; *p = tolower(*p), p++);
|
||||||
|
mb->show[i] = (!filter || regex_match(pattern, subject));
|
||||||
|
free(subject);
|
||||||
|
}
|
||||||
|
free(pattern);
|
||||||
|
|
||||||
|
// active entry maybe filtered. step backward
|
||||||
|
while (!mb->show[mb->box_active] && mb->box_active > 0)
|
||||||
|
mb->box_active--;
|
||||||
|
|
||||||
|
// active entry maybe filtered. step forward
|
||||||
|
while (!mb->show[mb->box_active] && mb->box_active < mb->box_count-1)
|
||||||
|
mb->box_active++;
|
||||||
|
}
|
||||||
|
|
||||||
void menubox_key_up(Menubox *mb)
|
void menubox_key_up(Menubox *mb)
|
||||||
{
|
{
|
||||||
if (mb->box_active > 0) mb->box_active--;
|
if (mb->box_active > 0) mb->box_active--;
|
||||||
@@ -186,16 +216,6 @@ void menubox_key_down(Menubox *mb)
|
|||||||
if (mb->box_active < mb->box_count-1) mb->box_active++;
|
if (mb->box_active < mb->box_count-1) mb->box_active++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void menubox_key_home(Menubox *mb)
|
|
||||||
{
|
|
||||||
mb->box_active = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void menubox_key_end(Menubox *mb)
|
|
||||||
{
|
|
||||||
mb->box_active = mb->box_count-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle a keypress in edit mode
|
// handle a keypress in edit mode
|
||||||
// 0 = unhandled
|
// 0 = unhandled
|
||||||
// 1 = handled
|
// 1 = handled
|
||||||
@@ -205,17 +225,20 @@ int menubox_keypress(Menubox *mb, XEvent *ev)
|
|||||||
{
|
{
|
||||||
KeySym key; Status stat; char pad[32];
|
KeySym key; Status stat; char pad[32];
|
||||||
|
|
||||||
int len = XmbLookupString(mb->xic, &ev->xkey, pad, sizeof(pad), &key, &stat);
|
int len = XmbLookupString(mb->input->xic, &ev->xkey, pad, sizeof(pad), &key, &stat);
|
||||||
pad[len] = 0;
|
pad[len] = 0;
|
||||||
|
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
case XK_Up : menubox_key_up(mb); return 1;
|
case XK_Up : { menubox_key_up(mb); rc = 1; break; }
|
||||||
case XK_Down : menubox_key_down(mb); return 1;
|
case XK_Down : { menubox_key_down(mb); rc = 1; break; }
|
||||||
case XK_Home : menubox_key_home(mb); return 1;
|
case XK_Escape : { rc = -2; break; }
|
||||||
case XK_End : menubox_key_end(mb); return 1;
|
case XK_Return : { rc = -1; break; }
|
||||||
case XK_Escape : return -2;
|
default: rc = textbox_keypress(mb->input, ev);
|
||||||
case XK_Return : return -1;
|
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
menubox_filter(mb);
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
19
textbox.c
19
textbox.c
@@ -95,9 +95,10 @@ void textbox_font(Textbox *tb, char *font, char *fg, char *bg)
|
|||||||
void textbox_extents(Textbox *tb)
|
void textbox_extents(Textbox *tb)
|
||||||
{
|
{
|
||||||
int length = strlen(tb->text) + strlen(tb->prompt);
|
int length = strlen(tb->text) + strlen(tb->prompt);
|
||||||
char line[length + 1];
|
char *line = calloc(length + 1, sizeof(char));
|
||||||
sprintf(line, "%s%s", tb->prompt, tb->text);
|
sprintf(line, "%s%s", tb->prompt, tb->text);
|
||||||
XftTextExtents8(display, tb->font, (unsigned char*)line, length, &tb->extents);
|
XftTextExtents8(display, tb->font, (unsigned char*)line, length, &tb->extents);
|
||||||
|
free(line);
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the default text to display
|
// set the default text to display
|
||||||
@@ -162,7 +163,6 @@ void textbox_free(Textbox *tb)
|
|||||||
|
|
||||||
void textbox_draw(Textbox *tb)
|
void textbox_draw(Textbox *tb)
|
||||||
{
|
{
|
||||||
int i;
|
|
||||||
XGlyphInfo extents;
|
XGlyphInfo extents;
|
||||||
|
|
||||||
GC context = XCreateGC(display, tb->window, 0, 0);
|
GC context = XCreateGC(display, tb->window, 0, 0);
|
||||||
@@ -172,9 +172,10 @@ void textbox_draw(Textbox *tb)
|
|||||||
// clear canvas
|
// clear canvas
|
||||||
XftDrawRect(draw, &tb->color_bg, 0, 0, tb->w, tb->h);
|
XftDrawRect(draw, &tb->color_bg, 0, 0, tb->w, tb->h);
|
||||||
|
|
||||||
char *line = tb->text,
|
char *line = tb->text,
|
||||||
*text = tb->text ? tb->text: "",
|
*text = tb->text ? tb->text: "",
|
||||||
*prompt = tb->prompt ? tb->prompt: "";
|
*prompt = tb->prompt ? tb->prompt: "",
|
||||||
|
*eline = NULL;
|
||||||
|
|
||||||
int text_len = strlen(text);
|
int text_len = strlen(text);
|
||||||
int length = text_len;
|
int length = text_len;
|
||||||
@@ -190,17 +191,17 @@ void textbox_draw(Textbox *tb)
|
|||||||
length = text_len + prompt_len;
|
length = text_len + prompt_len;
|
||||||
cursor_offset = MIN(tb->cursor + prompt_len, length);
|
cursor_offset = MIN(tb->cursor + prompt_len, length);
|
||||||
|
|
||||||
char eline[length + 10]; line = eline;
|
eline = calloc(length+10, sizeof(char)); line = eline;
|
||||||
sprintf(line, "%s%s", prompt, text);
|
sprintf(line, "%s%s", prompt, text);
|
||||||
|
|
||||||
// replace spaces so XftTextExtents8 includes their width
|
// replace trailing space so XftTextExtents8 includes its width
|
||||||
for (i = 0; i < length; i++) if (isspace(line[i])) line[i] = '_';
|
if (length > 0 && isspace(line[length-1])) line[length-1] = '.';
|
||||||
|
|
||||||
// calc cursor position
|
// calc cursor position
|
||||||
XftTextExtents8(display, tb->font, (unsigned char*)line, cursor_offset, &extents);
|
XftTextExtents8(display, tb->font, (unsigned char*)line, cursor_offset, &extents);
|
||||||
cursor_x = extents.width;
|
cursor_x = extents.width;
|
||||||
|
|
||||||
// restore correct text string with spaces
|
// restore correct text string
|
||||||
sprintf(line, "%s%s", prompt, text);
|
sprintf(line, "%s%s", prompt, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,6 +226,8 @@ void textbox_draw(Textbox *tb)
|
|||||||
XFreeGC(display, context);
|
XFreeGC(display, context);
|
||||||
XftDrawDestroy(draw);
|
XftDrawDestroy(draw);
|
||||||
XFreePixmap(display, canvas);
|
XFreePixmap(display, canvas);
|
||||||
|
|
||||||
|
free(eline);
|
||||||
}
|
}
|
||||||
|
|
||||||
// cursor handling for edit mode
|
// cursor handling for edit mode
|
||||||
|
|||||||
2
xoat.c
2
xoat.c
@@ -52,10 +52,10 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|||||||
|
|
||||||
Display *display;
|
Display *display;
|
||||||
|
|
||||||
|
#include "regex.c"
|
||||||
#include "atom.c"
|
#include "atom.c"
|
||||||
#include "textbox.c"
|
#include "textbox.c"
|
||||||
#include "menubox.c"
|
#include "menubox.c"
|
||||||
#include "regex.c"
|
|
||||||
|
|
||||||
#define STACK 64
|
#define STACK 64
|
||||||
#define MONITORS 3
|
#define MONITORS 3
|
||||||
|
|||||||
Reference in New Issue
Block a user