Apply a GDI region to the top level Island window to allow dragging with a single Island (#929)

* Use a region to cut off the dragable region
* Use proper measurements for the draggable area
* Working better, paint works most of the time
* Fix a bug where paint is incomplete when double clicking the dragbar
* Remove old fork on XamlApplication
* Upgrade to XamlApp preview6.2
* Add Microsoft.VCRTForwarders to make it easy to dogfood

Co-Authored-By: Michael Niksa <miniksa@microsoft.com>
Co-Authored-By: Mike Griese <migrie@microsoft.com>
This commit is contained in:
Oscar Calvo 2019-06-25 13:06:11 -07:00 committed by Dustin L. Howett (MSFT)
parent b115799810
commit ab08320dde
33 changed files with 480 additions and 635 deletions

View File

@ -1,7 +1,7 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27004.2008
# Visual Studio Version 16
VisualStudioVersion = 16.0.29001.49
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Terminal", "Terminal", "{59840756-302F-44DF-AA47-441A9D673202}"
EndProject
@ -202,8 +202,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TerminalSettings", "src\cas
EndProject
Project("{C7167F0D-BC9F-4E6E-AFE1-012C56B48DB5}") = "OpenConsolePackage", "pkg\appx\OpenConsolePackage.wapproj", "{2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.UI.Xaml.Markup", "src\cascadia\Microsoft.UI.Xaml.Markup\Microsoft.UI.Xaml.Markup.vcxproj", "{015A0047-772D-4F1A-88C9-45C18F0ADFB6}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UnitTests_TerminalCore", "src\cascadia\UnitTests_TerminalCore\UnitTests.vcxproj", "{2C2BEEF4-9333-4D05-B12A-1905CBF112F9}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Internal", "src\internal\internal.vcxproj", "{EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00}"
@ -1050,24 +1048,6 @@ Global
{2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.Release|x86.ActiveCfg = Release|x86
{2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.Release|x86.Build.0 = Release|x86
{2D310963-F3E0-4EE5-8AC6-FBC94DCC3310}.Release|x86.Deploy.0 = Release|x86
{015A0047-772D-4F1A-88C9-45C18F0ADFB6}.AuditMode|ARM64.ActiveCfg = Release|ARM64
{015A0047-772D-4F1A-88C9-45C18F0ADFB6}.AuditMode|ARM64.Build.0 = Release|ARM64
{015A0047-772D-4F1A-88C9-45C18F0ADFB6}.AuditMode|x64.ActiveCfg = Release|x64
{015A0047-772D-4F1A-88C9-45C18F0ADFB6}.AuditMode|x64.Build.0 = Release|x64
{015A0047-772D-4F1A-88C9-45C18F0ADFB6}.AuditMode|x86.ActiveCfg = Release|Win32
{015A0047-772D-4F1A-88C9-45C18F0ADFB6}.AuditMode|x86.Build.0 = Release|Win32
{015A0047-772D-4F1A-88C9-45C18F0ADFB6}.Debug|ARM64.ActiveCfg = Debug|ARM64
{015A0047-772D-4F1A-88C9-45C18F0ADFB6}.Debug|ARM64.Build.0 = Debug|ARM64
{015A0047-772D-4F1A-88C9-45C18F0ADFB6}.Debug|x64.ActiveCfg = Debug|x64
{015A0047-772D-4F1A-88C9-45C18F0ADFB6}.Debug|x64.Build.0 = Debug|x64
{015A0047-772D-4F1A-88C9-45C18F0ADFB6}.Debug|x86.ActiveCfg = Debug|Win32
{015A0047-772D-4F1A-88C9-45C18F0ADFB6}.Debug|x86.Build.0 = Debug|Win32
{015A0047-772D-4F1A-88C9-45C18F0ADFB6}.Release|ARM64.ActiveCfg = Release|ARM64
{015A0047-772D-4F1A-88C9-45C18F0ADFB6}.Release|ARM64.Build.0 = Release|ARM64
{015A0047-772D-4F1A-88C9-45C18F0ADFB6}.Release|x64.ActiveCfg = Release|x64
{015A0047-772D-4F1A-88C9-45C18F0ADFB6}.Release|x64.Build.0 = Release|x64
{015A0047-772D-4F1A-88C9-45C18F0ADFB6}.Release|x86.ActiveCfg = Release|Win32
{015A0047-772D-4F1A-88C9-45C18F0ADFB6}.Release|x86.Build.0 = Release|Win32
{2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.AuditMode|ARM64.ActiveCfg = AuditMode|ARM64
{2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.AuditMode|ARM64.Build.0 = AuditMode|ARM64
{2C2BEEF4-9333-4D05-B12A-1905CBF112F9}.AuditMode|x64.ActiveCfg = AuditMode|x64
@ -1173,7 +1153,6 @@ Global
{CA5CAD1A-44BD-4AC7-AC72-F16E576FDD12} = {59840756-302F-44DF-AA47-441A9D673202}
{CA5CAD1A-D7EC-4107-B7C6-79CB77AE2907} = {59840756-302F-44DF-AA47-441A9D673202}
{2D310963-F3E0-4EE5-8AC6-FBC94DCC3310} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
{015A0047-772D-4F1A-88C9-45C18F0ADFB6} = {59840756-302F-44DF-AA47-441A9D673202}
{2C2BEEF4-9333-4D05-B12A-1905CBF112F9} = {59840756-302F-44DF-AA47-441A9D673202}
{EF3E32A7-5FF6-42B4-B6E2-96CD7D033F00} = {E8F24881-5E37-4362-B191-A3BA0ED7F4EB}
{16376381-CE22-42BE-B667-C6B35007008D} = {81C352DB-1818-45B7-A284-18E259F1CC87}

View File

@ -1,3 +0,0 @@
EXPORTS
DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE
DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE

View File

@ -1,68 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<PropertyGroup>
<!-- cppwinrt.build.pre.props depends on these settings: -->
<!-- build a dll, not exe (Application) -->
<ConfigurationType>DynamicLibrary</ConfigurationType>
<SubSystem>Console</SubSystem>
<!-- sets a bunch of Windows Universal properties -->
<OpenConsoleUniversalApp>true</OpenConsoleUniversalApp>
</PropertyGroup>
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.pre.props" />
<PropertyGroup Label="Globals">
<ProjectGuid>{015a0047-772d-4f1a-88c9-45c18f0adfb6}</ProjectGuid>
<ProjectName>Microsoft.UI.Xaml.Markup</ProjectName>
<RootNamespace>Microsoft.UI.Xaml.Markup</RootNamespace>
</PropertyGroup>
<ItemDefinitionGroup>
<Link>
<OutputFile>$(OutDir)\$(TargetName)$(TargetExt)</OutputFile>
<AdditionalDependencies>WindowsApp.lib;Kernel32.lib;User32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
<ClInclude Include="XamlApplication.h">
<DependentUpon>XamlApplication.idl</DependentUpon>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="XamlApplication.cpp">
<DependentUpon>XamlApplication.idl</DependentUpon>
</ClCompile>
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
</ItemGroup>
<ItemGroup>
<Midl Include="XamlApplication.idl" />
</ItemGroup>
<ItemGroup>
<None Include="Microsoft.UI.Xaml.Markup.def" />
<None Include="packages.config" />
<None Include="ReadMe.md" />
</ItemGroup>
<PropertyGroup>
<!--
DON'T REDIRECT OUR OUTPUT.
Setting this will tell cppwinrt.build.post.props to copy our output from
the default OutDir up one level, so the wapproj will be able to find it.
-->
<NoOutputRedirection>true</NoOutputRedirection>
</PropertyGroup>
<Import Project="$(OpenConsoleDir)src\common.build.post.props" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
</Project>

View File

@ -1,22 +0,0 @@
# Xaml Application for Win32
This project implements an Xaml application that is suited for Win32 projects.
A pseudo implementation of this object is:
```
namespace Microsoft.UI.Xaml.Markup
{
interface IXamlMetadataProviderContainer
{
Windows.Foundation.Collections.IVector<Windows.UI.Xaml.Markup.IXamlMetadataProvider> Providers { get; };
};
class XamlApplication : Windows.UI.Xaml.Application, IXamlMetadataProviderContainer, IDisposable
{
XamlApplication()
{
WindowsXamlManager.InitializeForThread();
}
}
}
```

View File

@ -1,130 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"
#include "XamlApplication.h"
#include "XamlApplication.g.cpp"
namespace xaml = ::winrt::Windows::UI::Xaml;
extern "C" {
WINBASEAPI HMODULE WINAPI LoadLibraryExW(_In_ LPCWSTR lpLibFileName, _Reserved_ HANDLE hFile, _In_ DWORD dwFlags);
WINBASEAPI HMODULE WINAPI GetModuleHandleW(_In_opt_ LPCWSTR lpModuleName);
WINUSERAPI BOOL WINAPI PeekMessageW(_Out_ LPMSG lpMsg, _In_opt_ HWND hWnd, _In_ UINT wMsgFilterMin, _In_ UINT wMsgFilterMax, _In_ UINT wRemoveMsg);
WINUSERAPI LRESULT WINAPI DispatchMessageW(_In_ CONST MSG* lpMsg);
}
namespace winrt::Microsoft::UI::Xaml::Markup::implementation
{
XamlApplication::XamlApplication(winrt::Windows::UI::Xaml::Markup::IXamlMetadataProvider parentProvider)
{
m_providers.Append(parentProvider);
}
XamlApplication::XamlApplication()
{
}
void XamlApplication::Close()
{
if (m_bIsClosed)
{
return;
}
m_bIsClosed = true;
m_providers.Clear();
Exit();
{
MSG msg = {};
while (PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE))
{
::DispatchMessageW(&msg);
}
}
}
XamlApplication::~XamlApplication()
{
Close();
}
xaml::Markup::IXamlType XamlApplication::GetXamlType(xaml::Interop::TypeName const& type)
{
for (const auto& provider : m_providers)
{
const auto xamlType = provider.GetXamlType(type);
if (xamlType != nullptr)
{
return xamlType;
}
}
return nullptr;
}
xaml::Markup::IXamlType XamlApplication::GetXamlType(winrt::hstring const& fullName)
{
for (const auto& provider : m_providers)
{
const auto xamlType = provider.GetXamlType(fullName);
if (xamlType != nullptr)
{
return xamlType;
}
}
return nullptr;
}
winrt::com_array<xaml::Markup::XmlnsDefinition> XamlApplication::GetXmlnsDefinitions()
{
std::list<xaml::Markup::XmlnsDefinition> definitions;
for (const auto& provider : m_providers)
{
auto defs = provider.GetXmlnsDefinitions();
for (const auto& def : defs)
{
definitions.insert(definitions.begin(), def);
}
}
return winrt::com_array<xaml::Markup::XmlnsDefinition>(definitions.begin(), definitions.end());
}
winrt::Windows::Foundation::Collections::IVector<xaml::Markup::IXamlMetadataProvider> XamlApplication::Providers()
{
return m_providers;
}
}
namespace winrt::Microsoft::UI::Xaml::Markup::factory_implementation
{
XamlApplication::XamlApplication()
{
// Workaround a bug where twinapi.appcore.dll and threadpoolwinrt.dll gets loaded after it has been unloaded
// because of a call to GetActivationFactory
const wchar_t* preloadDlls[] = {
L"twinapi.appcore.dll",
L"threadpoolwinrt.dll",
};
for (auto dllName : preloadDlls)
{
const auto module = ::LoadLibraryExW(dllName, nullptr, 0);
m_preloadInstances.push_back(module);
}
}
XamlApplication::~XamlApplication()
{
for (auto module : m_preloadInstances)
{
::FreeLibrary(module);
}
m_preloadInstances.clear();
}
}

View File

@ -1,46 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include "XamlApplication.g.h"
#include <winrt/Windows.UI.Xaml.Hosting.h>
#include <winrt/Windows.UI.ViewManagement.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <Windows.h>
namespace winrt::Microsoft::UI::Xaml::Markup::implementation
{
class XamlApplication : public XamlApplicationT<XamlApplication, Windows::UI::Xaml::Markup::IXamlMetadataProvider>
{
public:
XamlApplication();
XamlApplication(winrt::Windows::UI::Xaml::Markup::IXamlMetadataProvider parentProvider);
~XamlApplication();
void Close();
winrt::Windows::UI::Xaml::Markup::IXamlType GetXamlType(winrt::Windows::UI::Xaml::Interop::TypeName const& type);
winrt::Windows::UI::Xaml::Markup::IXamlType GetXamlType(winrt::hstring const& fullName);
winrt::com_array<winrt::Windows::UI::Xaml::Markup::XmlnsDefinition> GetXmlnsDefinitions();
winrt::Windows::Foundation::Collections::IVector<winrt::Windows::UI::Xaml::Markup::IXamlMetadataProvider> Providers();
private:
winrt::Windows::Foundation::Collections::IVector<winrt::Windows::UI::Xaml::Markup::IXamlMetadataProvider> m_providers = winrt::single_threaded_vector<Windows::UI::Xaml::Markup::IXamlMetadataProvider>();
bool m_bIsClosed = false;
};
}
namespace winrt::Microsoft::UI::Xaml::Markup::factory_implementation
{
class XamlApplication : public XamlApplicationT<XamlApplication, implementation::XamlApplication>
{
public:
XamlApplication();
~XamlApplication();
private:
std::vector<HMODULE> m_preloadInstances;
};
}

View File

@ -1,17 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
namespace Microsoft.UI.Xaml.Markup
{
interface IXamlMetadataProviderContainer
{
Windows.Foundation.Collections.IVector<Windows.UI.Xaml.Markup.IXamlMetadataProvider> Providers { get; };
};
[default_interface]
unsealed runtimeclass XamlApplication : Windows.UI.Xaml.Application, IXamlMetadataProviderContainer, Windows.Foundation.IClosable
{
XamlApplication();
protected XamlApplication(Windows.UI.Xaml.Markup.IXamlMetadataProvider parentProvider);
}
}

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Windows.CppWinRT" version="2.0.190417.3" targetFramework="native" />
</packages>

View File

@ -1,4 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#include "pch.h"

View File

@ -1,21 +0,0 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
#pragma once
#include <SDKDDKVer.h>
// Exclude rarely-used stuff from Windows headers
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
// This is inexplicable, but for whatever reason, cppwinrt conflicts with the
// SDK definition of this function, so the only fix is to undef it.
// from WinBase.h
// Windows::UI::Xaml::Media::Animation::IStoryboard::GetCurrentTime
#ifdef GetCurrentTime
#undef GetCurrentTime
#endif
// To enable support for non-WinRT interfaces, unknwn.h must be included before any C++/WinRT headers.
#include <unknwn.h>
#include <winrt/Windows.Foundation.h>

View File

@ -0,0 +1,40 @@
#pragma once
namespace winrt::TerminalApp::implementation
{
template<typename D, typename... I>
struct App_baseWithProvider : public App_base<D, ::winrt::Windows::UI::Xaml::Markup::IXamlMetadataProvider>
{
using IXamlType = ::winrt::Windows::UI::Xaml::Markup::IXamlType;
IXamlType GetXamlType(::winrt::Windows::UI::Xaml::Interop::TypeName const& type)
{
return AppProvider()->GetXamlType(type);
}
IXamlType GetXamlType(::winrt::hstring const& fullName)
{
return AppProvider()->GetXamlType(fullName);
}
::winrt::com_array<::winrt::Windows::UI::Xaml::Markup::XmlnsDefinition> GetXmlnsDefinitions()
{
return AppProvider()->GetXmlnsDefinitions();
}
private:
bool _contentLoaded{ false };
std::shared_ptr<XamlMetaDataProvider> _appProvider;
std::shared_ptr<XamlMetaDataProvider> AppProvider()
{
if (!_appProvider)
{
_appProvider = std::make_shared<XamlMetaDataProvider>();
}
return _appProvider;
}
};
template<typename D, typename... I>
using AppT2 = App_baseWithProvider<D, I...>;
}

View File

@ -34,12 +34,6 @@ namespace winrt
namespace winrt::TerminalApp::implementation
{
App::App() :
App(winrt::TerminalApp::XamlMetaDataProvider())
{
}
App::App(Windows::UI::Xaml::Markup::IXamlMetadataProvider const& parentProvider) :
base_type(parentProvider),
_settings{},
_tabs{},
_loadedInitialSettings{ false },
@ -67,13 +61,13 @@ namespace winrt::TerminalApp::implementation
// - <none>
// Return Value:
// - <none>
void App::Create()
void App::Create(uint64_t hWnd)
{
// Assert that we've already loaded our settings. We have to do
// this as a MTA, before the app is Create()'d
WINRT_ASSERT(_loadedInitialSettings);
TraceLoggingRegister(g_hTerminalAppProvider);
_Create();
_Create(hWnd);
}
App::~App()
@ -87,7 +81,7 @@ namespace winrt::TerminalApp::implementation
// * Creates the tab content area, which is where we'll display the tabs/panes.
// * Initializes the first terminal control, using the default profile,
// and adds it to our list of tabs.
void App::_Create()
void App::_Create(uint64_t parentHwnd)
{
_tabView = MUX::Controls::TabView{};
@ -106,7 +100,6 @@ namespace winrt::TerminalApp::implementation
// another for the settings button.
auto tabsColDef = Controls::ColumnDefinition();
auto newTabBtnColDef = Controls::ColumnDefinition();
newTabBtnColDef.Width(GridLengthHelper::Auto());
_tabRow.ColumnDefinitions().Append(tabsColDef);
@ -119,11 +112,10 @@ namespace winrt::TerminalApp::implementation
_root.RowDefinitions().Append(tabBarRowDef);
_root.RowDefinitions().Append(Controls::RowDefinition{});
if (_settings->GlobalSettings().GetShowTabsInTitlebar() == false)
{
_root.Children().Append(_tabRow);
Controls::Grid::SetRow(_tabRow, 0);
}
_root.Children().Append(_tabRow);
Controls::Grid::SetRow(_tabRow, 0);
_root.Children().Append(_tabContent);
Controls::Grid::SetRow(_tabContent, 1);
Controls::Grid::SetColumn(_tabView, 0);
@ -147,7 +139,20 @@ namespace winrt::TerminalApp::implementation
_CreateNewTabFlyout();
_tabRow.Children().Append(_tabView);
_tabRow.Children().Append(_newTabButton);
if (_settings->GlobalSettings().GetShowTabsInTitlebar())
{
_minMaxCloseControl = winrt::TerminalApp::MinMaxCloseControl(parentHwnd);
Controls::Grid::SetRow(_minMaxCloseControl, 0);
Controls::Grid::SetColumn(_minMaxCloseControl, 1);
_minMaxCloseControl.Content().Children().Append(_newTabButton);
_tabRow.Children().Append(_minMaxCloseControl);
}
else
{
_tabRow.Children().Append(_newTabButton);
}
_tabContent.VerticalAlignment(VerticalAlignment::Stretch);
_tabContent.HorizontalAlignment(HorizontalAlignment::Stretch);
@ -466,6 +471,16 @@ namespace winrt::TerminalApp::implementation
winrt::Windows::System::Launcher::LaunchUriAsync({ L"https://github.com/microsoft/Terminal/issues" });
}
Windows::UI::Xaml::Controls::Border App::GetDragBar() noexcept
{
if (_minMaxCloseControl)
{
return _minMaxCloseControl.DragBar();
}
return nullptr;
}
// Method Description:
// - Called when the about button is clicked. See _ShowAboutDialog for more info.
// Arguments:

View File

@ -6,6 +6,7 @@
#include "Tab.h"
#include "CascadiaSettings.h"
#include "App.g.h"
#include "App.base.h"
#include "../../cascadia/inc/cppwinrt_utils.h"
#include <winrt/Microsoft.Terminal.TerminalControl.h>
@ -18,18 +19,18 @@
namespace winrt::TerminalApp::implementation
{
// We dont use AppT as it does not provide access to protected constructors
template<typename D, typename... I>
using AppT_Override = App_base<D, I...>;
struct App : AppT_Override<App>
struct App : AppT2<App>
{
public:
App();
Windows::UI::Xaml::UIElement GetRoot() noexcept;
Windows::UI::Xaml::UIElement GetTabs() noexcept;
void Create();
// Gets the current dragglable area in the non client region of the top level window
Windows::UI::Xaml::Controls::Border GetDragBar() noexcept;
void Create(uint64_t hParentWnd);
void LoadSettings();
Windows::Foundation::Point GetLaunchDimensions(uint32_t dpi);
@ -44,8 +45,6 @@ namespace winrt::TerminalApp::implementation
DECLARE_EVENT(LastTabClosed, _lastTabClosedHandlers, winrt::TerminalApp::LastTabClosedEventArgs);
private:
App(Windows::UI::Xaml::Markup::IXamlMetadataProvider const& parentProvider);
// If you add controls here, but forget to null them either here or in
// the ctor, you're going to have a bad time. It'll mysteriously fail to
// activate the app.
@ -57,6 +56,7 @@ namespace winrt::TerminalApp::implementation
Windows::UI::Xaml::Controls::Grid _tabRow{ nullptr };
Windows::UI::Xaml::Controls::Grid _tabContent{ nullptr };
Windows::UI::Xaml::Controls::SplitButton _newTabButton{ nullptr };
winrt::TerminalApp::MinMaxCloseControl _minMaxCloseControl{ nullptr };
std::vector<std::shared_ptr<Tab>> _tabs;
@ -71,7 +71,7 @@ namespace winrt::TerminalApp::implementation
std::atomic<bool> _settingsReloadQueued{ false };
void _Create();
void _Create(uint64_t parentHWnd);
void _CreateNewTabFlyout();
fire_and_forget _ShowDialog(const winrt::Windows::Foundation::IInspectable& titleElement,

View File

@ -5,7 +5,7 @@ namespace TerminalApp
{
delegate void LastTabClosedEventArgs();
[default_interface]
runtimeclass App : Microsoft.UI.Xaml.Markup.XamlApplication
runtimeclass App : Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication
{
App();
@ -14,12 +14,13 @@ namespace TerminalApp
// then it might look like TermApp just failed to activate, which will
// cause you to chase down the rabbit hole of "why is TermApp not
// registered?" when it definitely is.
void Create();
void Create(UInt64 hParentWnd);
void LoadSettings();
Windows.UI.Xaml.UIElement GetRoot();
Windows.UI.Xaml.UIElement GetTabs();
Windows.UI.Xaml.Controls.Border GetDragBar{ get; };
Windows.Foundation.Point GetLaunchDimensions(UInt32 dpi);
Boolean GetShowTabsInTitlebar();
@ -28,11 +29,5 @@ namespace TerminalApp
event LastTabClosedEventArgs LastTabClosed;
String GetTitle();
// IXamlMetadataProvider, Xaml.Application:
// Application's composing initializer will register the composing class
// as the toplevel "active" Xaml application. This Application (through IXamlMetadataProvider)
// will be queried for all unknown types during all Xaml and XBF (Xaml Binary Format) parse
// operations.
}
}

View File

@ -1,18 +1,18 @@
<!-- Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
the MIT License. See LICENSE in the project root for license information. -->
<MSMarkup:XamlApplication
<Toolkit:XamlApplication
x:Class="TerminalApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TerminalApp"
xmlns:MSMarkup="using:Microsoft.UI.Xaml.Markup"
xmlns:Toolkit="using:Microsoft.Toolkit.Win32.UI.XamlHost"
xmlns:TA="using:TerminalApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<!-- If you want to prove this works, then add `RequestedTheme="Light"` to
the properties on the XamlApplication -->
<MSMarkup:XamlApplication.Resources>
<Toolkit:XamlApplication.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
@ -60,5 +60,5 @@ the MIT License. See LICENSE in the project root for license information. -->
</ResourceDictionary>
</MSMarkup:XamlApplication.Resources>
</MSMarkup:XamlApplication>
</Toolkit:XamlApplication.Resources>
</Toolkit:XamlApplication>

View File

@ -0,0 +1,58 @@
//
// MinMaxCloseControl.xaml.cpp
// Implementation of the MinMaxCloseControl class
//
#include "pch.h"
#include "MinMaxCloseControl.h"
#include "MinMaxCloseControl.g.cpp"
namespace winrt::TerminalApp::implementation
{
MinMaxCloseControl::MinMaxCloseControl(uint64_t hWnd) :
_window(reinterpret_cast<HWND>(hWnd))
{
const winrt::Windows::Foundation::Uri resourceLocator{ L"ms-appx:///MinMaxCloseControl.xaml" };
winrt::Windows::UI::Xaml::Application::LoadComponent(*this, resourceLocator, winrt::Windows::UI::Xaml::Controls::Primitives::ComponentResourceLocation::Nested);
}
void MinMaxCloseControl::_OnMaximize(byte flag)
{
POINT point1 = {};
::GetCursorPos(&point1);
const LPARAM lParam = MAKELPARAM(point1.x, point1.y);
WINDOWPLACEMENT placement = { sizeof(placement) };
::GetWindowPlacement(_window, &placement);
if (placement.showCmd == SW_SHOWNORMAL)
{
::PostMessage(_window, WM_SYSCOMMAND, SC_MAXIMIZE | flag, lParam);
}
else if (placement.showCmd == SW_SHOWMAXIMIZED)
{
::PostMessage(_window, WM_SYSCOMMAND, SC_RESTORE | flag, lParam);
}
}
void MinMaxCloseControl::Maximize_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e)
{
_OnMaximize(HTMAXBUTTON);
}
void MinMaxCloseControl::DragBar_DoubleTapped(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Input::DoubleTappedRoutedEventArgs const& e)
{
_OnMaximize(HTCAPTION);
}
void MinMaxCloseControl::Minimize_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e)
{
::PostMessage(_window, WM_SYSCOMMAND, SC_MINIMIZE | HTMINBUTTON, 0);
}
void MinMaxCloseControl::Close_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e)
{
::PostQuitMessage(0);
}
}

View File

@ -0,0 +1,34 @@
//
// Declaration of the MainUserControl class.
//
#pragma once
#include "winrt/Windows.UI.Xaml.h"
#include "winrt/Windows.UI.Xaml.Markup.h"
#include "winrt/Windows.UI.Xaml.Interop.h"
#include "MinMaxCloseControl.g.h"
namespace winrt::TerminalApp::implementation
{
struct MinMaxCloseControl : MinMaxCloseControlT<MinMaxCloseControl>
{
MinMaxCloseControl(uint64_t hWnd);
void Minimize_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
void Maximize_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
void Close_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::RoutedEventArgs const& e);
void DragBar_DoubleTapped(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Input::DoubleTappedRoutedEventArgs const& e);
private:
void _OnMaximize(byte flag);
HWND _window = nullptr;
};
}
namespace winrt::TerminalApp::factory_implementation
{
struct MinMaxCloseControl : MinMaxCloseControlT<MinMaxCloseControl, implementation::MinMaxCloseControl>
{
};
}

View File

@ -0,0 +1,11 @@
namespace TerminalApp
{
[default_interface]
runtimeclass MinMaxCloseControl : Windows.UI.Xaml.Controls.StackPanel
{
MinMaxCloseControl(UInt64 hParentWnd);
Windows.UI.Xaml.Controls.Grid Content{ get; };
Windows.UI.Xaml.Controls.Border DragBar{ get; };
}
}

View File

@ -0,0 +1,21 @@
<StackPanel
x:Class="TerminalApp.MinMaxCloseControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:TerminalApp"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
Orientation="Horizontal"
d:DesignHeight="300"
d:DesignWidth="400">
<Grid x:Name="Content" ></Grid>
<Border Height="36.0" MinWidth="175.0" x:Name="DragBar" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" DoubleTapped="DragBar_DoubleTapped"/>
<Button Height="36.0" Width="40.0" x:Name="Minimize" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Click="Minimize_Click">_</Button>
<Button Height="36.0" Width="40.0" x:Name="Maximize" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Click="Maximize_Click">-</Button>
<Button Height="36.0" Width="40.0" x:Name="Close" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Click="Close_Click">X</Button>
</StackPanel>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview6.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview6.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<PropertyGroup>
<!-- cppwinrt.build.pre.props depends on these settings: -->
@ -15,7 +16,6 @@
<ProjectName>TerminalApp</ProjectName>
<RootNamespace>TerminalApp</RootNamespace>
</PropertyGroup>
<!-- ========================= XAML files ======================== -->
<ItemGroup>
<!-- HERE BE DRAGONS:
@ -33,9 +33,12 @@
<SubType>Designer</SubType>
</Page>
</ItemGroup> -->
<!-- ========================= Headers ======================== -->
<ItemGroup>
<ClInclude Include="App.base.h" />
<ClInclude Include="MinMaxCloseControl.h">
<DependentUpon>MinMaxCloseControl.xaml</DependentUpon>
</ClInclude>
<ClInclude Include="Tab.h" />
<ClInclude Include="Pane.h" />
<ClInclude Include="ColorScheme.h" />
@ -53,9 +56,15 @@
<DependentUpon>App.xaml</DependentUpon>
</ClInclude>
</ItemGroup>
<!-- ========================= Cpp Files ======================== -->
<ItemGroup>
<ClCompile Include="MinMaxCloseControl.cpp">
<DependentUpon>MinMaxCloseControl.xaml</DependentUpon>
</ClCompile>
<Midl Include="MinMaxCloseControl.idl">
<DependentUpon>MinMaxCloseControl.xaml</DependentUpon>
<SubType>Code</SubType>
</Midl>
<ClCompile Include="Tab.cpp" />
<ClCompile Include="Pane.cpp" />
<ClCompile Include="ColorScheme.cpp" />
@ -76,15 +85,12 @@
<DependentUpon>App.xaml</DependentUpon>
</ClCompile>
<ClCompile Include="$(GeneratedFilesDir)module.g.cpp" />
<!-- You _NEED_ to include this file and the jsoncpp IncludePath (below) if
you want to use jsoncpp -->
<ClCompile Include="$(OpenConsoleDir)\dep\jsoncpp\jsoncpp.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<!-- ========================= idl Files ======================== -->
<ItemGroup>
<Midl Include="App.idl">
@ -92,13 +98,11 @@
</Midl>
<Midl Include="AppKeyBindings.idl" />
</ItemGroup>
<!-- ========================= Misc Files ======================== -->
<ItemGroup>
<None Include="packages.config" />
<None Include="TerminalApp.def" />
</ItemGroup>
<!-- ========================= Project References ======================== -->
<ItemGroup>
<!--
@ -112,14 +116,12 @@
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\TerminalControl.vcxproj">
<Project>{CA5CAD1A-44BD-4AC7-AC72-6CA5B3AB89ED}</Project>
</ProjectReference>
<!-- This is needed to be able to reference the XamlApplication type. -->
<ProjectReference Include="..\Microsoft.UI.Xaml.Markup\Microsoft.UI.Xaml.Markup.vcxproj">
<Project>{015a0047-772d-4f1a-88c9-45c18f0adfb6}</Project>
<Private>true</Private>
<CopyLocalSatelliteAssemblies>true</CopyLocalSatelliteAssemblies>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Page Include="MinMaxCloseControl.xaml">
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<PropertyGroup>
<!--
@ -133,9 +135,8 @@
<ClCompile>
<AdditionalIncludeDirectories>$(OpenConsoleDir)\dep\jsoncpp\json;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>WindowsApp.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>User32.lib;WindowsApp.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<Import Project="$(OpenConsoleDir)src\common.build.post.props" />
@ -146,5 +147,8 @@
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.1.190405001-prerelease\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.1.190405001-prerelease\build\native\Microsoft.UI.Xaml.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview6.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview6.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview6.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview6.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
</Target>
</Project>
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview6.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview6.2\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
</Project>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.0.0-preview6.2" targetFramework="native" />
<package id="Microsoft.UI.Xaml" version="2.1.190405001-prerelease" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.190417.3" targetFramework="native" />
</packages>
</packages>

View File

@ -34,6 +34,7 @@
#include <winrt/Windows.UI.Xaml.Controls.Primitives.h>
#include <winrt/Windows.ui.xaml.media.h>
#include <winrt/Windows.ui.xaml.input.h>
#include <winrt/Windows.UI.Xaml.Hosting.h>
#include <windows.ui.xaml.media.dxinterop.h>

View File

@ -4,7 +4,7 @@
#include "pch.h"
#include "AppHost.h"
#include "../types/inc/Viewport.hpp"
#include "../types/inc/Utils.hpp"
#include "../types/inc/utils.hpp"
using namespace winrt::Windows::UI;
using namespace winrt::Windows::UI::Composition;
@ -14,15 +14,6 @@ using namespace winrt::Windows::Foundation::Numerics;
using namespace ::Microsoft::Console;
using namespace ::Microsoft::Console::Types;
// The tabs are 34.8px tall. This is their default height - we're not
// controlling the styling of the tabs at all currently. If we change the size
// of those, we'll need to change the size here, too. We can't get this size
// from the tab control until the control is added to a XAML element, and we
// can't create any XAML elements until we have a window, and we need to know
// this size before we can create a window, so unfortunately we're stuck
// hardcoding this.
const int NON_CLIENT_CONTENT_HEIGHT = static_cast<int>(std::round(34.8));
AppHost::AppHost() noexcept :
_app{},
_window{ nullptr }
@ -32,9 +23,6 @@ AppHost::AppHost() noexcept :
if (_useNonClientArea)
{
_window = std::make_unique<NonClientIslandWindow>();
auto pNcWindow = static_cast<NonClientIslandWindow*>(_window.get());
pNcWindow->SetNonClientHeight(NON_CLIENT_CONTENT_HEIGHT);
}
else
{
@ -53,6 +41,7 @@ AppHost::AppHost() noexcept :
AppHost::~AppHost()
{
_app.Close();
}
// Method Description:
@ -68,20 +57,17 @@ AppHost::~AppHost()
// - <none>
void AppHost::Initialize()
{
_app.Initialize();
_window->Initialize();
_app.Create();
const auto handle = _window->GetHandle();
_app.Create(reinterpret_cast<uint64_t>(handle));
_app.TitleChanged({ this, &AppHost::AppTitleChanged });
_app.LastTabClosed({ this, &AppHost::LastTabClosed });
AppTitleChanged(_app.GetTitle());
_window->SetRootContent(_app.GetRoot());
if (_useNonClientArea)
{
auto pNcWindow = static_cast<NonClientIslandWindow*>(_window.get());
pNcWindow->SetNonClientContent(_app.GetTabs());
}
_window->OnAppInitialized(_app);
}
// Method Description:

View File

@ -6,6 +6,8 @@
// Custom window messages
#define CM_UPDATE_TITLE (WM_USER)
#include <wil/resource.h>
template<typename T>
class BaseWindow
{
@ -26,7 +28,7 @@ public:
T* that = static_cast<T*>(cs->lpCreateParams);
WINRT_ASSERT(that);
WINRT_ASSERT(!that->_window);
that->_window = window;
that->_window = wil::unique_hwnd(window);
SetWindowLongPtr(window, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(that));
EnableNonClientDpiScaling(window);
@ -46,7 +48,7 @@ public:
{
case WM_DPICHANGED:
{
return HandleDpiChange(_window, wparam, lparam);
return HandleDpiChange(_window.get(), wparam, lparam);
}
case WM_DESTROY:
@ -90,12 +92,12 @@ public:
}
case CM_UPDATE_TITLE:
{
SetWindowTextW(_window, _title.c_str());
SetWindowTextW(_window.get(), _title.c_str());
break;
}
}
return DefWindowProc(_window, message, wparam, lparam);
return DefWindowProc(_window.get(), message, wparam, lparam);
}
// DPI Change handler. on WM_DPICHANGE resize the window
@ -125,18 +127,18 @@ public:
RECT GetWindowRect() const noexcept
{
RECT rc = { 0 };
::GetWindowRect(_window, &rc);
::GetWindowRect(_window.get(), &rc);
return rc;
}
HWND GetHandle() const noexcept
{
return _window;
return _window.get();
};
float GetCurrentDpiScale() const noexcept
{
const auto dpi = ::GetDpiForWindow(_window);
const auto dpi = ::GetDpiForWindow(_window.get());
const auto scale = static_cast<float>(dpi) / static_cast<float>(USER_DEFAULT_SCREEN_DPI);
return scale;
}
@ -145,7 +147,7 @@ public:
SIZE GetPhysicalSize() const noexcept
{
RECT rect = {};
GetClientRect(_window, &rect);
GetClientRect(_window.get(), &rect);
const auto windowsWidth = rect.right - rect.left;
const auto windowsHeight = rect.bottom - rect.top;
return SIZE{ windowsWidth, windowsHeight };
@ -162,10 +164,10 @@ public:
//// https://docs.microsoft.com/en-us/windows/desktop/hidpi/high-dpi-desktop-application-development-on-windows#per-monitor-and-per-monitor-v2-dpi-awareness
winrt::Windows::Foundation::Size GetLogicalSize(const SIZE physicalSize) const noexcept
{
const auto dpi = GetCurrentDpiScale();
const auto scale = GetCurrentDpiScale();
// 0.5 is to ensure that we pixel snap correctly at the edges, this is necessary with odd DPIs like 1.25, 1.5, 1, .75
const auto logicalWidth = (physicalSize.cx / dpi) + 0.5f;
const auto logicalHeigth = (physicalSize.cy / dpi) + 0.5f;
const auto logicalWidth = (physicalSize.cx / scale) + 0.5f;
const auto logicalHeigth = (physicalSize.cy / scale) + 0.5f;
return winrt::Windows::Foundation::Size(logicalWidth, logicalHeigth);
}
@ -183,12 +185,12 @@ public:
void UpdateTitle(std::wstring_view newTitle)
{
_title = newTitle;
PostMessageW(_window, CM_UPDATE_TITLE, 0, reinterpret_cast<LPARAM>(nullptr));
PostMessageW(_window.get(), CM_UPDATE_TITLE, 0, reinterpret_cast<LPARAM>(nullptr));
};
protected:
using base_type = BaseWindow<T>;
HWND _window = nullptr;
wil::unique_hwnd _window;
unsigned int _currentDpi = 0;
bool _inDpiChange = false;

View File

@ -27,6 +27,7 @@ IslandWindow::IslandWindow() noexcept :
IslandWindow::~IslandWindow()
{
_source.Close();
}
// Method Description:
@ -111,11 +112,11 @@ void IslandWindow::_HandleCreateWindow(const WPARAM, const LPARAM lParam) noexce
if (_pfnCreateCallback)
{
_pfnCreateCallback(_window, rc);
_pfnCreateCallback(_window.get(), rc);
}
ShowWindow(_window, SW_SHOW);
UpdateWindow(_window);
ShowWindow(_window.get(), SW_SHOW);
UpdateWindow(_window.get());
}
void IslandWindow::Initialize()
@ -125,23 +126,19 @@ void IslandWindow::Initialize()
_source = DesktopWindowXamlSource{};
auto interop = _source.as<IDesktopWindowXamlSourceNative>();
winrt::check_hresult(interop->AttachToWindow(_window));
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);
_rootGrid = winrt::Windows::UI::Xaml::Controls::Grid();
_source.Content(_rootGrid);
// Do a quick resize to force the island to paint
OnSize();
}
void IslandWindow::OnSize()
void IslandWindow::OnSize(const UINT width, const UINT height)
{
const auto physicalSize = GetPhysicalSize();
// update the interop window size
SetWindowPos(_interopWindowHandle, 0, 0, 0, physicalSize.cx, physicalSize.cy, SWP_SHOWWINDOW);
SetWindowPos(_interopWindowHandle, 0, 0, 0, width, height, SWP_SHOWWINDOW);
if (_rootGrid)
{
@ -187,9 +184,12 @@ void IslandWindow::OnSize()
// Arguments:
// - width: the new width of the window _in pixels_
// - height: the new height of the window _in pixels_
void IslandWindow::OnResize(const UINT /*width*/, const UINT /*height*/)
void IslandWindow::OnResize(const UINT width, const UINT height)
{
OnSize();
if (_interopWindowHandle)
{
OnSize(width, height);
}
}
// Method Description:
@ -206,8 +206,12 @@ void IslandWindow::OnRestore()
// TODO MSFT#21315817 Stop rendering island content when the app is minimized.
}
void IslandWindow::SetRootContent(winrt::Windows::UI::Xaml::UIElement content)
void IslandWindow::OnAppInitialized(winrt::TerminalApp::App app)
{
_rootGrid.Children().Clear();
_rootGrid.Children().Append(content);
_rootGrid.Children().Append(app.GetRoot());
// Do a quick resize to force the island to paint
const auto size = GetPhysicalSize();
OnSize(size.cx, size.cy);
}

View File

@ -14,19 +14,26 @@ public:
void MakeWindow() noexcept;
void Close();
virtual void OnSize();
virtual void OnSize(const UINT width, const UINT height);
[[nodiscard]] virtual LRESULT MessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept override;
void OnResize(const UINT width, const UINT height) override;
void OnMinimize() override;
void OnRestore() override;
void SetRootContent(winrt::Windows::UI::Xaml::UIElement content);
virtual void OnAppInitialized(winrt::TerminalApp::App app);
virtual void Initialize();
void Initialize();
void SetCreateCallback(std::function<void(const HWND, const RECT)> pfn) noexcept;
protected:
void ForceResize()
{
// Do a quick resize to force the island to paint
const auto size = GetPhysicalSize();
OnSize(size.cx, size.cy);
}
HWND _interopWindowHandle;
winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource _source;

View File

@ -26,10 +26,6 @@ constexpr int RECT_HEIGHT(const RECT* const pRect)
NonClientIslandWindow::NonClientIslandWindow() noexcept :
IslandWindow{},
_nonClientInteropWindowHandle{ nullptr },
_nonClientRootGrid{ nullptr },
_nonClientSource{ nullptr },
_maximizedMargins{ 0 },
_isMaximized{ false }
{
}
@ -38,162 +34,102 @@ NonClientIslandWindow::~NonClientIslandWindow()
{
}
// Method Description:
// - Used to initialize the XAML island for the non-client area. Also calls our
// base IslandWindow's Initialize, which will initialize the client XAML
// Island.
void NonClientIslandWindow::Initialize()
void NonClientIslandWindow::OnDragBarSizeChanged(winrt::Windows::Foundation::IInspectable sender, winrt::Windows::UI::Xaml::SizeChangedEventArgs eventArgs)
{
_nonClientSource = DesktopWindowXamlSource{};
auto interop = _nonClientSource.as<IDesktopWindowXamlSourceNative>();
winrt::check_hresult(interop->AttachToWindow(_window));
// stash the child interop handle so we can resize it when the main hwnd is resized
interop->get_WindowHandle(&_nonClientInteropWindowHandle);
_nonClientRootGrid = winrt::Windows::UI::Xaml::Controls::Grid{};
_nonClientSource.Content(_nonClientRootGrid);
// Call the IslandWindow Initialize to set up the client xaml island
IslandWindow::Initialize();
InvalidateRect(NULL, NULL, TRUE);
ForceResize();
}
// Method Description:
// - Sets the content of the non-client area of our window to the given XAML element.
// Arguments:
// - content: a XAML element to use as the content of the titlebar.
// Return Value:
// - <none>
void NonClientIslandWindow::SetNonClientContent(winrt::Windows::UI::Xaml::UIElement content)
void NonClientIslandWindow::OnAppInitialized(winrt::TerminalApp::App app)
{
_nonClientRootGrid.Children().Clear();
_nonClientRootGrid.Children().Append(content);
_dragBar = app.GetDragBar();
_rootGrid.SizeChanged({ this, &NonClientIslandWindow::OnDragBarSizeChanged });
IslandWindow::OnAppInitialized(app);
}
// Method Description:
// - Set the height we expect to reserve for the non-client content.
// Arguments:
// - contentHeight: the size in pixels we should use for the non-client content.
void NonClientIslandWindow::SetNonClientHeight(const int contentHeight) noexcept
RECT NonClientIslandWindow::GetDragAreaRect() const noexcept
{
_titlebarUnscaledContentHeight = contentHeight;
}
// Method Description:
// - Gets the size of the content area of the titlebar (the non-client area).
// This can be padded either by the margins from maximization (when the window
// is maximized) or the normal window borders.
// Return Value:
// - A Viewport representing the area of the window which should be the titlebar
// content, in window coordinates.
Viewport NonClientIslandWindow::GetTitlebarContentArea() const noexcept
{
const auto scale = GetCurrentDpiScale();
const auto titlebarContentHeight = _titlebarUnscaledContentHeight * scale;
const auto titlebarMarginRight = _titlebarMarginRight;
const auto physicalSize = GetPhysicalSize();
const auto clientWidth = physicalSize.cx;
auto titlebarWidth = clientWidth - (_windowMarginSides + titlebarMarginRight);
// Adjust for maximized margins
titlebarWidth -= (_maximizedMargins.cxLeftWidth + _maximizedMargins.cxRightWidth);
const auto titlebarHeight = titlebarContentHeight - (_titlebarMarginTop + _titlebarMarginBottom);
COORD titlebarOrigin = { static_cast<short>(_windowMarginSides),
static_cast<short>(_titlebarMarginTop) };
if (_isMaximized)
if (_dragBar)
{
titlebarOrigin.X = static_cast<short>(_maximizedMargins.cxLeftWidth);
titlebarOrigin.Y = static_cast<short>(_maximizedMargins.cyTopHeight);
const auto scale = GetCurrentDpiScale();
const auto transform = _dragBar.TransformToVisual(_rootGrid);
const auto logicalDragBarRect = winrt::Windows::Foundation::Rect{ 0.0f, 0.0f, static_cast<float>(_dragBar.ActualWidth()), static_cast<float>(_dragBar.ActualHeight()) };
const auto clientDragBarRect = transform.TransformBounds(logicalDragBarRect);
RECT dragBarRect = {
static_cast<LONG>(clientDragBarRect.X * scale),
static_cast<LONG>(clientDragBarRect.Y * scale),
static_cast<LONG>((clientDragBarRect.Width + clientDragBarRect.X) * scale),
static_cast<LONG>((clientDragBarRect.Height + clientDragBarRect.Y) * scale),
};
return dragBarRect;
}
return Viewport::FromDimensions(titlebarOrigin,
{ static_cast<short>(titlebarWidth), static_cast<short>(titlebarHeight) });
return RECT{};
}
// Method Description:
// - Gets the size of the client content area of the window.
// This can be padded either by the margins from maximization (when the window
// is maximized) or the normal window borders.
// Arguments:
// - <none>
// Return Value:
// - A Viewport representing the area of the window which should be the client
// content, in window coordinates.
Viewport NonClientIslandWindow::GetClientContentArea() const noexcept
// - called when the size of the window changes for any reason. Updates the
// sizes of our child Xaml Islands to match our new sizing.
void NonClientIslandWindow::OnSize(const UINT width, const UINT height)
{
MARGINS margins = GetFrameMargins();
if (!_interopWindowHandle)
{
return;
}
COORD clientOrigin = { static_cast<short>(margins.cxLeftWidth),
static_cast<short>(margins.cyTopHeight) };
const auto scale = GetCurrentDpiScale();
const auto dpi = ::GetDpiForWindow(_window.get());
const auto physicalSize = GetPhysicalSize();
auto clientWidth = physicalSize.cx;
auto clientHeight = physicalSize.cy;
const auto dragY = ::GetSystemMetricsForDpi(SM_CYDRAG, dpi);
const auto dragX = ::GetSystemMetricsForDpi(SM_CXDRAG, dpi);
// If we're maximized, we don't want to use the frame as our margins,
// instead we want to use the margins from the maximization. If we included
// the left&right sides of the frame in this calculation while maximized,
// you' have a few pixels of the window border on the sides while maximized,
// which most apps do not have.
if (_isMaximized)
{
clientWidth -= (_maximizedMargins.cxLeftWidth + _maximizedMargins.cxRightWidth);
clientHeight -= (margins.cyTopHeight + _maximizedMargins.cyBottomHeight);
clientOrigin.X = static_cast<short>(_maximizedMargins.cxLeftWidth);
}
else
{
// Remove the left and right width of the frame from the client area
clientWidth -= (margins.cxLeftWidth + margins.cxRightWidth);
clientHeight -= (margins.cyTopHeight + margins.cyBottomHeight);
}
const auto bordersWidth = _isMaximized ?
(_maximizedMargins.cxLeftWidth + _maximizedMargins.cxRightWidth) :
(dragX * 2);
const auto bordersHeight = _isMaximized ?
(_maximizedMargins.cyBottomHeight + _maximizedMargins.cyTopHeight) :
(dragY * 2);
// The top maximization margin is already included in the GetFrameMargins
// calcualtion.
const auto windowsWidth = width - bordersWidth;
const auto windowsHeight = height - bordersHeight;
const auto xPos = _isMaximized ? _maximizedMargins.cxLeftWidth : dragX;
const auto yPos = _isMaximized ? _maximizedMargins.cyTopHeight : dragY;
return Viewport::FromDimensions(clientOrigin,
{ static_cast<short>(clientWidth), static_cast<short>(clientHeight) });
}
// Method Description:
// - called when the size of the window changes for any reason. Updates the
// sizes of our child Xaml Islands to match our new sizing.
void NonClientIslandWindow::OnSize()
{
auto clientArea = GetClientContentArea();
auto titlebarArea = GetTitlebarContentArea();
// update the interop window size
SetWindowPos(_interopWindowHandle,
0,
clientArea.Left(),
clientArea.Top(),
clientArea.Width(),
clientArea.Height(),
SWP_SHOWWINDOW);
winrt::check_bool(SetWindowPos(_interopWindowHandle, HWND_BOTTOM, xPos, yPos, windowsWidth, windowsHeight, SWP_SHOWWINDOW));
if (_rootGrid)
{
const SIZE physicalSize{ clientArea.Width(), clientArea.Height() };
const auto logicalSize = GetLogicalSize(physicalSize);
_rootGrid.Width(logicalSize.Width);
_rootGrid.Height(logicalSize.Height);
winrt::Windows::Foundation::Size size{ (windowsWidth / scale) + 0.5f, (windowsHeight / scale) + 0.5f };
_rootGrid.Height(size.Height);
_rootGrid.Width(size.Width);
_rootGrid.Measure(size);
winrt::Windows::Foundation::Rect finalRect{};
_rootGrid.Arrange(finalRect);
}
// update the interop window size
SetWindowPos(_nonClientInteropWindowHandle,
0,
titlebarArea.Left(),
titlebarArea.Top(),
titlebarArea.Width(),
titlebarArea.Height(),
SWP_SHOWWINDOW);
if (_dragBar)
{
const auto dragBarRect = GetDragAreaRect();
const auto nonClientHeight = dragBarRect.bottom - dragBarRect.top;
auto nonClientRegion = wil::unique_hrgn(CreateRectRgn(0, 0, 0, 0));
auto nonClientLeftRegion = wil::unique_hrgn(CreateRectRgn(0, 0, dragBarRect.left, nonClientHeight));
auto nonClientRightRegion = wil::unique_hrgn(CreateRectRgn(dragBarRect.right, 0, windowsWidth, nonClientHeight));
winrt::check_bool(CombineRgn(nonClientRegion.get(), nonClientLeftRegion.get(), nonClientRightRegion.get(), RGN_OR));
_dragBarRegion = wil::unique_hrgn(CreateRectRgn(0, 0, 0, 0));
auto clientRegion = wil::unique_hrgn(CreateRectRgn(0, nonClientHeight, windowsWidth, windowsHeight));
winrt::check_bool(CombineRgn(_dragBarRegion.get(), nonClientRegion.get(), clientRegion.get(), RGN_OR));
winrt::check_bool(SetWindowRgn(_interopWindowHandle, _dragBarRegion.get(), true));
}
winrt::check_hresult(_UpdateFrameMargins());
}
// Method Description:
@ -268,13 +204,19 @@ void NonClientIslandWindow::OnSize()
// - A MARGINS struct containing the border dimensions we want.
MARGINS NonClientIslandWindow::GetFrameMargins() const noexcept
{
const auto titlebarView = GetTitlebarContentArea();
const auto scale = GetCurrentDpiScale();
const auto dpi = ::GetDpiForWindow(_window.get());
const auto windowMarginSides = ::GetSystemMetricsForDpi(SM_CXDRAG, dpi);
const auto windowMarginBottom = ::GetSystemMetricsForDpi(SM_CXDRAG, dpi);
const auto dragBarRect = GetDragAreaRect();
const auto nonClientHeight = dragBarRect.bottom - dragBarRect.top;
MARGINS margins{ 0 };
margins.cxLeftWidth = _windowMarginSides;
margins.cxRightWidth = _windowMarginSides;
margins.cyBottomHeight = _windowMarginBottom;
margins.cyTopHeight = titlebarView.BottomExclusive();
margins.cxLeftWidth = windowMarginSides;
margins.cxRightWidth = windowMarginSides;
margins.cyBottomHeight = windowMarginBottom;
margins.cyTopHeight = nonClientHeight + windowMarginBottom;
return margins;
}
@ -292,7 +234,7 @@ MARGINS NonClientIslandWindow::GetFrameMargins() const noexcept
// for the non-client content.
MARGINS margins = GetFrameMargins();
// Extend the frame into the client area.
return DwmExtendFrameIntoClientArea(_window, &margins);
return DwmExtendFrameIntoClientArea(_window.get(), &margins);
}
// Routine Description:
@ -313,8 +255,7 @@ MARGINS NonClientIslandWindow::GetFrameMargins() const noexcept
// origin in pixels. Measures the outer edges of the potential window.
// NOTE:
// Heavily taken from WindowMetrics::GetMaxWindowRectInPixels in conhost.
RECT NonClientIslandWindow::GetMaxWindowRectInPixels(const RECT* const prcSuggested,
_Out_opt_ UINT* pDpiSuggested)
RECT NonClientIslandWindow::GetMaxWindowRectInPixels(const RECT* const prcSuggested, _Out_opt_ UINT* pDpiSuggested)
{
// prepare rectangle
RECT rc = *prcSuggested;
@ -336,7 +277,7 @@ RECT NonClientIslandWindow::GetMaxWindowRectInPixels(const RECT* const prcSugges
else
{
// Otherwise, get the monitor from the window handle.
hMonitor = MonitorFromWindow(_window, MONITOR_DEFAULTTONEAREST);
hMonitor = MonitorFromWindow(_window.get(), MONITOR_DEFAULTTONEAREST);
}
// If for whatever reason there is no monitor, we're going to give back whatever we got since we can't figure anything out.
@ -357,7 +298,7 @@ RECT NonClientIslandWindow::GetMaxWindowRectInPixels(const RECT* const prcSugges
// We need to pad the work rectangle with the border dimensions to represent the actual max outer edges of the window rect.
WINDOWINFO wi = { 0 };
wi.cbSize = sizeof(WINDOWINFO);
GetWindowInfo(_window, &wi);
GetWindowInfo(_window.get(), &wi);
// In non-full screen, we want to only use the work area (avoiding the task bar space)
rc = MonitorInfo.rcWork;
@ -372,7 +313,7 @@ RECT NonClientIslandWindow::GetMaxWindowRectInPixels(const RECT* const prcSugges
}
else
{
*pDpiSuggested = GetDpiForWindow(_window);
*pDpiSuggested = GetDpiForWindow(_window.get());
}
}
@ -396,7 +337,7 @@ RECT NonClientIslandWindow::GetMaxWindowRectInPixels(const RECT* const prcSugges
// First call DwmDefWindowProc. This might handle things like the
// min/max/close buttons for us.
const bool dwmHandledMessage = DwmDefWindowProc(_window, message, wParam, lParam, &lRet);
const bool dwmHandledMessage = DwmDefWindowProc(_window.get(), message, wParam, lParam, &lRet);
switch (message)
{
@ -445,6 +386,75 @@ RECT NonClientIslandWindow::GetMaxWindowRectInPixels(const RECT* const prcSugges
}
break;
}
case WM_EXITSIZEMOVE:
{
ForceResize();
break;
}
case WM_NCACTIVATE:
case WM_NCPAINT:
{
if (!_dragBar)
{
return 0;
}
const auto hdc = wil::GetDC(_window.get());
if (hdc.get())
{
const auto scale = GetCurrentDpiScale();
const auto dpi = ::GetDpiForWindow(_window.get());
const auto dragY = ::GetSystemMetricsForDpi(SM_CYDRAG, dpi);
const auto dragX = ::GetSystemMetricsForDpi(SM_CXDRAG, dpi);
const auto xPos = _isMaximized ? _maximizedMargins.cxLeftWidth : dragX;
const auto yPos = _isMaximized ? _maximizedMargins.cyTopHeight : dragY;
const auto backgroundBrush = _dragBar.Background();
const auto backgroundSolidBrush = backgroundBrush.as<winrt::Windows::UI::Xaml::Media::SolidColorBrush>();
const auto backgroundColor = backgroundSolidBrush.Color();
const auto color = RGB(backgroundColor.R, backgroundColor.G, backgroundColor.B);
_backgroundBrush = wil::unique_hbrush(CreateSolidBrush(color));
RECT windowRect = {};
::GetWindowRect(_window.get(), &windowRect);
const auto cx = windowRect.right - windowRect.left;
const auto cy = windowRect.bottom - windowRect.top;
RECT clientRect = { 0, 0, cx, yPos };
::FillRect(hdc.get(), &clientRect, _backgroundBrush.get());
clientRect = { 0, 0, xPos, cy };
::FillRect(hdc.get(), &clientRect, _backgroundBrush.get());
clientRect = { 0, cy - yPos, cx, cy };
::FillRect(hdc.get(), &clientRect, _backgroundBrush.get());
clientRect = { cx - xPos, 0, cx, cy };
::FillRect(hdc.get(), &clientRect, _backgroundBrush.get());
RECT dragBarRect = GetDragAreaRect();
dragBarRect.left += xPos;
dragBarRect.right += xPos;
dragBarRect.bottom += yPos;
dragBarRect.top += yPos;
::FillRect(hdc.get(), &dragBarRect, _backgroundBrush.get());
}
return 0;
}
case WM_LBUTTONDOWN:
{
POINT point1 = {};
::GetCursorPos(&point1);
const auto region = HitTestNCA(point1);
if (region == HTCAPTION)
{
const auto longParam = MAKELPARAM(point1.x, point1.y);
::SetActiveWindow(_window.get());
::PostMessage(_window.get(), WM_SYSCOMMAND, SC_MOVE | HTCAPTION, longParam);
}
break;
}
case WM_WINDOWPOSCHANGING:
{
// Enforce maximum size here instead of WM_GETMINMAXINFO. If we return
@ -476,19 +486,6 @@ RECT NonClientIslandWindow::GetMaxWindowRectInPixels(const RECT* const prcSugges
// non-client area of the window.
void NonClientIslandWindow::_HandleActivateWindow()
{
const auto dpi = GetDpiForWindow(_window);
// Use DwmGetWindowAttribute to get the complete size of the caption buttons.
RECT captionSize{ 0 };
THROW_IF_FAILED(DwmGetWindowAttribute(_window, DWMWA_CAPTION_BUTTON_BOUNDS, &captionSize, sizeof(RECT)));
// Divide by 3 to get the width of a single button
// Multiply by 4 to reserve the space of one button as the "grab handle"
_titlebarMarginRight = MulDiv(RECT_WIDTH(&captionSize), 4, 3);
// _titlebarUnscaledContentHeight is set with SetNonClientHeight by the app
// hosting us.
THROW_IF_FAILED(_UpdateFrameMargins());
}
@ -561,7 +558,7 @@ bool NonClientIslandWindow::_HandleWindowPosChanging(WINDOWPOS* const windowPos)
}
}
const auto windowStyle = GetWindowStyle(_window);
const auto windowStyle = GetWindowStyle(_window.get());
const auto isMaximized = WI_IsFlagSet(windowStyle, WS_MAXIMIZE);
// If we're about to maximize the window, determine how much we're about to

View File

@ -22,6 +22,7 @@ Author(s):
#include "../../types/inc/Viewport.hpp"
#include <dwmapi.h>
#include <windowsx.h>
#include <wil\resource.h>
class NonClientIslandWindow : public IslandWindow
{
@ -29,37 +30,23 @@ public:
NonClientIslandWindow() noexcept;
virtual ~NonClientIslandWindow() override;
virtual void OnSize() override;
virtual void OnSize(const UINT width, const UINT height) override;
[[nodiscard]] virtual LRESULT MessageHandler(UINT const message, WPARAM const wparam, LPARAM const lparam) noexcept override;
void SetNonClientContent(winrt::Windows::UI::Xaml::UIElement content);
virtual void Initialize() override;
MARGINS GetFrameMargins() const noexcept;
void SetNonClientHeight(const int contentHeight) noexcept;
void OnAppInitialized(winrt::TerminalApp::App app) override;
private:
winrt::Windows::UI::Xaml::Hosting::DesktopWindowXamlSource _nonClientSource;
wil::unique_hbrush _backgroundBrush;
wil::unique_hrgn _dragBarRegion;
HWND _nonClientInteropWindowHandle;
winrt::Windows::UI::Xaml::Controls::Grid _nonClientRootGrid;
int _windowMarginBottom = 2;
int _windowMarginSides = 2;
int _titlebarMarginRight = 0;
int _titlebarMarginTop = 2;
int _titlebarMarginBottom = 0;
int _titlebarUnscaledContentHeight = 0;
::Microsoft::Console::Types::Viewport GetTitlebarContentArea() const noexcept;
::Microsoft::Console::Types::Viewport GetClientContentArea() const noexcept;
MARGINS _maximizedMargins;
MARGINS _maximizedMargins = { 0 };
bool _isMaximized;
winrt::Windows::UI::Xaml::Controls::Border _dragBar{ nullptr };
RECT GetDragAreaRect() const noexcept;
[[nodiscard]] LRESULT HitTestNCA(POINT ptMouse) const noexcept;
@ -68,5 +55,7 @@ private:
void _HandleActivateWindow();
bool _HandleWindowPosChanging(WINDOWPOS* const windowPos);
void OnDragBarSizeChanged(winrt::Windows::Foundation::IInspectable sender, winrt::Windows::UI::Xaml::SizeChangedEventArgs eventArgs);
RECT GetMaxWindowRectInPixels(const RECT* const prcSuggested, _Out_opt_ UINT* pDpiSuggested);
};

View File

@ -130,7 +130,7 @@
<activatableClass name="Microsoft.UI.Xaml.Media.RevealBorderBrush" threadingModel="both" xmlns="urn:schemas-microsoft-com:winrt.v1"></activatableClass>
<activatableClass name="Microsoft.UI.Xaml.XamlTypeInfo.XamlControlsXamlMetaDataProvider" threadingModel="both" xmlns="urn:schemas-microsoft-com:winrt.v1"></activatableClass>
</file>
<file name="Microsoft.UI.Xaml.Markup.dll" hashalg="SHA1">
<activatableClass name="Microsoft.UI.Xaml.Markup.XamlApplication" threadingModel="both" xmlns="urn:schemas-microsoft-com:winrt.v1"></activatableClass>
<file name="Microsoft.Toolkit.Win32.UI.XamlHost.dll" hashalg="SHA1">
<activatableClass name="Microsoft.Toolkit.Win32.UI.XamlHost.XamlApplication" threadingModel="both" xmlns="urn:schemas-microsoft-com:winrt.v1"></activatableClass>
</file>
</assembly>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview6.1\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview6.1\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" />
<Import Project="..\..\..\common.openconsole.props" Condition="'$(OpenConsoleDir)'==''" />
<PropertyGroup>
<ConfigurationType>Application</ConfigurationType>
@ -35,7 +36,7 @@
<AdditionalIncludeDirectories>"$(OpenConsoleDir)src\cascadia\TerminalCore\lib\Generated Files";%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<AdditionalDependencies>dwmapi.lib;Shcore.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>gdi32.lib;dwmapi.lib;Shcore.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<PropertyGroup>
@ -76,13 +77,19 @@
<DeploymentContent>true</DeploymentContent>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</NativeReferenceFile>
<!-- Manually include the xbf files from the app project as content files -->
<NativeReferenceFile Include="$(OpenConsoleDir)$(Platform)\$(Configuration)\TerminalApp\*.xbf">
<DeploymentContent>true</DeploymentContent>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</NativeReferenceFile>
<!--
The reason why this is needed for ARM64 is unknown,
If not added, the centenial package will fail to include the XamlHost dll.
-->
<NativeReferenceFile Include="$(OpenConsoleDir)$(Platform)\$(Configuration)\TerminalApp\Microsoft.Toolkit.Win32.UI.XamlHost.dll" Condition="'$(Platform)'=='ARM64'">
<DeploymentContent>true</DeploymentContent>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</NativeReferenceFile>
<!--
the packaging project wont recurse through our dependencies, you have to
make sure that if you add a cppwinrt dependency to any of these projects,
@ -92,7 +99,6 @@
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalControl\TerminalControl.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalConnection\TerminalConnection.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\TerminalApp\TerminalApp.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\cascadia\Microsoft.UI.Xaml.Markup\Microsoft.UI.Xaml.Markup.vcxproj" />
<ProjectReference Include="$(OpenConsoleDir)src\types\lib\types.vcxproj" />
</ItemGroup>
<!--
@ -116,7 +122,14 @@
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\..\packages\Microsoft.UI.Xaml.2.1.190405001-prerelease\build\native\Microsoft.UI.Xaml.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.UI.Xaml.2.1.190405001-prerelease\build\native\Microsoft.UI.Xaml.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.190521.3\build\native\Microsoft.Windows.ImplementationLibrary.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.190521.3\build\native\Microsoft.Windows.ImplementationLibrary.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview6.1\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview6.1\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.props'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview6.1\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview6.1\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets'))" />
<Error Condition="!Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.0-rc\build\native\Microsoft.VCRTForwarders.140.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.0-rc\build\native\Microsoft.VCRTForwarders.140.targets'))" />
</Target>
<Import Project="$(OpenConsoleDir)src\common.build.post.props" />
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
</Project>
<Import Project="..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.190521.3\build\native\Microsoft.Windows.ImplementationLibrary.targets" Condition="Exists('..\..\..\packages\Microsoft.Windows.ImplementationLibrary.1.0.190521.3\build\native\Microsoft.Windows.ImplementationLibrary.targets')" />
<Import Project="..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview6.1\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets" Condition="Exists('..\..\..\packages\Microsoft.Toolkit.Win32.UI.XamlApplication.6.0.0-preview6.1\build\native\Microsoft.Toolkit.Win32.UI.XamlApplication.targets')" />
<Import Project="..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.0-rc\build\native\Microsoft.VCRTForwarders.140.targets" Condition="Exists('..\..\..\packages\Microsoft.VCRTForwarders.140.1.0.0-rc\build\native\Microsoft.VCRTForwarders.140.targets')" />
</Project>

View File

@ -34,9 +34,6 @@ int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
// This works because Kenny Kerr said it would, and he wrote cpp/winrt, so he knows.
winrt::init_apartment(winrt::apartment_type::single_threaded);
// Initialize the Xaml Hosting Manager
auto manager = Windows::UI::Xaml::Hosting::WindowsXamlManager::InitializeForCurrentThread();
// Initialize the xaml content. This must be called AFTER the
// WindowsXamlManager is initalized.
host.Initialize();

View File

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Toolkit.Win32.UI.XamlApplication" version="6.0.0-preview6.1" targetFramework="native" />
<package id="Microsoft.UI.Xaml" version="2.1.190405001-prerelease" targetFramework="native" />
<package id="Microsoft.VCRTForwarders.140" version="1.0.0-rc" targetFramework="native" />
<package id="Microsoft.Windows.CppWinRT" version="2.0.190417.3" targetFramework="native" />
</packages>
<package id="Microsoft.Windows.ImplementationLibrary" version="1.0.190521.3" targetFramework="native" />
</packages>

View File

@ -41,6 +41,7 @@ Abstract:
#include <winrt/Windows.system.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.UI.Xaml.Hosting.h>
#include <winrt/Microsoft.Toolkit.Win32.UI.XamlHost.h>
#include <windows.ui.xaml.hosting.desktopwindowxamlsource.h>
// Additional headers for various xaml features. We need:
@ -48,3 +49,5 @@ Abstract:
// * Media for ScaleTransform
#include <winrt/Windows.UI.Xaml.Controls.h>
#include <winrt/Windows.ui.xaml.media.h>
#include <wil/resource.h>