| 1 |
const std = @import("std");
|
| 2 |
const xlib = @import("xlib.zig");
|
| 3 |
|
| 4 |
pub const Atoms = struct {
|
| 5 |
// ICCCM atoms
|
| 6 |
wm_protocols: xlib.Atom,
|
| 7 |
wm_delete: xlib.Atom,
|
| 8 |
wm_state: xlib.Atom,
|
| 9 |
wm_take_focus: xlib.Atom,
|
| 10 |
|
| 11 |
// EWHM atoms
|
| 12 |
net_supported: xlib.Atom,
|
| 13 |
net_wm_name: xlib.Atom,
|
| 14 |
net_wm_state: xlib.Atom,
|
| 15 |
net_wm_check: xlib.Atom,
|
| 16 |
net_wm_state_fullscreen: xlib.Atom,
|
| 17 |
net_active_window: xlib.Atom,
|
| 18 |
net_wm_window_type: xlib.Atom,
|
| 19 |
net_wm_window_type_dialog: xlib.Atom,
|
| 20 |
net_client_list: xlib.Atom,
|
| 21 |
|
| 22 |
/// Intern all atoms and set up the EWMH check window on `root`.
|
| 23 |
///
|
| 24 |
/// `check_window` is a 1×1 invisible window created solely to satisfy
|
| 25 |
/// the _NET_SUPPORTING_WM_CHECK convention. The caller owns it and
|
| 26 |
/// should destroy it on shutdown via `XDestroyWindow`.
|
| 27 |
pub fn init(display: *xlib.Display, root: xlib.Window) struct {
|
| 28 |
atoms: Atoms,
|
| 29 |
check_window: xlib.Window,
|
| 30 |
} {
|
| 31 |
const intern = struct {
|
| 32 |
fn call(dpy: *xlib.Display, name: [*:0]const u8) xlib.Atom {
|
| 33 |
return xlib.XInternAtom(dpy, name, xlib.False);
|
| 34 |
}
|
| 35 |
}.call;
|
| 36 |
|
| 37 |
const atoms = Atoms{
|
| 38 |
.wm_protocols = intern(display, "WM_PROTOCOLS"),
|
| 39 |
.wm_delete = intern(display, "WM_DELETE_WINDOW"),
|
| 40 |
.wm_state = intern(display, "WM_STATE"),
|
| 41 |
.wm_take_focus = intern(display, "WM_TAKE_FOCUS"),
|
| 42 |
|
| 43 |
.net_supported = intern(display, "_NET_SUPPORTED"),
|
| 44 |
.net_wm_name = intern(display, "_NET_WM_NAME"),
|
| 45 |
.net_wm_state = intern(display, "_NET_WM_STATE"),
|
| 46 |
.net_wm_check = intern(display, "_NET_SUPPORTING_WM_CHECK"),
|
| 47 |
.net_wm_state_fullscreen = intern(display, "_NET_WM_STATE_FULLSCREEN"),
|
| 48 |
.net_active_window = intern(display, "_NET_ACTIVE_WINDOW"),
|
| 49 |
.net_wm_window_type = intern(display, "_NET_WM_WINDOW_TYPE"),
|
| 50 |
.net_wm_window_type_dialog = intern(display, "_NET_WM_WINDOW_TYPE_DIALOG"),
|
| 51 |
.net_client_list = intern(display, "_NET_CLIENT_LIST"),
|
| 52 |
};
|
| 53 |
|
| 54 |
const utf8_string = intern(display, "UTF8_STRING");
|
| 55 |
|
| 56 |
// Create the EWMH check window.
|
| 57 |
var check_win = xlib.XCreateSimpleWindow(display, root, 0, 0, 1, 1, 0, 0, 0);
|
| 58 |
|
| 59 |
_ = xlib.XChangeProperty(display, check_win, atoms.net_wm_check, xlib.XA_WINDOW, 32, xlib.PropModeReplace, @ptrCast(&check_win), 1);
|
| 60 |
_ = xlib.XChangeProperty(display, check_win, atoms.net_wm_name, utf8_string, 8, xlib.PropModeReplace, "oxwm", 4);
|
| 61 |
_ = xlib.XChangeProperty(display, root, atoms.net_wm_check, xlib.XA_WINDOW, 32, xlib.PropModeReplace, @ptrCast(&check_win), 1);
|
| 62 |
|
| 63 |
// Advertise supported EWMH hints on the root window.
|
| 64 |
var net_atoms = [_]xlib.Atom{
|
| 65 |
atoms.net_supported,
|
| 66 |
atoms.net_wm_name,
|
| 67 |
atoms.net_wm_state,
|
| 68 |
atoms.net_wm_check,
|
| 69 |
atoms.net_wm_state_fullscreen,
|
| 70 |
atoms.net_active_window,
|
| 71 |
atoms.net_wm_window_type,
|
| 72 |
atoms.net_wm_window_type_dialog,
|
| 73 |
atoms.net_client_list,
|
| 74 |
};
|
| 75 |
_ = xlib.XChangeProperty(display, root, atoms.net_supported, xlib.XA_ATOM, 32, xlib.PropModeReplace, @ptrCast(&net_atoms), net_atoms.len);
|
| 76 |
|
| 77 |
_ = xlib.XDeleteProperty(display, root, atoms.net_client_list);
|
| 78 |
|
| 79 |
return .{ .atoms = atoms, .check_window = check_win };
|
| 80 |
}
|
| 81 |
};
|