Skip to content

Commit 90fe13c

Browse files
authored
Merge branch 'main' into opacitymaskview-experiment
2 parents 26702eb + 80cf3d0 commit 90fe13c

File tree

98 files changed

+23929
-18
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

98 files changed

+23929
-18
lines changed

.config/dotnet-tools.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"isRoot": true,
44
"tools": {
55
"uno.check": {
6-
"version": "1.20.2",
6+
"version": "1.27.4",
77
"commands": [
88
"uno-check"
99
]

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,4 +354,4 @@ jobs:
354354
if: ${{ (env.ENABLE_DIAGNOSTICS == 'true' || env.COREHOST_TRACE != '') && always() }}
355355
with:
356356
name: linux-logs
357-
path: ./**/*.*log
357+
path: ./**/*.*log

Directory.Build.props

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,13 @@
1515
<NoWarn>$(NoWarn);Uno0001</NoWarn>
1616

1717
<!-- See https://github.com/CommunityToolkit/Labs-Windows/pull/605#issuecomment-2498743676 -->
18-
<WarningsNotAsErrors>NU1901;NU1902;NU1903;NU1904</WarningsNotAsErrors>
18+
<WarningsNotAsErrors>NU1901;NU1902;NU1903;NU1904;</WarningsNotAsErrors>
19+
20+
<!-- Labs only: No error for 'Missing XML comment for publicly visible type or member' -->
21+
<WarningsNotAsErrors>$(WarningsNotAsErrors);CS1591;CS1574;</WarningsNotAsErrors>
22+
23+
<!-- See https://github.com/CommunityToolkit/Windows/pull/609#issuecomment-2613505591 -->
24+
<WarningsNotAsErrors>$(WarningsNotAsErrors);CS0419;CS1570;</WarningsNotAsErrors>
1925
</PropertyGroup>
2026

2127
<Import Project="Windows.Toolkit.Common.props" />

components/AppServices/CommunityToolkit.AppServices.SourceGenerators/AppServiceGenerator.Helpers.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public static bool IsUwpTarget(Compilation compilation, AnalyzerConfigOptions an
3434
{
3535
if (bool.TryParse(propertyValue, out bool useUwpTools))
3636
{
37-
return true;
37+
return useUwpTools;
3838
}
3939
}
4040

components/AppServices/CommunityToolkit.AppServices.SourceGenerators/AppServiceGenerator.cs

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
7878
});
7979

8080
// Gather all interfaces, and only enable this branch if the target is a UWP app (the host)
81-
IncrementalValuesProvider<(HierarchyInfo Hierarchy, AppServiceInfo Info)> appServiceHostInfo =
81+
IncrementalValuesProvider<(HierarchyInfo, AppServiceInfo)> appServiceHostInfo =
8282
context.ForAttributeWithMetadataNameAndOptions(
8383
"CommunityToolkit.AppServices.AppServiceAttribute",
8484
static (node, _) => node is InterfaceDeclarationSyntax,
@@ -105,6 +105,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
105105

106106
token.ThrowIfCancellationRequested();
107107

108+
// Gather all methods for the app service type
108109
ImmutableArray<MethodInfo> methods = MethodInfo.From(typeSymbol, token);
109110

110111
token.ThrowIfCancellationRequested();
@@ -113,8 +114,47 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
113114
})
114115
.Where(static item => item.Hierarchy is not null);
115116

116-
// Produce the host type
117-
context.RegisterSourceOutput(appServiceHostInfo, static (context, item) =>
117+
// Also gather all explicitly requested host implementation types
118+
IncrementalValuesProvider<(HierarchyInfo, AppServiceInfo)> additionalAppServiceHostInfo =
119+
context.ForAttributeWithMetadataNameAndOptions(
120+
"CommunityToolkit.AppServices.GeneratedAppServiceHostAttribute",
121+
static (node, _) => true,
122+
static (context, token) =>
123+
{
124+
// Only retrieve host info if the target is a UWP application
125+
if (!Helpers.IsUwpTarget(context.SemanticModel.Compilation, context.GlobalOptions))
126+
{
127+
return default;
128+
}
129+
130+
// Get the target interface
131+
if (context.Attributes[0].ConstructorArguments is not [{ Kind: TypedConstantKind.Type, Value: INamedTypeSymbol appServiceType }])
132+
{
133+
return default;
134+
}
135+
136+
// Check if the current interface is in fact an app service type
137+
if (!appServiceType.TryGetAppServicesNameFromAttribute(out string? appServiceName))
138+
{
139+
return default;
140+
}
141+
142+
token.ThrowIfCancellationRequested();
143+
144+
HierarchyInfo hierarchy = HierarchyInfo.From(appServiceType, appServiceType.Name.Substring(1));
145+
146+
token.ThrowIfCancellationRequested();
147+
148+
ImmutableArray<MethodInfo> methods = MethodInfo.From(appServiceType, token);
149+
150+
token.ThrowIfCancellationRequested();
151+
152+
return (Hierarchy: hierarchy, new AppServiceInfo(methods, appServiceName, appServiceType.GetFullyQualifiedName()));
153+
})
154+
.Where(static item => item.Hierarchy is not null);
155+
156+
// Shared helper to emit all discovered types
157+
static void GenerateAppServiceHostType(SourceProductionContext context, (HierarchyInfo Hierarchy, AppServiceInfo Info) item)
118158
{
119159
ConstructorDeclarationSyntax constructorSyntax = Host.GetConstructorSyntax(item.Hierarchy, item.Info);
120160
ImmutableArray<MethodDeclarationSyntax> methodDeclarations = Host.GetMethodDeclarationsSyntax(item.Info);
@@ -126,6 +166,10 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
126166
$"/// <summary>A generated host implementation for the <see cref=\"{item.Info.InterfaceFullyQualifiedName}\"/> interface.</summary>");
127167

128168
context.AddSource($"{item.Hierarchy.FilenameHint}.g.cs", compilationUnit.GetText(Encoding.UTF8));
129-
});
169+
}
170+
171+
// Produce the host types
172+
context.RegisterSourceOutput(appServiceHostInfo, GenerateAppServiceHostType);
173+
context.RegisterSourceOutput(additionalAppServiceHostInfo, GenerateAppServiceHostType);
130174
}
131175
}

components/AppServices/src/AppServiceHost.cs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@
88
using System.Runtime.CompilerServices;
99
using System.Threading;
1010
using System.Threading.Tasks;
11+
using CommunityToolkit.AppServices.Helpers;
1112
using Windows.ApplicationModel;
1213
using Windows.ApplicationModel.Activation;
1314
using Windows.ApplicationModel.AppService;
1415
using Windows.ApplicationModel.Background;
1516
using Windows.Foundation.Collections;
1617
using Windows.Foundation.Metadata;
1718
using Windows.System.Profile;
18-
using CommunityToolkit.AppServices.Helpers;
19+
using Windows.UI.Core.Preview;
1920

2021
#pragma warning disable CA1068
2122

@@ -143,6 +144,58 @@ public bool OnBackgroundActivated(BackgroundActivatedEventArgs args)
143144
return true;
144145
}
145146

147+
/// <summary>
148+
/// Handles the app service host shutdown when <see cref="SystemNavigationManagerPreview.CloseRequested"/> is raised.
149+
/// </summary>
150+
/// <param name="args">The args for the close request.</param>
151+
/// <remarks>
152+
/// <para>
153+
/// This method should be used as follows (from <c>App.xaml.cs</c>):
154+
/// <code language="cs">
155+
/// private void OnCloseRequested(object? sender, SystemNavigationCloseRequestedPreviewEventArgs e)
156+
/// {
157+
/// // Any other work, possibly marking the request as handled
158+
///
159+
/// DesktopExtension.OnCloseRequested(e);
160+
/// }
161+
/// </code>
162+
/// </para>
163+
/// <para>
164+
/// The app might be holding a deferral for the app service connection to the extension process, which is currently only completed when the
165+
/// connection is closed. This means that when the application is closed, that deferral will actually try to keep the connection alive, until
166+
/// the OS will eventually force terminate it. This will cause following launches of the app to be delayed until the previous process is
167+
/// completely gone, meaning that closing the app and immediately reopening it will cause it to remain stuck at the splash screen for a few
168+
/// seconds. Note that during this time, no app code is actually executed, it's just that the OS is waiting to terminate the existing connection
169+
/// and fully close the previous instance before allowing a new one to be started. To avoid this issue, this method takes care of fully closing
170+
/// any existing connection (by canceling its associated deferral), when the app is about to exit. This avoids the OS timeout for the connection.
171+
/// </para>
172+
/// </remarks>
173+
public void OnCloseRequested(SystemNavigationCloseRequestedPreviewEventArgs args)
174+
{
175+
// Do nothing if the close request has been handled
176+
if (args.Handled)
177+
{
178+
return;
179+
}
180+
181+
// Remove the registered connection handlers
182+
if (_appServiceConnection is { } appServiceConnection)
183+
{
184+
appServiceConnection.ServiceClosed -= AppServiceConnection_ServiceClosed;
185+
appServiceConnection.RequestReceived -= AppServiceConnection_RequestReceived;
186+
187+
_appServiceConnection = null;
188+
}
189+
190+
// Cancel the deferral, if present
191+
if (_appServiceDeferral is { } appServiceDeferral)
192+
{
193+
appServiceDeferral.Complete();
194+
195+
_appServiceDeferral = null;
196+
}
197+
}
198+
146199
/// <summary>
147200
/// Creates a new <see cref="AppServiceRequest"/> for a given operation.
148201
/// </summary>

components/AppServices/src/CommunityToolkit.AppServices.csproj

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@
66
<GenerateDocumentationFile>true</GenerateDocumentationFile>
77
<RootNamespace>CommunityToolkit.AppServices</RootNamespace>
88
<PackageId>$(PackageIdPrefix).$(ToolkitComponentName)</PackageId>
9+
<HasWindowsUIXaml>false</HasWindowsUIXaml>
910
<HasWinUI>false</HasWinUI>
11+
<EnableXamlCompilerMismatchedTfmUnoWorkaround>false</EnableXamlCompilerMismatchedTfmUnoWorkaround>
12+
13+
<!-- This library doesn't need XAML support, so we can just target 17763 (also disable the UWP build tools) -->
14+
<UseUwpTools>false</UseUwpTools>
15+
<UwpTargetFrameworks>uap10.0.17763;net8.0-windows10.0.17763.0;net9.0-windows10.0.17763.0;</UwpTargetFrameworks>
1016
</PropertyGroup>
1117

1218
<!-- Sets this up as a toolkit component's source project -->
@@ -29,7 +35,7 @@
2935
</PropertyGroup>
3036

3137
<!-- Add the Desktop Extension SDK when on UWP-->
32-
<ItemGroup Condition="'$(IsUwp)' == 'true' AND $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) != 'windows'">
38+
<ItemGroup Condition="'$(IsUwp)' == 'true' AND '$(MultiTargetPlatformIdentifier)' != 'windows'">
3339
<SDKReference Include="WindowsDesktop, Version=$(TargetPlatformVersion)">
3440
<Name>Windows Desktop Extensions for the UWP</Name>
3541
</SDKReference>
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
7+
namespace CommunityToolkit.AppServices;
8+
9+
/// <summary>
10+
/// An attribute that can be used to request the generator to emit a host implementation of a given app service.
11+
/// </summary>
12+
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false)]
13+
public sealed class GeneratedAppServiceHostAttribute : Attribute
14+
{
15+
/// <summary>
16+
/// Creates a new <see cref="GeneratedAppServiceHostAttribute"/> instance with the specified parameters.
17+
/// </summary>
18+
/// <param name="appServiceType">The type of the app service.</param>
19+
public GeneratedAppServiceHostAttribute(Type appServiceType)
20+
{
21+
AppServiceType = appServiceType;
22+
}
23+
24+
/// <summary>
25+
/// Gets the type of the app service.
26+
/// </summary>
27+
public Type AppServiceType { get; }
28+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# All file types:
2+
# - Treat as text
3+
# - Normalize to LF line endings
4+
* text=auto eol=lf
5+
6+
# Explicit settings for well known types
7+
*.cs text eol=lf
8+
*.csproj text eol=lf
9+
*.projitems text eol=lf
10+
*.shprroj text eol=lf
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<TargetFramework>netstandard2.0</TargetFramework>
4+
<Nullable>enable</Nullable>
5+
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
6+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
7+
8+
<!-- We're intentionally not always matching the namespace with folder path, to better organize the code -->
9+
<NoWarn>$(NoWarn);IDE0130</NoWarn>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.12.0" PrivateAssets="all" />
14+
<PackageReference Include="PolySharp" Version="1.15.0" PrivateAssets="all" />
15+
</ItemGroup>
16+
17+
<ItemGroup>
18+
<ProjectReference Include="..\CommunityToolkit.DependencyPropertyGenerator.SourceGenerators\CommunityToolkit.DependencyPropertyGenerator.SourceGenerators.csproj" />
19+
</ItemGroup>
20+
</Project>

0 commit comments

Comments
 (0)