Help preserving scroll position on BTextView resize

I’m working on a Haiku app with a BTextView inside a BScrollView. I’m trying to preserve the scroll position when the user resizes the main window, but I can’t seem to stop the scrollbars from jumping back to the top/left during resize.

fTextView = new UndoableTextView("TextView");
fScrollView = new BScrollView("TextViewScroll", fTextView,
    B_WILL_DRAW | B_FRAME_EVENTS, true, true, B_PLAIN_BORDER);

I have tried to save the scroll position in MainWindow::FrameResized:

void MainWindow::FrameResized(float newWidth, float newHeight)
{
    // Save current scroll position
    BPoint scrollOffset = fTextView->Bounds().LeftTop();
	if (scrollOffset.x > 0 || scrollOffset.y > 0)
		printf("Scroll offset: X%f, X%f\n", scrollOffset.x, scrollOffset.y);

    // Call parent implementation
    BWindow::FrameResized(newWidth, newHeight);

    // Restore scroll position
    fTextView->ScrollTo(scrollOffset);
}

The scroll values (scrollOffset) seem to get reset to 0.0 during resize. I confirmed with debug prints that they’re > 0 when resizing begins, but are being set to 0 during or after the resize event.

Any tips on how to properly restore the scroll position when resizing the window, without jumping back to (0,0)? Is there a better hook than FrameResized() for restoring scroll?

Thanks!

I don’t think any custom logic should be necessary, a BTextView inside a BScrollView should preserve scroll position even on resize. AboutSystem doesn’t do anything special here that I can see, and it “just works”: AboutSystem.cpp (revision 01b94ce7b8d99b7ba71ecae90c8f21b1583c8004) - OpenGrok cross reference for /haiku/src/apps/aboutsystem/AboutSystem.cpp

One possibility: Are you setting any kind of custom flags on that UndoableTextView? Does it work with a regular BTextView but not the custom one? If you inadvertently clear the B_SCROLL_VIEW_AWARE flag on the BTextView, then the scrollview may indeed behave oddly.

Thank you for the tip. Updating my constructor to include B_SCROLL_VIEW_AWARE seems to have fixed it.

BTextView(name, B_WILL_DRAW | B_SCROLL_VIEW_AWARE)

I’m not setting any custom flags, but the UndoableTextView can be changed both manually and programmatically, which might have caused the flag to be cleared.

Override UndoableTextView::SetFlags() to enforce B_SCROLL_VIEW_AWARE flag:

void
UndoableTextView::SetFlags(uint32 flags)
{
	BTextView::SetFlags(flags | B_SCROLL_VIEW_AWARE);
}

Appears a number of controls override SetFlags to do things like this already, we should probably do the same in BTextView itself I guess?

1 Like

Well, if it make no sense to support BTextView NOT having B_SCROLL_VIEW_AWARE flag set, yes, it will be easier.