Commit 2bed94b6 authored by Dominik Haumann's avatar Dominik Haumann
Browse files

Fix: View jumps when Scroll past end of document is enabled

Summary:
This patch fixes a corner case for the following setup:
- enable "[x] Scroll past end of document"
- disable dynamic word wrap (i.e. you see a horizontal
  scrollbar for long lines)
- open a document with several lines
- make sure the last line is NOT empty

Let's say the last two lines look as follows

yy|yy # '|' denoes the cursor position
zzzzz

Make sure you scrolled past the end of the document (either
with the mouse or with Ctrl+Down). Note that line 'zzzzz' is
completely visible.

Now press 'cursor down'.

What happens is that the view contents jumps and the scrolling
behavior acts as if "Scroll past end of document" is not enabled.

Expected behavior is that the cursor position goes one line down,
but the scroll position remains completely unchanged.

The bug here is the following if clause:

    } else if (c > viewLineOffset(startPos(), linesDisplayed() - m_minLinesVisible - 1)) {
        KTextEditor::Cursor scroll = viewLineOffset(c, -(linesDisplayed() - m_minLinesVisible - 1));
        scrollPos(scroll, false, calledExternally);
    }

In the buggy case, c==(28, 1), and viewLineOffset()==(28,0).
This triggers the bug that in the last line of the document for
columns > 0 the scroll position is adapted.

The proposed fix here is to not compare cursor positions, but only
the lines. Clearly, 28 < 28 is not true, leading to no change in
the scroll position.

BUG: 306745
FIXED-IN: KDE Frameworks 5.43

Test Plan: make test

Reviewers: cullmann

Reviewed By: cullmann

Subscribers: #frameworks

Tags: #kate, #frameworks

Differential Revision: https://phabricator.kde.org/D10054
parent fbdfe779
......@@ -291,6 +291,39 @@ void KateViewTest::testKillline()
QCOMPARE(doc.text(), QLatin1String("foo\nxxx\n"));
}
void KateViewTest::testScrollPastEndOfDocument()
{
KTextEditor::DocumentPrivate doc;
doc.setText(QStringLiteral("0000000000\n"
"1111111111\n"
"2222222222\n"
"3333333333\n"
"4444444444"));
QCOMPARE(doc.lines(), 5);
KTextEditor::ViewPrivate *view = new KTextEditor::ViewPrivate(&doc, nullptr);
view->setCursorPosition({ 3, 5 });
view->resize(400, 300);
view->show();
// enable "[x] Scroll past end of document"
view->config()->setScrollPastEnd(true);
QCOMPARE(view->config()->scrollPastEnd(), true);
// disable dynamic word wrap
view->config()->setDynWordWrap(false);
QCOMPARE(view->config()->dynWordWrap(), false);
view->scrollDown();
view->scrollDown();
view->scrollDown();
// at this point, only lines 3333333333 and 4444444444 are visible.
view->down();
QCOMPARE(view->cursorPosition(), KTextEditor::Cursor(4, 5));
// verify, that only lines 3333333333 and 4444444444 are still visible.
QCOMPARE(view->firstDisplayedLineInternal(KTextEditor::View::RealLine), 3);
}
void KateViewTest::testFoldFirstLine()
{
QTemporaryFile file("XXXXXX.cpp");
......
......@@ -41,6 +41,7 @@ private Q_SLOTS:
void testSelection();
void testKillline();
void testScrollPastEndOfDocument();
void testFoldFirstLine();
......
......@@ -709,7 +709,7 @@ void KateViewInternal::makeVisible(const KTextEditor::Cursor &c, int endCol, boo
} else if (center && (c < startPos() || c > endPos())) {
KTextEditor::Cursor scroll = viewLineOffset(c, -int(linesDisplayed()) / 2);
scrollPos(scroll, false, calledExternally);
} else if (c > viewLineOffset(startPos(), linesDisplayed() - m_minLinesVisible - 1)) {
} else if (c.line() > viewLineOffset(startPos(), linesDisplayed() - m_minLinesVisible - 1).line()) {
KTextEditor::Cursor scroll = viewLineOffset(c, -(linesDisplayed() - m_minLinesVisible - 1));
scrollPos(scroll, false, calledExternally);
} else if (c < viewLineOffset(startPos(), m_minLinesVisible)) {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment