mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-15 00:06:09 +03:00
core: make surface use only renderer.Size
This commit is contained in:
245
src/Surface.zig
245
src/Surface.zig
@ -113,13 +113,8 @@ io_thr: std.Thread,
|
|||||||
/// Terminal inspector
|
/// Terminal inspector
|
||||||
inspector: ?*inspector.Inspector = null,
|
inspector: ?*inspector.Inspector = null,
|
||||||
|
|
||||||
/// All the cached sizes since we need them at various times.
|
/// All our sizing information.
|
||||||
screen_size: renderer.ScreenSize,
|
size: renderer.Size,
|
||||||
grid_size: renderer.GridSize,
|
|
||||||
cell_size: renderer.CellSize,
|
|
||||||
|
|
||||||
/// Explicit padding due to configuration
|
|
||||||
padding: renderer.Padding,
|
|
||||||
|
|
||||||
/// The configuration derived from the main config. We "derive" it so that
|
/// The configuration derived from the main config. We "derive" it so that
|
||||||
/// we don't have a shared pointer hanging around that we need to worry about
|
/// we don't have a shared pointer hanging around that we need to worry about
|
||||||
@ -416,16 +411,27 @@ pub fn init(
|
|||||||
});
|
});
|
||||||
errdefer renderer_impl.deinit();
|
errdefer renderer_impl.deinit();
|
||||||
|
|
||||||
// Calculate our grid size based on known dimensions.
|
// Build our size struct which has all the sizes we need.
|
||||||
const surface_size = try rt_surface.getSize();
|
const size: renderer.Size = size: {
|
||||||
const screen_size: renderer.ScreenSize = .{
|
var size: renderer.Size = .{
|
||||||
.width = surface_size.width,
|
.screen = screen: {
|
||||||
.height = surface_size.height,
|
const surface_size = try rt_surface.getSize();
|
||||||
|
break :screen .{
|
||||||
|
.width = surface_size.width,
|
||||||
|
.height = surface_size.height,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
.cell = font_grid.cellSize(),
|
||||||
|
.padding = padding,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (config.@"window-padding-balance") {
|
||||||
|
size.balancePadding();
|
||||||
|
}
|
||||||
|
|
||||||
|
break :size size;
|
||||||
};
|
};
|
||||||
const grid_size = renderer.GridSize.init(
|
|
||||||
screen_size.subPadding(padding),
|
|
||||||
cell_size,
|
|
||||||
);
|
|
||||||
|
|
||||||
// The mutex used to protect our renderer state.
|
// The mutex used to protect our renderer state.
|
||||||
const mutex = try alloc.create(std.Thread.Mutex);
|
const mutex = try alloc.create(std.Thread.Mutex);
|
||||||
@ -467,10 +473,7 @@ pub fn init(
|
|||||||
.io = undefined,
|
.io = undefined,
|
||||||
.io_thread = io_thread,
|
.io_thread = io_thread,
|
||||||
.io_thr = undefined,
|
.io_thr = undefined,
|
||||||
.screen_size = .{ .width = 0, .height = 0 },
|
.size = size,
|
||||||
.grid_size = .{},
|
|
||||||
.cell_size = cell_size,
|
|
||||||
.padding = padding,
|
|
||||||
.config = derived_config,
|
.config = derived_config,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -510,9 +513,9 @@ pub fn init(
|
|||||||
errdefer io_mailbox.deinit(alloc);
|
errdefer io_mailbox.deinit(alloc);
|
||||||
|
|
||||||
try termio.Termio.init(&self.io, alloc, .{
|
try termio.Termio.init(&self.io, alloc, .{
|
||||||
.grid_size = grid_size,
|
.grid_size = size.grid(),
|
||||||
.cell_size = cell_size,
|
.cell_size = size.cell,
|
||||||
.screen_size = screen_size,
|
.screen_size = size.screen,
|
||||||
.padding = padding,
|
.padding = padding,
|
||||||
.full_config = config,
|
.full_config = config,
|
||||||
.config = try termio.Termio.DerivedConfig.init(alloc, config),
|
.config = try termio.Termio.DerivedConfig.init(alloc, config),
|
||||||
@ -532,7 +535,7 @@ pub fn init(
|
|||||||
try rt_app.performAction(
|
try rt_app.performAction(
|
||||||
.{ .surface = self },
|
.{ .surface = self },
|
||||||
.cell_size,
|
.cell_size,
|
||||||
.{ .width = cell_size.width, .height = cell_size.height },
|
.{ .width = size.cell.width, .height = size.cell.height },
|
||||||
);
|
);
|
||||||
|
|
||||||
// Set a minimum size that is cols=10 h=4. This matches Mac's Terminal.app
|
// Set a minimum size that is cols=10 h=4. This matches Mac's Terminal.app
|
||||||
@ -541,8 +544,8 @@ pub fn init(
|
|||||||
.{ .surface = self },
|
.{ .surface = self },
|
||||||
.size_limit,
|
.size_limit,
|
||||||
.{
|
.{
|
||||||
.min_width = cell_size.width * 10,
|
.min_width = size.cell.width * 10,
|
||||||
.min_height = cell_size.height * 4,
|
.min_height = size.cell.height * 4,
|
||||||
// No max:
|
// No max:
|
||||||
.max_width = 0,
|
.max_width = 0,
|
||||||
.max_height = 0,
|
.max_height = 0,
|
||||||
@ -554,7 +557,7 @@ pub fn init(
|
|||||||
// init stuff we should get rid of this. But this is required because
|
// init stuff we should get rid of this. But this is required because
|
||||||
// sizeCallback does retina-aware stuff we don't do here and don't want
|
// sizeCallback does retina-aware stuff we don't do here and don't want
|
||||||
// to duplicate.
|
// to duplicate.
|
||||||
try self.sizeCallback(surface_size);
|
try self.resize(self.size.screen);
|
||||||
|
|
||||||
// Give the renderer one more opportunity to finalize any surface
|
// Give the renderer one more opportunity to finalize any surface
|
||||||
// setup on the main thread prior to spinning up the rendering thread.
|
// setup on the main thread prior to spinning up the rendering thread.
|
||||||
@ -1152,18 +1155,12 @@ pub fn selectionInfo(self: *const Surface) ?apprt.Selection {
|
|||||||
// Our sizes are all scaled so we need to send the unscaled values back.
|
// Our sizes are all scaled so we need to send the unscaled values back.
|
||||||
const content_scale = self.rt_surface.getContentScale() catch .{ .x = 1, .y = 1 };
|
const content_scale = self.rt_surface.getContentScale() catch .{ .x = 1, .y = 1 };
|
||||||
|
|
||||||
// We need to account for padding as well.
|
|
||||||
const pad = if (self.config.window_padding_balance)
|
|
||||||
renderer.Padding.balanced(self.screen_size, self.grid_size, self.cell_size)
|
|
||||||
else
|
|
||||||
self.padding;
|
|
||||||
|
|
||||||
const x: f64 = x: {
|
const x: f64 = x: {
|
||||||
// Simple x * cell width gives the left
|
// Simple x * cell width gives the left
|
||||||
var x: f64 = @floatFromInt(tl_coord.x * self.cell_size.width);
|
var x: f64 = @floatFromInt(tl_coord.x * self.cell_size.width);
|
||||||
|
|
||||||
// Add padding
|
// Add padding
|
||||||
x += @floatFromInt(pad.left);
|
x += @floatFromInt(self.size.padding.left);
|
||||||
|
|
||||||
// Scale
|
// Scale
|
||||||
x /= content_scale.x;
|
x /= content_scale.x;
|
||||||
@ -1180,7 +1177,7 @@ pub fn selectionInfo(self: *const Surface) ?apprt.Selection {
|
|||||||
y -= @floatFromInt(self.font_metrics.cell_baseline);
|
y -= @floatFromInt(self.font_metrics.cell_baseline);
|
||||||
|
|
||||||
// Add padding
|
// Add padding
|
||||||
y += @floatFromInt(pad.top);
|
y += @floatFromInt(self.size.padding.top);
|
||||||
|
|
||||||
// Scale
|
// Scale
|
||||||
y /= content_scale.y;
|
y /= content_scale.y;
|
||||||
@ -1363,22 +1360,17 @@ fn setSelection(self: *Surface, sel_: ?terminal.Selection) !void {
|
|||||||
/// Change the cell size for the terminal grid. This can happen as
|
/// Change the cell size for the terminal grid. This can happen as
|
||||||
/// a result of changing the font size at runtime.
|
/// a result of changing the font size at runtime.
|
||||||
fn setCellSize(self: *Surface, size: renderer.CellSize) !void {
|
fn setCellSize(self: *Surface, size: renderer.CellSize) !void {
|
||||||
// Update our new cell size for future calcs
|
// Update our cell size within our size struct
|
||||||
self.cell_size = size;
|
self.size.cell = size;
|
||||||
|
if (self.config.window_padding_balance) self.size.balancePadding();
|
||||||
// Update our grid_size
|
|
||||||
self.grid_size = renderer.GridSize.init(
|
|
||||||
self.screen_size.subPadding(self.padding),
|
|
||||||
self.cell_size,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Notify the terminal
|
// Notify the terminal
|
||||||
self.io.queueMessage(.{
|
self.io.queueMessage(.{
|
||||||
.resize = .{
|
.resize = .{
|
||||||
.grid_size = self.grid_size,
|
.grid_size = self.size.grid(),
|
||||||
.cell_size = self.cell_size,
|
.cell_size = self.size.cell,
|
||||||
.screen_size = self.screen_size,
|
.screen_size = self.size.screen,
|
||||||
.padding = self.padding,
|
.padding = self.size.padding,
|
||||||
},
|
},
|
||||||
}, .unlocked);
|
}, .unlocked);
|
||||||
|
|
||||||
@ -1451,28 +1443,26 @@ pub fn sizeCallback(self: *Surface, size: apprt.SurfaceSize) !void {
|
|||||||
// Update our screen size, but only if it actually changed. And if
|
// Update our screen size, but only if it actually changed. And if
|
||||||
// the screen size didn't change, then our grid size could not have
|
// the screen size didn't change, then our grid size could not have
|
||||||
// changed, so we just return.
|
// changed, so we just return.
|
||||||
if (self.screen_size.equals(new_screen_size)) return;
|
if (self.size.screen.equals(new_screen_size)) return;
|
||||||
|
|
||||||
try self.resize(new_screen_size);
|
try self.resize(new_screen_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resize(self: *Surface, size: renderer.ScreenSize) !void {
|
fn resize(self: *Surface, size: renderer.ScreenSize) !void {
|
||||||
// Save our screen size
|
// Save our screen size
|
||||||
self.screen_size = size;
|
self.size.screen = size;
|
||||||
|
if (self.config.window_padding_balance) self.size.balancePadding();
|
||||||
|
|
||||||
// Recalculate our grid size. Because Ghostty supports fluid resizing,
|
// Recalculate our grid size. Because Ghostty supports fluid resizing,
|
||||||
// its possible the grid doesn't change at all even if the screen size changes.
|
// its possible the grid doesn't change at all even if the screen size changes.
|
||||||
// We have to update the IO thread no matter what because we send
|
// We have to update the IO thread no matter what because we send
|
||||||
// pixel-level sizing to the subprocess.
|
// pixel-level sizing to the subprocess.
|
||||||
self.grid_size = renderer.GridSize.init(
|
const grid_size = self.size.grid();
|
||||||
self.screen_size.subPadding(self.padding),
|
if (grid_size.columns < 5 and (self.size.padding.left > 0 or self.size.padding.right > 0)) {
|
||||||
self.cell_size,
|
|
||||||
);
|
|
||||||
if (self.grid_size.columns < 5 and (self.padding.left > 0 or self.padding.right > 0)) {
|
|
||||||
log.warn("WARNING: very small terminal grid detected with padding " ++
|
log.warn("WARNING: very small terminal grid detected with padding " ++
|
||||||
"set. Is your padding reasonable?", .{});
|
"set. Is your padding reasonable?", .{});
|
||||||
}
|
}
|
||||||
if (self.grid_size.rows < 2 and (self.padding.top > 0 or self.padding.bottom > 0)) {
|
if (grid_size.rows < 2 and (self.size.padding.top > 0 or self.size.padding.bottom > 0)) {
|
||||||
log.warn("WARNING: very small terminal grid detected with padding " ++
|
log.warn("WARNING: very small terminal grid detected with padding " ++
|
||||||
"set. Is your padding reasonable?", .{});
|
"set. Is your padding reasonable?", .{});
|
||||||
}
|
}
|
||||||
@ -1480,10 +1470,10 @@ fn resize(self: *Surface, size: renderer.ScreenSize) !void {
|
|||||||
// Mail the IO thread
|
// Mail the IO thread
|
||||||
self.io.queueMessage(.{
|
self.io.queueMessage(.{
|
||||||
.resize = .{
|
.resize = .{
|
||||||
.grid_size = self.grid_size,
|
.grid_size = grid_size,
|
||||||
.cell_size = self.cell_size,
|
.cell_size = self.size.cell,
|
||||||
.screen_size = self.screen_size,
|
.screen_size = self.size.screen,
|
||||||
.padding = self.padding,
|
.padding = self.size.padding,
|
||||||
},
|
},
|
||||||
}, .unlocked);
|
}, .unlocked);
|
||||||
}
|
}
|
||||||
@ -2144,7 +2134,8 @@ pub fn scrollCallback(
|
|||||||
if (!scroll_mods.precision) {
|
if (!scroll_mods.precision) {
|
||||||
// Calculate our magnitude of scroll. This is constant (not
|
// Calculate our magnitude of scroll. This is constant (not
|
||||||
// dependent on yoff).
|
// dependent on yoff).
|
||||||
const grid_rows_f64: f64 = @floatFromInt(self.grid_size.rows);
|
const grid_size = self.size.grid();
|
||||||
|
const grid_rows_f64: f64 = @floatFromInt(grid_size.rows);
|
||||||
const y_delta_f64: f64 = @round((grid_rows_f64 * self.config.mouse_scroll_multiplier) / 15.0);
|
const y_delta_f64: f64 = @round((grid_rows_f64 * self.config.mouse_scroll_multiplier) / 15.0);
|
||||||
const y_delta_usize: usize = @max(1, @as(usize, @intFromFloat(y_delta_f64)));
|
const y_delta_usize: usize = @max(1, @as(usize, @intFromFloat(y_delta_f64)));
|
||||||
|
|
||||||
@ -2171,7 +2162,7 @@ pub fn scrollCallback(
|
|||||||
|
|
||||||
// If the new offset is less than a single unit of scroll, we save
|
// If the new offset is less than a single unit of scroll, we save
|
||||||
// the new pending value and do not scroll yet.
|
// the new pending value and do not scroll yet.
|
||||||
const cell_size: f64 = @floatFromInt(self.cell_size.height);
|
const cell_size: f64 = @floatFromInt(self.size.cell.height);
|
||||||
if (@abs(poff) < cell_size) {
|
if (@abs(poff) < cell_size) {
|
||||||
self.mouse.pending_scroll_y = poff;
|
self.mouse.pending_scroll_y = poff;
|
||||||
break :y .{};
|
break :y .{};
|
||||||
@ -2201,7 +2192,7 @@ pub fn scrollCallback(
|
|||||||
|
|
||||||
const xoff_adjusted: f64 = xoff * self.config.mouse_scroll_multiplier;
|
const xoff_adjusted: f64 = xoff * self.config.mouse_scroll_multiplier;
|
||||||
const poff: f64 = self.mouse.pending_scroll_x + xoff_adjusted;
|
const poff: f64 = self.mouse.pending_scroll_x + xoff_adjusted;
|
||||||
const cell_size: f64 = @floatFromInt(self.cell_size.width);
|
const cell_size: f64 = @floatFromInt(self.size.cell.width);
|
||||||
if (@abs(poff) < cell_size) {
|
if (@abs(poff) < cell_size) {
|
||||||
self.mouse.pending_scroll_x = poff;
|
self.mouse.pending_scroll_x = poff;
|
||||||
break :x .{};
|
break :x .{};
|
||||||
@ -2326,36 +2317,41 @@ pub fn contentScaleCallback(self: *Surface, content_scale: apprt.ContentScale) !
|
|||||||
|
|
||||||
try self.setFontSize(size);
|
try self.setFontSize(size);
|
||||||
|
|
||||||
// Update our padding which is dependent on DPI.
|
// Update our padding which is dependent on DPI. We only do this for
|
||||||
self.padding = padding: {
|
// unbalanced padding since balanced padding is not dependent on DPI.
|
||||||
const padding_top: u32 = padding_top: {
|
if (!self.config.window_padding_balanced) {
|
||||||
const padding_top: f32 = @floatFromInt(self.config.window_padding_top);
|
self.size.padding = padding: {
|
||||||
break :padding_top @intFromFloat(@floor(padding_top * y_dpi / 72));
|
const padding_top: u32 = padding_top: {
|
||||||
};
|
const padding_top: f32 = @floatFromInt(self.config.window_padding_top);
|
||||||
const padding_bottom: u32 = padding_bottom: {
|
break :padding_top @intFromFloat(@floor(padding_top * y_dpi / 72));
|
||||||
const padding_bottom: f32 = @floatFromInt(self.config.window_padding_bottom);
|
};
|
||||||
break :padding_bottom @intFromFloat(@floor(padding_bottom * y_dpi / 72));
|
const padding_bottom: u32 = padding_bottom: {
|
||||||
};
|
const padding_bottom: f32 = @floatFromInt(self.config.window_padding_bottom);
|
||||||
const padding_left: u32 = padding_left: {
|
break :padding_bottom @intFromFloat(@floor(padding_bottom * y_dpi / 72));
|
||||||
const padding_left: f32 = @floatFromInt(self.config.window_padding_left);
|
};
|
||||||
break :padding_left @intFromFloat(@floor(padding_left * x_dpi / 72));
|
const padding_left: u32 = padding_left: {
|
||||||
};
|
const padding_left: f32 = @floatFromInt(self.config.window_padding_left);
|
||||||
const padding_right: u32 = padding_right: {
|
break :padding_left @intFromFloat(@floor(padding_left * x_dpi / 72));
|
||||||
const padding_right: f32 = @floatFromInt(self.config.window_padding_right);
|
};
|
||||||
break :padding_right @intFromFloat(@floor(padding_right * x_dpi / 72));
|
const padding_right: u32 = padding_right: {
|
||||||
|
const padding_right: f32 = @floatFromInt(self.config.window_padding_right);
|
||||||
|
break :padding_right @intFromFloat(@floor(padding_right * x_dpi / 72));
|
||||||
|
};
|
||||||
|
|
||||||
|
break :padding .{
|
||||||
|
.top = padding_top,
|
||||||
|
.bottom = padding_bottom,
|
||||||
|
.left = padding_left,
|
||||||
|
.right = padding_right,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
break :padding .{
|
self.padding = self.size.padding;
|
||||||
.top = padding_top,
|
}
|
||||||
.bottom = padding_bottom,
|
|
||||||
.left = padding_left,
|
|
||||||
.right = padding_right,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
// Force a resize event because the change in padding will affect
|
// Force a resize event because the change in padding will affect
|
||||||
// pixel-level changes to the renderer and viewport.
|
// pixel-level changes to the renderer and viewport.
|
||||||
try self.resize(self.screen_size);
|
try self.resize(self.size.screen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The type of action to report for a mouse event.
|
/// The type of action to report for a mouse event.
|
||||||
@ -2394,8 +2390,8 @@ fn mouseReport(
|
|||||||
// We always report release events no matter where they happen.
|
// We always report release events no matter where they happen.
|
||||||
if (action != .release) {
|
if (action != .release) {
|
||||||
const pos_out_viewport = pos_out_viewport: {
|
const pos_out_viewport = pos_out_viewport: {
|
||||||
const max_x: f32 = @floatFromInt(self.screen_size.width);
|
const max_x: f32 = @floatFromInt(self.size.screen.width);
|
||||||
const max_y: f32 = @floatFromInt(self.screen_size.height);
|
const max_y: f32 = @floatFromInt(self.size.screen.height);
|
||||||
break :pos_out_viewport pos.x < 0 or pos.y < 0 or
|
break :pos_out_viewport pos.x < 0 or pos.y < 0 or
|
||||||
pos.x > max_x or pos.y > max_y;
|
pos.x > max_x or pos.y > max_y;
|
||||||
};
|
};
|
||||||
@ -2554,15 +2550,22 @@ fn mouseReport(
|
|||||||
.sgr_pixels => {
|
.sgr_pixels => {
|
||||||
// Final character to send in the CSI
|
// Final character to send in the CSI
|
||||||
const final: u8 = if (action == .release) 'm' else 'M';
|
const final: u8 = if (action == .release) 'm' else 'M';
|
||||||
const adjusted = self.posAdjusted(pos.x, pos.y);
|
|
||||||
|
// The position has to be adjusted to the terminal space.
|
||||||
|
const coord: renderer.Coordinate.Terminal = (renderer.Coordinate{
|
||||||
|
.surface = .{
|
||||||
|
.x = pos.x,
|
||||||
|
.y = pos.y,
|
||||||
|
},
|
||||||
|
}).convert(.terminal, self.size).terminal;
|
||||||
|
|
||||||
// Response always is at least 4 chars, so this leaves the
|
// Response always is at least 4 chars, so this leaves the
|
||||||
// remainder for numbers which are very large...
|
// remainder for numbers which are very large...
|
||||||
var data: termio.Message.WriteReq.Small.Array = undefined;
|
var data: termio.Message.WriteReq.Small.Array = undefined;
|
||||||
const resp = try std.fmt.bufPrint(&data, "\x1B[<{d};{d};{d}{c}", .{
|
const resp = try std.fmt.bufPrint(&data, "\x1B[<{d};{d};{d}{c}", .{
|
||||||
button_code,
|
button_code,
|
||||||
@as(i32, @intFromFloat(@round(adjusted.x))),
|
@as(i32, @intFromFloat(@round(coord.x))),
|
||||||
@as(i32, @intFromFloat(@round(adjusted.y))),
|
@as(i32, @intFromFloat(@round(coord.y))),
|
||||||
final,
|
final,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -2817,7 +2820,7 @@ pub fn mouseButtonCallback(
|
|||||||
// If we move our cursor too much between clicks then we reset
|
// If we move our cursor too much between clicks then we reset
|
||||||
// the multi-click state.
|
// the multi-click state.
|
||||||
if (self.mouse.left_click_count > 0) {
|
if (self.mouse.left_click_count > 0) {
|
||||||
const max_distance: f64 = @floatFromInt(self.cell_size.width);
|
const max_distance: f64 = @floatFromInt(self.size.cell.width);
|
||||||
const distance = @sqrt(
|
const distance = @sqrt(
|
||||||
std.math.pow(f64, pos.x - self.mouse.left_click_xpos, 2) +
|
std.math.pow(f64, pos.x - self.mouse.left_click_xpos, 2) +
|
||||||
std.math.pow(f64, pos.y - self.mouse.left_click_ypos, 2),
|
std.math.pow(f64, pos.y - self.mouse.left_click_ypos, 2),
|
||||||
@ -3317,8 +3320,8 @@ pub fn cursorPosCallback(
|
|||||||
// We allow for a 1 pixel buffer at the top and bottom to detect
|
// We allow for a 1 pixel buffer at the top and bottom to detect
|
||||||
// scroll even in full screen windows.
|
// scroll even in full screen windows.
|
||||||
// Note: one day, we can change this from distance to time based if we want.
|
// Note: one day, we can change this from distance to time based if we want.
|
||||||
//log.warn("CURSOR POS: {} {}", .{ pos, self.screen_size });
|
//log.warn("CURSOR POS: {} {}", .{ pos, self.size.screen });
|
||||||
const max_y: f32 = @floatFromInt(self.screen_size.height);
|
const max_y: f32 = @floatFromInt(self.size.screen.height);
|
||||||
if (pos.y <= 1 or pos.y > max_y - 1) {
|
if (pos.y <= 1 or pos.y > max_y - 1) {
|
||||||
const delta: isize = if (pos.y < 0) -1 else 1;
|
const delta: isize = if (pos.y < 0) -1 else 1;
|
||||||
try self.io.terminal.scrollViewport(.{ .delta = delta });
|
try self.io.terminal.scrollViewport(.{ .delta = delta });
|
||||||
@ -3477,11 +3480,11 @@ fn dragLeftClickSingle(
|
|||||||
const click_pin = self.mouse.left_click_pin.?.*;
|
const click_pin = self.mouse.left_click_pin.?.*;
|
||||||
|
|
||||||
// the boundary point at which we consider selection or non-selection
|
// the boundary point at which we consider selection or non-selection
|
||||||
const cell_width_f64: f64 = @floatFromInt(self.cell_size.width);
|
const cell_width_f64: f64 = @floatFromInt(self.size.cell.width);
|
||||||
const cell_xboundary = cell_width_f64 * 0.6;
|
const cell_xboundary = cell_width_f64 * 0.6;
|
||||||
|
|
||||||
// first xpos of the clicked cell adjusted for padding
|
// first xpos of the clicked cell adjusted for padding
|
||||||
const left_padding_f64: f64 = @as(f64, @floatFromInt(self.padding.left));
|
const left_padding_f64: f64 = @as(f64, @floatFromInt(self.size.padding.left));
|
||||||
const cell_xstart = @as(f64, @floatFromInt(click_pin.x)) * cell_width_f64;
|
const cell_xstart = @as(f64, @floatFromInt(click_pin.x)) * cell_width_f64;
|
||||||
const cell_start_xpos = self.mouse.left_click_xpos - cell_xstart - left_padding_f64;
|
const cell_start_xpos = self.mouse.left_click_xpos - cell_xstart - left_padding_f64;
|
||||||
|
|
||||||
@ -3631,43 +3634,11 @@ pub fn colorSchemeCallback(self: *Surface, scheme: apprt.ColorScheme) !void {
|
|||||||
if (report) try self.reportColorScheme();
|
if (report) try self.reportColorScheme();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn posAdjusted(self: Surface, xpos: f64, ypos: f64) struct { x: f64, y: f64 } {
|
|
||||||
const pad = if (self.config.window_padding_balance)
|
|
||||||
renderer.Padding.balanced(self.screen_size, self.grid_size, self.cell_size)
|
|
||||||
else
|
|
||||||
self.padding;
|
|
||||||
|
|
||||||
return .{
|
|
||||||
.x = xpos - @as(f64, @floatFromInt(pad.left)),
|
|
||||||
.y = ypos - @as(f64, @floatFromInt(pad.top)),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn posToViewport(self: Surface, xpos: f64, ypos: f64) terminal.point.Coordinate {
|
pub fn posToViewport(self: Surface, xpos: f64, ypos: f64) terminal.point.Coordinate {
|
||||||
// xpos/ypos need to be adjusted for window padding
|
// Get our grid cell
|
||||||
// (i.e. "window-padding-*" settings.
|
const coord: renderer.Coordinate = .{ .surface = .{ .x = xpos, .y = ypos } };
|
||||||
const adjusted = self.posAdjusted(xpos, ypos);
|
const grid = coord.convert(.grid, self.size).grid;
|
||||||
|
return .{ .x = grid.x, .y = grid.y };
|
||||||
// adjusted.x and adjusted.y can be negative if while dragging, the user moves the
|
|
||||||
// mouse off the surface. Likewise, they can be larger than our surface
|
|
||||||
// width if the user drags out of the surface positively.
|
|
||||||
return .{
|
|
||||||
.x = if (adjusted.x < 0) 0 else x: {
|
|
||||||
// Our cell is the mouse divided by cell width
|
|
||||||
const cell_width: f64 = @floatFromInt(self.cell_size.width);
|
|
||||||
const x: usize = @intFromFloat(adjusted.x / cell_width);
|
|
||||||
|
|
||||||
// Can be off the screen if the user drags it out, so max
|
|
||||||
// it out on our available columns
|
|
||||||
break :x @min(x, self.grid_size.columns - 1);
|
|
||||||
},
|
|
||||||
|
|
||||||
.y = if (adjusted.y < 0) 0 else y: {
|
|
||||||
const cell_height: f64 = @floatFromInt(self.cell_size.height);
|
|
||||||
const y: usize = @intFromFloat(adjusted.y / cell_height);
|
|
||||||
break :y @min(y, self.grid_size.rows - 1);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Scroll to the bottom of the viewport.
|
/// Scroll to the bottom of the viewport.
|
||||||
@ -3905,21 +3876,21 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
|
|||||||
},
|
},
|
||||||
|
|
||||||
.scroll_page_up => {
|
.scroll_page_up => {
|
||||||
const rows: isize = @intCast(self.grid_size.rows);
|
const rows: isize = @intCast(self.size.grid().rows);
|
||||||
self.io.queueMessage(.{
|
self.io.queueMessage(.{
|
||||||
.scroll_viewport = .{ .delta = -1 * rows },
|
.scroll_viewport = .{ .delta = -1 * rows },
|
||||||
}, .unlocked);
|
}, .unlocked);
|
||||||
},
|
},
|
||||||
|
|
||||||
.scroll_page_down => {
|
.scroll_page_down => {
|
||||||
const rows: isize = @intCast(self.grid_size.rows);
|
const rows: isize = @intCast(self.size.grid().rows);
|
||||||
self.io.queueMessage(.{
|
self.io.queueMessage(.{
|
||||||
.scroll_viewport = .{ .delta = rows },
|
.scroll_viewport = .{ .delta = rows },
|
||||||
}, .unlocked);
|
}, .unlocked);
|
||||||
},
|
},
|
||||||
|
|
||||||
.scroll_page_fractional => |fraction| {
|
.scroll_page_fractional => |fraction| {
|
||||||
const rows: f32 = @floatFromInt(self.grid_size.rows);
|
const rows: f32 = @floatFromInt(self.size.grid().rows);
|
||||||
const delta: isize = @intFromFloat(@trunc(fraction * rows));
|
const delta: isize = @intFromFloat(@trunc(fraction * rows));
|
||||||
self.io.queueMessage(.{
|
self.io.queueMessage(.{
|
||||||
.scroll_viewport = .{ .delta = delta },
|
.scroll_viewport = .{ .delta = delta },
|
||||||
@ -3989,7 +3960,7 @@ pub fn performBindingAction(self: *Surface, action: input.Binding.Action) !bool
|
|||||||
.left => .left,
|
.left => .left,
|
||||||
.down => .down,
|
.down => .down,
|
||||||
.up => .up,
|
.up => .up,
|
||||||
.auto => if (self.screen_size.width > self.screen_size.height)
|
.auto => if (self.size.screen.width > self.size.screen.height)
|
||||||
.right
|
.right
|
||||||
else
|
else
|
||||||
.down,
|
.down,
|
||||||
|
@ -177,29 +177,30 @@ fn beforeSend(
|
|||||||
const obj = sentry.Value.initObject();
|
const obj = sentry.Value.initObject();
|
||||||
errdefer obj.decref();
|
errdefer obj.decref();
|
||||||
const surface = thr_state.surface;
|
const surface = thr_state.surface;
|
||||||
|
const grid_size = surface.size.grid();
|
||||||
obj.set(
|
obj.set(
|
||||||
"screen-width",
|
"screen-width",
|
||||||
sentry.Value.initInt32(std.math.cast(i32, surface.screen_size.width) orelse -1),
|
sentry.Value.initInt32(std.math.cast(i32, surface.size.screen.width) orelse -1),
|
||||||
);
|
);
|
||||||
obj.set(
|
obj.set(
|
||||||
"screen-height",
|
"screen-height",
|
||||||
sentry.Value.initInt32(std.math.cast(i32, surface.screen_size.height) orelse -1),
|
sentry.Value.initInt32(std.math.cast(i32, surface.size.screen.height) orelse -1),
|
||||||
);
|
);
|
||||||
obj.set(
|
obj.set(
|
||||||
"grid-columns",
|
"grid-columns",
|
||||||
sentry.Value.initInt32(std.math.cast(i32, surface.grid_size.columns) orelse -1),
|
sentry.Value.initInt32(std.math.cast(i32, grid_size.columns) orelse -1),
|
||||||
);
|
);
|
||||||
obj.set(
|
obj.set(
|
||||||
"grid-rows",
|
"grid-rows",
|
||||||
sentry.Value.initInt32(std.math.cast(i32, surface.grid_size.rows) orelse -1),
|
sentry.Value.initInt32(std.math.cast(i32, grid_size.rows) orelse -1),
|
||||||
);
|
);
|
||||||
obj.set(
|
obj.set(
|
||||||
"cell-width",
|
"cell-width",
|
||||||
sentry.Value.initInt32(std.math.cast(i32, surface.cell_size.width) orelse -1),
|
sentry.Value.initInt32(std.math.cast(i32, surface.size.cell.width) orelse -1),
|
||||||
);
|
);
|
||||||
obj.set(
|
obj.set(
|
||||||
"cell-height",
|
"cell-height",
|
||||||
sentry.Value.initInt32(std.math.cast(i32, surface.cell_size.height) orelse -1),
|
sentry.Value.initInt32(std.math.cast(i32, surface.size.cell.height) orelse -1),
|
||||||
);
|
);
|
||||||
|
|
||||||
contexts.set("Dimensions", obj);
|
contexts.set("Dimensions", obj);
|
||||||
|
@ -24,6 +24,16 @@ pub const Size = struct {
|
|||||||
pub fn grid(self: Size) GridSize {
|
pub fn grid(self: Size) GridSize {
|
||||||
return GridSize.init(self.screen.subPadding(self.padding), self.cell);
|
return GridSize.init(self.screen.subPadding(self.padding), self.cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set the padding to be balanced around the grid. Overwrites the current
|
||||||
|
/// padding.
|
||||||
|
pub fn balancePadding(self: *Size) void {
|
||||||
|
self.padding = Padding.balanced(
|
||||||
|
self.screen,
|
||||||
|
self.grid(),
|
||||||
|
self.cell,
|
||||||
|
);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A coordinate. This is defined as a tagged union to allow for different
|
/// A coordinate. This is defined as a tagged union to allow for different
|
||||||
|
@ -168,14 +168,14 @@ pub fn init(self: *Termio, alloc: Allocator, opts: termio.Options) !void {
|
|||||||
// Set our default cursor style
|
// Set our default cursor style
|
||||||
term.screen.cursor.cursor_style = opts.config.cursor_style;
|
term.screen.cursor.cursor_style = opts.config.cursor_style;
|
||||||
|
|
||||||
// Setup our backend.
|
|
||||||
var backend = opts.backend;
|
|
||||||
backend.initTerminal(&term);
|
|
||||||
|
|
||||||
// Setup our terminal size in pixels for certain requests.
|
// Setup our terminal size in pixels for certain requests.
|
||||||
term.width_px = opts.grid_size.columns * opts.cell_size.width;
|
term.width_px = opts.grid_size.columns * opts.cell_size.width;
|
||||||
term.height_px = opts.grid_size.rows * opts.cell_size.height;
|
term.height_px = opts.grid_size.rows * opts.cell_size.height;
|
||||||
|
|
||||||
|
// Setup our backend.
|
||||||
|
var backend = opts.backend;
|
||||||
|
backend.initTerminal(&term);
|
||||||
|
|
||||||
// Create our stream handler. This points to memory in self so it
|
// Create our stream handler. This points to memory in self so it
|
||||||
// isn't safe to use until self.* is set.
|
// isn't safe to use until self.* is set.
|
||||||
const handler: StreamHandler = handler: {
|
const handler: StreamHandler = handler: {
|
||||||
|
Reference in New Issue
Block a user