ithingmenu.c - thingmenu - A simple graphical menu launcher for X11. Err bitreich.org 70 hgit clone git://bitreich.org/thingmenu URL:git://bitreich.org/thingmenu bitreich.org 70 1Log /scm/thingmenu/log.gph bitreich.org 70 1Files /scm/thingmenu/files.gph bitreich.org 70 1Refs /scm/thingmenu/refs.gph bitreich.org 70 1Tags /scm/thingmenu/tag bitreich.org 70 1LICENSE /scm/thingmenu/file/LICENSE.gph bitreich.org 70 i--- Err bitreich.org 70 ithingmenu.c (15423B) Err bitreich.org 70 i--- Err bitreich.org 70 i 1 /* Err bitreich.org 70 i 2 * Copy me if you can. Err bitreich.org 70 i 3 * by 20h Err bitreich.org 70 i 4 */ Err bitreich.org 70 i 5 #include Err bitreich.org 70 i 6 #include Err bitreich.org 70 i 7 #include Err bitreich.org 70 i 8 #include Err bitreich.org 70 i 9 #include Err bitreich.org 70 i 10 #include Err bitreich.org 70 i 11 #include Err bitreich.org 70 i 12 #include Err bitreich.org 70 i 13 #include Err bitreich.org 70 i 14 #include Err bitreich.org 70 i 15 #include Err bitreich.org 70 i 16 #include Err bitreich.org 70 i 17 #include Err bitreich.org 70 i 18 #include Err bitreich.org 70 i 19 #include Err bitreich.org 70 i 20 Err bitreich.org 70 i 21 /* macros */ Err bitreich.org 70 i 22 #define MAX(a, b) ((a) > (b) ? (a) : (b)) Err bitreich.org 70 i 23 #define LENGTH(x) (sizeof x / sizeof x[0]) Err bitreich.org 70 i 24 Err bitreich.org 70 i 25 /* enums */ Err bitreich.org 70 i 26 enum { ColFG, ColBG, ColLast }; Err bitreich.org 70 i 27 enum { NetWMWindowType, NetLast }; Err bitreich.org 70 i 28 Err bitreich.org 70 i 29 /* typedefs */ Err bitreich.org 70 i 30 typedef unsigned int uint; Err bitreich.org 70 i 31 typedef unsigned long ulong; Err bitreich.org 70 i 32 Err bitreich.org 70 i 33 typedef struct { Err bitreich.org 70 i 34 ulong norm[ColLast]; Err bitreich.org 70 i 35 ulong press[ColLast]; Err bitreich.org 70 i 36 ulong high[ColLast]; Err bitreich.org 70 i 37 Err bitreich.org 70 i 38 Drawable drawable; Err bitreich.org 70 i 39 GC gc; Err bitreich.org 70 i 40 struct { Err bitreich.org 70 i 41 int ascent; Err bitreich.org 70 i 42 int descent; Err bitreich.org 70 i 43 int height; Err bitreich.org 70 i 44 XFontSet set; Err bitreich.org 70 i 45 XFontStruct *xfont; Err bitreich.org 70 i 46 } font; Err bitreich.org 70 i 47 } DC; /* draw context */ Err bitreich.org 70 i 48 Err bitreich.org 70 i 49 typedef struct { Err bitreich.org 70 i 50 char *label; Err bitreich.org 70 i 51 char *cmd; Err bitreich.org 70 i 52 uint width; Err bitreich.org 70 i 53 int x, y, w, h; Err bitreich.org 70 i 54 Bool highlighted; Err bitreich.org 70 i 55 Bool pressed; Err bitreich.org 70 i 56 Bool forceexit; Err bitreich.org 70 i 57 } Entry; Err bitreich.org 70 i 58 Err bitreich.org 70 i 59 /* function declarations */ Err bitreich.org 70 i 60 static void motionnotify(XEvent *e); Err bitreich.org 70 i 61 static void keyrelease(XEvent *e); Err bitreich.org 70 i 62 static void buttonpress(XEvent *e); Err bitreich.org 70 i 63 static void buttonrelease(XEvent *e); Err bitreich.org 70 i 64 static void cleanup(void); Err bitreich.org 70 i 65 static void configurenotify(XEvent *e); Err bitreich.org 70 i 66 static void unmapnotify(XEvent *e); Err bitreich.org 70 i 67 static void die(const char *errstr, ...); Err bitreich.org 70 i 68 static void drawmenu(void); Err bitreich.org 70 i 69 static void drawentry(Entry *e); Err bitreich.org 70 i 70 static void expose(XEvent *e); Err bitreich.org 70 i 71 static Entry *findentry(int x, int y); Err bitreich.org 70 i 72 static ulong getcolor(const char *colstr); Err bitreich.org 70 i 73 static void initfont(const char *fontstr); Err bitreich.org 70 i 74 static void leavenotify(XEvent *e); Err bitreich.org 70 i 75 static void press(Entry *e); Err bitreich.org 70 i 76 static void run(void); Err bitreich.org 70 i 77 static void setup(void); Err bitreich.org 70 i 78 static void sigchld(int unused); Err bitreich.org 70 i 79 static int textnw(const char *text, uint len); Err bitreich.org 70 i 80 static void unpress(Entry *e); Err bitreich.org 70 i 81 static void updateentries(void); Err bitreich.org 70 i 82 Err bitreich.org 70 i 83 /* variables */ Err bitreich.org 70 i 84 static int screen; Err bitreich.org 70 i 85 static void (*handler[LASTEvent]) (XEvent *) = { Err bitreich.org 70 i 86 [KeyRelease] = keyrelease, Err bitreich.org 70 i 87 [ButtonPress] = buttonpress, Err bitreich.org 70 i 88 [ButtonRelease] = buttonrelease, Err bitreich.org 70 i 89 [ConfigureNotify] = configurenotify, Err bitreich.org 70 i 90 [UnmapNotify] = unmapnotify, Err bitreich.org 70 i 91 [Expose] = expose, Err bitreich.org 70 i 92 [LeaveNotify] = leavenotify, Err bitreich.org 70 i 93 [MotionNotify] = motionnotify Err bitreich.org 70 i 94 }; Err bitreich.org 70 i 95 Err bitreich.org 70 i 96 static Display *dpy; Err bitreich.org 70 i 97 static DC dc; Err bitreich.org 70 i 98 static Window root, win; Err bitreich.org 70 i 99 static Bool running = True, horizontal = False; Err bitreich.org 70 i 100 /* Err bitreich.org 70 i 101 * ww = window width; www = wanted window width; wh = window height; Err bitreich.org 70 i 102 * wx = window x position; wy = window y position; Err bitreich.org 70 i 103 */ Err bitreich.org 70 i 104 static int ww = 0, www = 0, wh = 0, wx = 0, wy = 0; Err bitreich.org 70 i 105 static char *name = "thingmenu"; Err bitreich.org 70 i 106 Err bitreich.org 70 i 107 Entry **entries = NULL; Err bitreich.org 70 i 108 int nentries = 0; Err bitreich.org 70 i 109 int exitentry = -1; Err bitreich.org 70 i 110 int oneshot = 1; Err bitreich.org 70 i 111 Bool ispressing = 0; Err bitreich.org 70 i 112 Err bitreich.org 70 i 113 char *argv0; Err bitreich.org 70 i 114 Err bitreich.org 70 i 115 #include "arg.h" Err bitreich.org 70 i 116 Err bitreich.org 70 i 117 /* configuration, allows nested code to access above variables */ Err bitreich.org 70 i 118 #include "config.h" Err bitreich.org 70 i 119 Err bitreich.org 70 i 120 void Err bitreich.org 70 i 121 motionnotify(XEvent *e) Err bitreich.org 70 i 122 { Err bitreich.org 70 i 123 XPointerMovedEvent *ev = &e->xmotion; Err bitreich.org 70 i 124 int i; Err bitreich.org 70 i 125 Err bitreich.org 70 i 126 for(i = 0; i < nentries; i++) { Err bitreich.org 70 i 127 if(ev->x > entries[i]->x Err bitreich.org 70 i 128 && ev->x < entries[i]->x + entries[i]->w Err bitreich.org 70 i 129 && ev->y > entries[i]->y Err bitreich.org 70 i 130 && ev->y < entries[i]->y + entries[i]->h) { Err bitreich.org 70 i 131 if (entries[i]->highlighted != True) { Err bitreich.org 70 i 132 if (ispressing) { Err bitreich.org 70 i 133 entries[i]->pressed = True; Err bitreich.org 70 i 134 } else { Err bitreich.org 70 i 135 entries[i]->highlighted = True; Err bitreich.org 70 i 136 } Err bitreich.org 70 i 137 drawentry(entries[i]); Err bitreich.org 70 i 138 } Err bitreich.org 70 i 139 continue; Err bitreich.org 70 i 140 } Err bitreich.org 70 i 141 if (entries[i]->pressed == True) { Err bitreich.org 70 i 142 entries[i]->pressed = False; Err bitreich.org 70 i 143 drawentry(entries[i]); Err bitreich.org 70 i 144 } Err bitreich.org 70 i 145 if (entries[i]->highlighted == True) { Err bitreich.org 70 i 146 entries[i]->highlighted = False; Err bitreich.org 70 i 147 drawentry(entries[i]); Err bitreich.org 70 i 148 } Err bitreich.org 70 i 149 } Err bitreich.org 70 i 150 } Err bitreich.org 70 i 151 Err bitreich.org 70 i 152 void Err bitreich.org 70 i 153 keyrelease(XEvent *e) Err bitreich.org 70 i 154 { Err bitreich.org 70 i 155 int i; Err bitreich.org 70 i 156 XKeyEvent *xkey = &e->xkey; Err bitreich.org 70 i 157 KeySym key = XLookupKeysym(xkey, 0); Err bitreich.org 70 i 158 Err bitreich.org 70 i 159 for (i = 0; i < nentries && !entries[i]->highlighted; i++); Err bitreich.org 70 i 160 Err bitreich.org 70 i 161 if (key >= XK_0 && key <= XK_9) { Err bitreich.org 70 i 162 i = key - XK_0; Err bitreich.org 70 i 163 key = XK_Return; Err bitreich.org 70 i 164 } else if (key >= XK_KP_0 && key <= XK_KP_9) { Err bitreich.org 70 i 165 i = key - XK_KP_0; Err bitreich.org 70 i 166 key = XK_Return; Err bitreich.org 70 i 167 } Err bitreich.org 70 i 168 Err bitreich.org 70 i 169 switch (key) { Err bitreich.org 70 i 170 case XK_KP_Insert: Err bitreich.org 70 i 171 i = 0; Err bitreich.org 70 i 172 key = XK_Return; Err bitreich.org 70 i 173 break; Err bitreich.org 70 i 174 case XK_KP_End: Err bitreich.org 70 i 175 i = 1; Err bitreich.org 70 i 176 key = XK_Return; Err bitreich.org 70 i 177 break; Err bitreich.org 70 i 178 case XK_KP_Down: Err bitreich.org 70 i 179 i = 2; Err bitreich.org 70 i 180 key = XK_Return; Err bitreich.org 70 i 181 break; Err bitreich.org 70 i 182 case XK_KP_Page_Down: Err bitreich.org 70 i 183 i = 3; Err bitreich.org 70 i 184 key = XK_Return; Err bitreich.org 70 i 185 break; Err bitreich.org 70 i 186 case XK_KP_Left: Err bitreich.org 70 i 187 i = 4; Err bitreich.org 70 i 188 key = XK_Return; Err bitreich.org 70 i 189 break; Err bitreich.org 70 i 190 case XK_KP_Begin: Err bitreich.org 70 i 191 i = 5; Err bitreich.org 70 i 192 key = XK_Return; Err bitreich.org 70 i 193 break; Err bitreich.org 70 i 194 case XK_KP_Right: Err bitreich.org 70 i 195 i = 6; Err bitreich.org 70 i 196 key = XK_Return; Err bitreich.org 70 i 197 break; Err bitreich.org 70 i 198 case XK_KP_Home: Err bitreich.org 70 i 199 i = 7; Err bitreich.org 70 i 200 key = XK_Return; Err bitreich.org 70 i 201 break; Err bitreich.org 70 i 202 case XK_KP_Up: Err bitreich.org 70 i 203 i = 8; Err bitreich.org 70 i 204 key = XK_Return; Err bitreich.org 70 i 205 break; Err bitreich.org 70 i 206 case XK_KP_Page_Up: Err bitreich.org 70 i 207 i = 9; Err bitreich.org 70 i 208 key = XK_Return; Err bitreich.org 70 i 209 break; Err bitreich.org 70 i 210 } Err bitreich.org 70 i 211 Err bitreich.org 70 i 212 switch (key) { Err bitreich.org 70 i 213 case XK_k: Err bitreich.org 70 i 214 key = XK_Up; Err bitreich.org 70 i 215 case XK_j: Err bitreich.org 70 i 216 if(key == XK_j) Err bitreich.org 70 i 217 key = XK_Down; Err bitreich.org 70 i 218 case XK_Up: Err bitreich.org 70 i 219 case XK_Down: Err bitreich.org 70 i 220 if (i < nentries) { Err bitreich.org 70 i 221 entries[i]->highlighted = False; Err bitreich.org 70 i 222 drawentry(entries[i]); Err bitreich.org 70 i 223 } Err bitreich.org 70 i 224 Err bitreich.org 70 i 225 if (key == XK_Up) { Err bitreich.org 70 i 226 i = ((i - 1) + nentries) % nentries; Err bitreich.org 70 i 227 } else if(key == XK_Down) { Err bitreich.org 70 i 228 if (i < nentries) { Err bitreich.org 70 i 229 i = (i + 1) % nentries; Err bitreich.org 70 i 230 } else { Err bitreich.org 70 i 231 i = 0; Err bitreich.org 70 i 232 } Err bitreich.org 70 i 233 } Err bitreich.org 70 i 234 Err bitreich.org 70 i 235 entries[i]->highlighted = True; Err bitreich.org 70 i 236 drawentry(entries[i]); Err bitreich.org 70 i 237 break; Err bitreich.org 70 i 238 case XK_period: Err bitreich.org 70 i 239 case XK_KP_Decimal: Err bitreich.org 70 i 240 case XK_KP_Delete: Err bitreich.org 70 i 241 i = exitentry; Err bitreich.org 70 i 242 case XK_Return: Err bitreich.org 70 i 243 case XK_space: Err bitreich.org 70 i 244 if (i < nentries) { Err bitreich.org 70 i 245 press(entries[i]); Err bitreich.org 70 i 246 unpress(entries[i]); Err bitreich.org 70 i 247 } Err bitreich.org 70 i 248 break; Err bitreich.org 70 i 249 case XK_Escape: Err bitreich.org 70 i 250 running = False; Err bitreich.org 70 i 251 break; Err bitreich.org 70 i 252 } Err bitreich.org 70 i 253 } Err bitreich.org 70 i 254 Err bitreich.org 70 i 255 void Err bitreich.org 70 i 256 buttonpress(XEvent *e) Err bitreich.org 70 i 257 { Err bitreich.org 70 i 258 XButtonPressedEvent *ev = &e->xbutton; Err bitreich.org 70 i 259 Entry *en; Err bitreich.org 70 i 260 Err bitreich.org 70 i 261 if(ev->button != Button1) Err bitreich.org 70 i 262 return; Err bitreich.org 70 i 263 Err bitreich.org 70 i 264 ispressing = True; Err bitreich.org 70 i 265 Err bitreich.org 70 i 266 if((en = findentry(ev->x, ev->y))) Err bitreich.org 70 i 267 press(en); Err bitreich.org 70 i 268 } Err bitreich.org 70 i 269 Err bitreich.org 70 i 270 void Err bitreich.org 70 i 271 buttonrelease(XEvent *e) Err bitreich.org 70 i 272 { Err bitreich.org 70 i 273 XButtonPressedEvent *ev = &e->xbutton; Err bitreich.org 70 i 274 Entry *en; Err bitreich.org 70 i 275 Err bitreich.org 70 i 276 if(ev->button != Button1) Err bitreich.org 70 i 277 return; Err bitreich.org 70 i 278 Err bitreich.org 70 i 279 ispressing = False; Err bitreich.org 70 i 280 Err bitreich.org 70 i 281 if((en = findentry(ev->x, ev->y))) Err bitreich.org 70 i 282 unpress(en); Err bitreich.org 70 i 283 } Err bitreich.org 70 i 284 Err bitreich.org 70 i 285 void Err bitreich.org 70 i 286 cleanup(void) Err bitreich.org 70 i 287 { Err bitreich.org 70 i 288 if(dc.font.set) Err bitreich.org 70 i 289 XFreeFontSet(dpy, dc.font.set); Err bitreich.org 70 i 290 else Err bitreich.org 70 i 291 XFreeFont(dpy, dc.font.xfont); Err bitreich.org 70 i 292 XFreePixmap(dpy, dc.drawable); Err bitreich.org 70 i 293 XFreeGC(dpy, dc.gc); Err bitreich.org 70 i 294 XDestroyWindow(dpy, win); Err bitreich.org 70 i 295 XSync(dpy, False); Err bitreich.org 70 i 296 XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); Err bitreich.org 70 i 297 } Err bitreich.org 70 i 298 Err bitreich.org 70 i 299 void Err bitreich.org 70 i 300 configurenotify(XEvent *e) Err bitreich.org 70 i 301 { Err bitreich.org 70 i 302 XConfigureEvent *ev = &e->xconfigure; Err bitreich.org 70 i 303 Err bitreich.org 70 i 304 if(ev->window == win && (ev->width != ww || ev->height != wh)) { Err bitreich.org 70 i 305 ww = ev->width; Err bitreich.org 70 i 306 wh = ev->height; Err bitreich.org 70 i 307 XFreePixmap(dpy, dc.drawable); Err bitreich.org 70 i 308 dc.drawable = XCreatePixmap(dpy, root, ww, wh, Err bitreich.org 70 i 309 DefaultDepth(dpy, screen)); Err bitreich.org 70 i 310 updateentries(); Err bitreich.org 70 i 311 } Err bitreich.org 70 i 312 } Err bitreich.org 70 i 313 Err bitreich.org 70 i 314 void Err bitreich.org 70 i 315 die(const char *errstr, ...) Err bitreich.org 70 i 316 { Err bitreich.org 70 i 317 va_list ap; Err bitreich.org 70 i 318 Err bitreich.org 70 i 319 va_start(ap, errstr); Err bitreich.org 70 i 320 vfprintf(stderr, errstr, ap); Err bitreich.org 70 i 321 va_end(ap); Err bitreich.org 70 i 322 exit(EXIT_FAILURE); Err bitreich.org 70 i 323 } Err bitreich.org 70 i 324 Err bitreich.org 70 i 325 void Err bitreich.org 70 i 326 drawmenu(void) Err bitreich.org 70 i 327 { Err bitreich.org 70 i 328 int i; Err bitreich.org 70 i 329 Err bitreich.org 70 i 330 for(i = 0; i < nentries; i++) Err bitreich.org 70 i 331 drawentry(entries[i]); Err bitreich.org 70 i 332 XSync(dpy, False); Err bitreich.org 70 i 333 } Err bitreich.org 70 i 334 Err bitreich.org 70 i 335 void Err bitreich.org 70 i 336 drawentry(Entry *e) Err bitreich.org 70 i 337 { Err bitreich.org 70 i 338 int x, y, h, len; Err bitreich.org 70 i 339 XRectangle r = { e->x, e->y, e->w, e->h }; Err bitreich.org 70 i 340 const char *l; Err bitreich.org 70 i 341 ulong *col; Err bitreich.org 70 i 342 Err bitreich.org 70 i 343 if(e->pressed) Err bitreich.org 70 i 344 col = dc.press; Err bitreich.org 70 i 345 else if(e->highlighted) Err bitreich.org 70 i 346 col = dc.high; Err bitreich.org 70 i 347 else Err bitreich.org 70 i 348 col = dc.norm; Err bitreich.org 70 i 349 Err bitreich.org 70 i 350 XSetForeground(dpy, dc.gc, col[ColBG]); Err bitreich.org 70 i 351 XFillRectangles(dpy, dc.drawable, dc.gc, &r, 1); Err bitreich.org 70 i 352 XSetForeground(dpy, dc.gc, dc.norm[ColFG]); Err bitreich.org 70 i 353 r.height -= 1; Err bitreich.org 70 i 354 r.width -= 1; Err bitreich.org 70 i 355 XDrawRectangles(dpy, dc.drawable, dc.gc, &r, 1); Err bitreich.org 70 i 356 XSetForeground(dpy, dc.gc, col[ColFG]); Err bitreich.org 70 i 357 Err bitreich.org 70 i 358 l = e->label; Err bitreich.org 70 i 359 len = strlen(l); Err bitreich.org 70 i 360 h = dc.font.height; Err bitreich.org 70 i 361 y = e->y + (e->h / 2) - (h / 2) + dc.font.ascent; Err bitreich.org 70 i 362 x = e->x + (e->w / 2) - (textnw(l, len) / 2); Err bitreich.org 70 i 363 if(dc.font.set) { Err bitreich.org 70 i 364 XmbDrawString(dpy, dc.drawable, dc.font.set, dc.gc, x, y, l, Err bitreich.org 70 i 365 len); Err bitreich.org 70 i 366 } else Err bitreich.org 70 i 367 XDrawString(dpy, dc.drawable, dc.gc, x, y, l, len); Err bitreich.org 70 i 368 XCopyArea(dpy, dc.drawable, win, dc.gc, e->x, e->y, e->w, e->h, Err bitreich.org 70 i 369 e->x, e->y); Err bitreich.org 70 i 370 } Err bitreich.org 70 i 371 Err bitreich.org 70 i 372 void Err bitreich.org 70 i 373 unmapnotify(XEvent *e) Err bitreich.org 70 i 374 { Err bitreich.org 70 i 375 running = False; Err bitreich.org 70 i 376 } Err bitreich.org 70 i 377 Err bitreich.org 70 i 378 void Err bitreich.org 70 i 379 expose(XEvent *e) Err bitreich.org 70 i 380 { Err bitreich.org 70 i 381 XExposeEvent *ev = &e->xexpose; Err bitreich.org 70 i 382 Err bitreich.org 70 i 383 if(ev->count == 0 && (ev->window == win)) Err bitreich.org 70 i 384 drawmenu(); Err bitreich.org 70 i 385 } Err bitreich.org 70 i 386 Err bitreich.org 70 i 387 Entry * Err bitreich.org 70 i 388 findentry(int x, int y) Err bitreich.org 70 i 389 { Err bitreich.org 70 i 390 int i; Err bitreich.org 70 i 391 Err bitreich.org 70 i 392 for(i = 0; i < nentries; i++) { Err bitreich.org 70 i 393 if(x > entries[i]->x && x < entries[i]->x + entries[i]->w Err bitreich.org 70 i 394 && y > entries[i]->y Err bitreich.org 70 i 395 && y < entries[i]->y + entries[i]->h) { Err bitreich.org 70 i 396 return entries[i]; Err bitreich.org 70 i 397 } Err bitreich.org 70 i 398 } Err bitreich.org 70 i 399 return NULL; Err bitreich.org 70 i 400 } Err bitreich.org 70 i 401 Err bitreich.org 70 i 402 ulong Err bitreich.org 70 i 403 getcolor(const char *colstr) Err bitreich.org 70 i 404 { Err bitreich.org 70 i 405 Colormap cmap = DefaultColormap(dpy, screen); Err bitreich.org 70 i 406 XColor color; Err bitreich.org 70 i 407 Err bitreich.org 70 i 408 if(!XAllocNamedColor(dpy, cmap, colstr, &color, &color)) Err bitreich.org 70 i 409 die("error, cannot allocate color '%s'\n", colstr); Err bitreich.org 70 i 410 return color.pixel; Err bitreich.org 70 i 411 } Err bitreich.org 70 i 412 Err bitreich.org 70 i 413 void Err bitreich.org 70 i 414 initfont(const char *fontstr) Err bitreich.org 70 i 415 { Err bitreich.org 70 i 416 char *def, **missing; Err bitreich.org 70 i 417 int i, n; Err bitreich.org 70 i 418 Err bitreich.org 70 i 419 missing = NULL; Err bitreich.org 70 i 420 if(dc.font.set) Err bitreich.org 70 i 421 XFreeFontSet(dpy, dc.font.set); Err bitreich.org 70 i 422 dc.font.set = XCreateFontSet(dpy, fontstr, &missing, &n, &def); Err bitreich.org 70 i 423 if(missing) { Err bitreich.org 70 i 424 while(n--) { Err bitreich.org 70 i 425 fprintf(stderr, "thingmenu: missing fontset: %s\n", Err bitreich.org 70 i 426 missing[n]); Err bitreich.org 70 i 427 } Err bitreich.org 70 i 428 XFreeStringList(missing); Err bitreich.org 70 i 429 } Err bitreich.org 70 i 430 if(dc.font.set) { Err bitreich.org 70 i 431 XFontStruct **xfonts; Err bitreich.org 70 i 432 char **font_names; Err bitreich.org 70 i 433 dc.font.ascent = dc.font.descent = 0; Err bitreich.org 70 i 434 n = XFontsOfFontSet(dc.font.set, &xfonts, &font_names); Err bitreich.org 70 i 435 for(i = 0, dc.font.ascent = 0, dc.font.descent = 0; i < n; i++) { Err bitreich.org 70 i 436 dc.font.ascent = MAX(dc.font.ascent, (*xfonts)->ascent); Err bitreich.org 70 i 437 dc.font.descent = MAX(dc.font.descent,(*xfonts)->descent); Err bitreich.org 70 i 438 xfonts++; Err bitreich.org 70 i 439 } Err bitreich.org 70 i 440 } Err bitreich.org 70 i 441 else { Err bitreich.org 70 i 442 if(dc.font.xfont) Err bitreich.org 70 i 443 XFreeFont(dpy, dc.font.xfont); Err bitreich.org 70 i 444 dc.font.xfont = NULL; Err bitreich.org 70 i 445 if(!(dc.font.xfont = XLoadQueryFont(dpy, fontstr)) Err bitreich.org 70 i 446 && !(dc.font.xfont = XLoadQueryFont(dpy, "fixed"))) Err bitreich.org 70 i 447 die("error, cannot load font: '%s'\n", fontstr); Err bitreich.org 70 i 448 dc.font.ascent = dc.font.xfont->ascent; Err bitreich.org 70 i 449 dc.font.descent = dc.font.xfont->descent; Err bitreich.org 70 i 450 } Err bitreich.org 70 i 451 dc.font.height = dc.font.ascent + dc.font.descent; Err bitreich.org 70 i 452 } Err bitreich.org 70 i 453 Err bitreich.org 70 i 454 void Err bitreich.org 70 i 455 leavenotify(XEvent *e) Err bitreich.org 70 i 456 { Err bitreich.org 70 i 457 unpress(NULL); Err bitreich.org 70 i 458 } Err bitreich.org 70 i 459 Err bitreich.org 70 i 460 void Err bitreich.org 70 i 461 run(void) Err bitreich.org 70 i 462 { Err bitreich.org 70 i 463 XEvent ev; Err bitreich.org 70 i 464 Err bitreich.org 70 i 465 /* main event loop */ Err bitreich.org 70 i 466 XSync(dpy, False); Err bitreich.org 70 i 467 while(running) { Err bitreich.org 70 i 468 XNextEvent(dpy, &ev); Err bitreich.org 70 i 469 if(handler[ev.type]) Err bitreich.org 70 i 470 (handler[ev.type])(&ev); /* call handler */ Err bitreich.org 70 i 471 } Err bitreich.org 70 i 472 } Err bitreich.org 70 i 473 Err bitreich.org 70 i 474 void Err bitreich.org 70 i 475 setup(void) Err bitreich.org 70 i 476 { Err bitreich.org 70 i 477 XSetWindowAttributes wa; Err bitreich.org 70 i 478 XTextProperty str; Err bitreich.org 70 i 479 XSizeHints *sizeh; Err bitreich.org 70 i 480 XClassHint *ch; Err bitreich.org 70 i 481 int i, sh, sw, ls; Err bitreich.org 70 i 482 Err bitreich.org 70 i 483 /* clean up any zombies immediately */ Err bitreich.org 70 i 484 sigchld(0); Err bitreich.org 70 i 485 Err bitreich.org 70 i 486 /* init screen */ Err bitreich.org 70 i 487 screen = DefaultScreen(dpy); Err bitreich.org 70 i 488 root = RootWindow(dpy, screen); Err bitreich.org 70 i 489 sw = DisplayWidth(dpy, screen) - 1; Err bitreich.org 70 i 490 sh = DisplayHeight(dpy, screen) - 1; Err bitreich.org 70 i 491 initfont(font); Err bitreich.org 70 i 492 Err bitreich.org 70 i 493 /* init atoms */ Err bitreich.org 70 i 494 Err bitreich.org 70 i 495 /* init appearance */ Err bitreich.org 70 i 496 Err bitreich.org 70 i 497 for (i = 0, www = 0; i < nentries; i++) { Err bitreich.org 70 i 498 ls = textnw(entries[i]->label, Err bitreich.org 70 i 499 strlen(entries[i]->label)); Err bitreich.org 70 i 500 if (ls > www) Err bitreich.org 70 i 501 www = ls; Err bitreich.org 70 i 502 } Err bitreich.org 70 i 503 www *= widthscaling; Err bitreich.org 70 i 504 Err bitreich.org 70 i 505 if (!ww) { Err bitreich.org 70 i 506 if (horizontal) { Err bitreich.org 70 i 507 ww = www * nentries; Err bitreich.org 70 i 508 } else { Err bitreich.org 70 i 509 ww = www; Err bitreich.org 70 i 510 } Err bitreich.org 70 i 511 } Err bitreich.org 70 i 512 if (!wh) { Err bitreich.org 70 i 513 if (horizontal) { Err bitreich.org 70 i 514 wh = dc.font.height * heightscaling; Err bitreich.org 70 i 515 } else { Err bitreich.org 70 i 516 wh = nentries * dc.font.height * heightscaling; Err bitreich.org 70 i 517 } Err bitreich.org 70 i 518 } Err bitreich.org 70 i 519 if (!wy) Err bitreich.org 70 i 520 wy = (sh - wh) / 2; Err bitreich.org 70 i 521 if (wy < 0) Err bitreich.org 70 i 522 wy = sh + wy - wh; Err bitreich.org 70 i 523 if (!wx) Err bitreich.org 70 i 524 wx = (sw - ww) / 2; Err bitreich.org 70 i 525 if (wx < 0) Err bitreich.org 70 i 526 wx = sw + wx - ww; Err bitreich.org 70 i 527 Err bitreich.org 70 i 528 dc.norm[ColBG] = getcolor(normbgcolor); Err bitreich.org 70 i 529 dc.norm[ColFG] = getcolor(normfgcolor); Err bitreich.org 70 i 530 dc.press[ColBG] = getcolor(pressbgcolor); Err bitreich.org 70 i 531 dc.press[ColFG] = getcolor(pressfgcolor); Err bitreich.org 70 i 532 dc.high[ColBG] = getcolor(highlightbgcolor); Err bitreich.org 70 i 533 dc.high[ColFG] = getcolor(highlightfgcolor); Err bitreich.org 70 i 534 Err bitreich.org 70 i 535 dc.drawable = XCreatePixmap(dpy, root, ww, wh, DefaultDepth(dpy, screen)); Err bitreich.org 70 i 536 dc.gc = XCreateGC(dpy, root, 0, 0); Err bitreich.org 70 i 537 if(!dc.font.set) Err bitreich.org 70 i 538 XSetFont(dpy, dc.gc, dc.font.xfont->fid); Err bitreich.org 70 i 539 for(i = 0; i < nentries; i++) Err bitreich.org 70 i 540 entries[i]->pressed = 0; Err bitreich.org 70 i 541 Err bitreich.org 70 i 542 wa.override_redirect = !wmborder; Err bitreich.org 70 i 543 wa.border_pixel = dc.norm[ColFG]; Err bitreich.org 70 i 544 wa.background_pixel = dc.norm[ColBG]; Err bitreich.org 70 i 545 win = XCreateWindow(dpy, root, wx, wy, ww, wh, 0, Err bitreich.org 70 i 546 CopyFromParent, CopyFromParent, CopyFromParent, Err bitreich.org 70 i 547 CWOverrideRedirect | CWBorderPixel | CWBackingPixel, &wa); Err bitreich.org 70 i 548 XSelectInput(dpy, win, StructureNotifyMask|KeyReleaseMask| Err bitreich.org 70 i 549 ButtonReleaseMask|ButtonPressMask| Err bitreich.org 70 i 550 ExposureMask|LeaveWindowMask|PointerMotionMask); Err bitreich.org 70 i 551 Err bitreich.org 70 i 552 sizeh = XAllocSizeHints(); Err bitreich.org 70 i 553 sizeh->flags = PMaxSize | PMinSize; Err bitreich.org 70 i 554 sizeh->min_width = sizeh->max_width = ww; Err bitreich.org 70 i 555 sizeh->min_height = sizeh->max_height = wh; Err bitreich.org 70 i 556 XStringListToTextProperty(&name, 1, &str); Err bitreich.org 70 i 557 ch = XAllocClassHint(); Err bitreich.org 70 i 558 ch->res_class = name; Err bitreich.org 70 i 559 ch->res_name = name; Err bitreich.org 70 i 560 Err bitreich.org 70 i 561 XSetWMProperties(dpy, win, &str, &str, NULL, 0, sizeh, NULL, Err bitreich.org 70 i 562 ch); Err bitreich.org 70 i 563 Err bitreich.org 70 i 564 XFree(ch); Err bitreich.org 70 i 565 XFree(str.value); Err bitreich.org 70 i 566 XFree(sizeh); Err bitreich.org 70 i 567 Err bitreich.org 70 i 568 XMapRaised(dpy, win); Err bitreich.org 70 i 569 updateentries(); Err bitreich.org 70 i 570 drawmenu(); Err bitreich.org 70 i 571 } Err bitreich.org 70 i 572 Err bitreich.org 70 i 573 void Err bitreich.org 70 i 574 sigchld(int unused) Err bitreich.org 70 i 575 { Err bitreich.org 70 i 576 if (signal(SIGCHLD, sigchld) == SIG_ERR) Err bitreich.org 70 i 577 die("can't install SIGCHLD handler:"); Err bitreich.org 70 i 578 while (0 < waitpid(-1, NULL, WNOHANG)); Err bitreich.org 70 i 579 } Err bitreich.org 70 i 580 Err bitreich.org 70 i 581 int Err bitreich.org 70 i 582 textnw(const char *text, uint len) Err bitreich.org 70 i 583 { Err bitreich.org 70 i 584 XRectangle r; Err bitreich.org 70 i 585 Err bitreich.org 70 i 586 if(dc.font.set) { Err bitreich.org 70 i 587 XmbTextExtents(dc.font.set, text, len, NULL, &r); Err bitreich.org 70 i 588 return r.width; Err bitreich.org 70 i 589 } Err bitreich.org 70 i 590 return XTextWidth(dc.font.xfont, text, len); Err bitreich.org 70 i 591 } Err bitreich.org 70 i 592 Err bitreich.org 70 i 593 void Err bitreich.org 70 i 594 runentry(Entry *e) Err bitreich.org 70 i 595 { Err bitreich.org 70 i 596 char *shell; Err bitreich.org 70 i 597 Err bitreich.org 70 i 598 if (oneshot || e->forceexit) Err bitreich.org 70 i 599 running = False; Err bitreich.org 70 i 600 Err bitreich.org 70 i 601 switch (fork()) { Err bitreich.org 70 i 602 case -1: Err bitreich.org 70 i 603 break; Err bitreich.org 70 i 604 case 0: Err bitreich.org 70 i 605 shell = getenv("SHELL"); Err bitreich.org 70 i 606 if (!shell) Err bitreich.org 70 i 607 shell = "/bin/sh"; Err bitreich.org 70 i 608 Err bitreich.org 70 i 609 execlp(shell, basename(shell), "-c", e->cmd, (char *)NULL); Err bitreich.org 70 i 610 break; Err bitreich.org 70 i 611 } Err bitreich.org 70 i 612 } Err bitreich.org 70 i 613 Err bitreich.org 70 i 614 void Err bitreich.org 70 i 615 press(Entry *e) Err bitreich.org 70 i 616 { Err bitreich.org 70 i 617 e->pressed = !e->pressed; Err bitreich.org 70 i 618 Err bitreich.org 70 i 619 drawentry(e); Err bitreich.org 70 i 620 } Err bitreich.org 70 i 621 Err bitreich.org 70 i 622 void Err bitreich.org 70 i 623 unpress(Entry *e) Err bitreich.org 70 i 624 { Err bitreich.org 70 i 625 int i; Err bitreich.org 70 i 626 Err bitreich.org 70 i 627 if (e != NULL) { Err bitreich.org 70 i 628 e->pressed = !e->pressed; Err bitreich.org 70 i 629 Err bitreich.org 70 i 630 runentry(e); Err bitreich.org 70 i 631 drawentry(e); Err bitreich.org 70 i 632 } else { Err bitreich.org 70 i 633 for(i = 0; i < nentries; i++) { Err bitreich.org 70 i 634 if(entries[i]->pressed) { Err bitreich.org 70 i 635 entries[i]->pressed = 0; Err bitreich.org 70 i 636 drawentry(entries[i]); Err bitreich.org 70 i 637 } Err bitreich.org 70 i 638 } Err bitreich.org 70 i 639 } Err bitreich.org 70 i 640 } Err bitreich.org 70 i 641 Err bitreich.org 70 i 642 void Err bitreich.org 70 i 643 updateentries(void) Err bitreich.org 70 i 644 { Err bitreich.org 70 i 645 int i, x, y, h, w; Err bitreich.org 70 i 646 Err bitreich.org 70 i 647 x = 0; Err bitreich.org 70 i 648 y = 0; Err bitreich.org 70 i 649 Err bitreich.org 70 i 650 if (horizontal) { Err bitreich.org 70 i 651 h = wh; Err bitreich.org 70 i 652 w = www; Err bitreich.org 70 i 653 } else { Err bitreich.org 70 i 654 h = wh / nentries; Err bitreich.org 70 i 655 w = ww; Err bitreich.org 70 i 656 } Err bitreich.org 70 i 657 for(i = 0; i < nentries; i++) { Err bitreich.org 70 i 658 entries[i]->x = x; Err bitreich.org 70 i 659 entries[i]->y = y; Err bitreich.org 70 i 660 entries[i]->w = w; Err bitreich.org 70 i 661 entries[i]->h = h; Err bitreich.org 70 i 662 if (horizontal) { Err bitreich.org 70 i 663 x += w; Err bitreich.org 70 i 664 } else { Err bitreich.org 70 i 665 y += h; Err bitreich.org 70 i 666 } Err bitreich.org 70 i 667 } Err bitreich.org 70 i 668 } Err bitreich.org 70 i 669 Err bitreich.org 70 i 670 void Err bitreich.org 70 i 671 usage(void) Err bitreich.org 70 i 672 { Err bitreich.org 70 i 673 fprintf(stderr, "usage: %s [-hnosx] [-g geometry] [-w widthscaling] " Err bitreich.org 70 i 674 "[-e heightscaling] [--] " Err bitreich.org 70 i 675 "label0 cmd0 [label1 cmd1 ...]\n", argv0); Err bitreich.org 70 i 676 exit(1); Err bitreich.org 70 i 677 } Err bitreich.org 70 i 678 Err bitreich.org 70 i 679 int Err bitreich.org 70 i 680 main(int argc, char *argv[]) Err bitreich.org 70 i 681 { Err bitreich.org 70 i 682 Bool addexit, usenumpad; Err bitreich.org 70 i 683 char *label, *cmd; Err bitreich.org 70 i 684 int i, xr, yr, bitm; Err bitreich.org 70 i 685 unsigned int wr, hr; Err bitreich.org 70 i 686 Err bitreich.org 70 i 687 argv0 = argv[0]; Err bitreich.org 70 i 688 Err bitreich.org 70 i 689 addexit = True; Err bitreich.org 70 i 690 usenumpad = False; Err bitreich.org 70 i 691 Err bitreich.org 70 i 692 if (argc < 2) Err bitreich.org 70 i 693 usage(); Err bitreich.org 70 i 694 Err bitreich.org 70 i 695 ARGBEGIN { Err bitreich.org 70 i 696 case 'g': Err bitreich.org 70 i 697 bitm = XParseGeometry(EARGF(usage()), &xr, &yr, &wr, &hr); Err bitreich.org 70 i 698 if (bitm & XValue) Err bitreich.org 70 i 699 wx = xr; Err bitreich.org 70 i 700 if (bitm & YValue) Err bitreich.org 70 i 701 wy = yr; Err bitreich.org 70 i 702 if (bitm & WidthValue) Err bitreich.org 70 i 703 ww = (int)wr; Err bitreich.org 70 i 704 if (bitm & HeightValue) Err bitreich.org 70 i 705 wh = (int)hr; Err bitreich.org 70 i 706 if (bitm & XNegative && wx == 0) Err bitreich.org 70 i 707 wx = -1; Err bitreich.org 70 i 708 if (bitm & YNegative && wy == 0) Err bitreich.org 70 i 709 wy = -1; Err bitreich.org 70 i 710 break; Err bitreich.org 70 i 711 case 'e': Err bitreich.org 70 i 712 heightscaling = atof(EARGF(usage())); Err bitreich.org 70 i 713 break; Err bitreich.org 70 i 714 case 'n': Err bitreich.org 70 i 715 usenumpad = True; Err bitreich.org 70 i 716 break; Err bitreich.org 70 i 717 case 'o': Err bitreich.org 70 i 718 horizontal = True; Err bitreich.org 70 i 719 break; Err bitreich.org 70 i 720 case 's': Err bitreich.org 70 i 721 oneshot = 0; Err bitreich.org 70 i 722 break; Err bitreich.org 70 i 723 case 'w': Err bitreich.org 70 i 724 widthscaling = atof(EARGF(usage())); Err bitreich.org 70 i 725 break; Err bitreich.org 70 i 726 case 'x': Err bitreich.org 70 i 727 addexit = False; Err bitreich.org 70 i 728 break; Err bitreich.org 70 i 729 default: Err bitreich.org 70 i 730 usage(); Err bitreich.org 70 i 731 } ARGEND; Err bitreich.org 70 i 732 Err bitreich.org 70 i 733 for (i = 0; argv[i]; i++) { Err bitreich.org 70 i 734 label = argv[i]; Err bitreich.org 70 i 735 if (!argv[i+1]) Err bitreich.org 70 i 736 break; Err bitreich.org 70 i 737 i++; Err bitreich.org 70 i 738 cmd = argv[i]; Err bitreich.org 70 i 739 Err bitreich.org 70 i 740 if (!(entries = realloc(entries, sizeof(entries[0])*(++nentries)))) Err bitreich.org 70 i 741 die("realloc returned NULL"); Err bitreich.org 70 i 742 if (!(entries[nentries-1] = calloc(1, sizeof(*entries[0])))) Err bitreich.org 70 i 743 die("calloc returned NULL"); Err bitreich.org 70 i 744 if (usenumpad == True && nentries < 11) { Err bitreich.org 70 i 745 if (!(asprintf(&entries[nentries-1]->label, Err bitreich.org 70 i 746 "%d:%s", nentries-1, strdup(label)))) { Err bitreich.org 70 i 747 die("asprintf returned NULL\n"); Err bitreich.org 70 i 748 } Err bitreich.org 70 i 749 } else { Err bitreich.org 70 i 750 if (!(entries[nentries-1]->label = strdup(label))) Err bitreich.org 70 i 751 die("strdup returned NULL\n"); Err bitreich.org 70 i 752 } Err bitreich.org 70 i 753 if (!(entries[nentries-1]->cmd = strdup(cmd))) Err bitreich.org 70 i 754 die("strdup returned NULL\n"); Err bitreich.org 70 i 755 entries[nentries-1]->forceexit = False; Err bitreich.org 70 i 756 } Err bitreich.org 70 i 757 if (nentries < 1) Err bitreich.org 70 i 758 usage(); Err bitreich.org 70 i 759 Err bitreich.org 70 i 760 if (addexit) { Err bitreich.org 70 i 761 if (!(entries = realloc(entries, sizeof(entries[0])*(++nentries)))) Err bitreich.org 70 i 762 die("realloc returned NULL"); Err bitreich.org 70 i 763 if (!(entries[nentries-1] = calloc(1, sizeof(*entries[0])))) Err bitreich.org 70 i 764 die("calloc returned NULL"); Err bitreich.org 70 i 765 if (usenumpad == True) { Err bitreich.org 70 i 766 if (!(entries[nentries-1]->label = strdup(".:cancel"))) Err bitreich.org 70 i 767 die("strdup returned NULL\n"); Err bitreich.org 70 i 768 } else { Err bitreich.org 70 i 769 if (!(entries[nentries-1]->label = strdup("cancel"))) Err bitreich.org 70 i 770 die("strdup returned NULL\n"); Err bitreich.org 70 i 771 } Err bitreich.org 70 i 772 if (!(entries[nentries-1]->cmd = strdup("exit"))) Err bitreich.org 70 i 773 die("strdup returned NULL\n"); Err bitreich.org 70 i 774 entries[nentries-1]->forceexit = True; Err bitreich.org 70 i 775 exitentry = nentries - 1; Err bitreich.org 70 i 776 } Err bitreich.org 70 i 777 Err bitreich.org 70 i 778 if(!setlocale(LC_CTYPE, "") || !XSupportsLocale()) Err bitreich.org 70 i 779 fprintf(stderr, "warning: no locale support\n"); Err bitreich.org 70 i 780 if(!(dpy = XOpenDisplay(0))) Err bitreich.org 70 i 781 die("thingmenu: cannot open display\n"); Err bitreich.org 70 i 782 Err bitreich.org 70 i 783 setup(); Err bitreich.org 70 i 784 run(); Err bitreich.org 70 i 785 cleanup(); Err bitreich.org 70 i 786 XCloseDisplay(dpy); Err bitreich.org 70 i 787 Err bitreich.org 70 i 788 for (i = 0; i < nentries; i++) { Err bitreich.org 70 i 789 free(entries[i]->label); Err bitreich.org 70 i 790 free(entries[i]->cmd); Err bitreich.org 70 i 791 free(entries[i]); Err bitreich.org 70 i 792 } Err bitreich.org 70 i 793 free(entries); Err bitreich.org 70 i 794 Err bitreich.org 70 i 795 return 0; Err bitreich.org 70 i 796 } Err bitreich.org 70 i 797 Err bitreich.org 70 .