Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,21 +1,24 @@
GLIB_CFLAGS=$(shell pkg-config --cflags glib-2.0)
GLIB_LIBS=$(shell pkg-config --libs glib-2.0)

MAGICKWAND_CFLAGS=$(shell pkg-config --cflags MagickWand)
MAGICKWAND_LIBS=$(shell pkg-config --libs MagickWand)

XLIB_CFLAGS=-I /usr/X11R6/include

XLIB_LIBS=-L /usr/X11R6/lib -lX11 -lXmu

GD_LIBS=-lgd

LIBS=${GLIB_LIBS} ${XLIB_LIBS} ${GD_LIBS}
LIBS=${GLIB_LIBS} ${MAGICKWAND_LIBS} ${XLIB_LIBS} ${GD_LIBS}

PREFIX=/usr/local
BINDIR=$(PREFIX)/bin

all: xseticon

xseticon.o: xseticon.c
gcc ${GLIB_CFLAGS} ${XLIB_CFLAGS} -c $^ -o $@
gcc ${GLIB_CFLAGS} ${MAGICKWAND_CFLAGS} ${XLIB_CFLAGS} -c $^ -o $@

xseticon: xseticon.o
gcc $^ ${LIBS} -o $@
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,20 @@ Xterm, and likely many other X11 programs, do not set themselves window icons, w

Usage
=====
usage: xseticon [options] path/to/icon.png
usage: xseticon [options] path/to/icon
options:
-name : apply icon to the window of the name supplied
-id : apply icon to the window id supplied

Sets the window icon to the specified .png image. The image is loaded from
Sets the window icon to the specified image. The image is loaded from
the file at runtime and sent to the X server; thereafter the file does not
need to exist, and can be deleted/renamed/modified without the X server or
window manager noticing.
If no window selection option is specified, the window can be interactively
selected using the cursor.

Hints:
xseticon -id "$WINDOWID" path/to/icon.png
xseticon -id "$WINDOWID" path/to/icon
Will set the icon for an xterm.xseticon from Paul Evans (http://www.leonerd.org.uk/).

Build and install instructions
Expand All @@ -25,7 +25,7 @@ On Ubuntu / Debian:

``` bash
# Install dependencies
sudo apt install libxmu-headers libgd-dev libxmu-dev libglib2.0-dev
sudo apt install libxmu-headers libgd-dev libxmu-dev libglib2.0-dev libmagickwand-dev
# Build
make
# Install
Expand All @@ -35,7 +35,7 @@ On EL7:

```bash
# Install dependencies
sudo yum install libXmu-devel gd gd-devel glib2-devel
sudo yum install libXmu-devel gd gd-devel glib2-devel ImageMagick-devel
# Build
make
# Install
Expand Down
67 changes: 40 additions & 27 deletions xseticon.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@
#include <glib.h>

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/cursorfont.h>
#include <X11/Xatom.h>
#include <X11/Xmu/WinUtil.h>
#include <MagickWand/MagickWand.h>

#include <gd.h>

Expand Down Expand Up @@ -134,11 +134,8 @@ Window Select_Window_Args(Display* dpy, int screen, int* rargc, char* argv[])
NXTOPT;
if (verbose)
printf("Selecting window by ID %s\n", OPTION);
w=0;
sscanf(OPTION, "0x%lx", &w);
if (!w)
sscanf(OPTION, "%ld", &w);
if (!w)
w = strtoul(OPTION, NULL, 0);
if (!w || (w == LONG_MIN || w == LONG_MAX))
Fatal_Error("Invalid window id format: %s.", OPTION);
continue;
}
Expand Down Expand Up @@ -201,25 +198,44 @@ void abortprog(gchar* fname)
exit(1);
}

/*
* Loads the filename with MagickWand and creates a gdImagePtr from it if the file is valid if not returns NULL
*/
gdImagePtr get_png_image_from_file(gchar *filename)
{
MagickWandGenesis(); // Starts MagickWand
gdImagePtr imagePtr = NULL; // Default value, if the image can't be loaded then the result is going to be NULL
MagickWand *wand = NewMagickWand();
PixelWand *pixelWand = NewPixelWand();
PixelSetColor(pixelWand, "transparent"); // Color for the background
MagickSetBackgroundColor(wand, pixelWand); // The background has to be assigned before loading the file image
// to avoid white backgrounds (happens with svg files)
MagickReadImage(wand, filename); // Reads the file
int success = MagickSetImageFormat(wand, "png"); // Converts the wand to PNG format
if (success) { // If the conversion is successful then it creates an imagePtr from the content of the wand
size_t length;
unsigned char *info = MagickGetImageBlob(wand, &length); // Gets image data and size from the wand
imagePtr = gdImageCreateFromPngPtr((int) length, info); // Creates imagePtr from png data
}
DestroyMagickWand(wand);
MagickWandTerminus(); // Ends MagickWand
return imagePtr;
}

/* Note:
* dispite the fact this routine specifically loads 32bit data, it needs to
* load it into an unsigned long int array, not a guint32 array. The
* XChangeProperty() call wants to see a native size array when format == 32,
* not necessarily a 32bit one.
*/

void load_icon(gchar* filename, int* ndata, CARD32** data)
{
FILE* iconfile = fopen(filename, "r");
gdImagePtr icon = get_png_image_from_file(filename);

if (!iconfile) {
abortprog("fopen()");
if (icon == NULL) {
abortprog("get_png_image_from_file(filename)");
}

gdImagePtr icon = gdImageCreateFromPng(iconfile);

fclose(iconfile);

int width, height;

width = gdImageSX(icon);
Expand Down Expand Up @@ -297,16 +313,13 @@ int main(int argc, char* argv[])
if (verbose)
printf("Selecting window by mouse...\n");
window = Select_Window_Mouse(display, screen);
if (window != None) {
Window root;
int dummyi;
unsigned int dummy;

if (XGetGeometry (display, window, &root, &dummyi, &dummyi,
&dummy, &dummy, &dummy, &dummy)
&& window != root)
window = XmuClientWindow (display, window);
}
Window root;
int dummyi;
unsigned int dummy;
if (XGetGeometry(display, window, &root, &dummyi, &dummyi,
&dummy, &dummy, &dummy, &dummy)
&& window != root)
window = XmuClientWindow(display, window);
}

if (verbose)
Expand All @@ -320,10 +333,10 @@ int main(int argc, char* argv[])
guint nelements;
CARD32* data;

load_icon(argv[argindex], &nelements, &data);
load_icon(argv[argindex], (int *) &nelements, &data);

int result = XChangeProperty(display, window, property, XA_CARDINAL, 32, PropModeReplace,
(gchar*)data, nelements);
int result = XChangeProperty(display, window, property, XA_CARDINAL, 32, PropModeReplace,
(guchar*) data, (int) nelements);

if(!result)
abortprog("XChangeProperty");
Expand Down