rprichard / winpty

A Windows software package providing an interface similar to a Unix pty-master for communicating with Windows console programs.
MIT License
1.29k stars 167 forks source link

Having trouble sending scroll events to vim or less #128

Open gurinderhans opened 7 years ago

gurinderhans commented 7 years ago

I'm having trouble getting vim or less inside WSL to scroll. I'm using the winpty.dll with a wrapper application that sends codes such as \[M<buttonChar><xChar><yChar>.

buttonChar is 32 + (64 or 65) depending on scroll direction and xChar and yChar are mouse coordinates, but the codes seem to be ignored by winpty server and nothing happens...

* Please let me know if I didn't explain anything properly or skipped information.

gurinderhans commented 7 years ago

Could this possibly be related? https://github.com/rprichard/winpty/issues/96

rprichard commented 7 years ago

I don't think they're related?

I think the important idea here is a VT/100 terminal's "alternate screen". A terminal's alternate screen has no scrollback, and IIRC, terminals typically convert mouse wheel scrolling into a number of up/down keypresses.

IIRC, winpty never puts a terminal into alternate screen mode. It does enable a terminal's mouse input if the console's QuickEdit mode flag is disabled. I don't think WSL ever turns QuickEdit off, and in any case, you don't want the terminal's mouse mode enabled for less, because then you wouldn't be able to select text.

winpty already detects when a console buffer is resized to the window size and enters a "direct" scraping mode. Maybe it could then activate the alternate screen.

I wonder whether a terminal's alternate screen mode interacts with its mouse input setting at all.

It could be interesting to look at a program like htop in WSL. On Linux, htop enables the terminal's mouse mode, so I can click a process' row to select it. The scroll wheel doesn't do anything. With winpty+WSL, I wouldn't expect a mouse click to change the selected row, and instead I'd be able to select text. If winpty were to then put the terminal into alternate screen mode, the scroll wheel would presumably move htop's selection.

gurinderhans commented 7 years ago

Hey thanks for responding!

I'm trying to find out how the default "Bash on Ubuntu on Windows" does this however. For example if I enter vim and enable mouse mode by set mouse=a, it allows me to scroll the page using the mouse wheel, I can even click around the page and move the cursor to where I clicked.

Now, it also doesn't seem to be converting the scroll events into up/down keys, I can confirm this by looking at the cursor position, during mouse wheel scroll vs pressing arrow keys, the cursor is on the opposite sides (ie. top/bottom).

iTerm2 does this here (https://github.com/gnachman/iTerm2/blob/469d65f3e1521504b96d707c0f272eb285589ca2/sources/VT100Output.m#L451) and I wonder if winpty or another terminal on windows can do the same.

Would you know how this functionality can be achieved?

gurinderhans commented 7 years ago

Hmm, I was going through the source code and saw this (https://github.com/rprichard/winpty/blob/master/src/agent/ConsoleInput.cc#L526), clearly there's support for mouse events, but it doesn't seem to be working for some reason?

rprichard commented 7 years ago

That code converts a terminal scroll wheel escape into a console mouse event record.

The terminal will only generate a scroll wheel escape if a terminal program (such as winpty or vim) has enabled its mouse input. winpty probably isn't enabling the terminal's mouse mode, because the underlying console's QuickEdit flag is probably still on. See here: https://github.com/rprichard/winpty/blob/ce9239af5d751195ea6982a41c7d71356ac9201c/src/agent/Terminal.cc#L510-L527

Once the terminal's mouse input mode is enabled (even with just flag 1000), mouse clicks (including scroll wheel "clicks") no longer affect text selection or scrollback. Because it prevents selection, it would be wrong to enable them for less.

If these modes aren't enabled, then winpty can't detect use of the scroll wheel.

Nonetheless, if winpty did notice scroll wheel clicks, it would write them to the console with WriteConsoleInput. I don't know what happens if winpty-agent uses WriteConsoleInput to write mouse events to a console with WSL processes attached. Maybe WSL converts the mouse input to something WSL-appropriate, but maybe not? My guess is that it doesn't, but maybe it would? (I suppose I should test it sometime.) This issue is analogous: https://github.com/Microsoft/BashOnWindows/issues/111.

As a "workaround" of the above BashOnWindows issue, winpty generates VT/100 input escapes when ENABLE_VIRTUAL_TERMINAL_INPUT is enabled, and WSL does enable that flag. Maybe winpty could generate the mouse escapes that vim's mouse=a wants, but it'd be hard to configure because winpty won't know which of the 10xx mouse mode flags that WSL vim enabled. Presumably, you'd need to tell winpty which mouse encoding vim wants.

You could try winpty's --mouse option, which forces winpty to enable terminal mouse input. If nothing else, it should demonstrate that text selection in less stops working.

I wasn't aware of vim's set mouse=a config setting. With that flag, vim enables 10xx mouse modes in the terminal and then handles mouse escapes. I don't think less works this way.

rprichard commented 7 years ago

It would be interesting to see whether WSL mouse input works with ConEmu. This issue suggests that it doesn't: https://github.com/Maximus5/ConEmu/issues/1114.

gurinderhans commented 7 years ago

Yep, can personally confirm that vim scrolling inside ConEmu does not work.

gurinderhans commented 7 years ago

Also calling winpty_config_set_mouse_mode(agentCfg, WINPTY_MOUSE_MODE_FORCE); has no effect. Tried the other modes as well.

gurinderhans commented 7 years ago

so, I noticed I can type echo -e "\e[?1049h" and echo -e "\e[?1049l", enter / exit alternate terminal screen mode. I also found that vim/less scroll works by sending Ctrl + E & Ctrl + Y moving the page up/down.

However, I can't find a way to figure out whether winpty sends a code to let the terminal know whether it enters this alternate screen mode when launching vim/less for example.

maxhora commented 5 years ago

That seems still the issue. WinPTY seems doesn't propagate forward CSI to enter/exit alternative screen mode. @rprichard could you please advice if WinPTY can has such issue? For example, Xterm.JS expects receiving of 1049h CSI to know that terminal session was switched to ALT buffer and mouse mode logic also depends on knowing of the terminal buffer mode.