diff --git a/src/Window.zig b/src/Window.zig index 455edbe54..0059e5986 100644 --- a/src/Window.zig +++ b/src/Window.zig @@ -1644,6 +1644,45 @@ fn cursorPosCallback( const viewport_point = win.posToViewport(xpos, ypos); const screen_point = viewport_point.toScreen(&win.io.terminal.screen); + // Handle dragging depending on click count + switch (win.mouse.left_click_count) { + 1 => win.dragLeftClickSingle(screen_point, xpos), + 2 => win.dragLeftClickDouble(screen_point), + 3 => {}, // TODO + else => unreachable, + } +} + +/// Double-click dragging moves the selection one "word" at a time. +fn dragLeftClickDouble( + self: *Window, + screen_point: terminal.point.ScreenPoint, +) void { + // Get the word under our current point. If there isn't a word, do nothing. + const word = self.io.terminal.screen.selectWord(screen_point) orelse return; + + // Get our selection to grow it. If we don't have a selection, start it now. + // We may not have a selection if we started our dbl-click in an area + // that had no data, then we dragged our mouse into an area with data. + var sel = self.io.terminal.screen.selectWord(self.mouse.left_click_point) orelse { + self.io.terminal.selection = word; + return; + }; + + // Grow our selection + if (screen_point.before(self.mouse.left_click_point)) { + sel.start = word.start; + } else { + sel.end = word.end; + } + self.io.terminal.selection = sel; +} + +fn dragLeftClickSingle( + self: *Window, + screen_point: terminal.point.ScreenPoint, + xpos: f64, +) void { // 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 // common so its not like this performance heavy code is running that @@ -1653,13 +1692,13 @@ fn cursorPosCallback( // If we were selecting, and we switched directions, then we restart // calculations because it forces us to reconsider if the first cell is // selected. - if (win.io.terminal.selection) |sel| { + if (self.io.terminal.selection) |sel| { const reset: bool = if (sel.end.before(sel.start)) sel.start.before(screen_point) else screen_point.before(sel.start); - if (reset) win.io.terminal.selection = null; + if (reset) self.io.terminal.selection = null; } // Our logic for determing if the starting cell is selected: @@ -1675,23 +1714,23 @@ fn cursorPosCallback( // // the boundary point at which we consider selection or non-selection - const cell_xboundary = win.cell_size.width * 0.6; + const cell_xboundary = self.cell_size.width * 0.6; // first xpos of the clicked cell - const cell_xstart = @intToFloat(f32, win.mouse.left_click_point.x) * win.cell_size.width; - const cell_start_xpos = win.mouse.left_click_xpos - cell_xstart; + const cell_xstart = @intToFloat(f32, self.mouse.left_click_point.x) * self.cell_size.width; + const cell_start_xpos = self.mouse.left_click_xpos - cell_xstart; // 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 // started. - if (std.meta.eql(screen_point, win.mouse.left_click_point)) { + if (std.meta.eql(screen_point, self.mouse.left_click_point)) { const cell_xpos = xpos - cell_xstart; const selected: bool = if (cell_start_xpos < cell_xboundary) cell_xpos >= cell_xboundary else cell_xpos < cell_xboundary; - win.io.terminal.selection = if (selected) .{ + self.io.terminal.selection = if (selected) .{ .start = screen_point, .end = screen_point, } else null; @@ -1701,29 +1740,29 @@ fn cursorPosCallback( // If this is a different cell and we haven't started selection, // we determine the starting cell first. - if (win.io.terminal.selection == null) { + if (self.io.terminal.selection == null) { // - If we're moving to a point before the start, then we select // the starting cell if we started after the boundary, else // we start selection of the prior cell. // - Inverse logic for a point after the start. - const click_point = win.mouse.left_click_point; + const click_point = self.mouse.left_click_point; const start: terminal.point.ScreenPoint = if (screen_point.before(click_point)) start: { - if (win.mouse.left_click_xpos > cell_xboundary) { + if (self.mouse.left_click_xpos > cell_xboundary) { break :start click_point; } else { break :start if (click_point.x > 0) terminal.point.ScreenPoint{ .y = click_point.y, .x = click_point.x - 1, } else terminal.point.ScreenPoint{ - .x = win.io.terminal.screen.cols - 1, + .x = self.io.terminal.screen.cols - 1, .y = click_point.y -| 1, }; } } else start: { - if (win.mouse.left_click_xpos < cell_xboundary) { + if (self.mouse.left_click_xpos < cell_xboundary) { break :start click_point; } else { - break :start if (click_point.x < win.io.terminal.screen.cols - 1) terminal.point.ScreenPoint{ + break :start if (click_point.x < self.io.terminal.screen.cols - 1) terminal.point.ScreenPoint{ .y = click_point.y, .x = click_point.x + 1, } else terminal.point.ScreenPoint{ @@ -1733,7 +1772,7 @@ fn cursorPosCallback( } }; - win.io.terminal.selection = .{ .start = start, .end = screen_point }; + self.io.terminal.selection = .{ .start = start, .end = screen_point }; return; } @@ -1742,8 +1781,8 @@ fn cursorPosCallback( // We moved! Set the selection end point. The start point should be // set earlier. - assert(win.io.terminal.selection != null); - win.io.terminal.selection.?.end = screen_point; + assert(self.io.terminal.selection != null); + self.io.terminal.selection.?.end = screen_point; } fn posToViewport(self: Window, xpos: f64, ypos: f64) terminal.point.Viewport {