sites

public wiki contents of suckless.org
git clone git://git.suckless.org/sites
Log | Files | Refs

commit ee503e94ee7ddd2e8442c129d9b625b16435da64
parent 0b6b2f7a3634bf800f962b2dda581837c73f9acf
Author: Mikau <mikau@aaathats3as.com>
Date:   Sat,  5 Sep 2020 12:34:53 +0200

New patch for tabbed that adds an icon

This patch adds an icon to the tabbed window. This icon gets set to to
the currently selected tab's icon, or a default icon if none exists.

Diffstat:
Atools.suckless.org/tabbed/patches/icon/index.md | 18++++++++++++++++++
Atools.suckless.org/tabbed/patches/icon/tabbed-icon-20200905-2da4e96.diff | 210+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 228 insertions(+), 0 deletions(-)

diff --git a/tools.suckless.org/tabbed/patches/icon/index.md b/tools.suckless.org/tabbed/patches/icon/index.md @@ -0,0 +1,18 @@ +Icon +==== + +Description +----------- +This patch gives tabbed an icon. This icon is the currently selected tab's icon. +If the selected tab has no icon (or no tab is selected), use a (admittedly ugly) default icon. + +This patch supports both the new EWMH (\_NET\_WM\_ICON) and +legacy ICCCM (WM\_ICON) ways of setting a window's icon. + +Download +-------- +* [tabbed-icon-20200905-2da4e96.diff](tabbed-icon-20200905-2da4e96.diff) + +Author +------ +* Mikau - <mikau_AT_aaathats3as.com> diff --git a/tools.suckless.org/tabbed/patches/icon/tabbed-icon-20200905-2da4e96.diff b/tools.suckless.org/tabbed/patches/icon/tabbed-icon-20200905-2da4e96.diff @@ -0,0 +1,210 @@ +diff --git a/Makefile b/Makefile +index 1b95d15..e571818 100644 +--- a/Makefile ++++ b/Makefile +@@ -37,7 +37,7 @@ dist: clean + @echo creating dist tarball + @mkdir -p tabbed-${VERSION} + @cp -R LICENSE Makefile README config.def.h config.mk \ +- tabbed.1 arg.h ${SRC} tabbed-${VERSION} ++ tabbed.1 arg.h icon.h ${SRC} tabbed-${VERSION} + @tar -cf tabbed-${VERSION}.tar tabbed-${VERSION} + @gzip tabbed-${VERSION}.tar + @rm -rf tabbed-${VERSION} +diff --git a/TODO b/TODO +index 8e1986d..dbcb930 100644 +--- a/TODO ++++ b/TODO +@@ -1,4 +1,3 @@ + # TODO + * add some way to detach windows + * add some way to attach windows +- +diff --git a/icon.h b/icon.h +new file mode 100644 +index 0000000..e2ef631 +--- /dev/null ++++ b/icon.h +@@ -0,0 +1,41 @@ ++/* GIMP RGBA C-Source image dump (icon.c) */ ++ ++#define ICON_WIDTH (16) ++#define ICON_HEIGHT (16) ++#define ICON_BYTES_PER_PIXEL (4) /* 2:RGB16, 3:RGB, 4:RGBA */ ++#define ICON_COMMENT \ ++ "GIMP -> Export -> C-Source -> Prefixed name = ICON, Use macros, Save alpha" ++#define ICON_PIXEL_DATA ((unsigned char*) ICON_pixel_data) ++static const unsigned char ICON_pixel_data[16 * 16 * 4 + 1] = ++("\000\000\000\377\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\000\000\000\000\000\000\000\000\000\000" ++ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\000\000" ++ "\000\377\000\000\000\000\000\000\000\000\000\000\000\377\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" ++ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\000\000\000\377\000\000\000" ++ "\000\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" ++ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000" ++ "\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377" ++ "\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000" ++ "\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377" ++ "\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000" ++ "\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377" ++ "\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000" ++ "\000\377\000\000\000\377\000\000\000\000\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\000\000\000\000\000\000\000" ++ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\000\000" ++ "\000\377\000\000\000\000\000\000\000\000\000\000\000\377\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" ++ "\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377" ++ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377" ++ "\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\377\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000" ++ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\000\000\000\377\000" ++ "\000\000\377\000\000\000\000\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377" ++ "\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000" ++ "\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377" ++ "\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000" ++ "\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377" ++ "\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000" ++ "\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\377\000\000\000\000" ++ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" ++ "\000\000\377\000\000\000\377\000\000\000\377\000\000\000\000\000\000\000\377\000\000\000\377\000\000\000\000\000\000\000\001\000" ++ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\000" ++ "\000\000\377\000\000\000\000\000\000\000\000\000\000\000\377\000\000\000\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" ++ "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\377\000\000\000\000\000\000\000" ++ "\000\000\000\000\000\000\000\000\377\000\000\000\377"); +diff --git a/tabbed.c b/tabbed.c +index eafe28a..ec6212e 100644 +--- a/tabbed.c ++++ b/tabbed.c +@@ -18,6 +18,7 @@ + #include <X11/Xft/Xft.h> + + #include "arg.h" ++#include "icon.h" + + /* XEMBED messages */ + #define XEMBED_EMBEDDED_NOTIFY 0 +@@ -49,7 +50,7 @@ + + enum { ColFG, ColBG, ColLast }; /* color */ + enum { WMProtocols, WMDelete, WMName, WMState, WMFullscreen, +- XEmbed, WMSelectTab, WMLast }; /* default atoms */ ++ XEmbed, WMSelectTab, WMIcon, WMLast }; /* default atoms */ + + typedef union { + int i; +@@ -135,6 +136,7 @@ static void updatenumlockmask(void); + static void updatetitle(int c); + static int xerror(Display *dpy, XErrorEvent *ee); + static void xsettitle(Window w, const char *str); ++static void xseticon(void); + + /* variables */ + static int screen; +@@ -169,6 +171,7 @@ static char winid[64]; + static char **cmd; + static char *wmname = "tabbed"; + static const char *geometry; ++static unsigned long icon[ICON_WIDTH * ICON_HEIGHT + 2]; + + char *argv0; + +@@ -455,6 +458,8 @@ focus(int c) + n += snprintf(&buf[n], sizeof(buf) - n, " %s", cmd[i]); + + xsettitle(win, buf); ++ XChangeProperty(dpy, win, wmatom[WMIcon], XA_CARDINAL, 32, ++ PropModeReplace, (unsigned char *) icon, ICON_WIDTH * ICON_HEIGHT + 2); + XRaiseWindow(dpy, win); + + return; +@@ -474,6 +479,7 @@ focus(int c) + lastsel = sel; + sel = c; + } ++ xseticon(); + + if (clients[c]->urgent && (wmh = XGetWMHints(dpy, clients[c]->win))) { + wmh->flags &= ~XUrgencyHint; +@@ -868,9 +874,13 @@ propertynotify(const XEvent *e) + } + } + XFree(wmh); ++ if (c == sel) ++ xseticon(); + } else if (ev->state != PropertyDelete && ev->atom == XA_WM_NAME && + (c = getclient(ev->window)) > -1) { + updatetitle(c); ++ } else if (ev->atom == wmatom[WMIcon] && (c = getclient(ev->window)) > -1 && c == sel) { ++ xseticon(); + } + } + +@@ -995,6 +1005,7 @@ setup(void) + wmatom[WMSelectTab] = XInternAtom(dpy, "_TABBED_SELECT_TAB", False); + wmatom[WMState] = XInternAtom(dpy, "_NET_WM_STATE", False); + wmatom[XEmbed] = XInternAtom(dpy, "_XEMBED", False); ++ wmatom[WMIcon] = XInternAtom(dpy, "_NET_WM_ICON", False); + + /* init appearance */ + wx = 0; +@@ -1074,6 +1085,17 @@ setup(void) + snprintf(winid, sizeof(winid), "%lu", win); + setenv("XEMBED", winid, 1); + ++ /* change icon from RGBA to ARGB */ ++ icon[0] = ICON_WIDTH; ++ icon[1] = ICON_HEIGHT; ++ for (int i = 0; i < ICON_WIDTH * ICON_HEIGHT; ++i) { ++ icon[i + 2] = ++ ICON_PIXEL_DATA[i * 4 + 3] << 24 | ++ ICON_PIXEL_DATA[i * 4 + 0] << 0 | ++ ICON_PIXEL_DATA[i * 4 + 1] << 8 | ++ ICON_PIXEL_DATA[i * 4 + 2] << 16 ; ++ } ++ + nextfocus = foreground; + focus(-1); + } +@@ -1265,6 +1287,46 @@ xsettitle(Window w, const char *str) + } + } + ++void ++xseticon(void) ++{ ++ Atom ret_type; ++ XWMHints *wmh, *cwmh; ++ int ret_format; ++ unsigned long ret_nitems, ret_nleft; ++ long offset = 0L; ++ unsigned char *data; ++ ++ wmh = XGetWMHints(dpy, win); ++ wmh->flags &= ~(IconPixmapHint | IconMaskHint); ++ wmh->icon_pixmap = wmh->icon_mask = None; ++ ++ ++ if (XGetWindowProperty(dpy, clients[sel]->win, wmatom[WMIcon], offset, LONG_MAX, False, ++ XA_CARDINAL, &ret_type, &ret_format, &ret_nitems, ++ &ret_nleft, &data) == Success && ++ ret_type == XA_CARDINAL && ret_format == 32) ++ { ++ XChangeProperty(dpy, win, wmatom[WMIcon], XA_CARDINAL, 32, ++ PropModeReplace, data, ret_nitems); ++ } else if ((cwmh = XGetWMHints(dpy, clients[sel]->win)) && cwmh->flags & IconPixmapHint) { ++ XDeleteProperty(dpy, win, wmatom[WMIcon]); ++ wmh->flags |= IconPixmapHint; ++ wmh->icon_pixmap = cwmh->icon_pixmap; ++ if (cwmh->flags & IconMaskHint) { ++ wmh->flags |= IconMaskHint; ++ wmh->icon_mask = cwmh->icon_mask; ++ } ++ XFree(cwmh); ++ } else { ++ XChangeProperty(dpy, win, wmatom[WMIcon], XA_CARDINAL, 32, ++ PropModeReplace, (unsigned char *) icon, ICON_WIDTH * ICON_HEIGHT + 2); ++ } ++ XSetWMHints(dpy, win, wmh); ++ XFree(wmh); ++ XFree(data); ++} ++ + void + usage(void) + {