| 1 |
1 |
|
/* See LICENSE file for copyright and license details. */ |
| 2 |
2 |
|
#include <ctype.h> |
|
3 |
+ |
#include <locale.h> |
| 3 |
4 |
|
#include <stdio.h> |
| 4 |
5 |
|
#include <stdlib.h> |
| 5 |
6 |
|
#include <string.h> |
|
| 11 |
12 |
|
#ifdef XINERAMA |
| 12 |
13 |
|
#include <X11/extensions/Xinerama.h> |
| 13 |
14 |
|
#endif |
| 14 |
|
- |
#include "draw.h" |
|
15 |
+ |
#include <X11/Xft/Xft.h> |
|
16 |
+ |
|
|
17 |
+ |
#include "drw.h" |
|
18 |
+ |
#include "util.h" |
| 15 |
19 |
|
|
|
20 |
+ |
/* macros */ |
| 16 |
21 |
|
#define INTERSECT(x,y,w,h,r) (MAX(0, MIN((x)+(w),(r).x_org+(r).width) - MAX((x),(r).x_org)) \ |
| 17 |
22 |
|
* MAX(0, MIN((y)+(h),(r).y_org+(r).height) - MAX((y),(r).y_org))) |
| 18 |
|
- |
#define MIN(a,b) ((a) < (b) ? (a) : (b)) |
| 19 |
|
- |
#define MAX(a,b) ((a) > (b) ? (a) : (b)) |
|
23 |
+ |
#define LENGTH(X) (sizeof X / sizeof X[0]) |
|
24 |
+ |
#define TEXTNW(X,N) (drw_font_getexts_width(drw->fonts[0], (X), (N))) |
|
25 |
+ |
#define TEXTW(X) (drw_text(drw, 0, 0, 0, 0, (X), 0) + drw->fonts[0]->h) |
|
26 |
+ |
|
|
27 |
+ |
/* enums */ |
|
28 |
+ |
enum { SchemeNorm, SchemeSel, SchemeOut, SchemeLast }; /* color schemes */ |
| 20 |
29 |
|
|
| 21 |
30 |
|
typedef struct Item Item; |
| 22 |
31 |
|
struct Item { |
|
| 28 |
37 |
|
static void appenditem(Item *item, Item **list, Item **last); |
| 29 |
38 |
|
static void calcoffsets(void); |
| 30 |
39 |
|
static char *cistrstr(const char *s, const char *sub); |
|
40 |
+ |
static void cleanup(void); |
| 31 |
41 |
|
static void drawmenu(void); |
| 32 |
42 |
|
static void grabkeyboard(void); |
| 33 |
43 |
|
static void insert(const char *str, ssize_t n); |
|
| 44 |
54 |
|
static int bh, mw, mh; |
| 45 |
55 |
|
static int inputw, promptw; |
| 46 |
56 |
|
static size_t cursor = 0; |
| 47 |
|
- |
static unsigned long normcol[ColLast]; |
| 48 |
|
- |
static unsigned long selcol[ColLast]; |
| 49 |
|
- |
static unsigned long outcol[ColLast]; |
| 50 |
57 |
|
static Atom clip, utf8; |
| 51 |
|
- |
static DC *dc; |
| 52 |
58 |
|
static Item *items = NULL; |
| 53 |
59 |
|
static Item *matches, *matchend; |
| 54 |
60 |
|
static Item *prev, *curr, *next, *sel; |
|
| 56 |
62 |
|
static XIC xic; |
| 57 |
63 |
|
static int mon = -1; |
| 58 |
64 |
|
|
|
65 |
+ |
static ClrScheme scheme[SchemeLast]; |
|
66 |
+ |
static Display *dpy; |
|
67 |
+ |
static int screen; |
|
68 |
+ |
static Window root; |
|
69 |
+ |
static Drw *drw; |
|
70 |
+ |
static int sw, sh; /* X display screen geometry width, height */ |
|
71 |
+ |
|
| 59 |
72 |
|
#include "config.h" |
| 60 |
73 |
|
|
| 61 |
74 |
|
static int (*fstrncmp)(const char *, const char *, size_t) = strncmp; |
|
| 69 |
82 |
|
for(i = 1; i < argc; i++) |
| 70 |
83 |
|
/* these options take no arguments */ |
| 71 |
84 |
|
if(!strcmp(argv[i], "-v")) { /* prints version information */ |
| 72 |
|
- |
puts("dmenu-"VERSION", © 2006-2014 dmenu engineers, see LICENSE for details"); |
| 73 |
|
- |
exit(EXIT_SUCCESS); |
|
85 |
+ |
puts("dmenu-"VERSION", © 2006-2015 dmenu engineers, see LICENSE for details"); |
|
86 |
+ |
exit(0); |
| 74 |
87 |
|
} |
| 75 |
88 |
|
else if(!strcmp(argv[i], "-b")) /* appears at the bottom of the screen */ |
| 76 |
89 |
|
topbar = False; |
|
| 90 |
103 |
|
else if(!strcmp(argv[i], "-p")) /* adds prompt to left of input field */ |
| 91 |
104 |
|
prompt = argv[++i]; |
| 92 |
105 |
|
else if(!strcmp(argv[i], "-fn")) /* font or font set */ |
| 93 |
|
- |
font = argv[++i]; |
|
106 |
+ |
fonts[0] = argv[++i]; |
| 94 |
107 |
|
else if(!strcmp(argv[i], "-nb")) /* normal background color */ |
| 95 |
108 |
|
normbgcolor = argv[++i]; |
| 96 |
109 |
|
else if(!strcmp(argv[i], "-nf")) /* normal foreground color */ |
|
| 102 |
115 |
|
else |
| 103 |
116 |
|
usage(); |
| 104 |
117 |
|
|
| 105 |
|
- |
dc = initdc(); |
| 106 |
|
- |
initfont(dc, font); |
|
118 |
+ |
if(!setlocale(LC_CTYPE, "") || !XSupportsLocale()) |
|
119 |
+ |
fputs("warning: no locale support\n", stderr); |
|
120 |
+ |
if(!(dpy = XOpenDisplay(NULL))) |
|
121 |
+ |
die("dwm: cannot open display\n"); |
|
122 |
+ |
screen = DefaultScreen(dpy); |
|
123 |
+ |
root = RootWindow(dpy, screen); |
|
124 |
+ |
sw = DisplayWidth(dpy, screen); |
|
125 |
+ |
sh = DisplayHeight(dpy, screen); |
|
126 |
+ |
drw = drw_create(dpy, screen, root, sw, sh); |
|
127 |
+ |
drw_load_fonts(drw, fonts, LENGTH(fonts)); |
|
128 |
+ |
if(!drw->fontcount) |
|
129 |
+ |
die("No fonts could be loaded.\n"); |
|
130 |
+ |
drw_setscheme(drw, &scheme[SchemeNorm]); |
| 107 |
131 |
|
|
| 108 |
132 |
|
if(fast) { |
| 109 |
133 |
|
grabkeyboard(); |
|
| 138 |
162 |
|
if(lines > 0) |
| 139 |
163 |
|
n = lines * bh; |
| 140 |
164 |
|
else |
| 141 |
|
- |
n = mw - (promptw + inputw + textw(dc, "<") + textw(dc, ">")); |
|
165 |
+ |
n = mw - (promptw + inputw + TEXTW("<") + TEXTW(">")); |
| 142 |
166 |
|
/* calculate which items will begin the next page and previous page */ |
| 143 |
167 |
|
for(i = 0, next = curr; next; next = next->right) |
| 144 |
|
- |
if((i += (lines > 0) ? bh : MIN(textw(dc, next->text), n)) > n) |
|
168 |
+ |
if((i += (lines > 0) ? bh : MIN(TEXTW(next->text), n)) > n) |
| 145 |
169 |
|
break; |
| 146 |
170 |
|
for(i = 0, prev = curr; prev && prev->left; prev = prev->left) |
| 147 |
|
- |
if((i += (lines > 0) ? bh : MIN(textw(dc, prev->left->text), n)) > n) |
|
171 |
+ |
if((i += (lines > 0) ? bh : MIN(TEXTW(prev->left->text), n)) > n) |
| 148 |
172 |
|
break; |
| 149 |
173 |
|
} |
| 150 |
174 |
|
|
|
175 |
+ |
void |
|
176 |
+ |
cleanup(void) { |
|
177 |
+ |
XUngrabKey(dpy, AnyKey, AnyModifier, root); |
|
178 |
+ |
drw_clr_free(scheme[SchemeNorm].bg); |
|
179 |
+ |
drw_clr_free(scheme[SchemeNorm].fg); |
|
180 |
+ |
drw_clr_free(scheme[SchemeSel].fg); |
|
181 |
+ |
drw_clr_free(scheme[SchemeSel].bg); |
|
182 |
+ |
drw_clr_free(scheme[SchemeOut].fg); |
|
183 |
+ |
drw_clr_free(scheme[SchemeOut].bg); |
|
184 |
+ |
drw_free(drw); |
|
185 |
+ |
XSync(dpy, False); |
|
186 |
+ |
XCloseDisplay(dpy); |
|
187 |
+ |
} |
|
188 |
+ |
|
| 151 |
189 |
|
char * |
| 152 |
190 |
|
cistrstr(const char *s, const char *sub) { |
| 153 |
191 |
|
size_t len; |
|
| 162 |
200 |
|
drawmenu(void) { |
| 163 |
201 |
|
int curpos; |
| 164 |
202 |
|
Item *item; |
|
203 |
+ |
int x = 0, y = 0, h = bh, w; |
| 165 |
204 |
|
|
| 166 |
|
- |
dc->x = 0; |
| 167 |
|
- |
dc->y = 0; |
| 168 |
|
- |
dc->h = bh; |
| 169 |
|
- |
drawrect(dc, 0, 0, mw, mh, True, BG(dc, normcol)); |
|
205 |
+ |
drw_setscheme(drw, &scheme[SchemeNorm]); |
|
206 |
+ |
drw_rect(drw, 0, 0, mw, mh, True, 1, 1); |
| 170 |
207 |
|
|
| 171 |
208 |
|
if(prompt && *prompt) { |
| 172 |
|
- |
dc->w = promptw; |
| 173 |
|
- |
drawtext(dc, prompt, selcol); |
| 174 |
|
- |
dc->x = dc->w; |
|
209 |
+ |
drw_setscheme(drw, &scheme[SchemeSel]); |
|
210 |
+ |
drw_text(drw, x, 0, promptw, bh, prompt, 1); |
|
211 |
+ |
x += promptw; |
| 175 |
212 |
|
} |
| 176 |
213 |
|
/* draw input field */ |
| 177 |
|
- |
dc->w = (lines > 0 || !matches) ? mw - dc->x : inputw; |
| 178 |
|
- |
drawtext(dc, text, normcol); |
| 179 |
|
- |
if((curpos = textnw(dc, text, cursor) + dc->h/2 - 2) < dc->w) |
| 180 |
|
- |
drawrect(dc, curpos, 2, 1, dc->h - 4, True, FG(dc, normcol)); |
|
214 |
+ |
w = (lines > 0 || !matches) ? mw - x : inputw; |
|
215 |
+ |
drw_setscheme(drw, &scheme[SchemeNorm]); |
|
216 |
+ |
drw_text(drw, x, 0, w, bh, text, 0); |
|
217 |
+ |
|
|
218 |
+ |
if((curpos = TEXTNW(text, cursor) + bh/2 - 2) < w) { |
|
219 |
+ |
drw_setscheme(drw, &scheme[SchemeNorm]); |
|
220 |
+ |
drw_rect(drw, x + curpos + 2, 2, 1, bh - 4, 1, 1, 0); |
|
221 |
+ |
} |
| 181 |
222 |
|
|
| 182 |
223 |
|
if(lines > 0) { |
| 183 |
224 |
|
/* draw vertical list */ |
| 184 |
|
- |
dc->w = mw - dc->x; |
|
225 |
+ |
w = mw - x; |
| 185 |
226 |
|
for(item = curr; item != next; item = item->right) { |
| 186 |
|
- |
dc->y += dc->h; |
| 187 |
|
- |
drawtext(dc, item->text, (item == sel) ? selcol : |
| 188 |
|
- |
(item->out) ? outcol : normcol); |
|
227 |
+ |
y += h; |
|
228 |
+ |
if(item == sel) |
|
229 |
+ |
drw_setscheme(drw, &scheme[SchemeSel]); |
|
230 |
+ |
else if(item->out) |
|
231 |
+ |
drw_setscheme(drw, &scheme[SchemeOut]); |
|
232 |
+ |
else |
|
233 |
+ |
drw_setscheme(drw, &scheme[SchemeNorm]); |
|
234 |
+ |
|
|
235 |
+ |
drw_text(drw, x, y, w, bh, item->text, 0); |
| 189 |
236 |
|
} |
| 190 |
237 |
|
} |
| 191 |
238 |
|
else if(matches) { |
| 192 |
239 |
|
/* draw horizontal list */ |
| 193 |
|
- |
dc->x += inputw; |
| 194 |
|
- |
dc->w = textw(dc, "<"); |
| 195 |
|
- |
if(curr->left) |
| 196 |
|
- |
drawtext(dc, "<", normcol); |
|
240 |
+ |
x += inputw; |
|
241 |
+ |
w = TEXTW("<"); |
|
242 |
+ |
if(curr->left) { |
|
243 |
+ |
drw_setscheme(drw, &scheme[SchemeNorm]); |
|
244 |
+ |
drw_text(drw, x, 0, w, bh, "<", 0); |
|
245 |
+ |
} |
| 197 |
246 |
|
for(item = curr; item != next; item = item->right) { |
| 198 |
|
- |
dc->x += dc->w; |
| 199 |
|
- |
dc->w = MIN(textw(dc, item->text), mw - dc->x - textw(dc, ">")); |
| 200 |
|
- |
drawtext(dc, item->text, (item == sel) ? selcol : |
| 201 |
|
- |
(item->out) ? outcol : normcol); |
|
247 |
+ |
x += w; |
|
248 |
+ |
w = MIN(TEXTW(item->text), mw - x - TEXTW(">")); |
|
249 |
+ |
|
|
250 |
+ |
if(item == sel) |
|
251 |
+ |
drw_setscheme(drw, &scheme[SchemeSel]); |
|
252 |
+ |
else if(item->out) |
|
253 |
+ |
drw_setscheme(drw, &scheme[SchemeOut]); |
|
254 |
+ |
else |
|
255 |
+ |
drw_setscheme(drw, &scheme[SchemeNorm]); |
|
256 |
+ |
drw_text(drw, x, 0, w, bh, item->text, 0); |
| 202 |
257 |
|
} |
| 203 |
|
- |
dc->w = textw(dc, ">"); |
| 204 |
|
- |
dc->x = mw - dc->w; |
| 205 |
|
- |
if(next) |
| 206 |
|
- |
drawtext(dc, ">", normcol); |
|
258 |
+ |
w = TEXTW(">"); |
|
259 |
+ |
x = mw - w; |
|
260 |
+ |
if(next) { |
|
261 |
+ |
drw_setscheme(drw, &scheme[SchemeNorm]); |
|
262 |
+ |
drw_text(drw, x, 0, w, bh, ">", 0); |
|
263 |
+ |
} |
| 207 |
264 |
|
} |
| 208 |
|
- |
mapdc(dc, win, mw, mh); |
|
265 |
+ |
drw_map(drw, win, 0, 0, mw, mh); |
| 209 |
266 |
|
} |
| 210 |
267 |
|
|
| 211 |
268 |
|
void |
|
| 214 |
271 |
|
|
| 215 |
272 |
|
/* try to grab keyboard, we may have to wait for another process to ungrab */ |
| 216 |
273 |
|
for(i = 0; i < 1000; i++) { |
| 217 |
|
- |
if(XGrabKeyboard(dc->dpy, DefaultRootWindow(dc->dpy), True, |
|
274 |
+ |
if(XGrabKeyboard(dpy, DefaultRootWindow(dpy), True, |
| 218 |
275 |
|
GrabModeAsync, GrabModeAsync, CurrentTime) == GrabSuccess) |
| 219 |
276 |
|
return; |
| 220 |
277 |
|
usleep(1000); |
| 221 |
278 |
|
} |
| 222 |
|
- |
eprintf("cannot grab keyboard\n"); |
|
279 |
+ |
die("cannot grab keyboard\n"); |
| 223 |
280 |
|
} |
| 224 |
281 |
|
|
| 225 |
282 |
|
void |
|
| 276 |
333 |
|
insert(NULL, nextrune(-1) - cursor); |
| 277 |
334 |
|
break; |
| 278 |
335 |
|
case XK_y: /* paste selection */ |
| 279 |
|
- |
XConvertSelection(dc->dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY, |
|
336 |
+ |
XConvertSelection(dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY, |
| 280 |
337 |
|
utf8, utf8, win, CurrentTime); |
| 281 |
338 |
|
return; |
| 282 |
339 |
|
case XK_Return: |
| 283 |
340 |
|
case XK_KP_Enter: |
| 284 |
341 |
|
break; |
| 285 |
342 |
|
case XK_bracketleft: |
| 286 |
|
- |
exit(EXIT_FAILURE); |
|
343 |
+ |
cleanup(); |
|
344 |
+ |
exit(1); |
| 287 |
345 |
|
default: |
| 288 |
346 |
|
return; |
| 289 |
347 |
|
} |
|
| 330 |
388 |
|
sel = matchend; |
| 331 |
389 |
|
break; |
| 332 |
390 |
|
case XK_Escape: |
| 333 |
|
- |
exit(EXIT_FAILURE); |
|
391 |
+ |
cleanup(); |
|
392 |
+ |
exit(1); |
| 334 |
393 |
|
case XK_Home: |
| 335 |
394 |
|
if(sel == matches) { |
| 336 |
395 |
|
cursor = 0; |
|
| 368 |
427 |
|
case XK_Return: |
| 369 |
428 |
|
case XK_KP_Enter: |
| 370 |
429 |
|
puts((sel && !(ev->state & ShiftMask)) ? sel->text : text); |
| 371 |
|
- |
if(!(ev->state & ControlMask)) |
| 372 |
|
- |
exit(EXIT_SUCCESS); |
|
430 |
+ |
if(!(ev->state & ControlMask)) { |
|
431 |
+ |
cleanup(); |
|
432 |
+ |
exit(0); |
|
433 |
+ |
} |
| 373 |
434 |
|
if(sel) |
| 374 |
435 |
|
sel->out = True; |
| 375 |
436 |
|
break; |
|
| 413 |
474 |
|
/* separate input text into tokens to be matched individually */ |
| 414 |
475 |
|
for(s = strtok(buf, " "); s; tokv[tokc-1] = s, s = strtok(NULL, " ")) |
| 415 |
476 |
|
if(++tokc > tokn && !(tokv = realloc(tokv, ++tokn * sizeof *tokv))) |
| 416 |
|
- |
eprintf("cannot realloc %u bytes\n", tokn * sizeof *tokv); |
|
477 |
+ |
die("cannot realloc %u bytes\n", tokn * sizeof *tokv); |
| 417 |
478 |
|
len = tokc ? strlen(tokv[0]) : 0; |
| 418 |
479 |
|
|
| 419 |
480 |
|
matches = lprefix = lsubstr = matchend = prefixend = substrend = NULL; |
|
| 470 |
531 |
|
Atom da; |
| 471 |
532 |
|
|
| 472 |
533 |
|
/* we have been given the current selection, now insert it into input */ |
| 473 |
|
- |
XGetWindowProperty(dc->dpy, win, utf8, 0, (sizeof text / 4) + 1, False, |
|
534 |
+ |
XGetWindowProperty(dpy, win, utf8, 0, (sizeof text / 4) + 1, False, |
| 474 |
535 |
|
utf8, &da, &di, &dl, &dl, (unsigned char **)&p); |
| 475 |
536 |
|
insert(p, (q = strchr(p, '\n')) ? q-p : (ssize_t)strlen(p)); |
| 476 |
537 |
|
XFree(p); |
|
| 486 |
547 |
|
for(i = 0; fgets(buf, sizeof buf, stdin); i++) { |
| 487 |
548 |
|
if(i+1 >= size / sizeof *items) |
| 488 |
549 |
|
if(!(items = realloc(items, (size += BUFSIZ)))) |
| 489 |
|
- |
eprintf("cannot realloc %u bytes:", size); |
|
550 |
+ |
die("cannot realloc %u bytes:", size); |
| 490 |
551 |
|
if((p = strchr(buf, '\n'))) |
| 491 |
552 |
|
*p = '\0'; |
| 492 |
553 |
|
if(!(items[i].text = strdup(buf))) |
| 493 |
|
- |
eprintf("cannot strdup %u bytes:", strlen(buf)+1); |
|
554 |
+ |
die("cannot strdup %u bytes:", strlen(buf)+1); |
| 494 |
555 |
|
items[i].out = False; |
| 495 |
556 |
|
if(strlen(items[i].text) > max) |
| 496 |
557 |
|
max = strlen(maxstr = items[i].text); |
| 497 |
558 |
|
} |
| 498 |
559 |
|
if(items) |
| 499 |
560 |
|
items[i].text = NULL; |
| 500 |
|
- |
inputw = maxstr ? textw(dc, maxstr) : 0; |
|
561 |
+ |
inputw = maxstr ? TEXTW(maxstr) : 0; |
| 501 |
562 |
|
lines = MIN(lines, i); |
| 502 |
563 |
|
} |
| 503 |
564 |
|
|
|
| 505 |
566 |
|
run(void) { |
| 506 |
567 |
|
XEvent ev; |
| 507 |
568 |
|
|
| 508 |
|
- |
while(!XNextEvent(dc->dpy, &ev)) { |
|
569 |
+ |
while(!XNextEvent(dpy, &ev)) { |
| 509 |
570 |
|
if(XFilterEvent(&ev, win)) |
| 510 |
571 |
|
continue; |
| 511 |
572 |
|
switch(ev.type) { |
| 512 |
573 |
|
case Expose: |
| 513 |
574 |
|
if(ev.xexpose.count == 0) |
| 514 |
|
- |
mapdc(dc, win, mw, mh); |
|
575 |
+ |
drw_map(drw, win, 0, 0, mw, mh); |
| 515 |
576 |
|
break; |
| 516 |
577 |
|
case KeyPress: |
| 517 |
578 |
|
keypress(&ev.xkey); |
|
| 522 |
583 |
|
break; |
| 523 |
584 |
|
case VisibilityNotify: |
| 524 |
585 |
|
if(ev.xvisibility.state != VisibilityUnobscured) |
| 525 |
|
- |
XRaiseWindow(dc->dpy, win); |
|
586 |
+ |
XRaiseWindow(dpy, win); |
| 526 |
587 |
|
break; |
| 527 |
588 |
|
} |
| 528 |
589 |
|
} |
|
| 530 |
591 |
|
|
| 531 |
592 |
|
void |
| 532 |
593 |
|
setup(void) { |
| 533 |
|
- |
int x, y, screen = DefaultScreen(dc->dpy); |
| 534 |
|
- |
Window root = RootWindow(dc->dpy, screen); |
|
594 |
+ |
int x, y; |
| 535 |
595 |
|
XSetWindowAttributes swa; |
| 536 |
596 |
|
XIM xim; |
| 537 |
597 |
|
#ifdef XINERAMA |
| 538 |
|
- |
int n; |
| 539 |
598 |
|
XineramaScreenInfo *info; |
|
599 |
+ |
Window w, pw, dw, *dws; |
|
600 |
+ |
XWindowAttributes wa; |
|
601 |
+ |
int a, j, di, n, i = 0, area = 0; |
|
602 |
+ |
unsigned int du; |
| 540 |
603 |
|
#endif |
| 541 |
604 |
|
|
| 542 |
|
- |
normcol[ColBG] = getcolor(dc, normbgcolor); |
| 543 |
|
- |
normcol[ColFG] = getcolor(dc, normfgcolor); |
| 544 |
|
- |
selcol[ColBG] = getcolor(dc, selbgcolor); |
| 545 |
|
- |
selcol[ColFG] = getcolor(dc, selfgcolor); |
| 546 |
|
- |
outcol[ColBG] = getcolor(dc, outbgcolor); |
| 547 |
|
- |
outcol[ColFG] = getcolor(dc, outfgcolor); |
|
605 |
+ |
/* init appearance */ |
|
606 |
+ |
scheme[SchemeNorm].bg = drw_clr_create(drw, normbgcolor); |
|
607 |
+ |
scheme[SchemeNorm].fg = drw_clr_create(drw, normfgcolor); |
|
608 |
+ |
scheme[SchemeSel].bg = drw_clr_create(drw, selbgcolor); |
|
609 |
+ |
scheme[SchemeSel].fg = drw_clr_create(drw, selfgcolor); |
|
610 |
+ |
scheme[SchemeOut].bg = drw_clr_create(drw, outbgcolor); |
|
611 |
+ |
scheme[SchemeOut].fg = drw_clr_create(drw, outfgcolor); |
| 548 |
612 |
|
|
| 549 |
|
- |
clip = XInternAtom(dc->dpy, "CLIPBOARD", False); |
| 550 |
|
- |
utf8 = XInternAtom(dc->dpy, "UTF8_STRING", False); |
|
613 |
+ |
clip = XInternAtom(dpy, "CLIPBOARD", False); |
|
614 |
+ |
utf8 = XInternAtom(dpy, "UTF8_STRING", False); |
| 551 |
615 |
|
|
| 552 |
616 |
|
/* calculate menu geometry */ |
| 553 |
|
- |
bh = dc->font.height + 2; |
|
617 |
+ |
bh = drw->fonts[0]->h + 2; |
| 554 |
618 |
|
lines = MAX(lines, 0); |
| 555 |
619 |
|
mh = (lines + 1) * bh; |
| 556 |
620 |
|
#ifdef XINERAMA |
| 557 |
|
- |
if((info = XineramaQueryScreens(dc->dpy, &n))) { |
| 558 |
|
- |
int a, j, di, i = 0, area = 0; |
| 559 |
|
- |
unsigned int du; |
| 560 |
|
- |
Window w, pw, dw, *dws; |
| 561 |
|
- |
XWindowAttributes wa; |
| 562 |
|
- |
|
| 563 |
|
- |
XGetInputFocus(dc->dpy, &w, &di); |
|
621 |
+ |
if((info = XineramaQueryScreens(dpy, &n))) { |
|
622 |
+ |
XGetInputFocus(dpy, &w, &di); |
| 564 |
623 |
|
if(mon != -1 && mon < n) |
| 565 |
624 |
|
i = mon; |
| 566 |
625 |
|
if(!i && w != root && w != PointerRoot && w != None) { |
| 567 |
626 |
|
/* find top-level window containing current input focus */ |
| 568 |
627 |
|
do { |
| 569 |
|
- |
if(XQueryTree(dc->dpy, (pw = w), &dw, &w, &dws, &du) && dws) |
|
628 |
+ |
if(XQueryTree(dpy, (pw = w), &dw, &w, &dws, &du) && dws) |
| 570 |
629 |
|
XFree(dws); |
| 571 |
630 |
|
} while(w != root && w != pw); |
| 572 |
631 |
|
/* find xinerama screen with which the window intersects most */ |
| 573 |
|
- |
if(XGetWindowAttributes(dc->dpy, pw, &wa)) |
|
632 |
+ |
if(XGetWindowAttributes(dpy, pw, &wa)) |
| 574 |
633 |
|
for(j = 0; j < n; j++) |
| 575 |
634 |
|
if((a = INTERSECT(wa.x, wa.y, wa.width, wa.height, info[j])) > area) { |
| 576 |
635 |
|
area = a; |
|
| 578 |
637 |
|
} |
| 579 |
638 |
|
} |
| 580 |
639 |
|
/* no focused window is on screen, so use pointer location instead */ |
| 581 |
|
- |
if(mon == -1 && !area && XQueryPointer(dc->dpy, root, &dw, &dw, &x, &y, &di, &di, &du)) |
|
640 |
+ |
if(mon == -1 && !area && XQueryPointer(dpy, root, &dw, &dw, &x, &y, &di, &di, &du)) |
| 582 |
641 |
|
for(i = 0; i < n; i++) |
| 583 |
642 |
|
if(INTERSECT(x, y, 1, 1, info[i])) |
| 584 |
643 |
|
break; |
|
| 592 |
651 |
|
#endif |
| 593 |
652 |
|
{ |
| 594 |
653 |
|
x = 0; |
| 595 |
|
- |
y = topbar ? 0 : DisplayHeight(dc->dpy, screen) - mh; |
| 596 |
|
- |
mw = DisplayWidth(dc->dpy, screen); |
|
654 |
+ |
y = topbar ? 0 : sh - mh; |
|
655 |
+ |
mw = sw; |
| 597 |
656 |
|
} |
| 598 |
|
- |
promptw = (prompt && *prompt) ? textw(dc, prompt) : 0; |
|
657 |
+ |
promptw = (prompt && *prompt) ? TEXTW(prompt) : 0; |
| 599 |
658 |
|
inputw = MIN(inputw, mw/3); |
| 600 |
659 |
|
match(); |
| 601 |
660 |
|
|
| 602 |
661 |
|
/* create menu window */ |
| 603 |
662 |
|
swa.override_redirect = True; |
| 604 |
|
- |
swa.background_pixel = normcol[ColBG]; |
|
663 |
+ |
swa.background_pixel = scheme[SchemeNorm].bg->pix; |
| 605 |
664 |
|
swa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask; |
| 606 |
|
- |
win = XCreateWindow(dc->dpy, root, x, y, mw, mh, 0, |
| 607 |
|
- |
DefaultDepth(dc->dpy, screen), CopyFromParent, |
| 608 |
|
- |
DefaultVisual(dc->dpy, screen), |
|
665 |
+ |
win = XCreateWindow(dpy, root, x, y, mw, mh, 0, |
|
666 |
+ |
DefaultDepth(dpy, screen), CopyFromParent, |
|
667 |
+ |
DefaultVisual(dpy, screen), |
| 609 |
668 |
|
CWOverrideRedirect | CWBackPixel | CWEventMask, &swa); |
| 610 |
669 |
|
|
| 611 |
670 |
|
/* open input methods */ |
| 612 |
|
- |
xim = XOpenIM(dc->dpy, NULL, NULL, NULL); |
|
671 |
+ |
xim = XOpenIM(dpy, NULL, NULL, NULL); |
| 613 |
672 |
|
xic = XCreateIC(xim, XNInputStyle, XIMPreeditNothing | XIMStatusNothing, |
| 614 |
673 |
|
XNClientWindow, win, XNFocusWindow, win, NULL); |
| 615 |
674 |
|
|
| 616 |
|
- |
XMapRaised(dc->dpy, win); |
| 617 |
|
- |
resizedc(dc, mw, mh); |
|
675 |
+ |
XMapRaised(dpy, win); |
|
676 |
+ |
drw_resize(drw, mw, mh); |
| 618 |
677 |
|
drawmenu(); |
| 619 |
678 |
|
} |
| 620 |
679 |
|
|
|
| 622 |
681 |
|
usage(void) { |
| 623 |
682 |
|
fputs("usage: dmenu [-b] [-f] [-i] [-l lines] [-p prompt] [-fn font] [-m monitor]\n" |
| 624 |
683 |
|
" [-nb color] [-nf color] [-sb color] [-sf color] [-v]\n", stderr); |
| 625 |
|
- |
exit(EXIT_FAILURE); |
|
684 |
+ |
exit(1); |
| 626 |
685 |
|
} |