On Linux, when the user performs a middle-button mouse click, Chromium
fires both a mouse-down event *and* a paste event. This commit teaches
the TextEditorComponent to ignore the paste event.

When the user performs a middle-mouse click on a tab, we get close the
tab and attempt to prevent Chromium's default processing for the event.
[1] This prevents Chromium's default processing for the *mouse down*
event, but then Chromium also fires a *paste* event, and that event
pastes the clipboard's current content into the newly-focused text
editor. 🙀

Since Atom already has its own logic for handling pasting, we
shouldn't (🤞) need to handle browser paste events. By ignoring the
browser paste events on Linux, we fix atom/tabs#461.

[1]
ce1d92e0ab/lib/tab-bar-view.coffee (L416-L418)
This commit is contained in:
Jason Rudolph
2017-08-07 09:50:10 -04:00
parent b4125022b6
commit c7bfbc181c
2 changed files with 40 additions and 6 deletions

View File

@@ -2687,18 +2687,42 @@ describe('TextEditorComponent', () => {
expect(component.getScrollLeft()).toBe(maxScrollLeft)
})
it('positions the cursor on clicking the middle mouse button on Linux', async () => {
// The browser synthesizes the paste as a textInput event on mouseup
// so it is not possible to test it here.
it('pastes the previously selected text when clicking the middle mouse button on Linux', async () => {
spyOn(electron.ipcRenderer, 'send').andCallFake(function (eventName, selectedText) {
if (eventName === 'write-text-to-selection-clipboard') {
clipboard.writeText(selectedText, 'selection')
}
})
const {component, editor} = buildComponent({platform: 'linux'})
// Middle mouse pasting.
editor.setSelectedBufferRange([[1, 6], [1, 10]])
await conditionPromise(() => TextEditor.clipboard.read() === 'sort')
component.didMouseDownOnContent({
button: 1,
clientX: clientLeftForCharacter(component, 10, 0),
clientY: clientTopForLine(component, 10)
})
expect(editor.getSelectedBufferRange()).toEqual([[10, 0], [10, 0]])
expect(TextEditor.clipboard.read()).toBe('sort')
expect(editor.lineTextForBufferRow(10)).toBe('sort')
editor.undo()
// Ensure left clicks don't interfere.
editor.setSelectedBufferRange([[1, 2], [1, 5]])
await conditionPromise(() => TextEditor.clipboard.read() === 'var')
component.didMouseDownOnContent({
button: 0,
detail: 1,
clientX: clientLeftForCharacter(component, 10, 0),
clientY: clientTopForLine(component, 10)
})
component.didMouseDownOnContent({
button: 1,
clientX: clientLeftForCharacter(component, 10, 0),
clientY: clientTopForLine(component, 10)
})
expect(editor.lineTextForBufferRow(10)).toBe('var')
})
})

View File

@@ -5,6 +5,7 @@ const {Point, Range} = require('text-buffer')
const LineTopIndex = require('line-top-index')
const TextEditor = require('./text-editor')
const {isPairedCharacter} = require('./text-utils')
const clipboard = require('./safe-clipboard')
const electron = require('electron')
const $ = etch.dom
@@ -641,6 +642,7 @@ class TextEditorComponent {
didBlurHiddenInput: this.didBlurHiddenInput,
didFocusHiddenInput: this.didFocusHiddenInput,
didTextInput: this.didTextInput,
didPaste: this.didPaste,
didKeydown: this.didKeydown,
didKeyup: this.didKeyup,
didKeypress: this.didKeypress,
@@ -1549,6 +1551,11 @@ class TextEditorComponent {
}
}
didPaste (event) {
// TODO Explain the motivation for this logic
if ((this.props.platform || process.platform) === 'linux') event.preventDefault()
}
didTextInput (event) {
if (!this.isInputEnabled()) return
@@ -1654,8 +1661,10 @@ class TextEditorComponent {
// textInput event with the contents of the selection clipboard will be
// dispatched by the browser automatically on mouseup.
if (platform === 'linux' && button === 1) {
const selection = clipboard.readText('selection')
const screenPosition = this.screenPositionForMouseEvent(event)
model.setCursorScreenPosition(screenPosition, {autoscroll: false})
model.insertText(selection)
return
}
@@ -3356,8 +3365,8 @@ class CursorsAndInputComponent {
renderHiddenInput () {
const {
lineHeight, hiddenInputPosition, didBlurHiddenInput, didFocusHiddenInput,
didTextInput, didKeydown, didKeyup, didKeypress, didCompositionStart,
didCompositionUpdate, didCompositionEnd
didPaste, didTextInput, didKeydown, didKeyup, didKeypress,
didCompositionStart, didCompositionUpdate, didCompositionEnd
} = this.props
let top, left
@@ -3376,6 +3385,7 @@ class CursorsAndInputComponent {
on: {
blur: didBlurHiddenInput,
focus: didFocusHiddenInput,
paste: didPaste,
textInput: didTextInput,
keydown: didKeydown,
keyup: didKeyup,