diff --git a/.github/actions/spell-check/expect/expect.txt b/.github/actions/spell-check/expect/expect.txt
index 01b64c42d78..276d9778fae 100644
--- a/.github/actions/spell-check/expect/expect.txt
+++ b/.github/actions/spell-check/expect/expect.txt
@@ -1457,6 +1457,7 @@ natvis
naws
nbsp
Nc
+NCACTIVATE
NCCALCSIZE
NCCREATE
NCLBUTTONDOWN
diff --git a/src/cascadia/TerminalApp/MinMaxCloseControl.cpp b/src/cascadia/TerminalApp/MinMaxCloseControl.cpp
index ee5f3e0d9b7..cf145bbe917 100644
--- a/src/cascadia/TerminalApp/MinMaxCloseControl.cpp
+++ b/src/cascadia/TerminalApp/MinMaxCloseControl.cpp
@@ -79,6 +79,18 @@ namespace winrt::TerminalApp::implementation
CloseButton().Height(maximizedHeight);
break;
+ case WindowVisualState::WindowVisualStateUnfocused:
+ VisualStateManager::GoToState(MaximizeButton(), L"WindowStateUnfocused", false);
+ VisualStateManager::GoToState(MinimizeButton(), L"WindowStateUnfocused", false);
+ VisualStateManager::GoToState(CloseButton(), L"WindowStateUnfocused", false);
+ break;
+
+ case WindowVisualState::WindowVisualStateFocused:
+ VisualStateManager::GoToState(MaximizeButton(), L"WindowStateFocused", false);
+ VisualStateManager::GoToState(MinimizeButton(), L"WindowStateFocused", false);
+ VisualStateManager::GoToState(CloseButton(), L"WindowStateFocused", false);
+ break;
+
case WindowVisualState::WindowVisualStateNormal:
case WindowVisualState::WindowVisualStateIconified:
default:
diff --git a/src/cascadia/TerminalApp/MinMaxCloseControl.xaml b/src/cascadia/TerminalApp/MinMaxCloseControl.xaml
index 701c8720935..edd21725ceb 100644
--- a/src/cascadia/TerminalApp/MinMaxCloseControl.xaml
+++ b/src/cascadia/TerminalApp/MinMaxCloseControl.xaml
@@ -22,6 +22,7 @@ the MIT License. See LICENSE in the project root for license information. -->
+
@@ -35,6 +36,7 @@ the MIT License. See LICENSE in the project root for license information. -->
+
@@ -49,6 +51,7 @@ the MIT License. See LICENSE in the project root for license information. -->
+
@@ -125,6 +128,16 @@ the MIT License. See LICENSE in the project root for license information. -->
+
+
+
+
+
+
+
+
+
+
diff --git a/src/cascadia/TerminalApp/TitlebarControl.cpp b/src/cascadia/TerminalApp/TitlebarControl.cpp
index 05806726cfe..4c31950669a 100644
--- a/src/cascadia/TerminalApp/TitlebarControl.cpp
+++ b/src/cascadia/TerminalApp/TitlebarControl.cpp
@@ -66,6 +66,13 @@ namespace winrt::TerminalApp::implementation
}
}
+ void TitlebarControl::Focused(bool focused)
+ {
+ const auto state = focused ? winrt::TerminalApp::WindowVisualState::WindowVisualStateFocused :
+ winrt::TerminalApp::WindowVisualState::WindowVisualStateUnfocused;
+ MinMaxCloseControl().SetWindowVisualState(state);
+ }
+
void TitlebarControl::Maximize_Click(winrt::Windows::Foundation::IInspectable const& /*sender*/, winrt::Windows::UI::Xaml::RoutedEventArgs const& /*e*/)
{
_OnMaximizeOrRestore(HTMAXBUTTON);
diff --git a/src/cascadia/TerminalApp/TitlebarControl.h b/src/cascadia/TerminalApp/TitlebarControl.h
index a30f347d868..65778d70910 100644
--- a/src/cascadia/TerminalApp/TitlebarControl.h
+++ b/src/cascadia/TerminalApp/TitlebarControl.h
@@ -17,6 +17,9 @@ namespace winrt::TerminalApp::implementation
{
TitlebarControl(uint64_t handle);
+ bool Focused() const;
+ void Focused(bool focused);
+
IInspectable Content();
void Content(IInspectable content);
diff --git a/src/cascadia/TerminalApp/TitlebarControl.idl b/src/cascadia/TerminalApp/TitlebarControl.idl
index 104f7a2f26f..0b2d43dcf98 100644
--- a/src/cascadia/TerminalApp/TitlebarControl.idl
+++ b/src/cascadia/TerminalApp/TitlebarControl.idl
@@ -7,7 +7,9 @@ namespace TerminalApp
{
WindowVisualStateNormal = 0,
WindowVisualStateMaximized,
- WindowVisualStateIconified
+ WindowVisualStateIconified,
+ WindowVisualStateFocused,
+ WindowVisualStateUnfocused
};
[default_interface] runtimeclass TitlebarControl : Windows.UI.Xaml.Controls.Grid
@@ -15,6 +17,8 @@ namespace TerminalApp
TitlebarControl(UInt64 parentWindowHandle);
void SetWindowVisualState(WindowVisualState visualState);
+ Boolean Focused { get; set; };
+
IInspectable Content;
Windows.UI.Xaml.Controls.Border DragBar { get; };
}
diff --git a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp
index d8e67e7dec7..595a16ae28c 100644
--- a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp
+++ b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp
@@ -516,6 +516,32 @@ int NonClientIslandWindow::_GetResizeHandleHeight() const noexcept
return 0;
}
+// Method Description:
+// - Responds to the WM_NCACTIVATE message by changing the focus state of
+// the window.
+[[nodiscard]] LRESULT NonClientIslandWindow::_OnFocusChanged(const WPARAM wParam, const LPARAM lParam) noexcept
+{
+ const auto windowStyle = GetWindowStyle(_window.get());
+ const auto isIconified = WI_IsFlagSet(windowStyle, WS_ICONIC);
+
+ if (isIconified)
+ {
+ return DefWindowProc(_window.get(), WM_NCACTIVATE, wParam, lParam);
+ }
+
+ if (_titlebar)
+ {
+ _isFocused = wParam;
+ try
+ {
+ _titlebar.Focused(_isFocused);
+ }
+ CATCH_LOG();
+ }
+
+ return TRUE;
+}
+
// Method Description:
// - Hit test the frame for resizing and moving.
// Arguments:
@@ -689,6 +715,8 @@ void NonClientIslandWindow::_UpdateFrameMargins() const noexcept
return 0;
case WM_NCCALCSIZE:
return _OnNcCalcSize(wParam, lParam);
+ case WM_NCACTIVATE:
+ return _OnFocusChanged(wParam, lParam);
case WM_NCHITTEST:
return _OnNcHitTest({ GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) });
case WM_PAINT:
diff --git a/src/cascadia/WindowsTerminal/NonClientIslandWindow.h b/src/cascadia/WindowsTerminal/NonClientIslandWindow.h
index 10a39b4fcb1..b510611f106 100644
--- a/src/cascadia/WindowsTerminal/NonClientIslandWindow.h
+++ b/src/cascadia/WindowsTerminal/NonClientIslandWindow.h
@@ -61,6 +61,7 @@ class NonClientIslandWindow : public IslandWindow
winrt::Windows::UI::Xaml::ElementTheme _theme;
bool _isMaximized;
+ bool _isFocused;
[[nodiscard]] static LRESULT __stdcall _StaticInputSinkWndProc(HWND const window, UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept;
[[nodiscard]] LRESULT _InputSinkMessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept;
@@ -73,6 +74,7 @@ class NonClientIslandWindow : public IslandWindow
[[nodiscard]] LRESULT _OnNcCreate(WPARAM wParam, LPARAM lParam) noexcept override;
[[nodiscard]] LRESULT _OnNcCalcSize(const WPARAM wParam, const LPARAM lParam) noexcept;
+ [[nodiscard]] LRESULT _OnFocusChanged(const WPARAM wParam, const LPARAM lParam) noexcept;
[[nodiscard]] LRESULT _OnNcHitTest(POINT ptMouse) const noexcept;
[[nodiscard]] LRESULT _OnPaint() noexcept;
[[nodiscard]] LRESULT _OnSetCursor(WPARAM wParam, LPARAM lParam) const noexcept;