-
Notifications
You must be signed in to change notification settings - Fork 284
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
window pixel size #790
window pixel size #790
Conversation
im gonna make a release of winapi in a bit |
Just released the verision. You should be able to use it now without having to update the version, it was a path |
d4a81cb
to
de0e627
Compare
I have some issues/questions about this:
Meaning they can be set to zero by some terminals. I think the function should return Result<Option<(usize, usize)>>, which is None if these are zero (i.e. not set).
impl TerminalSize {
pub fn new() -> Result<Self>
/// Returns None if terminal size is zero.
pub fn new_non_zero() -> Result<Option<Self>>
pub fn size_cells(&self) -> (u32, u32)
pub fn size_pixels(&self) -> Option<(u32, u32) >
/// Not sure. This could also return an Option instead of zero sizes.
pub fn cell_sizes_in_pixels(&self) -> (u32, u32) {
if (self.x_pixels > self.columns)
&& (self.y_pixels > self.rows)
&& (self.columns != 0)
&& (self.rows != 0)
{
((self.x_pixels / self.columns), (self.y_pixels / self.rows))
} else {
(0, 0)
}
}
} |
@markus-bauer changing the return of |
@benjajaja Why? I don't think size would have to change. Perhaps the implementation, but not the interface. crossterm/src/terminal/sys/unix.rs Lines 42 to 43 in 1efdce7
You can still have separate functions for size, pixel_size (of the terminal), and cell_size_in_pixels/font_size. Point 4 was just about the new function. Whether you return zeros or Option/Result is a design decision. AFAIK, if a unix terminal is not reporting pixel size, ws_*pixel are zero. And a zero size terminal is impossible. Therefore it should/could be interpreted as None or Err. And with the last point, I wanted to say, that If the user want's to get both size and font_size, the unix backend would be doing the exact work twice. Therefore it should be possible to get both/all with one call. And the most obvious solution is to have a public interface on top of something like winsize. TLDR: |
@markus-bauer okay I changed it to |
I'm not sure about the windows side, but isn't this forcing additional syscalls and calculations on windows? Honestly, I don't know what the correct solution would be that satisfies both unix and windows. That's probably the reason why this wasn't added earlier. Perhaps @TimonPost can help you. As to your new code. There's an additional issue: |
@markus-bauer thanks for spotting that missing zero-check. Windows will always have to call the font-size syscall, as the terminal-size syscall doesn't return pixel sizes. It's not a problem since its |
@TimonPost BTW this is good to review now :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for working on this!
I am not sure If I understand if 'winsize.ws_xpixeland
winsize.ws_ypixel` are in physical pixels of the screen. The unix docs do state pixel height/width, whereas the windows docs state they are in 'in logical units':
Windows docs say:
A [COORD](https://learn.microsoft.com/en-us/windows/console/coord-str) structure that contains the width and height of each character in the font, in logical units. The X member contains the width, while the Y member contains the height.
The question I am having is wether we need to make this clear in the documentation if there is a difference here.
src/terminal.rs
Outdated
/// Returns the terminal size `[WindowSize]`. | ||
/// | ||
/// The width and height in pixels may not be reliably implemented and default to 0, as | ||
/// https://man7.org/linux/man-pages/man4/tty_ioctl.4.html documents them as "unused". |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As this is a public function please specify this applies for unix systems here.
I was also confused about that. The PR just assumed that these are the same. How could you verify that? @TimonPost Are you generally against target specific functions? Like In any case, at least on unix it's trivial to do this yourself, without crossterm, using libc or rustix (https://docs.rs/rustix/latest/rustix/termios/fn.tcgetwinsize.html). |
Good catch. I edited the comment so that it now mentions both uncertainties about unix & windows. But I don't think the windows implementation really matters, as the motivation here is to have control over drawing images with e.g. sixels and that is not implemented for any window terminal AFAIK. To be specific, I want this to work on https://github.com/tui-rs-revival/ratatui/, where the other "backends" are termion and termwiz, which both have a method to get the window pixel sizes.
Yes, but it would be somewhat sad having to do that, when there is already a syscall available for crossterm. |
Wouldn't this mean that the units of WindowSize are different depending on the os? Pixels on unix, logical units on windows. That's confusing. |
@markus-bauer yea you are right, I was ignorant about what "logical unit" means. |
@markus-bauer @TimonPost I am leaving |
Potential could do: physical_window_size Thats how winit defines their api's as well. Tho im fine with first doing it this way and not reusing the same api for different units. I can imagine that could result in confusion. |
It is possible to render images in terminals with protocols such as Sixel, iTerm2's, or Kitty's. For a basic sixel or iTerm2 image printing, it is sufficient to print some escape sequence with the data, e.g. cat image just works, the image is displayed and enough lines are scrolled. But for more sophisticated usage of images, such as TUIs, it is necessary to know exactly what area that image would cover, in terms of columns/rows of characters. Then it would be possible to e.g. resize the image to a size that fits a col/row area precisely, not overdraw the image area, accommodate layouts, etc. Thus, provide the window size in pixel width/height, in addition to cols/rows. The windows implementation always returns a "not implemented" error. The windows API exposes a font-size, but in logical units, not pixels. This could be further extended to expose either "logical window size", or "pixel font size" and "logical font size".
I would maybe expose something like |
* `sixel-bytes` encodes to `String` instead of file. * `serde` for `BackendType` for e.g. user configs. * `Send + Sync` for threads/tokio. * `rustix::termios` to get window/font size until ratatui/crossterm get `window_size()`: [`ratatui::Backend::window_size()`](ratatui/ratatui#276) needs [`crossterm::terminal::window_size()`](crossterm-rs/crossterm#790).
* `sixel-bytes` encodes to `String` instead of file. * `serde` for `BackendType` for e.g. user configs. * `Send + Sync` for threads/tokio. * `rustix::termios` to get window/font size until ratatui/crossterm get `window_size()`: [`ratatui::Backend::window_size()`](ratatui/ratatui#276) needs [`crossterm::terminal::window_size()`](crossterm-rs/crossterm#790).
* `sixel-bytes` encodes to `String` instead of file. * `serde` for `BackendType` for e.g. user configs. * `Send + Sync` for threads/tokio. * `rustix::termios` to get window/font size until ratatui/crossterm get `window_size()`: [`ratatui::Backend::window_size()`](ratatui/ratatui#276) needs [`crossterm::terminal::window_size()`](crossterm-rs/crossterm#790).
@TimonPost I think this could be merged, if I understood correctly. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally, I like to refrain from adding target-specific functions but we already have a few cases, and I do not really mind it that much as long it's clear from the docs that it doesn't work on windows. Current solution is good and allows us to eventually do something for windows of similar nature. Perhaps it should be hidden behind cfg(unix).
This was merged into main already? I wrote too much already, but there are some potential issues with the documentation: https://docs.rs/crossterm/latest/crossterm/terminal/fn.window_size.html.
|
It is possible to render images in terminals with protocols such as Sixel, iTerm2's, or Kitty's. For a basic sixel or iTerm2 image printing, it is sufficient to print some escape sequence with the data, e.g.
cat image
just works, the image is displayed and enough lines are scrolled.But for more sophisticated usage of images, such as TUIs, it is necessary to know exactly what area that image would cover, in terms of columns/rows of characters. Then it would be possible to e.g. resize the image to a size that fits a col/row area precisely, not overdraw the image area, accommodate layouts, etc.
Thus, provide the window size in pixel width/height, in addition to cols/rows.
(Screenshot is not up to date, I removed the call from the is_tty demo.