tty: implement winch handling
Signed-off-by: Tim Culverhouse <tim@timculverhouse.com>
This commit is contained in:
parent
3783bcad10
commit
a9c97d051b
2 changed files with 66 additions and 0 deletions
|
@ -17,6 +17,7 @@ pub fn main() !void {
|
||||||
break :outer;
|
break :outer;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
.winsize => {},
|
||||||
else => {},
|
else => {},
|
||||||
}
|
}
|
||||||
log.debug("event: {}\r\n", .{event});
|
log.debug("event: {}\r\n", .{event});
|
||||||
|
@ -25,5 +26,6 @@ pub fn main() !void {
|
||||||
|
|
||||||
const Event = union(enum) {
|
const Event = union(enum) {
|
||||||
key_press: odditui.Key,
|
key_press: odditui.Key,
|
||||||
|
winsize: std.os.system.winsize,
|
||||||
mouse: u8,
|
mouse: u8,
|
||||||
};
|
};
|
||||||
|
|
64
src/Tty.zig
64
src/Tty.zig
|
@ -1,4 +1,5 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const builtin = @import("builtin");
|
||||||
const os = std.os;
|
const os = std.os;
|
||||||
const odditui = @import("main.zig");
|
const odditui = @import("main.zig");
|
||||||
const App = odditui.App;
|
const App = odditui.App;
|
||||||
|
@ -57,9 +58,47 @@ pub fn run(
|
||||||
defer os.close(pipe[0]);
|
defer os.close(pipe[0]);
|
||||||
defer os.close(pipe[1]);
|
defer os.close(pipe[1]);
|
||||||
|
|
||||||
|
// get our initial winsize
|
||||||
|
const winsize = try getWinsize(self.fd);
|
||||||
|
log.debug("{}", .{winsize});
|
||||||
|
|
||||||
// assign the write end of the pipe to our quit_fd
|
// assign the write end of the pipe to our quit_fd
|
||||||
self.quit_fd = pipe[1];
|
self.quit_fd = pipe[1];
|
||||||
|
|
||||||
|
// Build a winch handler. We need build this struct to get an anonymous
|
||||||
|
// function which can post the winsize event
|
||||||
|
// TODO: more signals, move this outside of this function?
|
||||||
|
const WinchHandler = struct {
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
var winchApp: *App(EventType) = undefined;
|
||||||
|
var fd: os.fd_t = undefined;
|
||||||
|
|
||||||
|
fn init(app_arg: *App(EventType), fd_arg: os.fd_t) !void {
|
||||||
|
winchApp = app_arg;
|
||||||
|
fd = fd_arg;
|
||||||
|
var act = os.Sigaction{
|
||||||
|
.handler = .{ .handler = Self.handleWinch },
|
||||||
|
.mask = switch (builtin.os.tag) {
|
||||||
|
.macos => 0,
|
||||||
|
.linux => std.os.empty_sigset,
|
||||||
|
else => @compileError("os not supported"),
|
||||||
|
},
|
||||||
|
.flags = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
try os.sigaction(os.SIG.WINCH, &act, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handleWinch(_: c_int) callconv(.C) void {
|
||||||
|
const ws = getWinsize(fd) catch {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
winchApp.postEvent(.{ .winsize = ws });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
try WinchHandler.init(app, self.fd);
|
||||||
|
|
||||||
// the state of the parser
|
// the state of the parser
|
||||||
const State = enum {
|
const State = enum {
|
||||||
ground,
|
ground,
|
||||||
|
@ -167,3 +206,28 @@ pub fn makeRaw(fd: os.fd_t) !os.termios {
|
||||||
try os.tcsetattr(fd, .FLUSH, raw);
|
try os.tcsetattr(fd, .FLUSH, raw);
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const TIOCGWINSZ = switch (builtin.os.tag) {
|
||||||
|
.linux => 0x5413,
|
||||||
|
.macos => ior(0x40000000, 't', 104, @sizeOf(os.system.winsize)),
|
||||||
|
else => @compileError("Missing termiosbits for this target, sorry."),
|
||||||
|
};
|
||||||
|
|
||||||
|
const IOCPARM_MASK = 0x1fff;
|
||||||
|
fn ior(inout: u32, group: usize, num: usize, len: usize) usize {
|
||||||
|
return (inout | ((len & IOCPARM_MASK) << 16) | ((group) << 8) | (num));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getWinsize(fd: os.fd_t) !os.system.winsize {
|
||||||
|
var winsize = os.system.winsize{
|
||||||
|
.ws_row = 0,
|
||||||
|
.ws_col = 0,
|
||||||
|
.ws_xpixel = 0,
|
||||||
|
.ws_ypixel = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
const err = os.system.ioctl(fd, TIOCGWINSZ, @intFromPtr(&winsize));
|
||||||
|
if (os.errno(err) == .SUCCESS)
|
||||||
|
return winsize;
|
||||||
|
return error.IoctlError;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue