Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

ben-wes
Copy link
Contributor

@ben-wes ben-wes commented Jul 1, 2025

adds scrollwheel and touchpad interaction for sliders, numbox, float and list boxes.
currently only tested on macOS with touchpad and some logitech mouse with TclTk9.0.1 and TclTk8.6.16.

tested features:

  • proportional step sizes depending on ranges of sliders and float/list boxes (if range is limited)

  • adapts to logarithmic scale

  • uses vertical direction (also for horizontal sliders - not most intuitive with touchpad, but makes sense with mouse wheel)

  • interaction only possible in run mode (otherwise scrolls canvas)

  • closes Using scrolling to adjust sliders and number boxes #2561

demo showing all supported objects with TclTk9:

2025-07-02.11-39-45.mp4

known issues:

  • might be nice to support horizontal touchpad interaction for hsl.
  • if you interact with a float in a list gatom and its width changes, you might accidentally interact with another float since there's no interaction state (like for dragging), but only single events. i wouldn't know how to change this ...
  • similarly, when you're in run mode and scroll the canvas, the wheel event will be caught as soon as there's an object behind the mouse pointer. unless we manage some state here, this is expected as well.

@ben-wes ben-wes force-pushed the feat/scrollwheel-sliders branch 2 times, most recently from fff5712 to c9344ab Compare July 1, 2025 23:14
@Spacechild1

This comment was marked as outdated.

@Spacechild1
Copy link
Contributor

Awesome! Long overdue!

Some things I've noticed:

  1. the scroll direction should likely be configurable. It also should be consistent between canvas scrolling and number scrolling. For me, the natural scrolling direction for increasing a value would upwards whereas you have currently hardcoded it the other way. This is even more confusing because the canvas scrolling still works as expected (wheel up -> scroll up). Are there different platform defaults/expectations on Windows, Linux and macOS?

  2. Similarly, I would expect to scroll up to move a slider to the right. This is how volume and transport sliders work on all my media apps here on Windows. Either way, horizontal scrolling should follow the logic of vertical scrolling (up -> increase VS up -> decrease).

  3. I would use the small step by default and use a modifier for a large step. Also, 0.01 seems to be a rather small (default) multiplier.

similarly, when you're in run mode and scroll the canvas, the wheel event will be caught as soon as there's an object behind the mouse pointer. unless we manage some state here, this is expected as well.

This is a big problem and it would make scrolling almost unusable for me.

Solution Nr. 1: scrolling individual widgets always requires a keyboard modifier. This means we'd need to press, say, Cmd/Ctrl for "normal" scrolling. "fine" scrolling already uses "Shift", which is already used for horizontal canvas scrolling, so this would have to be "Cmd+Shift".

Solutions Nr. 2: only scroll if the element has the focus. Disadvantage: you first have to click on the object before you can scroll it. Also, objects like sliders don't have a notion of focus (yet).

Any ideas for other solutions?

proportional step sizes depending on ranges of sliders and float/list boxes (if range is limited)

Personally, I'm not a too big fan of this. IMO it would be better if we could explicitly set the step size (large and small step) as part of the GUI properties.

Also, is there a particular reason why you're doing this for sliders and gatoms, but not for IEM numberboxes? They are all just different representations of the same thing. I can somehow see why it makes sense for sliders (because of the linear graphical representation) but not so much for gatoms.

That being said, I can imagine the proportional step size being a useful default mechanism in case the user do not resp. cannot specify the step size. I just don't think that (x->a_draghi - x->a_draglo) / 127.0 is good formula. What about <next power of 10 of the high limit> * 0.1:

Range Next power of 10 (Large) step size
0 - 0.05 0.1 0.01
0 - 1 1 0.1
1 - 8 10 1
1 - 80 100 10

Side note: In the future we might also support stepping values with the keyboard (which IMO is also long overdue). In that case, the scroll wheel and arrow keys are just two ways of doing the same thing.

Another side note: Qt has a really nice option that is called "adaptive decimal step". The idea is that the step size depends on the number of decimals of the current value. Examples: 1 -> 1.1, 10 -> 11, 100 -> 110, etc. See https://doc.qt.io/qt-6/qdoublespinbox.html#setStepType. Just something to keep in our minds as a (future) option.

if you interact with a float in a list gatom and its width changes, you might accidentally interact with another float since there's no interaction state (like for dragging),

TIL that you can drag individual items in a list atom! 😮 I would have never expected this.

@ben-wes
Copy link
Contributor Author

ben-wes commented Jul 2, 2025

@Spacechild1 thanks a lot for the feedback on this!

Are there different platform defaults/expectations on Windows, Linux and macOS?

coming from Windows, i was quite irritated about the inverted scrollwheel direction on macOS first, but got used to it. for the sliders and number boxes, it felt natural to me that an upward movement also rises the value. i guess, i'll need test with more systems to be sure it is consistent. seems like this needs OS specific handling (since your expectation about the slider interaction is similar to mine). and it certainly makes sense to make it configurable!

horizontal scrolling should follow the logic of vertical scrolling

so right -> higher, i guess? that might become a bit complicated with tcltk8. i'll need to look into this more - but it seemed to me like tcltk8 is sending shift+scroll for right swipe, which collides with the fine grained control

I would use the small step by default and use a modifier for a large step. Also, 0.01 seems to be a rather small (default) multiplier.

i also wasn't sure about the 0.01. maybe 0.1 is enough. but do we really want to invert the logic here compared to the drag interaction with sliders and number boxes?

Solution Nr. 1: scrolling individual widgets always requires a keyboard modifier.

i hadn't thought of this! sounds like a good option to avoid unexpected behaviour if the user's intent is to just scroll in run mode (as learnt with previous versions). i'm a bit hesitant though since i also like the mouse-only interaction with objects in run mode (thinking of performance setups for example).

checked some random web demo for mousewheel/slider interaction now that seems to work with a timeout for the element interaction. if i continuously scroll up down there with the cursor passing the slider, it keeps scrolling. only if i stop scrolling (or move the mouse), it switches to slider interaction afterwards. for (macbook) touchpad, it seems to be handled in an even more dedicated way and check the 2-finger touch. not sure if this is applicable in our context. timeout might certainly be an option - but obviously also add complexity.
https://owlcarousel2.github.io/OwlCarousel2/demos/mousewheel.html

Solutions Nr. 2: only scroll if the element has the focus. Disadvantage: you first have to click on the object before you can scroll it. Also, objects like sliders don't have a notion of focus (yet).

i thought about this, too. we'll probably need it in some way for keyboard interaction anyway, right? and there should be a visual feedback as well then ... i'm not sure if i'll manage to handle all of that though.

why you're doing this for sliders and gatoms, but not for IEM numberboxes

i mainly didn't like the check for the rather arbitrary default "unlimited" limit of -1e+37..1e+37. so i decided to always treat it as unlimited. also remembered the help info stating "As of Pd 0.52, the plan is to stop supporting this object in favor of the atom number box". but true - would be good anyway to have it behave consistently.

What about <next power of 10 of the high limit> * 0.1:

sounds good to me!

TIL that you can drag individual items in a list atom! 😮 I would have never expected this.

wait until you can use these to dynamically create a multichannel signal! :)

besides those points, i'm currently not completely sure about the event path:

  1. wheel handler in gui, sending message to pd
  2. hitbox check and object handling in pd
  3. otherwise message back to gui for canvas scroll handling

... does that seem right?

i'm also considering to get rid of the duplicate xy unpacking (once in tcl for canvas scroll and once in c for objects). might be better if the wheel messages were directly created with a deltax and deltay. any thoughts on this?

@Spacechild1
Copy link
Contributor

so right -> higher, i guess? that might become a bit complicated with tcltk8. i'll need to look into this more - but it seemed to me like tcltk8 is sending shift+scroll for right swipe, which collides with the fine grained control

With horizontal scrolling I meant scrolling horizontal widgets, like HSliders, not actual horizontal scrolling. Sorry for the confusion! I meant that horizontal widgets should logically behave the same as vertical widgets.

but do we really want to invert the logic here compared to the drag interaction with sliders and number boxes?

Good point! I didn't think of that. So now I know where the 0.01 multiplier comes from. And from that perspective it also makes sense that the Shift-modifier activates the smaller step size.

if i continuously scroll up down there with the cursor passing the slider, it keeps scrolling. only if i stop scrolling (or move the mouse), it switches to slider interaction afterwards.

I would still find this potentially annoying. I don't always scroll continuously. If I scroll through a patch, I would often stop to look at something. If the mouse happens to be over a slider, I would have to move the mouse to continue scrolling. Even worse: I might not notice and accidentally change the slider value.

Solutions Nr. 2: only scroll if the element has the focus. Disadvantage: you first have to click on the object before you can scroll it. Also, objects like sliders don't have a notion of focus (yet).

i thought about this, too. we'll probably need it in some way for keyboard interaction anyway, right?

That's what I was thinking, yes.

and there should be a visual feedback as well then ...

Definitely. This would be important for keyboard navigation.

i'm not sure if i'll manage to handle all of that though.

I can understand that. However, scroll wheel support should always be designed with keyboard navigation in mind because it's really two sides of the same picture.

  1. wheel handler in gui, sending message to pd
  2. hitbox check and object handling in pd
  3. otherwise message back to gui for canvas scroll handling

... does that seem right?

Looks right to me!

@porres
Copy link
Contributor

porres commented Jul 2, 2025

Solutions Nr. 2: only scroll if the element has the focus. Disadvantage: you first have to click on the object before you can scroll it. Also, objects like sliders don't have a notion of focus (yet).

That's my preferred idea. Something I've been looking into for [else/knob].

I agree sliders should be able to show us they have focus, like number boxes. Arguably radio buttons as well

By the way, [else/knob] can be either activated by a click or an "active" message input as well.

@ben-wes ben-wes force-pushed the feat/scrollwheel-sliders branch from 05e6e6a to d897104 Compare July 3, 2025 17:11
@ben-wes ben-wes requested a review from Spacechild1 July 3, 2025 17:15
@ben-wes ben-wes force-pushed the feat/scrollwheel-sliders branch from d897104 to 7c26827 Compare July 3, 2025 17:16
@ben-wes
Copy link
Contributor Author

ben-wes commented Jul 3, 2025

the current version should fix the unexpected scroll wheel inversion for value manipulation on non-macos systems. i had a preference added for this, but decided to remove it again with the last commit.

it now also works for GOP objects which wasn't the case before.

focus handling is not part of this yet. neither is the adaption of steps to powers of 10 (i'll gladly give both a try though). more considerations on these though:

I just don't think that (x->a_draghi - x->a_draglo) / 127.0 is good formula.

the reasoning here was that it makes sense for the default range of sliders. so it's not completely arbitrary. i don't say this is good - but just wanted to go sure that it's clear where this came from.

another thought on how the object interaction interferes with canvas scrolling: while the handling of an active state is certainly an option, i'm still not sure whether it's good to require an additional interaction (click) prior to the scroll wheel interaction for each manipulation of values. after all, smooth scrolling is possible in edit mode. but i also admit that it's annoying to scroll in run mode and i guess we can't have both. :)

btw: touchpad interaction feels a lot more natural with tcl/tk 9.

@ben-wes ben-wes force-pushed the feat/scrollwheel-sliders branch from 7c26827 to b27e34f Compare July 3, 2025 19:41
remove intermediate delta variables
@ben-wes
Copy link
Contributor Author

ben-wes commented Jul 4, 2025

scroll wheel support should always be designed with keyboard navigation in mind because it's really two sides of the same picture.

another consideration: (future) keyboard interaction should probably be possible for the active object regardless of the mouse position? i wonder if the same should be true then for mouse wheel interaction? that would mean that canvas scrolling is no more possible while an object is active. i don't say this is bad - but is that the expectation?

@porres
Copy link
Contributor

porres commented Jul 4, 2025

That's my preferred idea. Something I've been looking into for [else/knob].

For the record. I just implemented mouse wheel scrolling into [knob]. It just listens to mouse info and works if the object is active/clicked. Seems like a good mechanism to me. The only issue is that even so, other canvas interactions still happen so you can scroll things up and down. I never have messy patches like that, but not anyone is nice and clean like me.

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.

Using scrolling to adjust sliders and number boxes
3 participants