lib/sys/src/x11/xlib.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2
3 const sys = @import("../root.zig");
4 const display_mod = @import("display.zig");
5
6 pub const Error = error{
7 RuntimeUnavailable,
8 SymbolMissing,
9 InvalidDisplay,
10 };
11
12 pub const Display = opaque {};
13
14 const XOpenDisplayFn = *const fn (display_name: ?[*:0]const u8) callconv(.c) ?*Display;
15 const XCloseDisplayFn = *const fn (display: *Display) callconv(.c) c_int;
16
17 pub const Connection = struct {
18 library: sys.dynamic.Library,
19 display: *Display,
20 close_fn: XCloseDisplayFn,
21
22 pub fn close(self: *Connection) void {
23 _ = self.close_fn(self.display);
24 self.library.close();
25 self.* = undefined;
26 }
27 };
28
29 pub fn openTarget(target: display_mod.Target) Error!Connection {
30 var name_buffer: [32]u8 = undefined;
31 const name = std.fmt.bufPrintSentinel(&name_buffer, ":{d}.{d}", .{ target.display, target.screen }, 0) catch return error.InvalidDisplay;
32 return openName(name);
33 }
34
35 pub fn openDefault() Error!Connection {
36 return openName(null);
37 }
38
39 fn openName(name: ?[:0]const u8) Error!Connection {
40 var library = sys.dynamic.openX11Library() catch return error.RuntimeUnavailable;
41 errdefer library.close();
42
43 const open_fn = library.lookup(XOpenDisplayFn, "XOpenDisplay") orelse return error.SymbolMissing;
44 const close_fn = library.lookup(XCloseDisplayFn, "XCloseDisplay") orelse return error.SymbolMissing;
45 const display = open_fn(if (name) |actual| actual.ptr else null) orelse return error.RuntimeUnavailable;
46 return .{
47 .library = library,
48 .display = display,
49 .close_fn = close_fn,
50 };
51 }
52
53 test "xlib dynamic candidate list is host-scoped" {
54 const candidates = sys.dynamic.x11LibraryCandidates();
55 try std.testing.expect(candidates.len >= 1);
56 if (comptime @import("builtin").os.tag == .linux) {
57 try std.testing.expect(sys.dynamic.hasHostCandidate(candidates));
58 }
59 }