mirror of https://github.com/microsoft/WSL
Merge latest master into feature/wsl-for-apps (#13749)
* Merge latest master into feature/wsl-for-apps * Fix test failure * Fix test failure * Fix test failure * Fix test failure
This commit is contained in:
parent
50bfffa09d
commit
dde52d075d
|
|
@ -58,6 +58,7 @@ IncludeCategories:
|
|||
- Regex: '^"(stdafx.h|pch.h|precomp.h)"$'
|
||||
Priority: -1
|
||||
IndentCaseLabels: false
|
||||
InsertBraces: true
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
|
|
|
|||
|
|
@ -267,15 +267,16 @@ else()
|
|||
endif()
|
||||
|
||||
# Determine the Visual Studio installation directory which contains LLVM tools
|
||||
# N.B. The version is set to VS2022 to ensure local runs match pipeline behavior
|
||||
execute_process(
|
||||
COMMAND "${VSWHERE_SOURCE_DIR}/vswhere.exe" -latest -products * -property installationPath
|
||||
COMMAND "${VSWHERE_SOURCE_DIR}/vswhere.exe" -version "[17.0,18.0)" -products * -property installationPath
|
||||
OUTPUT_VARIABLE VS_INSTALL_DIR
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
COMMAND_ERROR_IS_FATAL ANY
|
||||
)
|
||||
|
||||
if (NOT VS_INSTALL_DIR)
|
||||
message(FATAL_ERROR "Could not determine Visual Studio installation directory.")
|
||||
message(FATAL_ERROR "Could not determine Visual Studio 2022 installation directory.")
|
||||
endif()
|
||||
|
||||
if("${CMAKE_HOST_SYSTEM_PROCESSOR}" STREQUAL "AMD64")
|
||||
|
|
|
|||
|
|
@ -125,12 +125,12 @@
|
|||
"FriendlyName": "AlmaLinux OS 9",
|
||||
"Default": false,
|
||||
"Amd64Url": {
|
||||
"Url": "https://github.com/AlmaLinux/wsl-images/releases/download/v9.6.20250522.0/AlmaLinux-9.6_x64_20250522.0.wsl",
|
||||
"Sha256": "e0f6acf1ce5aff80f2e60d3d8191c0a3857720149a7e5521b96e11777cdd2779"
|
||||
"Url": "https://github.com/AlmaLinux/wsl-images/releases/download/v9.7.20251119.0/AlmaLinux-9.7_x64_20251119.0.wsl",
|
||||
"Sha256": "0a6588f4f723fcb3edbc37dd3e3e13be8ffe0a5027e47513e3d4d2a4451794e7"
|
||||
},
|
||||
"Arm64Url": {
|
||||
"Url": "https://github.com/AlmaLinux/wsl-images/releases/download/v9.6.20250522.0/AlmaLinux-9.6_ARM64_20250522.0.wsl",
|
||||
"Sha256": "58d1cc623c4570307825036460e51a406bdcf53b4b5a4148cf644f5f68ce48dd"
|
||||
"Url": "https://github.com/AlmaLinux/wsl-images/releases/download/v9.7.20251119.0/AlmaLinux-9.7_ARM64_20251119.0.wsl",
|
||||
"Sha256": "b3e2632efe029a81db1ae7a914ea3b7e9e6e20d8c71c158270c331e6fea39bf8"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -537,7 +537,7 @@ Argumentos para administrar distribuciones en el Subsistema de Windows para Linu
|
|||
|
||||
--export <Distro> <FileName> [Options]
|
||||
Exporta la distribución a un archivo tar.
|
||||
El nombre de archivo puede ser: para stdout.
|
||||
El nombre de archivo puede ser - para stdout.
|
||||
|
||||
Opciones:
|
||||
--format <Format>
|
||||
|
|
@ -545,7 +545,7 @@ Argumentos para administrar distribuciones en el Subsistema de Windows para Linu
|
|||
|
||||
--import <Distro> <InstallLocation> <FileName> [Options]
|
||||
Importa el archivo tar especificado como una nueva distribución.
|
||||
El nombre de archivo puede ser : para stdin.
|
||||
El nombre de archivo puede ser - para stdin.
|
||||
|
||||
Opciones:
|
||||
--version <Version>
|
||||
|
|
|
|||
|
|
@ -606,7 +606,7 @@ Argumenten voor het beheren van distributies in het Windows-subsysteem voor Linu
|
|||
"}{Locked="--quiet,"}{Locked="--verbose,"}{Locked="--online,"}{Locked="--install'"}{Locked="--set-default,"}{Locked="--set-version "}{Locked="--terminate,"}{Locked="--unregister "}Command line arguments, file names and string inserts should not be translated</comment>
|
||||
</data>
|
||||
<data name="MessagePackageVersions" xml:space="preserve">
|
||||
<value>WSL-versiie: {}
|
||||
<value>WSL-versie: {}
|
||||
Kernelversie: {}
|
||||
WSLg-versie: {}
|
||||
MSRDC-versie: {}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,9 @@ void SecCompDispatcher::Run()
|
|||
for (;;)
|
||||
{
|
||||
if (!wait_for_fd(m_notifyFd.get(), POLLIN))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Clear the buffers to make the 5.15 kernel happy.
|
||||
notification_buffer.clear();
|
||||
|
|
|
|||
|
|
@ -955,6 +955,7 @@ try
|
|||
//
|
||||
|
||||
if (Config.InitPid.has_value())
|
||||
{
|
||||
try
|
||||
{
|
||||
std::string LinkPath = std::format(WSL_INTEROP_SOCKET_FORMAT, WSL_TEMP_FOLDER, 1, WSL_INTEROP_SOCKET);
|
||||
|
|
@ -963,7 +964,8 @@ try
|
|||
LOG_ERROR("symlink({}, {}) failed {}", InteropServer.Path(), LinkPath.c_str(), errno);
|
||||
}
|
||||
}
|
||||
CATCH_LOG()
|
||||
CATCH_LOG()
|
||||
}
|
||||
|
||||
UtilCreateWorkerThread(
|
||||
"Interop", [InteropChannel = std::move(InteropChannel), InteropServer = std::move(InteropServer), Elevated, &Config]() mutable {
|
||||
|
|
|
|||
|
|
@ -221,6 +221,7 @@ int WslEntryPoint(int Argc, char* Argv[])
|
|||
{
|
||||
// Handle the special case for import result messages, everything else is sent to the binfmt interpreter.
|
||||
if (Pid == 1 && strcmp(BaseName, "init") == 0 && Argc == 3 && strcmp(Argv[1], LX_INIT_IMPORT_MESSAGE_ARG) == 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
wsl::shared::MessageWriter<LX_MINI_INIT_IMPORT_RESULT> message;
|
||||
|
|
@ -230,7 +231,8 @@ int WslEntryPoint(int Argc, char* Argv[])
|
|||
read(STDIN_FILENO, buffer, sizeof(buffer));
|
||||
exit(0);
|
||||
}
|
||||
CATCH_RETURN_ERRNO()
|
||||
CATCH_RETURN_ERRNO()
|
||||
}
|
||||
|
||||
ExitCode = CreateNtProcess(Argc - 1, &Argv[1]);
|
||||
}
|
||||
|
|
@ -327,6 +329,10 @@ int GenerateSystemdUnits(int Argc, char** Argv)
|
|||
File.reset();
|
||||
}
|
||||
|
||||
// Mask systemd-networkd-wait-online.service since WSL always ensures that networking is configured during boot.
|
||||
// That unit can cause systemd boot timeouts since WSL's network interface is unmanaged by systemd.
|
||||
THROW_LAST_ERROR_IF(symlink("/dev/null", std::format("{}/systemd-networkd-wait-online.service", installPath).c_str()) < 0);
|
||||
|
||||
// Only create the wslg unit if both enabled in wsl.conf, and if the wslg folder actually exists.
|
||||
if (enableGuiApps && access("/mnt/wslg/runtime-dir", F_OK) == 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -25,7 +25,9 @@ public:
|
|||
{
|
||||
std::unique_lock lck(m_mtx);
|
||||
while (m_value.has_value())
|
||||
{
|
||||
m_cv.wait(lck);
|
||||
}
|
||||
m_value = value;
|
||||
m_cv.notify_all();
|
||||
}
|
||||
|
|
@ -39,7 +41,9 @@ public:
|
|||
{
|
||||
std::unique_lock lck(m_mtx);
|
||||
while (!m_value.has_value())
|
||||
{
|
||||
m_cv.wait(lck);
|
||||
}
|
||||
auto return_value = m_value.value();
|
||||
m_value.reset();
|
||||
m_cv.notify_all();
|
||||
|
|
@ -57,8 +61,12 @@ public:
|
|||
{
|
||||
std::unique_lock lck(m_mtx);
|
||||
while (!m_value.has_value())
|
||||
{
|
||||
if (m_cv.wait_for(lck, timeout) == std::cv_status::timeout)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
auto return_value = m_value.value();
|
||||
m_value.reset();
|
||||
m_cv.notify_all();
|
||||
|
|
|
|||
|
|
@ -65,23 +65,41 @@ bool ParseArpReply(const T& ArpReply, uint16_t ProtocolType, const Neighbor& Sou
|
|||
Target.ipAddress.ConvertToBytes(TargetIp.data());
|
||||
|
||||
if (ArpReply.Destination != Source.macAddress)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (ArpReply.EthernetType != htons(ETH_P_ARP))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (ArpReply.HardwareType != htons(ARPHRD_ETHER))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (ArpReply.ProtocolType != htons(ProtocolType))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (ArpReply.HardwareAddressLength != sizeof(ArpReply.SenderHardwareAddress))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (ArpReply.ProtocolAddressLength != sizeof(ArpReply.SenderIpAddress))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (ArpReply.Operation != htons(ARPOP_REPLY))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (ArpReply.TargetHardwareAddress != Source.macAddress)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (ArpReply.TargetIpAddress != SourceIp)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Target.macAddress = ArpReply.SenderHardwareAddress;
|
||||
return true;
|
||||
|
|
@ -129,7 +147,9 @@ bool IpNeighborManager::PerformNeighborDiscovery(Neighbor& Local, Neighbor& Neig
|
|||
while (std::chrono::steady_clock::now() < expiry)
|
||||
{
|
||||
if (!wait_for_read(packet_socket.get(), std::chrono::duration_cast<std::chrono::milliseconds>(expiry - std::chrono::steady_clock::now())))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int bytes_read = Syscall(read, packet_socket.get(), &ArpReply, ArpPacketSize);
|
||||
if (bytes_read != ArpPacketSize)
|
||||
{
|
||||
|
|
@ -138,12 +158,16 @@ bool IpNeighborManager::PerformNeighborDiscovery(Neighbor& Local, Neighbor& Neig
|
|||
if (Local.getFamily() == AF_INET)
|
||||
{
|
||||
if (ParseArpReply(ArpReply.IPv4, ETH_P_IP, Local, Neighbor))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ParseArpReply(ArpReply.IPv6, ETH_P_IPV6, Local, Neighbor))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,10 +31,14 @@ public:
|
|||
bool adjust_head(long count)
|
||||
{
|
||||
if ((count + data_offset) < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((count + data_offset) > data_end_offset)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
data_offset += count;
|
||||
return true;
|
||||
|
|
@ -43,9 +47,13 @@ public:
|
|||
bool adjust_tail(long count)
|
||||
{
|
||||
if ((count + data_end_offset) < data_offset)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ((count + data_end_offset) > Buffer.size())
|
||||
{
|
||||
Buffer.resize(count + data_end_offset);
|
||||
}
|
||||
|
||||
data_end_offset += count;
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -2033,6 +2033,7 @@ int wsl::windows::common::WslClient::Main(_In_ LPCWSTR commandLine)
|
|||
|
||||
// Print error messages for failures.
|
||||
if (FAILED(result))
|
||||
{
|
||||
try
|
||||
{
|
||||
std::wstring errorString{};
|
||||
|
|
@ -2086,7 +2087,8 @@ int wsl::windows::common::WslClient::Main(_In_ LPCWSTR commandLine)
|
|||
}
|
||||
}
|
||||
}
|
||||
CATCH_LOG()
|
||||
CATCH_LOG()
|
||||
}
|
||||
|
||||
if (g_promptBeforeExit)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -400,6 +400,7 @@ void wsl::core::Config::Initialize(_In_opt_ HANDLE UserToken)
|
|||
|
||||
// Load NAT configuration from the registry.
|
||||
if (NetworkingMode == wsl::core::NetworkingMode::Nat)
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto machineKey = wsl::windows::common::registry::OpenLxssMachineKey();
|
||||
|
|
@ -410,10 +411,12 @@ void wsl::core::Config::Initialize(_In_opt_ HANDLE UserToken)
|
|||
const auto userKey = wsl::windows::common::registry::OpenLxssUserKey();
|
||||
NatIpAddress = wsl::windows::common::registry::ReadString(userKey.get(), nullptr, c_natIpAddress, L"");
|
||||
}
|
||||
CATCH_LOG()
|
||||
CATCH_LOG()
|
||||
}
|
||||
|
||||
// Due to an issue with Global Secure Access Client, do not use DNS tunneling if the service is present.
|
||||
if (EnableDnsTunneling)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Open a handle to the service control manager and check if the inbox service is registered.
|
||||
|
|
@ -438,7 +441,8 @@ void wsl::core::Config::Initialize(_In_opt_ HANDLE UserToken)
|
|||
}
|
||||
}
|
||||
}
|
||||
CATCH_LOG()
|
||||
CATCH_LOG()
|
||||
}
|
||||
|
||||
// Ensure that settings are consistent (disable features that require other features that are not present).
|
||||
if (EnableSafeMode)
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ int wsl::windows::common::socket::ReceiveNoThrow(
|
|||
Overlapped.hEvent = OverlappedEvent.get();
|
||||
DWORD BytesReturned{};
|
||||
if (WSARecv(Socket, &VectorBuffer, 1, &BytesReturned, &Flags, &Overlapped, nullptr) != 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
BytesReturned = SOCKET_ERROR;
|
||||
|
|
@ -117,6 +118,7 @@ int wsl::windows::common::socket::ReceiveNoThrow(
|
|||
// Receive will call GetLastError to look for the error code
|
||||
SetLastError(wil::ResultFromCaughtException());
|
||||
}
|
||||
}
|
||||
|
||||
return BytesReturned;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -378,11 +378,13 @@ wsl::windows::common::SvcComm::LaunchProcess(
|
|||
//
|
||||
|
||||
if ((WI_IsFlagSet(LaunchFlags, LXSS_LAUNCH_FLAG_ENABLE_INTEROP)) && (ServerPortHandle))
|
||||
{
|
||||
try
|
||||
{
|
||||
InitializeInterop(ServerPortHandle.get(), DistributionId);
|
||||
}
|
||||
CATCH_LOG()
|
||||
CATCH_LOG()
|
||||
}
|
||||
|
||||
ServerPortHandle.reset();
|
||||
|
||||
|
|
@ -473,11 +475,13 @@ wsl::windows::common::SvcComm::LaunchProcess(
|
|||
//
|
||||
|
||||
if (WI_IsFlagSet(LaunchFlags, LXSS_LAUNCH_FLAG_ENABLE_INTEROP))
|
||||
{
|
||||
try
|
||||
{
|
||||
SpawnWslHost(InteropSocket.get(), DistributionId, &InstanceId);
|
||||
}
|
||||
CATCH_LOG()
|
||||
CATCH_LOG()
|
||||
}
|
||||
|
||||
//
|
||||
// Begin reading messages from the utility vm.
|
||||
|
|
|
|||
|
|
@ -346,6 +346,7 @@ bool LxssInstance::RequestStop(_In_ bool Force)
|
|||
// Send the message to the init daemon to check if the instance can be terminated.
|
||||
bool shutdown = true;
|
||||
if (m_InitMessagePort)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto lock = m_InitMessagePort->Lock();
|
||||
|
|
@ -358,7 +359,8 @@ bool LxssInstance::RequestStop(_In_ bool Force)
|
|||
m_InitMessagePort->Receive(&terminateResponse, sizeof(terminateResponse));
|
||||
shutdown = terminateResponse.Result;
|
||||
}
|
||||
CATCH_LOG()
|
||||
CATCH_LOG()
|
||||
}
|
||||
|
||||
return shutdown;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2952,11 +2952,13 @@ void LxssUserSessionImpl::_DeleteDistributionLockHeld(_In_ const LXSS_DISTRO_CON
|
|||
if (PathFileExistsW(Configuration.VhdFilePath.c_str()))
|
||||
{
|
||||
if (m_utilityVm)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_utilityVm->EjectVhd(Configuration.VhdFilePath.c_str());
|
||||
}
|
||||
CATCH_LOG()
|
||||
CATCH_LOG()
|
||||
}
|
||||
|
||||
if (WI_IsFlagSet(Flags, LXSS_DELETE_DISTRO_FLAGS_VHD))
|
||||
{
|
||||
|
|
@ -2997,13 +2999,15 @@ void LxssUserSessionImpl::_DeleteDistributionLockHeld(_In_ const LXSS_DISTRO_CON
|
|||
|
||||
// Remove start menu shortcuts for WSLg applications.
|
||||
if (WI_IsFlagSet(Flags, LXSS_DELETE_DISTRO_FLAGS_WSLG_SHORTCUTS))
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto dllPath = wsl::windows::common::wslutil::GetBasePath() / WSLG_TS_PLUGIN_DLL;
|
||||
static LxssDynamicFunction<decltype(RemoveAppProvider)> removeAppProvider(dllPath.c_str(), "RemoveAppProvider");
|
||||
LOG_IF_FAILED(removeAppProvider(Configuration.Name.c_str()));
|
||||
}
|
||||
CATCH_LOG()
|
||||
CATCH_LOG()
|
||||
}
|
||||
|
||||
// If the basepath is empty, delete it.
|
||||
try
|
||||
|
|
@ -3059,11 +3063,13 @@ std::vector<DistributionRegistration> LxssUserSessionImpl::_EnumerateDistributio
|
|||
|
||||
// Ensure that the default distribution is still valid.
|
||||
if (!orphanedDistributions.empty())
|
||||
{
|
||||
try
|
||||
{
|
||||
_GetDefaultDistro(LxssKey);
|
||||
}
|
||||
CATCH_LOG()
|
||||
CATCH_LOG()
|
||||
}
|
||||
|
||||
return distributions;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -412,13 +412,15 @@ void WslCoreInstance::Initialize()
|
|||
|
||||
// Launch the interop server with the user's token.
|
||||
if (response.InteropPort != LX_INIT_UTILITY_VM_INVALID_PORT)
|
||||
{
|
||||
try
|
||||
{
|
||||
const wil::unique_socket socket{wsl::windows::common::hvsocket::Connect(m_runtimeId, response.InteropPort)};
|
||||
wil::unique_handle info{wsl::windows::common::helpers::LaunchInteropServer(
|
||||
nullptr, reinterpret_cast<HANDLE>(socket.get()), nullptr, nullptr, &m_runtimeId, m_userToken.get())};
|
||||
}
|
||||
CATCH_LOG()
|
||||
CATCH_LOG()
|
||||
}
|
||||
|
||||
// Initialization was successful.
|
||||
m_initialized = true;
|
||||
|
|
@ -463,6 +465,7 @@ bool WslCoreInstance::RequestStop(_In_ bool Force)
|
|||
bool shutdown = true;
|
||||
std::lock_guard lock(m_lock);
|
||||
if (m_initChannel)
|
||||
{
|
||||
try
|
||||
{
|
||||
LX_INIT_TERMINATE_INSTANCE terminateMessage{};
|
||||
|
|
@ -477,7 +480,8 @@ bool WslCoreInstance::RequestStop(_In_ bool Force)
|
|||
shutdown = message->Result;
|
||||
}
|
||||
}
|
||||
CATCH_LOG()
|
||||
CATCH_LOG()
|
||||
}
|
||||
|
||||
return shutdown;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -274,18 +274,21 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken
|
|||
// N.B. wslhost.exe is launched at medium integrity level and its lifetime
|
||||
// is tied to the lifetime of the utility VM.
|
||||
if (m_vmConfig.EnableDebugConsole || !m_vmConfig.DebugConsoleLogFile.empty())
|
||||
{
|
||||
try
|
||||
{
|
||||
m_vmConfig.EnableDebugConsole = true;
|
||||
m_comPipe0 = wsl::windows::common::helpers::GetUniquePipeName();
|
||||
}
|
||||
CATCH_LOG()
|
||||
CATCH_LOG()
|
||||
}
|
||||
|
||||
// If the system supports virtio console serial ports, use dmesg capture for telemetry and/or debug output.
|
||||
// Legacy serial is much slower, so this is not enabled without virtio console support.
|
||||
auto enableVirtioSerial = m_vmConfig.EnableVirtio && helpers::IsVirtioSerialConsoleSupported();
|
||||
m_vmConfig.EnableDebugShell &= enableVirtioSerial;
|
||||
if (enableVirtioSerial)
|
||||
{
|
||||
try
|
||||
{
|
||||
bool enableTelemetry = TraceLoggingProviderEnabled(g_hTraceLoggingProvider, WINEVENT_LEVEL_INFO, 0);
|
||||
|
|
@ -302,9 +305,11 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken
|
|||
// Initialize the guest telemetry logger.
|
||||
m_gnsTelemetryLogger = GuestTelemetryLogger::Create(VmId, m_vmExitEvent);
|
||||
}
|
||||
CATCH_LOG()
|
||||
CATCH_LOG()
|
||||
}
|
||||
|
||||
if (m_vmConfig.EnableDebugConsole)
|
||||
{
|
||||
try
|
||||
{
|
||||
// If specified, create a file to log the debug console output.
|
||||
|
|
@ -321,7 +326,8 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken
|
|||
wsl::windows::common::helpers::LaunchDebugConsole(
|
||||
m_comPipe0.c_str(), !!m_dmesgCollector, m_restrictedToken.get(), logFile ? logFile.get() : nullptr, !m_vmConfig.EnableTelemetry);
|
||||
}
|
||||
CATCH_LOG()
|
||||
CATCH_LOG()
|
||||
}
|
||||
|
||||
// Create the utility VM and store the runtime ID.
|
||||
std::wstring json = GenerateConfigJson();
|
||||
|
|
@ -393,12 +399,14 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken
|
|||
THROW_IF_FAILED(wil::ExpandEnvironmentStringsW(L"%SystemRoot%\\System32\\lxss\\lib", path));
|
||||
|
||||
if (wsl::windows::common::filesystem::FileExists(path.c_str()))
|
||||
{
|
||||
try
|
||||
{
|
||||
addShare(TEXT(LXSS_GPU_INBOX_LIB_SHARE), path.c_str());
|
||||
m_enableInboxGpuLibs = true;
|
||||
}
|
||||
CATCH_LOG()
|
||||
CATCH_LOG()
|
||||
}
|
||||
|
||||
#ifdef WSL_GPU_LIB_PATH
|
||||
|
||||
|
|
@ -475,6 +483,7 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken
|
|||
// the user does not have write access.
|
||||
ULONG swapLun = ULONG_MAX;
|
||||
if ((m_systemDistroDeviceId != ULONG_MAX) && (m_vmConfig.SwapSizeBytes > 0))
|
||||
{
|
||||
try
|
||||
{
|
||||
{
|
||||
|
|
@ -517,7 +526,8 @@ void WslCoreVm::Initialize(const GUID& VmId, const wil::shared_handle& UserToken
|
|||
|
||||
swapLun = AttachDiskLockHeld(m_vmConfig.SwapFilePath.c_str(), DiskType::VHD, MountFlags::None, {}, false, m_userToken.get());
|
||||
}
|
||||
CATCH_LOG()
|
||||
CATCH_LOG()
|
||||
}
|
||||
|
||||
// Validate that the requesting network mode is supported.
|
||||
//
|
||||
|
|
@ -770,11 +780,13 @@ WslCoreVm::~WslCoreVm() noexcept
|
|||
// If the notification did not arrive within the timeout, the VM is
|
||||
// forcefully terminated.
|
||||
if (forcedTerminate)
|
||||
{
|
||||
try
|
||||
{
|
||||
wsl::windows::common::hcs::TerminateComputeSystem(m_system.get());
|
||||
}
|
||||
CATCH_LOG()
|
||||
CATCH_LOG()
|
||||
}
|
||||
}
|
||||
|
||||
m_vmExitEvent.wait(UTILITY_VM_TERMINATE_TIMEOUT);
|
||||
|
|
@ -833,33 +845,40 @@ WslCoreVm::~WslCoreVm() noexcept
|
|||
}
|
||||
|
||||
if (WI_IsFlagSet(Entry.second.Flags, DiskStateFlags::AccessGranted))
|
||||
{
|
||||
try
|
||||
{
|
||||
wsl::windows::common::hcs::RevokeVmAccess(m_machineId.c_str(), Entry.first.Path.c_str());
|
||||
}
|
||||
CATCH_LOG()
|
||||
CATCH_LOG()
|
||||
}
|
||||
});
|
||||
|
||||
// Delete the swap vhd if one was created.
|
||||
if (m_swapFileCreated)
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto runAsUser = wil::impersonate_token(m_userToken.get());
|
||||
LOG_IF_WIN32_BOOL_FALSE(DeleteFileW(m_vmConfig.SwapFilePath.c_str()));
|
||||
}
|
||||
CATCH_LOG()
|
||||
CATCH_LOG()
|
||||
}
|
||||
|
||||
// Delete the temp folder if it was created.
|
||||
if (m_tempDirectoryCreated)
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto runAsUser = wil::impersonate_token(m_userToken.get());
|
||||
wil::RemoveDirectoryRecursive(m_tempPath.c_str());
|
||||
}
|
||||
CATCH_LOG()
|
||||
CATCH_LOG()
|
||||
}
|
||||
|
||||
// Delete the mstsc.exe local devices key if one was created.
|
||||
if (m_localDevicesKeyCreated)
|
||||
{
|
||||
try
|
||||
{
|
||||
const auto runAsUser = wil::impersonate_token(m_userToken.get());
|
||||
|
|
@ -867,7 +886,8 @@ WslCoreVm::~WslCoreVm() noexcept
|
|||
const auto key = wsl::windows::common::registry::CreateKey(userKey.get(), c_localDevicesKey, KEY_SET_VALUE);
|
||||
THROW_IF_WIN32_ERROR(::RegDeleteKeyValueW(key.get(), nullptr, m_machineId.c_str()));
|
||||
}
|
||||
CATCH_LOG()
|
||||
CATCH_LOG()
|
||||
}
|
||||
|
||||
WSL_LOG("TerminateVmStop");
|
||||
}
|
||||
|
|
@ -1583,6 +1603,7 @@ std::wstring WslCoreVm::GenerateConfigJson()
|
|||
// N.B. This is done because arm64 and some older amd64 processors do not support nested virtualization.
|
||||
// Nested virtualization not supported on Windows 10.
|
||||
if (m_vmConfig.EnableNestedVirtualization)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::vector<std::string> processorFeatures{};
|
||||
|
|
@ -1600,7 +1621,8 @@ std::wstring WslCoreVm::GenerateConfigJson()
|
|||
EMIT_USER_WARNING(wsl::shared::Localization::MessageNestedVirtualizationNotSupported());
|
||||
}
|
||||
}
|
||||
CATCH_LOG()
|
||||
CATCH_LOG()
|
||||
}
|
||||
|
||||
#ifdef _AMD64_
|
||||
|
||||
|
|
@ -1843,12 +1865,14 @@ void WslCoreVm::InitializeGuest()
|
|||
if (LXSS_ENABLE_GUI_APPS())
|
||||
{
|
||||
if (m_vmConfig.EnableVirtio)
|
||||
{
|
||||
try
|
||||
{
|
||||
MountSharedMemoryDevice(c_virtiofsClassId, L"wslg", L"wslg", WSLG_SHARED_MEMORY_SIZE_MB);
|
||||
m_sharedMemoryRoot = std::format(L"WSL\\{}\\wslg", m_machineId);
|
||||
}
|
||||
CATCH_LOG()
|
||||
CATCH_LOG()
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
|
||||
<StackPanel
|
||||
Margin="32,24"
|
||||
Margin="{StaticResource ContentPageMargin}"
|
||||
VerticalAlignment="Top"
|
||||
Orientation="Vertical"
|
||||
Spacing="12">
|
||||
|
|
|
|||
|
|
@ -1,15 +1,46 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Windows.UI.ViewManagement;
|
||||
|
||||
namespace WslSettings.Controls
|
||||
{
|
||||
public sealed partial class OOBEContent : UserControl
|
||||
{
|
||||
// Constants for hero image height calculations
|
||||
private const double BaseImageHeight = 280.0;
|
||||
private const double MinimumImageHeight = 200.0;
|
||||
|
||||
private static readonly UISettings Settings = new UISettings();
|
||||
|
||||
public OOBEContent()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
|
||||
// Set initial hero image height based on current text scaling
|
||||
UpdateHeroImageHeight();
|
||||
|
||||
// Subscribe to text scale factor changes for dynamic updates
|
||||
Settings.TextScaleFactorChanged += OnTextScaleFactorChanged;
|
||||
|
||||
// Ensure event cleanup when control is unloaded
|
||||
this.Unloaded += (s, e) => Settings.TextScaleFactorChanged -= OnTextScaleFactorChanged;
|
||||
}
|
||||
|
||||
private void UpdateHeroImageHeight()
|
||||
{
|
||||
double textScaleFactor = Settings.TextScaleFactor;
|
||||
|
||||
// Reduce image height when text scaling increases to preserve content space
|
||||
// Use inverse relationship: as text gets larger, image gets proportionally smaller
|
||||
HeroImageHeight = Math.Max(BaseImageHeight / textScaleFactor, MinimumImageHeight);
|
||||
}
|
||||
|
||||
private void OnTextScaleFactorChanged(UISettings sender, object args)
|
||||
{
|
||||
// Update hero image height when text scaling changes at runtime
|
||||
this.DispatcherQueue.TryEnqueue(() => UpdateHeroImageHeight());
|
||||
}
|
||||
|
||||
public string Title
|
||||
|
|
@ -46,6 +77,6 @@ namespace WslSettings.Controls
|
|||
public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register("Description", typeof(string), typeof(OOBEContent), new PropertyMetadata(default(string)));
|
||||
public static readonly DependencyProperty HeroImageProperty = DependencyProperty.Register("HeroImage", typeof(string), typeof(OOBEContent), new PropertyMetadata(default(string)));
|
||||
public static readonly DependencyProperty PageContentProperty = DependencyProperty.Register("PageContent", typeof(object), typeof(OOBEContent), new PropertyMetadata(new Grid()));
|
||||
public static readonly DependencyProperty HeroImageHeightProperty = DependencyProperty.Register("HeroImageHeight", typeof(double), typeof(OOBEContent), new PropertyMetadata(280.0));
|
||||
public static readonly DependencyProperty HeroImageHeightProperty = DependencyProperty.Register("HeroImageHeight", typeof(double), typeof(OOBEContent), new PropertyMetadata(BaseImageHeight));
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
// Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
|
||||
using CommunityToolkit.WinUI.Controls;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
|
@ -47,4 +49,39 @@ public class RuntimeHelper
|
|||
FindNextElementOptions fneo = new() { SearchRoot = button.XamlRoot.Content };
|
||||
FocusManager.TryMoveFocus(FocusNavigationDirection.Previous, fneo);
|
||||
}
|
||||
|
||||
public static void SetupSettingsExpanderFocusManagement(Microsoft.UI.Xaml.FrameworkElement expander, Microsoft.UI.Xaml.Controls.Control firstFocusableElement)
|
||||
{
|
||||
if (expander is CommunityToolkit.WinUI.Controls.SettingsExpander settingsExpander)
|
||||
{
|
||||
settingsExpander.RegisterPropertyChangedCallback(CommunityToolkit.WinUI.Controls.SettingsExpander.IsExpandedProperty, (sender, dp) =>
|
||||
{
|
||||
if (sender is CommunityToolkit.WinUI.Controls.SettingsExpander se && se.IsExpanded)
|
||||
{
|
||||
System.EventHandler<object>? layoutHandler = null;
|
||||
layoutHandler = (s, e) =>
|
||||
{
|
||||
se.LayoutUpdated -= layoutHandler;
|
||||
firstFocusableElement.Focus(Microsoft.UI.Xaml.FocusState.Keyboard);
|
||||
};
|
||||
|
||||
se.LayoutUpdated += layoutHandler;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetupExpanderFocusManagementByName(Microsoft.UI.Xaml.FrameworkElement parent, string expanderName, string textBoxName)
|
||||
{
|
||||
var expander = parent.FindName(expanderName) as Microsoft.UI.Xaml.FrameworkElement;
|
||||
var textBox = parent.FindName(textBoxName) as Microsoft.UI.Xaml.Controls.Control;
|
||||
|
||||
Debug.Assert(expander != null, $"Expander '{expanderName}' not found");
|
||||
Debug.Assert(textBox != null, $"TextBox '{textBoxName}' not found");
|
||||
|
||||
if (expander != null && textBox != null)
|
||||
{
|
||||
SetupSettingsExpanderFocusManagement(expander, textBox);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -80,7 +80,7 @@ namespace LibWsl
|
|||
|
||||
internal static bool __TryGetNativeToManagedMapping(IntPtr native, out global::LibWsl.WslConfig managed)
|
||||
{
|
||||
|
||||
|
||||
return NativeToManagedMap.TryGetValue(native, out managed);
|
||||
}
|
||||
|
||||
|
|
@ -171,7 +171,7 @@ namespace LibWsl
|
|||
|
||||
internal static bool __TryGetNativeToManagedMapping(IntPtr native, out global::LibWsl.WslConfigSetting managed)
|
||||
{
|
||||
|
||||
|
||||
return NativeToManagedMap.TryGetValue(native, out managed);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,12 @@
|
|||
xmlns:controls="using:WslSettings.Controls"
|
||||
behaviors:NavigationViewHeaderBehavior.HeaderMode="Never">
|
||||
|
||||
<Page.Resources>
|
||||
<DataTemplate x:Key="UnderlinedHyperlinkTemplate">
|
||||
<TextBlock Text="{Binding}" TextDecorations="Underline" />
|
||||
</DataTemplate>
|
||||
</Page.Resources>
|
||||
|
||||
<Grid Margin="{ThemeResource ContentPageMargin}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
|
|
@ -20,10 +26,10 @@
|
|||
<ctControls:SettingsExpander.Items>
|
||||
<ctControls:SettingsCard HorizontalContentAlignment="Left" ContentAlignment="Left" Margin="-42,0,0,0">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<HyperlinkButton x:Uid="Settings_IssuesLink" Margin="{StaticResource HyperlinkButtonNegativeMargin}" />
|
||||
<HyperlinkButton x:Uid="Settings_DocumentationLink" Margin="{StaticResource HyperlinkButtonNegativeMargin}" />
|
||||
<HyperlinkButton x:Uid="Settings_ReleaseNotesLink" Margin="{StaticResource HyperlinkButtonNegativeMargin}" />
|
||||
<HyperlinkButton x:Uid="Settings_PrivacyPolicyLink" Margin="{StaticResource HyperlinkButtonNegativeMargin}" />
|
||||
<HyperlinkButton x:Uid="Settings_IssuesLink" Margin="{StaticResource HyperlinkButtonNegativeMargin}" ContentTemplate="{StaticResource UnderlinedHyperlinkTemplate}" />
|
||||
<HyperlinkButton x:Uid="Settings_DocumentationLink" Margin="{StaticResource HyperlinkButtonNegativeMargin}" ContentTemplate="{StaticResource UnderlinedHyperlinkTemplate}" />
|
||||
<HyperlinkButton x:Uid="Settings_ReleaseNotesLink" Margin="{StaticResource HyperlinkButtonNegativeMargin}" ContentTemplate="{StaticResource UnderlinedHyperlinkTemplate}" />
|
||||
<HyperlinkButton x:Uid="Settings_PrivacyPolicyLink" Margin="{StaticResource HyperlinkButtonNegativeMargin}" ContentTemplate="{StaticResource UnderlinedHyperlinkTemplate}" />
|
||||
</StackPanel>
|
||||
</ctControls:SettingsCard>
|
||||
</ctControls:SettingsExpander.Items>
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@
|
|||
<ctControls:SettingsCard x:Uid="Settings_HWPerfCounters">
|
||||
<ToggleSwitch x:Uid="Settings_HWPerfCountersToggleSwitch" HorizontalAlignment="Right" MinWidth="0" IsOn="{x:Bind ViewModel.IsOnHWPerfCounters, Mode=TwoWay}"/>
|
||||
</ctControls:SettingsCard>
|
||||
<ctControls:SettingsExpander x:Uid="Settings_CustomKernelPath">
|
||||
<ctControls:SettingsExpander x:Name="CustomKernelPathExpander" x:Uid="Settings_CustomKernelPath">
|
||||
<TextBlock Style="{StaticResource TextBlockFilePathStyle}" Text="{x:Bind ViewModel.CustomKernelPath, Mode=OneWay}"/>
|
||||
<ctControls:SettingsExpander.Items>
|
||||
<ctControls:SettingsCard HorizontalContentAlignment="Left" ContentAlignment="Left" Margin="{StaticResource SettingsExpanderItemMargin}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox x:Uid="Settings_CustomKernelPathTextBox" Style="{StaticResource TextBoxFilePathStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
<TextBox x:Name="CustomKernelPathTextBox" x:Uid="Settings_CustomKernelPathTextBox" Style="{StaticResource TextBoxFilePathStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
Text="{x:Bind ViewModel.CustomKernelPath, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"/>
|
||||
<Button x:Uid="Settings_CustomKernelPathBrowseButton" Style="{StaticResource ButtonSettingStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
Click="CustomKernelPath_Click"/>
|
||||
|
|
@ -38,12 +38,12 @@
|
|||
</ctControls:SettingsCard>
|
||||
</ctControls:SettingsExpander.Items>
|
||||
</ctControls:SettingsExpander>
|
||||
<ctControls:SettingsExpander x:Uid="Settings_CustomKernelModulesPath">
|
||||
<ctControls:SettingsExpander x:Name="CustomKernelModulesPathExpander" x:Uid="Settings_CustomKernelModulesPath">
|
||||
<TextBlock Style="{StaticResource TextBlockFilePathStyle}" Text="{x:Bind ViewModel.CustomKernelModulesPath, Mode=OneWay}"/>
|
||||
<ctControls:SettingsExpander.Items>
|
||||
<ctControls:SettingsCard HorizontalContentAlignment="Left" ContentAlignment="Left" Margin="{StaticResource SettingsExpanderItemMargin}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox x:Uid="Settings_CustomKernelModulesPathTextBox" Style="{StaticResource TextBoxFilePathStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
<TextBox x:Name="CustomKernelModulesPathTextBox" x:Uid="Settings_CustomKernelModulesPathTextBox" Style="{StaticResource TextBoxFilePathStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
Text="{x:Bind ViewModel.CustomKernelModulesPath, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"/>
|
||||
<Button x:Uid="Settings_CustomKernelModulesPathBrowseButton" Style="{StaticResource ButtonSettingStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
Click="CustomKernelModulesPath_Click"/>
|
||||
|
|
@ -51,7 +51,7 @@
|
|||
</ctControls:SettingsCard>
|
||||
</ctControls:SettingsExpander.Items>
|
||||
</ctControls:SettingsExpander>
|
||||
<ctControls:SettingsExpander x:Uid="Settings_CustomSystemDistroPath">
|
||||
<ctControls:SettingsExpander x:Name="CustomSystemDistroPathExpander" x:Uid="Settings_CustomSystemDistroPath">
|
||||
<ctControls:SettingsExpander.Description>
|
||||
<controls:HyperlinkTextBlock x:Uid="Settings_CustomSystemDistroPathDescription"/>
|
||||
</ctControls:SettingsExpander.Description>
|
||||
|
|
@ -59,7 +59,7 @@
|
|||
<ctControls:SettingsExpander.Items>
|
||||
<ctControls:SettingsCard HorizontalContentAlignment="Left" ContentAlignment="Left" Margin="{StaticResource SettingsExpanderItemMargin}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox x:Uid="Settings_CustomSystemDistroPathTextBox" Style="{StaticResource TextBoxFilePathStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
<TextBox x:Name="CustomSystemDistroPathTextBox" x:Uid="Settings_CustomSystemDistroPathTextBox" Style="{StaticResource TextBoxFilePathStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
Text="{x:Bind ViewModel.CustomSystemDistroPath, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"/>
|
||||
<Button x:Uid="Settings_CustomSystemDistroPathBrowseButton" Style="{StaticResource ButtonSettingStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
Click="CustomSystemDistroPath_Click"/>
|
||||
|
|
|
|||
|
|
@ -27,6 +27,15 @@ public sealed partial class DeveloperPage : Page
|
|||
FrameworkElementAutomationPeer.FromElement(Settings_ErrorTryAgainLater).RaiseAutomationEvent(AutomationEvents.LiveRegionChanged);
|
||||
}
|
||||
});
|
||||
|
||||
this.Loaded += OnPageLoaded;
|
||||
}
|
||||
|
||||
private void OnPageLoaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
RuntimeHelper.SetupExpanderFocusManagementByName(this, "CustomKernelPathExpander", "CustomKernelPathTextBox");
|
||||
RuntimeHelper.SetupExpanderFocusManagementByName(this, "CustomKernelModulesPathExpander", "CustomKernelModulesPathTextBox");
|
||||
RuntimeHelper.SetupExpanderFocusManagementByName(this, "CustomSystemDistroPathExpander", "CustomSystemDistroPathTextBox");
|
||||
}
|
||||
|
||||
override protected void OnNavigatedFrom(NavigationEventArgs e)
|
||||
|
|
|
|||
|
|
@ -18,12 +18,12 @@
|
|||
<ScrollViewer Grid.Row="2" VerticalScrollBarVisibility="Auto"
|
||||
Visibility="{x:Bind ViewModel.SettingsContentVisibility, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
||||
<ctControls:SettingsExpander x:Uid="Settings_DefaultVHDSize">
|
||||
<ctControls:SettingsExpander x:Name="DefaultVHDSizeExpander" x:Uid="Settings_DefaultVHDSize">
|
||||
<TextBlock Style="{StaticResource TextBlockSettingStyle}" Text="{x:Bind ViewModel.DefaultVHDSize, Mode=OneWay, Converter={StaticResource MegabyteStringConverter}}"/>
|
||||
<ctControls:SettingsExpander.Items>
|
||||
<ctControls:SettingsCard HorizontalContentAlignment="Left" ContentAlignment="Left" Margin="{StaticResource SettingsExpanderItemMargin}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox x:Uid="Settings_DefaultVHDSizeTextBox" Style="{StaticResource TextBoxSettingStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
<TextBox x:Name="DefaultVHDSizeTextBox" x:Uid="Settings_DefaultVHDSizeTextBox" Style="{StaticResource TextBoxSettingStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
Text="{x:Bind ViewModel.DefaultVHDSize, Mode=TwoWay, UpdateSourceTrigger=LostFocus, Converter={StaticResource MegabyteNumberConverter}}" TextChanged="DefaultVHDSizeTextBox_TextChanged"/>
|
||||
<Button x:Uid="Settings_DefaultVHDSizeResetButton" Style="{StaticResource ButtonSettingStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
Command="{x:Bind ViewModel.DefaultVHDSize_ResetCommand}" IsEnabled="{x:Bind ViewModel.DefaultVHDSize_ResetEnabled, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
// Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
|
||||
using CommunityToolkit.WinUI.Controls;
|
||||
using Microsoft.UI.Xaml.Automation.Peers;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Microsoft.UI.Xaml.Navigation;
|
||||
using System.Diagnostics;
|
||||
using WslSettings.Contracts.Services;
|
||||
using WslSettings.ViewModels.Settings;
|
||||
|
||||
|
|
@ -26,6 +28,8 @@ public sealed partial class FileSystemPage : Page
|
|||
FrameworkElementAutomationPeer.FromElement(Settings_ErrorTryAgainLater).RaiseAutomationEvent(AutomationEvents.LiveRegionChanged);
|
||||
}
|
||||
});
|
||||
|
||||
this.Loaded += OnPageLoaded;
|
||||
}
|
||||
|
||||
override protected void OnNavigatedFrom(NavigationEventArgs e)
|
||||
|
|
@ -53,4 +57,18 @@ public sealed partial class FileSystemPage : Page
|
|||
TextBox? textBox = sender as TextBox;
|
||||
ViewModel.SetDefaultVHDSize_ResetEnabled(textBox!.Text);
|
||||
}
|
||||
|
||||
private void OnPageLoaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
var expander = this.FindName("DefaultVHDSizeExpander") as SettingsExpander;
|
||||
var textBox = this.FindName("DefaultVHDSizeTextBox") as TextBox;
|
||||
|
||||
Debug.Assert(expander != null, "DefaultVHDSizeExpander not found");
|
||||
Debug.Assert(textBox != null, "DefaultVHDSizeTextBox not found");
|
||||
|
||||
if (expander != null && textBox != null)
|
||||
{
|
||||
RuntimeHelper.SetupSettingsExpanderFocusManagement(expander, textBox);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,12 +18,12 @@
|
|||
<ScrollViewer Grid.Row="2" VerticalScrollBarVisibility="Auto"
|
||||
Visibility="{x:Bind ViewModel.SettingsContentVisibility, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||
<StackPanel Spacing="{StaticResource SettingsCardSpacing}">
|
||||
<ctControls:SettingsExpander x:Uid="Settings_ProcCount">
|
||||
<ctControls:SettingsExpander x:Name="ProcCountExpander" x:Uid="Settings_ProcCount">
|
||||
<TextBlock Style="{StaticResource TextBlockSettingStyle}" Text="{x:Bind ViewModel.ProcCount, Mode=OneWay}"/>
|
||||
<ctControls:SettingsExpander.Items>
|
||||
<ctControls:SettingsCard HorizontalContentAlignment="Left" ContentAlignment="Left" Margin="{StaticResource SettingsExpanderItemMargin}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox x:Uid="Settings_ProcCountTextBox" Style="{StaticResource TextBoxSettingStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
<TextBox x:Name="ProcCountTextBox" x:Uid="Settings_ProcCountTextBox" Style="{StaticResource TextBoxSettingStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
Text="{x:Bind ViewModel.ProcCount, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" TextChanged="ProcCountTextBox_TextChanged"/>
|
||||
<Button x:Uid="Settings_ProcCountResetButton" Style="{StaticResource ButtonSettingStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
Command="{x:Bind ViewModel.ProcCount_ResetCommand}" IsEnabled="{x:Bind ViewModel.ProcCount_ResetEnabled, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
|
|
@ -32,12 +32,12 @@
|
|||
</ctControls:SettingsCard>
|
||||
</ctControls:SettingsExpander.Items>
|
||||
</ctControls:SettingsExpander>
|
||||
<ctControls:SettingsExpander x:Uid="Settings_MemorySize">
|
||||
<ctControls:SettingsExpander x:Name="MemorySizeExpander" x:Uid="Settings_MemorySize">
|
||||
<TextBlock Style="{StaticResource TextBlockSettingStyle}" Text="{x:Bind ViewModel.MemorySize, Mode=OneWay, Converter={StaticResource MegabyteStringConverter}}"/>
|
||||
<ctControls:SettingsExpander.Items>
|
||||
<ctControls:SettingsCard HorizontalContentAlignment="Left" ContentAlignment="Left" Margin="{StaticResource SettingsExpanderItemMargin}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox x:Uid="Settings_MemorySizeTextBox" Style="{StaticResource TextBoxSettingStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
<TextBox x:Name="MemorySizeTextBox" x:Uid="Settings_MemorySizeTextBox" Style="{StaticResource TextBoxSettingStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
Text="{x:Bind ViewModel.MemorySize, Mode=TwoWay, UpdateSourceTrigger=LostFocus, Converter={StaticResource MegabyteNumberConverter}}" TextChanged="MemorySizeTextBox_TextChanged"/>
|
||||
<Button x:Uid="Settings_MemorySizeResetButton" Style="{StaticResource ButtonSettingStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
Command="{x:Bind ViewModel.MemorySize_ResetCommand}" IsEnabled="{x:Bind ViewModel.MemorySize_ResetEnabled, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
|
|
@ -46,12 +46,12 @@
|
|||
</ctControls:SettingsCard>
|
||||
</ctControls:SettingsExpander.Items>
|
||||
</ctControls:SettingsExpander>
|
||||
<ctControls:SettingsExpander x:Uid="Settings_SwapSize">
|
||||
<ctControls:SettingsExpander x:Name="SwapSizeExpander" x:Uid="Settings_SwapSize">
|
||||
<TextBlock Style="{StaticResource TextBlockSettingStyle}" Text="{x:Bind ViewModel.SwapSize, Mode=OneWay, Converter={StaticResource MegabyteStringConverter}}"/>
|
||||
<ctControls:SettingsExpander.Items>
|
||||
<ctControls:SettingsCard HorizontalContentAlignment="Left" ContentAlignment="Left" Margin="{StaticResource SettingsExpanderItemMargin}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox x:Uid="Settings_SwapSizeTextBox" Style="{StaticResource TextBoxSettingStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
<TextBox x:Name="SwapSizeTextBox" x:Uid="Settings_SwapSizeTextBox" Style="{StaticResource TextBoxSettingStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
Text="{x:Bind ViewModel.SwapSize, Mode=TwoWay, UpdateSourceTrigger=LostFocus, Converter={StaticResource MegabyteNumberConverter}}" TextChanged="SwapSizeTextBox_TextChanged"/>
|
||||
<Button x:Uid="Settings_SwapSizeResetButton" Style="{StaticResource ButtonSettingStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
Command="{x:Bind ViewModel.SwapSize_ResetCommand}" IsEnabled="{x:Bind ViewModel.SwapSize_ResetEnabled, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
|
|
@ -60,12 +60,12 @@
|
|||
</ctControls:SettingsCard>
|
||||
</ctControls:SettingsExpander.Items>
|
||||
</ctControls:SettingsExpander>
|
||||
<ctControls:SettingsExpander x:Uid="Settings_SwapFilePath">
|
||||
<ctControls:SettingsExpander x:Name="SwapFilePathExpander" x:Uid="Settings_SwapFilePath">
|
||||
<TextBlock Style="{StaticResource TextBlockFilePathStyle}" Text="{x:Bind ViewModel.SwapFilePath, Mode=OneWay}"/>
|
||||
<ctControls:SettingsExpander.Items>
|
||||
<ctControls:SettingsCard HorizontalContentAlignment="Left" ContentAlignment="Left" Margin="{StaticResource SettingsExpanderItemMargin}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox x:Uid="Settings_SwapFilePathTextBox" Style="{StaticResource TextBoxFilePathStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
<TextBox x:Name="SwapFilePathTextBox" x:Uid="Settings_SwapFilePathTextBox" Style="{StaticResource TextBoxFilePathStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
Text="{x:Bind ViewModel.SwapFilePath, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"/>
|
||||
<Button x:Uid="Settings_SwapFilePathBrowseButton" Style="{StaticResource ButtonSettingStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
Click="SwapFilePath_Click"/>
|
||||
|
|
|
|||
|
|
@ -27,6 +27,16 @@ public sealed partial class MemAndProcPage : Page
|
|||
FrameworkElementAutomationPeer.FromElement(Settings_ErrorTryAgainLater).RaiseAutomationEvent(AutomationEvents.LiveRegionChanged);
|
||||
}
|
||||
});
|
||||
|
||||
this.Loaded += OnPageLoaded;
|
||||
}
|
||||
|
||||
private void OnPageLoaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
RuntimeHelper.SetupExpanderFocusManagementByName(this, "ProcCountExpander", "ProcCountTextBox");
|
||||
RuntimeHelper.SetupExpanderFocusManagementByName(this, "MemorySizeExpander", "MemorySizeTextBox");
|
||||
RuntimeHelper.SetupExpanderFocusManagementByName(this, "SwapSizeExpander", "SwapSizeTextBox");
|
||||
RuntimeHelper.SetupExpanderFocusManagementByName(this, "SwapFilePathExpander", "SwapFilePathTextBox");
|
||||
}
|
||||
|
||||
override protected void OnNavigatedFrom(NavigationEventArgs e)
|
||||
|
|
|
|||
|
|
@ -25,12 +25,12 @@
|
|||
<ctControls:SettingsCard x:Uid="Settings_HyperVFirewall">
|
||||
<ToggleSwitch x:Uid="Settings_HyperVFirewallToggleSwitch" HorizontalAlignment="Right" MinWidth="0" IsOn="{x:Bind ViewModel.IsOnHyperVFirewall, Mode=TwoWay}"/>
|
||||
</ctControls:SettingsCard>
|
||||
<ctControls:SettingsExpander x:Uid="Settings_IgnoredPorts">
|
||||
<ctControls:SettingsExpander x:Name="IgnoredPortsExpander" x:Uid="Settings_IgnoredPorts">
|
||||
<TextBlock Style="{StaticResource TextBlockSettingStyle}" Text="{x:Bind ViewModel.IgnoredPorts, Mode=OneWay}"/>
|
||||
<ctControls:SettingsExpander.Items>
|
||||
<ctControls:SettingsCard HorizontalContentAlignment="Left" ContentAlignment="Left" Margin="{StaticResource SettingsExpanderItemMargin}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox x:Uid="Settings_IgnoredPortsTextBox" Style="{StaticResource TextBoxSettingStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
<TextBox x:Name="IgnoredPortsTextBox" x:Uid="Settings_IgnoredPortsTextBox" Style="{StaticResource TextBoxSettingStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
Text="{x:Bind ViewModel.IgnoredPorts, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"/>
|
||||
<Button x:Uid="Settings_IgnoredPortsResetButton" Style="{StaticResource ButtonSettingStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
Command="{x:Bind ViewModel.IgnoredPorts_ResetCommand}" IsEnabled="{x:Bind ViewModel.IgnoredPorts_ResetEnabled, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
|
|
@ -48,12 +48,12 @@
|
|||
<ctControls:SettingsCard x:Uid="Settings_AutoProxy">
|
||||
<ToggleSwitch x:Uid="Settings_AutoProxyToggleSwitch" HorizontalAlignment="Right" MinWidth="0" IsOn="{x:Bind ViewModel.IsOnAutoProxy, Mode=TwoWay}"/>
|
||||
</ctControls:SettingsCard>
|
||||
<ctControls:SettingsExpander x:Uid="Settings_InitialAutoProxyTimeout">
|
||||
<ctControls:SettingsExpander x:Name="InitialAutoProxyTimeoutExpander" x:Uid="Settings_InitialAutoProxyTimeout">
|
||||
<TextBlock Style="{StaticResource TextBlockSettingStyle}" Text="{x:Bind ViewModel.InitialAutoProxyTimeout, Mode=OneWay, Converter={StaticResource MillisecondsStringConverter}}"/>
|
||||
<ctControls:SettingsExpander.Items>
|
||||
<ctControls:SettingsCard HorizontalContentAlignment="Left" ContentAlignment="Left" Margin="{StaticResource SettingsExpanderItemMargin}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox x:Uid="Settings_InitialAutoProxyTimeoutTextBox" Style="{StaticResource TextBoxSettingStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
<TextBox x:Name="InitialAutoProxyTimeoutTextBox" x:Uid="Settings_InitialAutoProxyTimeoutTextBox" Style="{StaticResource TextBoxSettingStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
Text="{x:Bind ViewModel.InitialAutoProxyTimeout, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" TextChanged="InitialAutoProxyTimeoutTextBox_TextChanged"/>
|
||||
<Button x:Uid="Settings_InitialAutoProxyTimeoutResetButton" Style="{StaticResource ButtonSettingStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
Command="{x:Bind ViewModel.InitialAutoProxyTimeout_ResetCommand}" IsEnabled="{x:Bind ViewModel.InitialAutoProxyTimeout_ResetEnabled, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
|
|
|
|||
|
|
@ -26,6 +26,14 @@ public sealed partial class NetworkingPage : Page
|
|||
FrameworkElementAutomationPeer.FromElement(Settings_ErrorTryAgainLater).RaiseAutomationEvent(AutomationEvents.LiveRegionChanged);
|
||||
}
|
||||
});
|
||||
|
||||
this.Loaded += OnPageLoaded;
|
||||
}
|
||||
|
||||
private void OnPageLoaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
RuntimeHelper.SetupExpanderFocusManagementByName(this, "IgnoredPortsExpander", "IgnoredPortsTextBox");
|
||||
RuntimeHelper.SetupExpanderFocusManagementByName(this, "InitialAutoProxyTimeoutExpander", "InitialAutoProxyTimeoutTextBox");
|
||||
}
|
||||
|
||||
override protected void OnNavigatedFrom(NavigationEventArgs e)
|
||||
|
|
|
|||
|
|
@ -38,12 +38,12 @@
|
|||
<ctControls:SettingsCard x:Uid="Settings_SparseVHD">
|
||||
<ToggleSwitch x:Uid="Settings_SparseVHDToggleSwitch" HorizontalAlignment="Right" MinWidth="0" IsOn="{x:Bind ViewModel.IsOnSparseVHD, Mode=TwoWay}"/>
|
||||
</ctControls:SettingsCard>
|
||||
<ctControls:SettingsExpander x:Uid="Settings_VMIdleTimeout">
|
||||
<ctControls:SettingsExpander x:Name="VMIdleTimeoutExpander" x:Uid="Settings_VMIdleTimeout">
|
||||
<TextBlock Style="{StaticResource TextBlockSettingStyle}" Text="{x:Bind ViewModel.VMIdleTimeout, Mode=OneWay, Converter={StaticResource MillisecondsStringConverter}}"/>
|
||||
<ctControls:SettingsExpander.Items>
|
||||
<ctControls:SettingsCard HorizontalContentAlignment="Left" ContentAlignment="Left" Margin="{StaticResource SettingsExpanderItemMargin}">
|
||||
<StackPanel Orientation="Horizontal">
|
||||
<TextBox x:Uid="Settings_VMIdleTimeoutTextBox" Style="{StaticResource TextBoxFilePathStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
<TextBox x:Name="VMIdleTimeoutTextBox" x:Uid="Settings_VMIdleTimeoutTextBox" Style="{StaticResource TextBoxFilePathStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
Text="{x:Bind ViewModel.VMIdleTimeout, Mode=TwoWay, UpdateSourceTrigger=LostFocus}" TextChanged="VMIdleTimeoutTextBox_TextChanged"/>
|
||||
<Button x:Uid="Settings_VMIdleTimeoutResetButton" Style="{StaticResource ButtonSettingStyle}" Margin="{StaticResource InputControlSpacingMargin}"
|
||||
Command="{x:Bind ViewModel.VMIdleTimeout_ResetCommand}" IsEnabled="{x:Bind ViewModel.VMIdleTimeout_ResetEnabled, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
|
||||
|
|
|
|||
|
|
@ -26,6 +26,14 @@ public sealed partial class OptionalFeaturesPage : Page
|
|||
FrameworkElementAutomationPeer.FromElement(Settings_ErrorTryAgainLater).RaiseAutomationEvent(AutomationEvents.LiveRegionChanged);
|
||||
}
|
||||
});
|
||||
|
||||
this.Loaded += OnPageLoaded;
|
||||
}
|
||||
|
||||
private void OnPageLoaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
|
||||
{
|
||||
RuntimeHelper.SetupExpanderFocusManagementByName(this, "SystemdSettingsExpander", "InitTextBox");
|
||||
RuntimeHelper.SetupExpanderFocusManagementByName(this, "VMIdleTimeoutExpander", "VMIdleTimeoutTextBox");
|
||||
}
|
||||
|
||||
override protected void OnNavigatedFrom(NavigationEventArgs e)
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:windowex="using:WinUIEx"
|
||||
MinWidth="480"
|
||||
MinHeight="480"
|
||||
MinWidth="600"
|
||||
MinHeight="600"
|
||||
Closed="Window_Closed"
|
||||
mc:Ignorable="d">
|
||||
<Window.SystemBackdrop>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
// Copyright (c) Microsoft Corporation
|
||||
// Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
|
||||
using Microsoft.UI.Windowing;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Input;
|
||||
using System.Runtime.InteropServices;
|
||||
using Windows.Graphics;
|
||||
using Windows.System;
|
||||
using WinUIEx.Messaging;
|
||||
using Windows.UI.ViewManagement;
|
||||
using Windows.UI.WindowManagement;
|
||||
|
|
@ -39,6 +41,7 @@ public sealed partial class OOBEWindow : WindowEx, IDisposable
|
|||
|
||||
// Theme change code picked from https://github.com/microsoft/WinUI-Gallery/pull/1239
|
||||
settings.ColorValuesChanged += Settings_ColorValuesChanged; // cannot use FrameworkElement.ActualThemeChanged event
|
||||
settings.TextScaleFactorChanged += Settings_TextScaleFactorChanged;
|
||||
|
||||
WindowManager.Get(this).IsMinimizable = false;
|
||||
WindowManager.Get(this).IsMaximizable = false;
|
||||
|
|
@ -60,6 +63,8 @@ public sealed partial class OOBEWindow : WindowEx, IDisposable
|
|||
e.Handled = true;
|
||||
}
|
||||
};
|
||||
|
||||
this.Activated += OnWindowActivated;
|
||||
}
|
||||
|
||||
// this handles updating the caption button colors correctly when windows system theme is changed
|
||||
|
|
@ -73,6 +78,16 @@ public sealed partial class OOBEWindow : WindowEx, IDisposable
|
|||
});
|
||||
}
|
||||
|
||||
// This handles text scaling changes for accessibility
|
||||
private void Settings_TextScaleFactorChanged(UISettings sender, object args)
|
||||
{
|
||||
// This calls comes off-thread, hence we will need to dispatch it to current app's thread
|
||||
dispatcherQueue.TryEnqueue(() =>
|
||||
{
|
||||
ResizeWindow();
|
||||
});
|
||||
}
|
||||
|
||||
private void Window_SizeChanged(object sender, WindowSizeChangedEventArgs args)
|
||||
{
|
||||
var dpi = GetDpiForWindow(hWnd);
|
||||
|
|
@ -93,9 +108,15 @@ public sealed partial class OOBEWindow : WindowEx, IDisposable
|
|||
|
||||
private void ResizeWindow()
|
||||
{
|
||||
float scalingFactor = (float)currentDPI / DefaultDPI;
|
||||
int width = (int)(ExpectedWidth * scalingFactor);
|
||||
int height = (int)(ExpectedHeight * scalingFactor);
|
||||
float dpiScalingFactor = (float)currentDPI / DefaultDPI;
|
||||
float textScalingFactor = (float)settings.TextScaleFactor;
|
||||
|
||||
// Combine DPI scaling and text scaling for accessibility
|
||||
float combinedScalingFactor = dpiScalingFactor * textScalingFactor;
|
||||
|
||||
int width = (int)(ExpectedWidth * combinedScalingFactor);
|
||||
int height = (int)(ExpectedHeight * combinedScalingFactor);
|
||||
|
||||
SizeInt32 size;
|
||||
size.Width = width;
|
||||
size.Height = height;
|
||||
|
|
@ -108,6 +129,13 @@ public sealed partial class OOBEWindow : WindowEx, IDisposable
|
|||
{
|
||||
msgMonitor?.Dispose();
|
||||
settings.ColorValuesChanged -= Settings_ColorValuesChanged;
|
||||
settings.TextScaleFactorChanged -= Settings_TextScaleFactorChanged;
|
||||
this.Activated -= OnWindowActivated;
|
||||
if (this.Content is Microsoft.UI.Xaml.Controls.Page page)
|
||||
{
|
||||
page.KeyboardAccelerators.Clear();
|
||||
}
|
||||
|
||||
disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -118,4 +146,25 @@ public sealed partial class OOBEWindow : WindowEx, IDisposable
|
|||
Dispose(disposing: true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private void OnWindowActivated(object sender, WindowActivatedEventArgs args)
|
||||
{
|
||||
if (args.WindowActivationState != WindowActivationState.Deactivated && this.Content != null)
|
||||
{
|
||||
this.Activated -= OnWindowActivated;
|
||||
|
||||
if (this.Content is Microsoft.UI.Xaml.Controls.Page page)
|
||||
{
|
||||
var escapeAccelerator = new KeyboardAccelerator() { Key = VirtualKey.Escape };
|
||||
escapeAccelerator.Invoked += OnCloseKeyboardAcceleratorInvoked;
|
||||
page.KeyboardAccelerators.Add(escapeAccelerator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCloseKeyboardAcceleratorInvoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
|
||||
{
|
||||
Close();
|
||||
args.Handled = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -791,7 +791,7 @@ private:
|
|||
} Data;
|
||||
} Reparse{};
|
||||
|
||||
constexpr ULONG ReparseBufferSize = REPARSE_DATA_BUFFER_HEADER_SIZE + sizeof(ULONG);
|
||||
const ULONG ReparseBufferSize = REPARSE_DATA_BUFFER_HEADER_SIZE + sizeof(ULONG);
|
||||
|
||||
//
|
||||
// The data length is the buffer size excluding the header.
|
||||
|
|
|
|||
|
|
@ -211,6 +211,12 @@ class UnitTests
|
|||
|
||||
auto revert = EnableSystemd();
|
||||
VERIFY_IS_TRUE(IsSystemdRunning(L"--system"));
|
||||
|
||||
// Validate that systemd-networkd-wait-online.service is masked.
|
||||
auto [out, _] =
|
||||
LxsstuLaunchWslAndCaptureOutput(L"systemctl status systemd-networkd-wait-online.service | grep -iF Loaded:");
|
||||
|
||||
VERIFY_ARE_EQUAL(out, L" Loaded: masked (Reason: Unit systemd-networkd-wait-online.service is masked.)\n");
|
||||
}
|
||||
|
||||
TEST_METHOD(SystemdUser)
|
||||
|
|
@ -2797,7 +2803,7 @@ Error code: Wsl/InstallDistro/WSL_E_DISTRO_NOT_FOUND
|
|||
|
||||
VERIFY_ARE_EQUAL(LxsstuLaunchWsl(std::format(L"--import {} . \"{}\" --version 2", name, g_testDistroPath)), 0L);
|
||||
|
||||
auto cleanupName = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, []() {
|
||||
auto cleanupName = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [name]() {
|
||||
LxsstuLaunchWsl(std::format(L"--unregister {}", name));
|
||||
std::filesystem::remove_all(testFolder);
|
||||
});
|
||||
|
|
@ -2873,9 +2879,9 @@ Error code: Wsl/InstallDistro/WSL_E_DISTRO_NOT_FOUND
|
|||
WslShutdown();
|
||||
|
||||
auto cleanupName =
|
||||
wil::scope_exit_log(WI_DIAGNOSTICS_INFO, []() { LxsstuLaunchWsl(std::format(L"--unregister {}", name)); });
|
||||
wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [name]() { LxsstuLaunchWsl(std::format(L"--unregister {}", name)); });
|
||||
|
||||
auto validateDistro = [](LPCWSTR size, LPCWSTR expectedSize, LPCWSTR expectedError = nullptr) {
|
||||
auto validateDistro = [name](LPCWSTR size, LPCWSTR expectedSize, LPCWSTR expectedError = nullptr) {
|
||||
auto [out, _] = LxsstuLaunchWslAndCaptureOutput(std::format(L"--manage {} --resize {}", name, size), expectedError ? -1 : 0);
|
||||
if (expectedError)
|
||||
{
|
||||
|
|
@ -3578,8 +3584,8 @@ localhostForwarding=true
|
|||
|
||||
constexpr auto TestUser = L"testuser";
|
||||
|
||||
auto cleanup =
|
||||
wil::scope_exit_log(WI_DIAGNOSTICS_INFO, []() { LxsstuLaunchWsl(std::format(L"-u root userdel -f {}", TestUser)); });
|
||||
auto cleanup = wil::scope_exit_log(
|
||||
WI_DIAGNOSTICS_INFO, [TestUser]() { LxsstuLaunchWsl(std::format(L"-u root userdel -f {}", TestUser)); });
|
||||
|
||||
ULONG Uid{};
|
||||
ULONG Gid{};
|
||||
|
|
@ -3719,7 +3725,7 @@ localhostForwarding=true
|
|||
constexpr auto testTar = L"exported-distro.tar";
|
||||
constexpr auto tmpDistroName = L"tmpdistro";
|
||||
|
||||
auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, []() {
|
||||
auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [tmpDistroName]() {
|
||||
DeleteFile(testTar);
|
||||
LxsstuLaunchWsl(std::format(L"--unregister {}", tmpDistroName));
|
||||
});
|
||||
|
|
@ -3950,7 +3956,7 @@ VERSION_ID="Invalid|Format"
|
|||
constexpr auto testDistroName = L"test-oobe-import";
|
||||
|
||||
std::filesystem::create_directory(testDir);
|
||||
auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [this]() {
|
||||
auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [this, testDistroName]() {
|
||||
LxsstuLaunchWsl(std::format(L"--unregister {}", testDistroName));
|
||||
std::error_code error;
|
||||
std::filesystem::remove_all(testDir, error);
|
||||
|
|
@ -4511,7 +4517,7 @@ Error code: Wsl/Service/RegisterDistro/E_INVALIDARG\r\n";
|
|||
constexpr auto distroName = L"custom-terminal-profile";
|
||||
constexpr auto tarName = L"custom-terminal-profile.tar";
|
||||
|
||||
auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, []() {
|
||||
auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [distroName]() {
|
||||
DeleteFile(tarName);
|
||||
LxsstuLaunchWsl(std::format(L"--unregister {}", distroName));
|
||||
});
|
||||
|
|
@ -4553,7 +4559,7 @@ Error code: Wsl/Service/RegisterDistro/E_INVALIDARG\r\n";
|
|||
constexpr auto distroName = L"custom-terminal-profile-bad-json";
|
||||
constexpr auto tarName = L"custom-terminal-profile-bad-json.tar";
|
||||
|
||||
auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, []() {
|
||||
auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [distroName]() {
|
||||
DeleteFile(tarName);
|
||||
LxsstuLaunchWsl(std::format(L"--unregister {}", distroName));
|
||||
});
|
||||
|
|
@ -4581,7 +4587,7 @@ Error code: Wsl/Service/RegisterDistro/E_INVALIDARG\r\n";
|
|||
constexpr auto distroName = L"custom-terminal-profile-hide";
|
||||
constexpr auto tarName = L"custom-terminal-profile-hide.tar";
|
||||
|
||||
auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, []() {
|
||||
auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [distroName]() {
|
||||
DeleteFile(tarName);
|
||||
LxsstuLaunchWsl(std::format(L"--unregister {}", distroName));
|
||||
});
|
||||
|
|
@ -4625,7 +4631,7 @@ Error code: Wsl/Service/RegisterDistro/E_INVALIDARG\r\n";
|
|||
constexpr auto distroName = L"no-terminal-profile";
|
||||
constexpr auto tarName = L"no-terminal-profile.tar";
|
||||
|
||||
auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, []() {
|
||||
auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [distroName]() {
|
||||
DeleteFile(tarName);
|
||||
LxsstuLaunchWsl(std::format(L"--unregister {}", distroName));
|
||||
});
|
||||
|
|
@ -4647,7 +4653,7 @@ Error code: Wsl/Service/RegisterDistro/E_INVALIDARG\r\n";
|
|||
constexpr auto distroName = L"no-shortcut";
|
||||
constexpr auto tarName = L"no-shortcut.tar";
|
||||
|
||||
auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, []() {
|
||||
auto cleanup = wil::scope_exit_log(WI_DIAGNOSTICS_INFO, [distroName]() {
|
||||
DeleteFile(tarName);
|
||||
LxsstuLaunchWsl(std::format(L"--unregister {}", distroName));
|
||||
});
|
||||
|
|
@ -6146,8 +6152,8 @@ Error code: Wsl/InstallDistro/WSL_E_INVALID_JSON\r\n",
|
|||
TEST_METHOD(ImportExportStdout)
|
||||
{
|
||||
constexpr auto test_distro = L"import-test-distro";
|
||||
auto cleanup =
|
||||
wil::scope_exit_log(WI_DIAGNOSTICS_INFO, []() { LxsstuLaunchWsl(std::format(L"--unregister {}", test_distro)); });
|
||||
auto cleanup = wil::scope_exit_log(
|
||||
WI_DIAGNOSTICS_INFO, [test_distro]() { LxsstuLaunchWsl(std::format(L"--unregister {}", test_distro)); });
|
||||
|
||||
// The below logline makes it easier to find the bsdtar output when debugging this test case.
|
||||
fprintf(stderr, "Starting ImportExportStdout test case\n");
|
||||
|
|
|
|||
|
|
@ -40,7 +40,12 @@ $FilePatterns = "\.(h|cpp|hpp|c|hxx)$"
|
|||
|
||||
$IgnoreFolders = "(out|.git|.vs|.vscode|bin|CMakeFiles|generated|debug|x64|packages|_deps)$"
|
||||
|
||||
$RepoRoot = (Resolve-Path "$PSScriptRoot")
|
||||
# Handle both execution methods: direct PowerShell and powershell.exe script invocation
|
||||
if ([string]::IsNullOrEmpty($PSScriptRoot)) {
|
||||
$RepoRoot = (Get-Location).Path
|
||||
} else {
|
||||
$RepoRoot = (Resolve-Path "$PSScriptRoot")
|
||||
}
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
|
@ -170,9 +175,9 @@ function Format-Directory {
|
|||
$FilesToFormat = @()
|
||||
if ((Get-Item -Path $Path) -is [System.IO.DirectoryInfo]) {
|
||||
Get-ChildItem -Path $Path -File `
|
||||
| Where-Object { $_ -match $FilePatterns } `
|
||||
| Where-Object { $_.Name -match $FilePatterns } `
|
||||
| ForEach-Object {
|
||||
$FilePath = "$Path\$_"
|
||||
$FilePath = "$Path\$($_.Name)"
|
||||
if (($null -eq $ModifiedFiles) -or ($ModifiedFiles -contains $FilePath)) {
|
||||
if (!($FilePath -match "Intermediate")) {
|
||||
$FilesToFormat += $FilePath
|
||||
|
|
@ -180,9 +185,9 @@ function Format-Directory {
|
|||
}
|
||||
}
|
||||
Get-ChildItem -Path $Path -Directory `
|
||||
| Where-Object { $_ -notmatch $IgnoreFolders } `
|
||||
| Where-Object { $_.Name -notmatch $IgnoreFolders } `
|
||||
| ForEach-Object {
|
||||
$SubResult = (Format-Directory -Path "$Path\$_" `
|
||||
$SubResult = (Format-Directory -Path "$Path\$($_.Name)" `
|
||||
-ClangFormat $ClangFormat `
|
||||
-RepoRoot $RepoRoot `
|
||||
-FilePatterns $FilePatterns `
|
||||
|
|
|
|||
Loading…
Reference in New Issue