diff --git a/Converters/SKColorTypeConverter.cs b/Converters/SKColorTypeConverter.cs
new file mode 100644
index 0000000..2b10804
--- /dev/null
+++ b/Converters/SKColorTypeConverter.cs
@@ -0,0 +1,259 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.ComponentModel;
+using System.Globalization;
+using SkiaSharp;
+using Microsoft.Maui.Graphics;
+
+namespace Microsoft.Maui.Platform.Linux.Converters;
+
+///
+/// Type converter for converting between MAUI Color and SKColor.
+/// Enables XAML styling with Color values that get applied to Skia controls.
+///
+public class SKColorTypeConverter : TypeConverter
+{
+ public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)
+ {
+ return sourceType == typeof(string) ||
+ sourceType == typeof(Color) ||
+ base.CanConvertFrom(context, sourceType);
+ }
+
+ public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType)
+ {
+ return destinationType == typeof(string) ||
+ destinationType == typeof(Color) ||
+ base.CanConvertTo(context, destinationType);
+ }
+
+ public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value)
+ {
+ if (value is Color mauiColor)
+ {
+ return ToSKColor(mauiColor);
+ }
+
+ if (value is string str)
+ {
+ return ParseColor(str);
+ }
+
+ return base.ConvertFrom(context, culture, value);
+ }
+
+ public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType)
+ {
+ if (value is SKColor skColor)
+ {
+ if (destinationType == typeof(string))
+ {
+ return $"#{skColor.Alpha:X2}{skColor.Red:X2}{skColor.Green:X2}{skColor.Blue:X2}";
+ }
+
+ if (destinationType == typeof(Color))
+ {
+ return ToMauiColor(skColor);
+ }
+ }
+
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+
+ ///
+ /// Converts a MAUI Color to an SKColor.
+ ///
+ public static SKColor ToSKColor(Color mauiColor)
+ {
+ return new SKColor(
+ (byte)(mauiColor.Red * 255),
+ (byte)(mauiColor.Green * 255),
+ (byte)(mauiColor.Blue * 255),
+ (byte)(mauiColor.Alpha * 255));
+ }
+
+ ///
+ /// Converts an SKColor to a MAUI Color.
+ ///
+ public static Color ToMauiColor(SKColor skColor)
+ {
+ return new Color(
+ skColor.Red / 255f,
+ skColor.Green / 255f,
+ skColor.Blue / 255f,
+ skColor.Alpha / 255f);
+ }
+
+ ///
+ /// Parses a color string (hex, named, or rgb format).
+ ///
+ private static SKColor ParseColor(string colorString)
+ {
+ if (string.IsNullOrWhiteSpace(colorString))
+ return SKColors.Black;
+
+ colorString = colorString.Trim();
+
+ // Try hex format
+ if (colorString.StartsWith("#"))
+ {
+ return SKColor.Parse(colorString);
+ }
+
+ // Try named colors
+ var namedColor = GetNamedColor(colorString.ToLowerInvariant());
+ if (namedColor.HasValue)
+ return namedColor.Value;
+
+ // Try rgb/rgba format
+ if (colorString.StartsWith("rgb", StringComparison.OrdinalIgnoreCase))
+ {
+ return ParseRgbColor(colorString);
+ }
+
+ // Fallback to SKColor.Parse
+ if (SKColor.TryParse(colorString, out var parsed))
+ return parsed;
+
+ return SKColors.Black;
+ }
+
+ private static SKColor? GetNamedColor(string name) => name switch
+ {
+ "transparent" => SKColors.Transparent,
+ "black" => SKColors.Black,
+ "white" => SKColors.White,
+ "red" => SKColors.Red,
+ "green" => SKColors.Green,
+ "blue" => SKColors.Blue,
+ "yellow" => SKColors.Yellow,
+ "cyan" => SKColors.Cyan,
+ "magenta" => SKColors.Magenta,
+ "gray" or "grey" => SKColors.Gray,
+ "darkgray" or "darkgrey" => SKColors.DarkGray,
+ "lightgray" or "lightgrey" => SKColors.LightGray,
+ "orange" => new SKColor(0xFF, 0xA5, 0x00),
+ "pink" => new SKColor(0xFF, 0xC0, 0xCB),
+ "purple" => new SKColor(0x80, 0x00, 0x80),
+ "brown" => new SKColor(0xA5, 0x2A, 0x2A),
+ "navy" => new SKColor(0x00, 0x00, 0x80),
+ "teal" => new SKColor(0x00, 0x80, 0x80),
+ "olive" => new SKColor(0x80, 0x80, 0x00),
+ "silver" => new SKColor(0xC0, 0xC0, 0xC0),
+ "maroon" => new SKColor(0x80, 0x00, 0x00),
+ "lime" => new SKColor(0x00, 0xFF, 0x00),
+ "aqua" => new SKColor(0x00, 0xFF, 0xFF),
+ "fuchsia" => new SKColor(0xFF, 0x00, 0xFF),
+ "gold" => new SKColor(0xFF, 0xD7, 0x00),
+ "coral" => new SKColor(0xFF, 0x7F, 0x50),
+ "salmon" => new SKColor(0xFA, 0x80, 0x72),
+ "crimson" => new SKColor(0xDC, 0x14, 0x3C),
+ "indigo" => new SKColor(0x4B, 0x00, 0x82),
+ "violet" => new SKColor(0xEE, 0x82, 0xEE),
+ "turquoise" => new SKColor(0x40, 0xE0, 0xD0),
+ "tan" => new SKColor(0xD2, 0xB4, 0x8C),
+ "chocolate" => new SKColor(0xD2, 0x69, 0x1E),
+ "tomato" => new SKColor(0xFF, 0x63, 0x47),
+ "steelblue" => new SKColor(0x46, 0x82, 0xB4),
+ "skyblue" => new SKColor(0x87, 0xCE, 0xEB),
+ "slategray" or "slategrey" => new SKColor(0x70, 0x80, 0x90),
+ "seagreen" => new SKColor(0x2E, 0x8B, 0x57),
+ "royalblue" => new SKColor(0x41, 0x69, 0xE1),
+ "plum" => new SKColor(0xDD, 0xA0, 0xDD),
+ "peru" => new SKColor(0xCD, 0x85, 0x3F),
+ "orchid" => new SKColor(0xDA, 0x70, 0xD6),
+ "orangered" => new SKColor(0xFF, 0x45, 0x00),
+ "olivedrab" => new SKColor(0x6B, 0x8E, 0x23),
+ "midnightblue" => new SKColor(0x19, 0x19, 0x70),
+ "mediumblue" => new SKColor(0x00, 0x00, 0xCD),
+ "limegreen" => new SKColor(0x32, 0xCD, 0x32),
+ "hotpink" => new SKColor(0xFF, 0x69, 0xB4),
+ "honeydew" => new SKColor(0xF0, 0xFF, 0xF0),
+ "greenyellow" => new SKColor(0xAD, 0xFF, 0x2F),
+ "forestgreen" => new SKColor(0x22, 0x8B, 0x22),
+ "firebrick" => new SKColor(0xB2, 0x22, 0x22),
+ "dodgerblue" => new SKColor(0x1E, 0x90, 0xFF),
+ "deeppink" => new SKColor(0xFF, 0x14, 0x93),
+ "deepskyblue" => new SKColor(0x00, 0xBF, 0xFF),
+ "darkviolet" => new SKColor(0x94, 0x00, 0xD3),
+ "darkturquoise" => new SKColor(0x00, 0xCE, 0xD1),
+ "darkslategray" or "darkslategrey" => new SKColor(0x2F, 0x4F, 0x4F),
+ "darkred" => new SKColor(0x8B, 0x00, 0x00),
+ "darkorange" => new SKColor(0xFF, 0x8C, 0x00),
+ "darkolivegreen" => new SKColor(0x55, 0x6B, 0x2F),
+ "darkmagenta" => new SKColor(0x8B, 0x00, 0x8B),
+ "darkkhaki" => new SKColor(0xBD, 0xB7, 0x6B),
+ "darkgreen" => new SKColor(0x00, 0x64, 0x00),
+ "darkgoldenrod" => new SKColor(0xB8, 0x86, 0x0B),
+ "darkcyan" => new SKColor(0x00, 0x8B, 0x8B),
+ "darkblue" => new SKColor(0x00, 0x00, 0x8B),
+ "cornflowerblue" => new SKColor(0x64, 0x95, 0xED),
+ "cadetblue" => new SKColor(0x5F, 0x9E, 0xA0),
+ "blueviolet" => new SKColor(0x8A, 0x2B, 0xE2),
+ "azure" => new SKColor(0xF0, 0xFF, 0xFF),
+ "aquamarine" => new SKColor(0x7F, 0xFF, 0xD4),
+ "aliceblue" => new SKColor(0xF0, 0xF8, 0xFF),
+ _ => null
+ };
+
+ private static SKColor ParseRgbColor(string colorString)
+ {
+ try
+ {
+ var isRgba = colorString.StartsWith("rgba", StringComparison.OrdinalIgnoreCase);
+ var startIndex = colorString.IndexOf('(');
+ var endIndex = colorString.IndexOf(')');
+
+ if (startIndex == -1 || endIndex == -1)
+ return SKColors.Black;
+
+ var values = colorString.Substring(startIndex + 1, endIndex - startIndex - 1)
+ .Split(',')
+ .Select(v => v.Trim())
+ .ToArray();
+
+ if (values.Length < 3)
+ return SKColors.Black;
+
+ var r = byte.Parse(values[0]);
+ var g = byte.Parse(values[1]);
+ var b = byte.Parse(values[2]);
+ byte a = 255;
+
+ if (isRgba && values.Length >= 4)
+ {
+ var alphaValue = float.Parse(values[3], CultureInfo.InvariantCulture);
+ a = (byte)(alphaValue <= 1 ? alphaValue * 255 : alphaValue);
+ }
+
+ return new SKColor(r, g, b, a);
+ }
+ catch
+ {
+ return SKColors.Black;
+ }
+ }
+}
+
+///
+/// Extension methods for color conversion.
+///
+public static class ColorExtensions
+{
+ ///
+ /// Converts a MAUI Color to an SKColor.
+ ///
+ public static SKColor ToSKColor(this Color color)
+ {
+ return SKColorTypeConverter.ToSKColor(color);
+ }
+
+ ///
+ /// Converts an SKColor to a MAUI Color.
+ ///
+ public static Color ToMauiColor(this SKColor color)
+ {
+ return SKColorTypeConverter.ToMauiColor(color);
+ }
+}
diff --git a/Converters/SKRectTypeConverter.cs b/Converters/SKRectTypeConverter.cs
new file mode 100644
index 0000000..c1cf0df
--- /dev/null
+++ b/Converters/SKRectTypeConverter.cs
@@ -0,0 +1,328 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.ComponentModel;
+using System.Globalization;
+using SkiaSharp;
+using Microsoft.Maui;
+
+namespace Microsoft.Maui.Platform.Linux.Converters;
+
+///
+/// Type converter for converting between MAUI Thickness and SKRect (for padding/margin).
+/// Enables XAML styling with Thickness values that get applied to Skia controls.
+///
+public class SKRectTypeConverter : TypeConverter
+{
+ public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)
+ {
+ return sourceType == typeof(string) ||
+ sourceType == typeof(Thickness) ||
+ sourceType == typeof(double) ||
+ sourceType == typeof(float) ||
+ base.CanConvertFrom(context, sourceType);
+ }
+
+ public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType)
+ {
+ return destinationType == typeof(string) ||
+ destinationType == typeof(Thickness) ||
+ base.CanConvertTo(context, destinationType);
+ }
+
+ public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value)
+ {
+ if (value is Thickness thickness)
+ {
+ return ThicknessToSKRect(thickness);
+ }
+
+ if (value is double d)
+ {
+ return new SKRect((float)d, (float)d, (float)d, (float)d);
+ }
+
+ if (value is float f)
+ {
+ return new SKRect(f, f, f, f);
+ }
+
+ if (value is string str)
+ {
+ return ParseRect(str);
+ }
+
+ return base.ConvertFrom(context, culture, value);
+ }
+
+ public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType)
+ {
+ if (value is SKRect rect)
+ {
+ if (destinationType == typeof(string))
+ {
+ return $"{rect.Left},{rect.Top},{rect.Right},{rect.Bottom}";
+ }
+
+ if (destinationType == typeof(Thickness))
+ {
+ return SKRectToThickness(rect);
+ }
+ }
+
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+
+ ///
+ /// Converts a MAUI Thickness to an SKRect (used as padding storage).
+ ///
+ public static SKRect ThicknessToSKRect(Thickness thickness)
+ {
+ return new SKRect(
+ (float)thickness.Left,
+ (float)thickness.Top,
+ (float)thickness.Right,
+ (float)thickness.Bottom);
+ }
+
+ ///
+ /// Converts an SKRect (used as padding storage) to a MAUI Thickness.
+ ///
+ public static Thickness SKRectToThickness(SKRect rect)
+ {
+ return new Thickness(rect.Left, rect.Top, rect.Right, rect.Bottom);
+ }
+
+ ///
+ /// Parses a string into an SKRect for padding/margin.
+ /// Supports formats: "uniform", "horizontal,vertical", "left,top,right,bottom"
+ ///
+ private static SKRect ParseRect(string str)
+ {
+ if (string.IsNullOrWhiteSpace(str))
+ return SKRect.Empty;
+
+ str = str.Trim();
+ var parts = str.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
+
+ if (parts.Length == 1)
+ {
+ // Uniform padding
+ if (float.TryParse(parts[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var uniform))
+ {
+ return new SKRect(uniform, uniform, uniform, uniform);
+ }
+ }
+ else if (parts.Length == 2)
+ {
+ // Horizontal, Vertical
+ if (float.TryParse(parts[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var horizontal) &&
+ float.TryParse(parts[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var vertical))
+ {
+ return new SKRect(horizontal, vertical, horizontal, vertical);
+ }
+ }
+ else if (parts.Length == 4)
+ {
+ // Left, Top, Right, Bottom
+ if (float.TryParse(parts[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var left) &&
+ float.TryParse(parts[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var top) &&
+ float.TryParse(parts[2], NumberStyles.Float, CultureInfo.InvariantCulture, out var right) &&
+ float.TryParse(parts[3], NumberStyles.Float, CultureInfo.InvariantCulture, out var bottom))
+ {
+ return new SKRect(left, top, right, bottom);
+ }
+ }
+
+ return SKRect.Empty;
+ }
+}
+
+///
+/// Type converter for SKSize.
+///
+public class SKSizeTypeConverter : TypeConverter
+{
+ public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)
+ {
+ return sourceType == typeof(string) ||
+ sourceType == typeof(Size) ||
+ base.CanConvertFrom(context, sourceType);
+ }
+
+ public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType)
+ {
+ return destinationType == typeof(string) ||
+ destinationType == typeof(Size) ||
+ base.CanConvertTo(context, destinationType);
+ }
+
+ public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value)
+ {
+ if (value is Size size)
+ {
+ return new SKSize((float)size.Width, (float)size.Height);
+ }
+
+ if (value is string str)
+ {
+ return ParseSize(str);
+ }
+
+ return base.ConvertFrom(context, culture, value);
+ }
+
+ public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType)
+ {
+ if (value is SKSize size)
+ {
+ if (destinationType == typeof(string))
+ {
+ return $"{size.Width},{size.Height}";
+ }
+
+ if (destinationType == typeof(Size))
+ {
+ return new Size(size.Width, size.Height);
+ }
+ }
+
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+
+ private static SKSize ParseSize(string str)
+ {
+ if (string.IsNullOrWhiteSpace(str))
+ return SKSize.Empty;
+
+ str = str.Trim();
+ var parts = str.Split(new[] { ',', ' ', 'x', 'X' }, StringSplitOptions.RemoveEmptyEntries);
+
+ if (parts.Length == 1)
+ {
+ if (float.TryParse(parts[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var uniform))
+ {
+ return new SKSize(uniform, uniform);
+ }
+ }
+ else if (parts.Length == 2)
+ {
+ if (float.TryParse(parts[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var width) &&
+ float.TryParse(parts[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var height))
+ {
+ return new SKSize(width, height);
+ }
+ }
+
+ return SKSize.Empty;
+ }
+}
+
+///
+/// Type converter for SKPoint.
+///
+public class SKPointTypeConverter : TypeConverter
+{
+ public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)
+ {
+ return sourceType == typeof(string) ||
+ sourceType == typeof(Point) ||
+ base.CanConvertFrom(context, sourceType);
+ }
+
+ public override bool CanConvertTo(ITypeDescriptorContext? context, Type? destinationType)
+ {
+ return destinationType == typeof(string) ||
+ destinationType == typeof(Point) ||
+ base.CanConvertTo(context, destinationType);
+ }
+
+ public override object? ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value)
+ {
+ if (value is Point point)
+ {
+ return new SKPoint((float)point.X, (float)point.Y);
+ }
+
+ if (value is string str)
+ {
+ return ParsePoint(str);
+ }
+
+ return base.ConvertFrom(context, culture, value);
+ }
+
+ public override object? ConvertTo(ITypeDescriptorContext? context, CultureInfo? culture, object? value, Type destinationType)
+ {
+ if (value is SKPoint point)
+ {
+ if (destinationType == typeof(string))
+ {
+ return $"{point.X},{point.Y}";
+ }
+
+ if (destinationType == typeof(Point))
+ {
+ return new Point(point.X, point.Y);
+ }
+ }
+
+ return base.ConvertTo(context, culture, value, destinationType);
+ }
+
+ private static SKPoint ParsePoint(string str)
+ {
+ if (string.IsNullOrWhiteSpace(str))
+ return SKPoint.Empty;
+
+ str = str.Trim();
+ var parts = str.Split(new[] { ',', ' ' }, StringSplitOptions.RemoveEmptyEntries);
+
+ if (parts.Length == 2)
+ {
+ if (float.TryParse(parts[0], NumberStyles.Float, CultureInfo.InvariantCulture, out var x) &&
+ float.TryParse(parts[1], NumberStyles.Float, CultureInfo.InvariantCulture, out var y))
+ {
+ return new SKPoint(x, y);
+ }
+ }
+
+ return SKPoint.Empty;
+ }
+}
+
+///
+/// Extension methods for SkiaSharp type conversions.
+///
+public static class SKTypeExtensions
+{
+ public static SKRect ToSKRect(this Thickness thickness)
+ {
+ return SKRectTypeConverter.ThicknessToSKRect(thickness);
+ }
+
+ public static Thickness ToThickness(this SKRect rect)
+ {
+ return SKRectTypeConverter.SKRectToThickness(rect);
+ }
+
+ public static SKSize ToSKSize(this Size size)
+ {
+ return new SKSize((float)size.Width, (float)size.Height);
+ }
+
+ public static Size ToSize(this SKSize size)
+ {
+ return new Size(size.Width, size.Height);
+ }
+
+ public static SKPoint ToSKPoint(this Point point)
+ {
+ return new SKPoint((float)point.X, (float)point.Y);
+ }
+
+ public static Point ToPoint(this SKPoint point)
+ {
+ return new Point(point.X, point.Y);
+ }
+}
diff --git a/Handlers/ActivityIndicatorHandler.Linux.cs b/Handlers/ActivityIndicatorHandler.Linux.cs
index 624ea32..11b9722 100644
--- a/Handlers/ActivityIndicatorHandler.Linux.cs
+++ b/Handlers/ActivityIndicatorHandler.Linux.cs
@@ -15,6 +15,8 @@ public partial class ActivityIndicatorHandler : ViewHandler CommandMapper = new(ViewHandler.ViewCommandMapper);
@@ -40,4 +42,22 @@ public partial class ActivityIndicatorHandler : ViewHandler
+/// Handler for MAUI Application on Linux.
+/// Bridges the MAUI Application lifecycle with LinuxApplication.
+///
+public partial class ApplicationHandler : ElementHandler
+{
+ public static IPropertyMapper Mapper =
+ new PropertyMapper(ElementHandler.ElementMapper)
+ {
+ };
+
+ public static CommandMapper CommandMapper =
+ new(ElementHandler.ElementCommandMapper)
+ {
+ [nameof(IApplication.OpenWindow)] = MapOpenWindow,
+ [nameof(IApplication.CloseWindow)] = MapCloseWindow,
+ };
+
+ public ApplicationHandler() : base(Mapper, CommandMapper)
+ {
+ }
+
+ public ApplicationHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
+ : base(mapper ?? Mapper, commandMapper ?? CommandMapper)
+ {
+ }
+
+ protected override LinuxApplicationContext CreatePlatformElement()
+ {
+ return new LinuxApplicationContext();
+ }
+
+ protected override void ConnectHandler(LinuxApplicationContext platformView)
+ {
+ base.ConnectHandler(platformView);
+ platformView.Application = VirtualView;
+ }
+
+ protected override void DisconnectHandler(LinuxApplicationContext platformView)
+ {
+ platformView.Application = null;
+ base.DisconnectHandler(platformView);
+ }
+
+ public static void MapOpenWindow(ApplicationHandler handler, IApplication application, object? args)
+ {
+ if (args is IWindow window)
+ {
+ handler.PlatformView?.OpenWindow(window);
+ }
+ }
+
+ public static void MapCloseWindow(ApplicationHandler handler, IApplication application, object? args)
+ {
+ if (args is IWindow window)
+ {
+ handler.PlatformView?.CloseWindow(window);
+ }
+ }
+}
+
+///
+/// Platform context for the MAUI Application on Linux.
+/// Manages windows and the application lifecycle.
+///
+public class LinuxApplicationContext
+{
+ private readonly List _windows = new();
+ private IApplication? _application;
+
+ ///
+ /// Gets or sets the MAUI Application.
+ ///
+ public IApplication? Application
+ {
+ get => _application;
+ set
+ {
+ _application = value;
+ if (_application != null)
+ {
+ // Initialize windows from the application
+ foreach (var window in _application.Windows)
+ {
+ if (!_windows.Contains(window))
+ {
+ _windows.Add(window);
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ /// Gets the list of open windows.
+ ///
+ public IReadOnlyList Windows => _windows;
+
+ ///
+ /// Opens a window and creates its handler.
+ ///
+ public void OpenWindow(IWindow window)
+ {
+ if (!_windows.Contains(window))
+ {
+ _windows.Add(window);
+ }
+ }
+
+ ///
+ /// Closes a window and cleans up its handler.
+ ///
+ public void CloseWindow(IWindow window)
+ {
+ _windows.Remove(window);
+
+ if (_windows.Count == 0)
+ {
+ // Last window closed, stop the application
+ LinuxApplication.Current?.MainWindow?.Stop();
+ }
+ }
+
+ ///
+ /// Gets the main window of the application.
+ ///
+ public IWindow? MainWindow => _windows.Count > 0 ? _windows[0] : null;
+}
diff --git a/Handlers/BorderHandler.cs b/Handlers/BorderHandler.cs
index b68dec4..a0392a9 100644
--- a/Handlers/BorderHandler.cs
+++ b/Handlers/BorderHandler.cs
@@ -20,7 +20,9 @@ public partial class BorderHandler : ViewHandler
[nameof(IBorderView.Content)] = MapContent,
[nameof(IBorderStroke.Stroke)] = MapStroke,
[nameof(IBorderStroke.StrokeThickness)] = MapStrokeThickness,
+ ["StrokeShape"] = MapStrokeShape, // StrokeShape is on Border, not IBorderStroke
[nameof(IView.Background)] = MapBackground,
+ ["BackgroundColor"] = MapBackgroundColor,
[nameof(IPadding.Padding)] = MapPadding,
};
@@ -55,13 +57,25 @@ public partial class BorderHandler : ViewHandler
public static void MapContent(BorderHandler handler, IBorderView border)
{
- if (handler.PlatformView is null) return;
+ if (handler.PlatformView is null || handler.MauiContext is null) return;
handler.PlatformView.ClearChildren();
- if (border.PresentedContent?.Handler?.PlatformView is SkiaView skiaContent)
+ var content = border.PresentedContent;
+ if (content != null)
{
- handler.PlatformView.AddChild(skiaContent);
+ // Create handler for content if it doesn't exist
+ if (content.Handler == null)
+ {
+ Console.WriteLine($"[BorderHandler] Creating handler for content: {content.GetType().Name}");
+ content.Handler = content.ToHandler(handler.MauiContext);
+ }
+
+ if (content.Handler?.PlatformView is SkiaView skiaContent)
+ {
+ Console.WriteLine($"[BorderHandler] Adding content: {skiaContent.GetType().Name}");
+ handler.PlatformView.AddChild(skiaContent);
+ }
}
}
@@ -91,6 +105,17 @@ public partial class BorderHandler : ViewHandler
}
}
+ public static void MapBackgroundColor(BorderHandler handler, IBorderView border)
+ {
+ if (handler.PlatformView is null) return;
+
+ if (border is VisualElement ve && ve.BackgroundColor != null)
+ {
+ handler.PlatformView.BackgroundColor = ve.BackgroundColor.ToSKColor();
+ handler.PlatformView.Invalidate();
+ }
+ }
+
public static void MapPadding(BorderHandler handler, IBorderView border)
{
if (handler.PlatformView is null) return;
@@ -101,4 +126,33 @@ public partial class BorderHandler : ViewHandler
handler.PlatformView.PaddingRight = (float)padding.Right;
handler.PlatformView.PaddingBottom = (float)padding.Bottom;
}
+
+ public static void MapStrokeShape(BorderHandler handler, IBorderView border)
+ {
+ if (handler.PlatformView is null) return;
+
+ // StrokeShape is on the Border control class, not IBorderView interface
+ if (border is not Border borderControl) return;
+
+ var shape = borderControl.StrokeShape;
+ if (shape is Microsoft.Maui.Controls.Shapes.RoundRectangle roundRect)
+ {
+ // RoundRectangle can have different corner radii, but we use a uniform one
+ // Take the top-left corner as the uniform radius
+ var cornerRadius = roundRect.CornerRadius;
+ handler.PlatformView.CornerRadius = (float)cornerRadius.TopLeft;
+ }
+ else if (shape is Microsoft.Maui.Controls.Shapes.Rectangle)
+ {
+ handler.PlatformView.CornerRadius = 0;
+ }
+ else if (shape is Microsoft.Maui.Controls.Shapes.Ellipse)
+ {
+ // For ellipse, use half the min dimension as corner radius
+ // This will be applied during rendering when bounds are known
+ handler.PlatformView.CornerRadius = float.MaxValue; // Marker for "fully rounded"
+ }
+
+ handler.PlatformView.Invalidate();
+ }
}
diff --git a/Handlers/BoxViewHandler.cs b/Handlers/BoxViewHandler.cs
new file mode 100644
index 0000000..6b9ddd5
--- /dev/null
+++ b/Handlers/BoxViewHandler.cs
@@ -0,0 +1,67 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.Maui.Controls;
+using Microsoft.Maui.Handlers;
+using SkiaSharp;
+
+namespace Microsoft.Maui.Platform.Linux.Handlers;
+
+///
+/// Handler for BoxView on Linux.
+///
+public partial class BoxViewHandler : ViewHandler
+{
+ public static IPropertyMapper Mapper =
+ new PropertyMapper(ViewMapper)
+ {
+ [nameof(BoxView.Color)] = MapColor,
+ [nameof(BoxView.CornerRadius)] = MapCornerRadius,
+ [nameof(IView.Background)] = MapBackground,
+ ["BackgroundColor"] = MapBackgroundColor,
+ };
+
+ public BoxViewHandler() : base(Mapper)
+ {
+ }
+
+ protected override SkiaBoxView CreatePlatformView()
+ {
+ return new SkiaBoxView();
+ }
+
+ public static void MapColor(BoxViewHandler handler, BoxView boxView)
+ {
+ if (boxView.Color != null)
+ {
+ handler.PlatformView.Color = new SKColor(
+ (byte)(boxView.Color.Red * 255),
+ (byte)(boxView.Color.Green * 255),
+ (byte)(boxView.Color.Blue * 255),
+ (byte)(boxView.Color.Alpha * 255));
+ }
+ }
+
+ public static void MapCornerRadius(BoxViewHandler handler, BoxView boxView)
+ {
+ handler.PlatformView.CornerRadius = (float)boxView.CornerRadius.TopLeft;
+ }
+
+ public static void MapBackground(BoxViewHandler handler, BoxView boxView)
+ {
+ if (boxView.Background is SolidColorBrush solidBrush && solidBrush.Color != null)
+ {
+ handler.PlatformView.BackgroundColor = solidBrush.Color.ToSKColor();
+ handler.PlatformView.Invalidate();
+ }
+ }
+
+ public static void MapBackgroundColor(BoxViewHandler handler, BoxView boxView)
+ {
+ if (boxView.BackgroundColor != null)
+ {
+ handler.PlatformView.BackgroundColor = boxView.BackgroundColor.ToSKColor();
+ handler.PlatformView.Invalidate();
+ }
+ }
+}
diff --git a/Handlers/ButtonHandler.Linux.cs b/Handlers/ButtonHandler.Linux.cs
index ba3e1f7..54feb11 100644
--- a/Handlers/ButtonHandler.Linux.cs
+++ b/Handlers/ButtonHandler.Linux.cs
@@ -60,6 +60,21 @@ public partial class ButtonHandler : ViewHandler
platformView.Clicked += OnClicked;
platformView.Pressed += OnPressed;
platformView.Released += OnReleased;
+
+ // Manually map all properties on connect since MAUI may not trigger updates
+ // for properties that were set before handler connection
+ if (VirtualView != null)
+ {
+ MapText(this, VirtualView);
+ MapTextColor(this, VirtualView);
+ MapBackground(this, VirtualView);
+ MapFont(this, VirtualView);
+ MapPadding(this, VirtualView);
+ MapCornerRadius(this, VirtualView);
+ MapBorderColor(this, VirtualView);
+ MapBorderWidth(this, VirtualView);
+ MapIsEnabled(this, VirtualView);
+ }
}
protected override void DisconnectHandler(SkiaButton platformView)
@@ -105,7 +120,8 @@ public partial class ButtonHandler : ViewHandler
var background = button.Background;
if (background is SolidColorBrush solidBrush && solidBrush.Color != null)
{
- handler.PlatformView.BackgroundColor = solidBrush.Color.ToSKColor();
+ // Use ButtonBackgroundColor which is used for rendering, not base BackgroundColor
+ handler.PlatformView.ButtonBackgroundColor = solidBrush.Color.ToSKColor();
}
handler.PlatformView.Invalidate();
}
@@ -156,6 +172,7 @@ public partial class ButtonHandler : ViewHandler
public static void MapIsEnabled(ButtonHandler handler, IButton button)
{
+ Console.WriteLine($"[ButtonHandler] MapIsEnabled called - Text='{handler.PlatformView.Text}', IsEnabled={button.IsEnabled}");
handler.PlatformView.IsEnabled = button.IsEnabled;
handler.PlatformView.Invalidate();
}
diff --git a/Handlers/ButtonHandler.cs b/Handlers/ButtonHandler.cs
index 6b58bbb..33110d9 100644
--- a/Handlers/ButtonHandler.cs
+++ b/Handlers/ButtonHandler.cs
@@ -20,6 +20,7 @@ public partial class ButtonHandler : ViewHandler
[nameof(IButtonStroke.CornerRadius)] = MapCornerRadius,
[nameof(IView.Background)] = MapBackground,
[nameof(IPadding.Padding)] = MapPadding,
+ [nameof(IView.IsEnabled)] = MapIsEnabled,
};
public static CommandMapper CommandMapper = new(ViewHandler.ViewCommandMapper)
@@ -47,6 +48,18 @@ public partial class ButtonHandler : ViewHandler
platformView.Clicked += OnClicked;
platformView.Pressed += OnPressed;
platformView.Released += OnReleased;
+
+ // Manually map all properties on connect since MAUI may not trigger updates
+ // for properties that were set before handler connection
+ if (VirtualView != null)
+ {
+ MapStrokeColor(this, VirtualView);
+ MapStrokeThickness(this, VirtualView);
+ MapCornerRadius(this, VirtualView);
+ MapBackground(this, VirtualView);
+ MapPadding(this, VirtualView);
+ MapIsEnabled(this, VirtualView);
+ }
}
protected override void DisconnectHandler(SkiaButton platformView)
@@ -88,7 +101,8 @@ public partial class ButtonHandler : ViewHandler
if (button.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
- handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
+ // Set ButtonBackgroundColor (used for rendering) not base BackgroundColor
+ handler.PlatformView.ButtonBackgroundColor = solidPaint.Color.ToSKColor();
}
}
@@ -103,6 +117,14 @@ public partial class ButtonHandler : ViewHandler
(float)padding.Right,
(float)padding.Bottom);
}
+
+ public static void MapIsEnabled(ButtonHandler handler, IButton button)
+ {
+ if (handler.PlatformView is null) return;
+ Console.WriteLine($"[ButtonHandler] MapIsEnabled - Text='{handler.PlatformView.Text}', IsEnabled={button.IsEnabled}");
+ handler.PlatformView.IsEnabled = button.IsEnabled;
+ handler.PlatformView.Invalidate();
+ }
}
///
@@ -124,6 +146,21 @@ public partial class TextButtonHandler : ButtonHandler
{
}
+ protected override void ConnectHandler(SkiaButton platformView)
+ {
+ base.ConnectHandler(platformView);
+
+ // Manually map text properties on connect since MAUI may not trigger updates
+ // for properties that were set before handler connection
+ if (VirtualView is ITextButton textButton)
+ {
+ MapText(this, textButton);
+ MapTextColor(this, textButton);
+ MapFont(this, textButton);
+ MapCharacterSpacing(this, textButton);
+ }
+ }
+
public static void MapText(TextButtonHandler handler, ITextButton button)
{
if (handler.PlatformView is null) return;
diff --git a/Handlers/CheckBoxHandler.Linux.cs b/Handlers/CheckBoxHandler.Linux.cs
index 3ea84e0..d8d81e8 100644
--- a/Handlers/CheckBoxHandler.Linux.cs
+++ b/Handlers/CheckBoxHandler.Linux.cs
@@ -19,6 +19,8 @@ public partial class CheckBoxHandler : ViewHandler
[nameof(ICheckBox.IsChecked)] = MapIsChecked,
[nameof(ICheckBox.Foreground)] = MapForeground,
[nameof(IView.IsEnabled)] = MapIsEnabled,
+ [nameof(IView.Background)] = MapBackground,
+ ["BackgroundColor"] = MapBackgroundColor,
};
///
@@ -90,4 +92,22 @@ public partial class CheckBoxHandler : ViewHandler
handler.PlatformView.IsEnabled = checkBox.IsEnabled;
handler.PlatformView.Invalidate();
}
+
+ public static void MapBackground(CheckBoxHandler handler, ICheckBox checkBox)
+ {
+ if (checkBox.Background is SolidColorBrush solidBrush && solidBrush.Color != null)
+ {
+ handler.PlatformView.BackgroundColor = solidBrush.Color.ToSKColor();
+ handler.PlatformView.Invalidate();
+ }
+ }
+
+ public static void MapBackgroundColor(CheckBoxHandler handler, ICheckBox checkBox)
+ {
+ if (checkBox is Microsoft.Maui.Controls.VisualElement ve && ve.BackgroundColor != null)
+ {
+ handler.PlatformView.BackgroundColor = ve.BackgroundColor.ToSKColor();
+ handler.PlatformView.Invalidate();
+ }
+ }
}
diff --git a/Handlers/CheckBoxHandler.cs b/Handlers/CheckBoxHandler.cs
index b18830e..cfc966b 100644
--- a/Handlers/CheckBoxHandler.cs
+++ b/Handlers/CheckBoxHandler.cs
@@ -18,6 +18,8 @@ public partial class CheckBoxHandler : ViewHandler
[nameof(ICheckBox.IsChecked)] = MapIsChecked,
[nameof(ICheckBox.Foreground)] = MapForeground,
[nameof(IView.Background)] = MapBackground,
+ [nameof(IView.VerticalLayoutAlignment)] = MapVerticalLayoutAlignment,
+ [nameof(IView.HorizontalLayoutAlignment)] = MapHorizontalLayoutAlignment,
};
public static CommandMapper CommandMapper = new(ViewHandler.ViewCommandMapper)
@@ -83,4 +85,32 @@ public partial class CheckBoxHandler : ViewHandler
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
+
+ public static void MapVerticalLayoutAlignment(CheckBoxHandler handler, ICheckBox checkBox)
+ {
+ if (handler.PlatformView is null) return;
+
+ handler.PlatformView.VerticalOptions = checkBox.VerticalLayoutAlignment switch
+ {
+ Primitives.LayoutAlignment.Start => LayoutOptions.Start,
+ Primitives.LayoutAlignment.Center => LayoutOptions.Center,
+ Primitives.LayoutAlignment.End => LayoutOptions.End,
+ Primitives.LayoutAlignment.Fill => LayoutOptions.Fill,
+ _ => LayoutOptions.Fill
+ };
+ }
+
+ public static void MapHorizontalLayoutAlignment(CheckBoxHandler handler, ICheckBox checkBox)
+ {
+ if (handler.PlatformView is null) return;
+
+ handler.PlatformView.HorizontalOptions = checkBox.HorizontalLayoutAlignment switch
+ {
+ Primitives.LayoutAlignment.Start => LayoutOptions.Start,
+ Primitives.LayoutAlignment.Center => LayoutOptions.Center,
+ Primitives.LayoutAlignment.End => LayoutOptions.End,
+ Primitives.LayoutAlignment.Fill => LayoutOptions.Fill,
+ _ => LayoutOptions.Start
+ };
+ }
}
diff --git a/Handlers/CollectionViewHandler.cs b/Handlers/CollectionViewHandler.cs
index 47d0141..e76a4a6 100644
--- a/Handlers/CollectionViewHandler.cs
+++ b/Handlers/CollectionViewHandler.cs
@@ -15,6 +15,8 @@ namespace Microsoft.Maui.Platform.Linux.Handlers;
///
public partial class CollectionViewHandler : ViewHandler
{
+ private bool _isUpdatingSelection;
+
public static IPropertyMapper Mapper =
new PropertyMapper(ViewHandler.ViewMapper)
{
@@ -36,6 +38,7 @@ public partial class CollectionViewHandler : ViewHandler CommandMapper =
@@ -76,21 +79,34 @@ public partial class CollectionViewHandler : ViewHandler
+ {
+ try
+ {
+ // Create view from template
+ var content = template.CreateContent();
+ if (content is View view)
+ {
+ // Set binding context FIRST so bindings evaluate
+ view.BindingContext = item;
+
+ // Force binding evaluation by accessing the visual tree
+ // This ensures child bindings are evaluated before handler creation
+ PropagateBindingContext(view, item);
+
+ // Create handler for the view
+ if (view.Handler == null && handler.MauiContext != null)
+ {
+ view.Handler = view.ToHandler(handler.MauiContext);
+ }
+
+ if (view.Handler?.PlatformView is SkiaView skiaView)
+ {
+ return skiaView;
+ }
+ }
+ else if (content is ViewCell cell)
+ {
+ cell.BindingContext = item;
+ var cellView = cell.View;
+ if (cellView != null)
+ {
+ if (cellView.Handler == null && handler.MauiContext != null)
+ {
+ cellView.Handler = cellView.ToHandler(handler.MauiContext);
+ }
+
+ if (cellView.Handler?.PlatformView is SkiaView skiaView)
+ {
+ return skiaView;
+ }
+ }
+ }
+ }
+ catch
+ {
+ // Ignore template creation errors
+ }
+ return null;
+ };
+ }
+
+ handler.PlatformView.Invalidate();
}
public static void MapEmptyView(CollectionViewHandler handler, CollectionView collectionView)
@@ -146,19 +220,40 @@ public partial class CollectionViewHandler : ViewHandler 0)
+ try
{
- handler.PlatformView.SelectedItem = selectedItems.First();
+ handler._isUpdatingSelection = true;
+
+ // Sync selected items
+ var selectedItems = collectionView.SelectedItems;
+ if (selectedItems != null && selectedItems.Count > 0)
+ {
+ handler.PlatformView.SelectedItem = selectedItems.First();
+ }
+ }
+ finally
+ {
+ handler._isUpdatingSelection = false;
}
}
@@ -214,12 +309,26 @@ public partial class CollectionViewHandler : ViewHandler
+ /// Recursively propagates binding context to all child views to force binding evaluation.
+ ///
+ private static void PropagateBindingContext(View view, object? bindingContext)
+ {
+ view.BindingContext = bindingContext;
+
+ // Propagate to children
+ if (view is Layout layout)
+ {
+ foreach (var child in layout.Children)
+ {
+ if (child is View childView)
+ {
+ PropagateBindingContext(childView, bindingContext);
+ }
+ }
+ }
+ else if (view is ContentView contentView && contentView.Content != null)
+ {
+ PropagateBindingContext(contentView.Content, bindingContext);
+ }
+ else if (view is Border border && border.Content is View borderContent)
+ {
+ PropagateBindingContext(borderContent, bindingContext);
+ }
+ }
}
diff --git a/Handlers/EditorHandler.cs b/Handlers/EditorHandler.cs
index 1e0ba7e..447eede 100644
--- a/Handlers/EditorHandler.cs
+++ b/Handlers/EditorHandler.cs
@@ -31,6 +31,7 @@ public partial class EditorHandler : ViewHandler
[nameof(IEditor.HorizontalTextAlignment)] = MapHorizontalTextAlignment,
[nameof(IEditor.VerticalTextAlignment)] = MapVerticalTextAlignment,
[nameof(IView.Background)] = MapBackground,
+ ["BackgroundColor"] = MapBackgroundColor,
};
public static CommandMapper CommandMapper =
@@ -82,6 +83,7 @@ public partial class EditorHandler : ViewHandler
{
if (handler.PlatformView is null) return;
handler.PlatformView.Text = editor.Text ?? "";
+ handler.PlatformView.Invalidate();
}
public static void MapPlaceholder(EditorHandler handler, IEditor editor)
@@ -165,4 +167,15 @@ public partial class EditorHandler : ViewHandler
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
+
+ public static void MapBackgroundColor(EditorHandler handler, IEditor editor)
+ {
+ if (handler.PlatformView is null) return;
+
+ if (editor is VisualElement ve && ve.BackgroundColor != null)
+ {
+ handler.PlatformView.BackgroundColor = ve.BackgroundColor.ToSKColor();
+ handler.PlatformView.Invalidate();
+ }
+ }
}
diff --git a/Handlers/EntryHandler.Linux.cs b/Handlers/EntryHandler.Linux.cs
index 9c99862..1f2eac6 100644
--- a/Handlers/EntryHandler.Linux.cs
+++ b/Handlers/EntryHandler.Linux.cs
@@ -30,6 +30,7 @@ public partial class EntryHandler : ViewHandler
[nameof(IEntry.ReturnType)] = MapReturnType,
[nameof(IView.IsEnabled)] = MapIsEnabled,
[nameof(IEntry.Background)] = MapBackground,
+ ["BackgroundColor"] = MapBackgroundColor,
};
///
@@ -186,4 +187,13 @@ public partial class EntryHandler : ViewHandler
}
handler.PlatformView.Invalidate();
}
+
+ public static void MapBackgroundColor(EntryHandler handler, IEntry entry)
+ {
+ if (entry is Microsoft.Maui.Controls.VisualElement ve && ve.BackgroundColor != null)
+ {
+ handler.PlatformView.BackgroundColor = ve.BackgroundColor.ToSKColor();
+ handler.PlatformView.Invalidate();
+ }
+ }
}
diff --git a/Handlers/EntryHandler.cs b/Handlers/EntryHandler.cs
index 1cd054a..ac0ff82 100644
--- a/Handlers/EntryHandler.cs
+++ b/Handlers/EntryHandler.cs
@@ -85,7 +85,10 @@ public partial class EntryHandler : ViewHandler
if (handler.PlatformView is null) return;
if (handler.PlatformView.Text != entry.Text)
+ {
handler.PlatformView.Text = entry.Text ?? string.Empty;
+ handler.PlatformView.Invalidate();
+ }
}
public static void MapTextColor(EntryHandler handler, IEntry entry)
diff --git a/Handlers/FrameHandler.cs b/Handlers/FrameHandler.cs
new file mode 100644
index 0000000..88847b7
--- /dev/null
+++ b/Handlers/FrameHandler.cs
@@ -0,0 +1,104 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.Maui.Controls;
+using Microsoft.Maui.Handlers;
+using SkiaSharp;
+
+namespace Microsoft.Maui.Platform.Linux.Handlers;
+
+///
+/// Handler for Frame on Linux using SkiaFrame.
+///
+public partial class FrameHandler : ViewHandler
+{
+ public static IPropertyMapper Mapper =
+ new PropertyMapper(ViewMapper)
+ {
+ [nameof(Frame.BorderColor)] = MapBorderColor,
+ [nameof(Frame.CornerRadius)] = MapCornerRadius,
+ [nameof(Frame.HasShadow)] = MapHasShadow,
+ [nameof(Frame.BackgroundColor)] = MapBackgroundColor,
+ [nameof(Frame.Padding)] = MapPadding,
+ [nameof(Frame.Content)] = MapContent,
+ };
+
+ public FrameHandler() : base(Mapper)
+ {
+ }
+
+ public FrameHandler(IPropertyMapper? mapper)
+ : base(mapper ?? Mapper)
+ {
+ }
+
+ protected override SkiaFrame CreatePlatformView()
+ {
+ return new SkiaFrame();
+ }
+
+ public static void MapBorderColor(FrameHandler handler, Frame frame)
+ {
+ if (frame.BorderColor != null)
+ {
+ handler.PlatformView.Stroke = new SKColor(
+ (byte)(frame.BorderColor.Red * 255),
+ (byte)(frame.BorderColor.Green * 255),
+ (byte)(frame.BorderColor.Blue * 255),
+ (byte)(frame.BorderColor.Alpha * 255));
+ }
+ }
+
+ public static void MapCornerRadius(FrameHandler handler, Frame frame)
+ {
+ handler.PlatformView.CornerRadius = frame.CornerRadius;
+ }
+
+ public static void MapHasShadow(FrameHandler handler, Frame frame)
+ {
+ handler.PlatformView.HasShadow = frame.HasShadow;
+ }
+
+ public static void MapBackgroundColor(FrameHandler handler, Frame frame)
+ {
+ if (frame.BackgroundColor != null)
+ {
+ handler.PlatformView.BackgroundColor = new SKColor(
+ (byte)(frame.BackgroundColor.Red * 255),
+ (byte)(frame.BackgroundColor.Green * 255),
+ (byte)(frame.BackgroundColor.Blue * 255),
+ (byte)(frame.BackgroundColor.Alpha * 255));
+ }
+ }
+
+ public static void MapPadding(FrameHandler handler, Frame frame)
+ {
+ handler.PlatformView.SetPadding(
+ (float)frame.Padding.Left,
+ (float)frame.Padding.Top,
+ (float)frame.Padding.Right,
+ (float)frame.Padding.Bottom);
+ }
+
+ public static void MapContent(FrameHandler handler, Frame frame)
+ {
+ if (handler.PlatformView is null || handler.MauiContext is null) return;
+
+ handler.PlatformView.ClearChildren();
+
+ var content = frame.Content;
+ if (content != null)
+ {
+ // Create handler for content if it doesn't exist
+ if (content.Handler == null)
+ {
+ content.Handler = content.ToHandler(handler.MauiContext);
+ }
+
+ if (content.Handler?.PlatformView is SkiaView skiaContent)
+ {
+ handler.PlatformView.AddChild(skiaContent);
+ }
+ }
+ }
+}
diff --git a/Handlers/LabelHandler.Linux.cs b/Handlers/LabelHandler.Linux.cs
index a2bb8c2..3df3fd4 100644
--- a/Handlers/LabelHandler.Linux.cs
+++ b/Handlers/LabelHandler.Linux.cs
@@ -26,6 +26,8 @@ public partial class LabelHandler : ViewHandler
[nameof(ILabel.Padding)] = MapPadding,
[nameof(ILabel.TextDecorations)] = MapTextDecorations,
[nameof(ILabel.LineHeight)] = MapLineHeight,
+ [nameof(ILabel.Background)] = MapBackground,
+ ["BackgroundColor"] = MapBackgroundColor,
};
///
@@ -151,4 +153,22 @@ public partial class LabelHandler : ViewHandler
handler.PlatformView.LineHeight = (float)label.LineHeight;
handler.PlatformView.Invalidate();
}
+
+ public static void MapBackground(LabelHandler handler, ILabel label)
+ {
+ if (label.Background is SolidColorBrush solidBrush && solidBrush.Color != null)
+ {
+ handler.PlatformView.BackgroundColor = solidBrush.Color.ToSKColor();
+ handler.PlatformView.Invalidate();
+ }
+ }
+
+ public static void MapBackgroundColor(LabelHandler handler, ILabel label)
+ {
+ if (label is Microsoft.Maui.Controls.VisualElement ve && ve.BackgroundColor != null)
+ {
+ handler.PlatformView.BackgroundColor = ve.BackgroundColor.ToSKColor();
+ handler.PlatformView.Invalidate();
+ }
+ }
}
diff --git a/Handlers/LabelHandler.cs b/Handlers/LabelHandler.cs
index 726eba6..a94953f 100644
--- a/Handlers/LabelHandler.cs
+++ b/Handlers/LabelHandler.cs
@@ -23,8 +23,12 @@ public partial class LabelHandler : ViewHandler
[nameof(ITextAlignment.VerticalTextAlignment)] = MapVerticalTextAlignment,
[nameof(ILabel.TextDecorations)] = MapTextDecorations,
[nameof(ILabel.LineHeight)] = MapLineHeight,
+ ["LineBreakMode"] = MapLineBreakMode,
+ ["MaxLines"] = MapMaxLines,
[nameof(IPadding.Padding)] = MapPadding,
[nameof(IView.Background)] = MapBackground,
+ [nameof(IView.VerticalLayoutAlignment)] = MapVerticalLayoutAlignment,
+ [nameof(IView.HorizontalLayoutAlignment)] = MapHorizontalLayoutAlignment,
};
public static CommandMapper CommandMapper = new(ViewHandler.ViewCommandMapper)
@@ -121,6 +125,37 @@ public partial class LabelHandler : ViewHandler
handler.PlatformView.LineHeight = (float)label.LineHeight;
}
+ public static void MapLineBreakMode(LabelHandler handler, ILabel label)
+ {
+ if (handler.PlatformView is null) return;
+
+ // LineBreakMode is on Label control, not ILabel interface
+ if (label is Microsoft.Maui.Controls.Label mauiLabel)
+ {
+ handler.PlatformView.LineBreakMode = mauiLabel.LineBreakMode switch
+ {
+ Microsoft.Maui.LineBreakMode.NoWrap => Platform.LineBreakMode.NoWrap,
+ Microsoft.Maui.LineBreakMode.WordWrap => Platform.LineBreakMode.WordWrap,
+ Microsoft.Maui.LineBreakMode.CharacterWrap => Platform.LineBreakMode.CharacterWrap,
+ Microsoft.Maui.LineBreakMode.HeadTruncation => Platform.LineBreakMode.HeadTruncation,
+ Microsoft.Maui.LineBreakMode.TailTruncation => Platform.LineBreakMode.TailTruncation,
+ Microsoft.Maui.LineBreakMode.MiddleTruncation => Platform.LineBreakMode.MiddleTruncation,
+ _ => Platform.LineBreakMode.TailTruncation
+ };
+ }
+ }
+
+ public static void MapMaxLines(LabelHandler handler, ILabel label)
+ {
+ if (handler.PlatformView is null) return;
+
+ // MaxLines is on Label control, not ILabel interface
+ if (label is Microsoft.Maui.Controls.Label mauiLabel)
+ {
+ handler.PlatformView.MaxLines = mauiLabel.MaxLines;
+ }
+ }
+
public static void MapPadding(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
@@ -142,4 +177,32 @@ public partial class LabelHandler : ViewHandler
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
+
+ public static void MapVerticalLayoutAlignment(LabelHandler handler, ILabel label)
+ {
+ if (handler.PlatformView is null) return;
+
+ handler.PlatformView.VerticalOptions = label.VerticalLayoutAlignment switch
+ {
+ Primitives.LayoutAlignment.Start => LayoutOptions.Start,
+ Primitives.LayoutAlignment.Center => LayoutOptions.Center,
+ Primitives.LayoutAlignment.End => LayoutOptions.End,
+ Primitives.LayoutAlignment.Fill => LayoutOptions.Fill,
+ _ => LayoutOptions.Start
+ };
+ }
+
+ public static void MapHorizontalLayoutAlignment(LabelHandler handler, ILabel label)
+ {
+ if (handler.PlatformView is null) return;
+
+ handler.PlatformView.HorizontalOptions = label.HorizontalLayoutAlignment switch
+ {
+ Primitives.LayoutAlignment.Start => LayoutOptions.Start,
+ Primitives.LayoutAlignment.Center => LayoutOptions.Center,
+ Primitives.LayoutAlignment.End => LayoutOptions.End,
+ Primitives.LayoutAlignment.Fill => LayoutOptions.Fill,
+ _ => LayoutOptions.Start
+ };
+ }
}
diff --git a/Handlers/LayoutHandler.Linux.cs b/Handlers/LayoutHandler.Linux.cs
index 96a200a..f5fd97a 100644
--- a/Handlers/LayoutHandler.Linux.cs
+++ b/Handlers/LayoutHandler.Linux.cs
@@ -17,7 +17,9 @@ public partial class LayoutHandler : ViewHandler
public static IPropertyMapper Mapper = new PropertyMapper(ViewHandler.ViewMapper)
{
[nameof(ILayout.Background)] = MapBackground,
+ ["BackgroundColor"] = MapBackgroundColor,
[nameof(ILayout.ClipsToBounds)] = MapClipsToBounds,
+ [nameof(IPadding.Padding)] = MapPadding,
};
///
@@ -53,8 +55,46 @@ public partial class LayoutHandler : ViewHandler
return new SkiaStackLayout();
}
+ protected override void ConnectHandler(SkiaLayoutView platformView)
+ {
+ base.ConnectHandler(platformView);
+
+ // Explicitly map BackgroundColor since it may be set before handler creation
+ // (e.g., in ItemTemplates for CollectionView)
+ if (VirtualView is Microsoft.Maui.Controls.VisualElement ve && ve.BackgroundColor != null)
+ {
+ platformView.BackgroundColor = ve.BackgroundColor.ToSKColor();
+ platformView.Invalidate();
+ }
+
+ // Add existing children (important for template-created views)
+ if (VirtualView is ILayout layout && MauiContext != null)
+ {
+ for (int i = 0; i < layout.Count; i++)
+ {
+ var child = layout[i];
+ if (child == null) continue;
+
+ // Create handler for child if it doesn't exist
+ if (child.Handler == null)
+ {
+ child.Handler = child.ToHandler(MauiContext);
+ }
+
+ if (child.Handler?.PlatformView is SkiaView skiaChild)
+ {
+ platformView.AddChild(skiaChild);
+ }
+ }
+ }
+ }
+
public static void MapBackground(LayoutHandler handler, ILayout layout)
{
+ // Don't override if BackgroundColor is explicitly set
+ if (layout is Microsoft.Maui.Controls.VisualElement ve && ve.BackgroundColor != null)
+ return;
+
var background = layout.Background;
if (background is SolidColorBrush solidBrush && solidBrush.Color != null)
{
@@ -63,12 +103,36 @@ public partial class LayoutHandler : ViewHandler
handler.PlatformView.Invalidate();
}
+ public static void MapBackgroundColor(LayoutHandler handler, ILayout layout)
+ {
+ if (layout is Microsoft.Maui.Controls.VisualElement ve && ve.BackgroundColor != null)
+ {
+ handler.PlatformView.BackgroundColor = ve.BackgroundColor.ToSKColor();
+ handler.PlatformView.Invalidate();
+ }
+ }
+
public static void MapClipsToBounds(LayoutHandler handler, ILayout layout)
{
handler.PlatformView.ClipToBounds = layout.ClipsToBounds;
handler.PlatformView.Invalidate();
}
+ public static void MapPadding(LayoutHandler handler, ILayout layout)
+ {
+ if (layout is IPadding paddable)
+ {
+ var padding = paddable.Padding;
+ handler.PlatformView.Padding = new SKRect(
+ (float)padding.Left,
+ (float)padding.Top,
+ (float)padding.Right,
+ (float)padding.Bottom);
+ handler.PlatformView.InvalidateMeasure();
+ handler.PlatformView.Invalidate();
+ }
+ }
+
public static void MapAdd(LayoutHandler handler, ILayout layout, object? arg)
{
if (arg is LayoutHandlerUpdate update)
@@ -194,9 +258,16 @@ public partial class GridHandler : LayoutHandler
{
[nameof(IGridLayout.ColumnSpacing)] = MapColumnSpacing,
[nameof(IGridLayout.RowSpacing)] = MapRowSpacing,
+ [nameof(IGridLayout.RowDefinitions)] = MapRowDefinitions,
+ [nameof(IGridLayout.ColumnDefinitions)] = MapColumnDefinitions,
};
- public GridHandler() : base(Mapper)
+ public static new CommandMapper GridCommandMapper = new(LayoutHandler.CommandMapper)
+ {
+ ["Add"] = MapGridAdd,
+ };
+
+ public GridHandler() : base(Mapper, GridCommandMapper)
{
}
@@ -205,6 +276,52 @@ public partial class GridHandler : LayoutHandler
return new SkiaGrid();
}
+ protected override void ConnectHandler(SkiaLayoutView platformView)
+ {
+ Console.WriteLine($"[GridHandler.ConnectHandler] Called! VirtualView={VirtualView?.GetType().Name}, PlatformView={platformView?.GetType().Name}, MauiContext={(MauiContext != null ? "set" : "null")}");
+ base.ConnectHandler(platformView);
+
+ // Map definitions on connect
+ if (VirtualView is IGridLayout gridLayout && platformView is SkiaGrid grid && MauiContext != null)
+ {
+ Console.WriteLine($"[GridHandler.ConnectHandler] Grid has {gridLayout.Count} children, RowDefs={gridLayout.RowDefinitions?.Count ?? 0}");
+ UpdateRowDefinitions(grid, gridLayout);
+ UpdateColumnDefinitions(grid, gridLayout);
+
+ // Add existing children (important for template-created views)
+ for (int i = 0; i < gridLayout.Count; i++)
+ {
+ var child = gridLayout[i];
+ if (child == null) continue;
+
+ Console.WriteLine($"[GridHandler.ConnectHandler] Child[{i}]: {child.GetType().Name}, Handler={child.Handler?.GetType().Name ?? "null"}");
+
+ // Create handler for child if it doesn't exist
+ if (child.Handler == null)
+ {
+ child.Handler = child.ToHandler(MauiContext);
+ Console.WriteLine($"[GridHandler.ConnectHandler] Created handler for child[{i}]: {child.Handler?.GetType().Name ?? "failed"}");
+ }
+
+ if (child.Handler?.PlatformView is SkiaView skiaChild)
+ {
+ // Get grid position from attached properties
+ int row = 0, column = 0, rowSpan = 1, columnSpan = 1;
+ if (child is Microsoft.Maui.Controls.View mauiView)
+ {
+ row = Microsoft.Maui.Controls.Grid.GetRow(mauiView);
+ column = Microsoft.Maui.Controls.Grid.GetColumn(mauiView);
+ rowSpan = Microsoft.Maui.Controls.Grid.GetRowSpan(mauiView);
+ columnSpan = Microsoft.Maui.Controls.Grid.GetColumnSpan(mauiView);
+ }
+ Console.WriteLine($"[GridHandler.ConnectHandler] Adding child[{i}] at row={row}, col={column}");
+ grid.AddChild(skiaChild, row, column, rowSpan, columnSpan);
+ }
+ }
+ Console.WriteLine($"[GridHandler.ConnectHandler] Grid now has {grid.Children.Count} SkiaView children");
+ }
+ }
+
public static void MapColumnSpacing(GridHandler handler, IGridLayout layout)
{
if (handler.PlatformView is SkiaGrid grid)
@@ -222,6 +339,79 @@ public partial class GridHandler : LayoutHandler
grid.Invalidate();
}
}
+
+ public static void MapRowDefinitions(GridHandler handler, IGridLayout layout)
+ {
+ if (handler.PlatformView is SkiaGrid grid)
+ {
+ UpdateRowDefinitions(grid, layout);
+ grid.InvalidateMeasure();
+ grid.Invalidate();
+ }
+ }
+
+ public static void MapColumnDefinitions(GridHandler handler, IGridLayout layout)
+ {
+ if (handler.PlatformView is SkiaGrid grid)
+ {
+ UpdateColumnDefinitions(grid, layout);
+ grid.InvalidateMeasure();
+ grid.Invalidate();
+ }
+ }
+
+ private static void UpdateRowDefinitions(SkiaGrid grid, IGridLayout layout)
+ {
+ grid.RowDefinitions.Clear();
+ foreach (var rowDef in layout.RowDefinitions)
+ {
+ var height = rowDef.Height;
+ if (height.IsAbsolute)
+ grid.RowDefinitions.Add(new GridLength((float)height.Value, GridUnitType.Absolute));
+ else if (height.IsAuto)
+ grid.RowDefinitions.Add(GridLength.Auto);
+ else // Star
+ grid.RowDefinitions.Add(new GridLength((float)height.Value, GridUnitType.Star));
+ }
+ }
+
+ private static void UpdateColumnDefinitions(SkiaGrid grid, IGridLayout layout)
+ {
+ grid.ColumnDefinitions.Clear();
+ foreach (var colDef in layout.ColumnDefinitions)
+ {
+ var width = colDef.Width;
+ if (width.IsAbsolute)
+ grid.ColumnDefinitions.Add(new GridLength((float)width.Value, GridUnitType.Absolute));
+ else if (width.IsAuto)
+ grid.ColumnDefinitions.Add(GridLength.Auto);
+ else // Star
+ grid.ColumnDefinitions.Add(new GridLength((float)width.Value, GridUnitType.Star));
+ }
+ }
+
+ public static void MapGridAdd(GridHandler handler, ILayout layout, object? arg)
+ {
+ if (arg is LayoutHandlerUpdate update && handler.PlatformView is SkiaGrid grid)
+ {
+ var childHandler = update.View.Handler;
+ if (childHandler?.PlatformView is SkiaView skiaView)
+ {
+ // Get grid position from attached properties
+ int row = 0, column = 0, rowSpan = 1, columnSpan = 1;
+
+ if (update.View is Microsoft.Maui.Controls.View mauiView)
+ {
+ row = Microsoft.Maui.Controls.Grid.GetRow(mauiView);
+ column = Microsoft.Maui.Controls.Grid.GetColumn(mauiView);
+ rowSpan = Microsoft.Maui.Controls.Grid.GetRowSpan(mauiView);
+ columnSpan = Microsoft.Maui.Controls.Grid.GetColumnSpan(mauiView);
+ }
+
+ grid.AddChild(skiaView, row, column, rowSpan, columnSpan);
+ }
+ }
+ }
}
///
diff --git a/Handlers/LayoutHandler.cs b/Handlers/LayoutHandler.cs
index 3341767..3b94823 100644
--- a/Handlers/LayoutHandler.cs
+++ b/Handlers/LayoutHandler.cs
@@ -17,6 +17,7 @@ public partial class LayoutHandler : ViewHandler
{
[nameof(ILayout.ClipsToBounds)] = MapClipsToBounds,
[nameof(IView.Background)] = MapBackground,
+ [nameof(IPadding.Padding)] = MapPadding,
};
public static CommandMapper CommandMapper = new(ViewHandler.ViewCommandMapper)
@@ -42,6 +43,38 @@ public partial class LayoutHandler : ViewHandler
return new SkiaStackLayout();
}
+ protected override void ConnectHandler(SkiaLayoutView platformView)
+ {
+ base.ConnectHandler(platformView);
+
+ // Create handlers for all children and add them to the platform view
+ if (VirtualView == null || MauiContext == null) return;
+
+ // Explicitly map BackgroundColor since it may be set before handler creation
+ if (VirtualView is Microsoft.Maui.Controls.VisualElement ve && ve.BackgroundColor != null)
+ {
+ platformView.BackgroundColor = ve.BackgroundColor.ToSKColor();
+ }
+
+ for (int i = 0; i < VirtualView.Count; i++)
+ {
+ var child = VirtualView[i];
+ if (child == null) continue;
+
+ // Create handler for child if it doesn't exist
+ if (child.Handler == null)
+ {
+ child.Handler = child.ToHandler(MauiContext);
+ }
+
+ // Add child's platform view to our layout
+ if (child.Handler?.PlatformView is SkiaView skiaChild)
+ {
+ platformView.AddChild(skiaChild);
+ }
+ }
+ }
+
public static void MapClipsToBounds(LayoutHandler handler, ILayout layout)
{
if (handler.PlatformView == null) return;
@@ -102,6 +135,23 @@ public partial class LayoutHandler : ViewHandler
// Force re-layout
handler.PlatformView?.InvalidateMeasure();
}
+
+ public static void MapPadding(LayoutHandler handler, ILayout layout)
+ {
+ if (handler.PlatformView == null) return;
+
+ if (layout is IPadding paddable)
+ {
+ var padding = paddable.Padding;
+ handler.PlatformView.Padding = new SKRect(
+ (float)padding.Left,
+ (float)padding.Top,
+ (float)padding.Right,
+ (float)padding.Bottom);
+ handler.PlatformView.InvalidateMeasure();
+ handler.PlatformView.Invalidate();
+ }
+ }
}
///
@@ -138,6 +188,29 @@ public partial class StackLayoutHandler : LayoutHandler
return new SkiaStackLayout();
}
+ protected override void ConnectHandler(SkiaLayoutView platformView)
+ {
+ // Set orientation first
+ if (platformView is SkiaStackLayout stackLayout && VirtualView is IStackLayout stackView)
+ {
+ // Determine orientation based on view type
+ if (VirtualView is Microsoft.Maui.Controls.HorizontalStackLayout)
+ {
+ stackLayout.Orientation = StackOrientation.Horizontal;
+ }
+ else if (VirtualView is Microsoft.Maui.Controls.VerticalStackLayout ||
+ VirtualView is Microsoft.Maui.Controls.StackLayout)
+ {
+ stackLayout.Orientation = StackOrientation.Vertical;
+ }
+
+ stackLayout.Spacing = (float)stackView.Spacing;
+ }
+
+ // Let base handle children
+ base.ConnectHandler(platformView);
+ }
+
public static void MapSpacing(StackLayoutHandler handler, IStackLayout layout)
{
if (handler.PlatformView is SkiaStackLayout stackLayout)
@@ -156,6 +229,8 @@ public partial class GridHandler : LayoutHandler
{
[nameof(IGridLayout.RowSpacing)] = MapRowSpacing,
[nameof(IGridLayout.ColumnSpacing)] = MapColumnSpacing,
+ [nameof(IGridLayout.RowDefinitions)] = MapRowDefinitions,
+ [nameof(IGridLayout.ColumnDefinitions)] = MapColumnDefinitions,
};
public GridHandler() : base(Mapper)
@@ -167,6 +242,80 @@ public partial class GridHandler : LayoutHandler
return new SkiaGrid();
}
+ protected override void ConnectHandler(SkiaLayoutView platformView)
+ {
+ try
+ {
+ // Don't call base - we handle children specially for Grid
+ if (VirtualView is not IGridLayout gridLayout || MauiContext == null || platformView is not SkiaGrid grid) return;
+
+ Console.WriteLine($"[GridHandler] ConnectHandler: {gridLayout.Count} children, {gridLayout.RowDefinitions.Count} rows, {gridLayout.ColumnDefinitions.Count} cols");
+
+ // Explicitly map BackgroundColor since it may be set before handler creation
+ if (VirtualView is Microsoft.Maui.Controls.VisualElement ve && ve.BackgroundColor != null)
+ {
+ platformView.BackgroundColor = ve.BackgroundColor.ToSKColor();
+ }
+
+ // Explicitly map Padding since it may be set before handler creation
+ if (VirtualView is IPadding paddable)
+ {
+ var padding = paddable.Padding;
+ platformView.Padding = new SKRect(
+ (float)padding.Left,
+ (float)padding.Top,
+ (float)padding.Right,
+ (float)padding.Bottom);
+ Console.WriteLine($"[GridHandler] Applied Padding: L={padding.Left}, T={padding.Top}, R={padding.Right}, B={padding.Bottom}");
+ }
+
+ // Map row/column definitions first
+ MapRowDefinitions(this, gridLayout);
+ MapColumnDefinitions(this, gridLayout);
+
+ // Add each child with its row/column position
+ for (int i = 0; i < gridLayout.Count; i++)
+ {
+ var child = gridLayout[i];
+ if (child == null) continue;
+
+ Console.WriteLine($"[GridHandler] Processing child {i}: {child.GetType().Name}");
+
+ // Create handler for child if it doesn't exist
+ if (child.Handler == null)
+ {
+ child.Handler = child.ToHandler(MauiContext);
+ }
+
+ // Get grid position from attached properties
+ int row = 0, column = 0, rowSpan = 1, columnSpan = 1;
+ if (child is Microsoft.Maui.Controls.View mauiView)
+ {
+ row = Microsoft.Maui.Controls.Grid.GetRow(mauiView);
+ column = Microsoft.Maui.Controls.Grid.GetColumn(mauiView);
+ rowSpan = Microsoft.Maui.Controls.Grid.GetRowSpan(mauiView);
+ columnSpan = Microsoft.Maui.Controls.Grid.GetColumnSpan(mauiView);
+ }
+
+ Console.WriteLine($"[GridHandler] Child {i} at row={row}, col={column}, handler={child.Handler?.GetType().Name}");
+
+ // Add child's platform view to our grid
+ if (child.Handler?.PlatformView is SkiaView skiaChild)
+ {
+ grid.AddChild(skiaChild, row, column, rowSpan, columnSpan);
+ Console.WriteLine($"[GridHandler] Added child {i} to grid");
+ }
+ }
+ Console.WriteLine($"[GridHandler] ConnectHandler complete");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"[GridHandler] EXCEPTION in ConnectHandler: {ex.GetType().Name}: {ex.Message}");
+ Console.WriteLine($"[GridHandler] Stack trace: {ex.StackTrace}");
+ throw;
+ }
+ }
+
public static void MapRowSpacing(GridHandler handler, IGridLayout layout)
{
if (handler.PlatformView is SkiaGrid grid)
@@ -182,4 +331,38 @@ public partial class GridHandler : LayoutHandler
grid.ColumnSpacing = (float)layout.ColumnSpacing;
}
}
+
+ public static void MapRowDefinitions(GridHandler handler, IGridLayout layout)
+ {
+ if (handler.PlatformView is not SkiaGrid grid) return;
+
+ grid.RowDefinitions.Clear();
+ foreach (var rowDef in layout.RowDefinitions)
+ {
+ var height = rowDef.Height;
+ if (height.IsAbsolute)
+ grid.RowDefinitions.Add(new Microsoft.Maui.Platform.GridLength((float)height.Value, Microsoft.Maui.Platform.GridUnitType.Absolute));
+ else if (height.IsAuto)
+ grid.RowDefinitions.Add(Microsoft.Maui.Platform.GridLength.Auto);
+ else // Star
+ grid.RowDefinitions.Add(new Microsoft.Maui.Platform.GridLength((float)height.Value, Microsoft.Maui.Platform.GridUnitType.Star));
+ }
+ }
+
+ public static void MapColumnDefinitions(GridHandler handler, IGridLayout layout)
+ {
+ if (handler.PlatformView is not SkiaGrid grid) return;
+
+ grid.ColumnDefinitions.Clear();
+ foreach (var colDef in layout.ColumnDefinitions)
+ {
+ var width = colDef.Width;
+ if (width.IsAbsolute)
+ grid.ColumnDefinitions.Add(new Microsoft.Maui.Platform.GridLength((float)width.Value, Microsoft.Maui.Platform.GridUnitType.Absolute));
+ else if (width.IsAuto)
+ grid.ColumnDefinitions.Add(Microsoft.Maui.Platform.GridLength.Auto);
+ else // Star
+ grid.ColumnDefinitions.Add(new Microsoft.Maui.Platform.GridLength((float)width.Value, Microsoft.Maui.Platform.GridUnitType.Star));
+ }
+ }
}
diff --git a/Handlers/NavigationPageHandler.cs b/Handlers/NavigationPageHandler.cs
index 3ab62f2..8e899a4 100644
--- a/Handlers/NavigationPageHandler.cs
+++ b/Handlers/NavigationPageHandler.cs
@@ -6,6 +6,7 @@ using Microsoft.Maui.Graphics;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using SkiaSharp;
+using System.Collections.Specialized;
namespace Microsoft.Maui.Platform.Linux.Handlers;
@@ -50,10 +51,15 @@ public partial class NavigationPageHandler : ViewHandler _toolbarSubscriptions = new();
+
+ private void MapToolbarItems(SkiaPage skiaPage, Page page)
+ {
+ if (skiaPage is SkiaContentPage contentPage)
+ {
+ Console.WriteLine($"[NavigationPageHandler] MapToolbarItems for '{page.Title}', count={page.ToolbarItems.Count}");
+
+ contentPage.ToolbarItems.Clear();
+ foreach (var item in page.ToolbarItems)
+ {
+ Console.WriteLine($"[NavigationPageHandler] Adding toolbar item: '{item.Text}', Order={item.Order}");
+ // Default and Primary should both be treated as Primary (shown in toolbar)
+ // Only Secondary goes to overflow menu
+ var order = item.Order == ToolbarItemOrder.Secondary
+ ? SkiaToolbarItemOrder.Secondary
+ : SkiaToolbarItemOrder.Primary;
+
+ // Create a command that invokes the Clicked event
+ var toolbarItem = item; // Capture for closure
+ var clickCommand = new RelayCommand(() =>
+ {
+ Console.WriteLine($"[NavigationPageHandler] ToolbarItem '{toolbarItem.Text}' clicked, invoking...");
+ // Use IMenuItemController to send the click
+ if (toolbarItem is IMenuItemController menuController)
+ {
+ menuController.Activate();
+ }
+ else
+ {
+ // Fallback: invoke Command if set
+ toolbarItem.Command?.Execute(toolbarItem.CommandParameter);
+ }
+ });
+
+ contentPage.ToolbarItems.Add(new SkiaToolbarItem
+ {
+ Text = item.Text ?? "",
+ Order = order,
+ Command = clickCommand
+ });
+ }
+
+ // Subscribe to ToolbarItems changes if not already subscribed
+ if (page.ToolbarItems is INotifyCollectionChanged notifyCollection && !_toolbarSubscriptions.ContainsKey(page))
+ {
+ Console.WriteLine($"[NavigationPageHandler] Subscribing to ToolbarItems changes for '{page.Title}'");
+ notifyCollection.CollectionChanged += (s, e) =>
+ {
+ Console.WriteLine($"[NavigationPageHandler] ToolbarItems changed for '{page.Title}', action={e.Action}");
+ MapToolbarItems(skiaPage, page);
+ skiaPage.Invalidate();
+ };
+ _toolbarSubscriptions[page] = (skiaPage, notifyCollection);
+ }
+ }
+ }
+
+ private void OnVirtualViewPushed(object? sender, Microsoft.Maui.Controls.NavigationEventArgs e)
+ {
+ try
+ {
+ Console.WriteLine($"[NavigationPageHandler] VirtualView Pushed: {e.Page?.Title}");
+ if (e.Page == null || PlatformView == null || MauiContext == null) return;
+
+ // Ensure the page has a handler
+ if (e.Page.Handler == null)
+ {
+ Console.WriteLine($"[NavigationPageHandler] Creating handler for page: {e.Page.GetType().Name}");
+ e.Page.Handler = e.Page.ToHandler(MauiContext);
+ Console.WriteLine($"[NavigationPageHandler] Handler created: {e.Page.Handler?.GetType().Name}");
+ }
+
+ if (e.Page.Handler?.PlatformView is SkiaPage skiaPage)
+ {
+ Console.WriteLine($"[NavigationPageHandler] Setting up skiaPage, content: {skiaPage.Content?.GetType().Name ?? "null"}");
+ skiaPage.ShowNavigationBar = true;
+ skiaPage.TitleBarColor = PlatformView.BarBackgroundColor;
+ skiaPage.TitleTextColor = PlatformView.BarTextColor;
+ Console.WriteLine($"[NavigationPageHandler] Mapping toolbar items");
+ MapToolbarItems(skiaPage, e.Page);
+ Console.WriteLine($"[NavigationPageHandler] Pushing page to platform");
+ PlatformView.Push(skiaPage, true);
+ Console.WriteLine($"[NavigationPageHandler] Push complete");
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"[NavigationPageHandler] EXCEPTION in OnVirtualViewPushed: {ex.GetType().Name}: {ex.Message}");
+ Console.WriteLine($"[NavigationPageHandler] Stack trace: {ex.StackTrace}");
+ throw;
+ }
+ }
+
+ private void OnVirtualViewPopped(object? sender, Microsoft.Maui.Controls.NavigationEventArgs e)
+ {
+ Console.WriteLine($"[NavigationPageHandler] VirtualView Popped: {e.Page?.Title}");
+ // Pop on the platform side to sync with MAUI navigation
+ PlatformView?.Pop(true);
+ }
+
+ private void OnVirtualViewPoppedToRoot(object? sender, Microsoft.Maui.Controls.NavigationEventArgs e)
+ {
+ Console.WriteLine($"[NavigationPageHandler] VirtualView PoppedToRoot");
+ PlatformView?.PopToRoot(true);
}
private void OnPushed(object? sender, NavigationEventArgs e)
@@ -81,7 +266,12 @@ public partial class NavigationPageHandler : ViewHandler 1)
+ {
+ // Don't trigger another pop on platform side
+ VirtualView.Navigation.RemovePage(VirtualView.Navigation.NavigationStack.Last());
+ }
}
private void OnPoppedToRoot(object? sender, NavigationEventArgs e)
@@ -131,14 +321,29 @@ public partial class NavigationPageHandler : ViewHandler
+/// Simple relay command for invoking actions.
+///
+internal class RelayCommand : System.Windows.Input.ICommand
+{
+ private readonly Action _execute;
+ private readonly Func? _canExecute;
+
+ public RelayCommand(Action execute, Func? canExecute = null)
+ {
+ _execute = execute ?? throw new ArgumentNullException(nameof(execute));
+ _canExecute = canExecute;
+ }
+
+ public event EventHandler? CanExecuteChanged;
+
+ public bool CanExecute(object? parameter) => _canExecute?.Invoke() ?? true;
+
+ public void Execute(object? parameter) => _execute();
+
+ public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
+}
diff --git a/Handlers/PageHandler.cs b/Handlers/PageHandler.cs
index 34aba24..67e42e7 100644
--- a/Handlers/PageHandler.cs
+++ b/Handlers/PageHandler.cs
@@ -58,6 +58,7 @@ public partial class PageHandler : ViewHandler
private void OnAppearing(object? sender, EventArgs e)
{
+ Console.WriteLine($"[PageHandler] OnAppearing received for: {VirtualView?.Title}");
(VirtualView as IPageController)?.SendAppearing();
}
@@ -133,18 +134,29 @@ public partial class ContentPageHandler : PageHandler
public static void MapContent(ContentPageHandler handler, ContentPage page)
{
- if (handler.PlatformView is null) return;
+ if (handler.PlatformView is null || handler.MauiContext is null) return;
// Get the platform view for the content
var content = page.Content;
if (content != null)
{
- // The content's handler should provide the platform view
- var contentHandler = content.Handler;
- if (contentHandler?.PlatformView is SkiaView skiaContent)
+ // Create handler for content if it doesn't exist
+ if (content.Handler == null)
{
+ Console.WriteLine($"[ContentPageHandler] Creating handler for content: {content.GetType().Name}");
+ content.Handler = content.ToHandler(handler.MauiContext);
+ }
+
+ // The content's handler should provide the platform view
+ if (content.Handler?.PlatformView is SkiaView skiaContent)
+ {
+ Console.WriteLine($"[ContentPageHandler] Setting content: {skiaContent.GetType().Name}");
handler.PlatformView.Content = skiaContent;
}
+ else
+ {
+ Console.WriteLine($"[ContentPageHandler] Content handler PlatformView is not SkiaView: {content.Handler?.PlatformView?.GetType().Name ?? "null"}");
+ }
}
else
{
diff --git a/Handlers/PickerHandler.cs b/Handlers/PickerHandler.cs
index d53dd74..2c015be 100644
--- a/Handlers/PickerHandler.cs
+++ b/Handlers/PickerHandler.cs
@@ -6,6 +6,7 @@ using Microsoft.Maui.Graphics;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using SkiaSharp;
+using System.Collections.Specialized;
namespace Microsoft.Maui.Platform.Linux.Handlers;
@@ -25,6 +26,7 @@ public partial class PickerHandler : ViewHandler
[nameof(IPicker.HorizontalTextAlignment)] = MapHorizontalTextAlignment,
[nameof(IPicker.VerticalTextAlignment)] = MapVerticalTextAlignment,
[nameof(IView.Background)] = MapBackground,
+ [nameof(Picker.ItemsSource)] = MapItemsSource,
};
public static CommandMapper CommandMapper =
@@ -32,6 +34,8 @@ public partial class PickerHandler : ViewHandler
{
};
+ private INotifyCollectionChanged? _itemsCollection;
+
public PickerHandler() : base(Mapper, CommandMapper)
{
}
@@ -51,6 +55,13 @@ public partial class PickerHandler : ViewHandler
base.ConnectHandler(platformView);
platformView.SelectedIndexChanged += OnSelectedIndexChanged;
+ // Subscribe to items collection changes
+ if (VirtualView is Picker picker && picker.Items is INotifyCollectionChanged items)
+ {
+ _itemsCollection = items;
+ _itemsCollection.CollectionChanged += OnItemsCollectionChanged;
+ }
+
// Load items
ReloadItems();
}
@@ -58,9 +69,21 @@ public partial class PickerHandler : ViewHandler
protected override void DisconnectHandler(SkiaPicker platformView)
{
platformView.SelectedIndexChanged -= OnSelectedIndexChanged;
+
+ if (_itemsCollection != null)
+ {
+ _itemsCollection.CollectionChanged -= OnItemsCollectionChanged;
+ _itemsCollection = null;
+ }
+
base.DisconnectHandler(platformView);
}
+ private void OnItemsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
+ {
+ ReloadItems();
+ }
+
private void OnSelectedIndexChanged(object? sender, EventArgs e)
{
if (VirtualView is null || PlatformView is null) return;
@@ -130,4 +153,9 @@ public partial class PickerHandler : ViewHandler
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
+
+ public static void MapItemsSource(PickerHandler handler, IPicker picker)
+ {
+ handler.ReloadItems();
+ }
}
diff --git a/Handlers/ProgressBarHandler.Linux.cs b/Handlers/ProgressBarHandler.Linux.cs
index 23ee3b6..e12f5fe 100644
--- a/Handlers/ProgressBarHandler.Linux.cs
+++ b/Handlers/ProgressBarHandler.Linux.cs
@@ -15,6 +15,8 @@ public partial class ProgressBarHandler : ViewHandler CommandMapper = new(ViewHandler.ViewCommandMapper);
@@ -40,4 +42,22 @@ public partial class ProgressBarHandler : ViewHandler
+/// Handler for ScrollView on Linux using SkiaScrollView.
+///
+public partial class ScrollViewHandler : ViewHandler
+{
+ public static IPropertyMapper Mapper =
+ new PropertyMapper(ViewMapper)
+ {
+ [nameof(IScrollView.Content)] = MapContent,
+ [nameof(IScrollView.HorizontalScrollBarVisibility)] = MapHorizontalScrollBarVisibility,
+ [nameof(IScrollView.VerticalScrollBarVisibility)] = MapVerticalScrollBarVisibility,
+ [nameof(IScrollView.Orientation)] = MapOrientation,
+ };
+
+ public static CommandMapper CommandMapper =
+ new(ViewCommandMapper)
+ {
+ [nameof(IScrollView.RequestScrollTo)] = MapRequestScrollTo
+ };
+
+ public ScrollViewHandler() : base(Mapper, CommandMapper)
+ {
+ }
+
+ public ScrollViewHandler(IPropertyMapper? mapper)
+ : base(mapper ?? Mapper, CommandMapper)
+ {
+ }
+
+ protected override SkiaScrollView CreatePlatformView()
+ {
+ return new SkiaScrollView();
+ }
+
+ public static void MapContent(ScrollViewHandler handler, IScrollView scrollView)
+ {
+ if (handler.PlatformView == null || handler.MauiContext == null)
+ return;
+
+ var content = scrollView.PresentedContent;
+ if (content != null)
+ {
+ Console.WriteLine($"[ScrollViewHandler] MapContent: {content.GetType().Name}");
+
+ // Create handler for content if it doesn't exist
+ if (content.Handler == null)
+ {
+ content.Handler = content.ToHandler(handler.MauiContext);
+ }
+
+ if (content.Handler?.PlatformView is SkiaView skiaContent)
+ {
+ Console.WriteLine($"[ScrollViewHandler] Setting content: {skiaContent.GetType().Name}");
+ handler.PlatformView.Content = skiaContent;
+ }
+ }
+ else
+ {
+ handler.PlatformView.Content = null;
+ }
+ }
+
+ public static void MapHorizontalScrollBarVisibility(ScrollViewHandler handler, IScrollView scrollView)
+ {
+ handler.PlatformView.HorizontalScrollBarVisibility = scrollView.HorizontalScrollBarVisibility switch
+ {
+ Microsoft.Maui.ScrollBarVisibility.Always => ScrollBarVisibility.Always,
+ Microsoft.Maui.ScrollBarVisibility.Never => ScrollBarVisibility.Never,
+ _ => ScrollBarVisibility.Default
+ };
+ }
+
+ public static void MapVerticalScrollBarVisibility(ScrollViewHandler handler, IScrollView scrollView)
+ {
+ handler.PlatformView.VerticalScrollBarVisibility = scrollView.VerticalScrollBarVisibility switch
+ {
+ Microsoft.Maui.ScrollBarVisibility.Always => ScrollBarVisibility.Always,
+ Microsoft.Maui.ScrollBarVisibility.Never => ScrollBarVisibility.Never,
+ _ => ScrollBarVisibility.Default
+ };
+ }
+
+ public static void MapOrientation(ScrollViewHandler handler, IScrollView scrollView)
+ {
+ handler.PlatformView.Orientation = scrollView.Orientation switch
+ {
+ Microsoft.Maui.ScrollOrientation.Horizontal => ScrollOrientation.Horizontal,
+ Microsoft.Maui.ScrollOrientation.Both => ScrollOrientation.Both,
+ Microsoft.Maui.ScrollOrientation.Neither => ScrollOrientation.Neither,
+ _ => ScrollOrientation.Vertical
+ };
+ }
+
+ public static void MapRequestScrollTo(ScrollViewHandler handler, IScrollView scrollView, object? args)
+ {
+ if (args is ScrollToRequest request)
+ {
+ // Instant means no animation, so we pass !Instant for animated parameter
+ handler.PlatformView.ScrollTo((float)request.HorizontalOffset, (float)request.VerticalOffset, !request.Instant);
+ }
+ }
+}
diff --git a/Handlers/ShellHandler.cs b/Handlers/ShellHandler.cs
index 6c52b76..bd7a2b7 100644
--- a/Handlers/ShellHandler.cs
+++ b/Handlers/ShellHandler.cs
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Graphics;
using SkiaSharp;
@@ -10,13 +11,13 @@ namespace Microsoft.Maui.Platform.Linux.Handlers;
///
/// Handler for Shell on Linux using Skia rendering.
///
-public partial class ShellHandler : ViewHandler
+public partial class ShellHandler : ViewHandler
{
- public static IPropertyMapper Mapper = new PropertyMapper(ViewHandler.ViewMapper)
+ public static IPropertyMapper Mapper = new PropertyMapper(ViewHandler.ViewMapper)
{
};
- public static CommandMapper CommandMapper = new(ViewHandler.ViewCommandMapper)
+ public static CommandMapper CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
@@ -39,12 +40,26 @@ public partial class ShellHandler : ViewHandler
base.ConnectHandler(platformView);
platformView.FlyoutIsPresentedChanged += OnFlyoutIsPresentedChanged;
platformView.Navigated += OnNavigated;
+
+ // Subscribe to Shell navigation events
+ if (VirtualView != null)
+ {
+ VirtualView.Navigating += OnShellNavigating;
+ VirtualView.Navigated += OnShellNavigated;
+ }
}
protected override void DisconnectHandler(SkiaShell platformView)
{
platformView.FlyoutIsPresentedChanged -= OnFlyoutIsPresentedChanged;
platformView.Navigated -= OnNavigated;
+
+ if (VirtualView != null)
+ {
+ VirtualView.Navigating -= OnShellNavigating;
+ VirtualView.Navigated -= OnShellNavigated;
+ }
+
base.DisconnectHandler(platformView);
}
@@ -55,6 +70,24 @@ public partial class ShellHandler : ViewHandler
private void OnNavigated(object? sender, ShellNavigationEventArgs e)
{
- // Handle navigation events
+ // Handle platform navigation events
+ }
+
+ private void OnShellNavigating(object? sender, ShellNavigatingEventArgs e)
+ {
+ Console.WriteLine($"[ShellHandler] Shell Navigating to: {e.Target?.Location}");
+
+ // Route to platform view
+ if (PlatformView != null && e.Target?.Location != null)
+ {
+ var route = e.Target.Location.ToString().TrimStart('/');
+ Console.WriteLine($"[ShellHandler] Routing to: {route}");
+ PlatformView.GoToAsync(route);
+ }
+ }
+
+ private void OnShellNavigated(object? sender, ShellNavigatedEventArgs e)
+ {
+ Console.WriteLine($"[ShellHandler] Shell Navigated to: {e.Current?.Location}");
}
}
diff --git a/Handlers/SliderHandler.Linux.cs b/Handlers/SliderHandler.Linux.cs
index dcf32cd..5f76b5b 100644
--- a/Handlers/SliderHandler.Linux.cs
+++ b/Handlers/SliderHandler.Linux.cs
@@ -19,6 +19,8 @@ public partial class SliderHandler : ViewHandler
[nameof(ISlider.MaximumTrackColor)] = MapMaximumTrackColor,
[nameof(ISlider.ThumbColor)] = MapThumbColor,
[nameof(IView.IsEnabled)] = MapIsEnabled,
+ [nameof(IView.Background)] = MapBackground,
+ ["BackgroundColor"] = MapBackgroundColor,
};
public static CommandMapper CommandMapper = new(ViewHandler.ViewCommandMapper);
@@ -100,4 +102,22 @@ public partial class SliderHandler : ViewHandler
handler.PlatformView.IsEnabled = slider.IsEnabled;
handler.PlatformView.Invalidate();
}
+
+ public static void MapBackground(SliderHandler handler, ISlider slider)
+ {
+ if (slider.Background is SolidColorBrush solidBrush && solidBrush.Color != null)
+ {
+ handler.PlatformView.BackgroundColor = solidBrush.Color.ToSKColor();
+ handler.PlatformView.Invalidate();
+ }
+ }
+
+ public static void MapBackgroundColor(SliderHandler handler, ISlider slider)
+ {
+ if (slider is Microsoft.Maui.Controls.VisualElement ve && ve.BackgroundColor != null)
+ {
+ handler.PlatformView.BackgroundColor = ve.BackgroundColor.ToSKColor();
+ handler.PlatformView.Invalidate();
+ }
+ }
}
diff --git a/Handlers/SliderHandler.cs b/Handlers/SliderHandler.cs
index 31ba9fc..2eb4583 100644
--- a/Handlers/SliderHandler.cs
+++ b/Handlers/SliderHandler.cs
@@ -22,6 +22,7 @@ public partial class SliderHandler : ViewHandler
[nameof(ISlider.MaximumTrackColor)] = MapMaximumTrackColor,
[nameof(ISlider.ThumbColor)] = MapThumbColor,
[nameof(IView.Background)] = MapBackground,
+ [nameof(IView.IsEnabled)] = MapIsEnabled,
};
public static CommandMapper CommandMapper = new(ViewHandler.ViewCommandMapper)
@@ -48,6 +49,15 @@ public partial class SliderHandler : ViewHandler
platformView.ValueChanged += OnValueChanged;
platformView.DragStarted += OnDragStarted;
platformView.DragCompleted += OnDragCompleted;
+
+ // Sync properties that may have been set before handler connection
+ if (VirtualView != null)
+ {
+ MapMinimum(this, VirtualView);
+ MapMaximum(this, VirtualView);
+ MapValue(this, VirtualView);
+ MapIsEnabled(this, VirtualView);
+ }
}
protected override void DisconnectHandler(SkiaSlider platformView)
@@ -133,4 +143,11 @@ public partial class SliderHandler : ViewHandler
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
+
+ public static void MapIsEnabled(SliderHandler handler, ISlider slider)
+ {
+ if (handler.PlatformView is null) return;
+ handler.PlatformView.IsEnabled = slider.IsEnabled;
+ handler.PlatformView.Invalidate();
+ }
}
diff --git a/Handlers/SwitchHandler.Linux.cs b/Handlers/SwitchHandler.Linux.cs
index fd90d66..fd9873e 100644
--- a/Handlers/SwitchHandler.Linux.cs
+++ b/Handlers/SwitchHandler.Linux.cs
@@ -16,6 +16,8 @@ public partial class SwitchHandler : ViewHandler
[nameof(ISwitch.TrackColor)] = MapTrackColor,
[nameof(ISwitch.ThumbColor)] = MapThumbColor,
[nameof(IView.IsEnabled)] = MapIsEnabled,
+ [nameof(IView.Background)] = MapBackground,
+ ["BackgroundColor"] = MapBackgroundColor,
};
public static CommandMapper CommandMapper = new(ViewHandler.ViewCommandMapper);
@@ -71,4 +73,22 @@ public partial class SwitchHandler : ViewHandler
handler.PlatformView.IsEnabled = @switch.IsEnabled;
handler.PlatformView.Invalidate();
}
+
+ public static void MapBackground(SwitchHandler handler, ISwitch @switch)
+ {
+ if (@switch.Background is SolidColorBrush solidBrush && solidBrush.Color != null)
+ {
+ handler.PlatformView.BackgroundColor = solidBrush.Color.ToSKColor();
+ handler.PlatformView.Invalidate();
+ }
+ }
+
+ public static void MapBackgroundColor(SwitchHandler handler, ISwitch @switch)
+ {
+ if (@switch is Microsoft.Maui.Controls.VisualElement ve && ve.BackgroundColor != null)
+ {
+ handler.PlatformView.BackgroundColor = ve.BackgroundColor.ToSKColor();
+ handler.PlatformView.Invalidate();
+ }
+ }
}
diff --git a/Handlers/WebViewHandler.cs b/Handlers/WebViewHandler.cs
new file mode 100644
index 0000000..d4e5e79
--- /dev/null
+++ b/Handlers/WebViewHandler.cs
@@ -0,0 +1,96 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using Microsoft.Maui.Controls;
+using Microsoft.Maui.Handlers;
+using Microsoft.Maui.Platform;
+
+namespace Microsoft.Maui.Platform.Linux.Handlers;
+
+///
+/// Handler for WebView control on Linux using WebKitGTK.
+///
+public partial class WebViewHandler : ViewHandler
+{
+ public static IPropertyMapper Mapper = new PropertyMapper(ViewHandler.ViewMapper)
+ {
+ [nameof(IWebView.Source)] = MapSource,
+ };
+
+ public static CommandMapper CommandMapper = new(ViewHandler.ViewCommandMapper)
+ {
+ [nameof(IWebView.GoBack)] = MapGoBack,
+ [nameof(IWebView.GoForward)] = MapGoForward,
+ [nameof(IWebView.Reload)] = MapReload,
+ };
+
+ public WebViewHandler() : base(Mapper, CommandMapper)
+ {
+ }
+
+ public WebViewHandler(IPropertyMapper? mapper = null, CommandMapper? commandMapper = null)
+ : base(mapper ?? Mapper, commandMapper ?? CommandMapper)
+ {
+ }
+
+ protected override SkiaWebView CreatePlatformView()
+ {
+ return new SkiaWebView();
+ }
+
+ protected override void ConnectHandler(SkiaWebView platformView)
+ {
+ base.ConnectHandler(platformView);
+
+ platformView.Navigating += OnNavigating;
+ platformView.Navigated += OnNavigated;
+ }
+
+ protected override void DisconnectHandler(SkiaWebView platformView)
+ {
+ platformView.Navigating -= OnNavigating;
+ platformView.Navigated -= OnNavigated;
+
+ base.DisconnectHandler(platformView);
+ }
+
+ private void OnNavigating(object? sender, WebNavigatingEventArgs e)
+ {
+ // Forward to virtual view if needed
+ }
+
+ private void OnNavigated(object? sender, WebNavigatedEventArgs e)
+ {
+ // Forward to virtual view if needed
+ }
+
+ public static void MapSource(WebViewHandler handler, IWebView webView)
+ {
+ if (handler.PlatformView == null) return;
+
+ var source = webView.Source;
+ if (source is UrlWebViewSource urlSource)
+ {
+ handler.PlatformView.Source = urlSource.Url ?? "";
+ }
+ else if (source is HtmlWebViewSource htmlSource)
+ {
+ handler.PlatformView.Html = htmlSource.Html ?? "";
+ }
+ }
+
+ public static void MapGoBack(WebViewHandler handler, IWebView webView, object? args)
+ {
+ handler.PlatformView?.GoBack();
+ }
+
+ public static void MapGoForward(WebViewHandler handler, IWebView webView, object? args)
+ {
+ handler.PlatformView?.GoForward();
+ }
+
+ public static void MapReload(WebViewHandler handler, IWebView webView, object? args)
+ {
+ handler.PlatformView?.Reload();
+ }
+}
diff --git a/Handlers/WindowHandler.cs b/Handlers/WindowHandler.cs
index 62b25b2..7dc08aa 100644
--- a/Handlers/WindowHandler.cs
+++ b/Handlers/WindowHandler.cs
@@ -141,6 +141,7 @@ public partial class WindowHandler : ElementHandler
///
/// Skia window wrapper for Linux display servers.
+/// Handles rendering of content and popup overlays automatically.
///
public class SkiaWindow
{
@@ -164,6 +165,28 @@ public class SkiaWindow
}
}
+ ///
+ /// Renders the window content and popup overlays to the canvas.
+ /// This should be called by the platform rendering loop.
+ ///
+ public void Render(SKCanvas canvas)
+ {
+ // Clear background
+ canvas.Clear(SKColors.White);
+
+ // Draw main content
+ if (_content != null)
+ {
+ _content.Measure(new SKSize(_width, _height));
+ _content.Arrange(new SKRect(0, 0, _width, _height));
+ _content.Draw(canvas);
+ }
+
+ // Draw popup overlays on top (dropdowns, date pickers, etc.)
+ // This ensures popups always render above all other content
+ SkiaView.DrawPopupOverlays(canvas);
+ }
+
public string Title
{
get => _title;
diff --git a/Hosting/LinuxMauiAppBuilderExtensions.cs b/Hosting/LinuxMauiAppBuilderExtensions.cs
index 62b0530..baa6339 100644
--- a/Hosting/LinuxMauiAppBuilderExtensions.cs
+++ b/Hosting/LinuxMauiAppBuilderExtensions.cs
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
+using System.ComponentModel;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Maui.ApplicationModel;
@@ -8,9 +9,11 @@ using Microsoft.Maui.ApplicationModel.Communication;
using Microsoft.Maui.ApplicationModel.DataTransfer;
using Microsoft.Maui.Hosting;
using Microsoft.Maui.Platform.Linux.Services;
+using Microsoft.Maui.Platform.Linux.Converters;
using Microsoft.Maui.Storage;
using Microsoft.Maui.Platform.Linux.Handlers;
using Microsoft.Maui.Controls;
+using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Hosting;
@@ -47,51 +50,69 @@ public static class LinuxMauiAppBuilderExtensions
builder.Services.TryAddSingleton();
builder.Services.TryAddSingleton();
+ // Register type converters for XAML support
+ RegisterTypeConverters();
+
// Register Linux-specific handlers
builder.ConfigureMauiHandlers(handlers =>
{
- // Phase 1 - MVP controls
- handlers.AddHandler();
- handlers.AddHandler();
- handlers.AddHandler();
- handlers.AddHandler();
- handlers.AddHandler();
- handlers.AddHandler();
- handlers.AddHandler();
+ // Application handler
+ handlers.AddHandler();
- // Phase 2 - Input controls
- handlers.AddHandler();
- handlers.AddHandler();
- handlers.AddHandler();
- handlers.AddHandler();
- handlers.AddHandler();
+ // Core controls
+ handlers.AddHandler();
+ handlers.AddHandler
public class SkiaTimePicker : SkiaView
{
- private TimeSpan _time = DateTime.Now.TimeOfDay;
- private bool _isOpen;
- private string _format = "t";
- private int _selectedHour;
- private int _selectedMinute;
- private bool _isSelectingHours = true;
+ #region BindableProperties
- // Styling
- public SKColor TextColor { get; set; } = SKColors.Black;
- public SKColor BorderColor { get; set; } = new SKColor(0xBD, 0xBD, 0xBD);
- public SKColor ClockBackgroundColor { get; set; } = SKColors.White;
- public SKColor ClockFaceColor { get; set; } = new SKColor(0xF5, 0xF5, 0xF5);
- public SKColor SelectedColor { get; set; } = new SKColor(0x21, 0x96, 0xF3);
- public SKColor HeaderColor { get; set; } = new SKColor(0x21, 0x96, 0xF3);
- public float FontSize { get; set; } = 14;
- public float CornerRadius { get; set; } = 4;
+ public static readonly BindableProperty TimeProperty =
+ BindableProperty.Create(nameof(Time), typeof(TimeSpan), typeof(SkiaTimePicker), DateTime.Now.TimeOfDay, BindingMode.TwoWay,
+ propertyChanged: (b, o, n) => ((SkiaTimePicker)b).OnTimePropertyChanged());
- private const float ClockSize = 280;
- private const float ClockRadius = 100;
- private const float HeaderHeight = 80;
+ public static readonly BindableProperty FormatProperty =
+ BindableProperty.Create(nameof(Format), typeof(string), typeof(SkiaTimePicker), "t",
+ propertyChanged: (b, o, n) => ((SkiaTimePicker)b).Invalidate());
+
+ public static readonly BindableProperty TextColorProperty =
+ BindableProperty.Create(nameof(TextColor), typeof(SKColor), typeof(SkiaTimePicker), SKColors.Black,
+ propertyChanged: (b, o, n) => ((SkiaTimePicker)b).Invalidate());
+
+ public static readonly BindableProperty BorderColorProperty =
+ BindableProperty.Create(nameof(BorderColor), typeof(SKColor), typeof(SkiaTimePicker), new SKColor(0xBD, 0xBD, 0xBD),
+ propertyChanged: (b, o, n) => ((SkiaTimePicker)b).Invalidate());
+
+ public static readonly BindableProperty ClockBackgroundColorProperty =
+ BindableProperty.Create(nameof(ClockBackgroundColor), typeof(SKColor), typeof(SkiaTimePicker), SKColors.White,
+ propertyChanged: (b, o, n) => ((SkiaTimePicker)b).Invalidate());
+
+ public static readonly BindableProperty ClockFaceColorProperty =
+ BindableProperty.Create(nameof(ClockFaceColor), typeof(SKColor), typeof(SkiaTimePicker), new SKColor(0xF5, 0xF5, 0xF5),
+ propertyChanged: (b, o, n) => ((SkiaTimePicker)b).Invalidate());
+
+ public static readonly BindableProperty SelectedColorProperty =
+ BindableProperty.Create(nameof(SelectedColor), typeof(SKColor), typeof(SkiaTimePicker), new SKColor(0x21, 0x96, 0xF3),
+ propertyChanged: (b, o, n) => ((SkiaTimePicker)b).Invalidate());
+
+ public static readonly BindableProperty HeaderColorProperty =
+ BindableProperty.Create(nameof(HeaderColor), typeof(SKColor), typeof(SkiaTimePicker), new SKColor(0x21, 0x96, 0xF3),
+ propertyChanged: (b, o, n) => ((SkiaTimePicker)b).Invalidate());
+
+ public static readonly BindableProperty FontSizeProperty =
+ BindableProperty.Create(nameof(FontSize), typeof(float), typeof(SkiaTimePicker), 14f,
+ propertyChanged: (b, o, n) => ((SkiaTimePicker)b).InvalidateMeasure());
+
+ public static readonly BindableProperty CornerRadiusProperty =
+ BindableProperty.Create(nameof(CornerRadius), typeof(float), typeof(SkiaTimePicker), 4f,
+ propertyChanged: (b, o, n) => ((SkiaTimePicker)b).Invalidate());
+
+ #endregion
+
+ #region Properties
public TimeSpan Time
{
- get => _time;
- set
- {
- if (_time != value)
- {
- _time = value;
- _selectedHour = _time.Hours;
- _selectedMinute = _time.Minutes;
- TimeSelected?.Invoke(this, EventArgs.Empty);
- Invalidate();
- }
- }
+ get => (TimeSpan)GetValue(TimeProperty);
+ set => SetValue(TimeProperty, value);
}
public string Format
{
- get => _format;
- set { _format = value; Invalidate(); }
+ get => (string)GetValue(FormatProperty);
+ set => SetValue(FormatProperty, value);
+ }
+
+ public SKColor TextColor
+ {
+ get => (SKColor)GetValue(TextColorProperty);
+ set => SetValue(TextColorProperty, value);
+ }
+
+ public SKColor BorderColor
+ {
+ get => (SKColor)GetValue(BorderColorProperty);
+ set => SetValue(BorderColorProperty, value);
+ }
+
+ public SKColor ClockBackgroundColor
+ {
+ get => (SKColor)GetValue(ClockBackgroundColorProperty);
+ set => SetValue(ClockBackgroundColorProperty, value);
+ }
+
+ public SKColor ClockFaceColor
+ {
+ get => (SKColor)GetValue(ClockFaceColorProperty);
+ set => SetValue(ClockFaceColorProperty, value);
+ }
+
+ public SKColor SelectedColor
+ {
+ get => (SKColor)GetValue(SelectedColorProperty);
+ set => SetValue(SelectedColorProperty, value);
+ }
+
+ public SKColor HeaderColor
+ {
+ get => (SKColor)GetValue(HeaderColorProperty);
+ set => SetValue(HeaderColorProperty, value);
+ }
+
+ public float FontSize
+ {
+ get => (float)GetValue(FontSizeProperty);
+ set => SetValue(FontSizeProperty, value);
+ }
+
+ public float CornerRadius
+ {
+ get => (float)GetValue(CornerRadiusProperty);
+ set => SetValue(CornerRadiusProperty, value);
}
public bool IsOpen
{
get => _isOpen;
- set { _isOpen = value; Invalidate(); }
+ set
+ {
+ if (_isOpen != value)
+ {
+ _isOpen = value;
+ if (_isOpen)
+ RegisterPopupOverlay(this, DrawClockOverlay);
+ else
+ UnregisterPopupOverlay(this);
+ Invalidate();
+ }
+ }
}
+ #endregion
+
+ private bool _isOpen;
+ private int _selectedHour;
+ private int _selectedMinute;
+ private bool _isSelectingHours = true;
+
+ private const float ClockSize = 280;
+ private const float ClockRadius = 100;
+ private const float HeaderHeight = 80;
+ private const float PopupHeight = ClockSize + HeaderHeight;
+
public event EventHandler? TimeSelected;
+ ///
+ /// Gets the clock popup rectangle with edge detection applied.
+ ///
+ private SKRect GetPopupRect(SKRect pickerBounds)
+ {
+ // Get window dimensions for edge detection
+ var windowWidth = LinuxApplication.Current?.MainWindow?.Width ?? 800;
+ var windowHeight = LinuxApplication.Current?.MainWindow?.Height ?? 600;
+
+ // Calculate default position (below the picker)
+ var popupLeft = pickerBounds.Left;
+ var popupTop = pickerBounds.Bottom + 4;
+
+ // Edge detection: adjust horizontal position if popup would go off-screen
+ if (popupLeft + ClockSize > windowWidth)
+ {
+ popupLeft = windowWidth - ClockSize - 4;
+ }
+ if (popupLeft < 0) popupLeft = 4;
+
+ // Edge detection: show above if popup would go off-screen vertically
+ if (popupTop + PopupHeight > windowHeight)
+ {
+ popupTop = pickerBounds.Top - PopupHeight - 4;
+ }
+ if (popupTop < 0) popupTop = 4;
+
+ return new SKRect(popupLeft, popupTop, popupLeft + ClockSize, popupTop + PopupHeight);
+ }
+
public SkiaTimePicker()
{
IsFocusable = true;
- _selectedHour = _time.Hours;
- _selectedMinute = _time.Minutes;
+ _selectedHour = DateTime.Now.Hour;
+ _selectedMinute = DateTime.Now.Minute;
+ }
+
+ private void OnTimePropertyChanged()
+ {
+ _selectedHour = Time.Hours;
+ _selectedMinute = Time.Minutes;
+ TimeSelected?.Invoke(this, EventArgs.Empty);
+ Invalidate();
+ }
+
+ private void DrawClockOverlay(SKCanvas canvas)
+ {
+ if (!_isOpen) return;
+ // Use ScreenBounds for popup drawing (accounts for scroll offset)
+ DrawClockPopup(canvas, ScreenBounds);
}
protected override void OnDraw(SKCanvas canvas, SKRect bounds)
{
DrawPickerButton(canvas, bounds);
-
- if (_isOpen)
- {
- DrawClockPopup(canvas, bounds);
- }
}
private void DrawPickerButton(SKCanvas canvas, SKRect bounds)
{
- // Draw background
using var bgPaint = new SKPaint
{
Color = IsEnabled ? BackgroundColor : new SKColor(0xF5, 0xF5, 0xF5),
@@ -89,7 +215,6 @@ public class SkiaTimePicker : SkiaView
};
canvas.DrawRoundRect(new SKRoundRect(bounds, CornerRadius), bgPaint);
- // Draw border
using var borderPaint = new SKPaint
{
Color = IsFocused ? SelectedColor : BorderColor,
@@ -99,23 +224,17 @@ public class SkiaTimePicker : SkiaView
};
canvas.DrawRoundRect(new SKRoundRect(bounds, CornerRadius), borderPaint);
- // Draw time text
using var font = new SKFont(SKTypeface.Default, FontSize);
using var textPaint = new SKPaint(font)
{
Color = IsEnabled ? TextColor : TextColor.WithAlpha(128),
IsAntialias = true
};
-
- var timeText = DateTime.Today.Add(_time).ToString(_format);
+ var timeText = DateTime.Today.Add(Time).ToString(Format);
var textBounds = new SKRect();
textPaint.MeasureText(timeText, ref textBounds);
+ canvas.DrawText(timeText, bounds.Left + 12, bounds.MidY - textBounds.MidY, textPaint);
- var textX = bounds.Left + 12;
- var textY = bounds.MidY - textBounds.MidY;
- canvas.DrawText(timeText, textX, textY, textPaint);
-
- // Draw clock icon
DrawClockIcon(canvas, new SKRect(bounds.Right - 36, bounds.MidY - 10, bounds.Right - 12, bounds.MidY + 10));
}
@@ -128,108 +247,52 @@ public class SkiaTimePicker : SkiaView
StrokeWidth = 1.5f,
IsAntialias = true
};
-
- var centerX = bounds.MidX;
- var centerY = bounds.MidY;
var radius = Math.Min(bounds.Width, bounds.Height) / 2 - 2;
-
- // Clock circle
- canvas.DrawCircle(centerX, centerY, radius, paint);
-
- // Hour hand
- canvas.DrawLine(centerX, centerY, centerX, centerY - radius * 0.5f, paint);
-
- // Minute hand
- canvas.DrawLine(centerX, centerY, centerX + radius * 0.4f, centerY, paint);
-
- // Center dot
+ canvas.DrawCircle(bounds.MidX, bounds.MidY, radius, paint);
+ canvas.DrawLine(bounds.MidX, bounds.MidY, bounds.MidX, bounds.MidY - radius * 0.5f, paint);
+ canvas.DrawLine(bounds.MidX, bounds.MidY, bounds.MidX + radius * 0.4f, bounds.MidY, paint);
paint.Style = SKPaintStyle.Fill;
- canvas.DrawCircle(centerX, centerY, 1.5f, paint);
+ canvas.DrawCircle(bounds.MidX, bounds.MidY, 1.5f, paint);
}
private void DrawClockPopup(SKCanvas canvas, SKRect bounds)
{
- var popupRect = new SKRect(
- bounds.Left,
- bounds.Bottom + 4,
- bounds.Left + ClockSize,
- bounds.Bottom + 4 + HeaderHeight + ClockSize);
+ var popupRect = GetPopupRect(bounds);
- // Draw shadow
- using var shadowPaint = new SKPaint
- {
- Color = new SKColor(0, 0, 0, 40),
- MaskFilter = SKMaskFilter.CreateBlur(SKBlurStyle.Normal, 4),
- Style = SKPaintStyle.Fill
- };
+ using var shadowPaint = new SKPaint { Color = new SKColor(0, 0, 0, 40), MaskFilter = SKMaskFilter.CreateBlur(SKBlurStyle.Normal, 4), Style = SKPaintStyle.Fill };
canvas.DrawRoundRect(new SKRoundRect(new SKRect(popupRect.Left + 2, popupRect.Top + 2, popupRect.Right + 2, popupRect.Bottom + 2), CornerRadius), shadowPaint);
- // Draw background
- using var bgPaint = new SKPaint
- {
- Color = ClockBackgroundColor,
- Style = SKPaintStyle.Fill,
- IsAntialias = true
- };
+ using var bgPaint = new SKPaint { Color = ClockBackgroundColor, Style = SKPaintStyle.Fill, IsAntialias = true };
canvas.DrawRoundRect(new SKRoundRect(popupRect, CornerRadius), bgPaint);
- // Draw border
- using var borderPaint = new SKPaint
- {
- Color = BorderColor,
- Style = SKPaintStyle.Stroke,
- StrokeWidth = 1,
- IsAntialias = true
- };
+ using var borderPaint = new SKPaint { Color = BorderColor, Style = SKPaintStyle.Stroke, StrokeWidth = 1, IsAntialias = true };
canvas.DrawRoundRect(new SKRoundRect(popupRect, CornerRadius), borderPaint);
- // Draw header with time display
DrawTimeHeader(canvas, new SKRect(popupRect.Left, popupRect.Top, popupRect.Right, popupRect.Top + HeaderHeight));
-
- // Draw clock face
DrawClockFace(canvas, new SKRect(popupRect.Left, popupRect.Top + HeaderHeight, popupRect.Right, popupRect.Bottom));
}
private void DrawTimeHeader(SKCanvas canvas, SKRect bounds)
{
- // Draw header background
- using var headerPaint = new SKPaint
- {
- Color = HeaderColor,
- Style = SKPaintStyle.Fill
- };
-
+ using var headerPaint = new SKPaint { Color = HeaderColor, Style = SKPaintStyle.Fill };
canvas.Save();
canvas.ClipRoundRect(new SKRoundRect(new SKRect(bounds.Left, bounds.Top, bounds.Right, bounds.Top + CornerRadius * 2), CornerRadius));
canvas.DrawRect(bounds, headerPaint);
canvas.Restore();
canvas.DrawRect(new SKRect(bounds.Left, bounds.Top + CornerRadius, bounds.Right, bounds.Bottom), headerPaint);
- // Draw time display
using var font = new SKFont(SKTypeface.Default, 32);
- using var selectedPaint = new SKPaint(font)
- {
- Color = SKColors.White,
- IsAntialias = true
- };
- using var unselectedPaint = new SKPaint(font)
- {
- Color = new SKColor(255, 255, 255, 150),
- IsAntialias = true
- };
+ using var selectedPaint = new SKPaint(font) { Color = SKColors.White, IsAntialias = true };
+ using var unselectedPaint = new SKPaint(font) { Color = new SKColor(255, 255, 255, 150), IsAntialias = true };
var hourText = _selectedHour.ToString("D2");
var minuteText = _selectedMinute.ToString("D2");
- var colonText = ":";
-
var hourPaint = _isSelectingHours ? selectedPaint : unselectedPaint;
var minutePaint = _isSelectingHours ? unselectedPaint : selectedPaint;
- var hourBounds = new SKRect();
- var colonBounds = new SKRect();
- var minuteBounds = new SKRect();
+ var hourBounds = new SKRect(); var colonBounds = new SKRect(); var minuteBounds = new SKRect();
hourPaint.MeasureText(hourText, ref hourBounds);
- selectedPaint.MeasureText(colonText, ref colonBounds);
+ selectedPaint.MeasureText(":", ref colonBounds);
minutePaint.MeasureText(minuteText, ref minuteBounds);
var totalWidth = hourBounds.Width + colonBounds.Width + minuteBounds.Width + 8;
@@ -237,7 +300,7 @@ public class SkiaTimePicker : SkiaView
var centerY = bounds.MidY - hourBounds.MidY;
canvas.DrawText(hourText, startX, centerY, hourPaint);
- canvas.DrawText(colonText, startX + hourBounds.Width + 4, centerY, selectedPaint);
+ canvas.DrawText(":", startX + hourBounds.Width + 4, centerY, selectedPaint);
canvas.DrawText(minuteText, startX + hourBounds.Width + colonBounds.Width + 8, centerY, minutePaint);
}
@@ -246,94 +309,53 @@ public class SkiaTimePicker : SkiaView
var centerX = bounds.MidX;
var centerY = bounds.MidY;
- // Draw clock face background
- using var facePaint = new SKPaint
- {
- Color = ClockFaceColor,
- Style = SKPaintStyle.Fill,
- IsAntialias = true
- };
+ using var facePaint = new SKPaint { Color = ClockFaceColor, Style = SKPaintStyle.Fill, IsAntialias = true };
canvas.DrawCircle(centerX, centerY, ClockRadius + 20, facePaint);
- // Draw numbers
using var font = new SKFont(SKTypeface.Default, 14);
- using var textPaint = new SKPaint(font)
- {
- Color = TextColor,
- IsAntialias = true
- };
+ using var textPaint = new SKPaint(font) { Color = TextColor, IsAntialias = true };
if (_isSelectingHours)
{
- // Draw hour numbers (1-12)
for (int i = 1; i <= 12; i++)
{
var angle = (i * 30 - 90) * Math.PI / 180;
var x = centerX + (float)(ClockRadius * Math.Cos(angle));
var y = centerY + (float)(ClockRadius * Math.Sin(angle));
-
- var numText = i.ToString();
- var textBounds = new SKRect();
- textPaint.MeasureText(numText, ref textBounds);
-
var isSelected = (_selectedHour % 12 == i % 12);
if (isSelected)
{
- using var selectedBgPaint = new SKPaint
- {
- Color = SelectedColor,
- Style = SKPaintStyle.Fill,
- IsAntialias = true
- };
- canvas.DrawCircle(x, y, 18, selectedBgPaint);
+ using var selBgPaint = new SKPaint { Color = SelectedColor, Style = SKPaintStyle.Fill, IsAntialias = true };
+ canvas.DrawCircle(x, y, 18, selBgPaint);
textPaint.Color = SKColors.White;
}
- else
- {
- textPaint.Color = TextColor;
- }
-
- canvas.DrawText(numText, x - textBounds.MidX, y - textBounds.MidY, textPaint);
+ else textPaint.Color = TextColor;
+ var textBounds = new SKRect();
+ textPaint.MeasureText(i.ToString(), ref textBounds);
+ canvas.DrawText(i.ToString(), x - textBounds.MidX, y - textBounds.MidY, textPaint);
}
-
- // Draw center point and hand
DrawClockHand(canvas, centerX, centerY, (_selectedHour % 12) * 30 - 90, ClockRadius - 18);
}
else
{
- // Draw minute numbers (0, 5, 10, ... 55)
for (int i = 0; i < 12; i++)
{
var minute = i * 5;
var angle = (minute * 6 - 90) * Math.PI / 180;
var x = centerX + (float)(ClockRadius * Math.Cos(angle));
var y = centerY + (float)(ClockRadius * Math.Sin(angle));
-
- var numText = minute.ToString("D2");
- var textBounds = new SKRect();
- textPaint.MeasureText(numText, ref textBounds);
-
var isSelected = (_selectedMinute / 5 == i);
if (isSelected)
{
- using var selectedBgPaint = new SKPaint
- {
- Color = SelectedColor,
- Style = SKPaintStyle.Fill,
- IsAntialias = true
- };
- canvas.DrawCircle(x, y, 18, selectedBgPaint);
+ using var selBgPaint = new SKPaint { Color = SelectedColor, Style = SKPaintStyle.Fill, IsAntialias = true };
+ canvas.DrawCircle(x, y, 18, selBgPaint);
textPaint.Color = SKColors.White;
}
- else
- {
- textPaint.Color = TextColor;
- }
-
- canvas.DrawText(numText, x - textBounds.MidX, y - textBounds.MidY, textPaint);
+ else textPaint.Color = TextColor;
+ var textBounds = new SKRect();
+ textPaint.MeasureText(minute.ToString("D2"), ref textBounds);
+ canvas.DrawText(minute.ToString("D2"), x - textBounds.MidX, y - textBounds.MidY, textPaint);
}
-
- // Draw center point and hand
DrawClockHand(canvas, centerX, centerY, _selectedMinute * 6 - 90, ClockRadius - 18);
}
}
@@ -341,19 +363,8 @@ public class SkiaTimePicker : SkiaView
private void DrawClockHand(SKCanvas canvas, float centerX, float centerY, float angleDegrees, float length)
{
var angle = angleDegrees * Math.PI / 180;
- var endX = centerX + (float)(length * Math.Cos(angle));
- var endY = centerY + (float)(length * Math.Sin(angle));
-
- using var handPaint = new SKPaint
- {
- Color = SelectedColor,
- Style = SKPaintStyle.Stroke,
- StrokeWidth = 2,
- IsAntialias = true
- };
- canvas.DrawLine(centerX, centerY, endX, endY, handPaint);
-
- // Center dot
+ using var handPaint = new SKPaint { Color = SelectedColor, Style = SKPaintStyle.Stroke, StrokeWidth = 2, IsAntialias = true };
+ canvas.DrawLine(centerX, centerY, centerX + (float)(length * Math.Cos(angle)), centerY + (float)(length * Math.Sin(angle)), handPaint);
handPaint.Style = SKPaintStyle.Fill;
canvas.DrawCircle(centerX, centerY, 6, handPaint);
}
@@ -362,31 +373,24 @@ public class SkiaTimePicker : SkiaView
{
if (!IsEnabled) return;
- if (_isOpen)
+ if (IsOpen)
{
- var popupTop = Bounds.Bottom + 4;
- var popupLeft = Bounds.Left;
+ // Use ScreenBounds for popup coordinate calculations (accounts for scroll offset)
+ var screenBounds = ScreenBounds;
+ var popupRect = GetPopupRect(screenBounds);
- // Check header click (toggle hours/minutes)
- if (e.Y >= popupTop && e.Y < popupTop + HeaderHeight)
+ // Check if click is in header area
+ var headerRect = new SKRect(popupRect.Left, popupRect.Top, popupRect.Right, popupRect.Top + HeaderHeight);
+ if (headerRect.Contains(e.X, e.Y))
{
- var centerX = popupLeft + ClockSize / 2;
- if (e.X < centerX)
- {
- _isSelectingHours = true;
- }
- else
- {
- _isSelectingHours = false;
- }
+ _isSelectingHours = e.X < popupRect.Left + ClockSize / 2;
Invalidate();
return;
}
- // Check clock face click
- var clockCenterX = popupLeft + ClockSize / 2;
- var clockCenterY = popupTop + HeaderHeight + ClockSize / 2;
-
+ // Check if click is in clock face area
+ var clockCenterX = popupRect.Left + ClockSize / 2;
+ var clockCenterY = popupRect.Top + HeaderHeight + ClockSize / 2;
var dx = e.X - clockCenterX;
var dy = e.Y - clockCenterY;
var distance = Math.Sqrt(dx * dx + dy * dy);
@@ -400,114 +404,86 @@ public class SkiaTimePicker : SkiaView
{
_selectedHour = ((int)Math.Round(angle / 30) % 12);
if (_selectedHour == 0) _selectedHour = 12;
- // Preserve AM/PM
- if (_time.Hours >= 12 && _selectedHour != 12)
- _selectedHour += 12;
- else if (_time.Hours < 12 && _selectedHour == 12)
- _selectedHour = 0;
-
- _isSelectingHours = false; // Move to minutes
+ if (Time.Hours >= 12 && _selectedHour != 12) _selectedHour += 12;
+ else if (Time.Hours < 12 && _selectedHour == 12) _selectedHour = 0;
+ _isSelectingHours = false;
}
else
{
_selectedMinute = ((int)Math.Round(angle / 6) % 60);
- // Apply the time
Time = new TimeSpan(_selectedHour, _selectedMinute, 0);
- _isOpen = false;
+ IsOpen = false;
}
Invalidate();
return;
}
- // Click outside popup - close
- if (e.Y < popupTop)
+ // Click is outside clock - check if it's on the picker itself to toggle
+ if (screenBounds.Contains(e.X, e.Y))
{
- _isOpen = false;
+ IsOpen = false;
}
}
else
{
- _isOpen = true;
+ IsOpen = true;
_isSelectingHours = true;
}
-
Invalidate();
}
+ public override void OnFocusLost()
+ {
+ base.OnFocusLost();
+ // Close popup when focus is lost (clicking outside)
+ if (IsOpen)
+ {
+ IsOpen = false;
+ }
+ }
+
public override void OnKeyDown(KeyEventArgs e)
{
if (!IsEnabled) return;
switch (e.Key)
{
- case Key.Enter:
- case Key.Space:
- if (_isOpen)
- {
- if (_isSelectingHours)
- {
- _isSelectingHours = false;
- }
- else
- {
- Time = new TimeSpan(_selectedHour, _selectedMinute, 0);
- _isOpen = false;
- }
- }
- else
- {
- _isOpen = true;
- _isSelectingHours = true;
- }
- e.Handled = true;
- break;
-
- case Key.Escape:
- if (_isOpen)
- {
- _isOpen = false;
- e.Handled = true;
- }
- break;
-
- case Key.Up:
- if (_isSelectingHours)
- {
- _selectedHour = (_selectedHour + 1) % 24;
- }
- else
- {
- _selectedMinute = (_selectedMinute + 1) % 60;
- }
- e.Handled = true;
- break;
-
- case Key.Down:
- if (_isSelectingHours)
- {
- _selectedHour = (_selectedHour - 1 + 24) % 24;
- }
- else
- {
- _selectedMinute = (_selectedMinute - 1 + 60) % 60;
- }
- e.Handled = true;
- break;
-
- case Key.Left:
- case Key.Right:
- _isSelectingHours = !_isSelectingHours;
- e.Handled = true;
- break;
+ case Key.Enter: case Key.Space:
+ if (IsOpen) { if (_isSelectingHours) _isSelectingHours = false; else { Time = new TimeSpan(_selectedHour, _selectedMinute, 0); IsOpen = false; } }
+ else { IsOpen = true; _isSelectingHours = true; }
+ e.Handled = true; break;
+ case Key.Escape: if (IsOpen) { IsOpen = false; e.Handled = true; } break;
+ case Key.Up: if (_isSelectingHours) _selectedHour = (_selectedHour + 1) % 24; else _selectedMinute = (_selectedMinute + 1) % 60; e.Handled = true; break;
+ case Key.Down: if (_isSelectingHours) _selectedHour = (_selectedHour - 1 + 24) % 24; else _selectedMinute = (_selectedMinute - 1 + 60) % 60; e.Handled = true; break;
+ case Key.Left: case Key.Right: _isSelectingHours = !_isSelectingHours; e.Handled = true; break;
}
-
Invalidate();
}
protected override SKSize MeasureOverride(SKSize availableSize)
{
- return new SKSize(
- availableSize.Width < float.MaxValue ? Math.Min(availableSize.Width, 200) : 200,
- 40);
+ return new SKSize(availableSize.Width < float.MaxValue ? Math.Min(availableSize.Width, 200) : 200, 40);
+ }
+
+ ///
+ /// Override to include clock popup area in hit testing.
+ ///
+ protected override bool HitTestPopupArea(float x, float y)
+ {
+ // Use ScreenBounds for hit testing (accounts for scroll offset)
+ var screenBounds = ScreenBounds;
+
+ // Always include the picker button itself
+ if (screenBounds.Contains(x, y))
+ return true;
+
+ // When open, also include the clock popup area (with edge detection)
+ if (_isOpen)
+ {
+ var popupRect = GetPopupRect(screenBounds);
+ return popupRect.Contains(x, y);
+ }
+
+ return false;
}
}
diff --git a/Views/SkiaView.cs b/Views/SkiaView.cs
index da90956..bfb4e03 100644
--- a/Views/SkiaView.cs
+++ b/Views/SkiaView.cs
@@ -7,8 +7,9 @@ namespace Microsoft.Maui.Platform;
///
/// Base class for all Skia-rendered views on Linux.
+/// Inherits from BindableObject to enable XAML styling, data binding, and Visual State Manager.
///
-public abstract class SkiaView : IDisposable
+public abstract class SkiaView : BindableObject, IDisposable
{
// Popup overlay system for dropdowns, calendars, etc.
private static readonly List<(SkiaView Owner, Action Draw)> _popupOverlays = new();
@@ -32,7 +33,7 @@ public abstract class SkiaView : IDisposable
{
canvas.Restore();
}
-
+
foreach (var (_, draw) in _popupOverlays)
{
canvas.Save();
@@ -41,6 +42,189 @@ public abstract class SkiaView : IDisposable
}
}
+ ///
+ /// Gets the popup owner that should receive pointer events at the given coordinates.
+ /// This allows popups to receive events even outside their normal bounds.
+ ///
+ public static SkiaView? GetPopupOwnerAt(float x, float y)
+ {
+ // Check in reverse order (topmost popup first)
+ for (int i = _popupOverlays.Count - 1; i >= 0; i--)
+ {
+ var owner = _popupOverlays[i].Owner;
+ if (owner.HitTestPopupArea(x, y))
+ {
+ return owner;
+ }
+ }
+ return null;
+ }
+
+ ///
+ /// Checks if there are any active popup overlays.
+ ///
+ public static bool HasActivePopup => _popupOverlays.Count > 0;
+
+ ///
+ /// Override this to define the popup area for hit testing.
+ ///
+ protected virtual bool HitTestPopupArea(float x, float y)
+ {
+ // Default: no popup area beyond normal bounds
+ return Bounds.Contains(x, y);
+ }
+
+ #region BindableProperties
+
+ ///
+ /// Bindable property for IsVisible.
+ ///
+ public static readonly BindableProperty IsVisibleProperty =
+ BindableProperty.Create(
+ nameof(IsVisible),
+ typeof(bool),
+ typeof(SkiaView),
+ true,
+ propertyChanged: (b, o, n) => ((SkiaView)b).OnVisibilityChanged());
+
+ ///
+ /// Bindable property for IsEnabled.
+ ///
+ public static readonly BindableProperty IsEnabledProperty =
+ BindableProperty.Create(
+ nameof(IsEnabled),
+ typeof(bool),
+ typeof(SkiaView),
+ true,
+ propertyChanged: (b, o, n) => ((SkiaView)b).OnEnabledChanged());
+
+ ///
+ /// Bindable property for Opacity.
+ ///
+ public static readonly BindableProperty OpacityProperty =
+ BindableProperty.Create(
+ nameof(Opacity),
+ typeof(float),
+ typeof(SkiaView),
+ 1.0f,
+ coerceValue: (b, v) => Math.Clamp((float)v, 0f, 1f),
+ propertyChanged: (b, o, n) => ((SkiaView)b).Invalidate());
+
+ ///
+ /// Bindable property for BackgroundColor.
+ ///
+ public static readonly BindableProperty BackgroundColorProperty =
+ BindableProperty.Create(
+ nameof(BackgroundColor),
+ typeof(SKColor),
+ typeof(SkiaView),
+ SKColors.Transparent,
+ propertyChanged: (b, o, n) => ((SkiaView)b).Invalidate());
+
+ ///
+ /// Bindable property for WidthRequest.
+ ///
+ public static readonly BindableProperty WidthRequestProperty =
+ BindableProperty.Create(
+ nameof(WidthRequest),
+ typeof(double),
+ typeof(SkiaView),
+ -1.0,
+ propertyChanged: (b, o, n) => ((SkiaView)b).InvalidateMeasure());
+
+ ///
+ /// Bindable property for HeightRequest.
+ ///
+ public static readonly BindableProperty HeightRequestProperty =
+ BindableProperty.Create(
+ nameof(HeightRequest),
+ typeof(double),
+ typeof(SkiaView),
+ -1.0,
+ propertyChanged: (b, o, n) => ((SkiaView)b).InvalidateMeasure());
+
+ ///
+ /// Bindable property for MinimumWidthRequest.
+ ///
+ public static readonly BindableProperty MinimumWidthRequestProperty =
+ BindableProperty.Create(
+ nameof(MinimumWidthRequest),
+ typeof(double),
+ typeof(SkiaView),
+ 0.0,
+ propertyChanged: (b, o, n) => ((SkiaView)b).InvalidateMeasure());
+
+ ///
+ /// Bindable property for MinimumHeightRequest.
+ ///
+ public static readonly BindableProperty MinimumHeightRequestProperty =
+ BindableProperty.Create(
+ nameof(MinimumHeightRequest),
+ typeof(double),
+ typeof(SkiaView),
+ 0.0,
+ propertyChanged: (b, o, n) => ((SkiaView)b).InvalidateMeasure());
+
+ ///
+ /// Bindable property for IsFocusable.
+ ///
+ public static readonly BindableProperty IsFocusableProperty =
+ BindableProperty.Create(
+ nameof(IsFocusable),
+ typeof(bool),
+ typeof(SkiaView),
+ false);
+
+ ///
+ /// Bindable property for Margin.
+ ///
+ public static readonly BindableProperty MarginProperty =
+ BindableProperty.Create(
+ nameof(Margin),
+ typeof(Thickness),
+ typeof(SkiaView),
+ default(Thickness),
+ propertyChanged: (b, o, n) => ((SkiaView)b).InvalidateMeasure());
+
+ ///
+ /// Bindable property for HorizontalOptions.
+ ///
+ public static readonly BindableProperty HorizontalOptionsProperty =
+ BindableProperty.Create(
+ nameof(HorizontalOptions),
+ typeof(LayoutOptions),
+ typeof(SkiaView),
+ LayoutOptions.Fill,
+ propertyChanged: (b, o, n) => ((SkiaView)b).InvalidateMeasure());
+
+ ///
+ /// Bindable property for VerticalOptions.
+ ///
+ public static readonly BindableProperty VerticalOptionsProperty =
+ BindableProperty.Create(
+ nameof(VerticalOptions),
+ typeof(LayoutOptions),
+ typeof(SkiaView),
+ LayoutOptions.Fill,
+ propertyChanged: (b, o, n) => ((SkiaView)b).InvalidateMeasure());
+
+ ///
+ /// Bindable property for Name (used for template child lookup).
+ ///
+ public static readonly BindableProperty NameProperty =
+ BindableProperty.Create(
+ nameof(Name),
+ typeof(string),
+ typeof(SkiaView),
+ string.Empty);
+
+ #endregion
+
+ private bool _disposed;
+ private SKRect _bounds;
+ private SkiaView? _parent;
+ private readonly List _children = new();
+
///
/// Gets the absolute bounds of this view in screen coordinates.
///
@@ -64,15 +248,6 @@ public abstract class SkiaView : IDisposable
return bounds;
}
- private bool _disposed;
- private SKRect _bounds;
- private bool _isVisible = true;
- private bool _isEnabled = true;
- private float _opacity = 1.0f;
- private SKColor _backgroundColor = SKColors.Transparent;
- private SkiaView? _parent;
- private readonly List _children = new();
-
///
/// Gets or sets the bounds of this view in parent coordinates.
///
@@ -94,15 +269,8 @@ public abstract class SkiaView : IDisposable
///
public bool IsVisible
{
- get => _isVisible;
- set
- {
- if (_isVisible != value)
- {
- _isVisible = value;
- Invalidate();
- }
- }
+ get => (bool)GetValue(IsVisibleProperty);
+ set => SetValue(IsVisibleProperty, value);
}
///
@@ -110,15 +278,8 @@ public abstract class SkiaView : IDisposable
///
public bool IsEnabled
{
- get => _isEnabled;
- set
- {
- if (_isEnabled != value)
- {
- _isEnabled = value;
- Invalidate();
- }
- }
+ get => (bool)GetValue(IsEnabledProperty);
+ set => SetValue(IsEnabledProperty, value);
}
///
@@ -126,21 +287,14 @@ public abstract class SkiaView : IDisposable
///
public float Opacity
{
- get => _opacity;
- set
- {
- var clamped = Math.Clamp(value, 0f, 1f);
- if (_opacity != clamped)
- {
- _opacity = clamped;
- Invalidate();
- }
- }
+ get => (float)GetValue(OpacityProperty);
+ set => SetValue(OpacityProperty, value);
}
///
/// Gets or sets the background color.
///
+ private SKColor _backgroundColor = SKColors.Transparent;
public SKColor BackgroundColor
{
get => _backgroundColor;
@@ -149,6 +303,7 @@ public abstract class SkiaView : IDisposable
if (_backgroundColor != value)
{
_backgroundColor = value;
+ SetValue(BackgroundColorProperty, value); // Keep BindableProperty in sync for bindings
Invalidate();
}
}
@@ -157,17 +312,101 @@ public abstract class SkiaView : IDisposable
///
/// Gets or sets the requested width.
///
- public double RequestedWidth { get; set; } = -1;
+ public double WidthRequest
+ {
+ get => (double)GetValue(WidthRequestProperty);
+ set => SetValue(WidthRequestProperty, value);
+ }
///
/// Gets or sets the requested height.
///
- public double RequestedHeight { get; set; } = -1;
+ public double HeightRequest
+ {
+ get => (double)GetValue(HeightRequestProperty);
+ set => SetValue(HeightRequestProperty, value);
+ }
+
+ ///
+ /// Gets or sets the minimum width request.
+ ///
+ public double MinimumWidthRequest
+ {
+ get => (double)GetValue(MinimumWidthRequestProperty);
+ set => SetValue(MinimumWidthRequestProperty, value);
+ }
+
+ ///
+ /// Gets or sets the minimum height request.
+ ///
+ public double MinimumHeightRequest
+ {
+ get => (double)GetValue(MinimumHeightRequestProperty);
+ set => SetValue(MinimumHeightRequestProperty, value);
+ }
+
+ ///
+ /// Gets or sets the requested width (backwards compatibility alias).
+ ///
+ public double RequestedWidth
+ {
+ get => WidthRequest;
+ set => WidthRequest = value;
+ }
+
+ ///
+ /// Gets or sets the requested height (backwards compatibility alias).
+ ///
+ public double RequestedHeight
+ {
+ get => HeightRequest;
+ set => HeightRequest = value;
+ }
///
/// Gets or sets whether this view can receive keyboard focus.
///
- public bool IsFocusable { get; set; }
+ public bool IsFocusable
+ {
+ get => (bool)GetValue(IsFocusableProperty);
+ set => SetValue(IsFocusableProperty, value);
+ }
+
+ ///
+ /// Gets or sets the margin around this view.
+ ///
+ public Thickness Margin
+ {
+ get => (Thickness)GetValue(MarginProperty);
+ set => SetValue(MarginProperty, value);
+ }
+
+ ///
+ /// Gets or sets the horizontal layout options.
+ ///
+ public LayoutOptions HorizontalOptions
+ {
+ get => (LayoutOptions)GetValue(HorizontalOptionsProperty);
+ set => SetValue(HorizontalOptionsProperty, value);
+ }
+
+ ///
+ /// Gets or sets the vertical layout options.
+ ///
+ public LayoutOptions VerticalOptions
+ {
+ get => (LayoutOptions)GetValue(VerticalOptionsProperty);
+ set => SetValue(VerticalOptionsProperty, value);
+ }
+
+ ///
+ /// Gets or sets the name of this view (used for template child lookup).
+ ///
+ public string Name
+ {
+ get => (string)GetValue(NameProperty);
+ set => SetValue(NameProperty, value);
+ }
///
/// Gets or sets whether this view currently has keyboard focus.
@@ -183,6 +422,34 @@ public abstract class SkiaView : IDisposable
internal set => _parent = value;
}
+ ///
+ /// Gets the bounds of this view in screen coordinates (accounting for scroll offsets).
+ ///
+ public SKRect ScreenBounds
+ {
+ get
+ {
+ var bounds = Bounds;
+ var parent = _parent;
+
+ // Walk up the tree and adjust for scroll offsets
+ while (parent != null)
+ {
+ if (parent is SkiaScrollView scrollView)
+ {
+ bounds = new SKRect(
+ bounds.Left - scrollView.ScrollX,
+ bounds.Top - scrollView.ScrollY,
+ bounds.Right - scrollView.ScrollX,
+ bounds.Bottom - scrollView.ScrollY);
+ }
+ parent = parent.Parent;
+ }
+
+ return bounds;
+ }
+ }
+
///
/// Gets the desired size calculated during measure.
///
@@ -198,6 +465,36 @@ public abstract class SkiaView : IDisposable
///
public event EventHandler? Invalidated;
+ ///
+ /// Called when visibility changes.
+ ///
+ protected virtual void OnVisibilityChanged()
+ {
+ Invalidate();
+ }
+
+ ///
+ /// Called when enabled state changes.
+ ///
+ protected virtual void OnEnabledChanged()
+ {
+ Invalidate();
+ }
+
+ ///
+ /// Called when binding context changes. Propagates to children.
+ ///
+ protected override void OnBindingContextChanged()
+ {
+ base.OnBindingContextChanged();
+
+ // Propagate binding context to children
+ foreach (var child in _children)
+ {
+ SetInheritedBindingContext(child, BindingContext);
+ }
+ }
+
///
/// Adds a child view.
///
@@ -208,6 +505,13 @@ public abstract class SkiaView : IDisposable
child._parent = this;
_children.Add(child);
+
+ // Propagate binding context to new child
+ if (BindingContext != null)
+ {
+ SetInheritedBindingContext(child, BindingContext);
+ }
+
Invalidate();
}
@@ -234,6 +538,13 @@ public abstract class SkiaView : IDisposable
child._parent = this;
_children.Insert(index, child);
+
+ // Propagate binding context to new child
+ if (BindingContext != null)
+ {
+ SetInheritedBindingContext(child, BindingContext);
+ }
+
Invalidate();
}
@@ -275,7 +586,9 @@ public abstract class SkiaView : IDisposable
public void Draw(SKCanvas canvas)
{
if (!IsVisible || Opacity <= 0)
+ {
return;
+ }
canvas.Save();
@@ -338,8 +651,8 @@ public abstract class SkiaView : IDisposable
///
protected virtual SKSize MeasureOverride(SKSize availableSize)
{
- var width = RequestedWidth >= 0 ? (float)RequestedWidth : 0;
- var height = RequestedHeight >= 0 ? (float)RequestedHeight : 0;
+ var width = WidthRequest >= 0 ? (float)WidthRequest : 0;
+ var height = HeightRequest >= 0 ? (float)HeightRequest : 0;
return new SKSize(width, height);
}
@@ -369,6 +682,7 @@ public abstract class SkiaView : IDisposable
///
/// Performs hit testing to find the view at the given coordinates.
+ /// Coordinates are in absolute window space, matching how Bounds are stored.
///
public virtual SkiaView? HitTest(float x, float y)
{
@@ -379,11 +693,10 @@ public abstract class SkiaView : IDisposable
return null;
// Check children in reverse order (top-most first)
- var localX = x - Bounds.Left;
- var localY = y - Bounds.Top;
+ // Coordinates stay in absolute space since children have absolute Bounds
for (int i = _children.Count - 1; i >= 0; i--)
{
- var hit = _children[i].HitTest(localX, localY);
+ var hit = _children[i].HitTest(x, y);
if (hit != null)
return hit;
}
diff --git a/Views/SkiaVisualStateManager.cs b/Views/SkiaVisualStateManager.cs
new file mode 100644
index 0000000..6472d8d
--- /dev/null
+++ b/Views/SkiaVisualStateManager.cs
@@ -0,0 +1,216 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace Microsoft.Maui.Platform;
+
+///
+/// Visual State Manager for Skia-rendered controls.
+/// Provides state-based styling through XAML VisualStateGroups.
+///
+public static class SkiaVisualStateManager
+{
+ ///
+ /// Common visual state names.
+ ///
+ public static class CommonStates
+ {
+ public const string Normal = "Normal";
+ public const string Disabled = "Disabled";
+ public const string Focused = "Focused";
+ public const string PointerOver = "PointerOver";
+ public const string Pressed = "Pressed";
+ public const string Selected = "Selected";
+ public const string Checked = "Checked";
+ public const string Unchecked = "Unchecked";
+ public const string On = "On";
+ public const string Off = "Off";
+ }
+
+ ///
+ /// Attached property for VisualStateGroups.
+ ///
+ public static readonly BindableProperty VisualStateGroupsProperty =
+ BindableProperty.CreateAttached(
+ "VisualStateGroups",
+ typeof(SkiaVisualStateGroupList),
+ typeof(SkiaVisualStateManager),
+ null,
+ propertyChanged: OnVisualStateGroupsChanged);
+
+ ///
+ /// Gets the visual state groups for the specified view.
+ ///
+ public static SkiaVisualStateGroupList? GetVisualStateGroups(SkiaView view)
+ {
+ return (SkiaVisualStateGroupList?)view.GetValue(VisualStateGroupsProperty);
+ }
+
+ ///
+ /// Sets the visual state groups for the specified view.
+ ///
+ public static void SetVisualStateGroups(SkiaView view, SkiaVisualStateGroupList? value)
+ {
+ view.SetValue(VisualStateGroupsProperty, value);
+ }
+
+ private static void OnVisualStateGroupsChanged(BindableObject bindable, object? oldValue, object? newValue)
+ {
+ if (bindable is SkiaView view && newValue is SkiaVisualStateGroupList groups)
+ {
+ // Initialize to default state
+ GoToState(view, CommonStates.Normal);
+ }
+ }
+
+ ///
+ /// Transitions the view to the specified visual state.
+ ///
+ /// The view to transition.
+ /// The name of the state to transition to.
+ /// True if the state was found and applied, false otherwise.
+ public static bool GoToState(SkiaView view, string stateName)
+ {
+ var groups = GetVisualStateGroups(view);
+ if (groups == null || groups.Count == 0)
+ return false;
+
+ bool stateFound = false;
+
+ foreach (var group in groups)
+ {
+ // Find the state in this group
+ SkiaVisualState? targetState = null;
+ foreach (var state in group.States)
+ {
+ if (state.Name == stateName)
+ {
+ targetState = state;
+ break;
+ }
+ }
+
+ if (targetState != null)
+ {
+ // Unapply current state if different
+ if (group.CurrentState != null && group.CurrentState != targetState)
+ {
+ UnapplyState(view, group.CurrentState);
+ }
+
+ // Apply new state
+ ApplyState(view, targetState);
+ group.CurrentState = targetState;
+ stateFound = true;
+ }
+ }
+
+ return stateFound;
+ }
+
+ private static void ApplyState(SkiaView view, SkiaVisualState state)
+ {
+ foreach (var setter in state.Setters)
+ {
+ setter.Apply(view);
+ }
+ }
+
+ private static void UnapplyState(SkiaView view, SkiaVisualState state)
+ {
+ foreach (var setter in state.Setters)
+ {
+ setter.Unapply(view);
+ }
+ }
+}
+
+///
+/// A list of visual state groups.
+///
+public class SkiaVisualStateGroupList : List
+{
+}
+
+///
+/// A group of mutually exclusive visual states.
+///
+public class SkiaVisualStateGroup
+{
+ ///
+ /// Gets or sets the name of this group.
+ ///
+ public string Name { get; set; } = "";
+
+ ///
+ /// Gets the collection of states in this group.
+ ///
+ public List States { get; } = new();
+
+ ///
+ /// Gets or sets the currently active state.
+ ///
+ public SkiaVisualState? CurrentState { get; set; }
+}
+
+///
+/// Represents a single visual state with its setters.
+///
+public class SkiaVisualState
+{
+ ///
+ /// Gets or sets the name of this state.
+ ///
+ public string Name { get; set; } = "";
+
+ ///
+ /// Gets the collection of setters for this state.
+ ///
+ public List Setters { get; } = new();
+}
+
+///
+/// Sets a property value when a visual state is active.
+///
+public class SkiaVisualStateSetter
+{
+ ///
+ /// Gets or sets the property to set.
+ ///
+ public BindableProperty? Property { get; set; }
+
+ ///
+ /// Gets or sets the value to set.
+ ///
+ public object? Value { get; set; }
+
+ // Store original value for unapply
+ private object? _originalValue;
+ private bool _hasOriginalValue;
+
+ ///
+ /// Applies this setter to the target view.
+ ///
+ public void Apply(SkiaView view)
+ {
+ if (Property == null) return;
+
+ // Store original value if not already stored
+ if (!_hasOriginalValue)
+ {
+ _originalValue = view.GetValue(Property);
+ _hasOriginalValue = true;
+ }
+
+ view.SetValue(Property, Value);
+ }
+
+ ///
+ /// Unapplies this setter, restoring the original value.
+ ///
+ public void Unapply(SkiaView view)
+ {
+ if (Property == null || !_hasOriginalValue) return;
+
+ view.SetValue(Property, _originalValue);
+ }
+}
diff --git a/Views/SkiaWebView.cs b/Views/SkiaWebView.cs
new file mode 100644
index 0000000..371c9c1
--- /dev/null
+++ b/Views/SkiaWebView.cs
@@ -0,0 +1,695 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Runtime.InteropServices;
+using SkiaSharp;
+
+namespace Microsoft.Maui.Platform;
+
+///
+/// WebView implementation using WebKitGTK for Linux.
+/// Renders web content in a native GTK window and composites to Skia.
+///
+public class SkiaWebView : SkiaView
+{
+ #region Native Interop - GTK
+
+ private const string LibGtk4 = "libgtk-4.so.1";
+ private const string LibGtk3 = "libgtk-3.so.0";
+ private const string LibWebKit2Gtk4 = "libwebkitgtk-6.0.so.4";
+ private const string LibWebKit2Gtk3 = "libwebkit2gtk-4.1.so.0";
+ private const string LibGObject = "libgobject-2.0.so.0";
+ private const string LibGLib = "libglib-2.0.so.0";
+
+ private static bool _useGtk4;
+ private static bool _gtkInitialized;
+ private static string _webkitLib = LibWebKit2Gtk3;
+
+ // GTK functions
+ [DllImport(LibGtk4, EntryPoint = "gtk_init")]
+ private static extern void gtk4_init();
+
+ [DllImport(LibGtk3, EntryPoint = "gtk_init_check")]
+ private static extern bool gtk3_init_check(ref int argc, ref IntPtr argv);
+
+ [DllImport(LibGtk4, EntryPoint = "gtk_window_new")]
+ private static extern IntPtr gtk4_window_new();
+
+ [DllImport(LibGtk3, EntryPoint = "gtk_window_new")]
+ private static extern IntPtr gtk3_window_new(int type);
+
+ [DllImport(LibGtk4, EntryPoint = "gtk_window_set_default_size")]
+ private static extern void gtk4_window_set_default_size(IntPtr window, int width, int height);
+
+ [DllImport(LibGtk3, EntryPoint = "gtk_window_set_default_size")]
+ private static extern void gtk3_window_set_default_size(IntPtr window, int width, int height);
+
+ [DllImport(LibGtk4, EntryPoint = "gtk_window_set_child")]
+ private static extern void gtk4_window_set_child(IntPtr window, IntPtr child);
+
+ [DllImport(LibGtk3, EntryPoint = "gtk_container_add")]
+ private static extern void gtk3_container_add(IntPtr container, IntPtr widget);
+
+ [DllImport(LibGtk4, EntryPoint = "gtk_widget_show")]
+ private static extern void gtk4_widget_show(IntPtr widget);
+
+ [DllImport(LibGtk3, EntryPoint = "gtk_widget_show_all")]
+ private static extern void gtk3_widget_show_all(IntPtr widget);
+
+ [DllImport(LibGtk4, EntryPoint = "gtk_widget_hide")]
+ private static extern void gtk4_widget_hide(IntPtr widget);
+
+ [DllImport(LibGtk3, EntryPoint = "gtk_widget_hide")]
+ private static extern void gtk3_widget_hide(IntPtr widget);
+
+ [DllImport(LibGtk4, EntryPoint = "gtk_widget_get_width")]
+ private static extern int gtk4_widget_get_width(IntPtr widget);
+
+ [DllImport(LibGtk4, EntryPoint = "gtk_widget_get_height")]
+ private static extern int gtk4_widget_get_height(IntPtr widget);
+
+ // GObject
+ [DllImport(LibGObject, EntryPoint = "g_object_unref")]
+ private static extern void g_object_unref(IntPtr obj);
+
+ [DllImport(LibGObject, EntryPoint = "g_signal_connect_data")]
+ private static extern ulong g_signal_connect_data(IntPtr instance,
+ [MarshalAs(UnmanagedType.LPStr)] string signal,
+ IntPtr handler, IntPtr data, IntPtr destroyData, int flags);
+
+ // GLib main loop (for event processing)
+ [DllImport(LibGLib, EntryPoint = "g_main_context_iteration")]
+ private static extern bool g_main_context_iteration(IntPtr context, bool mayBlock);
+
+ #endregion
+
+ #region WebKit Functions
+
+ // We'll load these dynamically based on available version
+ private delegate IntPtr WebKitWebViewNewDelegate();
+ private delegate void WebKitWebViewLoadUriDelegate(IntPtr webView, [MarshalAs(UnmanagedType.LPStr)] string uri);
+ private delegate void WebKitWebViewLoadHtmlDelegate(IntPtr webView, [MarshalAs(UnmanagedType.LPStr)] string html, [MarshalAs(UnmanagedType.LPStr)] string? baseUri);
+ private delegate IntPtr WebKitWebViewGetUriDelegate(IntPtr webView);
+ private delegate IntPtr WebKitWebViewGetTitleDelegate(IntPtr webView);
+ private delegate void WebKitWebViewGoBackDelegate(IntPtr webView);
+ private delegate void WebKitWebViewGoForwardDelegate(IntPtr webView);
+ private delegate bool WebKitWebViewCanGoBackDelegate(IntPtr webView);
+ private delegate bool WebKitWebViewCanGoForwardDelegate(IntPtr webView);
+ private delegate void WebKitWebViewReloadDelegate(IntPtr webView);
+ private delegate void WebKitWebViewStopLoadingDelegate(IntPtr webView);
+ private delegate double WebKitWebViewGetEstimatedLoadProgressDelegate(IntPtr webView);
+ private delegate IntPtr WebKitWebViewGetSettingsDelegate(IntPtr webView);
+ private delegate void WebKitSettingsSetEnableJavascriptDelegate(IntPtr settings, bool enabled);
+
+ private static WebKitWebViewNewDelegate? _webkitWebViewNew;
+ private static WebKitWebViewLoadUriDelegate? _webkitLoadUri;
+ private static WebKitWebViewLoadHtmlDelegate? _webkitLoadHtml;
+ private static WebKitWebViewGetUriDelegate? _webkitGetUri;
+ private static WebKitWebViewGetTitleDelegate? _webkitGetTitle;
+ private static WebKitWebViewGoBackDelegate? _webkitGoBack;
+ private static WebKitWebViewGoForwardDelegate? _webkitGoForward;
+ private static WebKitWebViewCanGoBackDelegate? _webkitCanGoBack;
+ private static WebKitWebViewCanGoForwardDelegate? _webkitCanGoForward;
+ private static WebKitWebViewReloadDelegate? _webkitReload;
+ private static WebKitWebViewStopLoadingDelegate? _webkitStopLoading;
+ private static WebKitWebViewGetEstimatedLoadProgressDelegate? _webkitGetProgress;
+ private static WebKitWebViewGetSettingsDelegate? _webkitGetSettings;
+ private static WebKitSettingsSetEnableJavascriptDelegate? _webkitSetJavascript;
+
+ [DllImport("libdl.so.2")]
+ private static extern IntPtr dlopen([MarshalAs(UnmanagedType.LPStr)] string? filename, int flags);
+
+ [DllImport("libdl.so.2")]
+ private static extern IntPtr dlsym(IntPtr handle, [MarshalAs(UnmanagedType.LPStr)] string symbol);
+
+ [DllImport("libdl.so.2")]
+ private static extern IntPtr dlerror();
+
+ private const int RTLD_NOW = 2;
+ private const int RTLD_GLOBAL = 0x100;
+
+ private static IntPtr _webkitHandle;
+
+ #endregion
+
+ #region Fields
+
+ private IntPtr _gtkWindow;
+ private IntPtr _webView;
+ private string _source = "";
+ private string _html = "";
+ private bool _isInitialized;
+ private bool _javascriptEnabled = true;
+ private double _loadProgress;
+
+ #endregion
+
+ #region Properties
+
+ ///
+ /// Gets or sets the URL to navigate to.
+ ///
+ public string Source
+ {
+ get => _source;
+ set
+ {
+ if (_source != value)
+ {
+ _source = value;
+ if (_isInitialized && !string.IsNullOrEmpty(value))
+ {
+ LoadUrl(value);
+ }
+ Invalidate();
+ }
+ }
+ }
+
+ ///
+ /// Gets or sets the HTML content to display.
+ ///
+ public string Html
+ {
+ get => _html;
+ set
+ {
+ if (_html != value)
+ {
+ _html = value;
+ if (_isInitialized && !string.IsNullOrEmpty(value))
+ {
+ LoadHtml(value);
+ }
+ Invalidate();
+ }
+ }
+ }
+
+ ///
+ /// Gets whether the WebView can navigate back.
+ ///
+ public bool CanGoBack => _webView != IntPtr.Zero && _webkitCanGoBack?.Invoke(_webView) == true;
+
+ ///
+ /// Gets whether the WebView can navigate forward.
+ ///
+ public bool CanGoForward => _webView != IntPtr.Zero && _webkitCanGoForward?.Invoke(_webView) == true;
+
+ ///
+ /// Gets the current URL.
+ ///
+ public string? CurrentUrl
+ {
+ get
+ {
+ if (_webView == IntPtr.Zero || _webkitGetUri == null) return null;
+ var ptr = _webkitGetUri(_webView);
+ return ptr != IntPtr.Zero ? Marshal.PtrToStringAnsi(ptr) : null;
+ }
+ }
+
+ ///
+ /// Gets the current page title.
+ ///
+ public string? Title
+ {
+ get
+ {
+ if (_webView == IntPtr.Zero || _webkitGetTitle == null) return null;
+ var ptr = _webkitGetTitle(_webView);
+ return ptr != IntPtr.Zero ? Marshal.PtrToStringAnsi(ptr) : null;
+ }
+ }
+
+ ///
+ /// Gets or sets whether JavaScript is enabled.
+ ///
+ public bool JavaScriptEnabled
+ {
+ get => _javascriptEnabled;
+ set
+ {
+ _javascriptEnabled = value;
+ UpdateJavaScriptSetting();
+ }
+ }
+
+ ///
+ /// Gets the load progress (0.0 to 1.0).
+ ///
+ public double LoadProgress => _loadProgress;
+
+ ///
+ /// Gets whether WebKit is available on this system.
+ ///
+ public static bool IsSupported => InitializeWebKit();
+
+ #endregion
+
+ #region Events
+
+ public event EventHandler? Navigating;
+ public event EventHandler? Navigated;
+ public event EventHandler? TitleChanged;
+ public event EventHandler? LoadProgressChanged;
+
+ #endregion
+
+ #region Constructor
+
+ public SkiaWebView()
+ {
+ RequestedWidth = 400;
+ RequestedHeight = 300;
+ BackgroundColor = SKColors.White;
+ }
+
+ #endregion
+
+ #region Initialization
+
+ private static bool InitializeWebKit()
+ {
+ if (_webkitHandle != IntPtr.Zero) return true;
+
+ // Try WebKitGTK 6.0 (GTK4) first
+ _webkitHandle = dlopen(LibWebKit2Gtk4, RTLD_NOW | RTLD_GLOBAL);
+ if (_webkitHandle != IntPtr.Zero)
+ {
+ _useGtk4 = true;
+ _webkitLib = LibWebKit2Gtk4;
+ }
+ else
+ {
+ // Fall back to WebKitGTK 4.1 (GTK3)
+ _webkitHandle = dlopen(LibWebKit2Gtk3, RTLD_NOW | RTLD_GLOBAL);
+ if (_webkitHandle != IntPtr.Zero)
+ {
+ _useGtk4 = false;
+ _webkitLib = LibWebKit2Gtk3;
+ }
+ else
+ {
+ // Try older WebKitGTK 4.0
+ _webkitHandle = dlopen("libwebkit2gtk-4.0.so.37", RTLD_NOW | RTLD_GLOBAL);
+ if (_webkitHandle != IntPtr.Zero)
+ {
+ _useGtk4 = false;
+ _webkitLib = "libwebkit2gtk-4.0.so.37";
+ }
+ }
+ }
+
+ if (_webkitHandle == IntPtr.Zero)
+ {
+ Console.WriteLine("[WebView] WebKitGTK not found. Install with: sudo apt install libwebkit2gtk-4.1-0");
+ return false;
+ }
+
+ // Load function pointers
+ _webkitWebViewNew = LoadFunction("webkit_web_view_new");
+ _webkitLoadUri = LoadFunction("webkit_web_view_load_uri");
+ _webkitLoadHtml = LoadFunction("webkit_web_view_load_html");
+ _webkitGetUri = LoadFunction("webkit_web_view_get_uri");
+ _webkitGetTitle = LoadFunction("webkit_web_view_get_title");
+ _webkitGoBack = LoadFunction("webkit_web_view_go_back");
+ _webkitGoForward = LoadFunction("webkit_web_view_go_forward");
+ _webkitCanGoBack = LoadFunction("webkit_web_view_can_go_back");
+ _webkitCanGoForward = LoadFunction("webkit_web_view_can_go_forward");
+ _webkitReload = LoadFunction("webkit_web_view_reload");
+ _webkitStopLoading = LoadFunction("webkit_web_view_stop_loading");
+ _webkitGetProgress = LoadFunction("webkit_web_view_get_estimated_load_progress");
+ _webkitGetSettings = LoadFunction("webkit_web_view_get_settings");
+ _webkitSetJavascript = LoadFunction("webkit_settings_set_enable_javascript");
+
+ Console.WriteLine($"[WebView] Using {_webkitLib}");
+ return _webkitWebViewNew != null;
+ }
+
+ private static T? LoadFunction(string name) where T : Delegate
+ {
+ var ptr = dlsym(_webkitHandle, name);
+ if (ptr == IntPtr.Zero) return null;
+ return Marshal.GetDelegateForFunctionPointer(ptr);
+ }
+
+ private void Initialize()
+ {
+ if (_isInitialized) return;
+ if (!InitializeWebKit()) return;
+
+ try
+ {
+ // Initialize GTK if needed
+ if (!_gtkInitialized)
+ {
+ if (_useGtk4)
+ {
+ gtk4_init();
+ }
+ else
+ {
+ int argc = 0;
+ IntPtr argv = IntPtr.Zero;
+ gtk3_init_check(ref argc, ref argv);
+ }
+ _gtkInitialized = true;
+ }
+
+ // Create WebKit view
+ _webView = _webkitWebViewNew!();
+ if (_webView == IntPtr.Zero)
+ {
+ Console.WriteLine("[WebView] Failed to create WebKit view");
+ return;
+ }
+
+ // Create GTK window to host the WebView
+ if (_useGtk4)
+ {
+ _gtkWindow = gtk4_window_new();
+ gtk4_window_set_default_size(_gtkWindow, (int)RequestedWidth, (int)RequestedHeight);
+ gtk4_window_set_child(_gtkWindow, _webView);
+ }
+ else
+ {
+ _gtkWindow = gtk3_window_new(0); // GTK_WINDOW_TOPLEVEL
+ gtk3_window_set_default_size(_gtkWindow, (int)RequestedWidth, (int)RequestedHeight);
+ gtk3_container_add(_gtkWindow, _webView);
+ }
+
+ UpdateJavaScriptSetting();
+ _isInitialized = true;
+
+ // Load initial content
+ if (!string.IsNullOrEmpty(_source))
+ {
+ LoadUrl(_source);
+ }
+ else if (!string.IsNullOrEmpty(_html))
+ {
+ LoadHtml(_html);
+ }
+
+ Console.WriteLine("[WebView] Initialized successfully");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"[WebView] Initialization failed: {ex.Message}");
+ }
+ }
+
+ #endregion
+
+ #region Navigation
+
+ public void LoadUrl(string url)
+ {
+ if (!_isInitialized) Initialize();
+ if (_webView == IntPtr.Zero || _webkitLoadUri == null) return;
+
+ Navigating?.Invoke(this, new WebNavigatingEventArgs(url));
+ _webkitLoadUri(_webView, url);
+ }
+
+ public void LoadHtml(string html, string? baseUrl = null)
+ {
+ if (!_isInitialized) Initialize();
+ if (_webView == IntPtr.Zero || _webkitLoadHtml == null) return;
+
+ _webkitLoadHtml(_webView, html, baseUrl);
+ }
+
+ public void GoBack()
+ {
+ if (_webView != IntPtr.Zero && CanGoBack)
+ {
+ _webkitGoBack?.Invoke(_webView);
+ }
+ }
+
+ public void GoForward()
+ {
+ if (_webView != IntPtr.Zero && CanGoForward)
+ {
+ _webkitGoForward?.Invoke(_webView);
+ }
+ }
+
+ public void Reload()
+ {
+ if (_webView != IntPtr.Zero)
+ {
+ _webkitReload?.Invoke(_webView);
+ }
+ }
+
+ public void Stop()
+ {
+ if (_webView != IntPtr.Zero)
+ {
+ _webkitStopLoading?.Invoke(_webView);
+ }
+ }
+
+ private void UpdateJavaScriptSetting()
+ {
+ if (_webView == IntPtr.Zero || _webkitGetSettings == null || _webkitSetJavascript == null) return;
+
+ var settings = _webkitGetSettings(_webView);
+ if (settings != IntPtr.Zero)
+ {
+ _webkitSetJavascript(settings, _javascriptEnabled);
+ }
+ }
+
+ #endregion
+
+ #region Event Processing
+
+ ///
+ /// Process pending GTK events. Call this from your main loop.
+ ///
+ public void ProcessEvents()
+ {
+ if (!_isInitialized) return;
+
+ // Process GTK events
+ g_main_context_iteration(IntPtr.Zero, false);
+
+ // Update progress
+ if (_webView != IntPtr.Zero && _webkitGetProgress != null)
+ {
+ var progress = _webkitGetProgress(_webView);
+ if (Math.Abs(progress - _loadProgress) > 0.01)
+ {
+ _loadProgress = progress;
+ LoadProgressChanged?.Invoke(this, progress);
+ }
+ }
+ }
+
+ ///
+ /// Show the native WebView window (for testing/debugging).
+ ///
+ public void ShowNativeWindow()
+ {
+ if (!_isInitialized) Initialize();
+ if (_gtkWindow == IntPtr.Zero) return;
+
+ if (_useGtk4)
+ {
+ gtk4_widget_show(_gtkWindow);
+ }
+ else
+ {
+ gtk3_widget_show_all(_gtkWindow);
+ }
+ }
+
+ ///
+ /// Hide the native WebView window.
+ ///
+ public void HideNativeWindow()
+ {
+ if (_gtkWindow == IntPtr.Zero) return;
+
+ if (_useGtk4)
+ {
+ gtk4_widget_hide(_gtkWindow);
+ }
+ else
+ {
+ gtk3_widget_hide(_gtkWindow);
+ }
+ }
+
+ #endregion
+
+ #region Rendering
+
+ protected override void OnDraw(SKCanvas canvas, SKRect bounds)
+ {
+ base.OnDraw(canvas, bounds);
+
+ // Draw placeholder/loading state
+ using var bgPaint = new SKPaint { Color = BackgroundColor, Style = SKPaintStyle.Fill };
+ canvas.DrawRect(bounds, bgPaint);
+
+ // Draw border
+ using var borderPaint = new SKPaint
+ {
+ Color = new SKColor(200, 200, 200),
+ Style = SKPaintStyle.Stroke,
+ StrokeWidth = 1
+ };
+ canvas.DrawRect(bounds, borderPaint);
+
+ // Draw web icon and status
+ var centerX = bounds.MidX;
+ var centerY = bounds.MidY;
+
+ // Globe icon
+ using var iconPaint = new SKPaint
+ {
+ Color = new SKColor(100, 100, 100),
+ Style = SKPaintStyle.Stroke,
+ StrokeWidth = 2,
+ IsAntialias = true
+ };
+ canvas.DrawCircle(centerX, centerY - 20, 25, iconPaint);
+ canvas.DrawLine(centerX - 25, centerY - 20, centerX + 25, centerY - 20, iconPaint);
+ canvas.DrawArc(new SKRect(centerX - 15, centerY - 45, centerX + 15, centerY + 5), 0, 180, false, iconPaint);
+
+ // Status text
+ using var textPaint = new SKPaint
+ {
+ Color = new SKColor(80, 80, 80),
+ IsAntialias = true,
+ TextSize = 14
+ };
+
+ string statusText;
+ if (!IsSupported)
+ {
+ statusText = "WebKitGTK not installed";
+ }
+ else if (_isInitialized)
+ {
+ statusText = string.IsNullOrEmpty(_source) ? "No URL loaded" : $"Loading: {_source}";
+ if (_loadProgress > 0 && _loadProgress < 1)
+ {
+ statusText = $"Loading: {(int)(_loadProgress * 100)}%";
+ }
+ }
+ else
+ {
+ statusText = "WebView (click to open)";
+ }
+
+ var textWidth = textPaint.MeasureText(statusText);
+ canvas.DrawText(statusText, centerX - textWidth / 2, centerY + 30, textPaint);
+
+ // Draw install hint if not supported
+ if (!IsSupported)
+ {
+ using var hintPaint = new SKPaint
+ {
+ Color = new SKColor(120, 120, 120),
+ IsAntialias = true,
+ TextSize = 11
+ };
+ var hint = "Install: sudo apt install libwebkit2gtk-4.1-0";
+ var hintWidth = hintPaint.MeasureText(hint);
+ canvas.DrawText(hint, centerX - hintWidth / 2, centerY + 50, hintPaint);
+ }
+
+ // Progress bar
+ if (_loadProgress > 0 && _loadProgress < 1)
+ {
+ var progressRect = new SKRect(bounds.Left + 20, bounds.Bottom - 30, bounds.Right - 20, bounds.Bottom - 20);
+ using var progressBgPaint = new SKPaint { Color = new SKColor(230, 230, 230), Style = SKPaintStyle.Fill };
+ canvas.DrawRoundRect(new SKRoundRect(progressRect, 5), progressBgPaint);
+
+ var filledWidth = progressRect.Width * (float)_loadProgress;
+ var filledRect = new SKRect(progressRect.Left, progressRect.Top, progressRect.Left + filledWidth, progressRect.Bottom);
+ using var progressPaint = new SKPaint { Color = new SKColor(33, 150, 243), Style = SKPaintStyle.Fill };
+ canvas.DrawRoundRect(new SKRoundRect(filledRect, 5), progressPaint);
+ }
+ }
+
+ public override void OnPointerPressed(PointerEventArgs e)
+ {
+ base.OnPointerPressed(e);
+
+ if (!_isInitialized && IsSupported)
+ {
+ Initialize();
+ ShowNativeWindow();
+ }
+ else if (_isInitialized)
+ {
+ ShowNativeWindow();
+ }
+ }
+
+ #endregion
+
+ #region Cleanup
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ if (_gtkWindow != IntPtr.Zero)
+ {
+ if (_useGtk4)
+ {
+ gtk4_widget_hide(_gtkWindow);
+ }
+ else
+ {
+ gtk3_widget_hide(_gtkWindow);
+ }
+ g_object_unref(_gtkWindow);
+ _gtkWindow = IntPtr.Zero;
+ }
+ _webView = IntPtr.Zero;
+ _isInitialized = false;
+ }
+
+ base.Dispose(disposing);
+ }
+
+ #endregion
+}
+
+#region Event Args
+
+public class WebNavigatingEventArgs : EventArgs
+{
+ public string Url { get; }
+ public bool Cancel { get; set; }
+
+ public WebNavigatingEventArgs(string url)
+ {
+ Url = url;
+ }
+}
+
+public class WebNavigatedEventArgs : EventArgs
+{
+ public string Url { get; }
+ public bool Success { get; }
+ public string? Error { get; }
+
+ public WebNavigatedEventArgs(string url, bool success, string? error = null)
+ {
+ Url = url;
+ Success = success;
+ Error = error;
+ }
+}
+
+#endregion
diff --git a/Window/WaylandWindow.cs b/Window/WaylandWindow.cs
new file mode 100644
index 0000000..7cdf811
--- /dev/null
+++ b/Window/WaylandWindow.cs
@@ -0,0 +1,1334 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Runtime.InteropServices;
+using Microsoft.Maui.Platform.Linux.Input;
+
+namespace Microsoft.Maui.Platform.Linux.Window;
+
+///
+/// Native Wayland window implementation using xdg-shell protocol.
+/// Provides full Wayland support without XWayland dependency.
+///
+public class WaylandWindow : IDisposable
+{
+ #region Native Interop - libwayland-client
+
+ private const string LibWaylandClient = "libwayland-client.so.0";
+
+ // Core display functions (actually exported)
+ [DllImport(LibWaylandClient)]
+ private static extern IntPtr wl_display_connect(string? name);
+
+ [DllImport(LibWaylandClient)]
+ private static extern void wl_display_disconnect(IntPtr display);
+
+ [DllImport(LibWaylandClient)]
+ private static extern int wl_display_dispatch(IntPtr display);
+
+ [DllImport(LibWaylandClient)]
+ private static extern int wl_display_dispatch_pending(IntPtr display);
+
+ [DllImport(LibWaylandClient)]
+ private static extern int wl_display_roundtrip(IntPtr display);
+
+ [DllImport(LibWaylandClient)]
+ private static extern int wl_display_flush(IntPtr display);
+
+ [DllImport(LibWaylandClient)]
+ private static extern int wl_display_get_fd(IntPtr display);
+
+ // Low-level proxy API (actually exported - used to implement protocol wrappers)
+ [DllImport(LibWaylandClient)]
+ private static extern IntPtr wl_proxy_marshal_constructor(
+ IntPtr proxy, uint opcode, IntPtr iface, IntPtr arg);
+
+ [DllImport(LibWaylandClient)]
+ private static extern IntPtr wl_proxy_marshal_constructor_versioned(
+ IntPtr proxy, uint opcode, IntPtr iface, uint version, IntPtr arg);
+
+ [DllImport(LibWaylandClient)]
+ private static extern void wl_proxy_marshal(IntPtr proxy, uint opcode);
+
+ [DllImport(LibWaylandClient)]
+ private static extern void wl_proxy_marshal(IntPtr proxy, uint opcode, IntPtr arg1);
+
+ [DllImport(LibWaylandClient)]
+ private static extern void wl_proxy_marshal(IntPtr proxy, uint opcode, int arg1, int arg2);
+
+ [DllImport(LibWaylandClient)]
+ private static extern void wl_proxy_marshal(IntPtr proxy, uint opcode, IntPtr arg1, int arg2, int arg3);
+
+ [DllImport(LibWaylandClient)]
+ private static extern void wl_proxy_marshal(IntPtr proxy, uint opcode, int arg1, int arg2, int arg3, int arg4);
+
+ [DllImport(LibWaylandClient)]
+ private static extern void wl_proxy_marshal(IntPtr proxy, uint opcode, uint arg1);
+
+ [DllImport(LibWaylandClient)]
+ private static extern void wl_proxy_marshal(IntPtr proxy, uint opcode,
+ [MarshalAs(UnmanagedType.LPStr)] string arg1);
+
+ [DllImport(LibWaylandClient)]
+ private static extern IntPtr wl_proxy_marshal_array_constructor(
+ IntPtr proxy, uint opcode, IntPtr args, IntPtr iface);
+
+ [DllImport(LibWaylandClient)]
+ private static extern IntPtr wl_proxy_marshal_array_constructor_versioned(
+ IntPtr proxy, uint opcode, IntPtr args, IntPtr iface, uint version);
+
+ [DllImport(LibWaylandClient)]
+ private static extern int wl_proxy_add_listener(IntPtr proxy, IntPtr impl, IntPtr data);
+
+ [DllImport(LibWaylandClient)]
+ private static extern void wl_proxy_destroy(IntPtr proxy);
+
+ [DllImport(LibWaylandClient)]
+ private static extern uint wl_proxy_get_version(IntPtr proxy);
+
+ // Interface globals (exported as data symbols)
+ [DllImport(LibWaylandClient)]
+ private static extern IntPtr wl_registry_interface_ptr();
+
+ // We need to load these at runtime since they're data symbols
+ private static IntPtr _wl_registry_interface;
+ private static IntPtr _wl_compositor_interface;
+ private static IntPtr _wl_shm_interface;
+ private static IntPtr _wl_shm_pool_interface;
+ private static IntPtr _wl_buffer_interface;
+ private static IntPtr _wl_surface_interface;
+ private static IntPtr _wl_seat_interface;
+ private static IntPtr _wl_pointer_interface;
+ private static IntPtr _wl_keyboard_interface;
+
+ // dlsym for loading interface symbols
+ [DllImport("libdl.so.2", EntryPoint = "dlopen")]
+ private static extern IntPtr dlopen(string? filename, int flags);
+
+ [DllImport("libdl.so.2", EntryPoint = "dlsym")]
+ private static extern IntPtr dlsym(IntPtr handle, string symbol);
+
+ [DllImport("libdl.so.2", EntryPoint = "dlclose")]
+ private static extern int dlclose(IntPtr handle);
+
+ private const int RTLD_NOW = 2;
+ private const int RTLD_GLOBAL = 0x100;
+
+ #endregion
+
+ #region Wayland Protocol Opcodes
+
+ // wl_display opcodes
+ private const uint WL_DISPLAY_GET_REGISTRY = 1;
+
+ // wl_registry opcodes
+ private const uint WL_REGISTRY_BIND = 0;
+
+ // wl_compositor opcodes
+ private const uint WL_COMPOSITOR_CREATE_SURFACE = 0;
+
+ // wl_surface opcodes
+ private const uint WL_SURFACE_DESTROY = 0;
+ private const uint WL_SURFACE_ATTACH = 1;
+ private const uint WL_SURFACE_DAMAGE = 2;
+ private const uint WL_SURFACE_COMMIT = 6;
+ private const uint WL_SURFACE_DAMAGE_BUFFER = 9;
+
+ // wl_shm opcodes
+ private const uint WL_SHM_CREATE_POOL = 0;
+
+ // wl_shm_pool opcodes
+ private const uint WL_SHM_POOL_CREATE_BUFFER = 0;
+ private const uint WL_SHM_POOL_DESTROY = 1;
+
+ // wl_buffer opcodes
+ private const uint WL_BUFFER_DESTROY = 0;
+
+ // wl_seat opcodes
+ private const uint WL_SEAT_GET_POINTER = 0;
+ private const uint WL_SEAT_GET_KEYBOARD = 1;
+
+ // xdg_wm_base opcodes
+ private const uint XDG_WM_BASE_GET_XDG_SURFACE = 2;
+ private const uint XDG_WM_BASE_PONG = 3;
+
+ // xdg_surface opcodes
+ private const uint XDG_SURFACE_DESTROY = 0;
+ private const uint XDG_SURFACE_GET_TOPLEVEL = 1;
+ private const uint XDG_SURFACE_ACK_CONFIGURE = 4;
+
+ // xdg_toplevel opcodes
+ private const uint XDG_TOPLEVEL_DESTROY = 0;
+ private const uint XDG_TOPLEVEL_SET_TITLE = 2;
+ private const uint XDG_TOPLEVEL_SET_APP_ID = 3;
+
+ #endregion
+
+ #region Protocol Wrapper Methods
+
+ private static void LoadInterfaceSymbols()
+ {
+ if (_wl_registry_interface != IntPtr.Zero) return;
+
+ var handle = dlopen("libwayland-client.so.0", RTLD_NOW | RTLD_GLOBAL);
+ if (handle == IntPtr.Zero)
+ throw new InvalidOperationException("Failed to load libwayland-client.so.0");
+
+ _wl_registry_interface = dlsym(handle, "wl_registry_interface");
+ _wl_compositor_interface = dlsym(handle, "wl_compositor_interface");
+ _wl_shm_interface = dlsym(handle, "wl_shm_interface");
+ _wl_shm_pool_interface = dlsym(handle, "wl_shm_pool_interface");
+ _wl_buffer_interface = dlsym(handle, "wl_buffer_interface");
+ _wl_surface_interface = dlsym(handle, "wl_surface_interface");
+ _wl_seat_interface = dlsym(handle, "wl_seat_interface");
+ _wl_pointer_interface = dlsym(handle, "wl_pointer_interface");
+ _wl_keyboard_interface = dlsym(handle, "wl_keyboard_interface");
+
+ // Don't close - we need the symbols to remain valid
+ }
+
+ // wl_display_get_registry wrapper
+ private static IntPtr wl_display_get_registry(IntPtr display)
+ {
+ return wl_proxy_marshal_constructor(display, WL_DISPLAY_GET_REGISTRY,
+ _wl_registry_interface, IntPtr.Zero);
+ }
+
+ // wl_registry_add_listener wrapper
+ private static int wl_registry_add_listener(IntPtr registry, IntPtr listener, IntPtr data)
+ {
+ return wl_proxy_add_listener(registry, listener, data);
+ }
+
+ // wl_registry_bind wrapper - uses special marshaling
+ [DllImport(LibWaylandClient, EntryPoint = "wl_proxy_marshal_flags")]
+ private static extern IntPtr wl_proxy_marshal_flags(
+ IntPtr proxy, uint opcode, IntPtr iface, uint version, uint flags,
+ uint name, IntPtr ifaceName, uint ifaceVersion);
+
+ private static IntPtr wl_registry_bind(IntPtr registry, uint name, IntPtr iface, uint version)
+ {
+ // For registry bind, we need to use marshal_flags with the interface
+ return wl_proxy_marshal_flags(registry, WL_REGISTRY_BIND, iface, version, 0,
+ name, iface, version);
+ }
+
+ // wl_compositor_create_surface wrapper
+ private static IntPtr wl_compositor_create_surface(IntPtr compositor)
+ {
+ return wl_proxy_marshal_constructor(compositor, WL_COMPOSITOR_CREATE_SURFACE,
+ _wl_surface_interface, IntPtr.Zero);
+ }
+
+ // wl_surface methods
+ private static void wl_surface_attach(IntPtr surface, IntPtr buffer, int x, int y)
+ {
+ wl_proxy_marshal(surface, WL_SURFACE_ATTACH, buffer, x, y);
+ }
+
+ private static void wl_surface_damage(IntPtr surface, int x, int y, int width, int height)
+ {
+ wl_proxy_marshal(surface, WL_SURFACE_DAMAGE, x, y, width, height);
+ }
+
+ private static void wl_surface_damage_buffer(IntPtr surface, int x, int y, int width, int height)
+ {
+ wl_proxy_marshal(surface, WL_SURFACE_DAMAGE_BUFFER, x, y, width, height);
+ }
+
+ private static void wl_surface_commit(IntPtr surface)
+ {
+ wl_proxy_marshal(surface, WL_SURFACE_COMMIT);
+ }
+
+ private static void wl_surface_destroy(IntPtr surface)
+ {
+ wl_proxy_marshal(surface, WL_SURFACE_DESTROY);
+ wl_proxy_destroy(surface);
+ }
+
+ // wl_shm_create_pool wrapper
+ [DllImport(LibWaylandClient, EntryPoint = "wl_proxy_marshal_flags")]
+ private static extern IntPtr wl_proxy_marshal_flags_fd(
+ IntPtr proxy, uint opcode, IntPtr iface, uint version, uint flags,
+ IntPtr newId, int fd, int size);
+
+ private static IntPtr wl_shm_create_pool(IntPtr shm, int fd, int size)
+ {
+ return wl_proxy_marshal_flags_fd(shm, WL_SHM_CREATE_POOL,
+ _wl_shm_pool_interface, wl_proxy_get_version(shm), 0,
+ IntPtr.Zero, fd, size);
+ }
+
+ // wl_shm_pool methods
+ [DllImport(LibWaylandClient, EntryPoint = "wl_proxy_marshal_flags")]
+ private static extern IntPtr wl_proxy_marshal_flags_buffer(
+ IntPtr proxy, uint opcode, IntPtr iface, uint version, uint flags,
+ IntPtr newId, int offset, int width, int height, int stride, uint format);
+
+ private static IntPtr wl_shm_pool_create_buffer(IntPtr pool, int offset, int width, int height, int stride, uint format)
+ {
+ return wl_proxy_marshal_flags_buffer(pool, WL_SHM_POOL_CREATE_BUFFER,
+ _wl_buffer_interface, wl_proxy_get_version(pool), 0,
+ IntPtr.Zero, offset, width, height, stride, format);
+ }
+
+ private static void wl_shm_pool_destroy(IntPtr pool)
+ {
+ wl_proxy_marshal(pool, WL_SHM_POOL_DESTROY);
+ wl_proxy_destroy(pool);
+ }
+
+ // wl_buffer methods
+ private static void wl_buffer_destroy(IntPtr buffer)
+ {
+ wl_proxy_marshal(buffer, WL_BUFFER_DESTROY);
+ wl_proxy_destroy(buffer);
+ }
+
+ private static int wl_buffer_add_listener(IntPtr buffer, IntPtr listener, IntPtr data)
+ {
+ return wl_proxy_add_listener(buffer, listener, data);
+ }
+
+ // wl_seat methods
+ private static int wl_seat_add_listener(IntPtr seat, IntPtr listener, IntPtr data)
+ {
+ return wl_proxy_add_listener(seat, listener, data);
+ }
+
+ private static IntPtr wl_seat_get_pointer(IntPtr seat)
+ {
+ return wl_proxy_marshal_constructor(seat, WL_SEAT_GET_POINTER,
+ _wl_pointer_interface, IntPtr.Zero);
+ }
+
+ private static IntPtr wl_seat_get_keyboard(IntPtr seat)
+ {
+ return wl_proxy_marshal_constructor(seat, WL_SEAT_GET_KEYBOARD,
+ _wl_keyboard_interface, IntPtr.Zero);
+ }
+
+ private static int wl_pointer_add_listener(IntPtr pointer, IntPtr listener, IntPtr data)
+ {
+ return wl_proxy_add_listener(pointer, listener, data);
+ }
+
+ private static int wl_keyboard_add_listener(IntPtr keyboard, IntPtr listener, IntPtr data)
+ {
+ return wl_proxy_add_listener(keyboard, listener, data);
+ }
+
+ #endregion
+
+ #region xdg-shell Protocol Wrappers
+
+ private static IntPtr _xdg_wm_base_interface;
+ private static IntPtr _xdg_surface_interface;
+ private static IntPtr _xdg_toplevel_interface;
+
+ // We need to create and pin interface structures for xdg-shell
+ private static GCHandle _xdgWmBaseInterfaceHandle;
+ private static GCHandle _xdgSurfaceInterfaceHandle;
+ private static GCHandle _xdgToplevelInterfaceHandle;
+ private static IntPtr _xdgWmBaseName;
+ private static IntPtr _xdgSurfaceName;
+ private static IntPtr _xdgToplevelName;
+
+ private static void LoadXdgShellInterfaces()
+ {
+ if (_xdg_wm_base_interface != IntPtr.Zero) return;
+
+ // xdg-shell interfaces are NOT in libwayland-client
+ // We need to create minimal interface structs ourselves
+ // The key fields are: name (string ptr), version, method_count, methods, event_count, events
+
+ // Allocate interface names
+ _xdgWmBaseName = Marshal.StringToHGlobalAnsi("xdg_wm_base");
+ _xdgSurfaceName = Marshal.StringToHGlobalAnsi("xdg_surface");
+ _xdgToplevelName = Marshal.StringToHGlobalAnsi("xdg_toplevel");
+
+ // Create interface structures
+ var wmBaseInterface = new WlInterface
+ {
+ Name = _xdgWmBaseName,
+ Version = 6,
+ MethodCount = 4, // destroy, create_positioner, get_xdg_surface, pong
+ Methods = IntPtr.Zero,
+ EventCount = 1, // ping
+ Events = IntPtr.Zero
+ };
+ _xdgWmBaseInterfaceHandle = GCHandle.Alloc(wmBaseInterface, GCHandleType.Pinned);
+ _xdg_wm_base_interface = _xdgWmBaseInterfaceHandle.AddrOfPinnedObject();
+
+ var surfaceInterface = new WlInterface
+ {
+ Name = _xdgSurfaceName,
+ Version = 6,
+ MethodCount = 5, // destroy, get_toplevel, get_popup, set_window_geometry, ack_configure
+ Methods = IntPtr.Zero,
+ EventCount = 1, // configure
+ Events = IntPtr.Zero
+ };
+ _xdgSurfaceInterfaceHandle = GCHandle.Alloc(surfaceInterface, GCHandleType.Pinned);
+ _xdg_surface_interface = _xdgSurfaceInterfaceHandle.AddrOfPinnedObject();
+
+ var toplevelInterface = new WlInterface
+ {
+ Name = _xdgToplevelName,
+ Version = 6,
+ MethodCount = 14, // destroy, set_parent, set_title, set_app_id, etc.
+ Methods = IntPtr.Zero,
+ EventCount = 4, // configure, close, configure_bounds, wm_capabilities
+ Events = IntPtr.Zero
+ };
+ _xdgToplevelInterfaceHandle = GCHandle.Alloc(toplevelInterface, GCHandleType.Pinned);
+ _xdg_toplevel_interface = _xdgToplevelInterfaceHandle.AddrOfPinnedObject();
+ }
+
+ private static IntPtr xdg_wm_base_get_xdg_surface(IntPtr wmBase, IntPtr surface)
+ {
+ return wl_proxy_marshal_constructor(wmBase, XDG_WM_BASE_GET_XDG_SURFACE,
+ _xdg_surface_interface, surface);
+ }
+
+ private static void xdg_wm_base_pong(IntPtr wmBase, uint serial)
+ {
+ wl_proxy_marshal(wmBase, XDG_WM_BASE_PONG, serial);
+ }
+
+ private static int xdg_wm_base_add_listener(IntPtr wmBase, IntPtr listener, IntPtr data)
+ {
+ return wl_proxy_add_listener(wmBase, listener, data);
+ }
+
+ private static IntPtr xdg_surface_get_toplevel(IntPtr xdgSurface)
+ {
+ return wl_proxy_marshal_constructor(xdgSurface, XDG_SURFACE_GET_TOPLEVEL,
+ _xdg_toplevel_interface, IntPtr.Zero);
+ }
+
+ private static void xdg_surface_ack_configure(IntPtr xdgSurface, uint serial)
+ {
+ wl_proxy_marshal(xdgSurface, XDG_SURFACE_ACK_CONFIGURE, serial);
+ }
+
+ private static int xdg_surface_add_listener(IntPtr xdgSurface, IntPtr listener, IntPtr data)
+ {
+ return wl_proxy_add_listener(xdgSurface, listener, data);
+ }
+
+ private static void xdg_surface_destroy(IntPtr xdgSurface)
+ {
+ wl_proxy_marshal(xdgSurface, XDG_SURFACE_DESTROY);
+ wl_proxy_destroy(xdgSurface);
+ }
+
+ private static void xdg_toplevel_set_title(IntPtr toplevel, string title)
+ {
+ wl_proxy_marshal(toplevel, XDG_TOPLEVEL_SET_TITLE, title);
+ }
+
+ private static void xdg_toplevel_set_app_id(IntPtr toplevel, string appId)
+ {
+ wl_proxy_marshal(toplevel, XDG_TOPLEVEL_SET_APP_ID, appId);
+ }
+
+ private static int xdg_toplevel_add_listener(IntPtr toplevel, IntPtr listener, IntPtr data)
+ {
+ return wl_proxy_add_listener(toplevel, listener, data);
+ }
+
+ private static void xdg_toplevel_destroy(IntPtr toplevel)
+ {
+ wl_proxy_marshal(toplevel, XDG_TOPLEVEL_DESTROY);
+ wl_proxy_destroy(toplevel);
+ }
+
+ #endregion
+
+ #region Native Interop - libc
+
+ [DllImport("libc", EntryPoint = "shm_open")]
+ private static extern int shm_open([MarshalAs(UnmanagedType.LPStr)] string name, int oflag, int mode);
+
+ [DllImport("libc", EntryPoint = "shm_unlink")]
+ private static extern int shm_unlink([MarshalAs(UnmanagedType.LPStr)] string name);
+
+ [DllImport("libc", EntryPoint = "ftruncate")]
+ private static extern int ftruncate(int fd, long length);
+
+ [DllImport("libc", EntryPoint = "mmap")]
+ private static extern IntPtr mmap(IntPtr addr, nuint length, int prot, int flags, int fd, long offset);
+
+ [DllImport("libc", EntryPoint = "munmap")]
+ private static extern int munmap(IntPtr addr, nuint length);
+
+ [DllImport("libc", EntryPoint = "close")]
+ private static extern int close(int fd);
+
+ [DllImport("libc", EntryPoint = "memfd_create")]
+ private static extern int memfd_create([MarshalAs(UnmanagedType.LPStr)] string name, uint flags);
+
+ private const int O_RDWR = 2;
+ private const int O_CREAT = 64;
+ private const int O_EXCL = 128;
+ private const int PROT_READ = 1;
+ private const int PROT_WRITE = 2;
+ private const int MAP_SHARED = 1;
+ private const uint MFD_CLOEXEC = 1;
+
+ #endregion
+
+ #region Wayland Structures
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct WlInterface
+ {
+ public IntPtr Name;
+ public int Version;
+ public int MethodCount;
+ public IntPtr Methods;
+ public int EventCount;
+ public IntPtr Events;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct WlRegistryListener
+ {
+ public IntPtr Global;
+ public IntPtr GlobalRemove;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct WlSurfaceListener
+ {
+ public IntPtr Enter;
+ public IntPtr Leave;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct WlBufferListener
+ {
+ public IntPtr Release;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct WlSeatListener
+ {
+ public IntPtr Capabilities;
+ public IntPtr Name;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct WlPointerListener
+ {
+ public IntPtr Enter;
+ public IntPtr Leave;
+ public IntPtr Motion;
+ public IntPtr Button;
+ public IntPtr Axis;
+ public IntPtr Frame;
+ public IntPtr AxisSource;
+ public IntPtr AxisStop;
+ public IntPtr AxisDiscrete;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct WlKeyboardListener
+ {
+ public IntPtr Keymap;
+ public IntPtr Enter;
+ public IntPtr Leave;
+ public IntPtr Key;
+ public IntPtr Modifiers;
+ public IntPtr RepeatInfo;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct XdgWmBaseListener
+ {
+ public IntPtr Ping;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct XdgSurfaceListener
+ {
+ public IntPtr Configure;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ private struct XdgToplevelListener
+ {
+ public IntPtr Configure;
+ public IntPtr Close;
+ }
+
+ private const uint WL_SHM_FORMAT_ARGB8888 = 0;
+ private const uint WL_SHM_FORMAT_XRGB8888 = 1;
+
+ // Seat capabilities
+ private const uint WL_SEAT_CAPABILITY_POINTER = 1;
+ private const uint WL_SEAT_CAPABILITY_KEYBOARD = 2;
+
+ // Pointer button states
+ private const uint WL_POINTER_BUTTON_STATE_RELEASED = 0;
+ private const uint WL_POINTER_BUTTON_STATE_PRESSED = 1;
+
+ // Linux input button codes
+ private const uint BTN_LEFT = 0x110;
+ private const uint BTN_RIGHT = 0x111;
+ private const uint BTN_MIDDLE = 0x112;
+
+ // Key states
+ private const uint WL_KEYBOARD_KEY_STATE_RELEASED = 0;
+ private const uint WL_KEYBOARD_KEY_STATE_PRESSED = 1;
+
+ #endregion
+
+ #region Fields
+
+ private IntPtr _display;
+ private IntPtr _registry;
+ private IntPtr _compositor;
+ private IntPtr _shm;
+ private IntPtr _seat;
+ private IntPtr _xdgWmBase;
+ private IntPtr _surface;
+ private IntPtr _xdgSurface;
+ private IntPtr _xdgToplevel;
+ private IntPtr _pointer;
+ private IntPtr _keyboard;
+ private IntPtr _shmPool;
+ private IntPtr _buffer;
+ private IntPtr _pixelData;
+ private int _shmFd = -1;
+ private int _bufferSize;
+ private int _stride;
+
+ private int _width;
+ private int _height;
+ private int _pendingWidth;
+ private int _pendingHeight;
+ private string _title;
+ private bool _isRunning;
+ private bool _disposed;
+ private bool _configured;
+ private uint _lastConfigureSerial;
+
+ // Input state
+ private float _pointerX;
+ private float _pointerY;
+ private uint _pointerSerial;
+ private uint _modifiers;
+
+ // Delegates to prevent GC
+ private WlRegistryListener _registryListener;
+ private WlSeatListener _seatListener;
+ private WlPointerListener _pointerListener;
+ private WlKeyboardListener _keyboardListener;
+ private XdgWmBaseListener _wmBaseListener;
+ private XdgSurfaceListener _xdgSurfaceListener;
+ private XdgToplevelListener _toplevelListener;
+ private WlBufferListener _bufferListener;
+
+ // GCHandles for listener structs to prevent GC
+ private GCHandle _registryListenerHandle;
+ private GCHandle _seatListenerHandle;
+ private GCHandle _pointerListenerHandle;
+ private GCHandle _keyboardListenerHandle;
+ private GCHandle _wmBaseListenerHandle;
+ private GCHandle _xdgSurfaceListenerHandle;
+ private GCHandle _toplevelListenerHandle;
+ private GCHandle _bufferListenerHandle;
+
+ private static bool _interfacesInitialized;
+
+ // GCHandles to prevent delegate collection
+ private GCHandle _thisHandle;
+
+ #endregion
+
+ #region Properties
+
+ public IntPtr Display => _display;
+ public IntPtr Surface => _surface;
+ public int Width => _width;
+ public int Height => _height;
+ public bool IsRunning => _isRunning;
+ public IntPtr PixelData => _pixelData;
+ public int Stride => _stride;
+
+ #endregion
+
+ #region Events
+
+ public event EventHandler? KeyDown;
+ public event EventHandler? KeyUp;
+ public event EventHandler? TextInput;
+ public event EventHandler? PointerMoved;
+ public event EventHandler? PointerPressed;
+ public event EventHandler? PointerReleased;
+ public event EventHandler? Scroll;
+ public event EventHandler? Exposed;
+ public event EventHandler<(int Width, int Height)>? Resized;
+ public event EventHandler? CloseRequested;
+ public event EventHandler? FocusGained;
+ public event EventHandler? FocusLost;
+
+ #endregion
+
+ #region Constructor
+
+ public WaylandWindow(string title, int width, int height)
+ {
+ _title = title;
+ _width = width;
+ _height = height;
+ _pendingWidth = width;
+ _pendingHeight = height;
+
+ InitializeInterfaces();
+ Initialize();
+ }
+
+ #endregion
+
+ #region Initialization
+
+ private static void InitializeInterfaces()
+ {
+ if (_interfacesInitialized) return;
+
+ // Load interface symbols from libwayland-client using dlsym
+ LoadInterfaceSymbols();
+ LoadXdgShellInterfaces();
+
+ _interfacesInitialized = true;
+ }
+
+ private void Initialize()
+ {
+ // Keep this object alive for callbacks
+ _thisHandle = GCHandle.Alloc(this);
+
+ // Connect to Wayland display
+ _display = wl_display_connect(null);
+ if (_display == IntPtr.Zero)
+ {
+ throw new InvalidOperationException(
+ "Failed to connect to Wayland display. " +
+ "Ensure WAYLAND_DISPLAY is set and a compositor is running.");
+ }
+
+ // Get registry
+ _registry = wl_display_get_registry(_display);
+ if (_registry == IntPtr.Zero)
+ {
+ throw new InvalidOperationException("Failed to get Wayland registry");
+ }
+
+ // Set up registry listener
+ _registryListener = new WlRegistryListener
+ {
+ Global = Marshal.GetFunctionPointerForDelegate(RegistryGlobal),
+ GlobalRemove = Marshal.GetFunctionPointerForDelegate(RegistryGlobalRemove)
+ };
+ _registryListenerHandle = GCHandle.Alloc(_registryListener, GCHandleType.Pinned);
+ wl_registry_add_listener(_registry, _registryListenerHandle.AddrOfPinnedObject(), GCHandle.ToIntPtr(_thisHandle));
+
+ // Do initial roundtrip to get globals
+ wl_display_roundtrip(_display);
+
+ // Verify we got required globals
+ if (_compositor == IntPtr.Zero)
+ throw new InvalidOperationException("Wayland compositor not found");
+ if (_shm == IntPtr.Zero)
+ throw new InvalidOperationException("Wayland shm not found");
+ if (_xdgWmBase == IntPtr.Zero)
+ throw new InvalidOperationException("xdg_wm_base not found - compositor doesn't support xdg-shell");
+
+ // Create surface
+ _surface = wl_compositor_create_surface(_compositor);
+ if (_surface == IntPtr.Zero)
+ throw new InvalidOperationException("Failed to create Wayland surface");
+
+ // Create xdg_surface
+ _xdgSurface = xdg_wm_base_get_xdg_surface(_xdgWmBase, _surface);
+ if (_xdgSurface == IntPtr.Zero)
+ throw new InvalidOperationException("Failed to create xdg_surface");
+
+ _xdgSurfaceListener = new XdgSurfaceListener
+ {
+ Configure = Marshal.GetFunctionPointerForDelegate(XdgSurfaceConfigure)
+ };
+ _xdgSurfaceListenerHandle = GCHandle.Alloc(_xdgSurfaceListener, GCHandleType.Pinned);
+ xdg_surface_add_listener(_xdgSurface, _xdgSurfaceListenerHandle.AddrOfPinnedObject(), GCHandle.ToIntPtr(_thisHandle));
+
+ // Create toplevel
+ _xdgToplevel = xdg_surface_get_toplevel(_xdgSurface);
+ if (_xdgToplevel == IntPtr.Zero)
+ throw new InvalidOperationException("Failed to create xdg_toplevel");
+
+ _toplevelListener = new XdgToplevelListener
+ {
+ Configure = Marshal.GetFunctionPointerForDelegate(XdgToplevelConfigure),
+ Close = Marshal.GetFunctionPointerForDelegate(XdgToplevelClose)
+ };
+ _toplevelListenerHandle = GCHandle.Alloc(_toplevelListener, GCHandleType.Pinned);
+ xdg_toplevel_add_listener(_xdgToplevel, _toplevelListenerHandle.AddrOfPinnedObject(), GCHandle.ToIntPtr(_thisHandle));
+
+ // Set title and app_id
+ xdg_toplevel_set_title(_xdgToplevel, _title);
+ xdg_toplevel_set_app_id(_xdgToplevel, "com.openmaui.app");
+
+ // Commit empty surface to get initial configure
+ wl_surface_commit(_surface);
+ wl_display_roundtrip(_display);
+
+ // Create shared memory buffer
+ CreateShmBuffer();
+
+ Console.WriteLine($"[Wayland] Window created: {_width}x{_height}");
+ }
+
+ private void CreateShmBuffer()
+ {
+ _stride = _width * 4;
+ _bufferSize = _stride * _height;
+
+ // Create anonymous file for shared memory
+ _shmFd = memfd_create("maui-buffer", MFD_CLOEXEC);
+ if (_shmFd < 0)
+ {
+ // Fall back to shm_open
+ string shmName = $"/maui-{Environment.ProcessId}-{DateTime.Now.Ticks}";
+ _shmFd = shm_open(shmName, O_RDWR | O_CREAT | O_EXCL, 0x180); // 0600
+ if (_shmFd >= 0)
+ shm_unlink(shmName);
+ }
+
+ if (_shmFd < 0)
+ throw new InvalidOperationException("Failed to create shared memory");
+
+ if (ftruncate(_shmFd, _bufferSize) < 0)
+ {
+ close(_shmFd);
+ throw new InvalidOperationException("Failed to resize shared memory");
+ }
+
+ _pixelData = mmap(IntPtr.Zero, (nuint)_bufferSize, PROT_READ | PROT_WRITE, MAP_SHARED, _shmFd, 0);
+ if (_pixelData == IntPtr.Zero || _pixelData == new IntPtr(-1))
+ {
+ close(_shmFd);
+ throw new InvalidOperationException("Failed to mmap shared memory");
+ }
+
+ // Create pool and buffer
+ _shmPool = wl_shm_create_pool(_shm, _shmFd, _bufferSize);
+ if (_shmPool == IntPtr.Zero)
+ {
+ munmap(_pixelData, (nuint)_bufferSize);
+ close(_shmFd);
+ throw new InvalidOperationException("Failed to create wl_shm_pool");
+ }
+
+ _buffer = wl_shm_pool_create_buffer(_shmPool, 0, _width, _height, _stride, WL_SHM_FORMAT_ARGB8888);
+ if (_buffer == IntPtr.Zero)
+ {
+ wl_shm_pool_destroy(_shmPool);
+ munmap(_pixelData, (nuint)_bufferSize);
+ close(_shmFd);
+ throw new InvalidOperationException("Failed to create wl_buffer");
+ }
+
+ // Listen for buffer release
+ _bufferListener = new WlBufferListener
+ {
+ Release = Marshal.GetFunctionPointerForDelegate(BufferRelease)
+ };
+ if (_bufferListenerHandle.IsAllocated) _bufferListenerHandle.Free();
+ _bufferListenerHandle = GCHandle.Alloc(_bufferListener, GCHandleType.Pinned);
+ wl_buffer_add_listener(_buffer, _bufferListenerHandle.AddrOfPinnedObject(), GCHandle.ToIntPtr(_thisHandle));
+ }
+
+ private void ResizeBuffer(int newWidth, int newHeight)
+ {
+ if (newWidth == _width && newHeight == _height) return;
+ if (newWidth <= 0 || newHeight <= 0) return;
+
+ // Destroy old buffer
+ if (_buffer != IntPtr.Zero)
+ wl_buffer_destroy(_buffer);
+ if (_shmPool != IntPtr.Zero)
+ wl_shm_pool_destroy(_shmPool);
+ if (_pixelData != IntPtr.Zero && _pixelData != new IntPtr(-1))
+ munmap(_pixelData, (nuint)_bufferSize);
+ if (_shmFd >= 0)
+ close(_shmFd);
+
+ _width = newWidth;
+ _height = newHeight;
+
+ CreateShmBuffer();
+ Resized?.Invoke(this, (_width, _height));
+ }
+
+ #endregion
+
+ #region Callback Delegates
+
+ private delegate void RegistryGlobalDelegate(IntPtr data, IntPtr registry, uint name, IntPtr iface, uint version);
+ private delegate void RegistryGlobalRemoveDelegate(IntPtr data, IntPtr registry, uint name);
+ private delegate void SeatCapabilitiesDelegate(IntPtr data, IntPtr seat, uint capabilities);
+ private delegate void SeatNameDelegate(IntPtr data, IntPtr seat, IntPtr name);
+ private delegate void PointerEnterDelegate(IntPtr data, IntPtr pointer, uint serial, IntPtr surface, int x, int y);
+ private delegate void PointerLeaveDelegate(IntPtr data, IntPtr pointer, uint serial, IntPtr surface);
+ private delegate void PointerMotionDelegate(IntPtr data, IntPtr pointer, uint time, int x, int y);
+ private delegate void PointerButtonDelegate(IntPtr data, IntPtr pointer, uint serial, uint time, uint button, uint state);
+ private delegate void PointerAxisDelegate(IntPtr data, IntPtr pointer, uint time, uint axis, int value);
+ private delegate void PointerFrameDelegate(IntPtr data, IntPtr pointer);
+ private delegate void KeyboardKeymapDelegate(IntPtr data, IntPtr keyboard, uint format, int fd, uint size);
+ private delegate void KeyboardEnterDelegate(IntPtr data, IntPtr keyboard, uint serial, IntPtr surface, IntPtr keys);
+ private delegate void KeyboardLeaveDelegate(IntPtr data, IntPtr keyboard, uint serial, IntPtr surface);
+ private delegate void KeyboardKeyDelegate(IntPtr data, IntPtr keyboard, uint serial, uint time, uint key, uint state);
+ private delegate void KeyboardModifiersDelegate(IntPtr data, IntPtr keyboard, uint serial, uint modsDepressed, uint modsLatched, uint modsLocked, uint group);
+ private delegate void XdgWmBasePingDelegate(IntPtr data, IntPtr wmBase, uint serial);
+ private delegate void XdgSurfaceConfigureDelegate(IntPtr data, IntPtr xdgSurface, uint serial);
+ private delegate void XdgToplevelConfigureDelegate(IntPtr data, IntPtr toplevel, int width, int height, IntPtr states);
+ private delegate void XdgToplevelCloseDelegate(IntPtr data, IntPtr toplevel);
+ private delegate void BufferReleaseDelegate(IntPtr data, IntPtr buffer);
+
+ #endregion
+
+ #region Callback Implementations
+
+ private static void RegistryGlobal(IntPtr data, IntPtr registry, uint name, IntPtr iface, uint version)
+ {
+ var handle = GCHandle.FromIntPtr(data);
+ if (!handle.IsAllocated) return;
+ var window = (WaylandWindow)handle.Target!;
+
+ var interfaceName = Marshal.PtrToStringAnsi(iface);
+ Console.WriteLine($"[Wayland] Global: {interfaceName} v{version}");
+
+ switch (interfaceName)
+ {
+ case "wl_compositor":
+ window._compositor = wl_registry_bind(registry, name, _wl_compositor_interface, Math.Min(version, 4u));
+ break;
+ case "wl_shm":
+ window._shm = wl_registry_bind(registry, name, _wl_shm_interface, 1);
+ break;
+ case "wl_seat":
+ window._seat = wl_registry_bind(registry, name, _wl_seat_interface, Math.Min(version, 5u));
+ window.SetupSeat();
+ break;
+ case "xdg_wm_base":
+ window._xdgWmBase = wl_registry_bind(registry, name, _xdg_wm_base_interface, Math.Min(version, 2u));
+ window.SetupXdgWmBase();
+ break;
+ }
+ }
+
+ private static void RegistryGlobalRemove(IntPtr data, IntPtr registry, uint name)
+ {
+ // Handle global removal if needed
+ }
+
+ private void SetupSeat()
+ {
+ if (_seat == IntPtr.Zero) return;
+
+ _seatListener = new WlSeatListener
+ {
+ Capabilities = Marshal.GetFunctionPointerForDelegate(SeatCapabilities),
+ Name = Marshal.GetFunctionPointerForDelegate(SeatName)
+ };
+ _seatListenerHandle = GCHandle.Alloc(_seatListener, GCHandleType.Pinned);
+ wl_seat_add_listener(_seat, _seatListenerHandle.AddrOfPinnedObject(), GCHandle.ToIntPtr(_thisHandle));
+ }
+
+ private static void SeatCapabilities(IntPtr data, IntPtr seat, uint capabilities)
+ {
+ var handle = GCHandle.FromIntPtr(data);
+ if (!handle.IsAllocated) return;
+ var window = (WaylandWindow)handle.Target!;
+
+ if ((capabilities & WL_SEAT_CAPABILITY_POINTER) != 0 && window._pointer == IntPtr.Zero)
+ {
+ window._pointer = wl_seat_get_pointer(seat);
+ window.SetupPointer();
+ }
+
+ if ((capabilities & WL_SEAT_CAPABILITY_KEYBOARD) != 0 && window._keyboard == IntPtr.Zero)
+ {
+ window._keyboard = wl_seat_get_keyboard(seat);
+ window.SetupKeyboard();
+ }
+ }
+
+ private static void SeatName(IntPtr data, IntPtr seat, IntPtr name) { }
+
+ private void SetupPointer()
+ {
+ if (_pointer == IntPtr.Zero) return;
+
+ _pointerListener = new WlPointerListener
+ {
+ Enter = Marshal.GetFunctionPointerForDelegate(PointerEnter),
+ Leave = Marshal.GetFunctionPointerForDelegate(PointerLeave),
+ Motion = Marshal.GetFunctionPointerForDelegate(PointerMotion),
+ Button = Marshal.GetFunctionPointerForDelegate(OnPointerButton),
+ Axis = Marshal.GetFunctionPointerForDelegate(PointerAxis),
+ Frame = Marshal.GetFunctionPointerForDelegate(PointerFrame),
+ };
+ _pointerListenerHandle = GCHandle.Alloc(_pointerListener, GCHandleType.Pinned);
+ wl_pointer_add_listener(_pointer, _pointerListenerHandle.AddrOfPinnedObject(), GCHandle.ToIntPtr(_thisHandle));
+ }
+
+ private static void PointerEnter(IntPtr data, IntPtr pointer, uint serial, IntPtr surface, int x, int y)
+ {
+ var handle = GCHandle.FromIntPtr(data);
+ if (!handle.IsAllocated) return;
+ var window = (WaylandWindow)handle.Target!;
+ window._pointerSerial = serial;
+ window._pointerX = x / 256.0f;
+ window._pointerY = y / 256.0f;
+ }
+
+ private static void PointerLeave(IntPtr data, IntPtr pointer, uint serial, IntPtr surface) { }
+
+ private static void PointerMotion(IntPtr data, IntPtr pointer, uint time, int x, int y)
+ {
+ var handle = GCHandle.FromIntPtr(data);
+ if (!handle.IsAllocated) return;
+ var window = (WaylandWindow)handle.Target!;
+
+ window._pointerX = x / 256.0f;
+ window._pointerY = y / 256.0f;
+ window.PointerMoved?.Invoke(window, new PointerEventArgs((int)window._pointerX, (int)window._pointerY));
+ }
+
+ private static void OnPointerButton(IntPtr data, IntPtr pointer, uint serial, uint time, uint button, uint state)
+ {
+ var handle = GCHandle.FromIntPtr(data);
+ if (!handle.IsAllocated) return;
+ var window = (WaylandWindow)handle.Target!;
+
+ var ptrButton = button switch
+ {
+ BTN_LEFT => Microsoft.Maui.Platform.PointerButton.Left,
+ BTN_RIGHT => Microsoft.Maui.Platform.PointerButton.Right,
+ BTN_MIDDLE => Microsoft.Maui.Platform.PointerButton.Middle,
+ _ => Microsoft.Maui.Platform.PointerButton.None
+ };
+
+ var args = new PointerEventArgs((int)window._pointerX, (int)window._pointerY, ptrButton);
+
+ if (state == WL_POINTER_BUTTON_STATE_PRESSED)
+ window.PointerPressed?.Invoke(window, args);
+ else
+ window.PointerReleased?.Invoke(window, args);
+ }
+
+ private static void PointerAxis(IntPtr data, IntPtr pointer, uint time, uint axis, int value)
+ {
+ var handle = GCHandle.FromIntPtr(data);
+ if (!handle.IsAllocated) return;
+ var window = (WaylandWindow)handle.Target!;
+
+ float delta = value / 256.0f / 10.0f;
+ if (axis == 0) // Vertical
+ window.Scroll?.Invoke(window, new ScrollEventArgs((int)window._pointerX, (int)window._pointerY, 0, delta));
+ else // Horizontal
+ window.Scroll?.Invoke(window, new ScrollEventArgs((int)window._pointerX, (int)window._pointerY, delta, 0));
+ }
+
+ private static void PointerFrame(IntPtr data, IntPtr pointer) { }
+
+ private void SetupKeyboard()
+ {
+ if (_keyboard == IntPtr.Zero) return;
+
+ _keyboardListener = new WlKeyboardListener
+ {
+ Keymap = Marshal.GetFunctionPointerForDelegate(KeyboardKeymap),
+ Enter = Marshal.GetFunctionPointerForDelegate(KeyboardEnter),
+ Leave = Marshal.GetFunctionPointerForDelegate(KeyboardLeave),
+ Key = Marshal.GetFunctionPointerForDelegate(KeyboardKey),
+ Modifiers = Marshal.GetFunctionPointerForDelegate(KeyboardModifiers),
+ };
+ _keyboardListenerHandle = GCHandle.Alloc(_keyboardListener, GCHandleType.Pinned);
+ wl_keyboard_add_listener(_keyboard, _keyboardListenerHandle.AddrOfPinnedObject(), GCHandle.ToIntPtr(_thisHandle));
+ }
+
+ private static void KeyboardKeymap(IntPtr data, IntPtr keyboard, uint format, int fd, uint size)
+ {
+ close(fd);
+ }
+
+ private static void KeyboardEnter(IntPtr data, IntPtr keyboard, uint serial, IntPtr surface, IntPtr keys)
+ {
+ var handle = GCHandle.FromIntPtr(data);
+ if (!handle.IsAllocated) return;
+ var window = (WaylandWindow)handle.Target!;
+ window.FocusGained?.Invoke(window, EventArgs.Empty);
+ }
+
+ private static void KeyboardLeave(IntPtr data, IntPtr keyboard, uint serial, IntPtr surface)
+ {
+ var handle = GCHandle.FromIntPtr(data);
+ if (!handle.IsAllocated) return;
+ var window = (WaylandWindow)handle.Target!;
+ window.FocusLost?.Invoke(window, EventArgs.Empty);
+ }
+
+ private static void KeyboardKey(IntPtr data, IntPtr keyboard, uint serial, uint time, uint keycode, uint state)
+ {
+ var handle = GCHandle.FromIntPtr(data);
+ if (!handle.IsAllocated) return;
+ var window = (WaylandWindow)handle.Target!;
+
+ // Convert Linux keycode to Key enum (add 8 for X11 compat)
+ var key = KeyMapping.FromLinuxKeycode(keycode + 8);
+ var modifiers = (KeyModifiers)window._modifiers;
+ var args = new KeyEventArgs(key, modifiers);
+
+ if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
+ {
+ window.KeyDown?.Invoke(window, args);
+
+ // Generate text input for printable keys
+ char? ch = KeyMapping.ToChar(key, modifiers);
+ if (ch.HasValue)
+ window.TextInput?.Invoke(window, new TextInputEventArgs(ch.Value.ToString()));
+ }
+ else
+ {
+ window.KeyUp?.Invoke(window, args);
+ }
+ }
+
+ private static void KeyboardModifiers(IntPtr data, IntPtr keyboard, uint serial, uint modsDepressed, uint modsLatched, uint modsLocked, uint group)
+ {
+ var handle = GCHandle.FromIntPtr(data);
+ if (!handle.IsAllocated) return;
+ var window = (WaylandWindow)handle.Target!;
+ window._modifiers = modsDepressed | modsLatched;
+ }
+
+ private void SetupXdgWmBase()
+ {
+ if (_xdgWmBase == IntPtr.Zero) return;
+
+ _wmBaseListener = new XdgWmBaseListener
+ {
+ Ping = Marshal.GetFunctionPointerForDelegate(XdgWmBasePing)
+ };
+ _wmBaseListenerHandle = GCHandle.Alloc(_wmBaseListener, GCHandleType.Pinned);
+ xdg_wm_base_add_listener(_xdgWmBase, _wmBaseListenerHandle.AddrOfPinnedObject(), GCHandle.ToIntPtr(_thisHandle));
+ }
+
+ private static void XdgWmBasePing(IntPtr data, IntPtr wmBase, uint serial)
+ {
+ xdg_wm_base_pong(wmBase, serial);
+ }
+
+ private static void XdgSurfaceConfigure(IntPtr data, IntPtr xdgSurface, uint serial)
+ {
+ var handle = GCHandle.FromIntPtr(data);
+ if (!handle.IsAllocated) return;
+ var window = (WaylandWindow)handle.Target!;
+
+ xdg_surface_ack_configure(xdgSurface, serial);
+ window._lastConfigureSerial = serial;
+
+ if (!window._configured)
+ {
+ window._configured = true;
+ if (window._pendingWidth > 0 && window._pendingHeight > 0)
+ {
+ window.ResizeBuffer(window._pendingWidth, window._pendingHeight);
+ }
+ window.Exposed?.Invoke(window, EventArgs.Empty);
+ }
+ }
+
+ private static void XdgToplevelConfigure(IntPtr data, IntPtr toplevel, int width, int height, IntPtr states)
+ {
+ var handle = GCHandle.FromIntPtr(data);
+ if (!handle.IsAllocated) return;
+ var window = (WaylandWindow)handle.Target!;
+
+ if (width > 0 && height > 0)
+ {
+ window._pendingWidth = width;
+ window._pendingHeight = height;
+
+ if (window._configured)
+ {
+ window.ResizeBuffer(width, height);
+ }
+ }
+ }
+
+ private static void XdgToplevelClose(IntPtr data, IntPtr toplevel)
+ {
+ var handle = GCHandle.FromIntPtr(data);
+ if (!handle.IsAllocated) return;
+ var window = (WaylandWindow)handle.Target!;
+
+ window.CloseRequested?.Invoke(window, EventArgs.Empty);
+ window._isRunning = false;
+ }
+
+ private static void BufferRelease(IntPtr data, IntPtr buffer)
+ {
+ // Buffer is available for reuse
+ }
+
+ #endregion
+
+ #region Public Methods
+
+ public void Show()
+ {
+ _isRunning = true;
+
+ // Attach buffer and commit
+ wl_surface_attach(_surface, _buffer, 0, 0);
+ wl_surface_damage_buffer(_surface, 0, 0, _width, _height);
+ wl_surface_commit(_surface);
+ wl_display_flush(_display);
+ }
+
+ public void Hide()
+ {
+ wl_surface_attach(_surface, IntPtr.Zero, 0, 0);
+ wl_surface_commit(_surface);
+ wl_display_flush(_display);
+ }
+
+ public void SetTitle(string title)
+ {
+ _title = title;
+ if (_xdgToplevel != IntPtr.Zero)
+ xdg_toplevel_set_title(_xdgToplevel, title);
+ }
+
+ public void Resize(int width, int height)
+ {
+ ResizeBuffer(width, height);
+ }
+
+ public void ProcessEvents()
+ {
+ if (!_isRunning || _display == IntPtr.Zero) return;
+
+ wl_display_dispatch_pending(_display);
+ wl_display_flush(_display);
+ }
+
+ public void Stop()
+ {
+ _isRunning = false;
+ }
+
+ public void CommitFrame()
+ {
+ if (_surface != IntPtr.Zero && _buffer != IntPtr.Zero)
+ {
+ wl_surface_attach(_surface, _buffer, 0, 0);
+ wl_surface_damage_buffer(_surface, 0, 0, _width, _height);
+ wl_surface_commit(_surface);
+ wl_display_flush(_display);
+ }
+ }
+
+ public int GetFileDescriptor()
+ {
+ return wl_display_get_fd(_display);
+ }
+
+ #endregion
+
+ #region IDisposable
+
+ public void Dispose()
+ {
+ if (_disposed) return;
+ _disposed = true;
+ _isRunning = false;
+
+ if (_buffer != IntPtr.Zero)
+ {
+ wl_buffer_destroy(_buffer);
+ _buffer = IntPtr.Zero;
+ }
+
+ if (_shmPool != IntPtr.Zero)
+ {
+ wl_shm_pool_destroy(_shmPool);
+ _shmPool = IntPtr.Zero;
+ }
+
+ if (_pixelData != IntPtr.Zero && _pixelData != new IntPtr(-1))
+ {
+ munmap(_pixelData, (nuint)_bufferSize);
+ _pixelData = IntPtr.Zero;
+ }
+
+ if (_shmFd >= 0)
+ {
+ close(_shmFd);
+ _shmFd = -1;
+ }
+
+ if (_xdgToplevel != IntPtr.Zero)
+ {
+ xdg_toplevel_destroy(_xdgToplevel);
+ _xdgToplevel = IntPtr.Zero;
+ }
+
+ if (_xdgSurface != IntPtr.Zero)
+ {
+ xdg_surface_destroy(_xdgSurface);
+ _xdgSurface = IntPtr.Zero;
+ }
+
+ if (_surface != IntPtr.Zero)
+ {
+ wl_surface_destroy(_surface);
+ _surface = IntPtr.Zero;
+ }
+
+ if (_display != IntPtr.Zero)
+ {
+ wl_display_disconnect(_display);
+ _display = IntPtr.Zero;
+ }
+
+ // Free listener GCHandles
+ if (_registryListenerHandle.IsAllocated) _registryListenerHandle.Free();
+ if (_seatListenerHandle.IsAllocated) _seatListenerHandle.Free();
+ if (_pointerListenerHandle.IsAllocated) _pointerListenerHandle.Free();
+ if (_keyboardListenerHandle.IsAllocated) _keyboardListenerHandle.Free();
+ if (_wmBaseListenerHandle.IsAllocated) _wmBaseListenerHandle.Free();
+ if (_xdgSurfaceListenerHandle.IsAllocated) _xdgSurfaceListenerHandle.Free();
+ if (_toplevelListenerHandle.IsAllocated) _toplevelListenerHandle.Free();
+ if (_bufferListenerHandle.IsAllocated) _bufferListenerHandle.Free();
+
+ if (_thisHandle.IsAllocated)
+ _thisHandle.Free();
+
+ GC.SuppressFinalize(this);
+ }
+
+ ~WaylandWindow()
+ {
+ Dispose();
+ }
+
+ #endregion
+}
diff --git a/Window/X11Window.cs b/Window/X11Window.cs
index 45641e7..49358fa 100644
--- a/Window/X11Window.cs
+++ b/Window/X11Window.cs
@@ -288,8 +288,12 @@ public class X11Window : IDisposable
KeyDown?.Invoke(this, new KeyEventArgs(key, modifiers));
- // Generate text input for printable characters
- if (keysym >= 32 && keysym <= 126)
+ // Generate text input for printable characters, but NOT when Control or Alt is held
+ // (those are keyboard shortcuts, not text input)
+ bool isControlHeld = (keyEvent.State & 0x04) != 0; // ControlMask
+ bool isAltHeld = (keyEvent.State & 0x08) != 0; // Mod1Mask (Alt)
+
+ if (keysym >= 32 && keysym <= 126 && !isControlHeld && !isAltHeld)
{
TextInput?.Invoke(this, new TextInputEventArgs(((char)keysym).ToString()));
}
diff --git a/out.xml b/out.xml
new file mode 100644
index 0000000..2a5502c
--- /dev/null
+++ b/out.xml
@@ -0,0 +1,19333 @@
+
+
+
+
+
+ <_AfterSdkPublishDependsOn Condition="'$(_IsAspNetCoreProject)' == 'true'">AfterPublish
+ <_AfterSdkPublishDependsOn Condition="'$(_IsAspNetCoreProject)' != 'true'">Publish
+
+
+
+
+ true
+
+ true
+ $(CustomAfterDirectoryBuildProps);$(MSBuildThisFileDirectory)UseArtifactsOutputPath.props
+
+
+ $(ProjectExtensionsPathForSpecifiedProject)
+
+
+
+
+
+ true
+ true
+ true
+ true
+ true
+
+
+
+ <_DirectoryBuildPropsFile Condition="'$(_DirectoryBuildPropsFile)' == ''">Directory.Build.props
+ <_DirectoryBuildPropsBasePath Condition="'$(_DirectoryBuildPropsBasePath)' == ''">$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), '$(_DirectoryBuildPropsFile)'))
+ $([System.IO.Path]::Combine('$(_DirectoryBuildPropsBasePath)', '$(_DirectoryBuildPropsFile)'))
+
+
+
+
+
+
+
+
+ true
+ $(MSBuildProjectName)
+
+
+ $(ArtifactsPath)\obj\$(ArtifactsProjectName)\
+ $(ArtifactsPath)\obj\
+
+
+
+ <_ArtifactsPathSetEarly>true
+
+
+
+
+
+ obj\
+ $(BaseIntermediateOutputPath)\
+ <_InitialBaseIntermediateOutputPath>$(BaseIntermediateOutputPath)
+ $(BaseIntermediateOutputPath)
+
+ $([System.IO.Path]::Combine('$(MSBuildProjectDirectory)', '$(MSBuildProjectExtensionsPath)'))
+ $(MSBuildProjectExtensionsPath)\
+
+ false
+ true
+ <_InitialMSBuildProjectExtensionsPath Condition=" '$(ImportProjectExtensionProps)' == 'true' ">$(MSBuildProjectExtensionsPath)
+
+
+
+ True
+ NuGet
+ $(MSBuildThisFileDirectory)project.assets.json
+ /Users/nible/.nuget/packages/
+ /Users/nible/.nuget/packages/
+ PackageReference
+ 6.12.2
+
+
+
+
+
+
+
+
+
+
+
+
+ <_MauiSkipSdkAutoImport>true
+
+
+
+
+
+ Designer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MSBuild:Compile
+ $(DefaultXamlRuntime)
+
+
+ MSBuild:Compile
+ $(DefaultXamlRuntime)
+
+
+ MSBuild:Compile
+ $(DefaultXamlRuntime)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(MSBuildExtensionsPath)\v$(MSBuildToolsVersion)\Custom.Before.$(MSBuildThisFile)
+ $(MSBuildExtensionsPath)\v$(MSBuildToolsVersion)\Custom.After.$(MSBuildThisFile)
+
+
+
+
+ true
+
+
+ $(DefaultProjectConfiguration)
+ $(DefaultProjectPlatform)
+
+
+ WJProject
+ JavaScript
+
+
+
+
+
+
+
+ $([MSBuild]::IsRunningFromVisualStudio())
+ $([MSBuild]::GetToolsDirectory32())\..\..\..\Common7\IDE\CommonExtensions\Microsoft\NuGet\NuGet.props
+ $(MSBuildToolsPath)\NuGet.props
+
+
+
+
+
+ true
+
+
+
+ <_DirectoryPackagesPropsFile Condition="'$(_DirectoryPackagesPropsFile)' == ''">Directory.Packages.props
+ <_DirectoryPackagesPropsBasePath Condition="'$(_DirectoryPackagesPropsBasePath)' == ''">$([MSBuild]::GetDirectoryNameOfFileAbove('$(MSBuildProjectDirectory)', '$(_DirectoryPackagesPropsFile)'))
+ $([MSBuild]::NormalizePath('$(_DirectoryPackagesPropsBasePath)', '$(_DirectoryPackagesPropsFile)'))
+
+
+
+ true
+
+
+
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+
+
+
+
+
+
+ true
+
+
+
+ Debug;Release
+ AnyCPU
+ Debug
+ AnyCPU
+
+
+
+
+ true
+
+
+
+ Library
+ 512
+ prompt
+ $(MSBuildProjectName)
+ $(MSBuildProjectName.Replace(" ", "_"))
+ true
+
+
+
+ true
+ false
+
+
+ true
+
+
+
+
+ <_PlatformWithoutConfigurationInference>$(Platform)
+
+
+ x64
+
+
+ x86
+
+
+ ARM
+
+
+ arm64
+
+
+
+
+ {CandidateAssemblyFiles}
+ $(AssemblySearchPaths);{HintPathFromItem}
+ $(AssemblySearchPaths);{TargetFrameworkDirectory}
+ $(AssemblySearchPaths);{RawFileName}
+
+
+ None
+ portable
+
+ false
+
+ true
+ true
+
+ PackageReference
+ $(AssemblySearchPaths)
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ false
+ true
+ 1.0.3
+ false
+ true
+ true
+
+
+
+
+
+ $(MSBuildThisFileDirectory)GenerateDeps\GenerateDeps.proj
+
+
+
+
+
+ $(MSBuildThisFileDirectory)..\..\..\Microsoft.NETCoreSdk.BundledVersions.props
+
+
+
+
+ $([MSBuild]::NormalizePath('$(MSBuildThisFileDirectory)../../'))
+ $([MSBuild]::EnsureTrailingSlash('$(NetCoreRoot)'))packs
+ <_NetFrameworkHostedCompilersVersion>4.12.0-3.24570.6
+ 9.0
+ 9.0
+ 9.0.0
+ 2.1
+ 2.1.0
+ 9.0.0-rtm.24528.9
+ $(MSBuildThisFileDirectory)RuntimeIdentifierGraph.json
+ 9.0.101
+ 9.0.100
+ osx-arm64
+ osx-arm64
+ <_NETCoreSdkIsPreview>false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_KnownRuntimeIdentiferPlatforms Include="any;aot;freebsd;illumos;solaris;unix;any;aot;freebsd;illumos;solaris;unix;any;aot;freebsd;illumos;solaris;unix;any;aot;freebsd;illumos;solaris;unix;any;aot;freebsd;illumos;solaris;unix;any;aot;freebsd;illumos;solaris;unix;any;aot;freebsd;illumos;solaris;unix;any;aot;freebsd;illumos;solaris;unix;any;aot;freebsd;illumos;solaris;unix;any;aot;freebsd;illumos;solaris;unix;any;aot;freebsd;illumos;solaris;unix;any;aot;freebsd;illumos;solaris;unix;any;aot;freebsd;illumos;solaris;unix;any;aot;freebsd;illumos;solaris;unix;any;aot;freebsd;illumos;solaris;unix" />
+ <_ExcludedKnownRuntimeIdentiferPlatforms Include="rhel.6;tizen.4.0.0;tizen.5.0.0;rhel.6;tizen.4.0.0;tizen.5.0.0;rhel.6;tizen.4.0.0;tizen.5.0.0;rhel.6;tizen.4.0.0;tizen.5.0.0;rhel.6;tizen.4.0.0;tizen.5.0.0;rhel.6;tizen.4.0.0;tizen.5.0.0;rhel.6;tizen.4.0.0;tizen.5.0.0;rhel.6;tizen.4.0.0;tizen.5.0.0;rhel.6;tizen.4.0.0;tizen.5.0.0;rhel.6;tizen.4.0.0;tizen.5.0.0;rhel.6;tizen.4.0.0;tizen.5.0.0;rhel.6;tizen.4.0.0;tizen.5.0.0;rhel.6;tizen.4.0.0;tizen.5.0.0;rhel.6;tizen.4.0.0;tizen.5.0.0;rhel.6;tizen.4.0.0;tizen.5.0.0;rhel.6;tizen.4.0.0;tizen.5.0.0" />
+
+
+
+ $(MSBuildThisFileDirectory)..\..\..\Microsoft.NETCoreSdk.BundledMSBuildInformation.props
+
+
+
+
+ 17.11.0
+ 17.12.12
+ <_MSBuildVersionMajorMinor>$([System.Version]::Parse('$(MSBuildVersion)').ToString(2))
+ <_IsDisjointMSBuildVersion>$([MSBuild]::VersionLessThan('$(_MSBuildVersionMajorMinor)', '17.12'))
+
+
+
+
+ false
+
+
+ <__WindowsAppSdkDefaultImageIncludes>**/*.png;**/*.bmp;**/*.jpg;**/*.dds;**/*.tif;**/*.tga;**/*.gif
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <__DisableWorkloadResolverSentinelPath Condition="'$(MSBuildRuntimeType)' == 'Core'">$(MSBuildBinPath)\DisableWorkloadResolver.sentinel
+ <__DisableWorkloadResolverSentinelPath Condition="'$(MSBuildRuntimeType)' != 'Core'">$(MSBuildToolsPath32)\SdkResolvers\Microsoft.DotNet.MSBuildSdkResolver\DisableWorkloadResolver.sentinel
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ false
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(Identity)'))
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(Identity)'))
+ false
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(Identity)'))
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(Identity)'))
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(Identity)'))
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(Identity)'))
+ true
+
+
+
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(Identity)'))
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ false
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ false
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ false
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(Identity)'))
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(Identity)'))
+ false
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(Identity)'))
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(Identity)'))
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(Identity)'))
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(Identity)'))
+ true
+
+
+
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(Identity)'))
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ false
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ false
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+ true
+
+
+
+ $([MSBuild]::MakeRelative ('$(MSBuildProjectDirectory)', '%(FullPath)'))
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 10.0
+ 17.16
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ <_SourceLinkPropsImported>true
+
+
+
+
+
+ $(MSBuildThisFileDirectory)..\tools\net472\Microsoft.Build.Tasks.Git.dll
+ $(MSBuildThisFileDirectory)..\tools\core\Microsoft.Build.Tasks.Git.dll
+
+
+
+
+
+ <_MicrosoftSourceLinkCommonAssemblyFile Condition="'$(MSBuildRuntimeType)' != 'Core'">$(MSBuildThisFileDirectory)..\tools\net472\Microsoft.SourceLink.Common.dll
+ <_MicrosoftSourceLinkCommonAssemblyFile Condition="'$(MSBuildRuntimeType)' == 'Core'">$(MSBuildThisFileDirectory)..\tools\core\Microsoft.SourceLink.Common.dll
+
+
+
+ true
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1701;1702
+
+ $(WarningsAsErrors);NU1605
+
+
+ $(DefineConstants);
+ $(DefineConstants)TRACE
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(TargetsForTfmSpecificContentInPackage);PackTool
+
+
+
+
+
+ $(TargetsForTfmSpecificContentInPackage);_PackProjectToolValidation
+
+
+
+
+
+ MSBuild:Compile
+ $(DefaultXamlRuntime)
+ Designer
+
+
+ MSBuild:Compile
+ $(DefaultXamlRuntime)
+ Designer
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_WpfCommonNetFxReference Include="WindowsBase" />
+ <_WpfCommonNetFxReference Include="PresentationCore" />
+ <_WpfCommonNetFxReference Include="PresentationFramework" />
+ <_WpfCommonNetFxReference Include="System.Xaml" Condition="'$(_TargetFrameworkVersionValue)' != '' And '$(_TargetFrameworkVersionValue)' >= '4.0'">
+ 4.0
+
+ <_WpfCommonNetFxReference Include="UIAutomationClient" Condition="'$(_TargetFrameworkVersionValue)' != '' And '$(_TargetFrameworkVersionValue)' >= '4.0'" />
+ <_WpfCommonNetFxReference Include="UIAutomationClientSideProviders" Condition="'$(_TargetFrameworkVersionValue)' != '' And '$(_TargetFrameworkVersionValue)' >= '4.0'" />
+ <_WpfCommonNetFxReference Include="UIAutomationProvider" Condition="'$(_TargetFrameworkVersionValue)' != '' And '$(_TargetFrameworkVersionValue)' >= '4.0'" />
+ <_WpfCommonNetFxReference Include="UIAutomationTypes" Condition="'$(_TargetFrameworkVersionValue)' != '' And '$(_TargetFrameworkVersionValue)' >= '4.0'" />
+ <_WpfCommonNetFxReference Include="System.Windows.Controls.Ribbon" Condition="'$(_TargetFrameworkVersionValue)' != '' And '$(_TargetFrameworkVersionValue)' >= '4.5'" />
+
+
+ <_SDKImplicitReference Include="@(_WpfCommonNetFxReference)" Condition="'$(UseWPF)' == 'true'" />
+ <_SDKImplicitReference Include="System.Windows.Forms" Condition="('$(UseWindowsForms)' == 'true') " />
+ <_SDKImplicitReference Include="WindowsFormsIntegration" Condition=" ('$(UseWindowsForms)' == 'true') And ('$(UseWPF)' == 'true') " />
+
+
+
+
+
+ <_UnsupportedNETCoreAppTargetFramework Include=".NETCoreApp,Version=v1.0" />
+ <_UnsupportedNETCoreAppTargetFramework Include=".NETCoreApp,Version=v1.1" />
+ <_UnsupportedNETCoreAppTargetFramework Include=".NETCoreApp,Version=v2.0" />
+ <_UnsupportedNETCoreAppTargetFramework Include=".NETCoreApp,Version=v2.1" />
+ <_UnsupportedNETCoreAppTargetFramework Include=".NETCoreApp,Version=v2.2" />
+
+ <_UnsupportedNETStandardTargetFramework Include="@(SupportedNETStandardTargetFramework)" />
+
+ <_UnsupportedNETFrameworkTargetFramework Include=".NETFramework,Version=v2.0" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+ <_TargetFrameworkVersionValue>0.0
+ <_WindowsDesktopSdkTargetFrameworkVersionFloor>3.0
+
+
+
+
+
+ net9.0
+ enable
+ enable
+ OpenMaui.Platform.Linux
+ OpenMaui.Controls.Linux
+ true
+ true
+ $(NoWarn);CS0108;CS1591;CS0618
+
+ OpenMaui.Controls.Linux
+ 1.0.0-preview.1
+ MarketAlly LLC, David H. Friedel Jr.
+ MarketAlly LLC
+ OpenMaui Linux Controls
+ Linux desktop support for .NET MAUI applications using SkiaSharp rendering. Supports X11 and Wayland display servers with 35+ controls, platform services, and accessibility support.
+ Copyright 2025 MarketAlly LLC
+ MIT
+ https://github.com/open-maui/maui-linux
+ https://github.com/open-maui/maui-linux.git
+ git
+ maui;linux;desktop;skia;gui;cross-platform;dotnet;x11;wayland;openmaui
+ Initial preview release with 35+ controls and full platform services.
+ README.md
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+ <_IsExecutable Condition="'$(OutputType)' == 'Exe' or '$(OutputType)'=='WinExe'">true
+
+
+ $(_IsExecutable)
+ <_UsingDefaultForHasRuntimeOutput>true
+
+
+
+
+ 1.0.0
+ $(VersionPrefix)-$(VersionSuffix)
+ $(VersionPrefix)
+
+
+ $(AssemblyName)
+ $(Authors)
+ $(AssemblyName)
+ $(AssemblyName)
+
+
+
+
+ Debug
+ AnyCPU
+ $(Platform)
+
+
+
+
+
+
+ true
+ <_PublishProfileDesignerFolder Condition="'$(AppDesignerFolder)' != ''">$(AppDesignerFolder)
+ <_PublishProfileDesignerFolder Condition="'$(_PublishProfileDesignerFolder)' == ''">Properties
+ <_PublishProfileRootFolder Condition="'$(_PublishProfileRootFolder)' == ''">$(MSBuildProjectDirectory)\$(_PublishProfileDesignerFolder)\PublishProfiles\
+ $([System.IO.Path]::GetFileNameWithoutExtension($(PublishProfile)))
+ $(_PublishProfileRootFolder)$(PublishProfileName).pubxml
+ $(PublishProfileFullPath)
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+ $([MSBuild]::GetTargetFrameworkIdentifier('$(TargetFramework)'))
+ v$([MSBuild]::GetTargetFrameworkVersion('$(TargetFramework)', 2))
+
+
+ <_TargetFrameworkVersionWithoutV>$(TargetFrameworkVersion.TrimStart('vV'))
+
+
+
+ $([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)'))
+ $([MSBuild]::GetTargetPlatformVersion('$(TargetFramework)', 4))
+ $([MSBuild]::GetTargetPlatformVersion('$(TargetFramework)', 2))
+
+
+ Windows
+
+
+
+ <_UnsupportedTargetFrameworkError>true
+
+
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ v0.0
+
+
+ _
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+ <_EnableDefaultWindowsPlatform>false
+ false
+
+
+ 2.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ApplicableTargetPlatformVersion Include="@(SdkSupportedTargetPlatformVersion)" Condition="'@(SdkSupportedTargetPlatformVersion)' != '' and '%(SdkSupportedTargetPlatformVersion.DefineConstantsOnly)' != 'true'" RemoveMetadata="DefineConstantsOnly" />
+ <_ValidTargetPlatformVersion Include="@(_ApplicableTargetPlatformVersion)" Condition="'@(_ApplicableTargetPlatformVersion)' != '' and $([MSBuild]::VersionEquals(%(Identity), $(TargetPlatformVersion)))" />
+
+
+ @(_ValidTargetPlatformVersion->Distinct())
+
+
+
+
+ true
+ <_ValidTargetPlatformVersions Condition="'@(_ApplicableTargetPlatformVersion)' != ''">@(_ApplicableTargetPlatformVersion, '%0a')
+ <_ValidTargetPlatformVersions Condition="'@(_ApplicableTargetPlatformVersion)' == ''">None
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+
+
+
+
+ true
+ false
+ true
+ <_PlatformToAppendToOutputPath Condition="'$(AppendPlatformToOutputPath)' == 'true'">$(PlatformName)\
+
+
+
+
+
+
+
+ <_DefaultArtifactsPathPropsImported>true
+
+
+
+ true
+ true
+ <_ArtifactsPathLocationType>ExplicitlySpecified
+
+
+
+
+ $(_DirectoryBuildPropsBasePath)\artifacts
+ true
+ <_ArtifactsPathLocationType>DirectoryBuildPropsFolder
+
+
+
+ $(MSBuildProjectDirectory)\artifacts
+ <_ArtifactsPathLocationType>ProjectFolder
+
+
+
+ $(MSBuildProjectName)
+ bin
+ publish
+ package
+
+
+ $(Configuration.ToLowerInvariant())
+
+ $(ArtifactsPivots)_$(TargetFramework.ToLowerInvariant())
+
+ $(ArtifactsPivots)_$(RuntimeIdentifier.ToLowerInvariant())
+
+
+
+ $(ArtifactsPath)\$(ArtifactsBinOutputName)\$(ArtifactsProjectName)\
+ $(ArtifactsPath)\obj\$(ArtifactsProjectName)\
+ $(ArtifactsPath)\$(ArtifactsPublishOutputName)\$(ArtifactsProjectName)\$(ArtifactsPivots)\
+
+
+
+ $(ArtifactsPath)\$(ArtifactsBinOutputName)\
+ $(ArtifactsPath)\obj\
+ $(ArtifactsPath)\$(ArtifactsPublishOutputName)\$(ArtifactsPivots)\
+
+
+ $(BaseOutputPath)$(ArtifactsPivots)\
+ $(BaseIntermediateOutputPath)$(ArtifactsPivots)\
+
+ $(ArtifactsPath)\$(ArtifactsPackageOutputName)\$(Configuration.ToLowerInvariant())\
+
+
+ bin\
+ $(BaseOutputPath)\
+ $(BaseOutputPath)$(_PlatformToAppendToOutputPath)$(Configuration)\
+ $(OutputPath)\
+
+
+
+ obj\
+ $(BaseIntermediateOutputPath)\
+ $(BaseIntermediateOutputPath)$(_PlatformToAppendToOutputPath)$(Configuration)\
+ $(IntermediateOutputPath)\
+
+
+
+ $(OutputPath)
+
+
+
+ $(DefaultItemExcludes);$(OutputPath)/**
+ $(DefaultItemExcludes);$(IntermediateOutputPath)/**
+
+
+ $(DefaultItemExcludes);$(ArtifactsPath)/**
+
+ $(DefaultItemExcludes);bin/**;obj/**
+
+
+
+ $(OutputPath)$(TargetFramework.ToLowerInvariant())\
+
+
+ $(IntermediateOutputPath)$(TargetFramework.ToLowerInvariant())\
+
+
+
+
+
+
+
+
+
+
+ true
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_RuntimePackInWorkloadVersionCurrent>9.0.11
+ <_RuntimePackInWorkloadVersion8>8.0.22
+ <_RuntimePackInWorkloadVersion7>7.0.20
+ <_RuntimePackInWorkloadVersion6>6.0.36
+ true
+
+ false
+ true
+
+
+ true
+ true
+ true
+
+ $(WasmNativeWorkload8)
+
+
+
+ <_BrowserWorkloadNotSupportedForTFM Condition="$([MSBuild]::VersionLessThan($(TargetFrameworkVersion), '6.0'))">true
+ <_BrowserWorkloadDisabled>$(_BrowserWorkloadNotSupportedForTFM)
+ <_UsingBlazorOrWasmSdk Condition="'$(UsingMicrosoftNETSdkBlazorWebAssembly)' == 'true' or '$(UsingMicrosoftNETSdkWebAssembly)' == 'true'">true
+
+
+ true
+ $(WasmNativeWorkload9)
+ $(WasmNativeWorkload8)
+ $(WasmNativeWorkload7)
+ $(WasmNativeWorkload)
+ false
+ $(WasmNativeWorkloadAvailable)
+
+
+
+
+
+ <_WasmPropertiesDifferFromRuntimePackThusNativeBuildNeeded Condition="
'$(WasmEnableSIMD)' == 'false' or
'$(WasmEnableExceptionHandling)' == 'false' or
'$(InvariantTimezone)' == 'true' or
('$(_UsingBlazorOrWasmSdk)' != 'true' and '$(InvariantGlobalization)' == 'true') or
'$(WasmNativeStrip)' == 'false'">true
+
+
+ <_WasmNativeWorkloadNeeded Condition="
'$(_WasmPropertiesDifferFromRuntimePackThusNativeBuildNeeded)' == 'true' or
'$(RunAOTCompilation)' == 'true' or
'$(WasmBuildNative)' == 'true' or
'$(WasmGenerateAppBundle)' == 'true' or
'$(_UsingBlazorOrWasmSdk)' != 'true' or
'$(EmccMaximumHeapSize)' != '' ">true
+ false
+ true
+ $(WasmNativeWorkloadAvailable)
+
+
+
+ <_IsAndroidLibraryMode Condition="'$(RuntimeIdentifier)' == 'android-arm64' or '$(RuntimeIdentifier)' == 'android-arm' or '$(RuntimeIdentifier)' == 'android-x64' or '$(RuntimeIdentifier)' == 'android-x86'">true
+ <_IsAppleMobileLibraryMode Condition="'$(RuntimeIdentifier)' == 'ios-arm64' or '$(RuntimeIdentifier)' == 'iossimulator-arm64' or '$(RuntimeIdentifier)' == 'iossimulator-x64' or '$(RuntimeIdentifier)' == 'maccatalyst-arm64' or '$(RuntimeIdentifier)' == 'maccatalyst-x64' or '$(RuntimeIdentifier)' == 'tvos-arm64'">true
+ <_IsiOSLibraryMode Condition="'$(RuntimeIdentifier)' == 'ios-arm64' or '$(RuntimeIdentifier)' == 'iossimulator-arm64' or '$(RuntimeIdentifier)' == 'iossimulator-x64'">true
+ <_IsMacCatalystLibraryMode Condition="'$(RuntimeIdentifier)' == 'maccatalyst-arm64' or '$(RuntimeIdentifier)' == 'maccatalyst-x64'">true
+ <_IstvOSLibraryMode Condition="'$(RuntimeIdentifier)' == 'tvos-arm64'">true
+
+
+ true
+
+
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_MonoWorkloadTargetsMobile>true
+ <_MonoWorkloadRuntimePackPackageVersion>$(_RuntimePackInWorkloadVersionCurrent)
+ <_KnownWebAssemblySdkPackVersion>$(_RuntimePackInWorkloadVersionCurrent)
+
+
+
+ true
+ 1.0
+
+
+
+
+
+
+ true
+ 1.0
+
+
+
+
+
+
+
+ %(RuntimePackRuntimeIdentifiers);wasi-wasm
+ $(_MonoWorkloadRuntimePackPackageVersion)
+
+ Microsoft.NETCore.App.Runtime.Mono.multithread.**RID**
+
+
+ $(_MonoWorkloadRuntimePackPackageVersion)
+
+
+ $(_KnownWebAssemblySdkPackVersion)
+ $(_KnownWebAssemblySdkPackVersion)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ <_NativeBuildNeeded Condition="'$(RunAOTCompilation)' == 'true'">true
+ WebAssembly workloads (required for AOT) are only supported for projects targeting net6.0+
+
+
+ true
+ $(WasmNativeWorkload)
+
+
+ 8.0
+ 9.0
+
+
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_MonoWorkloadTargetsMobile>true
+ <_MonoWorkloadRuntimePackPackageVersion>$(_RuntimePackInWorkloadVersion6)
+
+
+
+ $(_MonoWorkloadRuntimePackPackageVersion)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_MonoWorkloadTargetsMobile>true
+ <_MonoWorkloadRuntimePackPackageVersion>$(_RuntimePackInWorkloadVersion7)
+
+
+
+ $(_MonoWorkloadRuntimePackPackageVersion)
+
+ Microsoft.NETCore.App.Runtime.Mono.multithread.**RID**
+ Microsoft.NETCore.App.Runtime.Mono.perftrace.**RID**
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_MonoWorkloadTargetsMobile>true
+ <_MonoWorkloadRuntimePackPackageVersion>$(_RuntimePackInWorkloadVersion8)
+
+
+
+
+ %(RuntimePackRuntimeIdentifiers);wasi-wasm
+ $(_MonoWorkloadRuntimePackPackageVersion)
+
+ Microsoft.NETCore.App.Runtime.Mono.multithread.**RID**
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ResolvedSuggestedWorkload Include="@(SuggestedWorkload)" />
+ <_ResolvedSuggestedWorkload Include="@(SuggestedWorkloadFromReference)" />
+
+
+
+
+
+
+
+
+ <_UsingDefaultRuntimeIdentifier>true
+ win7-x64
+ win7-x86
+ win-x64
+ win-x86
+
+
+
+ true
+
+
+
+ $(PublishSelfContained)
+
+
+
+ true
+
+
+ $(NETCoreSdkPortableRuntimeIdentifier)
+
+
+ $(PublishRuntimeIdentifier)
+
+
+ <_UsingDefaultPlatformTarget>true
+
+
+
+
+
+
+ x86
+
+
+
+
+ x64
+
+
+
+
+ arm
+
+
+
+
+ arm64
+
+
+
+
+ AnyCPU
+
+
+
+
+
+
+ <_SelfContainedWasSpecified Condition="'$(SelfContained)' != ''">true
+
+
+
+ true
+ false
+ <_RuntimeIdentifierUsesAppHost Condition="$(RuntimeIdentifier.StartsWith('ios')) or $(RuntimeIdentifier.StartsWith('tvos')) or $(RuntimeIdentifier.StartsWith('maccatalyst')) or $(RuntimeIdentifier.StartsWith('android')) or $(RuntimeIdentifier.StartsWith('browser'))">false
+ <_RuntimeIdentifierUsesAppHost Condition="'$(_IsPublishing)' == 'true' and '$(PublishAot)' == 'true'">false
+ <_RuntimeIdentifierUsesAppHost Condition="'$(_RuntimeIdentifierUsesAppHost)' == ''">true
+ true
+ false
+
+
+
+ $(NETCoreSdkRuntimeIdentifier)
+ win-x64
+ win-x86
+ win-arm
+ win-arm64
+
+ $(DefaultAppHostRuntimeIdentifier.Replace("arm64", "x64"))
+
+ $(DefaultAppHostRuntimeIdentifier.Replace("arm64", "x64"))
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+ $(IntermediateOutputPath)$(RuntimeIdentifier)\
+ $(OutputPath)$(RuntimeIdentifier)\
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+ <_EolNetCoreTargetFrameworkVersions Include="1.0;1.1;2.0;2.1;2.2;3.0;3.1;5.0;7.0" />
+
+
+ <_MinimumNonEolSupportedNetCoreTargetFramework>net6.0
+
+
+
+
+
+
+
+
+
+
+ <_IsNETCoreOrNETStandard Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp'">true
+ <_IsNETCoreOrNETStandard Condition="'$(TargetFrameworkIdentifier)' == '.NETStandard'">true
+
+
+
+ true
+ true
+ true
+
+
+ true
+
+
+
+ true
+
+ true
+
+ .dll
+
+ false
+
+
+
+ $(PreserveCompilationContext)
+
+
+
+ publish
+
+ $(OutputPath)$(RuntimeIdentifier)\$(PublishDirName)\
+ $(OutputPath)$(PublishDirName)\
+
+
+
+
+
+ <_NugetFallbackFolder>$(MSBuildThisFileDirectory)..\..\..\..\NuGetFallbackFolder
+ <_IsNETCore1x Condition=" '$(TargetFrameworkIdentifier)' == '.NETCoreApp' and '$(_TargetFrameworkVersionWithoutV)' < '2.0' ">true
+ <_WorkloadLibraryPacksFolder Condition="'$(_WorkloadLibraryPacksFolder)' == ''">$([MSBuild]::EnsureTrailingSlash('$(NetCoreRoot)'))library-packs
+
+
+ $(RestoreAdditionalProjectSources);$(_NugetFallbackFolder)
+ $(RestoreAdditionalProjectFallbackFoldersExcludes);$(_NugetFallbackFolder)
+ $(RestoreAdditionalProjectFallbackFolders);$(_NugetFallbackFolder)
+
+
+ $(RestoreAdditionalProjectSources);$(_WorkloadLibraryPacksFolder)
+
+
+
+ <_SDKImplicitReference Include="System" />
+ <_SDKImplicitReference Include="System.Data" />
+ <_SDKImplicitReference Include="System.Drawing" />
+ <_SDKImplicitReference Include="System.Xml" />
+
+
+ <_SDKImplicitReference Include="System.Core" Condition=" '$(_TargetFrameworkVersionWithoutV)' >= '3.5' " />
+ <_SDKImplicitReference Include="System.Runtime.Serialization" Condition=" '$(_TargetFrameworkVersionWithoutV)' >= '3.5' " />
+ <_SDKImplicitReference Include="System.Xml.Linq" Condition=" '$(_TargetFrameworkVersionWithoutV)' >= '3.5' " />
+
+ <_SDKImplicitReference Include="System.Numerics" Condition=" '$(_TargetFrameworkVersionWithoutV)' >= '4.0' " />
+
+ <_SDKImplicitReference Include="System.IO.Compression.FileSystem" Condition=" '$(_TargetFrameworkVersionWithoutV)' >= '4.5' " />
+ <_SDKImplicitReference Update="@(_SDKImplicitReference)" Pack="false" IsImplicitlyDefined="true" />
+
+ <_SDKImplicitReference Remove="@(Reference)" />
+
+
+
+
+
+ false
+
+
+ $(AssetTargetFallback);net461;net462;net47;net471;net472;net48;net481
+
+
+
+ <_FrameworkIdentifierForImplicitDefine>$(TargetFrameworkIdentifier.Replace('.', '').ToUpperInvariant())
+ <_FrameworkIdentifierForImplicitDefine Condition=" '$(TargetFrameworkIdentifier)' == '.NETCoreApp' and $([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), 5.0)) ">NET
+ $(_FrameworkIdentifierForImplicitDefine)
+ <_FrameworkIdentifierForImplicitDefine Condition=" '$(TargetFrameworkIdentifier)' == '.NETFramework'">NET
+ <_FrameworkVersionForImplicitDefine>$(TargetFrameworkVersion.TrimStart('vV'))
+ <_FrameworkVersionForImplicitDefine>$(_FrameworkVersionForImplicitDefine.Replace('.', '_'))
+ <_FrameworkVersionForImplicitDefine Condition=" '$(TargetFrameworkIdentifier)' == '.NETFramework'">$(_FrameworkVersionForImplicitDefine.Replace('_', ''))
+ $(_FrameworkIdentifierForImplicitDefine)$(_FrameworkVersionForImplicitDefine)
+ $(TargetFrameworkIdentifier.Replace('.', '').ToUpperInvariant())
+
+
+
+
+ <_PlatformIdentifierForImplicitDefine>$(TargetPlatformIdentifier.ToUpperInvariant())
+ <_PlatformVersionForImplicitDefine>$(TargetPlatformVersion.Replace('.', '_'))
+
+
+ <_ImplicitDefineConstant Include="$(_PlatformIdentifierForImplicitDefine)" />
+ <_ImplicitDefineConstant Include="$(_PlatformIdentifierForImplicitDefine)$(_PlatformVersionForImplicitDefine)" />
+
+
+
+
+
+ <_SupportedFrameworkVersions Include="@(SupportedNETCoreAppTargetFramework->'%(Identity)'->TrimStart('.NETCoreApp,Version=v'))" Condition=" '$(TargetFrameworkIdentifier)' == '.NETCoreApp' " />
+ <_SupportedFrameworkVersions Include="@(SupportedNETFrameworkTargetFramework->'%(Identity)'->TrimStart('.NETFramework,Version=v'))" Condition=" '$(TargetFrameworkIdentifier)' == '.NETFramework' " />
+ <_SupportedFrameworkVersions Include="@(SupportedNETStandardTargetFramework->'%(Identity)'->TrimStart('.NETStandard,Version=v'))" Condition=" '$(TargetFrameworkIdentifier)' == '.NETStandard' " />
+ <_CompatibleFrameworkVersions Include="@(_SupportedFrameworkVersions)" Condition=" $([MSBuild]::VersionLessThanOrEquals(%(Identity), $(TargetFrameworkVersion))) " />
+ <_FormattedCompatibleFrameworkVersions Include="@(_CompatibleFrameworkVersions)" Condition=" '$(TargetFrameworkIdentifier)' == '.NETCoreApp' or '$(TargetFrameworkIdentifier)' == '.NETStandard' " />
+ <_FormattedCompatibleFrameworkVersions Include="@(_CompatibleFrameworkVersions->'%(Identity)'->Replace('.', ''))" Condition=" '$(TargetFrameworkIdentifier)' == '.NETFramework' " />
+ <_ImplicitDefineConstant Include="@(_FormattedCompatibleFrameworkVersions->'$(_FrameworkIdentifierForImplicitDefine)%(Identity)_OR_GREATER'->Replace('.', '_'))" Condition=" '$(TargetFrameworkIdentifier)' != '.NETCoreApp' or $([MSBuild]::VersionGreaterThanOrEquals(%(_FormattedCompatibleFrameworkVersions.Identity), 5.0)) " />
+ <_ImplicitDefineConstant Include="@(_FormattedCompatibleFrameworkVersions->'NETCOREAPP%(Identity)_OR_GREATER'->Replace('.', '_'))" Condition=" '$(TargetFrameworkIdentifier)' == '.NETCoreApp' and $([MSBuild]::VersionLessThan(%(_FormattedCompatibleFrameworkVersions.Identity), 5.0)) " />
+
+
+
+
+
+ <_SupportedPlatformCompatibleVersions Include="@(SdkSupportedTargetPlatformVersion)" Condition=" %(Identity) != '' and $([MSBuild]::VersionLessThanOrEquals(%(Identity), $(TargetPlatformVersion))) " />
+ <_ImplicitDefineConstant Include="@(_SupportedPlatformCompatibleVersions->Distinct()->'$(TargetPlatformIdentifier.ToUpper())%(Identity)_OR_GREATER'->Replace('.', '_'))" />
+
+
+
+
+
+ <_DefineConstantsWithoutTrace Include="$(DefineConstants)" />
+ <_DefineConstantsWithoutTrace Remove="TRACE" />
+
+
+ @(_DefineConstantsWithoutTrace)
+
+
+
+
+
+ $(DefineConstants);@(_ImplicitDefineConstant)
+ $(FinalDefineConstants),@(_ImplicitDefineConstant->'%(Identity)=-1', ',')
+
+
+
+
+ false
+ true
+
+
+ $(AssemblyName).xml
+ $(IntermediateOutputPath)$(AssemblyName).xml
+
+
+
+
+
+ true
+ true
+ true
+
+
+
+
+
+
+ true
+
+
+
+ $(MSBuildToolsPath)\Microsoft.CSharp.targets
+ $(MSBuildToolsPath)\Microsoft.VisualBasic.targets
+ $(MSBuildThisFileDirectory)..\targets\Microsoft.NET.Sdk.FSharpTargetsShim.targets
+
+ $(MSBuildToolsPath)\Microsoft.Common.targets
+
+
+
+
+
+
+
+ $(MSBuildToolsPath)\Microsoft.CSharp.CrossTargeting.targets
+
+
+
+
+ $(MSBuildToolsPath)\Microsoft.CSharp.CurrentVersion.targets
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+ true
+ true
+ true
+ true
+
+
+
+
+ $(MSBuildExtensionsPath)\v$(MSBuildToolsVersion)\Custom.Before.Microsoft.CSharp.targets
+ $(MSBuildExtensionsPath)\v$(MSBuildToolsVersion)\Custom.After.Microsoft.CSharp.targets
+
+
+
+ .cs
+ C#
+ Managed
+ true
+ true
+ true
+ true
+ true
+ {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ Properties
+
+
+
+
+ File
+
+
+ BrowseObject
+
+
+
+
+
+
+
+
+
+
+
+
+ <_Temporary Remove="@(_Temporary)" />
+
+
+
+
+
+
+
+
+
+
+
+
+ <_Temporary Remove="@(_Temporary)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+ <_DebugSymbolsIntermediatePathTemporary Include="$(PdbFile)" />
+
+ <_DebugSymbolsIntermediatePath Include="@(_DebugSymbolsIntermediatePathTemporary->'%(RootDir)%(Directory)%(Filename).pdb')" />
+
+
+ $(CoreCompileDependsOn);_ComputeNonExistentFileProperty;ResolveCodeAnalysisRuleSet
+ true
+
+
+
+
+
+ $(NoWarn);1701;1702
+
+
+
+ $(NoWarn);2008
+
+
+
+
+
+
+
+
+ $(AppConfig)
+
+ $(IntermediateOutputPath)$(TargetName).compile.pdb
+
+
+
+ false
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+ $(RoslynTargetsPath)\Microsoft.CSharp.Core.targets
+
+
+
+
+
+
+
+
+
+ roslyn4.12
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+ <_SkipAnalyzers />
+ <_ImplicitlySkipAnalyzers />
+
+
+
+ <_SkipAnalyzers>true
+
+
+
+ <_ImplicitlySkipAnalyzers>true
+ <_SkipAnalyzers>true
+ run-nullable-analysis=never;$(Features)
+
+
+
+
+
+ <_LastBuildWithSkipAnalyzers>$(IntermediateOutputPath)$(MSBuildProjectFile).BuildWithSkipAnalyzers
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_AllDirectoriesAbove Include="@(Compile->GetPathsOfAllDirectoriesAbove())" Condition="'$(DiscoverEditorConfigFiles)' != 'false' or '$(DiscoverGlobalAnalyzerConfigFiles)' != 'false'" />
+
+
+
+
+
+
+
+
+
+
+
+ $(IntermediateOutputPath)$(MSBuildProjectName).GeneratedMSBuildEditorConfig.editorconfig
+ true
+ <_GeneratedEditorConfigHasItems Condition="'@(CompilerVisibleItemMetadata->Count())' != '0'">true
+ <_GeneratedEditorConfigShouldRun Condition="'$(GenerateMSBuildEditorConfigFile)' == 'true' and ('$(_GeneratedEditorConfigHasItems)' == 'true' or '@(CompilerVisibleProperty->Count())' != '0')">true
+
+
+
+
+
+ <_GeneratedEditorConfigProperty Include="@(CompilerVisibleProperty)">
+ $(%(CompilerVisibleProperty.Identity))
+
+
+ <_GeneratedEditorConfigMetadata Include="@(%(CompilerVisibleItemMetadata.Identity))" Condition="'$(_GeneratedEditorConfigHasItems)' == 'true'">
+ %(Identity)
+ %(CompilerVisibleItemMetadata.MetadataName)
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+ <_MappedSourceRoot Remove="@(_MappedSourceRoot)" />
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+ <_TopLevelSourceRoot Include="@(SourceRoot)" Condition="'%(SourceRoot.NestedRoot)' == ''">
+ $([MSBuild]::ValueOrDefault('%(Identity)', '').Replace(',', ',,').Replace('=', '=='))
+ $([MSBuild]::ValueOrDefault('%(MappedPath)', '').Replace(',', ',,').Replace('=', '=='))
+
+
+
+
+ @(_TopLevelSourceRoot->'%(EscapedKey)=%(EscapedValue)', ','),$(PathMap)
+
+
+
+
+
+
+
+
+
+
+ false
+
+ $(IntermediateOutputPath)/generated
+
+
+
+
+
+
+
+
+
+
+
+
+ <_MaxSupportedLangVersion Condition="('$(TargetFrameworkIdentifier)' != '.NETCoreApp' OR '$(_TargetFrameworkVersionWithoutV)' < '3.0') AND
('$(TargetFrameworkIdentifier)' != '.NETStandard' OR '$(_TargetFrameworkVersionWithoutV)' < '2.1')">7.3
+
+ <_MaxSupportedLangVersion Condition="(('$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND '$(_TargetFrameworkVersionWithoutV)' < '5.0') OR
('$(TargetFrameworkIdentifier)' == '.NETStandard' AND '$(_TargetFrameworkVersionWithoutV)' == '2.1')) AND
'$(_MaxSupportedLangVersion)' == ''">8.0
+
+ <_MaxSupportedLangVersion Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND '$(_TargetFrameworkVersionWithoutV)' == '5.0' AND
'$(_MaxSupportedLangVersion)' == ''">9.0
+
+ <_MaxSupportedLangVersion Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND '$(_TargetFrameworkVersionWithoutV)' == '6.0' AND
'$(_MaxSupportedLangVersion)' == ''">10.0
+
+ <_MaxSupportedLangVersion Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND '$(_TargetFrameworkVersionWithoutV)' == '7.0' AND
'$(_MaxSupportedLangVersion)' == ''">11.0
+
+ <_MaxSupportedLangVersion Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND '$(_TargetFrameworkVersionWithoutV)' == '8.0' AND
'$(_MaxSupportedLangVersion)' == ''">12.0
+
+ <_MaxSupportedLangVersion Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' AND '$(_TargetFrameworkVersionWithoutV)' == '9.0' AND
'$(_MaxSupportedLangVersion)' == ''">13.0
+ $(_MaxSupportedLangVersion)
+ $(_MaxSupportedLangVersion)
+
+
+
+
+ $(NoWarn);1701;1702
+
+
+
+ $(NoWarn);2008
+
+
+
+ $(AppConfig)
+
+ $(IntermediateOutputPath)$(TargetName).compile.pdb
+
+
+
+
+
+
+ <_CoreCompileResourceInputs Remove="@(_CoreCompileResourceInputs)" />
+
+
+
+
+
+ -langversion:$(LangVersion)
+ $(CommandLineArgsForDesignTimeEvaluation) -checksumalgorithm:$(ChecksumAlgorithm)
+ $(CommandLineArgsForDesignTimeEvaluation) -define:$(DefineConstants)
+
+
+
+
+
+ $(MSBuildExtensionsPath)\Microsoft\VisualStudio\Managed\Microsoft.CSharp.DesignTime.targets
+
+
+
+
+
+ $(MSBuildToolsPath)\Microsoft.Common.CurrentVersion.targets
+
+
+
+
+
+ true
+ true
+ true
+ true
+
+
+
+
+
+
+ 10.0
+
+
+ $(MSBuildExtensionsPath)\v$(MSBuildToolsVersion)\Custom.Before.Microsoft.Common.targets
+ $(MSBuildExtensionsPath)\v$(MSBuildToolsVersion)\Custom.After.Microsoft.Common.targets
+ $(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\ReportingServices\Microsoft.ReportingServices.targets
+
+
+
+
+ Managed
+
+
+
+ .NETFramework
+ v4.0
+
+
+
+ Any CPU,x86,x64,Itanium
+ Any CPU,x86,x64
+
+
+
+
+
+
+
+ $(SDK40ToolsPath)
+
+
+
+ true
+
+
+ false
+
+
+
+
+ true
+
+ true
+
+
+ $(TargetFrameworkIdentifier),Version=$(TargetFrameworkVersion),Profile=$(TargetFrameworkProfile)
+ $(TargetFrameworkIdentifier),Version=$(TargetFrameworkVersion)
+
+ $(TargetFrameworkRootPath)$(TargetFrameworkIdentifier)\$(TargetFrameworkVersion)
+
+ $([Microsoft.Build.Utilities.ToolLocationHelper]::GetPathToStandardLibraries($(TargetFrameworkIdentifier), $(TargetFrameworkVersion), $(TargetFrameworkProfile), $(PlatformTarget), $(TargetFrameworkRootPath), $(TargetFrameworkFallbackSearchPaths)))
+ $(MSBuildFrameworkToolsPath)
+
+
+ Windows
+ 7.0
+ $(TargetPlatformSdkRootOverride)\
+ $([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\Software\Microsoft\Microsoft SDKs\Windows\v$(TargetPlatformVersion)', InstallationFolder, null, RegistryView.Registry32, RegistryView.Default))
+ $([Microsoft.Build.Utilities.ToolLocationHelper]::GetPlatformSDKLocation($(TargetPlatformIdentifier), $(TargetPlatformVersion)))
+ $(TargetPlatformSdkPath)Windows Metadata
+ $(TargetPlatformSdkPath)References\CommonConfiguration\Neutral
+ $(TargetPlatformSdkMetadataLocation)
+ true
+ $(WinDir)\System32\WinMetadata
+ $(TargetPlatformIdentifier),Version=$(TargetPlatformVersion)
+ $([Microsoft.Build.Utilities.ToolLocationHelper]::GetPlatformSDKDisplayName($(TargetPlatformIdentifier), $(TargetPlatformVersion)))
+
+
+
+
+ <_OriginalPlatform>$(Platform)
+
+ <_OriginalConfiguration>$(Configuration)
+
+ <_OutputPathWasMissing Condition="'$(_OriginalPlatform)' != '' and '$(_OriginalConfiguration)' != '' and '$(OutputPath)' == ''">true
+
+ true
+
+
+ AnyCPU
+ $(Platform)
+ Debug
+ $(Configuration)
+ bin\
+ $(BaseOutputPath)\
+ $(BaseOutputPath)$(Configuration)\
+ $(BaseOutputPath)$(PlatformName)\$(Configuration)\
+ $(OutputPath)\
+ obj\
+ $(BaseIntermediateOutputPath)\
+ $(BaseIntermediateOutputPath)$(Configuration)\
+ $(BaseIntermediateOutputPath)$(PlatformName)\$(Configuration)\
+ $(IntermediateOutputPath)\
+
+
+
+ $(TargetType)
+ library
+ exe
+ true
+
+ <_DebugSymbolsProduced>false
+ <_DebugSymbolsProduced Condition="'$(DebugSymbols)'=='true'">true
+ <_DebugSymbolsProduced Condition="'$(DebugType)'=='none'">false
+ <_DebugSymbolsProduced Condition="'$(DebugType)'=='pdbonly'">true
+ <_DebugSymbolsProduced Condition="'$(DebugType)'=='full'">true
+ <_DebugSymbolsProduced Condition="'$(DebugType)'=='portable'">true
+ <_DebugSymbolsProduced Condition="'$(DebugType)'=='embedded'">false
+ <_DebugSymbolsProduced Condition="'$(ProduceOnlyReferenceAssembly)'=='true'">false
+
+ <_DocumentationFileProduced>true
+ <_DocumentationFileProduced Condition="'$(DocumentationFile)'==''">false
+
+ false
+
+
+
+
+ <_InvalidConfigurationError Condition=" '$(SkipInvalidConfigurations)' != 'true' ">true
+ <_InvalidConfigurationWarning Condition=" '$(SkipInvalidConfigurations)' == 'true' ">true
+
+
+
+ .exe
+ .exe
+ .exe
+ .dll
+ .netmodule
+ .winmdobj
+
+
+
+ true
+ $(OutputPath)
+
+
+ $(OutDir)\
+ $(MSBuildProjectName)
+
+
+ $(OutDir)$(ProjectName)\
+ $(MSBuildProjectName)
+ $(RootNamespace)
+ $(AssemblyName)
+
+ $(MSBuildProjectFile)
+
+ $(MSBuildProjectExtension)
+
+ $(TargetName).winmd
+ $(WinMDExpOutputWindowsMetadataFilename)
+ $(TargetName)$(TargetExt)
+
+
+
+
+ <_DeploymentPublishableProjectDefault Condition="'$(OutputType)'=='winexe' or '$(OutputType)'=='exe' or '$(OutputType)'=='appcontainerexe'">true
+ $(_DeploymentPublishableProjectDefault)
+ <_DeploymentTargetApplicationManifestFileName Condition="'$(OutputType)'=='library'">Native.$(AssemblyName).manifest
+
+ <_DeploymentTargetApplicationManifestFileName Condition="'$(OutputType)'=='winexe'">$(TargetFileName).manifest
+
+ <_DeploymentTargetApplicationManifestFileName Condition="'$(OutputType)'=='exe'">$(TargetFileName).manifest
+
+ <_DeploymentTargetApplicationManifestFileName Condition="'$(OutputType)'=='appcontainerexe'">$(TargetFileName).manifest
+
+ $(AssemblyName).application
+
+ $(AssemblyName).xbap
+
+ $(GenerateManifests)
+ <_DeploymentApplicationManifestIdentity Condition="'$(OutputType)'=='library'">Native.$(AssemblyName)
+ <_DeploymentApplicationManifestIdentity Condition="'$(OutputType)'=='winexe'">$(AssemblyName).exe
+ <_DeploymentApplicationManifestIdentity Condition="'$(OutputType)'=='exe'">$(AssemblyName).exe
+ <_DeploymentApplicationManifestIdentity Condition="'$(OutputType)'=='appcontainerexe'">$(AssemblyName).exe
+ <_DeploymentDeployManifestIdentity Condition="'$(HostInBrowser)' != 'true'">$(AssemblyName).application
+ <_DeploymentDeployManifestIdentity Condition="'$(HostInBrowser)' == 'true'">$(AssemblyName).xbap
+ <_DeploymentFileMappingExtension Condition="'$(MapFileExtensions)'=='true'">.deploy
+ <_DeploymentFileMappingExtension Condition="'$(MapFileExtensions)'!='true'" />
+ <_DeploymentBuiltUpdateInterval Condition="'$(UpdatePeriodically)'=='true'">$(UpdateInterval)
+ <_DeploymentBuiltUpdateIntervalUnits Condition="'$(UpdatePeriodically)'=='true'">$(UpdateIntervalUnits)
+ <_DeploymentBuiltUpdateInterval Condition="'$(UpdatePeriodically)'!='true'">0
+ <_DeploymentBuiltUpdateIntervalUnits Condition="'$(UpdatePeriodically)'!='true'">Days
+ <_DeploymentBuiltMinimumRequiredVersion Condition="'$(UpdateRequired)'=='true' and '$(Install)'=='true'">$(MinimumRequiredVersion)
+ <_DeploymentLauncherBased Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp'">true
+ 100
+
+
+
+ *
+ $(UICulture)
+
+
+
+ <_OutputPathItem Include="$(OutDir)" />
+ <_UnmanagedRegistrationCache Include="$(BaseIntermediateOutputPath)$(MSBuildProjectFile).UnmanagedRegistration.cache" />
+ <_ResolveComReferenceCache Include="$(IntermediateOutputPath)$(MSBuildProjectFile).ResolveComReference.cache" />
+
+
+
+
+ $([MSBuild]::Escape($([System.IO.Path]::GetFullPath(`$([System.IO.Path]::Combine(`$(MSBuildProjectDirectory)`, `$(OutDir)`))`))))
+
+ $(TargetDir)$(TargetFileName)
+ $([MSBuild]::NormalizePath($(TargetDir), 'ref', $(TargetFileName)))
+ $([MSBuild]::NormalizePath($(MSBuildProjectDirectory), $(IntermediateOutputPath), 'ref', $(TargetFileName)))
+
+ $([MSBuild]::EnsureTrailingSlash($(MSBuildProjectDirectory)))
+
+ $(ProjectDir)$(ProjectFileName)
+
+
+
+
+
+
+
+ *Undefined*
+ *Undefined*
+
+ *Undefined*
+
+ *Undefined*
+
+ *Undefined*
+
+ *Undefined*
+
+
+
+ true
+
+ true
+
+
+ true
+ false
+
+
+ $(MSBuildProjectFile).FileListAbsolute.txt
+
+ false
+
+ true
+ true
+ <_ResolveReferenceDependencies Condition="'$(_ResolveReferenceDependencies)' == ''">false
+ <_GetChildProjectCopyToOutputDirectoryItems Condition="'$(_GetChildProjectCopyToOutputDirectoryItems)' == ''">true
+ false
+ false
+
+
+ <_GenerateBindingRedirectsIntermediateAppConfig>$(IntermediateOutputPath)$(TargetFileName).config
+
+
+ $(MSBuildProjectFile)
+
+ $([MSBuild]::SubstringByAsciiChars($(MSBuildProjectFile), 0, 8)).$([MSBuild]::StableStringHash($(MSBuildProjectFile)).ToString("X8"))
+ $(MSBuildCopyMarkerName).Up2Date
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_DebugSymbolsIntermediatePath Include="$(IntermediateOutputPath)$(TargetName).compile.pdb" Condition="'$(OutputType)' == 'winmdobj' and '@(_DebugSymbolsIntermediatePath)' == ''" />
+ <_DebugSymbolsIntermediatePath Include="$(IntermediateOutputPath)$(TargetName).pdb" Condition="'$(OutputType)' != 'winmdobj' and '@(_DebugSymbolsIntermediatePath)' == ''" />
+ <_DebugSymbolsOutputPath Include="@(_DebugSymbolsIntermediatePath->'$(OutDir)%(Filename)%(Extension)')" />
+
+
+ $(IntermediateOutputPath)$(TargetName).pdb
+ <_WinMDDebugSymbolsOutputPath>$([System.IO.Path]::Combine('$(OutDir)', $([System.IO.Path]::GetFileName('$(WinMDExpOutputPdb)'))))
+
+
+ $(IntermediateOutputPath)$(TargetName).xml
+ <_WinMDDocFileOutputPath>$([System.IO.Path]::Combine('$(OutDir)', $([System.IO.Path]::GetFileName('$(WinMDOutputDocumentationFile)'))))
+
+
+ <_IntermediateWindowsMetadataPath>$(IntermediateOutputPath)$(WinMDExpOutputWindowsMetadataFilename)
+ <_WindowsMetadataOutputPath>$(OutDir)$(WinMDExpOutputWindowsMetadataFilename)
+
+
+
+ <_SupportedArchitectures>amd64 arm64
+
+
+
+ <_DeploymentManifestEntryPoint Include="@(IntermediateAssembly)">
+ $(TargetFileName)
+
+
+
+ <_DeploymentManifestIconFile Include="$(ApplicationIcon)" Condition="Exists('$(ApplicationIcon)')">
+ $(ApplicationIcon)
+
+
+
+ $(_DeploymentTargetApplicationManifestFileName)
+
+
+ <_ApplicationManifestFinal Include="$(OutDir)$(_DeploymentTargetApplicationManifestFileName)">
+ $(_DeploymentTargetApplicationManifestFileName)
+
+
+
+ $(TargetDeployManifestFileName)
+
+
+ <_DeploymentIntermediateTrustInfoFile Include="$(IntermediateOutputPath)$(TargetName).TrustInfo.xml" Condition="'$(TargetZone)'!=''" />
+
+
+
+ <_DeploymentUrl Condition="'$(_DeploymentUrl)'==''">$(UpdateUrl)
+ <_DeploymentUrl Condition="'$(_DeploymentUrl)'==''">$(InstallUrl)
+ <_DeploymentUrl Condition="'$(_DeploymentUrl)'==''">$(PublishUrl)
+ <_DeploymentUrl Condition="!('$(UpdateUrl)'=='') and '$(Install)'=='false'" />
+ <_DeploymentUrl Condition="'$(_DeploymentUrl)'!=''">$(_DeploymentUrl)$(TargetDeployManifestFileName)
+
+ <_DeploymentUrl Condition="'$(UpdateUrl)'=='' and !('$(Install)'=='true' and '$(UpdateEnabled)'=='true')" />
+ <_DeploymentUrl Condition="'$(ExcludeDeploymentUrl)'=='true'" />
+
+
+
+ <_DeploymentApplicationUrl Condition="'$(IsWebBootstrapper)'=='true'">$(InstallUrl)
+ <_DeploymentApplicationUrl Condition="'$(IsWebBootstrapper)'=='true' and '$(InstallUrl)'==''">$(PublishUrl)
+ <_DeploymentComponentsUrl Condition="'$(BootstrapperComponentsLocation)'=='Absolute'">$(BootstrapperComponentsUrl)
+
+
+
+ $(PublishDir)\
+ $(OutputPath)app.publish\
+
+
+
+ $(PublishDir)
+ $(ClickOncePublishDir)\
+
+
+
+
+ $(PlatformTarget)
+
+ msil
+ amd64
+ ia64
+ x86
+ arm
+
+
+ true
+
+
+
+ $(Platform)
+ msil
+ amd64
+ ia64
+ x86
+ arm
+
+ None
+ $(PROCESSOR_ARCHITECTURE)
+
+
+
+ CLR2
+ CLR4
+ CurrentRuntime
+ true
+ false
+ $(PlatformTarget)
+ x86
+ x64
+ CurrentArchitecture
+
+
+
+ Client
+
+
+
+ false
+
+
+
+
+ true
+ true
+ false
+
+
+
+ AssemblyFoldersEx
+ Software\Microsoft\$(TargetFrameworkIdentifier)
+ Software\Microsoft\Microsoft SDKs\$(TargetPlatformIdentifier)
+ $([MSBuild]::GetToolsDirectory32())\AssemblyFolders.config
+ {AssemblyFoldersFromConfig:$(AssemblyFoldersConfigFile),$(TargetFrameworkVersion)};
+
+
+ .winmd;
+ .dll;
+ .exe
+
+
+
+ .pdb;
+ .xml;
+ .pri;
+ .dll.config;
+ .exe.config
+
+
+ Full
+
+
+
+ {CandidateAssemblyFiles}
+ $(AssemblySearchPaths);$(ReferencePath)
+ $(AssemblySearchPaths);{HintPathFromItem}
+ $(AssemblySearchPaths);{TargetFrameworkDirectory}
+ $(AssemblySearchPaths);$(AssemblyFoldersConfigFileSearchPath)
+ $(AssemblySearchPaths);{Registry:$(FrameworkRegistryBase),$(TargetFrameworkVersion),$(AssemblyFoldersSuffix)$(AssemblyFoldersExConditions)}
+ $(AssemblySearchPaths);{AssemblyFolders}
+ $(AssemblySearchPaths);{GAC}
+ $(AssemblySearchPaths);{RawFileName}
+ $(AssemblySearchPaths);$(OutDir)
+
+
+
+ false
+
+
+
+ $(NoWarn)
+ $(WarningsAsErrors)
+ $(WarningsNotAsErrors)
+
+
+
+ $(MSBuildThisFileDirectory)$(LangName)\
+
+
+
+ $(MSBuildThisFileDirectory)en-US\
+
+
+
+
+ Project
+
+
+ BrowseObject
+
+
+ File
+
+
+ Invisible
+
+
+ File;BrowseObject
+
+
+ File;ProjectSubscriptionService
+
+
+
+ $(DefineCommonItemSchemas)
+
+
+
+
+ ;BrowseObject
+
+
+ ProjectSubscriptionService;BrowseObject
+
+
+
+ ;BrowseObject
+
+
+ ProjectSubscriptionService;BrowseObject
+
+
+
+ ;BrowseObject
+
+
+ ProjectSubscriptionService;BrowseObject
+
+
+
+
+
+
+
+
+ Never
+
+
+ Never
+
+
+ Never
+
+
+ Never
+
+
+
+
+
+ true
+
+
+
+
+ <_GlobalPropertiesToRemoveFromProjectReferences Condition="'$(PassOutputPathToReferencedProjects)'=='false'">$(_GlobalPropertiesToRemoveFromProjectReferences);OutputPath
+
+
+
+
+
+ <_InvalidConfigurationMessageText>The BaseOutputPath/OutputPath property is not set for project '$(MSBuildProjectFile)'. Please check to make sure that you have specified a valid combination of Configuration and Platform for this project. Configuration='$(_OriginalConfiguration)' Platform='$(_OriginalPlatform)'.
+ <_InvalidConfigurationMessageText Condition="'$(BuildingInsideVisualStudio)' == 'true'">$(_InvalidConfigurationMessageText) This error may also appear if some other project is trying to follow a project-to-project reference to this project, this project has been unloaded or is not included in the solution, and the referencing project does not build using the same or an equivalent Configuration or Platform.
+ <_InvalidConfigurationMessageText Condition="'$(BuildingInsideVisualStudio)' != 'true'">$(_InvalidConfigurationMessageText) You may be seeing this message because you are trying to build a project without a solution file, and have specified a non-default Configuration or Platform that doesn't exist for this project.
+
+
+
+
+
+
+
+
+
+
+
+ x86
+
+
+
+
+
+
+
+
+
+
+
+
+ BeforeBuild;
+ CoreBuild;
+ AfterBuild
+
+
+
+
+
+
+
+
+
+
+ BuildOnlySettings;
+ PrepareForBuild;
+ PreBuildEvent;
+ ResolveReferences;
+ PrepareResources;
+ ResolveKeySource;
+ Compile;
+ ExportWindowsMDFile;
+ UnmanagedUnregistration;
+ GenerateSerializationAssemblies;
+ CreateSatelliteAssemblies;
+ GenerateManifests;
+ GetTargetPath;
+ PrepareForRun;
+ UnmanagedRegistration;
+ IncrementalClean;
+ PostBuildEvent
+
+
+
+
+
+
+
+
+ <_ProjectDefaultTargets Condition="'$(MSBuildProjectDefaultTargets)' != ''">$(MSBuildProjectDefaultTargets)
+ <_ProjectDefaultTargets Condition="'$(MSBuildProjectDefaultTargets)' == ''">Build
+
+ BeforeRebuild;
+ Clean;
+ $(_ProjectDefaultTargets);
+ AfterRebuild;
+
+
+ BeforeRebuild;
+ Clean;
+ Build;
+ AfterRebuild;
+
+
+
+
+
+
+
+
+
+ Build
+
+
+
+
+
+
+
+
+
+
+ Build
+
+
+
+
+
+
+
+
+
+
+ Build
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+ true
+
+
+
+
+
+ $(PrepareForBuildDependsOn);GetFrameworkPaths;GetReferenceAssemblyPaths;AssignLinkMetadata
+
+
+
+
+ $(TargetFileName).config
+
+
+
+
+
+
+
+
+
+
+
+
+ @(_TargetFramework40DirectoryItem)
+ @(_TargetFramework35DirectoryItem)
+ @(_TargetFramework30DirectoryItem)
+ @(_TargetFramework20DirectoryItem)
+
+ @(_TargetFramework20DirectoryItem)
+ @(_TargetFramework40DirectoryItem)
+ @(_TargetedFrameworkDirectoryItem)
+ @(_TargetFrameworkSDKDirectoryItem)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(_TargetFrameworkDirectories);$(TargetFrameworkDirectory);$(WinFXAssemblyDirectory)
+ $(TargetFrameworkDirectory);$(TargetPlatformWinMDLocation)
+
+
+
+ true
+
+
+ $(AssemblySearchPaths.Replace('{AssemblyFolders}', '').Split(';'))
+
+
+
+
+
+
+ $(TargetFrameworkDirectory);@(DesignTimeFacadeDirectories)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_Temp Remove="@(_Temp)" />
+
+
+
+
+
+
+
+
+ <_Temp Remove="@(_Temp)" />
+
+
+
+
+
+
+
+
+ <_Temp Remove="@(_Temp)" />
+
+
+
+
+
+
+
+
+ <_Temp Remove="@(_Temp)" />
+
+
+
+
+
+
+
+
+ <_Temp Remove="@(_Temp)" />
+
+
+
+
+
+
+
+
+ <_Temp Remove="@(_Temp)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(PlatformTargetAsMSBuildArchitecture)
+
+
+
+ $(TargetFrameworkAsMSBuildRuntime)
+
+ CurrentRuntime
+
+
+
+
+
+
+
+
+
+ BeforeResolveReferences;
+ AssignProjectConfiguration;
+ ResolveProjectReferences;
+ FindInvalidProjectReferences;
+ ResolveNativeReferences;
+ ResolveAssemblyReferences;
+ GenerateBindingRedirects;
+ GenerateBindingRedirectsUpdateAppConfig;
+ ResolveComReferences;
+ AfterResolveReferences
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+ true
+ true
+ false
+
+ false
+
+ true
+
+
+
+
+
+
+
+
+
+
+ <_ProjectReferenceWithConfiguration>
+ true
+ true
+
+
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+ <_MSBuildProjectReference Include="@(ProjectReferenceWithConfiguration)" Condition="'$(BuildingInsideVisualStudio)'!='true' and '@(ProjectReferenceWithConfiguration)'!=''" />
+
+
+
+ <_MSBuildProjectReferenceExistent Include="@(_MSBuildProjectReference)" Condition="Exists('%(Identity)')" />
+ <_MSBuildProjectReferenceNonexistent Include="@(_MSBuildProjectReference)" Condition="!Exists('%(Identity)')" />
+
+
+
+
+ true
+
+
+
+
+
+ <_MSBuildProjectReferenceExistent Condition="'%(_MSBuildProjectReferenceExistent.SetPlatform)' != ''">
+ true
+
+
+
+ <_ProjectReferencePlatformPossibilities Include="@(_MSBuildProjectReferenceExistent)" Condition="'%(_MSBuildProjectReferenceExistent.SkipGetPlatformProperties)' != 'true'" />
+
+
+
+
+ <_ProjectReferencePlatformPossibilities Condition="'$(MSBuildProjectExtension)' != '.vcxproj' and '$(MSBuildProjectExtension)' != '.nativeproj' and '%(_ProjectReferencePlatformPossibilities.IsVcxOrNativeProj)' == 'true'">
+
+ x86=Win32
+
+
+ <_ProjectReferencePlatformPossibilities Condition="('$(MSBuildProjectExtension)' == '.vcxproj' or '$(MSBuildProjectExtension)' == '.nativeproj') and '%(_ProjectReferencePlatformPossibilities.IsVcxOrNativeProj)' != 'true'">
+ Win32=x86
+
+
+
+
+
+
+
+
+
+ Platform=%(ProjectsWithNearestPlatform.NearestPlatform)
+
+
+
+ %(ProjectsWithNearestPlatform.UndefineProperties);Platform
+
+ <_MSBuildProjectReferenceExistent Remove="@(_MSBuildProjectReferenceExistent)" Condition="'%(_MSBuildProjectReferenceExistent.SkipGetPlatformProperties)' != 'true'" />
+ <_MSBuildProjectReferenceExistent Include="@(ProjectsWithNearestPlatform)" />
+
+
+
+
+
+
+ $(NuGetTargetMoniker)
+ $(TargetFrameworkMoniker)
+
+
+
+ <_MSBuildProjectReferenceExistent Condition="'%(_MSBuildProjectReferenceExistent.SkipGetTargetFrameworkProperties)' == '' and ('%(Extension)' == '.vcxproj' or '%(Extension)' == '.nativeproj')">
+
+ true
+ %(_MSBuildProjectReferenceExistent.UndefineProperties);TargetFramework
+
+
+
+
+ <_MSBuildProjectReferenceExistent Condition="'%(_MSBuildProjectReferenceExistent.SetTargetFramework)' != ''">
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectReferenceTargetFrameworkPossibilitiesOriginalItemSpec Include="@(_ProjectReferenceTargetFrameworkPossibilities->'%(OriginalItemSpec)')" />
+ <_ProjectReferenceTargetFrameworkPossibilities Remove="@(_ProjectReferenceTargetFrameworkPossibilities)" />
+ <_ProjectReferenceTargetFrameworkPossibilities Include="@(_ProjectReferenceTargetFrameworkPossibilitiesOriginalItemSpec)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TargetFramework=%(AnnotatedProjects.NearestTargetFramework)
+
+
+
+ %(AnnotatedProjects.UndefineProperties);TargetFramework
+
+
+
+ %(AnnotatedProjects.UndefineProperties);RuntimeIdentifier;SelfContained
+
+
+ <_MSBuildProjectReferenceExistent Remove="@(_MSBuildProjectReferenceExistent)" Condition="'%(_MSBuildProjectReferenceExistent.SkipGetTargetFrameworkProperties)' != 'true'" />
+ <_MSBuildProjectReferenceExistent Include="@(AnnotatedProjects)" />
+
+
+
+
+
+
+
+
+ <_ThisProjectBuildMetadata Include="$(MSBuildProjectFullPath)">
+ @(_TargetFrameworkInfo)
+ @(_TargetFrameworkInfo->'%(TargetFrameworkMonikers)')
+ @(_TargetFrameworkInfo->'%(TargetPlatformMonikers)')
+ $(_AdditionalPropertiesFromProject)
+ true
+ @(_TargetFrameworkInfo->'%(IsRidAgnostic)')
+
+ true
+ $(Platform)
+ $(Platforms)
+
+ @(ProjectConfiguration->'%(Platform)'->Distinct())
+
+
+
+
+
+ <_AdditionalTargetFrameworkInfoPropertyWithValue Include="@(AdditionalTargetFrameworkInfoProperty)">
+ $(%(AdditionalTargetFrameworkInfoProperty.Identity))
+
+
+
+ <_UseAttributeForTargetFrameworkInfoPropertyNames Condition="'$(_UseAttributeForTargetFrameworkInfoPropertyNames)' == ''">false
+
+
+
+
+
+ <_TargetFrameworkInfo Include="$(TargetFramework)">
+ $(TargetFramework)
+ $(TargetFrameworkMoniker)
+ $(TargetPlatformMoniker)
+ None
+ $(_AdditionalTargetFrameworkInfoProperties)
+
+ $(IsRidAgnostic)
+ true
+ false
+
+
+
+
+
+
+
+
+ AssignProjectConfiguration;
+ _SplitProjectReferencesByFileExistence;
+ _GetProjectReferenceTargetFrameworkProperties;
+ _GetProjectReferencePlatformProperties
+
+
+
+
+
+
+
+
+ $(ProjectReferenceBuildTargets)
+
+
+ ProjectReference
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ResolvedProjectReferencePaths Remove="@(_ResolvedProjectReferencePaths)" Condition="'%(_ResolvedProjectReferencePaths.ResolveableAssembly)' == 'false'" />
+
+ <_ResolvedProjectReferencePaths>
+ %(_ResolvedProjectReferencePaths.OriginalItemSpec)
+
+
+
+
+
+
+
+
+
+ <_ProjectReferencesFromRAR Include="@(ReferencePath->WithMetadataValue('ReferenceSourceTarget', 'ProjectReference'))">
+ %(ReferencePath.ProjectReferenceOriginalItemSpec)
+
+
+
+
+
+
+
+
+ $(GetTargetPathDependsOn)
+
+
+
+
+
+ $(TargetPlatformMoniker)
+ $(TargetPlatformIdentifier)
+ $(TargetFrameworkIdentifier)
+ $(TargetFrameworkVersion.TrimStart('vV'))
+ $(TargetRefPath)
+ @(CopyUpToDateMarker)
+
+
+
+
+
+
+
+ %(_ApplicationManifestFinal.FullPath)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ResolveProjectReferences;
+ FindInvalidProjectReferences;
+ GetFrameworkPaths;
+ GetReferenceAssemblyPaths;
+ PrepareForBuild;
+ ResolveSDKReferences;
+ ExpandSDKReferences;
+
+
+
+
+ <_ReferenceInstalledAssemblyDirectory Include="$(TargetFrameworkDirectory)" />
+ <_ReferenceInstalledAssemblySubsets Include="$(TargetFrameworkSubset)" />
+
+
+
+ $(IntermediateOutputPath)$(MSBuildProjectFile).AssemblyReference.cache
+
+
+
+ <_ResolveAssemblyReferencesApplicationConfigFileForExes Include="@(AppConfigWithTargetPath)" Condition="'$(AutoGenerateBindingRedirects)'=='true' or '$(AutoUnifyAssemblyReferences)'=='false'" />
+
+
+
+ <_FindDependencies Condition="'$(BuildingProject)' != 'true' and '$(_ResolveReferenceDependencies)' != 'true'">false
+ true
+ false
+ Warning
+ $(BuildingProject)
+ $(BuildingProject)
+ $(BuildingProject)
+ false
+
+
+
+
+
+ true
+
+
+
+
+ false
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ %(FullPath)
+
+
+ %(ReferencePath.Identity)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_NewGenerateBindingRedirectsIntermediateAppConfig Condition="Exists('$(_GenerateBindingRedirectsIntermediateAppConfig)')">true
+ $(_GenerateBindingRedirectsIntermediateAppConfig)
+
+
+
+
+ $(TargetFileName).config
+
+
+
+
+
+ Software\Microsoft\Microsoft SDKs
+ $(LocalAppData)\Microsoft SDKs;$(MSBuildProgramFiles32)\Microsoft SDKs
+
+ $(MSBuildProgramFiles32)\Microsoft SDKs\Windows Kits\10;$(WindowsKitsRoot)
+
+ true
+ Windows
+ 8.1
+
+ false
+ WindowsPhoneApp
+ 8.1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GetInstalledSDKLocations
+
+
+
+ Debug
+ Retail
+ Retail
+ $(ProcessorArchitecture)
+ Neutral
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GetReferenceTargetPlatformMonikers
+
+
+
+
+
+
+
+ <_ResolvedProjectReferencePaths Remove="@(InvalidProjectReferences)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ResolveSDKReferences
+
+
+ .winmd;
+ .dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+ false
+ false
+ $(TargetFrameworkSDKToolsDirectory)
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ReferencesFromRAR Include="@(ReferencePath->WithMetadataValue('ReferenceSourceTarget', 'ResolveAssemblyReference'))" />
+
+
+
+
+ {CandidateAssemblyFiles};
+ $(ReferencePath);
+ {HintPathFromItem};
+ {TargetFrameworkDirectory};
+ {Registry:$(FrameworkRegistryBase),$(TargetFrameworkVersion),$(AssemblyFoldersSuffix)$(AssemblyFoldersExConditions)};
+ {RawFileName};
+ $(TargetDir)
+
+
+
+
+
+ GetFrameworkPaths;
+ GetReferenceAssemblyPaths;
+ ResolveReferences
+
+
+
+
+ <_DesignTimeReferenceInstalledAssemblyDirectory Include="$(TargetFrameworkDirectory)" />
+
+
+ $(IntermediateOutputPath)$(MSBuildProjectFile)DesignTimeResolveAssemblyReferences.cache
+
+
+
+ {CandidateAssemblyFiles};
+ $(ReferencePath);
+ {HintPathFromItem};
+ {TargetFrameworkDirectory};
+ {Registry:$(FrameworkRegistryBase),$(TargetFrameworkVersion),$(AssemblyFoldersSuffix)$(AssemblyFoldersExConditions)};
+ {RawFileName};
+ $(OutDir)
+
+
+
+ false
+ false
+ false
+ false
+ false
+ true
+ false
+
+
+ <_DesignTimeReferenceAssemblies Include="$(DesignTimeReference)" />
+
+
+ <_RARResolvedReferencePath Include="@(ReferencePath)" />
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+ $(IntermediateOutputPath)
+
+
+
+
+ $(PlatformTargetAsMSBuildArchitecture)
+ $(TargetFrameworkSDKToolsDirectory)
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(PrepareResourcesDependsOn);
+ PrepareResourceNames;
+ ResGen;
+ CompileLicxFiles
+
+
+
+
+
+
+ AssignTargetPaths;
+ SplitResourcesByCulture;
+ CreateManifestResourceNames;
+ CreateCustomManifestResourceNames
+
+
+
+
+
+
+
+
+
+ <_Temporary Remove="@(_Temporary)" />
+
+
+
+
+
+
+
+
+
+ <_Temporary Remove="@(_Temporary)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+ <_LicxFile Include="@(EmbeddedResource)" Condition="'%(Extension)'=='.licx'" />
+
+
+ Resx
+
+
+ Non-Resx
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Resx
+
+
+ Non-Resx
+
+
+
+
+
+
+
+
+
+
+
+ <_MixedResourceWithNoCulture Remove="@(_MixedResourceWithNoCulture)" />
+ <_MixedResourceWithCulture Remove="@(_MixedResourceWithCulture)" />
+
+
+
+
+
+
+
+
+
+ ResolveAssemblyReferences;SplitResourcesByCulture;BeforeResGen;CoreResGen;AfterResGen
+ FindReferenceAssembliesForReferences
+ true
+ false
+
+
+
+
+
+
+
+
+
+ <_Temporary Remove="@(_Temporary)" />
+
+
+ $(PlatformTargetAsMSBuildArchitecture)
+ $(TargetFrameworkSDKToolsDirectory)
+
+
+
+ $(TargetFrameworkAsMSBuildRuntime)
+
+ CurrentRuntime
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_Temporary Remove="@(_Temporary)" />
+
+
+ true
+
+
+ true
+
+
+
+ true
+
+
+ true
+
+
+
+
+
+
+
+
+
+ $(PlatformTargetAsMSBuildArchitecture)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ResolveReferences;
+ ResolveKeySource;
+ SetWin32ManifestProperties;
+ _SetPreferNativeArm64Win32ManifestProperties;
+ FindReferenceAssembliesForReferences;
+ _GenerateCompileInputs;
+ BeforeCompile;
+ _TimeStampBeforeCompile;
+ _GenerateCompileDependencyCache;
+ CoreCompile;
+ _TimeStampAfterCompile;
+ AfterCompile;
+
+
+
+
+
+
+
+
+
+ <_CoreCompileResourceInputs Include="@(EmbeddedResource->'%(OutputResource)')" Condition="'%(EmbeddedResource.WithCulture)' == 'false' and '%(EmbeddedResource.Type)' == 'Resx'" />
+ <_CoreCompileResourceInputs Include="@(EmbeddedResource)" Condition="'%(EmbeddedResource.WithCulture)' == 'false' and '%(EmbeddedResource.Type)' == 'Non-Resx' " />
+
+ <_CoreCompileResourceInputs Include="@(ManifestResourceWithNoCulture)" Condition="'%(ManifestResourceWithNoCulture.EmittedForCompatibilityOnly)'==''">
+ Resx
+ false
+
+ <_CoreCompileResourceInputs Include="@(ManifestNonResxWithNoCultureOnDisk)" Condition="'%(ManifestNonResxWithNoCultureOnDisk.EmittedForCompatibilityOnly)'==''">
+ Non-Resx
+ false
+
+
+
+
+
+
+ true
+ $([System.IO.Path]::Combine('$(IntermediateOutputPath)','$(TargetFrameworkMoniker).AssemblyAttributes$(DefaultLanguageSourceExtension)'))
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_AssemblyTimestampBeforeCompile>%(IntermediateAssembly.ModifiedTime)
+
+
+
+
+
+ $(IntermediateOutputPath)$(MSBuildProjectFile).SuggestedBindingRedirects.cache
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_AssemblyTimestampAfterCompile>%(IntermediateAssembly.ModifiedTime)
+
+
+
+
+
+ __NonExistentSubDir__\__NonExistentFile__
+
+
+
+
+ <_SGenDllName>$(TargetName).XmlSerializers.dll
+ <_SGenDllCreated>false
+ <_SGenGenerateSerializationAssembliesConfig>$(GenerateSerializationAssemblies)
+ <_SGenGenerateSerializationAssembliesConfig Condition="'$(GenerateSerializationAssemblies)' == ''">Auto
+ <_SGenGenerateSerializationAssembliesConfig Condition="'$(ConfigurationName)'=='Debug' and '$(_SGenGenerateSerializationAssembliesConfig)' == 'Auto'">Off
+ true
+ false
+ true
+
+
+
+
+ $(PlatformTargetAsMSBuildArchitecture)
+
+
+
+
+
+
+
+
+
+ $(CreateSatelliteAssembliesDependsOn);
+ _GenerateSatelliteAssemblyInputs;
+ ComputeIntermediateSatelliteAssemblies;
+ GenerateSatelliteAssemblies
+
+
+
+
+
+
+
+
+
+ <_SatelliteAssemblyResourceInputs Include="@(EmbeddedResource->'%(OutputResource)')" Condition="'%(EmbeddedResource.WithCulture)' == 'true' and '%(EmbeddedResource.Type)' == 'Resx'" />
+ <_SatelliteAssemblyResourceInputs Include="@(EmbeddedResource)" Condition="'%(EmbeddedResource.WithCulture)' == 'true' and '%(EmbeddedResource.Type)' == 'Non-Resx'" />
+
+ <_SatelliteAssemblyResourceInputs Include="@(ManifestResourceWithCulture)" Condition="'%(ManifestResourceWithCulture.EmittedForCompatibilityOnly)'==''">
+ Resx
+ true
+
+ <_SatelliteAssemblyResourceInputs Include="@(ManifestNonResxWithCultureOnDisk)" Condition="'%(ManifestNonResxWithCultureOnDisk.EmittedForCompatibilityOnly)'==''">
+ Non-Resx
+ true
+
+
+
+
+
+
+ <_ALExeToolPath Condition="'$(_ALExeToolPath)' == ''">$(TargetFrameworkSDKToolsDirectory)
+
+
+
+
+
+
+
+
+
+ CreateManifestResourceNames
+
+
+
+
+
+ %(EmbeddedResource.Culture)
+ %(EmbeddedResource.Culture)\$(TargetName).resources.dll
+
+
+
+
+
+ $(Win32Manifest)
+
+
+
+
+
+
+ <_DeploymentBaseManifest>$(ApplicationManifest)
+ <_DeploymentBaseManifest Condition="'$(_DeploymentBaseManifest)'==''">@(_DeploymentBaseManifestWithTargetPath)
+
+ true
+
+
+
+
+ $(ApplicationManifest)
+ $(ApplicationManifest)
+
+
+
+
+
+
+ $(_FrameworkVersion40Path)\default.win32manifest
+
+
+
+
+
+
+
+
+ $(_Win32Manifest)
+
+
+
+
+
+
+ SetWin32ManifestProperties;
+ GenerateApplicationManifest;
+ GenerateDeploymentManifest
+
+
+
+
+
+ <_DeploymentPublishFileOfTypeManifestEntryPoint Include="@(PublishFile)" Condition="'%(FileType)'=='ManifestEntryPoint'" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_DeploymentCopyApplicationManifest>true
+
+
+
+
+
+ <_DeploymentManifestTargetFrameworkMoniker>$(TargetFrameworkMoniker)
+ <_DeploymentManifestTargetFrameworkVersion>$(TargetFrameworkVersion)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_DeploymentManifestTargetFrameworkVersion Condition="'$(DeploymentManifestTargetFrameworkVersionOverride)' == ''">v4.5
+ <_DeploymentManifestTargetFrameworkVersion Condition="'$(DeploymentManifestTargetFrameworkVersionOverride)' != ''">$(DeploymentManifestTargetFrameworkVersionOverride)
+ <_DeploymentManifestTargetFrameworkMoniker>.NETFramework,Version=$(_DeploymentManifestTargetFrameworkVersion)
+
+
+
+
+
+
+
+
+
+
+ <_DeploymentManifestEntryPoint Remove="@(_DeploymentManifestEntryPoint)" />
+ <_DeploymentManifestEntryPoint Include="@(_DeploymentManifestLauncherEntryPoint)" />
+
+
+
+
+
+
+
+
+
+ <_DeploymentManifestType>Native
+
+
+
+
+
+
+ <_DeploymentManifestVersion>@(_IntermediateAssemblyIdentity->'%(Version)')
+
+
+
+
+
+
+ <_SGenDllsRelatedToCurrentDll Include="@(_ReferenceSerializationAssemblyPaths->'%(FullPath)')" Condition="'%(Extension)' == '.dll'" />
+ <_SGenDllsRelatedToCurrentDll Include="@(SerializationAssembly->'%(FullPath)')" Condition="'%(Extension)' == '.dll'" />
+
+
+ <_CopyLocalFalseRefPaths Include="@(ReferencePath)" Condition="'%(CopyLocal)' == 'false'" />
+ <_CopyLocalFalseRefPathsWithExclusion Include="@(_CopyLocalFalseRefPaths)" Exclude="@(ReferenceCopyLocalPaths);@(_NETStandardLibraryNETFrameworkLib)" />
+
+
+ <_ClickOnceSatelliteAssemblies Include="@(IntermediateSatelliteAssembliesWithTargetPath);@(ReferenceSatellitePaths)" />
+
+
+
+ <_DeploymentReferencePaths Include="@(ReferenceCopyLocalPaths)" Condition="('%(Extension)' == '.dll' Or '%(Extension)' == '.exe' Or '%(Extension)' == '.md') and ('%(ReferenceCopyLocalPaths.CopyToPublishDirectory)' != 'false')">
+ true
+
+ <_DeploymentReferencePaths Include="@(_CopyLocalFalseRefPathsWithExclusion)" />
+
+
+
+ <_ManifestManagedReferences Include="@(_DeploymentReferencePaths);@(ReferenceDependencyPaths);@(_SGenDllsRelatedToCurrentDll);@(SerializationAssembly);@(ReferenceCOMWrappersToCopyLocal)" Exclude="@(_ClickOnceSatelliteAssemblies);@(_ReferenceScatterPaths);@(_ExcludedAssembliesFromManifestGeneration)" />
+
+
+
+
+ <_ClickOnceRuntimeCopyLocalItems Include="@(RuntimeTargetsCopyLocalItems)" Condition="'%(RuntimeTargetsCopyLocalItems.CopyLocal)' == 'true'" />
+ <_ClickOnceRuntimeCopyLocalItems Include="@(NativeCopyLocalItems)" Condition="'%(NativeCopyLocalItems.CopyLocal)' == 'true'" />
+ <_ClickOnceRuntimeCopyLocalItems Remove="@(_DeploymentReferencePaths)" />
+
+ <_ClickOnceTransitiveContentItemsTemp Include="@(_TransitiveItemsToCopyToOutputDirectory->WithoutMetadataValue('CopyToPublishDirectory', 'Never')->'%(TargetPath)')" Condition="'$(PublishProtocol)' == 'ClickOnce'">
+ %(Identity)
+
+ <_ClickOnceTransitiveContentItems Include="@(_ClickOnceTransitiveContentItemsTemp->'%(SavedIdentity)')" Condition="'%(Identity)'=='@(PublishFile)' Or '%(Extension)'=='.exe' Or '%(Extension)'=='.dll'" />
+
+ <_ClickOnceContentItems Include="@(ContentWithTargetPath->WithoutMetadataValue('CopyToPublishDirectory', 'Never'))" />
+ <_ClickOnceContentItems Include="@(_ClickOnceTransitiveContentItems)" />
+
+
+ <_ClickOnceNoneItemsTemp Include="@(_NoneWithTargetPath->WithoutMetadataValue('CopyToPublishDirectory', 'Never')->'%(TargetPath)')" Condition="'$(PublishProtocol)'=='Clickonce' And ('%(_NoneWithTargetPath.CopyToOutputDirectory)'=='Always' or '%(_NoneWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest')">
+ %(Identity)
+
+ <_ClickOnceNoneItems Include="@(_ClickOnceNoneItemsTemp->'%(SavedIdentity)')" Condition="'%(Identity)'=='@(PublishFile)' Or '%(Extension)'=='.exe' Or '%(Extension)'=='.dll'" />
+ <_ClickOnceFiles Include="@(_ClickOnceContentItems);@(_DeploymentManifestIconFile);@(AppConfigWithTargetPath);@(NetCoreRuntimeJsonFilesForClickOnce);@(_ClickOnceRuntimeCopyLocalItems);@(_ClickOnceNoneItems)" />
+
+ <_ClickOnceNoneItemsTemp Remove="@(_ClickOnceNoneItemsTemp)" />
+ <_ClickOnceNoneItems Remove="@(_ClickOnceNoneItems)" />
+ <_ClickOnceTransitiveContentItemsTemp Remove="@(_ClickOnceTransitiveContentItemsTemp)" />
+ <_ClickOnceTransitiveContentItems Remove="@(_ClickOnceTransitiveContentItems)" />
+ <_ClickOnceContentItems Remove="@(_ClickOnceContentItems)" />
+ <_ClickOnceRuntimeCopyLocalItems Remove="@(_ClickOnceRuntimeCopyLocalItems)" />
+
+
+
+ <_ClickOnceFiles Include="$(PublishedSingleFilePath);@(_DeploymentManifestIconFile)" />
+ <_ClickOnceFiles Include="@(_FilesExcludedFromBundle)" />
+
+ <_FileAssociationIcons Include="%(FileAssociation.DefaultIcon)" />
+ <_ClickOnceFiles Include="@(ContentWithTargetPath)" Condition="'%(Identity)'=='@(_FileAssociationIcons)'" />
+
+
+
+
+
+ <_ManifestManagedReferences Remove="@(_ReadyToRunCompileList)" />
+ <_ClickOnceFiles Remove="@(_ReadyToRunCompileList)" />
+ <_ClickOnceFiles Include="@(_ReadyToRunFilesToPublish)" />
+ <_ClickOnceTargetFile Include="@(_ReadyToRunFilesToPublish)" Condition="'%(Filename)%(Extension)' == '$(TargetFileName)'" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_DeploymentManifestDependencies Include="@(_DeploymentManifestDependenciesUnfiltered)" Condition="!('%(_DeploymentManifestDependenciesUnfiltered.CopyLocal)' == 'false' And '%(_DeploymentManifestDependenciesUnfiltered.DependencyType)' != 'Install')" />
+
+
+ <_DeploymentManifestType>ClickOnce
+
+
+
+ <_DeploymentPlatformTarget Condition="'$(_DeploymentLauncherBased)' != 'true'">$(PlatformTarget)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+ CopyFilesToOutputDirectory
+
+
+
+
+
+
+ false
+ false
+
+
+
+
+ false
+ false
+ false
+
+
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_TargetsThatPrepareProjectReferences>_SplitProjectReferencesByFileExistence
+
+ true
+ <_TargetsThatPrepareProjectReferences Condition=" '$(MSBuildCopyContentTransitively)' == 'true' ">
+ AssignProjectConfiguration;
+ _SplitProjectReferencesByFileExistence
+
+
+ AssignTargetPaths;
+ $(_TargetsThatPrepareProjectReferences);
+ _GetProjectReferenceTargetFrameworkProperties;
+ _PopulateCommonStateForGetCopyToOutputDirectoryItems
+
+
+ <_RecursiveTargetForContentCopying>GetCopyToOutputDirectoryItems
+
+ <_RecursiveTargetForContentCopying Condition=" '$(MSBuildCopyContentTransitively)' == 'false' ">_GetCopyToOutputDirectoryItemsFromThisProject
+
+
+
+
+ <_GCTODIKeepDuplicates>false
+ <_GCTODIKeepMetadata>CopyToOutputDirectory;TargetPath
+
+
+
+
+
+
+
+
+
+ <_CopyToOutputDirectoryTransitiveItems KeepDuplicates=" '$(_GCTODIKeepDuplicates)' != 'false' " KeepMetadata="$(_GCTODIKeepMetadata)" Include="@(_AllChildProjectItemsWithTargetPath->'%(FullPath)')" Condition="'%(_AllChildProjectItemsWithTargetPath.CopyToOutputDirectory)'=='Always'" />
+ <_CopyToOutputDirectoryTransitiveItems KeepDuplicates=" '$(_GCTODIKeepDuplicates)' != 'false' " KeepMetadata="$(_GCTODIKeepMetadata)" Include="@(_AllChildProjectItemsWithTargetPath->'%(FullPath)')" Condition="'%(_AllChildProjectItemsWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'" />
+
+
+
+ <_AllChildProjectItemsWithTargetPath Remove="@(_AllChildProjectItemsWithTargetPath)" />
+
+
+
+ <_CopyToOutputDirectoryTransitiveItems KeepMetadata="$(_GCTODIKeepMetadata)" Include="@(ContentWithTargetPath->'%(FullPath)')" Condition="'%(ContentWithTargetPath.CopyToOutputDirectory)'=='Always' AND '%(ContentWithTargetPath.MSBuildSourceProjectFile)'!=''" />
+ <_CopyToOutputDirectoryTransitiveItems KeepMetadata="$(_GCTODIKeepMetadata)" Include="@(ContentWithTargetPath->'%(FullPath)')" Condition="'%(ContentWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest' AND '%(ContentWithTargetPath.MSBuildSourceProjectFile)'!=''" />
+
+
+ <_CopyToOutputDirectoryTransitiveItems KeepMetadata="$(_GCTODIKeepMetadata)" Include="@(EmbeddedResource->'%(FullPath)')" Condition="'%(EmbeddedResource.CopyToOutputDirectory)'=='Always' AND '%(EmbeddedResource.MSBuildSourceProjectFile)'!=''" />
+ <_CopyToOutputDirectoryTransitiveItems KeepMetadata="$(_GCTODIKeepMetadata)" Include="@(EmbeddedResource->'%(FullPath)')" Condition="'%(EmbeddedResource.CopyToOutputDirectory)'=='PreserveNewest' AND '%(EmbeddedResource.MSBuildSourceProjectFile)'!=''" />
+
+
+ <_CompileItemsToCopy Include="@(Compile->'%(FullPath)')" Condition="('%(Compile.CopyToOutputDirectory)'=='Always' or '%(Compile.CopyToOutputDirectory)'=='PreserveNewest') AND '%(Compile.MSBuildSourceProjectFile)'!=''" />
+
+
+
+
+
+ <_CopyToOutputDirectoryTransitiveItems KeepMetadata="$(_GCTODIKeepMetadata)" Include="@(_CompileItemsToCopyWithTargetPath)" Condition="'%(_CompileItemsToCopyWithTargetPath.CopyToOutputDirectory)'=='Always'" />
+ <_CopyToOutputDirectoryTransitiveItems KeepMetadata="$(_GCTODIKeepMetadata)" Include="@(_CompileItemsToCopyWithTargetPath)" Condition="'%(_CompileItemsToCopyWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'" />
+
+
+ <_CopyToOutputDirectoryTransitiveItems KeepMetadata="$(_GCTODIKeepMetadata)" Include="@(_NoneWithTargetPath->'%(FullPath)')" Condition="'%(_NoneWithTargetPath.CopyToOutputDirectory)'=='Always' AND '%(_NoneWithTargetPath.MSBuildSourceProjectFile)'!=''" />
+ <_CopyToOutputDirectoryTransitiveItems KeepMetadata="$(_GCTODIKeepMetadata)" Include="@(_NoneWithTargetPath->'%(FullPath)')" Condition="'%(_NoneWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest' AND '%(_NoneWithTargetPath.MSBuildSourceProjectFile)'!=''" />
+
+
+
+
+ <_ThisProjectItemsToCopyToOutputDirectory KeepMetadata="$(_GCTODIKeepMetadata)" Include="@(ContentWithTargetPath->'%(FullPath)')" Condition="'%(ContentWithTargetPath.CopyToOutputDirectory)'=='Always' AND '%(ContentWithTargetPath.MSBuildSourceProjectFile)'==''" />
+ <_ThisProjectItemsToCopyToOutputDirectory KeepMetadata="$(_GCTODIKeepMetadata)" Include="@(ContentWithTargetPath->'%(FullPath)')" Condition="'%(ContentWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest' AND '%(ContentWithTargetPath.MSBuildSourceProjectFile)'==''" />
+
+
+ <_ThisProjectItemsToCopyToOutputDirectory KeepMetadata="$(_GCTODIKeepMetadata)" Include="@(EmbeddedResource->'%(FullPath)')" Condition="'%(EmbeddedResource.CopyToOutputDirectory)'=='Always' AND '%(EmbeddedResource.MSBuildSourceProjectFile)'==''" />
+ <_ThisProjectItemsToCopyToOutputDirectory KeepMetadata="$(_GCTODIKeepMetadata)" Include="@(EmbeddedResource->'%(FullPath)')" Condition="'%(EmbeddedResource.CopyToOutputDirectory)'=='PreserveNewest' AND '%(EmbeddedResource.MSBuildSourceProjectFile)'==''" />
+
+
+ <_CompileItemsToCopy Include="@(Compile->'%(FullPath)')" Condition="('%(Compile.CopyToOutputDirectory)'=='Always' or '%(Compile.CopyToOutputDirectory)'=='PreserveNewest') AND '%(Compile.MSBuildSourceProjectFile)'==''" />
+
+
+
+
+
+ <_ThisProjectItemsToCopyToOutputDirectory KeepMetadata="$(_GCTODIKeepMetadata)" Include="@(_CompileItemsToCopyWithTargetPath)" Condition="'%(_CompileItemsToCopyWithTargetPath.CopyToOutputDirectory)'=='Always'" />
+ <_ThisProjectItemsToCopyToOutputDirectory KeepMetadata="$(_GCTODIKeepMetadata)" Include="@(_CompileItemsToCopyWithTargetPath)" Condition="'%(_CompileItemsToCopyWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest'" />
+
+
+ <_ThisProjectItemsToCopyToOutputDirectory KeepMetadata="$(_GCTODIKeepMetadata)" Include="@(_NoneWithTargetPath->'%(FullPath)')" Condition="'%(_NoneWithTargetPath.CopyToOutputDirectory)'=='Always' AND '%(_NoneWithTargetPath.MSBuildSourceProjectFile)'==''" />
+ <_ThisProjectItemsToCopyToOutputDirectory KeepMetadata="$(_GCTODIKeepMetadata)" Include="@(_NoneWithTargetPath->'%(FullPath)')" Condition="'%(_NoneWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest' AND '%(_NoneWithTargetPath.MSBuildSourceProjectFile)'==''" />
+
+
+
+
+
+
+
+
+
+
+
+
+ <_TransitiveItemsToCopyToOutputDirectory Remove="@(_ThisProjectItemsToCopyToOutputDirectory)" MatchOnMetadata="TargetPath" MatchOnMetadataOptions="PathLike" />
+
+
+ <_TransitiveItemsToCopyToOutputDirectoryAlways KeepDuplicates=" '$(_GCTODIKeepDuplicates)' != 'false' " KeepMetadata="$(_GCTODIKeepMetadata)" Include="@(_TransitiveItemsToCopyToOutputDirectory->'%(FullPath)')" Condition="'%(_TransitiveItemsToCopyToOutputDirectory.CopyToOutputDirectory)'=='Always'" />
+ <_TransitiveItemsToCopyToOutputDirectoryPreserveNewest KeepDuplicates=" '$(_GCTODIKeepDuplicates)' != 'false' " KeepMetadata="$(_GCTODIKeepMetadata)" Include="@(_TransitiveItemsToCopyToOutputDirectory->'%(FullPath)')" Condition="'%(_TransitiveItemsToCopyToOutputDirectory.CopyToOutputDirectory)'=='PreserveNewest'" />
+ <_ThisProjectItemsToCopyToOutputDirectoryAlways KeepDuplicates=" '$(_GCTODIKeepDuplicates)' != 'false' " KeepMetadata="$(_GCTODIKeepMetadata)" Include="@(_ThisProjectItemsToCopyToOutputDirectory->'%(FullPath)')" Condition="'%(_ThisProjectItemsToCopyToOutputDirectory.CopyToOutputDirectory)'=='Always'" />
+ <_ThisProjectItemsToCopyToOutputDirectoryPreserveNewest KeepDuplicates=" '$(_GCTODIKeepDuplicates)' != 'false' " KeepMetadata="$(_GCTODIKeepMetadata)" Include="@(_ThisProjectItemsToCopyToOutputDirectory->'%(FullPath)')" Condition="'%(_ThisProjectItemsToCopyToOutputDirectory.CopyToOutputDirectory)'=='PreserveNewest'" />
+
+ <_SourceItemsToCopyToOutputDirectoryAlways Include="@(_TransitiveItemsToCopyToOutputDirectoryAlways);@(_ThisProjectItemsToCopyToOutputDirectoryAlways)" />
+ <_SourceItemsToCopyToOutputDirectory Include="@(_TransitiveItemsToCopyToOutputDirectoryPreserveNewest);@(_ThisProjectItemsToCopyToOutputDirectoryPreserveNewest)" />
+
+
+ <_TransitiveItemsToCopyToOutputDirectoryAlways Remove="@(_TransitiveItemsToCopyToOutputDirectoryAlways)" />
+ <_TransitiveItemsToCopyToOutputDirectoryPreserveNewest Remove="@(_TransitiveItemsToCopyToOutputDirectoryPreserveNewest)" />
+ <_ThisProjectItemsToCopyToOutputDirectoryAlways Remove="@(_ThisProjectItemsToCopyToOutputDirectoryAlways)" />
+ <_ThisProjectItemsToCopyToOutputDirectoryPreserveNewest Remove="@(_ThisProjectItemsToCopyToOutputDirectoryPreserveNewest)" />
+ <_ThisProjectItemsToCopyToOutputDirectory Remove="@(_ThisProjectItemsToCopyToOutputDirectory)" />
+
+
+
+
+
+
+ %(CopyToOutputDirectory)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_DocumentationFileProduced Condition="!Exists('@(DocFileItem)')">false
+
+
+
+
+
+
+ <_DebugSymbolsProduced Condition="!Exists('@(_DebugSymbolsIntermediatePath)')">false
+
+
+
+
+
+
+
+
+
+ <_SGenDllCreated Condition="Exists('$(IntermediateOutputPath)$(_SGenDllName)')">true
+
+
+
+
+
+
+
+
+
+
+
+
+ $(PlatformTargetAsMSBuildArchitecture)
+
+
+
+ $(TargetFrameworkAsMSBuildRuntime)
+
+ CurrentRuntime
+
+
+
+
+
+
+
+
+
+
+
+ <_CleanOrphanFileWrites Include="@(_CleanPriorFileWrites)" Exclude="@(_CleanCurrentFileWrites)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_CleanRemainingFileWritesAfterIncrementalClean Include="@(_CleanPriorFileWrites);@(_CleanCurrentFileWrites)" Exclude="@(_CleanOrphanFilesDeleted)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_CleanPriorFileWrites Include="@(_CleanUnfilteredPriorFileWrites)" Exclude="@(_ResolveAssemblyReferenceResolvedFilesAbsolute)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_CleanCurrentFileWritesWithNoReferences Include="@(_CleanCurrentFileWritesInOutput);@(_CleanCurrentFileWritesInIntermediate)" Exclude="@(_ResolveAssemblyReferenceResolvedFilesAbsolute)" />
+
+
+
+
+
+
+
+
+
+
+ BeforeClean;
+ UnmanagedUnregistration;
+ CoreClean;
+ CleanReferencedProjects;
+ CleanPublishFolder;
+ AfterClean
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_CleanRemainingFileWritesAfterClean Include="@(_CleanPriorFileWrites)" Exclude="@(_CleanPriorFileWritesDeleted)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ CleanPublishFolder;
+ $(_RecursiveTargetForContentCopying);
+ _DeploymentGenerateTrustInfo;
+ $(DeploymentComputeClickOnceManifestInfoDependsOn)
+
+
+
+
+
+ SetGenerateManifests;
+ Build;
+ PublishOnly
+
+
+ _DeploymentUnpublishable
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+ SetGenerateManifests;
+ PublishBuild;
+ BeforePublish;
+ GenerateManifests;
+ CopyFilesToOutputDirectory;
+ _CopyFilesToPublishFolder;
+ _DeploymentGenerateBootstrapper;
+ ResolveKeySource;
+ _DeploymentSignClickOnceDeployment;
+ AfterPublish
+
+
+
+
+
+
+
+
+
+
+ BuildOnlySettings;
+ PrepareForBuild;
+ ResolveReferences;
+ PrepareResources;
+ ResolveKeySource;
+ GenerateSerializationAssemblies;
+ CreateSatelliteAssemblies;
+
+
+
+
+
+
+
+
+
+
+ <_DeploymentApplicationFolderName>Application Files\$(AssemblyName)_$(_DeploymentApplicationVersionFragment)
+ <_DeploymentApplicationDir>$(ClickOncePublishDir)$(_DeploymentApplicationFolderName)\
+
+
+
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ $(TargetPath)
+ $(TargetFileName)
+ true
+
+
+
+
+
+ true
+ $(TargetPath)
+ $(TargetFileName)
+
+
+
+
+ PrepareForBuild
+ true
+
+
+
+ <_BuiltProjectOutputGroupOutputIntermediate Include="@(BuiltProjectOutputGroupKeyOutput)" />
+
+
+
+ <_BuiltProjectOutputGroupOutputIntermediate Include="$(AppConfig)" Condition="'$(AddAppConfigToBuildOutputs)'=='true'">
+ $(TargetDir)$(TargetFileName).config
+ $(TargetFileName).config
+
+ $(AppConfig)
+
+
+
+ <_IsolatedComReference Include="@(COMReference)" Condition=" '%(COMReference.Isolated)' == 'true' " />
+ <_IsolatedComReference Include="@(COMFileReference)" Condition=" '%(COMFileReference.Isolated)' == 'true' " />
+
+
+
+ <_BuiltProjectOutputGroupOutputIntermediate Include="$(OutDir)$(_DeploymentTargetApplicationManifestFileName)" Condition="('@(NativeReference)'!='' or '@(_IsolatedComReference)'!='') And Exists('$(OutDir)$(_DeploymentTargetApplicationManifestFileName)')">
+ $(_DeploymentTargetApplicationManifestFileName)
+
+ $(OutDir)$(_DeploymentTargetApplicationManifestFileName)
+
+
+
+
+
+
+ %(_BuiltProjectOutputGroupOutputIntermediate.FullPath)
+
+
+
+
+
+
+
+
+
+ @(_DebugSymbolsOutputPath->'%(FullPath)')
+ @(_DebugSymbolsIntermediatePath->'%(Filename)%(Extension)')
+
+
+
+
+
+
+ @(WinMDExpFinalOutputPdbItem->'%(FullPath)')
+ @(WinMDExpOutputPdbItem->'%(Filename)%(Extension)')
+
+
+
+
+
+
+
+
+
+ @(FinalDocFile->'%(FullPath)')
+ true
+ @(DocFileItem->'%(Filename)%(Extension)')
+
+
+
+
+
+
+ @(WinMDExpFinalOutputDocItem->'%(FullPath)')
+ @(WinMDOutputDocumentationFileItem->'%(Filename)%(Extension)')
+
+
+
+
+
+ $(SatelliteDllsProjectOutputGroupDependsOn);PrepareForBuild;PrepareResourceNames
+
+
+
+
+ %(EmbeddedResource.Culture)\$(TargetName).resources.dll
+ %(EmbeddedResource.Culture)
+
+
+
+
+
+ $(TargetDir)%(SatelliteDllsProjectOutputGroupOutputIntermediate.TargetPath)
+
+ %(SatelliteDllsProjectOutputGroupOutputIntermediate.Identity)
+
+
+
+
+
+ PrepareForBuild;AssignTargetPaths
+
+
+
+
+
+
+
+
+
+
+
+ $(MSBuildProjectFullPath)
+ $(ProjectFileName)
+
+
+
+
+
+
+
+ PrepareForBuild;AssignTargetPaths
+
+
+
+
+
+
+
+
+
+
+
+
+
+ @(_OutputPathItem->'%(FullPath)$(_SGenDllName)')
+ $(_SGenDllName)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ResolveSDKReferences;ExpandSDKReferences
+
+
+
+
+
+
+
+
+
+
+
+
+ $(CommonOutputGroupsDependsOn);
+ BuildOnlySettings;
+ PrepareForBuild;
+ AssignTargetPaths;
+ ResolveReferences
+
+
+
+
+
+
+
+ $(BuiltProjectOutputGroupDependenciesDependsOn);
+ $(CommonOutputGroupsDependsOn)
+
+
+
+
+
+
+
+
+
+
+ $(DebugSymbolsProjectOutputGroupDependenciesDependsOn);
+ $(CommonOutputGroupsDependsOn)
+
+
+
+
+
+
+
+
+
+
+
+ $(SatelliteDllsProjectOutputGroupDependenciesDependsOn);
+ $(CommonOutputGroupsDependsOn)
+
+
+
+
+
+
+
+
+
+
+
+ $(DocumentationProjectOutputGroupDependenciesDependsOn);
+ $(CommonOutputGroupsDependsOn)
+
+
+
+
+
+
+
+
+
+
+
+ $(SGenFilesOutputGroupDependenciesDependsOn);
+ $(CommonOutputGroupsDependsOn)
+
+
+
+
+
+
+
+
+
+
+
+ $(ReferenceCopyLocalPathsOutputGroupDependsOn);
+ $(CommonOutputGroupsDependsOn)
+
+
+
+
+
+ %(ReferenceCopyLocalPaths.DestinationSubDirectory)%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension)
+
+
+
+
+
+
+ $(DesignerRuntimeImplementationProjectOutputGroupDependsOn);
+ $(CommonOutputGroupsDependsOn)
+
+
+
+
+
+
+
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeAnalysis\Microsoft.CodeAnalysis.targets
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\TeamTest\Microsoft.TeamTest.targets
+
+
+
+ false
+
+
+
+
+
+
+
+ $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\AppxPackage\Microsoft.AppXPackage.Targets
+
+ true
+
+
+
+
+
+
+
+ $([MSBuild]::IsRunningFromVisualStudio())
+ $([MSBuild]::GetToolsDirectory32())\..\..\..\Common7\IDE\CommonExtensions\Microsoft\NuGet\NuGet.targets
+ $(MSBuildToolsPath)\NuGet.targets
+
+
+
+
+
+ true
+
+ NuGet.Build.Tasks.dll
+
+ false
+
+ true
+ true
+
+ false
+
+ WarnAndContinue
+
+ $(BuildInParallel)
+ true
+
+ <_RestoreSolutionFileUsed Condition=" '$(_RestoreSolutionFileUsed)' == '' AND '$(SolutionDir)' != '' AND $(MSBuildProjectFullPath.EndsWith('.metaproj')) == 'true' ">true
+
+ $(MSBuildInteractive)
+
+ true
+
+ true
+
+ <_CentralPackageVersionsEnabled Condition="'$(ManagePackageVersionsCentrally)' == 'true' AND '$(CentralPackageVersionsFileImported)' == 'true'">true
+
+
+
+
+ true
+
+ low
+
+ direct
+
+
+
+ <_GenerateRestoreGraphProjectEntryInputProperties>ExcludeRestorePackageImports=true
+
+ <_GenerateRestoreGraphProjectEntryInputProperties Condition=" '$(RestoreUseCustomAfterTargets)' == 'true' ">
+ $(_GenerateRestoreGraphProjectEntryInputProperties);
+ NuGetRestoreTargets=$(MSBuildThisFileFullPath);
+ RestoreUseCustomAfterTargets=$(RestoreUseCustomAfterTargets);
+ CustomAfterMicrosoftCommonCrossTargetingTargets=$(MSBuildThisFileFullPath);
+ CustomAfterMicrosoftCommonTargets=$(MSBuildThisFileFullPath);
+
+
+ <_GenerateRestoreGraphProjectEntryInputProperties Condition=" '$(_RestoreSolutionFileUsed)' == 'true' ">
+ $(_GenerateRestoreGraphProjectEntryInputProperties);
+ _RestoreSolutionFileUsed=true;
+ SolutionDir=$(SolutionDir);
+ SolutionName=$(SolutionName);
+ SolutionFileName=$(SolutionFileName);
+ SolutionPath=$(SolutionPath);
+ SolutionExt=$(SolutionExt);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(ContinueOnError)
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(ContinueOnError)
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(ContinueOnError)
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+ <_FrameworkReferenceForRestore Include="@(FrameworkReference)" Condition="'%(FrameworkReference.IsTransitiveFrameworkReference)' != 'true'" />
+
+
+
+
+
+
+ $(ContinueOnError)
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ exclusionlist
+
+
+
+ <_FilteredRestoreGraphProjectInputItemsTmp Include="@(RestoreGraphProjectInputItems)" Condition=" '%(RestoreGraphProjectInputItems.Extension)' == '.csproj' Or
'%(RestoreGraphProjectInputItems.Extension)' == '.vbproj' Or
'%(RestoreGraphProjectInputItems.Extension)' == '.fsproj' Or
'%(RestoreGraphProjectInputItems.Extension)' == '.nuproj' Or
'%(RestoreGraphProjectInputItems.Extension)' == '.proj' Or
'%(RestoreGraphProjectInputItems.Extension)' == '.msbuildproj' Or
'%(RestoreGraphProjectInputItems.Extension)' == '.vcxproj' " />
+
+
+
+ <_FilteredRestoreGraphProjectInputItemsTmp Include="@(RestoreGraphProjectInputItems)" Condition=" '%(RestoreGraphProjectInputItems.Extension)' != '.metaproj'
AND '%(RestoreGraphProjectInputItems.Extension)' != '.shproj'
AND '%(RestoreGraphProjectInputItems.Extension)' != '.vcxitems'
AND '%(RestoreGraphProjectInputItems.Extension)' != '.vdproj'
AND '%(RestoreGraphProjectInputItems.Extension)' != '' " />
+
+
+
+ <_FilteredRestoreGraphProjectInputItemsTmp Include="@(RestoreGraphProjectInputItems)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_GenerateRestoreGraphProjectEntryInput Include="@(FilteredRestoreGraphProjectInputItems)" Condition=" '$(RestoreRecursive)' != 'true' " />
+ <_GenerateRestoreGraphProjectEntryInput Include="@(_RestoreProjectPathItems)" Condition=" '$(RestoreRecursive)' == 'true' " />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_RestoreGraphEntry Include="$([System.Guid]::NewGuid())" Condition=" '$(RestoreProjectStyle)' != 'Unknown' ">
+ RestoreSpec
+ $(MSBuildProjectFullPath)
+
+
+
+
+
+
+ netcoreapp1.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_HasPackageReferenceItems Condition="'@(PackageReference)' != ''">true
+
+
+ <_HasPackageReferenceItems Condition="@(PackageReference->Count()) > 0">true
+
+
+
+
+
+
+ <_HasPackageReferenceItems />
+
+
+
+
+
+ true
+
+
+
+
+
+ <_RestoreProjectFramework />
+ <_TargetFrameworkToBeUsed Condition=" '$(_TargetFrameworkOverride)' == '' ">$(TargetFrameworks)
+
+
+
+
+
+
+ <_RestoreTargetFrameworksOutputFiltered Include="$(_RestoreProjectFramework.Split(';'))" />
+
+
+
+
+
+ <_RestoreTargetFrameworkItems Include="$(TargetFrameworks.Split(';'))" />
+
+
+ <_RestoreTargetFrameworkItems Include="$(_TargetFrameworkOverride)" />
+
+
+
+
+
+ $(SolutionDir)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_RestoreSettingsPerFramework Include="$([System.Guid]::NewGuid())">
+ $(RestoreAdditionalProjectSources)
+ $(RestoreAdditionalProjectFallbackFolders)
+ $(RestoreAdditionalProjectFallbackFoldersExcludes)
+
+
+
+
+
+
+
+ $(MSBuildProjectExtensionsPath)
+
+
+
+
+
+
+ <_RestoreProjectName>$(MSBuildProjectName)
+ <_RestoreProjectName Condition=" '$(PackageReferenceCompatibleProjectStyle)' == 'true' AND '$(AssemblyName)' != '' ">$(AssemblyName)
+ <_RestoreProjectName Condition=" '$(PackageReferenceCompatibleProjectStyle)' == 'true' AND '$(PackageId)' != '' ">$(PackageId)
+
+
+
+ <_RestoreProjectVersion>1.0.0
+ <_RestoreProjectVersion Condition=" '$(Version)' != '' ">$(Version)
+ <_RestoreProjectVersion Condition=" '$(PackageVersion)' != '' ">$(PackageVersion)
+
+
+
+ <_RestoreCrossTargeting>true
+
+
+
+ <_RestoreSkipContentFileWrite Condition=" '$(TargetFrameworks)' == '' AND '$(TargetFramework)' == '' ">true
+
+
+
+ <_RestoreGraphEntry Include="$([System.Guid]::NewGuid())">
+ ProjectSpec
+ $(_RestoreProjectVersion)
+ $(MSBuildProjectFullPath)
+ $(MSBuildProjectFullPath)
+ $(_RestoreProjectName)
+ $(_OutputSources)
+ $(_OutputFallbackFolders)
+ $(_OutputPackagesPath)
+ $(RestoreProjectStyle)
+ $(RestoreOutputAbsolutePath)
+ $(RuntimeIdentifiers);$(RuntimeIdentifier)
+ $(RuntimeSupports)
+ $(_RestoreCrossTargeting)
+ $(RestoreLegacyPackagesDirectory)
+ $(ValidateRuntimeIdentifierCompatibility)
+ $(_RestoreSkipContentFileWrite)
+ $(_OutputConfigFilePaths)
+ $(TreatWarningsAsErrors)
+ $(WarningsAsErrors)
+ $(WarningsNotAsErrors)
+ $(NoWarn)
+ $(RestorePackagesWithLockFile)
+ $(NuGetLockFilePath)
+ $(RestoreLockedMode)
+ <_CentralPackageVersionsEnabled>$(_CentralPackageVersionsEnabled)
+ $(CentralPackageFloatingVersionsEnabled)
+ $(CentralPackageVersionOverrideEnabled)
+ $(CentralPackageTransitivePinningEnabled)
+ $(NuGetAudit)
+ $(NuGetAuditLevel)
+ $(NuGetAuditMode)
+ $(SdkAnalysisLevel)
+ $(UsingMicrosoftNETSdk)
+ $(RestoreUseLegacyDependencyResolver)
+
+
+
+
+ <_RestoreGraphEntry Include="$([System.Guid]::NewGuid())">
+ ProjectSpec
+ $(MSBuildProjectFullPath)
+ $(MSBuildProjectFullPath)
+ $(_RestoreProjectName)
+ $(_OutputSources)
+ $(RestoreOutputAbsolutePath)
+ $(_OutputFallbackFolders)
+ $(_OutputPackagesPath)
+ $(_CurrentProjectJsonPath)
+ $(RestoreProjectStyle)
+ $(_OutputConfigFilePaths)
+
+
+
+
+ <_RestoreGraphEntry Include="$([System.Guid]::NewGuid())">
+ ProjectSpec
+ $(MSBuildProjectFullPath)
+ $(MSBuildProjectFullPath)
+ $(_RestoreProjectName)
+ $(RestoreProjectStyle)
+ $(MSBuildProjectDirectory)\packages.$(MSBuildProjectName).config
+ $(MSBuildProjectDirectory)\packages.config
+ $(RestorePackagesWithLockFile)
+ $(NuGetLockFilePath)
+ $(RestoreLockedMode)
+ $(_OutputSources)
+ $(SolutionDir)
+ $(_OutputRepositoryPath)
+ $(_OutputConfigFilePaths)
+ $(_OutputPackagesPath)
+ @(_RestoreTargetFrameworksOutputFiltered)
+ $(NuGetAudit)
+ $(NuGetAuditLevel)
+
+
+
+
+ <_RestoreGraphEntry Include="$([System.Guid]::NewGuid())">
+ ProjectSpec
+ $(MSBuildProjectFullPath)
+ $(MSBuildProjectFullPath)
+ $(_RestoreProjectName)
+ $(RestoreProjectStyle)
+ @(_RestoreTargetFrameworksOutputFiltered)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_RestoreGraphEntry Include="$([System.Guid]::NewGuid())">
+ TargetFrameworkInformation
+ $(MSBuildProjectFullPath)
+ $(PackageTargetFallback)
+ $(AssetTargetFallback)
+ $(TargetFramework)
+ $(TargetFrameworkIdentifier)
+ $(TargetFrameworkVersion)
+ $(TargetFrameworkMoniker)
+ $(TargetFrameworkProfile)
+ $(TargetPlatformMoniker)
+ $(TargetPlatformIdentifier)
+ $(TargetPlatformVersion)
+ $(TargetPlatformMinVersion)
+ $(CLRSupport)
+ $(RuntimeIdentifierGraphPath)
+ $(WindowsTargetPlatformMinVersion)
+
+
+
+
+
+
+
+
+
+
+
+
+ <_RestoreProjectPathItems Include="$(_RestoreGraphAbsoluteProjectPaths)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_GenerateRestoreProjectPathWalkOutputs Include="$(MSBuildProjectFullPath)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_RestorePackagesPathOverride>$(RestorePackagesPath)
+
+
+
+
+
+ <_RestorePackagesPathOverride>$(RestoreRepositoryPath)
+
+
+
+
+
+ <_RestoreSourcesOverride>$(RestoreSources)
+
+
+
+
+
+ <_RestoreFallbackFoldersOverride>$(RestoreFallbackFolders)
+
+
+
+
+
+
+
+
+
+
+
+
+ <_TargetFrameworkOverride Condition=" '$(TargetFrameworks)' == '' ">$(TargetFramework)
+
+
+
+
+
+ <_ValidProjectsForRestore Include="$(MSBuildProjectFullPath)" />
+
+
+
+
+
+
+
+
+
+ $(MSBuildExtensionsPath)\Microsoft\Microsoft.NET.Build.Extensions\Microsoft.NET.Build.Extensions.targets
+
+
+
+
+ <_TargetFrameworkVersionWithoutV>$(TargetFrameworkVersion.TrimStart('vV'))
+ $(MSBuildThisFileDirectory)\tools\net9.0\Microsoft.NET.Build.Extensions.Tasks.dll
+ $(MSBuildThisFileDirectory)\tools\net472\Microsoft.NET.Build.Extensions.Tasks.dll
+
+ true
+
+
+
+
+
+
+
+
+
+
+ $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
+ $(MSBuildExtensionsPath)\Microsoft.TestPlatform.targets
+
+
+
+
+
+ Microsoft.TestPlatform.Build.dll
+ $([System.IO.Path]::Combine($(MSBuildThisFileDirectory),"vstest.console.dll"))
+ False
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+ true
+
+
+
+
+
+ true
+
+
+
+
+ $(AfterMicrosoftNETSdkTargets);$(MSBuildThisFileDirectory)Microsoft.Maui.Resizetizer.After.targets
+
+
+
+
+
+ <_Microsoft_Extensions_OptionsAnalyzer Include="@(Analyzer)" Condition="'%(Analyzer.NuGetPackageId)' == 'Microsoft.Extensions.Options'" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_Microsoft_Extensions_Logging_AbstractionsAnalyzer Include="@(Analyzer)" Condition="'%(Analyzer.NuGetPackageId)' == 'Microsoft.Extensions.Logging.Abstractions'" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+ true
+
+
+
+ $(AfterMicrosoftNETSdkTargets);$(MSBuildThisFileDirectory)Microsoft.Maui.Core.After.targets
+
+
+
+
+ true
+
+
+
+
+ <_IsHotRestartDefined>$([System.Text.RegularExpressions.Regex]::IsMatch('$(DefineConstants.Trim())', '(^|;)HOTRESTART($|;)'))
+ HOTRESTART;$(DefineConstants)
+ True
+
+
+
+
+
+
+
+
+
+
+
+ Platforms\
+ $([MSBuild]::EnsureTrailingSlash('$(PlatformsProjectFolder)'))
+
+ <_KeepLaunchProfiles>true
+
+ false
+ $(PlatformsProjectFolder)Android\
+ $([MSBuild]::EnsureTrailingSlash('$(AndroidProjectFolder)'))
+
+ false
+ $(PlatformsProjectFolder)iOS\
+ $([MSBuild]::EnsureTrailingSlash('$(iOSProjectFolder)'))
+
+ false
+ $(PlatformsProjectFolder)MacCatalyst\
+ $([MSBuild]::EnsureTrailingSlash('$(MacCatalystProjectFolder)'))
+
+ false
+ $(PlatformsProjectFolder)Windows\
+ $([MSBuild]::EnsureTrailingSlash('$(WindowsProjectFolder)'))
+
+ false
+ $(PlatformsProjectFolder)Tizen\
+ $([MSBuild]::EnsureTrailingSlash('$(TizenProjectFolder)'))
+
+
+
+
+
+
+
+
+
+ $(AndroidProjectFolder)AndroidManifest.xml
+ $(AndroidProjectFolder)Resources
+ $(AndroidProjectFolder)Assets
+
+
+ $(iOSProjectFolder)Resources
+ $(iOSProjectFolder)Entitlements.plist
+ <_SingleProjectiOSExcludes>$(iOSProjectFolder)/**/.*/**
+
+
+ $(MacCatalystProjectFolder)Resources
+ $(MacCatalystProjectFolder)Entitlements.plist
+ <_SingleProjectMacCatalystExcludes>$(MacCatalystProjectFolder)/**/.*/**
+
+
+ $(WindowsProjectFolder)app.manifest
+ $(WindowsProjectFolder)Package.appxmanifest
+ False
+ False
+ <_SingleProjectWindowsExcludes>$(WindowsProjectFolder)/**/.*/**
+
+
+ $(TizenProjectFolder)tizen-manifest.xml
+ $(TizenProjectFolder)res
+ $(TizenProjectFolder)shared
+
+
+
+
+
+ $(AfterMicrosoftNETSdkTargets);$(MSBuildThisFileDirectory)Microsoft.Maui.Controls.Build.Tasks.After.targets
+
+
+
+
+
+ true
+
+
+
+ <_DirectoryBuildTargetsFile Condition="'$(_DirectoryBuildTargetsFile)' == ''">Directory.Build.targets
+ <_DirectoryBuildTargetsBasePath Condition="'$(_DirectoryBuildTargetsBasePath)' == ''">$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildProjectDirectory), '$(_DirectoryBuildTargetsFile)'))
+ $([System.IO.Path]::Combine('$(_DirectoryBuildTargetsBasePath)', '$(_DirectoryBuildTargetsFile)'))
+
+
+
+
+
+
+
+
+
+// <autogenerated />
+using System%3b
+using System.Reflection%3b
+[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute("$(TargetFrameworkMoniker)", FrameworkDisplayName = "$(TargetFrameworkMonikerDisplayName)")]
+
+
+
+
+ true
+
+ true
+ true
+
+ $([System.Globalization.CultureInfo]::CurrentUICulture.Name)
+
+
+
+
+ <_ExplicitReference Include="$(FrameworkPathOverride)\mscorlib.dll" />
+
+
+
+
+
+
+
+
+
+ TargetFramework
+ TargetFrameworks
+
+
+ true
+
+
+
+
+
+
+
+
+ <_MainReferenceTargetForBuild Condition="'$(BuildProjectReferences)' == '' or '$(BuildProjectReferences)' == 'true'">.projectReferenceTargetsOrDefaultTargets
+ <_MainReferenceTargetForBuild Condition="'$(_MainReferenceTargetForBuild)' == ''">GetTargetPath
+ $(_MainReferenceTargetForBuild);GetNativeManifest;$(_RecursiveTargetForContentCopying);$(ProjectReferenceTargetsForBuild)
+
+ <_MainReferenceTargetForPublish Condition="'$(NoBuild)' == 'true'">GetTargetPath
+ <_MainReferenceTargetForPublish Condition="'$(NoBuild)' != 'true'">$(_MainReferenceTargetForBuild)
+ GetTargetFrameworks;$(_MainReferenceTargetForPublish);GetNativeManifest;GetCopyToPublishDirectoryItems;$(ProjectReferenceTargetsForPublish)
+
+ $(ProjectReferenceTargetsForBuild);$(ProjectReferenceTargetsForPublish)
+ $(ProjectReferenceTargetsForRebuild);$(ProjectReferenceTargetsForPublish)
+ GetCopyToPublishDirectoryItems;$(ProjectReferenceTargetsForGetCopyToPublishDirectoryItems)
+
+
+ .default;$(ProjectReferenceTargetsForBuild)
+
+
+ Clean;$(ProjectReferenceTargetsForClean)
+ $(ProjectReferenceTargetsForClean);$(ProjectReferenceTargetsForBuild);$(ProjectReferenceTargetsForRebuild)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(MSBuildThisFileDirectory)..\tools\
+ net9.0
+ net472
+ $(MicrosoftNETBuildTasksDirectoryRoot)$(MicrosoftNETBuildTasksTFM)\
+ $(MicrosoftNETBuildTasksDirectory)Microsoft.NET.Build.Tasks.dll
+
+ Microsoft.NETCore.App;NETStandard.Library
+
+
+
+ <_IsExecutable Condition="'$(OutputType)' == 'Exe' or '$(OutputType)'=='WinExe'">true
+ $(_IsExecutable)
+
+
+
+ netcoreapp2.2
+
+
+ false
+ DotnetTool
+ $(RuntimeIdentifiers);$(PackAsToolShimRuntimeIdentifiers)
+
+
+ Preview
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+ $(MSBuildProjectExtensionsPath)/project.assets.json
+ $([MSBuild]::NormalizePath($(MSBuildProjectDirectory), $(ProjectAssetsFile)))
+
+ $(IntermediateOutputPath)$(MSBuildProjectName).assets.cache
+ $([MSBuild]::NormalizePath($(MSBuildProjectDirectory), $(ProjectAssetsCacheFile)))
+
+ false
+
+ false
+
+ true
+ $(IntermediateOutputPath)NuGet\
+ true
+ $(TargetPlatformIdentifier),Version=v$([System.Version]::Parse('$(TargetPlatformMinVersion)').ToString(3))
+ $(TargetFrameworkMoniker)
+ true
+
+ false
+
+ true
+
+
+
+ <_NugetTargetMonikerAndRID Condition="'$(RuntimeIdentifier)' == ''">$(NuGetTargetMoniker)
+ <_NugetTargetMonikerAndRID Condition="'$(RuntimeIdentifier)' != ''">$(NuGetTargetMoniker)/$(RuntimeIdentifier)
+
+
+
+
+
+
+
+
+ $(ResolveAssemblyReferencesDependsOn);
+ ResolvePackageDependenciesForBuild;
+ _HandlePackageFileConflicts;
+
+
+ ResolvePackageDependenciesForBuild;
+ _HandlePackageFileConflicts;
+ $(PrepareResourcesDependsOn)
+
+
+
+
+
+ $(RootNamespace)
+
+
+ $(AssemblyName)
+
+
+ $(MSBuildProjectDirectory)
+
+
+ $(TargetFileName)
+
+
+ $(MSBuildProjectFile)
+
+
+
+
+
+ true
+
+
+
+
+
+ ResolveLockFileReferences;
+ ResolveLockFileAnalyzers;
+ ResolveLockFileCopyLocalFiles;
+ ResolveRuntimePackAssets;
+ RunProduceContentAssets;
+ IncludeTransitiveProjectReferences
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_RoslynApiVersion>$([System.Version]::Parse(%(_CodeAnalysisIdentity.Version)).Major).$([System.Version]::Parse(%(_CodeAnalysisIdentity.Version)).Minor)
+ roslyn$(_RoslynApiVersion)
+
+
+
+
+
+ false
+
+
+ true
+
+
+ true
+
+
+
+ true
+
+
+ <_PackAsToolShimRuntimeIdentifiers Condition="@(_PackAsToolShimRuntimeIdentifiers) ==''" Include="$(PackAsToolShimRuntimeIdentifiers)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_NativeRestoredAppHostNETCore Include="@(NativeCopyLocalItems)" Condition="'%(NativeCopyLocalItems.FileName)%(NativeCopyLocalItems.Extension)' == '$(_DotNetAppHostExecutableName)'" />
+
+
+ <_ApphostsForShimRuntimeIdentifiers Include="@(_ApphostsForShimRuntimeIdentifiersResolvePackageAssets)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ResolvedCopyLocalBuildAssets Include="@(RuntimeCopyLocalItems)" Condition="'%(RuntimeCopyLocalItems.CopyLocal)' == 'true'" />
+ <_ResolvedCopyLocalBuildAssets Include="@(ResourceCopyLocalItems)" Condition="'%(ResourceCopyLocalItems.CopyLocal)' == 'true'" />
+
+ <_ResolvedCopyLocalBuildAssets Include="@(NativeCopyLocalItems)" Exclude="@(_NativeRestoredAppHostNETCore)" Condition="'%(NativeCopyLocalItems.CopyLocal)' == 'true'" />
+ <_ResolvedCopyLocalBuildAssets Include="@(RuntimeTargetsCopyLocalItems)" Condition="'%(RuntimeTargetsCopyLocalItems.CopyLocal)' == 'true'" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ true
+ true
+ true
+
+
+
+
+ $(DefaultItemExcludes);$(BaseOutputPath)/**
+
+ $(DefaultItemExcludes);$(BaseIntermediateOutputPath)/**
+
+ $(DefaultItemExcludes);**/*.user
+ $(DefaultItemExcludes);**/*.*proj
+ $(DefaultItemExcludes);**/*.sln
+ $(DefaultItemExcludes);**/*.vssscc
+ $(DefaultItemExcludes);**/.DS_Store
+
+ $(DefaultExcludesInProjectFolder);$(DefaultItemExcludesInProjectFolder);**/.*/**
+
+
+
+
+ 1.6.1
+
+ 2.0.3
+
+
+
+
+
+ true
+ false
+ <_TargetLatestRuntimePatchIsDefault>true
+
+
+ true
+
+
+
+
+ all
+ true
+
+
+ all
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(_TargetFrameworkVersionWithoutV)
+
+
+
+
+
+
+
+ https://aka.ms/sdkimplicitrefs
+
+
+
+
+
+
+
+
+
+
+ <_PackageReferenceToAdd Remove="@(_PackageReferenceToAdd)" />
+
+
+
+ false
+
+
+
+
+
+ https://aka.ms/sdkimplicititems
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_WindowsDesktopTransitiveFrameworkReference Include="@(TransitiveFrameworkReference)" Condition="'%(Identity)' == 'Microsoft.WindowsDesktop.App' Or
'%(Identity)' == 'Microsoft.WindowsDesktop.App.WPF' Or
'%(Identity)' == 'Microsoft.WindowsDesktop.App.WindowsForms'" />
+
+
+
+
+
+
+
+
+
+
+
+
+ $([MSBuild]::EnsureTrailingSlash(%(LinkBase)))
+
+ %(LinkBase)%(RecursiveDir)%(Filename)%(Extension)
+
+
+ $([MSBuild]::EnsureTrailingSlash(%(LinkBase)))
+ %(LinkBase)%(RecursiveDir)%(Filename)%(Extension)
+
+
+ $([MSBuild]::EnsureTrailingSlash(%(LinkBase)))
+ %(LinkBase)%(RecursiveDir)%(Filename)%(Extension)
+
+
+ $([MSBuild]::EnsureTrailingSlash(%(LinkBase)))
+ %(LinkBase)%(RecursiveDir)%(Filename)%(Extension)
+
+
+ $([MSBuild]::EnsureTrailingSlash(%(LinkBase)))
+ %(LinkBase)%(RecursiveDir)%(Filename)%(Extension)
+
+
+ $([MSBuild]::EnsureTrailingSlash(%(LinkBase)))
+ %(LinkBase)%(RecursiveDir)%(Filename)%(Extension)
+
+
+ $([MSBuild]::EnsureTrailingSlash(%(LinkBase)))
+ %(LinkBase)%(RecursiveDir)%(Filename)%(Extension)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+ $(ResolveAssemblyReferencesDependsOn);
+ ResolveTargetingPackAssets;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ true
+
+
+ <_NuGetRestoreSupported Condition="('$(Language)' == 'C++' and '$(_EnablePackageReferencesInVCProjects)' != 'true')">false
+
+
+ <_PackAsToolShimRuntimeIdentifiers Condition="@(_PackAsToolShimRuntimeIdentifiers) ==''" Include="$(PackAsToolShimRuntimeIdentifiers)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(RuntimeIdentifier)
+ $(DefaultAppHostRuntimeIdentifier)
+
+
+
+
+
+
+
+
+
+
+ true
+ true
+ false
+
+
+
+ [%(_PackageToDownload.Version)]
+
+
+
+
+
+
+
+ <_ImplicitPackageReference Remove="@(PackageReference)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ %(ResolvedTargetingPack.PackageDirectory)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ApphostsForShimRuntimeIdentifiers Include="%(_ApphostsForShimRuntimeIdentifiersGetPackageDirectory.PackageDirectory)\%(_ApphostsForShimRuntimeIdentifiersGetPackageDirectory.PathInPackage)">
+ %(_ApphostsForShimRuntimeIdentifiersGetPackageDirectory.RuntimeIdentifier)
+
+
+
+
+ %(ResolvedAppHostPack.PackageDirectory)\%(ResolvedAppHostPack.PathInPackage)
+
+
+
+ @(ResolvedAppHostPack->'%(Path)')
+
+
+
+ %(ResolvedSingleFileHostPack.PackageDirectory)\%(ResolvedSingleFileHostPack.PathInPackage)
+
+
+
+ @(ResolvedSingleFileHostPack->'%(Path)')
+
+
+
+ %(ResolvedComHostPack.PackageDirectory)\%(ResolvedComHostPack.PathInPackage)
+
+
+
+ @(ResolvedComHostPack->'%(Path)')
+
+
+
+ %(ResolvedIjwHostPack.PackageDirectory)\%(ResolvedIjwHostPack.PathInPackage)
+
+
+
+ @(ResolvedIjwHostPack->'%(Path)')
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ false
+
+
+
+
+
+
+
+
+
+
+
+ $([MSBuild]::Unescape($(PackageConflictPreferredPackages)))
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ExistingReferenceAssembliesPackageReference Include="@(PackageReference)" Condition="'%(PackageReference.Identity)' == 'Microsoft.NETFramework.ReferenceAssemblies'" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_Parameter1>$(UserSecretsId.Trim())
+
+
+
+
+
+
+
+
+
+ $(_IsNETCoreOrNETStandard)
+
+
+ true
+ false
+ true
+ $(MSBuildProjectDirectory)/runtimeconfig.template.json
+ true
+ true
+ <_GenerateRuntimeConfigurationPropertyInputsCache Condition="'$(_GenerateRuntimeConfigurationPropertyInputsCache)' == ''">$(IntermediateOutputPath)$(MSBuildProjectName).genruntimeconfig.cache
+ <_GenerateRuntimeConfigurationPropertyInputsCache>$([MSBuild]::NormalizePath($(MSBuildProjectDirectory), $(_GenerateRuntimeConfigurationPropertyInputsCache)))
+ <_GeneratePublishDependencyFilePropertyInputsCache Condition="'$(_GeneratePublishDependencyFilePropertyInputsCache)' == ''">$(IntermediateOutputPath)$(MSBuildProjectName).genpublishdeps.cache
+ <_GeneratePublishDependencyFilePropertyInputsCache>$([MSBuild]::NormalizePath($(MSBuildProjectDirectory), $(_GeneratePublishDependencyFilePropertyInputsCache)))
+ <_GenerateSingleFileBundlePropertyInputsCache Condition="'$(_GenerateSingleFileBundlePropertyInputsCache)' == ''">$(IntermediateOutputPath)$(MSBuildProjectName).genbundle.cache
+ <_GenerateSingleFileBundlePropertyInputsCache>$([MSBuild]::NormalizePath($(MSBuildProjectDirectory), $(_GenerateSingleFileBundlePropertyInputsCache)))
+
+
+
+ <_UseRidGraphWasSpecified Condition="'$(UseRidGraph)' != ''">true
+
+
+ false
+ true
+
+
+ $(BundledRuntimeIdentifierGraphFile)
+
+ $([System.IO.Path]::GetDirectoryName($(BundledRuntimeIdentifierGraphFile)))/PortableRuntimeIdentifierGraph.json
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+ false
+
+
+ $(AssemblyName).deps.json
+ $(TargetDir)$(ProjectDepsFileName)
+ $(AssemblyName).runtimeconfig.json
+ $(TargetDir)$(ProjectRuntimeConfigFileName)
+ $(TargetDir)$(AssemblyName).runtimeconfig.dev.json
+ true
+
+
+
+
+
+ true
+ true
+
+
+
+ CurrentArchitecture
+ CurrentRuntime
+
+
+ <_NativeLibraryPrefix Condition="'$(_NativeLibraryPrefix)' == '' and !$(RuntimeIdentifier.StartsWith('win'))">lib
+ <_NativeLibraryExtension Condition="'$(_NativeLibraryExtension)' == '' and $(RuntimeIdentifier.StartsWith('win'))">.dll
+ <_NativeLibraryExtension Condition="'$(_NativeLibraryExtension)' == '' and $(RuntimeIdentifier.StartsWith('osx'))">.dylib
+ <_NativeLibraryExtension Condition="'$(_NativeLibraryExtension)' == ''">.so
+ <_NativeExecutableExtension Condition="'$(_NativeExecutableExtension)' == '' and ($(RuntimeIdentifier.StartsWith('win')) or $(DefaultAppHostRuntimeIdentifier.StartsWith('win')))">.exe
+ <_ComHostLibraryExtension Condition="'$(_ComHostLibraryExtension)' == '' and ($(RuntimeIdentifier.StartsWith('win')) or $(DefaultAppHostRuntimeIdentifier.StartsWith('win')))">.dll
+ <_IjwHostLibraryExtension Condition="'$(_IjwHostLibraryExtension)' == '' and ($(RuntimeIdentifier.StartsWith('win')) or $(DefaultAppHostRuntimeIdentifier.StartsWith('win')))">.dll
+ <_DotNetHostExecutableName>dotnet$(_NativeExecutableExtension)
+ <_DotNetAppHostExecutableNameWithoutExtension>apphost
+ <_DotNetAppHostExecutableName>$(_DotNetAppHostExecutableNameWithoutExtension)$(_NativeExecutableExtension)
+ <_DotNetSingleFileHostExecutableNameWithoutExtension>singlefilehost
+ <_DotNetComHostLibraryNameWithoutExtension>comhost
+ <_DotNetComHostLibraryName>$(_DotNetComHostLibraryNameWithoutExtension)$(_ComHostLibraryExtension)
+ <_DotNetIjwHostLibraryNameWithoutExtension>Ijwhost
+ <_DotNetIjwHostLibraryName>$(_DotNetIjwHostLibraryNameWithoutExtension)$(_IjwHostLibraryExtension)
+ <_DotNetHostPolicyLibraryName>$(_NativeLibraryPrefix)hostpolicy$(_NativeLibraryExtension)
+ <_DotNetHostFxrLibraryName>$(_NativeLibraryPrefix)hostfxr$(_NativeLibraryExtension)
+
+
+
+
+
+ <_ExcludeFromPublishPackageReference Include="@(PackageReference)" Condition="('%(PackageReference.Publish)' == 'false')" />
+
+
+
+
+
+ Microsoft.NETCore.App
+
+
+
+
+ <_DefaultUserProfileRuntimeStorePath>$(HOME)
+ <_DefaultUserProfileRuntimeStorePath Condition="$([MSBuild]::IsOSPlatform(`Windows`))">$(USERPROFILE)
+ <_DefaultUserProfileRuntimeStorePath>$([System.IO.Path]::Combine($(_DefaultUserProfileRuntimeStorePath), '.dotnet', 'store'))
+ $(_DefaultUserProfileRuntimeStorePath)
+
+
+ true
+
+
+ true
+
+
+ true
+
+
+
+ false
+ true
+
+
+
+ true
+
+
+ true
+
+
+ $(AvailablePlatforms),ARM32
+
+
+ $(AvailablePlatforms),ARM64
+
+
+ $(AvailablePlatforms),ARM64
+
+
+
+ false
+
+
+
+ true
+
+
+
+
+ <_ProjectTypeRequiresBinaryFormatter Condition="'$(UseWindowsForms)' == 'true' AND $([MSBuild]::VersionLessThanOrEquals($(TargetFrameworkVersion), '8.0'))">true
+ <_ProjectTypeRequiresBinaryFormatter Condition="'$(UseWPF)' == 'true' AND $([MSBuild]::VersionLessThanOrEquals($(TargetFrameworkVersion), '8.0'))">true
+
+ <_BinaryFormatterObsoleteAsError>true
+
+ true
+ false
+
+
+
+ _CheckForBuildWithNoBuild;
+ $(CoreBuildDependsOn);
+ GenerateBuildDependencyFile;
+ GenerateBuildRuntimeConfigurationFiles
+
+
+
+
+ _SdkBeforeClean;
+ $(CoreCleanDependsOn)
+
+
+
+
+ _SdkBeforeRebuild;
+ $(RebuildDependsOn)
+
+
+
+
+ true
+
+
+ $(NuGetPackageRoot)\microsoft.net.sdk.compilers.toolset\$(NETCoreSdkVersion)
+ <_NeedToDownloadMicrosoftNetSdkCompilersToolsetPackage>true
+ <_MicrosoftNetSdkCompilersToolsetPackageRootEmpty Condition="'$(NuGetPackageRoot)' == ''">true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1.0.0
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ValidRuntimeIdentifierPlatformsForAssets Include="@(_KnownRuntimeIdentiferPlatforms)" />
+
+ <_ValidRuntimeIdentifierPlatformsForAssets Include="@(_KnownRuntimeIdentifierPlatformsForTargetFramework)" Exclude="@(_ExcludedKnownRuntimeIdentiferPlatforms)" />
+
+
+
+
+
+
+
+
+
+
+
+ <_GenerateRuntimeConfigurationPropertyInputsCacheToHash Include="@(AdditionalProbingPath->'%(Identity)')" />
+ <_GenerateRuntimeConfigurationPropertyInputsCacheToHash Include="$(EnableDynamicLoading)" />
+ <_GenerateRuntimeConfigurationPropertyInputsCacheToHash Include="$(RollForward)" />
+ <_GenerateRuntimeConfigurationPropertyInputsCacheToHash Include="@(RuntimeHostConfigurationOption->'%(Identity)%(Value)')" />
+ <_GenerateRuntimeConfigurationPropertyInputsCacheToHash Include="$(RuntimeIdentifier)" />
+ <_GenerateRuntimeConfigurationPropertyInputsCacheToHash Include="$(SelfContained)" />
+ <_GenerateRuntimeConfigurationPropertyInputsCacheToHash Include="$(TargetFramework)" />
+ <_GenerateRuntimeConfigurationPropertyInputsCacheToHash Include="$(UserRuntimeConfig)" />
+ <_GenerateRuntimeConfigurationPropertyInputsCacheToHash Include="$(_WriteIncludedFrameworks)" />
+
+
+
+
+
+
+
+
+
+
+
+
+ <_IsRollForwardSupported Condition="'$(_TargetFrameworkVersionWithoutV)' >= '3.0'">true
+ LatestMinor
+
+
+
+
+ <_WriteIncludedFrameworks Condition="'$(SelfContained)' == 'true' and '$(_TargetFrameworkVersionWithoutV)' >= '3.1'">true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_CleaningWithoutRebuilding>true
+ false
+
+
+
+
+ <_CleaningWithoutRebuilding>false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(CompileDependsOn);
+ _CreateAppHost;
+ _CreateComHost;
+ _GetIjwHostPaths;
+
+
+
+
+
+ <_UseWindowsGraphicalUserInterface Condition="($(RuntimeIdentifier.StartsWith('win')) or $(DefaultAppHostRuntimeIdentifier.StartsWith('win'))) and '$(OutputType)'=='WinExe'">true
+ <_EnableMacOSCodeSign Condition="'$(_EnableMacOSCodeSign)' == '' and $([MSBuild]::IsOSPlatform(`OSX`)) and Exists('/usr/bin/codesign') and
($(RuntimeIdentifier.StartsWith('osx')) or $(AppHostRuntimeIdentifier.StartsWith('osx')))">true
+ <_UseSingleFileHostForPublish Condition="'$(PublishSingleFile)' == 'true' and
'$(SelfContained)' == 'true' and
'$(SingleFileHostSourcePath)' != '' and
'$(TargetFrameworkIdentifier)' == '.NETCoreApp' and
$([MSBuild]::VersionGreaterThanOrEquals($(TargetFrameworkVersion), 5.0))">true
+ <_DisableCetCompat Condition="'$(CetCompat)' == 'false'">true
+
+ AppRelative
+ <_UpdateAppHostForPublish Condition="'$(_UseSingleFileHostForPublish)' != 'true' and
('$(AppHostRelativeDotNet)' != '' or '$(AppHostDotNetSearch)' != '')">true
+
+
+
+
+
+
+
+
+
+
+
+
+ @(_NativeRestoredAppHostNETCore)
+
+
+ $([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)apphost$(_NativeExecutableExtension)'))
+ $([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)apphost_publish$(_NativeExecutableExtension)'))
+ $([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)singlefilehost$(_NativeExecutableExtension)'))
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(AssemblyName).comhost$(_ComHostLibraryExtension)
+ $([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)$(ComHostFileName)'))
+
+
+
+
+
+
+
+
+
+
+
+ <_CopyAndRenameDotnetHost Condition="'$(_CopyAndRenameDotnetHost)' == ''">true
+
+
+
+ $(AssemblyName)$(_NativeExecutableExtension)
+ PreserveNewest
+ PreserveNewest
+
+
+
+
+
+ PreserveNewest
+ Never
+
+
+
+
+ $(AssemblyName)$(_NativeExecutableExtension)
+ PreserveNewest
+
+ Always
+
+
+
+
+ $(AssemblyName).$(_DotNetComHostLibraryName)
+ PreserveNewest
+ PreserveNewest
+
+
+ %(FileName)%(Extension)
+ PreserveNewest
+ PreserveNewest
+
+
+
+
+ $(_DotNetIjwHostLibraryName)
+ PreserveNewest
+ PreserveNewest
+
+
+
+
+
+
+ <_FrameworkReferenceAssemblies Include="@(ReferencePath)" Condition="(%(ReferencePath.FrameworkFile) == 'true' or
%(ReferencePath.ResolvedFrom) == 'ImplicitlyExpandDesignTimeFacades')
and ('%(ReferencePath.NuGetSourceType)' == '' or
'%(ReferencePath.NuGetIsFrameworkReference)' == 'true')" />
+
+ <_ReferenceOnlyAssemblies Include="@(ReferencePath)" Exclude="@(_FrameworkReferenceAssemblies)" Condition="%(ReferencePath.CopyLocal) != 'true' and
%(ReferencePath.NuGetSourceType) == ''" />
+ <_ReferenceAssemblies Include="@(_FrameworkReferenceAssemblies)" />
+ <_ReferenceAssemblies Include="@(_ReferenceOnlyAssemblies)" />
+
+
+
+
+
+
+
+ true
+
+
+ true
+
+
+
+
+
+
+
+
+ $(StartWorkingDirectory)
+
+
+
+
+ $(StartProgram)
+ $(StartArguments)
+
+
+
+
+
+ dotnet
+ <_NetCoreRunArguments>exec "$(TargetPath)"
+ $(_NetCoreRunArguments) $(StartArguments)
+ $(_NetCoreRunArguments)
+
+
+ $(TargetDir)$(AssemblyName)$(_NativeExecutableExtension)
+ $(StartArguments)
+
+
+
+
+ $(TargetPath)
+ $(StartArguments)
+
+
+ mono
+ "$(TargetPath)" $(StartArguments)
+
+
+
+
+
+ $([System.IO.Path]::GetFullPath($([System.IO.Path]::Combine('$(MSBuildProjectDirectory)', '$(RunWorkingDirectory)'))))
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(CreateSatelliteAssembliesDependsOn);
+ CoreGenerateSatelliteAssemblies
+
+
+
+
+
+
+ <_AssemblyInfoFile>$(IntermediateOutputPath)%(_SatelliteAssemblyResourceInputs.Culture)\$(TargetName).resources.cs
+ <_OutputAssembly>$(IntermediateOutputPath)%(_SatelliteAssemblyResourceInputs.Culture)\$(TargetName).resources.dll
+
+
+
+ <_Parameter1>%(_SatelliteAssemblyResourceInputs.Culture)
+
+
+
+
+
+
+ true
+
+
+ <_SatelliteAssemblyReferences Remove="@(_SatelliteAssemblyReferences)" />
+ <_SatelliteAssemblyReferences Include="@(ReferencePath)" Condition="'%(Filename)' == 'mscorlib' or '%(Filename)' == 'netstandard' or '%(Filename)' == 'System.Runtime' " />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(TargetFrameworkIdentifier)
+ $(_TargetFrameworkVersionWithoutV)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+ false
+
+
+
+ false
+
+
+
+ <_UseAttributeForTargetFrameworkInfoPropertyNames Condition="$([MSBuild]::VersionGreaterThanOrEquals($(MSBuildVersion), '17.0'))">true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_SourceLinkSdkSubDir>build
+ <_SourceLinkSdkSubDir Condition="'$(IsCrossTargetingBuild)' == 'true'">buildMultiTargeting
+
+ true
+
+
+
+
+
+
+
+ local
+
+
+
+
+
+
+
+
+
+
+
+ git
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(RepositoryUrl)
+ $(ScmRepositoryUrl)
+
+
+
+ %(SourceRoot.ScmRepositoryUrl)
+
+
+
+
+
+
+
+ <_SourceLinkFilePath>$(IntermediateOutputPath)$(MSBuildProjectName).sourcelink.json
+
+
+
+
+
+
+
+
+ <_GenerateSourceLinkFileBeforeTargets>Link
+ <_GenerateSourceLinkFileDependsOnTargets>ComputeLinkSwitches
+
+
+ <_GenerateSourceLinkFileBeforeTargets>CoreCompile
+ <_GenerateSourceLinkFileDependsOnTargets />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ %(Link.AdditionalOptions) /sourcelink:"$(SourceLink)"
+
+
+
+
+
+
+
+
+ <_SourceLinkGitHubAssemblyFile Condition="'$(MSBuildRuntimeType)' != 'Core'">$(MSBuildThisFileDirectory)..\tools\net472\Microsoft.SourceLink.GitHub.dll
+ <_SourceLinkGitHubAssemblyFile Condition="'$(MSBuildRuntimeType)' == 'Core'">$(MSBuildThisFileDirectory)..\tools\core\Microsoft.SourceLink.GitHub.dll
+
+
+
+
+ $(SourceLinkUrlInitializerTargets);_InitializeGitHubSourceLinkUrl
+ $(SourceControlManagerUrlTranslationTargets);TranslateGitHubUrlsInSourceControlInformation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_TranslatedSourceRoot Remove="@(_TranslatedSourceRoot)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_SourceLinkGitLabAssemblyFile Condition="'$(MSBuildRuntimeType)' != 'Core'">$(MSBuildThisFileDirectory)..\tools\net472\Microsoft.SourceLink.GitLab.dll
+ <_SourceLinkGitLabAssemblyFile Condition="'$(MSBuildRuntimeType)' == 'Core'">$(MSBuildThisFileDirectory)..\tools\core\Microsoft.SourceLink.GitLab.dll
+
+
+
+
+ $(SourceLinkUrlInitializerTargets);_InitializeGitLabSourceLinkUrl
+ $(SourceControlManagerUrlTranslationTargets);TranslateGitLabUrlsInSourceControlInformation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_TranslatedSourceRoot Remove="@(_TranslatedSourceRoot)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_SourceLinkAzureReposGitAssemblyFile Condition="'$(MSBuildRuntimeType)' != 'Core'">$(MSBuildThisFileDirectory)..\tools\net472\Microsoft.SourceLink.AzureRepos.Git.dll
+ <_SourceLinkAzureReposGitAssemblyFile Condition="'$(MSBuildRuntimeType)' == 'Core'">$(MSBuildThisFileDirectory)..\tools\core\Microsoft.SourceLink.AzureRepos.Git.dll
+
+
+
+
+ $(SourceLinkUrlInitializerTargets);_InitializeAzureReposGitSourceLinkUrl
+ $(SourceControlManagerUrlTranslationTargets);TranslateAzureReposGitUrlsInSourceControlInformation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_TranslatedSourceRoot Remove="@(_TranslatedSourceRoot)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_SourceLinkBitbucketAssemblyFile Condition="'$(MSBuildRuntimeType)' != 'Core'">$(MSBuildThisFileDirectory)..\tools\net472\Microsoft.SourceLink.Bitbucket.Git.dll
+ <_SourceLinkBitbucketAssemblyFile Condition="'$(MSBuildRuntimeType)' == 'Core'">$(MSBuildThisFileDirectory)..\tools\core\Microsoft.SourceLink.Bitbucket.Git.dll
+
+
+
+
+ $(SourceLinkUrlInitializerTargets);_InitializeBitbucketGitSourceLinkUrl
+ $(SourceControlManagerUrlTranslationTargets);TranslateBitbucketGitUrlsInSourceControlInformation
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_TranslatedSourceRoot Remove="@(_TranslatedSourceRoot)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ .NET Standard $(_TargetFrameworkVersionWithoutV)
+ .NET Core $(_TargetFrameworkVersionWithoutV)
+ .NET $(_TargetFrameworkVersionWithoutV)
+ <_TargetFrameworkDirectories />
+
+
+
+ true
+
+
+
+
+
+
+ $(CommonOutputGroupsDependsOn);
+
+
+
+
+ $(DesignerRuntimeImplementationProjectOutputGroupDependsOn);
+ _GenerateDesignerDepsFile;
+ _GenerateDesignerRuntimeConfigFile;
+ GetCopyToOutputDirectoryItems;
+ _GatherDesignerShadowCopyFiles;
+
+ <_DesignerDepsFileName>$(AssemblyName).designer.deps.json
+ <_DesignerRuntimeConfigFileName>$(AssemblyName).designer.runtimeconfig.json
+ <_DesignerDepsFilePath>$(IntermediateOutputPath)$(_DesignerDepsFileName)
+ <_DesignerRuntimeConfigFilePath>$(IntermediateOutputPath)$(_DesignerRuntimeConfigFileName)
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_DesignerHostConfigurationOption Include="Microsoft.NETCore.DotNetHostPolicy.SetAppPaths" Value="true" />
+
+
+
+
+
+
+
+
+
+
+ <_DesignerShadowCopy Include="@(ReferenceCopyLocalPaths)" />
+
+ <_DesignerShadowCopy Remove="@(_ResolvedCopyLocalBuildAssets)" Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp'" />
+
+ <_DesignerShadowCopy Remove="@(RuntimePackAsset)" Condition="'%(RuntimePackAsset.RuntimePackAlwaysCopyLocal)' != 'true'" />
+
+
+
+
+
+
+
+
+
+
+ $(IntermediateOutputPath)$(MSBuildProjectName).AssemblyInfo$(DefaultLanguageSourceExtension)
+ true
+
+
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+
+
+
+
+
+
+ <_InformationalVersionContainsPlus>false
+ <_InformationalVersionContainsPlus Condition="$(InformationalVersion.Contains('+'))">true
+ $(InformationalVersion)+$(SourceRevisionId)
+ $(InformationalVersion).$(SourceRevisionId)
+
+
+
+
+
+ <_Parameter1>$(Company)
+
+
+ <_Parameter1>$(Configuration)
+
+
+ <_Parameter1>$(Copyright)
+
+
+ <_Parameter1>$(Description)
+
+
+ <_Parameter1>$(FileVersion)
+
+
+ <_Parameter1>$(InformationalVersion)
+
+
+ <_Parameter1>$(Product)
+
+
+ <_Parameter1>$(Trademark)
+
+
+ <_Parameter1>$(AssemblyTitle)
+
+
+ <_Parameter1>$(AssemblyVersion)
+
+
+ <_Parameter1>RepositoryUrl
+ <_Parameter2 Condition="'$(RepositoryUrl)' != ''">$(RepositoryUrl)
+ <_Parameter2 Condition="'$(RepositoryUrl)' == ''">$(PrivateRepositoryUrl)
+
+
+ <_Parameter1>$(NeutralLanguage)
+
+
+ %(InternalsVisibleTo.PublicKey)
+
+
+ <_Parameter1 Condition="'%(InternalsVisibleTo.Key)' != ''">%(InternalsVisibleTo.Identity), PublicKey=%(InternalsVisibleTo.Key)
+ <_Parameter1 Condition="'%(InternalsVisibleTo.Key)' == '' and '$(PublicKey)' != ''">%(InternalsVisibleTo.Identity), PublicKey=$(PublicKey)
+ <_Parameter1 Condition="'%(InternalsVisibleTo.Key)' == '' and '$(PublicKey)' == ''">%(InternalsVisibleTo.Identity)
+
+
+ <_Parameter1>%(AssemblyMetadata.Identity)
+ <_Parameter2>%(AssemblyMetadata.Value)
+
+
+
+
+
+ <_Parameter1>$(TargetPlatformIdentifier)$(TargetPlatformVersion)
+
+
+
+
+ <_Parameter1>$(TargetPlatformIdentifier)$(SupportedOSPlatformVersion)
+
+
+ <_Parameter1>$(TargetPlatformIdentifier)
+
+
+
+
+
+
+
+
+
+ $(IntermediateOutputPath)$(MSBuildProjectName).AssemblyInfoInputs.cache
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(AssemblyVersion)
+ $(Version)
+
+
+
+
+
+
+
+
+ $(IntermediateOutputPath)$(MSBuildProjectName).GlobalUsings.g$(DefaultLanguageSourceExtension)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_GenerateSupportedRuntimeIntermediateAppConfig>$(IntermediateOutputPath)$(TargetFileName).withSupportedRuntime.config
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_AllProjects Include="$(AdditionalProjects.Split('%3B'))" />
+ <_AllProjects Include="$(MSBuildProjectFullPath)" />
+
+
+
+
+
+
+
+
+
+ %(PackageReference.Identity)
+ %(PackageReference.Version)
+
+ StorePackageName=%(PackageReference.Identity);
+ StorePackageVersion=%(PackageReference.Version);
+ ComposeWorkingDir=$(ComposeWorkingDir);
+ PublishDir=$(PublishDir);
+ StoreStagingDir=$(StoreStagingDir);
+ TargetFramework=$(TargetFramework);
+ RuntimeIdentifier=$(RuntimeIdentifier);
+ JitPath=$(JitPath);
+ Crossgen=$(Crossgen);
+ SkipUnchangedFiles=$(SkipUnchangedFiles);
+ PreserveStoreLayout=$(PreserveStoreLayout);
+ CreateProfilingSymbols=$(CreateProfilingSymbols);
+ StoreSymbolsStagingDir=$(StoreSymbolsStagingDir);
+ DisableImplicitFrameworkReferences=false;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_StoreArtifactContent>
+@(ListOfPackageReference)
+
+]]>
+
+
+
+
+
+
+
+
+
+ <_OptimizedResolvedFileToPublish Include="$(StoreStagingDir)\**\*.*" />
+ <_OptimizedSymbolFileToPublish Include="$(StoreSymbolsStagingDir)\**\*.*" />
+
+
+
+
+
+
+
+
+
+
+
+ true
+ true
+ <_TFM Condition="'$(_TFM)' == ''">$(TargetFramework)
+ true
+
+
+
+
+
+ $(UserProfileRuntimeStorePath)
+ <_ProfilingSymbolsDirectoryName>symbols
+ $([System.IO.Path]::Combine($(DefaultComposeDir), $(_ProfilingSymbolsDirectoryName)))
+ $([System.IO.Path]::Combine($(ComposeDir), $(_ProfilingSymbolsDirectoryName)))
+ $([System.IO.Path]::Combine($(ProfilingSymbolsDir), $(PlatformTarget)))
+ $(DefaultProfilingSymbolsDir)
+ $([System.IO.Path]::Combine($(ProfilingSymbolsDir), $(_TFM)))
+ $(ProfilingSymbolsDir)\
+ $(DefaultComposeDir)
+ $([System.IO.Path]::Combine($(ComposeDir), $(PlatformTarget)))
+ $([System.IO.Path]::Combine($(ComposeDir), $(_TFM)))
+ $([System.IO.Path]::Combine($(ComposeDir),"artifact.xml"))
+ $([System.IO.Path]::GetFullPath($(ComposeDir)))
+ <_RandomFileName>$([System.IO.Path]::GetRandomFileName())
+ $([System.IO.Path]::GetTempPath())
+ $([System.IO.Path]::Combine($(TEMP), $(_RandomFileName)))
+ $([System.IO.Path]::GetFullPath($(ComposeWorkingDir)))
+ $([System.IO.Path]::Combine($(ComposeWorkingDir),"StagingDir"))
+
+ $([System.IO.Path]::Combine($(ComposeWorkingDir),"SymbolsStagingDir"))
+
+ $(PublishDir)\
+
+
+
+ false
+ true
+
+
+
+
+
+
+
+ $(StorePackageVersion.Replace('*','-'))
+ $([System.IO.Path]::Combine($(ComposeWorkingDir),"$(StorePackageName)_$(StorePackageVersionForFolderName)"))
+ <_PackageProjFile>$([System.IO.Path]::Combine($(StoreWorkerWorkingDir), "Restore.csproj"))
+ $(StoreWorkerWorkingDir)\
+ $(BaseIntermediateOutputPath)\project.assets.json
+
+
+ $(MicrosoftNETPlatformLibrary)
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ManagedResolvedFileToPublishCandidates Include="@(ResolvedFileToPublish)" Condition="'%(ResolvedFileToPublish.AssetType)'=='runtime'" />
+ <_UnOptimizedResolvedFileToPublish Include="@(ResolvedFileToPublish)" Condition="'%(ResolvedFileToPublish.AssetType)'!='runtime'" />
+
+
+ true
+
+
+
+
+
+ <_UnOptimizedResolvedFileToPublish Include="@(ResolvedFileToPublish)" />
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ true
+ false
+ true
+ false
+ true
+ 1
+
+
+
+
+
+ <_CoreclrResolvedPath Include="@(CrossgenResolvedAssembliesToPublish)" Condition="'%(CrossgenResolvedAssembliesToPublish.Filename)'=='coreclr'" />
+ <_CoreclrResolvedPath Include="@(CrossgenResolvedAssembliesToPublish)" Condition="'%(CrossgenResolvedAssembliesToPublish.Filename)'=='libcoreclr'" />
+ <_JitResolvedPath Include="@(CrossgenResolvedAssembliesToPublish)" Condition="'%(CrossgenResolvedAssembliesToPublish.Filename)'=='clrjit'" />
+ <_JitResolvedPath Include="@(CrossgenResolvedAssembliesToPublish)" Condition="'%(CrossgenResolvedAssembliesToPublish.Filename)'=='libclrjit'" />
+
+
+
+
+
+
+
+ <_CoreclrPath>@(_CoreclrResolvedPath)
+ @(_JitResolvedPath)
+ <_CoreclrDir>$([System.IO.Path]::GetDirectoryName($(_CoreclrPath)))
+ <_CoreclrPkgDir>$([System.IO.Path]::Combine($(_CoreclrDir),"..\..\..\"))
+ $([System.IO.Path]::Combine($(_CoreclrPkgDir),"tools"))
+
+ $([System.IO.Path]::Combine($(CrossgenDir),"crossgen"))
+ $([System.IO.Path]::Combine($(CrossgenDir),"crossgen.exe"))
+
+
+
+
+
+
+
+ $([System.IO.Path]::GetFullPath($([System.IO.Path]::Combine($(_NetCoreRefDir), $([System.IO.Path]::GetFileName($(Crossgen)))))))
+
+
+
+
+
+
+
+ CrossgenExe=$(Crossgen);
+ CrossgenJit=$(JitPath);
+ CrossgenInputAssembly=%(_ManagedResolvedFilesToOptimize.Fullpath);
+ CrossgenOutputAssembly=$(_RuntimeOptimizedDir)$(DirectorySeparatorChar)%(_ManagedResolvedFilesToOptimize.FileName)%(_ManagedResolvedFilesToOptimize.Extension);
+ CrossgenSubOutputPath=%(_ManagedResolvedFilesToOptimize.DestinationSubPath);
+ _RuntimeOptimizedDir=$(_RuntimeOptimizedDir);
+ PublishDir=$(StoreStagingDir);
+ CrossgenPlatformAssembliesPath=$(_RuntimeRefDir)$(PathSeparator)$(_NetCoreRefDir);
+ CreateProfilingSymbols=$(CreateProfilingSymbols);
+ StoreSymbolsStagingDir=$(StoreSymbolsStagingDir);
+ _RuntimeSymbolsDir=$(_RuntimeSymbolsDir)
+
+
+
+
+
+
+
+
+
+ $([System.IO.Path]::GetDirectoryName($(_RuntimeSymbolsDir)\$(CrossgenSubOutputPath)))
+ $([System.IO.Path]::GetDirectoryName($(StoreSymbolsStagingDir)\$(CrossgenSubOutputPath)))
+ $(CrossgenExe) -nologo -readytorun -in "$(CrossgenInputAssembly)" -out "$(CrossgenOutputAssembly)" -jitpath "$(CrossgenJit)" -platform_assemblies_paths "$(CrossgenPlatformAssembliesPath)"
+ CreatePDB
+ CreatePerfMap
+
+
+
+
+
+
+
+
+
+
+
+ <_ProfilingSymbols Include="$(CrossgenProfilingSymbolsOutputDirectory)\*" Condition="'$(CreateProfilingSymbols)' == 'true'" />
+
+
+
+
+
+
+
+ $([System.IO.Path]::PathSeparator)
+ $([System.IO.Path]::DirectorySeparatorChar)
+
+
+
+
+
+ <_CrossProjFileDir>$([System.IO.Path]::Combine($(ComposeWorkingDir),"Optimize"))
+ <_NetCoreRefDir>$([System.IO.Path]::Combine($(_CrossProjFileDir), "netcoreapp"))
+
+
+
+
+ <_CrossProjAssetsFile>$([System.IO.Path]::Combine($(_CrossProjFileDir), project.assets.json))
+
+
+
+
+
+ <_RuntimeRefDir>$([System.IO.Path]::Combine($(StoreWorkerWorkingDir), "runtimeref"))
+
+ <_RuntimeOptimizedDir>$([System.IO.Path]::Combine($(StoreWorkerWorkingDir), "runtimopt"))
+
+ <_RuntimeSymbolsDir>$([System.IO.Path]::Combine($(StoreWorkerWorkingDir), "runtimesymbols"))
+
+
+ <_ManagedResolvedFilesToOptimize Include="@(_ManagedResolvedFileToPublishCandidates)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(MSBuildThisFileDirectory)..\tasks\net7.0\Microsoft.NET.Sdk.Crossgen.dll
+ $(MSBuildThisFileDirectory)..\tasks\net472\Microsoft.NET.Sdk.Crossgen.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ReadyToRunOutputPath>$(IntermediateOutputPath)R2R
+
+
+
+ <_ReadyToRunImplementationAssemblies Include="@(ResolvedFileToPublish->WithMetadataValue('PostprocessAssembly', 'true'))" />
+
+
+
+ <_ReadyToRunImplementationAssemblies Include="@(_ManagedRuntimePackAssembly)" ReferenceOnly="true" />
+
+
+
+
+
+ <_ReadyToRunImplementationAssemblies Remove="@(_ReadyToRunImplementationAssemblies)" />
+ <_ReadyToRunImplementationAssemblies Include="@(_ReadyToRunImplementationAssembliesWithoutConflicts)" />
+
+
+ <_ReadyToRunPgoFiles Include="@(PublishReadyToRunPgoFiles)" />
+ <_ReadyToRunPgoFiles Include="@(RuntimePackAsset)" Condition="'%(RuntimePackAsset.AssetType)' == 'pgodata' and '%(RuntimePackAsset.Extension)' == '.mibc' and '$(PublishReadyToRunUseRuntimePackOptimizationData)' == 'true'" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ReadyToRunCompilerHasWarnings Condition="'$(_ReadyToRunWarningsDetected)' == 'true'">true
+
+
+ <_ReadyToRunCompilationFailures Condition="'$(_ReadyToRunCompilerExitCode)' != '' And $(_ReadyToRunCompilerExitCode) != 0" Include="@(_ReadyToRunCompileList)" />
+
+
+
+
+
+
+
+
+
+
+ <_ReadyToRunCompilerHasWarnings Condition="'$(_ReadyToRunWarningsDetected)' == 'true'">true
+
+
+ <_ReadyToRunCompilationFailures Condition="'$(_ReadyToRunCompilerExitCode)' != '' And $(_ReadyToRunCompilerExitCode) != 0" Include="@(_ReadyToRunSymbolsCompileList)" />
+
+
+
+
+
+
+ $(MSBuildThisFileDirectory)..\..\..\Microsoft.NETCoreSdk.BundledCliTools.props
+
+
+
+
+
+
+ <_ReferenceToObsoleteDotNetCliTool Include="@(DotNetCliToolReference)" />
+
+ <_ReferenceToObsoleteDotNetCliTool Remove="@(DotNetCliToolReference)" />
+
+
+
+
+
+
+
+
+ true
+ <_GetChildProjectCopyToPublishDirectoryItems Condition="'$(_GetChildProjectCopyToPublishDirectoryItems)' == ''">true
+ true
+
+
+
+
+ true
+ true
+ <_FirstTargetFrameworkToSupportTrimming>net6.0
+ <_FirstTargetFrameworkToSupportAot>net7.0
+ <_FirstTargetFrameworkToSupportSingleFile>net6.0
+ <_FirstTargetFrameworkVersionToSupportTrimAnalyzer>$([MSBuild]::GetTargetFrameworkVersion('$(_FirstTargetFrameworkToSupportTrimming)'))
+ <_FirstTargetFrameworkVersionToSupportAotAnalyzer>$([MSBuild]::GetTargetFrameworkVersion('$(_FirstTargetFrameworkToSupportAot)'))
+ <_FirstTargetFrameworkVersionToSupportSingleFileAnalyzer>$([MSBuild]::GetTargetFrameworkVersion('$(_FirstTargetFrameworkToSupportSingleFile)'))
+
+
+
+ Always
+
+
+
+
+
+ <_RequiresILLinkPack Condition="'$(_RequiresILLinkPack)' == '' And (
'$(PublishAot)' == 'true' Or
'$(IsAotCompatible)' == 'true' Or '$(EnableAotAnalyzer)' == 'true' Or
'$(PublishTrimmed)' == 'true' Or
'$(IsTrimmable)' == 'true' Or '$(EnableTrimAnalyzer)' == 'true' Or
'$(EnableSingleFileAnalyzer)' == 'true')">true
+ <_RequiresILLinkPack Condition="'$(_RequiresILLinkPack)' == ''">false
+
+
+
+
+ <_MinNonEolTargetFrameworkForTrimming>$(_MinimumNonEolSupportedNetCoreTargetFramework)
+ <_MinNonEolTargetFrameworkForSingleFile>$(_MinimumNonEolSupportedNetCoreTargetFramework)
+
+ <_MinNonEolTargetFrameworkForAot>$(_MinimumNonEolSupportedNetCoreTargetFramework)
+ <_MinNonEolTargetFrameworkForAot Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(_FirstTargetFrameworkToSupportAot)', '$(_MinimumNonEolSupportedNetCoreTargetFramework)'))">$(_FirstTargetFrameworkToSupportAot)
+
+
+ <_TargetFramework Include="$(TargetFrameworks)" />
+ <_DecomposedTargetFramework Include="@(_TargetFramework)">
+ $([MSBuild]::IsTargetFrameworkCompatible('%(Identity)', '$(_FirstTargetFrameworkToSupportTrimming)'))
+ $([MSBuild]::IsTargetFrameworkCompatible('$(_MinNonEolTargetFrameworkForTrimming)', '%(Identity)'))
+ $([MSBuild]::IsTargetFrameworkCompatible('%(Identity)', '$(_FirstTargetFrameworkToSupportAot)'))
+ $([MSBuild]::IsTargetFrameworkCompatible('$(_MinNonEolTargetFrameworkForAot)', '%(Identity)'))
+ $([MSBuild]::IsTargetFrameworkCompatible('%(Identity)', '$(_FirstTargetFrameworkToSupportSingleFile)'))
+ $([MSBuild]::IsTargetFrameworkCompatible('$(_MinNonEolTargetFrameworkForSingleFile)', '%(Identity)'))
+
+ <_TargetFrameworkToSilenceIsTrimmableUnsupportedWarning Include="@(_DecomposedTargetFramework)" Condition="'%(SupportsTrimming)' == 'true' And '%(SupportedByMinNonEolTargetFrameworkForTrimming)' == 'true'" />
+ <_TargetFrameworkToSilenceIsAotCompatibleUnsupportedWarning Include="@(_DecomposedTargetFramework->'%(Identity)')" Condition="'%(SupportsAot)' == 'true' And '%(SupportedByMinNonEolTargetFrameworkForAot)' == 'true'" />
+ <_TargetFrameworkToSilenceEnableSingleFileAnalyzerUnsupportedWarning Include="@(_DecomposedTargetFramework)" Condition="'%(SupportsSingleFile)' == 'true' And '%(SupportedByMinNonEolTargetFrameworkForSingleFile)' == 'true'" />
+
+
+
+ <_SilenceIsTrimmableUnsupportedWarning Condition="'$(_SilenceIsTrimmableUnsupportedWarning)' == '' And
@(_TargetFrameworkToSilenceIsTrimmableUnsupportedWarning->Count()) > 0">true
+ <_SilenceIsAotCompatibleUnsupportedWarning Condition="'$(_SilenceIsAotCompatibleUnsupportedWarning)' == '' And
@(_TargetFrameworkToSilenceIsAotCompatibleUnsupportedWarning->Count()) > 0">true
+ <_SilenceEnableSingleFileAnalyzerUnsupportedWarning Condition="'$(_SilenceEnableSingleFileAnalyzerUnsupportedWarning)' == '' And
@(_TargetFrameworkToSilenceEnableSingleFileAnalyzerUnsupportedWarning->Count()) > 0">true
+
+
+
+
+
+
+
+ <_BeforePublishNoBuildTargets>
+ BuildOnlySettings;
+ _PreventProjectReferencesFromBuilding;
+ ResolveReferences;
+ PrepareResourceNames;
+ ComputeIntermediateSatelliteAssemblies;
+ ComputeEmbeddedApphostPaths;
+
+ <_CorePublishTargets>
+ PrepareForPublish;
+ ComputeAndCopyFilesToPublishDirectory;
+ $(PublishProtocolProviderTargets);
+ PublishItemsOutputGroup;
+
+ <_PublishNoBuildAlternativeDependsOn>$(_BeforePublishNoBuildTargets);$(_CorePublishTargets)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(PublishDir)\
+
+
+
+
+
+
+
+
+
+
+
+ <_OrphanPublishFileWrites Include="@(_PriorPublishFileWrites)" Exclude="@(_CurrentPublishFileWrites)" />
+
+
+
+
+
+
+
+
+
+
+
+ <_NormalizedPublishDir>$([MSBuild]::NormalizeDirectory($(PublishDir)))
+
+
+
+
+
+ <_PublishCleanFile Condition="'$(PublishCleanFile)'==''">PublishOutputs.$(_NormalizedPublishDirHash.Substring(0, 10)).txt
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_CurrentPublishFileWritesUnfiltered Include="@(ResolvedFileToPublish->'$(_NormalizedPublishDir)%(RelativePath)')" />
+ <_CurrentPublishFileWritesUnfiltered Include="$(_NormalizedPublishDir)$(AssemblyName)$(_NativeExecutableExtension)" Condition="'$(UseAppHost)' == 'true'" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ResolvedFileToPublishPreserveNewest Include="@(ResolvedFileToPublish)" Condition="'%(ResolvedFileToPublish.CopyToPublishDirectory)'=='PreserveNewest'" />
+ <_ResolvedFileToPublishAlways Include="@(ResolvedFileToPublish)" Condition="'%(ResolvedFileToPublish.CopyToPublishDirectory)'=='Always'" />
+
+
+ <_ResolvedUnbundledFileToPublishPreserveNewest Include="@(_ResolvedFileToPublishPreserveNewest)" Condition="'$(PublishSingleFile)' != 'true' or
'%(_ResolvedFileToPublishPreserveNewest.ExcludeFromSingleFile)'=='true'" />
+ <_ResolvedUnbundledFileToPublishAlways Include="@(_ResolvedFileToPublishAlways)" Condition="'$(PublishSingleFile)' != 'true' or
'%(_ResolvedFileToPublishAlways.ExcludeFromSingleFile)'=='true'" />
+
+
+
+
+
+
+
+ true
+ true
+ false
+
+
+
+
+
+
+
+ @(IntermediateAssembly->'%(Filename)%(Extension)')
+ PreserveNewest
+
+
+
+ $(ProjectDepsFileName)
+ PreserveNewest
+
+
+
+ $(ProjectRuntimeConfigFileName)
+ PreserveNewest
+
+
+
+ @(AppConfigWithTargetPath->'%(TargetPath)')
+ PreserveNewest
+
+
+
+ @(_DebugSymbolsIntermediatePath->'%(Filename)%(Extension)')
+ PreserveNewest
+ true
+
+
+
+ %(IntermediateSatelliteAssembliesWithTargetPath.Culture)\%(Filename)%(Extension)
+ PreserveNewest
+
+
+
+ %(Filename)%(Extension)
+ PreserveNewest
+
+
+
+
+
+
+
+
+ <_ResolvedCopyLocalPublishAssets Remove="@(_ResolvedCopyLocalPublishAssetsRemoved)" />
+
+
+
+ %(_ResolvedCopyLocalPublishAssets.DestinationSubDirectory)%(Filename)%(Extension)
+ PreserveNewest
+
+
+
+ @(FinalDocFile->'%(Filename)%(Extension)')
+ PreserveNewest
+
+
+
+ shims/%(_EmbeddedApphostPaths.ShimRuntimeIdentifier)/%(_EmbeddedApphostPaths.Filename)%(_EmbeddedApphostPaths.Extension)
+ PreserveNewest
+
+
+ <_FilesToDrop Include="@(ResolvedFileToPublish)" Condition="'$(PublishSingleFile)' == 'true' and
'%(ResolvedFileToPublish.DropFromSingleFile)' == 'true'" />
+
+
+
+
+
+
+
+
+
+
+
+ <_ResolvedCopyLocalPublishAssets Include="@(RuntimePackAsset)" Condition="('$(SelfContained)' == 'true' Or '%(RuntimePackAsset.RuntimePackAlwaysCopyLocal)' == 'true') and '%(RuntimePackAsset.AssetType)' != 'pgodata'" />
+
+
+
+ <_ResolvedCopyLocalPublishAssets Remove="@(_NativeRestoredAppHostNETCore)" />
+
+
+ <_ResolvedCopyLocalPublishAssets Include="@(_ResolvedCopyLocalBuildAssets)" Condition="'%(_ResolvedCopyLocalBuildAssets.CopyToPublishDirectory)' != 'false' " />
+
+
+
+
+
+
+
+
+
+
+
+
+ <_PublishSatelliteResources Include="@(_ResolvedCopyLocalPublishAssets)" Condition="'%(_ResolvedCopyLocalPublishAssets.AssetType)' == 'resources'" />
+
+
+
+
+
+ <_ResolvedCopyLocalPublishAssets Remove="@(_PublishSatelliteResources)" />
+ <_ResolvedCopyLocalPublishAssets Include="@(_FilteredPublishSatelliteResources)" />
+
+
+
+
+
+ <_ResolvedCopyLocalPublishAssets Include="@(ReferenceCopyLocalPaths)" Exclude="@(_ResolvedCopyLocalBuildAssets);@(RuntimePackAsset)" Condition="('$(PublishReferencesDocumentationFiles)' == 'true' or '%(ReferenceCopyLocalPaths.Extension)' != '.xml') and '%(ReferenceCopyLocalPaths.Private)' != 'false'">
+ %(ReferenceCopyLocalPaths.DestinationSubDirectory)%(ReferenceCopyLocalPaths.Filename)%(ReferenceCopyLocalPaths.Extension)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ %(_SourceItemsToCopyToPublishDirectoryAlways.TargetPath)
+ Always
+ True
+
+
+ %(_SourceItemsToCopyToPublishDirectory.TargetPath)
+ PreserveNewest
+ True
+
+
+
+
+
+
+
+ <_GCTPDIKeepDuplicates>false
+ <_GCTPDIKeepMetadata>CopyToPublishDirectory;ExcludeFromSingleFile;TargetPath
+
+
+
+
+
+
+
+ <_SourceItemsToCopyToPublishDirectoryAlways KeepDuplicates=" '$(_GCTPDIKeepDuplicates)' != 'false' " KeepMetadata="$(_GCTPDIKeepMetadata)" Include="@(_AllChildProjectPublishItemsWithTargetPath->'%(FullPath)')" Condition="'%(_AllChildProjectPublishItemsWithTargetPath.CopyToPublishDirectory)'=='Always'" />
+ <_SourceItemsToCopyToPublishDirectory KeepDuplicates=" '$(_GCTPDIKeepDuplicates)' != 'false' " KeepMetadata="$(_GCTPDIKeepMetadata)" Include="@(_AllChildProjectPublishItemsWithTargetPath->'%(FullPath)')" Condition="'%(_AllChildProjectPublishItemsWithTargetPath.CopyToPublishDirectory)'=='PreserveNewest'" />
+
+
+
+ <_AllChildProjectPublishItemsWithTargetPath Remove="@(_AllChildProjectPublishItemsWithTargetPath)" />
+
+
+
+ <_SourceItemsToCopyToPublishDirectoryAlways KeepMetadata="$(_GCTPDIKeepMetadata)" Include="@(ContentWithTargetPath->'%(FullPath)')" Condition="'%(ContentWithTargetPath.CopyToPublishDirectory)'=='Always'" />
+ <_SourceItemsToCopyToPublishDirectory KeepMetadata="$(_GCTPDIKeepMetadata)" Include="@(ContentWithTargetPath->'%(FullPath)')" Condition="'%(ContentWithTargetPath.CopyToPublishDirectory)'=='PreserveNewest'" />
+
+
+ <_SourceItemsToCopyToPublishDirectoryAlways KeepMetadata="$(_GCTPDIKeepMetadata)" Include="@(EmbeddedResource->'%(FullPath)')" Condition="'%(EmbeddedResource.CopyToPublishDirectory)'=='Always'" />
+ <_SourceItemsToCopyToPublishDirectory KeepMetadata="$(_GCTPDIKeepMetadata)" Include="@(EmbeddedResource->'%(FullPath)')" Condition="'%(EmbeddedResource.CopyToPublishDirectory)'=='PreserveNewest'" />
+
+
+ <_CompileItemsToPublish Include="@(Compile->'%(FullPath)')" Condition="'%(Compile.CopyToPublishDirectory)'=='Always' or '%(Compile.CopyToPublishDirectory)'=='PreserveNewest'" />
+
+
+
+
+
+ <_SourceItemsToCopyToPublishDirectoryAlways KeepMetadata="$(_GCTPDIKeepMetadata)" Include="@(_CompileItemsToPublishWithTargetPath)" Condition="'%(_CompileItemsToPublishWithTargetPath.CopyToPublishDirectory)'=='Always'" />
+ <_SourceItemsToCopyToPublishDirectory KeepMetadata="$(_GCTPDIKeepMetadata)" Include="@(_CompileItemsToPublishWithTargetPath)" Condition="'%(_CompileItemsToPublishWithTargetPath.CopyToPublishDirectory)'=='PreserveNewest'" />
+
+
+ <_SourceItemsToCopyToPublishDirectoryAlways KeepMetadata="$(_GCTPDIKeepMetadata)" Include="@(_NoneWithTargetPath->'%(FullPath)')" Condition="'%(_NoneWithTargetPath.CopyToPublishDirectory)'=='Always'" />
+ <_SourceItemsToCopyToPublishDirectory KeepMetadata="$(_GCTPDIKeepMetadata)" Include="@(_NoneWithTargetPath->'%(FullPath)')" Condition="'%(_NoneWithTargetPath.CopyToPublishDirectory)'=='PreserveNewest'" />
+
+
+
+ <_SourceItemsToCopyToPublishDirectoryAlways Remove="$(AppHostIntermediatePath)" />
+ <_SourceItemsToCopyToPublishDirectory Remove="$(AppHostIntermediatePath)" />
+
+ <_SourceItemsToCopyToPublishDirectoryAlways Include="$(SingleFileHostIntermediatePath)" CopyToOutputDirectory="Always" TargetPath="$(AssemblyName)$(_NativeExecutableExtension)" />
+
+
+
+ <_SourceItemsToCopyToPublishDirectoryAlways Remove="$(AppHostIntermediatePath)" />
+ <_SourceItemsToCopyToPublishDirectory Remove="$(AppHostIntermediatePath)" />
+
+ <_SourceItemsToCopyToPublishDirectoryAlways Include="$(AppHostForPublishIntermediatePath)" CopyToOutputDirectory="Always" TargetPath="$(AssemblyName)$(_NativeExecutableExtension)" />
+
+
+
+
+
+
+
+
+
+ Always
+
+
+ PreserveNewest
+
+
+ Always
+
+
+ PreserveNewest
+
+
+ Always
+
+
+ PreserveNewest
+
+ <_NoneWithTargetPath Condition="'%(_NoneWithTargetPath.CopyToOutputDirectory)'=='Always' and '%(_NoneWithTargetPath.CopyToPublishDirectory)' == ''">
+ Always
+
+ <_NoneWithTargetPath Condition="'%(_NoneWithTargetPath.CopyToOutputDirectory)'=='PreserveNewest' and '%(_NoneWithTargetPath.CopyToPublishDirectory)' == ''">
+ PreserveNewest
+
+
+
+
+ <_ComputeManagedRuntimePackAssembliesIfSelfContained>_ComputeManagedRuntimePackAssemblies
+
+
+
+
+
+
+ <_ManagedRuntimeAssembly Include="@(RuntimeCopyLocalItems)" />
+
+ <_ManagedRuntimeAssembly Include="@(UserRuntimeAssembly)" />
+
+ <_ManagedRuntimeAssembly Include="@(IntermediateAssembly)" />
+
+
+
+ <_ManagedRuntimeAssembly Include="@(_ManagedRuntimePackAssembly)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ManagedRuntimePackAssembly Include="@(RuntimePackAsset)" Condition="'%(RuntimePackAsset.AssetType)' == 'runtime'
or '%(RuntimePackAsset.Filename)' == 'System.Private.Corelib'" />
+
+
+
+
+
+ <_TrimRuntimeAssets Condition="'$(PublishSingleFile)' == 'true' and '$(SelfContained)' == 'true'">true
+ <_UseBuildDependencyFile Condition="'@(_ExcludeFromPublishPackageReference)' == '' and
'@(RuntimeStorePackages)' == '' and
'$(PreserveStoreLayout)' != 'true' and
'$(PublishTrimmed)' != 'true' and
'$(_TrimRuntimeAssets)' != 'true'">true
+
+
+
+
+
+ <_FilesToBundle Include="@(ResolvedFileToPublish)" Condition="'%(ResolvedFileToPublish.ExcludeFromSingleFile)' != 'true'" />
+
+
+
+ $(AssemblyName)$(_NativeExecutableExtension)
+ $(PublishDir)$(PublishedSingleFileName)
+
+
+
+
+
+
+
+ $(PublishedSingleFileName)
+
+
+
+
+ <_GenerateSingleFileBundlePropertyInputsCacheToHash Include="$(PublishedSingleFilePath)" />
+ <_GenerateSingleFileBundlePropertyInputsCacheToHash Include="$(TraceSingleFileBundler)" />
+ <_GenerateSingleFileBundlePropertyInputsCacheToHash Include="$(IncludeSymbolsInSingleFile)" />
+ <_GenerateSingleFileBundlePropertyInputsCacheToHash Include="$(IncludeAllContentForSelfExtract)" />
+ <_GenerateSingleFileBundlePropertyInputsCacheToHash Include="$(IncludeNativeLibrariesForSelfExtract)" />
+ <_GenerateSingleFileBundlePropertyInputsCacheToHash Include="$(EnableCompressionInSingleFile)" />
+ <_GenerateSingleFileBundlePropertyInputsCacheToHash Include="$(PublishedSingleFileName)" />
+ <_GenerateSingleFileBundlePropertyInputsCacheToHash Include="$(RuntimeIdentifier)" />
+ <_GenerateSingleFileBundlePropertyInputsCacheToHash Include="$(PublishDir)" />
+ <_GenerateSingleFileBundlePropertyInputsCacheToHash Include="$(_TargetFrameworkVersionWithoutV)" />
+ <_GenerateSingleFileBundlePropertyInputsCacheToHash Include="@(FilesToBundle)" />
+
+
+
+
+
+
+
+
+
+ false
+ false
+ false
+ $(IncludeAllContentForSelfExtract)
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(PublishDepsFilePath)
+ $(IntermediateOutputPath)$(ProjectDepsFileName)
+
+
+
+
+ <_GeneratePublishDependencyFilePropertyInputsCacheToHash Include="$(PublishDepsFilePath)" />
+ <_GeneratePublishDependencyFilePropertyInputsCacheToHash Include="$(PublishSingleFile)" />
+ <_GeneratePublishDependencyFilePropertyInputsCacheToHash Include="$(MSBuildProjectFullPath)" />
+ <_GeneratePublishDependencyFilePropertyInputsCacheToHash Include="$(ProjectAssetsFile)" />
+ <_GeneratePublishDependencyFilePropertyInputsCacheToHash Include="$(IntermediateDepsFilePath)" />
+ <_GeneratePublishDependencyFilePropertyInputsCacheToHash Include="$(TargetFramework)" />
+ <_GeneratePublishDependencyFilePropertyInputsCacheToHash Include="$(AssemblyName)" />
+ <_GeneratePublishDependencyFilePropertyInputsCacheToHash Include="$(TargetExt)" />
+ <_GeneratePublishDependencyFilePropertyInputsCacheToHash Include="$(Version)" />
+ <_GeneratePublishDependencyFilePropertyInputsCacheToHash Include="$(IncludeMainProjectInDepsFile)" />
+ <_GeneratePublishDependencyFilePropertyInputsCacheToHash Include="$(RuntimeIdentifier)" />
+ <_GeneratePublishDependencyFilePropertyInputsCacheToHash Include="$(MicrosoftNETPlatformLibrary)" />
+ <_GeneratePublishDependencyFilePropertyInputsCacheToHash Include="$(SelfContained)" />
+ <_GeneratePublishDependencyFilePropertyInputsCacheToHash Include="$(IncludeFileVersionsInDependencyFile)" />
+ <_GeneratePublishDependencyFilePropertyInputsCacheToHash Include="$(RuntimeIdentifierGraphPath)" />
+ <_GeneratePublishDependencyFilePropertyInputsCacheToHash Include="$(IncludeProjectsNotInAssetsFileInDepsFile)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(PublishDir)$(ProjectDepsFileName)
+ <_IsSingleFilePublish Condition="'$(PublishSingleFile)' == ''">false
+ <_IsSingleFilePublish Condition="'$(PublishSingleFile)' != ''">$(PublishSingleFile)
+
+
+
+
+
+ <_ResolvedNuGetFilesForPublish Include="@(NativeCopyLocalItems)" Condition="'%(NativeCopyLocalItems.CopyToPublishDirectory)' != 'false'" />
+ <_ResolvedNuGetFilesForPublish Include="@(ResourceCopyLocalItems)" Condition="'%(ResourceCopyLocalItems.CopyToPublishDirectory)' != 'false'" />
+ <_ResolvedNuGetFilesForPublish Include="@(RuntimeCopyLocalItems)" Condition="'%(RuntimeCopyLocalItems.CopyToPublishDirectory)' != 'false'" />
+ <_ResolvedNuGetFilesForPublish Remove="@(_PublishConflictPackageFiles)" Condition="'%(_PublishConflictPackageFiles.ConflictItemType)' != 'Reference'" />
+
+
+
+
+ $(ProjectDepsFileName)
+
+
+
+
+
+
+
+ <_PackAsToolShimRuntimeIdentifiers Condition="@(_PackAsToolShimRuntimeIdentifiers) ==''" Include="$(PackAsToolShimRuntimeIdentifiers)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(PublishItemsOutputGroupDependsOn);
+ ResolveReferences;
+ ComputeResolvedFilesToPublishList;
+ _ComputeFilesToBundle;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ToolsSettingsFilePath>$(BaseIntermediateOutputPath)DotnetToolSettings.xml
+ true
+ <_PackToolPublishDependency Condition=" ('$(GeneratePackageOnBuild)' != 'true' and '$(NoBuild)' != 'true') and $(IsPublishable) == 'true' ">_PublishBuildAlternative
+ <_PackToolPublishDependency Condition=" ('$(GeneratePackageOnBuild)' == 'true' or '$(NoBuild)' == 'true') and $(IsPublishable) == 'true' ">$(_PublishNoBuildAlternativeDependsOn)
+
+
+
+ <_GeneratedFiles Include="$(PublishDepsFilePath)" Condition="'$(GenerateDependencyFile)' != 'true' or '$(_UseBuildDependencyFile)' == 'true'" />
+ <_GeneratedFiles Include="$(PublishRuntimeConfigFilePath)" />
+ <_GeneratedFiles Include="$(_ToolsSettingsFilePath)" />
+
+
+
+
+
+
+ tools/$(_NuGetShortFolderName)/any/%(_GeneratedFiles.RecursiveDir)%(_GeneratedFiles.Filename)%(_GeneratedFiles.Extension)
+
+
+ %(_ResolvedFileToPublishWithPackagePath.PackagePath)
+
+
+
+
+ $(TargetName)
+ $(TargetFileName)
+ <_GenerateToolsSettingsFileCacheFile Condition="'$(_GenerateToolsSettingsFileCacheFile)' == ''">$(IntermediateOutputPath)$(MSBuildProjectName).toolssettingsinput.cache
+ <_GenerateToolsSettingsFileCacheFile>$([MSBuild]::NormalizePath($(MSBuildProjectDirectory), $(_GenerateToolsSettingsFileCacheFile)))
+
+
+
+ <_GenerateToolsSettingsFileInputCacheToHash Include="$(ToolEntryPoint)" />
+ <_GenerateToolsSettingsFileInputCacheToHash Include="$(ToolCommandName)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ShimInputCacheFile Condition="'$(_ShimInputCacheFile)' == ''">$(IntermediateOutputPath)$(MSBuildProjectName).shiminput.cache
+ <_ShimInputCacheFile>$([MSBuild]::NormalizePath($(MSBuildProjectDirectory), $(_ShimInputCacheFile)))
+ <_ShimCreatedSentinelFile Condition="'$(_ShimCreatedSentinelFile)' == ''">$(IntermediateOutputPath)$(MSBuildProjectName).shimcreated.sentinel
+ <_ShimCreatedSentinelFile>$([MSBuild]::NormalizePath($(MSBuildProjectDirectory), $(_ShimCreatedSentinelFile)))
+ $(OutDir)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_GenerateShimsAssetsInput Include="$(_ShimInputCacheFile)" />
+ <_GenerateShimsAssetsInput Include="@(_ApphostsForShimRuntimeIdentifiers)" />
+ <_GenerateShimsAssetsInput Include="$(_ShimCreatedSentinelFile)" />
+ <_GenerateShimsAssetsInput Include="$(ProjectAssetsFile)" />
+ <_GenerateShimsAssetsInputCacheToHash Include="$(PackageId)" />
+ <_GenerateShimsAssetsInputCacheToHash Include="$(Version)" />
+ <_GenerateShimsAssetsInputCacheToHash Include="$(NuGetTargetMoniker)" />
+ <_GenerateShimsAssetsInputCacheToHash Include="$(ToolCommandName)" />
+ <_GenerateShimsAssetsInputCacheToHash Include="$(ToolEntryPoint)" />
+ <_GenerateShimsAssetsInputCacheToHash Include="$(PackAsToolShimRuntimeIdentifiers)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ refs
+ $(PreserveCompilationContext)
+
+
+
+
+ $(DefineConstants)
+ $(LangVersion)
+ $(PlatformTarget)
+ $(AllowUnsafeBlocks)
+ $(TreatWarningsAsErrors)
+ $(Optimize)
+ $(AssemblyOriginatorKeyFile)
+ $(DelaySign)
+ $(PublicSign)
+ $(DebugType)
+ $(OutputType)
+ $(GenerateDocumentationFile)
+
+
+
+
+
+
+
+
+
+
+ <_RefAssembliesToExclude Include="@(_ResolvedCopyLocalPublishAssets->'%(FullPath)')" />
+
+ <_RefAssembliesToExclude Include="@(_RuntimeItemsInRuntimeStore)" />
+
+ $(RefAssembliesFolderName)\%(Filename)%(Extension)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Microsoft.CSharp|4.4.0;
+ Microsoft.Win32.Primitives|4.3.0;
+ Microsoft.Win32.Registry|4.4.0;
+ runtime.debian.8-x64.runtime.native.System.Security.Cryptography.OpenSsl|4.3.0;
+ runtime.fedora.23-x64.runtime.native.System.Security.Cryptography.OpenSsl|4.3.0;
+ runtime.fedora.24-x64.runtime.native.System.Security.Cryptography.OpenSsl|4.3.0;
+ runtime.opensuse.13.2-x64.runtime.native.System.Security.Cryptography.OpenSsl|4.3.0;
+ runtime.opensuse.42.1-x64.runtime.native.System.Security.Cryptography.OpenSsl|4.3.0;
+ runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.Apple|4.3.0;
+ runtime.osx.10.10-x64.runtime.native.System.Security.Cryptography.OpenSsl|4.3.0;
+ runtime.rhel.7-x64.runtime.native.System.Security.Cryptography.OpenSsl|4.3.0;
+ runtime.ubuntu.14.04-x64.runtime.native.System.Security.Cryptography.OpenSsl|4.3.0;
+ runtime.ubuntu.16.04-x64.runtime.native.System.Security.Cryptography.OpenSsl|4.3.0;
+ runtime.ubuntu.16.10-x64.runtime.native.System.Security.Cryptography.OpenSsl|4.3.0;
+ System.AppContext|4.3.0;
+ System.Buffers|4.4.0;
+ System.Collections|4.3.0;
+ System.Collections.Concurrent|4.3.0;
+ System.Collections.Immutable|1.4.0;
+ System.Collections.NonGeneric|4.3.0;
+ System.Collections.Specialized|4.3.0;
+ System.ComponentModel|4.3.0;
+ System.ComponentModel.EventBasedAsync|4.3.0;
+ System.ComponentModel.Primitives|4.3.0;
+ System.ComponentModel.TypeConverter|4.3.0;
+ System.Console|4.3.0;
+ System.Data.Common|4.3.0;
+ System.Diagnostics.Contracts|4.3.0;
+ System.Diagnostics.Debug|4.3.0;
+ System.Diagnostics.DiagnosticSource|4.4.0;
+ System.Diagnostics.FileVersionInfo|4.3.0;
+ System.Diagnostics.Process|4.3.0;
+ System.Diagnostics.StackTrace|4.3.0;
+ System.Diagnostics.TextWriterTraceListener|4.3.0;
+ System.Diagnostics.Tools|4.3.0;
+ System.Diagnostics.TraceSource|4.3.0;
+ System.Diagnostics.Tracing|4.3.0;
+ System.Dynamic.Runtime|4.3.0;
+ System.Globalization|4.3.0;
+ System.Globalization.Calendars|4.3.0;
+ System.Globalization.Extensions|4.3.0;
+ System.IO|4.3.0;
+ System.IO.Compression|4.3.0;
+ System.IO.Compression.ZipFile|4.3.0;
+ System.IO.FileSystem|4.3.0;
+ System.IO.FileSystem.AccessControl|4.4.0;
+ System.IO.FileSystem.DriveInfo|4.3.0;
+ System.IO.FileSystem.Primitives|4.3.0;
+ System.IO.FileSystem.Watcher|4.3.0;
+ System.IO.IsolatedStorage|4.3.0;
+ System.IO.MemoryMappedFiles|4.3.0;
+ System.IO.Pipes|4.3.0;
+ System.IO.UnmanagedMemoryStream|4.3.0;
+ System.Linq|4.3.0;
+ System.Linq.Expressions|4.3.0;
+ System.Linq.Queryable|4.3.0;
+ System.Net.Http|4.3.0;
+ System.Net.NameResolution|4.3.0;
+ System.Net.Primitives|4.3.0;
+ System.Net.Requests|4.3.0;
+ System.Net.Security|4.3.0;
+ System.Net.Sockets|4.3.0;
+ System.Net.WebHeaderCollection|4.3.0;
+ System.ObjectModel|4.3.0;
+ System.Private.DataContractSerialization|4.3.0;
+ System.Reflection|4.3.0;
+ System.Reflection.Emit|4.3.0;
+ System.Reflection.Emit.ILGeneration|4.3.0;
+ System.Reflection.Emit.Lightweight|4.3.0;
+ System.Reflection.Extensions|4.3.0;
+ System.Reflection.Metadata|1.5.0;
+ System.Reflection.Primitives|4.3.0;
+ System.Reflection.TypeExtensions|4.3.0;
+ System.Resources.ResourceManager|4.3.0;
+ System.Runtime|4.3.0;
+ System.Runtime.Extensions|4.3.0;
+ System.Runtime.Handles|4.3.0;
+ System.Runtime.InteropServices|4.3.0;
+ System.Runtime.InteropServices.RuntimeInformation|4.3.0;
+ System.Runtime.Loader|4.3.0;
+ System.Runtime.Numerics|4.3.0;
+ System.Runtime.Serialization.Formatters|4.3.0;
+ System.Runtime.Serialization.Json|4.3.0;
+ System.Runtime.Serialization.Primitives|4.3.0;
+ System.Security.AccessControl|4.4.0;
+ System.Security.Claims|4.3.0;
+ System.Security.Cryptography.Algorithms|4.3.0;
+ System.Security.Cryptography.Cng|4.4.0;
+ System.Security.Cryptography.Csp|4.3.0;
+ System.Security.Cryptography.Encoding|4.3.0;
+ System.Security.Cryptography.OpenSsl|4.4.0;
+ System.Security.Cryptography.Primitives|4.3.0;
+ System.Security.Cryptography.X509Certificates|4.3.0;
+ System.Security.Cryptography.Xml|4.4.0;
+ System.Security.Principal|4.3.0;
+ System.Security.Principal.Windows|4.4.0;
+ System.Text.Encoding|4.3.0;
+ System.Text.Encoding.Extensions|4.3.0;
+ System.Text.RegularExpressions|4.3.0;
+ System.Threading|4.3.0;
+ System.Threading.Overlapped|4.3.0;
+ System.Threading.Tasks|4.3.0;
+ System.Threading.Tasks.Extensions|4.3.0;
+ System.Threading.Tasks.Parallel|4.3.0;
+ System.Threading.Thread|4.3.0;
+ System.Threading.ThreadPool|4.3.0;
+ System.Threading.Timer|4.3.0;
+ System.ValueTuple|4.3.0;
+ System.Xml.ReaderWriter|4.3.0;
+ System.Xml.XDocument|4.3.0;
+ System.Xml.XmlDocument|4.3.0;
+ System.Xml.XmlSerializer|4.3.0;
+ System.Xml.XPath|4.3.0;
+ System.Xml.XPath.XDocument|4.3.0;
+
+
+
+
+ Microsoft.Win32.Primitives|4.3.0;
+ System.AppContext|4.3.0;
+ System.Collections|4.3.0;
+ System.Collections.Concurrent|4.3.0;
+ System.Collections.Immutable|1.4.0;
+ System.Collections.NonGeneric|4.3.0;
+ System.Collections.Specialized|4.3.0;
+ System.ComponentModel|4.3.0;
+ System.ComponentModel.EventBasedAsync|4.3.0;
+ System.ComponentModel.Primitives|4.3.0;
+ System.ComponentModel.TypeConverter|4.3.0;
+ System.Console|4.3.0;
+ System.Data.Common|4.3.0;
+ System.Diagnostics.Contracts|4.3.0;
+ System.Diagnostics.Debug|4.3.0;
+ System.Diagnostics.FileVersionInfo|4.3.0;
+ System.Diagnostics.Process|4.3.0;
+ System.Diagnostics.StackTrace|4.3.0;
+ System.Diagnostics.TextWriterTraceListener|4.3.0;
+ System.Diagnostics.Tools|4.3.0;
+ System.Diagnostics.TraceSource|4.3.0;
+ System.Diagnostics.Tracing|4.3.0;
+ System.Dynamic.Runtime|4.3.0;
+ System.Globalization|4.3.0;
+ System.Globalization.Calendars|4.3.0;
+ System.Globalization.Extensions|4.3.0;
+ System.IO|4.3.0;
+ System.IO.Compression|4.3.0;
+ System.IO.Compression.ZipFile|4.3.0;
+ System.IO.FileSystem|4.3.0;
+ System.IO.FileSystem.DriveInfo|4.3.0;
+ System.IO.FileSystem.Primitives|4.3.0;
+ System.IO.FileSystem.Watcher|4.3.0;
+ System.IO.IsolatedStorage|4.3.0;
+ System.IO.MemoryMappedFiles|4.3.0;
+ System.IO.Pipes|4.3.0;
+ System.IO.UnmanagedMemoryStream|4.3.0;
+ System.Linq|4.3.0;
+ System.Linq.Expressions|4.3.0;
+ System.Linq.Queryable|4.3.0;
+ System.Net.Http|4.3.0;
+ System.Net.NameResolution|4.3.0;
+ System.Net.Primitives|4.3.0;
+ System.Net.Requests|4.3.0;
+ System.Net.Security|4.3.0;
+ System.Net.Sockets|4.3.0;
+ System.Net.WebHeaderCollection|4.3.0;
+ System.ObjectModel|4.3.0;
+ System.Private.DataContractSerialization|4.3.0;
+ System.Reflection|4.3.0;
+ System.Reflection.Emit|4.3.0;
+ System.Reflection.Emit.ILGeneration|4.3.0;
+ System.Reflection.Emit.Lightweight|4.3.0;
+ System.Reflection.Extensions|4.3.0;
+ System.Reflection.Primitives|4.3.0;
+ System.Reflection.TypeExtensions|4.3.0;
+ System.Resources.ResourceManager|4.3.0;
+ System.Runtime|4.3.0;
+ System.Runtime.Extensions|4.3.0;
+ System.Runtime.Handles|4.3.0;
+ System.Runtime.InteropServices|4.3.0;
+ System.Runtime.InteropServices.RuntimeInformation|4.3.0;
+ System.Runtime.Loader|4.3.0;
+ System.Runtime.Numerics|4.3.0;
+ System.Runtime.Serialization.Formatters|4.3.0;
+ System.Runtime.Serialization.Json|4.3.0;
+ System.Runtime.Serialization.Primitives|4.3.0;
+ System.Security.AccessControl|4.4.0;
+ System.Security.Claims|4.3.0;
+ System.Security.Cryptography.Algorithms|4.3.0;
+ System.Security.Cryptography.Csp|4.3.0;
+ System.Security.Cryptography.Encoding|4.3.0;
+ System.Security.Cryptography.Primitives|4.3.0;
+ System.Security.Cryptography.X509Certificates|4.3.0;
+ System.Security.Cryptography.Xml|4.4.0;
+ System.Security.Principal|4.3.0;
+ System.Security.Principal.Windows|4.4.0;
+ System.Text.Encoding|4.3.0;
+ System.Text.Encoding.Extensions|4.3.0;
+ System.Text.RegularExpressions|4.3.0;
+ System.Threading|4.3.0;
+ System.Threading.Overlapped|4.3.0;
+ System.Threading.Tasks|4.3.0;
+ System.Threading.Tasks.Extensions|4.3.0;
+ System.Threading.Tasks.Parallel|4.3.0;
+ System.Threading.Thread|4.3.0;
+ System.Threading.ThreadPool|4.3.0;
+ System.Threading.Timer|4.3.0;
+ System.ValueTuple|4.3.0;
+ System.Xml.ReaderWriter|4.3.0;
+ System.Xml.XDocument|4.3.0;
+ System.Xml.XmlDocument|4.3.0;
+ System.Xml.XmlSerializer|4.3.0;
+ System.Xml.XPath|4.3.0;
+ System.Xml.XPath.XDocument|4.3.0;
+
+
+
+
+
+
+
+
+
+
+ <_RuntimeAssetsForConflictResolution Include="@(RuntimeCopyLocalItems);
@(NativeCopyLocalItems);
@(ResourceCopyLocalItems);
@(RuntimeTargetsCopyLocalItems)" Exclude="@(ReferenceCopyLocalPaths)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ResolvedCopyLocalPublishAssets Remove="@(_ResolvedCopyLocalPublishAssets)" />
+ <_ResolvedCopyLocalPublishAssets Include="@(_ResolvedCopyLocalPublishAssetsWithoutConflicts)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Properties
+
+
+ $(Configuration.ToUpperInvariant())
+
+ $(ImplicitConfigurationDefine.Replace('-', '_'))
+ $(ImplicitConfigurationDefine.Replace('.', '_'))
+ $(ImplicitConfigurationDefine.Replace(' ', '_'))
+ $(DefineConstants);$(ImplicitConfigurationDefine)
+
+
+ $(DefineConstants);$(VersionlessImplicitFrameworkDefine);$(ImplicitFrameworkDefine);$(BackwardsCompatFrameworkDefine)
+
+
+
+
+
+
+
+ $(WarningsAsErrors);SYSLIB0011
+
+
+
+
+
+
+
+
+
+
+
+ <_NoneAnalysisLevel>4.0
+
+ <_LatestAnalysisLevel>9.0
+ <_PreviewAnalysisLevel>10.0
+ latest
+ $(_TargetFrameworkVersionWithoutV)
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(AnalysisLevel), '-(.)*', ''))
+ $([System.Text.RegularExpressions.Regex]::Replace($(AnalysisLevel), '$(AnalysisLevelPrefix)-', ''))
+
+ $(_NoneAnalysisLevel)
+ $(_LatestAnalysisLevel)
+ $(_PreviewAnalysisLevel)
+
+ $(AnalysisLevelPrefix)
+ $(AnalysisLevel)
+
+
+
+ 9999
+
+ 4
+
+ $(_TargetFrameworkVersionWithoutV.Substring(0, 1))
+
+
+
+
+ true
+
+ true
+
+ true
+
+ true
+
+ false
+
+
+
+ false
+ false
+ false
+ false
+ false
+
+
+
+
+
+
+
+ <_NETAnalyzersSDKAssemblyVersion>9.0.0
+
+
+
+ CA1000;CA1001;CA1002;CA1003;CA1005;CA1008;CA1010;CA1012;CA1014;CA1016;CA1017;CA1018;CA1019;CA1021;CA1024;CA1027;CA1028;CA1030;CA1031;CA1032;CA1033;CA1034;CA1036;CA1040;CA1041;CA1043;CA1044;CA1045;CA1046;CA1047;CA1050;CA1051;CA1052;CA1054;CA1055;CA1056;CA1058;CA1060;CA1061;CA1062;CA1063;CA1064;CA1065;CA1066;CA1067;CA1068;CA1069;CA1070;CA1200;CA1303;CA1304;CA1305;CA1307;CA1308;CA1309;CA1310;CA1311;CA1401;CA1416;CA1417;CA1418;CA1419;CA1420;CA1421;CA1422;CA1501;CA1502;CA1505;CA1506;CA1507;CA1508;CA1509;CA1510;CA1511;CA1512;CA1513;CA1514;CA1515;CA1700;CA1707;CA1708;CA1710;CA1711;CA1712;CA1713;CA1715;CA1716;CA1720;CA1721;CA1724;CA1725;CA1727;CA1802;CA1805;CA1806;CA1810;CA1812;CA1813;CA1814;CA1815;CA1816;CA1819;CA1820;CA1821;CA1822;CA1823;CA1824;CA1825;CA1826;CA1827;CA1828;CA1829;CA1830;CA1831;CA1832;CA1833;CA1834;CA1835;CA1836;CA1837;CA1838;CA1839;CA1840;CA1841;CA1842;CA1843;CA1844;CA1845;CA1846;CA1847;CA1848;CA1849;CA1850;CA1851;CA1852;CA1853;CA1854;CA1855;CA1856;CA1857;CA1858;CA1859;CA1860;CA1861;CA1862;CA1863;CA1864;CA1865;CA1866;CA1867;CA1868;CA1869;CA1870;CA1871;CA1872;CA2000;CA2002;CA2007;CA2008;CA2009;CA2011;CA2012;CA2013;CA2014;CA2015;CA2016;CA2017;CA2018;CA2019;CA2020;CA2021;CA2022;CA2100;CA2101;CA2119;CA2153;CA2200;CA2201;CA2207;CA2208;CA2211;CA2213;CA2214;CA2215;CA2216;CA2217;CA2218;CA2219;CA2224;CA2225;CA2226;CA2227;CA2231;CA2234;CA2235;CA2237;CA2241;CA2242;CA2243;CA2244;CA2245;CA2246;CA2247;CA2248;CA2249;CA2250;CA2251;CA2252;CA2253;CA2254;CA2255;CA2256;CA2257;CA2258;CA2259;CA2260;CA2261;CA2262;CA2263;CA2264;CA2265;CA2300;CA2301;CA2302;CA2305;CA2310;CA2311;CA2312;CA2315;CA2321;CA2322;CA2326;CA2327;CA2328;CA2329;CA2330;CA2350;CA2351;CA2352;CA2353;CA2354;CA2355;CA2356;CA2361;CA2362;CA3001;CA3002;CA3003;CA3004;CA3005;CA3006;CA3007;CA3008;CA3009;CA3010;CA3011;CA3012;CA3061;CA3075;CA3076;CA3077;CA3147;CA5350;CA5351;CA5358;CA5359;CA5360;CA5361;CA5362;CA5363;CA5364;CA5365;CA5366;CA5367;CA5368;CA5369;CA5370;CA5371;CA5372;CA5373;CA5374;CA5375;CA5376;CA5377;CA5378;CA5379;CA5380;CA5381;CA5382;CA5383;CA5384;CA5385;CA5386;CA5387;CA5388;CA5389;CA5390;CA5391;CA5392;CA5393;CA5394;CA5395;CA5396;CA5397;CA5398;CA5399;CA5400;CA5401;CA5402;CA5403;CA5404;CA5405
+ $(CodeAnalysisTreatWarningsAsErrors)
+ $(WarningsNotAsErrors);$(CodeAnalysisRuleIds)
+
+
+
+
+
+
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(EffectiveAnalysisLevel), '(.0)*$', ''))
+
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzers>$(AnalysisLevelSuffix)
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzers Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzers)' == ''">$(AnalysisMode)
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzers Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzers)' == 'AllEnabledByDefault'">All
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzers Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzers)' == 'AllDisabledByDefault'">None
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzers Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzers)' == ''">Default
+
+
+ $(CodeAnalysisTreatWarningsAsErrors)
+
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzers_WarnAsErrorSuffix Condition="'$(EffectiveCodeAnalysisTreatWarningsAsErrors)' == 'true'">_warnaserror
+
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzers Condition="'$(MicrosoftCodeAnalysisNetAnalyzersRulesVersion)' != ''">AnalysisLevel_$(MicrosoftCodeAnalysisNetAnalyzersRulesVersion.Replace(".","_"))_$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzers)$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzers_WarnAsErrorSuffix).globalconfig
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzers>$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzers.ToLowerInvariant())
+ <_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzers Condition="'$(_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzers)' == ''">$(MSBuildThisFileDirectory)config
+ <_GlobalAnalyzerConfigFile_MicrosoftCodeAnalysisNetAnalyzers Condition="'$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzers)' != ''">$(_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzers)\$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzers)
+
+
+
+
+
+
+
+
+
+ $(AnalysisLevel)
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(AnalysisLevelDesign), '-(.)*', ''))
+ $([System.Text.RegularExpressions.Regex]::Replace($(AnalysisLevelDesign), '$(AnalysisLevelPrefixDesign)-', ''))
+
+ $(_NoneAnalysisLevel)
+ $(_LatestAnalysisLevel)
+ $(_PreviewAnalysisLevel)
+
+ $(AnalysisLevelPrefixDesign)
+ $(AnalysisLevelDesign)
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(EffectiveAnalysisLevelDesign), '(.0)*$', ''))
+
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersDesign>$(AnalysisLevelSuffixDesign)
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersDesign Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersDesign)' == ''">$(AnalysisModeDesign)
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersDesign Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersDesign)' == 'AllEnabledByDefault'">All
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersDesign Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersDesign)' == 'AllDisabledByDefault'">None
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersDesign Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersDesign)' == ''">Default
+
+
+ $(CodeAnalysisTreatWarningsAsErrors)
+
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersDesign_WarnAsErrorSuffix Condition="'$(EffectiveCodeAnalysisTreatWarningsAsErrors)' == 'true'">_warnaserror
+
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersDesign Condition="'$(MicrosoftCodeAnalysisNetAnalyzersDesignRulesVersion)' != ''">AnalysisLevelDesign_$(MicrosoftCodeAnalysisNetAnalyzersDesignRulesVersion.Replace(".","_"))_$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersDesign)$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersDesign_WarnAsErrorSuffix).globalconfig
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersDesign>$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersDesign.ToLowerInvariant())
+ <_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersDesign Condition="'$(_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersDesign)' == ''">$(MSBuildThisFileDirectory)config
+ <_GlobalAnalyzerConfigFile_MicrosoftCodeAnalysisNetAnalyzersDesign Condition="'$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersDesign)' != ''">$(_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersDesign)\$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersDesign)
+
+
+
+
+
+
+
+
+
+ $(AnalysisLevel)
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(AnalysisLevelDocumentation), '-(.)*', ''))
+ $([System.Text.RegularExpressions.Regex]::Replace($(AnalysisLevelDocumentation), '$(AnalysisLevelPrefixDocumentation)-', ''))
+
+ $(_NoneAnalysisLevel)
+ $(_LatestAnalysisLevel)
+ $(_PreviewAnalysisLevel)
+
+ $(AnalysisLevelPrefixDocumentation)
+ $(AnalysisLevelDocumentation)
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(EffectiveAnalysisLevelDocumentation), '(.0)*$', ''))
+
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersDocumentation>$(AnalysisLevelSuffixDocumentation)
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersDocumentation Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersDocumentation)' == ''">$(AnalysisModeDocumentation)
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersDocumentation Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersDocumentation)' == 'AllEnabledByDefault'">All
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersDocumentation Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersDocumentation)' == 'AllDisabledByDefault'">None
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersDocumentation Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersDocumentation)' == ''">Default
+
+
+ $(CodeAnalysisTreatWarningsAsErrors)
+
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersDocumentation_WarnAsErrorSuffix Condition="'$(EffectiveCodeAnalysisTreatWarningsAsErrors)' == 'true'">_warnaserror
+
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersDocumentation Condition="'$(MicrosoftCodeAnalysisNetAnalyzersDocumentationRulesVersion)' != ''">AnalysisLevelDocumentation_$(MicrosoftCodeAnalysisNetAnalyzersDocumentationRulesVersion.Replace(".","_"))_$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersDocumentation)$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersDocumentation_WarnAsErrorSuffix).globalconfig
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersDocumentation>$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersDocumentation.ToLowerInvariant())
+ <_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersDocumentation Condition="'$(_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersDocumentation)' == ''">$(MSBuildThisFileDirectory)config
+ <_GlobalAnalyzerConfigFile_MicrosoftCodeAnalysisNetAnalyzersDocumentation Condition="'$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersDocumentation)' != ''">$(_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersDocumentation)\$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersDocumentation)
+
+
+
+
+
+
+
+
+
+ $(AnalysisLevel)
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(AnalysisLevelGlobalization), '-(.)*', ''))
+ $([System.Text.RegularExpressions.Regex]::Replace($(AnalysisLevelGlobalization), '$(AnalysisLevelPrefixGlobalization)-', ''))
+
+ $(_NoneAnalysisLevel)
+ $(_LatestAnalysisLevel)
+ $(_PreviewAnalysisLevel)
+
+ $(AnalysisLevelPrefixGlobalization)
+ $(AnalysisLevelGlobalization)
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(EffectiveAnalysisLevelGlobalization), '(.0)*$', ''))
+
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersGlobalization>$(AnalysisLevelSuffixGlobalization)
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersGlobalization Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersGlobalization)' == ''">$(AnalysisModeGlobalization)
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersGlobalization Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersGlobalization)' == 'AllEnabledByDefault'">All
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersGlobalization Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersGlobalization)' == 'AllDisabledByDefault'">None
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersGlobalization Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersGlobalization)' == ''">Default
+
+
+ $(CodeAnalysisTreatWarningsAsErrors)
+
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersGlobalization_WarnAsErrorSuffix Condition="'$(EffectiveCodeAnalysisTreatWarningsAsErrors)' == 'true'">_warnaserror
+
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersGlobalization Condition="'$(MicrosoftCodeAnalysisNetAnalyzersGlobalizationRulesVersion)' != ''">AnalysisLevelGlobalization_$(MicrosoftCodeAnalysisNetAnalyzersGlobalizationRulesVersion.Replace(".","_"))_$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersGlobalization)$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersGlobalization_WarnAsErrorSuffix).globalconfig
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersGlobalization>$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersGlobalization.ToLowerInvariant())
+ <_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersGlobalization Condition="'$(_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersGlobalization)' == ''">$(MSBuildThisFileDirectory)config
+ <_GlobalAnalyzerConfigFile_MicrosoftCodeAnalysisNetAnalyzersGlobalization Condition="'$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersGlobalization)' != ''">$(_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersGlobalization)\$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersGlobalization)
+
+
+
+
+
+
+
+
+
+ $(AnalysisLevel)
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(AnalysisLevelInteroperability), '-(.)*', ''))
+ $([System.Text.RegularExpressions.Regex]::Replace($(AnalysisLevelInteroperability), '$(AnalysisLevelPrefixInteroperability)-', ''))
+
+ $(_NoneAnalysisLevel)
+ $(_LatestAnalysisLevel)
+ $(_PreviewAnalysisLevel)
+
+ $(AnalysisLevelPrefixInteroperability)
+ $(AnalysisLevelInteroperability)
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(EffectiveAnalysisLevelInteroperability), '(.0)*$', ''))
+
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersInteroperability>$(AnalysisLevelSuffixInteroperability)
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersInteroperability Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersInteroperability)' == ''">$(AnalysisModeInteroperability)
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersInteroperability Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersInteroperability)' == 'AllEnabledByDefault'">All
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersInteroperability Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersInteroperability)' == 'AllDisabledByDefault'">None
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersInteroperability Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersInteroperability)' == ''">Default
+
+
+ $(CodeAnalysisTreatWarningsAsErrors)
+
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersInteroperability_WarnAsErrorSuffix Condition="'$(EffectiveCodeAnalysisTreatWarningsAsErrors)' == 'true'">_warnaserror
+
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersInteroperability Condition="'$(MicrosoftCodeAnalysisNetAnalyzersInteroperabilityRulesVersion)' != ''">AnalysisLevelInteroperability_$(MicrosoftCodeAnalysisNetAnalyzersInteroperabilityRulesVersion.Replace(".","_"))_$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersInteroperability)$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersInteroperability_WarnAsErrorSuffix).globalconfig
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersInteroperability>$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersInteroperability.ToLowerInvariant())
+ <_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersInteroperability Condition="'$(_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersInteroperability)' == ''">$(MSBuildThisFileDirectory)config
+ <_GlobalAnalyzerConfigFile_MicrosoftCodeAnalysisNetAnalyzersInteroperability Condition="'$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersInteroperability)' != ''">$(_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersInteroperability)\$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersInteroperability)
+
+
+
+
+
+
+
+
+
+ $(AnalysisLevel)
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(AnalysisLevelMaintainability), '-(.)*', ''))
+ $([System.Text.RegularExpressions.Regex]::Replace($(AnalysisLevelMaintainability), '$(AnalysisLevelPrefixMaintainability)-', ''))
+
+ $(_NoneAnalysisLevel)
+ $(_LatestAnalysisLevel)
+ $(_PreviewAnalysisLevel)
+
+ $(AnalysisLevelPrefixMaintainability)
+ $(AnalysisLevelMaintainability)
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(EffectiveAnalysisLevelMaintainability), '(.0)*$', ''))
+
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersMaintainability>$(AnalysisLevelSuffixMaintainability)
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersMaintainability Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersMaintainability)' == ''">$(AnalysisModeMaintainability)
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersMaintainability Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersMaintainability)' == 'AllEnabledByDefault'">All
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersMaintainability Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersMaintainability)' == 'AllDisabledByDefault'">None
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersMaintainability Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersMaintainability)' == ''">Default
+
+
+ $(CodeAnalysisTreatWarningsAsErrors)
+
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersMaintainability_WarnAsErrorSuffix Condition="'$(EffectiveCodeAnalysisTreatWarningsAsErrors)' == 'true'">_warnaserror
+
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersMaintainability Condition="'$(MicrosoftCodeAnalysisNetAnalyzersMaintainabilityRulesVersion)' != ''">AnalysisLevelMaintainability_$(MicrosoftCodeAnalysisNetAnalyzersMaintainabilityRulesVersion.Replace(".","_"))_$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersMaintainability)$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersMaintainability_WarnAsErrorSuffix).globalconfig
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersMaintainability>$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersMaintainability.ToLowerInvariant())
+ <_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersMaintainability Condition="'$(_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersMaintainability)' == ''">$(MSBuildThisFileDirectory)config
+ <_GlobalAnalyzerConfigFile_MicrosoftCodeAnalysisNetAnalyzersMaintainability Condition="'$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersMaintainability)' != ''">$(_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersMaintainability)\$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersMaintainability)
+
+
+
+
+
+
+
+
+
+ $(AnalysisLevel)
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(AnalysisLevelNaming), '-(.)*', ''))
+ $([System.Text.RegularExpressions.Regex]::Replace($(AnalysisLevelNaming), '$(AnalysisLevelPrefixNaming)-', ''))
+
+ $(_NoneAnalysisLevel)
+ $(_LatestAnalysisLevel)
+ $(_PreviewAnalysisLevel)
+
+ $(AnalysisLevelPrefixNaming)
+ $(AnalysisLevelNaming)
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(EffectiveAnalysisLevelNaming), '(.0)*$', ''))
+
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersNaming>$(AnalysisLevelSuffixNaming)
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersNaming Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersNaming)' == ''">$(AnalysisModeNaming)
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersNaming Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersNaming)' == 'AllEnabledByDefault'">All
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersNaming Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersNaming)' == 'AllDisabledByDefault'">None
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersNaming Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersNaming)' == ''">Default
+
+
+ $(CodeAnalysisTreatWarningsAsErrors)
+
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersNaming_WarnAsErrorSuffix Condition="'$(EffectiveCodeAnalysisTreatWarningsAsErrors)' == 'true'">_warnaserror
+
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersNaming Condition="'$(MicrosoftCodeAnalysisNetAnalyzersNamingRulesVersion)' != ''">AnalysisLevelNaming_$(MicrosoftCodeAnalysisNetAnalyzersNamingRulesVersion.Replace(".","_"))_$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersNaming)$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersNaming_WarnAsErrorSuffix).globalconfig
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersNaming>$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersNaming.ToLowerInvariant())
+ <_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersNaming Condition="'$(_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersNaming)' == ''">$(MSBuildThisFileDirectory)config
+ <_GlobalAnalyzerConfigFile_MicrosoftCodeAnalysisNetAnalyzersNaming Condition="'$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersNaming)' != ''">$(_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersNaming)\$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersNaming)
+
+
+
+
+
+
+
+
+
+ $(AnalysisLevel)
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(AnalysisLevelPerformance), '-(.)*', ''))
+ $([System.Text.RegularExpressions.Regex]::Replace($(AnalysisLevelPerformance), '$(AnalysisLevelPrefixPerformance)-', ''))
+
+ $(_NoneAnalysisLevel)
+ $(_LatestAnalysisLevel)
+ $(_PreviewAnalysisLevel)
+
+ $(AnalysisLevelPrefixPerformance)
+ $(AnalysisLevelPerformance)
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(EffectiveAnalysisLevelPerformance), '(.0)*$', ''))
+
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersPerformance>$(AnalysisLevelSuffixPerformance)
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersPerformance Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersPerformance)' == ''">$(AnalysisModePerformance)
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersPerformance Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersPerformance)' == 'AllEnabledByDefault'">All
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersPerformance Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersPerformance)' == 'AllDisabledByDefault'">None
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersPerformance Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersPerformance)' == ''">Default
+
+
+ $(CodeAnalysisTreatWarningsAsErrors)
+
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersPerformance_WarnAsErrorSuffix Condition="'$(EffectiveCodeAnalysisTreatWarningsAsErrors)' == 'true'">_warnaserror
+
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersPerformance Condition="'$(MicrosoftCodeAnalysisNetAnalyzersPerformanceRulesVersion)' != ''">AnalysisLevelPerformance_$(MicrosoftCodeAnalysisNetAnalyzersPerformanceRulesVersion.Replace(".","_"))_$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersPerformance)$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersPerformance_WarnAsErrorSuffix).globalconfig
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersPerformance>$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersPerformance.ToLowerInvariant())
+ <_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersPerformance Condition="'$(_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersPerformance)' == ''">$(MSBuildThisFileDirectory)config
+ <_GlobalAnalyzerConfigFile_MicrosoftCodeAnalysisNetAnalyzersPerformance Condition="'$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersPerformance)' != ''">$(_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersPerformance)\$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersPerformance)
+
+
+
+
+
+
+
+
+
+ $(AnalysisLevel)
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(AnalysisLevelReliability), '-(.)*', ''))
+ $([System.Text.RegularExpressions.Regex]::Replace($(AnalysisLevelReliability), '$(AnalysisLevelPrefixReliability)-', ''))
+
+ $(_NoneAnalysisLevel)
+ $(_LatestAnalysisLevel)
+ $(_PreviewAnalysisLevel)
+
+ $(AnalysisLevelPrefixReliability)
+ $(AnalysisLevelReliability)
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(EffectiveAnalysisLevelReliability), '(.0)*$', ''))
+
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersReliability>$(AnalysisLevelSuffixReliability)
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersReliability Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersReliability)' == ''">$(AnalysisModeReliability)
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersReliability Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersReliability)' == 'AllEnabledByDefault'">All
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersReliability Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersReliability)' == 'AllDisabledByDefault'">None
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersReliability Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersReliability)' == ''">Default
+
+
+ $(CodeAnalysisTreatWarningsAsErrors)
+
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersReliability_WarnAsErrorSuffix Condition="'$(EffectiveCodeAnalysisTreatWarningsAsErrors)' == 'true'">_warnaserror
+
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersReliability Condition="'$(MicrosoftCodeAnalysisNetAnalyzersReliabilityRulesVersion)' != ''">AnalysisLevelReliability_$(MicrosoftCodeAnalysisNetAnalyzersReliabilityRulesVersion.Replace(".","_"))_$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersReliability)$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersReliability_WarnAsErrorSuffix).globalconfig
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersReliability>$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersReliability.ToLowerInvariant())
+ <_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersReliability Condition="'$(_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersReliability)' == ''">$(MSBuildThisFileDirectory)config
+ <_GlobalAnalyzerConfigFile_MicrosoftCodeAnalysisNetAnalyzersReliability Condition="'$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersReliability)' != ''">$(_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersReliability)\$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersReliability)
+
+
+
+
+
+
+
+
+
+ $(AnalysisLevel)
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(AnalysisLevelSecurity), '-(.)*', ''))
+ $([System.Text.RegularExpressions.Regex]::Replace($(AnalysisLevelSecurity), '$(AnalysisLevelPrefixSecurity)-', ''))
+
+ $(_NoneAnalysisLevel)
+ $(_LatestAnalysisLevel)
+ $(_PreviewAnalysisLevel)
+
+ $(AnalysisLevelPrefixSecurity)
+ $(AnalysisLevelSecurity)
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(EffectiveAnalysisLevelSecurity), '(.0)*$', ''))
+
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersSecurity>$(AnalysisLevelSuffixSecurity)
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersSecurity Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersSecurity)' == ''">$(AnalysisModeSecurity)
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersSecurity Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersSecurity)' == 'AllEnabledByDefault'">All
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersSecurity Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersSecurity)' == 'AllDisabledByDefault'">None
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersSecurity Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersSecurity)' == ''">Default
+
+
+ $(CodeAnalysisTreatWarningsAsErrors)
+
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersSecurity_WarnAsErrorSuffix Condition="'$(EffectiveCodeAnalysisTreatWarningsAsErrors)' == 'true'">_warnaserror
+
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersSecurity Condition="'$(MicrosoftCodeAnalysisNetAnalyzersSecurityRulesVersion)' != ''">AnalysisLevelSecurity_$(MicrosoftCodeAnalysisNetAnalyzersSecurityRulesVersion.Replace(".","_"))_$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersSecurity)$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersSecurity_WarnAsErrorSuffix).globalconfig
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersSecurity>$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersSecurity.ToLowerInvariant())
+ <_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersSecurity Condition="'$(_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersSecurity)' == ''">$(MSBuildThisFileDirectory)config
+ <_GlobalAnalyzerConfigFile_MicrosoftCodeAnalysisNetAnalyzersSecurity Condition="'$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersSecurity)' != ''">$(_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersSecurity)\$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersSecurity)
+
+
+
+
+
+
+
+
+
+ $(AnalysisLevel)
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(AnalysisLevelUsage), '-(.)*', ''))
+ $([System.Text.RegularExpressions.Regex]::Replace($(AnalysisLevelUsage), '$(AnalysisLevelPrefixUsage)-', ''))
+
+ $(_NoneAnalysisLevel)
+ $(_LatestAnalysisLevel)
+ $(_PreviewAnalysisLevel)
+
+ $(AnalysisLevelPrefixUsage)
+ $(AnalysisLevelUsage)
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(EffectiveAnalysisLevelUsage), '(.0)*$', ''))
+
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersUsage>$(AnalysisLevelSuffixUsage)
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersUsage Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersUsage)' == ''">$(AnalysisModeUsage)
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersUsage Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersUsage)' == 'AllEnabledByDefault'">All
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersUsage Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersUsage)' == 'AllDisabledByDefault'">None
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersUsage Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersUsage)' == ''">Default
+
+
+ $(CodeAnalysisTreatWarningsAsErrors)
+
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersUsage_WarnAsErrorSuffix Condition="'$(EffectiveCodeAnalysisTreatWarningsAsErrors)' == 'true'">_warnaserror
+
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersUsage Condition="'$(MicrosoftCodeAnalysisNetAnalyzersUsageRulesVersion)' != ''">AnalysisLevelUsage_$(MicrosoftCodeAnalysisNetAnalyzersUsageRulesVersion.Replace(".","_"))_$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisNetAnalyzersUsage)$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersUsage_WarnAsErrorSuffix).globalconfig
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersUsage>$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersUsage.ToLowerInvariant())
+ <_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersUsage Condition="'$(_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersUsage)' == ''">$(MSBuildThisFileDirectory)config
+ <_GlobalAnalyzerConfigFile_MicrosoftCodeAnalysisNetAnalyzersUsage Condition="'$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersUsage)' != ''">$(_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisNetAnalyzersUsage)\$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisNetAnalyzersUsage)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_SupportedPlatformList>@(SupportedPlatform, ',')
+
+
+
+
+
+
+
+
+ $(CodeAnalysisTreatWarningsAsErrors)
+ $(WarningsNotAsErrors);$(CodeAnalysisRuleIds)
+
+
+
+
+
+
+
+
+ $(AnalysisLevel)
+
+ $([System.Text.RegularExpressions.Regex]::Replace($(AnalysisLevelStyle), '-(.)*', ''))
+ $([System.Text.RegularExpressions.Regex]::Replace($(AnalysisLevelStyle), '$(AnalysisLevelPrefixStyle)-', ''))
+
+ $(AnalysisLevelSuffix)
+
+ $(AnalysisMode)
+
+ $(_NoneAnalysisLevel)
+ $(_LatestAnalysisLevel)
+ $(_PreviewAnalysisLevel)
+
+ $(AnalysisLevelPrefixStyle)
+ $(AnalysisLevelStyle)
+
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisCSharpCodeStyle>$(AnalysisModeStyle)
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisCSharpCodeStyle Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisCSharpCodeStyle)' == ''">$(AnalysisLevelSuffixStyle)
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisCSharpCodeStyle Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisCSharpCodeStyle)' == 'AllEnabledByDefault'">All
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisCSharpCodeStyle Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisCSharpCodeStyle)' == 'AllDisabledByDefault'">None
+ <_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisCSharpCodeStyle Condition="'$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisCSharpCodeStyle)' == ''">Default
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisCSharpCodeStyle>AnalysisLevelStyle_$(_GlobalAnalyzerConfigAnalysisMode_MicrosoftCodeAnalysisCSharpCodeStyle).globalconfig
+ <_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisCSharpCodeStyle>$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisCSharpCodeStyle.ToLowerInvariant())
+ <_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisCSharpCodeStyle Condition="'$(_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisCSharpCodeStyle)' == ''">$(MSBuildThisFileDirectory)config
+ <_GlobalAnalyzerConfigFile_MicrosoftCodeAnalysisCSharpCodeStyle Condition="'$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisCSharpCodeStyle)' != ''">$(_GlobalAnalyzerConfigDir_MicrosoftCodeAnalysisCSharpCodeStyle)\$(_GlobalAnalyzerConfigFileName_MicrosoftCodeAnalysisCSharpCodeStyle)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ true
+
+
+ $(AfterMicrosoftNETSdkTargets);$(MSBuildThisFileDirectory)../../Microsoft.NET.Sdk.WindowsDesktop/targets/Microsoft.NET.Sdk.WindowsDesktop.targets
+
+
+
+
+
+
+
+
+
+ 0.0
+ $(TargetPlatformIdentifier),Version=$(TargetPlatformVersion)
+ $([Microsoft.Build.Utilities.ToolLocationHelper]::GetPlatformSDKDisplayName($(TargetPlatformIdentifier), $(TargetPlatformVersion)))
+
+
+
+ $(TargetPlatformVersion)
+
+
+
+
+
+
+
+
+
+
+ <_ResizetizerTaskAssemblyName>$(MSBuildThisFileDirectory)\Microsoft.Maui.Resizetizer.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(CleanDependsOn);
+ _CleanResizetizer;
+
+ <_ResizetizerPlatformIdentifier>$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)'))
+ <_ResizetizerNoTargetPlatform Condition="'$(_ResizetizerPlatformIdentifier)' == ''">True
+ <_ResizetizerPlatformIsAndroid Condition="'$(_ResizetizerPlatformIdentifier)' == 'android'">True
+ <_ResizetizerPlatformIsiOS Condition="'$(_ResizetizerPlatformIdentifier)' == 'ios'">True
+ <_ResizetizerPlatformIsMacCatalyst Condition="'$(_ResizetizerPlatformIdentifier)' == 'maccatalyst'">True
+ <_ResizetizerPlatformIsmacOS Condition="'$(_ResizetizerPlatformIdentifier)' == 'macos'">True
+ <_ResizetizerPlatformIstvOS Condition="'$(_ResizetizerPlatformIdentifier)' == 'tvos'">True
+ <_ResizetizerPlatformIsWindows Condition="$(_ResizetizerPlatformIdentifier.Contains('windows')) == 'True'">True
+ <_ResizetizerPlatformIsTizen Condition="'$(_ResizetizerPlatformIdentifier)' == 'tizen'">True
+ <_ResizetizerIntermediateOutputPath Condition=" '$(_ResizetizerIntermediateOutputPath)' == '' ">$(IntermediateOutputPath)
+ <_ResizetizerInputsFile>$(_ResizetizerIntermediateOutputPath)mauiimage.inputs
+ <_ResizetizerOutputsFile>$(_ResizetizerIntermediateOutputPath)mauiimage.outputs
+ <_ResizetizerStampFile>$(_ResizetizerIntermediateOutputPath)mauiimage.stamp
+ <_MauiFontInputsFile>$(_ResizetizerIntermediateOutputPath)mauifont.inputs
+ <_MauiFontStampFile>$(_ResizetizerIntermediateOutputPath)mauifont.stamp
+ <_MauiSplashInputsFile>$(_ResizetizerIntermediateOutputPath)mauisplash.inputs
+ <_MauiSplashStampFile>$(_ResizetizerIntermediateOutputPath)mauisplash.stamp
+ <_MauiManifestStampFile>$(_ResizetizerIntermediateOutputPath)mauimanifest.stamp
+ <_ResizetizerIntermediateOutputRoot>$(_ResizetizerIntermediateOutputPath)resizetizer\
+ <_MauiIntermediateImages>$(_ResizetizerIntermediateOutputRoot)r\
+ <_MauiIntermediateFonts>$(_ResizetizerIntermediateOutputRoot)f\
+ <_MauiIntermediateSplashScreen>$(_ResizetizerIntermediateOutputRoot)sp\
+ <_MauiIntermediateManifest>$(_ResizetizerIntermediateOutputRoot)m\
+ False
+ <_ResizetizerDefaultInvalidFilenamesErrorMessage>One or more invalid file names were detected. File names must be lowercase, start and end with a letter character, and contain only alphanumeric characters or underscores:
+ <_ResizetizerDefaultDuplicateFilenamesErrorMessage>One or more duplicate file names were detected. All image output filenames must be unique:
+ <_ResizetizerThrowsErrorOnInvalidFilename>true
+ <_ResizetizerThrowsErrorOnInvalidFilename Condition="'$(ResizetizerErrorOnInvalidFilename)' == 'false'">false
+ <_ResizetizerThrowsErrorOnDuplicateOutputFilename>true
+ <_ResizetizerThrowsErrorOnDuplicateOutputFilename Condition="'$(ResizetizerErrorOnDuplicateOutputFilename)' == 'false'">false
+ true
+ true
+ true
+ true
+
+
+ <_ResizetizerIsNetCore>True
+ <_ResizetizerIsAndroidApp Condition=" '$(_ResizetizerPlatformIsAndroid)' == 'True' And '$(AndroidApplication)' == 'True'">True
+ <_ResizetizerIsiOSApp Condition="( '$(_ResizetizerPlatformIsiOS)' == 'True' OR '$(_ResizetizerPlatformIsMacCatalyst)' == 'True' ) And ('$(OutputType)' == 'Exe' Or '$(IsAppExtension)' == 'True')">True
+ <_ResizetizerIsiOSSpecificApp Condition=" '$(_ResizetizerPlatformIsiOS)' == 'True' And ('$(OutputType)' == 'Exe' Or '$(IsAppExtension)' == 'True')">True
+ <_ResizetizerIsWPFApp Condition="'$(IsApplication)' == 'True' And '$(NuGetRuntimeIdentifier)' == 'win' And '$(_ResizetizerPlatformIsWindows)' == 'True'">True
+ <_ResizetizerIsWindowsAppSdk Condition="'$(MicrosoftWindowsAppSDKPackageDir)' != '' And '$(_ResizetizerPlatformIsWindows)' == 'True' And ('$(OutputType)' == 'WinExe' Or '$(OutputType)' == 'Exe')">True
+ <_ResizetizerIsTizenApp Condition="'$(_ResizetizerPlatformIsTizen)' == 'True' And ( '$(OutputType)' == 'Exe' )">True
+
+
+ <_ResizetizerIsCompatibleApp>True
+
+ $(ResizetizeDependsOnTargets);
+ ResizetizeCollectItems;
+ ProcessMauiSplashScreens;
+ _ReadResizetizeImagesOutputs;
+
+
+ $(ProcessMauiFontsDependsOnTargets);
+ ResizetizeCollectItems;
+ ProcessMauiAssets;
+ ProcessMauiSplashScreens;
+
+
+
+
+ ios
+
+ true
+
+ $(CollectBundleResourcesDependsOn);
+ ResizetizeCollectItems;
+
+
+ $(CompileImageAssetsDependsOn);
+ ResizetizeCollectItems;
+
+
+ $(ResizetizeAfterTargets);
+ ResizetizeCollectItems;
+
+
+ ProcessMauiFonts;
+ ProcessMauiSplashScreens;
+ $(CollectAppManifestsDependsOn)
+
+
+
+
+ android
+
+ $(ResizetizeCollectItemsBeforeTargets);
+ _ComputeAndroidResourcePaths;
+
+
+ $(ResizetizeAfterTargets);
+ ResizetizeCollectItems;
+
+
+ $(ProcessMauiFontsAfterTargets);
+ ResizetizeCollectItems;
+
+
+
+
+ uwp
+
+ $(ResizetizeBeforeTargets);
+ AssignTargetPaths;
+
+
+ $(ProcessMauiFontsBeforeTargets);
+ AssignTargetPaths;
+
+
+ $(MauiGeneratePackageAppxManifestDependsOnTargets);
+ ResizetizeCollectItems;
+
+
+
+
+ wpf
+
+ $(ResizetizeBeforeTargets);
+ FileClassification;
+
+
+ $(ProcessMauiFontsBeforeTargets);
+ FileClassification;
+
+
+
+
+ tizen
+
+ $(ResizetizeBeforeTargets);
+ PrepareResources;
+
+
+ $(ResizetizeAfterTargets);
+ ResizetizeCollectItems;
+
+
+ $(ProcessMauiFontsAfterTargets);
+ ResizetizeCollectItems;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ResizetizeCollectItemsProjectWithOIS Include="@(_ResolvedProjectReferencePaths->HasMetadata('OriginalProjectReferenceItemSpec'))" />
+
+ <_ResizetizeCollectItemsProjectWithItemSpec Include="@(_ResizetizeCollectItemsProjectWithOIS->'%(OriginalProjectReferenceItemSpec)')" />
+
+ <_ResizetizeCollectItemsProject Include="@(_ResizetizeCollectItemsProjectWithItemSpec->HasMetadata('NearestTargetFramework'))" />
+
+ <_ResizetizeCollectItemsProject Include="@(ProjectReference)" Exclude="@(_ResizetizeCollectItemsProject)" NearestTargetFramework="$(TargetFramework)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_MauiSplashScreenWithHashes Update="@(_MauiSplashScreenWithHashes)" InputsFileHash="$(_MauiSplashInputsFileHash)" />
+
+
+
+
+
+
+
+
+
+
+ <_MauiAssetWithLinkMetadata Include="@(MauiAsset)" Link="%(MauiAsset.LogicalName)" Condition="'%(MauiAsset.Link)' == '' And '%(MauiAsset.LogicalName)' != ''" />
+ <_MauiAssetWithLinkMetadata Include="@(MauiAsset)" Condition="'%(MauiAsset.Link)' != '' Or '%(MauiAsset.LogicalName)' == ''" />
+
+
+
+ <_MauiAssetItemMetadata Condition="'$(_ResizetizerIsAndroidApp)' == 'True'">Link
+ <_MauiAssetItemMetadata Condition="'$(_ResizetizerIsiOSApp)' == 'True'">Link
+ <_MauiAssetItemMetadata Condition="'$(_ResizetizerIsWindowsAppSdk)' == 'True'">TargetPath
+ <_MauiAssetItemMetadata Condition="'$(_ResizetizerIsTizenApp)' == 'True'">TizenTpkFileName
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_MauiHasSplashScreens>false
+ <_MauiHasSplashScreens Condition="'@(MauiSplashScreen->Count())' != '0'">true
+ <_MauiShouldGenerateSplashScreen Condition="'$(_MauiHasSplashScreens)' == 'true'">true
+ <_MauiShouldGenerateSplashScreen Condition="'$(_ResizetizerIsiOSSpecificApp)' == 'True' and '$(_MauiHasSplashScreens)' != 'true' and '$(EnableBlankMauiSplashScreen)' == 'true'">true
+
+
+
+
+
+
+ <_MauiSplashAssets Include="$(_MauiIntermediateSplashScreen)**\*" />
+
+ $(_ResizetizerStampFile)
+
+
+
+
+
+ <_MauiSplashScreenWithHashesInFilename Include="@(_MauiSplashScreenWithHashes->HasMetadata('Link'))" OriginalLink="%(_MauiSplashScreenWithHashes.Link)" Link="$([System.IO.Path]::GetFilenameWithoutExtension('%(_MauiSplashScreenWithHashes.Link)'))_%(InputsFileHash)$([System.IO.Path]::GetExtension('%(_MauiSplashScreenWithHashes.Link)'))" />
+ <_MauiSplashScreenWithHashesInFilename Include="@(_MauiSplashScreenWithHashes)" Exclude="@(_MauiSplashScreenWithHashesInFilename)" Link="%(Filename)_%(InputsFileHash)%(Extension)" />
+
+
+
+ <_MauiIntermediateStoryboard>$(_MauiIntermediateSplashScreen)MauiSplash.storyboard
+ <_MauiIntermediatePList>$(_MauiIntermediateSplashScreen)MauiInfo.plist
+
+
+
+ <_MauiSplashAssets Include="$(_MauiIntermediateSplashScreen)**\*" />
+ <_MauiSplashStoryboard Include="$(_MauiIntermediateStoryboard)" />
+ <_MauiSplashPList Include="$(_MauiIntermediatePList)" />
+ <_MauiSplashImages Include="@(_MauiSplashAssets)" Exclude="@(_MauiSplashStoryboard);@(_MauiSplashPList)" />
+
+
+
+
+
+
+ %(_MauiSplashImages.Filename)%(_MauiSplashImages.Extension)
+ %(_MauiSplashImages.Filename)%(_MauiSplashImages.Extension)
+
+
+
+
+
+ <_MauiSplashAssets Include="$(_MauiIntermediateSplashScreen)**\*" />
+
+ %(_MauiSplashAssets.Filename)%(_MauiSplashAssets.Extension)
+ PreserveNewest
+
+
+
+
+
+ <_MauiSplashAssets Include="$(_MauiIntermediateSplashScreen)**\*" />
+
+ <_MauiSplashScreens Include="$(_MauiIntermediateSplashScreen)splash\*" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_MauiFontCopied Include="$(_MauiIntermediateFonts)*" />
+
+
+
+
+ <_MauiFontBundleResource Include="@(_MauiFontCopied)">
+ $([System.IO.Path]::GetFileName(%(_MauiFontCopied.Identity)))
+ $([System.IO.Path]::GetFileName(%(_MauiFontCopied.Identity)))
+
+
+
+
+
+
+
+ <_MauiFontPListFiles Include="$(_MauiIntermediateFonts)MauiInfo.plist" Condition="Exists('$(_MauiIntermediateFonts)MauiInfo.plist')" />
+
+
+
+
+
+
+ $([System.IO.Path]::GetFileName(%(_MauiFontCopied.Identity)))
+
+
+
+
+
+ $([System.IO.Path]::GetFileName(%(_MauiFontCopied.Identity)))
+ PreserveNewest
+
+
+
+
+
+ $([System.IO.Path]::GetFileName(%(_MauiFontCopied.Identity)))
+ $([System.IO.Path]::GetFileName(%(_MauiFontCopied.Identity)))
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_MauiImageToProcess Include="@(MauiImage)" Condition=" '%(FileName)%(Extension)' != '.DS_Store' " />
+
+
+
+
+
+
+
+
+
+ <_ResizetizerCollectedImages Condition="'@(_CopiedResources->Count())' != '0'" Include="@(_CopiedResources)" />
+ <_ResizetizerExistingImages Include="$(_MauiIntermediateImages)\**\*" />
+ <_ResizetizerImagesToDelete Include="@(_ResizetizerExistingImages->'%(FullPath)')" />
+ <_ResizetizerCollectedImages Condition="'@(_CopiedResources)' == ''" Include="@(_ResizetizerExistingImages->'%(FullPath)')" />
+ <_ResizetizerImagesToDelete Remove="@(_ResizetizerCollectedImages)" />
+
+
+
+
+
+
+ <_ResizetizerCollectedBundleResourceImages Include="@(_ResizetizerCollectedImages->'%(FullPath)')">
+ %(_ResizetizerCollectedImages.Filename)%(_ResizetizerCollectedImages.Extension)
+ %(_ResizetizerCollectedImages.Filename)%(_ResizetizerCollectedImages.Extension)
+
+
+
+
+ Assets.xcassets\$([System.IO.Path]::GetFileName($([System.IO.Path]::GetDirectoryName(%(_ResizetizerCollectedBundleResourceImages.Identity)))))\%(_ResizetizerCollectedBundleResourceImages.Filename)%(_ResizetizerCollectedBundleResourceImages.Extension)
+ Assets.xcassets\$([System.IO.Path]::GetFileName($([System.IO.Path]::GetDirectoryName(%(_ResizetizerCollectedBundleResourceImages.Identity)))))\%(_ResizetizerCollectedBundleResourceImages.Filename)%(_ResizetizerCollectedBundleResourceImages.Extension)
+ Assets.xcassets\$([System.IO.Path]::GetFileName($([System.IO.Path]::GetDirectoryName(%(_ResizetizerCollectedBundleResourceImages.Identity)))))\%(_ResizetizerCollectedBundleResourceImages.Filename)%(_ResizetizerCollectedBundleResourceImages.Extension)
+
+
+
+
+
+
+
+ $(_ResizetizerStampFile)
+
+
+
+
+
+
+ %(_ResizetizerCollectedImages.Filename)%(_ResizetizerCollectedImages.Extension)
+ PreserveNewest
+
+
+ <_MauiAppIconFile Include="@(_ResizetizerCollectedImages)" Condition="'%(Extension)' == '.ico'" />
+
+
+ %(_MauiAppIconFile.Identity)
+
+
+
+
+ %(_ResizetizerCollectedImages.Filename)%(_ResizetizerCollectedImages.Extension)
+ %(_ResizetizerCollectedImages.Filename)%(_ResizetizerCollectedImages.Extension)
+
+
+
+
+
+ $([System.IO.Path]::GetFullPath('$(_MauiIntermediateImages)'))
+
+
+
+
+
+ $([MSBuild]::MakeRelative($(ResizetizerIntermediateOutputAbsolutePath), $([System.IO.Path]::GetFullPath('%(_ResizetizerCollectedImages.RelativeDir)'))))
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_MauiAppxManifest Include="@(AppxManifest)" />
+
+
+
+
+
+
+
+ <_MauiWindowsApplicationId Condition="'$(_MauiWindowsApplicationId)' == '' and '$(ApplicationIdGuid)' != ''">$(ApplicationIdGuid)
+ <_MauiWindowsApplicationId Condition="'$(_MauiWindowsApplicationId)' == '' and '$(ApplicationId)' != ''">$(ApplicationId)
+
+
+
+
+
+
+
+
+ <_MauiAppxManifest Remove="@(_MauiAppxManifest)" />
+ <_MauiAppxManifest Include="$(_MauiIntermediateManifest)Package.appxmanifest" />
+
+
+
+
+
+
+
+
+
+
+
+ <_MauiAppxManifestContents>$([System.IO.File]::ReadAllText('$(_MauiIntermediateManifest)Package.appxmanifest'))
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_Parameter1>Microsoft.Maui.ApplicationModel.AppInfo.PackageName
+ <_Parameter2>@(_MauiAppxManifestIdentity)
+
+
+ <_Parameter1>Microsoft.Maui.ApplicationModel.AppInfo.PublisherName
+ <_Parameter2>@(_MauiAppxManifestPublisher)
+
+
+ <_Parameter1>Microsoft.Maui.ApplicationModel.AppInfo.Name
+ <_Parameter2>@(_MauiAppxManifestDisplayName)
+
+
+ <_Parameter1>Microsoft.Maui.ApplicationModel.AppInfo.Version
+ <_Parameter2>@(_MauiAppxManifestVersion)
+
+
+
+
+
+
+
+ $(_MauiIntermediateManifest)tizen-manifest.xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(MSBuildWarningsAsMessages);XA4218
+
+
+
+ 9.0.40
+ 9.0
+ 9.0.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(EnableDefaultItems)
+ $(EnableDefaultMauiItems)
+ $(EnableDefaultMauiItems)
+ $(EnableDefaultMauiItems)
+
+
+
+
+
+
+
+
+ true
+ True
+ True
+
+ true
+
+ false
+
+
+
+
+
+
+
+
+
+
+ <_MauiBindingInterceptorsSupport Condition=" '$(_MauiBindingInterceptorsSupport)' == '' and '$(DisableMauiAnalyzers)' != 'true' ">true
+ $(InterceptorsPreviewNamespaces);Microsoft.Maui.Controls.Generated
+
+
+
+
+
+
+
+
+
+
+ <_MauiTargetsImportedAgain Condition="'$(_MauiTargetsImported)'=='True'">True
+ <_MauiTargetsImported>True
+ true
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_MauiXamlWithResourceNames Remove="@(_MauiXamlWithResourceNames)" />
+ <_MauiXamlWithTargetPath Remove="@(_MauiXamlWithTargetPath)" />
+ <_MauiCssWithResourceNames Remove="@(_MauiCssWithResourceNames)" />
+ <_MauiCssWithTargetPath Remove="@(_MauiCssWithTargetPath)" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_MauiXamlWithResourceNames Remove="@(_MauiXamlWithResourceNames)" />
+ <_MauiXamlWithTargetPath Remove="@(_MauiXamlWithTargetPath)" />
+ <_MauiCssWithResourceNames Remove="@(_MauiCssWithResourceNames)" />
+ <_MauiCssWithTargetPath Remove="@(_MauiCssWithTargetPath)" />
+
+
+
+
+
+ _MauiAddXamlEmbeddedResources;
+ $(PrepareResourcesDependsOn);
+
+
+
+
+
+
+
+
+
+
+
+ $(CompileDependsOn);
+ XamlC;
+
+
+
+
+ <_MauiXamlCValidateOnly>$(MauiXamlCValidateOnly)
+ <_MauiXamlCValidateOnly Condition="'$(Configuration)' == 'Debug' AND '$(_MauiForceXamlCForDebug)' != 'True'">True
+ <_MauiXamlCValidateOnly Condition="'$(BuildingForLiveUnitTesting)' == 'True' ">True
+ true
+ <_MauiXamlCWarningsNotAsErrors>$(WarningsNotAsErrors)
+ <_MauiXamlCWarningsNotAsErrors Condition="'$(MauiStrictXamlCompilation)' != 'true'">$(_MauiXamlCWarningsNotAsErrors);XC0022;XC0023;XC0025
+ <_MauiXamlCGenerateFullPaths Condition="'$(_MauiXamlCGenerateFullPaths)' == '' and '$(GenerateFullPaths)' == 'true'">true
+ <_MauiXamlCGenerateFullPaths Condition="'$(_MauiXamlCGenerateFullPaths)' == ''">false
+ <_MauiXamlCFullPathPrefix Condition="'$(_MauiXamlCFullPathPrefix)' == '' and '$(_MauiXamlCGenerateFullPaths)' == 'true'">$(MSBuildProjectDirectory)
+
+
+
+
+
+
+
+
+
+
+
+ IncludeProguardForAndroid;
+ $(CoreCompileDependsOn);
+
+
+ ValidateTargetFrameworkVersionForMaui;
+ $(PrepareForBuildDependsOn);
+
+
+
+
+
+
+
+
+
+ 10.0
+ $(TargetFrameworkVersion.TrimStart('vV'))
+
+
+
+
+
+ false
+
+
+ false
+ false
+ false
+ true
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+ false
+
+
+
+
+
+
+
+
+
+ <_MauiXamlToRemove Condition="'$(WindowsProjectFolder)' != ''" Include="$(WindowsProjectFolder)**/*.xaml" />
+
+
+
+
+
+
+
+ <_MauiOld_ResourcePrefix>$(_ResourcePrefix)
+ <_ResourcePrefix>Resources;$(_ResourcePrefix)
+
+
+
+
+ <_ResourcePrefix>$(_MauiOld_ResourcePrefix)
+
+
+
+
+ $(MSBuildExtensionsPath)\Microsoft\VisualStudio\Maui\Maui.DesignTime.targets
+
+
+
+
+
+
+
+
+
+ $(MSBuildThisFileDirectory)..\tools\net472\Microsoft.DotNet.ApiCompat.Task.dll
+ $(MSBuildThisFileDirectory)..\tools\net9.0\Microsoft.DotNet.ApiCompat.Task.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_UseRoslynToolsetPackage Condition="'$(ApiCompatUseRoslynToolsetPackagePath)' == 'true' and '@(PackageReference->AnyHaveMetadataValue('Identity', 'Microsoft.Net.Compilers.Toolset'))' == 'true'">true
+
+ $([System.IO.Path]::GetDirectoryName('$(CSharpCoreTargetsPath)'))
+
+ $(RoslynTargetsPath)
+
+ $([System.IO.Path]::Combine('$(RoslynAssembliesPath)', 'bincore'))
+
+
+
+ $(GenerateCompatibilitySuppressionFile)
+
+
+
+
+
+
+ <_apiCompatDefaultProjectSuppressionFile>$([MSBuild]::NormalizePath('$(MSBuildProjectDirectory)', 'CompatibilitySuppressions.xml'))
+
+ $(_apiCompatDefaultProjectSuppressionFile)
+
+
+
+
+
+
+
+
+
+
+ <_ApiCompatValidatePackageSemaphoreFile>$(IntermediateOutputPath)$(MSBuildThisFileName).semaphore
+
+ CollectApiCompatInputs;_GetReferencePathFromInnerProjects;$(RunPackageValidationDependsOn)
+
+
+
+ $(PackageId)
+ $([MSBuild]::NormalizePath('$(NuGetPackageRoot)', '$(PackageValidationBaselineName.ToLower())', '$(PackageValidationBaselineVersion)', '$(PackageValidationBaselineName.ToLower()).$(PackageValidationBaselineVersion).nupkg'))
+ <_packageValidationBaselinePath Condition="'$(DisablePackageBaselineValidation)' != 'true'">$(PackageValidationBaselinePath)
+
+
+ <_PackageTargetPath Include="@(NuGetPackOutput->WithMetadataValue('Extension', '.nupkg'))" Condition="!$([System.String]::new('%(Identity)').EndsWith('.symbols.nupkg'))" />
+
+
+
+
+
+
+
+
+
+ $(TargetPlatformMoniker)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(MSBuildThisFileDirectory)..\..\NuGet.Build.Tasks.Pack\buildCrossTargeting\NuGet.Build.Tasks.Pack.targets
+ $(MSBuildThisFileDirectory)..\..\NuGet.Build.Tasks.Pack\build\NuGet.Build.Tasks.Pack.targets
+ true
+
+
+
+
+
+ ..\CoreCLR\NuGet.Build.Tasks.Pack.dll
+ ..\Desktop\NuGet.Build.Tasks.Pack.dll
+
+
+
+
+
+
+
+
+ $(AssemblyName)
+ $(Version)
+ true
+ _LoadPackInputItems; _GetTargetFrameworksOutput; _WalkEachTargetPerFramework; _GetPackageFiles; $(GenerateNuspecDependsOn)
+ $(Description)
+ Package Description
+ false
+ true
+ true
+ tools
+ lib
+ content;contentFiles
+ $(BeforePack); _IntermediatePack; GenerateNuspec; $(PackDependsOn)
+ true
+ symbols.nupkg
+ DeterminePortableBuildCapabilities
+ false
+ false
+ .dll; .exe; .winmd; .json; .pri; .xml
+ $(DefaultAllowedOutputExtensionsInPackageBuildOutputFolder) ;$(AllowedOutputExtensionsInPackageBuildOutputFolder)
+ .pdb; .mdb; $(AllowedOutputExtensionsInPackageBuildOutputFolder); $(AllowedOutputExtensionsInSymbolsPackageBuildOutputFolder)
+ .pdb
+ false
+
+
+ $(GenerateNuspecDependsOn)
+
+
+ Build;$(GenerateNuspecDependsOn)
+
+
+
+
+
+
+ $(TargetFramework)
+
+
+
+ $(MSBuildProjectExtensionsPath)
+ $(BaseOutputPath)$(Configuration)\
+ $(BaseIntermediateOutputPath)$(Configuration)\
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectFrameworks />
+
+
+
+
+
+ <_TargetFrameworks Include="$(_ProjectFrameworks.Split(';'))" />
+
+
+
+
+
+
+ <_PackageFilesToDelete Include="@(_OutputPackItems)" />
+
+
+
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+ $(PrivateRepositoryUrl)
+ $(SourceRevisionId)
+ $(SourceBranchName)
+
+
+
+
+
+
+ $(MSBuildProjectFullPath)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_ProjectPathWithVersion Include="$(MSBuildProjectFullPath)">
+ $(PackageVersion)
+ 1.0.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_TfmWithDependenciesSuppressed Include="$(TargetFramework)" Condition="'$(SuppressDependenciesWhenPacking)' == 'true'" />
+
+
+
+
+
+ $(TargetFramework)
+
+
+
+
+
+
+
+
+
+
+
+
+ %(TfmSpecificPackageFile.RecursiveDir)
+ %(TfmSpecificPackageFile.BuildAction)
+
+
+
+
+
+ <_TargetPathsToSymbolsWithTfm Include="@(DebugSymbolsProjectOutputGroupOutput)">
+ $(TargetFramework)
+
+
+
+ <_TargetPathsToSymbolsWithTfm Include="@(TfmSpecificDebugSymbolsFile)" />
+
+
+
+
+
+ <_PathToPriFile Include="$(ProjectPriFullPath)">
+ $(ProjectPriFullPath)
+ $(ProjectPriFileName)
+
+
+
+
+
+
+ <_PackageFilesToExclude Include="@(Content)" Condition="'%(Content.Pack)' == 'false'" />
+
+
+
+ <_PackageFiles Include="@(Content)" Condition=" %(Content.Pack) != 'false' ">
+ Content
+
+ <_PackageFiles Include="@(Compile)" Condition=" %(Compile.Pack) == 'true' ">
+ Compile
+
+ <_PackageFiles Include="@(None)" Condition=" %(None.Pack) == 'true' ">
+ None
+
+ <_PackageFiles Include="@(EmbeddedResource)" Condition=" %(EmbeddedResource.Pack) == 'true' ">
+ EmbeddedResource
+
+ <_PackageFiles Include="@(ApplicationDefinition)" Condition=" %(ApplicationDefinition.Pack) == 'true' ">
+ ApplicationDefinition
+
+ <_PackageFiles Include="@(Page)" Condition=" %(Page.Pack) == 'true' ">
+ Page
+
+ <_PackageFiles Include="@(Resource)" Condition=" %(Resource.Pack) == 'true' ">
+ Resource
+
+ <_PackageFiles Include="@(SplashScreen)" Condition=" %(SplashScreen.Pack) == 'true' ">
+ SplashScreen
+
+ <_PackageFiles Include="@(DesignData)" Condition=" %(DesignData.Pack) == 'true' ">
+ DesignData
+
+ <_PackageFiles Include="@(DesignDataWithDesignTimeCreatableTypes)" Condition=" %(DesignDataWithDesignTimeCreatableTypes.Pack) == 'true' ">
+ DesignDataWithDesignTimeCreatableTypes
+
+ <_PackageFiles Include="@(CodeAnalysisDictionary)" Condition=" %(CodeAnalysisDictionary.Pack) == 'true' ">
+ CodeAnalysisDictionary
+
+ <_PackageFiles Include="@(AndroidAsset)" Condition=" %(AndroidAsset.Pack) == 'true' ">
+ AndroidAsset
+
+ <_PackageFiles Include="@(AndroidResource)" Condition=" %(AndroidResource.Pack) == 'true' ">
+ AndroidResource
+
+ <_PackageFiles Include="@(BundleResource)" Condition=" %(BundleResource.Pack) == 'true' ">
+ BundleResource
+
+
+
+
+
+
+ <_IsNotSetContainersTargetsDir>false
+ <_IsNotSetContainersTargetsDir Condition=" '$(_ContainersTargetsDir)'=='' ">true
+ <_ContainersTargetsDir Condition="$(_IsNotSetContainersTargetsDir)">$(MSBuildThisFileDirectory)..\..\..\Containers\build\
+
+
+
+
+ true
+ tasks
+ net9.0
+ net472
+ containerize
+
+ $(MSBuildThisFileDirectory)..\$(ContainerTaskFolderName)\$(ContainerTaskFramework)\
+ $(MSBuildThisFileDirectory)..\$(ContainerizeFolderName)\
+
+ $(ContainerCustomTasksFolder)$(MSBuildThisFileName).dll
+
+
+
+
+
+
+
+
+ <_IsSDKContainerAllowedVersion>false
+
+ <_IsSDKContainerAllowedVersion Condition="$([MSBuild]::VersionGreaterThan($(NetCoreSdkVersion), 7.0.100))
OR ( $([MSBuild]::VersionEquals($(NetCoreSdkVersion), 7.0.100))
AND (
$(NETCoreSdkVersion.Contains('-preview.7'))
OR $(NETCoreSdkVersion.Contains('-rc'))
OR $(NETCoreSdkVersion.Contains('-')) == false
)
)">true
+ <_ContainerIsTargetingNet8TFM>false
+ <_ContainerIsTargetingNet8TFM Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' And $([MSBuild]::VersionGreaterThanOrEquals($(_TargetFrameworkVersionWithoutV), '8.0'))">true
+ <_ContainerIsSelfContained>false
+ <_ContainerIsSelfContained Condition="'$(SelfContained)' == 'true' or '$(PublishSelfContained)' == 'true'">true
+
+
+
+
+
+
+
+
+
+
+
+ $(RuntimeIdentifier)
+ linux-$(NETCoreSdkPortableRuntimeIdentifier.Split('-')[1])
+ <_ContainerIsUsingMicrosoftDefaultImages Condition="'$(ContainerBaseImage)' == ''">true
+ <_ContainerIsUsingMicrosoftDefaultImages Condition="'$(ContainerBaseImage)' != ''">false
+
+
+
+
+
+
+
+
+ $(RegistryUrl)
+
+ $(PublishImageTag)
+
+ $([System.DateTime]::UtcNow.ToString('yyyyMMddhhmmss'))
+
+
+
+
+
+
+
+
+
+
+ $(ContainerImageName)
+
+ $(AssemblyName)
+
+ latest
+ $([System.DateTime]::UtcNow.ToString('yyyyMMddhhmmss'))
+
+ <_ContainerIsTargetingWindows>false
+ <_ContainerIsTargetingWindows Condition="$(ContainerRuntimeIdentifier.StartsWith('win'))">true
+
+ /app/
+ C:\app\
+
+
+
+
+
+
+
+
+
+ ContainerUser
+
+
+
+
+
+
+
+
+
+
+
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+ true
+
+
+ $(Description)
+ $(Authors)
+ $(PackageProjectUrl)
+ $(PackageProjectUrl)
+ $(PackageVersion)
+ $(PackageLicenseExpression)
+ $(Title)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <_TrimmedRepositoryUrl Condition="'$(RepositoryType)' == 'git' and '$(PrivateRepositoryUrl)' != '' and $(PrivateRepositoryUrl.EndsWith('.git'))">$(PrivateRepositoryUrl.Substring(0, $(PrivateRepositoryUrl.LastIndexOf('.git'))))
+ <_TrimmedRepositoryUrl Condition="'$(_TrimmedRepositoryUrl)' == '' and '$(PrivateRepositoryUrl)' != ''">$(PrivateRepositoryUrl)
+
+
+
+
+
+
+
+
+ _ContainerVerifySDKVersion;
+ ComputeContainerConfig;
+ _CheckContainersPackage
+
+
+
+
+
+ <_ContainersPackageIdentity>Microsoft.NET.Build.Containers
+ <_WebDefaultSdkVersion>7.0.300
+ <_WorkerDefaultSdkVersion>8.0.100
+ <_ConsoleDefaultSdkVersion>8.0.200
+
+ <_SdkCanPublishWeb>$([MSBuild]::VersionGreaterThanOrEquals('$(NETCoreSdkVersion)', '$(_WebDefaultSdkVersion)'))
+ <_SdkCanPublishWorker>$([MSBuild]::VersionGreaterThanOrEquals('$(NETCoreSdkVersion)', '$(_WorkerDefaultSdkVersion)'))
+ <_SdkCanPublishConsole>$([MSBuild]::VersionGreaterThanOrEquals('$(NETCoreSdkVersion)', '$(_ConsoleDefaultSdkVersion)'))
+
+ <_ContainerPackageIsPresent>false
+ <_ContainerPackageIsPresent Condition="@(PackageReference->AnyHaveMetadataValue('Identity', '$(_ContainersPackageIdentity)'))">true
+ <_IsWebProject>false
+ <_IsWebProject Condition="@(ProjectCapability->AnyHaveMetadataValue('Identity', 'DotNetCoreWeb'))">true
+ <_IsWorkerProject>false
+ <_IsWorkerProject Condition="@(ProjectCapability->AnyHaveMetadataValue('Identity', 'DotNetCoreWorker'))">true
+
+
+
+ true
+
+
+
+
+ $(NetCoreRoot)
+ dotnet
+ dotnet.exe
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/samples/ControlGallery/App.xaml b/samples/ControlGallery/App.xaml
deleted file mode 100644
index 8de3e73..0000000
--- a/samples/ControlGallery/App.xaml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
- #512BD4
- #3B1F9E
- #DFD8F7
- #2B0B98
- #E1E1E1
- #C8C8C8
- #ACACAC
- #919191
- #6E6E6E
- #404040
- #212121
-
-
-
diff --git a/samples/ControlGallery/App.xaml.cs b/samples/ControlGallery/App.xaml.cs
deleted file mode 100644
index 9270a3b..0000000
--- a/samples/ControlGallery/App.xaml.cs
+++ /dev/null
@@ -1,10 +0,0 @@
-namespace ControlGallery;
-
-public partial class App : Application
-{
- public App()
- {
- InitializeComponent();
- MainPage = new AppShell();
- }
-}
diff --git a/samples/ControlGallery/AppShell.xaml b/samples/ControlGallery/AppShell.xaml
deleted file mode 100644
index 40514a6..0000000
--- a/samples/ControlGallery/AppShell.xaml
+++ /dev/null
@@ -1,39 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/ControlGallery/AppShell.xaml.cs b/samples/ControlGallery/AppShell.xaml.cs
deleted file mode 100644
index 419d271..0000000
--- a/samples/ControlGallery/AppShell.xaml.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace ControlGallery;
-
-public partial class AppShell : Shell
-{
- public AppShell()
- {
- InitializeComponent();
- }
-}
diff --git a/samples/ControlGallery/ControlGallery.csproj b/samples/ControlGallery/ControlGallery.csproj
deleted file mode 100644
index 4b6880d..0000000
--- a/samples/ControlGallery/ControlGallery.csproj
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
- net9.0
- Exe
- enable
- enable
- ControlGallery
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/ControlGallery/MauiProgram.cs b/samples/ControlGallery/MauiProgram.cs
deleted file mode 100644
index ea6104d..0000000
--- a/samples/ControlGallery/MauiProgram.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using Microsoft.Maui.Hosting;
-using OpenMaui.Platform.Linux.Hosting;
-
-namespace ControlGallery;
-
-public static class MauiProgram
-{
- public static MauiApp CreateMauiApp()
- {
- var builder = MauiApp.CreateBuilder();
- builder
- .UseMauiApp()
- .UseOpenMauiLinux()
- .ConfigureFonts(fonts =>
- {
- fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
- fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
- });
-
- return builder.Build();
- }
-}
diff --git a/samples/ControlGallery/Pages/ButtonsPage.xaml b/samples/ControlGallery/Pages/ButtonsPage.xaml
deleted file mode 100644
index 0f03138..0000000
--- a/samples/ControlGallery/Pages/ButtonsPage.xaml
+++ /dev/null
@@ -1,73 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/ControlGallery/Pages/ButtonsPage.xaml.cs b/samples/ControlGallery/Pages/ButtonsPage.xaml.cs
deleted file mode 100644
index 9751a42..0000000
--- a/samples/ControlGallery/Pages/ButtonsPage.xaml.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-namespace ControlGallery.Pages;
-
-public partial class ButtonsPage : ContentPage
-{
- private int _clickCount = 0;
-
- public ButtonsPage()
- {
- InitializeComponent();
- }
-
- private void OnButtonClicked(object sender, EventArgs e)
- {
- _clickCount++;
- ButtonResultLabel.Text = $"Button clicked {_clickCount} time(s)";
- }
-
- private async void OnImageButtonClicked(object sender, EventArgs e)
- {
- await DisplayAlert("ImageButton", "You clicked the ImageButton!", "OK");
- }
-}
diff --git a/samples/ControlGallery/Pages/CarouselViewPage.xaml b/samples/ControlGallery/Pages/CarouselViewPage.xaml
deleted file mode 100644
index f650a0e..0000000
--- a/samples/ControlGallery/Pages/CarouselViewPage.xaml
+++ /dev/null
@@ -1,58 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/ControlGallery/Pages/CarouselViewPage.xaml.cs b/samples/ControlGallery/Pages/CarouselViewPage.xaml.cs
deleted file mode 100644
index 4d0c4c1..0000000
--- a/samples/ControlGallery/Pages/CarouselViewPage.xaml.cs
+++ /dev/null
@@ -1,70 +0,0 @@
-namespace ControlGallery.Pages;
-
-public partial class CarouselViewPage : ContentPage
-{
- private readonly List _items;
-
- public CarouselViewPage()
- {
- InitializeComponent();
-
- _items = new List
- {
- new() { Title = "Welcome", Description = "Get started with OpenMaui", Icon = "👋", Color = Color.FromArgb("#512BD4") },
- new() { Title = "Controls", Description = "35+ beautiful controls", Icon = "🎨", Color = Color.FromArgb("#2196F3") },
- new() { Title = "Native", Description = "X11 & Wayland support", Icon = "🐧", Color = Color.FromArgb("#4CAF50") },
- new() { Title = "Fast", Description = "Hardware accelerated", Icon = "⚡", Color = Color.FromArgb("#FF9800") },
- new() { Title = "Accessible", Description = "Screen reader support", Icon = "♿", Color = Color.FromArgb("#9C27B0") },
- };
-
- Carousel.ItemsSource = _items;
- Carousel.IndicatorView = CarouselIndicator;
-
- UpdateCurrentItemLabel();
- }
-
- private void OnCurrentItemChanged(object sender, CurrentItemChangedEventArgs e)
- {
- UpdateCurrentItemLabel();
- }
-
- private void UpdateCurrentItemLabel()
- {
- var index = _items.IndexOf(Carousel.CurrentItem as CarouselItem);
- CurrentItemLabel.Text = $"Slide {index + 1} of {_items.Count}";
- }
-
- private void OnPreviousClicked(object sender, EventArgs e)
- {
- var index = _items.IndexOf(Carousel.CurrentItem as CarouselItem);
- if (index > 0)
- {
- Carousel.ScrollTo(index - 1);
- }
- else
- {
- Carousel.ScrollTo(_items.Count - 1);
- }
- }
-
- private void OnNextClicked(object sender, EventArgs e)
- {
- var index = _items.IndexOf(Carousel.CurrentItem as CarouselItem);
- if (index < _items.Count - 1)
- {
- Carousel.ScrollTo(index + 1);
- }
- else
- {
- Carousel.ScrollTo(0);
- }
- }
-}
-
-public class CarouselItem
-{
- public string Title { get; set; } = string.Empty;
- public string Description { get; set; } = string.Empty;
- public string Icon { get; set; } = string.Empty;
- public Color Color { get; set; } = Colors.Gray;
-}
diff --git a/samples/ControlGallery/Pages/CollectionViewPage.xaml b/samples/ControlGallery/Pages/CollectionViewPage.xaml
deleted file mode 100644
index bff04ed..0000000
--- a/samples/ControlGallery/Pages/CollectionViewPage.xaml
+++ /dev/null
@@ -1,47 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/ControlGallery/Pages/CollectionViewPage.xaml.cs b/samples/ControlGallery/Pages/CollectionViewPage.xaml.cs
deleted file mode 100644
index 5fd3b98..0000000
--- a/samples/ControlGallery/Pages/CollectionViewPage.xaml.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-namespace ControlGallery.Pages;
-
-public partial class CollectionViewPage : ContentPage
-{
- public CollectionViewPage()
- {
- InitializeComponent();
-
- var items = new List
- {
- new() { Title = "Product A", Description = "High quality item", Price = 29.99m, Color = Colors.Purple },
- new() { Title = "Product B", Description = "Best seller", Price = 49.99m, Color = Colors.Blue },
- new() { Title = "Product C", Description = "New arrival", Price = 19.99m, Color = Colors.Green },
- new() { Title = "Product D", Description = "Limited edition", Price = 99.99m, Color = Colors.Orange },
- new() { Title = "Product E", Description = "Customer favorite", Price = 39.99m, Color = Colors.Red },
- new() { Title = "Product F", Description = "Eco-friendly", Price = 24.99m, Color = Colors.Teal },
- new() { Title = "Product G", Description = "Premium quality", Price = 79.99m, Color = Colors.Indigo },
- new() { Title = "Product H", Description = "Budget friendly", Price = 9.99m, Color = Colors.Pink },
- };
-
- ItemsCollection.ItemsSource = items;
- }
-
- private async void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- if (e.CurrentSelection.FirstOrDefault() is ItemModel item)
- {
- await DisplayAlert("Selected", $"You selected {item.Title}", "OK");
- ((CollectionView)sender).SelectedItem = null;
- }
- }
-}
-
-public class ItemModel
-{
- public string Title { get; set; } = string.Empty;
- public string Description { get; set; } = string.Empty;
- public decimal Price { get; set; }
- public Color Color { get; set; } = Colors.Gray;
-}
diff --git a/samples/ControlGallery/Pages/EntryPage.xaml b/samples/ControlGallery/Pages/EntryPage.xaml
deleted file mode 100644
index 4da70b4..0000000
--- a/samples/ControlGallery/Pages/EntryPage.xaml
+++ /dev/null
@@ -1,77 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/ControlGallery/Pages/EntryPage.xaml.cs b/samples/ControlGallery/Pages/EntryPage.xaml.cs
deleted file mode 100644
index 4af119b..0000000
--- a/samples/ControlGallery/Pages/EntryPage.xaml.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-namespace ControlGallery.Pages;
-
-public partial class EntryPage : ContentPage
-{
- public EntryPage()
- {
- InitializeComponent();
- }
-
- private void OnEntryTextChanged(object sender, TextChangedEventArgs e)
- {
- BoundLabel.Text = $"You typed: {e.NewTextValue}";
- }
-}
diff --git a/samples/ControlGallery/Pages/HomePage.xaml b/samples/ControlGallery/Pages/HomePage.xaml
deleted file mode 100644
index 470375d..0000000
--- a/samples/ControlGallery/Pages/HomePage.xaml
+++ /dev/null
@@ -1,60 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/ControlGallery/Pages/HomePage.xaml.cs b/samples/ControlGallery/Pages/HomePage.xaml.cs
deleted file mode 100644
index e3fb27f..0000000
--- a/samples/ControlGallery/Pages/HomePage.xaml.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-namespace ControlGallery.Pages;
-
-public partial class HomePage : ContentPage
-{
- public HomePage()
- {
- InitializeComponent();
- }
-
- private async void OnGetStartedClicked(object sender, EventArgs e)
- {
- await Shell.Current.GoToAsync("//ButtonsPage");
- }
-}
diff --git a/samples/ControlGallery/Pages/ImagesPage.xaml b/samples/ControlGallery/Pages/ImagesPage.xaml
deleted file mode 100644
index 5c58ece..0000000
--- a/samples/ControlGallery/Pages/ImagesPage.xaml
+++ /dev/null
@@ -1,102 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/ControlGallery/Pages/ImagesPage.xaml.cs b/samples/ControlGallery/Pages/ImagesPage.xaml.cs
deleted file mode 100644
index ff435a4..0000000
--- a/samples/ControlGallery/Pages/ImagesPage.xaml.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace ControlGallery.Pages;
-
-public partial class ImagesPage : ContentPage
-{
- public ImagesPage()
- {
- InitializeComponent();
- }
-}
diff --git a/samples/ControlGallery/Pages/LabelsPage.xaml b/samples/ControlGallery/Pages/LabelsPage.xaml
deleted file mode 100644
index 74cf13e..0000000
--- a/samples/ControlGallery/Pages/LabelsPage.xaml
+++ /dev/null
@@ -1,82 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/ControlGallery/Pages/LabelsPage.xaml.cs b/samples/ControlGallery/Pages/LabelsPage.xaml.cs
deleted file mode 100644
index d574d49..0000000
--- a/samples/ControlGallery/Pages/LabelsPage.xaml.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace ControlGallery.Pages;
-
-public partial class LabelsPage : ContentPage
-{
- public LabelsPage()
- {
- InitializeComponent();
- }
-}
diff --git a/samples/ControlGallery/Pages/PickersPage.xaml b/samples/ControlGallery/Pages/PickersPage.xaml
deleted file mode 100644
index e634681..0000000
--- a/samples/ControlGallery/Pages/PickersPage.xaml
+++ /dev/null
@@ -1,59 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Red
- Green
- Blue
- Yellow
- Purple
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/ControlGallery/Pages/PickersPage.xaml.cs b/samples/ControlGallery/Pages/PickersPage.xaml.cs
deleted file mode 100644
index b4efb26..0000000
--- a/samples/ControlGallery/Pages/PickersPage.xaml.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-namespace ControlGallery.Pages;
-
-public partial class PickersPage : ContentPage
-{
- public PickersPage()
- {
- InitializeComponent();
-
- // Set date range
- RangeDatePicker.MinimumDate = DateTime.Today;
- RangeDatePicker.MaximumDate = DateTime.Today.AddDays(30);
- }
-
- private void OnColorPickerChanged(object sender, EventArgs e)
- {
- var picker = (Picker)sender;
- if (picker.SelectedIndex >= 0)
- {
- ColorResultLabel.Text = $"Selected: {picker.Items[picker.SelectedIndex]}";
- }
- }
-
- private void OnDateSelected(object sender, DateChangedEventArgs e)
- {
- DateResultLabel.Text = $"Selected: {e.NewDate:MMMM dd, yyyy}";
- }
-
- private void OnTimeChanged(object sender, PropertyChangedEventArgs e)
- {
- if (e.PropertyName == nameof(TimePicker.Time))
- {
- var picker = (TimePicker)sender;
- TimeResultLabel.Text = $"Selected: {picker.Time:hh\\:mm}";
- }
- }
-}
diff --git a/samples/ControlGallery/Pages/ProgressPage.xaml b/samples/ControlGallery/Pages/ProgressPage.xaml
deleted file mode 100644
index 0aee33b..0000000
--- a/samples/ControlGallery/Pages/ProgressPage.xaml
+++ /dev/null
@@ -1,88 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/ControlGallery/Pages/ProgressPage.xaml.cs b/samples/ControlGallery/Pages/ProgressPage.xaml.cs
deleted file mode 100644
index 651b06d..0000000
--- a/samples/ControlGallery/Pages/ProgressPage.xaml.cs
+++ /dev/null
@@ -1,33 +0,0 @@
-namespace ControlGallery.Pages;
-
-public partial class ProgressPage : ContentPage
-{
- public ProgressPage()
- {
- InitializeComponent();
- }
-
- private void OnProgress0(object sender, EventArgs e) => DemoProgress.Progress = 0;
- private void OnProgress50(object sender, EventArgs e) => DemoProgress.Progress = 0.5;
- private void OnProgress100(object sender, EventArgs e) => DemoProgress.Progress = 1.0;
-
- private void OnStartIndicator(object sender, EventArgs e) => ControlledIndicator.IsRunning = true;
- private void OnStopIndicator(object sender, EventArgs e) => ControlledIndicator.IsRunning = false;
-
- private async void OnAnimateProgress(object sender, EventArgs e)
- {
- AnimatedProgress.Progress = 0;
- await AnimatedProgress.ProgressTo(1.0, 2000, Easing.Linear);
- }
-
- private async void OnShowLoading(object sender, EventArgs e)
- {
- ContentPanel.IsVisible = false;
- LoadingPanel.IsVisible = true;
-
- await Task.Delay(2000);
-
- LoadingPanel.IsVisible = false;
- ContentPanel.IsVisible = true;
- }
-}
diff --git a/samples/ControlGallery/Pages/RefreshViewPage.xaml b/samples/ControlGallery/Pages/RefreshViewPage.xaml
deleted file mode 100644
index 212b499..0000000
--- a/samples/ControlGallery/Pages/RefreshViewPage.xaml
+++ /dev/null
@@ -1,68 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/ControlGallery/Pages/RefreshViewPage.xaml.cs b/samples/ControlGallery/Pages/RefreshViewPage.xaml.cs
deleted file mode 100644
index 30d77c9..0000000
--- a/samples/ControlGallery/Pages/RefreshViewPage.xaml.cs
+++ /dev/null
@@ -1,48 +0,0 @@
-namespace ControlGallery.Pages;
-
-public partial class RefreshViewPage : ContentPage
-{
- private readonly Random _random = new();
- private readonly string[] _headlines = new[]
- {
- "OpenMaui 1.0 Released!",
- "Linux Desktop Apps Made Easy",
- "SkiaSharp Powers Modern UIs",
- "Cross-Platform Development Grows",
- ".NET 9 Performance Boost",
- "XAML Hot Reload Coming Soon",
- "Wayland Support Expanding",
- "Community Contributions Welcome",
- "New Controls Added Weekly",
- "Accessibility Features Improved"
- };
-
- public RefreshViewPage()
- {
- InitializeComponent();
- UpdateNews();
- }
-
- private async void OnRefreshing(object sender, EventArgs e)
- {
- // Simulate network delay
- await Task.Delay(1500);
-
- UpdateNews();
- LastRefreshLabel.Text = $"Last refreshed: {DateTime.Now:HH:mm:ss}";
-
- RefreshContainer.IsRefreshing = false;
- }
-
- private void OnManualRefreshClicked(object sender, EventArgs e)
- {
- RefreshContainer.IsRefreshing = true;
- }
-
- private void UpdateNews()
- {
- NewsItem1.Text = _headlines[_random.Next(_headlines.Length)];
- NewsItem2.Text = _headlines[_random.Next(_headlines.Length)];
- NewsItem3.Text = _headlines[_random.Next(_headlines.Length)];
- }
-}
diff --git a/samples/ControlGallery/Pages/SlidersPage.xaml b/samples/ControlGallery/Pages/SlidersPage.xaml
deleted file mode 100644
index 148c33b..0000000
--- a/samples/ControlGallery/Pages/SlidersPage.xaml
+++ /dev/null
@@ -1,71 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/ControlGallery/Pages/SlidersPage.xaml.cs b/samples/ControlGallery/Pages/SlidersPage.xaml.cs
deleted file mode 100644
index c78c867..0000000
--- a/samples/ControlGallery/Pages/SlidersPage.xaml.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-namespace ControlGallery.Pages;
-
-public partial class SlidersPage : ContentPage
-{
- public SlidersPage()
- {
- InitializeComponent();
- }
-
- private void OnSliderValueChanged(object sender, ValueChangedEventArgs e)
- {
- SliderValueLabel.Text = $"Value: {e.NewValue:F0}";
- }
-
- private void OnStepperValueChanged(object sender, ValueChangedEventArgs e)
- {
- StepperValueLabel.Text = $"Value: {e.NewValue:F0}";
- }
-
- private void OnDecimalStepperValueChanged(object sender, ValueChangedEventArgs e)
- {
- DecimalStepperLabel.Text = $"Value: {e.NewValue:F1}";
- }
-
- private void OnSizeSliderChanged(object sender, ValueChangedEventArgs e)
- {
- DemoBox.WidthRequest = e.NewValue;
- DemoBox.HeightRequest = e.NewValue;
- }
-}
diff --git a/samples/ControlGallery/Pages/SwipeViewPage.xaml b/samples/ControlGallery/Pages/SwipeViewPage.xaml
deleted file mode 100644
index 0fa0a4e..0000000
--- a/samples/ControlGallery/Pages/SwipeViewPage.xaml
+++ /dev/null
@@ -1,121 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/ControlGallery/Pages/SwipeViewPage.xaml.cs b/samples/ControlGallery/Pages/SwipeViewPage.xaml.cs
deleted file mode 100644
index a162a34..0000000
--- a/samples/ControlGallery/Pages/SwipeViewPage.xaml.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-namespace ControlGallery.Pages;
-
-public partial class SwipeViewPage : ContentPage
-{
- public SwipeViewPage()
- {
- InitializeComponent();
- }
-
- private async void OnDeleteInvoked(object sender, EventArgs e)
- {
- await DisplayAlert("Delete", "Item would be deleted", "OK");
- }
-
- private async void OnArchiveInvoked(object sender, EventArgs e)
- {
- await DisplayAlert("Archive", "Item would be archived", "OK");
- }
-
- private async void OnFavoriteInvoked(object sender, EventArgs e)
- {
- await DisplayAlert("Favorite", "Item added to favorites", "OK");
- }
-
- private async void OnReplyInvoked(object sender, EventArgs e)
- {
- await DisplayAlert("Reply", "Opening reply composer", "OK");
- }
-
- private async void OnForwardInvoked(object sender, EventArgs e)
- {
- await DisplayAlert("Forward", "Opening forward dialog", "OK");
- }
-}
diff --git a/samples/ControlGallery/Pages/TogglesPage.xaml b/samples/ControlGallery/Pages/TogglesPage.xaml
deleted file mode 100644
index 3b7d429..0000000
--- a/samples/ControlGallery/Pages/TogglesPage.xaml
+++ /dev/null
@@ -1,102 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/samples/ControlGallery/Pages/TogglesPage.xaml.cs b/samples/ControlGallery/Pages/TogglesPage.xaml.cs
deleted file mode 100644
index 1c9ca0f..0000000
--- a/samples/ControlGallery/Pages/TogglesPage.xaml.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-namespace ControlGallery.Pages;
-
-public partial class TogglesPage : ContentPage
-{
- public TogglesPage()
- {
- InitializeComponent();
- }
-
- private void OnCheckBoxChanged(object sender, CheckedChangedEventArgs e)
- {
- CheckBoxLabel.Text = e.Value ? "Agreed!" : "Not agreed";
- }
-
- private void OnSwitchToggled(object sender, ToggledEventArgs e)
- {
- SwitchLabel.Text = $"Notifications: {(e.Value ? "On" : "Off")}";
- }
-
- private void OnRadioButtonChecked(object sender, CheckedChangedEventArgs e)
- {
- if (e.Value && sender is RadioButton rb)
- {
- RadioLabel.Text = $"Selected: {rb.Content}";
- }
- }
-}
diff --git a/samples/ControlGallery/README.md b/samples/ControlGallery/README.md
deleted file mode 100644
index 0ddf0cc..0000000
--- a/samples/ControlGallery/README.md
+++ /dev/null
@@ -1,41 +0,0 @@
-# OpenMaui Control Gallery
-
-A comprehensive sample application demonstrating all 35+ controls available in OpenMaui for Linux.
-
-## Features
-
-This gallery showcases:
-
-- **Basic Controls**: Buttons, Labels, Entry, Editor
-- **Selection Controls**: Picker, DatePicker, TimePicker, Slider, Stepper
-- **Toggle Controls**: CheckBox, Switch, RadioButton
-- **Progress Controls**: ProgressBar, ActivityIndicator
-- **Image Controls**: Image, ImageButton with various aspect ratios
-- **Collection Controls**: CollectionView, CarouselView with IndicatorView
-- **Gesture Controls**: SwipeView, RefreshView
-
-## Running the Sample
-
-```bash
-cd samples/ControlGallery
-dotnet run
-```
-
-## Requirements
-
-- .NET 9.0 SDK
-- Linux with X11 or Wayland
-- OpenMaui.Controls.Linux NuGet package
-
-## Screenshots
-
-The gallery uses Shell navigation with a flyout menu to organize controls by category.
-
-## Adding Images
-
-Before running, add the following images to `Resources/Images/`:
-- `dotnet_bot.png` - From official MAUI templates
-
-## License
-
-MIT License - Copyright 2025 MarketAlly LLC
diff --git a/samples/ControlGallery/Resources/Fonts/.gitkeep b/samples/ControlGallery/Resources/Fonts/.gitkeep
deleted file mode 100644
index d41856e..0000000
--- a/samples/ControlGallery/Resources/Fonts/.gitkeep
+++ /dev/null
@@ -1,2 +0,0 @@
-# Add fonts here
-# Recommended: OpenSans-Regular.ttf, OpenSans-Semibold.ttf
diff --git a/samples/ControlGallery/Resources/Images/.gitkeep b/samples/ControlGallery/Resources/Images/.gitkeep
deleted file mode 100644
index 29e3f93..0000000
--- a/samples/ControlGallery/Resources/Images/.gitkeep
+++ /dev/null
@@ -1,2 +0,0 @@
-# Add images here
-# Required: dotnet_bot.png
diff --git a/samples/LinuxDemo/Program.cs b/samples/LinuxDemo/Program.cs
deleted file mode 100644
index 7e9932e..0000000
--- a/samples/LinuxDemo/Program.cs
+++ /dev/null
@@ -1,797 +0,0 @@
-using System.Runtime.InteropServices;
-using Microsoft.Maui.Platform;
-using SkiaSharp;
-
-var demo = new AllControlsDemo();
-demo.Run();
-
-class AllControlsDemo
-{
- private IntPtr _display, _window, _gc;
- private int _screen, _width = 1024, _height = 768;
- private bool _running = true;
- private IntPtr _wmDeleteMessage, _pixelBuffer = IntPtr.Zero;
- private int _bufferSize = 0;
-
- private SkiaScrollView _scrollView = null!;
- private SkiaStackLayout _rootLayout = null!;
- private SkiaView? _pressedView = null;
- private SkiaView? _focusedView = null;
- private SkiaCollectionView _collectionView = null!;
- private SkiaDatePicker _datePicker = null!;
- private SkiaTimePicker _timePicker = null!;
- private SkiaPicker _picker = null!;
- private SkiaEntry _entry = null!;
- private SkiaSearchBar _searchBar = null!;
- private DateTime _lastMotionRender = DateTime.MinValue;
-
- public void Run()
- {
- try { InitializeX11(); CreateUI(); RunEventLoop(); }
- catch (Exception ex) { Console.WriteLine($"Error: {ex}"); }
- finally { Cleanup(); }
- }
-
- private void InitializeX11()
- {
- _display = XOpenDisplay(IntPtr.Zero);
- if (_display == IntPtr.Zero) throw new Exception("Cannot open X11 display");
- _screen = XDefaultScreen(_display);
- var root = XRootWindow(_display, _screen);
- _window = XCreateSimpleWindow(_display, root, 50, 50, (uint)_width, (uint)_height, 1,
- XBlackPixel(_display, _screen), XWhitePixel(_display, _screen));
- XStoreName(_display, _window, "MAUI Linux Demo - All Controls");
- XSelectInput(_display, _window, ExposureMask | KeyPressMask | KeyReleaseMask |
- ButtonPressMask | ButtonReleaseMask | PointerMotionMask | StructureNotifyMask);
- _gc = XCreateGC(_display, _window, 0, IntPtr.Zero);
- _wmDeleteMessage = XInternAtom(_display, "WM_DELETE_WINDOW", false);
- XSetWMProtocols(_display, _window, ref _wmDeleteMessage, 1);
- EnsurePixelBuffer(_width, _height);
- XMapWindow(_display, _window);
- XFlush(_display);
- }
-
- private void EnsurePixelBuffer(int w, int h)
- {
- int needed = w * h * 4;
- if (_pixelBuffer == IntPtr.Zero || _bufferSize < needed) {
- if (_pixelBuffer != IntPtr.Zero) Marshal.FreeHGlobal(_pixelBuffer);
- _pixelBuffer = Marshal.AllocHGlobal(needed);
- _bufferSize = needed;
- }
- }
-
- private void CreateUI()
- {
- _scrollView = new SkiaScrollView { BackgroundColor = new SKColor(250, 250, 250) };
- _rootLayout = new SkiaStackLayout {
- Orientation = Microsoft.Maui.Platform.StackOrientation.Vertical,
- Spacing = 12, Padding = new SKRect(24, 24, 24, 24),
- BackgroundColor = new SKColor(250, 250, 250)
- };
-
- // Title
- _rootLayout.AddChild(new SkiaLabel { Text = "MAUI Linux Demo", FontSize = 28, IsBold = true,
- TextColor = new SKColor(25, 118, 210), RequestedHeight = 40 });
-
- // Basic Controls
- AddSection("Basic Controls");
-
- var button = new SkiaButton { Text = "Click Me!", RequestedHeight = 44 };
- button.Clicked += (s, e) => Console.WriteLine("Button clicked!");
- _rootLayout.AddChild(button);
-
- _rootLayout.AddChild(new SkiaLabel { Text = "This is a Label with some text", RequestedHeight = 24 });
-
- _entry = new SkiaEntry { Placeholder = "Type here...", RequestedHeight = 44 };
- _rootLayout.AddChild(_entry);
-
- // Toggle Controls
- AddSection("Toggle Controls");
-
- var checkbox = new SkiaCheckBox { IsChecked = true, RequestedHeight = 32 };
- _rootLayout.AddChild(checkbox);
-
- var switchCtrl = new SkiaSwitch { IsOn = true, RequestedHeight = 32 };
- _rootLayout.AddChild(switchCtrl);
-
- // Sliders
- AddSection("Sliders & Progress");
-
- var slider = new SkiaSlider { Value = 0.5, Minimum = 0, Maximum = 1, RequestedHeight = 40 };
- _rootLayout.AddChild(slider);
-
- var progress = new SkiaProgressBar { Progress = 0.7f, RequestedHeight = 16 };
- _rootLayout.AddChild(progress);
-
- // Pickers - These are the ones with popups
- AddSection("Pickers (click to open popups)");
-
- _datePicker = new SkiaDatePicker { Date = DateTime.Today, RequestedHeight = 44 };
- _rootLayout.AddChild(_datePicker);
-
- _timePicker = new SkiaTimePicker { Time = DateTime.Now.TimeOfDay, RequestedHeight = 44 };
- _rootLayout.AddChild(_timePicker);
-
- _picker = new SkiaPicker { Title = "Select a fruit...", RequestedHeight = 44 };
- _picker.SetItems(new[] { "Apple", "Banana", "Cherry", "Date", "Elderberry", "Fig", "Grape" });
- _rootLayout.AddChild(_picker);
-
- // CollectionView
- AddSection("CollectionView (scroll with mouse wheel)");
-
- _collectionView = new SkiaCollectionView { RequestedHeight = 180, ItemHeight = 36 };
- var items = new List();
- for (int i = 1; i <= 50; i++) items.Add($"Collection Item #{i}");
- _collectionView.ItemsSource = items;
- _rootLayout.AddChild(_collectionView);
-
- // Activity Indicator
- AddSection("Activity Indicator");
- var activity = new SkiaActivityIndicator { IsRunning = true, RequestedHeight = 50 };
- _rootLayout.AddChild(activity);
-
- // SearchBar
- AddSection("SearchBar");
- _searchBar = new SkiaSearchBar { Placeholder = "Search...", RequestedHeight = 44 };
- _rootLayout.AddChild(_searchBar);
-
- // Footer
- _rootLayout.AddChild(new SkiaLabel {
- Text = "Scroll this page to see all controls. ESC to exit.",
- FontSize = 12, TextColor = new SKColor(128, 128, 128), RequestedHeight = 30
- });
-
- _scrollView.Content = _rootLayout;
- }
-
- private void AddSection(string title)
- {
- _rootLayout.AddChild(new SkiaLabel {
- Text = title, FontSize = 16, IsBold = true,
- TextColor = new SKColor(55, 71, 79), RequestedHeight = 32
- });
- }
-
- private void RunEventLoop()
- {
- Console.WriteLine("MAUI Linux Demo running... ESC to quit");
- Console.WriteLine("- Click DatePicker/TimePicker/Picker to test popups");
- Console.WriteLine("- Use mouse wheel on CollectionView to scroll it");
- Console.WriteLine("- Use mouse wheel elsewhere to scroll the page");
- Render();
- var lastRender = DateTime.Now;
- while (_running) {
- while (XPending(_display) > 0) { XNextEvent(_display, out var ev); HandleEvent(ref ev); }
-
- // Continuous rendering for animations (ActivityIndicator, cursor blink, etc.)
- var now = DateTime.Now;
- if ((now - lastRender).TotalMilliseconds >= 50) // ~20 FPS for animations
- {
- lastRender = now;
- Render();
- }
- Thread.Sleep(8);
- }
- }
-
- private void HandleEvent(ref XEvent e)
- {
- switch (e.type)
- {
- case Expose: if (e.xexpose.count == 0) Render(); break;
- case ConfigureNotify:
- if (e.xconfigure.width != _width || e.xconfigure.height != _height) {
- _width = e.xconfigure.width; _height = e.xconfigure.height;
- EnsurePixelBuffer(_width, _height); Render();
- }
- break;
- case KeyPress:
- var keysym = XLookupKeysym(ref e.xkey, 0);
- if (keysym == 0xFF1B) { _running = false; break; } // ESC
-
- // Forward to focused view
- if (_focusedView != null)
- {
- var key = KeysymToKey(keysym);
- if (key != Key.Unknown)
- {
- _focusedView.OnKeyDown(new KeyEventArgs(key));
- Render();
- }
-
- // Handle text input for printable characters
- var ch = KeysymToChar(keysym, e.xkey.state);
- if (ch != '\0')
- {
- _focusedView.OnTextInput(new TextInputEventArgs(ch.ToString()));
- Render();
- }
- }
- break;
- case ButtonPress:
- float sx = e.xbutton.x, sy = e.xbutton.y;
- if (e.xbutton.button == 4 || e.xbutton.button == 5) {
- // Mouse wheel
- var cvBounds = _collectionView.GetAbsoluteBounds();
- bool overCV = sx >= cvBounds.Left && sx <= cvBounds.Right &&
- sy >= cvBounds.Top && sy <= cvBounds.Bottom;
- float delta = (e.xbutton.button == 4) ? -1.5f : 1.5f;
- if (overCV) {
- _collectionView.OnScroll(new ScrollEventArgs(sx, sy, 0, delta));
- } else {
- _scrollView.ScrollY = Math.Max(0, _scrollView.ScrollY + (delta > 0 ? 40 : -40));
- }
- Render();
- } else {
- // Check if clicking on popup areas first
- bool handledPopup = HandlePopupClick(sx, sy);
- if (!handledPopup) {
- _pressedView = _scrollView.HitTest(sx, sy);
- if (_pressedView != null && _pressedView != _scrollView) {
- // Update focus
- if (_pressedView != _focusedView && _pressedView.IsFocusable)
- {
- _focusedView?.OnFocusLost();
- _focusedView = _pressedView;
- _focusedView.OnFocusGained();
- }
- _pressedView.OnPointerPressed(new Microsoft.Maui.Platform.PointerEventArgs(sx, sy, Microsoft.Maui.Platform.PointerButton.Left));
- }
- else if (_pressedView == null || _pressedView == _scrollView)
- {
- // Clicked on empty area - clear focus
- _focusedView?.OnFocusLost();
- _focusedView = null;
- }
- }
- Render();
- }
- break;
- case MotionNotify:
- // Forward drag events to pressed view (for sliders, etc.)
- if (_pressedView != null) {
- // Close any open popups during drag to prevent glitches
- if (_datePicker.IsOpen) _datePicker.IsOpen = false;
- if (_timePicker.IsOpen) _timePicker.IsOpen = false;
- if (_picker.IsOpen) _picker.IsOpen = false;
-
- _pressedView.OnPointerMoved(new Microsoft.Maui.Platform.PointerEventArgs(e.xmotion.x, e.xmotion.y, Microsoft.Maui.Platform.PointerButton.Left));
-
- // Throttle motion renders to prevent overwhelming the system
- var now = DateTime.Now;
- if ((now - _lastMotionRender).TotalMilliseconds >= 16) // ~60 FPS max for drag
- {
- _lastMotionRender = now;
- Render();
- }
- }
- break;
- case ButtonRelease:
- if (e.xbutton.button != 4 && e.xbutton.button != 5 && _pressedView != null) {
- _pressedView.OnPointerReleased(new Microsoft.Maui.Platform.PointerEventArgs(e.xbutton.x, e.xbutton.y, Microsoft.Maui.Platform.PointerButton.Left));
- _pressedView = null;
- Render();
- }
- break;
- case ClientMessage:
- if (e.xclient.data_l0 == (long)_wmDeleteMessage) _running = false;
- break;
- }
- }
-
- private bool HandlePopupClick(float x, float y)
- {
- // Handle date picker popup clicks
- if (_datePicker.IsOpen)
- {
- var bounds = _datePicker.GetAbsoluteBounds();
- var popupRect = new SKRect(bounds.Left, bounds.Bottom + 4, bounds.Left + 280, bounds.Bottom + 324);
- if (x >= popupRect.Left && x <= popupRect.Right && y >= popupRect.Top && y <= popupRect.Bottom)
- {
- // Click inside popup - handle calendar navigation/selection
- HandleDatePickerPopupClick(x, y, bounds);
- return true;
- }
- else if (y >= bounds.Top && y <= bounds.Bottom && x >= bounds.Left && x <= bounds.Right)
- {
- // Click on picker button - toggle
- _datePicker.IsOpen = false;
- return true;
- }
- else
- {
- // Click outside - close
- _datePicker.IsOpen = false;
- return true;
- }
- }
-
- // Handle time picker popup clicks
- if (_timePicker.IsOpen)
- {
- var bounds = _timePicker.GetAbsoluteBounds();
- var popupRect = new SKRect(bounds.Left, bounds.Bottom + 4, bounds.Left + 280, bounds.Bottom + 364);
- if (y < popupRect.Top)
- {
- _timePicker.IsOpen = false;
- return true;
- }
- }
-
- // Handle dropdown picker popup clicks
- if (_picker.IsOpen)
- {
- var bounds = _picker.GetAbsoluteBounds();
- var dropdownRect = new SKRect(bounds.Left, bounds.Bottom + 4, bounds.Right, bounds.Bottom + 204);
- if (x >= dropdownRect.Left && x <= dropdownRect.Right && y >= dropdownRect.Top && y <= dropdownRect.Bottom)
- {
- // Click on item
- int itemIndex = (int)((y - dropdownRect.Top) / 40);
- if (itemIndex >= 0 && itemIndex < 7)
- {
- _picker.SelectedIndex = itemIndex;
- }
- _picker.IsOpen = false;
- return true;
- }
- else if (y < dropdownRect.Top)
- {
- _picker.IsOpen = false;
- return true;
- }
- }
-
- return false;
- }
-
- private DateTime _displayMonth = DateTime.Today;
-
- private void HandleDatePickerPopupClick(float x, float y, SKRect pickerBounds)
- {
- var popupTop = pickerBounds.Bottom + 4;
- var headerHeight = 48f;
- var weekdayHeight = 30f;
-
- // Navigation arrows
- if (y >= popupTop && y < popupTop + headerHeight)
- {
- if (x < pickerBounds.Left + 40)
- {
- _displayMonth = _displayMonth.AddMonths(-1);
- }
- else if (x > pickerBounds.Left + 240)
- {
- _displayMonth = _displayMonth.AddMonths(1);
- }
- return;
- }
-
- // Day selection
- var daysTop = popupTop + headerHeight + weekdayHeight;
- if (y >= daysTop)
- {
- var cellWidth = 280f / 7;
- var cellHeight = 38f;
- var col = (int)((x - pickerBounds.Left) / cellWidth);
- var row = (int)((y - daysTop) / cellHeight);
-
- var firstDay = new DateTime(_displayMonth.Year, _displayMonth.Month, 1);
- var startDayOfWeek = (int)firstDay.DayOfWeek;
- var dayIndex = row * 7 + col - startDayOfWeek + 1;
- var daysInMonth = DateTime.DaysInMonth(_displayMonth.Year, _displayMonth.Month);
-
- if (dayIndex >= 1 && dayIndex <= daysInMonth)
- {
- _datePicker.Date = new DateTime(_displayMonth.Year, _displayMonth.Month, dayIndex);
- _datePicker.IsOpen = false;
- }
- }
- }
-
- private void Render()
- {
- _scrollView.Measure(new SKSize(_width, _height));
- _scrollView.Arrange(new SKRect(0, 0, _width, _height));
-
- var info = new SKImageInfo(_width, _height, SKColorType.Bgra8888, SKAlphaType.Premul);
- using var surface = SKSurface.Create(info, _pixelBuffer, _width * 4);
- if (surface == null) return;
- var canvas = surface.Canvas;
-
- canvas.Clear(new SKColor(250, 250, 250));
- _scrollView.Draw(canvas);
-
- // Draw popups on top (outside of scrollview clipping)
- DrawPopups(canvas);
-
- canvas.Flush();
-
- var image = XCreateImage(_display, XDefaultVisual(_display, _screen),
- (uint)XDefaultDepth(_display, _screen), 2, 0, _pixelBuffer, (uint)_width, (uint)_height, 32, _width * 4);
- if (image != IntPtr.Zero) {
- XPutImage(_display, _window, _gc, image, 0, 0, 0, 0, (uint)_width, (uint)_height);
- XFree(image);
- }
- XFlush(_display);
- }
-
- private void DrawPopups(SKCanvas canvas)
- {
- // Draw DatePicker calendar popup
- if (_datePicker.IsOpen)
- {
- var bounds = _datePicker.GetAbsoluteBounds();
- DrawCalendarPopup(canvas, bounds);
- }
-
- // Draw TimePicker clock popup
- if (_timePicker.IsOpen)
- {
- var bounds = _timePicker.GetAbsoluteBounds();
- DrawTimePickerPopup(canvas, bounds);
- }
-
- // Draw Picker dropdown
- if (_picker.IsOpen)
- {
- var bounds = _picker.GetAbsoluteBounds();
- DrawPickerDropdown(canvas, bounds);
- }
- }
-
- private void DrawCalendarPopup(SKCanvas canvas, SKRect pickerBounds)
- {
- var popupRect = new SKRect(
- pickerBounds.Left, pickerBounds.Bottom + 4,
- pickerBounds.Left + 280, pickerBounds.Bottom + 324);
-
- // Shadow
- using var shadowPaint = new SKPaint {
- Color = new SKColor(0, 0, 0, 50),
- MaskFilter = SKMaskFilter.CreateBlur(SKBlurStyle.Normal, 6)
- };
- canvas.DrawRoundRect(new SKRoundRect(
- new SKRect(popupRect.Left + 3, popupRect.Top + 3, popupRect.Right + 3, popupRect.Bottom + 3), 8), shadowPaint);
-
- // Background
- using var bgPaint = new SKPaint { Color = SKColors.White, Style = SKPaintStyle.Fill, IsAntialias = true };
- canvas.DrawRoundRect(new SKRoundRect(popupRect, 8), bgPaint);
-
- // Border
- using var borderPaint = new SKPaint { Color = new SKColor(200, 200, 200), Style = SKPaintStyle.Stroke, StrokeWidth = 1 };
- canvas.DrawRoundRect(new SKRoundRect(popupRect, 8), borderPaint);
-
- // Header with month/year
- var headerRect = new SKRect(popupRect.Left, popupRect.Top, popupRect.Right, popupRect.Top + 48);
- using var headerPaint = new SKPaint { Color = new SKColor(33, 150, 243), Style = SKPaintStyle.Fill };
- canvas.Save();
- canvas.ClipRoundRect(new SKRoundRect(new SKRect(headerRect.Left, headerRect.Top, headerRect.Right, headerRect.Top + 16), 8));
- canvas.DrawRect(headerRect, headerPaint);
- canvas.Restore();
- canvas.DrawRect(new SKRect(headerRect.Left, headerRect.Top + 8, headerRect.Right, headerRect.Bottom), headerPaint);
-
- // Month/year text
- using var headerFont = new SKFont(SKTypeface.Default, 18);
- using var headerTextPaint = new SKPaint(headerFont) { Color = SKColors.White, IsAntialias = true };
- var monthYear = _displayMonth.ToString("MMMM yyyy");
- var textBounds = new SKRect();
- headerTextPaint.MeasureText(monthYear, ref textBounds);
- canvas.DrawText(monthYear, headerRect.MidX - textBounds.MidX, headerRect.MidY - textBounds.MidY, headerTextPaint);
-
- // Navigation arrows
- using var arrowPaint = new SKPaint { Color = SKColors.White, Style = SKPaintStyle.Stroke, StrokeWidth = 2, IsAntialias = true };
- // Left arrow
- canvas.DrawLine(popupRect.Left + 24, headerRect.MidY, popupRect.Left + 18, headerRect.MidY, arrowPaint);
- canvas.DrawLine(popupRect.Left + 18, headerRect.MidY, popupRect.Left + 22, headerRect.MidY - 4, arrowPaint);
- canvas.DrawLine(popupRect.Left + 18, headerRect.MidY, popupRect.Left + 22, headerRect.MidY + 4, arrowPaint);
- // Right arrow
- canvas.DrawLine(popupRect.Right - 24, headerRect.MidY, popupRect.Right - 18, headerRect.MidY, arrowPaint);
- canvas.DrawLine(popupRect.Right - 18, headerRect.MidY, popupRect.Right - 22, headerRect.MidY - 4, arrowPaint);
- canvas.DrawLine(popupRect.Right - 18, headerRect.MidY, popupRect.Right - 22, headerRect.MidY + 4, arrowPaint);
-
- // Weekday headers
- var dayNames = new[] { "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" };
- var cellWidth = 280f / 7;
- var weekdayTop = popupRect.Top + 48;
- using var weekdayFont = new SKFont(SKTypeface.Default, 12);
- using var weekdayPaint = new SKPaint(weekdayFont) { Color = new SKColor(128, 128, 128), IsAntialias = true };
- for (int i = 0; i < 7; i++)
- {
- var dayBounds = new SKRect();
- weekdayPaint.MeasureText(dayNames[i], ref dayBounds);
- var x = popupRect.Left + i * cellWidth + cellWidth / 2 - dayBounds.MidX;
- canvas.DrawText(dayNames[i], x, weekdayTop + 20, weekdayPaint);
- }
-
- // Days grid
- var daysTop = weekdayTop + 30;
- var cellHeight = 38f;
- var firstDay = new DateTime(_displayMonth.Year, _displayMonth.Month, 1);
- var daysInMonth = DateTime.DaysInMonth(_displayMonth.Year, _displayMonth.Month);
- var startDayOfWeek = (int)firstDay.DayOfWeek;
- var today = DateTime.Today;
- var selectedDate = _datePicker.Date;
-
- using var dayFont = new SKFont(SKTypeface.Default, 14);
- using var dayPaint = new SKPaint(dayFont) { IsAntialias = true };
- using var circlePaint = new SKPaint { Style = SKPaintStyle.Fill, IsAntialias = true };
-
- for (int day = 1; day <= daysInMonth; day++)
- {
- var dayDate = new DateTime(_displayMonth.Year, _displayMonth.Month, day);
- var cellIndex = startDayOfWeek + day - 1;
- var row = cellIndex / 7;
- var col = cellIndex % 7;
-
- var cellX = popupRect.Left + col * cellWidth;
- var cellY = daysTop + row * cellHeight;
- var cellCenterX = cellX + cellWidth / 2;
- var cellCenterY = cellY + cellHeight / 2;
-
- var isSelected = dayDate.Date == selectedDate.Date;
- var isToday = dayDate.Date == today;
-
- // Draw selection/today circle
- if (isSelected)
- {
- circlePaint.Color = new SKColor(33, 150, 243);
- canvas.DrawCircle(cellCenterX, cellCenterY, 16, circlePaint);
- }
- else if (isToday)
- {
- circlePaint.Color = new SKColor(33, 150, 243, 60);
- canvas.DrawCircle(cellCenterX, cellCenterY, 16, circlePaint);
- }
-
- // Draw day number
- dayPaint.Color = isSelected ? SKColors.White : SKColors.Black;
- var dayText = day.ToString();
- var dayBounds = new SKRect();
- dayPaint.MeasureText(dayText, ref dayBounds);
- canvas.DrawText(dayText, cellCenterX - dayBounds.MidX, cellCenterY - dayBounds.MidY, dayPaint);
- }
- }
-
- private void DrawTimePickerPopup(SKCanvas canvas, SKRect pickerBounds)
- {
- var popupRect = new SKRect(
- pickerBounds.Left, pickerBounds.Bottom + 4,
- pickerBounds.Left + 280, pickerBounds.Bottom + 364);
-
- // Shadow
- using var shadowPaint = new SKPaint {
- Color = new SKColor(0, 0, 0, 50),
- MaskFilter = SKMaskFilter.CreateBlur(SKBlurStyle.Normal, 6)
- };
- canvas.DrawRoundRect(new SKRoundRect(
- new SKRect(popupRect.Left + 3, popupRect.Top + 3, popupRect.Right + 3, popupRect.Bottom + 3), 8), shadowPaint);
-
- // Background
- using var bgPaint = new SKPaint { Color = SKColors.White, Style = SKPaintStyle.Fill, IsAntialias = true };
- canvas.DrawRoundRect(new SKRoundRect(popupRect, 8), bgPaint);
-
- // Header
- var headerRect = new SKRect(popupRect.Left, popupRect.Top, popupRect.Right, popupRect.Top + 80);
- using var headerPaint = new SKPaint { Color = new SKColor(33, 150, 243), Style = SKPaintStyle.Fill };
- canvas.Save();
- canvas.ClipRoundRect(new SKRoundRect(new SKRect(headerRect.Left, headerRect.Top, headerRect.Right, headerRect.Top + 16), 8));
- canvas.DrawRect(headerRect, headerPaint);
- canvas.Restore();
- canvas.DrawRect(new SKRect(headerRect.Left, headerRect.Top + 8, headerRect.Right, headerRect.Bottom), headerPaint);
-
- // Time display
- using var timeFont = new SKFont(SKTypeface.Default, 32);
- using var timePaint = new SKPaint(timeFont) { Color = SKColors.White, IsAntialias = true };
- var time = _timePicker.Time;
- var timeText = $"{time.Hours:D2}:{time.Minutes:D2}";
- var timeBounds = new SKRect();
- timePaint.MeasureText(timeText, ref timeBounds);
- canvas.DrawText(timeText, headerRect.MidX - timeBounds.MidX, headerRect.MidY - timeBounds.MidY, timePaint);
-
- // Clock face
- var clockCenterX = popupRect.MidX;
- var clockCenterY = popupRect.Top + 80 + 140;
- var clockRadius = 100f;
-
- using var clockBgPaint = new SKPaint { Color = new SKColor(245, 245, 245), Style = SKPaintStyle.Fill, IsAntialias = true };
- canvas.DrawCircle(clockCenterX, clockCenterY, clockRadius + 20, clockBgPaint);
-
- // Hour numbers
- using var numFont = new SKFont(SKTypeface.Default, 14);
- using var numPaint = new SKPaint(numFont) { Color = SKColors.Black, IsAntialias = true };
- for (int i = 1; i <= 12; i++)
- {
- var angle = (i * 30 - 90) * Math.PI / 180;
- var x = clockCenterX + (float)(clockRadius * Math.Cos(angle));
- var y = clockCenterY + (float)(clockRadius * Math.Sin(angle));
- var numText = i.ToString();
- var numBounds = new SKRect();
- numPaint.MeasureText(numText, ref numBounds);
- canvas.DrawText(numText, x - numBounds.MidX, y - numBounds.MidY, numPaint);
- }
-
- // Clock hand
- var selectedHour = time.Hours % 12;
- if (selectedHour == 0) selectedHour = 12;
- var handAngle = (selectedHour * 30 - 90) * Math.PI / 180;
- var handEndX = clockCenterX + (float)((clockRadius - 20) * Math.Cos(handAngle));
- var handEndY = clockCenterY + (float)((clockRadius - 20) * Math.Sin(handAngle));
-
- using var handPaint = new SKPaint { Color = new SKColor(33, 150, 243), Style = SKPaintStyle.Stroke, StrokeWidth = 2, IsAntialias = true };
- canvas.DrawLine(clockCenterX, clockCenterY, handEndX, handEndY, handPaint);
-
- // Center dot
- handPaint.Style = SKPaintStyle.Fill;
- canvas.DrawCircle(clockCenterX, clockCenterY, 6, handPaint);
-
- // Selected hour highlight
- using var selPaint = new SKPaint { Color = new SKColor(33, 150, 243), Style = SKPaintStyle.Fill, IsAntialias = true };
- var selX = clockCenterX + (float)(clockRadius * Math.Cos(handAngle));
- var selY = clockCenterY + (float)(clockRadius * Math.Sin(handAngle));
- canvas.DrawCircle(selX, selY, 18, selPaint);
- numPaint.Color = SKColors.White;
- var selText = selectedHour.ToString();
- var selBounds = new SKRect();
- numPaint.MeasureText(selText, ref selBounds);
- canvas.DrawText(selText, selX - selBounds.MidX, selY - selBounds.MidY, numPaint);
- }
-
- private void DrawPickerDropdown(SKCanvas canvas, SKRect pickerBounds)
- {
- var items = new[] { "Apple", "Banana", "Cherry", "Date", "Elderberry", "Fig", "Grape" };
- var itemHeight = 40f;
- var dropdownHeight = items.Length * itemHeight;
-
- var dropdownRect = new SKRect(
- pickerBounds.Left, pickerBounds.Bottom + 4,
- pickerBounds.Right, pickerBounds.Bottom + 4 + dropdownHeight);
-
- // Shadow
- using var shadowPaint = new SKPaint {
- Color = new SKColor(0, 0, 0, 50),
- MaskFilter = SKMaskFilter.CreateBlur(SKBlurStyle.Normal, 6)
- };
- canvas.DrawRoundRect(new SKRoundRect(
- new SKRect(dropdownRect.Left + 3, dropdownRect.Top + 3, dropdownRect.Right + 3, dropdownRect.Bottom + 3), 4), shadowPaint);
-
- // Background
- using var bgPaint = new SKPaint { Color = SKColors.White, Style = SKPaintStyle.Fill, IsAntialias = true };
- canvas.DrawRoundRect(new SKRoundRect(dropdownRect, 4), bgPaint);
-
- // Border
- using var borderPaint = new SKPaint { Color = new SKColor(200, 200, 200), Style = SKPaintStyle.Stroke, StrokeWidth = 1 };
- canvas.DrawRoundRect(new SKRoundRect(dropdownRect, 4), borderPaint);
-
- // Items
- using var itemFont = new SKFont(SKTypeface.Default, 14);
- using var itemPaint = new SKPaint(itemFont) { Color = SKColors.Black, IsAntialias = true };
- using var selBgPaint = new SKPaint { Color = new SKColor(33, 150, 243, 40), Style = SKPaintStyle.Fill };
-
- for (int i = 0; i < items.Length; i++)
- {
- var itemTop = dropdownRect.Top + i * itemHeight;
- var itemRect = new SKRect(dropdownRect.Left, itemTop, dropdownRect.Right, itemTop + itemHeight);
-
- if (i == _picker.SelectedIndex)
- {
- canvas.DrawRect(itemRect, selBgPaint);
- }
-
- var textBounds = new SKRect();
- itemPaint.MeasureText(items[i], ref textBounds);
- canvas.DrawText(items[i], itemRect.Left + 12, itemRect.MidY - textBounds.MidY, itemPaint);
- }
- }
-
- private Key KeysymToKey(ulong keysym)
- {
- return keysym switch
- {
- 0xFF08 => Key.Backspace,
- 0xFF09 => Key.Tab,
- 0xFF0D => Key.Enter,
- 0xFF1B => Key.Escape,
- 0xFFFF => Key.Delete,
- 0xFF50 => Key.Home,
- 0xFF51 => Key.Left,
- 0xFF52 => Key.Up,
- 0xFF53 => Key.Right,
- 0xFF54 => Key.Down,
- 0xFF55 => Key.PageUp,
- 0xFF56 => Key.PageDown,
- 0xFF57 => Key.End,
- 0x0020 => Key.Space,
- _ => Key.Unknown
- };
- }
-
- private char KeysymToChar(ulong keysym, uint state)
- {
- bool shift = (state & 1) != 0; // ShiftMask
- bool capsLock = (state & 2) != 0; // LockMask
-
- // Letters a-z / A-Z
- if (keysym >= 0x61 && keysym <= 0x7A) // a-z
- {
- char ch = (char)keysym;
- if (shift ^ capsLock) ch = char.ToUpper(ch);
- return ch;
- }
-
- // Numbers and symbols
- if (keysym >= 0x20 && keysym <= 0x7E)
- {
- if (shift)
- {
- return keysym switch
- {
- 0x31 => '!', 0x32 => '@', 0x33 => '#', 0x34 => '$', 0x35 => '%',
- 0x36 => '^', 0x37 => '&', 0x38 => '*', 0x39 => '(', 0x30 => ')',
- 0x2D => '_', 0x3D => '+', 0x5B => '{', 0x5D => '}', 0x5C => '|',
- 0x3B => ':', 0x27 => '"', 0x60 => '~', 0x2C => '<', 0x2E => '>',
- 0x2F => '?',
- _ => (char)keysym
- };
- }
- return (char)keysym;
- }
-
- // Numpad
- if (keysym >= 0xFFB0 && keysym <= 0xFFB9)
- return (char)('0' + (keysym - 0xFFB0));
-
- return '\0';
- }
-
- private void Cleanup()
- {
- if (_pixelBuffer != IntPtr.Zero) Marshal.FreeHGlobal(_pixelBuffer);
- if (_gc != IntPtr.Zero) XFreeGC(_display, _gc);
- if (_window != IntPtr.Zero) XDestroyWindow(_display, _window);
- if (_display != IntPtr.Zero) XCloseDisplay(_display);
- }
-
- const string LibX11 = "libX11.so.6";
- [DllImport(LibX11)] static extern IntPtr XOpenDisplay(IntPtr d);
- [DllImport(LibX11)] static extern int XCloseDisplay(IntPtr d);
- [DllImport(LibX11)] static extern int XDefaultScreen(IntPtr d);
- [DllImport(LibX11)] static extern IntPtr XRootWindow(IntPtr d, int s);
- [DllImport(LibX11)] static extern ulong XBlackPixel(IntPtr d, int s);
- [DllImport(LibX11)] static extern ulong XWhitePixel(IntPtr d, int s);
- [DllImport(LibX11)] static extern IntPtr XCreateSimpleWindow(IntPtr d, IntPtr p, int x, int y, uint w, uint h, uint bw, ulong b, ulong bg);
- [DllImport(LibX11)] static extern int XMapWindow(IntPtr d, IntPtr w);
- [DllImport(LibX11)] static extern int XStoreName(IntPtr d, IntPtr w, string n);
- [DllImport(LibX11)] static extern int XSelectInput(IntPtr d, IntPtr w, long m);
- [DllImport(LibX11)] static extern IntPtr XCreateGC(IntPtr d, IntPtr dr, ulong vm, IntPtr v);
- [DllImport(LibX11)] static extern int XFreeGC(IntPtr d, IntPtr gc);
- [DllImport(LibX11)] static extern int XFlush(IntPtr d);
- [DllImport(LibX11)] static extern int XPending(IntPtr d);
- [DllImport(LibX11)] static extern int XNextEvent(IntPtr d, out XEvent e);
- [DllImport(LibX11)] static extern ulong XLookupKeysym(ref XKeyEvent k, int i);
- [DllImport(LibX11)] static extern int XDestroyWindow(IntPtr d, IntPtr w);
- [DllImport(LibX11)] static extern IntPtr XDefaultVisual(IntPtr d, int s);
- [DllImport(LibX11)] static extern int XDefaultDepth(IntPtr d, int s);
- [DllImport(LibX11)] static extern IntPtr XCreateImage(IntPtr d, IntPtr v, uint dp, int f, int o, IntPtr data, uint w, uint h, int bp, int bpl);
- [DllImport(LibX11)] static extern int XPutImage(IntPtr d, IntPtr dr, IntPtr gc, IntPtr i, int sx, int sy, int dx, int dy, uint w, uint h);
- [DllImport(LibX11)] static extern int XFree(IntPtr data);
- [DllImport(LibX11)] static extern IntPtr XInternAtom(IntPtr d, string n, bool o);
- [DllImport(LibX11)] static extern int XSetWMProtocols(IntPtr d, IntPtr w, ref IntPtr p, int c);
-
- const long ExposureMask = 1L<<15, KeyPressMask = 1L<<0, KeyReleaseMask = 1L<<1;
- const long ButtonPressMask = 1L<<2, ButtonReleaseMask = 1L<<3, PointerMotionMask = 1L<<6, StructureNotifyMask = 1L<<17;
- const int KeyPress = 2, ButtonPress = 4, ButtonRelease = 5, MotionNotify = 6, Expose = 12, ConfigureNotify = 22, ClientMessage = 33;
-
- [StructLayout(LayoutKind.Explicit, Size = 192)] struct XEvent {
- [FieldOffset(0)] public int type; [FieldOffset(0)] public XExposeEvent xexpose;
- [FieldOffset(0)] public XConfigureEvent xconfigure; [FieldOffset(0)] public XKeyEvent xkey;
- [FieldOffset(0)] public XButtonEvent xbutton; [FieldOffset(0)] public XMotionEvent xmotion;
- [FieldOffset(0)] public XClientMessageEvent xclient;
- }
- [StructLayout(LayoutKind.Sequential)] struct XExposeEvent { public int type; public ulong serial; public int send_event; public IntPtr display, window; public int x, y, width, height, count; }
- [StructLayout(LayoutKind.Sequential)] struct XConfigureEvent { public int type; public ulong serial; public int send_event; public IntPtr display, evt, window; public int x, y, width, height, border_width; public IntPtr above; public int override_redirect; }
- [StructLayout(LayoutKind.Sequential)] struct XKeyEvent { public int type; public ulong serial; public int send_event; public IntPtr display, window, root, subwindow; public ulong time; public int x, y, x_root, y_root; public uint state, keycode; public int same_screen; }
- [StructLayout(LayoutKind.Sequential)] struct XButtonEvent { public int type; public ulong serial; public int send_event; public IntPtr display, window, root, subwindow; public ulong time; public int x, y, x_root, y_root; public uint state, button; public int same_screen; }
- [StructLayout(LayoutKind.Sequential)] struct XMotionEvent { public int type; public ulong serial; public int send_event; public IntPtr display, window, root, subwindow; public ulong time; public int x, y, x_root, y_root; public uint state; public byte is_hint; public int same_screen; }
- [StructLayout(LayoutKind.Sequential)] struct XClientMessageEvent { public int type; public ulong serial; public int send_event; public IntPtr display, window, message_type; public int format; public long data_l0, data_l1, data_l2, data_l3, data_l4; }
-}
diff --git a/samples/ShellDemo/App.cs b/samples/ShellDemo/App.cs
new file mode 100644
index 0000000..2615a41
--- /dev/null
+++ b/samples/ShellDemo/App.cs
@@ -0,0 +1,78 @@
+// ShellDemo App - Comprehensive Control Demo
+
+using Microsoft.Maui.Controls;
+
+namespace ShellDemo;
+
+///
+/// Main application class with Shell navigation.
+///
+public class App : Application
+{
+ public App()
+ {
+ MainPage = new AppShell();
+ }
+}
+
+///
+/// Shell definition with flyout menu - comprehensive control demo.
+///
+public class AppShell : Shell
+{
+ public AppShell()
+ {
+ FlyoutBehavior = FlyoutBehavior.Flyout;
+ Title = "OpenMaui Controls Demo";
+
+ // Register routes for push navigation (pages not in flyout)
+ Routing.RegisterRoute("detail", typeof(DetailPage));
+
+ // Home
+ Items.Add(CreateFlyoutItem("Home", typeof(HomePage)));
+
+ // Buttons Demo
+ Items.Add(CreateFlyoutItem("Buttons", typeof(ButtonsPage)));
+
+ // Text Input Demo
+ Items.Add(CreateFlyoutItem("Text Input", typeof(TextInputPage)));
+
+ // Selection Controls Demo
+ Items.Add(CreateFlyoutItem("Selection", typeof(SelectionPage)));
+
+ // Pickers Demo
+ Items.Add(CreateFlyoutItem("Pickers", typeof(PickersPage)));
+
+ // Lists Demo
+ Items.Add(CreateFlyoutItem("Lists", typeof(ListsPage)));
+
+ // Progress Demo
+ Items.Add(CreateFlyoutItem("Progress", typeof(ProgressPage)));
+
+ // Grids Demo
+ Items.Add(CreateFlyoutItem("Grids", typeof(GridsPage)));
+
+ // About
+ Items.Add(CreateFlyoutItem("About", typeof(AboutPage)));
+ }
+
+ private FlyoutItem CreateFlyoutItem(string title, Type pageType)
+ {
+ // Route is required for Shell.GoToAsync navigation to work
+ var route = title.Replace(" ", "");
+ return new FlyoutItem
+ {
+ Title = title,
+ Route = route,
+ Items =
+ {
+ new ShellContent
+ {
+ Title = title,
+ Route = route,
+ ContentTemplate = new DataTemplate(pageType)
+ }
+ }
+ };
+ }
+}
diff --git a/samples/ShellDemo/MauiProgram.cs b/samples/ShellDemo/MauiProgram.cs
new file mode 100644
index 0000000..0ec2a7e
--- /dev/null
+++ b/samples/ShellDemo/MauiProgram.cs
@@ -0,0 +1,24 @@
+// MauiProgram.cs - Shared MAUI app configuration
+// Works across all platforms (iOS, Android, Windows, Linux)
+
+using Microsoft.Maui.Hosting;
+using Microsoft.Maui.Platform.Linux.Hosting;
+
+namespace ShellDemo;
+
+public static class MauiProgram
+{
+ public static MauiApp CreateMauiApp()
+ {
+ var builder = MauiApp.CreateBuilder();
+
+ // Configure the app (shared across all platforms)
+ builder.UseMauiApp();
+
+ // Add Linux platform support
+ // On other platforms, this would be iOS/Android/Windows specific
+ builder.UseLinux();
+
+ return builder.Build();
+ }
+}
diff --git a/samples/ShellDemo/Pages/AboutPage.cs b/samples/ShellDemo/Pages/AboutPage.cs
new file mode 100644
index 0000000..e38d027
--- /dev/null
+++ b/samples/ShellDemo/Pages/AboutPage.cs
@@ -0,0 +1,115 @@
+// AboutPage - Information about OpenMaui Linux
+
+using Microsoft.Maui.Controls;
+using Microsoft.Maui.Graphics;
+
+namespace ShellDemo;
+
+public class AboutPage : ContentPage
+{
+ public AboutPage()
+ {
+ Title = "About";
+
+ Content = new ScrollView
+ {
+ Content = new VerticalStackLayout
+ {
+ Padding = new Thickness(20),
+ Spacing = 20,
+ Children =
+ {
+ new Label
+ {
+ Text = "OpenMaui Linux",
+ FontSize = 32,
+ FontAttributes = FontAttributes.Bold,
+ TextColor = Color.FromArgb("#1A237E"),
+ HorizontalOptions = LayoutOptions.Center
+ },
+ new Label
+ {
+ Text = "Version 1.0.0",
+ FontSize = 16,
+ TextColor = Colors.Gray,
+ HorizontalOptions = LayoutOptions.Center
+ },
+ new BoxView { HeightRequest = 1, Color = Colors.LightGray },
+ new Label
+ {
+ Text = "OpenMaui Linux brings .NET MAUI to Linux desktops using SkiaSharp for rendering. " +
+ "It provides a native Linux experience while maintaining compatibility with MAUI's cross-platform API.",
+ FontSize = 14,
+ LineBreakMode = LineBreakMode.WordWrap
+ },
+ CreateInfoCard("Platform", "Linux (X11/Wayland)"),
+ CreateInfoCard("Rendering", "SkiaSharp"),
+ CreateInfoCard("Framework", ".NET MAUI"),
+ CreateInfoCard("License", "MIT License"),
+ new BoxView { HeightRequest = 1, Color = Colors.LightGray },
+ new Label
+ {
+ Text = "Features",
+ FontSize = 20,
+ FontAttributes = FontAttributes.Bold
+ },
+ CreateFeatureItem("Full XAML support with styles and resources"),
+ CreateFeatureItem("Shell navigation with flyout menus"),
+ CreateFeatureItem("All standard MAUI controls"),
+ CreateFeatureItem("Data binding and MVVM"),
+ CreateFeatureItem("Keyboard and mouse input"),
+ CreateFeatureItem("High DPI support"),
+ new BoxView { HeightRequest = 1, Color = Colors.LightGray },
+ new Label
+ {
+ Text = "https://github.com/pablotoledo/OpenMaui-Linux",
+ FontSize = 12,
+ TextColor = Colors.Blue,
+ HorizontalOptions = LayoutOptions.Center
+ }
+ }
+ }
+ };
+ }
+
+ private Frame CreateInfoCard(string label, string value)
+ {
+ return new Frame
+ {
+ CornerRadius = 8,
+ Padding = new Thickness(15),
+ BackgroundColor = Color.FromArgb("#F5F5F5"),
+ HasShadow = false,
+ Content = new HorizontalStackLayout
+ {
+ Children =
+ {
+ new Label
+ {
+ Text = label + ":",
+ FontAttributes = FontAttributes.Bold,
+ WidthRequest = 100
+ },
+ new Label
+ {
+ Text = value,
+ TextColor = Colors.Gray
+ }
+ }
+ }
+ };
+ }
+
+ private View CreateFeatureItem(string text)
+ {
+ return new HorizontalStackLayout
+ {
+ Spacing = 10,
+ Children =
+ {
+ new Label { Text = "✓", TextColor = Color.FromArgb("#4CAF50"), FontSize = 16 },
+ new Label { Text = text, FontSize = 14 }
+ }
+ };
+ }
+}
diff --git a/samples/ShellDemo/Pages/ButtonsPage.cs b/samples/ShellDemo/Pages/ButtonsPage.cs
new file mode 100644
index 0000000..695ae97
--- /dev/null
+++ b/samples/ShellDemo/Pages/ButtonsPage.cs
@@ -0,0 +1,229 @@
+// ButtonsPage - Comprehensive Button Control Demo
+
+using Microsoft.Maui.Controls;
+using Microsoft.Maui.Graphics;
+
+namespace ShellDemo;
+
+public class ButtonsPage : ContentPage
+{
+ private readonly Label _eventLog;
+ private int _eventCount = 0;
+
+ public ButtonsPage()
+ {
+ Title = "Buttons Demo";
+
+ _eventLog = new Label
+ {
+ Text = "Events will appear here...",
+ FontSize = 11,
+ TextColor = Colors.Gray,
+ LineBreakMode = LineBreakMode.WordWrap
+ };
+
+ Content = new Grid
+ {
+ RowDefinitions =
+ {
+ new RowDefinition { Height = new GridLength(1, GridUnitType.Star) },
+ new RowDefinition { Height = new GridLength(120) }
+ },
+ Children =
+ {
+ CreateMainContent(),
+ CreateEventLogPanel()
+ }
+ };
+
+ Grid.SetRow((View)((Grid)Content).Children[0], 0);
+ Grid.SetRow((View)((Grid)Content).Children[1], 1);
+ }
+
+ private View CreateMainContent()
+ {
+ return new ScrollView
+ {
+ Content = new VerticalStackLayout
+ {
+ Padding = new Thickness(20),
+ Spacing = 20,
+ Children =
+ {
+ new Label { Text = "Button Styles & Events", FontSize = 24, FontAttributes = FontAttributes.Bold },
+
+ // Basic Buttons
+ CreateSection("Basic Buttons", CreateBasicButtons()),
+
+ // Styled Buttons
+ CreateSection("Styled Buttons", CreateStyledButtons()),
+
+ // Button States
+ CreateSection("Button States", CreateButtonStates()),
+
+ // Button with Icons (text simulation)
+ CreateSection("Button Variations", CreateButtonVariations())
+ }
+ }
+ };
+ }
+
+ private View CreateBasicButtons()
+ {
+ var layout = new VerticalStackLayout { Spacing = 10 };
+
+ var defaultBtn = new Button { Text = "Default Button" };
+ defaultBtn.Clicked += (s, e) => LogEvent("Default Button clicked");
+ defaultBtn.Pressed += (s, e) => LogEvent("Default Button pressed");
+ defaultBtn.Released += (s, e) => LogEvent("Default Button released");
+
+ var textBtn = new Button { Text = "Text Only", BackgroundColor = Colors.Transparent, TextColor = Colors.Blue };
+ textBtn.Clicked += (s, e) => LogEvent("Text Button clicked");
+
+ layout.Children.Add(defaultBtn);
+ layout.Children.Add(textBtn);
+
+ return layout;
+ }
+
+ private View CreateStyledButtons()
+ {
+ var layout = new HorizontalStackLayout { Spacing = 10 };
+
+ var colors = new[]
+ {
+ ("#2196F3", "Primary"),
+ ("#4CAF50", "Success"),
+ ("#FF9800", "Warning"),
+ ("#F44336", "Danger"),
+ ("#9C27B0", "Purple")
+ };
+
+ foreach (var (color, name) in colors)
+ {
+ var btn = new Button
+ {
+ Text = name,
+ BackgroundColor = Color.FromArgb(color),
+ TextColor = Colors.White,
+ CornerRadius = 5
+ };
+ btn.Clicked += (s, e) => LogEvent($"{name} button clicked");
+ layout.Children.Add(btn);
+ }
+
+ return layout;
+ }
+
+ private View CreateButtonStates()
+ {
+ var layout = new VerticalStackLayout { Spacing = 10 };
+
+ var enabledBtn = new Button { Text = "Enabled Button", IsEnabled = true };
+ enabledBtn.Clicked += (s, e) => LogEvent("Enabled button clicked");
+
+ var disabledBtn = new Button { Text = "Disabled Button", IsEnabled = false };
+
+ var toggleBtn = new Button { Text = "Toggle Above Button" };
+ toggleBtn.Clicked += (s, e) =>
+ {
+ disabledBtn.IsEnabled = !disabledBtn.IsEnabled;
+ disabledBtn.Text = disabledBtn.IsEnabled ? "Now Enabled!" : "Disabled Button";
+ LogEvent($"Toggled button to: {(disabledBtn.IsEnabled ? "Enabled" : "Disabled")}");
+ };
+
+ layout.Children.Add(enabledBtn);
+ layout.Children.Add(disabledBtn);
+ layout.Children.Add(toggleBtn);
+
+ return layout;
+ }
+
+ private View CreateButtonVariations()
+ {
+ var layout = new VerticalStackLayout { Spacing = 10 };
+
+ var wideBtn = new Button
+ {
+ Text = "Wide Button",
+ HorizontalOptions = LayoutOptions.Fill,
+ BackgroundColor = Color.FromArgb("#673AB7"),
+ TextColor = Colors.White
+ };
+ wideBtn.Clicked += (s, e) => LogEvent("Wide button clicked");
+
+ var tallBtn = new Button
+ {
+ Text = "Tall Button",
+ HeightRequest = 60,
+ BackgroundColor = Color.FromArgb("#009688"),
+ TextColor = Colors.White
+ };
+ tallBtn.Clicked += (s, e) => LogEvent("Tall button clicked");
+
+ var roundBtn = new Button
+ {
+ Text = "Round",
+ WidthRequest = 80,
+ HeightRequest = 80,
+ CornerRadius = 40,
+ BackgroundColor = Color.FromArgb("#E91E63"),
+ TextColor = Colors.White
+ };
+ roundBtn.Clicked += (s, e) => LogEvent("Round button clicked");
+
+ layout.Children.Add(wideBtn);
+ layout.Children.Add(tallBtn);
+ layout.Children.Add(new HorizontalStackLayout { Children = { roundBtn } });
+
+ return layout;
+ }
+
+ private Frame CreateSection(string title, View content)
+ {
+ return new Frame
+ {
+ CornerRadius = 8,
+ Padding = new Thickness(15),
+ BackgroundColor = Colors.White,
+ Content = new VerticalStackLayout
+ {
+ Spacing = 10,
+ Children =
+ {
+ new Label { Text = title, FontSize = 16, FontAttributes = FontAttributes.Bold },
+ content
+ }
+ }
+ };
+ }
+
+ private View CreateEventLogPanel()
+ {
+ return new Frame
+ {
+ BackgroundColor = Color.FromArgb("#F5F5F5"),
+ Padding = new Thickness(10),
+ CornerRadius = 0,
+ Content = new VerticalStackLayout
+ {
+ Children =
+ {
+ new Label { Text = "Event Log:", FontSize = 12, FontAttributes = FontAttributes.Bold },
+ new ScrollView
+ {
+ HeightRequest = 80,
+ Content = _eventLog
+ }
+ }
+ }
+ };
+ }
+
+ private void LogEvent(string message)
+ {
+ _eventCount++;
+ var timestamp = DateTime.Now.ToString("HH:mm:ss");
+ _eventLog.Text = $"[{timestamp}] {_eventCount}. {message}\n{_eventLog.Text}";
+ }
+}
diff --git a/samples/ShellDemo/Pages/ControlsPage.cs b/samples/ShellDemo/Pages/ControlsPage.cs
new file mode 100644
index 0000000..6478bdc
--- /dev/null
+++ b/samples/ShellDemo/Pages/ControlsPage.cs
@@ -0,0 +1,203 @@
+// ControlsPage - Demonstrates various MAUI controls
+
+using Microsoft.Maui.Controls;
+using Microsoft.Maui.Graphics;
+
+namespace ShellDemo;
+
+public class ControlsPage : ContentPage
+{
+ public ControlsPage()
+ {
+ Title = "Controls";
+
+ Content = new ScrollView
+ {
+ Content = new VerticalStackLayout
+ {
+ Padding = new Thickness(20),
+ Spacing = 15,
+ Children =
+ {
+ new Label
+ {
+ Text = "Control Gallery",
+ FontSize = 24,
+ FontAttributes = FontAttributes.Bold
+ },
+
+ // Buttons
+ CreateSection("Buttons", new View[]
+ {
+ CreateButtonRow()
+ }),
+
+ // CheckBox & Switch
+ CreateSection("Selection", new View[]
+ {
+ CreateCheckBoxRow(),
+ CreateSwitchRow()
+ }),
+
+ // Slider
+ CreateSection("Slider", new View[]
+ {
+ CreateSliderRow()
+ }),
+
+ // Picker
+ CreateSection("Picker", new View[]
+ {
+ CreatePickerRow()
+ }),
+
+ // Progress
+ CreateSection("Progress", new View[]
+ {
+ CreateProgressRow()
+ })
+ }
+ }
+ };
+ }
+
+ private Frame CreateSection(string title, View[] content)
+ {
+ var layout = new VerticalStackLayout { Spacing = 10 };
+ layout.Children.Add(new Label
+ {
+ Text = title,
+ FontSize = 18,
+ FontAttributes = FontAttributes.Bold
+ });
+
+ foreach (var view in content)
+ {
+ layout.Children.Add(view);
+ }
+
+ return new Frame
+ {
+ CornerRadius = 8,
+ Padding = new Thickness(15),
+ BackgroundColor = Colors.White,
+ Content = layout
+ };
+ }
+
+ private View CreateButtonRow()
+ {
+ var resultLabel = new Label { TextColor = Colors.Gray, FontSize = 12 };
+
+ var layout = new VerticalStackLayout { Spacing = 10 };
+
+ var buttonRow = new HorizontalStackLayout { Spacing = 10 };
+
+ var primaryBtn = new Button { Text = "Primary", BackgroundColor = Color.FromArgb("#2196F3"), TextColor = Colors.White };
+ primaryBtn.Clicked += (s, e) => resultLabel.Text = "Primary clicked!";
+
+ var successBtn = new Button { Text = "Success", BackgroundColor = Color.FromArgb("#4CAF50"), TextColor = Colors.White };
+ successBtn.Clicked += (s, e) => resultLabel.Text = "Success clicked!";
+
+ var dangerBtn = new Button { Text = "Danger", BackgroundColor = Color.FromArgb("#F44336"), TextColor = Colors.White };
+ dangerBtn.Clicked += (s, e) => resultLabel.Text = "Danger clicked!";
+
+ buttonRow.Children.Add(primaryBtn);
+ buttonRow.Children.Add(successBtn);
+ buttonRow.Children.Add(dangerBtn);
+
+ layout.Children.Add(buttonRow);
+ layout.Children.Add(resultLabel);
+
+ return layout;
+ }
+
+ private View CreateCheckBoxRow()
+ {
+ var layout = new HorizontalStackLayout { Spacing = 20 };
+
+ var cb1 = new CheckBox { IsChecked = true };
+ var cb2 = new CheckBox { IsChecked = false };
+
+ layout.Children.Add(cb1);
+ layout.Children.Add(new Label { Text = "Option 1", VerticalOptions = LayoutOptions.Center });
+ layout.Children.Add(cb2);
+ layout.Children.Add(new Label { Text = "Option 2", VerticalOptions = LayoutOptions.Center });
+
+ return layout;
+ }
+
+ private View CreateSwitchRow()
+ {
+ var label = new Label { Text = "Off", VerticalOptions = LayoutOptions.Center };
+ var sw = new Switch { IsToggled = false };
+ sw.Toggled += (s, e) => label.Text = e.Value ? "On" : "Off";
+
+ return new HorizontalStackLayout
+ {
+ Spacing = 10,
+ Children = { sw, label }
+ };
+ }
+
+ private View CreateSliderRow()
+ {
+ var label = new Label { Text = "Value: 50" };
+ var slider = new Slider { Minimum = 0, Maximum = 100, Value = 50 };
+ slider.ValueChanged += (s, e) => label.Text = $"Value: {(int)e.NewValue}";
+
+ return new VerticalStackLayout
+ {
+ Spacing = 5,
+ Children = { slider, label }
+ };
+ }
+
+ private View CreatePickerRow()
+ {
+ var label = new Label { Text = "Selected: (none)", TextColor = Colors.Gray };
+ var picker = new Picker { Title = "Select a fruit" };
+ picker.Items.Add("Apple");
+ picker.Items.Add("Banana");
+ picker.Items.Add("Cherry");
+ picker.Items.Add("Date");
+ picker.Items.Add("Elderberry");
+
+ picker.SelectedIndexChanged += (s, e) =>
+ {
+ if (picker.SelectedIndex >= 0)
+ label.Text = $"Selected: {picker.Items[picker.SelectedIndex]}";
+ };
+
+ return new VerticalStackLayout
+ {
+ Spacing = 5,
+ Children = { picker, label }
+ };
+ }
+
+ private View CreateProgressRow()
+ {
+ var progress = new ProgressBar { Progress = 0.7 };
+ var activity = new ActivityIndicator { IsRunning = true };
+
+ return new VerticalStackLayout
+ {
+ Spacing = 10,
+ Children =
+ {
+ progress,
+ new Label { Text = "70% Complete", FontSize = 12, TextColor = Colors.Gray },
+ new HorizontalStackLayout
+ {
+ Spacing = 10,
+ Children =
+ {
+ activity,
+ new Label { Text = "Loading...", VerticalOptions = LayoutOptions.Center, TextColor = Colors.Gray }
+ }
+ }
+ }
+ };
+ }
+}
diff --git a/samples/ShellDemo/Pages/DetailPage.cs b/samples/ShellDemo/Pages/DetailPage.cs
new file mode 100644
index 0000000..438751b
--- /dev/null
+++ b/samples/ShellDemo/Pages/DetailPage.cs
@@ -0,0 +1,123 @@
+// DetailPage - Demonstrates push/pop navigation
+
+using Microsoft.Maui.Controls;
+using Microsoft.Maui.Graphics;
+using Microsoft.Maui.Platform.Linux.Hosting;
+
+namespace ShellDemo;
+
+///
+/// A detail page that can be pushed onto the navigation stack.
+///
+public class DetailPage : ContentPage
+{
+ private readonly string _itemName;
+
+ public DetailPage() : this("Detail Item")
+ {
+ }
+
+ public DetailPage(string itemName)
+ {
+ _itemName = itemName;
+ Title = "Detail Page";
+
+ Content = new VerticalStackLayout
+ {
+ Padding = new Thickness(30),
+ Spacing = 20,
+ VerticalOptions = LayoutOptions.Center,
+ Children =
+ {
+ new Label
+ {
+ Text = "Pushed Page",
+ FontSize = 28,
+ FontAttributes = FontAttributes.Bold,
+ HorizontalOptions = LayoutOptions.Center,
+ TextColor = Color.FromArgb("#9C27B0")
+ },
+
+ new Label
+ {
+ Text = $"You navigated to: {_itemName}",
+ FontSize = 16,
+ HorizontalOptions = LayoutOptions.Center
+ },
+
+ new Label
+ {
+ Text = "This page was pushed onto the navigation stack using Shell.Current.GoToAsync()",
+ FontSize = 14,
+ TextColor = Colors.Gray,
+ HorizontalTextAlignment = TextAlignment.Center,
+ LineBreakMode = LineBreakMode.WordWrap
+ },
+
+ new BoxView
+ {
+ HeightRequest = 2,
+ Color = Color.FromArgb("#E0E0E0"),
+ Margin = new Thickness(0, 20)
+ },
+
+ CreateBackButton(),
+
+ new Label
+ {
+ Text = "Use the back button above or the hardware/gesture back to pop this page",
+ FontSize = 12,
+ TextColor = Colors.Gray,
+ HorizontalTextAlignment = TextAlignment.Center,
+ Margin = new Thickness(0, 20, 0, 0)
+ }
+ }
+ };
+ }
+
+ private Button CreateBackButton()
+ {
+ var backBtn = new Button
+ {
+ Text = "Go Back (Pop)",
+ BackgroundColor = Color.FromArgb("#9C27B0"),
+ TextColor = Colors.White,
+ HorizontalOptions = LayoutOptions.Center,
+ Padding = new Thickness(30, 10)
+ };
+
+ backBtn.Clicked += (s, e) =>
+ {
+ // Pop this page off the navigation stack using LinuxViewRenderer
+ Console.WriteLine("[DetailPage] Go Back clicked");
+ var success = LinuxViewRenderer.PopPage();
+ Console.WriteLine($"[DetailPage] PopPage result: {success}");
+ };
+
+ return backBtn;
+ }
+}
+
+///
+/// Query property for passing data to DetailPage.
+///
+[QueryProperty(nameof(ItemName), "item")]
+public class DetailPageWithQuery : DetailPage
+{
+ private string _itemName = "Item";
+
+ public string ItemName
+ {
+ get => _itemName;
+ set
+ {
+ _itemName = value;
+ // Update the title when the property is set
+ Title = $"Detail: {value}";
+ }
+ }
+
+ public DetailPageWithQuery() : base()
+ {
+ }
+}
diff --git a/samples/ShellDemo/Pages/GridsPage.cs b/samples/ShellDemo/Pages/GridsPage.cs
new file mode 100644
index 0000000..09cea44
--- /dev/null
+++ b/samples/ShellDemo/Pages/GridsPage.cs
@@ -0,0 +1,594 @@
+// GridsPage - Demonstrates Grid layouts with various options
+
+using Microsoft.Maui.Controls;
+using Microsoft.Maui.Graphics;
+
+namespace ShellDemo;
+
+public class GridsPage : ContentPage
+{
+ public GridsPage()
+ {
+ Title = "Grids";
+
+ Content = new ScrollView
+ {
+ Orientation = ScrollOrientation.Both,
+ Content = new VerticalStackLayout
+ {
+ Spacing = 25,
+ Children =
+ {
+ CreateSectionHeader("Basic Grid (2x2)"),
+ CreateBasicGrid(),
+
+ CreateSectionHeader("Column Definitions"),
+ CreateColumnDefinitionsDemo(),
+
+ CreateSectionHeader("Row Definitions"),
+ CreateRowDefinitionsDemo(),
+
+ CreateSectionHeader("Auto Rows (Empty vs Content)"),
+ CreateAutoRowsDemo(),
+
+ CreateSectionHeader("Star Sizing (Proportional)"),
+ CreateStarSizingDemo(),
+
+ CreateSectionHeader("Row & Column Spacing"),
+ CreateSpacingDemo(),
+
+ CreateSectionHeader("Row & Column Span"),
+ CreateSpanDemo(),
+
+ CreateSectionHeader("Mixed Sizing"),
+ CreateMixedSizingDemo(),
+
+ CreateSectionHeader("Nested Grids"),
+ CreateNestedGridDemo(),
+
+ new BoxView { HeightRequest = 20 } // Bottom padding
+ }
+ }
+ };
+ }
+
+ private Label CreateSectionHeader(string text)
+ {
+ return new Label
+ {
+ Text = text,
+ FontSize = 18,
+ FontAttributes = FontAttributes.Bold,
+ TextColor = Color.FromArgb("#2196F3"),
+ Margin = new Thickness(0, 10, 0, 5)
+ };
+ }
+
+ private View CreateBasicGrid()
+ {
+ var grid = new Grid
+ {
+ RowDefinitions =
+ {
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = GridLength.Auto }
+ },
+ ColumnDefinitions =
+ {
+ new ColumnDefinition { Width = GridLength.Star },
+ new ColumnDefinition { Width = GridLength.Star }
+ },
+ BackgroundColor = Color.FromArgb("#F5F5F5")
+ };
+
+ var cell1 = CreateCell("Row 0, Col 0", "#E3F2FD");
+ var cell2 = CreateCell("Row 0, Col 1", "#E8F5E9");
+ var cell3 = CreateCell("Row 1, Col 0", "#FFF3E0");
+ var cell4 = CreateCell("Row 1, Col 1", "#FCE4EC");
+
+ Grid.SetRow(cell1, 0); Grid.SetColumn(cell1, 0);
+ Grid.SetRow(cell2, 0); Grid.SetColumn(cell2, 1);
+ Grid.SetRow(cell3, 1); Grid.SetColumn(cell3, 0);
+ Grid.SetRow(cell4, 1); Grid.SetColumn(cell4, 1);
+
+ grid.Children.Add(cell1);
+ grid.Children.Add(cell2);
+ grid.Children.Add(cell3);
+ grid.Children.Add(cell4);
+
+ return CreateDemoContainer(grid, "Equal columns using Star sizing");
+ }
+
+ private View CreateColumnDefinitionsDemo()
+ {
+ var stack = new VerticalStackLayout { Spacing = 15 };
+
+ // Auto width columns
+ var autoGrid = new Grid
+ {
+ ColumnDefinitions =
+ {
+ new ColumnDefinition { Width = GridLength.Auto },
+ new ColumnDefinition { Width = GridLength.Auto },
+ new ColumnDefinition { Width = GridLength.Auto }
+ },
+ BackgroundColor = Color.FromArgb("#F5F5F5")
+ };
+
+ var a1 = CreateCell("Auto", "#BBDEFB");
+ var a2 = CreateCell("Auto Width", "#C8E6C9");
+ var a3 = CreateCell("A", "#FFECB3");
+ Grid.SetColumn(a1, 0);
+ Grid.SetColumn(a2, 1);
+ Grid.SetColumn(a3, 2);
+ autoGrid.Children.Add(a1);
+ autoGrid.Children.Add(a2);
+ autoGrid.Children.Add(a3);
+
+ stack.Children.Add(new Label { Text = "Auto: Sizes to content", FontSize = 12, TextColor = Colors.Gray });
+ stack.Children.Add(autoGrid);
+
+ // Absolute width columns
+ var absoluteGrid = new Grid
+ {
+ ColumnDefinitions =
+ {
+ new ColumnDefinition { Width = new GridLength(50) },
+ new ColumnDefinition { Width = new GridLength(100) },
+ new ColumnDefinition { Width = new GridLength(150) }
+ },
+ BackgroundColor = Color.FromArgb("#F5F5F5")
+ };
+
+ var b1 = CreateCell("50px", "#BBDEFB");
+ var b2 = CreateCell("100px", "#C8E6C9");
+ var b3 = CreateCell("150px", "#FFECB3");
+ Grid.SetColumn(b1, 0);
+ Grid.SetColumn(b2, 1);
+ Grid.SetColumn(b3, 2);
+ absoluteGrid.Children.Add(b1);
+ absoluteGrid.Children.Add(b2);
+ absoluteGrid.Children.Add(b3);
+
+ stack.Children.Add(new Label { Text = "Absolute: Fixed pixel widths (50, 100, 150)", FontSize = 12, TextColor = Colors.Gray, Margin = new Thickness(0, 10, 0, 0) });
+ stack.Children.Add(absoluteGrid);
+
+ return stack;
+ }
+
+ private View CreateRowDefinitionsDemo()
+ {
+ var grid = new Grid
+ {
+ WidthRequest = 200,
+ RowDefinitions =
+ {
+ new RowDefinition { Height = new GridLength(30) },
+ new RowDefinition { Height = new GridLength(50) },
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = new GridLength(40) }
+ },
+ ColumnDefinitions =
+ {
+ new ColumnDefinition { Width = GridLength.Star }
+ },
+ BackgroundColor = Color.FromArgb("#F5F5F5")
+ };
+
+ var r1 = CreateCell("30px height", "#BBDEFB");
+ var r2 = CreateCell("50px height", "#C8E6C9");
+ var r3 = CreateCell("Auto height\n(fits content)", "#FFECB3");
+ var r4 = CreateCell("40px height", "#F8BBD9");
+
+ Grid.SetRow(r1, 0);
+ Grid.SetRow(r2, 1);
+ Grid.SetRow(r3, 2);
+ Grid.SetRow(r4, 3);
+
+ grid.Children.Add(r1);
+ grid.Children.Add(r2);
+ grid.Children.Add(r3);
+ grid.Children.Add(r4);
+
+ return CreateDemoContainer(grid, "Different row heights: 30px, 50px, Auto, 40px");
+ }
+
+ private View CreateAutoRowsDemo()
+ {
+ var stack = new VerticalStackLayout { Spacing = 15 };
+
+ // Grid with empty Auto row
+ var emptyAutoGrid = new Grid
+ {
+ WidthRequest = 250,
+ RowDefinitions =
+ {
+ new RowDefinition { Height = new GridLength(40) },
+ new RowDefinition { Height = GridLength.Auto }, // Empty - should collapse
+ new RowDefinition { Height = new GridLength(40) }
+ },
+ ColumnDefinitions =
+ {
+ new ColumnDefinition { Width = GridLength.Star }
+ },
+ BackgroundColor = Color.FromArgb("#E0E0E0")
+ };
+
+ var r1 = CreateCell("Row 0: 40px", "#BBDEFB");
+ // Row 1 is Auto with NO content - should be 0 height
+ var r3 = CreateCell("Row 2: 40px", "#C8E6C9");
+
+ Grid.SetRow(r1, 0);
+ Grid.SetRow(r3, 2); // Skip row 1
+
+ emptyAutoGrid.Children.Add(r1);
+ emptyAutoGrid.Children.Add(r3);
+
+ stack.Children.Add(new Label { Text = "Empty Auto row (Row 1) should collapse to 0 height:", FontSize = 12, TextColor = Colors.Gray });
+ stack.Children.Add(emptyAutoGrid);
+
+ // Grid with Auto row that has content
+ var contentAutoGrid = new Grid
+ {
+ WidthRequest = 250,
+ RowDefinitions =
+ {
+ new RowDefinition { Height = new GridLength(40) },
+ new RowDefinition { Height = GridLength.Auto }, // Has content
+ new RowDefinition { Height = new GridLength(40) }
+ },
+ ColumnDefinitions =
+ {
+ new ColumnDefinition { Width = GridLength.Star }
+ },
+ BackgroundColor = Color.FromArgb("#E0E0E0")
+ };
+
+ var c1 = CreateCell("Row 0: 40px", "#BBDEFB");
+ var c2 = CreateCell("Row 1: Auto (sized to this content)", "#FFECB3");
+ var c3 = CreateCell("Row 2: 40px", "#C8E6C9");
+
+ Grid.SetRow(c1, 0);
+ Grid.SetRow(c2, 1);
+ Grid.SetRow(c3, 2);
+
+ contentAutoGrid.Children.Add(c1);
+ contentAutoGrid.Children.Add(c2);
+ contentAutoGrid.Children.Add(c3);
+
+ stack.Children.Add(new Label { Text = "Auto row with content sizes to fit:", FontSize = 12, TextColor = Colors.Gray, Margin = new Thickness(0, 10, 0, 0) });
+ stack.Children.Add(contentAutoGrid);
+
+ return stack;
+ }
+
+ private View CreateStarSizingDemo()
+ {
+ var grid = new Grid
+ {
+ ColumnDefinitions =
+ {
+ new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) },
+ new ColumnDefinition { Width = new GridLength(2, GridUnitType.Star) },
+ new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }
+ },
+ BackgroundColor = Color.FromArgb("#F5F5F5")
+ };
+
+ var s1 = CreateCell("1*", "#BBDEFB");
+ var s2 = CreateCell("2* (double)", "#C8E6C9");
+ var s3 = CreateCell("1*", "#FFECB3");
+
+ Grid.SetColumn(s1, 0);
+ Grid.SetColumn(s2, 1);
+ Grid.SetColumn(s3, 2);
+
+ grid.Children.Add(s1);
+ grid.Children.Add(s2);
+ grid.Children.Add(s3);
+
+ return CreateDemoContainer(grid, "Star proportions: 1* | 2* | 1* = 25% | 50% | 25%");
+ }
+
+ private View CreateSpacingDemo()
+ {
+ var stack = new VerticalStackLayout { Spacing = 15 };
+
+ // No spacing
+ var noSpacing = new Grid
+ {
+ RowSpacing = 0,
+ ColumnSpacing = 0,
+ RowDefinitions =
+ {
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = GridLength.Auto }
+ },
+ ColumnDefinitions =
+ {
+ new ColumnDefinition { Width = GridLength.Star },
+ new ColumnDefinition { Width = GridLength.Star }
+ }
+ };
+ AddFourCells(noSpacing);
+ stack.Children.Add(new Label { Text = "No spacing (RowSpacing=0, ColumnSpacing=0)", FontSize = 12, TextColor = Colors.Gray });
+ stack.Children.Add(noSpacing);
+
+ // With spacing
+ var withSpacing = new Grid
+ {
+ RowSpacing = 10,
+ ColumnSpacing = 10,
+ RowDefinitions =
+ {
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = GridLength.Auto }
+ },
+ ColumnDefinitions =
+ {
+ new ColumnDefinition { Width = GridLength.Star },
+ new ColumnDefinition { Width = GridLength.Star }
+ }
+ };
+ AddFourCells(withSpacing);
+ stack.Children.Add(new Label { Text = "With spacing (RowSpacing=10, ColumnSpacing=10)", FontSize = 12, TextColor = Colors.Gray, Margin = new Thickness(0, 10, 0, 0) });
+ stack.Children.Add(withSpacing);
+
+ // Different row/column spacing
+ var mixedSpacing = new Grid
+ {
+ RowSpacing = 5,
+ ColumnSpacing = 20,
+ RowDefinitions =
+ {
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = GridLength.Auto }
+ },
+ ColumnDefinitions =
+ {
+ new ColumnDefinition { Width = GridLength.Star },
+ new ColumnDefinition { Width = GridLength.Star }
+ }
+ };
+ AddFourCells(mixedSpacing);
+ stack.Children.Add(new Label { Text = "Mixed spacing (RowSpacing=5, ColumnSpacing=20)", FontSize = 12, TextColor = Colors.Gray, Margin = new Thickness(0, 10, 0, 0) });
+ stack.Children.Add(mixedSpacing);
+
+ return stack;
+ }
+
+ private View CreateSpanDemo()
+ {
+ var grid = new Grid
+ {
+ RowSpacing = 5,
+ ColumnSpacing = 5,
+ RowDefinitions =
+ {
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = GridLength.Auto }
+ },
+ ColumnDefinitions =
+ {
+ new ColumnDefinition { Width = GridLength.Star },
+ new ColumnDefinition { Width = GridLength.Star },
+ new ColumnDefinition { Width = GridLength.Star }
+ }
+ };
+
+ // Spanning header
+ var header = CreateCell("ColumnSpan=3 (Header)", "#1976D2", Colors.White);
+ Grid.SetRow(header, 0);
+ Grid.SetColumn(header, 0);
+ Grid.SetColumnSpan(header, 3);
+
+ // Left sidebar spanning 2 rows
+ var sidebar = CreateCell("RowSpan=2\n(Sidebar)", "#388E3C", Colors.White);
+ Grid.SetRow(sidebar, 1);
+ Grid.SetColumn(sidebar, 0);
+ Grid.SetRowSpan(sidebar, 2);
+
+ // Content cells
+ var content1 = CreateCell("Content 1", "#E3F2FD");
+ Grid.SetRow(content1, 1);
+ Grid.SetColumn(content1, 1);
+
+ var content2 = CreateCell("Content 2", "#E8F5E9");
+ Grid.SetRow(content2, 1);
+ Grid.SetColumn(content2, 2);
+
+ var content3 = CreateCell("Content 3", "#FFF3E0");
+ Grid.SetRow(content3, 2);
+ Grid.SetColumn(content3, 1);
+
+ var content4 = CreateCell("Content 4", "#FCE4EC");
+ Grid.SetRow(content4, 2);
+ Grid.SetColumn(content4, 2);
+
+ grid.Children.Add(header);
+ grid.Children.Add(sidebar);
+ grid.Children.Add(content1);
+ grid.Children.Add(content2);
+ grid.Children.Add(content3);
+ grid.Children.Add(content4);
+
+ return CreateDemoContainer(grid, "Header spans 3 columns, Sidebar spans 2 rows");
+ }
+
+ private View CreateMixedSizingDemo()
+ {
+ var grid = new Grid
+ {
+ ColumnSpacing = 5,
+ ColumnDefinitions =
+ {
+ new ColumnDefinition { Width = new GridLength(60) }, // Fixed
+ new ColumnDefinition { Width = GridLength.Star }, // Fill
+ new ColumnDefinition { Width = GridLength.Auto }, // Auto
+ new ColumnDefinition { Width = new GridLength(60) } // Fixed
+ },
+ BackgroundColor = Color.FromArgb("#F5F5F5")
+ };
+
+ var c1 = CreateCell("60px", "#BBDEFB");
+ var c2 = CreateCell("Star (fills remaining)", "#C8E6C9");
+ var c3 = CreateCell("Auto", "#FFECB3");
+ var c4 = CreateCell("60px", "#F8BBD9");
+
+ Grid.SetColumn(c1, 0);
+ Grid.SetColumn(c2, 1);
+ Grid.SetColumn(c3, 2);
+ Grid.SetColumn(c4, 3);
+
+ grid.Children.Add(c1);
+ grid.Children.Add(c2);
+ grid.Children.Add(c3);
+ grid.Children.Add(c4);
+
+ return CreateDemoContainer(grid, "Mixed: 60px | Star | Auto | 60px");
+ }
+
+ private View CreateNestedGridDemo()
+ {
+ var outerGrid = new Grid
+ {
+ RowSpacing = 10,
+ ColumnSpacing = 10,
+ RowDefinitions =
+ {
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = GridLength.Auto }
+ },
+ ColumnDefinitions =
+ {
+ new ColumnDefinition { Width = GridLength.Star },
+ new ColumnDefinition { Width = GridLength.Star }
+ },
+ BackgroundColor = Color.FromArgb("#E0E0E0"),
+ Padding = new Thickness(10)
+ };
+
+ // Nested grid 1
+ var innerGrid1 = new Grid
+ {
+ RowSpacing = 2,
+ ColumnSpacing = 2,
+ RowDefinitions =
+ {
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = GridLength.Auto }
+ },
+ ColumnDefinitions =
+ {
+ new ColumnDefinition { Width = GridLength.Star },
+ new ColumnDefinition { Width = GridLength.Star }
+ }
+ };
+ var i1a = CreateCell("A", "#BBDEFB", null, 8);
+ var i1b = CreateCell("B", "#90CAF9", null, 8);
+ var i1c = CreateCell("C", "#64B5F6", null, 8);
+ var i1d = CreateCell("D", "#42A5F5", null, 8);
+ Grid.SetRow(i1a, 0); Grid.SetColumn(i1a, 0);
+ Grid.SetRow(i1b, 0); Grid.SetColumn(i1b, 1);
+ Grid.SetRow(i1c, 1); Grid.SetColumn(i1c, 0);
+ Grid.SetRow(i1d, 1); Grid.SetColumn(i1d, 1);
+ innerGrid1.Children.Add(i1a);
+ innerGrid1.Children.Add(i1b);
+ innerGrid1.Children.Add(i1c);
+ innerGrid1.Children.Add(i1d);
+
+ // Nested grid 2
+ var innerGrid2 = new Grid
+ {
+ RowSpacing = 2,
+ ColumnSpacing = 2,
+ RowDefinitions =
+ {
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = GridLength.Auto }
+ },
+ ColumnDefinitions =
+ {
+ new ColumnDefinition { Width = GridLength.Star },
+ new ColumnDefinition { Width = GridLength.Star }
+ }
+ };
+ var i2a = CreateCell("1", "#C8E6C9", null, 8);
+ var i2b = CreateCell("2", "#A5D6A7", null, 8);
+ var i2c = CreateCell("3", "#81C784", null, 8);
+ var i2d = CreateCell("4", "#66BB6A", null, 8);
+ Grid.SetRow(i2a, 0); Grid.SetColumn(i2a, 0);
+ Grid.SetRow(i2b, 0); Grid.SetColumn(i2b, 1);
+ Grid.SetRow(i2c, 1); Grid.SetColumn(i2c, 0);
+ Grid.SetRow(i2d, 1); Grid.SetColumn(i2d, 1);
+ innerGrid2.Children.Add(i2a);
+ innerGrid2.Children.Add(i2b);
+ innerGrid2.Children.Add(i2c);
+ innerGrid2.Children.Add(i2d);
+
+ Grid.SetRow(innerGrid1, 0); Grid.SetColumn(innerGrid1, 0);
+ Grid.SetRow(innerGrid2, 0); Grid.SetColumn(innerGrid2, 1);
+
+ var label1 = new Label { Text = "Outer Grid Row 1", HorizontalOptions = LayoutOptions.Center };
+ var label2 = new Label { Text = "Spans both columns", HorizontalOptions = LayoutOptions.Center };
+ Grid.SetRow(label1, 1); Grid.SetColumn(label1, 0);
+ Grid.SetRow(label2, 1); Grid.SetColumn(label2, 1);
+
+ outerGrid.Children.Add(innerGrid1);
+ outerGrid.Children.Add(innerGrid2);
+ outerGrid.Children.Add(label1);
+ outerGrid.Children.Add(label2);
+
+ return CreateDemoContainer(outerGrid, "Outer grid contains two nested 2x2 grids");
+ }
+
+ private Border CreateCell(string text, string bgColor, Color? textColor = null, float fontSize = 12)
+ {
+ return new Border
+ {
+ BackgroundColor = Color.FromArgb(bgColor),
+ Padding = new Thickness(10, 8),
+ StrokeThickness = 0,
+ Content = new Label
+ {
+ Text = text,
+ FontSize = fontSize,
+ TextColor = textColor ?? Colors.Black,
+ HorizontalTextAlignment = TextAlignment.Center,
+ VerticalTextAlignment = TextAlignment.Center
+ }
+ };
+ }
+
+ private void AddFourCells(Grid grid)
+ {
+ var c1 = CreateCell("0,0", "#BBDEFB");
+ var c2 = CreateCell("0,1", "#C8E6C9");
+ var c3 = CreateCell("1,0", "#FFECB3");
+ var c4 = CreateCell("1,1", "#F8BBD9");
+
+ Grid.SetRow(c1, 0); Grid.SetColumn(c1, 0);
+ Grid.SetRow(c2, 0); Grid.SetColumn(c2, 1);
+ Grid.SetRow(c3, 1); Grid.SetColumn(c3, 0);
+ Grid.SetRow(c4, 1); Grid.SetColumn(c4, 1);
+
+ grid.Children.Add(c1);
+ grid.Children.Add(c2);
+ grid.Children.Add(c3);
+ grid.Children.Add(c4);
+ }
+
+ private View CreateDemoContainer(View content, string description)
+ {
+ return new VerticalStackLayout
+ {
+ Spacing = 5,
+ Children =
+ {
+ new Label { Text = description, FontSize = 12, TextColor = Colors.Gray },
+ content
+ }
+ };
+ }
+}
diff --git a/samples/ShellDemo/Pages/HomePage.cs b/samples/ShellDemo/Pages/HomePage.cs
new file mode 100644
index 0000000..9a39e63
--- /dev/null
+++ b/samples/ShellDemo/Pages/HomePage.cs
@@ -0,0 +1,265 @@
+// HomePage - Welcome page for the demo
+
+using Microsoft.Maui.Controls;
+using Microsoft.Maui.Graphics;
+using Microsoft.Maui.Platform.Linux.Hosting;
+
+namespace ShellDemo;
+
+public class HomePage : ContentPage
+{
+ public HomePage()
+ {
+ Title = "Home";
+
+ Content = new ScrollView
+ {
+ Orientation = ScrollOrientation.Both, // Enable horizontal scrolling when window is too narrow
+ Content = new VerticalStackLayout
+ {
+ Padding = new Thickness(30),
+ Spacing = 20,
+ Children =
+ {
+ new Label
+ {
+ Text = "OpenMaui Linux",
+ FontSize = 32,
+ FontAttributes = FontAttributes.Bold,
+ HorizontalOptions = LayoutOptions.Center,
+ TextColor = Color.FromArgb("#2196F3")
+ },
+
+ new Label
+ {
+ Text = "Controls Demo",
+ FontSize = 20,
+ HorizontalOptions = LayoutOptions.Center,
+ TextColor = Colors.Gray
+ },
+
+ new BoxView
+ {
+ HeightRequest = 2,
+ Color = Color.FromArgb("#E0E0E0"),
+ Margin = new Thickness(0, 10)
+ },
+
+ new Label
+ {
+ Text = "Welcome to the comprehensive controls demonstration for OpenMaui Linux. " +
+ "This app showcases all the major UI controls available in the framework.",
+ FontSize = 14,
+ LineBreakMode = LineBreakMode.WordWrap,
+ HorizontalTextAlignment = TextAlignment.Center
+ },
+
+ CreateFeatureSection(),
+
+ new Label
+ {
+ Text = "Use the flyout menu (swipe from left or tap the hamburger icon) to navigate between different control demos.",
+ FontSize = 12,
+ TextColor = Colors.Gray,
+ LineBreakMode = LineBreakMode.WordWrap,
+ HorizontalTextAlignment = TextAlignment.Center,
+ Margin = new Thickness(0, 20, 0, 0)
+ },
+
+ CreateQuickLinksSection(),
+
+ CreateNavigationDemoSection()
+ }
+ }
+ };
+ }
+
+ private View CreateFeatureSection()
+ {
+ var grid = new Grid
+ {
+ ColumnDefinitions =
+ {
+ new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) },
+ new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }
+ },
+ RowDefinitions =
+ {
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = GridLength.Auto },
+ new RowDefinition { Height = GridLength.Auto }
+ },
+ ColumnSpacing = 15,
+ RowSpacing = 15,
+ Margin = new Thickness(0, 20)
+ };
+
+ var features = new[]
+ {
+ ("Buttons", "Various button styles and events"),
+ ("Text Input", "Entry, Editor, SearchBar"),
+ ("Selection", "CheckBox, Switch, Slider"),
+ ("Pickers", "Picker, DatePicker, TimePicker"),
+ ("Lists", "CollectionView with selection"),
+ ("Progress", "ProgressBar, ActivityIndicator")
+ };
+
+ for (int i = 0; i < features.Length; i++)
+ {
+ var (title, desc) = features[i];
+ var card = CreateFeatureCard(title, desc);
+ Grid.SetRow(card, i / 2);
+ Grid.SetColumn(card, i % 2);
+ grid.Children.Add(card);
+ }
+
+ return grid;
+ }
+
+ private Frame CreateFeatureCard(string title, string description)
+ {
+ return new Frame
+ {
+ CornerRadius = 8,
+ Padding = new Thickness(15),
+ BackgroundColor = Colors.White,
+ HasShadow = true,
+ Content = new VerticalStackLayout
+ {
+ Spacing = 5,
+ Children =
+ {
+ new Label
+ {
+ Text = title,
+ FontSize = 14,
+ FontAttributes = FontAttributes.Bold,
+ TextColor = Color.FromArgb("#2196F3")
+ },
+ new Label
+ {
+ Text = description,
+ FontSize = 11,
+ TextColor = Colors.Gray,
+ LineBreakMode = LineBreakMode.WordWrap
+ }
+ }
+ }
+ };
+ }
+
+ private View CreateQuickLinksSection()
+ {
+ var layout = new VerticalStackLayout
+ {
+ Spacing = 10,
+ Margin = new Thickness(0, 20, 0, 0)
+ };
+
+ layout.Children.Add(new Label
+ {
+ Text = "Quick Actions",
+ FontSize = 16,
+ FontAttributes = FontAttributes.Bold,
+ HorizontalOptions = LayoutOptions.Center
+ });
+
+ var buttonRow = new HorizontalStackLayout
+ {
+ Spacing = 10,
+ HorizontalOptions = LayoutOptions.Center
+ };
+
+ var buttonsBtn = new Button
+ {
+ Text = "Try Buttons",
+ BackgroundColor = Color.FromArgb("#2196F3"),
+ TextColor = Colors.White
+ };
+ buttonsBtn.Clicked += (s, e) => LinuxViewRenderer.NavigateToRoute("Buttons");
+
+ var listsBtn = new Button
+ {
+ Text = "Try Lists",
+ BackgroundColor = Color.FromArgb("#4CAF50"),
+ TextColor = Colors.White
+ };
+ listsBtn.Clicked += (s, e) => LinuxViewRenderer.NavigateToRoute("Lists");
+
+ buttonRow.Children.Add(buttonsBtn);
+ buttonRow.Children.Add(listsBtn);
+ layout.Children.Add(buttonRow);
+
+ return layout;
+ }
+
+ private View CreateNavigationDemoSection()
+ {
+ var frame = new Frame
+ {
+ CornerRadius = 8,
+ Padding = new Thickness(20),
+ BackgroundColor = Color.FromArgb("#F3E5F5"),
+ Margin = new Thickness(0, 20, 0, 0),
+ Content = new VerticalStackLayout
+ {
+ Spacing = 15,
+ Children =
+ {
+ new Label
+ {
+ Text = "Navigation Stack Demo",
+ FontSize = 18,
+ FontAttributes = FontAttributes.Bold,
+ TextColor = Color.FromArgb("#9C27B0"),
+ HorizontalOptions = LayoutOptions.Center
+ },
+
+ new Label
+ {
+ Text = "Demonstrate push/pop navigation using Shell.GoToAsync()",
+ FontSize = 12,
+ TextColor = Colors.Gray,
+ HorizontalTextAlignment = TextAlignment.Center
+ },
+
+ CreatePushButton("Push Detail Page", "detail"),
+
+ new Label
+ {
+ Text = "Click the button to push a new page onto the navigation stack. " +
+ "Use the back button or 'Go Back' to pop it off.",
+ FontSize = 11,
+ TextColor = Colors.Gray,
+ HorizontalTextAlignment = TextAlignment.Center,
+ LineBreakMode = LineBreakMode.WordWrap
+ }
+ }
+ }
+ };
+
+ return frame;
+ }
+
+ private Button CreatePushButton(string text, string route)
+ {
+ var btn = new Button
+ {
+ Text = text,
+ BackgroundColor = Color.FromArgb("#9C27B0"),
+ TextColor = Colors.White,
+ HorizontalOptions = LayoutOptions.Center,
+ Padding = new Thickness(30, 10)
+ };
+
+ btn.Clicked += (s, e) =>
+ {
+ Console.WriteLine($"[HomePage] Push button clicked, navigating to {route}");
+ // Use LinuxViewRenderer.PushPage for Skia-based navigation
+ var success = LinuxViewRenderer.PushPage(new DetailPage());
+ Console.WriteLine($"[HomePage] PushPage result: {success}");
+ };
+
+ return btn;
+ }
+}
diff --git a/samples/ShellDemo/Pages/ListsPage.cs b/samples/ShellDemo/Pages/ListsPage.cs
new file mode 100644
index 0000000..1d93a67
--- /dev/null
+++ b/samples/ShellDemo/Pages/ListsPage.cs
@@ -0,0 +1,249 @@
+// ListsPage - CollectionView and ListView Demo
+
+using Microsoft.Maui.Controls;
+using Microsoft.Maui.Graphics;
+
+namespace ShellDemo;
+
+public class ListsPage : ContentPage
+{
+ private readonly Label _eventLog;
+ private int _eventCount = 0;
+
+ public ListsPage()
+ {
+ Title = "Lists";
+
+ _eventLog = new Label
+ {
+ Text = "Events will appear here...",
+ FontSize = 11,
+ TextColor = Colors.Gray,
+ LineBreakMode = LineBreakMode.WordWrap
+ };
+
+ Content = new Grid
+ {
+ RowDefinitions =
+ {
+ new RowDefinition { Height = new GridLength(1, GridUnitType.Star) },
+ new RowDefinition { Height = new GridLength(120) }
+ },
+ Children =
+ {
+ CreateMainContent(),
+ CreateEventLogPanel()
+ }
+ };
+
+ Grid.SetRow((View)((Grid)Content).Children[0], 0);
+ Grid.SetRow((View)((Grid)Content).Children[1], 1);
+ }
+
+ private View CreateMainContent()
+ {
+ return new ScrollView
+ {
+ Content = new VerticalStackLayout
+ {
+ Padding = new Thickness(20),
+ Spacing = 20,
+ Children =
+ {
+ new Label { Text = "List Controls", FontSize = 24, FontAttributes = FontAttributes.Bold },
+
+ CreateSection("CollectionView - Fruits", CreateFruitsCollectionView()),
+ CreateSection("CollectionView - Colors", CreateColorsCollectionView()),
+ CreateSection("CollectionView - Contacts", CreateContactsCollectionView())
+ }
+ }
+ };
+ }
+
+ private View CreateFruitsCollectionView()
+ {
+ var layout = new VerticalStackLayout { Spacing = 10 };
+
+ var fruits = new List
+ {
+ "Apple", "Banana", "Cherry", "Date", "Elderberry",
+ "Fig", "Grape", "Honeydew", "Kiwi", "Lemon",
+ "Mango", "Nectarine", "Orange", "Papaya", "Quince"
+ };
+
+ var selectedLabel = new Label { Text = "Tap a fruit to select", TextColor = Colors.Gray };
+
+ var collectionView = new CollectionView
+ {
+ ItemsSource = fruits,
+ HeightRequest = 200,
+ SelectionMode = SelectionMode.Single,
+ BackgroundColor = Color.FromArgb("#FAFAFA")
+ };
+
+ collectionView.SelectionChanged += (s, e) =>
+ {
+ if (e.CurrentSelection.Count > 0)
+ {
+ var item = e.CurrentSelection[0]?.ToString();
+ selectedLabel.Text = $"Selected: {item}";
+ LogEvent($"Fruit selected: {item}");
+ }
+ };
+
+ layout.Children.Add(collectionView);
+ layout.Children.Add(selectedLabel);
+
+ return layout;
+ }
+
+ private View CreateColorsCollectionView()
+ {
+ var layout = new VerticalStackLayout { Spacing = 10 };
+
+ var colors = new List
+ {
+ new("Red", "#F44336"),
+ new("Pink", "#E91E63"),
+ new("Purple", "#9C27B0"),
+ new("Deep Purple", "#673AB7"),
+ new("Indigo", "#3F51B5"),
+ new("Blue", "#2196F3"),
+ new("Cyan", "#00BCD4"),
+ new("Teal", "#009688"),
+ new("Green", "#4CAF50"),
+ new("Light Green", "#8BC34A"),
+ new("Lime", "#CDDC39"),
+ new("Yellow", "#FFEB3B"),
+ new("Amber", "#FFC107"),
+ new("Orange", "#FF9800"),
+ new("Deep Orange", "#FF5722")
+ };
+
+ var collectionView = new CollectionView
+ {
+ ItemsSource = colors,
+ HeightRequest = 180,
+ SelectionMode = SelectionMode.Single,
+ BackgroundColor = Colors.White
+ };
+
+ collectionView.SelectionChanged += (s, e) =>
+ {
+ if (e.CurrentSelection.Count > 0 && e.CurrentSelection[0] is ColorItem item)
+ {
+ LogEvent($"Color selected: {item.Name} ({item.Hex})");
+ }
+ };
+
+ layout.Children.Add(collectionView);
+ layout.Children.Add(new Label { Text = "Scroll to see all colors", FontSize = 11, TextColor = Colors.Gray });
+
+ return layout;
+ }
+
+ private View CreateContactsCollectionView()
+ {
+ var layout = new VerticalStackLayout { Spacing = 10 };
+
+ var contacts = new List
+ {
+ new("Alice Johnson", "alice@example.com", "Engineering"),
+ new("Bob Smith", "bob@example.com", "Marketing"),
+ new("Carol Williams", "carol@example.com", "Design"),
+ new("David Brown", "david@example.com", "Sales"),
+ new("Eva Martinez", "eva@example.com", "Engineering"),
+ new("Frank Lee", "frank@example.com", "Support"),
+ new("Grace Kim", "grace@example.com", "HR"),
+ new("Henry Wilson", "henry@example.com", "Finance")
+ };
+
+ var collectionView = new CollectionView
+ {
+ ItemsSource = contacts,
+ HeightRequest = 200,
+ SelectionMode = SelectionMode.Single,
+ BackgroundColor = Colors.White
+ };
+
+ collectionView.SelectionChanged += (s, e) =>
+ {
+ if (e.CurrentSelection.Count > 0 && e.CurrentSelection[0] is ContactItem contact)
+ {
+ LogEvent($"Contact: {contact.Name} - {contact.Department}");
+ }
+ };
+
+ layout.Children.Add(collectionView);
+
+ // Action buttons
+ var buttonRow = new HorizontalStackLayout { Spacing = 10 };
+ var addBtn = new Button { Text = "Add Contact", BackgroundColor = Colors.Green, TextColor = Colors.White };
+ addBtn.Clicked += (s, e) => LogEvent("Add contact clicked");
+ var deleteBtn = new Button { Text = "Delete Selected", BackgroundColor = Colors.Red, TextColor = Colors.White };
+ deleteBtn.Clicked += (s, e) => LogEvent("Delete contact clicked");
+ buttonRow.Children.Add(addBtn);
+ buttonRow.Children.Add(deleteBtn);
+ layout.Children.Add(buttonRow);
+
+ return layout;
+ }
+
+ private Frame CreateSection(string title, View content)
+ {
+ return new Frame
+ {
+ CornerRadius = 8,
+ Padding = new Thickness(15),
+ BackgroundColor = Colors.White,
+ Content = new VerticalStackLayout
+ {
+ Spacing = 10,
+ Children =
+ {
+ new Label { Text = title, FontSize = 16, FontAttributes = FontAttributes.Bold },
+ content
+ }
+ }
+ };
+ }
+
+ private View CreateEventLogPanel()
+ {
+ return new Frame
+ {
+ BackgroundColor = Color.FromArgb("#F5F5F5"),
+ Padding = new Thickness(10),
+ CornerRadius = 0,
+ Content = new VerticalStackLayout
+ {
+ Children =
+ {
+ new Label { Text = "Event Log:", FontSize = 12, FontAttributes = FontAttributes.Bold },
+ new ScrollView
+ {
+ HeightRequest = 80,
+ Content = _eventLog
+ }
+ }
+ }
+ };
+ }
+
+ private void LogEvent(string message)
+ {
+ _eventCount++;
+ var timestamp = DateTime.Now.ToString("HH:mm:ss");
+ _eventLog.Text = $"[{timestamp}] {_eventCount}. {message}\n{_eventLog.Text}";
+ }
+}
+
+public record ColorItem(string Name, string Hex)
+{
+ public override string ToString() => Name;
+}
+
+public record ContactItem(string Name, string Email, string Department)
+{
+ public override string ToString() => $"{Name} ({Department})";
+}
diff --git a/samples/ShellDemo/Pages/PickersPage.cs b/samples/ShellDemo/Pages/PickersPage.cs
new file mode 100644
index 0000000..b5ae1d9
--- /dev/null
+++ b/samples/ShellDemo/Pages/PickersPage.cs
@@ -0,0 +1,261 @@
+// PickersPage - Picker, DatePicker, TimePicker Demo
+
+using Microsoft.Maui.Controls;
+using Microsoft.Maui.Graphics;
+
+namespace ShellDemo;
+
+public class PickersPage : ContentPage
+{
+ private readonly Label _eventLog;
+ private int _eventCount = 0;
+
+ public PickersPage()
+ {
+ Title = "Pickers";
+
+ _eventLog = new Label
+ {
+ Text = "Events will appear here...",
+ FontSize = 11,
+ TextColor = Colors.Gray,
+ LineBreakMode = LineBreakMode.WordWrap
+ };
+
+ Content = new Grid
+ {
+ RowDefinitions =
+ {
+ new RowDefinition { Height = new GridLength(1, GridUnitType.Star) },
+ new RowDefinition { Height = new GridLength(120) }
+ },
+ Children =
+ {
+ CreateMainContent(),
+ CreateEventLogPanel()
+ }
+ };
+
+ Grid.SetRow((View)((Grid)Content).Children[0], 0);
+ Grid.SetRow((View)((Grid)Content).Children[1], 1);
+ }
+
+ private View CreateMainContent()
+ {
+ return new ScrollView
+ {
+ Content = new VerticalStackLayout
+ {
+ Padding = new Thickness(20),
+ Spacing = 20,
+ Children =
+ {
+ new Label { Text = "Picker Controls", FontSize = 24, FontAttributes = FontAttributes.Bold },
+
+ CreateSection("Picker", CreatePickerDemo()),
+ CreateSection("DatePicker", CreateDatePickerDemo()),
+ CreateSection("TimePicker", CreateTimePickerDemo())
+ }
+ }
+ };
+ }
+
+ private View CreatePickerDemo()
+ {
+ var layout = new VerticalStackLayout { Spacing = 15 };
+
+ // Basic picker
+ var selectedLabel = new Label { Text = "Selected: (none)", TextColor = Colors.Gray };
+ var picker1 = new Picker { Title = "Select a fruit" };
+ picker1.Items.Add("Apple");
+ picker1.Items.Add("Banana");
+ picker1.Items.Add("Cherry");
+ picker1.Items.Add("Date");
+ picker1.Items.Add("Elderberry");
+ picker1.Items.Add("Fig");
+ picker1.Items.Add("Grape");
+ picker1.SelectedIndexChanged += (s, e) =>
+ {
+ if (picker1.SelectedIndex >= 0)
+ {
+ var item = picker1.Items[picker1.SelectedIndex];
+ selectedLabel.Text = $"Selected: {item}";
+ LogEvent($"Fruit selected: {item}");
+ }
+ };
+ layout.Children.Add(picker1);
+ layout.Children.Add(selectedLabel);
+
+ // Picker with default selection
+ layout.Children.Add(new Label { Text = "With Default Selection:", FontSize = 12, Margin = new Thickness(0, 10, 0, 0) });
+ var picker2 = new Picker { Title = "Select a color" };
+ picker2.Items.Add("Red");
+ picker2.Items.Add("Green");
+ picker2.Items.Add("Blue");
+ picker2.Items.Add("Yellow");
+ picker2.Items.Add("Purple");
+ picker2.SelectedIndex = 2; // Blue
+ picker2.SelectedIndexChanged += (s, e) =>
+ {
+ if (picker2.SelectedIndex >= 0)
+ LogEvent($"Color selected: {picker2.Items[picker2.SelectedIndex]}");
+ };
+ layout.Children.Add(picker2);
+
+ // Styled picker
+ layout.Children.Add(new Label { Text = "Styled Picker:", FontSize = 12, Margin = new Thickness(0, 10, 0, 0) });
+ var picker3 = new Picker
+ {
+ Title = "Select size",
+ TextColor = Colors.DarkBlue,
+ TitleColor = Colors.Gray
+ };
+ picker3.Items.Add("Small");
+ picker3.Items.Add("Medium");
+ picker3.Items.Add("Large");
+ picker3.Items.Add("Extra Large");
+ picker3.SelectedIndexChanged += (s, e) =>
+ {
+ if (picker3.SelectedIndex >= 0)
+ LogEvent($"Size selected: {picker3.Items[picker3.SelectedIndex]}");
+ };
+ layout.Children.Add(picker3);
+
+ return layout;
+ }
+
+ private View CreateDatePickerDemo()
+ {
+ var layout = new VerticalStackLayout { Spacing = 15 };
+
+ // Basic date picker
+ var dateLabel = new Label { Text = $"Selected: {DateTime.Today:d}" };
+ var datePicker1 = new DatePicker { Date = DateTime.Today };
+ datePicker1.DateSelected += (s, e) =>
+ {
+ dateLabel.Text = $"Selected: {e.NewDate:d}";
+ LogEvent($"Date selected: {e.NewDate:d}");
+ };
+ layout.Children.Add(datePicker1);
+ layout.Children.Add(dateLabel);
+
+ // Date picker with range
+ layout.Children.Add(new Label { Text = "With Date Range (this month only):", FontSize = 12, Margin = new Thickness(0, 10, 0, 0) });
+ var startOfMonth = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1);
+ var endOfMonth = startOfMonth.AddMonths(1).AddDays(-1);
+ var datePicker2 = new DatePicker
+ {
+ MinimumDate = startOfMonth,
+ MaximumDate = endOfMonth,
+ Date = DateTime.Today
+ };
+ datePicker2.DateSelected += (s, e) => LogEvent($"Date (limited): {e.NewDate:d}");
+ layout.Children.Add(datePicker2);
+
+ // Styled date picker
+ layout.Children.Add(new Label { Text = "Styled DatePicker:", FontSize = 12, Margin = new Thickness(0, 10, 0, 0) });
+ var datePicker3 = new DatePicker
+ {
+ Date = DateTime.Today.AddDays(7),
+ TextColor = Colors.DarkGreen
+ };
+ datePicker3.DateSelected += (s, e) => LogEvent($"Styled date: {e.NewDate:d}");
+ layout.Children.Add(datePicker3);
+
+ return layout;
+ }
+
+ private View CreateTimePickerDemo()
+ {
+ var layout = new VerticalStackLayout { Spacing = 15 };
+
+ // Basic time picker
+ var timeLabel = new Label { Text = $"Selected: {DateTime.Now:t}" };
+ var timePicker1 = new TimePicker { Time = DateTime.Now.TimeOfDay };
+ timePicker1.PropertyChanged += (s, e) =>
+ {
+ if (e.PropertyName == nameof(TimePicker.Time))
+ {
+ var time = timePicker1.Time;
+ timeLabel.Text = $"Selected: {time:hh\\:mm}";
+ LogEvent($"Time selected: {time:hh\\:mm}");
+ }
+ };
+ layout.Children.Add(timePicker1);
+ layout.Children.Add(timeLabel);
+
+ // Styled time picker
+ layout.Children.Add(new Label { Text = "Styled TimePicker:", FontSize = 12, Margin = new Thickness(0, 10, 0, 0) });
+ var timePicker2 = new TimePicker
+ {
+ Time = new TimeSpan(14, 30, 0),
+ TextColor = Colors.DarkBlue
+ };
+ timePicker2.PropertyChanged += (s, e) =>
+ {
+ if (e.PropertyName == nameof(TimePicker.Time))
+ LogEvent($"Styled time: {timePicker2.Time:hh\\:mm}");
+ };
+ layout.Children.Add(timePicker2);
+
+ // Morning alarm example
+ layout.Children.Add(new Label { Text = "Alarm Time:", FontSize = 12, Margin = new Thickness(0, 10, 0, 0) });
+ var alarmRow = new HorizontalStackLayout { Spacing = 10 };
+ var alarmPicker = new TimePicker { Time = new TimeSpan(7, 0, 0) };
+ var alarmBtn = new Button { Text = "Set Alarm", BackgroundColor = Colors.Orange, TextColor = Colors.White };
+ alarmBtn.Clicked += (s, e) => LogEvent($"Alarm set for {alarmPicker.Time:hh\\:mm}");
+ alarmRow.Children.Add(alarmPicker);
+ alarmRow.Children.Add(alarmBtn);
+ layout.Children.Add(alarmRow);
+
+ return layout;
+ }
+
+ private Frame CreateSection(string title, View content)
+ {
+ return new Frame
+ {
+ CornerRadius = 8,
+ Padding = new Thickness(15),
+ BackgroundColor = Colors.White,
+ Content = new VerticalStackLayout
+ {
+ Spacing = 10,
+ Children =
+ {
+ new Label { Text = title, FontSize = 16, FontAttributes = FontAttributes.Bold },
+ content
+ }
+ }
+ };
+ }
+
+ private View CreateEventLogPanel()
+ {
+ return new Frame
+ {
+ BackgroundColor = Color.FromArgb("#F5F5F5"),
+ Padding = new Thickness(10),
+ CornerRadius = 0,
+ Content = new VerticalStackLayout
+ {
+ Children =
+ {
+ new Label { Text = "Event Log:", FontSize = 12, FontAttributes = FontAttributes.Bold },
+ new ScrollView
+ {
+ HeightRequest = 80,
+ Content = _eventLog
+ }
+ }
+ }
+ };
+ }
+
+ private void LogEvent(string message)
+ {
+ _eventCount++;
+ var timestamp = DateTime.Now.ToString("HH:mm:ss");
+ _eventLog.Text = $"[{timestamp}] {_eventCount}. {message}\n{_eventLog.Text}";
+ }
+}
diff --git a/samples/ShellDemo/Pages/ProgressPage.cs b/samples/ShellDemo/Pages/ProgressPage.cs
new file mode 100644
index 0000000..87e4828
--- /dev/null
+++ b/samples/ShellDemo/Pages/ProgressPage.cs
@@ -0,0 +1,261 @@
+// ProgressPage - ProgressBar and ActivityIndicator Demo
+
+using Microsoft.Maui.Controls;
+using Microsoft.Maui.Graphics;
+
+namespace ShellDemo;
+
+public class ProgressPage : ContentPage
+{
+ private readonly Label _eventLog;
+ private int _eventCount = 0;
+ private ProgressBar? _animatedProgress;
+ private bool _isAnimating = false;
+
+ public ProgressPage()
+ {
+ Title = "Progress";
+
+ _eventLog = new Label
+ {
+ Text = "Events will appear here...",
+ FontSize = 11,
+ TextColor = Colors.Gray,
+ LineBreakMode = LineBreakMode.WordWrap
+ };
+
+ Content = new Grid
+ {
+ RowDefinitions =
+ {
+ new RowDefinition { Height = new GridLength(1, GridUnitType.Star) },
+ new RowDefinition { Height = new GridLength(120) }
+ },
+ Children =
+ {
+ CreateMainContent(),
+ CreateEventLogPanel()
+ }
+ };
+
+ Grid.SetRow((View)((Grid)Content).Children[0], 0);
+ Grid.SetRow((View)((Grid)Content).Children[1], 1);
+ }
+
+ private View CreateMainContent()
+ {
+ return new ScrollView
+ {
+ Content = new VerticalStackLayout
+ {
+ Padding = new Thickness(20),
+ Spacing = 20,
+ Children =
+ {
+ new Label { Text = "Progress Indicators", FontSize = 24, FontAttributes = FontAttributes.Bold },
+
+ CreateSection("ProgressBar", CreateProgressBarDemo()),
+ CreateSection("ActivityIndicator", CreateActivityIndicatorDemo()),
+ CreateSection("Interactive Demo", CreateInteractiveDemo())
+ }
+ }
+ };
+ }
+
+ private View CreateProgressBarDemo()
+ {
+ var layout = new VerticalStackLayout { Spacing = 15 };
+
+ // Various progress values
+ var values = new[] { 0.0, 0.25, 0.5, 0.75, 1.0 };
+ foreach (var value in values)
+ {
+ var row = new HorizontalStackLayout { Spacing = 10 };
+ var progress = new ProgressBar { Progress = value, WidthRequest = 200 };
+ var label = new Label { Text = $"{value * 100:0}%", VerticalOptions = LayoutOptions.Center, WidthRequest = 50 };
+ row.Children.Add(progress);
+ row.Children.Add(label);
+ layout.Children.Add(row);
+ }
+
+ // Colored progress bars
+ layout.Children.Add(new Label { Text = "Colored Progress Bars:", FontSize = 12, Margin = new Thickness(0, 10, 0, 0) });
+
+ var colors = new[] { Colors.Red, Colors.Green, Colors.Blue, Colors.Orange, Colors.Purple };
+ foreach (var color in colors)
+ {
+ var progress = new ProgressBar { Progress = 0.7, ProgressColor = color };
+ layout.Children.Add(progress);
+ }
+
+ return layout;
+ }
+
+ private View CreateActivityIndicatorDemo()
+ {
+ var layout = new VerticalStackLayout { Spacing = 15 };
+
+ // Running indicator
+ var runningRow = new HorizontalStackLayout { Spacing = 15 };
+ var runningIndicator = new ActivityIndicator { IsRunning = true };
+ runningRow.Children.Add(runningIndicator);
+ runningRow.Children.Add(new Label { Text = "Loading...", VerticalOptions = LayoutOptions.Center });
+ layout.Children.Add(runningRow);
+
+ // Toggle indicator
+ var toggleRow = new HorizontalStackLayout { Spacing = 15 };
+ var toggleIndicator = new ActivityIndicator { IsRunning = false };
+ var toggleBtn = new Button { Text = "Start/Stop" };
+ toggleBtn.Clicked += (s, e) =>
+ {
+ toggleIndicator.IsRunning = !toggleIndicator.IsRunning;
+ LogEvent($"ActivityIndicator: {(toggleIndicator.IsRunning ? "Started" : "Stopped")}");
+ };
+ toggleRow.Children.Add(toggleIndicator);
+ toggleRow.Children.Add(toggleBtn);
+ layout.Children.Add(toggleRow);
+
+ // Colored indicators
+ layout.Children.Add(new Label { Text = "Colored Indicators:", FontSize = 12, Margin = new Thickness(0, 10, 0, 0) });
+ var colorRow = new HorizontalStackLayout { Spacing = 20 };
+ var indicatorColors = new[] { Colors.Red, Colors.Green, Colors.Blue, Colors.Orange };
+ foreach (var color in indicatorColors)
+ {
+ var indicator = new ActivityIndicator { IsRunning = true, Color = color };
+ colorRow.Children.Add(indicator);
+ }
+ layout.Children.Add(colorRow);
+
+ return layout;
+ }
+
+ private View CreateInteractiveDemo()
+ {
+ var layout = new VerticalStackLayout { Spacing = 15 };
+
+ // Slider-controlled progress
+ var progressLabel = new Label { Text = "Progress: 50%" };
+ _animatedProgress = new ProgressBar { Progress = 0.5 };
+
+ var slider = new Slider { Minimum = 0, Maximum = 100, Value = 50 };
+ slider.ValueChanged += (s, e) =>
+ {
+ var value = e.NewValue / 100.0;
+ _animatedProgress.Progress = value;
+ progressLabel.Text = $"Progress: {e.NewValue:0}%";
+ };
+
+ layout.Children.Add(_animatedProgress);
+ layout.Children.Add(slider);
+ layout.Children.Add(progressLabel);
+
+ // Animated progress buttons
+ var buttonRow = new HorizontalStackLayout { Spacing = 10, Margin = new Thickness(0, 10, 0, 0) };
+
+ var resetBtn = new Button { Text = "Reset", BackgroundColor = Colors.Gray, TextColor = Colors.White };
+ resetBtn.Clicked += async (s, e) =>
+ {
+ _animatedProgress.Progress = 0;
+ slider.Value = 0;
+ LogEvent("Progress reset to 0%");
+ };
+
+ var animateBtn = new Button { Text = "Animate to 100%", BackgroundColor = Colors.Blue, TextColor = Colors.White };
+ animateBtn.Clicked += async (s, e) =>
+ {
+ if (_isAnimating) return;
+ _isAnimating = true;
+ LogEvent("Animation started");
+
+ for (int i = (int)(slider.Value); i <= 100; i += 5)
+ {
+ _animatedProgress.Progress = i / 100.0;
+ slider.Value = i;
+ await Task.Delay(100);
+ }
+
+ _isAnimating = false;
+ LogEvent("Animation completed");
+ };
+
+ var simulateBtn = new Button { Text = "Simulate Download", BackgroundColor = Colors.Green, TextColor = Colors.White };
+ simulateBtn.Clicked += async (s, e) =>
+ {
+ if (_isAnimating) return;
+ _isAnimating = true;
+ LogEvent("Download simulation started");
+
+ _animatedProgress.Progress = 0;
+ slider.Value = 0;
+
+ var random = new Random();
+ double progress = 0;
+ while (progress < 1.0)
+ {
+ progress += random.NextDouble() * 0.1;
+ if (progress > 1.0) progress = 1.0;
+ _animatedProgress.Progress = progress;
+ slider.Value = progress * 100;
+ await Task.Delay(200 + random.Next(300));
+ }
+
+ _isAnimating = false;
+ LogEvent("Download simulation completed");
+ };
+
+ buttonRow.Children.Add(resetBtn);
+ buttonRow.Children.Add(animateBtn);
+ buttonRow.Children.Add(simulateBtn);
+ layout.Children.Add(buttonRow);
+
+ return layout;
+ }
+
+ private Frame CreateSection(string title, View content)
+ {
+ return new Frame
+ {
+ CornerRadius = 8,
+ Padding = new Thickness(15),
+ BackgroundColor = Colors.White,
+ Content = new VerticalStackLayout
+ {
+ Spacing = 10,
+ Children =
+ {
+ new Label { Text = title, FontSize = 16, FontAttributes = FontAttributes.Bold },
+ content
+ }
+ }
+ };
+ }
+
+ private View CreateEventLogPanel()
+ {
+ return new Frame
+ {
+ BackgroundColor = Color.FromArgb("#F5F5F5"),
+ Padding = new Thickness(10),
+ CornerRadius = 0,
+ Content = new VerticalStackLayout
+ {
+ Children =
+ {
+ new Label { Text = "Event Log:", FontSize = 12, FontAttributes = FontAttributes.Bold },
+ new ScrollView
+ {
+ HeightRequest = 80,
+ Content = _eventLog
+ }
+ }
+ }
+ };
+ }
+
+ private void LogEvent(string message)
+ {
+ _eventCount++;
+ var timestamp = DateTime.Now.ToString("HH:mm:ss");
+ _eventLog.Text = $"[{timestamp}] {_eventCount}. {message}\n{_eventLog.Text}";
+ }
+}
diff --git a/samples/ShellDemo/Pages/SelectionPage.cs b/samples/ShellDemo/Pages/SelectionPage.cs
new file mode 100644
index 0000000..e247af6
--- /dev/null
+++ b/samples/ShellDemo/Pages/SelectionPage.cs
@@ -0,0 +1,239 @@
+// SelectionPage - CheckBox, Switch, Slider Demo
+
+using Microsoft.Maui.Controls;
+using Microsoft.Maui.Graphics;
+
+namespace ShellDemo;
+
+public class SelectionPage : ContentPage
+{
+ private readonly Label _eventLog;
+ private int _eventCount = 0;
+
+ public SelectionPage()
+ {
+ Title = "Selection Controls";
+
+ _eventLog = new Label
+ {
+ Text = "Events will appear here...",
+ FontSize = 11,
+ TextColor = Colors.Gray,
+ LineBreakMode = LineBreakMode.WordWrap
+ };
+
+ Content = new Grid
+ {
+ RowDefinitions =
+ {
+ new RowDefinition { Height = new GridLength(1, GridUnitType.Star) },
+ new RowDefinition { Height = new GridLength(120) }
+ },
+ Children =
+ {
+ CreateMainContent(),
+ CreateEventLogPanel()
+ }
+ };
+
+ Grid.SetRow((View)((Grid)Content).Children[0], 0);
+ Grid.SetRow((View)((Grid)Content).Children[1], 1);
+ }
+
+ private View CreateMainContent()
+ {
+ return new ScrollView
+ {
+ Content = new VerticalStackLayout
+ {
+ Padding = new Thickness(20),
+ Spacing = 20,
+ Children =
+ {
+ new Label { Text = "Selection Controls", FontSize = 24, FontAttributes = FontAttributes.Bold },
+
+ CreateSection("CheckBox", CreateCheckBoxDemo()),
+ CreateSection("Switch", CreateSwitchDemo()),
+ CreateSection("Slider", CreateSliderDemo())
+ }
+ }
+ };
+ }
+
+ private View CreateCheckBoxDemo()
+ {
+ var layout = new VerticalStackLayout { Spacing = 15 };
+
+ // Basic checkboxes
+ var basicRow = new HorizontalStackLayout { Spacing = 20 };
+
+ var cb1 = new CheckBox { IsChecked = false };
+ cb1.CheckedChanged += (s, e) => LogEvent($"Checkbox 1: {(e.Value ? "Checked" : "Unchecked")}");
+ basicRow.Children.Add(cb1);
+ basicRow.Children.Add(new Label { Text = "Option 1", VerticalOptions = LayoutOptions.Center });
+
+ var cb2 = new CheckBox { IsChecked = true };
+ cb2.CheckedChanged += (s, e) => LogEvent($"Checkbox 2: {(e.Value ? "Checked" : "Unchecked")}");
+ basicRow.Children.Add(cb2);
+ basicRow.Children.Add(new Label { Text = "Option 2 (default checked)", VerticalOptions = LayoutOptions.Center });
+
+ layout.Children.Add(basicRow);
+
+ // Colored checkboxes
+ var colorRow = new HorizontalStackLayout { Spacing = 20 };
+ var colors = new[] { Colors.Red, Colors.Green, Colors.Blue, Colors.Purple };
+ foreach (var color in colors)
+ {
+ var cb = new CheckBox { Color = color, IsChecked = true };
+ cb.CheckedChanged += (s, e) => LogEvent($"{color} checkbox: {(e.Value ? "Checked" : "Unchecked")}");
+ colorRow.Children.Add(cb);
+ }
+ layout.Children.Add(new Label { Text = "Colored Checkboxes:", FontSize = 12 });
+ layout.Children.Add(colorRow);
+
+ // Disabled checkbox
+ var disabledRow = new HorizontalStackLayout { Spacing = 10 };
+ var disabledCb = new CheckBox { IsChecked = true, IsEnabled = false };
+ disabledRow.Children.Add(disabledCb);
+ disabledRow.Children.Add(new Label { Text = "Disabled (checked)", VerticalOptions = LayoutOptions.Center, TextColor = Colors.Gray });
+ layout.Children.Add(disabledRow);
+
+ return layout;
+ }
+
+ private View CreateSwitchDemo()
+ {
+ var layout = new VerticalStackLayout { Spacing = 15 };
+
+ // Basic switch
+ var basicRow = new HorizontalStackLayout { Spacing = 15 };
+ var statusLabel = new Label { Text = "Off", VerticalOptions = LayoutOptions.Center, WidthRequest = 50 };
+ var sw1 = new Switch { IsToggled = false };
+ sw1.Toggled += (s, e) =>
+ {
+ statusLabel.Text = e.Value ? "On" : "Off";
+ LogEvent($"Switch toggled: {(e.Value ? "ON" : "OFF")}");
+ };
+ basicRow.Children.Add(sw1);
+ basicRow.Children.Add(statusLabel);
+ layout.Children.Add(basicRow);
+
+ // Colored switches
+ var colorRow = new HorizontalStackLayout { Spacing = 20 };
+ var switchColors = new[] { Colors.Green, Colors.Orange, Colors.Purple };
+ foreach (var color in switchColors)
+ {
+ var sw = new Switch { IsToggled = true, OnColor = color };
+ sw.Toggled += (s, e) => LogEvent($"{color} switch: {(e.Value ? "ON" : "OFF")}");
+ colorRow.Children.Add(sw);
+ }
+ layout.Children.Add(new Label { Text = "Colored Switches:", FontSize = 12 });
+ layout.Children.Add(colorRow);
+
+ // Disabled switch
+ var disabledRow = new HorizontalStackLayout { Spacing = 10 };
+ var disabledSw = new Switch { IsToggled = true, IsEnabled = false };
+ disabledRow.Children.Add(disabledSw);
+ disabledRow.Children.Add(new Label { Text = "Disabled (on)", VerticalOptions = LayoutOptions.Center, TextColor = Colors.Gray });
+ layout.Children.Add(disabledRow);
+
+ return layout;
+ }
+
+ private View CreateSliderDemo()
+ {
+ var layout = new VerticalStackLayout { Spacing = 15 };
+
+ // Basic slider
+ var valueLabel = new Label { Text = "Value: 50" };
+ var slider1 = new Slider { Minimum = 0, Maximum = 100, Value = 50 };
+ slider1.ValueChanged += (s, e) =>
+ {
+ valueLabel.Text = $"Value: {(int)e.NewValue}";
+ LogEvent($"Slider value: {(int)e.NewValue}");
+ };
+ layout.Children.Add(slider1);
+ layout.Children.Add(valueLabel);
+
+ // Slider with custom range
+ layout.Children.Add(new Label { Text = "Temperature (0-40°C):", FontSize = 12, Margin = new Thickness(0, 10, 0, 0) });
+ var tempLabel = new Label { Text = "20°C" };
+ var tempSlider = new Slider { Minimum = 0, Maximum = 40, Value = 20 };
+ tempSlider.ValueChanged += (s, e) =>
+ {
+ tempLabel.Text = $"{(int)e.NewValue}°C";
+ LogEvent($"Temperature: {(int)e.NewValue}°C");
+ };
+ layout.Children.Add(tempSlider);
+ layout.Children.Add(tempLabel);
+
+ // Colored slider
+ layout.Children.Add(new Label { Text = "Colored Slider:", FontSize = 12, Margin = new Thickness(0, 10, 0, 0) });
+ var colorSlider = new Slider
+ {
+ Minimum = 0,
+ Maximum = 100,
+ Value = 75,
+ MinimumTrackColor = Colors.Green,
+ MaximumTrackColor = Colors.LightGray,
+ ThumbColor = Colors.DarkGreen
+ };
+ colorSlider.ValueChanged += (s, e) => LogEvent($"Colored slider: {(int)e.NewValue}");
+ layout.Children.Add(colorSlider);
+
+ // Disabled slider
+ layout.Children.Add(new Label { Text = "Disabled Slider:", FontSize = 12, Margin = new Thickness(0, 10, 0, 0) });
+ var disabledSlider = new Slider { Minimum = 0, Maximum = 100, Value = 30, IsEnabled = false };
+ layout.Children.Add(disabledSlider);
+
+ return layout;
+ }
+
+ private Frame CreateSection(string title, View content)
+ {
+ return new Frame
+ {
+ CornerRadius = 8,
+ Padding = new Thickness(15),
+ BackgroundColor = Colors.White,
+ Content = new VerticalStackLayout
+ {
+ Spacing = 10,
+ Children =
+ {
+ new Label { Text = title, FontSize = 16, FontAttributes = FontAttributes.Bold },
+ content
+ }
+ }
+ };
+ }
+
+ private View CreateEventLogPanel()
+ {
+ return new Frame
+ {
+ BackgroundColor = Color.FromArgb("#F5F5F5"),
+ Padding = new Thickness(10),
+ CornerRadius = 0,
+ Content = new VerticalStackLayout
+ {
+ Children =
+ {
+ new Label { Text = "Event Log:", FontSize = 12, FontAttributes = FontAttributes.Bold },
+ new ScrollView
+ {
+ HeightRequest = 80,
+ Content = _eventLog
+ }
+ }
+ }
+ };
+ }
+
+ private void LogEvent(string message)
+ {
+ _eventCount++;
+ var timestamp = DateTime.Now.ToString("HH:mm:ss");
+ _eventLog.Text = $"[{timestamp}] {_eventCount}. {message}\n{_eventLog.Text}";
+ }
+}
diff --git a/samples/ShellDemo/Pages/TextInputPage.cs b/samples/ShellDemo/Pages/TextInputPage.cs
new file mode 100644
index 0000000..95c4e28
--- /dev/null
+++ b/samples/ShellDemo/Pages/TextInputPage.cs
@@ -0,0 +1,166 @@
+// TextInputPage - Demonstrates text input controls
+
+using Microsoft.Maui.Controls;
+using Microsoft.Maui.Graphics;
+
+namespace ShellDemo;
+
+public class TextInputPage : ContentPage
+{
+ private Label _entryOutput;
+ private Label _searchOutput;
+ private Label _editorOutput;
+
+ public TextInputPage()
+ {
+ Title = "Text Input";
+
+ _entryOutput = new Label { TextColor = Colors.Gray, FontSize = 12 };
+ _searchOutput = new Label { TextColor = Colors.Gray, FontSize = 12 };
+ _editorOutput = new Label { TextColor = Colors.Gray, FontSize = 12 };
+
+ Content = new ScrollView
+ {
+ Content = new VerticalStackLayout
+ {
+ Padding = new Thickness(20),
+ Spacing = 15,
+ Children =
+ {
+ new Label
+ {
+ Text = "Text Input Controls",
+ FontSize = 24,
+ FontAttributes = FontAttributes.Bold
+ },
+ new Label
+ {
+ Text = "Click on any field and start typing. All keyboard input is handled by the framework.",
+ FontSize = 14,
+ TextColor = Colors.Gray
+ },
+
+ // Entry Section
+ new BoxView { HeightRequest = 1, Color = Colors.LightGray },
+ new Label { Text = "Entry (Single Line)", FontSize = 18, FontAttributes = FontAttributes.Bold },
+ CreateEntry("Enter your name...", e => _entryOutput.Text = $"You typed: {e.Text}"),
+ _entryOutput,
+
+ CreateEntry("Enter your email...", null, Keyboard.Email),
+ new Label { Text = "Email keyboard type", FontSize = 12, TextColor = Colors.Gray },
+
+ CreatePasswordEntry("Enter password..."),
+ new Label { Text = "Password field (text hidden)", FontSize = 12, TextColor = Colors.Gray },
+
+ // SearchBar Section
+ new BoxView { HeightRequest = 1, Color = Colors.LightGray },
+ new Label { Text = "SearchBar", FontSize = 18, FontAttributes = FontAttributes.Bold },
+ CreateSearchBar(),
+ _searchOutput,
+
+ // Editor Section
+ new BoxView { HeightRequest = 1, Color = Colors.LightGray },
+ new Label { Text = "Editor (Multi-line)", FontSize = 18, FontAttributes = FontAttributes.Bold },
+ CreateEditor(),
+ _editorOutput,
+
+ // Instructions
+ new BoxView { HeightRequest = 1, Color = Colors.LightGray },
+ new Frame
+ {
+ BackgroundColor = Color.FromArgb("#E3F2FD"),
+ CornerRadius = 8,
+ Padding = new Thickness(15),
+ Content = new VerticalStackLayout
+ {
+ Spacing = 5,
+ Children =
+ {
+ new Label
+ {
+ Text = "Keyboard Shortcuts",
+ FontAttributes = FontAttributes.Bold
+ },
+ new Label { Text = "Ctrl+A: Select all" },
+ new Label { Text = "Ctrl+C: Copy" },
+ new Label { Text = "Ctrl+V: Paste" },
+ new Label { Text = "Ctrl+X: Cut" },
+ new Label { Text = "Home/End: Move to start/end" },
+ new Label { Text = "Shift+Arrow: Select text" }
+ }
+ }
+ }
+ }
+ }
+ };
+ }
+
+ private Entry CreateEntry(string placeholder, Action? onTextChanged, Keyboard? keyboard = null)
+ {
+ var entry = new Entry
+ {
+ Placeholder = placeholder,
+ FontSize = 14
+ };
+
+ if (keyboard != null)
+ {
+ entry.Keyboard = keyboard;
+ }
+
+ if (onTextChanged != null)
+ {
+ entry.TextChanged += (s, e) => onTextChanged(entry);
+ }
+
+ return entry;
+ }
+
+ private Entry CreatePasswordEntry(string placeholder)
+ {
+ return new Entry
+ {
+ Placeholder = placeholder,
+ FontSize = 14,
+ IsPassword = true
+ };
+ }
+
+ private SearchBar CreateSearchBar()
+ {
+ var searchBar = new SearchBar
+ {
+ Placeholder = "Search for items..."
+ };
+
+ searchBar.TextChanged += (s, e) =>
+ {
+ _searchOutput.Text = $"Searching: {e.NewTextValue}";
+ };
+
+ searchBar.SearchButtonPressed += (s, e) =>
+ {
+ _searchOutput.Text = $"Search submitted: {searchBar.Text}";
+ };
+
+ return searchBar;
+ }
+
+ private Editor CreateEditor()
+ {
+ var editor = new Editor
+ {
+ Placeholder = "Enter multiple lines of text here...\nPress Enter to create new lines.",
+ HeightRequest = 120,
+ FontSize = 14
+ };
+
+ editor.TextChanged += (s, e) =>
+ {
+ var lineCount = string.IsNullOrEmpty(e.NewTextValue) ? 0 : e.NewTextValue.Split('\n').Length;
+ _editorOutput.Text = $"Lines: {lineCount}, Characters: {e.NewTextValue?.Length ?? 0}";
+ };
+
+ return editor;
+ }
+}
diff --git a/samples/ShellDemo/Platforms/Linux/Program.cs b/samples/ShellDemo/Platforms/Linux/Program.cs
new file mode 100644
index 0000000..4330c0f
--- /dev/null
+++ b/samples/ShellDemo/Platforms/Linux/Program.cs
@@ -0,0 +1,19 @@
+// Platforms/Linux/Program.cs - Linux platform entry point
+// Same pattern as Android's MainActivity or iOS's AppDelegate
+
+using Microsoft.Maui.Platform.Linux;
+using Microsoft.Maui.Platform.Linux.Hosting;
+
+namespace ShellDemo;
+
+class Program
+{
+ static void Main(string[] args)
+ {
+ // Create the shared MAUI app
+ var app = MauiProgram.CreateMauiApp();
+
+ // Run on Linux platform
+ LinuxApplication.Run(app, args);
+ }
+}
diff --git a/samples/ShellDemo/README.md b/samples/ShellDemo/README.md
new file mode 100644
index 0000000..b734932
--- /dev/null
+++ b/samples/ShellDemo/README.md
@@ -0,0 +1,157 @@
+# ShellDemo Sample
+
+A comprehensive control showcase application demonstrating all OpenMaui Linux controls with Shell navigation and flyout menu.
+
+## Features
+
+- **Shell Navigation** - Flyout menu with multiple pages
+- **Route-Based Navigation** - Push navigation with registered routes
+- **All Core Controls** - Button, Entry, Editor, CheckBox, Switch, Slider, Picker, etc.
+- **CollectionView** - Lists with selection and data binding
+- **Progress Indicators** - ProgressBar and ActivityIndicator with animations
+- **Grid Layouts** - Complex multi-column/row layouts
+- **Event Logging** - Real-time event feedback panel
+
+## Pages
+
+| Page | Controls Demonstrated |
+|------|----------------------|
+| **Home** | Welcome screen, navigation overview |
+| **Buttons** | Button styles, colors, states, click/press/release events |
+| **Text Input** | Entry, Editor, SearchBar, password fields, keyboard types |
+| **Selection** | CheckBox, Switch, Slider with colors and states |
+| **Pickers** | Picker, DatePicker, TimePicker with styling |
+| **Lists** | CollectionView with selection, custom items |
+| **Progress** | ProgressBar, ActivityIndicator, animated demos |
+| **Grids** | Grid layouts with row/column definitions |
+| **About** | App information |
+
+## Architecture
+
+```
+ShellDemo/
+├── App.cs # AppShell definition with flyout
+├── Program.cs # Linux platform bootstrap
+├── MauiProgram.cs # MAUI app builder
+└── Pages/
+ ├── HomePage.cs # Welcome page
+ ├── ButtonsPage.cs # Button demonstrations
+ ├── TextInputPage.cs # Entry, Editor, SearchBar
+ ├── SelectionPage.cs # CheckBox, Switch, Slider
+ ├── PickersPage.cs # Picker, DatePicker, TimePicker
+ ├── ListsPage.cs # CollectionView demos
+ ├── ProgressPage.cs # ProgressBar, ActivityIndicator
+ ├── GridsPage.cs # Grid layout demos
+ ├── DetailPage.cs # Push navigation target
+ └── AboutPage.cs # About information
+```
+
+## Shell Configuration
+
+```csharp
+public class AppShell : Shell
+{
+ public AppShell()
+ {
+ FlyoutBehavior = FlyoutBehavior.Flyout;
+ Title = "OpenMaui Controls Demo";
+
+ // Register routes for push navigation
+ Routing.RegisterRoute("detail", typeof(DetailPage));
+
+ // Add flyout items
+ Items.Add(CreateFlyoutItem("Home", typeof(HomePage)));
+ Items.Add(CreateFlyoutItem("Buttons", typeof(ButtonsPage)));
+ // ...more items
+ }
+}
+```
+
+## Control Demonstrations
+
+### Buttons Page
+- Default, styled, and transparent buttons
+- Color variations (Primary, Success, Warning, Danger)
+- Enabled/disabled state toggling
+- Wide, tall, and round button shapes
+- Pressed, clicked, released event handling
+
+### Text Input Page
+- Entry with placeholder and text change events
+- Password entry with hidden text
+- Email keyboard type
+- SearchBar with search button
+- Multi-line Editor
+- Keyboard shortcuts guide
+
+### Selection Page
+- CheckBox with colors and disabled state
+- Switch with OnColor customization
+- Slider with min/max range and track colors
+
+### Pickers Page
+- Picker with items and selection events
+- DatePicker with date range limits
+- TimePicker with time selection
+- Styled pickers with custom colors
+
+### Lists Page
+- CollectionView with string items
+- CollectionView with custom data types (ColorItem, ContactItem)
+- Selection handling and event feedback
+
+### Progress Page
+- ProgressBar at various percentages
+- Colored progress bars
+- ActivityIndicator running/stopped states
+- Colored activity indicators
+- Interactive slider-controlled progress
+- Animated progress simulation
+
+## Building and Running
+
+```bash
+# From the maui-linux-push directory
+cd samples/ShellDemo
+dotnet publish -c Release -r linux-arm64
+
+# Run on Linux
+./bin/Release/net9.0/linux-arm64/publish/ShellDemo
+```
+
+## Event Logging
+
+Each page features an event log panel that displays control interactions in real-time:
+
+```
+[14:32:15] 3. Button clicked: Primary
+[14:32:12] 2. Slider value: 75
+[14:32:08] 1. CheckBox: Checked
+```
+
+## Controls Reference
+
+| Control | Properties Demonstrated |
+|---------|------------------------|
+| Button | Text, BackgroundColor, TextColor, CornerRadius, IsEnabled, WidthRequest, HeightRequest |
+| Entry | Placeholder, Text, IsPassword, Keyboard, FontSize |
+| Editor | Placeholder, Text, HeightRequest |
+| SearchBar | Placeholder, Text, SearchButtonPressed |
+| CheckBox | IsChecked, Color, IsEnabled |
+| Switch | IsToggled, OnColor, IsEnabled |
+| Slider | Minimum, Maximum, Value, MinimumTrackColor, MaximumTrackColor, ThumbColor |
+| Picker | Title, Items, SelectedIndex, TextColor, TitleColor |
+| DatePicker | Date, MinimumDate, MaximumDate, TextColor |
+| TimePicker | Time, TextColor |
+| CollectionView | ItemsSource, SelectionMode, SelectionChanged, HeightRequest |
+| ProgressBar | Progress, ProgressColor |
+| ActivityIndicator | IsRunning, Color |
+| Label | Text, FontSize, FontAttributes, TextColor |
+| Frame | CornerRadius, Padding, BackgroundColor |
+| Grid | RowDefinitions, ColumnDefinitions, RowSpacing, ColumnSpacing |
+| StackLayout | Spacing, Padding, Orientation |
+| ScrollView | Content scrolling |
+
+## License
+
+MIT License - See repository root for details.
diff --git a/samples/LinuxDemo/LinuxDemo.csproj b/samples/ShellDemo/ShellDemo.csproj
similarity index 80%
rename from samples/LinuxDemo/LinuxDemo.csproj
rename to samples/ShellDemo/ShellDemo.csproj
index a11812d..1c0d871 100644
--- a/samples/LinuxDemo/LinuxDemo.csproj
+++ b/samples/ShellDemo/ShellDemo.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/samples/TodoApp/App.cs b/samples/TodoApp/App.cs
new file mode 100644
index 0000000..7ffbb8d
--- /dev/null
+++ b/samples/TodoApp/App.cs
@@ -0,0 +1,21 @@
+// TodoApp - Main Application with NavigationPage
+
+using Microsoft.Maui.Controls;
+
+namespace TodoApp;
+
+public class App : Application
+{
+ public static NavigationPage? NavigationPage { get; private set; }
+
+ public App()
+ {
+ NavigationPage = new NavigationPage(new TodoListPage())
+ {
+ Title = "OpenMaui Todo App",
+ BarBackgroundColor = Color.FromArgb("#2196F3"),
+ BarTextColor = Colors.White
+ };
+ MainPage = NavigationPage;
+ }
+}
diff --git a/samples/TodoApp/MauiProgram.cs b/samples/TodoApp/MauiProgram.cs
new file mode 100644
index 0000000..94b7677
--- /dev/null
+++ b/samples/TodoApp/MauiProgram.cs
@@ -0,0 +1,22 @@
+// MauiProgram.cs - MAUI app configuration
+
+using Microsoft.Maui.Hosting;
+using Microsoft.Maui.Platform.Linux.Hosting;
+
+namespace TodoApp;
+
+public static class MauiProgram
+{
+ public static MauiApp CreateMauiApp()
+ {
+ var builder = MauiApp.CreateBuilder();
+
+ // Configure the app
+ builder.UseMauiApp();
+
+ // Add Linux platform support with all handlers
+ builder.UseLinux();
+
+ return builder.Build();
+ }
+}
diff --git a/samples/TodoApp/NewTodoPage.xaml b/samples/TodoApp/NewTodoPage.xaml
new file mode 100644
index 0000000..7f4f1a4
--- /dev/null
+++ b/samples/TodoApp/NewTodoPage.xaml
@@ -0,0 +1,79 @@
+
+
+
+
+ #5C6BC0
+ #26A69A
+ #212121
+ #757575
+ #FFFFFF
+ #E8EAF6
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/TodoApp/NewTodoPage.xaml.cs b/samples/TodoApp/NewTodoPage.xaml.cs
new file mode 100644
index 0000000..ed1c90b
--- /dev/null
+++ b/samples/TodoApp/NewTodoPage.xaml.cs
@@ -0,0 +1,31 @@
+// NewTodoPage - Create a new todo item
+
+using Microsoft.Maui.Controls;
+using Microsoft.Maui.Graphics;
+
+namespace TodoApp;
+
+public partial class NewTodoPage : ContentPage
+{
+ private readonly TodoService _service = TodoService.Instance;
+
+ public NewTodoPage()
+ {
+ InitializeComponent();
+ }
+
+ private async void OnSaveClicked(object? sender, EventArgs e)
+ {
+ var title = TitleEntry.Text?.Trim();
+
+ if (string.IsNullOrEmpty(title))
+ {
+ TitleEntry.Placeholder = "Title is required!";
+ TitleEntry.PlaceholderColor = Colors.Red;
+ return;
+ }
+
+ _service.AddTodo(title, NotesEditor.Text ?? "");
+ await Navigation.PopAsync();
+ }
+}
diff --git a/samples/TodoApp/Program.cs b/samples/TodoApp/Program.cs
new file mode 100644
index 0000000..1602090
--- /dev/null
+++ b/samples/TodoApp/Program.cs
@@ -0,0 +1,67 @@
+// Program.cs - Linux platform entry point
+
+using Microsoft.Maui.Platform.Linux;
+
+namespace TodoApp;
+
+class Program
+{
+ static void Main(string[] args)
+ {
+ // Redirect console output to a log file for debugging
+ var logPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "todoapp.log");
+ using var logWriter = new StreamWriter(logPath, append: false) { AutoFlush = true };
+ var multiWriter = new MultiTextWriter(Console.Out, logWriter);
+ Console.SetOut(multiWriter);
+ Console.SetError(multiWriter);
+
+ // Global exception handler
+ AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
+ {
+ var ex = e.ExceptionObject as Exception;
+ Console.WriteLine($"[FATAL] Unhandled exception: {ex?.GetType().Name}: {ex?.Message}");
+ Console.WriteLine($"[FATAL] Stack trace: {ex?.StackTrace}");
+ if (ex?.InnerException != null)
+ {
+ Console.WriteLine($"[FATAL] Inner exception: {ex.InnerException.GetType().Name}: {ex.InnerException.Message}");
+ Console.WriteLine($"[FATAL] Inner stack trace: {ex.InnerException.StackTrace}");
+ }
+ };
+
+ TaskScheduler.UnobservedTaskException += (sender, e) =>
+ {
+ Console.WriteLine($"[FATAL] Unobserved task exception: {e.Exception?.GetType().Name}: {e.Exception?.Message}");
+ Console.WriteLine($"[FATAL] Stack trace: {e.Exception?.StackTrace}");
+ e.SetObserved(); // Prevent crash
+ };
+
+ Console.WriteLine($"[Program] Starting TodoApp at {DateTime.Now}");
+ Console.WriteLine($"[Program] Log file: {logPath}");
+
+ try
+ {
+ // Create the MAUI app with all handlers registered
+ var app = MauiProgram.CreateMauiApp();
+
+ // Run on Linux platform
+ LinuxApplication.Run(app, args);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"[FATAL] Exception in Main: {ex.GetType().Name}: {ex.Message}");
+ Console.WriteLine($"[FATAL] Stack trace: {ex.StackTrace}");
+ throw;
+ }
+ }
+}
+
+// Helper to write to both console and file
+class MultiTextWriter : TextWriter
+{
+ private readonly TextWriter[] _writers;
+ public MultiTextWriter(params TextWriter[] writers) => _writers = writers;
+ public override System.Text.Encoding Encoding => System.Text.Encoding.UTF8;
+ public override void Write(char value) { foreach (var w in _writers) w.Write(value); }
+ public override void WriteLine(string? value) { foreach (var w in _writers) w.WriteLine(value); }
+ public override void Flush() { foreach (var w in _writers) w.Flush(); }
+}
diff --git a/samples/TodoApp/README.md b/samples/TodoApp/README.md
new file mode 100644
index 0000000..67c5f85
--- /dev/null
+++ b/samples/TodoApp/README.md
@@ -0,0 +1,111 @@
+# TodoApp Sample
+
+A complete task management application demonstrating OpenMaui Linux capabilities with real-world XAML patterns.
+
+## Features
+
+- **NavigationPage** - Full page navigation with back button support
+- **CollectionView** - Scrollable list with data binding and selection
+- **XAML Data Binding** - Value converters for dynamic styling
+- **DisplayAlert Dialogs** - Confirmation dialogs for delete actions
+- **Grid Layouts** - Complex layouts with star sizing for expanding content
+- **Entry & Editor** - Single and multi-line text input
+- **Border with RoundRectangle** - Modern card-style UI
+- **ToolbarItems** - Navigation bar actions
+
+## Screenshots
+
+The app consists of three pages:
+
+1. **TodoListPage** - Shows all tasks with completion status indicators
+2. **NewTodoPage** - Create a new task with title and notes
+3. **TodoDetailPage** - View/edit task details, mark complete, or delete
+
+## Architecture
+
+```
+TodoApp/
+├── App.cs # Application entry with NavigationPage
+├── Program.cs # Linux platform bootstrap
+├── MauiProgram.cs # MAUI app builder
+├── TodoItem.cs # Data model
+├── TodoService.cs # In-memory data store
+├── TodoListPage.xaml(.cs) # Main list view
+├── NewTodoPage.xaml(.cs) # Create task page
+└── TodoDetailPage.xaml(.cs) # Task detail/edit page
+```
+
+## XAML Highlights
+
+### Value Converters
+The app uses custom converters for dynamic styling based on completion status:
+- `CompletedToColorConverter` - Gray text for completed items
+- `CompletedToTextDecorationsConverter` - Strikethrough for completed items
+- `CompletedToOpacityConverter` - Fade completed items
+- `AlternatingRowColorConverter` - Alternating background colors
+
+### ResourceDictionary
+```xml
+
+ #5C6BC0
+ #26A69A
+ #212121
+
+```
+
+### CollectionView with DataTemplate
+```xml
+
+
+
+
+
+
+
+
+
+```
+
+### Grid with Star Rows (Expanding Editor)
+```xml
+
+
+
+
+
+
+
+```
+
+## Building and Running
+
+```bash
+# From the maui-linux-push directory
+cd samples/TodoApp
+dotnet publish -c Release -r linux-arm64
+
+# Run on Linux
+./bin/Release/net9.0/linux-arm64/publish/TodoApp
+```
+
+## Controls Demonstrated
+
+| Control | Usage |
+|---------|-------|
+| NavigationPage | App navigation container |
+| ContentPage | Individual screens |
+| CollectionView | Task list with selection |
+| Grid | Page layouts |
+| VerticalStackLayout | Vertical grouping |
+| HorizontalStackLayout | Horizontal grouping |
+| Label | Text display |
+| Entry | Single-line input |
+| Editor | Multi-line input |
+| Button | Toolbar actions |
+| Border | Card styling with rounded corners |
+| CheckBox | Completion toggle |
+| BoxView | Visual separators |
+
+## License
+
+MIT License - See repository root for details.
diff --git a/samples/TodoApp/TodoApp.csproj b/samples/TodoApp/TodoApp.csproj
new file mode 100644
index 0000000..1c0d871
--- /dev/null
+++ b/samples/TodoApp/TodoApp.csproj
@@ -0,0 +1,15 @@
+
+
+
+ Exe
+ net9.0
+ enable
+ enable
+ true
+
+
+
+
+
+
+
diff --git a/samples/TodoApp/TodoDetailPage.xaml b/samples/TodoApp/TodoDetailPage.xaml
new file mode 100644
index 0000000..ea8037a
--- /dev/null
+++ b/samples/TodoApp/TodoDetailPage.xaml
@@ -0,0 +1,106 @@
+
+
+
+
+ #5C6BC0
+ #26A69A
+ #EF5350
+ #212121
+ #757575
+ #FFFFFF
+ #E8EAF6
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/TodoApp/TodoDetailPage.xaml.cs b/samples/TodoApp/TodoDetailPage.xaml.cs
new file mode 100644
index 0000000..d0d1df5
--- /dev/null
+++ b/samples/TodoApp/TodoDetailPage.xaml.cs
@@ -0,0 +1,91 @@
+// TodoDetailPage - View and edit a todo item
+
+using Microsoft.Maui.Controls;
+using Microsoft.Maui.Graphics;
+using Microsoft.Maui.Platform;
+
+namespace TodoApp;
+
+public partial class TodoDetailPage : ContentPage
+{
+ private readonly TodoItem _todo;
+ private readonly TodoService _service = TodoService.Instance;
+
+ // Colors for status label
+ private static readonly Color AccentColor = Color.FromArgb("#26A69A");
+ private static readonly Color TextPrimary = Color.FromArgb("#212121");
+
+ public TodoDetailPage(TodoItem todo)
+ {
+ try
+ {
+ Console.WriteLine($"[TodoDetailPage] Constructor starting for: {todo.Title}");
+ InitializeComponent();
+ Console.WriteLine($"[TodoDetailPage] InitializeComponent complete");
+
+ _todo = todo;
+
+ // Populate fields
+ Console.WriteLine($"[TodoDetailPage] Setting TitleEntry.Text");
+ TitleEntry.Text = _todo.Title;
+ Console.WriteLine($"[TodoDetailPage] Setting NotesEditor.Text");
+ NotesEditor.Text = _todo.Notes;
+ Console.WriteLine($"[TodoDetailPage] Setting CompletedCheckBox.IsChecked");
+ CompletedCheckBox.IsChecked = _todo.IsCompleted;
+ Console.WriteLine($"[TodoDetailPage] Calling UpdateStatusLabel");
+ UpdateStatusLabel(_todo.IsCompleted);
+ Console.WriteLine($"[TodoDetailPage] Setting CreatedLabel.Text");
+ CreatedLabel.Text = $"Created {_todo.CreatedAt:MMMM d, yyyy} at {_todo.CreatedAt:h:mm tt}";
+ Console.WriteLine($"[TodoDetailPage] Constructor complete");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"[TodoDetailPage] EXCEPTION in constructor: {ex.GetType().Name}: {ex.Message}");
+ Console.WriteLine($"[TodoDetailPage] Stack trace: {ex.StackTrace}");
+ throw;
+ }
+ }
+
+ private void OnCompletedChanged(object? sender, Microsoft.Maui.Controls.CheckedChangedEventArgs e)
+ {
+ Console.WriteLine($"[TodoDetailPage] OnCompletedChanged: {e.Value}");
+ UpdateStatusLabel(e.Value);
+ }
+
+ private void UpdateStatusLabel(bool isCompleted)
+ {
+ if (StatusLabel == null)
+ {
+ Console.WriteLine($"[TodoDetailPage] UpdateStatusLabel: StatusLabel is null, skipping");
+ return;
+ }
+ Console.WriteLine($"[TodoDetailPage] UpdateStatusLabel: setting to {(isCompleted ? "Completed" : "In Progress")}");
+ StatusLabel.Text = isCompleted ? "Completed" : "In Progress";
+ StatusLabel.TextColor = isCompleted ? AccentColor : TextPrimary;
+ }
+
+ private async void OnSaveClicked(object? sender, EventArgs e)
+ {
+ _todo.Title = TitleEntry.Text ?? "";
+ _todo.Notes = NotesEditor.Text ?? "";
+ _todo.IsCompleted = CompletedCheckBox.IsChecked;
+
+ await Navigation.PopAsync();
+ }
+
+ private async void OnDeleteClicked(object? sender, EventArgs e)
+ {
+ // Show confirmation dialog
+ var confirmed = await LinuxDialogService.ShowAlertAsync(
+ "Delete Task",
+ $"Are you sure you want to delete \"{_todo.Title}\"? This action cannot be undone.",
+ "Delete",
+ "Cancel");
+
+ if (confirmed)
+ {
+ _service.DeleteTodo(_todo);
+ await Navigation.PopAsync();
+ }
+ }
+}
diff --git a/samples/TodoApp/TodoItem.cs b/samples/TodoApp/TodoItem.cs
new file mode 100644
index 0000000..e7ab47c
--- /dev/null
+++ b/samples/TodoApp/TodoItem.cs
@@ -0,0 +1,81 @@
+// TodoItem - Data model for a todo item
+
+using System.ComponentModel;
+
+namespace TodoApp;
+
+public class TodoItem : INotifyPropertyChanged
+{
+ private string _title = "";
+ private string _notes = "";
+ private bool _isCompleted;
+ private DateTime _dueDate;
+
+ public int Id { get; set; }
+
+ ///
+ /// Index in the collection for alternating row colors.
+ ///
+ public int Index { get; set; }
+
+ public string Title
+ {
+ get => _title;
+ set
+ {
+ if (_title != value)
+ {
+ _title = value;
+ OnPropertyChanged(nameof(Title));
+ }
+ }
+ }
+
+ public string Notes
+ {
+ get => _notes;
+ set
+ {
+ if (_notes != value)
+ {
+ _notes = value;
+ OnPropertyChanged(nameof(Notes));
+ }
+ }
+ }
+
+ public bool IsCompleted
+ {
+ get => _isCompleted;
+ set
+ {
+ if (_isCompleted != value)
+ {
+ _isCompleted = value;
+ OnPropertyChanged(nameof(IsCompleted));
+ }
+ }
+ }
+
+ public DateTime DueDate
+ {
+ get => _dueDate;
+ set
+ {
+ if (_dueDate != value)
+ {
+ _dueDate = value;
+ OnPropertyChanged(nameof(DueDate));
+ }
+ }
+ }
+
+ public DateTime CreatedAt { get; set; } = DateTime.Now;
+
+ public event PropertyChangedEventHandler? PropertyChanged;
+
+ protected void OnPropertyChanged(string propertyName)
+ {
+ PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+ }
+}
diff --git a/samples/TodoApp/TodoListPage.xaml b/samples/TodoApp/TodoListPage.xaml
new file mode 100644
index 0000000..9299260
--- /dev/null
+++ b/samples/TodoApp/TodoListPage.xaml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+ #5C6BC0
+ #3949AB
+ #26A69A
+ #212121
+ #757575
+ #FFFFFF
+ #E0E0E0
+ #9E9E9E
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/samples/TodoApp/TodoListPage.xaml.cs b/samples/TodoApp/TodoListPage.xaml.cs
new file mode 100644
index 0000000..204541b
--- /dev/null
+++ b/samples/TodoApp/TodoListPage.xaml.cs
@@ -0,0 +1,174 @@
+// TodoListPage - Main page for viewing todos with XAML support
+
+using Microsoft.Maui.Controls;
+using Microsoft.Maui.Graphics;
+using System.Globalization;
+
+namespace TodoApp;
+
+public partial class TodoListPage : ContentPage
+{
+ private readonly TodoService _service = TodoService.Instance;
+
+ public TodoListPage()
+ {
+ Console.WriteLine("[TodoListPage] Constructor starting");
+ InitializeComponent();
+
+ TodoCollectionView.ItemsSource = _service.Todos;
+ UpdateStats();
+
+ Console.WriteLine("[TodoListPage] Constructor finished");
+ }
+
+ protected override void OnAppearing()
+ {
+ Console.WriteLine("[TodoListPage] OnAppearing called - refreshing CollectionView");
+ base.OnAppearing();
+
+ // Refresh indexes for alternating row colors
+ _service.RefreshIndexes();
+
+ // Refresh the collection view
+ TodoCollectionView.ItemsSource = null;
+ TodoCollectionView.ItemsSource = _service.Todos;
+ Console.WriteLine($"[TodoListPage] ItemsSource set with {_service.Todos.Count} items");
+ UpdateStats();
+ }
+
+ private async void OnAddClicked(object sender, EventArgs e)
+ {
+ await Navigation.PushAsync(new NewTodoPage());
+ }
+
+ private async void OnSelectionChanged(object? sender, SelectionChangedEventArgs e)
+ {
+ try
+ {
+ Console.WriteLine($"[TodoListPage] OnSelectionChanged: {e.CurrentSelection.Count} items selected");
+ if (e.CurrentSelection.FirstOrDefault() is TodoItem todo)
+ {
+ Console.WriteLine($"[TodoListPage] Navigating to TodoDetailPage for: {todo.Title}");
+ TodoCollectionView.SelectedItem = null; // Deselect
+ var detailPage = new TodoDetailPage(todo);
+ Console.WriteLine($"[TodoListPage] Created TodoDetailPage, pushing...");
+ await Navigation.PushAsync(detailPage);
+ Console.WriteLine($"[TodoListPage] Navigation complete");
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"[TodoListPage] EXCEPTION in OnSelectionChanged: {ex.GetType().Name}: {ex.Message}");
+ Console.WriteLine($"[TodoListPage] Stack trace: {ex.StackTrace}");
+ }
+ }
+
+ private void UpdateStats()
+ {
+ var completed = _service.CompletedCount;
+ var total = _service.TotalCount;
+
+ if (total == 0)
+ {
+ StatsLabel.Text = "";
+ }
+ else
+ {
+ StatsLabel.Text = $"{completed} of {total} completed";
+ }
+ }
+}
+
+///
+/// Converter for alternating row background colors.
+///
+public class AlternatingRowColorConverter : IValueConverter
+{
+ public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ if (value is int index)
+ {
+ return index % 2 == 0 ? Colors.White : Color.FromArgb("#F5F5F5");
+ }
+ return Colors.White;
+ }
+
+ public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+}
+
+///
+/// Converter for completed task text color and indicator color.
+///
+public class CompletedToColorConverter : IValueConverter
+{
+ // Define colors
+ private static readonly Color PrimaryColor = Color.FromArgb("#5C6BC0");
+ private static readonly Color AccentColor = Color.FromArgb("#26A69A");
+ private static readonly Color CompletedColor = Color.FromArgb("#9E9E9E");
+ private static readonly Color TextPrimary = Color.FromArgb("#212121");
+ private static readonly Color TextSecondary = Color.FromArgb("#757575");
+
+ public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ bool isCompleted = value is bool b && b;
+ string param = parameter as string ?? "";
+
+ // Indicator bar color
+ if (param == "indicator")
+ {
+ return isCompleted ? CompletedColor : AccentColor;
+ }
+
+ // Text colors
+ if (isCompleted)
+ {
+ return CompletedColor;
+ }
+ else
+ {
+ return param == "notes" ? TextSecondary : TextPrimary;
+ }
+ }
+
+ public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+}
+
+///
+/// Converter for completed task text decorations (strikethrough).
+///
+public class CompletedToTextDecorationsConverter : IValueConverter
+{
+ public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ bool isCompleted = value is bool b && b;
+ return isCompleted ? TextDecorations.Strikethrough : TextDecorations.None;
+ }
+
+ public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+}
+
+///
+/// Converter for completed task opacity (slightly faded when complete).
+///
+public class CompletedToOpacityConverter : IValueConverter
+{
+ public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ bool isCompleted = value is bool b && b;
+ return isCompleted ? 0.7 : 1.0;
+ }
+
+ public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+}
diff --git a/samples/TodoApp/TodoService.cs b/samples/TodoApp/TodoService.cs
new file mode 100644
index 0000000..f03844b
--- /dev/null
+++ b/samples/TodoApp/TodoService.cs
@@ -0,0 +1,61 @@
+// TodoService - Manages todo items
+
+using System.Collections.ObjectModel;
+
+namespace TodoApp;
+
+public class TodoService
+{
+ private static TodoService? _instance;
+ public static TodoService Instance => _instance ??= new TodoService();
+
+ private int _nextId = 1;
+
+ public ObservableCollection Todos { get; } = new();
+
+ private TodoService()
+ {
+ // Add sample todos with varying lengths to test MaxLines=2 with ellipsis
+ AddTodo("Learn OpenMaui Linux", "Explore the SkiaSharp-based rendering engine for .NET MAUI on Linux desktop. This is a very long description that should wrap to multiple lines and demonstrate the ellipsis truncation feature when MaxLines is set to 2.");
+ AddTodo("Build amazing apps", "Create cross-platform applications that run on Windows, macOS, iOS, Android, and Linux! With OpenMaui, you can write once and deploy everywhere.");
+ AddTodo("Share with the community", "Contribute to the open-source project and help others build great Linux apps. Join our growing community of developers who are passionate about bringing .NET MAUI to Linux.");
+ }
+
+ public TodoItem AddTodo(string title, string notes = "")
+ {
+ var todo = new TodoItem
+ {
+ Id = _nextId++,
+ Index = Todos.Count, // Set index for alternating row colors
+ Title = title,
+ Notes = notes,
+ DueDate = DateTime.Today.AddDays(7)
+ };
+ Todos.Add(todo);
+ return todo;
+ }
+
+ ///
+ /// Refreshes the Index property on all items for alternating row colors.
+ ///
+ public void RefreshIndexes()
+ {
+ for (int i = 0; i < Todos.Count; i++)
+ {
+ Todos[i].Index = i;
+ }
+ }
+
+ public TodoItem? GetTodo(int id)
+ {
+ return Todos.FirstOrDefault(t => t.Id == id);
+ }
+
+ public void DeleteTodo(TodoItem todo)
+ {
+ Todos.Remove(todo);
+ }
+
+ public int CompletedCount => Todos.Count(t => t.IsCompleted);
+ public int TotalCount => Todos.Count;
+}