From 69214dc26af85c5ed2369e374c6db485e48bc773 Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Tue, 5 Dec 2017 23:11:45 +0100 Subject: [PATCH 1/2] On clicks, only move cursor if there is one cursor without a selection --- src/text-editor-component.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/text-editor-component.js b/src/text-editor-component.js index da6ec452d..a43616122 100644 --- a/src/text-editor-component.js +++ b/src/text-editor-component.js @@ -1758,11 +1758,12 @@ class TextEditorComponent { const screenPosition = this.screenPositionForMouseEvent(event) - // All clicks should set the cursor position, but only left-clicks should - // have additional logic. - // On macOS, ctrl-click brings up the context menu so also handle that case. if (button !== 0 || (platform === 'darwin' && ctrlKey)) { - model.setCursorScreenPosition(screenPosition, {autoscroll: false}) + // Set cursor position only if there is one cursor with no selection + const ranges = model.getSelectedBufferRanges() + if (ranges.length === 1 && ranges[0].isEmpty()) { + model.setCursorScreenPosition(screenPosition, {autoscroll: false}) + } // On Linux, pasting happens on middle click. A textInput event with the // contents of the selection clipboard will be dispatched by the browser From db392502e4544ed7f01c4992087bba53dcc08e3e Mon Sep 17 00:00:00 2001 From: Wliu <50Wliu@users.noreply.github.com> Date: Tue, 5 Dec 2017 23:38:21 +0100 Subject: [PATCH 2/2] Always move the cursor on middle-click --- spec/text-editor-component-spec.js | 180 ++++++++++++++++++++--------- src/text-editor-component.js | 5 +- 2 files changed, 126 insertions(+), 59 deletions(-) diff --git a/spec/text-editor-component-spec.js b/spec/text-editor-component-spec.js index 47ba4ca63..578f6ec62 100644 --- a/spec/text-editor-component-spec.js +++ b/spec/text-editor-component-spec.js @@ -2840,83 +2840,149 @@ describe('TextEditorComponent', () => { describe('mouse input', () => { describe('on the lines', () => { - it('positions the cursor on single-click or when middle/right-clicking', async () => { - for (const button of [0, 1, 2]) { + describe('when there is only one cursor and no selection', () => { + it('positions the cursor on single-click or when middle/right-clicking', async () => { + for (const button of [0, 1, 2]) { + const {component, element, editor} = buildComponent() + const {lineHeight} = component.measurements + + editor.setCursorScreenPosition([Infinity, Infinity], {autoscroll: false}) + component.didMouseDownOnContent({ + detail: 1, + button, + clientX: clientLeftForCharacter(component, 0, 0) - 1, + clientY: clientTopForLine(component, 0) - 1 + }) + expect(editor.getCursorScreenPosition()).toEqual([0, 0]) + + const maxRow = editor.getLastScreenRow() + editor.setCursorScreenPosition([Infinity, Infinity], {autoscroll: false}) + component.didMouseDownOnContent({ + detail: 1, + button, + clientX: clientLeftForCharacter(component, maxRow, editor.lineLengthForScreenRow(maxRow)) + 1, + clientY: clientTopForLine(component, maxRow) + 1 + }) + expect(editor.getCursorScreenPosition()).toEqual([maxRow, editor.lineLengthForScreenRow(maxRow)]) + + component.didMouseDownOnContent({ + detail: 1, + button, + clientX: clientLeftForCharacter(component, 0, editor.lineLengthForScreenRow(0)) + 1, + clientY: clientTopForLine(component, 0) + lineHeight / 2 + }) + expect(editor.getCursorScreenPosition()).toEqual([0, editor.lineLengthForScreenRow(0)]) + + component.didMouseDownOnContent({ + detail: 1, + button, + clientX: (clientLeftForCharacter(component, 3, 0) + clientLeftForCharacter(component, 3, 1)) / 2, + clientY: clientTopForLine(component, 1) + lineHeight / 2 + }) + expect(editor.getCursorScreenPosition()).toEqual([1, 0]) + + component.didMouseDownOnContent({ + detail: 1, + button, + clientX: (clientLeftForCharacter(component, 3, 14) + clientLeftForCharacter(component, 3, 15)) / 2, + clientY: clientTopForLine(component, 3) + lineHeight / 2 + }) + expect(editor.getCursorScreenPosition()).toEqual([3, 14]) + + component.didMouseDownOnContent({ + detail: 1, + button, + clientX: (clientLeftForCharacter(component, 3, 14) + clientLeftForCharacter(component, 3, 15)) / 2 + 1, + clientY: clientTopForLine(component, 3) + lineHeight / 2 + }) + expect(editor.getCursorScreenPosition()).toEqual([3, 15]) + + editor.getBuffer().setTextInRange([[3, 14], [3, 15]], '🐣') + await component.getNextUpdatePromise() + + component.didMouseDownOnContent({ + detail: 1, + button, + clientX: (clientLeftForCharacter(component, 3, 14) + clientLeftForCharacter(component, 3, 16)) / 2, + clientY: clientTopForLine(component, 3) + lineHeight / 2 + }) + expect(editor.getCursorScreenPosition()).toEqual([3, 14]) + + component.didMouseDownOnContent({ + detail: 1, + button, + clientX: (clientLeftForCharacter(component, 3, 14) + clientLeftForCharacter(component, 3, 16)) / 2 + 1, + clientY: clientTopForLine(component, 3) + lineHeight / 2 + }) + expect(editor.getCursorScreenPosition()).toEqual([3, 16]) + + expect(editor.testAutoscrollRequests).toEqual([]) + } + }) + }) + + describe('when there is more than one cursor', () => { + it('does not move the cursor when right-clicking', async () => { const {component, element, editor} = buildComponent() const {lineHeight} = component.measurements - editor.setCursorScreenPosition([Infinity, Infinity], {autoscroll: false}) + editor.setCursorScreenPosition([5, 17], {autoscroll: false}) + editor.addCursorAtScreenPosition([2, 4]) component.didMouseDownOnContent({ detail: 1, - button, + button: 2, clientX: clientLeftForCharacter(component, 0, 0) - 1, clientY: clientTopForLine(component, 0) - 1 }) - expect(editor.getCursorScreenPosition()).toEqual([0, 0]) + expect(editor.getCursorScreenPositions()).toEqual([Point.fromObject([5, 17]), Point.fromObject([2, 4])]) + }) - const maxRow = editor.getLastScreenRow() - editor.setCursorScreenPosition([Infinity, Infinity], {autoscroll: false}) + it('does move the cursor when middle-clicking', async () => { + const {component, element, editor} = buildComponent() + const {lineHeight} = component.measurements + + editor.setCursorScreenPosition([5, 17], {autoscroll: false}) + editor.addCursorAtScreenPosition([2, 4]) component.didMouseDownOnContent({ detail: 1, - button, - clientX: clientLeftForCharacter(component, maxRow, editor.lineLengthForScreenRow(maxRow)) + 1, - clientY: clientTopForLine(component, maxRow) + 1 + button: 1, + clientX: clientLeftForCharacter(component, 0, 0) - 1, + clientY: clientTopForLine(component, 0) - 1 }) - expect(editor.getCursorScreenPosition()).toEqual([maxRow, editor.lineLengthForScreenRow(maxRow)]) + expect(editor.getCursorScreenPositions()).toEqual([Point.fromObject([0, 0])]) + }) + }) + describe('when there are non-empty selections', () => { + it('does not move the cursor when right-clicking', async () => { + const {component, element, editor} = buildComponent() + const {lineHeight} = component.measurements + + editor.setCursorScreenPosition([5, 17], {autoscroll: false}) + editor.selectRight(3) component.didMouseDownOnContent({ detail: 1, - button, - clientX: clientLeftForCharacter(component, 0, editor.lineLengthForScreenRow(0)) + 1, - clientY: clientTopForLine(component, 0) + lineHeight / 2 + button: 2, + clientX: clientLeftForCharacter(component, 0, 0) - 1, + clientY: clientTopForLine(component, 0) - 1 }) - expect(editor.getCursorScreenPosition()).toEqual([0, editor.lineLengthForScreenRow(0)]) + expect(editor.getSelectedScreenRange()).toEqual([[5, 17], [5, 20]]) + }) + it('does move the cursor when middle-clicking', async () => { + const {component, element, editor} = buildComponent() + const {lineHeight} = component.measurements + + editor.setCursorScreenPosition([5, 17], {autoscroll: false}) + editor.selectRight(3) component.didMouseDownOnContent({ detail: 1, - button, - clientX: (clientLeftForCharacter(component, 3, 0) + clientLeftForCharacter(component, 3, 1)) / 2, - clientY: clientTopForLine(component, 1) + lineHeight / 2 + button: 1, + clientX: clientLeftForCharacter(component, 0, 0) - 1, + clientY: clientTopForLine(component, 0) - 1 }) - expect(editor.getCursorScreenPosition()).toEqual([1, 0]) - - component.didMouseDownOnContent({ - detail: 1, - button, - clientX: (clientLeftForCharacter(component, 3, 14) + clientLeftForCharacter(component, 3, 15)) / 2, - clientY: clientTopForLine(component, 3) + lineHeight / 2 - }) - expect(editor.getCursorScreenPosition()).toEqual([3, 14]) - - component.didMouseDownOnContent({ - detail: 1, - button, - clientX: (clientLeftForCharacter(component, 3, 14) + clientLeftForCharacter(component, 3, 15)) / 2 + 1, - clientY: clientTopForLine(component, 3) + lineHeight / 2 - }) - expect(editor.getCursorScreenPosition()).toEqual([3, 15]) - - editor.getBuffer().setTextInRange([[3, 14], [3, 15]], '🐣') - await component.getNextUpdatePromise() - - component.didMouseDownOnContent({ - detail: 1, - button, - clientX: (clientLeftForCharacter(component, 3, 14) + clientLeftForCharacter(component, 3, 16)) / 2, - clientY: clientTopForLine(component, 3) + lineHeight / 2 - }) - expect(editor.getCursorScreenPosition()).toEqual([3, 14]) - - component.didMouseDownOnContent({ - detail: 1, - button, - clientX: (clientLeftForCharacter(component, 3, 14) + clientLeftForCharacter(component, 3, 16)) / 2 + 1, - clientY: clientTopForLine(component, 3) + lineHeight / 2 - }) - expect(editor.getCursorScreenPosition()).toEqual([3, 16]) - - expect(editor.testAutoscrollRequests).toEqual([]) - } + expect(editor.getSelectedScreenRange()).toEqual([[0, 0], [0, 0]]) + }) }) describe('when the input is for the primary mouse button', () => { diff --git a/src/text-editor-component.js b/src/text-editor-component.js index a43616122..06bbe535f 100644 --- a/src/text-editor-component.js +++ b/src/text-editor-component.js @@ -1759,9 +1759,10 @@ class TextEditorComponent { const screenPosition = this.screenPositionForMouseEvent(event) if (button !== 0 || (platform === 'darwin' && ctrlKey)) { - // Set cursor position only if there is one cursor with no selection + // Always set cursor position on middle-click + // Only set cursor position on right-click if there is one cursor with no selection const ranges = model.getSelectedBufferRanges() - if (ranges.length === 1 && ranges[0].isEmpty()) { + if (button === 1 || (ranges.length === 1 && ranges[0].isEmpty())) { model.setCursorScreenPosition(screenPosition, {autoscroll: false}) }