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

Suggestion: ability for terminals to set their tab icon #1868

Open
Tracked by #13392
mikemaccana opened this issue Jul 8, 2019 · 16 comments
Open
Tracked by #13392

Suggestion: ability for terminals to set their tab icon #1868

mikemaccana opened this issue Jul 8, 2019 · 16 comments
Labels
Area-VT Virtual Terminal sequence support Help Wanted We encourage anyone to jump in on these. Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. Product-Terminal The new Windows Terminal.
Milestone

Comments

@mikemaccana
Copy link
Contributor

#1685 Summary of the new feature/enhancement

The terminal currently provides a way for shells to specify the title:

image

In the world of web apps, both title and icon can be specified.

image

It would be useful for shells to be able to specify an icon for their tab for the same reasons:

  • Sometimes visuals are more obvious than text. The node.js green gem, or the python logo, or some custom app icon all 'pop' visually more than the equivalent text does

  • Terminals can update their icon to indicate specific conditions (a bell should be used for serious differences, but this could be used for more subtle ones, eg, showing a tunnel icon for an ssh tunnel running, then a shell icon if it stops and returns to the prompt)

  • If we let terminals specify their title, why not let them specify their icon?

@mikemaccana mikemaccana added the Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. label Jul 8, 2019
@ghost ghost added Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting Needs-Tag-Fix Doesn't match tag requirements labels Jul 8, 2019
@zadjii-msft zadjii-msft added the Area-VT Virtual Terminal sequence support label Jul 8, 2019
@zadjii-msft
Copy link
Member

We'd need to invent our own VT sequence for this. I'd hope that there was a existing OSC sequence for this, but unfortunately I don't trust the ones that I found.
There are these that look close:

OSC Ps ; Pt ST            
            Ps = 0  -> Change Icon Name and Window Title to Pt.
            Ps = 1  -> Change Icon Name to Pt.
            Ps = I  ; c -> Set icon to file.  Sun shelltool, CDE dtterm.
                           The file is expected to be XPM format, and uses the same
                           search logic as the iconHint resource.
            Ps = l  ; c -> Set window title.  Sun shelltool, CDE dtterm.
            Ps = L  ; c -> Set icon label.  Sun shelltool, CDE dtterm.

However, I'm pretty sure those are used to set the icon of the shortcut to the application (in windows terms) or the title of the taskbar entry for the window. This thread seems relevant. Since those seem like different, pretty unix-specific cases, I don't really want to overload them with our own use case.

So we'd need to design our own sequence for setting the icon within the context of the application.

I'd also probably want to implement it as a push/pop, since a new app adding support for this might be called from an app that doesn't know about this sequence, and the new app would then taint its parent process's icon.

@zadjii-msft zadjii-msft added the Product-Terminal The new Windows Terminal. label Jul 8, 2019
@ghost ghost removed the Needs-Tag-Fix Doesn't match tag requirements label Jul 8, 2019
@zadjii-msft zadjii-msft added this to Spec Needed ❓ in Specification Tracker via automation Jul 8, 2019
@zadjii-msft zadjii-msft added this to the Terminal Backlog milestone Jul 8, 2019
@DHowett-MSFT
Copy link
Contributor

OSC I seems fine; in the general case there is no “shortcut to the application” in unixen, so it must be referring to the window icon.

I don’t think we need to engineer a push/pop for it, though, because there isn’t one for SGR DECCOLM DECSCUSR (and so on)

@zadjii-msft
Copy link
Member

@DHowett-MSFT Good point about the push/pop thing - maybe we just need a "restore to default" value too.

How about: WTSICO - Windows Terminal Set Icon

OSC Ps ; Pt ST            
            Ps = 10000  -> Change tab Icon to the file specified by absolute path in Pt. If Pt is omitted, restore the icon to its default value.

Anyone know if OSC 10000+ is taken by anything? @Jaykul @j4james may know.

@egmontkob
Copy link

egmontkob commented Jul 8, 2019

"icon name" is indeed a pretty misleading terminology; it should probably be called "icon title". It's the string shown next to the icon whenever the window is iconified. In traditional Unix desktops, a window can have two different titles: one shown when in normal state, and another when iconified. OSC 1 sets the latter, OSC 2 sets the former, while OSC 0 sets both. Icon title is an ancient concept not really existing in modern environments. For this reason, VTE (gnome-terminal) dropped support for the icon title (icon name) feature recently.

I'm not aware of any extension regarding a graphical icon, although the idea is nice and there should be one. However, I dislike the idea of referring to the file with its path, this by design cannot work (or can even lead to incorrect result) over ssh. The icon itself should be transmitted (which raises a bunch of new questions).

For push/pop: there's CSI 22t and CSI 23t although CSI ... t has a pretty bad design: any number from 24 means to resize to that many rows, that is, it cannot be extended to allocate new numbers for saving/restoring the icon. Maybe 22/23 could also save/restore them, although it's probably not a wise idea.

@j4james
Copy link
Collaborator

j4james commented Jul 9, 2019

Anyone know if OSC 10000+ is taken by anything?

I know mintty has one documented OSC above 10000 (77119), but I don't know of anyone using the 10xxx range specifically. I don't have that wide a knowledge of terminal implementations, though, so I couldn't say with any certainty.

@mikemaccana
Copy link
Contributor Author

It would be worth finding out if/how modern Unix desktops and macOS implement OSC I. Ideally software authors could use the same escape sequence everywhere, rather than separate ones for Windows/Mac/Linux etc.

@Jaykul
Copy link
Contributor

Jaykul commented Jul 11, 2019

Right now we've implemented 0, 1, and 2 all the same way (based on xterm's implementation of Tektronix 4014 mode)

There's no purpose in doing it that way. Windows doesn't support the "icon title" notion, so I've been meaning to write up an issue asking permission to change it.

I was going to ask if we can change it to:

  • 0 - window title
  • 1 - icon uri
  • 2 - tab title (may also set the window title, depending on configuration)

If we do that, then the natural thing would be to implement CSI 22 and 23 as enhancements to that, riffing on xterm's implementation:

    Ps = 2 2 ; 0  -> Save window title on stack.
    Ps = 2 2 ; 1  -> Save icon uri on stack.
    Ps = 2 2 ; 2  -> Save tab title on stack.
    Ps = 2 3 ; 0  -> Restore window title from stack.
    Ps = 2 3 ; 1  -> Restore icon uri from stack.
    Ps = 2 3 ; 2  -> Restore tab title from stack.

I think using xterm's icon "title" for the icon uri is pretty safe:

  • We're not exactly pretending to be xterm-compatible anyway
  • I can't imagine anyone's setting the icon title separately these days (I know DisplayFusion has an icon mode for apps, but does this actually exist in any mainstream desktops these days?)
  • If we treat it as a uri, and fail to change when we can't resolve it, then it won't matter if some app tries to set it -- and what we're doing now is wrong, because we're changing the (tab and) window title when the source of the message explicitly avoided doing that.

Oh, and regarding SSH, I think calling this a URI makes it acceptable. I don't want to try to implement transporting base64-encoded image formats in text 😉 and the icon already supports URIs as it is, and although file paths may be part of that, it also supports web URIs like https://www.powershellmagazine.com/wp-content/uploads/2011/11/pscowboy_icon_250x250.jpg as well as portable uri references like ms-appdata:///roaming/Powershell_av32.png and internal icon references like (the horribly named) ms-appx:///ProfileIcons/{574e775e-4f2a-5b96-ac1e-a2962a402336}.png

@DHowett-MSFT DHowett-MSFT added Help Wanted We encourage anyone to jump in on these. and removed Needs-Triage It's a new issue that the core contributor team needs to triage at the next triage meeting labels Jul 11, 2019
@egmontkob
Copy link

egmontkob commented Jul 12, 2019

0 - window title, 2 - tab title

I'm firmly against this idea, for multiple reasons.

One is that existing applications pretty randomly choose to emit OSC 0 or 2 (or 1+2) for changing the title, expecting to overwrite the previous one. This would no longer be the case, resulting in user-perceived broken behavior when an application fails to replace the previous one's title. If separating window and tab titles is desired (which I strongly doubt) then one of them needs to get a brand new escape sequence. There are plenty of free OSC numbers to choose from.

My other concern is: Is this really a desired possibility? Even if applications immediately adapted to the new semantics, would I want this as an app developer (how should I decide what to put where) and would I want this as a user? As a user, my expectation is the window to have the active tab's title (maybe with a fixed prefix or suffix such as "Windows Terminal"). Allowing apps to deviate from this would not help me in any way, but would totally confuse me. I don't think this pattern is seen elsewhere, e.g. documents, web pages etc. all have a single title which becomes the tab and window title (the latter only if this tab is focused, obviously). If a single title per document is good enough for the web, it should good enough for terminal emulation. Furthermore: Many terminals hide the tab bar if only a single tab is present, this would no longer be possible, or a potentially important piece of information (tab title) would be hidden then from the user. Yet furthermore: A natural consequence of introducing the concept of "window title" is the user request that they want to see all the tab's "window titles" at once because that would help them quickly locate the one they're looking for, that is, some implementations would sure override the semantics and make it another line of "tab title".

And, if a by-product of this "tab icon" feature request (the original issue here) is really to separate "window title" from "tab title", then why don't we also need a separate "window icon" and "tab icon"?

I think using xterm's icon "title" for the icon uri is pretty safe

I disagree. OSC 1 is sure still supported in some terminal emulators and still being emitted by some applications. Why conflict with them when there are thousands (if not billions or quintillions) of free OSC numbers to choose from?

I don't want to try to implement transporting base64-encoded image formats in text

I, on the other hand, don't want to see a protocol extension emerging that doesn't work across serial line, telnet, ssh, login on the console of a virtual machine, etc. Remember: Terminal emulation, by its very definition and its history, emulates a world where remote communication takes place. It's only a frequent special case nowadays when it runs locally and has access to the local file system.

I especially don't get the "try to" bits in your sentence, and I could even quote Yoda. base64 is not a heuristic experimental technology that you try and perhaps succeed, perhaps fail. If the decision is to go for base64 (as a technical necessity for embedding binary data), so be it, it's easily implementable, I see no problem with it.

@zadjii-msft
Copy link
Member

I concur, I'd be pretty strongly against using an existing sequence to do something specific to the Windows Terminal. While the icon name doesn't really mean anything to us, there are systems where it does do something specific.

Your point about the uri not working over network connections is a good point, I hadn't considered that. I kinda wanted to avoid having developers need to load the images and convert them to base64 themselves. Say you're writing some sort of shell script, you'd need another utility to be able to set the tab icon from your script. Though I'm having a hard time thinking of another possibility that'll work over a network.

@egmontkob
Copy link

I'd expect that extremely few applications want to have a dynamic image, and if they dynamically create it, base64'ing is pretty cheap compared to that. The vast majority of apps would display a fixed "favicon" which is an artwork shipped by the app. In that case, especially for shell scripts that don't get compiled, IMO inlining the already base64'd string in the script is a perfectly reasonable solution (and results in the best runtime performance).

@Jaykul
Copy link
Contributor

Jaykul commented Jul 15, 2019

Sure. There's already a standard for base64 images as data:URIs.
They don't work in the terminal right now...

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH4wUJBB8dQLnJ7QAAAlhJREFUOMulk02IjlEUx3/3Pvc+zzvveM07ZnxlSkNGsrHDhiaSZEFKSsJCKB/5iJISC7spE2lqWFCS1SxkIcrnylIWFhKSUIzBmI/n3nMsnvd536ydzV38z/n/z//cc+A/wwCsOfyIp5f7WXvkyVxjLMYmmMRhTQLWYROHMRaTeIwpMGMTfKVjzJRMG8+93TSjq/eeiBBiwEpANKAxRyWgEpDYeCWgMWCsw5YELqsdUxFUAjcOpMxqny6KY0RibBarBDRGVCIYHrUIXGW9SCvp+sE6nW2FGhpQiQ312MxJfNuwBVh/5lWvdZUmsPvKT36MB24cnUt7mhctS6ToMDZtSD753AJUqt1LSvUyedelr4yN59w83kNC/o/3kqTaufC7BVCVzSp5AcSGQozsGvhAxScM7pvP5FTLnkjEpe1jIycq4xbA2GRHy18kxsiyHs+d072AMnT3HS4p2i9n4LLaEIBbvW9khk387BKYnM7Zu24mO9d28Pr9KKeG3/AnT0Fa36ka8dV6QVBfsGKlasFey5Sh/fPo6fbcfviOW09+0d1Roy4BFfjwZQojEVDNx0c/bxsUnLF+lUrAErh9cgFjv6fYfv4F3ybauXpoMUt7qs21PXvtJc9efsdar12LFk/f2mswmy58vG8MG2IMdKa/+TQqpM6iEpiazgl5ObiczBmMgaw25/GDi8v7ARwSUzVEo8LoREaWlltmSb3DOwNiUXWN6zE6c3bfnuYCfvvyqr/e1Wesr5JWqyS+jcRnuAwSD96DrYBpXI1NYHiL0a0DE4ycaOO/4y9T/nYLtgWe7wAAAABJRU5ErkJggg==

Neither github nor Stack Exchange seem to allow them ... 😉
PowerShell Blue Icon

@mikemaccana
Copy link
Contributor Author

Say you're writing some sort of shell script, you'd need another utility to be able to set the tab icon from your script. Though I'm having a hard time thinking of another possibility that'll work over a network.

+1 base64. I think it'd be reasonable for pwsh or whatever shell to include a png (or whatever) to base64 tool.

@egmontkob
Copy link

I created a proof of concept favicon implementation for gnome-terminal the other day, see the link for patches, screenshot and supporting shell script utilities.

I went for OSC 4266 which is definitely a temporary choice and I don't mean it to be final. (It's the word "icon" on a phone's keypad.)

What I do hope to be final is that I have a first field that is currently unused, followed by a second field that is the base64-encoded image. This follows the pattern of the OSC 8 explicit hyperlink feature's design, and allows for all kinds of future extensibility by adding arbitrary parameters. Such parameters can include the MIME type of the picture, or let's say allow to specify a solid color instead of a base64 image as the second parameter if it's desired, or whatever.

There's a lot more to do with this feature.

I think there should be a guideline about the resolution of the picture (I've searched for info on favicon's recommended sizes, it's a nightmare). We'd need to know where terminal emulators would display this icon, e.g. only in the tab bar (a smaller size is okay then) or some Alt+Tab-like switcher (then a much bigger size is desired).

We'd need to study or decide whether there is or should be a limit on the length of escape sequences (in some standard, or in some existing implementations), and whether such limit is high enough for the desired icon size. If not, we might need to stitch the image together from multiple escape sequences which is a pain for both the emulator and the app setting the icon.

As for the window title, there's an ancient escape sequence for setting it (supported by probably all emulators), and a pretty new for saving/restoring (probably only supported by a few). The latter one is present in new terminfo definitions in smcup/rmcup, that is, invoked automatically when entering/leaving the alternate screen. However, I still have the impression that only the strict definition of these escape sequences are specified, and there isn't a guideline/recommendation on whose responsibility it is to emit the sequences. Do we wish to change this for the icon, and come up with a guideline; that is, design the behavior of entire ecosystem rather than just one component of it? I'm leaning towards it, and saying that cleaning up (i.e. popping the previous from the stack) is the responsibility of whoever set the icon.

I can easily imagine that one wants to display a particular icon when the shell is presenting the command prompt, and another when the shell is running a command. This would mean flipping between two icons frequently, which is a significant amount of network traffic over ssh. Do we care? Can we help by offering some advanced stack operations, e.g. in addition to "push" and "pop" also implement a "swap" (the current with the stack's topmost)? Or shall the escape sequence allow defining "named" icons which can later be referred to using their name (with minimal network traffic)? Also, do we want to have a defined set of stock icons that can be set using their name (their exact look would depend on the implementation)?

@zadjii-msft
Copy link
Member

Good point on the length of the image string. Right now we're supporting arbitrary images as icons, but I wouldn't want to design a sequence that says "you might need to process a base64-encoded 4K .png to turn it into an icon".

I really like the two parameter idea.

I think I'm actually really on board with the "define named icons" route. The terminal could keep a small map of icon names as keys to images. With the map, would we need to implement a stack still?

I'm imagining a flow like this:

  1. The user starts up the terminal, their default shell is cmd.exe, and it has no icon by default. (for example)
  2. The user runs powershell.exe.
  3. powershell queries the terminal if it has a powershell.exe icon yet
  4. The terminal replies that there isn't
  5. powershell emits a sequence to say "set powershell.exe to {some base64 string}"
  6. powershell emits a sequence to say "use the powershell.exe icon"
  7. the user launches vim
  8. <vim does the same thing as powershell, but with vim as the icon key>
  9. The user exits vim. Powershell doesn't know what state the icon is in, so it will need to restore the icon to what it wants. It queries if there is a powershell.exe icon
  10. The terminal responds "yes there is a powershell.exe icon"
  11. powershell emits a sequence to say "use the powershell.exe icon"
  12. The user exits powershell. Because powershell doesn't know if its caller knows about setting the icon with VT (cmd.exe in this example won't), it's a good citizen, and emits VT to say "restore the icon to default".

In this example, we need:

  • A pair of request/response to/from the terminal to query if an icon is set already
  • A sequence to set the icon to a particular keyed icon
  • A sequence to reset the icon to it's default state (whatever the terminal wants)

If we only had a stack, then vim would need to always emit its entire icon over the wire to be able to set it, because it'd always be popped off. Additionally, powershell can more cleanly restore its own icon this way - regardless of what happens with vim (it decides to pop the stack and return to its caller's icon, or it closes unexpectedly and doesn't have the chance, or it just straight up decides not to pop the stack on exit), powershell can restore its icon without needing to re-emit it. Then, when the user inevitably re-enters vim, the icon will likely still be in the dictionary, and vim won't need to re-emit it on every subsequent launch.

Thoughts?

It's a little "chatty"-er than just pushing and popping, but less chat-y in the sense that we're not re-emitting the images constantly.

@egmontkob
Copy link

I wouldn't want to design a sequence that says "you might need to process a base64-encoded 4K .png to turn it into an icon".

I am personally absolutely fine with 4 kB data size, or even somewhat bigger than that (maybe topping around 64 kB-ish). An icon size of 24x24, assuming raw representation of RGBA, 8 bits for each channel, and a 4:3 overhead of base64, is 3 kB. Compressed image formats like PNG or JPG probably don't go significantly above this, whereas I guess SVG can, and so can ICO if it contains multiple resolutions.

My Firefox and Chrome display favicons at 16x16 size, but if I had a HiDPI screen I might be wishing for a logical 32x32 picture size for a nicer look, for this the limit has to be at least 5.5 kB-ish.

We might shave off a few bytes by using base85, although that has a worse availability in command line and libraries, and has multiple variants which truly scares me, so I vote for base64.

So could we perhaps state to go with base64, a recommended size of 32x32, and a limit of 8 kB? Does this sound reasonable?


I think I'm actually really on board with the "define named icons" route. The terminal could keep a small map of icon names as keys to images.

What is unclear to me: How would the terminal know when it's safe to drop an icon? E.g. would there be a hint escape sequence to drop it? Would it be okay to have a reasonable limit, let's say the 16 LRU ones, after which it's okay for the terminal to drop the old ones? Or would it just remember them infinitely, and rely on malicious applications not OOMing the terminal?

For the icon name, I recommend to go with the "reverse domain name"-like approach as with Java classnames, such as "org.vim.whatever" for Vim's icons. This way if parties play nice then there won't be a conflict.

Should the name be optional, or mandatory (send the image in an escape sequence, and set it in a second)? If the latter, we could be looking into future extensions (such as inline image display, or sound to play, or whatnot) and design it to be a more generic feature to transmit arbitrary resource files (without a size limit per se) to the terminal for various kinds of use; and then in a next step pick it to be used as favicon?

With the map, would we need to implement a stack still?

Good question. Maybe not. Let's think about it a bit more :)

it's a good citizen, and emits VT to say "restore the icon to default" [...] powershell can more cleanly restore its own icon this way - regardless of what happens with vim ([...] it closes unexpectedly and doesn't have the chance [...])

A crashing application is always a problem, there's no clear separation of applications in terminals, a crashing one can leave the terminal in underised mode for the next one in so many aspects (e.g. alternate charset, alternate screen, nondefault colors) that the icon won't be the biggest concern. I believe the basic should be that it's each application's responsibility to clean up after itself, to be a "good citizen" as you say, including to restore the icon (or lack thereof) by popping from the stack. (This also requires that popping from the empty stack clears the current icon.) In additon to this, a shell could indeed reasonably decide to reinforce the same icon whenever it displays its prompt.

An interesting case is to see how it'll go if all kinds of apps nest in each other, e.g. you ssh, then tmux, then start a vim, then a shell from that, then detach from tmux and reattach from elsewhere, then I-don't-know-what... In particular, I can't see at the moment how toggling mc's panels with Ctrl+O could toggle between two icons, how and when the subshell would set its icon.


powershell queries the terminal if it has a powershell.exe icon yet

I am strongly against all kinds of escape sequences that query the terminal (not just in this context). They are extremely fragile, and truly cumbersome (well, more precisely: straight impossible) to reliably use from an application. Plus, it's usually much slower to have to wait for a roundtrip time than to transmit a few kilobytes. See e.g. here (section "Asynchronous escape sequences") for details.

@Girmii
Copy link

Girmii commented Oct 23, 2020

I'm not sure if this is the right place to suggest the idea, but I think it would be useful to use an emoji as the tab icon. This opens up a wide array of new possibilities and makes the settings file self-contained.
For the latter reason, base64 encoding of images would also be a nice addition.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-VT Virtual Terminal sequence support Help Wanted We encourage anyone to jump in on these. Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. Product-Terminal The new Windows Terminal.
Projects
Specification Tracker
  
Spec Needed ❓
Development

No branches or pull requests

7 participants