1 /*! Cairo graphics and X11/Xlib motion example.
2 * @author Bernhard R. Fischer, 2048R/5C5FFD47 <bf@abenteuerland.at>.
4 * Compile with gcc -Wall $(pkg-config --cflags --libs cairo x11) -o cairo_xlib cairo_xlib.c
10 /*! Check for Xlib Mouse/Keypress events. All other events are discarded.
11 * @param sfc Pointer to Xlib surface.
12 * @param block If block is set to 0, this function always returns immediately
13 * and does not block. if set to a non-zero value, the function will block
14 * until the next event is received.
15 * @return The function returns 0 if no event occured (and block is set). A
16 * positive value indicates that a key was pressed and the X11 key symbol as
17 * defined in <X11/keysymdef.h> is returned. A negative value indicates a mouse
18 * button event. -1 is button 1 (left button), -2 is the middle button, and -3
21 int cairo_check_event (cairo_surface_t
* sfc
, int block
) {
26 if (block ||
XPending(cairo_xlib_surface_get_display(sfc
))) XNextEvent(cairo_xlib_surface_get_display(sfc
), &e
); else return 0;
28 case ButtonPress
: return -e
.xbutton
.button
;
29 case KeyPress
: XLookupString(&e
.xkey
, keybuf
.ptr
, keybuf
.length
, &key
, null); return key
;
30 default: //fprintf(stderr, "Dropping unhandled XEevent.type = %d.\n", e.type);
36 void fullscreen (Display
* dpy
, Window win
) {
38 atoms
[0] = XInternAtom(dpy
, "_NET_WM_STATE_FULLSCREEN", False
);
39 XChangeProperty(dpy
, win
, XInternAtom(dpy
, "_NET_WM_STATE", False
), XA_ATOM
, 32, PropModeReplace
, cast(ubyte*)atoms
.ptr
, 1);
43 /*! Open an X11 window and create a cairo surface base on that window. If x and
44 * y are set to 0 the function opens a full screen window and stores to window
45 * dimensions to x and y.
46 * @param x Pointer to width of window.
47 * @param y Pointer to height of window.
48 * @return Returns a pointer to a valid Xlib cairo surface. The function does
49 * not return on error (exit(3)).
51 cairo_surface_t
* cairo_create_x11_surface (int* x
, int* y
) {
58 if ((dsp
= XOpenDisplay(null)) is null) assert(0, "cannot open X11 display");
59 screen
= DefaultScreen(dsp
);
60 scr
= DefaultScreenOfDisplay(dsp
);
61 if (*x
== 0 ||
*y
== 0) {
62 *x
= WidthOfScreen(scr
);
63 *y
= HeightOfScreen(scr
);
64 da = XCreateSimpleWindow(dsp
, DefaultRootWindow(dsp
), 0, 0, *x
, *y
, 0, 0, 0);
67 da = XCreateSimpleWindow(dsp
, DefaultRootWindow(dsp
), 0, 0, *x
, *y
, 0, 0, 0);
69 XSelectInput(dsp
, da, ButtonPressMask | KeyPressMask
);
72 sfc
= cairo_xlib_surface_create(dsp
, da, DefaultVisual(dsp
, screen
), *x
, *y
);
73 cairo_xlib_surface_set_size(sfc
, *x
, *y
);
79 /*! Destroy cairo Xlib surface and close X connection.
81 void cairo_close_x11_surface (cairo_surface_t
* sfc
) {
82 Display
*dsp
= cairo_xlib_surface_get_display(sfc
);
83 cairo_surface_destroy(sfc
);
88 void turn (double v
, double max
, double* diff
) {
89 if (v
<= 0 || v
>= max
) *diff
*= -1.0;
93 void main (string
[] args
) {
94 import core
.sys
.posix
.signal
: timespec
;
95 import core
.sys
.posix
.time
: nanosleep
;
101 double x0
= 20, y0
= 20, x1
= 200, y1
= 400, x2
= 450, y2
= 100;
102 double dx0
= 1, dx1
= 1.5, dx2
= 2;
103 double dy0
= 2, dy1
= 1.5, dy2
= 1;
106 import std
.conv
: to
;
109 if (args
.length
> 1) x
= to
!int(args
[1]);
110 if (args
.length
> 2) y
= to
!int(args
[2]);
111 sfc
= cairo_create_x11_surface(&x
, &y
);
112 ctx
= cairo_create(sfc
);
115 cairo_push_group(ctx
);
116 cairo_set_source_rgb(ctx
, 1, 1, 1);
118 cairo_move_to(ctx
, x0
, y0
);
119 cairo_line_to(ctx
, x1
, y1
);
120 cairo_line_to(ctx
, x2
, y2
);
121 cairo_line_to(ctx
, x0
, y0
);
122 cairo_set_source_rgb(ctx
, 0, 0, 1);
123 cairo_fill_preserve(ctx
);
124 cairo_set_line_width(ctx
, 5);
125 cairo_set_source_rgb(ctx
, 1, 1, 0);
127 cairo_set_source_rgb(ctx
, 0, 0, 0);
128 cairo_move_to(ctx
, x0
, y0
);
129 cairo_show_text(ctx
, "P0");
130 cairo_move_to(ctx
, x1
, y1
);
131 cairo_show_text(ctx
, "P1");
132 cairo_move_to(ctx
, x2
, y2
);
133 cairo_show_text(ctx
, "P2");
134 cairo_pop_group_to_source(ctx
);
136 cairo_surface_flush(sfc
);
151 switch (cairo_check_event(sfc
, 0)) {
152 case 0xff53: // right cursor
156 case 0xff51: // left cursor
161 case -1: // left mouse button
169 ts
.tv_nsec
= 5000000;
170 nanosleep(&ts
, null);
174 cairo_close_x11_surface(sfc
);