diff --git a/README.md b/README.md index e851723..b3e2f79 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Contributions are welcome. | Bracketed Paste | ✅ | ✅ | ❌ | | Kitty Keyboard | ✅ | ✅ | ✅ | | Styled Underlines | ✅ | ✅ | ✅ | -| Mouse Shapes (OSC 22) | ✅ | planned | ❌ | +| Mouse Shapes (OSC 22) | ✅ | ✅ | ❌ | | System Clipboard (OSC 52) | ✅ | planned | ❌ | | System Notifications (OSC 9) | ✅ | ✅ | ❌ | | System Notifications (OSC 777) | ✅ | ✅ | ❌ | diff --git a/src/InternalScreen.zig b/src/InternalScreen.zig index 02d7f10..c75e770 100644 --- a/src/InternalScreen.zig +++ b/src/InternalScreen.zig @@ -2,6 +2,7 @@ const std = @import("std"); const assert = std.debug.assert; const Style = @import("cell.zig").Style; const Cell = @import("cell.zig").Cell; +const Shape = @import("Mouse.zig").Shape; const log = std.log.scoped(.internal_screen); @@ -27,6 +28,8 @@ cursor_row: usize = 0, cursor_col: usize = 0, cursor_vis: bool = false, +mouse_shape: Shape = .default, + /// sets each cell to the default cell pub fn init(alloc: std.mem.Allocator, w: usize, h: usize) !InternalScreen { var screen = InternalScreen{}; diff --git a/src/Mouse.zig b/src/Mouse.zig new file mode 100644 index 0000000..99aa0eb --- /dev/null +++ b/src/Mouse.zig @@ -0,0 +1,14 @@ +/// A mouse event +pub const Mouse = @This(); + +pub const Shape = enum { + default, + text, + pointer, + help, + progress, + wait, + @"ew-resize", + @"ns-resize", + cell, +}; diff --git a/src/Screen.zig b/src/Screen.zig index 16920a4..d87b6b5 100644 --- a/src/Screen.zig +++ b/src/Screen.zig @@ -2,6 +2,7 @@ const std = @import("std"); const assert = std.debug.assert; const Cell = @import("cell.zig").Cell; +const Shape = @import("Mouse.zig").Shape; const log = std.log.scoped(.screen); @@ -18,6 +19,8 @@ cursor_vis: bool = false, unicode: bool = false, +mouse_shape: Shape = .default, + pub fn init(alloc: std.mem.Allocator, w: usize, h: usize) !Screen { var self = Screen{ .buf = try alloc.alloc(Cell, w * h), diff --git a/src/ctlseqs.zig b/src/ctlseqs.zig index 874223e..4b66da1 100644 --- a/src/ctlseqs.zig +++ b/src/ctlseqs.zig @@ -84,3 +84,4 @@ pub const osc8 = "\x1b]8;{s};{s}\x1b\\"; pub const osc8_clear = "\x1b]8;;\x1b\\"; pub const osc9_notify = "\x1b]9;{s}\x1b\\"; pub const osc777_notify = "\x1b]777;notify;{s};{s}\x1b\\"; +pub const osc22_mouse_shape = "\x1b]22;{s}\x1b\\"; diff --git a/src/main.zig b/src/main.zig index b6f1d4e..1e760f7 100644 --- a/src/main.zig +++ b/src/main.zig @@ -18,6 +18,7 @@ pub fn init(comptime EventType: type, opts: Options) !Vaxis(EventType) { test { _ = @import("GraphemeCache.zig"); _ = @import("Key.zig"); + _ = @import("Mouse.zig"); _ = @import("Options.zig"); _ = @import("Parser.zig"); _ = @import("Screen.zig"); diff --git a/src/vaxis.zig b/src/vaxis.zig index 3f559ae..96f971e 100644 --- a/src/vaxis.zig +++ b/src/vaxis.zig @@ -11,8 +11,8 @@ const InternalScreen = @import("InternalScreen.zig"); const Window = @import("Window.zig"); const Options = @import("Options.zig"); const Style = @import("cell.zig").Style; -const strWidth = @import("ziglyph").display_width.strWidth; const gwidth = @import("gwidth.zig"); +const Shape = @import("Mouse.zig").Shape; /// Vaxis is the entrypoint for a Vaxis application. The provided type T should /// be a tagged union which contains all of the events the application will @@ -458,6 +458,13 @@ pub fn Vaxis(comptime T: type) type { ); _ = try tty.write(ctlseqs.show_cursor); } + if (self.screen.mouse_shape != self.screen_last.mouse_shape) { + try std.fmt.format( + tty.buffered_writer.writer(), + ctlseqs.osc22_mouse_shape, + .{@tagName(self.screen.mouse_shape)}, + ); + } } fn enableKittyKeyboard(self: *Self, flags: Key.KittyFlags) !void { @@ -510,6 +517,11 @@ pub fn Vaxis(comptime T: type) type { _ = try self.tty.?.write(seq); try self.tty.?.flush(); } + + /// set the mouse shape + pub fn setMouseShape(self: *Self, shape: Shape) void { + self.screen.mouse_shape = shape; + } }; }