slstatus

My fork of https://tools.suckless.org/slstatus/
git clone https://git.inz.fi/slstatus
Log | Files | Refs | README | LICENSE

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 }