~andreafeletto/levee

ref: a40cd1f35e815d58ac2b5bdf3968a611a8a0972e levee/src/Loop.zig -rw-r--r-- 2.2 KiB
a40cd1f3Andrea Feletto pulse: respect muted flag 4 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
const std = @import("std");
const mem = std.mem;
const os = std.os;

const State = @import("main.zig").State;
const Loop = @This();

state: *State,
sfd: os.fd_t,

pub const Event = struct {
    fd: os.pollfd,
    data: *anyopaque,
    callbackIn: Callback,
    callbackOut: Callback,

    pub const Callback = fn (*anyopaque) error{Terminate}!void;

    pub fn terminate(_: *anyopaque) error{Terminate}!void {
        return error.Terminate;
    }

    pub fn noop(_: *anyopaque) error{Terminate}!void {
        return;
    }
};

pub fn init(state: *State) !Loop {
    var mask = mem.zeroes(os.linux.sigset_t);
    os.linux.sigaddset(&mask, os.linux.SIG.INT);
    os.linux.sigaddset(&mask, os.linux.SIG.TERM);
    os.linux.sigaddset(&mask, os.linux.SIG.QUIT);
    _ = os.linux.sigprocmask(os.linux.SIG.BLOCK, &mask, null);
    const sfd = os.linux.signalfd(-1, &mask, os.linux.SFD.NONBLOCK);

    return Loop{ .state = state, .sfd = @intCast(os.fd_t, sfd) };
}

pub fn run(self: *Loop) !void {
    const gpa = self.state.gpa;
    const display = self.state.wayland.display;

    var events: std.MultiArrayList(Event) = .{};
    defer events.deinit(gpa);

    try events.append(gpa, .{
        .fd = .{ .fd = self.sfd, .events = os.POLL.IN, .revents = 0 },
        .data = undefined,
        .callbackIn = Event.terminate,
        .callbackOut = Event.noop,
    });
    try events.append(gpa, try self.state.wayland.getEvent());
    for (self.state.modules.modules.items) |*module| {
        try events.append(gpa, try module.getEvent());
    }

    const fds = events.items(.fd);
    while (true) {
        while (true) {
            const ret = try display.dispatchPending();
            _ = try display.flush();
            if (ret <= 0) break;
        }
        _ = try os.poll(fds, -1);

        for (fds) |fd, i| {
            if (fd.revents & os.POLL.HUP != 0) return;
            if (fd.revents & os.POLL.ERR != 0) return;

            if (fd.revents & os.POLL.IN != 0) {
                const event = events.get(i);
                event.callbackIn(event.data) catch return;
            }
            if (fd.revents & os.POLL.OUT != 0) {
                const event = events.get(i);
                event.callbackOut(event.data) catch return;
            }
        }
    }
}