mirror of https://github.com/0intro/wmii
[menu] Add vertical mode.
This commit is contained in:
parent
8ca9f3ca3a
commit
ed809b8471
|
@ -29,14 +29,14 @@ def message(message):
|
|||
call(*args, input=message)
|
||||
|
||||
def program_list(path):
|
||||
names = []
|
||||
names = set()
|
||||
for d in path:
|
||||
try:
|
||||
for f in os.listdir(d):
|
||||
p = '%s/%s' % (d, f)
|
||||
if f not in names and os.access(p, os.X_OK) and (
|
||||
os.path.isfile(p) or os.path.islink(p)):
|
||||
names.append(f)
|
||||
if (f not in names and os.access(p, os.X_OK) and
|
||||
os.path.isfile(p)):
|
||||
names.add(f)
|
||||
except Exception:
|
||||
pass
|
||||
return sorted(names)
|
||||
|
|
|
@ -5,12 +5,13 @@ include $(ROOT)/mk/wmii.mk
|
|||
main.c: $(ROOT)/mk/wmii.mk
|
||||
|
||||
bindings.c: keys.txt Makefile
|
||||
( echo "char binding_spec[] = "; \
|
||||
( echo "char binding_spec[] ="; \
|
||||
sed 's/.*/ "&\\n"/' keys.txt; \
|
||||
echo " ;" ) >bindings.c
|
||||
echo " ;" ) >$@
|
||||
|
||||
TARG = wimenu
|
||||
HFILES= dat.h fns.h
|
||||
TAGFILES= dat.h
|
||||
|
||||
PACKAGES += $(X11PACKAGES)
|
||||
|
||||
|
|
|
@ -69,9 +69,7 @@ caret_find(int dir, int type) {
|
|||
p = next;
|
||||
return p;
|
||||
case CHAR:
|
||||
if(p < end)
|
||||
return p+1;
|
||||
return p;
|
||||
return next_rune(p, &r);
|
||||
}
|
||||
}
|
||||
else if(dir == BACKWARD) {
|
||||
|
@ -88,9 +86,7 @@ caret_find(int dir, int type) {
|
|||
p = next;
|
||||
return p;
|
||||
case CHAR:
|
||||
if(p > end)
|
||||
return prev_rune(end, p, &r);
|
||||
return end;
|
||||
}
|
||||
}
|
||||
input.pos_end = nil;
|
||||
|
|
|
@ -11,8 +11,6 @@
|
|||
#include <stuff/x.h>
|
||||
#include <stuff/util.h>
|
||||
|
||||
#define BLOCK(x) do { x; }while(0)
|
||||
|
||||
#ifndef EXTERN
|
||||
# define EXTERN extern
|
||||
#endif
|
||||
|
@ -69,38 +67,40 @@ EXTERN struct {
|
|||
int filter_start;
|
||||
} input;
|
||||
|
||||
EXTERN struct {
|
||||
Window* win;
|
||||
Image* buf;
|
||||
char* prompt;
|
||||
int height;
|
||||
int rows;
|
||||
bool ontop;
|
||||
Rectangle itemr;
|
||||
Point arrow;
|
||||
} menu;
|
||||
|
||||
extern char binding_spec[];
|
||||
|
||||
EXTERN int numlock;
|
||||
|
||||
EXTERN long xtime;
|
||||
EXTERN Image* ibuf;
|
||||
EXTERN Font* font;
|
||||
EXTERN CTuple cnorm, csel;
|
||||
EXTERN bool ontop;
|
||||
|
||||
EXTERN Cursor cursor[1];
|
||||
EXTERN Visual* render_visual;
|
||||
|
||||
EXTERN IxpServer srv;
|
||||
|
||||
EXTERN Window* barwin;
|
||||
EXTERN struct {
|
||||
Item* all;
|
||||
Item* first;
|
||||
Item* start;
|
||||
Item* end;
|
||||
Item* sel;
|
||||
int maxwidth;
|
||||
} match;
|
||||
|
||||
EXTERN Item* items;
|
||||
EXTERN Item* matchfirst;
|
||||
EXTERN Item* matchstart;
|
||||
EXTERN Item* matchend;
|
||||
EXTERN Item* matchidx;
|
||||
Font* font;
|
||||
CTuple cnorm;
|
||||
CTuple csel;
|
||||
|
||||
EXTERN Item hist;
|
||||
EXTERN Item* histidx;
|
||||
EXTERN Item* histsel;
|
||||
|
||||
EXTERN int maxwidth;
|
||||
EXTERN int itempad;
|
||||
EXTERN int result;
|
||||
|
||||
EXTERN char* (*find)(const char*, const char*);
|
||||
EXTERN int (*compare)(const char*, const char*, size_t);
|
||||
|
||||
EXTERN char* prompt;
|
||||
EXTERN int promptw;
|
||||
|
||||
|
|
|
@ -19,25 +19,25 @@ history_search(int dir, char *string, int n) {
|
|||
Item *i;
|
||||
|
||||
if(dir == FORWARD) {
|
||||
if(histidx == &hist)
|
||||
if(histsel == &hist)
|
||||
return hist.string;
|
||||
for(i=histidx->next; i != hist.next; i=i->next)
|
||||
for(i=histsel->next; i != hist.next; i=i->next)
|
||||
if(!i->string || !compare(i->string, string, n)) {
|
||||
histidx = i;
|
||||
histsel = i;
|
||||
return i->string;
|
||||
}
|
||||
return string;
|
||||
}
|
||||
assert(dir == BACKWARD);
|
||||
|
||||
if(histidx == &hist) {
|
||||
if(histsel == &hist) {
|
||||
free(hist.string);
|
||||
hist.string = estrdup(input.string);
|
||||
}
|
||||
|
||||
for(i=histidx->prev; i != &hist; i=i->prev)
|
||||
for(i=histsel->prev; i != &hist; i=i->prev)
|
||||
if(!compare(i->string, string, n)) {
|
||||
histidx = i;
|
||||
histsel = i;
|
||||
return i->string;
|
||||
}
|
||||
return string;
|
||||
|
|
|
@ -14,6 +14,7 @@ struct Key {
|
|||
};
|
||||
|
||||
static Key* bindings;
|
||||
static int numlock;
|
||||
|
||||
/*
|
||||
* To do: Find my red black tree implementation.
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
/* Copyright ©2006-2010 Kris Maglione <maglione.k at Gmail>
|
||||
* See LICENSE file for license details.
|
||||
*/
|
||||
#define IXP_NO_P9_
|
||||
#define IXP_P9_STRUCTS
|
||||
#define EXTERN
|
||||
#include "dat.h"
|
||||
#include <X11/Xproto.h>
|
||||
|
@ -23,7 +21,9 @@ static int screen_hint;
|
|||
|
||||
static void
|
||||
usage(void) {
|
||||
fatal("usage: wimenu -i [-h <history>] [-a <address>] [-p <prompt>] [-s <screen>]\n");
|
||||
fprint(2, "usage: %s -i [-a <address>] [-h <history>] [-p <prompt>] [-r <rows>] [-s <screen>]\n", argv0);
|
||||
fprint(2, " See manual page for full usage details.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -50,13 +50,13 @@ populate_list(Biobuf *buf, bool hist) {
|
|||
bool stop;
|
||||
|
||||
stop = !hist && !isatty(buf->fid);
|
||||
ret.next_link = nil;
|
||||
i = &ret;
|
||||
while((p = Brdstr(buf, '\n', true))) {
|
||||
if(stop && p[0] == '\0')
|
||||
break;
|
||||
link(i, emallocz(sizeof *i));
|
||||
i->next_link = i->next;
|
||||
i = i->next;
|
||||
i->next_link = emallocz(sizeof *i);
|
||||
i = i->next_link;
|
||||
i->string = p;
|
||||
i->retstring = p;
|
||||
if(cmdsep && (p = strstr(p, cmdsep))) {
|
||||
|
@ -65,15 +65,12 @@ populate_list(Biobuf *buf, bool hist) {
|
|||
}
|
||||
if(!hist) {
|
||||
i->len = strlen(i->string);
|
||||
i->width = textwidth_l(font, i->string, i->len);
|
||||
if(i->width > maxwidth)
|
||||
maxwidth = i->width;
|
||||
i->width = textwidth_l(font, i->string, i->len) + itempad;
|
||||
match.maxwidth = max(i->width, match.maxwidth);
|
||||
}
|
||||
}
|
||||
|
||||
link(i, &ret);
|
||||
splice(&ret);
|
||||
return ret.next != &ret ? ret.next : nil;
|
||||
return ret.next_link;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -86,7 +83,7 @@ check_competions(IxpConn *c) {
|
|||
return;
|
||||
}
|
||||
input.filter_start = strtol(s, nil, 10);
|
||||
items = populate_list(cmplbuf, false);
|
||||
match.all = populate_list(cmplbuf, false);
|
||||
update_filter(false);
|
||||
menu_draw();
|
||||
}
|
||||
|
@ -143,8 +140,8 @@ update_filter(bool print) {
|
|||
if(input.pos < input.end)
|
||||
filter = freelater(estrndup(filter, input.pos - filter));
|
||||
|
||||
matchidx = nil;
|
||||
matchfirst = matchstart = filter_list(items, filter);
|
||||
match.sel = nil;
|
||||
match.first = match.start = filter_list(match.all, filter);
|
||||
if(print)
|
||||
update_input();
|
||||
}
|
||||
|
@ -158,8 +155,7 @@ init_screens(void) {
|
|||
int i, n;
|
||||
|
||||
rects = xinerama_screens(&n);
|
||||
if (screen_hint >= 0 && screen_hint < n)
|
||||
/* We were given a valid screen index, use that. */
|
||||
if(screen_hint >= 0 && screen_hint < n)
|
||||
i = screen_hint;
|
||||
else {
|
||||
/* Pick the screen with the pointer, for now. Later,
|
||||
|
@ -178,11 +174,11 @@ init_screens(void) {
|
|||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
Item *item;
|
||||
static char *address;
|
||||
static char *histfile;
|
||||
static char *keyfile;
|
||||
static bool nokeys;
|
||||
Item *item;
|
||||
int i;
|
||||
long ndump;
|
||||
|
||||
|
@ -220,7 +216,10 @@ main(int argc, char *argv[]) {
|
|||
ndump = strtol(EARGF(usage()), nil, 10);
|
||||
break;
|
||||
case 'p':
|
||||
prompt = EARGF(usage());
|
||||
menu.prompt = EARGF(usage());
|
||||
break;
|
||||
case 'r':
|
||||
menu.rows = strtol(EARGF(usage()), nil, 10);
|
||||
break;
|
||||
case 's':
|
||||
screen_hint = strtol(EARGF(usage()), nil, 10);
|
||||
|
@ -249,11 +248,13 @@ main(int argc, char *argv[]) {
|
|||
srv.preselect = event_preselect;
|
||||
ixp_listen(&srv, ConnectionNumber(display), nil, event_fdready, event_fdclosed);
|
||||
|
||||
ontop = !strcmp(readctl("bar on "), "top");
|
||||
menu.ontop = !strcmp(readctl("/ctl", "bar "), "on top");
|
||||
client_readconfig(&cnorm, &csel, &font);
|
||||
|
||||
itempad = (font->height & ~1) + font->pad.min.x + font->pad.max.x;
|
||||
|
||||
cmplbuf = Bfdopen(0, OREAD);
|
||||
items = populate_list(cmplbuf, false);
|
||||
match.all = populate_list(cmplbuf, false);
|
||||
if(!isatty(cmplbuf->fid))
|
||||
ixp_listen(&srv, cmplbuf->fid, inbuf, check_competions, nil);
|
||||
|
||||
|
@ -268,21 +269,18 @@ main(int argc, char *argv[]) {
|
|||
parse_keys(buffer);
|
||||
}
|
||||
|
||||
histidx = &hist;
|
||||
histsel = &hist;
|
||||
link(&hist, &hist);
|
||||
if(histfile) {
|
||||
inbuf = Bopen(histfile, OREAD);
|
||||
if(inbuf) {
|
||||
item = populate_list(inbuf, true);
|
||||
if(item) {
|
||||
if(histfile && (inbuf = Bopen(histfile, OREAD))) {
|
||||
item = filter_list(populate_list(inbuf, true), "");
|
||||
if(item->string) {
|
||||
link(item->prev, &hist);
|
||||
link(&hist, item);
|
||||
}
|
||||
Bterm(inbuf);
|
||||
}
|
||||
}
|
||||
|
||||
if(barwin == nil)
|
||||
if(menu.win == nil)
|
||||
menu_init();
|
||||
|
||||
init_screens();
|
||||
|
|
457
cmd/menu/menu.c
457
cmd/menu/menu.c
|
@ -5,269 +5,219 @@
|
|||
#include "fns.h"
|
||||
|
||||
static Handlers handlers;
|
||||
|
||||
static int ltwidth;
|
||||
|
||||
static void _menu_draw(bool);
|
||||
|
||||
enum {
|
||||
ACCEPT = CARET_LAST,
|
||||
REJECT,
|
||||
HIST,
|
||||
KILL,
|
||||
CMPL_NEXT,
|
||||
CMPL_PREV,
|
||||
CMPL_FIRST,
|
||||
CMPL_LAST,
|
||||
CMPL_NEXT_PAGE,
|
||||
CMPL_PREV_PAGE,
|
||||
};
|
||||
static int promptw;
|
||||
|
||||
void
|
||||
menu_init(void) {
|
||||
WinAttr wa;
|
||||
|
||||
wa.event_mask = ExposureMask | KeyPressMask;
|
||||
barwin = createwindow(&scr.root, Rect(-1, -1, 1, 1), scr.depth, InputOutput,
|
||||
menu.win = createwindow(&scr.root, Rect(-1, -1, 1, 1), scr.depth, InputOutput,
|
||||
&wa, CWEventMask);
|
||||
if(scr.xim)
|
||||
barwin->xic = XCreateIC(scr.xim,
|
||||
menu.win->xic = XCreateIC(scr.xim,
|
||||
XNInputStyle, XIMPreeditNothing | XIMStatusNothing,
|
||||
XNClientWindow, barwin->xid,
|
||||
XNFocusWindow, barwin->xid,
|
||||
XNClientWindow, menu.win->xid,
|
||||
XNFocusWindow, menu.win->xid,
|
||||
nil);
|
||||
|
||||
changeprop_long(barwin, Net("WM_WINDOW_TYPE"), "ATOM",
|
||||
(long[]){ TYPE("MENU") }, 1);
|
||||
changeprop_string(barwin, "_WMII_TAGS", "sel");
|
||||
changeprop_textlist(barwin, "WM_CLASS", "STRING",
|
||||
(char*[3]){ "wimenu", "wimenu", nil });
|
||||
changeprop_long(menu.win, Net("WM_WINDOW_TYPE"), "ATOM", (long[]){ TYPE("MENU") }, 1);
|
||||
changeprop_string(menu.win, "_WMII_TAGS", "sel");
|
||||
changeprop_textlist(menu.win, "WM_CLASS", "STRING", (char*[3]){ "wimenu", "wimenu" });
|
||||
|
||||
sethandler(barwin, &handlers);
|
||||
mapwin(barwin);
|
||||
sethandler(menu.win, &handlers);
|
||||
mapwin(menu.win);
|
||||
|
||||
int i = 0;
|
||||
while(!grabkeyboard(barwin)) {
|
||||
while(!grabkeyboard(menu.win)) {
|
||||
if(i++ > 1000)
|
||||
fatal("can't grab keyboard");
|
||||
usleep(1000);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
menu_unmap(long id, void *p) {
|
||||
void
|
||||
menu_show(void) {
|
||||
Rectangle r;
|
||||
|
||||
USED(id, p);
|
||||
unmapwin(barwin);
|
||||
XFlush(display);
|
||||
}
|
||||
if(menu.prompt)
|
||||
promptw = textwidth(font, menu.prompt) + itempad;
|
||||
|
||||
static void
|
||||
selectitem(Item *i) {
|
||||
if(i != matchidx) {
|
||||
caret_set(input.filter_start, input.pos - input.string);
|
||||
caret_insert(i->string, 0);
|
||||
matchidx = i;
|
||||
}
|
||||
}
|
||||
r = textextents_l(font, "<", 1, nil);
|
||||
menu.arrow = Pt(Dy(r) + itempad/2, Dx(r) + itempad/2);
|
||||
|
||||
static void
|
||||
menu_cmd(int op, int motion) {
|
||||
int n;
|
||||
menu.height = labelh(font);
|
||||
|
||||
switch(op) {
|
||||
case HIST:
|
||||
n = input.pos - input.string;
|
||||
caret_insert(history_search(motion, input.string, n), true);
|
||||
input.pos = input.string + n;
|
||||
break;
|
||||
case KILL:
|
||||
caret_delete(BACKWARD, motion);
|
||||
break;
|
||||
default:
|
||||
goto next;
|
||||
}
|
||||
update_filter(true);
|
||||
next:
|
||||
switch(op) {
|
||||
case ACCEPT:
|
||||
srv.running = false;
|
||||
if(!matchidx && matchfirst->retstring && !motion)
|
||||
if(input.filter_start == 0 && input.pos == input.end)
|
||||
menu_cmd(CMPL_FIRST, 0);
|
||||
if(!motion && matchidx && !strcmp(input.string, matchidx->string))
|
||||
lprint(1, "%s", matchidx->retstring);
|
||||
else
|
||||
lprint(1, "%s", input.string);
|
||||
break;
|
||||
case REJECT:
|
||||
srv.running = false;
|
||||
result = 1;
|
||||
break;
|
||||
case BACKWARD:
|
||||
case FORWARD:
|
||||
caret_move(op, motion);
|
||||
update_input();
|
||||
break;
|
||||
case CMPL_NEXT:
|
||||
selectitem(matchidx ? matchidx->next : matchfirst);
|
||||
break;
|
||||
case CMPL_PREV:
|
||||
selectitem((matchidx ? matchidx : matchstart)->prev);
|
||||
break;
|
||||
case CMPL_FIRST:
|
||||
matchstart = matchfirst;
|
||||
matchend = nil;
|
||||
selectitem(matchstart);
|
||||
break;
|
||||
case CMPL_LAST:
|
||||
selectitem(matchfirst->prev);
|
||||
break;
|
||||
case CMPL_NEXT_PAGE:
|
||||
if(matchend)
|
||||
selectitem(matchend->next);
|
||||
break;
|
||||
case CMPL_PREV_PAGE:
|
||||
matchend = matchstart->prev;
|
||||
matchidx = nil;
|
||||
_menu_draw(false);
|
||||
selectitem(matchstart);
|
||||
break;
|
||||
}
|
||||
freeimage(menu.buf);
|
||||
menu.buf = allocimage(Dx(scr.rect),
|
||||
!!menu.rows * 2 * menu.arrow.y + (menu.rows + 1) * menu.height,
|
||||
menu.win->depth);
|
||||
|
||||
mapwin(menu.win);
|
||||
raisewin(menu.win);
|
||||
menu_draw();
|
||||
}
|
||||
|
||||
/* I'd prefer to use ⌃ and ⌄, but few fonts support them. */
|
||||
static void
|
||||
_menu_draw(bool draw) {
|
||||
Rectangle r, rd, rp, r2, extent;
|
||||
CTuple *c;
|
||||
Item *i;
|
||||
int inputw, itemoff, end, pad, n, offset;
|
||||
drawarrow(Image *img, Rectangle r, int up, Color *col) {
|
||||
Point p[3], pt;
|
||||
|
||||
r = barwin->r;
|
||||
r = rectsetorigin(r, ZP);
|
||||
pt = Pt(menu.arrow.x - itempad/2, menu.arrow.y - itempad/2 & ~1);
|
||||
|
||||
pad = (font->height & ~1) + font->pad.min.x + font->pad.max.x;
|
||||
p[1] = Pt(r.min.x + Dx(r)/2, up ? r.min.y + itempad/4 : r.max.y - itempad/4);
|
||||
p[0] = Pt(p[1].x - pt.x/2, up ? p[1].y + pt.y : p[1].y - pt.y);
|
||||
p[2] = Pt(p[1].x + pt.x/2, p[0].y);
|
||||
drawpoly(img, p, nelem(p), CapProjecting, 1, col);
|
||||
}
|
||||
|
||||
rd = r;
|
||||
rp = ZR; // SET(rp)
|
||||
if (prompt) {
|
||||
if (!promptw)
|
||||
promptw = textwidth(font, prompt) + 2 * ltwidth + pad;
|
||||
rd.min.x += promptw;
|
||||
static Rectangle
|
||||
slice(Rectangle *rp, int x, int y) {
|
||||
Rectangle r;
|
||||
|
||||
rp = r;
|
||||
rp.max.x = promptw;
|
||||
}
|
||||
r = *rp;
|
||||
if(x)
|
||||
rp->min.x += x, r.max.x = min(rp->min.x, rp->max.x);
|
||||
if(y)
|
||||
rp->min.y += y, r.max.y = min(rp->min.y, rp->max.y);
|
||||
return r;
|
||||
}
|
||||
|
||||
inputw = min(Dx(rd) / 3, maxwidth);
|
||||
inputw = max(inputw, textwidth(font, input.string)) + pad;
|
||||
itemoff = inputw + 2 * ltwidth;
|
||||
end = Dx(rd) - ltwidth;
|
||||
static bool
|
||||
nextrect(Item *i, Rectangle *rp, Rectangle *src) {
|
||||
Rectangle r;
|
||||
|
||||
fill(ibuf, r, &cnorm.bg);
|
||||
|
||||
if(matchend && matchidx == matchend->next)
|
||||
matchstart = matchidx;
|
||||
else if(matchidx == matchstart->prev)
|
||||
matchend = matchidx;
|
||||
if (matchend == nil)
|
||||
matchend = matchstart;
|
||||
|
||||
if(matchend == matchstart->prev && matchstart != matchidx) {
|
||||
n = itemoff;
|
||||
matchstart = matchend;
|
||||
for(i=matchend; ; i=i->prev) {
|
||||
n += i->width + pad;
|
||||
if(n > end)
|
||||
break;
|
||||
matchstart = i;
|
||||
if(i == matchfirst)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!draw)
|
||||
return;
|
||||
|
||||
r2 = rd;
|
||||
for(i=matchstart; i->string; i=i->next) {
|
||||
r2.min.x = promptw + itemoff;
|
||||
itemoff = itemoff + i->width + pad;
|
||||
r2.max.x = promptw + min(itemoff, end);
|
||||
if(i != matchstart && itemoff > end)
|
||||
break;
|
||||
|
||||
c = (i == matchidx) ? &csel : &cnorm;
|
||||
fill(ibuf, r2, &c->bg);
|
||||
drawstring(ibuf, font, r2, Center, i->string, &c->fg);
|
||||
matchend = i;
|
||||
if(i->next == matchfirst)
|
||||
break;
|
||||
}
|
||||
|
||||
r2 = rd;
|
||||
r2.min.x = promptw + inputw;
|
||||
if(matchstart != matchfirst)
|
||||
drawstring(ibuf, font, r2, West, "<", &cnorm.fg);
|
||||
if(matchend->next != matchfirst)
|
||||
drawstring(ibuf, font, r2, East, ">", &cnorm.fg);
|
||||
|
||||
r2 = rd;
|
||||
r2.max.x = promptw + inputw;
|
||||
drawstring(ibuf, font, r2, West, input.string, &cnorm.fg);
|
||||
|
||||
extent = textextents_l(font, input.string, input.pos - input.string, &offset);
|
||||
r2.min.x = promptw + offset + font->pad.min.x - extent.min.x + pad/2 - 1;
|
||||
r2.max.x = r2.min.x + 2;
|
||||
r2.min.y++;
|
||||
r2.max.y--;
|
||||
border(ibuf, r2, 1, &cnorm.border);
|
||||
|
||||
if (prompt)
|
||||
drawstring(ibuf, font, rp, West, prompt, &cnorm.fg);
|
||||
|
||||
border(ibuf, rd, 1, &cnorm.border);
|
||||
copyimage(barwin, r, ibuf, ZP);
|
||||
if(menu.rows)
|
||||
r = slice(src, 0, menu.height);
|
||||
else
|
||||
r = slice(src, i->width, 0);
|
||||
return (Dx(*src) >= 0 && Dy(*src) >= 0) && (*rp = r, 1);
|
||||
}
|
||||
|
||||
void
|
||||
menu_draw(void) {
|
||||
_menu_draw(true);
|
||||
Rectangle barr, extent, itemr, inputr, r, r2;
|
||||
Item *item;
|
||||
int inputw, offset;
|
||||
|
||||
barr = r2 = Rect(0, 0, Dx(menu.win->r), menu.height);
|
||||
|
||||
inputw = max(match.maxwidth + textwidth_l(font, input.string, min(input.filter_start, strlen(input.string))),
|
||||
max(itempad + textwidth(font, input.string),
|
||||
Dx(barr) / 3));
|
||||
|
||||
/* Calculate items box, w/ and w/o arrows */
|
||||
if(menu.rows) {
|
||||
menu.itemr = barr;
|
||||
menu.itemr.max.y += Dy(barr) * (menu.rows - 1);
|
||||
if(menu.ontop)
|
||||
menu.itemr = rectaddpt(menu.itemr, Pt(0, Dy(barr)));
|
||||
itemr = menu.itemr;
|
||||
if(match.start != match.first)
|
||||
menu.itemr = rectaddpt(menu.itemr, Pt(0, menu.arrow.y));
|
||||
}
|
||||
else {
|
||||
itemr = r2;
|
||||
slice(&itemr, inputw + promptw, 0);
|
||||
menu.itemr = Rect(itemr.min.x + menu.arrow.x, itemr.min.y,
|
||||
itemr.max.x - menu.arrow.x, itemr.max.y);
|
||||
}
|
||||
|
||||
fill(menu.buf, menu.buf->r, &cnorm.bg);
|
||||
|
||||
/* Draw items */
|
||||
item = match.start, r2 = menu.itemr;
|
||||
nextrect(item, &r, &r2);
|
||||
do {
|
||||
match.end = item;
|
||||
if(item->string)
|
||||
fillstring(menu.buf, font, r, West, item->string,
|
||||
(item == match.sel ? &csel : &cnorm), 0);
|
||||
item = item->next;
|
||||
} while(item != match.first && nextrect(item, &r, &r2));
|
||||
|
||||
/* Adjust dimensions for arrows/number of items */
|
||||
if(menu.rows)
|
||||
itemr.max.y = r.max.y + (match.end->next != match.first ? menu.arrow.y : 0);
|
||||
else
|
||||
itemr.max.x = r.max.x + menu.arrow.x;
|
||||
if(menu.rows && !menu.ontop)
|
||||
barr = rectaddpt(barr, Pt(0, itemr.max.y));
|
||||
|
||||
/* Draw indicators */
|
||||
if(!menu.rows && match.start != match.first)
|
||||
drawstring(menu.buf, font, itemr, West, "<", &cnorm.fg);
|
||||
if(!menu.rows && match.end->next != match.first)
|
||||
drawstring(menu.buf, font, itemr, East, ">", &cnorm.fg);
|
||||
|
||||
if(menu.rows && match.start != match.first)
|
||||
drawarrow(menu.buf, itemr, 1, &cnorm.fg);
|
||||
if(menu.rows && match.end->next != match.first)
|
||||
drawarrow(menu.buf, itemr, 0, &cnorm.fg);
|
||||
|
||||
/* Draw prompt */
|
||||
r2 = barr;
|
||||
if(menu.prompt)
|
||||
drawstring(menu.buf, font, slice(&r2, promptw, 0),
|
||||
West, menu.prompt, &cnorm.fg);
|
||||
|
||||
/* Border input/horizontal items */
|
||||
border(menu.buf, r2, 1, &cnorm.border);
|
||||
|
||||
/* Draw input */
|
||||
inputr = slice(&r2, inputw, 0);
|
||||
drawstring(menu.buf, font, inputr, West, input.string, &cnorm.fg);
|
||||
|
||||
/* Draw cursor */
|
||||
extent = textextents_l(font, input.string, input.pos - input.string, &offset);
|
||||
r2 = insetrect(inputr, 2);
|
||||
r2.min.x = inputr.min.x - extent.min.x + offset + font->pad.min.x + itempad/2 - 1;
|
||||
r2.max.x = r2.min.x + 1;
|
||||
fill(menu.buf, r2, &cnorm.border);
|
||||
|
||||
/* Reshape window */
|
||||
r = scr.rect;
|
||||
if(menu.ontop)
|
||||
r.max.y = r.min.y + itemr.max.y;
|
||||
else
|
||||
r.min.y = r.max.y - barr.max.y;
|
||||
reshapewin(menu.win, r);
|
||||
|
||||
/* Border window */
|
||||
r = rectsubpt(r, r.min);
|
||||
border(menu.buf, r, 1, &cnorm.border);
|
||||
copyimage(menu.win, r, menu.buf, ZP);
|
||||
}
|
||||
|
||||
void
|
||||
menu_show(void) {
|
||||
Rectangle r;
|
||||
int height, pad;
|
||||
static Item*
|
||||
pagestart(Item *i) {
|
||||
Rectangle r, r2;
|
||||
|
||||
USED(menu_unmap);
|
||||
r = menu.itemr;
|
||||
nextrect(i, &r2, &r);
|
||||
while(i->prev != match.first->prev && nextrect(i->prev, &r2, &r))
|
||||
i = i->prev;
|
||||
return i;
|
||||
}
|
||||
|
||||
ltwidth = textwidth(font, "<");
|
||||
|
||||
pad = (font->height & ~1)/2;
|
||||
height = labelh(font);
|
||||
|
||||
r = scr.rect;
|
||||
if(ontop)
|
||||
r.max.y = r.min.y + height;
|
||||
else
|
||||
r.min.y = r.max.y - height;
|
||||
reshapewin(barwin, r);
|
||||
|
||||
freeimage(ibuf);
|
||||
ibuf = allocimage(Dx(r), Dy(r), scr.depth);
|
||||
|
||||
mapwin(barwin);
|
||||
raisewin(barwin);
|
||||
menu_draw();
|
||||
static void
|
||||
selectitem(Item *i) {
|
||||
if(i != match.sel) {
|
||||
caret_set(input.filter_start, input.pos - input.string);
|
||||
caret_insert(i->string, 0);
|
||||
match.sel = i;
|
||||
if(i == match.start->prev)
|
||||
match.start = pagestart(i);
|
||||
if(i == match.end->next)
|
||||
match.start = i;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
kdown_event(Window *w, void *aux, XKeyEvent *e) {
|
||||
char **action, **p;
|
||||
char *key;
|
||||
char buf[32];
|
||||
char buf[128];
|
||||
int num, status;
|
||||
KeySym ksym;
|
||||
|
||||
|
@ -276,8 +226,7 @@ kdown_event(Window *w, void *aux, XKeyEvent *e) {
|
|||
|
||||
status = XLookupBoth;
|
||||
if(w->xic)
|
||||
num = Xutf8LookupString(w->xic, e, buf, sizeof buf - 1, &ksym,
|
||||
&status);
|
||||
num = Xutf8LookupString(w->xic, e, buf, sizeof buf - 1, &ksym, &status);
|
||||
else
|
||||
num = XLookupString(e, buf, sizeof buf - 1, &ksym, nil);
|
||||
|
||||
|
@ -319,37 +268,65 @@ kdown_event(Window *w, void *aux, XKeyEvent *e) {
|
|||
have(LWORD) ? WORD :
|
||||
have(LLINE) ? LINE :
|
||||
-1);
|
||||
|
||||
switch(getsym(action[0])) {
|
||||
case LACCEPT:
|
||||
menu_cmd(ACCEPT, have(LLITERAL));
|
||||
break;
|
||||
case LBACKWARD:
|
||||
menu_cmd(BACKWARD, amount);
|
||||
break;
|
||||
case LCOMPLETE:
|
||||
amount = (
|
||||
have(LNEXT) ? CMPL_NEXT :
|
||||
have(LPREV) ? CMPL_PREV :
|
||||
have(LNEXTPAGE) ? CMPL_NEXT_PAGE :
|
||||
have(LPREVPAGE) ? CMPL_PREV_PAGE :
|
||||
have(LFIRST) ? CMPL_FIRST :
|
||||
have(LLAST) ? CMPL_LAST :
|
||||
CMPL_NEXT);
|
||||
menu_cmd(amount, 0);
|
||||
break;
|
||||
case LFORWARD:
|
||||
menu_cmd(FORWARD, amount);
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
case LHISTORY:
|
||||
menu_cmd(HIST, have(LBACKWARD) ? BACKWARD : FORWARD);
|
||||
num = input.pos - input.string;
|
||||
amount = have(LBACKWARD) ? BACKWARD : FORWARD;
|
||||
caret_insert(history_search(amount, input.string, num), true);
|
||||
input.pos = input.string + num;
|
||||
update_filter(true);
|
||||
break;
|
||||
case LKILL:
|
||||
menu_cmd(KILL, amount);
|
||||
caret_delete(BACKWARD, amount);
|
||||
update_filter(true);
|
||||
break;
|
||||
|
||||
case LACCEPT:
|
||||
srv.running = false;
|
||||
if(!have(LLITERAL) && !match.sel && match.start->retstring)
|
||||
if(input.filter_start == 0 && input.pos == input.end)
|
||||
selectitem(match.start);
|
||||
|
||||
if(!have(LLITERAL) && match.sel && !strcmp(input.string, match.sel->string))
|
||||
lprint(1, "%s", match.sel->retstring);
|
||||
else
|
||||
lprint(1, "%s", input.string);
|
||||
break;
|
||||
case LBACKWARD:
|
||||
caret_move(BACKWARD, amount);
|
||||
update_input();
|
||||
break;
|
||||
case LCOMPLETE:
|
||||
if(have(LNEXT))
|
||||
selectitem(match.sel ? match.sel->next : match.first);
|
||||
else if(have(LPREV))
|
||||
selectitem((match.sel ? match.sel : match.start)->prev);
|
||||
else if(have(LFIRST)) {
|
||||
match.start = match.first;
|
||||
selectitem(match.start);
|
||||
}
|
||||
else if(have(LLAST))
|
||||
selectitem(match.first->prev);
|
||||
else if(have(LNEXTPAGE))
|
||||
selectitem(match.end->next);
|
||||
else if(have(LPREVPAGE)) {
|
||||
match.start = pagestart(match.start->prev);
|
||||
selectitem(match.start);
|
||||
}
|
||||
break;
|
||||
case LFORWARD:
|
||||
caret_move(FORWARD, amount);
|
||||
update_input();
|
||||
break;
|
||||
case LREJECT:
|
||||
menu_cmd(REJECT, 0);
|
||||
srv.running = false;
|
||||
result = 1;
|
||||
break;
|
||||
}
|
||||
menu_draw();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -191,7 +191,7 @@ main(int argc, char *argv[]) {
|
|||
client_init(nil);
|
||||
|
||||
if(tray.edge == 0)
|
||||
tray.edge = West | (!strcmp(readctl("bar on "), "top") ? North : South);
|
||||
tray.edge = West | (!strcmp(readctl("/ctl", "bar on "), "top") ? North : South);
|
||||
|
||||
client_readconfig(&tray.normcolors, &tray.selcolors, &tray.font);
|
||||
|
||||
|
|
|
@ -195,9 +195,7 @@ bar_draw(WMScreen *s) {
|
|||
align = Center;
|
||||
if(b == s->bar[BRight])
|
||||
align = East;
|
||||
fill(ibuf, b->r, &b->colors.bg);
|
||||
drawstring(ibuf, def.font, b->r, align, b->text, &b->colors.fg);
|
||||
border(ibuf, b->r, 1, &b->colors.border);
|
||||
fillstring(ibuf, def.font, b->r, align, b->text, &b->colors, 1);
|
||||
}
|
||||
|
||||
if(s->barwin_rgba != (s->barwin->depth == 32))
|
||||
|
|
|
@ -220,7 +220,8 @@ apply_rules(Client *c) {
|
|||
bool ret, more;
|
||||
|
||||
ret = true;
|
||||
for(r=def.rules.rule; r; r=r->next)
|
||||
more = true;
|
||||
for(r=def.rules.rule; r && more; r=r->next)
|
||||
if(regexec(r->regex, c->props, nil, 0)) {
|
||||
more = false;
|
||||
for(rv=r->values; rv; rv=rv->next) {
|
||||
|
@ -234,15 +235,15 @@ apply_rules(Client *c) {
|
|||
}else {
|
||||
bufclear();
|
||||
bufprint("%s %s", rv->key, rv->value);
|
||||
m = ixp_message(buffer, sizeof buffer, MsgPack);
|
||||
if(!waserror()) {
|
||||
m = ixp_message(buffer, _buf_end - buffer, MsgPack);
|
||||
if(waserror())
|
||||
warning("processing rule %q=%q: %r", rv->key, rv->value);
|
||||
else {
|
||||
message_client(c, &m);
|
||||
poperror();
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!more)
|
||||
return ret;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -1093,6 +1094,11 @@ client_extratags(Client *c) {
|
|||
toks[i] = nil;
|
||||
tags = comm(CLeft, toks, c->retags);
|
||||
|
||||
if(i == 1 && !c->tagre.regex && !c->tagvre.regex) {
|
||||
free(tags);
|
||||
return nil;
|
||||
}
|
||||
|
||||
fmtstrinit(&fmt);
|
||||
if(i > 1)
|
||||
join(tags, "+", &fmt);
|
||||
|
@ -1131,17 +1137,16 @@ client_applytags(Client *c, const char *tags) {
|
|||
/* Check for regex. */
|
||||
if(cur[0] == '/') {
|
||||
cur++;
|
||||
*strchr(cur, '/') = '\0';
|
||||
*strrchr(cur, '/') = '\0';
|
||||
if(add == '+')
|
||||
reinit(&c->tagre, cur);
|
||||
else if(add == '-')
|
||||
reinit(&c->tagvre, cur);
|
||||
}
|
||||
|
||||
trim(cur, " \t\r\n");
|
||||
if(!strcmp(cur, "~"))
|
||||
else if(!strcmp(cur, "~"))
|
||||
c->floating = add ? On : Never;
|
||||
else {
|
||||
trim(cur, " \t\r\n");
|
||||
if(!strcmp(cur, "sel"))
|
||||
cur = selview->name;
|
||||
else if(Mbsearch(cur, badtags, bsstrcmp))
|
||||
|
|
|
@ -313,8 +313,7 @@ EXTERN struct Defs {
|
|||
uint keyssz;
|
||||
Ruleset colrules;
|
||||
Ruleset rules;
|
||||
char grabmod[5];
|
||||
ulong mod;
|
||||
long mod;
|
||||
uint border;
|
||||
uint snap;
|
||||
int colmode;
|
||||
|
|
|
@ -398,6 +398,7 @@ pushlabel(Image *img, Rectangle *rp, char *s, CTuple *col) {
|
|||
w = min(w, Dx(*rp) - 30); /* Magic number. */
|
||||
if(w > 0) {
|
||||
r = *rp;
|
||||
r.min.x = r.max.x - w;
|
||||
rp->max.x -= w;
|
||||
if(0)
|
||||
drawline(img, Pt(rp->max.x, r.min.y+2),
|
||||
|
@ -406,6 +407,7 @@ pushlabel(Image *img, Rectangle *rp, char *s, CTuple *col) {
|
|||
drawstring(img, def.font, r, East,
|
||||
s, &col->fg);
|
||||
}
|
||||
free(s);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -415,7 +417,6 @@ frame_draw(Frame *f) {
|
|||
CTuple *col;
|
||||
Image *img;
|
||||
char *s;
|
||||
uint w;
|
||||
int n, m;
|
||||
|
||||
if(f == nil || f->view != selview || f->area == nil)
|
||||
|
@ -443,6 +444,9 @@ frame_draw(Frame *f) {
|
|||
f->titlebar = insetrect(r, 3);
|
||||
f->titlebar.max.y += 3;
|
||||
|
||||
f->grabbox = insetrect(r, 2);
|
||||
f->grabbox.max.x = f->grabbox.min.x + Dy(f->grabbox);
|
||||
|
||||
/* Odd focus. Unselected, with keyboard focus. */
|
||||
/* Draw a border just inside the titlebar. */
|
||||
if(c != selclient() && c == disp.focus) {
|
||||
|
@ -450,15 +454,9 @@ frame_draw(Frame *f) {
|
|||
border(img, insetrect(r, 2), 1, &def.focuscolor.border);
|
||||
}
|
||||
|
||||
/* grabbox */
|
||||
r.min = Pt(2, 2);
|
||||
r.max.y -= 2;
|
||||
r.max.x = r.min.x + Dy(r);
|
||||
f->grabbox = r;
|
||||
|
||||
if(c->urgent)
|
||||
fill(img, r, &col->fg);
|
||||
border(img, r, 1, &col->border);
|
||||
fill(img, f->grabbox, &col->fg);
|
||||
border(img, f->grabbox, 1, &col->border);
|
||||
|
||||
/* Odd focus. Selected, without keyboard focus. */
|
||||
/* Draw a border around the grabbox. */
|
||||
|
@ -466,38 +464,34 @@ frame_draw(Frame *f) {
|
|||
border(img, insetrect(r, -1), 1, &def.normcolor.bg);
|
||||
|
||||
/* Draw a border on borderless+titleless selected apps. */
|
||||
if(f->area->floating && c->borderless && c->titleless && !c->fullscreen && c == selclient())
|
||||
if(c->borderless && c->titleless && f->area->floating && !c->fullscreen && c == selclient())
|
||||
setborder(c->framewin, def.border, &def.focuscolor.border);
|
||||
else
|
||||
setborder(c->framewin, 0, &def.focuscolor.border);
|
||||
|
||||
/* Label */
|
||||
r.min.x = r.max.x;
|
||||
r.max.x = fr.max.x;
|
||||
r.min.y = 0;
|
||||
r.max.y = labelh(def.font);
|
||||
r = Rect(f->grabbox.max.x, 0, fr.max.x, labelh(def.font));
|
||||
|
||||
/* Draw count on frames in 'max' columns. */
|
||||
if(f->area->max && !resizing) {
|
||||
/* XXX */
|
||||
n = stack_count(f, &m);
|
||||
s = smprint("%d/%d", m, n);
|
||||
pushlabel(img, &r, s, col);
|
||||
free(s);
|
||||
pushlabel(img, &r, smprint("%d/%d", m, n), col);
|
||||
}
|
||||
|
||||
/* Label clients with extra tags. */
|
||||
if((s = client_extratags(c))) {
|
||||
if((s = client_extratags(c)))
|
||||
pushlabel(img, &r, s, col);
|
||||
free(s);
|
||||
}else if(f->area->floating) /* Make sure floating clients have room for their indicators. */
|
||||
r.max.x -= Dx(f->grabbox);
|
||||
|
||||
if(f->area->floating) /* Make sure floating clients have room for their indicators. */
|
||||
r.max.x -= f->grabbox.max.x;
|
||||
|
||||
if(!ewmh_responsive_p(c))
|
||||
r.min.x += drawstring(img, def.font, r, West, "(wedged) ", &col->fg);
|
||||
w = drawstring(img, def.font, r, West, c->name, &col->fg);
|
||||
r.min.x += drawstring(img, def.font, r, West, c->name, &col->fg);
|
||||
|
||||
/* Draw inner border on floating clients. */
|
||||
if(f->area->floating) {
|
||||
r.min.x = r.min.x + w + 10;
|
||||
r.min.x += 10;
|
||||
r.max.x += Dx(f->grabbox);
|
||||
r.min.y = f->grabbox.min.y;
|
||||
r.max.y = f->grabbox.max.y;
|
||||
|
|
|
@ -372,8 +372,7 @@ main(int argc, char *argv[]) {
|
|||
initdisplay();
|
||||
|
||||
traperrors(true);
|
||||
selectinput(&scr.root, EnterWindowMask
|
||||
| SubstructureRedirectMask);
|
||||
selectinput(&scr.root, SubstructureRedirectMask);
|
||||
if(traperrors(false))
|
||||
fatal("another window manager is already running");
|
||||
|
||||
|
@ -388,7 +387,7 @@ main(int argc, char *argv[]) {
|
|||
|
||||
sock = ixp_announce(address);
|
||||
if(sock < 0)
|
||||
fatal("Can't create socket '%s': %r", address);
|
||||
fatal("Can't create socket %q: %r", address);
|
||||
closeexec(ConnectionNumber(display));
|
||||
closeexec(sock);
|
||||
|
||||
|
@ -413,7 +412,6 @@ main(int argc, char *argv[]) {
|
|||
def.incmode = ISqueeze;
|
||||
|
||||
def.mod = Mod1Mask;
|
||||
strcpy(def.grabmod, "Mod1");
|
||||
|
||||
loadcolor(&def.focuscolor, FOCUSCOLORS, nil);
|
||||
loadcolor(&def.normcolor, NORMCOLORS, nil);
|
||||
|
|
|
@ -656,7 +656,6 @@ message_root(void *p, IxpMsg *m) {
|
|||
if(!parsekey(s, &i, nil) || i == 0)
|
||||
return Ebadvalue;
|
||||
|
||||
utflcpy(def.grabmod, s, sizeof def.grabmod);
|
||||
def.mod = i;
|
||||
break;
|
||||
case LINCMODE:
|
||||
|
@ -700,7 +699,7 @@ readctl_root(void) {
|
|||
bufprint("font %s\n", def.font->name);
|
||||
bufprint("fontpad %d %d %d %d\n", def.font->pad.min.x, def.font->pad.max.x,
|
||||
def.font->pad.max.y, def.font->pad.min.y);
|
||||
bufprint("grabmod %s\n", def.grabmod);
|
||||
bufprint("grabmod %s\n", (Mask){&def.mod, modkey_names});
|
||||
bufprint("incmode %s\n", incmodetab[def.incmode]);
|
||||
bufprint("normcolors %s\n", def.normcolor.colstr);
|
||||
bufprint("view %s\n", selview->name);
|
||||
|
|
|
@ -426,7 +426,7 @@ xnamespace(int argc, char *argv[]) {
|
|||
path = ixp_namespace();
|
||||
if(path == nil)
|
||||
fatal("can't find namespace: %r\n");
|
||||
Blprint(outbuf, "%s\n", path);
|
||||
Blprint(outbuf, "%s", path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -58,15 +58,8 @@ static Font* font;
|
|||
|
||||
static int wborder;
|
||||
|
||||
char buffer[8092];
|
||||
char* _buffer;
|
||||
|
||||
/* for XSetWMProperties to use */
|
||||
int g_argc;
|
||||
char **g_argv;
|
||||
|
||||
char *initial = "";
|
||||
int cur;
|
||||
static char* initial = "";
|
||||
static int cur;
|
||||
|
||||
static char** labels; /* list of labels and commands */
|
||||
static char** commands;
|
||||
|
@ -78,13 +71,7 @@ void create_window(void);
|
|||
void size_window(int, int);
|
||||
void redraw(int, int);
|
||||
void warpmouse(int, int);
|
||||
void memory(void);
|
||||
int args(void);
|
||||
|
||||
Cursor cursor[1];
|
||||
Visual* render_visual;
|
||||
|
||||
void init_screens(void);
|
||||
void
|
||||
init_screens(void) {
|
||||
Rectangle *rects;
|
||||
|
@ -111,9 +98,6 @@ main(int argc, char **argv)
|
|||
char *cp;
|
||||
int i;
|
||||
|
||||
g_argc = argc;
|
||||
g_argv = argv;
|
||||
|
||||
ARGBEGIN{
|
||||
case 'v':
|
||||
lprint(1, "%s\n", version);
|
||||
|
@ -137,29 +121,24 @@ main(int argc, char **argv)
|
|||
create_window();
|
||||
|
||||
numitems = argc;
|
||||
|
||||
labels = emalloc(numitems * sizeof *labels);
|
||||
commands = emalloc(numitems * sizeof *labels);
|
||||
|
||||
for(i = 0; i < numitems; i++) {
|
||||
labels[i] = argv[i];
|
||||
commands[i] = argv[i];
|
||||
if((cp = strchr(labels[i], ':')) != nil) {
|
||||
*cp++ = '\0';
|
||||
commands[i] = cp;
|
||||
} else
|
||||
commands[i] = labels[i];
|
||||
}
|
||||
if(strcmp(labels[i], initial) == 0)
|
||||
cur = i;
|
||||
}
|
||||
|
||||
client_init(address);
|
||||
|
||||
wborder = strtol(readctl("border "), nil, 10);
|
||||
loadcolor(&cnorm, readctl("normcolors "), nil);
|
||||
loadcolor(&csel, readctl("focuscolors "), nil);
|
||||
font = loadfont(readctl("font "));
|
||||
if(!font)
|
||||
fatal("Can't load font");
|
||||
wborder = strtol(readctl("/ctl", "border "), nil, 10);
|
||||
client_readconfig(&cnorm, &csel, &font);
|
||||
|
||||
run_menu();
|
||||
|
||||
|
@ -167,26 +146,20 @@ main(int argc, char **argv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* usage --- print a usage message and die */
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
lprint(2, "usage: %s -v\n", argv0);
|
||||
lprint(2, " %s [-a <address>] [-i <arg>] menitem[:command] ...\n", argv0);
|
||||
lprint(2, "usage: %s [-a <address>] [-i <arg>] <menitem>[:<command>] ...\n", argv0);
|
||||
lprint(2, " %s -v\n", argv0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* run_menu --- put up the window, execute selected commands */
|
||||
|
||||
enum {
|
||||
MouseMask =
|
||||
ButtonPressMask
|
||||
MouseMask = ButtonPressMask
|
||||
| ButtonReleaseMask
|
||||
| ButtonMotionMask
|
||||
| PointerMotionMask,
|
||||
MenuMask =
|
||||
MouseMask
|
||||
MenuMask = MouseMask
|
||||
| StructureNotifyMask
|
||||
| ExposureMask
|
||||
};
|
||||
|
@ -197,8 +170,8 @@ run_menu(void)
|
|||
XEvent ev;
|
||||
int i, old, wide, high;
|
||||
|
||||
wide = 0;
|
||||
high = labelh(font);
|
||||
wide = 0;
|
||||
for(i = 0; i < numitems; i++)
|
||||
wide = max(wide, textwidth(font, labels[i]));
|
||||
wide += font->height & ~1;
|
||||
|
@ -231,12 +204,10 @@ run_menu(void)
|
|||
break;
|
||||
redraw(high, wide);
|
||||
break;
|
||||
case MapNotify:
|
||||
redraw(high, wide);
|
||||
break;
|
||||
case Expose:
|
||||
redraw(high, wide);
|
||||
break;
|
||||
case MapNotify:
|
||||
case ConfigureNotify:
|
||||
case MappingNotify:
|
||||
break;
|
||||
|
@ -244,13 +215,10 @@ run_menu(void)
|
|||
}
|
||||
}
|
||||
|
||||
/* set_wm_hints --- set all the window manager hints */
|
||||
|
||||
void
|
||||
create_window(void)
|
||||
{
|
||||
WinAttr wa = { 0 };
|
||||
XEvent e;
|
||||
|
||||
wa.override_redirect = true;
|
||||
menuwin = createwindow(&scr.root, Rect(-1, -1, 0, 0),
|
||||
|
@ -258,10 +226,8 @@ create_window(void)
|
|||
&wa, CWOverrideRedirect);
|
||||
selectinput(menuwin, MenuMask);
|
||||
mapwin(menuwin);
|
||||
XMaskEvent(display, StructureNotifyMask, &e);
|
||||
if(!grabpointer(menuwin, nil, 0, MouseMask))
|
||||
fatal("Failed to grab the mouse\n");
|
||||
XSetCommand(display, menuwin->xid, g_argv, g_argc);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -284,34 +250,22 @@ size_window(int wide, int high)
|
|||
p.y = min(p.y, scr.rect.max.y - h);
|
||||
|
||||
reshapewin(menuwin, rectaddpt(r, p));
|
||||
|
||||
//XSetWindowBackground(display, menuwin->xid, cnorm.bg);
|
||||
setborder(menuwin, 1, &cnorm.border);
|
||||
}
|
||||
|
||||
/* redraw --- actually redraw the menu */
|
||||
|
||||
void
|
||||
redraw(int high, int wide)
|
||||
{
|
||||
Rectangle r;
|
||||
CTuple *c;
|
||||
int i;
|
||||
|
||||
r = Rect(0, 0, wide, high);
|
||||
for(i = 0; i < numitems; i++) {
|
||||
if(cur == i)
|
||||
c = &csel;
|
||||
else
|
||||
c = &cnorm;
|
||||
r = rectsetorigin(r, Pt(0, i * high));
|
||||
fill(menuwin, r, &c->bg);
|
||||
drawstring(menuwin, font, r, Center, labels[i], &c->fg);
|
||||
fillstring(menuwin, font, r, Center, labels[i], (cur == i ? &csel : &cnorm), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* warpmouse --- bring the mouse to the menu */
|
||||
|
||||
void
|
||||
warpmouse(int wide, int high)
|
||||
{
|
||||
|
|
45
img/mkfile
45
img/mkfile
|
@ -2,37 +2,22 @@ MKSHELL=rc
|
|||
path=$PLAN9/bin $path
|
||||
|
||||
eps = wmii.eps
|
||||
calc = rc -c 'hoc -e $"*'
|
||||
calc = rc -c 'echo 4k $* p | dc}
|
||||
|
||||
epsbox = `{sed -n '/^%%BoundingBox:/{s/.*://p; q;}' $eps}
|
||||
iconwidth = 154
|
||||
iconscale = `{*=$epsbox; $calc $iconwidth / '('$3 - $1')'}
|
||||
iconheight = `{*=$epsbox; $calc '('$4 - $2') *' $iconscale}
|
||||
|
||||
%.png: %.eps
|
||||
* = `{hoc -e'-('$epsbox')'}
|
||||
x = $1
|
||||
y = $2
|
||||
gs -q -dBATCH -dNOPAUSE -s'DEVICE=pngalpha' -s'OutputFile='$target -g$iconwidth'x'$iconheight - <<!
|
||||
$iconscale $iconscale scale
|
||||
$x $y translate
|
||||
($eps) run
|
||||
showpage
|
||||
quit
|
||||
!
|
||||
optipng -fix $target
|
||||
iconwidth = 16
|
||||
imagewidth = 154
|
||||
|
||||
%.pdf: %.eps
|
||||
sh epstopdf $stem.eps
|
||||
|
||||
%-small.png: %.eps
|
||||
iconwidth = 16
|
||||
iconscale = `{*=$epsbox; hoc -e $iconwidth/'('$3-' '$1')'}
|
||||
iconheight = `{*=$epsbox; hoc -e '('$4-' '$2')*'$iconscale}
|
||||
epsbox = `{sed -n '/^%%BoundingBox:/{s/.*://p; q;}' $stem.eps}
|
||||
iconscale = `{*=$epsbox; $calc $iconwidth $3 $1 -/}
|
||||
iconheight = `{*=$epsbox; $calc $4 $2 - $iconscale '*'}
|
||||
* = `{hoc -e'-('$epsbox')'}
|
||||
x = $1
|
||||
y = $2
|
||||
gs -q -dBATCH -dNOPAUSE -s'DEVICE=pngalpha' -s'OutputFile='$target -g$iconwidth'x'$iconheight - <<!
|
||||
gs -q -dBATCH -dNOPAUSE -s'DEVICE=pngalpha' -s'OutputFile='$target -g$iconwidth^x^$iconheight - <<!
|
||||
$iconscale $iconscale scale
|
||||
$x $y translate
|
||||
($eps) run
|
||||
|
@ -41,3 +26,19 @@ iconheight = `{*=$epsbox; $calc '('$4 - $2') *' $iconscale}
|
|||
!
|
||||
optipng -fix $target
|
||||
|
||||
%.png: %.eps
|
||||
epsbox = `{sed -n '/^%%BoundingBox:/{s/.*://p; q;}' $stem.eps}
|
||||
imagescale = `{*=$epsbox; $calc $imagewidth $3 $1 -/}
|
||||
imageheight = `{*=$epsbox; $calc $4 $2 - $imagescale '*'}
|
||||
* = `{hoc -e'-('$epsbox')'}
|
||||
x = $1
|
||||
y = $2
|
||||
gs -q -dBATCH -dNOPAUSE -s'DEVICE=pngalpha' -s'OutputFile='$target -g$imagewidth^x^$imageheight - <<!
|
||||
$imagescale $imagescale scale
|
||||
$x $y translate
|
||||
($eps) run
|
||||
showpage
|
||||
quit
|
||||
!
|
||||
optipng -fix $target
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
# define CLIENTEXTERN extern
|
||||
#endif
|
||||
|
||||
char* readctl(char*);
|
||||
char* readctl(char*, char*);
|
||||
void client_init(char*);
|
||||
|
||||
CLIENTEXTERN IxpClient* client;
|
||||
|
|
|
@ -30,8 +30,8 @@ typedef enum Align Align;
|
|||
#define Dx(r) ((r).max.x - (r).min.x)
|
||||
#define Dy(r) ((r).max.y - (r).min.y)
|
||||
#define Pt(x, y) ((Point){(x), (y)})
|
||||
#define Rpt(p, q) ((Rectangle){p, q})
|
||||
#define Rect(x0, y0, x1, y1) ((Rectangle){Pt(x0, y0), Pt(x1, y1)})
|
||||
#define Rpt(p, q) ((Rectangle){(p), (q)})
|
||||
#define Rect(x0, y0, x1, y1) Rpt(Pt(x0, y0), Pt(x1, y1))
|
||||
|
||||
Point addpt(Point, Point);
|
||||
Point divpt(Point, Point);
|
||||
|
|
|
@ -42,13 +42,10 @@ enum {
|
|||
|
||||
int Blprint(Biobuf*, const char*, ...);
|
||||
int Bvlprint(Biobuf*, const char*, va_list);
|
||||
extern char* _buffer;
|
||||
void _die(char*, int, char*, ...);
|
||||
void backtrace(char*);
|
||||
extern char buffer[8092];
|
||||
void closeexec(int);
|
||||
char** comm(int, char**, char**);
|
||||
extern char* const _buf_end;
|
||||
int doublefork(void);
|
||||
void* emalloc(uint);
|
||||
void* emallocz(uint);
|
||||
|
@ -90,6 +87,10 @@ int unquote(char*, char*[], int);
|
|||
int utflcpy(char*, const char*, int);
|
||||
int vlprint(int, const char*, va_list);
|
||||
char* vsxprint(const char*, va_list);
|
||||
|
||||
extern char* _buffer;
|
||||
extern char buffer[8092];
|
||||
extern char* const _buf_end;
|
||||
#define bufclear() \
|
||||
BLOCK( _buffer = buffer; _buffer[0] = '\0' )
|
||||
#define bufprint(...) \
|
||||
|
|
|
@ -261,6 +261,7 @@ void drawpoly(Image*, Point*, int, int cap, int w, Color*);
|
|||
uint drawstring(Image*, Font*, Rectangle, Align, const char*, Color*);
|
||||
void fill(Image*, Rectangle, Color*);
|
||||
void fillpoly(Image*, Point*, int, Color*);
|
||||
uint fillstring(Image*, Font*, Rectangle, Align, const char*, CTuple*, int border);
|
||||
Window* findwin(XWindow);
|
||||
void freefont(Font*);
|
||||
void freeimage(Image *);
|
||||
|
|
|
@ -11,13 +11,13 @@ void
|
|||
client_readconfig(CTuple *norm, CTuple *focus, Font **font) {
|
||||
|
||||
if(norm)
|
||||
loadcolor(norm, readctl("normcolors "), nil);
|
||||
loadcolor(norm, readctl("/ctl", "normcolors "), nil);
|
||||
if(focus)
|
||||
loadcolor(focus, readctl("focuscolors "), nil);
|
||||
*font = loadfont(readctl("font "));
|
||||
loadcolor(focus, readctl("/ctl", "focuscolors "), nil);
|
||||
*font = loadfont(readctl("/ctl", "font "));
|
||||
if(!*font)
|
||||
fatal("Can't load font %q", readctl("font "));
|
||||
sscanf(readctl("fontpad "), "%d %d %d %d",
|
||||
fatal("Can't load font %q", readctl("/ctl", "font "));
|
||||
sscanf(readctl("/ctl", "fontpad "), "%d %d %d %d",
|
||||
&(*font)->pad.min.x, &(*font)->pad.max.x,
|
||||
&(*font)->pad.min.x, &(*font)->pad.max.y);
|
||||
}
|
||||
|
|
|
@ -10,20 +10,21 @@
|
|||
#include <stuff/clientutil.h>
|
||||
#include <stuff/util.h>
|
||||
|
||||
static IxpCFid* ctlfid;
|
||||
static char ctl[1024];
|
||||
static char* ectl;
|
||||
|
||||
char*
|
||||
readctl(char *key) {
|
||||
readctl(char *ctlname, char *key) {
|
||||
static char ctlfile[128];
|
||||
static char ctl[1024];
|
||||
static char* ectl;
|
||||
IxpCFid *fid;
|
||||
char *s, *p;
|
||||
int nkey, n;
|
||||
|
||||
if(ctlfid == nil) {
|
||||
ctlfid = ixp_open(client, "ctl", OREAD);
|
||||
n = ixp_read(ctlfid, ctl, 1023);
|
||||
if(strcmp(ctlname, ctlfile)) {
|
||||
strncpy(ctlfile, ctlname, sizeof ctlfile);
|
||||
fid = ixp_open(client, ctlfile, OREAD);
|
||||
n = ixp_read(fid, ctl, sizeof ctl - 1);
|
||||
ectl = ctl + n;
|
||||
ixp_close(ctlfid);
|
||||
ixp_close(fid);
|
||||
}
|
||||
|
||||
nkey = strlen(key);
|
||||
|
@ -36,7 +37,7 @@ readctl(char *key) {
|
|||
n = (s ? s : ectl) - p;
|
||||
s = freelater(emalloc(n + 1));
|
||||
s[n] = '\0';
|
||||
return strncpy(s, p, n);
|
||||
return memcpy(s, p, n);
|
||||
}
|
||||
} while((p = strchr(p, '\n')));
|
||||
return "";
|
||||
|
|
|
@ -4,6 +4,17 @@
|
|||
#include <string.h>
|
||||
#include "../x11.h"
|
||||
|
||||
uint
|
||||
fillstring(Image *dst, Font *font,
|
||||
Rectangle r, Align align,
|
||||
const char *text, CTuple *col, int borderw) {
|
||||
|
||||
fill(dst, r, &col->bg);
|
||||
if(borderw)
|
||||
border(dst, r, borderw, &col->border);
|
||||
return drawstring(dst, font, r, align, text, &col->fg);
|
||||
}
|
||||
|
||||
uint
|
||||
drawstring(Image *dst, Font *font,
|
||||
Rectangle r, Align align,
|
||||
|
|
|
@ -41,8 +41,8 @@ tags:
|
|||
for f in $(OBJ); do \
|
||||
[ -f "$$f.c" ] && files="$$files $$f.c"; \
|
||||
done; \
|
||||
echo CTAGS $$files $(TAGFILES) || \
|
||||
ctags $$files $(TAGFILES)
|
||||
echo CTAGS $$files $(TAGFILES); \
|
||||
$(DEBUG) $(CTAGS) $$files $(TAGFILES)
|
||||
|
||||
.PHONY: all options clean dist install uninstall depend cleandep tags
|
||||
.PHONY: simpleuninstall simpleinstall
|
||||
|
|
|
@ -49,7 +49,7 @@ undup() { # GCC is crap.
|
|||
nl=0
|
||||
maxl=6
|
||||
}
|
||||
/: (error|note): .?Each undeclared identifier|: error: for each function it appears|is dangerous, better use|is almost always misused|: In function |: At top level:|support .long long.|use of C99 long long|ISO C forbids conversion|warning:.*warn_unused_result/ {
|
||||
tolower($0) ~ /: (error|note): .?each undeclared identifier|: error: for each function it appears|is dangerous, better use|is almost always misused|: in function |: at top level:|support .long long.|use of c99 long long|iso c forbids conversion|warning:.*warn_unused_result/ {
|
||||
next
|
||||
}
|
||||
$1 == "warning:" {
|
||||
|
|
Loading…
Reference in New Issue