renderer: emit scrollbar apprt event when scrollbar changes

pull/9232/head
Mitchell Hashimoto 2025-10-15 21:03:25 -07:00
parent 5a9bd0e49e
commit da7736cd44
No known key found for this signature in database
GPG Key ID: 523D5DC389D273BC
6 changed files with 53 additions and 0 deletions

View File

@ -741,6 +741,13 @@ typedef struct {
uint64_t duration; uint64_t duration;
} ghostty_action_command_finished_s; } ghostty_action_command_finished_s;
// terminal.Scrollbar
typedef struct {
uint64_t total;
uint64_t offset;
uint64_t len;
} ghostty_action_scrollbar_s;
// apprt.Action.Key // apprt.Action.Key
typedef enum { typedef enum {
GHOSTTY_ACTION_QUIT, GHOSTTY_ACTION_QUIT,
@ -767,6 +774,7 @@ typedef enum {
GHOSTTY_ACTION_RESET_WINDOW_SIZE, GHOSTTY_ACTION_RESET_WINDOW_SIZE,
GHOSTTY_ACTION_INITIAL_SIZE, GHOSTTY_ACTION_INITIAL_SIZE,
GHOSTTY_ACTION_CELL_SIZE, GHOSTTY_ACTION_CELL_SIZE,
GHOSTTY_ACTION_SCROLLBAR,
GHOSTTY_ACTION_RENDER, GHOSTTY_ACTION_RENDER,
GHOSTTY_ACTION_INSPECTOR, GHOSTTY_ACTION_INSPECTOR,
GHOSTTY_ACTION_SHOW_GTK_INSPECTOR, GHOSTTY_ACTION_SHOW_GTK_INSPECTOR,
@ -809,6 +817,7 @@ typedef union {
ghostty_action_size_limit_s size_limit; ghostty_action_size_limit_s size_limit;
ghostty_action_initial_size_s initial_size; ghostty_action_initial_size_s initial_size;
ghostty_action_cell_size_s cell_size; ghostty_action_cell_size_s cell_size;
ghostty_action_scrollbar_s scrollbar;
ghostty_action_inspector_e inspector; ghostty_action_inspector_e inspector;
ghostty_action_desktop_notification_s desktop_notification; ghostty_action_desktop_notification_s desktop_notification;
ghostty_action_set_title_s set_title; ghostty_action_set_title_s set_title;

View File

@ -983,6 +983,8 @@ pub fn handleMessage(self: *Surface, msg: Message) !void {
.renderer_health => |health| self.updateRendererHealth(health), .renderer_health => |health| self.updateRendererHealth(health),
.scrollbar => |scrollbar| self.updateScrollbar(scrollbar),
.report_color_scheme => |force| self.reportColorScheme(force), .report_color_scheme => |force| self.reportColorScheme(force),
.present_surface => try self.presentSurface(), .present_surface => try self.presentSurface(),
@ -1459,6 +1461,17 @@ fn updateRendererHealth(self: *Surface, health: rendererpkg.Health) void {
}; };
} }
/// Called when the scrollbar state changes.
fn updateScrollbar(self: *Surface, scrollbar: terminal.Scrollbar) void {
_ = self.rt_app.performAction(
.{ .surface = self },
.scrollbar,
scrollbar,
) catch |err| {
log.warn("failed to notify app of scrollbar change err={}", .{err});
};
}
/// This should be called anytime `config_conditional_state` changes /// This should be called anytime `config_conditional_state` changes
/// so that the apprt can reload the configuration. /// so that the apprt can reload the configuration.
fn notifyConfigConditionalState(self: *Surface) void { fn notifyConfigConditionalState(self: *Surface) void {

View File

@ -164,6 +164,9 @@ pub const Action = union(Key) {
/// The cell size has changed to the given dimensions in pixels. /// The cell size has changed to the given dimensions in pixels.
cell_size: CellSize, cell_size: CellSize,
/// The scrollbar is updating.
scrollbar: terminal.Scrollbar,
/// The target should be re-rendered. This usually has a specific /// The target should be re-rendered. This usually has a specific
/// surface target but if the app is targeted then all active /// surface target but if the app is targeted then all active
/// surfaces should be redrawn. /// surfaces should be redrawn.
@ -324,6 +327,7 @@ pub const Action = union(Key) {
reset_window_size, reset_window_size,
initial_size, initial_size,
cell_size, cell_size,
scrollbar,
render, render,
inspector, inspector,
show_gtk_inspector, show_gtk_inspector,

View File

@ -104,6 +104,9 @@ pub const Message = union(enum) {
/// of the command. /// of the command.
stop_command: ?u8, stop_command: ?u8,
/// The scrollbar state changed for the surface.
scrollbar: terminal.Scrollbar,
pub const ReportTitleStyle = enum { pub const ReportTitleStyle = enum {
csi_21_t, csi_21_t,

View File

@ -1314,6 +1314,15 @@ pub fn Renderer(comptime GraphicsAPI: type) type {
self.draw_mutex.lock(); self.draw_mutex.lock();
defer self.draw_mutex.unlock(); defer self.draw_mutex.unlock();
// After the graphics API is complete (so we defer) we want to
// update our scrollbar state.
defer if (self.scrollbar_dirty) {
self.scrollbar_dirty = false;
_ = self.surface_mailbox.push(.{
.scrollbar = self.scrollbar,
}, .{ .forever = {} });
};
// Let our graphics API do any bookkeeping, etc. // Let our graphics API do any bookkeeping, etc.
// that it needs to do before / after `drawFrame`. // that it needs to do before / after `drawFrame`.
self.api.drawFrameStart(); self.api.drawFrameStart();

View File

@ -2110,6 +2110,21 @@ pub const Scrollbar = struct {
.len = 0, .len = 0,
}; };
// Sync with: ghostty_action_scrollbar_s
pub const C = extern struct {
total: u64,
offset: u64,
len: u64,
};
pub fn cval(self: Scrollbar) C {
return .{
.total = @intCast(self.total),
.offset = @intCast(self.offset),
.len = @intCast(self.len),
};
}
/// Comparison for scrollbars. /// Comparison for scrollbars.
pub fn eql(self: Scrollbar, other: Scrollbar) bool { pub fn eql(self: Scrollbar, other: Scrollbar) bool {
return self.total == other.total and return self.total == other.total and