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 Minimize to Tray and Tray Icon #10368

Merged
68 commits merged into from
Aug 12, 2021
Merged

Conversation

leonMSFT
Copy link
Contributor

@leonMSFT leonMSFT commented Jun 8, 2021

A brief summary of the behavior of the tray icon:

  • There will only ever be one tray icon representing all windows.
  • Left-Click on a Tray Icon brings up the MRU window.
  • Right-Click on a Tray Icon brings up a Context Menu:
Focus Terminal
----------------
Windows --> Window ID 1 - <unnamed window>
            Named Window
            Named Window Again
  • Focus Terminal will bring up the MRU window.
  • Clicking on any of the Window "names" in the submenu will summon the window.

Settings Changes

Two new global settings are introduced: alwaysShowTrayIcon and minimizeToTray. Here's a chart explaining the behavior with the two settings.

alwaysShowTrayIcon:true alwaysShowTrayIcon:false
minimizeToTray:true tray icon is always shown. minimize button will hide the window. tray icon is always shown. minimize button will hide the window.
minimizeToTray:false tray icon is always shown. tray icon is not shown ever.

Closes #5727

References

Spec for Minimize to Tray
Docs PR - MicrosoftDocs/terminal#352
#10448 - My list of TODOs

@leonMSFT leonMSFT added Area-Remoting Communication layer between windows. Often for windowing behavior, quake mode, etc. Area-User Interface Issues pertaining to the user interface of the Console or Terminal Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. Product-Terminal The new Windows Terminal. labels Jun 8, 2021
src/cascadia/WindowsTerminal/icon.cpp Outdated Show resolved Hide resolved
src/cascadia/WindowsTerminal/icon.cpp Outdated Show resolved Hide resolved
src/cascadia/WindowsTerminal/AppHost.cpp Outdated Show resolved Hide resolved
Comment on lines 1044 to 1050
// TODO: Other useful options may include:
// - Summon All
// - Summon MRU or Monarch
// - Though that's technically already available with a left click
// but may be a reasonable request to also put it explicitly in the
// context menu
// - Quit All
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't forget to tag up this bare TODO

src/cascadia/WindowsTerminal/AppHost.cpp Outdated Show resolved Hide resolved
src/cascadia/Remoting/WindowManager.cpp Outdated Show resolved Hide resolved
src/cascadia/Remoting/WindowManager.cpp Outdated Show resolved Hide resolved
src/cascadia/Remoting/Peasant.cpp Outdated Show resolved Hide resolved
src/cascadia/Remoting/Monarch.cpp Show resolved Hide resolved
@WSLUser
Copy link
Contributor

WSLUser commented Jun 15, 2021

Make an "AlwaysShowTrayIcon" option so people can control if they want it in their tray or not by default.

This should be a requirement. So many applications provide this option that it should be considered a defacto standard (like Xterm).

(I also personally like seeing all my tray icons. If I don't want to see one, I'll close the application instead, usually from left clicking on the icon, if it's supported, which it usually is.)

@zadjii-msft
Copy link
Member

This should be a requirement. So many applications provide this option that it should considered a defacto standard (like Xterm).

Yep, there's already a whole spec with a section devoted to this idea.

@zadjii-msft
Copy link
Member

I've introduced a new keybinding also named minimizeToTray for convenience in case users perfer to minimize with a keybinding instead of having to click on the minimize button. Upon activation, the currently focused window will become hidden.

wait uh, I don't think we need this. Win+down will minimize a window

Copy link
Member

@zadjii-msft zadjii-msft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blocking for discussion on the minimizeToTray action and the #if TIL_FEATURE thing

src/cascadia/WindowsTerminal/main.cpp Show resolved Hide resolved
@@ -637,6 +637,17 @@
<data name="CommandPaletteMenuItem" xml:space="preserve">
<value>Command Palette</value>
</data>
<data name="AppName" xml:space="preserve">
<value>Windows Terminal</value>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wait uh, if you're gonna pull it from the CascadiaPackage resources, do we need this string still?

src/cascadia/TerminalApp/AppLogic.cpp Outdated Show resolved Hide resolved
@ghost ghost added Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something and removed Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something labels Jul 21, 2021
@leonMSFT
Copy link
Contributor Author

wait uh, I don't think we need this. Win+down will minimize a window

Ah crap I didn't even know about this shortcut 😅
Ok so with this shortcut, the user can minimize to tray with the keyboard as long as minimizeToTray = true.
What about users who have minimizeToTray = false, alwaysShowTrayIcon = true? They may not want all minimize actions to minimizeToTray, but they'd likely want some way of sending the window to the tray considering they want the icon there. Perhaps it should be a system menu item? Or maybe it should be a tray icon menu item? 🤔

@zadjii-msft
Copy link
Member

They may not want all minimize actions to minimizeToTray, but they'd likely want some way of sending the window to the tray considering they want the icon there.

Hmm. Interesting. Okay, I'm convinced. I kinda think it should be a separate PR, but it's already here so ¯\_(ツ)_/¯

Copy link
Member

@zadjii-msft zadjii-msft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay most of these are just notes to self as I read the code. Mostly just indicators of where I might have been confused as I was following the logic.

I think at this point I'm mostly blocking on the "add a try/catch here" one.

I don't know how I feel about the minimize to tray action, but I don't feel like blocking that element of it.

This is ∞% better without all the ifdefs, thanks for that ☺️

const ActionEventArgs& args)
{
#if TIL_FEATURE_TRAYICON_ENABLED
if (_settings.GlobalSettings().MinimizeToTray() || _settings.GlobalSettings().AlwaysShowTrayIcon())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait so if they don't have either of these features on, then this will do nothing. I thought the point of this action was to allow minimizing a window to the tray even when neither setting is on?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right okay so this action only works when there is a tray icon. Right, cause otherwise the window would just disappear into the void. And we're not doing any sort of per-window tracking of "this window wanted to be able to minimize to the tray, so we must have a tray icon".

IDK I still feel weird about this action and almost wish it was a separate PR to review/discuss

Copy link
Contributor Author

@leonMSFT leonMSFT Aug 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, pretty much I don't want to let the user do be able to minimize if there won't be a tray icon. The idea was to be able to minimize when minimizeToTray = false, alwaysShowTrayIcon = true.

The per-window tracking would definitely be useful especially for big sweeping actions like "summon all" - I'll add it to the list.

I'll also split this off into its own PR and we could discuss some more there - makes the PR smaller too 😉

src/cascadia/WindowsTerminal/AppHost.cpp Show resolved Hide resolved
src/cascadia/WindowsTerminal/AppHost.cpp Outdated Show resolved Hide resolved
// work properly.
nid.uVersion = NOTIFYICON_VERSION_4;
Shell_NotifyIcon(NIM_SETVERSION, &nid);
void AppHost::_ShowTrayIconRequested()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we need to make sure to hop onto the BG thread at the top of this (and _HideTrayIconRequested)? Usually the COM x-proc calls end up throwing exceptions/gracefully doing nothing when called on the main thread.

Is this really never called on the main thread?

  • _IsQuakeWindowChanged - pretty sure that can be on the main thread... unsure tho
  • _windowManager.ShowTrayIconRequested okay this one's on the bg thread

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I've never observed it doing weird stuff, I'll throw it on a resume_background in the beginning of the functions just to be safe.

src/cascadia/WindowsTerminal/AppHost.cpp Show resolved Hide resolved
src/cascadia/WindowsTerminal/IslandWindow.cpp Show resolved Hide resolved
src/cascadia/WindowsTerminal/TrayIcon.cpp Outdated Show resolved Hide resolved
src/cascadia/WindowsTerminal/TrayIcon.cpp Outdated Show resolved Hide resolved
{
SummonWindowBehavior args{};
args.ToggleVisibility(false);
peasant.Summon(args);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrap this boy up in a try/catch

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm actually doing the _forAllPeasantsIgnoringTheDead thing for this little snippet, that has error handling in it so I should be good right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yep, you're good

// - <none>
void TrayIcon::DestroyTrayIcon()
{
Shell_NotifyIcon(NIM_DELETE, &_trayIconData);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also do a

            _trayIconData.reset();

here, like we used to?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was intending for this function to be more of a RemoveIconFromTray instead of a "destroy" (I'll rename). I wanted the actual "destruction" of the tray icon to be when AppHost sets its _trayIcon ptr to null, and if it ever wanted to get a new tray icon, it should instantiate a new one.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okeydokey, good enough for me

@ghost ghost added Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something and removed Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something labels Aug 3, 2021
Copy link
Member

@zadjii-msft zadjii-msft left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets do it

@leonMSFT leonMSFT added the AutoMerge Marked for automatic merge by the bot when requirements are met label Aug 11, 2021
@ghost
Copy link

ghost commented Aug 11, 2021

Hello @leonMSFT!

Because this pull request has the AutoMerge label, I will be glad to assist with helping to merge this pull request once all check-in policies pass.

p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (@msftbot) and give me an instruction to get started! Learn more here.

Copy link
Member

@carlos-zamora carlos-zamora left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • I think we should be using if constexpr (Feature_XXX::IsEnabled()) when possible
  • the gsl::narrow vs gsl::narrow_cast thing is a bit concerning, so I just want to double check that
  • the one copyright header that's missing

doc/cascadia/profiles.schema.json Outdated Show resolved Hide resolved
src/cascadia/TerminalApp/AppLogic.cpp Outdated Show resolved Hide resolved
src/cascadia/TerminalApp/AppLogic.cpp Outdated Show resolved Hide resolved
src/cascadia/Remoting/WindowManager.cpp Outdated Show resolved Hide resolved
src/cascadia/Remoting/WindowManager.cpp Show resolved Hide resolved
src/cascadia/WindowsTerminal/TrayIcon.cpp Outdated Show resolved Hide resolved
src/cascadia/WindowsTerminal/AppHost.cpp Outdated Show resolved Hide resolved
src/cascadia/WindowsTerminal/AppHost.cpp Outdated Show resolved Hide resolved
src/cascadia/WindowsTerminal/AppHost.cpp Outdated Show resolved Hide resolved
src/cascadia/WindowsTerminal/AppHost.cpp Outdated Show resolved Hide resolved
@ghost ghost merged commit a0edb12 into main Aug 12, 2021
@ghost ghost deleted the dev/lelian/notifyicon/yougetoneyougetone branch August 12, 2021 19:54
{
Shell_NotifyIcon(NIM_DELETE, &_trayIconData.value());
_trayIconData.reset();
_windowManager.RequestHideTrayIcon();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btw there's no guarantee that this destructs 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

argh I used the wrong one here it should be AppHost::_HideTrayIconRequested

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just kidding that's not the right one either

@@ -662,6 +655,20 @@ void AppHost::_BecomeMonarch(const winrt::Windows::Foundation::IInspectable& /*s
const winrt::Windows::Foundation::IInspectable& /*args*/)
{
_setupGlobalHotkeys();

// The monarch is just going to be THE listener for inbound connections.
_listenForInboundConnections();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doesn't break the defapp server?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh shit good catch

@leonMSFT leonMSFT mentioned this pull request Aug 12, 2021
ghost pushed a commit that referenced this pull request Aug 19, 2021
Some followups to #10368:
- Accidentally reverted a defapp change where the Monarch should not by default register itself as a handoff server.
- Destroy the tray icon if we're a monarch otherwise if we're a quake window we request the monarch to hide the icon.
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Remoting Communication layer between windows. Often for windowing behavior, quake mode, etc. Area-User Interface Issues pertaining to the user interface of the Console or Terminal AutoMerge Marked for automatic merge by the bot when requirements are met Issue-Feature Complex enough to require an in depth planning process and actual budgeted, scheduled work. Product-Terminal The new Windows Terminal.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature-request] Minimize to tray
7 participants