commit ee503e94ee7ddd2e8442c129d9b625b16435da64
Author: Mikau <[email protected]>
Date:   Sat Sep 5 12:34:53 2020 +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.

diff --git a/tools.suckless.org/tabbed/patches/icon/index.md 
b/tools.suckless.org/tabbed/patches/icon/index.md
new file mode 100644
index 00000000..8b5669ff
--- /dev/null
+++ 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
new file mode 100644
index 00000000..8b45b592
--- /dev/null
+++ 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] =
++("++ "++ "++ "++ "++ "++ "\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)
+ {


Reply via email to