1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
#include <stdint.h>
#include <stdio.h>
#include <cairo.h>
#include <cairo-xcb.h>
#include <glib-object.h>
#include <pango/pango.h>
#include <pango/pangocairo.h>
#include <xcb/xcb.h>
#include <xcb/xcb_util.h>
void draw_text(cairo_t *, const char *);
xcb_visualtype_t * find_visual(xcb_screen_t *);
static const int MARGIN = 20;
static const int WIDTH = 800;
static const int HEIGHT = 1131;
static const char * FONT = "Serif 34";
int main(int argc, const char ** argv)
{
const char * text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
if (2 == argc)
text = argv[2];
xcb_connection_t * c = xcb_connect(NULL, NULL);
if (xcb_connection_has_error(c))
{
dprintf(2, "Could not connect to X11 server");
return 1;
}
xcb_screen_t * s = xcb_setup_roots_iterator(xcb_get_setup(c)).data;
xcb_window_t w = xcb_generate_id(c);
const uint32_t mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
const uint32_t values[] = {s->white_pixel, XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS};
xcb_visualtype_t * visual = find_visual(s);
xcb_create_window(
c, XCB_COPY_FROM_PARENT, w, s->root, 0, 0, WIDTH, HEIGHT, 0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
s->root_visual, mask, values);
xcb_map_window(c, w);
cairo_surface_t * surface = cairo_xcb_surface_create(c, w, visual, WIDTH, HEIGHT);
cairo_t * ctx = cairo_create(surface);
xcb_flush(c);
int done = 0;
xcb_generic_event_t * e;
while (!done)
{
e = xcb_wait_for_event(c);
if (NULL == e)
break;
switch (XCB_EVENT_RESPONSE_TYPE(e))
{
default:
break;
case XCB_KEY_PRESS:
done = 1;
break;
case XCB_EXPOSE:
cairo_set_source_rgb(ctx, 1., 1., 1.);
cairo_paint(ctx);
cairo_set_source_rgb(ctx, 0., 0., 0.);
draw_text(ctx, text);
cairo_surface_flush(surface);
xcb_flush(c);
break;
}
free(e);
}
cairo_destroy(ctx);
cairo_surface_destroy(surface);
xcb_disconnect(c);
}
xcb_visualtype_t * find_visual(xcb_screen_t * s)
{
xcb_depth_iterator_t d = xcb_screen_allowed_depths_iterator(s);
for (; d.rem; xcb_depth_next(&d))
{
xcb_visualtype_iterator_t v = xcb_depth_visuals_iterator(d.data);
for (; v.rem; xcb_visualtype_next(&v))
if (v.data->visual_id == s->root_visual)
return v.data;
}
return NULL;
}
void draw_text(cairo_t * ctx, const char * text)
{
cairo_move_to(ctx, MARGIN, MARGIN);
PangoLayout * layout = pango_cairo_create_layout(ctx);
PangoFontDescription * desc = pango_font_description_from_string(FONT);
pango_layout_set_font_description(layout, desc);
pango_font_description_free(desc);
pango_layout_set_text(layout, text, -1);
pango_layout_set_wrap(layout, PANGO_WRAP_WORD);
pango_layout_set_width(layout, (WIDTH - 2 * MARGIN) * PANGO_SCALE);
pango_cairo_update_layout(ctx, layout);
pango_cairo_show_layout(ctx, layout);
g_object_unref(layout);
}
|