core: single click selection is on the way

This commit is contained in:
Mitchell Hashimoto
2024-03-10 17:26:32 -07:00
parent 75255780e9
commit 4254dc9eef
2 changed files with 81 additions and 58 deletions

View File

@ -1054,6 +1054,9 @@ fn setSelection(self: *Surface, sel_: ?terminal.Selection) !void {
const prev_ = self.io.terminal.screen.selection; const prev_ = self.io.terminal.screen.selection;
try self.io.terminal.screen.select(sel_); try self.io.terminal.screen.select(sel_);
// TODO(paged-terminal)
if (true) return;
// Determine the clipboard we want to copy selection to, if it is enabled. // Determine the clipboard we want to copy selection to, if it is enabled.
const clipboard: apprt.Clipboard = switch (self.config.copy_on_select) { const clipboard: apprt.Clipboard = switch (self.config.copy_on_select) {
.false => return, .false => return,
@ -2623,16 +2626,25 @@ pub fn cursorPosCallback(
// Convert to points // Convert to points
// TODO(paged-terminal) // TODO(paged-terminal)
// const screen_point = pos_vp.toScreen(&self.io.terminal.screen); const screen = &self.renderer_state.terminal.screen;
// const pin = screen.pages.pin(.{
// // Handle dragging depending on click count .viewport = .{
// switch (self.mouse.left_click_count) { .x = pos_vp.x,
// 1 => self.dragLeftClickSingle(screen_point, pos.x), .y = pos_vp.y,
},
}) orelse {
if (comptime std.debug.runtime_safety) unreachable;
return;
};
// Handle dragging depending on click count
switch (self.mouse.left_click_count) {
1 => try self.dragLeftClickSingle(pin, pos.x),
// 2 => self.dragLeftClickDouble(screen_point), // 2 => self.dragLeftClickDouble(screen_point),
// 3 => self.dragLeftClickTriple(screen_point), // 3 => self.dragLeftClickTriple(screen_point),
// 0 => unreachable, // handled above // 0 => unreachable, // handled above
// else => unreachable, else => unreachable,
// } }
return; return;
} }
@ -2730,9 +2742,9 @@ fn dragLeftClickTriple(
fn dragLeftClickSingle( fn dragLeftClickSingle(
self: *Surface, self: *Surface,
screen_point: terminal.point.ScreenPoint, drag_pin: terminal.Pin,
xpos: f64, xpos: f64,
) void { ) !void {
// NOTE(mitchellh): This logic super sucks. There has to be an easier way // NOTE(mitchellh): This logic super sucks. There has to be an easier way
// to calculate this, but this is good for a v1. Selection isn't THAT // to calculate this, but this is good for a v1. Selection isn't THAT
// common so its not like this performance heavy code is running that // common so its not like this performance heavy code is running that
@ -2742,7 +2754,8 @@ fn dragLeftClickSingle(
// If we were selecting, and we switched directions, then we restart // If we were selecting, and we switched directions, then we restart
// calculations because it forces us to reconsider if the first cell is // calculations because it forces us to reconsider if the first cell is
// selected. // selected.
self.checkResetSelSwitch(screen_point); // TODO(paged-terminal)
//self.checkResetSelSwitch(screen_point);
// Our logic for determining if the starting cell is selected: // Our logic for determining if the starting cell is selected:
// //
@ -2756,19 +2769,22 @@ fn dragLeftClickSingle(
// - Inverted logic for forwards selections. // - Inverted logic for forwards selections.
// //
// Our clicking point
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.cell_size.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.padding.left));
const cell_xstart = @as(f64, @floatFromInt(self.mouse.left_click_point.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;
// If this is the same cell, then we only start the selection if weve // If this is the same cell, then we only start the selection if weve
// moved past the boundary point the opposite direction from where we // moved past the boundary point the opposite direction from where we
// started. // started.
if (std.meta.eql(screen_point, self.mouse.left_click_point)) { if (click_pin.eql(drag_pin)) {
// Ensuring to adjusting the cursor position for padding // Ensuring to adjusting the cursor position for padding
const cell_xpos = xpos - cell_xstart - left_padding_f64; const cell_xpos = xpos - cell_xstart - left_padding_f64;
const selected: bool = if (cell_start_xpos < cell_xboundary) const selected: bool = if (cell_start_xpos < cell_xboundary)
@ -2776,11 +2792,11 @@ fn dragLeftClickSingle(
else else
cell_xpos < cell_xboundary; cell_xpos < cell_xboundary;
self.setSelection(if (selected) .{ try self.setSelection(if (selected) terminal.Selection.init(
.start = screen_point, drag_pin,
.end = screen_point, drag_pin,
.rectangle = self.mouse.mods.ctrlOrSuper() and self.mouse.mods.alt, self.mouse.mods.ctrlOrSuper() and self.mouse.mods.alt,
} else null); ) else null);
return; return;
} }
@ -2792,42 +2808,30 @@ fn dragLeftClickSingle(
// the starting cell if we started after the boundary, else // the starting cell if we started after the boundary, else
// we start selection of the prior cell. // we start selection of the prior cell.
// - Inverse logic for a point after the start. // - Inverse logic for a point after the start.
const click_point = self.mouse.left_click_point; const start: terminal.Pin = if (dragLeftClickBefore(
const start: terminal.point.ScreenPoint = if (dragLeftClickBefore( drag_pin,
screen_point, click_pin,
click_point,
self.mouse.mods, self.mouse.mods,
)) start: { )) start: {
if (cell_start_xpos >= cell_xboundary) { if (cell_start_xpos >= cell_xboundary) break :start click_pin;
break :start click_point; if (click_pin.x > 0) break :start click_pin.left(1);
} else { var start = click_pin.up(1) orelse click_pin;
break :start if (click_point.x > 0) terminal.point.ScreenPoint{ start.x = self.io.terminal.screen.pages.cols - 1;
.y = click_point.y, break :start start;
.x = click_point.x - 1,
} else terminal.point.ScreenPoint{
.x = self.io.terminal.screen.cols - 1,
.y = click_point.y -| 1,
};
}
} else start: { } else start: {
if (cell_start_xpos < cell_xboundary) { if (cell_start_xpos < cell_xboundary) break :start click_pin;
break :start click_point; if (click_pin.x < self.io.terminal.screen.pages.cols - 1)
} else { break :start click_pin.right(1);
break :start if (click_point.x < self.io.terminal.screen.cols - 1) terminal.point.ScreenPoint{ var start = click_pin.down(1) orelse click_pin;
.y = click_point.y, start.x = 0;
.x = click_point.x + 1, break :start start;
} else terminal.point.ScreenPoint{
.y = click_point.y + 1,
.x = 0,
};
}
}; };
self.setSelection(.{ try self.setSelection(terminal.Selection.init(
.start = start, start,
.end = screen_point, drag_pin,
.rectangle = self.mouse.mods.ctrlOrSuper() and self.mouse.mods.alt, self.mouse.mods.ctrlOrSuper() and self.mouse.mods.alt,
}); ));
return; return;
} }
@ -2837,9 +2841,12 @@ fn dragLeftClickSingle(
// We moved! Set the selection end point. The start point should be // We moved! Set the selection end point. The start point should be
// set earlier. // set earlier.
assert(self.io.terminal.screen.selection != null); assert(self.io.terminal.screen.selection != null);
var sel = self.io.terminal.screen.selection.?; const sel = self.io.terminal.screen.selection.?;
sel.end = screen_point; try self.setSelection(terminal.Selection.init(
self.setSelection(sel); sel.start(),
drag_pin,
sel.rectangle,
));
} }
// Resets the selection if we switched directions, depending on the select // Resets the selection if we switched directions, depending on the select
@ -2880,15 +2887,15 @@ fn checkResetSelSwitch(self: *Surface, screen_point: terminal.point.ScreenPoint)
// where to start the selection (before or after the click point). See // where to start the selection (before or after the click point). See
// dragLeftClickSingle for more details. // dragLeftClickSingle for more details.
fn dragLeftClickBefore( fn dragLeftClickBefore(
screen_point: terminal.point.ScreenPoint, drag_pin: terminal.Pin,
click_point: terminal.point.ScreenPoint, click_pin: terminal.Pin,
mods: input.Mods, mods: input.Mods,
) bool { ) bool {
if (mods.ctrlOrSuper() and mods.alt) { if (mods.ctrlOrSuper() and mods.alt) {
return screen_point.x < click_point.x; return drag_pin.x < click_pin.x;
} }
return screen_point.before(click_point); return drag_pin.before(click_pin);
} }
/// Call to notify Ghostty that the color scheme for the terminal has /// Call to notify Ghostty that the color scheme for the terminal has

View File

@ -2394,6 +2394,22 @@ pub const Pin = struct {
self.x == other.x; self.x == other.x;
} }
/// Move the pin left n columns. n must fit within the size.
pub fn left(self: Pin, n: usize) Pin {
assert(n <= self.x);
var result = self;
result.x -= n;
return result;
}
/// Move the pin right n columns. n must fit within the size.
pub fn right(self: Pin, n: usize) Pin {
assert(self.x + n < self.page.data.size.cols);
var result = self;
result.x += n;
return result;
}
/// Move the pin down a certain number of rows, or return null if /// Move the pin down a certain number of rows, or return null if
/// the pin goes beyond the end of the screen. /// the pin goes beyond the end of the screen.
pub fn down(self: Pin, n: usize) ?Pin { pub fn down(self: Pin, n: usize) ?Pin {