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

Make the window name _quake special #9785

Merged
11 commits merged into from
Apr 26, 2021
6 changes: 6 additions & 0 deletions .github/actions/spelling/expect/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1026,14 +1026,20 @@ hsl
hstr
hstring
hsv
HTBOTTOMLEFT
HTBOTTOMRIGHT
HTCAPTION
HTCLIENT
HTLEFT
htm
HTMAXBUTTON
HTMINBUTTON
html
HTMLTo
HTRIGHT
HTTOP
HTTOPLEFT
HTTOPRIGHT
hu
hungapp
HVP
Expand Down
18 changes: 16 additions & 2 deletions src/cascadia/TerminalApp/AppLogic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,12 +285,21 @@ namespace winrt::TerminalApp::implementation
// launched _fullscreen_, toggle fullscreen mode. This will make sure
// that the window size is _first_ set up as something sensible, so
// leaving fullscreen returns to a reasonable size.
//
// We know at the start, that the root TerminalPage definitely isn't
// in focus nor fullscreen mode. So "Toggle" here will always work
// to "enable".
const auto launchMode = this->GetLaunchMode();
if (launchMode == LaunchMode::FullscreenMode)
if (IsQuakeWindow())
{
_root->ToggleFocusMode();
Copy link
Member

Choose a reason for hiding this comment

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

Why ToggleFocusMode and not something like EnableFocusMode or SetFocusMode(true)? QM will always be in focus mode right?

Copy link
Member Author

Choose a reason for hiding this comment

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

Frankly, I hadn't written _SetFocusMode yet when I added this line 😋

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah, but that's a private member on TerminalPage... meh, I just didn't feel like adding another method that'll only have one usage right here

}
else if (launchMode == LaunchMode::FullscreenMode)
{
_root->ToggleFullscreen();
}
else if (launchMode == LaunchMode::FocusMode || launchMode == LaunchMode::MaximizedFocusMode)
else if (launchMode == LaunchMode::FocusMode ||
launchMode == LaunchMode::MaximizedFocusMode)
{
_root->ToggleFocusMode();
}
Expand Down Expand Up @@ -1439,4 +1448,9 @@ namespace winrt::TerminalApp::implementation
}
}

bool AppLogic::IsQuakeWindow() const noexcept
{
return _root->IsQuakeWindow();
}

}
2 changes: 2 additions & 0 deletions src/cascadia/TerminalApp/AppLogic.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ namespace winrt::TerminalApp::implementation
void WindowName(const winrt::hstring& name);
uint64_t WindowId();
void WindowId(const uint64_t& id);
bool IsQuakeWindow() const noexcept;

Windows::Foundation::Size GetLaunchDimensions(uint32_t dpi);
bool CenterOnLaunch();
Expand Down Expand Up @@ -158,6 +159,7 @@ namespace winrt::TerminalApp::implementation
FORWARDED_TYPED_EVENT(SetTaskbarProgress, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, SetTaskbarProgress);
FORWARDED_TYPED_EVENT(IdentifyWindowsRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, IdentifyWindowsRequested);
FORWARDED_TYPED_EVENT(RenameWindowRequested, Windows::Foundation::IInspectable, winrt::TerminalApp::RenameWindowRequestedArgs, _root, RenameWindowRequested);
FORWARDED_TYPED_EVENT(IsQuakeWindowChanged, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, IsQuakeWindowChanged);

#ifdef UNIT_TESTING
friend class TerminalAppLocalTests::CommandlineTest;
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalApp/AppLogic.idl
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ namespace TerminalApp
String WindowName;
UInt64 WindowId;
void RenameFailed();
Boolean IsQuakeWindow();

Windows.Foundation.Size GetLaunchDimensions(UInt32 dpi);
Boolean CenterOnLaunch { get; };
Expand Down Expand Up @@ -85,5 +86,6 @@ namespace TerminalApp
event Windows.Foundation.TypedEventHandler<Object, Object> SetTaskbarProgress;
event Windows.Foundation.TypedEventHandler<Object, Object> IdentifyWindowsRequested;
event Windows.Foundation.TypedEventHandler<Object, RenameWindowRequestedArgs> RenameWindowRequested;
event Windows.Foundation.TypedEventHandler<Object, Object> IsQuakeWindowChanged;
}
}
17 changes: 11 additions & 6 deletions src/cascadia/TerminalApp/TabManagement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -272,12 +272,17 @@ namespace winrt::TerminalApp::implementation
(_tabs.Size() > 1) ||
_settings.GlobalSettings().AlwaysShowTabs());

// collapse/show the tabs themselves
_tabView.Visibility(isVisible ? Visibility::Visible : Visibility::Collapsed);

// collapse/show the row that the tabs are in.
// NaN is the special value XAML uses for "Auto" sizing.
_tabRow.Height(isVisible ? NAN : 0);
if (_tabView)
{
// collapse/show the tabs themselves
_tabView.Visibility(isVisible ? Visibility::Visible : Visibility::Collapsed);
}
if (_tabRow)
{
// collapse/show the row that the tabs are in.
// NaN is the special value XAML uses for "Auto" sizing.
_tabRow.Height(isVisible ? NAN : 0);
}
zadjii-msft marked this conversation as resolved.
Show resolved Hide resolved
}

// Method Description:
Expand Down
34 changes: 31 additions & 3 deletions src/cascadia/TerminalApp/TerminalPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ namespace winrt
using IInspectable = Windows::Foundation::IInspectable;
}

static constexpr std::wstring_view QuakeWindowName{ L"_quake" };

namespace winrt::TerminalApp::implementation
{
TerminalPage::TerminalPage() :
Expand Down Expand Up @@ -2062,9 +2064,20 @@ namespace winrt::TerminalApp::implementation
// - <none>
void TerminalPage::ToggleFocusMode()
{
_isInFocusMode = !_isInFocusMode;
_UpdateTabView();
_FocusModeChangedHandlers(*this, nullptr);
_SetFocusMode(!_isInFocusMode);
}

void TerminalPage::_SetFocusMode(const bool inFocusMode)
{
// If we're the quake window, we must always be in focus mode.
// Prevent leaving focus mode here.
const bool newInFocusMode = inFocusMode || IsQuakeWindow();
if (newInFocusMode != FocusMode())
{
_isInFocusMode = newInFocusMode;
_UpdateTabView();
_FocusModeChangedHandlers(*this, nullptr);
}
}

// Method Description:
Expand Down Expand Up @@ -2610,6 +2623,7 @@ namespace winrt::TerminalApp::implementation

winrt::fire_and_forget TerminalPage::WindowName(const winrt::hstring& value)
{
const bool oldIsQuakeMode = IsQuakeWindow();
const bool changed = _WindowName != value;
if (changed)
{
Expand All @@ -2631,6 +2645,16 @@ namespace winrt::TerminalApp::implementation
if (page->_startupState == StartupState::Initialized)
{
page->IdentifyWindow();

// If we're entering quake mode, or leaving it
if (IsQuakeWindow() != oldIsQuakeMode)
{
// If we're entering Quake Mode from ~Focus Mode, then this will enter Focus Mode
// If we're entering Quake Mode from Focus Mode, then this will do nothing
// If we're leaving Quake Mode (we're already in Focus Mode), then this will do nothing
_SetFocusMode(true);
_IsQuakeWindowChangedHandlers(*this, nullptr);
}
}
}
}
Expand Down Expand Up @@ -2773,4 +2797,8 @@ namespace winrt::TerminalApp::implementation
}
}

bool TerminalPage::IsQuakeWindow() const noexcept
{
return WindowName() == QuakeWindowName;
}
}
4 changes: 4 additions & 0 deletions src/cascadia/TerminalApp/TerminalPage.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ namespace winrt::TerminalApp::implementation
void WindowId(const uint64_t& value);
winrt::hstring WindowIdForDisplay() const noexcept;
winrt::hstring WindowNameForDisplay() const noexcept;
bool IsQuakeWindow() const noexcept;

WINRT_CALLBACK(PropertyChanged, Windows::UI::Xaml::Data::PropertyChangedEventHandler);

Expand All @@ -122,6 +123,7 @@ namespace winrt::TerminalApp::implementation
TYPED_EVENT(Initialized, IInspectable, winrt::Windows::UI::Xaml::RoutedEventArgs);
TYPED_EVENT(IdentifyWindowsRequested, IInspectable, IInspectable);
TYPED_EVENT(RenameWindowRequested, Windows::Foundation::IInspectable, winrt::TerminalApp::RenameWindowRequestedArgs);
TYPED_EVENT(IsQuakeWindowChanged, IInspectable, IInspectable);

private:
friend struct TerminalPageT<TerminalPage>; // for Xaml to bind events
Expand Down Expand Up @@ -337,6 +339,8 @@ namespace winrt::TerminalApp::implementation

void _UpdateTeachingTipTheme(winrt::Windows::UI::Xaml::FrameworkElement element);

void _SetFocusMode(const bool inFocusMode);

#pragma region ActionHandlers
// These are all defined in AppActionHandlers.cpp
#define ON_ALL_ACTIONS(action) DECLARE_ACTION_HANDLER(action);
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalApp/TerminalPage.idl
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ namespace TerminalApp
String WindowNameForDisplay { get; };
String WindowIdForDisplay { get; };
void RenameFailed();
Boolean IsQuakeWindow();

// We cannot use the default XAML APIs because we want to make sure
// that there's only one application-global dialog visible at a time,
Expand All @@ -54,5 +55,6 @@ namespace TerminalApp
event Windows.Foundation.TypedEventHandler<Object, Object> SetTaskbarProgress;
event Windows.Foundation.TypedEventHandler<Object, Object> IdentifyWindowsRequested;
event Windows.Foundation.TypedEventHandler<Object, RenameWindowRequestedArgs> RenameWindowRequested;
event Windows.Foundation.TypedEventHandler<Object, Object> IsQuakeWindowChanged;
}
}
79 changes: 54 additions & 25 deletions src/cascadia/WindowsTerminal/AppHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ AppHost::AppHost() noexcept :
_window = std::make_unique<IslandWindow>();
}

// Update our own internal state tracking if we're in quake mode or not.
_IsQuakeWindowChanged(nullptr, nullptr);

// Tell the window to callback to us when it's about to handle a WM_CREATE
auto pfn = std::bind(&AppHost::_HandleCreateWindow,
this,
Expand Down Expand Up @@ -251,6 +254,7 @@ void AppHost::Initialize()
_logic.SetTaskbarProgress({ this, &AppHost::SetTaskbarProgress });
_logic.IdentifyWindowsRequested({ this, &AppHost::_IdentifyWindowsRequested });
_logic.RenameWindowRequested({ this, &AppHost::_RenameWindowRequested });
_logic.IsQuakeWindowChanged({ this, &AppHost::_IsQuakeWindowChanged });

_window->UpdateTitle(_logic.Title());

Expand Down Expand Up @@ -379,39 +383,58 @@ void AppHost::_HandleCreateWindow(const HWND hwnd, RECT proposedRect, LaunchMode

// Get the size of a window we'd need to host that client rect. This will
// add the titlebar space.
const auto nonClientSize = _window->GetTotalNonClientExclusiveSize(dpix);
adjustedWidth = islandWidth + nonClientSize.cx;
adjustedHeight = islandHeight + nonClientSize.cy;
const til::size nonClientSize = _window->GetTotalNonClientExclusiveSize(dpix);
adjustedWidth = islandWidth + nonClientSize.width<long>();
adjustedHeight = islandHeight + nonClientSize.height<long>();

til::size dimensions{ Utils::ClampToShortMax(adjustedWidth, 1),
Utils::ClampToShortMax(adjustedHeight, 1) };

// Find nearest monitor for the position that we've actually settled on
HMONITOR hMonNearest = MonitorFromRect(&proposedRect, MONITOR_DEFAULTTONEAREST);
MONITORINFO nearestMonitorInfo;
nearestMonitorInfo.cbSize = sizeof(MONITORINFO);
// Get monitor dimensions:
GetMonitorInfo(hMonNearest, &nearestMonitorInfo);
const til::size desktopDimensions{ gsl::narrow<short>(nearestMonitorInfo.rcWork.right - nearestMonitorInfo.rcWork.left),
gsl::narrow<short>(nearestMonitorInfo.rcWork.bottom - nearestMonitorInfo.rcWork.top) };

const COORD dimensions{ Utils::ClampToShortMax(adjustedWidth, 1),
Utils::ClampToShortMax(adjustedHeight, 1) };
til::point origin{ (proposedRect.left),
(proposedRect.top) };

if (centerOnLaunch)
if (_logic.IsQuakeWindow())
zadjii-msft marked this conversation as resolved.
Show resolved Hide resolved
{
// If we just use rcWork by itself, we'll fail to account for the invisible
// space reserved for the resize handles. So retrieve that size here.
const til::size ncSize{ _window->GetTotalNonClientExclusiveSize(dpix) };
const til::size availableSpace = desktopDimensions + nonClientSize;

origin = til::point{
::base::ClampSub<long>(nearestMonitorInfo.rcWork.left, (nonClientSize.width() / 2)),
(nearestMonitorInfo.rcWork.top)
};
dimensions = til::size{
availableSpace.width(),
availableSpace.height() / 2
};
launchMode = LaunchMode::FocusMode;
}
else if (centerOnLaunch)
{
// Find nearest monitor for the position that we've actually settled on
HMONITOR hMonNearest = MonitorFromRect(&proposedRect, MONITOR_DEFAULTTONEAREST);
MONITORINFO nearestMonitorInfo;
nearestMonitorInfo.cbSize = sizeof(MONITORINFO);
// Get monitor dimensions:
GetMonitorInfo(hMonNearest, &nearestMonitorInfo);
const COORD desktopDimensions{ gsl::narrow<short>(nearestMonitorInfo.rcWork.right - nearestMonitorInfo.rcWork.left),
gsl::narrow<short>(nearestMonitorInfo.rcWork.bottom - nearestMonitorInfo.rcWork.top) };
// Move our proposed location into the center of that specific monitor.
proposedRect.left = nearestMonitorInfo.rcWork.left +
((desktopDimensions.X / 2) - (dimensions.X / 2));
proposedRect.top = nearestMonitorInfo.rcWork.top +
((desktopDimensions.Y / 2) - (dimensions.Y / 2));
origin = til::point{
(nearestMonitorInfo.rcWork.left + ((desktopDimensions.width() / 2) - (dimensions.width() / 2))),
(nearestMonitorInfo.rcWork.top + ((desktopDimensions.height() / 2) - (dimensions.height() / 2)))
};
}
const COORD origin{ gsl::narrow<short>(proposedRect.left),
gsl::narrow<short>(proposedRect.top) };

const auto newPos = Viewport::FromDimensions(origin, dimensions);
const til::rectangle newRect{ origin, dimensions };
bool succeeded = SetWindowPos(hwnd,
nullptr,
newPos.Left(),
newPos.Top(),
newPos.Width(),
newPos.Height(),
newRect.left<int>(),
newRect.top<int>(),
newRect.width<int>(),
newRect.height<int>(),
SWP_NOACTIVATE | SWP_NOZORDER);

// Refresh the dpi of HWND because the dpi where the window will launch may be different
Expand Down Expand Up @@ -674,3 +697,9 @@ winrt::fire_and_forget AppHost::_RenameWindowRequested(const winrt::Windows::Fou
}
}
}

void AppHost::_IsQuakeWindowChanged(const winrt::Windows::Foundation::IInspectable&,
const winrt::Windows::Foundation::IInspectable&)
{
_window->IsQuakeWindow(_logic.IsQuakeWindow());
}
3 changes: 3 additions & 0 deletions src/cascadia/WindowsTerminal/AppHost.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,7 @@ class AppHost
const winrt::TerminalApp::RenameWindowRequestedArgs args);

GUID _CurrentDesktopGuid();

void _IsQuakeWindowChanged(const winrt::Windows::Foundation::IInspectable& sender,
const winrt::Windows::Foundation::IInspectable& args);
};
Loading