Create a window process for the tray icon (#10980)

Currently, the monarch window will show itself when opening the tray icon context menu. This is because a window must be set as the foreground window when the context menu opens, otherwise the menu won't be able to be dismissed when clicking outside of the context menu.

This PR makes the tray icon create a non visible/interactable window for the sole purpose of being set as the foreground window when the tray icon's context menu is opened. Then none of the terminal windows should be set as the foreground window when opening the context menu.

Closes #10936
This commit is contained in:
Leon Liang 2021-08-20 16:24:13 -07:00 committed by GitHub
parent acf1ddc9c4
commit 0c901edd81
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 38 additions and 1 deletions

View file

@ -23,6 +23,32 @@ TrayIcon::~TrayIcon()
RemoveIconFromTray();
}
void TrayIcon::_CreateWindow()
{
WNDCLASSW wc{};
wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
wc.hInstance = wil::GetModuleInstanceHandle();
wc.lpszClassName = L"TRAY_ICON_HOSTING_WINDOW_CLASS";
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = DefWindowProcW;
wc.hIcon = static_cast<HICON>(GetActiveAppIconHandle(true));
RegisterClass(&wc);
_trayIconHwnd = wil::unique_hwnd(CreateWindowW(wc.lpszClassName,
wc.lpszClassName,
WS_DISABLED,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
HWND_MESSAGE,
nullptr,
wc.hInstance,
nullptr));
WINRT_VERIFY(_trayIconHwnd);
}
// Method Description:
// - Creates and adds an icon to the notification tray.
// If an icon already exists, update the HWND associated
@ -33,6 +59,15 @@ TrayIcon::~TrayIcon()
// - <none>
void TrayIcon::CreateTrayIcon()
{
if (!_trayIconHwnd)
{
// Creating a disabled, non visible window just so we can set it
// as the foreground window when showing the context menu.
// This is done so that the context menu can be dismissed
// when clicking outside of it.
_CreateWindow();
}
NOTIFYICONDATA nid{};
nid.cbSize = sizeof(NOTIFYICONDATA);
@ -81,7 +116,7 @@ void TrayIcon::ShowTrayContextMenu(const til::point coord,
{
// We'll need to set our window to the foreground before calling
// TrackPopupMenuEx or else the menu won't dismiss when clicking away.
SetForegroundWindow(_owningHwnd);
SetForegroundWindow(_trayIconHwnd.get());
// User can select menu items with the left and right buttons.
UINT uFlags = TPM_RIGHTBUTTON;

View file

@ -30,8 +30,10 @@ public:
WINRT_CALLBACK(SummonWindowRequested, winrt::delegate<void(winrt::Microsoft::Terminal::Remoting::SummonWindowSelectionArgs)>);
private:
void _CreateWindow();
HMENU _CreateTrayContextMenu(winrt::Windows::Foundation::Collections::IMapView<uint64_t, winrt::hstring> peasants);
wil::unique_hwnd _trayIconHwnd;
HWND _owningHwnd;
NOTIFYICONDATA _trayIconData;
};