basic pty opening

This commit is contained in:
Mitchell Hashimoto
2022-04-15 13:09:35 -07:00
parent 38428f94c1
commit 2cd51f0cc4
4 changed files with 106 additions and 4 deletions

View File

@ -7,10 +7,11 @@ const std = @import("std");
const Allocator = std.mem.Allocator;
const Window = @import("Window.zig");
const log = std.log;
/// General purpose allocator
alloc: Allocator,
/// The primary window for the application. We currently support only
/// single window operations.
window: *Window,
/// Initialize the main app instance. This creates the main window, sets

76
src/Pty.zig Normal file
View File

@ -0,0 +1,76 @@
//! Linux PTY creation and management. This is just a thin layer on top
//! of Linux syscalls. The caller is responsible for detail-oriented handling
//! of the returned file handles.
const Pty = @This();
const std = @import("std");
const testing = std.testing;
const linux = std.os.linux;
const fd_t = std.os.fd_t;
const winsize = linux.winsize;
const c = @cImport({
@cInclude("pty.h");
});
/// The file descriptors for the master and slave side of the pty.
master: fd_t,
slave: fd_t,
/// Open a new PTY with the given initial size.
pub fn open(size: winsize) !Pty {
var master_fd: fd_t = undefined;
var slave_fd: fd_t = undefined;
if (c.openpty(
&master_fd,
&slave_fd,
null,
null,
@ptrCast([*c]const c.struct_winsize, &size),
) < 0)
return error.OpenptyFailed;
return Pty{
.master = master_fd,
.slave = slave_fd,
};
}
pub fn deinit(self: *Pty) void {
std.os.close(self.master);
self.* = undefined;
}
/// Return the size of the pty.
pub fn getSize(self: Pty) !winsize {
var ws: winsize = undefined;
if (linux.ioctl(self.master, linux.T.IOCGWINSZ, @ptrToInt(&ws)) < 0)
return error.IoctlFailed;
return ws;
}
/// Set the size of the pty.
pub fn setSize(self: Pty, size: winsize) !void {
if (linux.ioctl(self.master, linux.T.IOCSWINSZ, @ptrToInt(&size)) < 0)
return error.IoctlFailed;
}
test {
var ws: winsize = .{
.ws_row = 50,
.ws_col = 80,
.ws_xpixel = 1,
.ws_ypixel = 1,
};
var pty = try open(ws);
defer pty.deinit();
// Initialize size should match what we gave it
try testing.expectEqual(ws, try pty.getSize());
// Can set and read new sizes
ws.ws_row *= 2;
try pty.setSize(ws);
try testing.expectEqual(ws, try pty.getSize());
}

View File

@ -11,6 +11,7 @@ const Allocator = std.mem.Allocator;
const Grid = @import("Grid.zig");
const glfw = @import("glfw");
const gl = @import("opengl.zig");
const Pty = @import("Pty.zig");
const log = std.log.scoped(.window);
@ -20,6 +21,9 @@ window: glfw.Window,
/// The terminal grid attached to this window.
grid: Grid,
/// The underlying pty for this window.
pty: Pty,
/// Create a new window. This allocates and returns a pointer because we
/// need a stable pointer for user data callbacks. Therefore, a stack-only
/// initialization is not currently possible.
@ -61,13 +65,24 @@ pub fn create(alloc: Allocator) !*Window {
gl.c.glEnable(gl.c.GL_BLEND);
gl.c.glBlendFunc(gl.c.GL_SRC_ALPHA, gl.c.GL_ONE_MINUS_SRC_ALPHA);
// Create our terminal grid with a bogus initial size.
// Create our terminal grid with the initial window size
const window_size = try window.getSize();
var grid = try Grid.init(alloc);
try grid.setScreenSize(.{ .width = 640, .height = 480 });
try grid.setScreenSize(.{ .width = window_size.width, .height = window_size.height });
// Create our pty
var pty = try Pty.open(.{
.ws_row = @intCast(u16, grid.size.rows),
.ws_col = @intCast(u16, grid.size.columns),
.ws_xpixel = @intCast(u16, window_size.width),
.ws_ypixel = @intCast(u16, window_size.height),
});
errdefer pty.deinit();
self.* = .{
.window = window,
.grid = grid,
.pty = pty,
};
// Setup our callbacks and user data
@ -78,6 +93,7 @@ pub fn create(alloc: Allocator) !*Window {
}
pub fn destroy(self: *Window, alloc: Allocator) void {
self.pty.deinit();
self.grid.deinit();
self.window.destroy();
alloc.destroy(self);
@ -114,6 +130,14 @@ fn sizeCallback(window: glfw.Window, width: i32, height: i32) void {
// TODO: temp
win.grid.demoCells() catch unreachable;
// Update the size of our pty
win.pty.setSize(.{
.ws_row = @intCast(u16, win.grid.size.rows),
.ws_col = @intCast(u16, win.grid.size.columns),
.ws_xpixel = @intCast(u16, width),
.ws_ypixel = @intCast(u16, height),
}) catch |err| log.err("error updating pty screen size err={}", .{err});
// Update our viewport for this context to be the entire window
gl.viewport(0, 0, width, height) catch |err|
log.err("error updating OpenGL viewport err={}", .{err});

View File

@ -22,4 +22,5 @@ test {
_ = @import("Atlas.zig");
_ = @import("FontAtlas.zig");
_ = @import("Grid.zig");
_ = @import("Pty.zig");
}