2d19aeea650d4d2ad69a7bccdd0107852386d8fd
[dmenu.git] / common.c
1 /* See LICENSE file for copyright and license details. */
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <X11/keysym.h>
6 #ifdef XINERAMA
7 #include <X11/extensions/Xinerama.h>
8 #endif
9 #include "dmenu.h"
10
11 /* variables */
12 char *prompt = NULL;
13 char text[4096] = "";
14 int promptw = 0;
15 int screen;
16 unsigned int numlockmask = 0;
17 unsigned int mw, mh;
18 unsigned long normcol[ColLast];
19 unsigned long selcol[ColLast];
20 Bool topbar = True;
21 DC dc;
22 Display *dpy;
23 Window win, root;
24
25 void
26 grabkeyboard(void) {
27         unsigned int len;
28
29         for(len = 1000; len; len--) {
30                 if(XGrabKeyboard(dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime)
31                 == GrabSuccess)
32                         return;
33                 usleep(1000);
34         }
35         exit(EXIT_FAILURE);
36 }
37
38 void
39 run(void) {
40         XEvent ev;
41
42         /* main event loop */
43         XSync(dpy, False);
44         while(!XNextEvent(dpy, &ev))
45                 switch(ev.type) {
46                 case KeyPress:
47                         kpress(&ev.xkey);
48                         break;
49                 case Expose:
50                         if(ev.xexpose.count == 0)
51                                 drawbar();
52                         break;
53                 case VisibilityNotify:
54                         if(ev.xvisibility.state != VisibilityUnobscured)
55                                 XRaiseWindow(dpy, win);
56                         break;
57                 }
58         exit(EXIT_FAILURE);
59 }
60
61 void
62 setup(unsigned int lines) {
63         int i, j, x, y;
64 #if XINERAMA
65         int n;
66         XineramaScreenInfo *info = NULL;
67 #endif
68         XModifierKeymap *modmap;
69         XSetWindowAttributes wa;
70
71         /* init modifier map */
72         modmap = XGetModifierMapping(dpy);
73         for(i = 0; i < 8; i++)
74                 for(j = 0; j < modmap->max_keypermod; j++) {
75                         if(modmap->modifiermap[i * modmap->max_keypermod + j]
76                         == XKeysymToKeycode(dpy, XK_Num_Lock))
77                                 numlockmask = (1 << i);
78                 }
79         XFreeModifiermap(modmap);
80
81         dc.dpy = dpy;
82         normcol[ColBG] = getcolor(&dc, normbgcolor);
83         normcol[ColFG] = getcolor(&dc, normfgcolor);
84         selcol[ColBG] = getcolor(&dc, selbgcolor);
85         selcol[ColFG] = getcolor(&dc, selfgcolor);
86         initfont(&dc, font);
87
88         /* input window */
89         wa.override_redirect = True;
90         wa.background_pixmap = ParentRelative;
91         wa.event_mask = ExposureMask | KeyPressMask | VisibilityChangeMask;
92
93         /* input window geometry */
94         mh = (dc.font.height + 2) * (lines + 1);
95 #if XINERAMA
96         if(XineramaIsActive(dpy) && (info = XineramaQueryScreens(dpy, &n))) {
97                 i = 0;
98                 if(n > 1) {
99                         int di;
100                         unsigned int dui;
101                         Window dummy;
102                         if(XQueryPointer(dpy, root, &dummy, &dummy, &x, &y, &di, &di, &dui))
103                                 for(i = 0; i < n; i++)
104                                         if(INRECT(x, y, info[i].x_org, info[i].y_org, info[i].width, info[i].height))
105                                                 break;
106                 }
107                 x = info[i].x_org;
108                 y = topbar ? info[i].y_org : info[i].y_org + info[i].height - mh;
109                 mw = info[i].width;
110                 XFree(info);
111         }
112         else
113 #endif
114         {
115                 x = 0;
116                 y = topbar ? 0 : DisplayHeight(dpy, screen) - mh;
117                 mw = DisplayWidth(dpy, screen);
118         }
119
120         win = XCreateWindow(dpy, root, x, y, mw, mh, 0,
121                         DefaultDepth(dpy, screen), CopyFromParent,
122                         DefaultVisual(dpy, screen),
123                         CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
124
125         setupdraw(&dc, win);
126         if(prompt)
127                 promptw = MIN(textw(&dc, prompt), mw / 5);
128         XMapRaised(dpy, win);
129 }