Skip to content

Commit

Permalink
yea sure this works I guess
Browse files Browse the repository at this point in the history
  • Loading branch information
zadjii-msft committed May 19, 2023
1 parent 19ef8cc commit 3241ef0
Show file tree
Hide file tree
Showing 10 changed files with 295 additions and 62 deletions.
97 changes: 79 additions & 18 deletions src/cascadia/WindowsTerminal/AppHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ static constexpr short KeyPressed{ gsl::narrow_cast<short>(0x8000) };
AppHost::AppHost(const winrt::TerminalApp::AppLogic& logic,
winrt::Microsoft::Terminal::Remoting::WindowRequestedArgs args,
const Remoting::WindowManager& manager,
const Remoting::Peasant& peasant) noexcept :
const Remoting::Peasant& peasant,
std::unique_ptr<IslandWindow> window) noexcept :
_appLogic{ logic },
_windowLogic{ nullptr }, // don't make one, we're going to take a ref on app's
_windowManager{ manager },
Expand All @@ -44,13 +45,21 @@ AppHost::AppHost(const winrt::TerminalApp::AppLogic& logic,

// _HandleCommandlineArgs will create a _windowLogic
_useNonClientArea = _windowLogic.GetShowTabsInTitlebar();
if (_useNonClientArea)

if (window)
{
_window = std::make_unique<NonClientIslandWindow>(_windowLogic.GetRequestedTheme());
_window = std::move(window);
}
else
{
_window = std::make_unique<IslandWindow>();
if (_useNonClientArea)
{
_window = std::make_unique<NonClientIslandWindow>(_windowLogic.GetRequestedTheme());
}
else
{
_window = std::make_unique<IslandWindow>();
}
}

// Update our own internal state tracking if we're in quake mode or not.
Expand All @@ -65,16 +74,38 @@ AppHost::AppHost(const winrt::TerminalApp::AppLogic& logic,
std::placeholders::_2);
_window->SetCreateCallback(pfn);

_window->MouseScrolled({ this, &AppHost::_WindowMouseWheeled });
_window->WindowActivated({ this, &AppHost::_WindowActivated });
_window->WindowMoved({ this, &AppHost::_WindowMoved });
_windowCallbacks.MouseScrolled = _window->MouseScrolled({ this, &AppHost::_WindowMouseWheeled });
_windowCallbacks.WindowActivated = _window->WindowActivated({ this, &AppHost::_WindowActivated });
_windowCallbacks.WindowMoved = _window->WindowMoved({ this, &AppHost::_WindowMoved });
_windowCallbacks.ShouldExitFullscreen = _window->ShouldExitFullscreen({ &_windowLogic, &winrt::TerminalApp::TerminalWindow::RequestExitFullscreen });

_window->ShouldExitFullscreen({ &_windowLogic, &winrt::TerminalApp::TerminalWindow::RequestExitFullscreen });
// TODO! These call APIs that are re-entrant on the window message loop.
// If you call them in the ctor, then if we're being instantiated for a reheated thread, we'll deadlock.
// _window->SetAlwaysOnTop(_windowLogic.GetInitialAlwaysOnTop());
// _window->SetAutoHideWindow(_windowLogic.AutoHideWindow());

_window->SetAlwaysOnTop(_windowLogic.GetInitialAlwaysOnTop());
_window->SetAutoHideWindow(_windowLogic.AutoHideWindow());

_window->MakeWindow();
if (_window->GetHandle() == nullptr)
{
_window->MakeWindow();
}
else
{
// _window->Microwave();

//auto dispatcher = winrt::Windows::System::DispatcherQueue::GetForCurrentThread();
//dispatcher.TryEnqueue([this]() {
// // TODO! obv these bounds are wrong
// _HandleCreateWindow(_window->GetHandle(), til::rect{ 0, 0, 256, 256 });
//});

CREATESTRUCTW dumb{
.cy = 256,
.cx = 256,
.y = 0,
.x = 0,
};
PostMessageW(_window->GetHandle(), WM_CREATE, 0, (LPARAM)&dumb);
}
}

bool AppHost::OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down)
Expand Down Expand Up @@ -297,7 +328,7 @@ void AppHost::Initialize()

// Register the 'X' button of the window for a warning experience of multiple
// tabs opened, this is consistent with Alt+F4 closing
_window->WindowCloseButtonClicked([this]() {
_windowCallbacks.WindowCloseButtonClicked = _window->WindowCloseButtonClicked([this]() {
_CloseRequested(nullptr, nullptr);
});
// If the user requests a close in another way handle the same as if the 'X'
Expand All @@ -306,11 +337,11 @@ void AppHost::Initialize()

// Add an event handler to plumb clicks in the titlebar area down to the
// application layer.
_window->DragRegionClicked([this]() { _windowLogic.TitlebarClicked(); });
_windowCallbacks.DragRegionClicked = _window->DragRegionClicked([this]() { _windowLogic.TitlebarClicked(); });

_window->WindowVisibilityChanged([this](bool showOrHide) { _windowLogic.WindowVisibilityChanged(showOrHide); });
_windowCallbacks.WindowVisibilityChanged = _window->WindowVisibilityChanged([this](bool showOrHide) { _windowLogic.WindowVisibilityChanged(showOrHide); });

_window->UpdateSettingsRequested({ this, &AppHost::_requestUpdateSettings });
_windowCallbacks.UpdateSettingsRequested = _window->UpdateSettingsRequested({ this, &AppHost::_requestUpdateSettings });

_revokers.Initialized = _windowLogic.Initialized(winrt::auto_revoke, { this, &AppHost::_WindowInitializedHandler });
_revokers.RequestedThemeChanged = _windowLogic.RequestedThemeChanged(winrt::auto_revoke, { this, &AppHost::_UpdateTheme });
Expand All @@ -321,14 +352,14 @@ void AppHost::Initialize()
_revokers.SystemMenuChangeRequested = _windowLogic.SystemMenuChangeRequested(winrt::auto_revoke, { this, &AppHost::_SystemMenuChangeRequested });
_revokers.ChangeMaximizeRequested = _windowLogic.ChangeMaximizeRequested(winrt::auto_revoke, { this, &AppHost::_ChangeMaximizeRequested });

_window->MaximizeChanged([this](bool newMaximize) {
_windowCallbacks.MaximizeChanged = _window->MaximizeChanged([this](bool newMaximize) {
if (_windowLogic)
{
_windowLogic.Maximized(newMaximize);
}
});

_window->AutomaticShutdownRequested([this]() {
_windowCallbacks.AutomaticShutdownRequested = _window->AutomaticShutdownRequested([this]() {
// Raised when the OS is beginning an update of the app. We will quit,
// to save our state, before the OS manually kills us.
Remoting::WindowManager::RequestQuitAll(_peasant);
Expand Down Expand Up @@ -429,6 +460,36 @@ void AppHost::Close()
}
}

[[nodiscard]] std::unique_ptr<IslandWindow> AppHost::Refrigerate()
{
// After calling _window->Close() we should avoid creating more WinUI related actions.
// I suspect WinUI wouldn't like that very much. As such unregister all event handlers first.
_revokers = {};
_showHideWindowThrottler.reset();

// DO NOT CLOSE THE WINDOW
_window->Refrigerate();

_window->MouseScrolled(_windowCallbacks.MouseScrolled);
_window->WindowActivated(_windowCallbacks.WindowActivated);
_window->WindowMoved(_windowCallbacks.WindowMoved);
_window->ShouldExitFullscreen(_windowCallbacks.ShouldExitFullscreen);
_window->WindowCloseButtonClicked(_windowCallbacks.WindowCloseButtonClicked);
_window->DragRegionClicked(_windowCallbacks.DragRegionClicked);
_window->WindowVisibilityChanged(_windowCallbacks.WindowVisibilityChanged);
_window->UpdateSettingsRequested(_windowCallbacks.UpdateSettingsRequested);
_window->MaximizeChanged(_windowCallbacks.MaximizeChanged);
_window->AutomaticShutdownRequested(_windowCallbacks.AutomaticShutdownRequested);

if (_windowLogic)
{
_windowLogic.DismissDialog();
_windowLogic = nullptr;
}

return std::move(_window);
}

// Method Description:
// - Called every time when the active tab's title changes. We'll also fire off
// a window message so we can update the window's title on the main thread,
Expand Down
26 changes: 25 additions & 1 deletion src/cascadia/WindowsTerminal/AppHost.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,16 @@ class AppHost
AppHost(const winrt::TerminalApp::AppLogic& logic,
winrt::Microsoft::Terminal::Remoting::WindowRequestedArgs args,
const winrt::Microsoft::Terminal::Remoting::WindowManager& manager,
const winrt::Microsoft::Terminal::Remoting::Peasant& peasant) noexcept;
const winrt::Microsoft::Terminal::Remoting::Peasant& peasant,
std::unique_ptr<IslandWindow> window = nullptr) noexcept;

void AppTitleChanged(const winrt::Windows::Foundation::IInspectable& sender, winrt::hstring newTitle);
void LastTabClosed(const winrt::Windows::Foundation::IInspectable& sender, const winrt::TerminalApp::LastTabClosedEventArgs& args);
void Initialize();
void Close();

[[nodiscard]] std::unique_ptr<IslandWindow> Refrigerate();

bool OnDirectKeyEvent(const uint32_t vkey, const uint8_t scanCode, const bool down);
void SetTaskbarProgress(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::Foundation::IInspectable& args);

Expand Down Expand Up @@ -194,4 +198,24 @@ class AppHost
winrt::Microsoft::Terminal::Remoting::WindowManager::QuitAllRequested_revoker QuitAllRequested;
winrt::Microsoft::Terminal::Remoting::Peasant::SendContentRequested_revoker SendContentRequested;
} _revokers{};

// our IslandWindow is not a WinRT type. It can't make auto_revokers like
// the above. We also need to make sure to unregister ourself from the
// window when we refrigerate the window thread so that the window can later
// be re-used.
struct WindowRevokers
{
winrt::event_token MouseScrolled;
winrt::event_token WindowActivated;
winrt::event_token WindowMoved;
winrt::event_token ShouldExitFullscreen;
winrt::event_token WindowCloseButtonClicked;
winrt::event_token DragRegionClicked;
winrt::event_token WindowVisibilityChanged;
winrt::event_token UpdateSettingsRequested;
winrt::event_token MaximizeChanged;
winrt::event_token AutomaticShutdownRequested;
// LOAD BEARING!!
//If you add events here, make sure they're revokec in AppHost::Refrigerate
} _windowCallbacks{};
};
62 changes: 40 additions & 22 deletions src/cascadia/WindowsTerminal/IslandWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,24 @@ IslandWindow::~IslandWindow()

void IslandWindow::Close()
{
// auto a{ _source };
// winrt::detach_abi(_source);
if (_source)
{
_source.Close();
_source = nullptr;
}
}

void IslandWindow::Refrigerate() noexcept
{
_pfnCreateCallback = nullptr;
_pfnSnapDimensionCallback = nullptr;

_rootGrid.Children().Clear();
ShowWindow(_window.get(), SW_HIDE);
}

HWND IslandWindow::GetInteropHandle() const
{
return _interopWindowHandle;
Expand Down Expand Up @@ -295,38 +306,45 @@ LRESULT IslandWindow::_OnMoving(const WPARAM /*wParam*/, const LPARAM lParam)
return false;
}

void IslandWindow::Initialize()
// return true if this was a "cold" initialize, that didn't start XAML before.
bool IslandWindow::Initialize()
{
_source = DesktopWindowXamlSource{};
if (!_source)
{
_source = DesktopWindowXamlSource{};

auto interop = _source.as<IDesktopWindowXamlSourceNative>();
winrt::check_hresult(interop->AttachToWindow(_window.get()));
auto interop = _source.as<IDesktopWindowXamlSourceNative>();
winrt::check_hresult(interop->AttachToWindow(_window.get()));

// stash the child interop handle so we can resize it when the main hwnd is resized
interop->get_WindowHandle(&_interopWindowHandle);
// stash the child interop handle so we can resize it when the main hwnd is resized
interop->get_WindowHandle(&_interopWindowHandle);

// Immediately hide our XAML island hwnd. On earlier versions of Windows,
// this HWND could sometimes appear as an actual window in the taskbar
// without this!
ShowWindow(_interopWindowHandle, SW_HIDE);
// Immediately hide our XAML island hwnd. On earlier versions of Windows,
// this HWND could sometimes appear as an actual window in the taskbar
// without this!
ShowWindow(_interopWindowHandle, SW_HIDE);

_rootGrid = winrt::Windows::UI::Xaml::Controls::Grid();
_source.Content(_rootGrid);
_rootGrid = winrt::Windows::UI::Xaml::Controls::Grid();
_source.Content(_rootGrid);

// initialize the taskbar object
if (auto taskbar = wil::CoCreateInstanceNoThrow<ITaskbarList3>(CLSID_TaskbarList))
{
if (SUCCEEDED(taskbar->HrInit()))
// initialize the taskbar object
if (auto taskbar = wil::CoCreateInstanceNoThrow<ITaskbarList3>(CLSID_TaskbarList))
{
_taskbar = std::move(taskbar);
if (SUCCEEDED(taskbar->HrInit()))
{
_taskbar = std::move(taskbar);
}
}
}

_systemMenuNextItemId = IDM_SYSTEM_MENU_BEGIN;
_systemMenuNextItemId = IDM_SYSTEM_MENU_BEGIN;

// Enable vintage opacity by removing the XAML emergency backstop, GH#603.
// We don't really care if this failed or not.
TerminalTrySetTransparentBackground(true);

// Enable vintage opacity by removing the XAML emergency backstop, GH#603.
// We don't really care if this failed or not.
TerminalTrySetTransparentBackground(true);
return true;
}
return false;
}

void IslandWindow::OnSize(const UINT width, const UINT height)
Expand Down
6 changes: 5 additions & 1 deletion src/cascadia/WindowsTerminal/IslandWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "pch.h"
#include "BaseWindow.h"
#include <til/winrt.h>

void SetWindowLongWHelper(const HWND hWnd, const int nIndex, const LONG dwNewLong) noexcept;

Expand All @@ -21,6 +22,9 @@ class IslandWindow :

virtual void MakeWindow() noexcept;
virtual void Close();

void Refrigerate() noexcept;

virtual void OnSize(const UINT width, const UINT height);
HWND GetInteropHandle() const;

Expand All @@ -37,7 +41,7 @@ class IslandWindow :
virtual til::rect GetNonClientFrame(const UINT dpi) const noexcept;
virtual til::size GetTotalNonClientExclusiveSize(const UINT dpi) const noexcept;

virtual void Initialize();
virtual bool Initialize();

void SetCreateCallback(std::function<void(const HWND, const til::rect&)> pfn) noexcept;

Expand Down
10 changes: 6 additions & 4 deletions src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -335,9 +335,9 @@ void NonClientIslandWindow::OnAppInitialized()
IslandWindow::OnAppInitialized();
}

void NonClientIslandWindow::Initialize()
bool NonClientIslandWindow::Initialize()
{
IslandWindow::Initialize();
const bool coldInit = IslandWindow::Initialize();

_UpdateFrameMargins();

Expand Down Expand Up @@ -367,6 +367,8 @@ void NonClientIslandWindow::Initialize()
// then make sure to update its visual state to reflect if we're in the
// maximized state on launch.
_titlebar.Loaded([this](auto&&, auto&&) { _OnMaximizeChange(); });

return coldInit;
}

// Method Description:
Expand Down Expand Up @@ -519,8 +521,8 @@ void NonClientIslandWindow::_OnMaximizeChange() noexcept
const auto isIconified = WI_IsFlagSet(windowStyle, WS_ICONIC);

const auto state = _isMaximized ? winrt::TerminalApp::WindowVisualState::WindowVisualStateMaximized :
isIconified ? winrt::TerminalApp::WindowVisualState::WindowVisualStateIconified :
winrt::TerminalApp::WindowVisualState::WindowVisualStateNormal;
isIconified ? winrt::TerminalApp::WindowVisualState::WindowVisualStateIconified :
winrt::TerminalApp::WindowVisualState::WindowVisualStateNormal;

try
{
Expand Down
2 changes: 1 addition & 1 deletion src/cascadia/WindowsTerminal/NonClientIslandWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class NonClientIslandWindow : public IslandWindow
virtual til::rect GetNonClientFrame(UINT dpi) const noexcept override;
virtual til::size GetTotalNonClientExclusiveSize(UINT dpi) const noexcept override;

void Initialize() override;
bool Initialize() override;

void OnAppInitialized() override;
void SetContent(winrt::Windows::UI::Xaml::UIElement content) override;
Expand Down
Loading

1 comment on commit 3241ef0

@github-actions
Copy link

Choose a reason for hiding this comment

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

@check-spelling-bot Report

🔴 Please review

See the 📜action log for details.

Unrecognized words (4)

dtoring
DWXS
microwaved
revokec

Previously acknowledged words that are now absent Hirots NULs spand xwwyzz xxyyzz :arrow_right:
To accept ✔️ these unrecognized words as correct and remove the previously acknowledged and now absent words, run the following commands

... in a clone of the git@github.com:microsoft/terminal.git repository
on the dev/migrie/b/refrigerate-threads-for-later branch (ℹ️ how do I use this?):

curl -s -S -L 'https://raw.githubusercontent.com/check-spelling/check-spelling/v0.0.21/apply.pl' |
perl - 'https://github.com/microsoft/terminal/actions/runs/5028687221/attempts/1'
Errors (1)

See the 📜action log for details.

❌ Errors Count
❌ forbidden-pattern 1

See ❌ Event descriptions for more information.

✏️ Contributor please read this

By default the command suggestion will generate a file named based on your commit. That's generally ok as long as you add the file to your commit. Someone can reorganize it later.

⚠️ The command is written for posix shells. If it doesn't work for you, you can manually add (one word per line) / remove items to expect.txt and the excludes.txt files.

If the listed items are:

  • ... misspelled, then please correct them instead of using the command.
  • ... names, please add them to .github/actions/spelling/allow/names.txt.
  • ... APIs, you can add them to a file in .github/actions/spelling/allow/.
  • ... just things you're using, please add them to an appropriate file in .github/actions/spelling/expect/.
  • ... tokens you only need in one place and shouldn't generally be used, you can add an item in an appropriate file in .github/actions/spelling/patterns/.

See the README.md in each directory for more information.

🔬 You can test your commits without appending to a PR by creating a new branch with that extra change and pushing it to your fork. The check-spelling action will run in response to your push -- it doesn't require an open pull request. By using such a branch, you can limit the number of typos your peers see you make. 😉

If the flagged items are 🤯 false positives

If items relate to a ...

  • binary file (or some other file you wouldn't want to check at all).

    Please add a file path to the excludes.txt file matching the containing file.

    File paths are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your files.

    ^ refers to the file's path from the root of the repository, so ^README\.md$ would exclude README.md (on whichever branch you're using).

  • well-formed pattern.

    If you can write a pattern that would match it,
    try adding it to the patterns.txt file.

    Patterns are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your lines.

    Note that patterns can't match multiline strings.

Please sign in to comment.