From 7b7b84ad2197b68194dc2b9f46df40da15896f2c Mon Sep 17 00:00:00 2001 From: Kalle Carlbark Date: Thu, 4 Jul 2024 14:53:40 +0200 Subject: [PATCH] wip: macos --- examples/vt.zig | 3 + log.lg | 172 ++++++++++++++++++++++++++++++ src/widgets/terminal/Command.zig | 24 ++++- src/widgets/terminal/Pty.zig | 87 ++++++++++++++- src/widgets/terminal/Terminal.zig | 9 ++ src/widgets/terminal/log.lg | 5 + 6 files changed, 298 insertions(+), 2 deletions(-) create mode 100644 log.lg create mode 100644 src/widgets/terminal/log.lg diff --git a/examples/vt.zig b/examples/vt.zig index 4a61307..4b1a570 100644 --- a/examples/vt.zig +++ b/examples/vt.zig @@ -61,9 +61,11 @@ pub fn main() !void { var redraw: bool = false; while (true) { + std.debug.print("inside while loop before resize\n", .{}); std.time.sleep(8 * std.time.ns_per_ms); // try vt events first while (vt.tryEvent()) |event| { + std.debug.print("inside stryEventloop \n", .{}); redraw = true; switch (event) { .bell => {}, @@ -74,6 +76,7 @@ pub fn main() !void { } } while (loop.tryEvent()) |event| { + std.debug.print("inside loop.tryEvent\n", .{}); redraw = true; switch (event) { .key_press => |key| { diff --git a/log.lg b/log.lg new file mode 100644 index 0000000..cfb9f6c --- /dev/null +++ b/log.lg @@ -0,0 +1,172 @@ +info(loop): pixel mouse capability detected +info(loop): unicode capability detected +info(loop): color_scheme_updates capability detected +info(loop): kitty keyboard capability detected +info(loop): kitty graphics capability detected +slave name: /dev/ttys008 +posix opened : /dev/ttys008 +set size done +inside spawnwe are not child: 56928 +inside while loop before resize +inside run +inside while loop +inside loop.tryEvent +debug(vaxis): resizing screen: width=81 height=49 +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside loop.tryEvent +before switch event +inside print event +inside while loop +inside while loop before resize +inside stryEventloop +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside loop.tryEvent +before switch event +inside print event +inside while loop +inside while loop before resize +inside stryEventloop +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside loop.tryEvent +before switch event +inside handlec0 +inside while loop +before switch event +inside handlec0 +inside while loop +inside while loop before resize +inside stryEventloop +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside loop.tryEvent +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside while loop before resize +inside loop.tryEvent +before switch event +inside handlec0 +debug(vaxis): total renders = 8 +debug(vaxis): microseconds per render = 1393 diff --git a/src/widgets/terminal/Command.zig b/src/widgets/terminal/Command.zig index 84f86b8..3681028 100644 --- a/src/widgets/terminal/Command.zig +++ b/src/widgets/terminal/Command.zig @@ -17,6 +17,22 @@ pid: ?std.posix.pid_t = null, env_map: *const std.process.EnvMap, pty: Pty, +const TIOCSCTTY = if (builtin.os.tag == .macos) 536900705 else c.TIOCSCTTY; +const TIOCSWINSZ = if (builtin.os.tag == .macos) 2148037735 else c.TIOCSWINSZ; +const TIOCGWINSZ = if (builtin.os.tag == .macos) 1074295912 else c.TIOCGWINSZ; +extern "c" fn setsid() std.c.pid_t; +const c = struct { + usingnamespace switch (builtin.os.tag) { + .macos => @cImport({ + @cInclude("sys/ioctl.h"); // ioctl and constants + @cInclude("util.h"); // openpty() + }), + else => @cImport({ + @cInclude("sys/ioctl.h"); // ioctl and constants + @cInclude("pty.h"); + }), + }; +}; pub fn spawn(self: *Command, allocator: std.mem.Allocator) !void { var arena_allocator = std.heap.ArenaAllocator.init(allocator); @@ -33,10 +49,12 @@ pub fn spawn(self: *Command, allocator: std.mem.Allocator) !void { if (pid == 0) { // we are the child _ = std.os.linux.setsid(); + _ = setsid(); + // if (setsid() < 0) return error.ProcessGroupFailed; // set the controlling terminal var u: c_uint = std.posix.STDIN_FILENO; - if (posix.system.ioctl(self.pty.tty, posix.T.IOCSCTTY, @intFromPtr(&u)) != 0) return error.IoctlError; + if (c.ioctl(self.pty.tty, TIOCSCTTY, @intFromPtr(&u)) != 0) return error.IoctlError; // set up io try posix.dup2(self.pty.tty, std.posix.STDIN_FILENO); @@ -53,6 +71,10 @@ pub fn spawn(self: *Command, allocator: std.mem.Allocator) !void { // exec const err = std.posix.execvpeZ(argv_buf.ptr[0].?, argv_buf.ptr, envp); _ = err catch {}; + } else { + std.debug.print("we are not child: {d}\n", .{pid}); + // posix.close(self.pty.tty); + _ = posix.waitpid(pid, 0); } // we are the parent diff --git a/src/widgets/terminal/Pty.zig b/src/widgets/terminal/Pty.zig index 1258127..c3a046a 100644 --- a/src/widgets/terminal/Pty.zig +++ b/src/widgets/terminal/Pty.zig @@ -7,6 +7,25 @@ const Winsize = @import("../../main.zig").Winsize; const posix = std.posix; +extern "c" fn setsid() std.c.pid_t; + +const c = struct { + usingnamespace switch (builtin.os.tag) { + .macos => @cImport({ + @cInclude("sys/ioctl.h"); // ioctl and constants + @cInclude("util.h"); // openpty() + }), + else => @cImport({ + @cInclude("sys/ioctl.h"); // ioctl and constants + @cInclude("pty.h"); + }), + }; +}; + +const TIOCSCTTY = if (builtin.os.tag == .macos) 536900705 else c.TIOCSCTTY; +const TIOCSWINSZ = if (builtin.os.tag == .macos) 2148037735 else c.TIOCSWINSZ; +const TIOCGWINSZ = if (builtin.os.tag == .macos) 1074295912 else c.TIOCGWINSZ; + pty: posix.fd_t, tty: posix.fd_t, @@ -14,6 +33,7 @@ tty: posix.fd_t, pub fn init() !Pty { switch (builtin.os.tag) { .linux => return openPtyLinux(), + .macos => return openPtyMacos2(), else => @compileError("unsupported os"), } } @@ -32,10 +52,75 @@ pub fn setSize(self: Pty, ws: Winsize) !void { .ws_xpixel = @truncate(ws.x_pixel), .ws_ypixel = @truncate(ws.y_pixel), }; - if (posix.system.ioctl(self.pty, posix.T.IOCSWINSZ, @intFromPtr(&_ws)) != 0) + if (c.ioctl(self.pty, TIOCSWINSZ, @intFromPtr(&_ws)) != 0) return error.SetWinsizeError; } +fn openPtyMacos2() !Pty { + const p = try posix.open("/dev/ptmx", .{ .ACCMODE = .RDWR, .NOCTTY = true }, 0); + errdefer posix.close(p); + + // unlockpt + // var n: c_uint = 0; + if (c.ioctl(p, c.TIOCPTYUNLK) != 0) return error.IoctlError; + + // ptsname + if (c.ioctl(p, c.TIOCPTYGRANT) != 0) return error.IoctlError; + + var buf: [128]u8 = undefined; + // var buf2: [128]u8 = undefined; + if (c.ioctl(p, c.TIOCPTYGNAME, &buf) != 0) return error.IoctlError; + const sname = buf[0 .. 13 - 1]; + // std.debug.print("sizeof buf: {d}", .{buf.len}); + // const sname = try std.fmt.bufPrint(&buf2, "{s}", .{buf}); + std.debug.print("slave name: {s}\n", .{sname}); + // const sname = try std.fmt.bufPrint(&buf, "/dev/pts/{d}", .{n}); + // std.log.err("pts: {s}", .{sname}); + + const t = try posix.open(sname, .{ .ACCMODE = .RDWR, .NOCTTY = true }, 0); + std.debug.print("posix opened : {s}\n", .{sname}); + + var attrs: c.termios = undefined; + if (c.tcgetattr(p, &attrs) != 0) + return error.OpenptyFailed; + attrs.c_iflag |= c.IUTF8; + if (c.tcsetattr(p, c.TCSANOW, &attrs) != 0) + return error.OpenptyFailed; + + return .{ + .pty = p, + .tty = t, + }; +} + +fn openPtyMacos() !Pty { + var master_fd: posix.fd_t = undefined; + var slave_fd: posix.fd_t = undefined; + if (c.openpty( + &master_fd, + &slave_fd, + null, + null, + null, + ) < 0) + return error.OpenptyFailed; + errdefer { + _ = posix.system.close(master_fd); + _ = posix.system.close(slave_fd); + } + var attrs: c.termios = undefined; + if (c.tcgetattr(master_fd, &attrs) != 0) + return error.OpenptyFailed; + attrs.c_iflag |= c.IUTF8; + if (c.tcsetattr(master_fd, c.TCSANOW, &attrs) != 0) + return error.OpenptyFailed; + + return .{ + .pty = master_fd, + .tty = slave_fd, + }; +} + fn openPtyLinux() !Pty { const p = try posix.open("/dev/ptmx", .{ .ACCMODE = .RDWR, .NOCTTY = true }, 0); errdefer posix.close(p); diff --git a/src/widgets/terminal/Terminal.zig b/src/widgets/terminal/Terminal.zig index 1bc58ef..a61bea0 100644 --- a/src/widgets/terminal/Terminal.zig +++ b/src/widgets/terminal/Terminal.zig @@ -100,6 +100,7 @@ pub fn init( } const pty = try Pty.init(); try pty.setSize(opts.winsize); + std.debug.print("set size done\n", .{}); const cmd: Command = .{ .argv = argv, .env_map = env, @@ -159,6 +160,7 @@ pub fn deinit(self: *Terminal) void { } pub fn spawn(self: *Terminal) !void { + std.debug.print("inside spawn", .{}); if (self.thread != null) return; self.back_screen = &self.back_screen_pri; @@ -273,6 +275,7 @@ fn anyReader(self: *const Terminal) std.io.AnyReader { /// process the output from the command on the pty fn run(self: *Terminal) !void { + std.debug.print("inside run\n", .{}); var parser: Parser = .{ .buf = try std.ArrayList(u8).initCapacity(self.allocator, 128), }; @@ -282,6 +285,7 @@ fn run(self: *Terminal) !void { var reader = std.io.bufferedReader(self.anyReader()); while (!self.should_quit) { + std.debug.print("inside while loop\n", .{}); const event = try parser.parseReader(&reader); self.back_mutex.lock(); defer self.back_mutex.unlock(); @@ -289,8 +293,10 @@ fn run(self: *Terminal) !void { if (!self.dirty and self.event_queue.tryPush(.redraw)) self.dirty = true; + std.debug.print("before switch event\n", .{}); switch (event) { .print => |str| { + std.debug.print("inside print event\n", .{}); var iter = grapheme.Iterator.init(str, &self.unicode.grapheme_data); while (iter.next()) |g| { const gr = g.bytes(str); @@ -301,6 +307,7 @@ fn run(self: *Terminal) !void { }, .c0 => |b| try self.handleC0(b), .escape => |esc| { + std.debug.print("inside escape event\n", .{}); const final = esc[esc.len - 1]; switch (final) { 'B' => {}, // TODO: handle charsets @@ -714,6 +721,7 @@ fn run(self: *Terminal) !void { } inline fn handleC0(self: *Terminal, b: ansi.C0) !void { + std.debug.print("inside handlec0\n", .{}); switch (b) { .NUL, .SOH, .STX => {}, .EOT => {}, // we send EOT to quit the read thread @@ -730,6 +738,7 @@ inline fn handleC0(self: *Terminal, b: ansi.C0) !void { } pub fn setMode(self: *Terminal, mode: u16, val: bool) void { + std.debug.print("inside setmode\n", .{}); switch (mode) { 7 => self.mode.autowrap = val, 25 => self.mode.cursor = val, diff --git a/src/widgets/terminal/log.lg b/src/widgets/terminal/log.lg new file mode 100644 index 0000000..f371781 --- /dev/null +++ b/src/widgets/terminal/log.lg @@ -0,0 +1,5 @@ +info(loop): pixel mouse capability detected +info(loop): unicode capability detected +info(loop): color_scheme_updates capability detected +info(loop): kitty keyboard capability detected +info(loop): kitty graphics capability detected