mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 08:46:08 +03:00
hook up scrolling, kind of works, kind of broke
This commit is contained in:
@ -250,6 +250,7 @@ pub fn create(alloc: Allocator, loop: libuv.Loop, config: *const Config) !*Windo
|
|||||||
window.setKeyCallback(keyCallback);
|
window.setKeyCallback(keyCallback);
|
||||||
window.setFocusCallback(focusCallback);
|
window.setFocusCallback(focusCallback);
|
||||||
window.setRefreshCallback(refreshCallback);
|
window.setRefreshCallback(refreshCallback);
|
||||||
|
window.setScrollCallback(scrollCallback);
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@ -505,6 +506,24 @@ fn refreshCallback(window: glfw.Window) void {
|
|||||||
win.render_timer.schedule() catch unreachable;
|
win.render_timer.schedule() catch unreachable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn scrollCallback(window: glfw.Window, xoff: f64, yoff: f64) void {
|
||||||
|
const win = window.getUserPointer(Window) orelse return;
|
||||||
|
|
||||||
|
//log.info("SCROLL: {} {}", .{ xoff, yoff });
|
||||||
|
_ = xoff;
|
||||||
|
|
||||||
|
// Positive is up
|
||||||
|
const sign: isize = if (yoff < 0) -1 else 1;
|
||||||
|
const delta: isize = sign * @maximum(@divFloor(win.grid.size.rows, 15), 1);
|
||||||
|
log.info("scroll: delta={}", .{delta});
|
||||||
|
win.terminal.scrollViewport(.{ .delta = delta });
|
||||||
|
|
||||||
|
// Schedule render since scrolling usually does something.
|
||||||
|
// TODO(perf): we can only schedule render if we know scrolling
|
||||||
|
// did something
|
||||||
|
win.render_timer.schedule() catch unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
fn cursorTimerCallback(t: *libuv.Timer) void {
|
fn cursorTimerCallback(t: *libuv.Timer) void {
|
||||||
const tracy = trace(@src());
|
const tracy = trace(@src());
|
||||||
defer tracy.end();
|
defer tracy.end();
|
||||||
|
@ -187,12 +187,25 @@ pub fn scroll(self: *Screen, behavior: Scroll) void {
|
|||||||
.bottom => self.visible_offset = self.bottom - self.rows,
|
.bottom => self.visible_offset = self.bottom - self.rows,
|
||||||
|
|
||||||
// TODO: deltas greater than the entire scrollback
|
// TODO: deltas greater than the entire scrollback
|
||||||
.delta => |delta| self.scrollDown(delta, true),
|
.delta => |delta| self.scrollDelta(delta, true),
|
||||||
.delta_no_grow => |delta| self.scrollDown(delta, false),
|
.delta_no_grow => |delta| self.scrollDelta(delta, false),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scrollDown(self: *Screen, delta: isize, grow: bool) void {
|
fn scrollDelta(self: *Screen, delta: isize, grow: bool) void {
|
||||||
|
log.info("offsets before: top={} bottom={} visible={}", .{
|
||||||
|
self.top,
|
||||||
|
self.bottom,
|
||||||
|
self.visible_offset,
|
||||||
|
});
|
||||||
|
defer {
|
||||||
|
log.info("offsets after: top={} bottom={} visible={}", .{
|
||||||
|
self.top,
|
||||||
|
self.bottom,
|
||||||
|
self.visible_offset,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// If we're scrolling up, then we just subtract and we're done.
|
// If we're scrolling up, then we just subtract and we're done.
|
||||||
if (delta < 0) {
|
if (delta < 0) {
|
||||||
self.visible_offset -|= @intCast(usize, -delta);
|
self.visible_offset -|= @intCast(usize, -delta);
|
||||||
@ -255,22 +268,6 @@ fn scrollDown(self: *Screen, delta: isize, grow: bool) void {
|
|||||||
self.visible_offset -= rows_overlapped;
|
self.visible_offset -= rows_overlapped;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scroll the screen up (positive) or down (negative). Scrolling direction
|
|
||||||
/// is the direction text would move. For example, scrolling down would
|
|
||||||
/// move existing text downward.
|
|
||||||
pub fn scrollOld(self: *Screen, count: isize) void {
|
|
||||||
if (count < 0) {
|
|
||||||
const amount = @mod(@intCast(usize, -count), self.rows);
|
|
||||||
if (amount > self.top) {
|
|
||||||
self.top = self.rows - amount;
|
|
||||||
} else {
|
|
||||||
self.top -|= amount;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.top = @mod(self.top + @intCast(usize, count), self.rows);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Copy row at src to dst.
|
/// Copy row at src to dst.
|
||||||
pub fn copyRow(self: *Screen, dst: usize, src: usize) void {
|
pub fn copyRow(self: *Screen, dst: usize, src: usize) void {
|
||||||
const src_row = self.getRow(src);
|
const src_row = self.getRow(src);
|
||||||
@ -289,7 +286,7 @@ pub fn resize(self: *Screen, alloc: Allocator, rows: usize, cols: usize) !void {
|
|||||||
const old = self.*;
|
const old = self.*;
|
||||||
|
|
||||||
// Reallocate the storage
|
// Reallocate the storage
|
||||||
self.storage = try alloc.alloc(Cell, rows * cols);
|
self.storage = try alloc.alloc(Cell, (rows + self.max_scrollback) * cols);
|
||||||
self.top = 0;
|
self.top = 0;
|
||||||
self.bottom = rows - 1;
|
self.bottom = rows - 1;
|
||||||
self.rows = rows;
|
self.rows = rows;
|
||||||
|
@ -73,7 +73,8 @@ pub fn init(alloc: Allocator, cols: usize, rows: usize) !Terminal {
|
|||||||
return Terminal{
|
return Terminal{
|
||||||
.cols = cols,
|
.cols = cols,
|
||||||
.rows = rows,
|
.rows = rows,
|
||||||
.screen = try Screen.init(alloc, rows, cols, 0),
|
// TODO: configurable scrollback
|
||||||
|
.screen = try Screen.init(alloc, rows, cols, 1000),
|
||||||
.cursor = .{},
|
.cursor = .{},
|
||||||
.saved_cursor = .{},
|
.saved_cursor = .{},
|
||||||
.tabstops = try Tabstops.init(alloc, cols, TABSTOP_INTERVAL),
|
.tabstops = try Tabstops.init(alloc, cols, TABSTOP_INTERVAL),
|
||||||
@ -276,7 +277,7 @@ pub fn index(self: *Terminal) void {
|
|||||||
if (self.cursor.y < self.scrolling_region.top or
|
if (self.cursor.y < self.scrolling_region.top or
|
||||||
self.cursor.y > self.scrolling_region.bottom) return;
|
self.cursor.y > self.scrolling_region.bottom) return;
|
||||||
|
|
||||||
self.scrollUp();
|
self.screen.scroll(.{ .delta = 1 });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -673,16 +674,6 @@ pub fn deleteLines(self: *Terminal, count: usize) void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scroll the text up by one row.
|
|
||||||
pub fn scrollUp(self: *Terminal) void {
|
|
||||||
const tracy = trace(@src());
|
|
||||||
defer tracy.end();
|
|
||||||
|
|
||||||
self.screen.scroll(.{ .delta = 1 });
|
|
||||||
const last = self.screen.getRow(self.rows - 1);
|
|
||||||
for (last) |*cell| cell.char = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Scroll the text down by one row.
|
/// Scroll the text down by one row.
|
||||||
/// TODO: test
|
/// TODO: test
|
||||||
pub fn scrollDown(self: *Terminal, count: usize) void {
|
pub fn scrollDown(self: *Terminal, count: usize) void {
|
||||||
@ -698,6 +689,18 @@ pub fn scrollDown(self: *Terminal, count: usize) void {
|
|||||||
self.insertLines(count);
|
self.insertLines(count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Options for scrolling the viewport of the terminal grid.
|
||||||
|
pub const ScrollViewport = union(enum) {
|
||||||
|
delta: isize,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Scroll the viewport of the terminal grid.
|
||||||
|
pub fn scrollViewport(self: *Terminal, behavior: ScrollViewport) void {
|
||||||
|
self.screen.scroll(switch (behavior) {
|
||||||
|
.delta => |delta| .{ .delta_no_grow = delta },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// Set Top and Bottom Margins If bottom is not specified, 0 or bigger than
|
/// Set Top and Bottom Margins If bottom is not specified, 0 or bigger than
|
||||||
/// the number of the bottom-most row, it is adjusted to the number of the
|
/// the number of the bottom-most row, it is adjusted to the number of the
|
||||||
/// bottom most row.
|
/// bottom most row.
|
||||||
|
Reference in New Issue
Block a user