oxwm

https://git.tonybtw.com/oxwm.git git://git.tonybtw.com/oxwm.git
2,775 bytes raw
1
const std = @import("std");
2
const xlib = @import("xlib.zig");
3
4
pub const DisplayError = error{
5
    cannot_open_display,
6
    another_wm_running,
7
};
8
9
var wm_detected: bool = false;
10
11
pub const Display = struct {
12
    handle: *xlib.Display,
13
    screen: c_int,
14
    root: xlib.Window,
15
16
    pub fn open() DisplayError!Display {
17
        const handle = xlib.XOpenDisplay(null) orelse return DisplayError.cannot_open_display;
18
        const screen = xlib.XDefaultScreen(handle);
19
        const root = xlib.XRootWindow(handle, screen);
20
21
        return Display{
22
            .handle = handle,
23
            .screen = screen,
24
            .root = root,
25
        };
26
    }
27
28
    pub fn close(self: *Display) void {
29
        _ = xlib.XCloseDisplay(self.handle);
30
    }
31
32
    pub fn become_window_manager(self: *Display) DisplayError!void {
33
        wm_detected = false;
34
        _ = xlib.XSetErrorHandler(on_wm_detected);
35
        _ = xlib.XSelectInput(
36
            self.handle,
37
            self.root,
38
            xlib.SubstructureRedirectMask | xlib.SubstructureNotifyMask | xlib.ButtonPressMask | xlib.PointerMotionMask | xlib.EnterWindowMask,
39
        );
40
        _ = xlib.XSync(self.handle, xlib.False);
41
42
        if (wm_detected) {
43
            return DisplayError.another_wm_running;
44
        }
45
46
        _ = xlib.XSetErrorHandler(on_x_error);
47
    }
48
49
    pub fn screen_width(self: *Display) c_int {
50
        return xlib.XDisplayWidth(self.handle, self.screen);
51
    }
52
53
    pub fn screen_height(self: *Display) c_int {
54
        return xlib.XDisplayHeight(self.handle, self.screen);
55
    }
56
57
    pub fn next_event(self: *Display) xlib.XEvent {
58
        var event: xlib.XEvent = undefined;
59
        _ = xlib.XNextEvent(self.handle, &event);
60
        return event;
61
    }
62
63
    pub fn pending(self: *Display) c_int {
64
        return xlib.XPending(self.handle);
65
    }
66
67
    pub fn sync(self: *Display, discard: bool) void {
68
        _ = xlib.XSync(self.handle, if (discard) xlib.True else xlib.False);
69
    }
70
71
    pub fn grab_key(
72
        self: *Display,
73
        keycode: c_int,
74
        modifiers: c_uint,
75
    ) void {
76
        _ = xlib.XGrabKey(
77
            self.handle,
78
            keycode,
79
            modifiers,
80
            self.root,
81
            xlib.True,
82
            xlib.GrabModeAsync,
83
            xlib.GrabModeAsync,
84
        );
85
    }
86
87
    pub fn keysym_to_keycode(self: *Display, keysym: xlib.KeySym) c_int {
88
        return @intCast(xlib.XKeysymToKeycode(self.handle, keysym));
89
    }
90
};
91
92
fn on_wm_detected(_: ?*xlib.Display, _: [*c]xlib.XErrorEvent) callconv(.c) c_int {
93
    wm_detected = true;
94
    return 0;
95
}
96
97
fn on_x_error(_: ?*xlib.Display, event: [*c]xlib.XErrorEvent) callconv(.c) c_int {
98
    std.debug.print("x11 error: request={d} error={d}\n", .{ event.*.request_code, event.*.error_code });
99
    return 0;
100
}