From d642553351b051f0c2499effc25c550ce87f181f Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 18 Dec 2014 09:26:14 -0800 Subject: [PATCH 1/5] Paste selection clipboard after finalizing selections --- src/text-editor-component.coffee | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/text-editor-component.coffee b/src/text-editor-component.coffee index 51c4447b6..562dd849d 100644 --- a/src/text-editor-component.coffee +++ b/src/text-editor-component.coffee @@ -404,7 +404,7 @@ TextEditorComponent = React.createClass window.addEventListener 'resize', @requestHeightAndWidthMeasurement @listenForIMEEvents() - @listenForMiddleMousePaste() if process.platform is 'linux' + @trackSelectionClipboard() if process.platform is 'linux' listenForIMEEvents: -> node = @getDOMNode() @@ -432,15 +432,9 @@ TextEditorComponent = React.createClass editor.insertText(selectedText, select: true, undo: 'skip') event.target.value = '' - listenForMiddleMousePaste: -> - clipboard = require 'clipboard' - - @refs.scrollView.getDOMNode().addEventListener 'mouseup', ({which}) => - return unless which is 2 - - if selection = clipboard.readText('selection') - @props.editor.insertText(selection) - + # Listen for selection changes and store the currently selected text + # in the selection clipboard. This is only applicable on Linux. + trackSelectionClipboard: -> @subscribe @props.editor.onDidChangeSelectionRange => if selectedText = @props.editor.getSelectedText() # This uses ipc.send instead of clipboard.writeText because @@ -769,15 +763,21 @@ TextEditorComponent = React.createClass # Stop dragging when cursor enters dev tools because we can't detect mouseup onMouseUp() if event.which is 0 - onMouseUp = -> + onMouseUp = (event) -> stopDragging() editor.finalizeSelections() + pasteSelectionClipboard(event) stopDragging = -> dragging = false window.removeEventListener('mousemove', onMouseMove) window.removeEventListener('mouseup', onMouseUp) + pasteSelectionClipboard = (event) -> + if event.which is 2 and process.platform is 'linux' + if selection = require('clipboard').readText('selection') + editor.insertText(selection) + window.addEventListener('mousemove', onMouseMove) window.addEventListener('mouseup', onMouseUp) From 5115540f8e6386f54558e79623107b9b4948079b Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 18 Dec 2014 09:51:32 -0800 Subject: [PATCH 2/5] Track middle button mouse down events on Linux --- src/text-editor-component.coffee | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/text-editor-component.coffee b/src/text-editor-component.coffee index 562dd849d..8f237affd 100644 --- a/src/text-editor-component.coffee +++ b/src/text-editor-component.coffee @@ -554,7 +554,11 @@ TextEditorComponent = React.createClass scrollViewNode.scrollLeft = 0 onMouseDown: (event) -> - return unless event.button is 0 # only handle the left mouse button + unless event.button is 0 or (event.button is 1 and process.platform is 'linux') + # Only handle mouse down events for left mouse button on all platforms + # and middle mouse button on Linux since it pastes the selection clipboard + return + return if event.target?.classList.contains('horizontal-scrollbar') {editor} = @props From c96f976162827430d425c482860b7c53f2b907bd Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 18 Dec 2014 10:39:11 -0800 Subject: [PATCH 3/5] Write to selection clipboard from setTimeout This is so that in progress transactions aren't written to the selection clipboard. --- src/text-editor-component.coffee | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/text-editor-component.coffee b/src/text-editor-component.coffee index 8f237affd..385a20dbb 100644 --- a/src/text-editor-component.coffee +++ b/src/text-editor-component.coffee @@ -435,12 +435,16 @@ TextEditorComponent = React.createClass # Listen for selection changes and store the currently selected text # in the selection clipboard. This is only applicable on Linux. trackSelectionClipboard: -> - @subscribe @props.editor.onDidChangeSelectionRange => + timeoutId = null + writeSelectedTextToSelectionClipboard = => if selectedText = @props.editor.getSelectedText() # This uses ipc.send instead of clipboard.writeText because # clipboard.writeText is a sync ipc call on Linux and that # will slow down selections. ipc.send('write-text-to-selection-clipboard', selectedText) + @subscribe @props.editor.onDidChangeSelectionRange => + clearTimeout(timeoutId) + timeoutId = setTimeout(writeSelectedTextToSelectionClipboard) observeConfig: -> @subscribe atom.config.observe 'editor.useHardwareAcceleration', @setUseHardwareAcceleration From 435fee1433504e284da8af90b0486b1fda7e66ff Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 18 Dec 2014 10:40:44 -0800 Subject: [PATCH 4/5] Use skinny arrow --- src/text-editor-component.coffee | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/text-editor-component.coffee b/src/text-editor-component.coffee index 385a20dbb..f4e2856b9 100644 --- a/src/text-editor-component.coffee +++ b/src/text-editor-component.coffee @@ -442,7 +442,7 @@ TextEditorComponent = React.createClass # clipboard.writeText is a sync ipc call on Linux and that # will slow down selections. ipc.send('write-text-to-selection-clipboard', selectedText) - @subscribe @props.editor.onDidChangeSelectionRange => + @subscribe @props.editor.onDidChangeSelectionRange -> clearTimeout(timeoutId) timeoutId = setTimeout(writeSelectedTextToSelectionClipboard) From f5ae96820a2aeafea8b72c1c7a607267ca0a7e0a Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 18 Dec 2014 11:04:52 -0800 Subject: [PATCH 5/5] Update spec for new middle mouse paste behavior --- spec/text-editor-component-spec.coffee | 35 ++++++++++++++++---------- src/text-editor-component.coffee | 8 +++--- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/spec/text-editor-component-spec.coffee b/spec/text-editor-component-spec.coffee index bfc343c03..3e3de2928 100644 --- a/spec/text-editor-component-spec.coffee +++ b/spec/text-editor-component-spec.coffee @@ -2713,26 +2713,35 @@ describe "TextEditorComponent", -> expect(line1LeafNodes[1].classList.contains('indent-guide')).toBe false describe "middle mouse paste on Linux", -> - it "pastes the previously selected text", -> + originalPlatform = null + + beforeEach -> + originalPlatform = process.platform + Object.defineProperty process, 'platform', value: 'linux' + + afterEach -> + Object.defineProperty process, 'platform', value: originalPlatform + + it "pastes the previously selected text at the clicked location", -> + jasmine.unspy(window, 'setTimeout') + clipboardWrittenTo = false spyOn(require('ipc'), 'send').andCallFake (eventName, selectedText) -> if eventName is 'write-text-to-selection-clipboard' require('clipboard').writeText(selectedText, 'selection') + clipboardWrittenTo = true atom.clipboard.write('') - component.listenForMiddleMousePaste() - - editor.setCursorBufferPosition([10, 0]) - componentNode.querySelector('.scroll-view').dispatchEvent(buildMouseEvent('mouseup', which: 2)) - - expect(atom.clipboard.read()).toBe '' - expect(editor.lineTextForBufferRow(10)).toBe '' - + component.trackSelectionClipboard() editor.setSelectedBufferRange([[1, 6], [1, 10]]) - editor.setCursorBufferPosition([10, 0]) - componentNode.querySelector('.scroll-view').dispatchEvent(buildMouseEvent('mouseup', which: 2)) - expect(atom.clipboard.read()).toBe 'sort' - expect(editor.lineTextForBufferRow(10)).toBe 'sort' + waitsFor -> + clipboardWrittenTo + + runs -> + componentNode.querySelector('.scroll-view').dispatchEvent(buildMouseEvent('mousedown', clientCoordinatesForScreenPosition([10, 0]), button: 1)) + componentNode.querySelector('.scroll-view').dispatchEvent(buildMouseEvent('mouseup', clientCoordinatesForScreenPosition([10, 0]), which: 2)) + expect(atom.clipboard.read()).toBe 'sort' + expect(editor.lineTextForBufferRow(10)).toBe 'sort' buildMouseEvent = (type, properties...) -> properties = extend({bubbles: true, cancelable: true}, properties...) diff --git a/src/text-editor-component.coffee b/src/text-editor-component.coffee index f4e2856b9..743e44778 100644 --- a/src/text-editor-component.coffee +++ b/src/text-editor-component.coffee @@ -436,13 +436,15 @@ TextEditorComponent = React.createClass # in the selection clipboard. This is only applicable on Linux. trackSelectionClipboard: -> timeoutId = null + {editor} = @props writeSelectedTextToSelectionClipboard = => - if selectedText = @props.editor.getSelectedText() + return if editor.isDestroyed() + if selectedText = editor.getSelectedText() # This uses ipc.send instead of clipboard.writeText because # clipboard.writeText is a sync ipc call on Linux and that # will slow down selections. ipc.send('write-text-to-selection-clipboard', selectedText) - @subscribe @props.editor.onDidChangeSelectionRange -> + @subscribe editor.onDidChangeSelectionRange -> clearTimeout(timeoutId) timeoutId = setTimeout(writeSelectedTextToSelectionClipboard) @@ -782,7 +784,7 @@ TextEditorComponent = React.createClass window.removeEventListener('mouseup', onMouseUp) pasteSelectionClipboard = (event) -> - if event.which is 2 and process.platform is 'linux' + if event?.which is 2 and process.platform is 'linux' if selection = require('clipboard').readText('selection') editor.insertText(selection)