From a5183a761c4456cbbd0d14e44f2136d476ab9eed Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 1 Sep 2013 23:26:44 +0200 Subject: [PATCH] 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). --- .gitignore | 2 +- Makefile | 5 ++ TOOLS/gen-x11-icon.sh | 15 ++++++ etc/mpv-icon-8bit-16x16.png | Bin 0 -> 759 bytes etc/mpv-icon-8bit-32x32.png | Bin 0 -> 2124 bytes etc/mpv-icon-8bit-64x64.png | Bin 0 -> 5686 bytes video/out/x11_common.c | 104 ++++++++++++++++++++++++++++++++++++ video/out/x11_common.h | 1 + video/out/x11_icon.bin | Bin 0 -> 8486 bytes 9 files changed, 126 insertions(+), 1 deletion(-) create mode 100644 TOOLS/gen-x11-icon.sh create mode 100644 etc/mpv-icon-8bit-16x16.png create mode 100644 etc/mpv-icon-8bit-32x32.png create mode 100644 etc/mpv-icon-8bit-64x64.png create mode 100644 video/out/x11_icon.bin diff --git a/.gitignore b/.gitignore index b38112e747025..3dd965bfba0e4 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 440820b28165f..d40f89079024e 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 0000000000000..0faf2c1f5ee01 --- /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 0000000000000000000000000000000000000000..ac2cb819092adf71a87afcfdbcb9d4fb5ce8e1f7 GIT binary patch literal 759 zcmVkz=I zq*Trfpet#Gs_SE|AwQlksK|Fw_Ss8v_y_n4047zN1Kl%u9$_;S&mw>SGOz^#up>=Psou;=h@7PPf+@~^YJ85%}wjn z1Tb?^w)$cig%tfF7f)Sc|Bi!ncRfHU#f*9X3s_=h0MDuT9Rjv7rYaDWiufg;pj^Z* zTSQ@m)*7R$7=(c307e;=cf`p)?tWVRv_eoonTR!;SFv_m8@6kswPvvQ1pvyZJYXCk zDu#Yn(wmqa?0?4nYkjn=n8VD4&1~BH3-wbcRlDlB@re9j4uE3lcL9+NSQ5$WDT&k; zL7bk>K2q5f>vpXsmZ+&(*?03l&K*3DQVN3!9*y+=@irP6k_t?9%j#F|P9+)-j1QP@ zp3aPxG}>sM_q-(cY^X})tFe5?t&!`;fzff4Cje8H*0t_vtew^&NX>Up4)TTEf!m{< zr-9c%X&hw@lyk-B1AgFNi@9-eEGKD+6$4bHqoEJw_ZRv`9&|h`+`kMA1EnvQNdON> p0uzA*;C^P=81Mo32$aXy`V($oInG4hZ3h4V002ovPDHLkV1h@yWzYZs literal 0 HcmV?d00001 diff --git a/etc/mpv-icon-8bit-32x32.png b/etc/mpv-icon-8bit-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..bfb5f9cf4472774a73cbf5d27cc901d708939a8d GIT binary patch literal 2124 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 #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 53ca553a72d31..c2735ad82fa8d 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 0000000000000000000000000000000000000000..957d9fcffea2ee735606e04c4e32c9b78c458f49 GIT binary patch literal 8486 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 Uh278pKR=S^-vr|w0Z~){0D%>31poj5 literal 0 HcmV?d00001