mirror of
https://github.com/ghostty-org/ghostty.git
synced 2025-07-14 15:56:13 +03:00
Merge pull request #1081 from vancluever/vancluever-rect-select-fix-drag
Surface: fix some rectangle select behaviors
This commit is contained in:
@ -2348,14 +2348,7 @@ 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.
|
||||||
if (self.io.terminal.screen.selection) |sel| {
|
self.checkResetSelSwitch(screen_point);
|
||||||
const reset: bool = if (sel.end.before(sel.start))
|
|
||||||
sel.start.before(screen_point)
|
|
||||||
else
|
|
||||||
screen_point.before(sel.start);
|
|
||||||
|
|
||||||
if (reset) self.setSelection(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Our logic for determining if the starting cell is selected:
|
// Our logic for determining if the starting cell is selected:
|
||||||
//
|
//
|
||||||
@ -2406,8 +2399,12 @@ fn dragLeftClickSingle(
|
|||||||
// 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 click_point = self.mouse.left_click_point;
|
||||||
const start: terminal.point.ScreenPoint = if (screen_point.before(click_point)) start: {
|
const start: terminal.point.ScreenPoint = if (dragLeftClickBefore(
|
||||||
if ((ctrlOrSuper(self.mouse.mods) and self.mouse.mods.alt) or cell_start_xpos >= cell_xboundary) {
|
screen_point,
|
||||||
|
click_point,
|
||||||
|
self.mouse.mods,
|
||||||
|
)) start: {
|
||||||
|
if (cell_start_xpos >= cell_xboundary) {
|
||||||
break :start click_point;
|
break :start click_point;
|
||||||
} else {
|
} else {
|
||||||
break :start if (click_point.x > 0) terminal.point.ScreenPoint{
|
break :start if (click_point.x > 0) terminal.point.ScreenPoint{
|
||||||
@ -2419,7 +2416,7 @@ fn dragLeftClickSingle(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
} else start: {
|
} else start: {
|
||||||
if ((ctrlOrSuper(self.mouse.mods) and self.mouse.mods.alt) or cell_start_xpos < cell_xboundary) {
|
if (cell_start_xpos < cell_xboundary) {
|
||||||
break :start click_point;
|
break :start click_point;
|
||||||
} else {
|
} else {
|
||||||
break :start if (click_point.x < self.io.terminal.screen.cols - 1) terminal.point.ScreenPoint{
|
break :start if (click_point.x < self.io.terminal.screen.cols - 1) terminal.point.ScreenPoint{
|
||||||
@ -2451,6 +2448,56 @@ fn dragLeftClickSingle(
|
|||||||
self.setSelection(sel);
|
self.setSelection(sel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Resets the selection if we switched directions, depending on the select
|
||||||
|
// mode. See dragLeftClickSingle for more details.
|
||||||
|
fn checkResetSelSwitch(self: *Surface, screen_point: terminal.point.ScreenPoint) void {
|
||||||
|
var reset: bool = undefined;
|
||||||
|
if (self.io.terminal.screen.selection) |sel| {
|
||||||
|
if (sel.rectangle) {
|
||||||
|
// When we're in rectangle mode, we reset the selection relative to
|
||||||
|
// the click point depending on the selection mode we're in, with
|
||||||
|
// the exception of single-column selections, which we always reset
|
||||||
|
// on if we drift.
|
||||||
|
if (sel.start.x == sel.end.x) {
|
||||||
|
reset = screen_point.x != sel.start.x;
|
||||||
|
} else {
|
||||||
|
reset = switch (sel.order()) {
|
||||||
|
.forward => screen_point.x < sel.start.x or screen_point.y < sel.start.y,
|
||||||
|
.reverse => screen_point.x > sel.start.x or screen_point.y > sel.start.y,
|
||||||
|
.mirrored_forward => screen_point.x > sel.start.x or screen_point.y < sel.start.y,
|
||||||
|
.mirrored_reverse => screen_point.x < sel.start.x or screen_point.y > sel.start.y,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Normal select uses simpler logic that is just based on the
|
||||||
|
// selection start/end.
|
||||||
|
reset = if (sel.end.before(sel.start))
|
||||||
|
sel.start.before(screen_point)
|
||||||
|
else
|
||||||
|
screen_point.before(sel.start);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reset)
|
||||||
|
self.setSelection(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handles how whether or not the drag screen point is before the click point.
|
||||||
|
// When we are in rectangle select, we only interpret the x axis to determine
|
||||||
|
// where to start the selection (before or after the click point). See
|
||||||
|
// dragLeftClickSingle for more details.
|
||||||
|
fn dragLeftClickBefore(
|
||||||
|
screen_point: terminal.point.ScreenPoint,
|
||||||
|
click_point: terminal.point.ScreenPoint,
|
||||||
|
mods: input.Mods,
|
||||||
|
) bool {
|
||||||
|
if (ctrlOrSuper(mods) and mods.alt) {
|
||||||
|
return screen_point.x < click_point.x;
|
||||||
|
}
|
||||||
|
|
||||||
|
return screen_point.before(click_point);
|
||||||
|
}
|
||||||
|
|
||||||
fn posToViewport(self: Surface, xpos: f64, ypos: f64) terminal.point.Viewport {
|
fn posToViewport(self: Surface, xpos: f64, ypos: f64) terminal.point.Viewport {
|
||||||
// xpos/ypos need to be adjusted for window padding
|
// xpos/ypos need to be adjusted for window padding
|
||||||
// (i.e. "window-padding-*" settings.
|
// (i.e. "window-padding-*" settings.
|
||||||
|
@ -200,7 +200,7 @@ pub fn ordered(self: Selection, desired: Order) Selection {
|
|||||||
///
|
///
|
||||||
pub const Order = enum { forward, reverse, mirrored_forward, mirrored_reverse };
|
pub const Order = enum { forward, reverse, mirrored_forward, mirrored_reverse };
|
||||||
|
|
||||||
fn order(self: Selection) Order {
|
pub fn order(self: Selection) Order {
|
||||||
if (self.rectangle) {
|
if (self.rectangle) {
|
||||||
// Reverse (also handles single-column)
|
// Reverse (also handles single-column)
|
||||||
if (self.start.y > self.end.y and self.start.x >= self.end.x) return .reverse;
|
if (self.start.y > self.end.y and self.start.x >= self.end.x) return .reverse;
|
||||||
|
Reference in New Issue
Block a user