iv.vfs: don't turn "w+" mode to "r+" mode, lol
[iv.d.git] / cairo_samples / cairo_xlib.d
blob3665bbe76f77b6a89089d8bf6d9df8e5223a4c7a
1 /*! Cairo graphics and X11/Xlib motion example.
2 * @author Bernhard R. Fischer, 2048R/5C5FFD47 <bf@abenteuerland.at>.
3 * @version 2014110801
4 * Compile with gcc -Wall $(pkg-config --cflags --libs cairo x11) -o cairo_xlib cairo_xlib.c
5 */
6 import iv.cairo;
7 import iv.x11;
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
19 * the right button.
21 int cairo_check_event (cairo_surface_t* sfc, int block) {
22 char[8] keybuf;
23 KeySym key;
24 XEvent e;
25 for (;;) {
26 if (block || XPending(cairo_xlib_surface_get_display(sfc))) XNextEvent(cairo_xlib_surface_get_display(sfc), &e); else return 0;
27 switch (e.type) {
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) {
37 Atom[2] atoms = None;
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) {
52 Display* dsp;
53 Drawable da;
54 Screen* scr;
55 int screen;
56 cairo_surface_t *sfc;
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);
65 fullscreen(dsp, da);
66 } else {
67 da = XCreateSimpleWindow(dsp, DefaultRootWindow(dsp), 0, 0, *x, *y, 0, 0, 0);
69 XSelectInput(dsp, da, ButtonPressMask | KeyPressMask);
70 XMapWindow(dsp, da);
72 sfc = cairo_xlib_surface_create(dsp, da, DefaultVisual(dsp, screen), *x, *y);
73 cairo_xlib_surface_set_size(sfc, *x, *y);
75 return sfc;
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);
84 XCloseDisplay(dsp);
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;
97 cairo_surface_t* sfc;
98 cairo_t* ctx;
99 int x, y;
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;
104 bool running = true;
106 import std.conv : to;
108 x = y = 0;
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);
114 while (running) {
115 cairo_push_group(ctx);
116 cairo_set_source_rgb(ctx, 1, 1, 1);
117 cairo_paint(ctx);
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);
126 cairo_stroke(ctx);
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);
135 cairo_paint(ctx);
136 cairo_surface_flush(sfc);
138 x0 += dx0;
139 y0 += dy0;
140 x1 += dx1;
141 y1 += dy1;
142 x2 += dx2;
143 y2 += dy2;
144 turn(x0, x, &dx0);
145 turn(x1, x, &dx1);
146 turn(x2, x, &dx2);
147 turn(y0, y, &dy0);
148 turn(y1, y, &dy1);
149 turn(y2, y, &dy2);
151 switch (cairo_check_event(sfc, 0)) {
152 case 0xff53: // right cursor
153 dx0 *= 2.0;
154 dy0 *= 2.0;
155 break;
156 case 0xff51: // left cursor
157 dx0 /= 2.0;
158 dy0 /= 2.0;
159 break;
160 case 0xff1b: // Esc
161 case -1: // left mouse button
162 running = false;
163 break;
164 default:
167 timespec ts;
168 ts.tv_sec = 0;
169 ts.tv_nsec = 5000000;
170 nanosleep(&ts, null);
173 cairo_destroy(ctx);
174 cairo_close_x11_surface(sfc);