Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scroll speedup #629

Merged

Conversation

tangledhelix
Copy link
Collaborator

@tangledhelix tangledhelix commented Dec 31, 2024

Adjust scrolling speed during a drag-select operation based on how far outside the window we've moved.

For column-select mode, this affects all platforms. For linear select mode, it's only relevant on Mac.

Initial attempt:

  • For vertical scrolling:
    • Moving outside the boundary triggers a scroll operation every 500ms
    • Moving at least 20 pixels beyond the boundary accelerates to 250ms
    • Moving at least 40 pixels beyond the boundary accelerates to 125ms
  • For horizontal scrolling, the delay is cut in half, so 250, 125, and 62ms.

Edited to add:

Later this was changed to use a formula to scroll between 100-500ms (or 66-333ms for horizontal) depending on how far outside the viewport the mouse has moved.

This PoC will print debug info on output showing the current scroll speed (in ms) and how many pixels beyond the boundary the cursor is. Example output below (trimmed for brevity; the real output streams by quickly):

scroll=500 out of bounds 1 by 16
scroll=500 out of bounds 1 by 17
scroll=500 out of bounds 1 by 18
scroll=250 out of bounds 1 by 20
scroll=250 out of bounds 1 by 22

Aside from making sure scrolling continues to work properly, I'm soliciting feedback on the speed and how it ought to be adjusted.

@windymilla
Copy link
Collaborator

windymilla commented Jan 1, 2025

If I watch the line numbers on the left, I can see the changes of speed as I slowly move the cursor further out of the window, and the debug messages seem to confirm that.
An alternative would be to have a smoothly changing speed, something like
scroll_delay = int((250*20/out_of_bounds_distance)
to give similar speeds at the 20 and 40 pixel distances.
Or maybe a bigger number than 250 so that it's slower when you're nearby, but you can still build up a good speed by moving the cursor further out beyond 40 pixels.
I'd be happy with the stepped speed changes though if you think they are preferable.

@windymilla
Copy link
Collaborator

I hit a couple of problems almost certainly unrelated to this PR:

  1. If I start to do a normal select drag with the mouse, so the mouse button is held down, and then press the Alt key to switch to column select, I get an exception (see screenshot). This happened by mistake sometimes when I was pressing the Alt and mouse buttons almost simultaneously. I think this may only happen if its the first column select you do after starting the program - probably if you do a successful column select, the _autoscroll_active attribute has been set, so no exception. However, sometimes even on a later column select, if I pressed the Alt key after the mouse button, it showed the "switch back to normal select & scroll slowly" bug.
  2. When I had split screen, I had a couple odd things when I did column select in one window, then in the other (but not consistently). Sometimes it showed the "switch back to normal select & scroll slowly" bug (possibly a repeat of point 1 above). Sometimes, as I was dragging in the top window, which was apparently working, the bottom window started to scroll - not immediately, but after a while, and sometimes it only scrolled a bit, then stopped, with the correct scrolling still continuing in the top window.

image

@tangledhelix
Copy link
Collaborator Author

An alternative would be to have a smoothly changing speed, something like scroll_delay = int((250*20/out_of_bounds_distance) to give similar speeds at the 20 and 40 pixel distances.

I did something similar to this, but also capped the values. No faster than 50ms, no slower than 500ms.

@tangledhelix
Copy link
Collaborator Author

  1. If I start to do a normal select drag with the mouse, so the mouse button is held down, and then press the Alt key to switch to column select, I get an exception (see screenshot). This happened by mistake sometimes when I was pressing the Alt and mouse buttons almost simultaneously. I think this may only happen if its the first column select you do after starting the program - probably if you do a successful column select, the _autoscroll_active attribute has been set, so no exception. However, sometimes even on a later column select, if I pressed the Alt key after the mouse button, it showed the "switch back to normal select & scroll slowly" bug.

I couldn't reproduce this. The _autoscroll_active attribute should be initialized to False in __init__().

  1. When I had split screen, I had a couple odd things when I did column select in one window, then in the other (but not consistently). Sometimes it showed the "switch back to normal select & scroll slowly" bug (possibly a repeat of point 1 above). Sometimes, as I was dragging in the top window, which was apparently working, the bottom window started to scroll - not immediately, but after a while, and sometimes it only scrolled a bit, then stopped, with the correct scrolling still continuing in the top window.

I wasn't able to reproduce this. Maybe platform dependent?

@windymilla
Copy link
Collaborator

I couldn't reproduce this. The _autoscroll_active attribute should be initialized to False in __init__().

It is, but inside an is_mac() - but it gets queried on all platforms now, e.g. maintext.py:1588 in master

@windymilla
Copy link
Collaborator

  1. However, sometimes even on a later column select, if I pressed the Alt key after the mouse button, it showed the "switch back to normal select & scroll slowly" bug.

I couldn't reproduce this. The _autoscroll_active attribute should be initialized to False in __init__().

The last part of my point 1 is caused by the fact that when you start clicking and dragging, then LATER press the Alt key to switch it to column-mode, the method column_select_click is not called, so _autoscroll_active doesn't get set to True. I also notice that it doesn't set the cursor to tcross, which is a bug in my original implementation.

Not sure of the best way to re-organize. Essentially, we can't rely on Alt-click, because if you click then Alt, you don't get an Alt-click, hence the section in column_select_motion under the comment

        # Attempt to start up column selection if arriving here without a previous click
        # to start, e.g. user presses modifier key after beginning mouse-drag selection.

Adding

            self._autoscroll_active = True
            event.widget.config(cursor="tcross")

into that section does seem to fix the bug, but does involve duplicating a couple lines of code.

Copy link
Collaborator

@windymilla windymilla left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apart from commented out old code and debug print of course - all looks good to me.

Copy link
Member

@srjfoo srjfoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still very choppy on macOS for me -- the selection happens, but doesn't actually show on the screen unless I twitch the selection cursor, until I let up at end of selection. It's the same for both column select and default select. I don't know if that's fixable, but it's not a reason to hold up on the PR.

@tangledhelix
Copy link
Collaborator Author

Still very choppy on macOS for me -- the selection happens, but doesn't actually show on the screen unless I twitch the selection cursor, until I let up at end of selection. It's the same for both column select and default select. I don't know if that's fixable, but it's not a reason to hold up on the PR.

I agree, but I can't see a way to fix it. While I can control how often the scroll routine is called (to speed up as you move further outside the window), I'm already scrolling the minimum distance of 1 unit, and scrolling more than that in one step would surely make it choppier? I'm not sure Tk can do it more elegantly than this, or in any case I have no ideas how to improve it. We could keep tinkering with the speed of the callback running...

When dragging to select text and crossing the view's edge, scroll slowly at first, and increasingly faster the further from the edge the mouse is moved. Impose a min/max on this speed to not get out of control (and not scroll too slowly either).
@tangledhelix tangledhelix marked this pull request as ready for review January 4, 2025 05:17
@tangledhelix
Copy link
Collaborator Author

Hm, wasn't thinking when I re-requested review. You both approved already.

Rebased, squashed, tidied up debug prints, made CI happy...

Copy link
Member

@srjfoo srjfoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for formality's sake.

For what it's worth, I figured that we were stuck with the choppiness (or at least that I was), I just wanted to mention it in case there was something obvious that might make it smoother. 🤷‍♀️

@tangledhelix
Copy link
Collaborator Author

Just for formality's sake.

For what it's worth, I figured that we were stuck with the choppiness (or at least that I was), I just wanted to mention it in case there was something obvious that might make it smoother. 🤷‍♀️

I've played with .update() and .update_idletasks() and so on but still without jiggling the mouse it doesn't draw any differently.

@windymilla windymilla merged commit 4de52a3 into DistributedProofreaders:master Jan 4, 2025
1 check passed
@tangledhelix tangledhelix deleted the scroll-speedup branch January 4, 2025 19:58
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.

3 participants