Terminate selection drag on text input

On recent versions of OS X Yosemite, there is a delay before we receive
the `mouseup` event when dragging selections with the trackpad. This
means that we’re frequently accidentally inserting text before the
selection process terminates, leading to unexpected selections after the
text insertion. This fixes that behavior and makes the behavior more
straightforward even in the case where the mouse button is remains held
down during text insertion.
This commit is contained in:
Nathan Sobo
2015-08-19 11:50:14 -06:00
parent f31dc03e1d
commit 8ae3761cd7
2 changed files with 42 additions and 3 deletions

View File

@@ -1792,6 +1792,24 @@ describe "TextEditorComponent", ->
expect(nextAnimationFrame).toBe noAnimationFrame
expect(editor.getSelectedScreenRange()).toEqual [[2, 4], [6, 8]]
it "stops selecting if a textInput event occurs during the drag", ->
linesNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenPosition([2, 4]), which: 1))
linesNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenPosition([6, 8]), which: 1))
nextAnimationFrame()
expect(editor.getSelectedScreenRange()).toEqual [[2, 4], [6, 8]]
inputEvent = new Event('textInput')
inputEvent.data = 'x'
Object.defineProperty(inputEvent, 'target', get: -> componentNode.querySelector('.hidden-input'))
componentNode.dispatchEvent(inputEvent)
nextAnimationFrame()
expect(editor.getSelectedScreenRange()).toEqual [[2, 5], [2, 5]]
linesNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenPosition([8, 0]), which: 1))
expect(nextAnimationFrame).toBe noAnimationFrame
expect(editor.getSelectedScreenRange()).toEqual [[2, 5], [2, 5]]
describe "when the command key is held down", ->
it "adds a new selection and selects to the nearest screen position, then merges intersecting selections when the mouse button is released", ->
editor.setSelectedScreenRange([[4, 4], [4, 9]])
@@ -1979,6 +1997,24 @@ describe "TextEditorComponent", ->
nextAnimationFrame()
expect(editor.getScrollTop()).toBe maxScrollTop
it "stops selecting if a textInput event occurs during the drag", ->
gutterNode.dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenRowInGutter(2)))
gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(6)))
nextAnimationFrame()
expect(editor.getSelectedScreenRange()).toEqual [[2, 0], [7, 0]]
inputEvent = new Event('textInput')
inputEvent.data = 'x'
Object.defineProperty(inputEvent, 'target', get: -> componentNode.querySelector('.hidden-input'))
componentNode.dispatchEvent(inputEvent)
nextAnimationFrame()
expect(editor.getSelectedScreenRange()).toEqual [[2, 1], [2, 1]]
gutterNode.dispatchEvent(buildMouseEvent('mousemove', clientCoordinatesForScreenRowInGutter(12)))
expect(nextAnimationFrame).toBe noAnimationFrame
expect(editor.getSelectedScreenRange()).toEqual [[2, 1], [2, 1]]
describe "when the gutter is meta-clicked and dragged", ->
beforeEach ->
editor.setSelectedScreenRange([[3, 0], [3, 2]])

View File

@@ -523,15 +523,17 @@ class TextEditorComponent
onMouseUp() if event.which is 0
onMouseUp = (event) =>
stopDragging()
@editor.finalizeSelections()
@editor.mergeIntersectingSelections()
if dragging
stopDragging()
@editor.finalizeSelections()
@editor.mergeIntersectingSelections()
pasteSelectionClipboard(event)
stopDragging = ->
dragging = false
window.removeEventListener('mousemove', onMouseMove)
window.removeEventListener('mouseup', onMouseUp)
willInsertTextSubscription.dispose()
pasteSelectionClipboard = (event) =>
if event?.which is 2 and process.platform is 'linux'
@@ -540,6 +542,7 @@ class TextEditorComponent
window.addEventListener('mousemove', onMouseMove)
window.addEventListener('mouseup', onMouseUp)
willInsertTextSubscription = @editor.onWillInsertText(onMouseUp)
isVisible: ->
@domNode.offsetHeight > 0 or @domNode.offsetWidth > 0