Skip to content

element/scrollarea: add optional draggable scrollbar#89

Merged
vaxerski merged 1 commit into
hyprwm:mainfrom
UncleJ4ck:feat-scrollarea-scrollbar
Jun 12, 2026
Merged

element/scrollarea: add optional draggable scrollbar#89
vaxerski merged 1 commit into
hyprwm:mainfrom
UncleJ4ck:feat-scrollarea-scrollbar

Conversation

@UncleJ4ck

@UncleJ4ck UncleJ4ck commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Redone as a real element in the tree, per your suggestion.

showScrollbar(true) adds a track and a draggable thumb. The scroll offset is applied to every child, so the content now lives in an inner layer that scrolls, and the scrollbar sits on top as a sibling that stays put. The strip takes mouse input:

  • drag the thumb to scroll
  • click the track to jump there and keep dragging
  • thumb brightens on hover

Vertical and horizontal are both handled. The paintOver() hook from the first version is gone.

Tests (headless, hard assertions): scroll clamp, thumb size/position vs scroll, a tiny-viewport regression for a std::clamp abort that the first version hit, and a drag that asserts the scroll moves proportionally then stops on release.

@UncleJ4ck UncleJ4ck force-pushed the feat-scrollarea-scrollbar branch 3 times, most recently from 83e81bb to bcd1753 Compare June 3, 2026 14:11
@vaxerski

vaxerski commented Jun 3, 2026

Copy link
Copy Markdown
Member

would it not be better to make the scrollbar actually part of the layout tree so it can receive input events and stuff?

@UncleJ4ck

Copy link
Copy Markdown
Contributor Author

actually that's a good idea

@UncleJ4ck UncleJ4ck force-pushed the feat-scrollarea-scrollbar branch from bcd1753 to 8829ccf Compare June 3, 2026 15:08
@UncleJ4ck UncleJ4ck changed the title element/scrollarea: add optional fading scrollbar element/scrollarea: add optional draggable scrollbar Jun 3, 2026
@UncleJ4ck

Copy link
Copy Markdown
Contributor Author

redid it as a real element in the tree. the thumb is draggable now, click on the track jumps and keeps dragging, and it brightens on hover. content goes into an inner scrolled layer so the bar can sit on top and take input. dropped the paintOver hook.

@vaxerski

vaxerski commented Jun 3, 2026

Copy link
Copy Markdown
Member

it can still disappear, as long as its absolutely sized and not in a layout it wont reserve space.

@UncleJ4ck

UncleJ4ck commented Jun 4, 2026

Copy link
Copy Markdown
Contributor Author

yep that's how it's set up. the strip is HT_POSITION_ABSOLUTE anchored to the right/bottom edge, content sits in a separate inner layer at full size, so the bar overlays it and reserves no space. and it's removed entirely when there's nothing to scroll, so it disappears when not needed.

@vaxerski

vaxerski commented Jun 5, 2026

Copy link
Copy Markdown
Member

can you add a scroll area to the controls test? You could put the entire thing in a vertical scroll area for testing

@UncleJ4ck UncleJ4ck force-pushed the feat-scrollarea-scrollbar branch from 8829ccf to f083826 Compare June 7, 2026 14:41
@UncleJ4ck

Copy link
Copy Markdown
Contributor Author

done. the controls test already had everything in a vertical scroll area, so i turned the bar on there. it shows when the controls overflow the window and hides when they fit, and you can drag it.

@vaxerski

vaxerski commented Jun 8, 2026

Copy link
Copy Markdown
Member

very jittery when scrolling down continuously, constantly jitters and snaps up and down.

@UncleJ4ck UncleJ4ck force-pushed the feat-scrollarea-scrollbar branch from f083826 to 4ef0359 Compare June 10, 2026 14:15
@UncleJ4ck

Copy link
Copy Markdown
Contributor Author

good catch. the snap was the new inner content layer getting laid out twice per reposition: positionChildren(self) recurses through it and writes the content's natural height, then the grow pass overwrites that with the unconstrained height. maxScroll() measured the overflow live off whatever was currently in the content's box, so a wheel event landing while it was in the natural state read a smaller overflow and yanked the clamp down, then the next frame put it back. that back and forth was the jitter.

fix is to measure the overflow once per reposition while the content is in its grown state (recalcMaxScroll()) and have maxScroll() return the cached value, so the off-frame wheel/clamp path can't sample the transient box.

reproduced it under hyprland on the controls scroll area: max flipped 140 <-> 100 continuously while scrolling and the offset snapped with it, now it holds steady. added a regression test (scrollAreaMaxScrollIsStableAcrossContentRelayout) that fails without the cache. pushed to the same branch.

@vaxerski

Copy link
Copy Markdown
Member

Still here, less jittery, but bugged. FWIW, I am using continuous scroll for this (touchpad)

I scroll max down, and let go, then it snaps to the top. I start scrolling, it snaps to the bottom.

showScrollbar(true) puts a real scrollbar in the element tree, so it takes input:
drag the thumb or click the track to scroll, and the thumb brightens on hover.
content moves into an inner layer that scrolls while the bar stays on top.
@UncleJ4ck UncleJ4ck force-pushed the feat-scrollarea-scrollbar branch from 4ef0359 to 737cd58 Compare June 10, 2026 16:30
@UncleJ4ck

UncleJ4ck commented Jun 10, 2026

Copy link
Copy Markdown
Contributor Author

fixed. the scroll offset only lived in a one-shot pass over the content layer's children, so when a content element scheduled its own reflow the window relaid that layer with no offset and it jumped to the top while currentScroll stayed at the bottom. moved the offset onto the layer's own position (setAbsolutePosition) so any reposition keeps it scrolled. regression test added, pushed to the same branch.

@vaxerski

Copy link
Copy Markdown
Member

thanks. All good now. In the future, if you wanna work on it a bit more:

  • smooth scrolling for continuous scroll sources
  • scrollbar hiding (fading out) on no movement automatically
  • we seem to have a similar problem to the one in the polkit agent where text flickers between "hello" and "hel..." constantly in the spinbox.

@vaxerski vaxerski merged commit efbf51e into hyprwm:main Jun 12, 2026
2 checks passed
@UncleJ4ck UncleJ4ck deleted the feat-scrollarea-scrollbar branch June 12, 2026 14:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants