summaryrefslogtreecommitdiff
path: root/zig-x11-box/main.zig
blob: 8cc6ede4bfb4d2a8072020f4582bc4e218df1a33 (plain)
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
103
// https://tronche.com/gui/x/xlib/

const std = @import("std");
const xlib = @cImport({
    @cInclude("X11/Xlib.h");

    // This should work and pull in header with all the mappings
    // making xlib.XK_Escape available but it doesn't.
    @cInclude("X11/keysymdef.h");
});

// Defining key symbols by hand from keysymdef.h file.
const KeySym = enum(u32) {
    ESCAPE = 0xFF1B,
    LEFT = 0xff51,
    UP = 0xff52,
    RIGHT = 0xff53,
    DOWN = 0xff54,
};

const Box = struct {
    x: i32,
    y: i32,
};

const StepSize = 30;

pub fn main() !void {
    const display = xlib.XOpenDisplay(null);
    if (display == null) {
        return error.DisplayOpenFailed;
    }

    const root_window = xlib.XDefaultRootWindow(display);

    const main_window = xlib.XCreateSimpleWindow(
        display,
        root_window,
        0,
        0,
        400,
        800,
        0,
        0,
        0xFFFFFF,
    );

    _ = xlib.XMapWindow(display, main_window);
    _ = xlib.XFlush(display);

    _ = xlib.XSelectInput(display, main_window, xlib.KeyPressMask);
    _ = xlib.XMapWindow(display, main_window);

    _ = xlib.XStoreName(display, main_window, "Moving boxes");

    var gc = xlib.XCreateGC(display, main_window, 0, null) orelse {
        std.debug.print("Failed to create graphics context\n", .{});
        return error.CreateGCFailed;
    };
    defer {
        _ = xlib.XFreeGC(display, gc);
    }

    var box = Box{ .x = 0, .y = 0 };

    var event: xlib.XEvent = undefined;
    while (true) {
        _ = xlib.XNextEvent(display, &event);
        if (event.type == xlib.KeyPress) {
            var keysym = xlib.XLookupKeysym(&event.xkey, 0);

            // NOTE: There probably is a better way of matching key presses
            //       without casting. I tried creating enum with type
            //       c_ulong without luck. More described in link below.
            //       https://ziglang.org/documentation/0.9.1/#Primitive-Types

            if (keysym == @intFromEnum(KeySym.ESCAPE)) {
                std.debug.print("Exiting game\n", .{});
                break;
            }

            if (keysym == @intFromEnum(KeySym.LEFT)) {
                box.x -= StepSize;
            }

            if (keysym == @intFromEnum(KeySym.RIGHT)) {
                box.x += StepSize;
            }

            if (keysym == @intFromEnum(KeySym.UP)) {
                box.y -= StepSize;
            }

            if (keysym == @intFromEnum(KeySym.DOWN)) {
                box.y += StepSize;
            }
        }

        _ = xlib.XClearWindow(display, main_window);
        _ = xlib.XDrawString(display, main_window, gc, 150, 150, "Use arrow keys.", 15);
        _ = xlib.XFillRectangle(display, main_window, gc, box.x, box.y, 100, 100);
    }
}