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 Binary files /dev/null and b/etc/mpv-icon-8bit-16x16.png differ diff --git a/etc/mpv-icon-8bit-32x32.png b/etc/mpv-icon-8bit-32x32.png new file mode 100644 index 0000000000..bfb5f9cf44 Binary files /dev/null and b/etc/mpv-icon-8bit-32x32.png differ diff --git a/etc/mpv-icon-8bit-64x64.png b/etc/mpv-icon-8bit-64x64.png new file mode 100644 index 0000000000..46bb33d88e Binary files /dev/null and b/etc/mpv-icon-8bit-64x64.png 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 #endif +#if CONFIG_ZLIB +#include +#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 Binary files /dev/null and b/video/out/x11_icon.bin differ