190 lines
8.5 KiB
Diff
190 lines
8.5 KiB
Diff
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;
|
|
@@ -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)
|
|
{
|