From d9180d02002251b64c32c80b00b07030652b2143 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20=27Necoro=27=20Neumann?= Date: Sun, 30 Jun 2013 23:02:45 +0200 Subject: i3 -> i3-4.5.1 -- to be on the safe side --- x11-wm/i3-4.5.1/fix-floating-bug.patch | 108 ++++++++ x11-wm/i3-4.5.1/i3bar-4.5-icons.patch | 440 +++++++++++++++++++++++++++++++++ x11-wm/i3/fix-floating-bug.patch | 108 -------- x11-wm/i3/i3bar-4.5-icons.patch | 440 --------------------------------- 4 files changed, 548 insertions(+), 548 deletions(-) create mode 100644 x11-wm/i3-4.5.1/fix-floating-bug.patch create mode 100644 x11-wm/i3-4.5.1/i3bar-4.5-icons.patch delete mode 100644 x11-wm/i3/fix-floating-bug.patch delete mode 100644 x11-wm/i3/i3bar-4.5-icons.patch diff --git a/x11-wm/i3-4.5.1/fix-floating-bug.patch b/x11-wm/i3-4.5.1/fix-floating-bug.patch new file mode 100644 index 0000000..a72cd9f --- /dev/null +++ b/x11-wm/i3-4.5.1/fix-floating-bug.patch @@ -0,0 +1,108 @@ +From b4f7142509e3af51504a1e72163d544d305f0fa8 Mon Sep 17 00:00:00 2001 +From: Michael Stapelberg +Date: Sat, 29 Jun 2013 18:27:33 +0000 +Subject: Bugfix: fix focus handling in 'floating disable' on non-visible windows (Thanks necoro) + +fixes #1027 +--- +diff --git a/src/floating.c b/src/floating.c +index 49a4122..ea93747 100644 +--- a/src/floating.c ++++ b/src/floating.c +@@ -315,6 +315,8 @@ void floating_disable(Con *con, bool automatic) { + return; + } + ++ const bool set_focus = (con == focused); ++ + Con *ws = con_get_workspace(con); + + /* 1: detach from parent container */ +@@ -344,8 +346,9 @@ void floating_disable(Con *con, bool automatic) { + con_attach(con, con->parent, false); + + con_fix_percent(con->parent); +- // TODO: don’t influence focus handling when Con was not focused before. +- con_focus(con); ++ ++ if (set_focus) ++ con_focus(con); + } + + /* +diff --git a/testcases/t/208-regress-floating-criteria.t b/testcases/t/208-regress-floating-criteria.t +new file mode 100644 +index 0000000..09a29fd +--- a/dev/null ++++ b/testcases/t/208-regress-floating-criteria.t +@@ -0,0 +1,68 @@ ++#!perl ++# vim:ts=4:sw=4:expandtab ++# ++# Please read the following documents before working on tests: ++# • http://build.i3wm.org/docs/testsuite.html ++# (or docs/testsuite) ++# ++# • http://build.i3wm.org/docs/lib-i3test.html ++# (alternatively: perldoc ./testcases/lib/i3test.pm) ++# ++# • http://build.i3wm.org/docs/ipc.html ++# (or docs/ipc) ++# ++# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf ++# (unless you are already familiar with Perl) ++# ++# Regression test for focus handling when using floating enable/disable with ++# criteria for windows on non-visible workspaces. ++# Ticket: #1027 ++# Bug still in: 4.5.1-90-g6582da9 ++use i3test i3_autostart => 0; ++use X11::XCB qw(PROP_MODE_REPLACE); ++ ++my $config = <<'EOT'; ++# i3 config file (v4) ++font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1 ++ ++assign [class="^special$"] → mail ++for_window [class="^special$"] floating enable, floating disable ++EOT ++ ++my $pid = launch_with_config($config); ++ ++# TODO: move this to X11::XCB::Window ++sub set_wm_class { ++ my ($id, $class, $instance) = @_; ++ ++ # Add a _NET_WM_STRUT_PARTIAL hint ++ my $atomname = $x->atom(name => 'WM_CLASS'); ++ my $atomtype = $x->atom(name => 'STRING'); ++ ++ $x->change_property( ++ PROP_MODE_REPLACE, ++ $id, ++ $atomname->id, ++ $atomtype->id, ++ 8, ++ length($class) + length($instance) + 2, ++ "$instance\x00$class\x00" ++ ); ++} ++ ++my $window = open_window( ++ name => 'Borderless window', ++ before_map => sub { set_wm_class($_->id, 'special', 'special') }, ++ dont_map => 1, ++); ++$window->map; ++ ++sync_with_i3; ++ ++cmd '[class="^special$"] focus'; ++ ++does_i3_live; ++ ++exit_gracefully($pid); ++ ++done_testing; +-- +cgit v0.9.0.3 diff --git a/x11-wm/i3-4.5.1/i3bar-4.5-icons.patch b/x11-wm/i3-4.5.1/i3bar-4.5-icons.patch new file mode 100644 index 0000000..44215b9 --- /dev/null +++ b/x11-wm/i3-4.5.1/i3bar-4.5-icons.patch @@ -0,0 +1,440 @@ +diff --git a/common.mk b/common.mk +index de5c7e9..eff3468 100644 +--- a/common.mk ++++ b/common.mk +@@ -83,6 +83,7 @@ XCB_CFLAGS := $(call cflags_for_lib, xcb) + XCB_CFLAGS += $(call cflags_for_lib, xcb-event) + XCB_LIBS := $(call ldflags_for_lib, xcb,xcb) + XCB_LIBS += $(call ldflags_for_lib, xcb-event,xcb-event) ++XCB_LIBS += $(call ldflags_for_lib, xcb-image,xcb-image) + ifeq ($(shell pkg-config --exists xcb-util 2>/dev/null || echo 1),1) + XCB_CFLAGS += $(call cflags_for_lib, xcb-atom) + XCB_CFLAGS += $(call cflags_for_lib, xcb-aux) +diff --git a/i3bar/include/common.h b/i3bar/include/common.h +index 1365082..b141e1b 100644 +--- a/i3bar/include/common.h ++++ b/i3bar/include/common.h +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + #include "libi3.h" + #include "queue.h" + +@@ -39,6 +40,7 @@ struct status_block { + i3String *full_text; + + char *color; ++ char *icon; + uint32_t min_width; + blockalign_t align; + +@@ -53,6 +55,7 @@ struct status_block { + uint32_t width; + uint32_t x_offset; + uint32_t x_append; ++ xcb_image_t *icon_image; + + TAILQ_ENTRY(status_block) blocks; + }; +@@ -66,6 +69,7 @@ TAILQ_HEAD(statusline_head, status_block) statusline_head; + #include "workspaces.h" + #include "mode.h" + #include "trayclients.h" ++#include "xbm.h" + #include "xcb.h" + #include "config.h" + #include "libi3.h" +diff --git a/i3bar/include/xbm.h b/i3bar/include/xbm.h +new file mode 100644 +index 0000000..53837f7 +--- /dev/null ++++ b/i3bar/include/xbm.h +@@ -0,0 +1,47 @@ ++/* ++ * vim:ts=4:sw=4:expandtab ++ * ++ * i3bar - an xcb-based status- and ws-bar for i3 ++ * © 2010-2011 Axel Wagner and contributors (see also: LICENSE) ++ * ++ * xbm.c: Parsing/Loading xbm data ++ * ++ */ ++#ifndef XBM_H_ ++#define XBM_H_ ++ ++#include "queue.h" ++ ++#define BUFSZ 512 ++ ++struct raw_xbm { ++ uint32_t w,h; ++ uint32_t dlen; ++ uint8_t *data; ++}; ++ ++struct Cached_Xbm { ++ char *path; ++ xcb_image_t *icon; ++ int used; ++ SLIST_ENTRY(Cached_Xbm) xbm_cache; ++}; ++ ++/* Set the format information for loaded icons */ ++void set_format(xcb_connection_t * c, uint8_t depth, uint8_t bpp); ++ ++/* Set xcb context color for icon, needed with pango patch */ ++void set_icon_color(xcb_connection_t *c, xcb_gcontext_t gc, ++ uint32_t foreground, uint32_t background); ++ ++/* get the xcb image for the given icon path */ ++xcb_image_t* get_icon(char* path); ++ ++/* cache functions */ ++void xbm_clear_cache_used(); ++xcb_image_t* xbm_get_cached_icon(char* path); ++void xbm_cache_icon(char* path, xcb_image_t* icon); ++void xbm_free_unused_icons(); ++ ++ ++#endif +diff --git a/i3bar/src/child.c b/i3bar/src/child.c +index e5f4ea2..dbb87c3 100644 +--- a/i3bar/src/child.c ++++ b/i3bar/src/child.c +@@ -85,6 +85,7 @@ static int stdin_start_array(void *context) { + first = TAILQ_FIRST(&statusline_head); + I3STRING_FREE(first->full_text); + FREE(first->color); ++ FREE(first->icon); + TAILQ_REMOVE(&statusline_head, first, blocks); + free(first); + } +@@ -139,6 +140,9 @@ static int stdin_string(void *context, const unsigned char *val, unsigned int le + if (strcasecmp(ctx->last_map_key, "color") == 0) { + sasprintf(&(ctx->block.color), "%.*s", len, val); + } ++ if (strcasecmp(ctx->last_map_key, "icon") == 0) { ++ sasprintf(&(ctx->block.icon), "%.*s", len, val); ++ } + if (strcasecmp(ctx->last_map_key, "align") == 0) { + if (len == strlen("left") && !strncmp((const char*)val, "left", strlen("left"))) { + ctx->block.align = ALIGN_LEFT; +@@ -190,6 +194,7 @@ static int stdin_end_array(void *context) { + TAILQ_FOREACH(current, &statusline_head, blocks) { + DLOG("full_text = %s\n", i3string_as_utf8(current->full_text)); + DLOG("color = %s\n", current->color); ++ DLOG("icon = %s\n",current->icon); + } + DLOG("end of dump\n"); + return 1; +diff --git a/i3bar/src/xbm.c b/i3bar/src/xbm.c +new file mode 100644 +index 0000000..af7d18c +--- /dev/null ++++ b/i3bar/src/xbm.c +@@ -0,0 +1,239 @@ ++/* ++ * vim:ts=4:sw=4:expandtab ++ * ++ * i3bar - an xcb-based status- and ws-bar for i3 ++ * © 2010-2011 Axel Wagner and contributors (see also: LICENSE) ++ * ++ * xbm.c: Parsing/Loading xbm data ++ * ++ * set_format from: ++ * http://vincentsanders.blogspot.de/2010/04/xcb-programming-is-hard.html ++ */ ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "common.h" ++ ++static xcb_format_t* format = NULL; ++ ++void set_format(xcb_connection_t * c, uint8_t depth, uint8_t bpp) { ++ const xcb_setup_t *setup = xcb_get_setup(c); ++ xcb_format_t *fmt = xcb_setup_pixmap_formats(setup); ++ xcb_format_t *fmtend = fmt + xcb_setup_pixmap_formats_length(setup); ++ for(; fmt != fmtend; ++fmt) ++ if((fmt->depth == depth) && (fmt->bits_per_pixel == bpp)) ++ format = fmt; ++} ++ ++/* With pango we need to set colors ourselves, since the pango ++ * patch only sets font color */ ++void set_icon_color(xcb_connection_t *c, xcb_gcontext_t gc, ++ uint32_t foreground, uint32_t background) { ++ uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND; ++ uint32_t values[] = {foreground, background }; ++ xcb_change_gc(c, gc, mask, values); ++} ++ ++static int ++parse_xbm(char* file, struct raw_xbm* data) { ++ FILE *f; ++ char *str; ++ int i,p,r,lim; ++ char *c; ++ uint8_t *d; ++ ++ int in_array = 0; ++ ++ data->w = data->h = -1; ++ ++ f = fopen(file,"r"); ++ if (!f) { ++ ELOG("Could not open xbm file: %s",file); ++ return 1; ++ } ++ ++ str=malloc(BUFSZ); ++ if (!str) { ++ ELOG("Could not malloc buffer for xbm parsing"); ++ fclose(f); ++ return 1; ++ } ++ ++ while (fscanf(f," #define %s %d",str,&i) == 2) { ++ if (strstr(str,"width") != NULL) ++ data->w = i; ++ else if (strstr(str,"height") != NULL) ++ data->h = i; ++ } ++ ++ if (data->w <= 0 || data->h <= 0) { ++ ELOG("Could not find height and/or width in xbm: %s\n",file); ++ fclose(f); ++ free(str); ++ return 1; ++ } ++ ++ d = malloc(data->w*data->h); ++ p = 0; ++ ++ r = fread(str,1,BUFSZ,f); ++ lim = r; ++ while(r>0) { ++ if(in_array) { ++ while(c < (str+lim)) { ++ char* t = c; ++ while (*t && t!=(str+lim-1) && *t!=',' && *t!='}') t++; ++ if (*t && (*t==',' || *t=='}')) ++ d[p++] = strtol(c,NULL,16); ++ else ++ break; ++ c=t+1; ++ } ++ } else { ++ c = str; ++ while (*c && c!=(str+lim) && *c!='{') ++ c++; ++ if (*c && c!=(str+lim) && *c=='{') { ++ in_array=1; ++ c++; ++ if (c<(str+lim)) continue; ++ } ++ } ++ ++ i = (str+lim)-c; ++ if (i > 0) memcpy(str,c,i); ++ ++ r = fread(str+i,1,BUFSZ-i,f); ++ c=str; ++ lim = r+i; ++ } ++ ++ fclose(f); ++ free(str); ++ ++ /* will free if p==0, so we only have malloced mem ++ * when p!=0 */ ++ d = realloc(d,p); ++ ++ data->dlen = p; ++ data->data = d; ++ return p==0; ++} ++ ++static xcb_image_t * ++create_icon_image(struct raw_xbm *xbm) { ++ int i,rowsize,done,di; ++ unsigned char *imgdata; ++ if (format == NULL) return NULL; ++ ++ imgdata = (unsigned char *)malloc(xbm->w*xbm->h); ++ memset(imgdata,0,sizeof(imgdata)); ++ ++ rowsize = format->scanline_pad; ++ while(rowsize < xbm->w) rowsize+=format->scanline_pad; ++ ++ for(done=0,di=0,i=0;idlen;i++) { ++ imgdata[di] = xbm->data[i]; ++ di++; ++ done+=8; ++ if (done >= xbm->w) { ++ // pad out to rowsize ++ while (done < rowsize) { ++ di++; ++ done+=8; ++ } ++ done=0; ++ } ++ } ++ ++ return xcb_image_create(xbm->w, ++ xbm->h, ++ XCB_IMAGE_FORMAT_XY_BITMAP, ++ format->scanline_pad, ++ format->depth, ++ format->bits_per_pixel, ++ 0, ++ XCB_IMAGE_ORDER_LSB_FIRST, ++ XCB_IMAGE_ORDER_LSB_FIRST, ++ imgdata, ++ xbm->w*xbm->h, ++ imgdata); ++} ++ ++xcb_image_t* get_icon(char* path) { ++ xcb_image_t* ret; ++ struct raw_xbm rxbm; ++ ++ ret = xbm_get_cached_icon(path); ++ if (ret) return ret; ++ ++ DLOG("Loading xbm: %s\n",path); ++ ++ rxbm.data = NULL; ++ if (parse_xbm(path,&rxbm)) { ++ ELOG("Cannot parse xbm: %s\n",path); ++ return NULL; ++ } ++ ret = create_icon_image(&rxbm); ++ xbm_cache_icon(path,ret); ++ free(rxbm.data); ++ return ret; ++} ++ ++/* Below we implement a cache for parsed xbm icons. ++ * ++ * If an icon is used in a draw of the bar, it sticks around until the ++ * next draw, otherwise we throw it away at the end of a update. The ++ * idea being that most icons are fairly static, or change rarely ++ * (like when a battery threshold is reached). Therefore, we are very ++ * aggresive about throwing things out of the cache. ++ */ ++ ++static SLIST_HEAD(xbm_cache_head, Cached_Xbm) xbm_cache; ++ ++void xbm_clear_cache_used() { ++ struct Cached_Xbm* cxbm; ++ SLIST_FOREACH(cxbm,&xbm_cache,xbm_cache) { ++ cxbm->used = 0; ++ } ++} ++ ++xcb_image_t* xbm_get_cached_icon(char* path) { ++ struct Cached_Xbm* cxbm; ++ SLIST_FOREACH(cxbm,&xbm_cache,xbm_cache) { ++ if (!strcmp(path,cxbm->path)) { ++ cxbm->used = 1; ++ return cxbm->icon; ++ } ++ } ++ return NULL; ++} ++ ++void xbm_cache_icon(char* path, xcb_image_t* icon) { ++ struct Cached_Xbm *cxbm = smalloc(sizeof(struct Cached_Xbm)); ++ cxbm->used = 1; ++ cxbm->path = strdup(path); ++ cxbm->icon = icon; ++ SLIST_INSERT_HEAD(&xbm_cache,cxbm,xbm_cache); ++} ++ ++void xbm_free_unused_icons() { ++ struct Cached_Xbm* cxbm; ++ SLIST_FOREACH(cxbm,&xbm_cache,xbm_cache) { ++ if (!cxbm->used) { ++ SLIST_REMOVE(&xbm_cache, cxbm, Cached_Xbm, xbm_cache); ++ free(cxbm->path); ++ xcb_image_destroy(cxbm->icon); ++ free(cxbm); ++ } ++ } ++} ++ +diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c +index d5d4eb8..43351de 100644 +--- a/i3bar/src/xcb.c ++++ b/i3bar/src/xcb.c +@@ -128,6 +128,14 @@ void refresh_statusline(void) { + + block->width = predict_text_width(block->full_text); + ++ if (block->icon) { ++ block->icon_image = get_icon(block->icon); ++ if (!block->icon_image) ++ ELOG("Could not load icon: %s\n",block->icon); ++ else ++ statusline_width += block->icon_image->width+1; ++ } ++ + /* Compute offset and append for text aligment in min_width. */ + if (block->min_width <= block->width) { + block->x_offset = 0; +@@ -173,6 +181,18 @@ void refresh_statusline(void) { + + uint32_t colorpixel = (block->color ? get_colorpixel(block->color) : colors.bar_fg); + set_font_colors(statusline_ctx, colorpixel, colors.bar_bg); ++ ++ if (block->icon_image) { ++ int h = (font.height-block->icon_image->height)/2; ++ set_icon_color(xcb_connection,statusline_ctx, ++ colorpixel,colors.bar_bg); ++ xcb_image_put(xcb_connection,statusline_pm,statusline_ctx, ++ block->icon_image,x,h,0); ++ set_icon_color(xcb_connection,statusline_ctx, ++ get_colorpixel("#666666"),colors.bar_bg); ++ x+=block->icon_image->width+1; ++ } ++ + draw_text(block->full_text, statusline_pm, statusline_ctx, x + block->x_offset, 1, block->width); + x += block->width + block->x_offset + block->x_append; + +@@ -936,6 +956,8 @@ char *init_xcb_early() { + } + } + ++ /* Set the format for icons */ ++ set_format(xcb_connection,1,1); + + if (xcb_request_failed(sl_pm_cookie, "Could not allocate statusline-buffer") || + xcb_request_failed(clear_ctx_cookie, "Could not allocate statusline-buffer-clearcontext") || +@@ -1518,6 +1540,7 @@ void draw_bars(bool unhide) { + DLOG("Drawing Bars...\n"); + int i = 1; + ++ xbm_clear_cache_used(); + refresh_statusline(); + + static char *last_urgent_ws = NULL; +@@ -1685,6 +1708,8 @@ void draw_bars(bool unhide) { + } + } + ++ xbm_free_unused_icons(); ++ + redraw_bars(); + } + diff --git a/x11-wm/i3/fix-floating-bug.patch b/x11-wm/i3/fix-floating-bug.patch deleted file mode 100644 index a72cd9f..0000000 --- a/x11-wm/i3/fix-floating-bug.patch +++ /dev/null @@ -1,108 +0,0 @@ -From b4f7142509e3af51504a1e72163d544d305f0fa8 Mon Sep 17 00:00:00 2001 -From: Michael Stapelberg -Date: Sat, 29 Jun 2013 18:27:33 +0000 -Subject: Bugfix: fix focus handling in 'floating disable' on non-visible windows (Thanks necoro) - -fixes #1027 ---- -diff --git a/src/floating.c b/src/floating.c -index 49a4122..ea93747 100644 ---- a/src/floating.c -+++ b/src/floating.c -@@ -315,6 +315,8 @@ void floating_disable(Con *con, bool automatic) { - return; - } - -+ const bool set_focus = (con == focused); -+ - Con *ws = con_get_workspace(con); - - /* 1: detach from parent container */ -@@ -344,8 +346,9 @@ void floating_disable(Con *con, bool automatic) { - con_attach(con, con->parent, false); - - con_fix_percent(con->parent); -- // TODO: don’t influence focus handling when Con was not focused before. -- con_focus(con); -+ -+ if (set_focus) -+ con_focus(con); - } - - /* -diff --git a/testcases/t/208-regress-floating-criteria.t b/testcases/t/208-regress-floating-criteria.t -new file mode 100644 -index 0000000..09a29fd ---- a/dev/null -+++ b/testcases/t/208-regress-floating-criteria.t -@@ -0,0 +1,68 @@ -+#!perl -+# vim:ts=4:sw=4:expandtab -+# -+# Please read the following documents before working on tests: -+# • http://build.i3wm.org/docs/testsuite.html -+# (or docs/testsuite) -+# -+# • http://build.i3wm.org/docs/lib-i3test.html -+# (alternatively: perldoc ./testcases/lib/i3test.pm) -+# -+# • http://build.i3wm.org/docs/ipc.html -+# (or docs/ipc) -+# -+# • http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf -+# (unless you are already familiar with Perl) -+# -+# Regression test for focus handling when using floating enable/disable with -+# criteria for windows on non-visible workspaces. -+# Ticket: #1027 -+# Bug still in: 4.5.1-90-g6582da9 -+use i3test i3_autostart => 0; -+use X11::XCB qw(PROP_MODE_REPLACE); -+ -+my $config = <<'EOT'; -+# i3 config file (v4) -+font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1 -+ -+assign [class="^special$"] → mail -+for_window [class="^special$"] floating enable, floating disable -+EOT -+ -+my $pid = launch_with_config($config); -+ -+# TODO: move this to X11::XCB::Window -+sub set_wm_class { -+ my ($id, $class, $instance) = @_; -+ -+ # Add a _NET_WM_STRUT_PARTIAL hint -+ my $atomname = $x->atom(name => 'WM_CLASS'); -+ my $atomtype = $x->atom(name => 'STRING'); -+ -+ $x->change_property( -+ PROP_MODE_REPLACE, -+ $id, -+ $atomname->id, -+ $atomtype->id, -+ 8, -+ length($class) + length($instance) + 2, -+ "$instance\x00$class\x00" -+ ); -+} -+ -+my $window = open_window( -+ name => 'Borderless window', -+ before_map => sub { set_wm_class($_->id, 'special', 'special') }, -+ dont_map => 1, -+); -+$window->map; -+ -+sync_with_i3; -+ -+cmd '[class="^special$"] focus'; -+ -+does_i3_live; -+ -+exit_gracefully($pid); -+ -+done_testing; --- -cgit v0.9.0.3 diff --git a/x11-wm/i3/i3bar-4.5-icons.patch b/x11-wm/i3/i3bar-4.5-icons.patch deleted file mode 100644 index 44215b9..0000000 --- a/x11-wm/i3/i3bar-4.5-icons.patch +++ /dev/null @@ -1,440 +0,0 @@ -diff --git a/common.mk b/common.mk -index de5c7e9..eff3468 100644 ---- a/common.mk -+++ b/common.mk -@@ -83,6 +83,7 @@ XCB_CFLAGS := $(call cflags_for_lib, xcb) - XCB_CFLAGS += $(call cflags_for_lib, xcb-event) - XCB_LIBS := $(call ldflags_for_lib, xcb,xcb) - XCB_LIBS += $(call ldflags_for_lib, xcb-event,xcb-event) -+XCB_LIBS += $(call ldflags_for_lib, xcb-image,xcb-image) - ifeq ($(shell pkg-config --exists xcb-util 2>/dev/null || echo 1),1) - XCB_CFLAGS += $(call cflags_for_lib, xcb-atom) - XCB_CFLAGS += $(call cflags_for_lib, xcb-aux) -diff --git a/i3bar/include/common.h b/i3bar/include/common.h -index 1365082..b141e1b 100644 ---- a/i3bar/include/common.h -+++ b/i3bar/include/common.h -@@ -11,6 +11,7 @@ - #include - #include - #include -+#include - #include "libi3.h" - #include "queue.h" - -@@ -39,6 +40,7 @@ struct status_block { - i3String *full_text; - - char *color; -+ char *icon; - uint32_t min_width; - blockalign_t align; - -@@ -53,6 +55,7 @@ struct status_block { - uint32_t width; - uint32_t x_offset; - uint32_t x_append; -+ xcb_image_t *icon_image; - - TAILQ_ENTRY(status_block) blocks; - }; -@@ -66,6 +69,7 @@ TAILQ_HEAD(statusline_head, status_block) statusline_head; - #include "workspaces.h" - #include "mode.h" - #include "trayclients.h" -+#include "xbm.h" - #include "xcb.h" - #include "config.h" - #include "libi3.h" -diff --git a/i3bar/include/xbm.h b/i3bar/include/xbm.h -new file mode 100644 -index 0000000..53837f7 ---- /dev/null -+++ b/i3bar/include/xbm.h -@@ -0,0 +1,47 @@ -+/* -+ * vim:ts=4:sw=4:expandtab -+ * -+ * i3bar - an xcb-based status- and ws-bar for i3 -+ * © 2010-2011 Axel Wagner and contributors (see also: LICENSE) -+ * -+ * xbm.c: Parsing/Loading xbm data -+ * -+ */ -+#ifndef XBM_H_ -+#define XBM_H_ -+ -+#include "queue.h" -+ -+#define BUFSZ 512 -+ -+struct raw_xbm { -+ uint32_t w,h; -+ uint32_t dlen; -+ uint8_t *data; -+}; -+ -+struct Cached_Xbm { -+ char *path; -+ xcb_image_t *icon; -+ int used; -+ SLIST_ENTRY(Cached_Xbm) xbm_cache; -+}; -+ -+/* Set the format information for loaded icons */ -+void set_format(xcb_connection_t * c, uint8_t depth, uint8_t bpp); -+ -+/* Set xcb context color for icon, needed with pango patch */ -+void set_icon_color(xcb_connection_t *c, xcb_gcontext_t gc, -+ uint32_t foreground, uint32_t background); -+ -+/* get the xcb image for the given icon path */ -+xcb_image_t* get_icon(char* path); -+ -+/* cache functions */ -+void xbm_clear_cache_used(); -+xcb_image_t* xbm_get_cached_icon(char* path); -+void xbm_cache_icon(char* path, xcb_image_t* icon); -+void xbm_free_unused_icons(); -+ -+ -+#endif -diff --git a/i3bar/src/child.c b/i3bar/src/child.c -index e5f4ea2..dbb87c3 100644 ---- a/i3bar/src/child.c -+++ b/i3bar/src/child.c -@@ -85,6 +85,7 @@ static int stdin_start_array(void *context) { - first = TAILQ_FIRST(&statusline_head); - I3STRING_FREE(first->full_text); - FREE(first->color); -+ FREE(first->icon); - TAILQ_REMOVE(&statusline_head, first, blocks); - free(first); - } -@@ -139,6 +140,9 @@ static int stdin_string(void *context, const unsigned char *val, unsigned int le - if (strcasecmp(ctx->last_map_key, "color") == 0) { - sasprintf(&(ctx->block.color), "%.*s", len, val); - } -+ if (strcasecmp(ctx->last_map_key, "icon") == 0) { -+ sasprintf(&(ctx->block.icon), "%.*s", len, val); -+ } - if (strcasecmp(ctx->last_map_key, "align") == 0) { - if (len == strlen("left") && !strncmp((const char*)val, "left", strlen("left"))) { - ctx->block.align = ALIGN_LEFT; -@@ -190,6 +194,7 @@ static int stdin_end_array(void *context) { - TAILQ_FOREACH(current, &statusline_head, blocks) { - DLOG("full_text = %s\n", i3string_as_utf8(current->full_text)); - DLOG("color = %s\n", current->color); -+ DLOG("icon = %s\n",current->icon); - } - DLOG("end of dump\n"); - return 1; -diff --git a/i3bar/src/xbm.c b/i3bar/src/xbm.c -new file mode 100644 -index 0000000..af7d18c ---- /dev/null -+++ b/i3bar/src/xbm.c -@@ -0,0 +1,239 @@ -+/* -+ * vim:ts=4:sw=4:expandtab -+ * -+ * i3bar - an xcb-based status- and ws-bar for i3 -+ * © 2010-2011 Axel Wagner and contributors (see also: LICENSE) -+ * -+ * xbm.c: Parsing/Loading xbm data -+ * -+ * set_format from: -+ * http://vincentsanders.blogspot.de/2010/04/xcb-programming-is-hard.html -+ */ -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include "common.h" -+ -+static xcb_format_t* format = NULL; -+ -+void set_format(xcb_connection_t * c, uint8_t depth, uint8_t bpp) { -+ const xcb_setup_t *setup = xcb_get_setup(c); -+ xcb_format_t *fmt = xcb_setup_pixmap_formats(setup); -+ xcb_format_t *fmtend = fmt + xcb_setup_pixmap_formats_length(setup); -+ for(; fmt != fmtend; ++fmt) -+ if((fmt->depth == depth) && (fmt->bits_per_pixel == bpp)) -+ format = fmt; -+} -+ -+/* With pango we need to set colors ourselves, since the pango -+ * patch only sets font color */ -+void set_icon_color(xcb_connection_t *c, xcb_gcontext_t gc, -+ uint32_t foreground, uint32_t background) { -+ uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND; -+ uint32_t values[] = {foreground, background }; -+ xcb_change_gc(c, gc, mask, values); -+} -+ -+static int -+parse_xbm(char* file, struct raw_xbm* data) { -+ FILE *f; -+ char *str; -+ int i,p,r,lim; -+ char *c; -+ uint8_t *d; -+ -+ int in_array = 0; -+ -+ data->w = data->h = -1; -+ -+ f = fopen(file,"r"); -+ if (!f) { -+ ELOG("Could not open xbm file: %s",file); -+ return 1; -+ } -+ -+ str=malloc(BUFSZ); -+ if (!str) { -+ ELOG("Could not malloc buffer for xbm parsing"); -+ fclose(f); -+ return 1; -+ } -+ -+ while (fscanf(f," #define %s %d",str,&i) == 2) { -+ if (strstr(str,"width") != NULL) -+ data->w = i; -+ else if (strstr(str,"height") != NULL) -+ data->h = i; -+ } -+ -+ if (data->w <= 0 || data->h <= 0) { -+ ELOG("Could not find height and/or width in xbm: %s\n",file); -+ fclose(f); -+ free(str); -+ return 1; -+ } -+ -+ d = malloc(data->w*data->h); -+ p = 0; -+ -+ r = fread(str,1,BUFSZ,f); -+ lim = r; -+ while(r>0) { -+ if(in_array) { -+ while(c < (str+lim)) { -+ char* t = c; -+ while (*t && t!=(str+lim-1) && *t!=',' && *t!='}') t++; -+ if (*t && (*t==',' || *t=='}')) -+ d[p++] = strtol(c,NULL,16); -+ else -+ break; -+ c=t+1; -+ } -+ } else { -+ c = str; -+ while (*c && c!=(str+lim) && *c!='{') -+ c++; -+ if (*c && c!=(str+lim) && *c=='{') { -+ in_array=1; -+ c++; -+ if (c<(str+lim)) continue; -+ } -+ } -+ -+ i = (str+lim)-c; -+ if (i > 0) memcpy(str,c,i); -+ -+ r = fread(str+i,1,BUFSZ-i,f); -+ c=str; -+ lim = r+i; -+ } -+ -+ fclose(f); -+ free(str); -+ -+ /* will free if p==0, so we only have malloced mem -+ * when p!=0 */ -+ d = realloc(d,p); -+ -+ data->dlen = p; -+ data->data = d; -+ return p==0; -+} -+ -+static xcb_image_t * -+create_icon_image(struct raw_xbm *xbm) { -+ int i,rowsize,done,di; -+ unsigned char *imgdata; -+ if (format == NULL) return NULL; -+ -+ imgdata = (unsigned char *)malloc(xbm->w*xbm->h); -+ memset(imgdata,0,sizeof(imgdata)); -+ -+ rowsize = format->scanline_pad; -+ while(rowsize < xbm->w) rowsize+=format->scanline_pad; -+ -+ for(done=0,di=0,i=0;idlen;i++) { -+ imgdata[di] = xbm->data[i]; -+ di++; -+ done+=8; -+ if (done >= xbm->w) { -+ // pad out to rowsize -+ while (done < rowsize) { -+ di++; -+ done+=8; -+ } -+ done=0; -+ } -+ } -+ -+ return xcb_image_create(xbm->w, -+ xbm->h, -+ XCB_IMAGE_FORMAT_XY_BITMAP, -+ format->scanline_pad, -+ format->depth, -+ format->bits_per_pixel, -+ 0, -+ XCB_IMAGE_ORDER_LSB_FIRST, -+ XCB_IMAGE_ORDER_LSB_FIRST, -+ imgdata, -+ xbm->w*xbm->h, -+ imgdata); -+} -+ -+xcb_image_t* get_icon(char* path) { -+ xcb_image_t* ret; -+ struct raw_xbm rxbm; -+ -+ ret = xbm_get_cached_icon(path); -+ if (ret) return ret; -+ -+ DLOG("Loading xbm: %s\n",path); -+ -+ rxbm.data = NULL; -+ if (parse_xbm(path,&rxbm)) { -+ ELOG("Cannot parse xbm: %s\n",path); -+ return NULL; -+ } -+ ret = create_icon_image(&rxbm); -+ xbm_cache_icon(path,ret); -+ free(rxbm.data); -+ return ret; -+} -+ -+/* Below we implement a cache for parsed xbm icons. -+ * -+ * If an icon is used in a draw of the bar, it sticks around until the -+ * next draw, otherwise we throw it away at the end of a update. The -+ * idea being that most icons are fairly static, or change rarely -+ * (like when a battery threshold is reached). Therefore, we are very -+ * aggresive about throwing things out of the cache. -+ */ -+ -+static SLIST_HEAD(xbm_cache_head, Cached_Xbm) xbm_cache; -+ -+void xbm_clear_cache_used() { -+ struct Cached_Xbm* cxbm; -+ SLIST_FOREACH(cxbm,&xbm_cache,xbm_cache) { -+ cxbm->used = 0; -+ } -+} -+ -+xcb_image_t* xbm_get_cached_icon(char* path) { -+ struct Cached_Xbm* cxbm; -+ SLIST_FOREACH(cxbm,&xbm_cache,xbm_cache) { -+ if (!strcmp(path,cxbm->path)) { -+ cxbm->used = 1; -+ return cxbm->icon; -+ } -+ } -+ return NULL; -+} -+ -+void xbm_cache_icon(char* path, xcb_image_t* icon) { -+ struct Cached_Xbm *cxbm = smalloc(sizeof(struct Cached_Xbm)); -+ cxbm->used = 1; -+ cxbm->path = strdup(path); -+ cxbm->icon = icon; -+ SLIST_INSERT_HEAD(&xbm_cache,cxbm,xbm_cache); -+} -+ -+void xbm_free_unused_icons() { -+ struct Cached_Xbm* cxbm; -+ SLIST_FOREACH(cxbm,&xbm_cache,xbm_cache) { -+ if (!cxbm->used) { -+ SLIST_REMOVE(&xbm_cache, cxbm, Cached_Xbm, xbm_cache); -+ free(cxbm->path); -+ xcb_image_destroy(cxbm->icon); -+ free(cxbm); -+ } -+ } -+} -+ -diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c -index d5d4eb8..43351de 100644 ---- a/i3bar/src/xcb.c -+++ b/i3bar/src/xcb.c -@@ -128,6 +128,14 @@ void refresh_statusline(void) { - - block->width = predict_text_width(block->full_text); - -+ if (block->icon) { -+ block->icon_image = get_icon(block->icon); -+ if (!block->icon_image) -+ ELOG("Could not load icon: %s\n",block->icon); -+ else -+ statusline_width += block->icon_image->width+1; -+ } -+ - /* Compute offset and append for text aligment in min_width. */ - if (block->min_width <= block->width) { - block->x_offset = 0; -@@ -173,6 +181,18 @@ void refresh_statusline(void) { - - uint32_t colorpixel = (block->color ? get_colorpixel(block->color) : colors.bar_fg); - set_font_colors(statusline_ctx, colorpixel, colors.bar_bg); -+ -+ if (block->icon_image) { -+ int h = (font.height-block->icon_image->height)/2; -+ set_icon_color(xcb_connection,statusline_ctx, -+ colorpixel,colors.bar_bg); -+ xcb_image_put(xcb_connection,statusline_pm,statusline_ctx, -+ block->icon_image,x,h,0); -+ set_icon_color(xcb_connection,statusline_ctx, -+ get_colorpixel("#666666"),colors.bar_bg); -+ x+=block->icon_image->width+1; -+ } -+ - draw_text(block->full_text, statusline_pm, statusline_ctx, x + block->x_offset, 1, block->width); - x += block->width + block->x_offset + block->x_append; - -@@ -936,6 +956,8 @@ char *init_xcb_early() { - } - } - -+ /* Set the format for icons */ -+ set_format(xcb_connection,1,1); - - if (xcb_request_failed(sl_pm_cookie, "Could not allocate statusline-buffer") || - xcb_request_failed(clear_ctx_cookie, "Could not allocate statusline-buffer-clearcontext") || -@@ -1518,6 +1540,7 @@ void draw_bars(bool unhide) { - DLOG("Drawing Bars...\n"); - int i = 1; - -+ xbm_clear_cache_used(); - refresh_statusline(); - - static char *last_urgent_ws = NULL; -@@ -1685,6 +1708,8 @@ void draw_bars(bool unhide) { - } - } - -+ xbm_free_unused_icons(); -+ - redraw_bars(); - } - -- cgit v1.2.3