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

Add support for scroll wheels #345

Open
jeffwright13 opened this issue Feb 11, 2022 · 1 comment
Open

Add support for scroll wheels #345

jeffwright13 opened this issue Feb 11, 2022 · 1 comment

Comments

@jeffwright13
Copy link

As per our conversation 2022-02-06 at https://gitter.im/asciimatics/Lobby, I am requesting scrollwheel support in Asciimatics.

Main technical thrust: Modify Screen to recognize scrollwheel events and handle it in the Frame

I will begin work on this soon and submit a PR when I get it working.

=======================

Jeff Wright
@jeffwright13
Feb 06 06:35
@peterbrittain - is there a way to modify the scrolling behavior? When I use the scroll wheel on my mouse, it seems to want to scroll an entire page at a time, instead of what I have come to expect in a normal GUI: N lines at a time. The result is a very jumpy experience. I didn't see anything in the docs about configuring scroll behavior.
peterbrittain
@peterbrittain
Feb 06 06:46
That's because asciimatics doesn't support scroll wheels (due to patchy support in Linux). I suspect what you're seeing is the terminal intercepting the event and scrolling the whole buffer.
You'll be able to tell if this is the case, because asciimatics will still only draw on the original screen that was visible when you started the app.
Jeff Wright
@jeffwright13
Feb 06 06:55
So nothing to be done then?
peterbrittain
@peterbrittain
Feb 06 07:08
Mouse support has improved in ncurses 6. Do you know what version your system uses? We'd also need to see if there is a setting on your terminal to force it to pass the input to the running app (instead of consuming it itself).
Jeff Wright
@jeffwright13
Feb 06 07:14

I am running (currently) on a Macbook Pro (2019/Intel). Latest version of OSX. I usually run Pytest (and hence Asciimatics) out of iTerm2, although sometimes also from my IDE (VSCode, with Integrated Terminal). My shell is latest zsh.

$ tic -V
ncurses 5.7.20081102

BUT:

$ brew upgrade ncurses
Running brew update --preinstall...
==> Auto-updated Homebrew!
Updated 2 taps (homebrew/core and homebrew/cask).
==> Updated Formulae
Updated 84 formulae.
==> Updated Casks
Updated 36 casks.

Warning: ncurses 6.3 already installed

peterbrittain
@peterbrittain
Feb 06 08:02
Ok... with a newer version of ncurses, you then need to enable scroll wheel reporting. Looks like there's a setting in iterm2: https://iterm2.com/documentation-preferences-profiles-terminal.html
Finally, we'd need to tweak asciimatics Screen to recognize the events and handle it in the Frame.
All pretty self-contained changes, so I can explain them to you if you're up for submitting a PR.
Jeff Wright
@jeffwright13
Feb 06 09:16
Screen Shot 2022-02-06 at 9.16.13 AM.png
Screen Shot 2022-02-06 at 9.16.38 AM.png
Looks like I already had that setting enabled ("Enable mouse reporting")
Sure, I could submit a PR. Would need some guidance on where in the code to make changes.
peterbrittain
@peterbrittain
Feb 06 14:57
Ok... There are 2 basic changes. First is to _CursesScreen.get_event(). There's already logic to handle other buttons in there. We just need to find what events fire when you scroll the mouse wheel. You could either add some logging to the function, or use something like this: https://stackoverflow.com/questions/11893034/mouse-wheel-in-python-curses.
According to the curses maintainer, it should look like mouse buttons 4 and 5. See https://stackoverflow.com/questions/42356352/mouse-scroll-up-ncurses-c
Once you have those events translated into equivalent asciimatics MouseEvents, you just need to act on them in the scrollbar. That's in scrollbar.py. simply get the current position and add/subtract a percentage to the position on the relevant button.
Jeff Wright
@jeffwright13
Feb 06 20:54

I made the following changes to screen.py.

                # Some Linux modes only report clicks, so check for any
                # button down or click events.
                if (bstate & curses.BUTTON1_PRESSED != 0 or
                        bstate & curses.BUTTON1_CLICKED != 0):
                    buttons |= MouseEvent.LEFT_CLICK
                if (bstate & curses.BUTTON3_PRESSED != 0 or
                        bstate & curses.BUTTON3_CLICKED != 0):
                    buttons |= MouseEvent.RIGHT_CLICK
                if bstate & curses.BUTTON1_DOUBLE_CLICKED != 0:
                    buttons |= MouseEvent.DOUBLE_CLICK
                if bstate & curses.BUTTON4_PRESSED != 0:
                    print("BUTTON4_PRESSED")
                if bstate & curses.BUTTON5_PRESSED != 0:
                    print("BUTTON5_PRESSED")
                if bstate & curses.BUTTON4_CLICKED != 0:
                    print("BUTTON4_CLICKED")
                if bstate & curses.BUTTON5_CLICKED != 0:
                    print("BUTTON5_CLICKED")
                return MouseEvent(x, y, buttons)

This resulted in an exception when the scroll wheel was rolled:

Traceback (most recent call last):
File "/Users/jwr003/coding/pytest-fold/pytest_fold/tui.py", line 186, in
main()
File "/Users/jwr003/coding/pytest-fold/pytest_fold/tui.py", line 179, in main
Screen.wrapper(demo, catch_interrupt=True, arguments=[last_scene])
File "/Users/jwr003/coding/pytest-fold/venv/lib/python3.9/site-packages/asciimatics/screen.py", line 1393, in wrapper
return func(screen, *arguments)
File "/Users/jwr003/coding/pytest-fold/pytest_fold/tui.py", line 166, in demo
screen.play(
File "/Users/jwr003/coding/pytest-fold/venv/lib/python3.9/site-packages/asciimatics/screen.py", line 1566, in play
self.draw_next_frame(repeat=repeat)
File "/Users/jwr003/coding/pytest-fold/venv/lib/python3.9/site-packages/asciimatics/screen.py", line 1649, in draw_next_frame
event = self.get_event()
File "/Users/jwr003/coding/pytest-fold/venv/lib/python3.9/site-packages/asciimatics/screen.py", line 2494, in get_event
if bstate & curses.BUTTON5_PRESSED != 0:
AttributeError: module 'curses' has no attribute 'BUTTON5_PRESSED'

I am on a Mac. I saw the following comment in _curses.py:

# Darwin ncurses doesn't provide BUTTON5_* constants

Maybe that's the issue with the crash above.
peterbrittain
@peterbrittain
Feb 07 00:58
Yeah - I wondered if we'd start hitting issue like this. We can create the constants ourselves if needed. For now, I suggest you just log the bstate in hex and compare it to https://github.com/mirror/ncurses/blob/d30f99439fcc8d4bb4c38e5c4afb4f6555fc6ad4/include/curses.tail
Note that print doesn't work in alternate screens (like asciimatics uses). Also, if you don't like doing the bit maths, you can probably use this definition instead: https://github.com/mattn/pdcurses/blob/master/curses.h
Jeff Wright
@jeffwright13
Feb 07 11:14
The print was meant for initial diagnosis to see what button the system registered when I scrolled. Definitely will remove before issuing a PR!
peterbrittain
@peterbrittain
Feb 07 11:57
:-)

@peterbrittain
Copy link
Owner

That would be a cool addition. Looking forwards to the PR... Feel free to reach out on gitter if you need more help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants