1const std = @import("std");
2const log = std.log;
3const mem = std.mem;
4const posix = std.posix;
5const linux = std.os.linux;
6const io = std.io;
7
8const render = @import("render.zig");
9const Loop = @This();
10
11const state = &@import("root").state;
12
13sfd: posix.fd_t,
14
15pub fn init() !Loop {
16 var mask = posix.empty_sigset;
17 linux.sigaddset(&mask, linux.SIG.INT);
18 linux.sigaddset(&mask, linux.SIG.TERM);
19 linux.sigaddset(&mask, linux.SIG.QUIT);
20
21 _ = linux.sigprocmask(linux.SIG.BLOCK, &mask, null);
22 const sfd = linux.signalfd(-1, &mask, linux.SFD.NONBLOCK);
23
24 return Loop{ .sfd = @intCast(sfd) };
25}
26
27pub fn run(self: *Loop) !void {
28 const wayland = &state.wayland;
29
30 var fds = [_]posix.pollfd{
31 .{
32 .fd = self.sfd,
33 .events = posix.POLL.IN,
34 .revents = undefined,
35 },
36 .{
37 .fd = wayland.fd,
38 .events = posix.POLL.IN,
39 .revents = undefined,
40 },
41 .{
42 .fd = posix.STDIN_FILENO,
43 .events = posix.POLL.IN,
44 .revents = undefined,
45 },
46 };
47
48 var reader = io.getStdIn().reader();
49 while (true) {
50 while (true) {
51 const ret = wayland.display.dispatchPending();
52 _ = wayland.display.flush();
53 if (ret == .SUCCESS) break;
54 }
55
56 _ = posix.poll(&fds, -1) catch |err| {
57 log.err("poll failed: {s}", .{@errorName(err)});
58 return;
59 };
60
61 for (fds) |fd| {
62 if (fd.revents & posix.POLL.HUP != 0 or fd.revents & posix.POLL.ERR != 0) {
63 return;
64 }
65 }
66
67 // signals
68 if (fds[0].revents & posix.POLL.IN != 0) {
69 return;
70 }
71
72 // wayland
73 if (fds[1].revents & posix.POLL.IN != 0) {
74 const errno = wayland.display.dispatch();
75 if (errno != .SUCCESS) return;
76 }
77 if (fds[1].revents & posix.POLL.OUT != 0) {
78 const errno = wayland.display.flush();
79 if (errno != .SUCCESS) return;
80 }
81
82 // status input
83 if (fds[2].revents & posix.POLL.IN != 0) {
84 if (state.wayland.river_seat) |seat| {
85 if (seat.focusedBar()) |bar| {
86 seat.status_text.reset();
87 try reader.streamUntilDelimiter(seat.status_text.writer(), '\n', null);
88
89 render.renderText(bar, seat.status_text.getWritten()) catch |err| {
90 log.err("renderText failed for monitor {}: {s}",
91 .{bar.monitor.globalName, @errorName(err)});
92 continue;
93 };
94
95 bar.text.surface.commit();
96 bar.background.surface.commit();
97 }
98 }
99 }
100 }
101}