| tabbed-icon-20200905-2da4e96.diff - sites - public wiki contents of suckless.org | |
| git clone git://git.suckless.org/sites | |
| Log | |
| Files | |
| Refs | |
| --- | |
| tabbed-icon-20200905-2da4e96.diff (9398B) | |
| --- | |
| 1 diff --git a/Makefile b/Makefile | |
| 2 index 1b95d15..e571818 100644 | |
| 3 --- a/Makefile | |
| 4 +++ b/Makefile | |
| 5 @@ -37,7 +37,7 @@ dist: clean | |
| 6 @echo creating dist tarball | |
| 7 @mkdir -p tabbed-${VERSION} | |
| 8 @cp -R LICENSE Makefile README config.def.h config.mk \ | |
| 9 - tabbed.1 arg.h ${SRC} tabbed-${VERSION} | |
| 10 + tabbed.1 arg.h icon.h ${SRC} tabbed-${VERSION} | |
| 11 @tar -cf tabbed-${VERSION}.tar tabbed-${VERSION} | |
| 12 @gzip tabbed-${VERSION}.tar | |
| 13 @rm -rf tabbed-${VERSION} | |
| 14 diff --git a/TODO b/TODO | |
| 15 index 8e1986d..dbcb930 100644 | |
| 16 --- a/TODO | |
| 17 +++ b/TODO | |
| 18 @@ -1,4 +1,3 @@ | |
| 19 # TODO | |
| 20 * add some way to detach windows | |
| 21 * add some way to attach windows | |
| 22 - | |
| 23 diff --git a/icon.h b/icon.h | |
| 24 new file mode 100644 | |
| 25 index 0000000..e2ef631 | |
| 26 --- /dev/null | |
| 27 +++ b/icon.h | |
| 28 @@ -0,0 +1,41 @@ | |
| 29 +/* GIMP RGBA C-Source image dump (icon.c) */ | |
| 30 + | |
| 31 +#define ICON_WIDTH (16) | |
| 32 +#define ICON_HEIGHT (16) | |
| 33 +#define ICON_BYTES_PER_PIXEL (4) /* 2:RGB16, 3:RGB, 4:RGBA */ | |
| 34 +#define ICON_COMMENT \ | |
| 35 + "GIMP -> Export -> C-Source -> Prefixed name = ICON, Use macros, Save… | |
| 36 +#define ICON_PIXEL_DATA ((unsigned char*) ICON_pixel_data) | |
| 37 +static const unsigned char ICON_pixel_data[16 * 16 * 4 + 1] = | |
| 38 +("\000\000\000\377\000\000\000\377\000\000\000\000\000\000\000\000\000\… | |
| 39 + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\… | |
| 40 + "\000\377\000\000\000\000\000\000\000\000\000\000\000\377\000\000\000\… | |
| 41 + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\… | |
| 42 + "\000\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\000\… | |
| 43 + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\… | |
| 44 + "\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\… | |
| 45 + "\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\… | |
| 46 + "\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\… | |
| 47 + "\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\… | |
| 48 + "\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\… | |
| 49 + "\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\… | |
| 50 + "\000\377\000\000\000\377\000\000\000\000\000\000\000\377\000\000\000\… | |
| 51 + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\… | |
| 52 + "\000\377\000\000\000\000\000\000\000\000\000\000\000\377\000\000\000\… | |
| 53 + "\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\000\000\… | |
| 54 + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\000\… | |
| 55 + "\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\377\000\… | |
| 56 + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\… | |
| 57 + "\000\000\377\000\000\000\000\000\000\000\377\000\000\000\377\000\000\… | |
| 58 + "\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\… | |
| 59 + "\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\… | |
| 60 + "\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\… | |
| 61 + "\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\… | |
| 62 + "\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\… | |
| 63 + "\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\… | |
| 64 + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\… | |
| 65 + "\000\000\377\000\000\000\377\000\000\000\377\000\000\000\000\000\000\… | |
| 66 + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\… | |
| 67 + "\000\000\377\000\000\000\000\000\000\000\000\000\000\000\377\000\000\… | |
| 68 + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\… | |
| 69 + "\000\000\000\000\000\000\000\000\377\000\000\000\377"); | |
| 70 diff --git a/tabbed.c b/tabbed.c | |
| 71 index eafe28a..ec6212e 100644 | |
| 72 --- a/tabbed.c | |
| 73 +++ b/tabbed.c | |
| 74 @@ -18,6 +18,7 @@ | |
| 75 #include <X11/Xft/Xft.h> | |
| 76 | |
| 77 #include "arg.h" | |
| 78 +#include "icon.h" | |
| 79 | |
| 80 /* XEMBED messages */ | |
| 81 #define XEMBED_EMBEDDED_NOTIFY 0 | |
| 82 @@ -49,7 +50,7 @@ | |
| 83 | |
| 84 enum { ColFG, ColBG, ColLast }; /* color */ | |
| 85 enum { WMProtocols, WMDelete, WMName, WMState, WMFullscreen, | |
| 86 - XEmbed, WMSelectTab, WMLast }; /* default atoms */ | |
| 87 + XEmbed, WMSelectTab, WMIcon, WMLast }; /* default atoms */ | |
| 88 | |
| 89 typedef union { | |
| 90 int i; | |
| 91 @@ -135,6 +136,7 @@ static void updatenumlockmask(void); | |
| 92 static void updatetitle(int c); | |
| 93 static int xerror(Display *dpy, XErrorEvent *ee); | |
| 94 static void xsettitle(Window w, const char *str); | |
| 95 +static void xseticon(void); | |
| 96 | |
| 97 /* variables */ | |
| 98 static int screen; | |
| 99 @@ -169,6 +171,7 @@ static char winid[64]; | |
| 100 static char **cmd; | |
| 101 static char *wmname = "tabbed"; | |
| 102 static const char *geometry; | |
| 103 +static unsigned long icon[ICON_WIDTH * ICON_HEIGHT + 2]; | |
| 104 | |
| 105 char *argv0; | |
| 106 | |
| 107 @@ -455,6 +458,8 @@ focus(int c) | |
| 108 n += snprintf(&buf[n], sizeof(buf) - n, " %s", … | |
| 109 | |
| 110 xsettitle(win, buf); | |
| 111 + XChangeProperty(dpy, win, wmatom[WMIcon], XA_CARDINAL, … | |
| 112 + PropModeReplace, (unsigned char *) icon… | |
| 113 XRaiseWindow(dpy, win); | |
| 114 | |
| 115 return; | |
| 116 @@ -474,6 +479,7 @@ focus(int c) | |
| 117 lastsel = sel; | |
| 118 sel = c; | |
| 119 } | |
| 120 + xseticon(); | |
| 121 | |
| 122 if (clients[c]->urgent && (wmh = XGetWMHints(dpy, clients[c]->w… | |
| 123 wmh->flags &= ~XUrgencyHint; | |
| 124 @@ -868,9 +874,13 @@ propertynotify(const XEvent *e) | |
| 125 } | |
| 126 } | |
| 127 XFree(wmh); | |
| 128 + if (c == sel) | |
| 129 + xseticon(); | |
| 130 } else if (ev->state != PropertyDelete && ev->atom == XA_WM_NAM… | |
| 131 (c = getclient(ev->window)) > -1) { | |
| 132 updatetitle(c); | |
| 133 + } else if (ev->atom == wmatom[WMIcon] && (c = getclient(ev->win… | |
| 134 + xseticon(); | |
| 135 } | |
| 136 } | |
| 137 | |
| 138 @@ -995,6 +1005,7 @@ setup(void) | |
| 139 wmatom[WMSelectTab] = XInternAtom(dpy, "_TABBED_SELECT_TAB", Fa… | |
| 140 wmatom[WMState] = XInternAtom(dpy, "_NET_WM_STATE", False); | |
| 141 wmatom[XEmbed] = XInternAtom(dpy, "_XEMBED", False); | |
| 142 + wmatom[WMIcon] = XInternAtom(dpy, "_NET_WM_ICON", False); | |
| 143 | |
| 144 /* init appearance */ | |
| 145 wx = 0; | |
| 146 @@ -1074,6 +1085,17 @@ setup(void) | |
| 147 snprintf(winid, sizeof(winid), "%lu", win); | |
| 148 setenv("XEMBED", winid, 1); | |
| 149 | |
| 150 + /* change icon from RGBA to ARGB */ | |
| 151 + icon[0] = ICON_WIDTH; | |
| 152 + icon[1] = ICON_HEIGHT; | |
| 153 + for (int i = 0; i < ICON_WIDTH * ICON_HEIGHT; ++i) { | |
| 154 + icon[i + 2] = | |
| 155 + ICON_PIXEL_DATA[i * 4 + 3] << 24 | | |
| 156 + ICON_PIXEL_DATA[i * 4 + 0] << 0 | | |
| 157 + ICON_PIXEL_DATA[i * 4 + 1] << 8 | | |
| 158 + ICON_PIXEL_DATA[i * 4 + 2] << 16 ; | |
| 159 + } | |
| 160 + | |
| 161 nextfocus = foreground; | |
| 162 focus(-1); | |
| 163 } | |
| 164 @@ -1265,6 +1287,46 @@ xsettitle(Window w, const char *str) | |
| 165 } | |
| 166 } | |
| 167 | |
| 168 +void | |
| 169 +xseticon(void) | |
| 170 +{ | |
| 171 + Atom ret_type; | |
| 172 + XWMHints *wmh, *cwmh; | |
| 173 + int ret_format; | |
| 174 + unsigned long ret_nitems, ret_nleft; | |
| 175 + long offset = 0L; | |
| 176 + unsigned char *data; | |
| 177 + | |
| 178 + wmh = XGetWMHints(dpy, win); | |
| 179 + wmh->flags &= ~(IconPixmapHint | IconMaskHint); | |
| 180 + wmh->icon_pixmap = wmh->icon_mask = None; | |
| 181 + | |
| 182 + | |
| 183 + if (XGetWindowProperty(dpy, clients[sel]->win, wmatom[WMIcon], … | |
| 184 + XA_CARDINAL, &ret_type, &ret_format, &re… | |
| 185 + &ret_nleft, &data) == Success && | |
| 186 + ret_type == XA_CARDINAL && ret_format == 32) | |
| 187 + { | |
| 188 + XChangeProperty(dpy, win, wmatom[WMIcon], XA_CARDINAL, … | |
| 189 + PropModeReplace, data, ret_nitems); | |
| 190 + } else if ((cwmh = XGetWMHints(dpy, clients[sel]->win)) && cwmh… | |
| 191 + XDeleteProperty(dpy, win, wmatom[WMIcon]); | |
| 192 + wmh->flags |= IconPixmapHint; | |
| 193 + wmh->icon_pixmap = cwmh->icon_pixmap; | |
| 194 + if (cwmh->flags & IconMaskHint) { | |
| 195 + wmh->flags |= IconMaskHint; | |
| 196 + wmh->icon_mask = cwmh->icon_mask; | |
| 197 + } | |
| 198 + XFree(cwmh); | |
| 199 + } else { | |
| 200 + XChangeProperty(dpy, win, wmatom[WMIcon], XA_CARDINAL, … | |
| 201 + PropModeReplace, (unsigned char *) icon… | |
| 202 + } | |
| 203 + XSetWMHints(dpy, win, wmh); | |
| 204 + XFree(wmh); | |
| 205 + XFree(data); | |
| 206 +} | |
| 207 + | |
| 208 void | |
| 209 usage(void) | |
| 210 { |