oxwm

https://git.tonybtw.com/oxwm.git git://git.tonybtw.com/oxwm.git
4,278 bytes raw
1
const std = @import("std");
2
const xlib = @import("x11/xlib.zig");
3
const Client = @import("client.zig").Client;
4
5
pub const Layout = struct {
6
    symbol: []const u8,
7
    arrange_fn: ?*const fn (*Monitor) void,
8
};
9
10
pub const Pertag = struct {
11
    curtag: u32 = 1,
12
    prevtag: u32 = 1,
13
    nmasters: [10]i32 = [_]i32{1} ** 10,
14
    mfacts: [10]f32 = [_]f32{0.55} ** 10,
15
    sellts: [10]u32 = [_]u32{0} ** 10,
16
    ltidxs: [10][5]?*const Layout = [_][5]?*const Layout{.{ null, null, null, null, null }} ** 10,
17
    showbars: [10]bool = [_]bool{true} ** 10,
18
};
19
20
pub const Monitor = struct {
21
    lt_symbol: [16]u8 = std.mem.zeroes([16]u8),
22
    mfact: f32 = 0.55,
23
    nmaster: i32 = 1,
24
    num: i32 = 0,
25
    bar_y: i32 = 0,
26
    mon_x: i32 = 0,
27
    mon_y: i32 = 0,
28
    mon_w: i32 = 0,
29
    mon_h: i32 = 0,
30
    win_x: i32 = 0,
31
    win_y: i32 = 0,
32
    win_w: i32 = 0,
33
    win_h: i32 = 0,
34
    gap_inner_h: i32 = 0,
35
    gap_inner_v: i32 = 0,
36
    gap_outer_h: i32 = 0,
37
    gap_outer_v: i32 = 0,
38
    scroll_offset: i32 = 0,
39
    sel_tags: u32 = 0,
40
    sel_lt: u32 = 0,
41
    tagset: [2]u32 = .{ 1, 1 },
42
    show_bar: bool = true,
43
    top_bar: bool = true,
44
    clients: ?*Client = null,
45
    sel: ?*Client = null,
46
    stack: ?*Client = null,
47
    next: ?*Monitor = null,
48
    bar_win: xlib.Window = 0,
49
    lt: [5]?*const Layout = .{ null, null, null, null, null },
50
    pertag: Pertag = Pertag{},
51
};
52
53
pub var monitors: ?*Monitor = null;
54
pub var selected_monitor: ?*Monitor = null;
55
56
var allocator: std.mem.Allocator = undefined;
57
58
pub fn init(alloc: std.mem.Allocator) void {
59
    allocator = alloc;
60
}
61
62
pub fn create() ?*Monitor {
63
    const mon = allocator.create(Monitor) catch return null;
64
    mon.* = Monitor{};
65
    return mon;
66
}
67
68
pub fn destroy(mon: *Monitor) void {
69
    allocator.destroy(mon);
70
}
71
72
var root_window: xlib.Window = 0;
73
var display_handle: ?*xlib.Display = null;
74
75
pub fn set_root_window(root: xlib.Window, display: *xlib.Display) void {
76
    root_window = root;
77
    display_handle = display;
78
}
79
80
pub fn window_to_monitor(win: xlib.Window) ?*Monitor {
81
    if (win == root_window and display_handle != null) {
82
        var root_x: c_int = undefined;
83
        var root_y: c_int = undefined;
84
        var dummy_win: xlib.Window = undefined;
85
        var dummy_int: c_int = undefined;
86
        var dummy_uint: c_uint = undefined;
87
        if (xlib.XQueryPointer(display_handle.?, root_window, &dummy_win, &dummy_win, &root_x, &root_y, &dummy_int, &dummy_int, &dummy_uint) != 0) {
88
            return rect_to_monitor(root_x, root_y, 1, 1);
89
        }
90
    }
91
92
    var current = monitors;
93
    while (current) |monitor| {
94
        if (monitor.bar_win == win) {
95
            return monitor;
96
        }
97
        current = monitor.next;
98
    }
99
100
    const client = @import("client.zig").window_to_client(win);
101
    if (client) |found_client| {
102
        return found_client.monitor;
103
    }
104
105
    return selected_monitor;
106
}
107
108
pub fn rect_to_monitor(x: i32, y: i32, width: i32, height: i32) ?*Monitor {
109
    var result = selected_monitor;
110
    var max_area: i32 = 0;
111
112
    var current = monitors;
113
    while (current) |monitor| {
114
        const intersect_x = @max(0, @min(x + width, monitor.win_x + monitor.win_w) - @max(x, monitor.win_x));
115
        const intersect_y = @max(0, @min(y + height, monitor.win_y + monitor.win_h) - @max(y, monitor.win_y));
116
        const area = intersect_x * intersect_y;
117
        if (area > max_area) {
118
            max_area = area;
119
            result = monitor;
120
        }
121
        current = monitor.next;
122
    }
123
    return result;
124
}
125
126
pub fn dir_to_monitor(direction: i32) ?*Monitor {
127
    var target: ?*Monitor = null;
128
129
    if (direction > 0) {
130
        target = if (selected_monitor) |current| current.next else null;
131
        if (target == null) {
132
            target = monitors;
133
        }
134
    } else if (selected_monitor == monitors) {
135
        var last = monitors;
136
        while (last) |iter| {
137
            if (iter.next == null) {
138
                target = iter;
139
                break;
140
            }
141
            last = iter.next;
142
        }
143
    } else {
144
        var previous = monitors;
145
        while (previous) |iter| {
146
            if (iter.next == selected_monitor) {
147
                target = iter;
148
                break;
149
            }
150
            previous = iter.next;
151
        }
152
    }
153
    return target;
154
}