We strive to avoid conditional compilation in i3 as much as possible.
cairo and pangocairo have been around long enough in the versions that
we need that it’s time to unconditionally depend on them.
Also update DEPENDS with the last-known-good-versions while at it.
┌──────────────┬────────┬────────┬───────────────────────────────────────────────────────────┐
│ dependency │ min. │ lkgv │ URL │
├──────────────┼────────┼────────┼───────────────────────────────────────────────────────────┤
┌──────────────┬────────┬────────┬───────────────────────────────────────────────────────────┐
│ dependency │ min. │ lkgv │ URL │
├──────────────┼────────┼────────┼───────────────────────────────────────────────────────────┤
-│ pkg-config │ 0.25 │ 0.28 │ http://pkgconfig.freedesktop.org/ │
-│ libxcb │ 1.1.93 │ 1.11 │ http://xcb.freedesktop.org/dist/ │
+│ pkg-config │ 0.25 │ 0.29 │ http://pkgconfig.freedesktop.org/ │
+│ libxcb │ 1.1.93 │ 1.12 │ http://xcb.freedesktop.org/dist/ │
│ xcb-util │ 0.3.3 │ 0.4.1 │ http://xcb.freedesktop.org/dist/ │
│ xcb-util │ 0.3.3 │ 0.4.1 │ http://xcb.freedesktop.org/dist/ │
-│ xkbcommon │ 0.4.0 │ 0.5.0 │ http://xkbcommon.org/ │
-│ xkbcommon-x11│ 0.4.0 │ 0.5.0 │ http://xkbcommon.org/ │
-│ util-cursor³⁴│ 0.0.99 │ 0.1.2 │ http://xcb.freedesktop.org/dist/ │
+│ xkbcommon │ 0.4.0 │ 0.6.1 │ http://xkbcommon.org/ │
+│ xkbcommon-x11│ 0.4.0 │ 0.6.1 │ http://xkbcommon.org/ │
+│ util-cursor³⁴│ 0.0.99 │ 0.1.3 │ http://xcb.freedesktop.org/dist/ │
│ util-wm⁴ │ 0.3.8 │ 0.3.8 │ http://xcb.freedesktop.org/dist/ │
│ util-keysyms⁴│ 0.3.8 │ 0.4.0 │ http://xcb.freedesktop.org/dist/ │
│ util-xrm⁴ │ 1.0.0 │ 1.0.0 │ https://github.com/Airblader/xcb-util-xrm │
│ libev │ 4.0 │ 4.19 │ http://libev.schmorp.de/ │
│ yajl │ 2.0.1 │ 2.1.0 │ http://lloyd.github.com/yajl/ │
│ util-wm⁴ │ 0.3.8 │ 0.3.8 │ http://xcb.freedesktop.org/dist/ │
│ util-keysyms⁴│ 0.3.8 │ 0.4.0 │ http://xcb.freedesktop.org/dist/ │
│ util-xrm⁴ │ 1.0.0 │ 1.0.0 │ https://github.com/Airblader/xcb-util-xrm │
│ libev │ 4.0 │ 4.19 │ http://libev.schmorp.de/ │
│ yajl │ 2.0.1 │ 2.1.0 │ http://lloyd.github.com/yajl/ │
-│ asciidoc │ 8.3.0 │ 8.6.8 │ http://www.methods.co.nz/asciidoc/ │
+│ asciidoc │ 8.3.0 │ 8.6.9 │ http://www.methods.co.nz/asciidoc/ │
│ xmlto │ 0.0.23 │ 0.0.23 │ http://www.methods.co.nz/asciidoc/ │
│ Pod::Simple² │ 3.22 │ 3.22 │ http://search.cpan.org/~dwheeler/Pod-Simple-3.23/ │
│ docbook-xml │ 4.5 │ 4.5 │ http://www.methods.co.nz/asciidoc/ │
│ xmlto │ 0.0.23 │ 0.0.23 │ http://www.methods.co.nz/asciidoc/ │
│ Pod::Simple² │ 3.22 │ 3.22 │ http://search.cpan.org/~dwheeler/Pod-Simple-3.23/ │
│ docbook-xml │ 4.5 │ 4.5 │ http://www.methods.co.nz/asciidoc/ │
-│ PCRE │ 8.12 │ 8.35 │ http://www.pcre.org/ │
+│ PCRE │ 8.12 │ 8.38 │ http://www.pcre.org/ │
│ libsn¹ │ 0.10 │ 0.12 │ http://freedesktop.org/wiki/Software/startup-notification │
│ libsn¹ │ 0.10 │ 0.12 │ http://freedesktop.org/wiki/Software/startup-notification │
-│ pango │ 1.30.0 | 1.36.8 │ http://www.pango.org/ │
-│ cairo │ 1.14.4 │ 1.14.4 │ http://cairographics.org/ │
+│ pango │ 1.30.0 | 1.40.1 │ http://www.pango.org/ │
+│ cairo │ 1.14.4 │ 1.14.6 │ http://cairographics.org/ │
└──────────────┴────────┴────────┴───────────────────────────────────────────────────────────┘
¹ libsn = libstartup-notification
² Pod::Simple is a Perl module required for converting the testsuite
└──────────────┴────────┴────────┴───────────────────────────────────────────────────────────┘
¹ libsn = libstartup-notification
² Pod::Simple is a Perl module required for converting the testsuite
# Pango
PANGO_CFLAGS := $(call cflags_for_lib, cairo)
PANGO_CFLAGS += $(call cflags_for_lib, pangocairo)
# Pango
PANGO_CFLAGS := $(call cflags_for_lib, cairo)
PANGO_CFLAGS += $(call cflags_for_lib, pangocairo)
-I3_CPPFLAGS += -DPANGO_SUPPORT=1
-ifeq ($(shell $(PKG_CONFIG) --atleast-version=1.14.4 cairo 2>/dev/null && echo 1),1)
-I3_CPPFLAGS += -DCAIRO_SUPPORT=1
+ifneq ($(shell $(PKG_CONFIG) --atleast-version=1.14.4 cairo 2>/dev/null && echo 1),1)
+$(error "cairo >= 1.14.4 missing")
endif
PANGO_LIBS := $(call ldflags_for_lib, cairo)
PANGO_LIBS += $(call ldflags_for_lib, pangocairo)
endif
PANGO_LIBS := $(call ldflags_for_lib, cairo)
PANGO_LIBS += $(call ldflags_for_lib, pangocairo)
libyajl-dev (>= 2.0.4),
libpcre3-dev (>= 1:8.10),
libstartup-notification0-dev (>= 0.10),
libyajl-dev (>= 2.0.4),
libpcre3-dev (>= 1:8.10),
libstartup-notification0-dev (>= 0.10),
+ libcairo2-dev (>= 1.14.4),
libpango1.0-dev,
libpod-simple-perl
Standards-Version: 3.9.7
libpango1.0-dev,
libpod-simple-perl
Standards-Version: 3.9.7
#include <xcb/xproto.h>
#include <xcb/xcb_keysyms.h>
#include <xcb/xproto.h>
#include <xcb/xcb_keysyms.h>
-#endif
-#if CAIRO_SUPPORT
#include <cairo/cairo-xcb.h>
#include <cairo/cairo-xcb.h>
#define DEFAULT_DIR_MODE (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
#define DEFAULT_DIR_MODE (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
xcb_charinfo_t *table;
} xcb;
xcb_charinfo_t *table;
} xcb;
/** The pango font description */
PangoFontDescription *pango_desc;
/** The pango font description */
PangoFontDescription *pango_desc;
*/
char *format_placeholders(char *format, placeholder_t *placeholders, int num);
*/
char *format_placeholders(char *format, placeholder_t *placeholders, int num);
/* We need to flush cairo surfaces twice to avoid an assertion bug. See #1989
* and https://bugs.freedesktop.org/show_bug.cgi?id=92455. */
#define CAIRO_SURFACE_FLUSH(surface) \
/* We need to flush cairo surfaces twice to avoid an assertion bug. See #1989
* and https://bugs.freedesktop.org/show_bug.cgi?id=92455. */
#define CAIRO_SURFACE_FLUSH(surface) \
cairo_surface_flush(surface); \
cairo_surface_flush(surface); \
} while (0)
cairo_surface_flush(surface); \
cairo_surface_flush(surface); \
} while (0)
/* A wrapper grouping an XCB drawable and both a graphics context
* and the corresponding cairo objects representing it. */
/* A wrapper grouping an XCB drawable and both a graphics context
* and the corresponding cairo objects representing it. */
/* A cairo surface representing the drawable. */
cairo_surface_t *surface;
/* The cairo object representing the drawable. In general,
* this is what one should use for any drawing operation. */
cairo_t *cr;
/* A cairo surface representing the drawable. */
cairo_surface_t *surface;
/* The cairo object representing the drawable. In general,
* this is what one should use for any drawing operation. */
cairo_t *cr;
#include <string.h>
#include <xcb/xcb.h>
#include <xcb/xcb_aux.h>
#include <string.h>
#include <xcb/xcb.h>
#include <xcb/xcb_aux.h>
#include <cairo/cairo-xcb.h>
#include <cairo/cairo-xcb.h>
ELOG("Could not create graphical context. Error code: %d. Please report this bug.\n", error->error_code);
}
ELOG("Could not create graphical context. Error code: %d. Please report this bug.\n", error->error_code);
}
surface->surface = cairo_xcb_surface_create(conn, surface->id, surface->visual_type, width, height);
surface->cr = cairo_create(surface->surface);
surface->surface = cairo_xcb_surface_create(conn, surface->id, surface->visual_type, width, height);
surface->cr = cairo_create(surface->surface);
*/
void draw_util_surface_free(xcb_connection_t *conn, surface_t *surface) {
xcb_free_gc(conn, surface->gc);
*/
void draw_util_surface_free(xcb_connection_t *conn, surface_t *surface) {
xcb_free_gc(conn, surface->gc);
cairo_surface_destroy(surface->surface);
cairo_destroy(surface->cr);
cairo_surface_destroy(surface->surface);
cairo_destroy(surface->cr);
* when setting the border of a window to none and then closing it. */
surface->surface = NULL;
surface->cr = NULL;
* when setting the border of a window to none and then closing it. */
surface->surface = NULL;
surface->cr = NULL;
void draw_util_surface_set_size(surface_t *surface, int width, int height) {
surface->width = width;
surface->height = height;
void draw_util_surface_set_size(surface_t *surface, int width, int height) {
surface->width = width;
surface->height = height;
cairo_xcb_surface_set_size(surface->surface, width, height);
cairo_xcb_surface_set_size(surface->surface, width, height);
static void draw_util_set_source_color(xcb_connection_t *conn, surface_t *surface, color_t color) {
RETURN_UNLESS_SURFACE_INITIALIZED(surface);
static void draw_util_set_source_color(xcb_connection_t *conn, surface_t *surface, color_t color) {
RETURN_UNLESS_SURFACE_INITIALIZED(surface);
cairo_set_source_rgba(surface->cr, color.red, color.green, color.blue, color.alpha);
cairo_set_source_rgba(surface->cr, color.red, color.green, color.blue, color.alpha);
-#else
- uint32_t colorpixel = color.colorpixel;
- xcb_change_gc(conn, surface->gc, XCB_GC_FOREGROUND | XCB_GC_BACKGROUND,
- (uint32_t[]){colorpixel, colorpixel});
-#endif
void draw_util_text(i3String *text, surface_t *surface, color_t fg_color, color_t bg_color, int x, int y, int max_width) {
RETURN_UNLESS_SURFACE_INITIALIZED(surface);
void draw_util_text(i3String *text, surface_t *surface, color_t fg_color, color_t bg_color, int x, int y, int max_width) {
RETURN_UNLESS_SURFACE_INITIALIZED(surface);
/* Flush any changes before we draw the text as this might use XCB directly. */
CAIRO_SURFACE_FLUSH(surface->surface);
/* Flush any changes before we draw the text as this might use XCB directly. */
CAIRO_SURFACE_FLUSH(surface->surface);
set_font_colors(surface->gc, fg_color, bg_color);
draw_text(text, surface->id, surface->gc, surface->visual_type, x, y, max_width);
set_font_colors(surface->gc, fg_color, bg_color);
draw_text(text, surface->id, surface->gc, surface->visual_type, x, y, max_width);
/* Notify cairo that we (possibly) used another way to draw on the surface. */
cairo_surface_mark_dirty(surface->surface);
/* Notify cairo that we (possibly) used another way to draw on the surface. */
cairo_surface_mark_dirty(surface->surface);
void draw_util_rectangle(xcb_connection_t *conn, surface_t *surface, color_t color, double x, double y, double w, double h) {
RETURN_UNLESS_SURFACE_INITIALIZED(surface);
void draw_util_rectangle(xcb_connection_t *conn, surface_t *surface, color_t color, double x, double y, double w, double h) {
RETURN_UNLESS_SURFACE_INITIALIZED(surface);
cairo_save(surface->cr);
/* Using the SOURCE operator will copy both color and alpha information directly
cairo_save(surface->cr);
/* Using the SOURCE operator will copy both color and alpha information directly
CAIRO_SURFACE_FLUSH(surface->surface);
cairo_restore(surface->cr);
CAIRO_SURFACE_FLUSH(surface->surface);
cairo_restore(surface->cr);
-#else
- draw_util_set_source_color(conn, surface, color);
-
- xcb_rectangle_t rect = {x, y, w, h};
- xcb_poly_fill_rectangle(conn, surface->id, surface->gc, 1, &rect);
-#endif
void draw_util_clear_surface(xcb_connection_t *conn, surface_t *surface, color_t color) {
RETURN_UNLESS_SURFACE_INITIALIZED(surface);
void draw_util_clear_surface(xcb_connection_t *conn, surface_t *surface, color_t color) {
RETURN_UNLESS_SURFACE_INITIALIZED(surface);
cairo_save(surface->cr);
/* Using the SOURCE operator will copy both color and alpha information directly
cairo_save(surface->cr);
/* Using the SOURCE operator will copy both color and alpha information directly
CAIRO_SURFACE_FLUSH(surface->surface);
cairo_restore(surface->cr);
CAIRO_SURFACE_FLUSH(surface->surface);
cairo_restore(surface->cr);
-#else
- draw_util_set_source_color(conn, surface, color);
-
- xcb_rectangle_t rect = {0, 0, surface->width, surface->height};
- xcb_poly_fill_rectangle(conn, surface->id, surface->gc, 1, &rect);
-#endif
RETURN_UNLESS_SURFACE_INITIALIZED(src);
RETURN_UNLESS_SURFACE_INITIALIZED(dest);
RETURN_UNLESS_SURFACE_INITIALIZED(src);
RETURN_UNLESS_SURFACE_INITIALIZED(dest);
cairo_save(dest->cr);
/* Using the SOURCE operator will copy both color and alpha information directly
cairo_save(dest->cr);
/* Using the SOURCE operator will copy both color and alpha information directly
CAIRO_SURFACE_FLUSH(dest->surface);
cairo_restore(dest->cr);
CAIRO_SURFACE_FLUSH(dest->surface);
cairo_restore(dest->cr);
-#else
- xcb_copy_area(conn, src->id, dest->id, dest->gc, (int16_t)src_x, (int16_t)src_y,
- (int16_t)dest_x, (int16_t)dest_y, (uint16_t)width, (uint16_t)height);
-#endif
#include <err.h>
#include <cairo/cairo-xcb.h>
#include <err.h>
#include <cairo/cairo-xcb.h>
#include <pango/pangocairo.h>
#include <pango/pangocairo.h>
#include "libi3.h"
static const i3Font *savedFont = NULL;
#include "libi3.h"
static const i3Font *savedFont = NULL;
static xcb_visualtype_t *root_visual_type;
static double pango_font_red;
static double pango_font_green;
static xcb_visualtype_t *root_visual_type;
static double pango_font_red;
static double pango_font_green;
/*
* Loads a font for usage, also getting its metrics. If fallback is true,
/*
* Loads a font for usage, also getting its metrics. If fallback is true,
/* Try to load a pango font if specified */
if (strlen(pattern) > strlen("pango:") && !strncmp(pattern, "pango:", strlen("pango:"))) {
const char *font_pattern = pattern + strlen("pango:");
/* Try to load a pango font if specified */
if (strlen(pattern) > strlen("pango:") && !strncmp(pattern, "pango:", strlen("pango:"))) {
const char *font_pattern = pattern + strlen("pango:");
/* Send all our requests first */
font.specific.xcb.id = xcb_generate_id(conn);
/* Send all our requests first */
font.specific.xcb.id = xcb_generate_id(conn);
free(savedFont->specific.xcb.info);
break;
}
free(savedFont->specific.xcb.info);
break;
}
case FONT_TYPE_PANGO:
/* Free the font description */
pango_font_description_free(savedFont->specific.pango_desc);
break;
case FONT_TYPE_PANGO:
/* Free the font description */
pango_font_description_free(savedFont->specific.pango_desc);
break;
default:
assert(false);
break;
default:
assert(false);
break;
xcb_change_gc(conn, gc, mask, values);
break;
}
xcb_change_gc(conn, gc, mask, values);
break;
}
case FONT_TYPE_PANGO:
/* Save the foreground font */
pango_font_red = foreground.red;
pango_font_green = foreground.green;
pango_font_blue = foreground.blue;
break;
case FONT_TYPE_PANGO:
/* Save the foreground font */
pango_font_red = foreground.red;
pango_font_green = foreground.green;
pango_font_blue = foreground.blue;
break;
default:
assert(false);
break;
default:
assert(false);
break;
*
*/
bool font_is_pango(void) {
*
*/
bool font_is_pango(void) {
return savedFont->type == FONT_TYPE_PANGO;
return savedFont->type == FONT_TYPE_PANGO;
-#else
- return false;
-#endif
}
static int predict_text_width_xcb(const xcb_char2b_t *text, size_t text_len);
}
static int predict_text_width_xcb(const xcb_char2b_t *text, size_t text_len);
void draw_text(i3String *text, xcb_drawable_t drawable, xcb_gcontext_t gc,
xcb_visualtype_t *visual, int x, int y, int max_width) {
assert(savedFont != NULL);
void draw_text(i3String *text, xcb_drawable_t drawable, xcb_gcontext_t gc,
xcb_visualtype_t *visual, int x, int y, int max_width) {
assert(savedFont != NULL);
if (visual == NULL) {
visual = root_visual_type;
}
if (visual == NULL) {
visual = root_visual_type;
}
switch (savedFont->type) {
case FONT_TYPE_NONE:
switch (savedFont->type) {
case FONT_TYPE_NONE:
draw_text_xcb(i3string_as_ucs2(text), i3string_get_num_glyphs(text),
drawable, gc, x, y, max_width);
break;
draw_text_xcb(i3string_as_ucs2(text), i3string_get_num_glyphs(text),
drawable, gc, x, y, max_width);
break;
case FONT_TYPE_PANGO:
/* Render the text using Pango */
draw_text_pango(i3string_as_utf8(text), i3string_get_num_bytes(text),
drawable, visual, x, y, max_width, i3string_is_markup(text));
return;
case FONT_TYPE_PANGO:
/* Render the text using Pango */
draw_text_pango(i3string_as_utf8(text), i3string_get_num_bytes(text),
drawable, visual, x, y, max_width, i3string_is_markup(text));
return;
default:
assert(false);
}
default:
assert(false);
}
case FONT_TYPE_PANGO:
/* Render the text using Pango */
draw_text_pango(text, strlen(text),
drawable, root_visual_type, x, y, max_width, false);
return;
case FONT_TYPE_PANGO:
/* Render the text using Pango */
draw_text_pango(text, strlen(text),
drawable, root_visual_type, x, y, max_width, false);
return;
default:
assert(false);
}
default:
assert(false);
}
return 0;
case FONT_TYPE_XCB:
return predict_text_width_xcb(i3string_as_ucs2(text), i3string_get_num_glyphs(text));
return 0;
case FONT_TYPE_XCB:
return predict_text_width_xcb(i3string_as_ucs2(text), i3string_get_num_glyphs(text));
case FONT_TYPE_PANGO:
/* Calculate extents using Pango */
return predict_text_width_pango(i3string_as_utf8(text), i3string_get_num_bytes(text),
i3string_is_markup(text));
case FONT_TYPE_PANGO:
/* Calculate extents using Pango */
return predict_text_width_pango(i3string_as_utf8(text), i3string_get_num_bytes(text),
i3string_is_markup(text));
default:
assert(false);
return 0;
default:
assert(false);
return 0;
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <string.h>
* Escape pango markup characters in the given string.
*/
i3String *i3string_escape_markup(i3String *str) {
* Escape pango markup characters in the given string.
*/
i3String *i3string_escape_markup(i3String *str) {
const char *text = i3string_as_utf8(str);
char *escaped = g_markup_escape_text(text, -1);
i3String *result = i3string_from_utf8(escaped);
free(escaped);
return result;
const char *text = i3string_as_utf8(str);
char *escaped = g_markup_escape_text(text, -1);
i3String *result = i3string_from_utf8(escaped);
free(escaped);
return result;
-#else
- return str;
-#endif
if (!font_is_pango())
return input;
if (!font_is_pango())
return input;
char *escaped = g_markup_escape_text(input, -1);
FREE(input);
return escaped;
char *escaped = g_markup_escape_text(input, -1);
FREE(input);
return escaped;