summarylogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.SRCINFO36
-rw-r--r--PKGBUILD77
-rw-r--r--iconsupport.patch331
3 files changed, 444 insertions, 0 deletions
diff --git a/.SRCINFO b/.SRCINFO
new file mode 100644
index 000000000000..79102667cb08
--- /dev/null
+++ b/.SRCINFO
@@ -0,0 +1,36 @@
+pkgbase = i3-wm-iconpatch
+ pkgdesc = An improved dynamic tiling window manager (with titlebar icon patch)
+ pkgver = 4.10.2
+ pkgrel = 1
+ url = http://i3wm.org/
+ arch = i686
+ arch = x86_64
+ groups = i3
+ license = BSD
+ makedepends = bison
+ makedepends = flex
+ makedepends = pkg-config
+ depends = xcb-util-cursor
+ depends = xcb-util-keysyms
+ depends = xcb-util-wm
+ depends = libev
+ depends = yajl
+ depends = startup-notification
+ depends = pango
+ depends = libxkbcommon-x11
+ optdepends = dmenu: As menu.
+ optdepends = i3lock: For locking your screen.
+ optdepends = i3status: To display systeminformation with a bar.
+ provides = i3-wm
+ conflicts = i3-wm
+ options = docs
+ options = !strip
+ source = http://i3wm.org/downloads/i3-4.10.2.tar.bz2
+ source = http://i3wm.org/downloads/i3-4.10.2.tar.bz2.asc
+ source = iconsupport.patch
+ sha1sums = dc50d112645b9838d05e5864dc09a160c4cec8a1
+ sha1sums = SKIP
+ sha1sums = 054a91ad3d83cfc01e2d02c90fda524f49616ebd
+
+pkgname = i3-wm-iconpatch
+
diff --git a/PKGBUILD b/PKGBUILD
new file mode 100644
index 000000000000..6b122d7ec49d
--- /dev/null
+++ b/PKGBUILD
@@ -0,0 +1,77 @@
+# Upstream Maintainer (i3-wm): Thorsten Töpper <atsutane-tu@freethoughts.de>
+# Patch Contributor: Marius Muja <mariusm@cs.ubc.ca>
+# Package Maintainer: cornholio <vigo.the.unholy.carpathian@gmail.com>
+
+pkgname=i3-wm-iconpatch
+_pkgsourcename=i3
+pkgver=4.10.2
+pkgrel=1
+pkgdesc='An improved dynamic tiling window manager (with titlebar icon patch)'
+arch=('i686' 'x86_64')
+url='http://i3wm.org/'
+license=('BSD')
+provides=('i3-wm')
+conflicts=('i3-wm')
+groups=('i3')
+depends=('xcb-util-cursor' 'xcb-util-keysyms' 'xcb-util-wm' 'libev' 'yajl'
+ 'startup-notification' 'pango' 'libxkbcommon-x11')
+makedepends=('bison' 'flex' 'pkg-config')
+optdepends=('dmenu: As menu.'
+ 'i3lock: For locking your screen.'
+ 'i3status: To display systeminformation with a bar.')
+options=('docs' '!strip')
+source=("http://i3wm.org/downloads/${_pkgsourcename}-${pkgver}.tar.bz2"
+ "http://i3wm.org/downloads/${_pkgsourcename}-${pkgver}.tar.bz2.asc"
+ "iconsupport.patch")
+sha1sums=('dc50d112645b9838d05e5864dc09a160c4cec8a1'
+ 'SKIP'
+ '054a91ad3d83cfc01e2d02c90fda524f49616ebd')
+
+build() {
+ cd "$srcdir/$_pkgsourcename-$pkgver"
+
+ # Apply icon titlebar patch
+ patch -p1 < "$srcdir/iconsupport.patch"
+
+ # In order to avoid problems with bison use only a single process
+ MAKEFLAGS="-j1"
+ make
+}
+
+package() {
+ cd "$srcdir/$_pkgsourcename-$pkgver"
+
+ make DESTDIR="$pkgdir/" install
+
+ install -Dm644 man/i3.1 \
+ ${pkgdir}/usr/share/man/man1/i3.1
+ install -Dm644 man/i3bar.1 \
+ ${pkgdir}/usr/share/man/man1/i3bar.1
+ install -Dm644 man/i3-config-wizard.1 \
+ ${pkgdir}/usr/share/man/man1/i3-config-wizard.1
+ install -Dm644 man/i3-input.1 \
+ ${pkgdir}/usr/share/man/man1/i3-input.1
+ install -Dm644 man/i3-msg.1 \
+ ${pkgdir}/usr/share/man/man1/i3-msg.1
+ install -Dm644 man/i3-migrate-config-to-v4.1 \
+ ${pkgdir}/usr/share/man/man1/i3-migrate-config-to-v4.1
+ install -Dm644 man/i3-nagbar.1 \
+ ${pkgdir}/usr/share/man/man1/i3-nagbar.1
+ install -Dm644 man/i3-dmenu-desktop.1 \
+ ${pkgdir}/usr/share/man/man1/i3-dmenu-desktop.1
+ install -Dm644 man/i3-dump-log.1 \
+ ${pkgdir}/usr/share/man/man1/i3-dump-log.1
+ install -Dm644 man/i3-sensible-editor.1 \
+ ${pkgdir}/usr/share/man/man1/i3-sensible-editor.1
+ install -Dm644 man/i3-sensible-pager.1 \
+ ${pkgdir}/usr/share/man/man1/i3-sensible-pager.1
+ install -Dm644 man/i3-sensible-terminal.1 \
+ ${pkgdir}/usr/share/man/man1/i3-sensible-terminal.1
+
+ install -Dm644 LICENSE \
+ ${pkgdir}/usr/share/licenses/${pkgname}/LICENSE
+
+ make clean
+}
+
+# vim:set ts=2 sw=2 et:
diff --git a/iconsupport.patch b/iconsupport.patch
new file mode 100644
index 000000000000..476b1566cae5
--- /dev/null
+++ b/iconsupport.patch
@@ -0,0 +1,331 @@
+diff -rupN i3-4.8-original/common.mk i3-4.8-patched/common.mk
+--- i3-4.8-original/common.mk 2014-06-15 13:12:43.000000000 -0400
++++ i3-4.8-patched/common.mk 2014-06-16 08:18:43.263744935 -0400
+@@ -1,6 +1,7 @@
+ UNAME=$(shell uname)
+ DEBUG=1
+ COVERAGE=0
++USE_ICONS=1
+ INSTALL=install
+ LN=ln
+ ifndef PREFIX
+@@ -56,6 +57,9 @@ I3_CPPFLAGS += -DMINOR_VERSION=${MINOR_V
+ I3_CPPFLAGS += -DPATCH_VERSION=${PATCH_VERSION}
+ I3_CPPFLAGS += -DSYSCONFDIR=\"${SYSCONFDIR}\"
+ I3_CPPFLAGS += -DI3__FILE__=__FILE__
++ifeq ($(USE_ICONS),1)
++I3_CPPFLAGS += -DUSE_ICONS
++endif
+
+
+ ## Libraries flags
+@@ -104,6 +108,9 @@ XCB_WM_CFLAGS += $(call cflags_for_lib,
+ XCB_WM_LIBS := $(call ldflags_for_lib, xcb-icccm,xcb-icccm)
+ XCB_WM_LIBS += $(call ldflags_for_lib, xcb-xinerama,xcb-xinerama)
+ XCB_WM_LIBS += $(call ldflags_for_lib, xcb-randr,xcb-randr)
++ifeq ($(USE_ICONS),1)
++XCB_WM_LIBS += $(call ldflags_for_lib, xcb-image,xcb-image)
++endif
+
+ # Xlib
+ X11_CFLAGS := $(call cflags_for_lib, x11)
+diff -rupN i3-4.8-original/include/atoms.xmacro i3-4.8-patched/include/atoms.xmacro
+--- i3-4.8-original/include/atoms.xmacro 2014-06-15 13:12:43.000000000 -0400
++++ i3-4.8-patched/include/atoms.xmacro 2014-06-16 08:18:43.267078172 -0400
+@@ -19,6 +19,7 @@ xmacro(_NET_CURRENT_DESKTOP)
+ xmacro(_NET_ACTIVE_WINDOW)
+ xmacro(_NET_STARTUP_ID)
+ xmacro(_NET_WORKAREA)
++xmacro(_NET_WM_ICON)
+ xmacro(WM_PROTOCOLS)
+ xmacro(WM_DELETE_WINDOW)
+ xmacro(UTF8_STRING)
+diff -rupN i3-4.8-original/include/data.h i3-4.8-patched/include/data.h
+--- i3-4.8-original/include/data.h 2014-06-15 13:12:43.000000000 -0400
++++ i3-4.8-patched/include/data.h 2014-06-16 08:18:43.267078172 -0400
+@@ -377,6 +377,11 @@ struct Window {
+
+ /** Depth of the window */
+ uint16_t depth;
++
++#ifdef USE_ICONS
++ /** Window icon, array of size 16x16 containing the ARGB pixels */
++ uint32_t* icon;
++#endif
+ };
+
+ /**
+diff -rupN i3-4.8-original/include/window.h i3-4.8-patched/include/window.h
+--- i3-4.8-original/include/window.h 2014-06-15 13:12:43.000000000 -0400
++++ i3-4.8-patched/include/window.h 2014-06-16 08:20:18.780985665 -0400
+@@ -63,6 +63,12 @@ void window_update_role(i3Window *win, x
+ void window_update_hints(i3Window *win, xcb_get_property_reply_t *prop, bool *urgency_hint);
+
+ /**
++ * Updates the _NET_WM_ICON
++ *
++ */
++void window_update_icon(i3Window *win, xcb_get_property_reply_t *prop);
++
++/**
+ * Updates the MOTIF_WM_HINTS. The container's border style should be set to
+ * `motif_border_style' if border style is not BS_NORMAL.
+ *
+diff -rupN i3-4.8-original/src/manage.c i3-4.8-patched/src/manage.c
+--- i3-4.8-original/src/manage.c 2014-06-15 13:12:43.000000000 -0400
++++ i3-4.8-patched/src/manage.c 2014-06-16 08:25:33.681888859 -0400
+@@ -92,6 +92,10 @@ void manage_window(xcb_window_t window,
+ role_cookie, startup_id_cookie, wm_hints_cookie,
+ wm_normal_hints_cookie, motif_wm_hints_cookie;
+
++ #ifdef USE_ICONS
++ xcb_get_property_cookie_t wm_icon_cookie;
++ #endif
++
+ geomc = xcb_get_geometry(conn, d);
+
+ /* Check if the window is mapped (it could be not mapped when intializing and
+@@ -161,6 +165,9 @@ void manage_window(xcb_window_t window,
+ wm_hints_cookie = xcb_icccm_get_wm_hints(conn, window);
+ wm_normal_hints_cookie = xcb_icccm_get_wm_normal_hints(conn, window);
+ motif_wm_hints_cookie = GET_PROPERTY(A__MOTIF_WM_HINTS, 5 * sizeof(uint64_t));
++ #ifdef USE_ICONS
++ wm_icon_cookie = xcb_get_property_unchecked(conn, false, window, A__NET_WM_ICON, XCB_ATOM_CARDINAL, 0, UINT32_MAX);
++ #endif
+
+ DLOG("Managing window 0x%08x\n", window);
+
+@@ -196,6 +203,10 @@ void manage_window(xcb_window_t window,
+ window_update_hints(cwindow, xcb_get_property_reply(conn, wm_hints_cookie, NULL), &urgency_hint);
+ border_style_t motif_border_style = BS_NORMAL;
+ window_update_motif_hints(cwindow, xcb_get_property_reply(conn, motif_wm_hints_cookie, NULL), &motif_border_style);
++ #ifdef USE_ICONS
++ window_update_icon(cwindow, xcb_get_property_reply(conn, wm_icon_cookie, NULL));
++ #endif
++
+ xcb_size_hints_t wm_size_hints;
+ if (!xcb_icccm_get_wm_size_hints_reply(conn, wm_normal_hints_cookie, &wm_size_hints, NULL))
+ memset(&wm_size_hints, '\0', sizeof(xcb_size_hints_t));
+diff -rupN i3-4.8-original/src/render.c i3-4.8-patched/src/render.c
+--- i3-4.8-original/src/render.c 2014-06-15 13:12:43.000000000 -0400
++++ i3-4.8-patched/src/render.c 2014-06-16 08:18:43.270411409 -0400
+@@ -215,6 +215,11 @@ void render_con(Con *con, bool render_fu
+
+ /* find the height for the decorations */
+ int deco_height = render_deco_height();
++#ifdef USE_ICONS
++ /* minimum decoration height to allow icon to fit
++ * not actuuly required, icon would be cropped otherwise */
++ deco_height = deco_height<16 ? 16 : deco_height;
++#endif
+
+ /* precalculate the sizes to be able to correct rounding errors */
+ int sizes[children];
+diff -rupN i3-4.8-original/src/tree.c i3-4.8-patched/src/tree.c
+--- i3-4.8-original/src/tree.c 2014-06-15 13:12:43.000000000 -0400
++++ i3-4.8-patched/src/tree.c 2014-06-16 08:27:37.981631499 -0400
+@@ -258,6 +258,9 @@ bool tree_close(Con *con, kill_window_t
+ FREE(con->window->class_class);
+ FREE(con->window->class_instance);
+ i3string_free(con->window->name);
++ #ifdef USE_ICONS
++ FREE(con->window->icon);
++ #endif
+ FREE(con->window->ran_assignments);
+ FREE(con->window);
+ }
+diff -rupN i3-4.8-original/src/window.c i3-4.8-patched/src/window.c
+--- i3-4.8-original/src/window.c 2014-06-15 13:12:43.000000000 -0400
++++ i3-4.8-patched/src/window.c 2014-06-16 08:18:43.270411409 -0400
+@@ -311,3 +311,83 @@ void window_update_motif_hints(i3Window
+ #undef MWM_DECOR_BORDER
+ #undef MWM_DECOR_TITLE
+ }
++
++#ifdef USE_ICONS
++/*
++ * Copy and resize icon if needed
++ */
++void copy_icon_with_resize(uint32_t *dst, int width, int height, uint32_t* src, int s_width, int s_height)
++{
++ int i, j;
++ if (width==s_width && height==s_height) {
++ /* easy case, same dimensions, just copy data */
++ memcpy(dst, src, width*height*sizeof(uint32_t));
++ }
++ else {
++ uint32_t* row = src;
++ int xstep = s_width/width;
++ int ystep = s_height/height*s_width;
++
++ for(i=0; i < height; ++i) {
++ uint32_t* ptr = row;
++ for(j=0; j < width; ++j) {
++ *dst++ = *ptr;
++ ptr+=xstep;
++ }
++ row += ystep;
++ }
++ }
++}
++
++
++void window_update_icon(i3Window *win, xcb_get_property_reply_t *prop)
++{
++ uint32_t *data = NULL;
++ uint64_t len = 0;
++
++ if(!prop || prop->type != XCB_ATOM_CARDINAL || prop->format != 32) {
++ DLOG("_NET_WM_ICON is not set\n");
++ FREE(prop);
++ return;
++ }
++
++ uint32_t prop_value_len = xcb_get_property_value_length(prop);
++ uint32_t *prop_value = (uint32_t *) xcb_get_property_value(prop);
++
++ /* Find the number of icons in the reply. */
++ while(prop_value_len > (sizeof(uint32_t) * 2) && prop_value && prop_value[0] && prop_value[1])
++ {
++ /* Check that the property is as long as it should be (in bytes),
++ handling integer overflow. "+2" to handle the width and height
++ fields. */
++ const uint64_t crt_len = prop_value[0] * (uint64_t) prop_value[1];
++ const uint64_t expected_len = (crt_len + 2) * 4;
++ if(expected_len > prop_value_len)
++ break;
++
++ if (len==0 || (crt_len>=16*16 && crt_len<len)) {
++ len = crt_len;
++ data = prop_value;
++ }
++ if (len==16*16) break; // found 16 pixels icon
++
++ /* Find pointer to next icon in the reply. */
++ prop_value_len -= expected_len;
++ prop_value = (uint32_t *) (((uint8_t *) prop_value) + expected_len);
++ }
++
++ if (!data ) {
++ DLOG("Could not get _NET_WM_ICON\n");
++ free(prop);
++ return;
++ }
++
++ LOG("Got _NET_WM_ICON of size: (%d,%d)\n", data[0], data[1]);
++
++ FREE(win->icon);
++ win->icon = malloc(16*16*sizeof(uint32_t));
++ copy_icon_with_resize(win->icon, 16, 16, data+2, data[0], data[1]);
++
++ free(prop);
++}
++#endif /* USE_ICONS */
+diff -rupN i3-4.8-original/src/x.c i3-4.8-patched/src/x.c
+--- i3-4.8-original/src/x.c 2014-06-15 13:12:43.000000000 -0400
++++ i3-4.8-patched/src/x.c 2014-06-16 08:32:24.960007993 -0400
+@@ -11,6 +11,9 @@
+ *
+ */
+ #include "all.h"
++#ifdef USE_ICONS
++#include <xcb/xcb_image.h>
++#endif
+
+ /* Stores the X11 window ID of the currently focused window */
+ xcb_window_t focused_id = XCB_NONE;
+@@ -301,6 +304,44 @@ void x_window_kill(xcb_window_t window,
+ free(event);
+ }
+
++#ifdef USE_ICONS
++
++static inline uint32_t pixel_blend(uint32_t d, uint32_t s)
++{
++ const uint32_t a = (s >> 24) + 1;
++
++ const uint32_t dstrb = d & 0xFF00FF;
++ const uint32_t dstg = d & 0xFF00;
++
++ const uint32_t srcrb = s & 0xFF00FF;
++ const uint32_t srcg = s & 0xFF00;
++
++ uint32_t drb = srcrb - dstrb;
++ uint32_t dg = srcg - dstg;
++
++ drb *= a;
++ dg *= a;
++ drb >>= 8;
++ dg >>= 8;
++
++ uint32_t rb = (drb + dstrb) & 0xFF00FF;
++ uint32_t g = (dg + dstg) & 0xFF00;
++
++ return rb | g;
++}
++
++/*
++ * Copy icon pixels, blend with background
++ */
++void copy_with_pixel_blend(uint32_t *dst, uint32_t* src, uint32_t background)
++{
++ int i;
++ for(i=0; i < 16*16; ++i) {
++ *dst++ = pixel_blend(background,*src++);
++ }
++}
++#endif
++
+ /*
+ * Draws the decoration of the given container onto its parent.
+ *
+@@ -530,12 +571,49 @@ void x_draw_decoration(Con *con) {
+ }
+ //DLOG("indent_level = %d, indent_mult = %d\n", indent_level, indent_mult);
+ int indent_px = (indent_level * 5) * indent_mult;
++ #ifdef USE_ICONS
++ if (win->icon) indent_px += 18;
++ #endif
+
+ draw_text(win->name,
+ parent->pixmap, parent->pm_gc,
+ con->deco_rect.x + 2 + indent_px, con->deco_rect.y + text_offset_y,
+ con->deco_rect.width - 2 - indent_px);
+
++ #ifdef USE_ICONS
++ /* Draw the icon */
++ if (win->icon) {
++ xcb_image_t* icon;
++
++ uint16_t width = 16;
++ uint16_t height = 16;
++ uint32_t icon_pixels[width*height];
++
++ copy_with_pixel_blend(icon_pixels, win->icon, p->color->background);
++
++ icon = xcb_image_create_native( conn,
++ width, height,
++ XCB_IMAGE_FORMAT_Z_PIXMAP,
++ root_depth,
++ NULL,
++ width*height*4,
++ (uint8_t*)icon_pixels
++ );
++
++ if (icon) {
++ int icon_offset_y = (con->deco_rect.height - 16) / 2;
++
++ xcb_image_put(conn, parent->pixmap, parent->pm_gc,
++ icon, con->deco_rect.x + indent_px - 16 , con->deco_rect.y + icon_offset_y, 0);
++
++ xcb_image_destroy(icon);
++ }
++ else {
++ ELOG("Error creating XCB image\n");
++ }
++ }
++ #endif
++
+ after_title:
+ /* Since we don’t clip the text at all, it might in some cases be painted
+ * on the border pixels on the right side of a window. Therefore, we draw