diff options
| author | Mitja Felicijan <mitja.felicijan@gmail.com> | 2024-09-17 08:48:40 +0200 |
|---|---|---|
| committer | Mitja Felicijan <mitja.felicijan@gmail.com> | 2024-09-17 08:48:40 +0200 |
| commit | fadbf136de03215a9bfaca04ee336b4085589de4 (patch) | |
| tree | 6f693db0e737dcd52a0b8719bd18ec23358c5e3e | |
| parent | b2503e50f7d6e31bf6b553c192d34d87eaac055b (diff) | |
| download | probe-fadbf136de03215a9bfaca04ee336b4085589de4.tar.gz | |
Added a bit more involved example of Zig and Xlib
| -rw-r--r-- | README.md | 1 | ||||
| -rw-r--r-- | zig-x11-box/Makefile | 2 | ||||
| -rw-r--r-- | zig-x11-box/main.zig | 103 |
3 files changed, 106 insertions, 0 deletions
@@ -19,3 +19,4 @@ reference them later if I need to. | [zig-telnet](./zig-telnet) | Connects to Redis server like it is a basic telnet server. | | [zig-x11](./zig-x11) | Uses X11 to create a basic window without any bindings needed. | | [zig-http](./zig-http) | Basic example of a HTTP 1.1 server without any routing etc. | +| [zig-x11-box](./zig-x11-box) | Move a box around with arrow keys with Xlib and Zig. | diff --git a/zig-x11-box/Makefile b/zig-x11-box/Makefile new file mode 100644 index 0000000..1ebb12c --- /dev/null +++ b/zig-x11-box/Makefile @@ -0,0 +1,2 @@ +default: + zig run main.zig -lX11 -lc diff --git a/zig-x11-box/main.zig b/zig-x11-box/main.zig new file mode 100644 index 0000000..8cc6ede --- /dev/null +++ b/zig-x11-box/main.zig @@ -0,0 +1,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); + } +} |
