Skip to content

Commit ad0ffc0

Browse files
[autocomplete-plus] Ensure editor is re-focused… (#1552)
* [autocomplete-plus] Ensure editor is re-focused… …after the user selects a suggestion via the mouse. * [autocomplete-plus] Fix failing spec * [autocomplete-plus] Add spec to demonstrate the fix
1 parent 55d971a commit ad0ffc0

2 files changed

Lines changed: 40 additions & 3 deletions

File tree

packages/autocomplete-plus/lib/suggestion-list.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,14 +326,21 @@ class SuggestionList {
326326
} else if (this.overlayDecoration && this.overlayDecoration.destroy) {
327327
this.overlayDecoration.destroy()
328328
}
329-
const editorElement = atom.views.getView(this.activeEditor)
329+
const activeEditor = this.activeEditor
330+
const editorElement = atom.views.getView(activeEditor)
330331
if (editorElement && editorElement.classList) {
331332
let timestamp = this.lastActiveAt
332333
atom.views.updateDocument(() => {
333334
// A newer timestamp here means that the menu is open again and we
334335
// shouldn't remove this class name anymore.
335336
if (this.lastActiveAt > timestamp) return
336337
editorElement.classList.remove('autocomplete-active')
338+
// If the user clicked on the suggestion, focus moved onto the overlay
339+
// before it was destroyed, so we'll move it back onto the editor. But
340+
// first we ensure that this is still the active editor!
341+
if (atom.workspace.getActiveTextEditor() === activeEditor) {
342+
editorElement.focus()
343+
}
337344
})
338345
}
339346
this.suggestionMarker = undefined

packages/autocomplete-plus/spec/autocomplete-manager-integration-spec.js

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,12 @@ const path = require('path')
1717

1818
let NodeTypeText = 3
1919

20+
function simulateClick(element) {
21+
element.dispatchEvent(new PointerEvent('mousedown', { bubbles: true, cancelable: true }));
22+
element.dispatchEvent(new PointerEvent('mouseup', { bubbles: true, cancelable: true }));
23+
element.dispatchEvent(new PointerEvent('click', { bubbles: true, cancelable: true }));
24+
}
25+
2026
describe('Autocomplete Manager', () => {
2127
let autocompleteManager, editor, editorView, gutterWidth, mainModule, workspaceElement
2228

@@ -141,7 +147,7 @@ describe('Autocomplete Manager', () => {
141147
expect(editorView.querySelector('.autocomplete-plus')).not.toExist()
142148
})
143149

144-
it('it refocuses the editor after pressing enter', async () => {
150+
it('refocuses the editor after pressing enter', async () => {
145151
expect(editorView.querySelector('.autocomplete-plus')).not.toExist()
146152
editor.insertText('a')
147153
await waitForAutocomplete(editor)
@@ -1311,6 +1317,30 @@ describe('Autocomplete Manager', () => {
13111317
expect(editorView.querySelector('.autocomplete-plus')).not.toExist()
13121318
})
13131319

1320+
it('hides the suggestions list when a suggestion is clicked on', async () => {
1321+
triggerAutocompletion(editor, false, 'a')
1322+
await waitForAutocomplete(editor)
1323+
1324+
expect(editorView.querySelector('.autocomplete-plus')).toExist()
1325+
1326+
// Accept suggestion
1327+
let suggestionListView = editorView.querySelector('.autocomplete-plus autocomplete-suggestion-list')
1328+
let firstOption = suggestionListView.querySelector('li')
1329+
1330+
// Manually blurring the editor here matches our observation that, when
1331+
// an actual human clicks on a suggestion, it blurs the editor and ends
1332+
// up focusing the BODY indirectly.
1333+
document.activeElement.blur()
1334+
simulateClick(firstOption)
1335+
1336+
// Ensure the menu is closed…
1337+
expect(editorView.querySelector('.autocomplete-plus')).not.toExist()
1338+
// …and our editor still has focus.
1339+
await conditionPromise(() => {
1340+
return document.activeElement.closest('atom-text-editor') === editorView
1341+
})
1342+
})
1343+
13141344
describe('when the replacementPrefix is empty', () => {
13151345
beforeEach(() => {
13161346
spyOn(provider, 'getSuggestions').andCallFake(() => [{text: 'someMethod()', replacementPrefix: ''}])
@@ -2350,7 +2380,7 @@ defm`
23502380
expect(items[0].innerText.trim()).toEqual('center')
23512381
})
23522382

2353-
it('stops providing autocompletions when disposed.', async () => {
2383+
it('stops providing autocompletions when disposed', async () => {
23542384
autocompleteDisposable.dispose()
23552385
bottomEditorView.focus()
23562386
triggerAutocompletion(bottomEditor)

0 commit comments

Comments
 (0)