Merge pull request #16328 from atom/wl-right-click-selections

Update auxiliary click logic for moving cursors
This commit is contained in:
Wliu
2017-12-21 12:18:41 -05:00
committed by GitHub
2 changed files with 129 additions and 61 deletions

View File

@@ -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', () => {

View File

@@ -1762,11 +1762,13 @@ 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})
// 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 (button === 1 || (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