| 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 |
}
|