Skip to content

Commit

Permalink
When the window is summoned and is already active, minimize it. (#9963)
Browse files Browse the repository at this point in the history
This adds a `toggleVisibility` parameter to `globalSummon`. 
* When `true` (default): when you press the global summon keybinding, and the window is currently the foreground window, we'll minimize the window.
* When `false`, we'll just do nothing.

## References
* Original thread: #653
* Spec: #9274 
* megathread: #8888

## PR Checklist
* [x] Checks a box in #8888
* [x] closes https://github.com/microsoft/terminal/projects/5#card-59030814
* [x] I work here
* [ ] No tests for this one.
* [ ] yes yes eventually I'll come back on the docs

## Detailed Description of the Pull Request / Additional comments

I've got nothing extra to add here. This one's pretty simple. I'm only targeting #9954 since that one laid so much foundation to build on, with the `SummonBehavior`

## Validation Steps Performed

Played with this for a while, and it's amazing.
  • Loading branch information
zadjii-msft authored Apr 28, 2021
1 parent 65b22b9 commit 30d2d2c
Show file tree
Hide file tree
Showing 10 changed files with 66 additions and 13 deletions.
1 change: 1 addition & 0 deletions .github/actions/spelling/dictionary/apis.txt
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ ICustom
IDialog
IDirect
IExplorer
IFACEMETHOD
IFile
IInheritable
IMap
Expand Down
2 changes: 1 addition & 1 deletion src/cascadia/Remoting/Peasant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
TraceLoggingWrite(g_hRemotingProvider,
"Peasant_Summon",
TraceLoggingUInt64(GetID(), "peasantID", "Our ID"),
TraceLoggingUInt64(localCopy->MoveToCurrentDesktop(), "MoveToCurrentDesktop", "true if we should move to the current desktop"),
TraceLoggingUInt64(localCopy.MoveToCurrentDesktop(), "MoveToCurrentDesktop", "true if we should move to the current desktop"),
TraceLoggingLevel(WINEVENT_LEVEL_VERBOSE));

_SummonRequestedHandlers(*this, localCopy);
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/Remoting/Peasant.idl
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ namespace Microsoft.Terminal.Remoting
[default_interface] runtimeclass SummonWindowBehavior {
SummonWindowBehavior();
Boolean MoveToCurrentDesktop;
Boolean ToggleVisibility;
// Other options:
// * CurrentMonitor
}
Expand Down
4 changes: 3 additions & 1 deletion src/cascadia/Remoting/SummonWindowBehavior.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation
public:
SummonWindowBehavior() = default;
WINRT_PROPERTY(bool, MoveToCurrentDesktop, true);
WINRT_PROPERTY(bool, ToggleVisibility, true);

public:
SummonWindowBehavior(const Remoting::SummonWindowBehavior& other) :
_MoveToCurrentDesktop{ other.MoveToCurrentDesktop() } {};
_MoveToCurrentDesktop{ other.MoveToCurrentDesktop() },
_ToggleVisibility{ other.ToggleVisibility() } {};
};
}

Expand Down
7 changes: 6 additions & 1 deletion src/cascadia/TerminalSettingsModel/ActionArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1045,9 +1045,11 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
GlobalSummonArgs() = default;
WINRT_PROPERTY(winrt::hstring, Name, L"");
WINRT_PROPERTY(Model::DesktopBehavior, Desktop, Model::DesktopBehavior::ToCurrent);
WINRT_PROPERTY(bool, ToggleVisibility, true);

static constexpr std::string_view NameKey{ "name" };
static constexpr std::string_view DesktopKey{ "desktop" };
static constexpr std::string_view ToggleVisibilityKey{ "toggleVisibility" };

public:
hstring GenerateName() const;
Expand All @@ -1057,7 +1059,8 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
if (auto otherAsUs = other.try_as<GlobalSummonArgs>())
{
return otherAsUs->_Name == _Name &&
otherAsUs->_Desktop == _Desktop;
otherAsUs->_Desktop == _Desktop &&
otherAsUs->_ToggleVisibility == _ToggleVisibility;
}
return false;
};
Expand All @@ -1067,13 +1070,15 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
auto args = winrt::make_self<GlobalSummonArgs>();
JsonUtils::GetValueForKey(json, NameKey, args->_Name);
JsonUtils::GetValueForKey(json, DesktopKey, args->_Desktop);
JsonUtils::GetValueForKey(json, ToggleVisibilityKey, args->_ToggleVisibility);
return { *args, {} };
}
IActionArgs Copy() const
{
auto copy{ winrt::make_self<GlobalSummonArgs>() };
copy->_Name = _Name;
copy->_Desktop = _Desktop;
copy->_ToggleVisibility = _ToggleVisibility;
return *copy;
}
// SPECIAL! This deserializer creates a GlobalSummonArgs with the
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalSettingsModel/ActionArgs.idl
Original file line number Diff line number Diff line change
Expand Up @@ -264,5 +264,6 @@ namespace Microsoft.Terminal.Settings.Model
{
String Name { get; };
DesktopBehavior Desktop { get; };
Boolean ToggleVisibility { get; };
};
}
9 changes: 6 additions & 3 deletions src/cascadia/UnitTests_Remoting/RemotingTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,20 @@ namespace RemotingUnitTests
{
struct MockDesktopManager : implements<MockDesktopManager, IVirtualDesktopManager>
{
HRESULT GetWindowDesktopId(HWND /*topLevelWindow*/, GUID* /*desktopId*/)
IFACEMETHOD(GetWindowDesktopId)
(HWND /*topLevelWindow*/, GUID* /*desktopId*/)
{
VERIFY_IS_TRUE(false, L"We shouldn't need GetWindowDesktopId in the tests.");
return E_FAIL;
}
HRESULT MoveWindowToDesktop(HWND /*topLevelWindow*/, REFGUID /*desktopId*/)
IFACEMETHOD(MoveWindowToDesktop)
(HWND /*topLevelWindow*/, REFGUID /*desktopId*/)
{
VERIFY_IS_TRUE(false, L"We shouldn't need GetWindowDesktopId in the tests.");
return E_FAIL;
}
HRESULT IsWindowOnCurrentVirtualDesktop(HWND topLevelWindow, BOOL* onCurrentDesktop)
IFACEMETHOD(IsWindowOnCurrentVirtualDesktop)
(HWND topLevelWindow, BOOL* onCurrentDesktop)
{
if (pfnIsWindowOnCurrentVirtualDesktop)
{
Expand Down
5 changes: 3 additions & 2 deletions src/cascadia/WindowsTerminal/AppHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ void AppHost::_DispatchCommandline(winrt::Windows::Foundation::IInspectable /*se
{
// Summon the window whenever we dispatch a commandline to it. This will
// make it obvious when a new tab/pane is created in a window.
_window->SummonWindow();
_window->SummonWindow(false);
_logic.ExecuteCommandline(args.Commandline(), args.CurrentDirectory());
}

Expand Down Expand Up @@ -692,6 +692,7 @@ void AppHost::_GlobalHotkeyPressed(const long hotkeyIndex)
// desktop:onCurrent - MoveToCurrentDesktop=false, OnCurrentDesktop=true
args.OnCurrentDesktop(summonArgs.Desktop() == Settings::Model::DesktopBehavior::OnCurrent);
args.SummonBehavior().MoveToCurrentDesktop(summonArgs.Desktop() == Settings::Model::DesktopBehavior::ToCurrent);
args.SummonBehavior().ToggleVisibility(summonArgs.ToggleVisibility());

_windowManager.SummonWindow(args);
if (args.FoundMatch())
Expand Down Expand Up @@ -774,7 +775,7 @@ bool AppHost::_LazyLoadDesktopManager()
void AppHost::_HandleSummon(const winrt::Windows::Foundation::IInspectable& /*sender*/,
const Remoting::SummonWindowBehavior& args)
{
_window->SummonWindow();
_window->SummonWindow(args.ToggleVisibility());

if (args != nullptr && args.MoveToCurrentDesktop())
{
Expand Down
44 changes: 40 additions & 4 deletions src/cascadia/WindowsTerminal/IslandWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -999,6 +999,33 @@ void IslandWindow::SetGlobalHotkeys(const std::vector<winrt::Microsoft::Terminal
}
}

// Method Description:
// - Summon the window, or possibly dismiss it. If toggleVisibility is true,
// then we'll dismiss (minimize) the window if it's currently active.
// Otherwise, we'll always just try to activate the window.
// Arguments:
// - toggleVisibility: controls how we should behave when already in the foreground.
// Return Value:
// - <none>
winrt::fire_and_forget IslandWindow::SummonWindow(const bool toggleVisibility)
{
// On the foreground thread:
co_await winrt::resume_foreground(_rootGrid.Dispatcher());

// * If the user doesn't want to toggleVisibility, then just always try to
// activate.
// * If the user does want to toggleVisibility, then dismiss the window if
// we're the current foreground window.
if (toggleVisibility && GetForegroundWindow() == _window.get())
{
_globalDismissWindow();
}
else
{
_globalActivateWindow();
}
}

// Method Description:
// - Force activate this window. This method will bring us to the foreground and
// activate us. If the window is minimized, it will restore the window. If the
Expand All @@ -1007,11 +1034,8 @@ void IslandWindow::SetGlobalHotkeys(const std::vector<winrt::Microsoft::Terminal
// - <none>
// Return Value:
// - <none>
winrt::fire_and_forget IslandWindow::SummonWindow()
void IslandWindow::_globalActivateWindow()
{
// On the foreground thread:
co_await winrt::resume_foreground(_rootGrid.Dispatcher());

// From: https://stackoverflow.com/a/59659421
// > The trick is to make windows ‘think’ that our process and the target
// > window (hwnd) are related by attaching the threads (using
Expand Down Expand Up @@ -1039,6 +1063,18 @@ winrt::fire_and_forget IslandWindow::SummonWindow()
LOG_LAST_ERROR_IF_NULL(SetActiveWindow(_window.get()));
}

// Method Description:
// - Minimize the window. This is called when the window is summoned, but is
// already active
// Arguments:
// - <none>
// Return Value:
// - <none>
void IslandWindow::_globalDismissWindow()
{
LOG_IF_WIN32_BOOL_FALSE(ShowWindow(_window.get(), SW_MINIMIZE));
}

bool IslandWindow::IsQuakeWindow() const noexcept
{
return _isQuakeWindow;
Expand Down
5 changes: 4 additions & 1 deletion src/cascadia/WindowsTerminal/IslandWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class IslandWindow :
void UnsetHotkeys(const std::vector<winrt::Microsoft::Terminal::Control::KeyChord>& hotkeyList);
void SetGlobalHotkeys(const std::vector<winrt::Microsoft::Terminal::Control::KeyChord>& hotkeyList);

winrt::fire_and_forget SummonWindow();
winrt::fire_and_forget SummonWindow(const bool toggleVisibility);

bool IsQuakeWindow() const noexcept;
void IsQuakeWindow(bool isQuakeWindow) noexcept;
Expand Down Expand Up @@ -93,6 +93,9 @@ class IslandWindow :
void _OnGetMinMaxInfo(const WPARAM wParam, const LPARAM lParam);
long _calculateTotalSize(const bool isWidth, const long clientSize, const long nonClientSize);

void _globalActivateWindow();
void _globalDismissWindow();

bool _isQuakeWindow{ false };
void _enterQuakeMode();

Expand Down

0 comments on commit 30d2d2c

Please sign in to comment.