wintitle.c (2028B)
1 /* See LICENSE file for copyright and license details. */ 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 #include <regex.h> 6 #include <X11/Xlib.h> 7 #include <X11/Xutil.h> 8 9 #include "../util.h" 10 11 static const char *getname(Window); 12 static const char *grepw(Window, const char *, int *); 13 const char *rematch(const regex_t *, const char *str, int *cl); 14 static Display *dpy = NULL; 15 static Atom netwmname; 16 17 const char * 18 rematch(const regex_t *re, const char *str, int *cl) 19 { 20 regmatch_t m[2]; 21 if (regexec(re, str, sizeof(m) / sizeof(*m), m, 0) || 22 m[1].rm_so == -1) 23 return NULL; 24 25 *cl = m[1].rm_eo - m[1].rm_so; 26 return str + m[1].rm_so; 27 } 28 29 const char * 30 wintitle(const char *arg) 31 { 32 int rl; 33 const char *rv; 34 35 if (!dpy) { 36 if (!(dpy = getdisplay())) { 37 warn("XOpenDisplay: Failed to open display"); 38 return NULL; 39 } 40 netwmname = XInternAtom(dpy, "_NET_WM_NAME", False); 41 } 42 43 rv = grepw(DefaultRootWindow(dpy), arg, &rl); 44 45 if (!rv) 46 return NULL; 47 48 return bprintf("%.*s", rl, rv); 49 } 50 51 const char * 52 grepw(Window win, const char *pattern, int *rl) { 53 unsigned int n; 54 Window *wins, *w, dw; 55 XWindowAttributes wa; 56 const char *rv = NULL; 57 regex_t re; 58 59 if (regcomp(&re, pattern, REG_EXTENDED)) 60 goto err1; 61 if(!XQueryTree(dpy, win, &dw, &dw, &wins, &n)) 62 goto err2; 63 for(w = &wins[n-1]; w >= &wins[0]; w--) 64 if(XGetWindowAttributes(dpy, *w, &wa) 65 && !wa.override_redirect && wa.map_state == IsViewable) 66 if ((rv = rematch(&re, getname(*w), rl))) 67 break; 68 69 err2: 70 XFree(wins); 71 err1: 72 regfree(&re); 73 74 return rv; 75 } 76 77 const char * 78 getname(Window win) { 79 static char buf[BUFSIZ]; 80 char **list; 81 int n; 82 XTextProperty prop; 83 84 if(!XGetTextProperty(dpy, win, &prop, netwmname) || prop.nitems == 0) 85 if(!XGetWMName(dpy, win, &prop) || prop.nitems == 0) 86 return ""; 87 if(!XmbTextPropertyToTextList(dpy, &prop, &list, &n) && n > 0) { 88 strncpy(buf, list[0], sizeof buf); 89 XFreeStringList(list); 90 } else 91 strncpy(buf, (char *)prop.value, sizeof buf); 92 XFree(prop.value); 93 buf[sizeof buf - 1] = '\0'; 94 return buf; 95 }