Advertisement
Guest User

Untitled

a guest
Feb 19th, 2012
209
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 29.30 KB | None | 0 0
  1. From 31329bf7791219aa667dc5d14388ba1f34a3c27f 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            |  256 ++++++++++++++++++++++++++++++++++++++++++-----
  15.  libi3/get_visualtype.c  |   24 +++++
  16.  src/config.c            |    2 +-
  17.  src/main.c              |    3 +
  18.  src/xcb.c               |   10 +-
  19.  11 files changed, 330 insertions(+), 52 deletions(-)
  20.  create mode 100644 libi3/get_visualtype.c
  21.  
  22. diff --git a/common.mk b/common.mk
  23. index 537d4dd..71ed531 100644
  24. --- a/common.mk
  25. +++ b/common.mk
  26. @@ -89,6 +89,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 cf55c38..fd4eef6 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 a3312ca..8d2a6f7 100644
  104. --- a/i3bar/src/xcb.c
  105. +++ b/i3bar/src/xcb.c
  106. @@ -47,10 +47,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. @@ -811,7 +812,8 @@ char *init_xcb_early() {
  120.      #include "xcb_atoms.def"
  121.  
  122.      xcb_screen = xcb_setup_roots_iterator(xcb_get_setup(xcb_connection)).data;
  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. @@ -821,14 +823,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. @@ -836,7 +838,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. @@ -860,7 +862,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. @@ -968,7 +970,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. @@ -1021,7 +1023,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. @@ -1029,7 +1031,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. @@ -1051,7 +1053,7 @@ void clean_xcb() {
  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. @@ -1120,7 +1122,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. @@ -1130,7 +1132,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. @@ -1140,7 +1142,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. @@ -1194,7 +1196,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 973c885..e65402e 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. @@ -237,4 +257,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 3a68cb7..8ad47fc 100644
  306. --- a/libi3/font.c
  307. +++ b/libi3/font.c
  308. @@ -12,11 +12,129 @@
  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 */
  379. +    if (is_ucs2) {
  380. +        text = convert_ucs2_to_utf8((xcb_char2b_t*)text, text_len);
  381. +        if (!text)
  382. +            return;
  383. +    }
  384. +
  385. +    /* Do the drawing */
  386. +    cairo_set_source_rgb(cr, pango_font_red, pango_font_green, pango_font_blue);
  387. +    cairo_move_to(cr, x, y);
  388. +    pango_layout_set_text(layout, text, text_len);
  389. +    pango_cairo_update_layout(cr, layout);
  390. +    pango_cairo_show_layout(cr, layout);
  391. +
  392. +    /* Free resources */
  393. +    g_object_unref(layout);
  394. +    cairo_destroy(cr);
  395. +    cairo_surface_destroy(surface);
  396. +    if (is_ucs2)
  397. +        free(text);
  398. +}
  399. +
  400. +/*
  401. + * Calculate the text width using Pango rendering.
  402. + *
  403. + */
  404. +int predict_text_width_pango(char *text, size_t text_len, bool is_ucs2) {
  405. +    /* If the text is UCS-2, convert it to UTF-8 */
  406. +    if (is_ucs2) {
  407. +        text = convert_ucs2_to_utf8((xcb_char2b_t*)text, text_len);
  408. +        if (!text)
  409. +            return 10 * text_len;
  410. +    }
  411. +
  412. +    /* Create a dummy Pango layout */
  413. +    cairo_surface_t *surface = cairo_xcb_surface_create(conn, root, root_visual_type, 100, 100);
  414. +    cairo_t *cr = cairo_create(surface);
  415. +    PangoLayout *layout = pango_cairo_create_layout(cr);
  416. +
  417. +    /* Get the font height */
  418. +    gint width;
  419. +    pango_layout_set_font_description(layout, savedFont->specific.pango_desc);
  420. +    pango_layout_set_text(layout, text, text_len);
  421. +    pango_cairo_update_layout(cr, layout);
  422. +    pango_layout_get_pixel_size(layout, &width, NULL);
  423. +
  424. +    /* Free resources */
  425. +    g_object_unref(layout);
  426. +    cairo_destroy(cr);
  427. +    cairo_surface_destroy(surface);
  428. +    if (is_ucs2)
  429. +        free(text);
  430. +
  431. +    return width;
  432. +}
  433. +#endif
  434. +
  435.  /*
  436.   * Loads a font for usage, also getting its metrics. If fallback is true,
  437.   * the fonts 'fixed' or '-misc-*' will be loaded instead of exiting.
  438. @@ -24,12 +142,22 @@ static const i3Font *savedFont = NULL;
  439.   */
  440.  i3Font load_font(const char *pattern, const bool fallback) {
  441.      i3Font font;
  442. +    font.type = FONT_TYPE_NONE;
  443. +
  444. +#if PANGO_SUPPORT
  445. +    /* Try to load a pango font if specified */
  446. +    if (strlen(pattern) > 6 && !strncmp(pattern, "xft:", 4)) {
  447. +        pattern += 4;
  448. +        if (load_pango_font(&font, pattern))
  449. +            return font;
  450. +    }
  451. +#endif
  452.  
  453.      /* Send all our requests first */
  454. -    font.id = xcb_generate_id(conn);
  455. -    xcb_void_cookie_t font_cookie = xcb_open_font_checked(conn, font.id,
  456. +    font.specific.xcb.id = xcb_generate_id(conn);
  457. +    xcb_void_cookie_t font_cookie = xcb_open_font_checked(conn, font.specific.xcb.id,
  458.              strlen(pattern), pattern);
  459. -    xcb_query_font_cookie_t info_cookie = xcb_query_font(conn, font.id);
  460. +    xcb_query_font_cookie_t info_cookie = xcb_query_font(conn, font.specific.xcb.id);
  461.  
  462.      /* Check for errors. If errors, fall back to default font. */
  463.      xcb_generic_error_t *error;
  464. @@ -40,8 +168,9 @@ i3Font load_font(const char *pattern, const bool fallback) {
  465.          ELOG("Could not open font %s (X error %d). Trying fallback to 'fixed'.\n",
  466.               pattern, error->error_code);
  467.          pattern = "fixed";
  468. -        font_cookie = xcb_open_font_checked(conn, font.id, strlen(pattern), pattern);
  469. -        info_cookie = xcb_query_font(conn, font.id);
  470. +        font_cookie = xcb_open_font_checked(conn, font.specific.xcb.id,
  471. +                strlen(pattern), pattern);
  472. +        info_cookie = xcb_query_font(conn, font.specific.xcb.id);
  473.  
  474.          /* Check if we managed to open 'fixed' */
  475.          error = xcb_request_check(conn, font_cookie);
  476. @@ -50,8 +179,9 @@ i3Font load_font(const char *pattern, const bool fallback) {
  477.          if (error != NULL) {
  478.              ELOG("Could not open fallback font 'fixed', trying with '-misc-*'.\n");
  479.              pattern = "-misc-*";
  480. -            font_cookie = xcb_open_font_checked(conn, font.id, strlen(pattern), pattern);
  481. -            info_cookie = xcb_query_font(conn, font.id);
  482. +            font_cookie = xcb_open_font_checked(conn, font.specific.xcb.id,
  483. +                    strlen(pattern), pattern);
  484. +            info_cookie = xcb_query_font(conn, font.specific.xcb.id);
  485.  
  486.              if ((error = xcb_request_check(conn, font_cookie)) != NULL)
  487.                  errx(EXIT_FAILURE, "Could open neither requested font nor fallbacks "
  488. @@ -60,18 +190,20 @@ i3Font load_font(const char *pattern, const bool fallback) {
  489.      }
  490.  
  491.      /* Get information (height/name) for this font */
  492. -    if (!(font.info = xcb_query_font_reply(conn, info_cookie, NULL)))
  493. +    if (!(font.specific.xcb.info = xcb_query_font_reply(conn, info_cookie, NULL)))
  494.          errx(EXIT_FAILURE, "Could not load font \"%s\"", pattern);
  495.  
  496.      /* Get the font table, if possible */
  497. -    if (xcb_query_font_char_infos_length(font.info) == 0)
  498. -        font.table = NULL;
  499. +    if (xcb_query_font_char_infos_length(font.specific.xcb.info) == 0)
  500. +        font.specific.xcb.table = NULL;
  501.      else
  502. -        font.table = xcb_query_font_char_infos(font.info);
  503. +        font.specific.xcb.table = xcb_query_font_char_infos(font.specific.xcb.info);
  504.  
  505.      /* Calculate the font height */
  506. -    font.height = font.info->font_ascent + font.info->font_descent;
  507. +    font.height = font.specific.xcb.info->font_ascent + font.specific.xcb.info->font_descent;
  508.  
  509. +    /* Set the font type and return successfully */
  510. +    font.type = FONT_TYPE_XCB;
  511.      return font;
  512.  }
  513.  
  514. @@ -88,10 +220,27 @@ void set_font(i3Font *font) {
  515.   *
  516.   */
  517.  void free_font() {
  518. -    /* Close the font and free the info */
  519. -    xcb_close_font(conn, savedFont->id);
  520. -    if (savedFont->info)
  521. -        free(savedFont->info);
  522. +    switch (savedFont->type) {
  523. +        case FONT_TYPE_NONE:
  524. +            /* Nothing to do */
  525. +            break;
  526. +        case FONT_TYPE_XCB: {
  527. +            /* Close the font and free the info */
  528. +            xcb_close_font(conn, savedFont->specific.xcb.id);
  529. +            if (savedFont->specific.xcb.info)
  530. +                free(savedFont->specific.xcb.info);
  531. +            break;
  532. +        }
  533. +#if PANGO_SUPPORT
  534. +        case FONT_TYPE_PANGO:
  535. +            /* Free the font description */
  536. +            pango_font_description_free(savedFont->specific.pango_desc);
  537. +            break;
  538. +#endif
  539. +        default:
  540. +            assert(false);
  541. +            break;
  542. +    }
  543.  }
  544.  
  545.  /*
  546. @@ -100,9 +249,30 @@ void free_font() {
  547.   */
  548.  void set_font_colors(xcb_gcontext_t gc, uint32_t foreground, uint32_t background) {
  549.      assert(savedFont != NULL);
  550. -    uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
  551. -    uint32_t values[] = { foreground, background, savedFont->id };
  552. -    xcb_change_gc(conn, gc, mask, values);
  553. +
  554. +    switch (savedFont->type) {
  555. +        case FONT_TYPE_NONE:
  556. +            /* Nothing to do */
  557. +            break;
  558. +        case FONT_TYPE_XCB: {
  559. +            /* Change the font and colors in the GC */
  560. +            uint32_t mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
  561. +            uint32_t values[] = { foreground, background, savedFont->specific.xcb.id };
  562. +            xcb_change_gc(conn, gc, mask, values);
  563. +            break;
  564. +        }
  565. +#if PANGO_SUPPORT
  566. +        case FONT_TYPE_PANGO:
  567. +            /* Save the foreground font */
  568. +            pango_font_red = (foreground >> 16) / 255.0;
  569. +            pango_font_green = ((foreground >> 8) & 0xff) / 255.0;
  570. +            pango_font_blue = (foreground & 0xff) / 255.0;
  571. +            break;
  572. +#endif
  573. +        default:
  574. +            assert(false);
  575. +            break;
  576. +    }
  577.  }
  578.  
  579.  /*
  580. @@ -116,8 +286,25 @@ void draw_text(char *text, size_t text_len, bool is_ucs2, xcb_drawable_t drawabl
  581.      assert(savedFont != NULL);
  582.      assert(text_len != 0);
  583.  
  584. +    switch (savedFont->type) {
  585. +        case FONT_TYPE_NONE:
  586. +            /* Nothing to do */
  587. +            return;
  588. +        case FONT_TYPE_XCB:
  589. +            /* Continue below */
  590. +            break;
  591. +#if PANGO_SUPPORT
  592. +        case FONT_TYPE_PANGO:
  593. +            /* Render the text using Pango */
  594. +            draw_text_pango(text, text_len, is_ucs2, drawable, x, y, max_width);
  595. +            return;
  596. +#endif
  597. +        default:
  598. +            assert(false);
  599. +    }
  600. +
  601.      /* X11 coordinates for fonts start at the baseline */
  602. -    int pos_y = y + savedFont->info->font_ascent;
  603. +    int pos_y = y + savedFont->specific.xcb.info->font_ascent;
  604.  
  605.      /* As an optimization, check if we can bypass conversion */
  606.      if (!is_ucs2 && text_len <= 255) {
  607. @@ -168,7 +355,7 @@ static int xcb_query_text_width(xcb_char2b_t *text, size_t text_len) {
  608.      /* Query the text width */
  609.      xcb_generic_error_t *error;
  610.      xcb_query_text_extents_cookie_t cookie = xcb_query_text_extents(conn,
  611. -            savedFont->id, text_len, (xcb_char2b_t*)text);
  612. +            savedFont->specific.xcb.id, text_len, (xcb_char2b_t*)text);
  613.      xcb_query_text_extents_reply_t *reply = xcb_query_text_extents_reply(conn,
  614.              cookie, &error);
  615.      if (reply == NULL) {
  616. @@ -176,7 +363,7 @@ static int xcb_query_text_width(xcb_char2b_t *text, size_t text_len) {
  617.           * a crash. Plus, the user will see the error in his log. */
  618.          fprintf(stderr, "Could not get text extents (X error code %d)\n",
  619.                  error->error_code);
  620. -        return savedFont->info->max_bounds.character_width * text_len;
  621. +        return savedFont->specific.xcb.info->max_bounds.character_width * text_len;
  622.      }
  623.  
  624.      int width = reply->overall_width;
  625. @@ -190,6 +377,25 @@ static int xcb_query_text_width(xcb_char2b_t *text, size_t text_len) {
  626.   *
  627.   */
  628.  int predict_text_width(char *text, size_t text_len, bool is_ucs2) {
  629. +    assert(savedFont != NULL);
  630. +
  631. +    switch (savedFont->type) {
  632. +        case FONT_TYPE_NONE:
  633. +            /* Nothing to do */
  634. +            return 0;
  635. +        case FONT_TYPE_XCB:
  636. +            /* Continue below */
  637. +            break;
  638. +#if PANGO_SUPPORT
  639. +        case FONT_TYPE_PANGO:
  640. +            /* Calculate extents using Pango */
  641. +            return predict_text_width_pango(text, text_len, is_ucs2);
  642. +#endif
  643. +        default:
  644. +            assert(false);
  645. +            return 0;
  646. +    }
  647. +
  648.      /* Convert the text into UTF-16 so we can do basic pointer math */
  649.      xcb_char2b_t *input;
  650.      if (is_ucs2)
  651. @@ -198,13 +404,13 @@ int predict_text_width(char *text, size_t text_len, bool is_ucs2) {
  652.          input = convert_utf8_to_ucs2(text, &text_len);
  653.  
  654.      int width;
  655. -    if (savedFont->table == NULL) {
  656. +    if (savedFont->specific.xcb.table == NULL) {
  657.          /* If we don't have a font table, fall back to querying the server */
  658.          width = xcb_query_text_width(input, text_len);
  659.      } else {
  660.          /* Save some pointers for convenience */
  661. -        xcb_query_font_reply_t *font_info = savedFont->info;
  662. -        xcb_charinfo_t *font_table = savedFont->table;
  663. +        xcb_query_font_reply_t *font_info = savedFont->specific.xcb.info;
  664. +        xcb_charinfo_t *font_table = savedFont->specific.xcb.table;
  665.  
  666.          /* Calculate the width using the font table */
  667.          width = 0;
  668. diff --git a/libi3/get_visualtype.c b/libi3/get_visualtype.c
  669. new file mode 100644
  670. index 0000000..c639443
  671. --- /dev/null
  672. +++ b/libi3/get_visualtype.c
  673. @@ -0,0 +1,24 @@
  674. +/*
  675. + * vim:ts=4:sw=4:expandtab
  676. + *
  677. + * i3 - an improved dynamic tiling window manager
  678. + * © 2009-2011 Michael Stapelberg and contributors (see also: LICENSE)
  679. + *
  680. + */
  681. +#include "libi3.h"
  682. +
  683. +/*
  684. + * Returns the visual type associated with the given screen.
  685. + *
  686. + */
  687. +xcb_visualtype_t *get_visualtype(xcb_screen_t *s) {
  688. +    xcb_depth_iterator_t depth_iter = xcb_screen_allowed_depths_iterator(s);
  689. +    for (; depth_iter.rem;xcb_depth_next(&depth_iter)) {
  690. +        xcb_visualtype_iterator_t visual_iter = xcb_depth_visuals_iterator(depth_iter.data);
  691. +        for (; visual_iter.rem;xcb_visualtype_next(&visual_iter)) {
  692. +            if (s->root_visual == visual_iter.data->visual_id)
  693. +                return visual_iter.data;
  694. +        }
  695. +    }
  696. +    return NULL;
  697. +}
  698. diff --git a/src/config.c b/src/config.c
  699. index de59420..995f874 100644
  700. --- a/src/config.c
  701. +++ b/src/config.c
  702. @@ -392,7 +392,7 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath,
  703.          grab_all_keys(conn, false);
  704.      }
  705.  
  706. -    if (config.font.id == 0) {
  707. +    if (config.font.type == FONT_TYPE_NONE) {
  708.          ELOG("You did not specify required configuration option \"font\"\n");
  709.          config.font = load_font("fixed", true);
  710.          set_font(&config.font);
  711. diff --git a/src/main.c b/src/main.c
  712. index 76ea838..aea3c4f 100644
  713. --- a/src/main.c
  714. +++ b/src/main.c
  715. @@ -51,6 +51,7 @@ SnDisplay *sndisplay;
  716.   * notification). */
  717.  xcb_timestamp_t last_timestamp = XCB_CURRENT_TIME;
  718.  
  719. +xcb_visualtype_t *root_visual_type;
  720.  xcb_screen_t *root_screen;
  721.  xcb_window_t root;
  722.  
  723. @@ -518,6 +519,7 @@ int main(int argc, char *argv[]) {
  724.       * usually is TrueColor (24 bit depth) and the corresponding visual.
  725.       * However, we also check if a 32 bit depth and visual are available (for
  726.       * transparency) and use it if so. */
  727. +    root_visual_type = get_visualtype(root_screen);
  728.      root_depth = root_screen->root_depth;
  729.      visual_id = root_screen->root_visual;
  730.      colormap = root_screen->default_colormap;
  731. @@ -534,6 +536,7 @@ int main(int argc, char *argv[]) {
  732.              if (!visual_iter.rem)
  733.                  continue;
  734.  
  735. +            root_visual_type = visual_iter.data;
  736.              visual_id = visual_iter.data->visual_id;
  737.              root_depth = depth_iter.data->depth;
  738.              colormap = xcb_generate_id(conn);
  739. diff --git a/src/xcb.c b/src/xcb.c
  740. index 5aa74b3..036e95f 100644
  741. --- a/src/xcb.c
  742. +++ b/src/xcb.c
  743. @@ -52,8 +52,9 @@ xcb_window_t create_window(xcb_connection_t *conn, Rect dims, uint16_t window_cl
  744.          xcb_cursor_t cursor_id = xcb_generate_id(conn);
  745.          i3Font cursor_font = load_font("cursor", false);
  746.          int xcb_cursor = xcursor_get_xcb_cursor(cursor);
  747. -        xcb_create_glyph_cursor(conn, cursor_id, cursor_font.id, cursor_font.id,
  748. -                xcb_cursor, xcb_cursor + 1, 0, 0, 0, 65535, 65535, 65535);
  749. +        xcb_create_glyph_cursor(conn, cursor_id, cursor_font.specific.xcb.id,
  750. +                cursor_font.specific.xcb.id, xcb_cursor, xcb_cursor + 1, 0, 0, 0,
  751. +                65535, 65535, 65535);
  752.          xcb_change_window_attributes(conn, result, XCB_CW_CURSOR, &cursor_id);
  753.          xcb_free_cursor(conn, cursor_id);
  754.      }
  755. @@ -197,8 +198,9 @@ void xcb_set_root_cursor(int cursor) {
  756.      xcb_cursor_t cursor_id = xcb_generate_id(conn);
  757.      i3Font cursor_font = load_font("cursor", false);
  758.      int xcb_cursor = xcursor_get_xcb_cursor(cursor);
  759. -    xcb_create_glyph_cursor(conn, cursor_id, cursor_font.id, cursor_font.id,
  760. -            xcb_cursor, xcb_cursor + 1, 0, 0, 0, 65535, 65535, 65535);
  761. +    xcb_create_glyph_cursor(conn, cursor_id, cursor_font.specific.xcb.id,
  762. +            cursor_font.specific.xcb.id, xcb_cursor, xcb_cursor + 1, 0, 0, 0,
  763. +            65535, 65535, 65535);
  764.      xcb_change_window_attributes(conn, root, XCB_CW_CURSOR, &cursor_id);
  765.      xcb_free_cursor(conn, cursor_id);
  766.      xcb_flush(conn);
  767. --
  768. 1.7.9
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement