crossterm-rs / crossterm

Cross platform terminal library rust
MIT License
3.17k stars 273 forks source link

Support Pixel Coordinates in Mouse Events #873

Open bbb651 opened 5 months ago

bbb651 commented 5 months ago

Is your feature request related to a problem? Please describe. Some terminals offer the ability to report pixel coordinates of mouse events along with the character coordinate. I want to make a UI based on the kitty image protocol (also blocked by #834) where pixel coordinates of events are important.

Describe the solution you'd like I would like crossterm to provide access to these modes and add the pixel coordinates to MouseEvent.

Describe alternatives you've considered if any

Additional context I found this website describing the SGR-Pixels (1016) mode.

bbb651 commented 5 months ago

I just realized Event::Resize is also missing pixel sizes (there's a variety of xterm sequences for that, also there's TIOCGWINSZ with the ioctl syscall and SIGWINCH signal on unix). Are these not implemented due platform support? Also is this library for/against implementing image protocols such as the kitty image protocol, iTerm image protocol, sixel, etc? (they are relatively niche in terms of usage and platform support, and are relatively complex and require a cargo feature to avoid image crate dependencies, but I feel like there's a gap in the rust ecosystem for high level terminal image handling).

bogzbonny commented 1 month ago

bump! I would find this useful for the same reason. Basic image interaction in the terminal is an inhibiting feature for making some of my applications fully terminal based

joshka commented 1 week ago

Rather than bumping consider doing the work to work out / design how something like this should be implemented.

Some constraints to keep in mind would be:

Regarding image proto stuff, have you considered using ratatui and ratatui-image? I know that this goes one step further than just raw crossterm, but if your goal is writing working software then this might be a valid approach for your problem.

bogzbonny commented 1 week ago

Yeah I spent a bunch of time going through SGR-Pixels (1016)... the best that I could make out is that, to simply switch to 1016 would replace character positions altogether with pixel positions, making that an optional feature I think would be actually pretty straight-forward however not nearly as useful as having both pixel and character positions (IMO, thoughts?).

Considering that some terminals may not support pixels mouse responses, I imagine that it makes sense to add this under a feature flag (wezterm does, ref). One open question I haven't been able to figure out is - how to get the the height/width of a character from the console to then be able to back calculate the character positions from the pixel dimensions (as to be able to provide pixel and character coordinates). Once this is figured out, everything else seems pretty straight forward. Also I suppose the MouseEvent type would be modified and have a couple extra fields (for pixel coordinates) with this feature flag on.

One more complication which I just thought of is if it would be required to somehow query the terminal for pixel compatibility and only provide the character output if pixel output is not available (even with the feature-flag on).

More relevant discussions: https://github.com/dankamongmen/notcurses/issues/2326


edit: from that same document bbb651 posted, cells in pixels are CSI 16 t aka echo -e "\e[16t"

bogzbonny commented 1 week ago

@joshka btw implementing kitty image protocol from scratch isn't that difficult (I don't know about sixels though, I haven't tried), the need for supporting cursor location in pixels is so that one could hypothetically interact with an image while in the terminal - this logic is much more coupled with the inner workings of crossterm

joshka commented 5 days ago

One open question I haven't been able to figure out is - how to get the the height/width of a character from the console to then be able to back calculate the character positions from the pixel dimensions (as to be able to provide pixel and character coordinates). Once this is figured out, everything else seems pretty straight forward. Also I suppose the MouseEvent type would be modified and have a couple extra fields (for pixel coordinates) with this feature flag on.

That part should be simple. Call terminal::window_size() then divide width by columns, height by rows.