1// https://tronche.com/gui/x/xlib/
2
3const std = @import("std");
4const xlib = @cImport({
5 @cInclude("X11/Xlib.h");
6
7 // This should work and pull in header with all the mappings
8 // making xlib.XK_Escape available but it doesn't.
9 @cInclude("X11/keysymdef.h");
10});
11
12// Defining key symbols by hand from keysymdef.h file.
13const KeySym = enum(u32) {
14 ESCAPE = 0xFF1B,
15 LEFT = 0xff51,
16 UP = 0xff52,
17 RIGHT = 0xff53,
18 DOWN = 0xff54,
19};
20
21const Box = struct {
22 x: i32,
23 y: i32,
24};
25
26const StepSize = 30;
27
28pub fn main() !void {
29 const display = xlib.XOpenDisplay(null);
30 if (display == null) {
31 return error.DisplayOpenFailed;
32 }
33
34 const root_window = xlib.XDefaultRootWindow(display);
35
36 const main_window = xlib.XCreateSimpleWindow(
37 display,
38 root_window,
39 0,
40 0,
41 400,
42 800,
43 0,
44 0,
45 0xFFFFFF,
46 );
47
48 _ = xlib.XMapWindow(display, main_window);
49 _ = xlib.XFlush(display);
50
51 _ = xlib.XSelectInput(display, main_window, xlib.KeyPressMask);
52 _ = xlib.XMapWindow(display, main_window);
53
54 _ = xlib.XStoreName(display, main_window, "Moving boxes");
55
56 var gc = xlib.XCreateGC(display, main_window, 0, null) orelse {
57 std.debug.print("Failed to create graphics context\n", .{});
58 return error.CreateGCFailed;
59 };
60 defer {
61 _ = xlib.XFreeGC(display, gc);
62 }
63
64 var box = Box{ .x = 0, .y = 0 };
65
66 var event: xlib.XEvent = undefined;
67 while (true) {
68 _ = xlib.XNextEvent(display, &event);
69 if (event.type == xlib.KeyPress) {
70 var keysym = xlib.XLookupKeysym(&event.xkey, 0);
71
72 // NOTE: There probably is a better way of matching key presses
73 // without casting. I tried creating enum with type
74 // c_ulong without luck. More described in link below.
75 // https://ziglang.org/documentation/0.9.1/#Primitive-Types
76
77 if (keysym == @intFromEnum(KeySym.ESCAPE)) {
78 std.debug.print("Exiting game\n", .{});
79 break;
80 }
81
82 if (keysym == @intFromEnum(KeySym.LEFT)) {
83 box.x -= StepSize;
84 }
85
86 if (keysym == @intFromEnum(KeySym.RIGHT)) {
87 box.x += StepSize;
88 }
89
90 if (keysym == @intFromEnum(KeySym.UP)) {
91 box.y -= StepSize;
92 }
93
94 if (keysym == @intFromEnum(KeySym.DOWN)) {
95 box.y += StepSize;
96 }
97 }
98
99 _ = xlib.XClearWindow(display, main_window);
100 _ = xlib.XDrawString(display, main_window, gc, 150, 150, "Use arrow keys.", 15);
101 _ = xlib.XFillRectangle(display, main_window, gc, box.x, box.y, 100, 100);
102 }
103}