summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-09-01 23:26:44 +0200
committerwm4 <wm4@nowhere>2013-09-01 23:27:33 +0200
commita5183a761c4456cbbd0d14e44f2136d476ab9eed (patch)
tree54f51092a593ac4c946bbc24fa784393a8a50542
parent71335183ecff94e3991c1835c301357a8ab27030 (diff)
downloadmpv-a5183a761c4456cbbd0d14e44f2136d476ab9eed.tar.bz2
mpv-a5183a761c4456cbbd0d14e44f2136d476ab9eed.tar.xz
x11: add window icon
The png file added to etc/ are taken from the link mentioned in commit 303096b, except that they have been converted to 16 bit, sRGB (with color profile info dropped, if there was one), and transparent pixels reset for better compression. The file x11_icon.bin is generated by gen-x11-icon.sh. I'm adding it to the git repo directly, because the script requires ImageMagick, and we don't want to make building even more complicated. The way how this is done is basically a compromise between effort required in x11_common.c and in gen-x11-icon.sh. Ideally, x11_icon.bin would be directly in the format as required by _NET_WM_ICON, but trying to write the binary width/height values from shell would probably be a nightmare, so here we go. The zlib code in x11_common.c is lifted from demux_mkv.c, with some modifications (like accepting a gzip header, because I don't know how to make gzip write raw compressed data).
-rw-r--r--.gitignore2
-rw-r--r--Makefile5
-rw-r--r--TOOLS/gen-x11-icon.sh15
-rw-r--r--etc/mpv-icon-8bit-16x16.pngbin0 -> 759 bytes
-rw-r--r--etc/mpv-icon-8bit-32x32.pngbin0 -> 2124 bytes
-rw-r--r--etc/mpv-icon-8bit-64x64.pngbin0 -> 5686 bytes
-rw-r--r--video/out/x11_common.c104
-rw-r--r--video/out/x11_common.h1
-rw-r--r--video/out/x11_icon.binbin0 -> 8486 bytes
9 files changed, 126 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index b38112e747..3dd965bfba 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,7 +14,7 @@
/tags
/TAGS
/video/out/gl_video_shaders.h
-/video/out/vdpau_template.c
+/video/out/x11_icon.inc
/demux/ebml_defs.c
/demux/ebml_types.h
/sub/osd_font.h
diff --git a/Makefile b/Makefile
index 440820b281..d40f890790 100644
--- a/Makefile
+++ b/Makefile
@@ -373,6 +373,10 @@ video/out/gl_video.c: video/out/gl_video_shaders.h
video/out/gl_video_shaders.h: TOOLS/file2string.pl video/out/gl_video_shaders.glsl
./$^ >$@
+video/out/x11_common.c: video/out/x11_icon.inc
+video/out/x11_icon.inc: TOOLS/file2string.pl video/out/x11_icon.bin
+ ./$^ >$@
+
sub/osd_libass.c: sub/osd_font.h
sub/osd_font.h: TOOLS/file2string.pl sub/osd_font.otf
./$^ >$@
@@ -446,6 +450,7 @@ clean:
-$(RM) video/out/vdpau_template.c
-$(RM) demux/ebml_types.h demux/ebml_defs.c
-$(RM) video/out/gl_video_shaders.h
+ -$(RM) video/out/x11_icon.inc
-$(RM) sub/osd_font.h
distclean: clean
diff --git a/TOOLS/gen-x11-icon.sh b/TOOLS/gen-x11-icon.sh
new file mode 100644
index 0000000000..0faf2c1f5e
--- /dev/null
+++ b/TOOLS/gen-x11-icon.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+# This script is expected to be called as TOOLS/gen-x11-icon.sh (it will access
+# etc/mpv-icon...), and it will write video/out/x11_icon.bin.
+
+conv() {
+ echo
+ identify -format "icon: %w %h" $1
+ convert $1 -depth 8 rgba:-
+}
+
+(echo "# File generated by gen-x11-icon.sh" ;
+ conv etc/mpv-icon-8bit-16x16.png ;
+ conv etc/mpv-icon-8bit-32x32.png ;
+ conv etc/mpv-icon-8bit-64x64.png) | gzip -c > video/out/x11_icon.bin
diff --git a/etc/mpv-icon-8bit-16x16.png b/etc/mpv-icon-8bit-16x16.png
new file mode 100644
index 0000000000..ac2cb81909
--- /dev/null
+++ b/etc/mpv-icon-8bit-16x16.png
Binary files differ
diff --git a/etc/mpv-icon-8bit-32x32.png b/etc/mpv-icon-8bit-32x32.png
new file mode 100644
index 0000000000..bfb5f9cf44
--- /dev/null
+++ b/etc/mpv-icon-8bit-32x32.png
Binary files differ
diff --git a/etc/mpv-icon-8bit-64x64.png b/etc/mpv-icon-8bit-64x64.png
new file mode 100644
index 0000000000..46bb33d88e
--- /dev/null
+++ b/etc/mpv-icon-8bit-64x64.png
Binary files differ
diff --git a/video/out/x11_common.c b/video/out/x11_common.c
index 00c0f7625d..af83c6a53e 100644
--- a/video/out/x11_common.c
+++ b/video/out/x11_common.c
@@ -66,6 +66,10 @@
#include <X11/XF86keysym.h>
#endif
+#if CONFIG_ZLIB
+#include <zlib.h>
+#endif
+
#include "mpvcore/input/input.h"
#include "mpvcore/input/keycodes.h"
@@ -128,6 +132,10 @@ typedef struct
long state;
} MotifWmHints;
+static const char x11_icon[] =
+#include "video/out/x11_icon.inc"
+;
+
static void vo_x11_update_geometry(struct vo *vo);
static void vo_x11_fullscreen(struct vo *vo);
static int vo_x11_get_fs_type(struct vo *vo);
@@ -371,6 +379,7 @@ static void init_atoms(struct vo_x11_state *x11)
XA_INIT(_NET_WM_PID);
XA_INIT(_NET_WM_NAME);
XA_INIT(_NET_WM_ICON_NAME);
+ XA_INIT(_NET_WM_ICON);
XA_INIT(_WIN_PROTOCOLS);
XA_INIT(_WIN_LAYER);
XA_INIT(_WIN_HINTS);
@@ -945,6 +954,100 @@ static void vo_x11_update_window_title(struct vo *vo)
vo_x11_set_property_utf8(vo, x11->XA_NET_WM_ICON_NAME, title);
}
+#if CONFIG_ZLIB
+static bstr decompress_gz(bstr in)
+{
+ bstr res = {0};
+ z_stream zstream;
+ uint8_t *dest;
+ size_t size = in.len;
+ int result;
+
+ zstream.zalloc = (alloc_func) 0;
+ zstream.zfree = (free_func) 0;
+ zstream.opaque = (voidpf) 0;
+ // 32 for gzip header, 15 for max. window bits
+ if (inflateInit2(&zstream, 32 + 15) != Z_OK)
+ goto error;
+ zstream.next_in = (Bytef *) in.start;
+ zstream.avail_in = size;
+
+ dest = NULL;
+ zstream.avail_out = size;
+ do {
+ size += 4000;
+ dest = talloc_realloc_size(NULL, dest, size);
+ zstream.next_out = (Bytef *) (dest + zstream.total_out);
+ result = inflate(&zstream, Z_NO_FLUSH);
+ if (result != Z_OK && result != Z_STREAM_END) {
+ talloc_free(dest);
+ dest = NULL;
+ inflateEnd(&zstream);
+ goto error;
+ }
+ zstream.avail_out += 4000;
+ } while (zstream.avail_out == 4000 && zstream.avail_in != 0
+ && result != Z_STREAM_END);
+
+ size = zstream.total_out;
+ inflateEnd(&zstream);
+
+ res.start = dest;
+ res.len = size;
+error:
+ return res;
+}
+#else
+static bstr decompress_gz(bstr in)
+{
+ return (bstr){0};
+}
+#endif
+
+#define MAX_ICONS 10
+
+static void vo_x11_set_wm_icon(struct vo_x11_state *x11)
+{
+ int num_icons = 0;
+ void *icon_data[MAX_ICONS];
+ int icon_w[MAX_ICONS], icon_h[MAX_ICONS];
+
+ bstr uncompressed = decompress_gz((bstr){(char *)x11_icon, sizeof(x11_icon)});
+ bstr data = uncompressed;
+ while (data.len && num_icons < MAX_ICONS) {
+ bstr line = bstr_getline(data, &data);
+ if (bstr_eatstart0(&line, "icon: ")) {
+ int w, h;
+ if (bstr_sscanf(line, "%d %d", &w, &h) == 2) {
+ int size = w * h * 4;
+ icon_w[num_icons] = w;
+ icon_h[num_icons] = h;
+ icon_data[num_icons] = data.start;
+ num_icons++;
+ data = bstr_cut(data, size);
+ }
+ }
+ }
+
+ size_t icon_size = 0;
+ for (int n = 0; n < num_icons; n++)
+ icon_size += sizeof(long) * (2 + icon_w[n] * icon_h[n]);
+ long *icon = talloc_array(NULL, long, icon_size);
+ long *cur = icon;
+ for (int n = 0; n < num_icons; n++) {
+ *cur++ = icon_w[n];
+ *cur++ = icon_h[n];
+ uint32_t *src = icon_data[n];
+ for (int i = 0; i < icon_h[n] * icon_w[n]; i++)
+ *cur++ = src[i];
+ }
+
+ XChangeProperty(x11->display, x11->window, x11->XA_NET_WM_ICON,
+ XA_CARDINAL, 32, PropModeReplace, (char *)icon, icon_size);
+ talloc_free(icon);
+ talloc_free(uncompressed.start);
+}
+
static void find_default_visual(struct vo_x11_state *x11, XVisualInfo *vis)
{
Display *display = x11->display;
@@ -994,6 +1097,7 @@ static void vo_x11_create_window(struct vo *vo, XVisualInfo *vis, int x, int y,
XNFocusWindow, x11->window,
NULL);
+ vo_x11_set_wm_icon(x11);
vo_x11_update_window_title(vo);
}
diff --git a/video/out/x11_common.h b/video/out/x11_common.h
index 53ca553a72..c2735ad82f 100644
--- a/video/out/x11_common.h
+++ b/video/out/x11_common.h
@@ -117,6 +117,7 @@ struct vo_x11_state {
Atom XA_NET_WM_PID;
Atom XA_NET_WM_NAME;
Atom XA_NET_WM_ICON_NAME;
+ Atom XA_NET_WM_ICON;
Atom XA_WIN_PROTOCOLS;
Atom XA_WIN_LAYER;
Atom XA_WIN_HINTS;
diff --git a/video/out/x11_icon.bin b/video/out/x11_icon.bin
new file mode 100644
index 0000000000..957d9fcffe
--- /dev/null
+++ b/video/out/x11_icon.bin
Binary files differ