From 2bab59f760fbb510b0a8f0ba1c26671c8839304e Mon Sep 17 00:00:00 2001 From: aleks Date: Tue, 31 May 2022 00:16:17 +0200 Subject: [PATCH] Enable to set _NET_WM_ICON with a png-image Generally the icon of an application is defined by its desktop-entry. The patch desktopentry serves this purpose. Unfortunately, some programs like tint2 (https://gitlab.com/o9000/tint2) or alttab (https://github.com/sagb/alttab) can't make use of the desktop-entry and rely instead on a hardcoded icon which has to be defined by the application itself with the window-propery _NET_WM_ICON. Since st doesn't define _NET_WM_ICON this programs can't display the correct icon for st even if a desktop-entry exists. This patch solves this problem. The dependencies are gd and glib. By default each time st starts it will search for a file with the name st.png under /usr/local/share/pixmaps/. If you put an image with this name in the root-directory of the st-repository and call make install the image will be installed in /usr/local/share/pixmaps/ automatically. Otherwise you have to put the file there manually. If you use the desktopentry-patch you should adjust the icon in the file st.desktop by replacing the line *Icon=utilities-terminal* with *Icon=st*. Most programs which use the desktop-file to determine the icon should be able to find st.png under /usr/local/share/pixmaps/. If not report it to me and try changing in confing.mk the line *ICONPREFIX = $(PREFIX)/share/pixmaps* to *ICONPREFIX = $(PREFIX)/share/icons/hicolor/256x256/apps/* and install the icon there. The code for loading and transforming the image to an appropriate format is, except for minor modifications, from xseticon (https://www.leonerd.org.uk/code/xseticon/) which is developed by Paul Evans. --- Makefile | 3 +++ config.mk | 8 ++++++-- st.h | 5 +++-- x.c | 38 +++++++++++++++++++++++++++++++++++++- 4 files changed, 49 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 470ac86..96e27e3 100644 --- a/Makefile +++ b/Makefile @@ -49,9 +49,12 @@ install: st chmod 644 $(DESTDIR)$(MANPREFIX)/man1/st.1 tic -sx st.info @echo Please see the README file regarding the terminfo entry of st. + mkdir -p $(DESTDIR)$(ICONPREFIX) + [ -f $(ICONNAME) ] && cp -f $(ICONNAME) $(DESTDIR)$(ICONPREFIX) || : uninstall: rm -f $(DESTDIR)$(PREFIX)/bin/st rm -f $(DESTDIR)$(MANPREFIX)/man1/st.1 + rm -f $(DESTDIR)$(ICONPREFIX)/$(ICONNAME) .PHONY: all options clean dist install uninstall diff --git a/config.mk b/config.mk index 4c4c5d5..7af8ab7 100644 --- a/config.mk +++ b/config.mk @@ -6,6 +6,8 @@ VERSION = 0.8.5 # paths PREFIX = /usr/local MANPREFIX = $(PREFIX)/share/man +ICONPREFIX = $(PREFIX)/share/pixmaps +ICONNAME = st.png X11INC = /usr/X11R6/include X11LIB = /usr/X11R6/lib @@ -14,14 +16,16 @@ PKG_CONFIG = pkg-config # includes and libs INCS = -I$(X11INC) \ + `$(PKG_CONFIG) --cflags glib-2.0` \ `$(PKG_CONFIG) --cflags fontconfig` \ `$(PKG_CONFIG) --cflags freetype2` -LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft \ +LIBS = -L$(X11LIB) -lm -lrt -lX11 -lutil -lXft -lgd \ + `$(PKG_CONFIG) --libs glib-2.0` \ `$(PKG_CONFIG) --libs fontconfig` \ `$(PKG_CONFIG) --libs freetype2` # flags -STCPPFLAGS = -DVERSION=\"$(VERSION)\" -D_XOPEN_SOURCE=600 +STCPPFLAGS = -DVERSION=\"$(VERSION)\" -DICON=\"$(ICONPREFIX)/$(ICONNAME)\" -D_XOPEN_SOURCE=600 STCFLAGS = $(INCS) $(STCPPFLAGS) $(CPPFLAGS) $(CFLAGS) STLDFLAGS = $(LIBS) $(LDFLAGS) diff --git a/st.h b/st.h index 519b9bd..0f6e7d4 100644 --- a/st.h +++ b/st.h @@ -3,9 +3,10 @@ #include #include +#include +#include + /* macros */ -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define MAX(a, b) ((a) < (b) ? (b) : (a)) #define LEN(a) (sizeof(a) / sizeof(a)[0]) #define BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b)) #define DIVCEIL(n, d) (((n) + ((d) - 1)) / (d)) diff --git a/x.c b/x.c index 8a16faa..84a1e31 100644 --- a/x.c +++ b/x.c @@ -77,6 +77,8 @@ typedef XftDraw *Draw; typedef XftColor Color; typedef XftGlyphFontSpec GlyphFontSpec; +typedef unsigned long int CARD32; + /* Purely graphic info */ typedef struct { int tw, th; /* tty width and height */ @@ -93,7 +95,7 @@ typedef struct { Window win; Drawable buf; GlyphFontSpec *specbuf; /* font spec buffer used for rendering */ - Atom xembed, wmdeletewin, netwmname, netwmiconname, netwmpid; + Atom xembed, wmdeletewin, netwmname, netwmicon, netwmiconname, netwmpid; struct { XIM xim; XIC xic; @@ -1204,6 +1206,40 @@ xinit(int cols, int rows) xw.netwmiconname = XInternAtom(xw.dpy, "_NET_WM_ICON_NAME", False); XSetWMProtocols(xw.dpy, xw.win, &xw.wmdeletewin, 1); + /* use a png-image to set _NET_WM_ICON */ + FILE* file = fopen(ICON, "r"); + if (file) { + /* inititialize variables */ + const gdImagePtr icon_rgba = gdImageCreateFromPng(file); + fclose(file); + const int width = gdImageSX(icon_rgba); + const int height = gdImageSY(icon_rgba); + const int icon_n = width * height + 2; + CARD32 *icon_argb = g_new0(CARD32, icon_n); + /* set width and height of the icon */ + int i = 0; + icon_argb[i++] = width; + icon_argb[i++] = height; + /* RGBA -> ARGB */ + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + const int pixel_rgba = gdImageGetPixel(icon_rgba, x, y); + guint8* pixel_argb = (guint8*) &icon_argb[i++]; + pixel_argb[0] = gdImageBlue(icon_rgba, pixel_rgba); + pixel_argb[1] = gdImageGreen(icon_rgba, pixel_rgba); + pixel_argb[2] = gdImageRed(icon_rgba, pixel_rgba); + /* scale alpha from 0-127 to 0-255 */ + const int alpha = 127 - gdImageAlpha(icon_rgba, pixel_rgba); + pixel_argb[3] = alpha == 127 ? 255 : alpha * 2; + } + } + gdImageDestroy(icon_rgba); + /* set _NET_WM_ICON */ + xw.netwmicon = XInternAtom(xw.dpy, "_NET_WM_ICON", False); + XChangeProperty(xw.dpy, xw.win, xw.netwmicon, XA_CARDINAL, 32, + PropModeReplace, (uchar *)icon_argb, icon_n); + } + xw.netwmpid = XInternAtom(xw.dpy, "_NET_WM_PID", False); XChangeProperty(xw.dpy, xw.win, xw.netwmpid, XA_CARDINAL, 32, PropModeReplace, (uchar *)&thispid, 1); -- 2.36.1