diff --git a/spec/text-editor-presenter-spec.coffee b/spec/text-editor-presenter-spec.coffee index b1ee17ef1..8837fd598 100644 --- a/spec/text-editor-presenter-spec.coffee +++ b/spec/text-editor-presenter-spec.coffee @@ -323,6 +323,69 @@ describe "TextEditorPresenter", -> expectStateUpdate presenter, -> atom.config.set("editor.scrollPastEnd", false) expect(presenter.state.verticalScrollbar.scrollTop).toBe presenter.contentHeight - presenter.clientHeight + describe ".hiddenInput", -> + describe ".top/.left", -> + it "is positioned over the last cursor it is in view and the editor is focused", -> + editor.setCursorBufferPosition([3, 6]) + presenter = buildPresenter(focused: false, explicitHeight: 50, contentFrameWidth: 300, horizontalScrollbarHeight: 0, verticalScrollbarWidth: 0) + expectValues presenter.state.hiddenInput, {top: 0, left: 0} + + expectStateUpdate presenter, -> presenter.setFocused(true) + expectValues presenter.state.hiddenInput, {top: 3 * 10, left: 6 * 10} + + expectStateUpdate presenter, -> presenter.setScrollTop(15) + expectValues presenter.state.hiddenInput, {top: (3 * 10) - 15, left: 6 * 10} + + expectStateUpdate presenter, -> presenter.setScrollLeft(35) + expectValues presenter.state.hiddenInput, {top: (3 * 10) - 15, left: (6 * 10) - 35} + + expectStateUpdate presenter, -> presenter.setScrollTop(40) + expectValues presenter.state.hiddenInput, {top: 0, left: (6 * 10) - 35} + + expectStateUpdate presenter, -> presenter.setScrollLeft(70) + expectValues presenter.state.hiddenInput, {top: 0, left: 0} + + expectStateUpdate presenter, -> editor.setCursorBufferPosition([11, 43]) + expectValues presenter.state.hiddenInput, {top: 50 - 10, left: 300 - 10} + + newCursor = null + expectStateUpdate presenter, -> newCursor = editor.addCursorAtBufferPosition([6, 10]) + expectValues presenter.state.hiddenInput, {top: (6 * 10) - 40, left: (10 * 10) - 70} + + expectStateUpdate presenter, -> newCursor.destroy() + expectValues presenter.state.hiddenInput, {top: 50 - 10, left: 300 - 10} + + expectStateUpdate presenter, -> presenter.setFocused(false) + expectValues presenter.state.hiddenInput, {top: 0, left: 0} + + describe ".height", -> + it "is assigned based on the line height", -> + presenter = buildPresenter() + expect(presenter.state.hiddenInput.height).toBe 10 + + expectStateUpdate presenter, -> presenter.setLineHeight(20) + expect(presenter.state.hiddenInput.height).toBe 20 + + describe ".width", -> + it "is assigned based on the width of the character following the cursor", -> + waitsForPromise -> atom.packages.activatePackage('language-javascript') + + runs -> + editor.setCursorBufferPosition([3, 6]) + presenter = buildPresenter() + expect(presenter.state.hiddenInput.width).toBe 10 + + expectStateUpdate presenter, -> presenter.setBaseCharacterWidth(15) + expect(presenter.state.hiddenInput.width).toBe 15 + + expectStateUpdate presenter, -> presenter.setScopedCharacterWidth(['source.js', 'storage.modifier.js'], 'r', 20) + expect(presenter.state.hiddenInput.width).toBe 20 + + it "is 2px at the end of lines", -> + presenter = buildPresenter() + editor.setCursorBufferPosition([3, Infinity]) + expect(presenter.state.hiddenInput.width).toBe 2 + describe ".content", -> describe ".scrollingVertically", -> it "is true for ::stoppedScrollingDelay milliseconds following a changes to ::scrollTop", -> diff --git a/src/text-editor-presenter.coffee b/src/text-editor-presenter.coffee index 6e8417e49..5939beb73 100644 --- a/src/text-editor-presenter.coffee +++ b/src/text-editor-presenter.coffee @@ -86,6 +86,7 @@ class TextEditorPresenter @state = horizontalScrollbar: {} verticalScrollbar: {} + hiddenInput: {} content: scrollingVertically: false blinkCursorsOff: false @@ -106,6 +107,7 @@ class TextEditorPresenter @updateVerticalScrollState() @updateHorizontalScrollState() @updateScrollbarsState() + @updateHiddenInputState() @updateContentState() @updateDecorations() @updateLinesState() @@ -153,6 +155,25 @@ class TextEditorPresenter @emitter.emit 'did-update-state' + updateHiddenInputState: -> + return unless lastCursor = @model.getLastCursor() + + {top, left, height, width} = @pixelRectForScreenRange(lastCursor.getScreenRange()) + + if @focused + top -= @scrollTop + left -= @scrollLeft + @state.hiddenInput.top = Math.max(Math.min(top, @clientHeight - height), 0) + @state.hiddenInput.left = Math.max(Math.min(left, @clientWidth - width), 0) + else + @state.hiddenInput.top = 0 + @state.hiddenInput.left = 0 + + @state.hiddenInput.height = height + @state.hiddenInput.width = Math.max(width, 2) + + @emitter.emit 'did-update-state' + updateContentState: -> @state.content.scrollWidth = @scrollWidth @state.content.scrollLeft = @scrollLeft @@ -448,6 +469,11 @@ class TextEditorPresenter getCursorBlinkResumeDelay: -> @cursorBlinkResumeDelay + setFocused: (focused) -> + unless @focused is focused + @focused = focused + @updateHiddenInputState() + setScrollTop: (scrollTop) -> scrollTop = @constrainScrollTop(scrollTop) @@ -458,6 +484,7 @@ class TextEditorPresenter @updateEndRow() @didStartScrolling() @updateVerticalScrollState() + @updateHiddenInputState() @updateDecorations() @updateLinesState() @updateCursorsState() @@ -487,6 +514,7 @@ class TextEditorPresenter @scrollLeft = scrollLeft @model.setScrollLeft(scrollLeft) @updateHorizontalScrollState() + @updateHiddenInputState() @updateCursorsState() unless oldScrollLeft? setHorizontalScrollbarHeight: (horizontalScrollbarHeight) -> @@ -576,6 +604,7 @@ class TextEditorPresenter @updateHorizontalScrollState() @updateVerticalScrollState() @updateScrollbarsState() + @updateHiddenInputState() @updateDecorations() @updateLinesState() @updateCursorsState() @@ -623,6 +652,7 @@ class TextEditorPresenter @updateHorizontalScrollState() @updateVerticalScrollState() @updateScrollbarsState() + @updateHiddenInputState() @updateContentState() @updateDecorations() @updateLinesState() @@ -886,6 +916,7 @@ class TextEditorPresenter observeCursor: (cursor) -> didChangePositionDisposable = cursor.onDidChangePosition => + @updateHiddenInputState() if cursor.isLastCursor() @pauseCursorBlinking() @updateCursorsState() @@ -895,6 +926,7 @@ class TextEditorPresenter @disposables.remove(didChangePositionDisposable) @disposables.remove(didChangeVisibilityDisposable) @disposables.remove(didDestroyDisposable) + @updateHiddenInputState() @updateCursorsState() @disposables.add(didChangePositionDisposable) @@ -903,6 +935,7 @@ class TextEditorPresenter didAddCursor: (cursor) -> @observeCursor(cursor) + @updateHiddenInputState() @pauseCursorBlinking() @updateCursorsState()