Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on May 5th, 2012  |  syntax: Diff  |  size: 29.04 KB  |  hits: 20  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. From c52f74124c4c60c074b5a6e4524ca34dd6fd308d Mon Sep 17 00:00:00 2001
  2. From: =?UTF-8?q?Fernando=20Tarl=C3=A1=20Cardoso=20Lemos?=
  3.  <fernandotcl@gmail.com>
  4. Date: Mon, 14 Nov 2011 21:39:03 -0200
  5. Subject: [PATCH 1/2] Implement Pango rendering.
  6.  
  7. ---
  8. common.mk               |    9 ++
  9.  i3-config-wizard/main.c |    2 +
  10.  i3-input/main.c         |    2 +
  11.  i3-nagbar/main.c        |    2 +
  12.  i3bar/src/xcb.c         |   30 +++---
  13.  include/libi3.h         |   42 ++++++--
  14.  libi3/font.c            |  258 ++++++++++++++++++++++++++++++++++++++++++-----
  15.  libi3/get_visualtype.c  |   24 +++++
  16.  src/config.c            |    2 +-
  17.  src/main.c              |    2 +
  18.  src/xcb.c               |   10 +-
  19.  11 files changed, 331 insertions(+), 52 deletions(-)
  20.  create mode 100644 libi3/get_visualtype.c
  21.  
  22. diff --git a/common.mk b/common.mk
  23. index 4394905..a09e496 100644
  24. --- a/common.mk
  25. +++ b/common.mk
  26. @@ -92,6 +92,15 @@ LIBS += $(call ldflags_for_lib, libev,ev)
  27.  LIBS += $(call ldflags_for_lib, libpcre,pcre)
  28.  LIBS += $(call ldflags_for_lib, libstartup-notification-1.0,startup-notification-1)
  29.  
  30. +# Enable Pango support if available
  31. +ifeq ($(shell pkg-config --exists cairo pangocairo && echo 1),1)
  32. +CPPFLAGS += -DPANGO_SUPPORT=1
  33. +CFLAGS += $(shell pkg-config --cflags cairo pangocairo)
  34. +LIBS += $(shell pkg-config --libs cairo pangocairo)
  35. +else
  36. +CPPFLAGS += -DPANGO_SUPPORT=0
  37. +endif
  38. +
  39.  # Please test if -Wl,--as-needed works on your platform and send me a patch.
  40.  # it is known not to work on Darwin (Mac OS X)
  41.  ifneq (,$(filter Linux GNU GNU/%, $(UNAME)))
  42. diff --git a/i3-config-wizard/main.c b/i3-config-wizard/main.c
  43. index be04267..a5b9ed5 100644
  44. --- a/i3-config-wizard/main.c
  45. +++ b/i3-config-wizard/main.c
  46. @@ -77,6 +77,7 @@ static xcb_window_t win;
  47.  static xcb_pixmap_t pixmap;
  48.  static xcb_gcontext_t pixmap_gc;
  49.  static xcb_key_symbols_t *symbols;
  50. +xcb_visualtype_t *root_visual_type;
  51.  xcb_window_t root;
  52.  Display *dpy;
  53.  
  54. @@ -457,6 +458,7 @@ int main(int argc, char *argv[]) {
  55.      #undef xmacro
  56.  
  57.      xcb_screen_t *root_screen = xcb_aux_get_screen(conn, screens);
  58. +    root_visual_type = get_visualtype(root_screen);
  59.      root = root_screen->root;
  60.  
  61.      if (!(modmap_reply = xcb_get_modifier_mapping_reply(conn, modmap_cookie, NULL)))
  62. diff --git a/i3-input/main.c b/i3-input/main.c
  63. index b570952..2f88052 100644
  64. --- a/i3-input/main.c
  65. +++ b/i3-input/main.c
  66. @@ -52,6 +52,7 @@ static i3Font font;
  67.  static char *prompt;
  68.  static size_t prompt_len;
  69.  static int limit;
  70. +xcb_visualtype_t *root_visual_type;
  71.  xcb_window_t root;
  72.  xcb_connection_t *conn;
  73.  
  74. @@ -358,6 +359,7 @@ int main(int argc, char *argv[]) {
  75.          die("Cannot open display\n");
  76.  
  77.      xcb_screen_t *root_screen = xcb_aux_get_screen(conn, screens);
  78. +    root_visual_type = get_visualtype(root_screen);
  79.      root = root_screen->root;
  80.  
  81.      symbols = xcb_key_symbols_alloc(conn);
  82. diff --git a/i3-nagbar/main.c b/i3-nagbar/main.c
  83. index 1dbd773..1bdb8d6 100644
  84. --- a/i3-nagbar/main.c
  85. +++ b/i3-nagbar/main.c
  86. @@ -52,6 +52,7 @@ static uint32_t color_border;            /* color of the button border */
  87.  static uint32_t color_border_bottom;     /* color of the bottom border */
  88.  static uint32_t color_text;              /* color of the text */
  89.  
  90. +xcb_visualtype_t *root_visual_type;
  91.  xcb_window_t root;
  92.  xcb_connection_t *conn;
  93.  
  94. @@ -281,6 +282,7 @@ int main(int argc, char *argv[]) {
  95.      #undef xmacro
  96.  
  97.      xcb_screen_t *root_screen = xcb_aux_get_screen(conn, screens);
  98. +    root_visual_type = get_visualtype(root_screen);
  99.      root = root_screen->root;
  100.  
  101.      if (bar_type == TYPE_ERROR) {
  102. diff --git a/i3bar/src/xcb.c b/i3bar/src/xcb.c
  103. index 87926d3..683c6b6 100644
  104. --- a/i3bar/src/xcb.c
  105. +++ b/i3bar/src/xcb.c
  106. @@ -48,10 +48,11 @@ xcb_atom_t               atoms[NUM_ATOMS];
  107.  xcb_connection_t *xcb_connection;
  108.  int              screen;
  109.  xcb_screen_t     *xcb_screen;
  110. -xcb_window_t     xcb_root;
  111. +xcb_window_t     root;
  112.  
  113.  /* This is needed for integration with libi3 */
  114.  xcb_connection_t *conn;
  115. +xcb_visualtype_t *root_visual_type;
  116.  
  117.  /* The font we'll use */
  118.  static i3Font font;
  119. @@ -827,7 +828,8 @@ char *init_xcb_early() {
  120.      #include "xcb_atoms.def"
  121.  
  122.      xcb_screen = xcb_aux_get_screen(xcb_connection, screen);
  123. -    xcb_root = xcb_screen->root;
  124. +    root_visual_type = get_visualtype(xcb_screen);
  125. +    root = xcb_screen->root;
  126.  
  127.      /* We draw the statusline to a seperate pixmap, because it looks the same on all bars and
  128.       * this way, we can choose to crop it */
  129. @@ -837,14 +839,14 @@ char *init_xcb_early() {
  130.      statusline_clear = xcb_generate_id(xcb_connection);
  131.      xcb_void_cookie_t clear_ctx_cookie = xcb_create_gc_checked(xcb_connection,
  132.                                                                 statusline_clear,
  133. -                                                               xcb_root,
  134. +                                                               root,
  135.                                                                 mask,
  136.                                                                 vals);
  137.  
  138.      statusline_ctx = xcb_generate_id(xcb_connection);
  139.      xcb_void_cookie_t sl_ctx_cookie = xcb_create_gc_checked(xcb_connection,
  140.                                                              statusline_ctx,
  141. -                                                            xcb_root,
  142. +                                                            root,
  143.                                                              0,
  144.                                                              NULL);
  145.  
  146. @@ -852,7 +854,7 @@ char *init_xcb_early() {
  147.      xcb_void_cookie_t sl_pm_cookie = xcb_create_pixmap_checked(xcb_connection,
  148.                                                                 xcb_screen->root_depth,
  149.                                                                 statusline_pm,
  150. -                                                               xcb_root,
  151. +                                                               root,
  152.                                                                 xcb_screen->width_in_pixels,
  153.                                                                 xcb_screen->height_in_pixels);
  154.  
  155. @@ -876,7 +878,7 @@ char *init_xcb_early() {
  156.      xcb_get_property_cookie_t path_cookie;
  157.      path_cookie = xcb_get_property_unchecked(xcb_connection,
  158.                                     0,
  159. -                                   xcb_root,
  160. +                                   root,
  161.                                     atoms[I3_SOCKET_PATH],
  162.                                     XCB_GET_PROPERTY_TYPE_ANY,
  163.                                     0, PATH_MAX);
  164. @@ -984,7 +986,7 @@ void init_tray() {
  165.      xcb_create_window(xcb_connection,
  166.                        xcb_screen->root_depth,
  167.                        selwin,
  168. -                      xcb_root,
  169. +                      root,
  170.                        -1, -1,
  171.                        1, 1,
  172.                        1,
  173. @@ -1037,7 +1039,7 @@ void init_tray() {
  174.      void *event = scalloc(32);
  175.      xcb_client_message_event_t *ev = event;
  176.      ev->response_type = XCB_CLIENT_MESSAGE;
  177. -    ev->window = xcb_root;
  178. +    ev->window = root;
  179.      ev->type = atoms[MANAGER];
  180.      ev->format = 32;
  181.      ev->data.data32[0] = XCB_CURRENT_TIME;
  182. @@ -1045,7 +1047,7 @@ void init_tray() {
  183.      ev->data.data32[2] = selwin;
  184.      xcb_send_event(xcb_connection,
  185.                     0,
  186. -                   xcb_root,
  187. +                   root,
  188.                     XCB_EVENT_MASK_STRUCTURE_NOTIFY,
  189.                     (char*)ev);
  190.      free(event);
  191. @@ -1116,7 +1118,7 @@ void kick_tray_clients(i3_output *output) {
  192.          xcb_unmap_window(xcb_connection, trayclient->win);
  193.          xcb_reparent_window(xcb_connection,
  194.                              trayclient->win,
  195. -                            xcb_root,
  196. +                            root,
  197.                              0,
  198.                              0);
  199.  
  200. @@ -1155,7 +1157,7 @@ void realloc_sl_buffer() {
  201.      xcb_void_cookie_t sl_pm_cookie = xcb_create_pixmap_checked(xcb_connection,
  202.                                                                 xcb_screen->root_depth,
  203.                                                                 statusline_pm,
  204. -                                                               xcb_root,
  205. +                                                               root,
  206.                                                                 MAX(xcb_screen->width_in_pixels, statusline_width),
  207.                                                                 xcb_screen->height_in_pixels);
  208.  
  209. @@ -1165,7 +1167,7 @@ void realloc_sl_buffer() {
  210.      statusline_clear = xcb_generate_id(xcb_connection);
  211.      xcb_void_cookie_t clear_ctx_cookie = xcb_create_gc_checked(xcb_connection,
  212.                                                                 statusline_clear,
  213. -                                                               xcb_root,
  214. +                                                               root,
  215.                                                                 mask,
  216.                                                                 vals);
  217.  
  218. @@ -1175,7 +1177,7 @@ void realloc_sl_buffer() {
  219.      xcb_free_gc(xcb_connection, statusline_ctx);
  220.      xcb_void_cookie_t sl_ctx_cookie = xcb_create_gc_checked(xcb_connection,
  221.                                                              statusline_ctx,
  222. -                                                            xcb_root,
  223. +                                                            root,
  224.                                                              mask,
  225.                                                              vals);
  226.  
  227. @@ -1229,7 +1231,7 @@ void reconfig_windows() {
  228.              xcb_void_cookie_t win_cookie = xcb_create_window_checked(xcb_connection,
  229.                                                                       xcb_screen->root_depth,
  230.                                                                       walk->bar,
  231. -                                                                     xcb_root,
  232. +                                                                     root,
  233.                                                                       walk->rect.x, walk->rect.y + walk->rect.h - font.height - 6,
  234.                                                                       walk->rect.w, font.height + 6,
  235.                                                                       1,
  236. diff --git a/include/libi3.h b/include/libi3.h
  237. index b88bcb6..1de92d4 100644
  238. --- a/include/libi3.h
  239. +++ b/include/libi3.h
  240. @@ -18,6 +18,10 @@
  241.  #include <xcb/xproto.h>
  242.  #include <xcb/xcb_keysyms.h>
  243.  
  244. +#if PANGO_SUPPORT
  245. +#include <pango/pango.h>
  246. +#endif
  247. +
  248.  typedef struct Font i3Font;
  249.  
  250.  /**
  251. @@ -27,17 +31,33 @@ typedef struct Font i3Font;
  252.   *
  253.   */
  254.  struct Font {
  255. -    /** The xcb-id for the font */
  256. -    xcb_font_t id;
  257. -
  258. -    /** Font information gathered from the server */
  259. -    xcb_query_font_reply_t *info;
  260. -
  261. -    /** Font table for this font (may be NULL) */
  262. -    xcb_charinfo_t *table;
  263. +    /** The type of font */
  264. +    enum {
  265. +        FONT_TYPE_NONE = 0,
  266. +        FONT_TYPE_XCB,
  267. +        FONT_TYPE_PANGO
  268. +    } type;
  269.  
  270.      /** The height of the font, built from font_ascent + font_descent */
  271.      int height;
  272. +
  273. +    union {
  274. +        struct {
  275. +            /** The xcb-id for the font */
  276. +            xcb_font_t id;
  277. +
  278. +            /** Font information gathered from the server */
  279. +            xcb_query_font_reply_t *info;
  280. +
  281. +            /** Font table for this font (may be NULL) */
  282. +            xcb_charinfo_t *table;
  283. +        } xcb;
  284. +
  285. +#if PANGO_SUPPORT
  286. +        /** The pango font description */
  287. +        PangoFontDescription *pango_desc;
  288. +#endif
  289. +    } specific;
  290.  };
  291.  
  292.  /* Since this file also gets included by utilities which don’t use the i3 log
  293. @@ -242,4 +262,10 @@ void draw_text(char *text, size_t text_len, bool is_ucs2, xcb_drawable_t drawabl
  294.   */
  295.  int predict_text_width(char *text, size_t text_len, bool is_ucs2);
  296.  
  297. +/*
  298. + * Returns the visual type associated with the given screen.
  299. + *
  300. + */
  301. +xcb_visualtype_t *get_visualtype(xcb_screen_t *s);
  302. +
  303.  #endif
  304. diff --git a/libi3/font.c b/libi3/font.c
  305. index 0b276b0..88ee915 100644
  306. --- a/libi3/font.c
  307. +++ b/libi3/font.c
  308. @@ -12,11 +12,131 @@
  309.  #include <stdbool.h>
  310.  #include <err.h>
  311.  
  312. +#if PANGO_SUPPORT
  313. +#include <cairo/cairo-xcb.h>
  314. +#include <pango/pangocairo.h>
  315. +#endif
  316. +
  317.  #include "libi3.h"
  318.  
  319.  extern xcb_connection_t *conn;
  320. +extern xcb_visualtype_t *root_visual_type;
  321. +extern xcb_window_t root;
  322. +
  323.  static const i3Font *savedFont = NULL;
  324.  
  325. +#if PANGO_SUPPORT
  326. +static double pango_font_red;
  327. +static double pango_font_green;
  328. +static double pango_font_blue;
  329. +
  330. +/*
  331. + * Loads a Pango font description into an i3Font structure. Returns true
  332. + * on success, false otherwise.
  333. + *
  334. + */
  335. +static bool load_pango_font(i3Font *font, const char *desc) {
  336. +    /* Load the font description */
  337. +    font->specific.pango_desc = pango_font_description_from_string(desc);
  338. +    if (!font->specific.pango_desc)
  339. +        return false;
  340. +
  341. +    /* Create a dummy Pango layout */
  342. +    cairo_surface_t *surface = cairo_xcb_surface_create(conn, root, root_visual_type, 100, 100);
  343. +    cairo_t *cr = cairo_create(surface);
  344. +    PangoLayout *layout = pango_cairo_create_layout(cr);
  345. +    pango_layout_set_font_description(layout, font->specific.pango_desc);
  346. +
  347. +    /* Get the font height */
  348. +    gint height;
  349. +    pango_layout_get_pixel_size(layout, NULL, &height);
  350. +    font->height = height;
  351. +
  352. +    /* Free resources */
  353. +    g_object_unref(layout);
  354. +    cairo_destroy(cr);
  355. +    cairo_surface_destroy(surface);
  356. +
  357. +    /* Set the font type and return successfully */
  358. +    font->type = FONT_TYPE_PANGO;
  359. +    return true;
  360. +}
  361. +
  362. +/*
  363. + * Draws text using Pango rendering.
  364. + *
  365. + */
  366. +void draw_text_pango(char *text, size_t text_len, bool is_ucs2,
  367. +        xcb_drawable_t drawable, int x, int y, int max_width) {
  368. +    /* Create the Pango layout */
  369. +    cairo_surface_t *surface = cairo_xcb_surface_create(conn, drawable,
  370. +            root_visual_type, x + max_width, y + savedFont->height);
  371. +    cairo_t *cr = cairo_create(surface);
  372. +    PangoLayout *layout = pango_cairo_create_layout(cr);
  373. +    pango_layout_set_font_description(layout, savedFont->specific.pango_desc);
  374. +    pango_layout_set_width(layout, max_width * PANGO_SCALE);
  375. +    pango_layout_set_wrap(layout, PANGO_WRAP_CHAR);
  376. +    pango_layout_set_ellipsize(layout, PANGO_ELLIPSIZE_END);
  377. +
  378. +    /* If the text is UCS-2, convert it to UTF-8 and get the number
  379. +     * of bytes into text_len */
  380. +    if (is_ucs2) {
  381. +        text = convert_ucs2_to_utf8((xcb_char2b_t*)text, text_len);
  382. +        if (!text)
  383. +            return;
  384. +        text_len = strlen(text);
  385. +    }
  386. +
  387. +    /* Do the drawing */
  388. +    cairo_set_source_rgb(cr, pango_font_red, pango_font_green, pango_font_blue);
  389. +    cairo_move_to(cr, x, y);
  390. +    pango_layout_set_text(layout, text, text_len);
  391. +    pango_cairo_update_layout(cr, layout);
  392. +    pango_cairo_show_layout(cr, layout);
  393. +
  394. +    /* Free resources */
  395. +    g_object_unref(layout);
  396. +    cairo_destroy(cr);
  397. +    cairo_surface_destroy(surface);
  398. +    if (is_ucs2)
  399. +        free(text);
  400. +}
  401. +
  402. +/*
  403. + * Calculate the text width using Pango rendering.
  404. + *
  405. + */
  406. +int predict_text_width_pango(char *text, size_t text_len, bool is_ucs2) {
  407. +    /* If the text is UCS-2, convert it to UTF-8 */
  408. +    if (is_ucs2) {
  409. +        text = convert_ucs2_to_utf8((xcb_char2b_t*)text, text_len);
  410. +        if (!text)
  411. +            return 10 * text_len;
  412. +    }
  413. +
  414. +    /* Create a dummy Pango layout */
  415. +    cairo_surface_t *surface = cairo_xcb_surface_create(conn, root, root_visual_type, 100, 100);
  416. +    cairo_t *cr = cairo_create(surface);
  417. +    PangoLayout *layout = pango_cairo_create_layout(cr);
  418. +
  419. +    /* Get the font height */
  420. +    gint width;
  421. +    pango_layout_set_font_description(layout, savedFont->specific.pango_desc);
  422. +    pango_layout_set_text(layout, text, text_len);
  423. +    pango_cairo_update_layout(cr, layout);
  424. +    pango_layout_get_pixel_size(layout, &width, NULL);
  425. +
  426. +    /* Free resources */
  427. +    g_object_unref(layout);
  428. +    cairo_destroy(cr);
  429. +    cairo_surface_destroy(surface);
  430. +    if (is_ucs2)
  431. +        free(text);
  432. +
  433. +    return width;
  434. +}
  435. +#endif
  436. +
  437.  /*
  438.   * Loads a font for usage, also getting its metrics. If fallback is true,
  439.   * the fonts 'fixed' or '-misc-*' will be loaded instead of exiting.
  440. @@ -24,12 +144,22 @@ static const i3Font *savedFont = NULL;
  441.   */
  442.  i3Font load_font(const char *pattern, const bool fallback) {
  443.      i3Font font;
  444. +    font.type = FONT_TYPE_NONE;
  445. +
  446. +#if PANGO_SUPPORT
  447. +    /* Try to load a pango font if specified */
  448. +    if (strlen(pattern) > 6 && !strncmp(pattern, "xft:", 4)) {
  449. +        pattern += 4;
  450. +        if (load_pango_font(&font, pattern))
  451. +            return font;
  452. +    }
  453. +#endif
  454.  
  455.      /* Send all our requests first */
  456. -    font.id = xcb_generate_id(conn);
  457. -    xcb_void_cookie_t font_cookie = xcb_open_font_checked(conn, font.id,
  458. +    font.specific.xcb.id = xcb_generate_id(conn);
  459. +    xcb_void_cookie_t font_cookie = xcb_open_font_checked(conn, font.specific.xcb.id,
  460.              strlen(pattern), pattern);
  461. -    xcb_query_font_cookie_t info_cookie = xcb_query_font(conn, font.id);
  462. +    xcb_query_font_cookie_t info_cookie = xcb_query_font(conn, font.specific.xcb.id);
  463.  
  464.      /* Check for errors. If errors, fall back to default font. */
  465.      xcb_generic_error_t *error;
  466. @@ -40,8 +170,9 @@ i3Font load_font(const char *pattern, const bool fallback) {
  467.          ELOG("Could not open font %s (X error %d). Trying fallback to 'fixed'.\n",
  468.               pattern, error->error_code);
  469.          pattern = "fixed";
  470. -        font_cookie = xcb_open_font_checked(conn, font.id, strlen(pattern), pattern);
  471. -        info_cookie = xcb_query_font(conn, font.id);
  472. +        font_cookie = xcb_open_font_checked(conn, font.specific.xcb.id,
  473. +                strlen(pattern), pattern);
  474. +        info_cookie = xcb_query_font(conn, font.specific.xcb.id);
  475.  
  476.          /* Check if we managed to open 'fixed' */
  477.          error = xcb_request_check(conn, font_cookie);
  478. @@ -50,8 +181,9 @@ i3Font load_font(const char *pattern, const bool fallback) {
  479.          if (error != NULL) {
  480.              ELOG("Could not open fallback font 'fixed', trying with '-misc-*'.\n");
  481.              pattern = "-misc-*";
  482. -            font_cookie = xcb_open_font_checked(conn, font.id, strlen(pattern), pattern);
  483. -            info_cookie = xcb_query_font(conn, font.id);
  484. +            font_cookie = xcb_open_font_checked(conn, font.specific.xcb.id,
  485. +                    strlen(pattern), pattern);
  486. +            info_cookie = xcb_query_font(conn, font.specific.xcb.id);
  487.  
  488.              if ((error = xcb_request_check(conn, font_cookie)) != NULL)
  489.                  errx(EXIT_FAILURE, "Could open neither requested font nor fallbacks "
  490. @@ -60,18 +192,20 @@ i3Font load_font(const char *pattern, const bool fallback) {
  491.      }
  492.  
  493.      /* Get information (height/name) for this font */
  494. -    if (!(font.info = xcb_query_font_reply(conn, info_cookie, NULL)))
  495. +    if (!(font.specific.xcb.info = xcb_query_font_reply(conn, info_cookie, NULL)))
  496.          errx(EXIT_FAILURE, "Could not load font \"%s\"", pattern);
  497.  
  498.      /* Get the font table, if possible */
  499. -    if (xcb_query_font_char_infos_length(font.info) == 0)
  500. -        font.table = NULL;
  501. +    if (xcb_query_font_char_infos_length(font.specific.xcb.info) == 0)
  502. +        font.specific.xcb.table = NULL;
  503.      else
  504. -        font.table = xcb_query_font_char_infos(font.info);
  505. +        font.specific.xcb.table = xcb_query_font_char_infos(font.specific.xcb.info);
  506.  
  507.      /* Calculate the font height */
  508. -    font.height = font.info->font_ascent + font.info->font_descent;
  509. +    font.height = font.specific.xcb.info->font_ascent + font.specific.xcb.info->font_descent;
  510.  
  511. +    /* Set the font type and return successfully */
  512. +    font.type = FONT_TYPE_XCB;
  513.      return font;
  514.  }
  515.  
  516. @@ -88,10 +222,27 @@ void set_font(i3Font *font) {
  517.   *
  518.   */
  519.  void free_font(void) {
  520. -    /* Close the font and free the info */
  521. -    xcb_close_font(conn, savedFont->id);
  522. -    if (savedFont->info)
  523. -        free(savedFont->info);
  524. +    switch (savedFont->type) {
  525. +        case FONT_TYPE_NONE:
  526. +            /* Nothing to do */
  527. +            break;
  528. +        case FONT_TYPE_XCB: {
  529. +            /* Close the font and free the info */
  530. +            xcb_close_font(conn, savedFont->specific.xcb.id);
  531. +            if (savedFont->specific.xcb.info)
  532. +                free(savedFont->specific.xcb.info);
  533. +            break;
  534. +        }
  535. +#if PANGO_SUPPORT
  536. +        case FONT_TYPE_PANGO:
  537. +            /* Free the font description */
  538. +            pango_font_description_free(savedFont->specific.pango_desc);
  539. +            break;
  540. +#endif
  541. +        default:
  542. +            assert(false);
  543. +            break;
  544. +    }
  545.  }
  546.  
  547.  /*
  548. @@ -100,9 +251,30 @@ void free_font(void) {
  549.   */
  550.  void set_font_colors(xcb_gcontext_t gc, uint32_t foreground, uint32_t background) {
  551.      assert(savedFont != NULL);
  552. -    uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
  553. -    uint32_t values[] = { foreground, background, savedFont->id };
  554. -    xcb_change_gc(conn, gc, mask, values);
  555. +
  556. +    switch (savedFont->type) {
  557. +        case FONT_TYPE_NONE:
  558. +            /* Nothing to do */
  559. +            break;
  560. +        case FONT_TYPE_XCB: {
  561. +            /* Change the font and colors in the GC */
  562. +            uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
  563. +            uint32_t values[] = { foreground, background, savedFont->specific.xcb.id };
  564. +            xcb_change_gc(conn, gc, mask, values);
  565. +            break;
  566. +        }
  567. +#if PANGO_SUPPORT
  568. +        case FONT_TYPE_PANGO:
  569. +            /* Save the foreground font */
  570. +            pango_font_red = ((foreground >> 16) & 0xff) / 255.0;
  571. +            pango_font_green = ((foreground >> 8) & 0xff) / 255.0;
  572. +            pango_font_blue = (foreground & 0xff) / 255.0;
  573. +            break;
  574. +#endif
  575. +        default:
  576. +            assert(false);
  577. +            break;
  578. +    }
  579.  }
  580.  
  581.  /*
  582. @@ -121,8 +293,25 @@ void draw_text(char *text, size_t text_len, bool is_ucs2, xcb_drawable_t drawabl
  583.      assert(savedFont != NULL);
  584.      assert(text_len != 0);
  585.  
  586. +    switch (savedFont->type) {
  587. +        case FONT_TYPE_NONE:
  588. +            /* Nothing to do */
  589. +            return;
  590. +        case FONT_TYPE_XCB:
  591. +            /* Continue below */
  592. +            break;
  593. +#if PANGO_SUPPORT
  594. +        case FONT_TYPE_PANGO:
  595. +            /* Render the text using Pango */
  596. +            draw_text_pango(text, text_len, is_ucs2, drawable, x, y, max_width);
  597. +            return;
  598. +#endif
  599. +        default:
  600. +            assert(false);
  601. +    }
  602. +
  603.      /* X11 coordinates for fonts start at the baseline */
  604. -    int pos_y = y + savedFont->info->font_ascent;
  605. +    int pos_y = y + savedFont->specific.xcb.info->font_ascent;
  606.  
  607.      /* As an optimization, check if we can bypass conversion */
  608.      if (!is_ucs2 && text_len <= 255) {
  609. @@ -173,7 +362,7 @@ static int xcb_query_text_width(xcb_char2b_t *text, size_t text_len) {
  610.      /* Query the text width */
  611.      xcb_generic_error_t *error;
  612.      xcb_query_text_extents_cookie_t cookie = xcb_query_text_extents(conn,
  613. -            savedFont->id, text_len, (xcb_char2b_t*)text);
  614. +            savedFont->specific.xcb.id, text_len, (xcb_char2b_t*)text);
  615.      xcb_query_text_extents_reply_t *reply = xcb_query_text_extents_reply(conn,
  616.              cookie, &error);
  617.      if (reply == NULL) {
  618. @@ -181,7 +370,7 @@ static int xcb_query_text_width(xcb_char2b_t *text, size_t text_len) {
  619.           * a crash. Plus, the user will see the error in his log. */
  620.          fprintf(stderr, "Could not get text extents (X error code %d)\n",
  621.                  error->error_code);
  622. -        return savedFont->info->max_bounds.character_width * text_len;
  623. +        return savedFont->specific.xcb.info->max_bounds.character_width * text_len;
  624.      }
  625.  
  626.      int width = reply->overall_width;
  627. @@ -195,6 +384,25 @@ static int xcb_query_text_width(xcb_char2b_t *text, size_t text_len) {
  628.   *
  629.   */
  630.  int predict_text_width(char *text, size_t text_len, bool is_ucs2) {
  631. +    assert(savedFont != NULL);
  632. +
  633. +    switch (savedFont->type) {
  634. +        case FONT_TYPE_NONE:
  635. +            /* Nothing to do */
  636. +            return 0;
  637. +        case FONT_TYPE_XCB:
  638. +            /* Continue below */
  639. +            break;
  640. +#if PANGO_SUPPORT
  641. +        case FONT_TYPE_PANGO:
  642. +            /* Calculate extents using Pango */
  643. +            return predict_text_width_pango(text, text_len, is_ucs2);
  644. +#endif
  645. +        default:
  646. +            assert(false);
  647. +            return 0;
  648. +    }
  649. +
  650.      /* Convert the text into UTF-16 so we can do basic pointer math */
  651.      xcb_char2b_t *input;
  652.      if (is_ucs2)
  653. @@ -203,13 +411,13 @@ int predict_text_width(char *text, size_t text_len, bool is_ucs2) {
  654.          input = convert_utf8_to_ucs2(text, &text_len);
  655.  
  656.      int width;
  657. -    if (savedFont->table == NULL) {
  658. +    if (savedFont->specific.xcb.table == NULL) {
  659.          /* If we don't have a font table, fall back to querying the server */
  660.          width = xcb_query_text_width(input, text_len);
  661.      } else {
  662.          /* Save some pointers for convenience */
  663. -        xcb_query_font_reply_t *font_info = savedFont->info;
  664. -        xcb_charinfo_t *font_table = savedFont->table;
  665. +        xcb_query_font_reply_t *font_info = savedFont->specific.xcb.info;
  666. +        xcb_charinfo_t *font_table = savedFont->specific.xcb.table;
  667.  
  668.          /* Calculate the width using the font table */
  669.          width = 0;
  670. diff --git a/libi3/get_visualtype.c b/libi3/get_visualtype.c
  671. new file mode 100644
  672. index 0000000..c639443
  673. --- /dev/null
  674. +++ b/libi3/get_visualtype.c
  675. @@ -0,0 +1,24 @@
  676. +/*
  677. + * vim:ts=4:sw=4:expandtab
  678. + *
  679. + * i3 - an improved dynamic tiling window manager
  680. + * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
  681. + *
  682. + */
  683. +#include "libi3.h"
  684. +
  685. +/*
  686. + * Returns the visual type associated with the given screen.
  687. + *
  688. + */
  689. +xcb_visualtype_t *get_visualtype(xcb_screen_t *s) {
  690. +    xcb_depth_iterator_t depth_iter = xcb_screen_allowed_depths_iterator(s);
  691. +    for (; depth_iter.rem;xcb_depth_next(&depth_iter)) {
  692. +        xcb_visualtype_iterator_t visual_iter = xcb_depth_visuals_iterator(depth_iter.data);
  693. +        for (; visual_iter.rem;xcb_visualtype_next(&visual_iter)) {
  694. +            if (s->root_visual == visual_iter.data->visual_id)
  695. +                return visual_iter.data;
  696. +        }
  697. +    }
  698. +    return NULL;
  699. +}
  700. diff --git a/src/config.c b/src/config.c
  701. index 50ec282..3542d1c 100644
  702. --- a/src/config.c
  703. +++ b/src/config.c
  704. @@ -392,7 +392,7 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath,
  705.          grab_all_keys(conn, false);
  706.      }
  707.  
  708. -    if (config.font.id == 0) {
  709. +    if (config.font.type == FONT_TYPE_NONE) {
  710.          ELOG("You did not specify required configuration option \"font\"\n");
  711.          config.font = load_font("fixed", true);
  712.          set_font(&config.font);
  713. diff --git a/src/main.c b/src/main.c
  714. index 14786d2..e3957aa 100644
  715. --- a/src/main.c
  716. +++ b/src/main.c
  717. @@ -51,6 +51,7 @@ SnDisplay *sndisplay;
  718.   * notification). */
  719.  xcb_timestamp_t last_timestamp = XCB_CURRENT_TIME;
  720.  
  721. +xcb_visualtype_t *root_visual_type;
  722.  xcb_screen_t *root_screen;
  723.  xcb_window_t root;
  724.  
  725. @@ -517,6 +518,7 @@ int main(int argc, char *argv[]) {
  726.       * usually is TrueColor (24 bit depth) and the corresponding visual.
  727.       * However, we also check if a 32 bit depth and visual are available (for
  728.       * transparency) and use it if so. */
  729. +    root_visual_type = get_visualtype(root_screen);
  730.      root_depth = root_screen->root_depth;
  731.      visual_id = root_screen->root_visual;
  732.      colormap = root_screen->default_colormap;
  733. diff --git a/src/xcb.c b/src/xcb.c
  734. index 4d7a8c4..4bc68c9 100644
  735. --- a/src/xcb.c
  736. +++ b/src/xcb.c
  737. @@ -48,8 +48,9 @@ xcb_window_t create_window(xcb_connection_t *conn, Rect dims,
  738.          xcb_cursor_t cursor_id = xcb_generate_id(conn);
  739.          i3Font cursor_font = load_font("cursor", false);
  740.          int xcb_cursor = xcursor_get_xcb_cursor(cursor);
  741. -        xcb_create_glyph_cursor(conn, cursor_id, cursor_font.id, cursor_font.id,
  742. -                xcb_cursor, xcb_cursor + 1, 0, 0, 0, 65535, 65535, 65535);
  743. +        xcb_create_glyph_cursor(conn, cursor_id, cursor_font.specific.xcb.id,
  744. +                cursor_font.specific.xcb.id, xcb_cursor, xcb_cursor + 1, 0, 0, 0,
  745. +                65535, 65535, 65535);
  746.          xcb_change_window_attributes(conn, result, XCB_CW_CURSOR, &cursor_id);
  747.          xcb_free_cursor(conn, cursor_id);
  748.      }
  749. @@ -193,8 +194,9 @@ void xcb_set_root_cursor(int cursor) {
  750.      xcb_cursor_t cursor_id = xcb_generate_id(conn);
  751.      i3Font cursor_font = load_font("cursor", false);
  752.      int xcb_cursor = xcursor_get_xcb_cursor(cursor);
  753. -    xcb_create_glyph_cursor(conn, cursor_id, cursor_font.id, cursor_font.id,
  754. -            xcb_cursor, xcb_cursor + 1, 0, 0, 0, 65535, 65535, 65535);
  755. +    xcb_create_glyph_cursor(conn, cursor_id, cursor_font.specific.xcb.id,
  756. +            cursor_font.specific.xcb.id, xcb_cursor, xcb_cursor + 1, 0, 0, 0,
  757. +            65535, 65535, 65535);
  758.      xcb_change_window_attributes(conn, root, XCB_CW_CURSOR, &cursor_id);
  759.      xcb_free_cursor(conn, cursor_id);
  760.      xcb_flush(conn);
  761. --
  762. 1.7.10