mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-16 08:46:08 +03:00
core: single click selection is on the way
This commit is contained in:
123
src/Surface.zig
123
src/Surface.zig
@ -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,
|
||||||
// 2 => self.dragLeftClickDouble(screen_point),
|
},
|
||||||
// 3 => self.dragLeftClickTriple(screen_point),
|
}) orelse {
|
||||||
// 0 => unreachable, // handled above
|
if (comptime std.debug.runtime_safety) unreachable;
|
||||||
// else => 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),
|
||||||
|
// 3 => self.dragLeftClickTriple(screen_point),
|
||||||
|
// 0 => unreachable, // handled above
|
||||||
|
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
|
||||||
|
@ -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 {
|
||||||
|
Reference in New Issue
Block a user