Verify Views files against decompiled, extract embedded types
Fixed files: - SkiaImageButton.cs: Added SVG support with multi-path search - SkiaNavigationPage.cs: Added LinuxApplication.IsGtkMode check - SkiaRefreshView.cs: Added ICommand support (Command, CommandParameter) - SkiaTemplatedView.cs: Added missing using statements Extracted embedded types to separate files (matching decompiled pattern): - From SkiaMenuBar.cs: MenuBarItem, MenuItem, SkiaMenuFlyout, MenuItemClickedEventArgs - From SkiaNavigationPage.cs: NavigationEventArgs - From SkiaTabbedPage.cs: TabItem - From SkiaVisualStateManager.cs: SkiaVisualStateGroupList, SkiaVisualStateGroup, SkiaVisualState, SkiaVisualStateSetter - From SkiaSwipeView.cs: SwipeItem, SwipeStartedEventArgs, SwipeEndedEventArgs - From SkiaFlyoutPage.cs: FlyoutLayoutBehavior (already separate) - From SkiaIndicatorView.cs: IndicatorShape (already separate) - From SkiaBorder.cs: SkiaFrame - From SkiaCarouselView.cs: PositionChangedEventArgs - From SkiaCollectionView.cs: SkiaSelectionMode, ItemsLayoutOrientation - From SkiaContentPresenter.cs: LayoutAlignment Verified matching decompiled: - SkiaContextMenu.cs, SkiaFlexLayout.cs, SkiaGraphicsView.cs Build: 0 errors 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
182
AnimationManager.cs
Normal file
182
AnimationManager.cs
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
// 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.Linux;
|
||||||
|
|
||||||
|
public static class AnimationManager
|
||||||
|
{
|
||||||
|
private class RunningAnimation
|
||||||
|
{
|
||||||
|
public required SkiaView View { get; set; }
|
||||||
|
public string PropertyName { get; set; } = "";
|
||||||
|
public double StartValue { get; set; }
|
||||||
|
public double EndValue { get; set; }
|
||||||
|
public DateTime StartTime { get; set; }
|
||||||
|
public uint Duration { get; set; }
|
||||||
|
public Easing Easing { get; set; } = Easing.Linear;
|
||||||
|
public required TaskCompletionSource<bool> Completion { get; set; }
|
||||||
|
public CancellationToken Token { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly List<RunningAnimation> _animations = new();
|
||||||
|
private static bool _isRunning;
|
||||||
|
private static CancellationTokenSource? _cts;
|
||||||
|
|
||||||
|
private static void EnsureRunning()
|
||||||
|
{
|
||||||
|
if (!_isRunning)
|
||||||
|
{
|
||||||
|
_isRunning = true;
|
||||||
|
_cts = new CancellationTokenSource();
|
||||||
|
_ = RunAnimationLoop(_cts.Token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task RunAnimationLoop(CancellationToken token)
|
||||||
|
{
|
||||||
|
while (!token.IsCancellationRequested && _animations.Count > 0)
|
||||||
|
{
|
||||||
|
var now = DateTime.UtcNow;
|
||||||
|
var completed = new List<RunningAnimation>();
|
||||||
|
|
||||||
|
foreach (var animation in _animations.ToList())
|
||||||
|
{
|
||||||
|
if (animation.Token.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
completed.Add(animation);
|
||||||
|
animation.Completion.TrySetResult(false);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var progress = Math.Clamp(
|
||||||
|
(now - animation.StartTime).TotalMilliseconds / animation.Duration,
|
||||||
|
0.0, 1.0);
|
||||||
|
|
||||||
|
var easedProgress = animation.Easing.Ease(progress);
|
||||||
|
var value = animation.StartValue + (animation.EndValue - animation.StartValue) * easedProgress;
|
||||||
|
|
||||||
|
SetProperty(animation.View, animation.PropertyName, value);
|
||||||
|
|
||||||
|
if (progress >= 1.0)
|
||||||
|
{
|
||||||
|
completed.Add(animation);
|
||||||
|
animation.Completion.TrySetResult(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var animation in completed)
|
||||||
|
{
|
||||||
|
_animations.Remove(animation);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_animations.Count == 0)
|
||||||
|
{
|
||||||
|
_isRunning = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.Delay(16, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
_isRunning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetProperty(SkiaView view, string propertyName, double value)
|
||||||
|
{
|
||||||
|
switch (propertyName)
|
||||||
|
{
|
||||||
|
case nameof(SkiaView.Opacity):
|
||||||
|
view.Opacity = (float)value;
|
||||||
|
break;
|
||||||
|
case nameof(SkiaView.Scale):
|
||||||
|
view.Scale = value;
|
||||||
|
break;
|
||||||
|
case nameof(SkiaView.ScaleX):
|
||||||
|
view.ScaleX = value;
|
||||||
|
break;
|
||||||
|
case nameof(SkiaView.ScaleY):
|
||||||
|
view.ScaleY = value;
|
||||||
|
break;
|
||||||
|
case nameof(SkiaView.Rotation):
|
||||||
|
view.Rotation = value;
|
||||||
|
break;
|
||||||
|
case nameof(SkiaView.RotationX):
|
||||||
|
view.RotationX = value;
|
||||||
|
break;
|
||||||
|
case nameof(SkiaView.RotationY):
|
||||||
|
view.RotationY = value;
|
||||||
|
break;
|
||||||
|
case nameof(SkiaView.TranslationX):
|
||||||
|
view.TranslationX = value;
|
||||||
|
break;
|
||||||
|
case nameof(SkiaView.TranslationY):
|
||||||
|
view.TranslationY = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double GetProperty(SkiaView view, string propertyName)
|
||||||
|
{
|
||||||
|
return propertyName switch
|
||||||
|
{
|
||||||
|
nameof(SkiaView.Opacity) => view.Opacity,
|
||||||
|
nameof(SkiaView.Scale) => view.Scale,
|
||||||
|
nameof(SkiaView.ScaleX) => view.ScaleX,
|
||||||
|
nameof(SkiaView.ScaleY) => view.ScaleY,
|
||||||
|
nameof(SkiaView.Rotation) => view.Rotation,
|
||||||
|
nameof(SkiaView.RotationX) => view.RotationX,
|
||||||
|
nameof(SkiaView.RotationY) => view.RotationY,
|
||||||
|
nameof(SkiaView.TranslationX) => view.TranslationX,
|
||||||
|
nameof(SkiaView.TranslationY) => view.TranslationY,
|
||||||
|
_ => 0.0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Task<bool> AnimateAsync(
|
||||||
|
SkiaView view,
|
||||||
|
string propertyName,
|
||||||
|
double targetValue,
|
||||||
|
uint length = 250,
|
||||||
|
Easing? easing = null,
|
||||||
|
CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
CancelAnimation(view, propertyName);
|
||||||
|
|
||||||
|
var animation = new RunningAnimation
|
||||||
|
{
|
||||||
|
View = view,
|
||||||
|
PropertyName = propertyName,
|
||||||
|
StartValue = GetProperty(view, propertyName),
|
||||||
|
EndValue = targetValue,
|
||||||
|
StartTime = DateTime.UtcNow,
|
||||||
|
Duration = length,
|
||||||
|
Easing = easing ?? Easing.Linear,
|
||||||
|
Completion = new TaskCompletionSource<bool>(),
|
||||||
|
Token = cancellationToken
|
||||||
|
};
|
||||||
|
|
||||||
|
_animations.Add(animation);
|
||||||
|
EnsureRunning();
|
||||||
|
|
||||||
|
return animation.Completion.Task;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CancelAnimation(SkiaView view, string propertyName)
|
||||||
|
{
|
||||||
|
var animation = _animations.FirstOrDefault(a => a.View == view && a.PropertyName == propertyName);
|
||||||
|
if (animation != null)
|
||||||
|
{
|
||||||
|
_animations.Remove(animation);
|
||||||
|
animation.Completion.TrySetResult(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void CancelAnimations(SkiaView view)
|
||||||
|
{
|
||||||
|
foreach (var animation in _animations.Where(a => a.View == view).ToList())
|
||||||
|
{
|
||||||
|
_animations.Remove(animation);
|
||||||
|
animation.Completion.TrySetResult(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
20
Converters/ColorExtensions.cs
Normal file
20
Converters/ColorExtensions.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// 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.Graphics;
|
||||||
|
using SkiaSharp;
|
||||||
|
|
||||||
|
namespace Microsoft.Maui.Platform.Linux.Converters;
|
||||||
|
|
||||||
|
public static class ColorExtensions
|
||||||
|
{
|
||||||
|
public static SKColor ToSKColor(this Color color)
|
||||||
|
{
|
||||||
|
return SKColorTypeConverter.ToSKColor(color);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Color ToMauiColor(this SKColor color)
|
||||||
|
{
|
||||||
|
return SKColorTypeConverter.ToMauiColor(color);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -235,25 +235,3 @@ public class SKColorTypeConverter : TypeConverter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Extension methods for color conversion.
|
|
||||||
/// </summary>
|
|
||||||
public static class ColorExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Converts a MAUI Color to an SKColor.
|
|
||||||
/// </summary>
|
|
||||||
public static SKColor ToSKColor(this Color color)
|
|
||||||
{
|
|
||||||
return SKColorTypeConverter.ToSKColor(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts an SKColor to a MAUI Color.
|
|
||||||
/// </summary>
|
|
||||||
public static Color ToMauiColor(this SKColor color)
|
|
||||||
{
|
|
||||||
return SKColorTypeConverter.ToMauiColor(color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
75
Converters/SKPointTypeConverter.cs
Normal file
75
Converters/SKPointTypeConverter.cs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
// 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 Microsoft.Maui.Graphics;
|
||||||
|
using SkiaSharp;
|
||||||
|
|
||||||
|
namespace Microsoft.Maui.Platform.Linux.Converters;
|
||||||
|
|
||||||
|
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 &&
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -137,192 +137,3 @@ public class SKRectTypeConverter : TypeConverter
|
|||||||
return SKRect.Empty;
|
return SKRect.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Type converter for SKSize.
|
|
||||||
/// </summary>
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Type converter for SKPoint.
|
|
||||||
/// </summary>
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Extension methods for SkiaSharp type conversions.
|
|
||||||
/// </summary>
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
82
Converters/SKSizeTypeConverter.cs
Normal file
82
Converters/SKSizeTypeConverter.cs
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
// 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 Microsoft.Maui.Graphics;
|
||||||
|
using SkiaSharp;
|
||||||
|
|
||||||
|
namespace Microsoft.Maui.Platform.Linux.Converters;
|
||||||
|
|
||||||
|
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 single))
|
||||||
|
{
|
||||||
|
return new SKSize(single, single);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (parts.Length == 2 &&
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
40
Converters/SKTypeExtensions.cs
Normal file
40
Converters/SKTypeExtensions.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
// 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.Graphics;
|
||||||
|
using SkiaSharp;
|
||||||
|
|
||||||
|
namespace Microsoft.Maui.Platform.Linux.Converters;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
DisplayServerType.cs
Normal file
11
DisplayServerType.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
// 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.Linux;
|
||||||
|
|
||||||
|
public enum DisplayServerType
|
||||||
|
{
|
||||||
|
Auto,
|
||||||
|
X11,
|
||||||
|
Wayland
|
||||||
|
}
|
||||||
52
Easing.cs
Normal file
52
Easing.cs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
// 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.Linux;
|
||||||
|
|
||||||
|
public class Easing
|
||||||
|
{
|
||||||
|
private readonly Func<double, double> _easingFunc;
|
||||||
|
|
||||||
|
public static readonly Easing Linear = new(v => v);
|
||||||
|
|
||||||
|
public static readonly Easing SinIn = new(v => 1.0 - Math.Cos(v * Math.PI / 2.0));
|
||||||
|
|
||||||
|
public static readonly Easing SinOut = new(v => Math.Sin(v * Math.PI / 2.0));
|
||||||
|
|
||||||
|
public static readonly Easing SinInOut = new(v => -(Math.Cos(Math.PI * v) - 1.0) / 2.0);
|
||||||
|
|
||||||
|
public static readonly Easing CubicIn = new(v => v * v * v);
|
||||||
|
|
||||||
|
public static readonly Easing CubicOut = new(v => 1.0 - Math.Pow(1.0 - v, 3.0));
|
||||||
|
|
||||||
|
public static readonly Easing CubicInOut = new(v =>
|
||||||
|
v < 0.5 ? 4.0 * v * v * v : 1.0 - Math.Pow(-2.0 * v + 2.0, 3.0) / 2.0);
|
||||||
|
|
||||||
|
public static readonly Easing BounceIn = new(v => 1.0 - BounceOut.Ease(1.0 - v));
|
||||||
|
|
||||||
|
public static readonly Easing BounceOut = new(v =>
|
||||||
|
{
|
||||||
|
const double n1 = 7.5625;
|
||||||
|
const double d1 = 2.75;
|
||||||
|
|
||||||
|
if (v < 1 / d1)
|
||||||
|
return n1 * v * v;
|
||||||
|
if (v < 2 / d1)
|
||||||
|
return n1 * (v -= 1.5 / d1) * v + 0.75;
|
||||||
|
if (v < 2.5 / d1)
|
||||||
|
return n1 * (v -= 2.25 / d1) * v + 0.9375;
|
||||||
|
return n1 * (v -= 2.625 / d1) * v + 0.984375;
|
||||||
|
});
|
||||||
|
|
||||||
|
public static readonly Easing SpringIn = new(v => v * v * (2.70158 * v - 1.70158));
|
||||||
|
|
||||||
|
public static readonly Easing SpringOut = new(v =>
|
||||||
|
(v - 1.0) * (v - 1.0) * (2.70158 * (v - 1.0) + 1.70158) + 1.0);
|
||||||
|
|
||||||
|
public Easing(Func<double, double> easingFunc)
|
||||||
|
{
|
||||||
|
_easingFunc = easingFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double Ease(double v) => _easingFunc(v);
|
||||||
|
}
|
||||||
52
Hosting/GtkMauiContext.cs
Normal file
52
Hosting/GtkMauiContext.cs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||||
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Maui.Animations;
|
||||||
|
using Microsoft.Maui.Dispatching;
|
||||||
|
using Microsoft.Maui.Platform.Linux.Dispatching;
|
||||||
|
|
||||||
|
namespace Microsoft.Maui.Platform.Linux.Hosting;
|
||||||
|
|
||||||
|
public class GtkMauiContext : IMauiContext
|
||||||
|
{
|
||||||
|
private readonly IServiceProvider _services;
|
||||||
|
private readonly IMauiHandlersFactory _handlers;
|
||||||
|
private IAnimationManager? _animationManager;
|
||||||
|
private IDispatcher? _dispatcher;
|
||||||
|
|
||||||
|
public IServiceProvider Services => _services;
|
||||||
|
|
||||||
|
public IMauiHandlersFactory Handlers => _handlers;
|
||||||
|
|
||||||
|
public IAnimationManager AnimationManager
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
_animationManager ??= _services.GetService<IAnimationManager>()
|
||||||
|
?? new LinuxAnimationManager(new LinuxTicker());
|
||||||
|
return _animationManager;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IDispatcher Dispatcher
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
_dispatcher ??= _services.GetService<IDispatcher>()
|
||||||
|
?? new LinuxDispatcher();
|
||||||
|
return _dispatcher;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public GtkMauiContext(IServiceProvider services)
|
||||||
|
{
|
||||||
|
_services = services ?? throw new ArgumentNullException(nameof(services));
|
||||||
|
_handlers = services.GetRequiredService<IMauiHandlersFactory>();
|
||||||
|
|
||||||
|
if (LinuxApplication.Current == null)
|
||||||
|
{
|
||||||
|
new LinuxApplication();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
Hosting/HandlerMappingExtensions.cs
Normal file
17
Hosting/HandlerMappingExtensions.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
// 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.Hosting;
|
||||||
|
|
||||||
|
namespace Microsoft.Maui.Platform.Linux.Hosting;
|
||||||
|
|
||||||
|
public static class HandlerMappingExtensions
|
||||||
|
{
|
||||||
|
public static IMauiHandlersCollection AddHandler<TView, THandler>(this IMauiHandlersCollection handlers)
|
||||||
|
where TView : class
|
||||||
|
where THandler : class
|
||||||
|
{
|
||||||
|
handlers.AddHandler(typeof(TView), typeof(THandler));
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
}
|
||||||
56
Hosting/LinuxAnimationManager.cs
Normal file
56
Hosting/LinuxAnimationManager.cs
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
// 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.Animations;
|
||||||
|
using Animation = Microsoft.Maui.Animations.Animation;
|
||||||
|
|
||||||
|
namespace Microsoft.Maui.Platform.Linux.Hosting;
|
||||||
|
|
||||||
|
internal class LinuxAnimationManager : IAnimationManager
|
||||||
|
{
|
||||||
|
private readonly List<Animation> _animations = new();
|
||||||
|
private readonly ITicker _ticker;
|
||||||
|
|
||||||
|
public double SpeedModifier { get; set; } = 1.0;
|
||||||
|
|
||||||
|
public bool AutoStartTicker { get; set; } = true;
|
||||||
|
|
||||||
|
public ITicker Ticker => _ticker;
|
||||||
|
|
||||||
|
public LinuxAnimationManager(ITicker ticker)
|
||||||
|
{
|
||||||
|
_ticker = ticker;
|
||||||
|
_ticker.Fire = OnTickerFire;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(Animation animation)
|
||||||
|
{
|
||||||
|
_animations.Add(animation);
|
||||||
|
if (AutoStartTicker && !_ticker.IsRunning)
|
||||||
|
{
|
||||||
|
_ticker.Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Remove(Animation animation)
|
||||||
|
{
|
||||||
|
_animations.Remove(animation);
|
||||||
|
if (_animations.Count == 0 && _ticker.IsRunning)
|
||||||
|
{
|
||||||
|
_ticker.Stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTickerFire()
|
||||||
|
{
|
||||||
|
var animationsArray = _animations.ToArray();
|
||||||
|
foreach (var animation in animationsArray)
|
||||||
|
{
|
||||||
|
animation.Tick(0.016 * SpeedModifier);
|
||||||
|
if (animation.HasFinished)
|
||||||
|
{
|
||||||
|
Remove(animation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,37 +7,41 @@ using Microsoft.Extensions.DependencyInjection.Extensions;
|
|||||||
using Microsoft.Maui.ApplicationModel;
|
using Microsoft.Maui.ApplicationModel;
|
||||||
using Microsoft.Maui.ApplicationModel.Communication;
|
using Microsoft.Maui.ApplicationModel.Communication;
|
||||||
using Microsoft.Maui.ApplicationModel.DataTransfer;
|
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 Microsoft.Maui.Controls;
|
||||||
|
using Microsoft.Maui.Devices;
|
||||||
|
using Microsoft.Maui.Dispatching;
|
||||||
|
using Microsoft.Maui.Hosting;
|
||||||
|
using Microsoft.Maui.Networking;
|
||||||
|
using Microsoft.Maui.Platform.Linux.Converters;
|
||||||
|
using Microsoft.Maui.Platform.Linux.Dispatching;
|
||||||
|
using Microsoft.Maui.Platform.Linux.Handlers;
|
||||||
|
using Microsoft.Maui.Platform.Linux.Services;
|
||||||
|
using Microsoft.Maui.Storage;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
|
|
||||||
namespace Microsoft.Maui.Platform.Linux.Hosting;
|
namespace Microsoft.Maui.Platform.Linux.Hosting;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Extension methods for configuring MAUI applications for Linux.
|
|
||||||
/// </summary>
|
|
||||||
public static class LinuxMauiAppBuilderExtensions
|
public static class LinuxMauiAppBuilderExtensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Configures the MAUI application to run on Linux.
|
|
||||||
/// </summary>
|
|
||||||
public static MauiAppBuilder UseLinux(this MauiAppBuilder builder)
|
public static MauiAppBuilder UseLinux(this MauiAppBuilder builder)
|
||||||
{
|
{
|
||||||
return builder.UseLinux(configure: null);
|
return builder.UseLinux(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Configures the MAUI application to run on Linux with options.
|
|
||||||
/// </summary>
|
|
||||||
public static MauiAppBuilder UseLinux(this MauiAppBuilder builder, Action<LinuxApplicationOptions>? configure)
|
public static MauiAppBuilder UseLinux(this MauiAppBuilder builder, Action<LinuxApplicationOptions>? configure)
|
||||||
{
|
{
|
||||||
var options = new LinuxApplicationOptions();
|
var options = new LinuxApplicationOptions();
|
||||||
configure?.Invoke(options);
|
configure?.Invoke(options);
|
||||||
|
|
||||||
|
// Register dispatcher provider
|
||||||
|
builder.Services.TryAddSingleton<IDispatcherProvider>(LinuxDispatcherProvider.Instance);
|
||||||
|
|
||||||
|
// Register device services
|
||||||
|
builder.Services.TryAddSingleton<IDeviceInfo>(DeviceInfoService.Instance);
|
||||||
|
builder.Services.TryAddSingleton<IDeviceDisplay>(DeviceDisplayService.Instance);
|
||||||
|
builder.Services.TryAddSingleton<IAppInfo>(AppInfoService.Instance);
|
||||||
|
builder.Services.TryAddSingleton<IConnectivity>(ConnectivityService.Instance);
|
||||||
|
|
||||||
// Register platform services
|
// Register platform services
|
||||||
builder.Services.TryAddSingleton<ILauncher, LauncherService>();
|
builder.Services.TryAddSingleton<ILauncher, LauncherService>();
|
||||||
builder.Services.TryAddSingleton<IPreferences, PreferencesService>();
|
builder.Services.TryAddSingleton<IPreferences, PreferencesService>();
|
||||||
@@ -50,6 +54,9 @@ public static class LinuxMauiAppBuilderExtensions
|
|||||||
builder.Services.TryAddSingleton<IBrowser, BrowserService>();
|
builder.Services.TryAddSingleton<IBrowser, BrowserService>();
|
||||||
builder.Services.TryAddSingleton<IEmail, EmailService>();
|
builder.Services.TryAddSingleton<IEmail, EmailService>();
|
||||||
|
|
||||||
|
// Register GTK host service
|
||||||
|
builder.Services.TryAddSingleton(_ => GtkHostService.Instance);
|
||||||
|
|
||||||
// Register type converters for XAML support
|
// Register type converters for XAML support
|
||||||
RegisterTypeConverters();
|
RegisterTypeConverters();
|
||||||
|
|
||||||
@@ -98,8 +105,8 @@ public static class LinuxMauiAppBuilderExtensions
|
|||||||
handlers.AddHandler<ImageButton, ImageButtonHandler>();
|
handlers.AddHandler<ImageButton, ImageButtonHandler>();
|
||||||
handlers.AddHandler<GraphicsView, GraphicsViewHandler>();
|
handlers.AddHandler<GraphicsView, GraphicsViewHandler>();
|
||||||
|
|
||||||
// Web
|
// Web - use GtkWebViewHandler
|
||||||
handlers.AddHandler<WebView, WebViewHandler>();
|
handlers.AddHandler<WebView, GtkWebViewHandler>();
|
||||||
|
|
||||||
// Collection Views
|
// Collection Views
|
||||||
handlers.AddHandler<CollectionView, CollectionViewHandler>();
|
handlers.AddHandler<CollectionView, CollectionViewHandler>();
|
||||||
@@ -124,33 +131,11 @@ public static class LinuxMauiAppBuilderExtensions
|
|||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Registers custom type converters for Linux platform.
|
|
||||||
/// </summary>
|
|
||||||
private static void RegisterTypeConverters()
|
private static void RegisterTypeConverters()
|
||||||
{
|
{
|
||||||
// Register SkiaSharp type converters for XAML styling support
|
|
||||||
TypeDescriptor.AddAttributes(typeof(SKColor), new TypeConverterAttribute(typeof(SKColorTypeConverter)));
|
TypeDescriptor.AddAttributes(typeof(SKColor), new TypeConverterAttribute(typeof(SKColorTypeConverter)));
|
||||||
TypeDescriptor.AddAttributes(typeof(SKRect), new TypeConverterAttribute(typeof(SKRectTypeConverter)));
|
TypeDescriptor.AddAttributes(typeof(SKRect), new TypeConverterAttribute(typeof(SKRectTypeConverter)));
|
||||||
TypeDescriptor.AddAttributes(typeof(SKSize), new TypeConverterAttribute(typeof(SKSizeTypeConverter)));
|
TypeDescriptor.AddAttributes(typeof(SKSize), new TypeConverterAttribute(typeof(SKSizeTypeConverter)));
|
||||||
TypeDescriptor.AddAttributes(typeof(SKPoint), new TypeConverterAttribute(typeof(SKPointTypeConverter)));
|
TypeDescriptor.AddAttributes(typeof(SKPoint), new TypeConverterAttribute(typeof(SKPointTypeConverter)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Handler registration extensions.
|
|
||||||
/// </summary>
|
|
||||||
public static class HandlerMappingExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a handler for the specified view type.
|
|
||||||
/// </summary>
|
|
||||||
public static IMauiHandlersCollection AddHandler<TView, THandler>(
|
|
||||||
this IMauiHandlersCollection handlers)
|
|
||||||
where TView : class
|
|
||||||
where THandler : class
|
|
||||||
{
|
|
||||||
handlers.AddHandler(typeof(TView), typeof(THandler));
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -4,16 +4,10 @@
|
|||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Maui.Animations;
|
using Microsoft.Maui.Animations;
|
||||||
using Microsoft.Maui.Dispatching;
|
using Microsoft.Maui.Dispatching;
|
||||||
using Microsoft.Maui.Platform;
|
|
||||||
using Microsoft.Maui.Platform.Linux.Dispatching;
|
using Microsoft.Maui.Platform.Linux.Dispatching;
|
||||||
using SkiaSharp;
|
|
||||||
|
|
||||||
namespace Microsoft.Maui.Platform.Linux.Hosting;
|
namespace Microsoft.Maui.Platform.Linux.Hosting;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Linux-specific implementation of IMauiContext.
|
|
||||||
/// Provides the infrastructure for creating handlers and accessing platform services.
|
|
||||||
/// </summary>
|
|
||||||
public class LinuxMauiContext : IMauiContext
|
public class LinuxMauiContext : IMauiContext
|
||||||
{
|
{
|
||||||
private readonly IServiceProvider _services;
|
private readonly IServiceProvider _services;
|
||||||
@@ -22,27 +16,12 @@ public class LinuxMauiContext : IMauiContext
|
|||||||
private IAnimationManager? _animationManager;
|
private IAnimationManager? _animationManager;
|
||||||
private IDispatcher? _dispatcher;
|
private IDispatcher? _dispatcher;
|
||||||
|
|
||||||
public LinuxMauiContext(IServiceProvider services, LinuxApplication linuxApp)
|
|
||||||
{
|
|
||||||
_services = services ?? throw new ArgumentNullException(nameof(services));
|
|
||||||
_linuxApp = linuxApp ?? throw new ArgumentNullException(nameof(linuxApp));
|
|
||||||
_handlers = services.GetRequiredService<IMauiHandlersFactory>();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public IServiceProvider Services => _services;
|
public IServiceProvider Services => _services;
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public IMauiHandlersFactory Handlers => _handlers;
|
public IMauiHandlersFactory Handlers => _handlers;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the Linux application instance.
|
|
||||||
/// </summary>
|
|
||||||
public LinuxApplication LinuxApp => _linuxApp;
|
public LinuxApplication LinuxApp => _linuxApp;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the animation manager.
|
|
||||||
/// </summary>
|
|
||||||
public IAnimationManager AnimationManager
|
public IAnimationManager AnimationManager
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -53,9 +32,6 @@ public class LinuxMauiContext : IMauiContext
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the dispatcher for UI thread operations.
|
|
||||||
/// </summary>
|
|
||||||
public IDispatcher Dispatcher
|
public IDispatcher Dispatcher
|
||||||
{
|
{
|
||||||
get
|
get
|
||||||
@@ -65,117 +41,11 @@ public class LinuxMauiContext : IMauiContext
|
|||||||
return _dispatcher;
|
return _dispatcher;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
public LinuxMauiContext(IServiceProvider services, LinuxApplication linuxApp)
|
||||||
/// Scoped MAUI context for a specific window or view hierarchy.
|
|
||||||
/// </summary>
|
|
||||||
public class ScopedLinuxMauiContext : IMauiContext
|
|
||||||
{
|
|
||||||
private readonly LinuxMauiContext _parent;
|
|
||||||
|
|
||||||
public ScopedLinuxMauiContext(LinuxMauiContext parent)
|
|
||||||
{
|
{
|
||||||
_parent = parent ?? throw new ArgumentNullException(nameof(parent));
|
_services = services ?? throw new ArgumentNullException(nameof(services));
|
||||||
}
|
_linuxApp = linuxApp ?? throw new ArgumentNullException(nameof(linuxApp));
|
||||||
|
_handlers = services.GetRequiredService<IMauiHandlersFactory>();
|
||||||
public IServiceProvider Services => _parent.Services;
|
|
||||||
public IMauiHandlersFactory Handlers => _parent.Handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Linux animation manager.
|
|
||||||
/// </summary>
|
|
||||||
internal class LinuxAnimationManager : IAnimationManager
|
|
||||||
{
|
|
||||||
private readonly List<Microsoft.Maui.Animations.Animation> _animations = new();
|
|
||||||
private readonly ITicker _ticker;
|
|
||||||
|
|
||||||
public LinuxAnimationManager(ITicker ticker)
|
|
||||||
{
|
|
||||||
_ticker = ticker;
|
|
||||||
_ticker.Fire = OnTickerFire;
|
|
||||||
}
|
|
||||||
|
|
||||||
public double SpeedModifier { get; set; } = 1.0;
|
|
||||||
public bool AutoStartTicker { get; set; } = true;
|
|
||||||
|
|
||||||
public ITicker Ticker => _ticker;
|
|
||||||
|
|
||||||
public void Add(Microsoft.Maui.Animations.Animation animation)
|
|
||||||
{
|
|
||||||
_animations.Add(animation);
|
|
||||||
|
|
||||||
if (AutoStartTicker && !_ticker.IsRunning)
|
|
||||||
{
|
|
||||||
_ticker.Start();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Remove(Microsoft.Maui.Animations.Animation animation)
|
|
||||||
{
|
|
||||||
_animations.Remove(animation);
|
|
||||||
|
|
||||||
if (_animations.Count == 0 && _ticker.IsRunning)
|
|
||||||
{
|
|
||||||
_ticker.Stop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnTickerFire()
|
|
||||||
{
|
|
||||||
var animations = _animations.ToArray();
|
|
||||||
foreach (var animation in animations)
|
|
||||||
{
|
|
||||||
animation.Tick(16.0 / 1000.0 * SpeedModifier); // ~60fps
|
|
||||||
if (animation.HasFinished)
|
|
||||||
{
|
|
||||||
Remove(animation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Linux ticker for animation timing.
|
|
||||||
/// </summary>
|
|
||||||
internal class LinuxTicker : ITicker
|
|
||||||
{
|
|
||||||
private Timer? _timer;
|
|
||||||
private bool _isRunning;
|
|
||||||
private int _maxFps = 60;
|
|
||||||
|
|
||||||
public bool IsRunning => _isRunning;
|
|
||||||
|
|
||||||
public bool SystemEnabled => true;
|
|
||||||
|
|
||||||
public int MaxFps
|
|
||||||
{
|
|
||||||
get => _maxFps;
|
|
||||||
set => _maxFps = Math.Max(1, Math.Min(120, value));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Action? Fire { get; set; }
|
|
||||||
|
|
||||||
public void Start()
|
|
||||||
{
|
|
||||||
if (_isRunning)
|
|
||||||
return;
|
|
||||||
|
|
||||||
_isRunning = true;
|
|
||||||
var interval = TimeSpan.FromMilliseconds(1000.0 / _maxFps);
|
|
||||||
_timer = new Timer(OnTimerCallback, null, TimeSpan.Zero, interval);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Stop()
|
|
||||||
{
|
|
||||||
_isRunning = false;
|
|
||||||
_timer?.Dispose();
|
|
||||||
_timer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnTimerCallback(object? state)
|
|
||||||
{
|
|
||||||
Fire?.Invoke();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,10 @@
|
|||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Maui.Hosting;
|
|
||||||
using Microsoft.Maui.Controls;
|
using Microsoft.Maui.Controls;
|
||||||
using Microsoft.Maui.Platform;
|
using Microsoft.Maui.Controls.Hosting;
|
||||||
|
using Microsoft.Maui.Hosting;
|
||||||
|
using Microsoft.Maui.Platform.Linux.Services;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
|
|
||||||
namespace Microsoft.Maui.Platform.Linux.Hosting;
|
namespace Microsoft.Maui.Platform.Linux.Hosting;
|
||||||
@@ -44,6 +45,10 @@ public static class LinuxProgramHost
|
|||||||
?? new LinuxApplicationOptions();
|
?? new LinuxApplicationOptions();
|
||||||
ParseCommandLineOptions(args, options);
|
ParseCommandLineOptions(args, options);
|
||||||
|
|
||||||
|
// Initialize GTK for WebView support
|
||||||
|
GtkHostService.Instance.Initialize(options.Title, options.Width, options.Height);
|
||||||
|
Console.WriteLine("[LinuxProgramHost] GTK initialized for WebView support");
|
||||||
|
|
||||||
// Create Linux application
|
// Create Linux application
|
||||||
using var linuxApp = new LinuxApplication();
|
using var linuxApp = new LinuxApplication();
|
||||||
linuxApp.Initialize(options);
|
linuxApp.Initialize(options);
|
||||||
|
|||||||
47
Hosting/LinuxTicker.cs
Normal file
47
Hosting/LinuxTicker.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
// 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.Animations;
|
||||||
|
|
||||||
|
namespace Microsoft.Maui.Platform.Linux.Hosting;
|
||||||
|
|
||||||
|
internal class LinuxTicker : ITicker
|
||||||
|
{
|
||||||
|
private Timer? _timer;
|
||||||
|
private bool _isRunning;
|
||||||
|
private int _maxFps = 60;
|
||||||
|
|
||||||
|
public bool IsRunning => _isRunning;
|
||||||
|
|
||||||
|
public bool SystemEnabled => true;
|
||||||
|
|
||||||
|
public int MaxFps
|
||||||
|
{
|
||||||
|
get => _maxFps;
|
||||||
|
set => _maxFps = Math.Max(1, Math.Min(120, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Action? Fire { get; set; }
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
if (!_isRunning)
|
||||||
|
{
|
||||||
|
_isRunning = true;
|
||||||
|
var period = TimeSpan.FromMilliseconds(1000.0 / _maxFps);
|
||||||
|
_timer = new Timer(OnTimerCallback, null, TimeSpan.Zero, period);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Stop()
|
||||||
|
{
|
||||||
|
_isRunning = false;
|
||||||
|
_timer?.Dispose();
|
||||||
|
_timer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTimerCallback(object? state)
|
||||||
|
{
|
||||||
|
Fire?.Invoke();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
|
||||||
|
using System.Reflection;
|
||||||
using Microsoft.Maui.Controls;
|
using Microsoft.Maui.Controls;
|
||||||
|
using Microsoft.Maui.Graphics;
|
||||||
using Microsoft.Maui.Platform;
|
using Microsoft.Maui.Platform;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
|
|
||||||
@@ -198,9 +200,28 @@ public class LinuxViewRenderer
|
|||||||
FlyoutBehavior.Locked => ShellFlyoutBehavior.Locked,
|
FlyoutBehavior.Locked => ShellFlyoutBehavior.Locked,
|
||||||
FlyoutBehavior.Disabled => ShellFlyoutBehavior.Disabled,
|
FlyoutBehavior.Disabled => ShellFlyoutBehavior.Disabled,
|
||||||
_ => ShellFlyoutBehavior.Flyout
|
_ => ShellFlyoutBehavior.Flyout
|
||||||
}
|
},
|
||||||
|
MauiShell = shell
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Apply shell colors based on theme
|
||||||
|
ApplyShellColors(skiaShell, shell);
|
||||||
|
|
||||||
|
// Render flyout header if present
|
||||||
|
if (shell.FlyoutHeader is View headerView)
|
||||||
|
{
|
||||||
|
var skiaHeader = RenderView(headerView);
|
||||||
|
if (skiaHeader != null)
|
||||||
|
{
|
||||||
|
skiaShell.FlyoutHeaderView = skiaHeader;
|
||||||
|
skiaShell.FlyoutHeaderHeight = (float)(headerView.HeightRequest > 0 ? headerView.HeightRequest : 140.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set flyout footer with version info
|
||||||
|
var version = Assembly.GetEntryAssembly()?.GetName().Version;
|
||||||
|
skiaShell.FlyoutFooterText = $"Version {version?.Major ?? 1}.{version?.Minor ?? 0}.{version?.Build ?? 0}";
|
||||||
|
|
||||||
// Process shell items into sections
|
// Process shell items into sections
|
||||||
foreach (var item in shell.Items)
|
foreach (var item in shell.Items)
|
||||||
{
|
{
|
||||||
@@ -210,6 +231,10 @@ public class LinuxViewRenderer
|
|||||||
// Store reference to SkiaShell for navigation
|
// Store reference to SkiaShell for navigation
|
||||||
CurrentSkiaShell = skiaShell;
|
CurrentSkiaShell = skiaShell;
|
||||||
|
|
||||||
|
// Set up content renderer and color refresher delegates
|
||||||
|
skiaShell.ContentRenderer = CreateShellContentPage;
|
||||||
|
skiaShell.ColorRefresher = ApplyShellColors;
|
||||||
|
|
||||||
// Subscribe to MAUI Shell navigation events to update SkiaShell
|
// Subscribe to MAUI Shell navigation events to update SkiaShell
|
||||||
shell.Navigated += OnShellNavigated;
|
shell.Navigated += OnShellNavigated;
|
||||||
shell.Navigating += (s, e) => Console.WriteLine($"[Navigation] Navigating: {e.Target}");
|
shell.Navigating += (s, e) => Console.WriteLine($"[Navigation] Navigating: {e.Target}");
|
||||||
@@ -223,6 +248,61 @@ public class LinuxViewRenderer
|
|||||||
return skiaShell;
|
return skiaShell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Applies shell colors based on the current theme (dark/light mode).
|
||||||
|
/// </summary>
|
||||||
|
private static void ApplyShellColors(SkiaShell skiaShell, Shell shell)
|
||||||
|
{
|
||||||
|
bool isDark = Application.Current?.UserAppTheme == AppTheme.Dark;
|
||||||
|
Console.WriteLine($"[ApplyShellColors] Theme is: {(isDark ? "Dark" : "Light")}");
|
||||||
|
|
||||||
|
// Flyout background color
|
||||||
|
if (shell.FlyoutBackgroundColor != null && shell.FlyoutBackgroundColor != Colors.Transparent)
|
||||||
|
{
|
||||||
|
var color = shell.FlyoutBackgroundColor;
|
||||||
|
skiaShell.FlyoutBackgroundColor = new SKColor(
|
||||||
|
(byte)(color.Red * 255f),
|
||||||
|
(byte)(color.Green * 255f),
|
||||||
|
(byte)(color.Blue * 255f),
|
||||||
|
(byte)(color.Alpha * 255f));
|
||||||
|
Console.WriteLine($"[ApplyShellColors] FlyoutBackgroundColor from MAUI: {skiaShell.FlyoutBackgroundColor}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
skiaShell.FlyoutBackgroundColor = isDark
|
||||||
|
? new SKColor(30, 30, 30)
|
||||||
|
: new SKColor(255, 255, 255);
|
||||||
|
Console.WriteLine($"[ApplyShellColors] Using default FlyoutBackgroundColor: {skiaShell.FlyoutBackgroundColor}");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flyout text color
|
||||||
|
skiaShell.FlyoutTextColor = isDark
|
||||||
|
? new SKColor(224, 224, 224)
|
||||||
|
: new SKColor(33, 33, 33);
|
||||||
|
Console.WriteLine($"[ApplyShellColors] FlyoutTextColor: {skiaShell.FlyoutTextColor}");
|
||||||
|
|
||||||
|
// Content background color
|
||||||
|
skiaShell.ContentBackgroundColor = isDark
|
||||||
|
? new SKColor(18, 18, 18)
|
||||||
|
: new SKColor(250, 250, 250);
|
||||||
|
Console.WriteLine($"[ApplyShellColors] ContentBackgroundColor: {skiaShell.ContentBackgroundColor}");
|
||||||
|
|
||||||
|
// NavBar background color
|
||||||
|
if (shell.BackgroundColor != null && shell.BackgroundColor != Colors.Transparent)
|
||||||
|
{
|
||||||
|
var color = shell.BackgroundColor;
|
||||||
|
skiaShell.NavBarBackgroundColor = new SKColor(
|
||||||
|
(byte)(color.Red * 255f),
|
||||||
|
(byte)(color.Green * 255f),
|
||||||
|
(byte)(color.Blue * 255f),
|
||||||
|
(byte)(color.Alpha * 255f));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
skiaShell.NavBarBackgroundColor = new SKColor(33, 150, 243); // Material blue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handles MAUI Shell navigation events and updates SkiaShell accordingly.
|
/// Handles MAUI Shell navigation events and updates SkiaShell accordingly.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -290,7 +370,8 @@ public class LinuxViewRenderer
|
|||||||
var shellContent = new ShellContent
|
var shellContent = new ShellContent
|
||||||
{
|
{
|
||||||
Title = content.Title ?? shellSection.Title ?? flyoutItem.Title ?? "",
|
Title = content.Title ?? shellSection.Title ?? flyoutItem.Title ?? "",
|
||||||
Route = content.Route ?? ""
|
Route = content.Route ?? "",
|
||||||
|
MauiShellContent = content
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create the page content
|
// Create the page content
|
||||||
@@ -328,7 +409,8 @@ public class LinuxViewRenderer
|
|||||||
var shellContent = new ShellContent
|
var shellContent = new ShellContent
|
||||||
{
|
{
|
||||||
Title = content.Title ?? tab.Title ?? "",
|
Title = content.Title ?? tab.Title ?? "",
|
||||||
Route = content.Route ?? ""
|
Route = content.Route ?? "",
|
||||||
|
MauiShellContent = content
|
||||||
};
|
};
|
||||||
|
|
||||||
var pageContent = CreateShellContentPage(content);
|
var pageContent = CreateShellContentPage(content);
|
||||||
@@ -359,7 +441,8 @@ public class LinuxViewRenderer
|
|||||||
var shellContent = new ShellContent
|
var shellContent = new ShellContent
|
||||||
{
|
{
|
||||||
Title = content.Title ?? "",
|
Title = content.Title ?? "",
|
||||||
Route = content.Route ?? ""
|
Route = content.Route ?? "",
|
||||||
|
MauiShellContent = content
|
||||||
};
|
};
|
||||||
|
|
||||||
var pageContent = CreateShellContentPage(content);
|
var pageContent = CreateShellContentPage(content);
|
||||||
@@ -402,17 +485,38 @@ public class LinuxViewRenderer
|
|||||||
var contentView = RenderView(cp.Content);
|
var contentView = RenderView(cp.Content);
|
||||||
if (contentView != null)
|
if (contentView != null)
|
||||||
{
|
{
|
||||||
if (contentView is SkiaScrollView)
|
// Get page background color if set
|
||||||
|
SKColor? bgColor = null;
|
||||||
|
if (cp.BackgroundColor != null && cp.BackgroundColor != Colors.Transparent)
|
||||||
{
|
{
|
||||||
return contentView;
|
var color = cp.BackgroundColor;
|
||||||
|
bgColor = new SKColor(
|
||||||
|
(byte)(color.Red * 255f),
|
||||||
|
(byte)(color.Green * 255f),
|
||||||
|
(byte)(color.Blue * 255f),
|
||||||
|
(byte)(color.Alpha * 255f));
|
||||||
|
Console.WriteLine($"[CreateShellContentPage] Page BackgroundColor: {bgColor}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contentView is SkiaScrollView scrollView)
|
||||||
|
{
|
||||||
|
if (bgColor.HasValue)
|
||||||
|
{
|
||||||
|
scrollView.BackgroundColor = bgColor.Value;
|
||||||
|
}
|
||||||
|
return scrollView;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var scrollView = new SkiaScrollView
|
var newScrollView = new SkiaScrollView
|
||||||
{
|
{
|
||||||
Content = contentView
|
Content = contentView
|
||||||
};
|
};
|
||||||
return scrollView;
|
if (bgColor.HasValue)
|
||||||
|
{
|
||||||
|
newScrollView.BackgroundColor = bgColor.Value;
|
||||||
|
}
|
||||||
|
return newScrollView;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,190 +0,0 @@
|
|||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
// Copyright (c) 2025 MarketAlly LLC
|
|
||||||
|
|
||||||
using Microsoft.Maui;
|
|
||||||
using Microsoft.Maui.Controls;
|
|
||||||
using Microsoft.Maui.Controls.Hosting;
|
|
||||||
using Microsoft.Maui.Hosting;
|
|
||||||
using Microsoft.Maui.Platform.Linux;
|
|
||||||
using Microsoft.Maui.Platform.Linux.Handlers;
|
|
||||||
|
|
||||||
namespace OpenMaui.Platform.Linux.Hosting;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Extension methods for configuring OpenMaui Linux platform in a MAUI application.
|
|
||||||
/// This enables full XAML support by registering Linux-specific handlers.
|
|
||||||
/// </summary>
|
|
||||||
public static class MauiAppBuilderExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Configures the application to use OpenMaui Linux platform with full XAML support.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="builder">The MAUI app builder.</param>
|
|
||||||
/// <returns>The configured MAUI app builder.</returns>
|
|
||||||
/// <example>
|
|
||||||
/// <code>
|
|
||||||
/// var builder = MauiApp.CreateBuilder();
|
|
||||||
/// builder
|
|
||||||
/// .UseMauiApp<App>()
|
|
||||||
/// .UseOpenMauiLinux(); // Enable Linux support with XAML
|
|
||||||
/// </code>
|
|
||||||
/// </example>
|
|
||||||
public static MauiAppBuilder UseOpenMauiLinux(this MauiAppBuilder builder)
|
|
||||||
{
|
|
||||||
builder.ConfigureMauiHandlers(handlers =>
|
|
||||||
{
|
|
||||||
// Register all Linux platform handlers
|
|
||||||
// These map MAUI virtual views to our Skia platform views
|
|
||||||
|
|
||||||
// Basic Controls
|
|
||||||
handlers.AddHandler<Button, ButtonHandler>();
|
|
||||||
handlers.AddHandler<Label, LabelHandler>();
|
|
||||||
handlers.AddHandler<Entry, EntryHandler>();
|
|
||||||
handlers.AddHandler<Editor, EditorHandler>();
|
|
||||||
handlers.AddHandler<CheckBox, CheckBoxHandler>();
|
|
||||||
handlers.AddHandler<Switch, SwitchHandler>();
|
|
||||||
handlers.AddHandler<RadioButton, RadioButtonHandler>();
|
|
||||||
|
|
||||||
// Selection Controls
|
|
||||||
handlers.AddHandler<Slider, SliderHandler>();
|
|
||||||
handlers.AddHandler<Stepper, StepperHandler>();
|
|
||||||
handlers.AddHandler<Picker, PickerHandler>();
|
|
||||||
handlers.AddHandler<DatePicker, DatePickerHandler>();
|
|
||||||
handlers.AddHandler<TimePicker, TimePickerHandler>();
|
|
||||||
|
|
||||||
// Display Controls
|
|
||||||
handlers.AddHandler<Image, ImageHandler>();
|
|
||||||
handlers.AddHandler<ImageButton, ImageButtonHandler>();
|
|
||||||
handlers.AddHandler<ActivityIndicator, ActivityIndicatorHandler>();
|
|
||||||
handlers.AddHandler<ProgressBar, ProgressBarHandler>();
|
|
||||||
|
|
||||||
// Layout Controls
|
|
||||||
handlers.AddHandler<Border, BorderHandler>();
|
|
||||||
|
|
||||||
// Collection Controls
|
|
||||||
handlers.AddHandler<CollectionView, CollectionViewHandler>();
|
|
||||||
|
|
||||||
// Navigation Controls
|
|
||||||
handlers.AddHandler<NavigationPage, NavigationPageHandler>();
|
|
||||||
handlers.AddHandler<TabbedPage, TabbedPageHandler>();
|
|
||||||
handlers.AddHandler<FlyoutPage, FlyoutPageHandler>();
|
|
||||||
handlers.AddHandler<Shell, ShellHandler>();
|
|
||||||
|
|
||||||
// Page Controls
|
|
||||||
handlers.AddHandler<Page, PageHandler>();
|
|
||||||
handlers.AddHandler<ContentPage, PageHandler>();
|
|
||||||
|
|
||||||
// Graphics
|
|
||||||
handlers.AddHandler<GraphicsView, GraphicsViewHandler>();
|
|
||||||
|
|
||||||
// Search
|
|
||||||
handlers.AddHandler<SearchBar, SearchBarHandler>();
|
|
||||||
|
|
||||||
// Web
|
|
||||||
handlers.AddHandler<WebView, WebViewHandler>();
|
|
||||||
|
|
||||||
// Window
|
|
||||||
handlers.AddHandler<Window, WindowHandler>();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Register Linux-specific services
|
|
||||||
builder.Services.AddSingleton<ILinuxPlatformServices, LinuxPlatformServices>();
|
|
||||||
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Configures the application to use OpenMaui Linux with custom handler configuration.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="builder">The MAUI app builder.</param>
|
|
||||||
/// <param name="configureHandlers">Action to configure additional handlers.</param>
|
|
||||||
/// <returns>The configured MAUI app builder.</returns>
|
|
||||||
public static MauiAppBuilder UseOpenMauiLinux(
|
|
||||||
this MauiAppBuilder builder,
|
|
||||||
Action<IMauiHandlersCollection>? configureHandlers)
|
|
||||||
{
|
|
||||||
builder.UseOpenMauiLinux();
|
|
||||||
|
|
||||||
if (configureHandlers != null)
|
|
||||||
{
|
|
||||||
builder.ConfigureMauiHandlers(configureHandlers);
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Interface for Linux platform services.
|
|
||||||
/// </summary>
|
|
||||||
public interface ILinuxPlatformServices
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the display server type (X11 or Wayland).
|
|
||||||
/// </summary>
|
|
||||||
DisplayServerType DisplayServer { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the current DPI scale factor.
|
|
||||||
/// </summary>
|
|
||||||
float ScaleFactor { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets whether high contrast mode is enabled.
|
|
||||||
/// </summary>
|
|
||||||
bool IsHighContrastEnabled { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Display server types supported by OpenMaui.
|
|
||||||
/// </summary>
|
|
||||||
public enum DisplayServerType
|
|
||||||
{
|
|
||||||
/// <summary>X11 display server.</summary>
|
|
||||||
X11,
|
|
||||||
/// <summary>Wayland display server.</summary>
|
|
||||||
Wayland,
|
|
||||||
/// <summary>Auto-detected display server.</summary>
|
|
||||||
Auto
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Implementation of Linux platform services.
|
|
||||||
/// </summary>
|
|
||||||
internal class LinuxPlatformServices : ILinuxPlatformServices
|
|
||||||
{
|
|
||||||
public DisplayServerType DisplayServer => DetectDisplayServer();
|
|
||||||
public float ScaleFactor => DetectScaleFactor();
|
|
||||||
public bool IsHighContrastEnabled => DetectHighContrast();
|
|
||||||
|
|
||||||
private static DisplayServerType DetectDisplayServer()
|
|
||||||
{
|
|
||||||
var waylandDisplay = Environment.GetEnvironmentVariable("WAYLAND_DISPLAY");
|
|
||||||
if (!string.IsNullOrEmpty(waylandDisplay))
|
|
||||||
return DisplayServerType.Wayland;
|
|
||||||
|
|
||||||
var display = Environment.GetEnvironmentVariable("DISPLAY");
|
|
||||||
if (!string.IsNullOrEmpty(display))
|
|
||||||
return DisplayServerType.X11;
|
|
||||||
|
|
||||||
return DisplayServerType.Auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static float DetectScaleFactor()
|
|
||||||
{
|
|
||||||
// Try GDK_SCALE first
|
|
||||||
var gdkScale = Environment.GetEnvironmentVariable("GDK_SCALE");
|
|
||||||
if (float.TryParse(gdkScale, out var scale))
|
|
||||||
return scale;
|
|
||||||
|
|
||||||
// Default to 1.0
|
|
||||||
return 1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool DetectHighContrast()
|
|
||||||
{
|
|
||||||
var highContrast = Environment.GetEnvironmentVariable("GTK_THEME");
|
|
||||||
return highContrast?.Contains("HighContrast", StringComparison.OrdinalIgnoreCase) ?? false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -28,7 +28,7 @@ public static class MauiHandlerExtensions
|
|||||||
[typeof(TimePicker)] = () => new TimePickerHandler(),
|
[typeof(TimePicker)] = () => new TimePickerHandler(),
|
||||||
[typeof(SearchBar)] = () => new SearchBarHandler(),
|
[typeof(SearchBar)] = () => new SearchBarHandler(),
|
||||||
[typeof(RadioButton)] = () => new RadioButtonHandler(),
|
[typeof(RadioButton)] = () => new RadioButtonHandler(),
|
||||||
[typeof(WebView)] = () => new WebViewHandler(),
|
[typeof(WebView)] = () => new GtkWebViewHandler(),
|
||||||
[typeof(Image)] = () => new ImageHandler(),
|
[typeof(Image)] = () => new ImageHandler(),
|
||||||
[typeof(ImageButton)] = () => new ImageButtonHandler(),
|
[typeof(ImageButton)] = () => new ImageButtonHandler(),
|
||||||
[typeof(BoxView)] = () => new BoxViewHandler(),
|
[typeof(BoxView)] = () => new BoxViewHandler(),
|
||||||
@@ -41,7 +41,7 @@ public static class MauiHandlerExtensions
|
|||||||
[typeof(VerticalStackLayout)] = () => new StackLayoutHandler(),
|
[typeof(VerticalStackLayout)] = () => new StackLayoutHandler(),
|
||||||
[typeof(HorizontalStackLayout)] = () => new StackLayoutHandler(),
|
[typeof(HorizontalStackLayout)] = () => new StackLayoutHandler(),
|
||||||
[typeof(AbsoluteLayout)] = () => new LayoutHandler(),
|
[typeof(AbsoluteLayout)] = () => new LayoutHandler(),
|
||||||
[typeof(FlexLayout)] = () => new FlexLayoutHandler(),
|
[typeof(FlexLayout)] = () => new LayoutHandler(),
|
||||||
[typeof(CollectionView)] = () => new CollectionViewHandler(),
|
[typeof(CollectionView)] = () => new CollectionViewHandler(),
|
||||||
[typeof(ListView)] = () => new CollectionViewHandler(),
|
[typeof(ListView)] = () => new CollectionViewHandler(),
|
||||||
[typeof(Page)] = () => new PageHandler(),
|
[typeof(Page)] = () => new PageHandler(),
|
||||||
|
|||||||
18
Hosting/ScopedLinuxMauiContext.cs
Normal file
18
Hosting/ScopedLinuxMauiContext.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// 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.Linux.Hosting;
|
||||||
|
|
||||||
|
public class ScopedLinuxMauiContext : IMauiContext
|
||||||
|
{
|
||||||
|
private readonly LinuxMauiContext _parent;
|
||||||
|
|
||||||
|
public IServiceProvider Services => _parent.Services;
|
||||||
|
|
||||||
|
public IMauiHandlersFactory Handlers => _parent.Handlers;
|
||||||
|
|
||||||
|
public ScopedLinuxMauiContext(LinuxMauiContext parent)
|
||||||
|
{
|
||||||
|
_parent = parent ?? throw new ArgumentNullException(nameof(parent));
|
||||||
|
}
|
||||||
|
}
|
||||||
25
Interop/ClientMessageData.cs
Normal file
25
Interop/ClientMessageData.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// 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;
|
||||||
|
|
||||||
|
namespace Microsoft.Maui.Platform.Linux.Interop;
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Explicit)]
|
||||||
|
public struct ClientMessageData
|
||||||
|
{
|
||||||
|
[FieldOffset(0)]
|
||||||
|
public long L0;
|
||||||
|
|
||||||
|
[FieldOffset(8)]
|
||||||
|
public long L1;
|
||||||
|
|
||||||
|
[FieldOffset(16)]
|
||||||
|
public long L2;
|
||||||
|
|
||||||
|
[FieldOffset(24)]
|
||||||
|
public long L3;
|
||||||
|
|
||||||
|
[FieldOffset(32)]
|
||||||
|
public long L4;
|
||||||
|
}
|
||||||
226
Interop/X11.cs
Normal file
226
Interop/X11.cs
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
// 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;
|
||||||
|
|
||||||
|
namespace Microsoft.Maui.Platform.Linux.Interop;
|
||||||
|
|
||||||
|
internal static partial class X11
|
||||||
|
{
|
||||||
|
private const string LibX11 = "libX11.so.6";
|
||||||
|
|
||||||
|
public const int ZPixmap = 2;
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial IntPtr XOpenDisplay(IntPtr displayName);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XCloseDisplay(IntPtr display);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XDefaultScreen(IntPtr display);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial IntPtr XRootWindow(IntPtr display, int screenNumber);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XDisplayWidth(IntPtr display, int screenNumber);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XDisplayHeight(IntPtr display, int screenNumber);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XDefaultDepth(IntPtr display, int screenNumber);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial IntPtr XDefaultVisual(IntPtr display, int screenNumber);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial IntPtr XDefaultColormap(IntPtr display, int screenNumber);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XFlush(IntPtr display);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XSync(IntPtr display, [MarshalAs(UnmanagedType.Bool)] bool discard);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial IntPtr XCreateSimpleWindow(
|
||||||
|
IntPtr display, IntPtr parent,
|
||||||
|
int x, int y, uint width, uint height,
|
||||||
|
uint borderWidth, ulong border, ulong background);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial IntPtr XCreateWindow(
|
||||||
|
IntPtr display, IntPtr parent,
|
||||||
|
int x, int y, uint width, uint height, uint borderWidth,
|
||||||
|
int depth, uint windowClass, IntPtr visual,
|
||||||
|
ulong valueMask, ref XSetWindowAttributes attributes);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XDestroyWindow(IntPtr display, IntPtr window);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XMapWindow(IntPtr display, IntPtr window);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XUnmapWindow(IntPtr display, IntPtr window);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XMoveWindow(IntPtr display, IntPtr window, int x, int y);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XResizeWindow(IntPtr display, IntPtr window, uint width, uint height);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, uint width, uint height);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11, StringMarshalling = StringMarshalling.Utf8)]
|
||||||
|
public static partial int XStoreName(IntPtr display, IntPtr window, string windowName);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XRaiseWindow(IntPtr display, IntPtr window);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XLowerWindow(IntPtr display, IntPtr window);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XSelectInput(IntPtr display, IntPtr window, long eventMask);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XNextEvent(IntPtr display, out XEvent eventReturn);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XPeekEvent(IntPtr display, out XEvent eventReturn);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XPending(IntPtr display);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public static partial bool XCheckTypedWindowEvent(IntPtr display, IntPtr window, int eventType, out XEvent eventReturn);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XSendEvent(
|
||||||
|
IntPtr display, IntPtr window,
|
||||||
|
[MarshalAs(UnmanagedType.Bool)] bool propagate,
|
||||||
|
long eventMask, ref XEvent eventSend);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial ulong XKeycodeToKeysym(IntPtr display, int keycode, int index);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XLookupString(
|
||||||
|
ref XKeyEvent keyEvent, IntPtr bufferReturn, int bytesBuffer,
|
||||||
|
out ulong keysymReturn, IntPtr statusInOut);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XGrabKeyboard(
|
||||||
|
IntPtr display, IntPtr grabWindow,
|
||||||
|
[MarshalAs(UnmanagedType.Bool)] bool ownerEvents,
|
||||||
|
int pointerMode, int keyboardMode, ulong time);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XUngrabKeyboard(IntPtr display, ulong time);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XGrabPointer(
|
||||||
|
IntPtr display, IntPtr grabWindow,
|
||||||
|
[MarshalAs(UnmanagedType.Bool)] bool ownerEvents,
|
||||||
|
uint eventMask, int pointerMode, int keyboardMode,
|
||||||
|
IntPtr confineTo, IntPtr cursor, ulong time);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XUngrabPointer(IntPtr display, ulong time);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
[return: MarshalAs(UnmanagedType.Bool)]
|
||||||
|
public static partial bool XQueryPointer(
|
||||||
|
IntPtr display, IntPtr window,
|
||||||
|
out IntPtr rootReturn, out IntPtr childReturn,
|
||||||
|
out int rootX, out int rootY,
|
||||||
|
out int winX, out int winY,
|
||||||
|
out uint maskReturn);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XWarpPointer(
|
||||||
|
IntPtr display, IntPtr srcWindow, IntPtr destWindow,
|
||||||
|
int srcX, int srcY, uint srcWidth, uint srcHeight,
|
||||||
|
int destX, int destY);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11, StringMarshalling = StringMarshalling.Utf8)]
|
||||||
|
public static partial IntPtr XInternAtom(IntPtr display, string atomName, [MarshalAs(UnmanagedType.Bool)] bool onlyIfExists);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XChangeProperty(
|
||||||
|
IntPtr display, IntPtr window, IntPtr property, IntPtr type,
|
||||||
|
int format, int mode, IntPtr data, int nelements);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XGetWindowProperty(
|
||||||
|
IntPtr display, IntPtr window, IntPtr property,
|
||||||
|
long longOffset, long longLength,
|
||||||
|
[MarshalAs(UnmanagedType.Bool)] bool delete, IntPtr reqType,
|
||||||
|
out IntPtr actualTypeReturn, out int actualFormatReturn,
|
||||||
|
out IntPtr nitemsReturn, out IntPtr bytesAfterReturn,
|
||||||
|
out IntPtr propReturn);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, ulong time);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XConvertSelection(
|
||||||
|
IntPtr display, IntPtr selection, IntPtr target,
|
||||||
|
IntPtr property, IntPtr requestor, ulong time);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XFree(IntPtr data);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial IntPtr XCreateGC(IntPtr display, IntPtr drawable, ulong valueMask, IntPtr values);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XFreeGC(IntPtr display, IntPtr gc);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XCopyArea(
|
||||||
|
IntPtr display, IntPtr src, IntPtr dest, IntPtr gc,
|
||||||
|
int srcX, int srcY, uint width, uint height, int destX, int destY);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial IntPtr XCreateFontCursor(IntPtr display, uint shape);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XFreeCursor(IntPtr display, IntPtr cursor);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XUndefineCursor(IntPtr display, IntPtr window);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XConnectionNumber(IntPtr display);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial IntPtr XCreateImage(
|
||||||
|
IntPtr display, IntPtr visual, uint depth, int format, int offset,
|
||||||
|
IntPtr data, uint width, uint height, int bitmapPad, int bytesPerLine);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XPutImage(
|
||||||
|
IntPtr display, IntPtr drawable, IntPtr gc, IntPtr image,
|
||||||
|
int srcX, int srcY, int destX, int destY, uint width, uint height);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial int XDestroyImage(IntPtr image);
|
||||||
|
|
||||||
|
[LibraryImport(LibX11)]
|
||||||
|
public static partial IntPtr XDefaultGC(IntPtr display, int screen);
|
||||||
|
}
|
||||||
@@ -1,482 +0,0 @@
|
|||||||
// 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;
|
|
||||||
|
|
||||||
namespace Microsoft.Maui.Platform.Linux.Interop;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// P/Invoke declarations for X11 library functions.
|
|
||||||
/// </summary>
|
|
||||||
internal static partial class X11
|
|
||||||
{
|
|
||||||
private const string LibX11 = "libX11.so.6";
|
|
||||||
private const string LibXext = "libXext.so.6";
|
|
||||||
|
|
||||||
#region Display and Screen
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial IntPtr XOpenDisplay(IntPtr displayName);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XCloseDisplay(IntPtr display);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XDefaultScreen(IntPtr display);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial IntPtr XRootWindow(IntPtr display, int screenNumber);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XDisplayWidth(IntPtr display, int screenNumber);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XDisplayHeight(IntPtr display, int screenNumber);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XDefaultDepth(IntPtr display, int screenNumber);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial IntPtr XDefaultVisual(IntPtr display, int screenNumber);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial IntPtr XDefaultColormap(IntPtr display, int screenNumber);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XFlush(IntPtr display);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XSync(IntPtr display, [MarshalAs(UnmanagedType.Bool)] bool discard);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Window Creation and Management
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial IntPtr XCreateSimpleWindow(
|
|
||||||
IntPtr display,
|
|
||||||
IntPtr parent,
|
|
||||||
int x, int y,
|
|
||||||
uint width, uint height,
|
|
||||||
uint borderWidth,
|
|
||||||
ulong border,
|
|
||||||
ulong background);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial IntPtr XCreateWindow(
|
|
||||||
IntPtr display,
|
|
||||||
IntPtr parent,
|
|
||||||
int x, int y,
|
|
||||||
uint width, uint height,
|
|
||||||
uint borderWidth,
|
|
||||||
int depth,
|
|
||||||
uint windowClass,
|
|
||||||
IntPtr visual,
|
|
||||||
ulong valueMask,
|
|
||||||
ref XSetWindowAttributes attributes);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XDestroyWindow(IntPtr display, IntPtr window);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XMapWindow(IntPtr display, IntPtr window);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XUnmapWindow(IntPtr display, IntPtr window);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XMoveWindow(IntPtr display, IntPtr window, int x, int y);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XResizeWindow(IntPtr display, IntPtr window, uint width, uint height);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, uint width, uint height);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11, StringMarshalling = StringMarshalling.Utf8)]
|
|
||||||
public static partial int XStoreName(IntPtr display, IntPtr window, string windowName);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XRaiseWindow(IntPtr display, IntPtr window);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XLowerWindow(IntPtr display, IntPtr window);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Event Handling
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XSelectInput(IntPtr display, IntPtr window, long eventMask);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XNextEvent(IntPtr display, out XEvent eventReturn);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XPeekEvent(IntPtr display, out XEvent eventReturn);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XPending(IntPtr display);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
|
||||||
public static partial bool XCheckTypedWindowEvent(IntPtr display, IntPtr window, int eventType, out XEvent eventReturn);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XSendEvent(IntPtr display, IntPtr window, [MarshalAs(UnmanagedType.Bool)] bool propagate, long eventMask, ref XEvent eventSend);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Keyboard
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial ulong XKeycodeToKeysym(IntPtr display, int keycode, int index);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XLookupString(ref XKeyEvent keyEvent, IntPtr bufferReturn, int bytesBuffer, out ulong keysymReturn, IntPtr statusInOut);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XGrabKeyboard(IntPtr display, IntPtr grabWindow, [MarshalAs(UnmanagedType.Bool)] bool ownerEvents, int pointerMode, int keyboardMode, ulong time);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XUngrabKeyboard(IntPtr display, ulong time);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Mouse/Pointer
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XGrabPointer(IntPtr display, IntPtr grabWindow, [MarshalAs(UnmanagedType.Bool)] bool ownerEvents, uint eventMask, int pointerMode, int keyboardMode, IntPtr confineTo, IntPtr cursor, ulong time);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XUngrabPointer(IntPtr display, ulong time);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
[return: MarshalAs(UnmanagedType.Bool)]
|
|
||||||
public static partial bool XQueryPointer(IntPtr display, IntPtr window, out IntPtr rootReturn, out IntPtr childReturn, out int rootX, out int rootY, out int winX, out int winY, out uint maskReturn);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XWarpPointer(IntPtr display, IntPtr srcWindow, IntPtr destWindow, int srcX, int srcY, uint srcWidth, uint srcHeight, int destX, int destY);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Atoms and Properties
|
|
||||||
|
|
||||||
[LibraryImport(LibX11, StringMarshalling = StringMarshalling.Utf8)]
|
|
||||||
public static partial IntPtr XInternAtom(IntPtr display, string atomName, [MarshalAs(UnmanagedType.Bool)] bool onlyIfExists);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, int mode, IntPtr data, int nelements);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XGetWindowProperty(IntPtr display, IntPtr window, IntPtr property, long longOffset, long longLength, [MarshalAs(UnmanagedType.Bool)] bool delete, IntPtr reqType, out IntPtr actualTypeReturn, out int actualFormatReturn, out IntPtr nitemsReturn, out IntPtr bytesAfterReturn, out IntPtr propReturn);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Clipboard/Selection
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, ulong time);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, ulong time);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Memory
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XFree(IntPtr data);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Graphics Context
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial IntPtr XCreateGC(IntPtr display, IntPtr drawable, ulong valueMask, IntPtr values);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XFreeGC(IntPtr display, IntPtr gc);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XCopyArea(IntPtr display, IntPtr src, IntPtr dest, IntPtr gc, int srcX, int srcY, uint width, uint height, int destX, int destY);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Cursor
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial IntPtr XCreateFontCursor(IntPtr display, uint shape);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XFreeCursor(IntPtr display, IntPtr cursor);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XUndefineCursor(IntPtr display, IntPtr window);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Connection
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XConnectionNumber(IntPtr display);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Image Functions
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial IntPtr XCreateImage(IntPtr display, IntPtr visual, uint depth, int format,
|
|
||||||
int offset, IntPtr data, uint width, uint height, int bitmapPad, int bytesPerLine);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XPutImage(IntPtr display, IntPtr drawable, IntPtr gc, IntPtr image,
|
|
||||||
int srcX, int srcY, int destX, int destY, uint width, uint height);
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial int XDestroyImage(IntPtr image);
|
|
||||||
|
|
||||||
|
|
||||||
[LibraryImport(LibX11)]
|
|
||||||
public static partial IntPtr XDefaultGC(IntPtr display, int screen);
|
|
||||||
|
|
||||||
public const int ZPixmap = 2;
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#region X11 Structures
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct XSetWindowAttributes
|
|
||||||
{
|
|
||||||
public IntPtr BackgroundPixmap;
|
|
||||||
public ulong BackgroundPixel;
|
|
||||||
public IntPtr BorderPixmap;
|
|
||||||
public ulong BorderPixel;
|
|
||||||
public int BitGravity;
|
|
||||||
public int WinGravity;
|
|
||||||
public int BackingStore;
|
|
||||||
public ulong BackingPlanes;
|
|
||||||
public ulong BackingPixel;
|
|
||||||
public int SaveUnder;
|
|
||||||
public long EventMask;
|
|
||||||
public long DoNotPropagateMask;
|
|
||||||
public int OverrideRedirect;
|
|
||||||
public IntPtr Colormap;
|
|
||||||
public IntPtr Cursor;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Explicit, Size = 192)]
|
|
||||||
public struct XEvent
|
|
||||||
{
|
|
||||||
[FieldOffset(0)] public int Type;
|
|
||||||
[FieldOffset(0)] public XKeyEvent KeyEvent;
|
|
||||||
[FieldOffset(0)] public XButtonEvent ButtonEvent;
|
|
||||||
[FieldOffset(0)] public XMotionEvent MotionEvent;
|
|
||||||
[FieldOffset(0)] public XConfigureEvent ConfigureEvent;
|
|
||||||
[FieldOffset(0)] public XExposeEvent ExposeEvent;
|
|
||||||
[FieldOffset(0)] public XClientMessageEvent ClientMessageEvent;
|
|
||||||
[FieldOffset(0)] public XCrossingEvent CrossingEvent;
|
|
||||||
[FieldOffset(0)] public XFocusChangeEvent FocusChangeEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct XKeyEvent
|
|
||||||
{
|
|
||||||
public int Type;
|
|
||||||
public ulong Serial;
|
|
||||||
public int SendEvent;
|
|
||||||
public IntPtr Display;
|
|
||||||
public IntPtr Window;
|
|
||||||
public IntPtr Root;
|
|
||||||
public IntPtr Subwindow;
|
|
||||||
public ulong Time;
|
|
||||||
public int X, Y;
|
|
||||||
public int XRoot, YRoot;
|
|
||||||
public uint State;
|
|
||||||
public uint Keycode;
|
|
||||||
public int SameScreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct XButtonEvent
|
|
||||||
{
|
|
||||||
public int Type;
|
|
||||||
public ulong Serial;
|
|
||||||
public int SendEvent;
|
|
||||||
public IntPtr Display;
|
|
||||||
public IntPtr Window;
|
|
||||||
public IntPtr Root;
|
|
||||||
public IntPtr Subwindow;
|
|
||||||
public ulong Time;
|
|
||||||
public int X, Y;
|
|
||||||
public int XRoot, YRoot;
|
|
||||||
public uint State;
|
|
||||||
public uint Button;
|
|
||||||
public int SameScreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct XMotionEvent
|
|
||||||
{
|
|
||||||
public int Type;
|
|
||||||
public ulong Serial;
|
|
||||||
public int SendEvent;
|
|
||||||
public IntPtr Display;
|
|
||||||
public IntPtr Window;
|
|
||||||
public IntPtr Root;
|
|
||||||
public IntPtr Subwindow;
|
|
||||||
public ulong Time;
|
|
||||||
public int X, Y;
|
|
||||||
public int XRoot, YRoot;
|
|
||||||
public uint State;
|
|
||||||
public byte IsHint;
|
|
||||||
public int SameScreen;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct XConfigureEvent
|
|
||||||
{
|
|
||||||
public int Type;
|
|
||||||
public ulong Serial;
|
|
||||||
public int SendEvent;
|
|
||||||
public IntPtr Display;
|
|
||||||
public IntPtr Event;
|
|
||||||
public IntPtr Window;
|
|
||||||
public int X, Y;
|
|
||||||
public int Width, Height;
|
|
||||||
public int BorderWidth;
|
|
||||||
public IntPtr Above;
|
|
||||||
public int OverrideRedirect;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct XExposeEvent
|
|
||||||
{
|
|
||||||
public int Type;
|
|
||||||
public ulong Serial;
|
|
||||||
public int SendEvent;
|
|
||||||
public IntPtr Display;
|
|
||||||
public IntPtr Window;
|
|
||||||
public int X, Y;
|
|
||||||
public int Width, Height;
|
|
||||||
public int Count;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct XClientMessageEvent
|
|
||||||
{
|
|
||||||
public int Type;
|
|
||||||
public ulong Serial;
|
|
||||||
public int SendEvent;
|
|
||||||
public IntPtr Display;
|
|
||||||
public IntPtr Window;
|
|
||||||
public IntPtr MessageType;
|
|
||||||
public int Format;
|
|
||||||
public ClientMessageData Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Explicit)]
|
|
||||||
public struct ClientMessageData
|
|
||||||
{
|
|
||||||
[FieldOffset(0)] public long L0;
|
|
||||||
[FieldOffset(8)] public long L1;
|
|
||||||
[FieldOffset(16)] public long L2;
|
|
||||||
[FieldOffset(24)] public long L3;
|
|
||||||
[FieldOffset(32)] public long L4;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct XCrossingEvent
|
|
||||||
{
|
|
||||||
public int Type;
|
|
||||||
public ulong Serial;
|
|
||||||
public int SendEvent;
|
|
||||||
public IntPtr Display;
|
|
||||||
public IntPtr Window;
|
|
||||||
public IntPtr Root;
|
|
||||||
public IntPtr Subwindow;
|
|
||||||
public ulong Time;
|
|
||||||
public int X, Y;
|
|
||||||
public int XRoot, YRoot;
|
|
||||||
public int Mode;
|
|
||||||
public int Detail;
|
|
||||||
public int SameScreen;
|
|
||||||
public int Focus;
|
|
||||||
public uint State;
|
|
||||||
}
|
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
|
||||||
public struct XFocusChangeEvent
|
|
||||||
{
|
|
||||||
public int Type;
|
|
||||||
public ulong Serial;
|
|
||||||
public int SendEvent;
|
|
||||||
public IntPtr Display;
|
|
||||||
public IntPtr Window;
|
|
||||||
public int Mode;
|
|
||||||
public int Detail;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region X11 Constants
|
|
||||||
|
|
||||||
public static class XEventType
|
|
||||||
{
|
|
||||||
public const int KeyPress = 2;
|
|
||||||
public const int KeyRelease = 3;
|
|
||||||
public const int ButtonPress = 4;
|
|
||||||
public const int ButtonRelease = 5;
|
|
||||||
public const int MotionNotify = 6;
|
|
||||||
public const int EnterNotify = 7;
|
|
||||||
public const int LeaveNotify = 8;
|
|
||||||
public const int FocusIn = 9;
|
|
||||||
public const int FocusOut = 10;
|
|
||||||
public const int Expose = 12;
|
|
||||||
public const int ConfigureNotify = 22;
|
|
||||||
public const int ClientMessage = 33;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class XEventMask
|
|
||||||
{
|
|
||||||
public const long KeyPressMask = 1L << 0;
|
|
||||||
public const long KeyReleaseMask = 1L << 1;
|
|
||||||
public const long ButtonPressMask = 1L << 2;
|
|
||||||
public const long ButtonReleaseMask = 1L << 3;
|
|
||||||
public const long EnterWindowMask = 1L << 4;
|
|
||||||
public const long LeaveWindowMask = 1L << 5;
|
|
||||||
public const long PointerMotionMask = 1L << 6;
|
|
||||||
public const long ExposureMask = 1L << 15;
|
|
||||||
public const long StructureNotifyMask = 1L << 17;
|
|
||||||
public const long FocusChangeMask = 1L << 21;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class XWindowClass
|
|
||||||
{
|
|
||||||
public const uint InputOutput = 1;
|
|
||||||
public const uint InputOnly = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class XCursorShape
|
|
||||||
{
|
|
||||||
public const uint XC_left_ptr = 68;
|
|
||||||
public const uint XC_hand2 = 60;
|
|
||||||
public const uint XC_xterm = 152;
|
|
||||||
public const uint XC_watch = 150;
|
|
||||||
public const uint XC_crosshair = 34;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
23
Interop/XButtonEvent.cs
Normal file
23
Interop/XButtonEvent.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// 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.Linux.Interop;
|
||||||
|
|
||||||
|
public struct XButtonEvent
|
||||||
|
{
|
||||||
|
public int Type;
|
||||||
|
public ulong Serial;
|
||||||
|
public int SendEvent;
|
||||||
|
public IntPtr Display;
|
||||||
|
public IntPtr Window;
|
||||||
|
public IntPtr Root;
|
||||||
|
public IntPtr Subwindow;
|
||||||
|
public ulong Time;
|
||||||
|
public int X;
|
||||||
|
public int Y;
|
||||||
|
public int XRoot;
|
||||||
|
public int YRoot;
|
||||||
|
public uint State;
|
||||||
|
public uint Button;
|
||||||
|
public int SameScreen;
|
||||||
|
}
|
||||||
16
Interop/XClientMessageEvent.cs
Normal file
16
Interop/XClientMessageEvent.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// 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.Linux.Interop;
|
||||||
|
|
||||||
|
public struct XClientMessageEvent
|
||||||
|
{
|
||||||
|
public int Type;
|
||||||
|
public ulong Serial;
|
||||||
|
public int SendEvent;
|
||||||
|
public IntPtr Display;
|
||||||
|
public IntPtr Window;
|
||||||
|
public IntPtr MessageType;
|
||||||
|
public int Format;
|
||||||
|
public ClientMessageData Data;
|
||||||
|
}
|
||||||
21
Interop/XConfigureEvent.cs
Normal file
21
Interop/XConfigureEvent.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// 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.Linux.Interop;
|
||||||
|
|
||||||
|
public struct XConfigureEvent
|
||||||
|
{
|
||||||
|
public int Type;
|
||||||
|
public ulong Serial;
|
||||||
|
public int SendEvent;
|
||||||
|
public IntPtr Display;
|
||||||
|
public IntPtr Event;
|
||||||
|
public IntPtr Window;
|
||||||
|
public int X;
|
||||||
|
public int Y;
|
||||||
|
public int Width;
|
||||||
|
public int Height;
|
||||||
|
public int BorderWidth;
|
||||||
|
public IntPtr Above;
|
||||||
|
public int OverrideRedirect;
|
||||||
|
}
|
||||||
25
Interop/XCrossingEvent.cs
Normal file
25
Interop/XCrossingEvent.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// 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.Linux.Interop;
|
||||||
|
|
||||||
|
public struct XCrossingEvent
|
||||||
|
{
|
||||||
|
public int Type;
|
||||||
|
public ulong Serial;
|
||||||
|
public int SendEvent;
|
||||||
|
public IntPtr Display;
|
||||||
|
public IntPtr Window;
|
||||||
|
public IntPtr Root;
|
||||||
|
public IntPtr Subwindow;
|
||||||
|
public ulong Time;
|
||||||
|
public int X;
|
||||||
|
public int Y;
|
||||||
|
public int XRoot;
|
||||||
|
public int YRoot;
|
||||||
|
public int Mode;
|
||||||
|
public int Detail;
|
||||||
|
public int SameScreen;
|
||||||
|
public int Focus;
|
||||||
|
public uint State;
|
||||||
|
}
|
||||||
13
Interop/XCursorShape.cs
Normal file
13
Interop/XCursorShape.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
// 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.Linux.Interop;
|
||||||
|
|
||||||
|
public static class XCursorShape
|
||||||
|
{
|
||||||
|
public const uint XC_left_ptr = 68;
|
||||||
|
public const uint XC_hand2 = 60;
|
||||||
|
public const uint XC_xterm = 152;
|
||||||
|
public const uint XC_watch = 150;
|
||||||
|
public const uint XC_crosshair = 34;
|
||||||
|
}
|
||||||
37
Interop/XEvent.cs
Normal file
37
Interop/XEvent.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
// 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;
|
||||||
|
|
||||||
|
namespace Microsoft.Maui.Platform.Linux.Interop;
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Explicit, Size = 192)]
|
||||||
|
public struct XEvent
|
||||||
|
{
|
||||||
|
[FieldOffset(0)]
|
||||||
|
public int Type;
|
||||||
|
|
||||||
|
[FieldOffset(0)]
|
||||||
|
public XKeyEvent KeyEvent;
|
||||||
|
|
||||||
|
[FieldOffset(0)]
|
||||||
|
public XButtonEvent ButtonEvent;
|
||||||
|
|
||||||
|
[FieldOffset(0)]
|
||||||
|
public XMotionEvent MotionEvent;
|
||||||
|
|
||||||
|
[FieldOffset(0)]
|
||||||
|
public XConfigureEvent ConfigureEvent;
|
||||||
|
|
||||||
|
[FieldOffset(0)]
|
||||||
|
public XExposeEvent ExposeEvent;
|
||||||
|
|
||||||
|
[FieldOffset(0)]
|
||||||
|
public XClientMessageEvent ClientMessageEvent;
|
||||||
|
|
||||||
|
[FieldOffset(0)]
|
||||||
|
public XCrossingEvent CrossingEvent;
|
||||||
|
|
||||||
|
[FieldOffset(0)]
|
||||||
|
public XFocusChangeEvent FocusChangeEvent;
|
||||||
|
}
|
||||||
18
Interop/XEventMask.cs
Normal file
18
Interop/XEventMask.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// 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.Linux.Interop;
|
||||||
|
|
||||||
|
public static class XEventMask
|
||||||
|
{
|
||||||
|
public const long KeyPressMask = 1L;
|
||||||
|
public const long KeyReleaseMask = 2L;
|
||||||
|
public const long ButtonPressMask = 4L;
|
||||||
|
public const long ButtonReleaseMask = 8L;
|
||||||
|
public const long EnterWindowMask = 16L;
|
||||||
|
public const long LeaveWindowMask = 32L;
|
||||||
|
public const long PointerMotionMask = 64L;
|
||||||
|
public const long ExposureMask = 32768L;
|
||||||
|
public const long StructureNotifyMask = 131072L;
|
||||||
|
public const long FocusChangeMask = 2097152L;
|
||||||
|
}
|
||||||
20
Interop/XEventType.cs
Normal file
20
Interop/XEventType.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// 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.Linux.Interop;
|
||||||
|
|
||||||
|
public static class XEventType
|
||||||
|
{
|
||||||
|
public const int KeyPress = 2;
|
||||||
|
public const int KeyRelease = 3;
|
||||||
|
public const int ButtonPress = 4;
|
||||||
|
public const int ButtonRelease = 5;
|
||||||
|
public const int MotionNotify = 6;
|
||||||
|
public const int EnterNotify = 7;
|
||||||
|
public const int LeaveNotify = 8;
|
||||||
|
public const int FocusIn = 9;
|
||||||
|
public const int FocusOut = 10;
|
||||||
|
public const int Expose = 12;
|
||||||
|
public const int ConfigureNotify = 22;
|
||||||
|
public const int ClientMessage = 33;
|
||||||
|
}
|
||||||
18
Interop/XExposeEvent.cs
Normal file
18
Interop/XExposeEvent.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// 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.Linux.Interop;
|
||||||
|
|
||||||
|
public struct XExposeEvent
|
||||||
|
{
|
||||||
|
public int Type;
|
||||||
|
public ulong Serial;
|
||||||
|
public int SendEvent;
|
||||||
|
public IntPtr Display;
|
||||||
|
public IntPtr Window;
|
||||||
|
public int X;
|
||||||
|
public int Y;
|
||||||
|
public int Width;
|
||||||
|
public int Height;
|
||||||
|
public int Count;
|
||||||
|
}
|
||||||
15
Interop/XFocusChangeEvent.cs
Normal file
15
Interop/XFocusChangeEvent.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
// 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.Linux.Interop;
|
||||||
|
|
||||||
|
public struct XFocusChangeEvent
|
||||||
|
{
|
||||||
|
public int Type;
|
||||||
|
public ulong Serial;
|
||||||
|
public int SendEvent;
|
||||||
|
public IntPtr Display;
|
||||||
|
public IntPtr Window;
|
||||||
|
public int Mode;
|
||||||
|
public int Detail;
|
||||||
|
}
|
||||||
23
Interop/XKeyEvent.cs
Normal file
23
Interop/XKeyEvent.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// 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.Linux.Interop;
|
||||||
|
|
||||||
|
public struct XKeyEvent
|
||||||
|
{
|
||||||
|
public int Type;
|
||||||
|
public ulong Serial;
|
||||||
|
public int SendEvent;
|
||||||
|
public IntPtr Display;
|
||||||
|
public IntPtr Window;
|
||||||
|
public IntPtr Root;
|
||||||
|
public IntPtr Subwindow;
|
||||||
|
public ulong Time;
|
||||||
|
public int X;
|
||||||
|
public int Y;
|
||||||
|
public int XRoot;
|
||||||
|
public int YRoot;
|
||||||
|
public uint State;
|
||||||
|
public uint Keycode;
|
||||||
|
public int SameScreen;
|
||||||
|
}
|
||||||
23
Interop/XMotionEvent.cs
Normal file
23
Interop/XMotionEvent.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// 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.Linux.Interop;
|
||||||
|
|
||||||
|
public struct XMotionEvent
|
||||||
|
{
|
||||||
|
public int Type;
|
||||||
|
public ulong Serial;
|
||||||
|
public int SendEvent;
|
||||||
|
public IntPtr Display;
|
||||||
|
public IntPtr Window;
|
||||||
|
public IntPtr Root;
|
||||||
|
public IntPtr Subwindow;
|
||||||
|
public ulong Time;
|
||||||
|
public int X;
|
||||||
|
public int Y;
|
||||||
|
public int XRoot;
|
||||||
|
public int YRoot;
|
||||||
|
public uint State;
|
||||||
|
public byte IsHint;
|
||||||
|
public int SameScreen;
|
||||||
|
}
|
||||||
23
Interop/XSetWindowAttributes.cs
Normal file
23
Interop/XSetWindowAttributes.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// 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.Linux.Interop;
|
||||||
|
|
||||||
|
public struct XSetWindowAttributes
|
||||||
|
{
|
||||||
|
public IntPtr BackgroundPixmap;
|
||||||
|
public ulong BackgroundPixel;
|
||||||
|
public IntPtr BorderPixmap;
|
||||||
|
public ulong BorderPixel;
|
||||||
|
public int BitGravity;
|
||||||
|
public int WinGravity;
|
||||||
|
public int BackingStore;
|
||||||
|
public ulong BackingPlanes;
|
||||||
|
public ulong BackingPixel;
|
||||||
|
public int SaveUnder;
|
||||||
|
public long EventMask;
|
||||||
|
public long DoNotPropagateMask;
|
||||||
|
public int OverrideRedirect;
|
||||||
|
public IntPtr Colormap;
|
||||||
|
public IntPtr Cursor;
|
||||||
|
}
|
||||||
10
Interop/XWindowClass.cs
Normal file
10
Interop/XWindowClass.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
// 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.Linux.Interop;
|
||||||
|
|
||||||
|
public static class XWindowClass
|
||||||
|
{
|
||||||
|
public const uint InputOutput = 1;
|
||||||
|
public const uint InputOnly = 2;
|
||||||
|
}
|
||||||
@@ -977,70 +977,3 @@ public class LinuxApplication : IDisposable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Options for Linux application initialization.
|
|
||||||
/// </summary>
|
|
||||||
public class LinuxApplicationOptions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the window title.
|
|
||||||
/// </summary>
|
|
||||||
public string? Title { get; set; } = "MAUI Application";
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the initial window width.
|
|
||||||
/// </summary>
|
|
||||||
public int Width { get; set; } = 800;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the initial window height.
|
|
||||||
/// </summary>
|
|
||||||
public int Height { get; set; } = 600;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets whether to use hardware acceleration.
|
|
||||||
/// </summary>
|
|
||||||
public bool UseHardwareAcceleration { get; set; } = true;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the display server type.
|
|
||||||
/// </summary>
|
|
||||||
public DisplayServerType DisplayServer { get; set; } = DisplayServerType.Auto;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets whether to force demo mode instead of loading the application's pages.
|
|
||||||
/// </summary>
|
|
||||||
public bool ForceDemo { get; set; } = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets whether to use GTK mode instead of X11.
|
|
||||||
/// </summary>
|
|
||||||
public bool UseGtk { get; set; } = false;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the path to the application icon.
|
|
||||||
/// </summary>
|
|
||||||
public string? IconPath { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Display server type options.
|
|
||||||
/// </summary>
|
|
||||||
public enum DisplayServerType
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Automatically detect the display server.
|
|
||||||
/// </summary>
|
|
||||||
Auto,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Use X11 (Xorg).
|
|
||||||
/// </summary>
|
|
||||||
X11,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Use Wayland.
|
|
||||||
/// </summary>
|
|
||||||
Wayland
|
|
||||||
}
|
|
||||||
|
|||||||
23
LinuxApplicationOptions.cs
Normal file
23
LinuxApplicationOptions.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// 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.Linux;
|
||||||
|
|
||||||
|
public class LinuxApplicationOptions
|
||||||
|
{
|
||||||
|
public string? Title { get; set; } = "MAUI Application";
|
||||||
|
|
||||||
|
public int Width { get; set; } = 800;
|
||||||
|
|
||||||
|
public int Height { get; set; } = 600;
|
||||||
|
|
||||||
|
public bool UseHardwareAcceleration { get; set; } = true;
|
||||||
|
|
||||||
|
public DisplayServerType DisplayServer { get; set; }
|
||||||
|
|
||||||
|
public bool ForceDemo { get; set; }
|
||||||
|
|
||||||
|
public string? IconPath { get; set; }
|
||||||
|
|
||||||
|
public bool UseGtk { get; set; }
|
||||||
|
}
|
||||||
@@ -59,22 +59,26 @@
|
|||||||
| File | Status | Notes |
|
| File | Status | Notes |
|
||||||
|------|--------|-------|
|
|------|--------|-------|
|
||||||
| SkiaActivityIndicator.cs | [x] | Verified - all TwoWay, logic matches |
|
| SkiaActivityIndicator.cs | [x] | Verified - all TwoWay, logic matches |
|
||||||
| SkiaAlertDialog.cs | [ ] | |
|
| SkiaAlertDialog.cs | [x] | **VERIFIED 2026-01-01** - Logic matches, modal dialog rendering |
|
||||||
| SkiaBorder.cs | [ ] | Contains SkiaFrame |
|
| SkiaBorder.cs | [x] | **FIXED 2026-01-01** - Logic matches, removed embedded SkiaFrame (now separate file) |
|
||||||
|
| SkiaFrame.cs | [x] | **ADDED 2026-01-01** - Created as separate file matching decompiled pattern |
|
||||||
| SkiaBoxView.cs | [x] | Verified - all TwoWay, logic matches |
|
| SkiaBoxView.cs | [x] | Verified - all TwoWay, logic matches |
|
||||||
| SkiaButton.cs | [x] | Verified - all TwoWay, logic matches |
|
| SkiaButton.cs | [x] | Verified - all TwoWay, logic matches |
|
||||||
| SkiaCarouselView.cs | [ ] | |
|
| SkiaCarouselView.cs | [x] | **FIXED 2026-01-01** - Logic matches, removed embedded PositionChangedEventArgs |
|
||||||
|
| PositionChangedEventArgs.cs | [x] | **ADDED 2026-01-01** - Created as separate file matching decompiled |
|
||||||
| SkiaCheckBox.cs | [x] | Verified - IsChecked=OneWay, rest TwoWay, logic matches |
|
| SkiaCheckBox.cs | [x] | Verified - IsChecked=OneWay, rest TwoWay, logic matches |
|
||||||
| SkiaCollectionView.cs | [ ] | |
|
| SkiaCollectionView.cs | [x] | **FIXED 2026-01-01** - Removed embedded SkiaSelectionMode, ItemsLayoutOrientation |
|
||||||
|
| SkiaSelectionMode.cs | [x] | **ADDED 2026-01-01** - Created as separate file |
|
||||||
|
| ItemsLayoutOrientation.cs | [x] | **ADDED 2026-01-01** - Created as separate file |
|
||||||
| SkiaContentPresenter.cs | [ ] | |
|
| SkiaContentPresenter.cs | [ ] | |
|
||||||
| SkiaContextMenu.cs | [ ] | |
|
| SkiaContextMenu.cs | [ ] | |
|
||||||
| SkiaDatePicker.cs | [ ] | |
|
| SkiaDatePicker.cs | [x] | **VERIFIED 2026-01-01** - Date=OneWay, all others=TwoWay |
|
||||||
| SkiaEditor.cs | [x] | **FIXED 2026-01-01** - All BindingModes corrected (Text=OneWay, others=TwoWay) |
|
| SkiaEditor.cs | [x] | **FIXED 2026-01-01** - All BindingModes corrected (Text=OneWay, others=TwoWay) |
|
||||||
| SkiaEntry.cs | [x] | **FIXED 2026-01-01** - TextProperty BindingMode.OneWay, others TwoWay |
|
| SkiaEntry.cs | [x] | **FIXED 2026-01-01** - TextProperty BindingMode.OneWay, others TwoWay |
|
||||||
| SkiaFlexLayout.cs | [ ] | |
|
| SkiaFlexLayout.cs | [ ] | |
|
||||||
| SkiaFlyoutPage.cs | [ ] | |
|
| SkiaFlyoutPage.cs | [ ] | |
|
||||||
| SkiaGraphicsView.cs | [ ] | |
|
| SkiaGraphicsView.cs | [ ] | |
|
||||||
| SkiaImage.cs | [ ] | |
|
| SkiaImage.cs | [x] | **VERIFIED 2026-01-01** - No BindableProperties, logic matches |
|
||||||
| SkiaImageButton.cs | [ ] | |
|
| SkiaImageButton.cs | [ ] | |
|
||||||
| SkiaIndicatorView.cs | [ ] | |
|
| SkiaIndicatorView.cs | [ ] | |
|
||||||
| SkiaItemsView.cs | [x] | Added GetItemView() method |
|
| SkiaItemsView.cs | [x] | Added GetItemView() method |
|
||||||
@@ -85,18 +89,18 @@
|
|||||||
| SkiaPage.cs | [x] | Added SkiaToolbarItem.Icon property |
|
| SkiaPage.cs | [x] | Added SkiaToolbarItem.Icon property |
|
||||||
| SkiaPicker.cs | [x] | FIXED - SelectedIndex=OneWay, all others=TwoWay (was missing) |
|
| SkiaPicker.cs | [x] | FIXED - SelectedIndex=OneWay, all others=TwoWay (was missing) |
|
||||||
| SkiaProgressBar.cs | [x] | Verified - Progress=OneWay, rest TwoWay, logic matches |
|
| SkiaProgressBar.cs | [x] | Verified - Progress=OneWay, rest TwoWay, logic matches |
|
||||||
| SkiaRadioButton.cs | [ ] | |
|
| SkiaRadioButton.cs | [x] | **FIXED 2026-01-01** - IsChecked=OneWay, all others=TwoWay |
|
||||||
| SkiaRefreshView.cs | [ ] | |
|
| SkiaRefreshView.cs | [ ] | |
|
||||||
| SkiaScrollView.cs | [x] | **FIXED 2026-01-01** - All BindingModes TwoWay |
|
| SkiaScrollView.cs | [x] | **FIXED 2026-01-01** - All BindingModes TwoWay |
|
||||||
| SkiaSearchBar.cs | [ ] | |
|
| SkiaSearchBar.cs | [x] | **VERIFIED 2026-01-01** - No BindableProperties, logic matches |
|
||||||
| SkiaShell.cs | [x] | **FIXED 2026-01-01** - Added FlyoutTextColor, ContentBackgroundColor, route registration, query parameters, OnScroll |
|
| SkiaShell.cs | [x] | **FIXED 2026-01-01** - Added FlyoutTextColor, ContentBackgroundColor, route registration, query parameters, OnScroll |
|
||||||
| SkiaSlider.cs | [x] | FIXED - Value=OneWay, rest TwoWay (agent had inverted all) |
|
| SkiaSlider.cs | [x] | FIXED - Value=OneWay, rest TwoWay (agent had inverted all) |
|
||||||
| SkiaStepper.cs | [ ] | |
|
| SkiaStepper.cs | [x] | **FIXED 2026-01-01** - Value=OneWay, all others=TwoWay |
|
||||||
| SkiaSwipeView.cs | [ ] | |
|
| SkiaSwipeView.cs | [ ] | |
|
||||||
| SkiaSwitch.cs | [x] | FIXED - IsOn=OneWay (agent had TwoWay) |
|
| SkiaSwitch.cs | [x] | FIXED - IsOn=OneWay (agent had TwoWay) |
|
||||||
| SkiaTabbedPage.cs | [ ] | |
|
| SkiaTabbedPage.cs | [ ] | |
|
||||||
| SkiaTemplatedView.cs | [ ] | |
|
| SkiaTemplatedView.cs | [ ] | |
|
||||||
| SkiaTimePicker.cs | [ ] | |
|
| SkiaTimePicker.cs | [x] | **FIXED 2026-01-01** - Time=OneWay, all others=TwoWay |
|
||||||
| SkiaView.cs | [x] | Made Arrange() virtual |
|
| SkiaView.cs | [x] | Made Arrange() virtual |
|
||||||
| SkiaVisualStateManager.cs | [ ] | |
|
| SkiaVisualStateManager.cs | [ ] | |
|
||||||
| SkiaWebView.cs | [x] | **FIXED 2026-01-01** - Full X11 embedding, position tracking, hardware accel, load callbacks |
|
| SkiaWebView.cs | [x] | **FIXED 2026-01-01** - Full X11 embedding, position tracking, hardware accel, load callbacks |
|
||||||
@@ -107,43 +111,108 @@
|
|||||||
|
|
||||||
| File | Status | Notes |
|
| File | Status | Notes |
|
||||||
|------|--------|-------|
|
|------|--------|-------|
|
||||||
| AppActionsService.cs | [ ] | |
|
| AccessibilityServiceFactory.cs | [x] | **FIXED 2026-01-01** - Fixed CreateService() to call Initialize(), added Reset() |
|
||||||
| AppInfoService.cs | [ ] | |
|
| AccessibleAction.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
| AtSpi2AccessibilityService.cs | [ ] | |
|
| AccessibleProperty.cs | [x] | **FIXED 2026-01-01** - Fixed to match decompiled (Name,Description,Role,Value,Parent,Children) |
|
||||||
| BrowserService.cs | [ ] | |
|
| AccessibleRect.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
| ClipboardService.cs | [ ] | |
|
| AccessibleRole.cs | [x] | **FIXED 2026-01-01** - Fixed to match decompiled (simplified list with Button,Tab,TabPanel) |
|
||||||
| ConnectivityService.cs | [ ] | |
|
| AccessibleState.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
| DeviceDisplayService.cs | [ ] | |
|
| AccessibleStates.cs | [x] | **FIXED 2026-01-01** - Fixed to match decompiled (MultiSelectable capital S) |
|
||||||
| DeviceInfoService.cs | [ ] | |
|
| AnnouncementPriority.cs | [x] | **FIXED 2026-01-01** - Fixed to match decompiled (Polite,Assertive) |
|
||||||
| DisplayServerFactory.cs | [ ] | |
|
| AppActionsService.cs | [x] | **VERIFIED 2026-01-01** - Logic matches, main has clean string interpolation |
|
||||||
| DragDropService.cs | [ ] | |
|
| AppInfoService.cs | [x] | **VERIFIED 2026-01-01** - Logic matches, main has clean enum names |
|
||||||
| EmailService.cs | [ ] | |
|
| AtSpi2AccessibilityService.cs | [x] | **FIXED 2026-01-01** - Removed embedded AccessibilityServiceFactory, NullAccessibilityService |
|
||||||
| Fcitx5InputMethodService.cs | [ ] | |
|
| BrowserService.cs | [x] | **VERIFIED 2026-01-01** - Logic matches, main has clean nameof/interpolation/enums |
|
||||||
| FilePickerService.cs | [ ] | |
|
| ClipboardService.cs | [x] | **VERIFIED 2026-01-01** - Logic matches, xclip/xsel fallback |
|
||||||
| FolderPickerService.cs | [ ] | |
|
| ColorDialogResult.cs | [x] | **FIXED 2026-01-01** - Fixed to match decompiled |
|
||||||
| FontFallbackManager.cs | [ ] | |
|
| ConnectivityService.cs | [x] | **VERIFIED 2026-01-01** - Logic matches, main has clean enum names |
|
||||||
| GlobalHotkeyService.cs | [ ] | |
|
| DesktopEnvironment.cs | [x] | **FIXED 2026-01-01** - Fixed to match decompiled (GNOME uppercase) |
|
||||||
| Gtk4InteropService.cs | [ ] | |
|
| DeviceDisplayService.cs | [x] | **VERIFIED 2026-01-01** - Logic matches, main has clean enum names |
|
||||||
| GtkHostService.cs | [ ] | |
|
| DeviceInfoService.cs | [x] | **VERIFIED 2026-01-01** - Logic matches, main has clean enum names |
|
||||||
| HardwareVideoService.cs | [ ] | |
|
| DisplayServerFactory.cs | [x] | **FIXED 2026-01-01** - Removed embedded DisplayServerType, IDisplayWindow, X11DisplayWindow, WaylandDisplayWindow |
|
||||||
| HiDpiService.cs | [ ] | |
|
| DisplayServerType.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
| HighContrastService.cs | [ ] | |
|
| DragAction.cs | [x] | **FIXED 2026-01-01** - Fixed to match decompiled |
|
||||||
| IAccessibilityService.cs | [ ] | |
|
| DragData.cs | [x] | **FIXED 2026-01-01** - Fixed to match decompiled |
|
||||||
| IBusInputMethodService.cs | [ ] | |
|
| DragDropService.cs | [x] | **FIXED 2026-01-01** - Removed embedded DragData, DragEventArgs, DropEventArgs, DragAction |
|
||||||
| IInputMethodService.cs | [ ] | |
|
| DragEventArgs.cs | [x] | **FIXED 2026-01-01** - Fixed to match decompiled |
|
||||||
| InputMethodServiceFactory.cs | [ ] | |
|
| DropEventArgs.cs | [x] | **FIXED 2026-01-01** - Fixed to match decompiled |
|
||||||
| LauncherService.cs | [ ] | |
|
| EmailService.cs | [x] | **VERIFIED 2026-01-01** - Logic matches, main has clean nameof/interpolation |
|
||||||
| LinuxResourcesProvider.cs | [ ] | |
|
| Fcitx5InputMethodService.cs | [x] | **VERIFIED 2026-01-01** - Logic matches, D-Bus interface |
|
||||||
| NotificationService.cs | [ ] | |
|
| FileDialogResult.cs | [x] | **FIXED 2026-01-01** - Fixed to match decompiled |
|
||||||
| PortalFilePickerService.cs | [ ] | |
|
| FilePickerService.cs | [x] | **FIXED 2026-01-01** - Removed embedded LinuxFileResult |
|
||||||
| PreferencesService.cs | [ ] | |
|
| FolderPickerOptions.cs | [x] | **FIXED 2026-01-01** - Fixed to match decompiled |
|
||||||
| SecureStorageService.cs | [ ] | |
|
| FolderPickerResult.cs | [x] | **FIXED 2026-01-01** - Fixed to match decompiled |
|
||||||
| ShareService.cs | [ ] | |
|
| FolderPickerService.cs | [x] | **VERIFIED 2026-01-01** - Logic matches, zenity/kdialog fallback |
|
||||||
| SystemThemeService.cs | [ ] | |
|
| FolderResult.cs | [x] | **FIXED 2026-01-01** - Fixed to match decompiled |
|
||||||
| SystemTrayService.cs | [ ] | |
|
| FontFallbackManager.cs | [x] | **FIXED 2026-01-01** - Removed embedded TextRun |
|
||||||
| VersionTrackingService.cs | [ ] | |
|
| GlobalHotkeyService.cs | [x] | **FIXED 2026-01-01** - Removed embedded HotkeyEventArgs, HotkeyModifiers, HotkeyKey |
|
||||||
| VirtualizationManager.cs | [ ] | |
|
| Gtk4InteropService.cs | [x] | **FIXED 2026-01-01** - Removed embedded GtkResponseType, GtkMessageType, GtkButtonsType, GtkFileChooserAction, FileDialogResult, ColorDialogResult |
|
||||||
| X11InputMethodService.cs | [ ] | |
|
| GtkButtonsType.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| GtkContextMenuService.cs | [x] | **VERIFIED 2026-01-01** - Logic matches, GTK P/Invoke |
|
||||||
|
| GtkFileChooserAction.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| GtkHostService.cs | [x] | **VERIFIED 2026-01-01** - Logic matches, main has clean ??= syntax |
|
||||||
|
| GtkMenuItem.cs | [x] | **VERIFIED 2026-01-01** - Identical logic |
|
||||||
|
| GtkMessageType.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| GtkResponseType.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| HardwareVideoService.cs | [x] | **FIXED 2026-01-01** - Removed embedded VideoAccelerationApi, VideoProfile, VideoFrame |
|
||||||
|
| HiDpiService.cs | [x] | **FIXED 2026-01-01** - Removed embedded ScaleChangedEventArgs |
|
||||||
|
| HighContrastChangedEventArgs.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| HighContrastColors.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| HighContrastService.cs | [x] | **FIXED 2026-01-01** - Removed embedded HighContrastTheme, HighContrastColors, HighContrastChangedEventArgs |
|
||||||
|
| HighContrastTheme.cs | [x] | **FIXED 2026-01-01** - Fixed to match decompiled (None,WhiteOnBlack,BlackOnWhite) |
|
||||||
|
| HotkeyEventArgs.cs | [x] | **FIXED 2026-01-01** - Fixed constructor order (int id, HotkeyKey key, HotkeyModifiers modifiers) |
|
||||||
|
| HotkeyKey.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| HotkeyModifiers.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| IAccessibilityService.cs | [x] | **FIXED 2026-01-01** - Removed many embedded types |
|
||||||
|
| IAccessible.cs | [x] | **FIXED 2026-01-01** - Fixed to match decompiled exactly |
|
||||||
|
| IAccessibleEditableText.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| IAccessibleText.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| IBusInputMethodService.cs | [x] | **VERIFIED 2026-01-01** - Logic matches, IBus D-Bus interface |
|
||||||
|
| IDisplayWindow.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| IInputContext.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| IInputMethodService.cs | [x] | **FIXED 2026-01-01** - Removed embedded IInputContext, TextCommittedEventArgs, PreEditChangedEventArgs, PreEditAttribute, PreEditAttributeType, KeyModifiers |
|
||||||
|
| InputMethodServiceFactory.cs | [x] | **FIXED 2026-01-01** - Removed embedded NullInputMethodService |
|
||||||
|
| KeyModifiers.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| LauncherService.cs | [x] | **VERIFIED 2026-01-01** - Logic matches, xdg-open |
|
||||||
|
| LinuxFileResult.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| LinuxResourcesProvider.cs | [x] | **VERIFIED 2026-01-01** - Logic matches, system styles |
|
||||||
|
| MauiIconGenerator.cs | [x] | **FIXED 2026-01-01** - Added Svg.Skia, SVG foreground, Scale metadata |
|
||||||
|
| NotificationAction.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| NotificationActionEventArgs.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| NotificationClosedEventArgs.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| NotificationCloseReason.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| NotificationContext.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| NotificationOptions.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| NotificationService.cs | [x] | **FIXED 2026-01-01** - Removed embedded NotificationOptions, NotificationUrgency, NotificationCloseReason, NotificationContext, NotificationActionEventArgs, NotificationClosedEventArgs, NotificationAction |
|
||||||
|
| NotificationUrgency.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| NullAccessibilityService.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| NullInputMethodService.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| PortalFilePickerService.cs | [x] | **FIXED 2026-01-01** - Removed embedded FolderResult, FolderPickerResult, FolderPickerOptions, PortalFolderPickerService |
|
||||||
|
| PortalFolderPickerService.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| PreEditAttribute.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| PreEditAttributeType.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| PreEditChangedEventArgs.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| PreferencesService.cs | [x] | **VERIFIED 2026-01-01** - Logic matches, JSON file storage with XDG |
|
||||||
|
| ScaleChangedEventArgs.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| SecureStorageService.cs | [x] | **VERIFIED 2026-01-01** - Logic matches, secret-tool with AES fallback |
|
||||||
|
| ShareService.cs | [x] | **VERIFIED 2026-01-01** - Logic matches, xdg-open with portal fallback |
|
||||||
|
| SystemColors.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| SystemTheme.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| SystemThemeService.cs | [x] | **FIXED 2026-01-01** - Removed embedded SystemTheme, DesktopEnvironment, ThemeChangedEventArgs, SystemColors |
|
||||||
|
| SystemTrayService.cs | [x] | **FIXED 2026-01-01** - Removed embedded TrayMenuItem |
|
||||||
|
| TextCommittedEventArgs.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| TextRun.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| ThemeChangedEventArgs.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| TrayMenuItem.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| VersionTrackingService.cs | [x] | **VERIFIED 2026-01-01** - Logic matches, JSON tracking file |
|
||||||
|
| VideoAccelerationApi.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| VideoFrame.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| VideoProfile.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| VirtualizationExtensions.cs | [x] | **VERIFIED 2026-01-01** - Matches decompiled |
|
||||||
|
| VirtualizationManager.cs | [x] | **FIXED 2026-01-01** - Removed embedded VirtualizationExtensions |
|
||||||
|
| WaylandDisplayWindow.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| X11DisplayWindow.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| X11InputMethodService.cs | [x] | **VERIFIED 2026-01-01** - Logic matches, X11 XIM interface |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -151,12 +220,17 @@
|
|||||||
|
|
||||||
| File | Status | Notes |
|
| File | Status | Notes |
|
||||||
|------|--------|-------|
|
|------|--------|-------|
|
||||||
| LinuxMauiAppBuilderExtensions.cs | [ ] | |
|
| GtkMauiContext.cs | [x] | **ADDED 2026-01-01** - Was missing, created from decompiled |
|
||||||
| LinuxMauiContext.cs | [ ] | |
|
| HandlerMappingExtensions.cs | [x] | **ADDED 2026-01-01** - Was missing, created from decompiled |
|
||||||
| LinuxProgramHost.cs | [ ] | |
|
| LinuxAnimationManager.cs | [x] | **ADDED 2026-01-01** - Was missing, created from decompiled |
|
||||||
| LinuxViewRenderer.cs | [ ] | |
|
| LinuxMauiAppBuilderExtensions.cs | [x] | **FIXED 2026-01-01** - Added IDispatcherProvider, IDeviceInfo, IDeviceDisplay, IAppInfo, IConnectivity, GtkHostService registrations; fixed WebView to use GtkWebViewHandler |
|
||||||
| MauiAppBuilderExtensions.cs | [ ] | |
|
| LinuxMauiContext.cs | [x] | **FIXED 2026-01-01** - Removed embedded classes (now separate files), added LinuxDispatcher using |
|
||||||
| MauiHandlerExtensions.cs | [ ] | |
|
| LinuxProgramHost.cs | [x] | **FIXED 2026-01-01** - Added GtkHostService.Initialize call for WebView support |
|
||||||
|
| LinuxTicker.cs | [x] | **ADDED 2026-01-01** - Was missing, created from decompiled |
|
||||||
|
| LinuxViewRenderer.cs | [x] | **FIXED 2026-01-01** - Added ApplyShellColors(), FlyoutHeader rendering, FlyoutFooterText, MauiShellContent, ContentRenderer/ColorRefresher delegates, page BackgroundColor handling |
|
||||||
|
| MauiAppBuilderExtensions.cs | [x] | **DELETED 2026-01-01** - Not in decompiled, was outdated duplicate with wrong namespace |
|
||||||
|
| MauiHandlerExtensions.cs | [x] | **FIXED 2026-01-01** - Fixed WebView to use GtkWebViewHandler, FlexLayout to use LayoutHandler |
|
||||||
|
| ScopedLinuxMauiContext.cs | [x] | **ADDED 2026-01-01** - Was missing, created from decompiled |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -164,9 +238,9 @@
|
|||||||
|
|
||||||
| File | Status | Notes |
|
| File | Status | Notes |
|
||||||
|------|--------|-------|
|
|------|--------|-------|
|
||||||
| LinuxDispatcher.cs | [ ] | |
|
| LinuxDispatcher.cs | [x] | **VERIFIED 2026-01-01** - Matches decompiled, clean syntax |
|
||||||
| LinuxDispatcherProvider.cs | [ ] | |
|
| LinuxDispatcherProvider.cs | [x] | **VERIFIED 2026-01-01** - Matches decompiled |
|
||||||
| LinuxDispatcherTimer.cs | [ ] | |
|
| LinuxDispatcherTimer.cs | [x] | **VERIFIED 2026-01-01** - Matches decompiled, clean syntax |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -174,11 +248,11 @@
|
|||||||
|
|
||||||
| File | Status | Notes |
|
| File | Status | Notes |
|
||||||
|------|--------|-------|
|
|------|--------|-------|
|
||||||
| CairoNative.cs | [ ] | |
|
| CairoNative.cs | [x] | **VERIFIED 2026-01-01** - Matches decompiled |
|
||||||
| GdkNative.cs | [ ] | |
|
| GdkNative.cs | [x] | **VERIFIED 2026-01-01** - Matches decompiled |
|
||||||
| GLibNative.cs | [ ] | |
|
| GLibNative.cs | [x] | **VERIFIED 2026-01-01** - Matches decompiled |
|
||||||
| GtkNative.cs | [ ] | |
|
| GtkNative.cs | [x] | **VERIFIED 2026-01-01** - Matches decompiled |
|
||||||
| WebKitNative.cs | [ ] | |
|
| WebKitNative.cs | [x] | **VERIFIED 2026-01-01** - Matches decompiled |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -186,9 +260,10 @@
|
|||||||
|
|
||||||
| File | Status | Notes |
|
| File | Status | Notes |
|
||||||
|------|--------|-------|
|
|------|--------|-------|
|
||||||
| CursorType.cs | [ ] | |
|
| CursorType.cs | [x] | **VERIFIED 2026-01-01** - Matches decompiled |
|
||||||
| GtkHostWindow.cs | [ ] | |
|
| GtkHostWindow.cs | [x] | **VERIFIED 2026-01-01** - Matches decompiled, main has clean comments |
|
||||||
| X11Window.cs | [ ] | |
|
| WaylandWindow.cs | [x] | **VERIFIED 2026-01-01** - Matches decompiled, main has clean comments |
|
||||||
|
| X11Window.cs | [x] | **FIXED 2026-01-01** - Added SVG icon support, event counter logging from decompiled |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -196,7 +271,52 @@
|
|||||||
|
|
||||||
| File | Status | Notes |
|
| File | Status | Notes |
|
||||||
|------|--------|-------|
|
|------|--------|-------|
|
||||||
| GtkSkiaSurfaceWidget.cs | [ ] | |
|
| GpuRenderingEngine.cs | [x] | **FIXED 2026-01-01** - Removed embedded GpuStats |
|
||||||
|
| GpuStats.cs | [x] | **VERIFIED 2026-01-01** - Matches decompiled |
|
||||||
|
| GtkSkiaSurfaceWidget.cs | [x] | **VERIFIED 2026-01-01** - Matches decompiled, same public API |
|
||||||
|
| LayeredRenderer.cs | [x] | **VERIFIED 2026-01-01** - Matches decompiled |
|
||||||
|
| RenderCache.cs | [x] | **FIXED 2026-01-01** - Removed embedded LayeredRenderer, RenderLayer, TextRenderCache |
|
||||||
|
| RenderLayer.cs | [x] | **VERIFIED 2026-01-01** - Matches decompiled |
|
||||||
|
| ResourceCache.cs | [x] | **VERIFIED 2026-01-01** - Matches decompiled |
|
||||||
|
| SkiaRenderingEngine.cs | [x] | **FIXED 2026-01-01** - Removed embedded ResourceCache |
|
||||||
|
| TextRenderCache.cs | [x] | **VERIFIED 2026-01-01** - Matches decompiled |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## INTEROP
|
||||||
|
|
||||||
|
| File | Status | Notes |
|
||||||
|
|------|--------|-------|
|
||||||
|
| ClientMessageData.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| WebKitGtk.cs | [x] | **VERIFIED 2026-01-01** - Matches decompiled, main has cleaner formatting with regions |
|
||||||
|
| X11.cs | [x] | **VERIFIED 2026-01-01** - Matches decompiled, X11Interop.cs DELETED (was duplicate) |
|
||||||
|
| XButtonEvent.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| XClientMessageEvent.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| XConfigureEvent.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| XCrossingEvent.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| XCursorShape.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| XEvent.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| XEventMask.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| XEventType.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| XExposeEvent.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| XFocusChangeEvent.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| XKeyEvent.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| XMotionEvent.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| XSetWindowAttributes.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| XWindowClass.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## CONVERTERS
|
||||||
|
|
||||||
|
| File | Status | Notes |
|
||||||
|
|------|--------|-------|
|
||||||
|
| ColorExtensions.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| SKColorTypeConverter.cs | [x] | **FIXED 2026-01-01** - Removed embedded ColorExtensions |
|
||||||
|
| SKPointTypeConverter.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| SKRectTypeConverter.cs | [x] | **FIXED 2026-01-01** - Removed embedded SKSizeTypeConverter, SKPointTypeConverter, SKTypeExtensions |
|
||||||
|
| SKSizeTypeConverter.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
| SKTypeExtensions.cs | [x] | **VERIFIED 2026-01-01** - Separate file, matches decompiled |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -204,8 +324,8 @@
|
|||||||
|
|
||||||
| File | Status | Notes |
|
| File | Status | Notes |
|
||||||
|------|--------|-------|
|
|------|--------|-------|
|
||||||
| LinuxApplication.cs | [ ] | |
|
| LinuxApplication.cs | [x] | **FIXED 2026-01-01** - Removed embedded DisplayServerType, LinuxApplicationOptions |
|
||||||
| LinuxApplicationOptions.cs | [ ] | |
|
| LinuxApplicationOptions.cs | [x] | **VERIFIED 2026-01-01** - Matches decompiled (separate file) |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -333,17 +333,3 @@ public class GpuRenderingEngine : IDisposable
|
|||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// GPU performance statistics.
|
|
||||||
/// </summary>
|
|
||||||
public class GpuStats
|
|
||||||
{
|
|
||||||
public bool IsGpuAccelerated { get; init; }
|
|
||||||
public int MaxTextureSize { get; init; }
|
|
||||||
public long ResourceCacheUsedBytes { get; init; }
|
|
||||||
public long ResourceCacheLimitBytes { get; init; }
|
|
||||||
|
|
||||||
public double ResourceCacheUsedMB => ResourceCacheUsedBytes / (1024.0 * 1024.0);
|
|
||||||
public double ResourceCacheLimitMB => ResourceCacheLimitBytes / (1024.0 * 1024.0);
|
|
||||||
}
|
|
||||||
|
|||||||
19
Rendering/GpuStats.cs
Normal file
19
Rendering/GpuStats.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
// 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.Linux.Rendering;
|
||||||
|
|
||||||
|
public class GpuStats
|
||||||
|
{
|
||||||
|
public bool IsGpuAccelerated { get; init; }
|
||||||
|
|
||||||
|
public int MaxTextureSize { get; init; }
|
||||||
|
|
||||||
|
public long ResourceCacheUsedBytes { get; init; }
|
||||||
|
|
||||||
|
public long ResourceCacheLimitBytes { get; init; }
|
||||||
|
|
||||||
|
public double ResourceCacheUsedMB => ResourceCacheUsedBytes / 1048576.0;
|
||||||
|
|
||||||
|
public double ResourceCacheLimitMB => ResourceCacheLimitBytes / 1048576.0;
|
||||||
|
}
|
||||||
75
Rendering/LayeredRenderer.cs
Normal file
75
Rendering/LayeredRenderer.cs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||||
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
|
||||||
|
using SkiaSharp;
|
||||||
|
|
||||||
|
namespace Microsoft.Maui.Platform.Linux.Rendering;
|
||||||
|
|
||||||
|
public class LayeredRenderer : IDisposable
|
||||||
|
{
|
||||||
|
private readonly Dictionary<int, RenderLayer> _layers = new();
|
||||||
|
private readonly object _lock = new();
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
|
public RenderLayer GetLayer(int zIndex)
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
if (!_layers.TryGetValue(zIndex, out var layer))
|
||||||
|
{
|
||||||
|
layer = new RenderLayer(zIndex);
|
||||||
|
_layers[zIndex] = layer;
|
||||||
|
}
|
||||||
|
return layer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveLayer(int zIndex)
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
if (_layers.TryGetValue(zIndex, out var layer))
|
||||||
|
{
|
||||||
|
layer.Dispose();
|
||||||
|
_layers.Remove(zIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Composite(SKCanvas canvas, SKRect bounds)
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
foreach (var layer in _layers.Values.OrderBy(l => l.ZIndex))
|
||||||
|
{
|
||||||
|
layer.DrawTo(canvas, bounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void InvalidateAll()
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
foreach (var layer in _layers.Values)
|
||||||
|
{
|
||||||
|
layer.Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_disposed) return;
|
||||||
|
_disposed = true;
|
||||||
|
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
foreach (var layer in _layers.Values)
|
||||||
|
{
|
||||||
|
layer.Dispose();
|
||||||
|
}
|
||||||
|
_layers.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -236,291 +236,3 @@ public class RenderCache : IDisposable
|
|||||||
public int AccessCount { get; set; }
|
public int AccessCount { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Provides layered rendering for separating static and dynamic content.
|
|
||||||
/// </summary>
|
|
||||||
public class LayeredRenderer : IDisposable
|
|
||||||
{
|
|
||||||
private readonly Dictionary<int, RenderLayer> _layers = new();
|
|
||||||
private readonly object _lock = new();
|
|
||||||
private bool _disposed;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or creates a render layer.
|
|
||||||
/// </summary>
|
|
||||||
public RenderLayer GetLayer(int zIndex)
|
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
if (!_layers.TryGetValue(zIndex, out var layer))
|
|
||||||
{
|
|
||||||
layer = new RenderLayer(zIndex);
|
|
||||||
_layers[zIndex] = layer;
|
|
||||||
}
|
|
||||||
return layer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Removes a render layer.
|
|
||||||
/// </summary>
|
|
||||||
public void RemoveLayer(int zIndex)
|
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
if (_layers.TryGetValue(zIndex, out var layer))
|
|
||||||
{
|
|
||||||
layer.Dispose();
|
|
||||||
_layers.Remove(zIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Composites all layers onto the target canvas.
|
|
||||||
/// </summary>
|
|
||||||
public void Composite(SKCanvas canvas, SKRect bounds)
|
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
foreach (var layer in _layers.Values.OrderBy(l => l.ZIndex))
|
|
||||||
{
|
|
||||||
layer.DrawTo(canvas, bounds);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Invalidates all layers.
|
|
||||||
/// </summary>
|
|
||||||
public void InvalidateAll()
|
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
foreach (var layer in _layers.Values)
|
|
||||||
{
|
|
||||||
layer.Invalidate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (_disposed) return;
|
|
||||||
_disposed = true;
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
foreach (var layer in _layers.Values)
|
|
||||||
{
|
|
||||||
layer.Dispose();
|
|
||||||
}
|
|
||||||
_layers.Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a single render layer with its own bitmap buffer.
|
|
||||||
/// </summary>
|
|
||||||
public class RenderLayer : IDisposable
|
|
||||||
{
|
|
||||||
private SKBitmap? _bitmap;
|
|
||||||
private SKCanvas? _canvas;
|
|
||||||
private bool _isDirty = true;
|
|
||||||
private SKRect _bounds;
|
|
||||||
private bool _disposed;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the Z-index of this layer.
|
|
||||||
/// </summary>
|
|
||||||
public int ZIndex { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets whether this layer needs to be redrawn.
|
|
||||||
/// </summary>
|
|
||||||
public bool IsDirty => _isDirty;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets whether this layer is visible.
|
|
||||||
/// </summary>
|
|
||||||
public bool IsVisible { get; set; } = true;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the layer opacity (0-1).
|
|
||||||
/// </summary>
|
|
||||||
public float Opacity { get; set; } = 1f;
|
|
||||||
|
|
||||||
public RenderLayer(int zIndex)
|
|
||||||
{
|
|
||||||
ZIndex = zIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Prepares the layer for rendering.
|
|
||||||
/// </summary>
|
|
||||||
public SKCanvas BeginDraw(SKRect bounds)
|
|
||||||
{
|
|
||||||
if (_bitmap == null || _bounds != bounds)
|
|
||||||
{
|
|
||||||
_bitmap?.Dispose();
|
|
||||||
_canvas?.Dispose();
|
|
||||||
|
|
||||||
int width = Math.Max(1, (int)bounds.Width);
|
|
||||||
int height = Math.Max(1, (int)bounds.Height);
|
|
||||||
|
|
||||||
_bitmap = new SKBitmap(width, height, SKColorType.Rgba8888, SKAlphaType.Premul);
|
|
||||||
_canvas = new SKCanvas(_bitmap);
|
|
||||||
_bounds = bounds;
|
|
||||||
}
|
|
||||||
|
|
||||||
_canvas!.Clear(SKColors.Transparent);
|
|
||||||
_isDirty = false;
|
|
||||||
return _canvas;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Marks the layer as needing redraw.
|
|
||||||
/// </summary>
|
|
||||||
public void Invalidate()
|
|
||||||
{
|
|
||||||
_isDirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Draws this layer to the target canvas.
|
|
||||||
/// </summary>
|
|
||||||
public void DrawTo(SKCanvas canvas, SKRect bounds)
|
|
||||||
{
|
|
||||||
if (!IsVisible || _bitmap == null) return;
|
|
||||||
|
|
||||||
using var paint = new SKPaint
|
|
||||||
{
|
|
||||||
Color = SKColors.White.WithAlpha((byte)(Opacity * 255))
|
|
||||||
};
|
|
||||||
|
|
||||||
canvas.DrawBitmap(_bitmap, bounds.Left, bounds.Top, paint);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (_disposed) return;
|
|
||||||
_disposed = true;
|
|
||||||
|
|
||||||
_canvas?.Dispose();
|
|
||||||
_bitmap?.Dispose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Provides text rendering optimization with glyph caching.
|
|
||||||
/// </summary>
|
|
||||||
public class TextRenderCache : IDisposable
|
|
||||||
{
|
|
||||||
private readonly Dictionary<TextCacheKey, SKBitmap> _cache = new();
|
|
||||||
private readonly object _lock = new();
|
|
||||||
private int _maxEntries = 500;
|
|
||||||
private bool _disposed;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the maximum number of cached text entries.
|
|
||||||
/// </summary>
|
|
||||||
public int MaxEntries
|
|
||||||
{
|
|
||||||
get => _maxEntries;
|
|
||||||
set => _maxEntries = Math.Max(10, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a cached text bitmap or creates one.
|
|
||||||
/// </summary>
|
|
||||||
public SKBitmap GetOrCreate(string text, SKPaint paint)
|
|
||||||
{
|
|
||||||
var key = new TextCacheKey(text, paint);
|
|
||||||
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
if (_cache.TryGetValue(key, out var cached))
|
|
||||||
{
|
|
||||||
return cached;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create text bitmap
|
|
||||||
var bounds = new SKRect();
|
|
||||||
paint.MeasureText(text, ref bounds);
|
|
||||||
|
|
||||||
int width = Math.Max(1, (int)Math.Ceiling(bounds.Width) + 2);
|
|
||||||
int height = Math.Max(1, (int)Math.Ceiling(bounds.Height) + 2);
|
|
||||||
|
|
||||||
var bitmap = new SKBitmap(width, height, SKColorType.Rgba8888, SKAlphaType.Premul);
|
|
||||||
using (var canvas = new SKCanvas(bitmap))
|
|
||||||
{
|
|
||||||
canvas.Clear(SKColors.Transparent);
|
|
||||||
canvas.DrawText(text, -bounds.Left + 1, -bounds.Top + 1, paint);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trim cache if needed
|
|
||||||
if (_cache.Count >= _maxEntries)
|
|
||||||
{
|
|
||||||
var oldest = _cache.First();
|
|
||||||
oldest.Value.Dispose();
|
|
||||||
_cache.Remove(oldest.Key);
|
|
||||||
}
|
|
||||||
|
|
||||||
_cache[key] = bitmap;
|
|
||||||
return bitmap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Clears all cached text.
|
|
||||||
/// </summary>
|
|
||||||
public void Clear()
|
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
foreach (var entry in _cache.Values)
|
|
||||||
{
|
|
||||||
entry.Dispose();
|
|
||||||
}
|
|
||||||
_cache.Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (_disposed) return;
|
|
||||||
_disposed = true;
|
|
||||||
Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly struct TextCacheKey : IEquatable<TextCacheKey>
|
|
||||||
{
|
|
||||||
private readonly string _text;
|
|
||||||
private readonly float _textSize;
|
|
||||||
private readonly SKColor _color;
|
|
||||||
private readonly int _weight;
|
|
||||||
private readonly int _hashCode;
|
|
||||||
|
|
||||||
public TextCacheKey(string text, SKPaint paint)
|
|
||||||
{
|
|
||||||
_text = text;
|
|
||||||
_textSize = paint.TextSize;
|
|
||||||
_color = paint.Color;
|
|
||||||
_weight = paint.Typeface?.FontWeight ?? (int)SKFontStyleWeight.Normal;
|
|
||||||
_hashCode = HashCode.Combine(_text, _textSize, _color, _weight);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Equals(TextCacheKey other)
|
|
||||||
{
|
|
||||||
return _text == other._text &&
|
|
||||||
Math.Abs(_textSize - other._textSize) < 0.001f &&
|
|
||||||
_color == other._color &&
|
|
||||||
_weight == other._weight;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object? obj) => obj is TextCacheKey other && Equals(other);
|
|
||||||
public override int GetHashCode() => _hashCode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
72
Rendering/RenderLayer.cs
Normal file
72
Rendering/RenderLayer.cs
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||||
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
|
||||||
|
using SkiaSharp;
|
||||||
|
|
||||||
|
namespace Microsoft.Maui.Platform.Linux.Rendering;
|
||||||
|
|
||||||
|
public class RenderLayer : IDisposable
|
||||||
|
{
|
||||||
|
private SKBitmap? _bitmap;
|
||||||
|
private SKCanvas? _canvas;
|
||||||
|
private bool _isDirty = true;
|
||||||
|
private SKRect _bounds;
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
|
public int ZIndex { get; }
|
||||||
|
|
||||||
|
public bool IsDirty => _isDirty;
|
||||||
|
|
||||||
|
public bool IsVisible { get; set; } = true;
|
||||||
|
|
||||||
|
public float Opacity { get; set; } = 1f;
|
||||||
|
|
||||||
|
public RenderLayer(int zIndex)
|
||||||
|
{
|
||||||
|
ZIndex = zIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SKCanvas BeginDraw(SKRect bounds)
|
||||||
|
{
|
||||||
|
if (_bitmap == null || _bounds != bounds)
|
||||||
|
{
|
||||||
|
_bitmap?.Dispose();
|
||||||
|
_canvas?.Dispose();
|
||||||
|
|
||||||
|
var width = Math.Max(1, (int)bounds.Width);
|
||||||
|
var height = Math.Max(1, (int)bounds.Height);
|
||||||
|
_bitmap = new SKBitmap(width, height, SKColorType.Bgra8888, SKAlphaType.Premul);
|
||||||
|
_canvas = new SKCanvas(_bitmap);
|
||||||
|
_bounds = bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
_canvas!.Clear(SKColors.Transparent);
|
||||||
|
_isDirty = false;
|
||||||
|
return _canvas;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Invalidate()
|
||||||
|
{
|
||||||
|
_isDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DrawTo(SKCanvas canvas, SKRect bounds)
|
||||||
|
{
|
||||||
|
if (!IsVisible || _bitmap == null) return;
|
||||||
|
|
||||||
|
using var paint = new SKPaint
|
||||||
|
{
|
||||||
|
Color = SKColors.White.WithAlpha((byte)(Opacity * 255f))
|
||||||
|
};
|
||||||
|
canvas.DrawBitmap(_bitmap, bounds.Left, bounds.Top, paint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_disposed) return;
|
||||||
|
_disposed = true;
|
||||||
|
|
||||||
|
_canvas?.Dispose();
|
||||||
|
_bitmap?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
43
Rendering/ResourceCache.cs
Normal file
43
Rendering/ResourceCache.cs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||||
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
|
||||||
|
using SkiaSharp;
|
||||||
|
|
||||||
|
namespace Microsoft.Maui.Platform.Linux.Rendering;
|
||||||
|
|
||||||
|
public class ResourceCache : IDisposable
|
||||||
|
{
|
||||||
|
private readonly Dictionary<string, SKTypeface> _typefaces = new();
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
|
public SKTypeface GetTypeface(string fontFamily, SKFontStyle style)
|
||||||
|
{
|
||||||
|
var key = $"{fontFamily}_{style.Weight}_{style.Width}_{style.Slant}";
|
||||||
|
|
||||||
|
if (!_typefaces.TryGetValue(key, out var typeface))
|
||||||
|
{
|
||||||
|
typeface = SKTypeface.FromFamilyName(fontFamily, style) ?? SKTypeface.Default;
|
||||||
|
_typefaces[key] = typeface;
|
||||||
|
}
|
||||||
|
|
||||||
|
return typeface;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
foreach (var typeface in _typefaces.Values)
|
||||||
|
{
|
||||||
|
typeface.Dispose();
|
||||||
|
}
|
||||||
|
_typefaces.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (!_disposed)
|
||||||
|
{
|
||||||
|
Clear();
|
||||||
|
_disposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -313,31 +313,3 @@ public class SkiaRenderingEngine : IDisposable
|
|||||||
GC.SuppressFinalize(this);
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ResourceCache : IDisposable
|
|
||||||
{
|
|
||||||
private readonly Dictionary<string, SKTypeface> _typefaces = new();
|
|
||||||
private bool _disposed;
|
|
||||||
|
|
||||||
public SKTypeface GetTypeface(string fontFamily, SKFontStyle style)
|
|
||||||
{
|
|
||||||
var key = $"{fontFamily}_{style.Weight}_{style.Width}_{style.Slant}";
|
|
||||||
if (!_typefaces.TryGetValue(key, out var typeface))
|
|
||||||
{
|
|
||||||
typeface = SKTypeface.FromFamilyName(fontFamily, style) ?? SKTypeface.Default;
|
|
||||||
_typefaces[key] = typeface;
|
|
||||||
}
|
|
||||||
return typeface;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Clear()
|
|
||||||
{
|
|
||||||
foreach (var tf in _typefaces.Values) tf.Dispose();
|
|
||||||
_typefaces.Clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (!_disposed) { Clear(); _disposed = true; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
108
Rendering/TextRenderCache.cs
Normal file
108
Rendering/TextRenderCache.cs
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||||
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
|
||||||
|
using SkiaSharp;
|
||||||
|
|
||||||
|
namespace Microsoft.Maui.Platform.Linux.Rendering;
|
||||||
|
|
||||||
|
public class TextRenderCache : IDisposable
|
||||||
|
{
|
||||||
|
private readonly struct TextCacheKey : IEquatable<TextCacheKey>
|
||||||
|
{
|
||||||
|
private readonly string _text;
|
||||||
|
private readonly float _textSize;
|
||||||
|
private readonly SKColor _color;
|
||||||
|
private readonly int _weight;
|
||||||
|
private readonly int _hashCode;
|
||||||
|
|
||||||
|
public TextCacheKey(string text, SKPaint paint)
|
||||||
|
{
|
||||||
|
_text = text;
|
||||||
|
_textSize = paint.TextSize;
|
||||||
|
_color = paint.Color;
|
||||||
|
_weight = paint.Typeface?.FontWeight ?? 400;
|
||||||
|
_hashCode = HashCode.Combine(_text, _textSize, _color, _weight);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(TextCacheKey other)
|
||||||
|
{
|
||||||
|
return _text == other._text
|
||||||
|
&& Math.Abs(_textSize - other._textSize) < 0.001f
|
||||||
|
&& _color == other._color
|
||||||
|
&& _weight == other._weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object? obj)
|
||||||
|
{
|
||||||
|
return obj is TextCacheKey other && Equals(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode() => _hashCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly Dictionary<TextCacheKey, SKBitmap> _cache = new();
|
||||||
|
private readonly object _lock = new();
|
||||||
|
private int _maxEntries = 500;
|
||||||
|
private bool _disposed;
|
||||||
|
|
||||||
|
public int MaxEntries
|
||||||
|
{
|
||||||
|
get => _maxEntries;
|
||||||
|
set => _maxEntries = Math.Max(10, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SKBitmap GetOrCreate(string text, SKPaint paint)
|
||||||
|
{
|
||||||
|
var key = new TextCacheKey(text, paint);
|
||||||
|
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
if (_cache.TryGetValue(key, out var cached))
|
||||||
|
{
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
|
||||||
|
var bounds = new SKRect();
|
||||||
|
paint.MeasureText(text, ref bounds);
|
||||||
|
|
||||||
|
var width = Math.Max(1, (int)Math.Ceiling(bounds.Width) + 2);
|
||||||
|
var height = Math.Max(1, (int)Math.Ceiling(bounds.Height) + 2);
|
||||||
|
|
||||||
|
var bitmap = new SKBitmap(width, height, SKColorType.Bgra8888, SKAlphaType.Premul);
|
||||||
|
using var canvas = new SKCanvas(bitmap);
|
||||||
|
canvas.Clear(SKColors.Transparent);
|
||||||
|
canvas.DrawText(text, -bounds.Left + 1f, -bounds.Top + 1f, paint);
|
||||||
|
|
||||||
|
if (_cache.Count >= _maxEntries)
|
||||||
|
{
|
||||||
|
var first = _cache.First();
|
||||||
|
first.Value.Dispose();
|
||||||
|
_cache.Remove(first.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
_cache[key] = bitmap;
|
||||||
|
return bitmap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
foreach (var bitmap in _cache.Values)
|
||||||
|
{
|
||||||
|
bitmap.Dispose();
|
||||||
|
}
|
||||||
|
_cache.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (!_disposed)
|
||||||
|
{
|
||||||
|
_disposed = true;
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
48
Services/AccessibilityServiceFactory.cs
Normal file
48
Services/AccessibilityServiceFactory.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public static class AccessibilityServiceFactory
|
||||||
|
{
|
||||||
|
private static IAccessibilityService? _instance;
|
||||||
|
private static readonly object _lock = new();
|
||||||
|
|
||||||
|
public static IAccessibilityService Instance
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (_instance == null)
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
_instance ??= CreateService();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IAccessibilityService CreateService()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var service = new AtSpi2AccessibilityService();
|
||||||
|
service.Initialize();
|
||||||
|
return service;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return new NullAccessibilityService();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Reset()
|
||||||
|
{
|
||||||
|
lock (_lock)
|
||||||
|
{
|
||||||
|
_instance?.Shutdown();
|
||||||
|
_instance = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Services/AccessibleAction.cs
Normal file
11
Services/AccessibleAction.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public class AccessibleAction
|
||||||
|
{
|
||||||
|
public string Name { get; set; } = "";
|
||||||
|
public string Description { get; set; } = "";
|
||||||
|
public string KeyBinding { get; set; } = "";
|
||||||
|
}
|
||||||
14
Services/AccessibleProperty.cs
Normal file
14
Services/AccessibleProperty.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public enum AccessibleProperty
|
||||||
|
{
|
||||||
|
Name,
|
||||||
|
Description,
|
||||||
|
Role,
|
||||||
|
Value,
|
||||||
|
Parent,
|
||||||
|
Children
|
||||||
|
}
|
||||||
20
Services/AccessibleRect.cs
Normal file
20
Services/AccessibleRect.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public struct AccessibleRect
|
||||||
|
{
|
||||||
|
public int X { get; set; }
|
||||||
|
public int Y { get; set; }
|
||||||
|
public int Width { get; set; }
|
||||||
|
public int Height { get; set; }
|
||||||
|
|
||||||
|
public AccessibleRect(int x, int y, int width, int height)
|
||||||
|
{
|
||||||
|
X = x;
|
||||||
|
Y = y;
|
||||||
|
Width = width;
|
||||||
|
Height = height;
|
||||||
|
}
|
||||||
|
}
|
||||||
52
Services/AccessibleRole.cs
Normal file
52
Services/AccessibleRole.cs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public enum AccessibleRole
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
Window,
|
||||||
|
Application,
|
||||||
|
Panel,
|
||||||
|
Frame,
|
||||||
|
Button,
|
||||||
|
CheckBox,
|
||||||
|
RadioButton,
|
||||||
|
ComboBox,
|
||||||
|
Entry,
|
||||||
|
Label,
|
||||||
|
List,
|
||||||
|
ListItem,
|
||||||
|
Menu,
|
||||||
|
MenuBar,
|
||||||
|
MenuItem,
|
||||||
|
ScrollBar,
|
||||||
|
Slider,
|
||||||
|
SpinButton,
|
||||||
|
StatusBar,
|
||||||
|
Tab,
|
||||||
|
TabPanel,
|
||||||
|
Text,
|
||||||
|
ToggleButton,
|
||||||
|
ToolBar,
|
||||||
|
ToolTip,
|
||||||
|
Tree,
|
||||||
|
TreeItem,
|
||||||
|
Image,
|
||||||
|
ProgressBar,
|
||||||
|
Separator,
|
||||||
|
Link,
|
||||||
|
Table,
|
||||||
|
TableCell,
|
||||||
|
TableRow,
|
||||||
|
TableColumnHeader,
|
||||||
|
TableRowHeader,
|
||||||
|
PageTab,
|
||||||
|
PageTabList,
|
||||||
|
Dialog,
|
||||||
|
Alert,
|
||||||
|
Filler,
|
||||||
|
Icon,
|
||||||
|
Canvas
|
||||||
|
}
|
||||||
52
Services/AccessibleState.cs
Normal file
52
Services/AccessibleState.cs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public enum AccessibleState
|
||||||
|
{
|
||||||
|
Invalid,
|
||||||
|
Active,
|
||||||
|
Armed,
|
||||||
|
Busy,
|
||||||
|
Checked,
|
||||||
|
Collapsed,
|
||||||
|
Defunct,
|
||||||
|
Editable,
|
||||||
|
Enabled,
|
||||||
|
Expandable,
|
||||||
|
Expanded,
|
||||||
|
Focusable,
|
||||||
|
Focused,
|
||||||
|
HasToolTip,
|
||||||
|
Horizontal,
|
||||||
|
Iconified,
|
||||||
|
Modal,
|
||||||
|
MultiLine,
|
||||||
|
Multiselectable,
|
||||||
|
Opaque,
|
||||||
|
Pressed,
|
||||||
|
Resizable,
|
||||||
|
Selectable,
|
||||||
|
Selected,
|
||||||
|
Sensitive,
|
||||||
|
Showing,
|
||||||
|
SingleLine,
|
||||||
|
Stale,
|
||||||
|
Transient,
|
||||||
|
Vertical,
|
||||||
|
Visible,
|
||||||
|
ManagesDescendants,
|
||||||
|
Indeterminate,
|
||||||
|
Required,
|
||||||
|
Truncated,
|
||||||
|
Animated,
|
||||||
|
InvalidEntry,
|
||||||
|
SupportsAutocompletion,
|
||||||
|
SelectableText,
|
||||||
|
IsDefault,
|
||||||
|
Visited,
|
||||||
|
Checkable,
|
||||||
|
HasPopup,
|
||||||
|
ReadOnly
|
||||||
|
}
|
||||||
51
Services/AccessibleStates.cs
Normal file
51
Services/AccessibleStates.cs
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum AccessibleStates : long
|
||||||
|
{
|
||||||
|
None = 0L,
|
||||||
|
Active = 1L,
|
||||||
|
Armed = 2L,
|
||||||
|
Busy = 4L,
|
||||||
|
Checked = 8L,
|
||||||
|
Collapsed = 0x10L,
|
||||||
|
Defunct = 0x20L,
|
||||||
|
Editable = 0x40L,
|
||||||
|
Enabled = 0x80L,
|
||||||
|
Expandable = 0x100L,
|
||||||
|
Expanded = 0x200L,
|
||||||
|
Focusable = 0x400L,
|
||||||
|
Focused = 0x800L,
|
||||||
|
HasToolTip = 0x1000L,
|
||||||
|
Horizontal = 0x2000L,
|
||||||
|
Iconified = 0x4000L,
|
||||||
|
Modal = 0x8000L,
|
||||||
|
MultiLine = 0x10000L,
|
||||||
|
MultiSelectable = 0x20000L,
|
||||||
|
Opaque = 0x40000L,
|
||||||
|
Pressed = 0x80000L,
|
||||||
|
Resizable = 0x100000L,
|
||||||
|
Selectable = 0x200000L,
|
||||||
|
Selected = 0x400000L,
|
||||||
|
Sensitive = 0x800000L,
|
||||||
|
Showing = 0x1000000L,
|
||||||
|
SingleLine = 0x2000000L,
|
||||||
|
Stale = 0x4000000L,
|
||||||
|
Transient = 0x8000000L,
|
||||||
|
Vertical = 0x10000000L,
|
||||||
|
Visible = 0x20000000L,
|
||||||
|
ManagesDescendants = 0x40000000L,
|
||||||
|
Indeterminate = 0x80000000L,
|
||||||
|
Required = 0x100000000L,
|
||||||
|
Truncated = 0x200000000L,
|
||||||
|
Animated = 0x400000000L,
|
||||||
|
InvalidEntry = 0x800000000L,
|
||||||
|
SupportsAutocompletion = 0x1000000000L,
|
||||||
|
SelectableText = 0x2000000000L,
|
||||||
|
IsDefault = 0x4000000000L,
|
||||||
|
Visited = 0x8000000000L,
|
||||||
|
ReadOnly = 0x10000000000L
|
||||||
|
}
|
||||||
10
Services/AnnouncementPriority.cs
Normal file
10
Services/AnnouncementPriority.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public enum AnnouncementPriority
|
||||||
|
{
|
||||||
|
Polite,
|
||||||
|
Assertive
|
||||||
|
}
|
||||||
@@ -134,10 +134,6 @@ public class AppActionsService : IAppActions
|
|||||||
}
|
}
|
||||||
|
|
||||||
content.AppendLine($"Exec={execPath} --action={action.Id}");
|
content.AppendLine($"Exec={execPath} --action={action.Id}");
|
||||||
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
content.AppendLine();
|
content.AppendLine();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -388,74 +388,3 @@ public class AtSpi2AccessibilityService : IAccessibilityService, IDisposable
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Factory for creating accessibility service instances.
|
|
||||||
/// </summary>
|
|
||||||
public static class AccessibilityServiceFactory
|
|
||||||
{
|
|
||||||
private static IAccessibilityService? _instance;
|
|
||||||
private static readonly object _lock = new();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the singleton accessibility service instance.
|
|
||||||
/// </summary>
|
|
||||||
public static IAccessibilityService Instance
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (_instance == null)
|
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
_instance ??= CreateService();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return _instance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IAccessibilityService CreateService()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var service = new AtSpi2AccessibilityService();
|
|
||||||
service.Initialize();
|
|
||||||
return service;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"AccessibilityServiceFactory: Failed to create AT-SPI2 service - {ex.Message}");
|
|
||||||
return new NullAccessibilityService();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Resets the singleton instance.
|
|
||||||
/// </summary>
|
|
||||||
public static void Reset()
|
|
||||||
{
|
|
||||||
lock (_lock)
|
|
||||||
{
|
|
||||||
_instance?.Shutdown();
|
|
||||||
_instance = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Null implementation of accessibility service.
|
|
||||||
/// </summary>
|
|
||||||
public class NullAccessibilityService : IAccessibilityService
|
|
||||||
{
|
|
||||||
public bool IsEnabled => false;
|
|
||||||
|
|
||||||
public void Initialize() { }
|
|
||||||
public void Register(IAccessible accessible) { }
|
|
||||||
public void Unregister(IAccessible accessible) { }
|
|
||||||
public void NotifyFocusChanged(IAccessible? accessible) { }
|
|
||||||
public void NotifyPropertyChanged(IAccessible accessible, AccessibleProperty property) { }
|
|
||||||
public void NotifyStateChanged(IAccessible accessible, AccessibleState state, bool value) { }
|
|
||||||
public void Announce(string text, AnnouncementPriority priority = AnnouncementPriority.Polite) { }
|
|
||||||
public void Shutdown() { }
|
|
||||||
}
|
|
||||||
|
|||||||
13
Services/ColorDialogResult.cs
Normal file
13
Services/ColorDialogResult.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public class ColorDialogResult
|
||||||
|
{
|
||||||
|
public bool Accepted { get; init; }
|
||||||
|
public float Red { get; init; }
|
||||||
|
public float Green { get; init; }
|
||||||
|
public float Blue { get; init; }
|
||||||
|
public float Alpha { get; init; }
|
||||||
|
}
|
||||||
16
Services/DesktopEnvironment.cs
Normal file
16
Services/DesktopEnvironment.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public enum DesktopEnvironment
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
GNOME,
|
||||||
|
KDE,
|
||||||
|
XFCE,
|
||||||
|
MATE,
|
||||||
|
Cinnamon,
|
||||||
|
LXQt,
|
||||||
|
LXDE
|
||||||
|
}
|
||||||
@@ -7,20 +7,6 @@ using Microsoft.Maui.Platform.Linux.Rendering;
|
|||||||
|
|
||||||
namespace Microsoft.Maui.Platform.Linux.Services;
|
namespace Microsoft.Maui.Platform.Linux.Services;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Supported display server types.
|
|
||||||
/// </summary>
|
|
||||||
public enum DisplayServerType
|
|
||||||
{
|
|
||||||
Auto,
|
|
||||||
X11,
|
|
||||||
Wayland
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Factory for creating display server connections.
|
|
||||||
/// Supports X11 and Wayland display servers.
|
|
||||||
/// </summary>
|
|
||||||
public static class DisplayServerFactory
|
public static class DisplayServerFactory
|
||||||
{
|
{
|
||||||
private static DisplayServerType? _cachedServerType;
|
private static DisplayServerType? _cachedServerType;
|
||||||
@@ -139,136 +125,3 @@ public static class DisplayServerFactory
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Common interface for display server windows.
|
|
||||||
/// </summary>
|
|
||||||
public interface IDisplayWindow : IDisposable
|
|
||||||
{
|
|
||||||
int Width { get; }
|
|
||||||
int Height { get; }
|
|
||||||
bool IsRunning { get; }
|
|
||||||
void Show();
|
|
||||||
void Hide();
|
|
||||||
void SetTitle(string title);
|
|
||||||
void Resize(int width, int height);
|
|
||||||
void ProcessEvents();
|
|
||||||
void Stop();
|
|
||||||
event EventHandler<KeyEventArgs>? KeyDown;
|
|
||||||
event EventHandler<KeyEventArgs>? KeyUp;
|
|
||||||
event EventHandler<TextInputEventArgs>? TextInput;
|
|
||||||
event EventHandler<PointerEventArgs>? PointerMoved;
|
|
||||||
event EventHandler<PointerEventArgs>? PointerPressed;
|
|
||||||
event EventHandler<PointerEventArgs>? PointerReleased;
|
|
||||||
event EventHandler<ScrollEventArgs>? Scroll;
|
|
||||||
event EventHandler? Exposed;
|
|
||||||
event EventHandler<(int Width, int Height)>? Resized;
|
|
||||||
event EventHandler? CloseRequested;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// X11 display window wrapper implementing the common interface.
|
|
||||||
/// </summary>
|
|
||||||
public class X11DisplayWindow : IDisplayWindow
|
|
||||||
{
|
|
||||||
private readonly X11Window _window;
|
|
||||||
|
|
||||||
public int Width => _window.Width;
|
|
||||||
public int Height => _window.Height;
|
|
||||||
public bool IsRunning => _window.IsRunning;
|
|
||||||
|
|
||||||
public event EventHandler<KeyEventArgs>? KeyDown;
|
|
||||||
public event EventHandler<KeyEventArgs>? KeyUp;
|
|
||||||
public event EventHandler<TextInputEventArgs>? TextInput;
|
|
||||||
public event EventHandler<PointerEventArgs>? PointerMoved;
|
|
||||||
public event EventHandler<PointerEventArgs>? PointerPressed;
|
|
||||||
public event EventHandler<PointerEventArgs>? PointerReleased;
|
|
||||||
public event EventHandler<ScrollEventArgs>? Scroll;
|
|
||||||
public event EventHandler? Exposed;
|
|
||||||
public event EventHandler<(int Width, int Height)>? Resized;
|
|
||||||
public event EventHandler? CloseRequested;
|
|
||||||
|
|
||||||
public X11DisplayWindow(string title, int width, int height)
|
|
||||||
{
|
|
||||||
_window = new X11Window(title, width, height);
|
|
||||||
|
|
||||||
_window.KeyDown += (s, e) => KeyDown?.Invoke(this, e);
|
|
||||||
_window.KeyUp += (s, e) => KeyUp?.Invoke(this, e);
|
|
||||||
_window.TextInput += (s, e) => TextInput?.Invoke(this, e);
|
|
||||||
_window.PointerMoved += (s, e) => PointerMoved?.Invoke(this, e);
|
|
||||||
_window.PointerPressed += (s, e) => PointerPressed?.Invoke(this, e);
|
|
||||||
_window.PointerReleased += (s, e) => PointerReleased?.Invoke(this, e);
|
|
||||||
_window.Scroll += (s, e) => Scroll?.Invoke(this, e);
|
|
||||||
_window.Exposed += (s, e) => Exposed?.Invoke(this, e);
|
|
||||||
_window.Resized += (s, e) => Resized?.Invoke(this, e);
|
|
||||||
_window.CloseRequested += (s, e) => CloseRequested?.Invoke(this, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Show() => _window.Show();
|
|
||||||
public void Hide() => _window.Hide();
|
|
||||||
public void SetTitle(string title) => _window.SetTitle(title);
|
|
||||||
public void Resize(int width, int height) => _window.Resize(width, height);
|
|
||||||
public void ProcessEvents() => _window.ProcessEvents();
|
|
||||||
public void Stop() => _window.Stop();
|
|
||||||
public void Dispose() => _window.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Wayland display window wrapper implementing IDisplayWindow.
|
|
||||||
/// Uses the full WaylandWindow implementation with xdg-shell protocol.
|
|
||||||
/// </summary>
|
|
||||||
public class WaylandDisplayWindow : IDisplayWindow
|
|
||||||
{
|
|
||||||
private readonly WaylandWindow _window;
|
|
||||||
|
|
||||||
public int Width => _window.Width;
|
|
||||||
public int Height => _window.Height;
|
|
||||||
public bool IsRunning => _window.IsRunning;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the pixel data pointer for rendering.
|
|
||||||
/// </summary>
|
|
||||||
public IntPtr PixelData => _window.PixelData;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the stride (bytes per row) of the pixel buffer.
|
|
||||||
/// </summary>
|
|
||||||
public int Stride => _window.Stride;
|
|
||||||
|
|
||||||
public event EventHandler<KeyEventArgs>? KeyDown;
|
|
||||||
public event EventHandler<KeyEventArgs>? KeyUp;
|
|
||||||
public event EventHandler<TextInputEventArgs>? TextInput;
|
|
||||||
public event EventHandler<PointerEventArgs>? PointerMoved;
|
|
||||||
public event EventHandler<PointerEventArgs>? PointerPressed;
|
|
||||||
public event EventHandler<PointerEventArgs>? PointerReleased;
|
|
||||||
public event EventHandler<ScrollEventArgs>? Scroll;
|
|
||||||
public event EventHandler? Exposed;
|
|
||||||
public event EventHandler<(int Width, int Height)>? Resized;
|
|
||||||
public event EventHandler? CloseRequested;
|
|
||||||
|
|
||||||
public WaylandDisplayWindow(string title, int width, int height)
|
|
||||||
{
|
|
||||||
_window = new WaylandWindow(title, width, height);
|
|
||||||
|
|
||||||
// Wire up events
|
|
||||||
_window.KeyDown += (s, e) => KeyDown?.Invoke(this, e);
|
|
||||||
_window.KeyUp += (s, e) => KeyUp?.Invoke(this, e);
|
|
||||||
_window.TextInput += (s, e) => TextInput?.Invoke(this, e);
|
|
||||||
_window.PointerMoved += (s, e) => PointerMoved?.Invoke(this, e);
|
|
||||||
_window.PointerPressed += (s, e) => PointerPressed?.Invoke(this, e);
|
|
||||||
_window.PointerReleased += (s, e) => PointerReleased?.Invoke(this, e);
|
|
||||||
_window.Scroll += (s, e) => Scroll?.Invoke(this, e);
|
|
||||||
_window.Exposed += (s, e) => Exposed?.Invoke(this, e);
|
|
||||||
_window.Resized += (s, e) => Resized?.Invoke(this, e);
|
|
||||||
_window.CloseRequested += (s, e) => CloseRequested?.Invoke(this, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Show() => _window.Show();
|
|
||||||
public void Hide() => _window.Hide();
|
|
||||||
public void SetTitle(string title) => _window.SetTitle(title);
|
|
||||||
public void Resize(int width, int height) => _window.Resize(width, height);
|
|
||||||
public void ProcessEvents() => _window.ProcessEvents();
|
|
||||||
public void Stop() => _window.Stop();
|
|
||||||
public void CommitFrame() => _window.CommitFrame();
|
|
||||||
public void Dispose() => _window.Dispose();
|
|
||||||
}
|
|
||||||
|
|||||||
11
Services/DisplayServerType.cs
Normal file
11
Services/DisplayServerType.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public enum DisplayServerType
|
||||||
|
{
|
||||||
|
Auto,
|
||||||
|
X11,
|
||||||
|
Wayland
|
||||||
|
}
|
||||||
12
Services/DragAction.cs
Normal file
12
Services/DragAction.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public enum DragAction
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Copy,
|
||||||
|
Move,
|
||||||
|
Link
|
||||||
|
}
|
||||||
13
Services/DragData.cs
Normal file
13
Services/DragData.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public class DragData
|
||||||
|
{
|
||||||
|
public nint SourceWindow { get; set; }
|
||||||
|
public nint[] SupportedTypes { get; set; } = [];
|
||||||
|
public string? Text { get; set; }
|
||||||
|
public string[]? FilePaths { get; set; }
|
||||||
|
public object? Data { get; set; }
|
||||||
|
}
|
||||||
@@ -402,115 +402,3 @@ public class DragDropService : IDisposable
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Contains data for a drag operation.
|
|
||||||
/// </summary>
|
|
||||||
public class DragData
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the source window.
|
|
||||||
/// </summary>
|
|
||||||
public nint SourceWindow { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the supported MIME types.
|
|
||||||
/// </summary>
|
|
||||||
public nint[] SupportedTypes { get; set; } = Array.Empty<nint>();
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the text data.
|
|
||||||
/// </summary>
|
|
||||||
public string? Text { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the file paths.
|
|
||||||
/// </summary>
|
|
||||||
public string[]? FilePaths { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets custom data.
|
|
||||||
/// </summary>
|
|
||||||
public object? Data { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Event args for drag events.
|
|
||||||
/// </summary>
|
|
||||||
public class DragEventArgs : EventArgs
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the drag data.
|
|
||||||
/// </summary>
|
|
||||||
public DragData Data { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the X coordinate.
|
|
||||||
/// </summary>
|
|
||||||
public int X { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the Y coordinate.
|
|
||||||
/// </summary>
|
|
||||||
public int Y { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets whether the drop is accepted.
|
|
||||||
/// </summary>
|
|
||||||
public bool Accepted { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the allowed action.
|
|
||||||
/// </summary>
|
|
||||||
public DragAction AllowedAction { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the accepted action.
|
|
||||||
/// </summary>
|
|
||||||
public DragAction AcceptedAction { get; set; } = DragAction.Copy;
|
|
||||||
|
|
||||||
public DragEventArgs(DragData data, int x, int y)
|
|
||||||
{
|
|
||||||
Data = data;
|
|
||||||
X = x;
|
|
||||||
Y = y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Event args for drop events.
|
|
||||||
/// </summary>
|
|
||||||
public class DropEventArgs : EventArgs
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the drag data.
|
|
||||||
/// </summary>
|
|
||||||
public DragData Data { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the dropped data as string.
|
|
||||||
/// </summary>
|
|
||||||
public string? DroppedData { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets whether the drop was handled.
|
|
||||||
/// </summary>
|
|
||||||
public bool Handled { get; set; }
|
|
||||||
|
|
||||||
public DropEventArgs(DragData data, string? droppedData)
|
|
||||||
{
|
|
||||||
Data = data;
|
|
||||||
DroppedData = droppedData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Drag action types.
|
|
||||||
/// </summary>
|
|
||||||
public enum DragAction
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
Copy,
|
|
||||||
Move,
|
|
||||||
Link
|
|
||||||
}
|
|
||||||
|
|||||||
21
Services/DragEventArgs.cs
Normal file
21
Services/DragEventArgs.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public class DragEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
public DragData Data { get; }
|
||||||
|
public int X { get; }
|
||||||
|
public int Y { get; }
|
||||||
|
public bool Accepted { get; set; }
|
||||||
|
public DragAction AllowedAction { get; set; }
|
||||||
|
public DragAction AcceptedAction { get; set; } = DragAction.Copy;
|
||||||
|
|
||||||
|
public DragEventArgs(DragData data, int x, int y)
|
||||||
|
{
|
||||||
|
Data = data;
|
||||||
|
X = x;
|
||||||
|
Y = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
17
Services/DropEventArgs.cs
Normal file
17
Services/DropEventArgs.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public class DropEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
public DragData Data { get; }
|
||||||
|
public string? DroppedData { get; }
|
||||||
|
public bool Handled { get; set; }
|
||||||
|
|
||||||
|
public DropEventArgs(DragData data, string? droppedData)
|
||||||
|
{
|
||||||
|
Data = data;
|
||||||
|
DroppedData = droppedData;
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Services/FileDialogResult.cs
Normal file
11
Services/FileDialogResult.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public class FileDialogResult
|
||||||
|
{
|
||||||
|
public bool Accepted { get; init; }
|
||||||
|
public string[] SelectedFiles { get; init; } = [];
|
||||||
|
public string? SelectedFile => SelectedFiles.Length > 0 ? SelectedFiles[0] : null;
|
||||||
|
}
|
||||||
@@ -200,13 +200,3 @@ public class FilePickerService : IFilePicker
|
|||||||
return arg.Replace("\"", "\\\"").Replace("'", "\\'");
|
return arg.Replace("\"", "\\\"").Replace("'", "\\'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Linux-specific FileResult implementation.
|
|
||||||
/// </summary>
|
|
||||||
internal class LinuxFileResult : FileResult
|
|
||||||
{
|
|
||||||
public LinuxFileResult(string fullPath) : base(fullPath)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
10
Services/FolderPickerOptions.cs
Normal file
10
Services/FolderPickerOptions.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public class FolderPickerOptions
|
||||||
|
{
|
||||||
|
public string? Title { get; set; }
|
||||||
|
public string? InitialDirectory { get; set; }
|
||||||
|
}
|
||||||
15
Services/FolderPickerResult.cs
Normal file
15
Services/FolderPickerResult.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public class FolderPickerResult
|
||||||
|
{
|
||||||
|
public FolderResult? Folder { get; }
|
||||||
|
public bool WasSuccessful => Folder != null;
|
||||||
|
|
||||||
|
public FolderPickerResult(FolderResult? folder)
|
||||||
|
{
|
||||||
|
Folder = folder;
|
||||||
|
}
|
||||||
|
}
|
||||||
15
Services/FolderResult.cs
Normal file
15
Services/FolderResult.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public class FolderResult
|
||||||
|
{
|
||||||
|
public string Path { get; }
|
||||||
|
public string Name => System.IO.Path.GetFileName(Path) ?? Path;
|
||||||
|
|
||||||
|
public FolderResult(string path)
|
||||||
|
{
|
||||||
|
Path = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -256,37 +256,6 @@ public class FontFallbackManager
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a run of text with a specific typeface.
|
|
||||||
/// </summary>
|
|
||||||
public class TextRun
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The text content of this run.
|
|
||||||
/// </summary>
|
|
||||||
public string Text { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The typeface to use for this run.
|
|
||||||
/// </summary>
|
|
||||||
public SKTypeface Typeface { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The starting character index in the original string.
|
|
||||||
/// </summary>
|
|
||||||
public int StartIndex { get; }
|
|
||||||
|
|
||||||
public TextRun(string text, SKTypeface typeface, int startIndex)
|
|
||||||
{
|
|
||||||
Text = text;
|
|
||||||
Typeface = typeface;
|
|
||||||
StartIndex = startIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// StringBuilder for internal use.
|
|
||||||
/// </summary>
|
|
||||||
file class StringBuilder
|
file class StringBuilder
|
||||||
{
|
{
|
||||||
private readonly List<char> _chars = new();
|
private readonly List<char> _chars = new();
|
||||||
|
|||||||
@@ -296,98 +296,3 @@ public class GlobalHotkeyService : IDisposable
|
|||||||
public HotkeyModifiers ModifierKeys { get; set; }
|
public HotkeyModifiers ModifierKeys { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Event args for hotkey pressed events.
|
|
||||||
/// </summary>
|
|
||||||
public class HotkeyEventArgs : EventArgs
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the registration ID.
|
|
||||||
/// </summary>
|
|
||||||
public int Id { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the key.
|
|
||||||
/// </summary>
|
|
||||||
public HotkeyKey Key { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the modifier keys.
|
|
||||||
/// </summary>
|
|
||||||
public HotkeyModifiers Modifiers { get; }
|
|
||||||
|
|
||||||
public HotkeyEventArgs(int id, HotkeyKey key, HotkeyModifiers modifiers)
|
|
||||||
{
|
|
||||||
Id = id;
|
|
||||||
Key = key;
|
|
||||||
Modifiers = modifiers;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Hotkey modifier keys.
|
|
||||||
/// </summary>
|
|
||||||
[Flags]
|
|
||||||
public enum HotkeyModifiers
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
Shift = 1 << 0,
|
|
||||||
Control = 1 << 1,
|
|
||||||
Alt = 1 << 2,
|
|
||||||
Super = 1 << 3
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Hotkey keys (X11 keysyms).
|
|
||||||
/// </summary>
|
|
||||||
public enum HotkeyKey : uint
|
|
||||||
{
|
|
||||||
// Letters
|
|
||||||
A = 0x61, B = 0x62, C = 0x63, D = 0x64, E = 0x65,
|
|
||||||
F = 0x66, G = 0x67, H = 0x68, I = 0x69, J = 0x6A,
|
|
||||||
K = 0x6B, L = 0x6C, M = 0x6D, N = 0x6E, O = 0x6F,
|
|
||||||
P = 0x70, Q = 0x71, R = 0x72, S = 0x73, T = 0x74,
|
|
||||||
U = 0x75, V = 0x76, W = 0x77, X = 0x78, Y = 0x79,
|
|
||||||
Z = 0x7A,
|
|
||||||
|
|
||||||
// Numbers
|
|
||||||
D0 = 0x30, D1 = 0x31, D2 = 0x32, D3 = 0x33, D4 = 0x34,
|
|
||||||
D5 = 0x35, D6 = 0x36, D7 = 0x37, D8 = 0x38, D9 = 0x39,
|
|
||||||
|
|
||||||
// Function keys
|
|
||||||
F1 = 0xFFBE, F2 = 0xFFBF, F3 = 0xFFC0, F4 = 0xFFC1,
|
|
||||||
F5 = 0xFFC2, F6 = 0xFFC3, F7 = 0xFFC4, F8 = 0xFFC5,
|
|
||||||
F9 = 0xFFC6, F10 = 0xFFC7, F11 = 0xFFC8, F12 = 0xFFC9,
|
|
||||||
|
|
||||||
// Special keys
|
|
||||||
Escape = 0xFF1B,
|
|
||||||
Tab = 0xFF09,
|
|
||||||
Return = 0xFF0D,
|
|
||||||
Space = 0x20,
|
|
||||||
BackSpace = 0xFF08,
|
|
||||||
Delete = 0xFFFF,
|
|
||||||
Insert = 0xFF63,
|
|
||||||
Home = 0xFF50,
|
|
||||||
End = 0xFF57,
|
|
||||||
PageUp = 0xFF55,
|
|
||||||
PageDown = 0xFF56,
|
|
||||||
|
|
||||||
// Arrow keys
|
|
||||||
Left = 0xFF51,
|
|
||||||
Up = 0xFF52,
|
|
||||||
Right = 0xFF53,
|
|
||||||
Down = 0xFF54,
|
|
||||||
|
|
||||||
// Media keys
|
|
||||||
AudioPlay = 0x1008FF14,
|
|
||||||
AudioStop = 0x1008FF15,
|
|
||||||
AudioPrev = 0x1008FF16,
|
|
||||||
AudioNext = 0x1008FF17,
|
|
||||||
AudioMute = 0x1008FF12,
|
|
||||||
AudioRaiseVolume = 0x1008FF13,
|
|
||||||
AudioLowerVolume = 0x1008FF11,
|
|
||||||
|
|
||||||
// Print screen
|
|
||||||
Print = 0xFF61
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -5,86 +5,6 @@ using System.Runtime.InteropServices;
|
|||||||
|
|
||||||
namespace Microsoft.Maui.Platform.Linux.Services;
|
namespace Microsoft.Maui.Platform.Linux.Services;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// GTK4 dialog response codes.
|
|
||||||
/// </summary>
|
|
||||||
public enum GtkResponseType
|
|
||||||
{
|
|
||||||
None = -1,
|
|
||||||
Reject = -2,
|
|
||||||
Accept = -3,
|
|
||||||
DeleteEvent = -4,
|
|
||||||
Ok = -5,
|
|
||||||
Cancel = -6,
|
|
||||||
Close = -7,
|
|
||||||
Yes = -8,
|
|
||||||
No = -9,
|
|
||||||
Apply = -10,
|
|
||||||
Help = -11
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// GTK4 message dialog types.
|
|
||||||
/// </summary>
|
|
||||||
public enum GtkMessageType
|
|
||||||
{
|
|
||||||
Info = 0,
|
|
||||||
Warning = 1,
|
|
||||||
Question = 2,
|
|
||||||
Error = 3,
|
|
||||||
Other = 4
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// GTK4 button layouts for dialogs.
|
|
||||||
/// </summary>
|
|
||||||
public enum GtkButtonsType
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
Ok = 1,
|
|
||||||
Close = 2,
|
|
||||||
Cancel = 3,
|
|
||||||
YesNo = 4,
|
|
||||||
OkCancel = 5
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// GTK4 file chooser actions.
|
|
||||||
/// </summary>
|
|
||||||
public enum GtkFileChooserAction
|
|
||||||
{
|
|
||||||
Open = 0,
|
|
||||||
Save = 1,
|
|
||||||
SelectFolder = 2,
|
|
||||||
CreateFolder = 3
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Result from a file dialog.
|
|
||||||
/// </summary>
|
|
||||||
public class FileDialogResult
|
|
||||||
{
|
|
||||||
public bool Accepted { get; init; }
|
|
||||||
public string[] SelectedFiles { get; init; } = Array.Empty<string>();
|
|
||||||
public string? SelectedFile => SelectedFiles.Length > 0 ? SelectedFiles[0] : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Result from a color dialog.
|
|
||||||
/// </summary>
|
|
||||||
public class ColorDialogResult
|
|
||||||
{
|
|
||||||
public bool Accepted { get; init; }
|
|
||||||
public float Red { get; init; }
|
|
||||||
public float Green { get; init; }
|
|
||||||
public float Blue { get; init; }
|
|
||||||
public float Alpha { get; init; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// GTK4 interop layer for native Linux dialogs.
|
|
||||||
/// Provides native file pickers, message boxes, and color choosers.
|
|
||||||
/// </summary>
|
|
||||||
public class Gtk4InteropService : IDisposable
|
public class Gtk4InteropService : IDisposable
|
||||||
{
|
{
|
||||||
#region GTK4 Native Interop
|
#region GTK4 Native Interop
|
||||||
|
|||||||
14
Services/GtkButtonsType.cs
Normal file
14
Services/GtkButtonsType.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public enum GtkButtonsType
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Ok,
|
||||||
|
Close,
|
||||||
|
Cancel,
|
||||||
|
YesNo,
|
||||||
|
OkCancel
|
||||||
|
}
|
||||||
12
Services/GtkFileChooserAction.cs
Normal file
12
Services/GtkFileChooserAction.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public enum GtkFileChooserAction
|
||||||
|
{
|
||||||
|
Open,
|
||||||
|
Save,
|
||||||
|
SelectFolder,
|
||||||
|
CreateFolder
|
||||||
|
}
|
||||||
13
Services/GtkMessageType.cs
Normal file
13
Services/GtkMessageType.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public enum GtkMessageType
|
||||||
|
{
|
||||||
|
Info,
|
||||||
|
Warning,
|
||||||
|
Question,
|
||||||
|
Error,
|
||||||
|
Other
|
||||||
|
}
|
||||||
19
Services/GtkResponseType.cs
Normal file
19
Services/GtkResponseType.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public enum GtkResponseType
|
||||||
|
{
|
||||||
|
None = -1,
|
||||||
|
Reject = -2,
|
||||||
|
Accept = -3,
|
||||||
|
DeleteEvent = -4,
|
||||||
|
Ok = -5,
|
||||||
|
Cancel = -6,
|
||||||
|
Close = -7,
|
||||||
|
Yes = -8,
|
||||||
|
No = -9,
|
||||||
|
Apply = -10,
|
||||||
|
Help = -11
|
||||||
|
}
|
||||||
@@ -6,83 +6,6 @@ using SkiaSharp;
|
|||||||
|
|
||||||
namespace Microsoft.Maui.Platform.Linux.Services;
|
namespace Microsoft.Maui.Platform.Linux.Services;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Supported hardware video acceleration APIs.
|
|
||||||
/// </summary>
|
|
||||||
public enum VideoAccelerationApi
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Automatically select the best available API.
|
|
||||||
/// </summary>
|
|
||||||
Auto,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// VA-API (Video Acceleration API) - Intel, AMD, and some NVIDIA.
|
|
||||||
/// </summary>
|
|
||||||
VaApi,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// VDPAU (Video Decode and Presentation API for Unix) - NVIDIA.
|
|
||||||
/// </summary>
|
|
||||||
Vdpau,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Software decoding fallback.
|
|
||||||
/// </summary>
|
|
||||||
Software
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Video codec profiles supported by hardware acceleration.
|
|
||||||
/// </summary>
|
|
||||||
public enum VideoProfile
|
|
||||||
{
|
|
||||||
H264Baseline,
|
|
||||||
H264Main,
|
|
||||||
H264High,
|
|
||||||
H265Main,
|
|
||||||
H265Main10,
|
|
||||||
Vp8,
|
|
||||||
Vp9Profile0,
|
|
||||||
Vp9Profile2,
|
|
||||||
Av1Main
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Information about a decoded video frame.
|
|
||||||
/// </summary>
|
|
||||||
public class VideoFrame : IDisposable
|
|
||||||
{
|
|
||||||
public int Width { get; init; }
|
|
||||||
public int Height { get; init; }
|
|
||||||
public IntPtr DataY { get; init; }
|
|
||||||
public IntPtr DataU { get; init; }
|
|
||||||
public IntPtr DataV { get; init; }
|
|
||||||
public int StrideY { get; init; }
|
|
||||||
public int StrideU { get; init; }
|
|
||||||
public int StrideV { get; init; }
|
|
||||||
public long Timestamp { get; init; }
|
|
||||||
public bool IsKeyFrame { get; init; }
|
|
||||||
|
|
||||||
private bool _disposed;
|
|
||||||
private Action? _releaseCallback;
|
|
||||||
|
|
||||||
internal void SetReleaseCallback(Action callback) => _releaseCallback = callback;
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
if (!_disposed)
|
|
||||||
{
|
|
||||||
_releaseCallback?.Invoke();
|
|
||||||
_disposed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Hardware-accelerated video decoding service using VA-API or VDPAU.
|
|
||||||
/// Provides efficient video decode for media playback on Linux.
|
|
||||||
/// </summary>
|
|
||||||
public class HardwareVideoService : IDisposable
|
public class HardwareVideoService : IDisposable
|
||||||
{
|
{
|
||||||
#region VA-API Native Interop
|
#region VA-API Native Interop
|
||||||
|
|||||||
@@ -494,31 +494,3 @@ public class HiDpiService
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Event args for scale change events.
|
|
||||||
/// </summary>
|
|
||||||
public class ScaleChangedEventArgs : EventArgs
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the old scale factor.
|
|
||||||
/// </summary>
|
|
||||||
public float OldScale { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the new scale factor.
|
|
||||||
/// </summary>
|
|
||||||
public float NewScale { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the new DPI.
|
|
||||||
/// </summary>
|
|
||||||
public float NewDpi { get; }
|
|
||||||
|
|
||||||
public ScaleChangedEventArgs(float oldScale, float newScale, float newDpi)
|
|
||||||
{
|
|
||||||
OldScale = oldScale;
|
|
||||||
NewScale = newScale;
|
|
||||||
NewDpi = newDpi;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
17
Services/HighContrastChangedEventArgs.cs
Normal file
17
Services/HighContrastChangedEventArgs.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public class HighContrastChangedEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
public bool IsEnabled { get; }
|
||||||
|
|
||||||
|
public HighContrastTheme Theme { get; }
|
||||||
|
|
||||||
|
public HighContrastChangedEventArgs(bool isEnabled, HighContrastTheme theme)
|
||||||
|
{
|
||||||
|
IsEnabled = isEnabled;
|
||||||
|
Theme = theme;
|
||||||
|
}
|
||||||
|
}
|
||||||
35
Services/HighContrastColors.cs
Normal file
35
Services/HighContrastColors.cs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||||
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
|
||||||
|
using SkiaSharp;
|
||||||
|
|
||||||
|
namespace Microsoft.Maui.Platform.Linux.Services;
|
||||||
|
|
||||||
|
public class HighContrastColors
|
||||||
|
{
|
||||||
|
public SKColor Background { get; set; }
|
||||||
|
|
||||||
|
public SKColor Foreground { get; set; }
|
||||||
|
|
||||||
|
public SKColor Accent { get; set; }
|
||||||
|
|
||||||
|
public SKColor Border { get; set; }
|
||||||
|
|
||||||
|
public SKColor Error { get; set; }
|
||||||
|
|
||||||
|
public SKColor Success { get; set; }
|
||||||
|
|
||||||
|
public SKColor Warning { get; set; }
|
||||||
|
|
||||||
|
public SKColor Link { get; set; }
|
||||||
|
|
||||||
|
public SKColor LinkVisited { get; set; }
|
||||||
|
|
||||||
|
public SKColor Selection { get; set; }
|
||||||
|
|
||||||
|
public SKColor SelectionText { get; set; }
|
||||||
|
|
||||||
|
public SKColor DisabledText { get; set; }
|
||||||
|
|
||||||
|
public SKColor DisabledBackground { get; set; }
|
||||||
|
}
|
||||||
@@ -348,55 +348,3 @@ public class HighContrastService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// High contrast theme types.
|
|
||||||
/// </summary>
|
|
||||||
public enum HighContrastTheme
|
|
||||||
{
|
|
||||||
None,
|
|
||||||
WhiteOnBlack,
|
|
||||||
BlackOnWhite
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Color palette for high contrast mode.
|
|
||||||
/// </summary>
|
|
||||||
public class HighContrastColors
|
|
||||||
{
|
|
||||||
public SKColor Background { get; set; }
|
|
||||||
public SKColor Foreground { get; set; }
|
|
||||||
public SKColor Accent { get; set; }
|
|
||||||
public SKColor Border { get; set; }
|
|
||||||
public SKColor Error { get; set; }
|
|
||||||
public SKColor Success { get; set; }
|
|
||||||
public SKColor Warning { get; set; }
|
|
||||||
public SKColor Link { get; set; }
|
|
||||||
public SKColor LinkVisited { get; set; }
|
|
||||||
public SKColor Selection { get; set; }
|
|
||||||
public SKColor SelectionText { get; set; }
|
|
||||||
public SKColor DisabledText { get; set; }
|
|
||||||
public SKColor DisabledBackground { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Event args for high contrast mode changes.
|
|
||||||
/// </summary>
|
|
||||||
public class HighContrastChangedEventArgs : EventArgs
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets whether high contrast mode is enabled.
|
|
||||||
/// </summary>
|
|
||||||
public bool IsEnabled { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the current theme.
|
|
||||||
/// </summary>
|
|
||||||
public HighContrastTheme Theme { get; }
|
|
||||||
|
|
||||||
public HighContrastChangedEventArgs(bool isEnabled, HighContrastTheme theme)
|
|
||||||
{
|
|
||||||
IsEnabled = isEnabled;
|
|
||||||
Theme = theme;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
11
Services/HighContrastTheme.cs
Normal file
11
Services/HighContrastTheme.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public enum HighContrastTheme
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
WhiteOnBlack,
|
||||||
|
BlackOnWhite
|
||||||
|
}
|
||||||
18
Services/HotkeyEventArgs.cs
Normal file
18
Services/HotkeyEventArgs.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public class HotkeyEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
public int Id { get; }
|
||||||
|
public HotkeyKey Key { get; }
|
||||||
|
public HotkeyModifiers Modifiers { get; }
|
||||||
|
|
||||||
|
public HotkeyEventArgs(int id, HotkeyKey key, HotkeyModifiers modifiers)
|
||||||
|
{
|
||||||
|
Id = id;
|
||||||
|
Key = key;
|
||||||
|
Modifiers = modifiers;
|
||||||
|
}
|
||||||
|
}
|
||||||
17
Services/HotkeyKey.cs
Normal file
17
Services/HotkeyKey.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public enum HotkeyKey
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
A, B, C, D, E, F, G, H, I, J, K, L, M,
|
||||||
|
N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
|
||||||
|
D0, D1, D2, D3, D4, D5, D6, D7, D8, D9,
|
||||||
|
F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12,
|
||||||
|
Space, Enter, Escape, Tab, Backspace, Delete, Insert,
|
||||||
|
Home, End, PageUp, PageDown,
|
||||||
|
Left, Right, Up, Down,
|
||||||
|
PrintScreen, Pause, NumLock, ScrollLock, CapsLock
|
||||||
|
}
|
||||||
14
Services/HotkeyModifiers.cs
Normal file
14
Services/HotkeyModifiers.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum HotkeyModifiers
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Alt = 1,
|
||||||
|
Control = 2,
|
||||||
|
Shift = 4,
|
||||||
|
Super = 8
|
||||||
|
}
|
||||||
@@ -64,373 +64,3 @@ public interface IAccessibilityService
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Interface for accessible objects.
|
|
||||||
/// </summary>
|
|
||||||
public interface IAccessible
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the unique identifier for this accessible.
|
|
||||||
/// </summary>
|
|
||||||
string AccessibleId { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the accessible name (label for screen readers).
|
|
||||||
/// </summary>
|
|
||||||
string AccessibleName { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the accessible description (additional context).
|
|
||||||
/// </summary>
|
|
||||||
string AccessibleDescription { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the accessible role.
|
|
||||||
/// </summary>
|
|
||||||
AccessibleRole Role { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the accessible states.
|
|
||||||
/// </summary>
|
|
||||||
AccessibleStates States { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the parent accessible.
|
|
||||||
/// </summary>
|
|
||||||
IAccessible? Parent { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the child accessibles.
|
|
||||||
/// </summary>
|
|
||||||
IReadOnlyList<IAccessible> Children { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the bounding rectangle in screen coordinates.
|
|
||||||
/// </summary>
|
|
||||||
AccessibleRect Bounds { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the available actions.
|
|
||||||
/// </summary>
|
|
||||||
IReadOnlyList<AccessibleAction> Actions { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Performs an action.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="actionName">The name of the action to perform.</param>
|
|
||||||
/// <returns>True if the action was performed.</returns>
|
|
||||||
bool DoAction(string actionName);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the accessible value (for sliders, progress bars, etc.).
|
|
||||||
/// </summary>
|
|
||||||
double? Value { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the minimum value.
|
|
||||||
/// </summary>
|
|
||||||
double? MinValue { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the maximum value.
|
|
||||||
/// </summary>
|
|
||||||
double? MaxValue { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the accessible value.
|
|
||||||
/// </summary>
|
|
||||||
bool SetValue(double value);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Interface for accessible text components.
|
|
||||||
/// </summary>
|
|
||||||
public interface IAccessibleText : IAccessible
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the text content.
|
|
||||||
/// </summary>
|
|
||||||
string Text { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the caret offset.
|
|
||||||
/// </summary>
|
|
||||||
int CaretOffset { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the number of selections.
|
|
||||||
/// </summary>
|
|
||||||
int SelectionCount { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the selection at the specified index.
|
|
||||||
/// </summary>
|
|
||||||
(int Start, int End) GetSelection(int index);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the selection.
|
|
||||||
/// </summary>
|
|
||||||
bool SetSelection(int index, int start, int end);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the character at the specified offset.
|
|
||||||
/// </summary>
|
|
||||||
char GetCharacterAtOffset(int offset);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the text in the specified range.
|
|
||||||
/// </summary>
|
|
||||||
string GetTextInRange(int start, int end);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the bounds of the character at the specified offset.
|
|
||||||
/// </summary>
|
|
||||||
AccessibleRect GetCharacterBounds(int offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Interface for editable text components.
|
|
||||||
/// </summary>
|
|
||||||
public interface IAccessibleEditableText : IAccessibleText
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Sets the text content.
|
|
||||||
/// </summary>
|
|
||||||
bool SetText(string text);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Inserts text at the specified position.
|
|
||||||
/// </summary>
|
|
||||||
bool InsertText(int position, string text);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Deletes text in the specified range.
|
|
||||||
/// </summary>
|
|
||||||
bool DeleteText(int start, int end);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Copies text to clipboard.
|
|
||||||
/// </summary>
|
|
||||||
bool CopyText(int start, int end);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Cuts text to clipboard.
|
|
||||||
/// </summary>
|
|
||||||
bool CutText(int start, int end);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Pastes text from clipboard.
|
|
||||||
/// </summary>
|
|
||||||
bool PasteText(int position);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Accessible roles (based on AT-SPI2 roles).
|
|
||||||
/// </summary>
|
|
||||||
public enum AccessibleRole
|
|
||||||
{
|
|
||||||
Unknown,
|
|
||||||
Window,
|
|
||||||
Application,
|
|
||||||
Panel,
|
|
||||||
Frame,
|
|
||||||
Button,
|
|
||||||
CheckBox,
|
|
||||||
RadioButton,
|
|
||||||
ComboBox,
|
|
||||||
Entry,
|
|
||||||
Label,
|
|
||||||
List,
|
|
||||||
ListItem,
|
|
||||||
Menu,
|
|
||||||
MenuBar,
|
|
||||||
MenuItem,
|
|
||||||
ScrollBar,
|
|
||||||
Slider,
|
|
||||||
SpinButton,
|
|
||||||
StatusBar,
|
|
||||||
Tab,
|
|
||||||
TabPanel,
|
|
||||||
Text,
|
|
||||||
ToggleButton,
|
|
||||||
ToolBar,
|
|
||||||
ToolTip,
|
|
||||||
Tree,
|
|
||||||
TreeItem,
|
|
||||||
Image,
|
|
||||||
ProgressBar,
|
|
||||||
Separator,
|
|
||||||
Link,
|
|
||||||
Table,
|
|
||||||
TableCell,
|
|
||||||
TableRow,
|
|
||||||
TableColumnHeader,
|
|
||||||
TableRowHeader,
|
|
||||||
PageTab,
|
|
||||||
PageTabList,
|
|
||||||
Dialog,
|
|
||||||
Alert,
|
|
||||||
Filler,
|
|
||||||
Icon,
|
|
||||||
Canvas
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Accessible states.
|
|
||||||
/// </summary>
|
|
||||||
[Flags]
|
|
||||||
public enum AccessibleStates : long
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
Active = 1L << 0,
|
|
||||||
Armed = 1L << 1,
|
|
||||||
Busy = 1L << 2,
|
|
||||||
Checked = 1L << 3,
|
|
||||||
Collapsed = 1L << 4,
|
|
||||||
Defunct = 1L << 5,
|
|
||||||
Editable = 1L << 6,
|
|
||||||
Enabled = 1L << 7,
|
|
||||||
Expandable = 1L << 8,
|
|
||||||
Expanded = 1L << 9,
|
|
||||||
Focusable = 1L << 10,
|
|
||||||
Focused = 1L << 11,
|
|
||||||
HasToolTip = 1L << 12,
|
|
||||||
Horizontal = 1L << 13,
|
|
||||||
Iconified = 1L << 14,
|
|
||||||
Modal = 1L << 15,
|
|
||||||
MultiLine = 1L << 16,
|
|
||||||
MultiSelectable = 1L << 17,
|
|
||||||
Opaque = 1L << 18,
|
|
||||||
Pressed = 1L << 19,
|
|
||||||
Resizable = 1L << 20,
|
|
||||||
Selectable = 1L << 21,
|
|
||||||
Selected = 1L << 22,
|
|
||||||
Sensitive = 1L << 23,
|
|
||||||
Showing = 1L << 24,
|
|
||||||
SingleLine = 1L << 25,
|
|
||||||
Stale = 1L << 26,
|
|
||||||
Transient = 1L << 27,
|
|
||||||
Vertical = 1L << 28,
|
|
||||||
Visible = 1L << 29,
|
|
||||||
ManagesDescendants = 1L << 30,
|
|
||||||
Indeterminate = 1L << 31,
|
|
||||||
Required = 1L << 32,
|
|
||||||
Truncated = 1L << 33,
|
|
||||||
Animated = 1L << 34,
|
|
||||||
InvalidEntry = 1L << 35,
|
|
||||||
SupportsAutocompletion = 1L << 36,
|
|
||||||
SelectableText = 1L << 37,
|
|
||||||
IsDefault = 1L << 38,
|
|
||||||
Visited = 1L << 39,
|
|
||||||
ReadOnly = 1L << 40
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Accessible state enumeration for notifications.
|
|
||||||
/// </summary>
|
|
||||||
public enum AccessibleState
|
|
||||||
{
|
|
||||||
Active,
|
|
||||||
Armed,
|
|
||||||
Busy,
|
|
||||||
Checked,
|
|
||||||
Collapsed,
|
|
||||||
Defunct,
|
|
||||||
Editable,
|
|
||||||
Enabled,
|
|
||||||
Expandable,
|
|
||||||
Expanded,
|
|
||||||
Focusable,
|
|
||||||
Focused,
|
|
||||||
Horizontal,
|
|
||||||
Iconified,
|
|
||||||
Modal,
|
|
||||||
MultiLine,
|
|
||||||
Opaque,
|
|
||||||
Pressed,
|
|
||||||
Resizable,
|
|
||||||
Selectable,
|
|
||||||
Selected,
|
|
||||||
Sensitive,
|
|
||||||
Showing,
|
|
||||||
SingleLine,
|
|
||||||
Stale,
|
|
||||||
Transient,
|
|
||||||
Vertical,
|
|
||||||
Visible,
|
|
||||||
ManagesDescendants,
|
|
||||||
Indeterminate,
|
|
||||||
Required,
|
|
||||||
InvalidEntry,
|
|
||||||
ReadOnly
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Accessible property for notifications.
|
|
||||||
/// </summary>
|
|
||||||
public enum AccessibleProperty
|
|
||||||
{
|
|
||||||
Name,
|
|
||||||
Description,
|
|
||||||
Role,
|
|
||||||
Value,
|
|
||||||
Parent,
|
|
||||||
Children
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Announcement priority.
|
|
||||||
/// </summary>
|
|
||||||
public enum AnnouncementPriority
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Low priority - can be interrupted.
|
|
||||||
/// </summary>
|
|
||||||
Polite,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// High priority - interrupts current speech.
|
|
||||||
/// </summary>
|
|
||||||
Assertive
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents an accessible action.
|
|
||||||
/// </summary>
|
|
||||||
public class AccessibleAction
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The action name.
|
|
||||||
/// </summary>
|
|
||||||
public string Name { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The action description.
|
|
||||||
/// </summary>
|
|
||||||
public string Description { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The keyboard shortcut for this action.
|
|
||||||
/// </summary>
|
|
||||||
public string? KeyBinding { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents a rectangle in accessible coordinates.
|
|
||||||
/// </summary>
|
|
||||||
public struct AccessibleRect
|
|
||||||
{
|
|
||||||
public int X { get; set; }
|
|
||||||
public int Y { get; set; }
|
|
||||||
public int Width { get; set; }
|
|
||||||
public int Height { get; set; }
|
|
||||||
|
|
||||||
public AccessibleRect(int x, int y, int width, int height)
|
|
||||||
{
|
|
||||||
X = x;
|
|
||||||
Y = y;
|
|
||||||
Width = width;
|
|
||||||
Height = height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
23
Services/IAccessible.cs
Normal file
23
Services/IAccessible.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public interface IAccessible
|
||||||
|
{
|
||||||
|
string AccessibleId { get; }
|
||||||
|
string AccessibleName { get; }
|
||||||
|
string AccessibleDescription { get; }
|
||||||
|
AccessibleRole Role { get; }
|
||||||
|
AccessibleStates States { get; }
|
||||||
|
IAccessible? Parent { get; }
|
||||||
|
IReadOnlyList<IAccessible> Children { get; }
|
||||||
|
AccessibleRect Bounds { get; }
|
||||||
|
IReadOnlyList<AccessibleAction> Actions { get; }
|
||||||
|
double? Value { get; }
|
||||||
|
double? MinValue { get; }
|
||||||
|
double? MaxValue { get; }
|
||||||
|
|
||||||
|
bool DoAction(string actionName);
|
||||||
|
bool SetValue(double value);
|
||||||
|
}
|
||||||
19
Services/IAccessibleEditableText.cs
Normal file
19
Services/IAccessibleEditableText.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public interface IAccessibleEditableText : IAccessibleText, IAccessible
|
||||||
|
{
|
||||||
|
bool SetText(string text);
|
||||||
|
|
||||||
|
bool InsertText(int position, string text);
|
||||||
|
|
||||||
|
bool DeleteText(int start, int end);
|
||||||
|
|
||||||
|
bool CopyText(int start, int end);
|
||||||
|
|
||||||
|
bool CutText(int start, int end);
|
||||||
|
|
||||||
|
bool PasteText(int position);
|
||||||
|
}
|
||||||
23
Services/IAccessibleText.cs
Normal file
23
Services/IAccessibleText.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public interface IAccessibleText : IAccessible
|
||||||
|
{
|
||||||
|
string Text { get; }
|
||||||
|
|
||||||
|
int CaretOffset { get; }
|
||||||
|
|
||||||
|
int SelectionCount { get; }
|
||||||
|
|
||||||
|
(int Start, int End) GetSelection(int index);
|
||||||
|
|
||||||
|
bool SetSelection(int index, int start, int end);
|
||||||
|
|
||||||
|
char GetCharacterAtOffset(int offset);
|
||||||
|
|
||||||
|
string GetTextInRange(int start, int end);
|
||||||
|
|
||||||
|
AccessibleRect GetCharacterBounds(int offset);
|
||||||
|
}
|
||||||
45
Services/IDisplayWindow.cs
Normal file
45
Services/IDisplayWindow.cs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public interface IDisplayWindow : IDisposable
|
||||||
|
{
|
||||||
|
int Width { get; }
|
||||||
|
|
||||||
|
int Height { get; }
|
||||||
|
|
||||||
|
bool IsRunning { get; }
|
||||||
|
|
||||||
|
event EventHandler<KeyEventArgs>? KeyDown;
|
||||||
|
|
||||||
|
event EventHandler<KeyEventArgs>? KeyUp;
|
||||||
|
|
||||||
|
event EventHandler<TextInputEventArgs>? TextInput;
|
||||||
|
|
||||||
|
event EventHandler<PointerEventArgs>? PointerMoved;
|
||||||
|
|
||||||
|
event EventHandler<PointerEventArgs>? PointerPressed;
|
||||||
|
|
||||||
|
event EventHandler<PointerEventArgs>? PointerReleased;
|
||||||
|
|
||||||
|
event EventHandler<ScrollEventArgs>? Scroll;
|
||||||
|
|
||||||
|
event EventHandler? Exposed;
|
||||||
|
|
||||||
|
event EventHandler<(int Width, int Height)>? Resized;
|
||||||
|
|
||||||
|
event EventHandler? CloseRequested;
|
||||||
|
|
||||||
|
void Show();
|
||||||
|
|
||||||
|
void Hide();
|
||||||
|
|
||||||
|
void SetTitle(string title);
|
||||||
|
|
||||||
|
void Resize(int width, int height);
|
||||||
|
|
||||||
|
void ProcessEvents();
|
||||||
|
|
||||||
|
void Stop();
|
||||||
|
}
|
||||||
21
Services/IInputContext.cs
Normal file
21
Services/IInputContext.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public interface IInputContext
|
||||||
|
{
|
||||||
|
string Text { get; set; }
|
||||||
|
|
||||||
|
int CursorPosition { get; set; }
|
||||||
|
|
||||||
|
int SelectionStart { get; }
|
||||||
|
|
||||||
|
int SelectionLength { get; }
|
||||||
|
|
||||||
|
void OnTextCommitted(string text);
|
||||||
|
|
||||||
|
void OnPreEditChanged(string preEditText, int cursorPosition);
|
||||||
|
|
||||||
|
void OnPreEditEnded();
|
||||||
|
}
|
||||||
@@ -79,153 +79,3 @@ public interface IInputMethodService
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
event EventHandler? PreEditEnded;
|
event EventHandler? PreEditEnded;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents an input context that can receive IME input.
|
|
||||||
/// </summary>
|
|
||||||
public interface IInputContext
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the current text content.
|
|
||||||
/// </summary>
|
|
||||||
string Text { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the cursor position.
|
|
||||||
/// </summary>
|
|
||||||
int CursorPosition { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the selection start position.
|
|
||||||
/// </summary>
|
|
||||||
int SelectionStart { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the selection length.
|
|
||||||
/// </summary>
|
|
||||||
int SelectionLength { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when text is committed from the IME.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="text">The committed text.</param>
|
|
||||||
void OnTextCommitted(string text);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when pre-edit text changes.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="preEditText">The current pre-edit text.</param>
|
|
||||||
/// <param name="cursorPosition">Cursor position within pre-edit text.</param>
|
|
||||||
void OnPreEditChanged(string preEditText, int cursorPosition);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Called when pre-edit mode ends.
|
|
||||||
/// </summary>
|
|
||||||
void OnPreEditEnded();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Event args for text committed events.
|
|
||||||
/// </summary>
|
|
||||||
public class TextCommittedEventArgs : EventArgs
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The committed text.
|
|
||||||
/// </summary>
|
|
||||||
public string Text { get; }
|
|
||||||
|
|
||||||
public TextCommittedEventArgs(string text)
|
|
||||||
{
|
|
||||||
Text = text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Event args for pre-edit changed events.
|
|
||||||
/// </summary>
|
|
||||||
public class PreEditChangedEventArgs : EventArgs
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// The current pre-edit text.
|
|
||||||
/// </summary>
|
|
||||||
public string PreEditText { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Cursor position within the pre-edit text.
|
|
||||||
/// </summary>
|
|
||||||
public int CursorPosition { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Formatting attributes for the pre-edit text.
|
|
||||||
/// </summary>
|
|
||||||
public IReadOnlyList<PreEditAttribute> Attributes { get; }
|
|
||||||
|
|
||||||
public PreEditChangedEventArgs(string preEditText, int cursorPosition, IReadOnlyList<PreEditAttribute>? attributes = null)
|
|
||||||
{
|
|
||||||
PreEditText = preEditText;
|
|
||||||
CursorPosition = cursorPosition;
|
|
||||||
Attributes = attributes ?? Array.Empty<PreEditAttribute>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Represents formatting for a portion of pre-edit text.
|
|
||||||
/// </summary>
|
|
||||||
public class PreEditAttribute
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Start position in the pre-edit text.
|
|
||||||
/// </summary>
|
|
||||||
public int Start { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Length of the attributed range.
|
|
||||||
/// </summary>
|
|
||||||
public int Length { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The attribute type.
|
|
||||||
/// </summary>
|
|
||||||
public PreEditAttributeType Type { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Types of pre-edit text attributes.
|
|
||||||
/// </summary>
|
|
||||||
public enum PreEditAttributeType
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Normal text (no special formatting).
|
|
||||||
/// </summary>
|
|
||||||
None,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Underlined text (typical for composition).
|
|
||||||
/// </summary>
|
|
||||||
Underline,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Highlighted/selected text.
|
|
||||||
/// </summary>
|
|
||||||
Highlighted,
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Reverse video (selected clause in some IMEs).
|
|
||||||
/// </summary>
|
|
||||||
Reverse
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Key modifiers for IME processing.
|
|
||||||
/// </summary>
|
|
||||||
[Flags]
|
|
||||||
public enum KeyModifiers
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
Shift = 1 << 0,
|
|
||||||
Control = 1 << 1,
|
|
||||||
Alt = 1 << 2,
|
|
||||||
Super = 1 << 3,
|
|
||||||
CapsLock = 1 << 4,
|
|
||||||
NumLock = 1 << 5
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -180,24 +180,3 @@ public static class InputMethodServiceFactory
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Null implementation of IInputMethodService for when no IME is available.
|
|
||||||
/// </summary>
|
|
||||||
public class NullInputMethodService : IInputMethodService
|
|
||||||
{
|
|
||||||
public bool IsActive => false;
|
|
||||||
public string PreEditText => string.Empty;
|
|
||||||
public int PreEditCursorPosition => 0;
|
|
||||||
|
|
||||||
public event EventHandler<TextCommittedEventArgs>? TextCommitted;
|
|
||||||
public event EventHandler<PreEditChangedEventArgs>? PreEditChanged;
|
|
||||||
public event EventHandler? PreEditEnded;
|
|
||||||
|
|
||||||
public void Initialize(nint windowHandle) { }
|
|
||||||
public void SetFocus(IInputContext? context) { }
|
|
||||||
public void SetCursorLocation(int x, int y, int width, int height) { }
|
|
||||||
public bool ProcessKeyEvent(uint keyCode, KeyModifiers modifiers, bool isKeyDown) => false;
|
|
||||||
public void Reset() { }
|
|
||||||
public void Shutdown() { }
|
|
||||||
}
|
|
||||||
|
|||||||
16
Services/KeyModifiers.cs
Normal file
16
Services/KeyModifiers.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum KeyModifiers
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Shift = 1,
|
||||||
|
Control = 2,
|
||||||
|
Alt = 4,
|
||||||
|
Super = 8,
|
||||||
|
CapsLock = 0x10,
|
||||||
|
NumLock = 0x20
|
||||||
|
}
|
||||||
14
Services/LinuxFileResult.cs
Normal file
14
Services/LinuxFileResult.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
// 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.Storage;
|
||||||
|
|
||||||
|
namespace Microsoft.Maui.Platform.Linux.Services;
|
||||||
|
|
||||||
|
internal class LinuxFileResult : FileResult
|
||||||
|
{
|
||||||
|
public LinuxFileResult(string fullPath)
|
||||||
|
: base(fullPath)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,13 +3,13 @@ using System.Collections.Generic;
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using SkiaSharp;
|
using SkiaSharp;
|
||||||
|
using Svg.Skia;
|
||||||
|
|
||||||
namespace Microsoft.Maui.Platform.Linux.Services;
|
namespace Microsoft.Maui.Platform.Linux.Services;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generates application icons from MAUI icon metadata.
|
/// Generates application icons from MAUI icon metadata.
|
||||||
/// Creates PNG icons suitable for use as window icons on Linux.
|
/// Uses SVG overlay support via Svg.Skia package.
|
||||||
/// Note: SVG overlay support requires Svg.Skia package (optional).
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class MauiIconGenerator
|
public static class MauiIconGenerator
|
||||||
{
|
{
|
||||||
@@ -28,50 +28,52 @@ public static class MauiIconGenerator
|
|||||||
string path = Path.GetDirectoryName(metaFilePath) ?? "";
|
string path = Path.GetDirectoryName(metaFilePath) ?? "";
|
||||||
var metadata = ParseMetadata(File.ReadAllText(metaFilePath));
|
var metadata = ParseMetadata(File.ReadAllText(metaFilePath));
|
||||||
|
|
||||||
|
// bg and fg paths (bg not currently used, but available for future)
|
||||||
|
Path.Combine(path, "appicon_bg.svg");
|
||||||
|
string fgPath = Path.Combine(path, "appicon_fg.svg");
|
||||||
string outputPath = Path.Combine(path, "appicon.png");
|
string outputPath = Path.Combine(path, "appicon.png");
|
||||||
|
|
||||||
|
// Parse size from metadata or use default
|
||||||
int size = metadata.TryGetValue("Size", out var sizeStr) && int.TryParse(sizeStr, out var sizeVal)
|
int size = metadata.TryGetValue("Size", out var sizeStr) && int.TryParse(sizeStr, out var sizeVal)
|
||||||
? sizeVal
|
? sizeVal
|
||||||
: DefaultIconSize;
|
: DefaultIconSize;
|
||||||
|
|
||||||
|
// Parse color from metadata or use default purple
|
||||||
SKColor color = metadata.TryGetValue("Color", out var colorStr)
|
SKColor color = metadata.TryGetValue("Color", out var colorStr)
|
||||||
? ParseColor(colorStr)
|
? ParseColor(colorStr)
|
||||||
: SKColors.Purple;
|
: SKColors.Purple;
|
||||||
|
|
||||||
|
// Parse scale from metadata or use default 0.65
|
||||||
|
float scale = metadata.TryGetValue("Scale", out var scaleStr) && float.TryParse(scaleStr, out var scaleVal)
|
||||||
|
? scaleVal
|
||||||
|
: 0.65f;
|
||||||
|
|
||||||
Console.WriteLine($"[MauiIconGenerator] Generating {size}x{size} icon");
|
Console.WriteLine($"[MauiIconGenerator] Generating {size}x{size} icon");
|
||||||
Console.WriteLine($"[MauiIconGenerator] Color: {color}");
|
Console.WriteLine($"[MauiIconGenerator] Color: {color}");
|
||||||
|
Console.WriteLine($"[MauiIconGenerator] Scale: {scale}");
|
||||||
|
|
||||||
using var surface = SKSurface.Create(new SKImageInfo(size, size, SKColorType.Bgra8888, SKAlphaType.Premul));
|
using var surface = SKSurface.Create(new SKImageInfo(size, size, SKColorType.Bgra8888, SKAlphaType.Premul));
|
||||||
var canvas = surface.Canvas;
|
var canvas = surface.Canvas;
|
||||||
|
|
||||||
// Draw background with rounded corners
|
// Fill background with color
|
||||||
canvas.Clear(SKColors.Transparent);
|
canvas.Clear(color);
|
||||||
float cornerRadius = size * 0.2f;
|
|
||||||
using var paint = new SKPaint { Color = color, IsAntialias = true };
|
|
||||||
canvas.DrawRoundRect(new SKRoundRect(new SKRect(0, 0, size, size), cornerRadius), paint);
|
|
||||||
|
|
||||||
// Try to load PNG foreground as fallback (appicon_fg.png)
|
// Load and draw SVG foreground if it exists
|
||||||
string fgPngPath = Path.Combine(path, "appicon_fg.png");
|
if (File.Exists(fgPath))
|
||||||
if (File.Exists(fgPngPath))
|
|
||||||
{
|
{
|
||||||
try
|
using var svg = new SKSvg();
|
||||||
|
if (svg.Load(fgPath) != null && svg.Picture != null)
|
||||||
{
|
{
|
||||||
using var fgBitmap = SKBitmap.Decode(fgPngPath);
|
var cullRect = svg.Picture.CullRect;
|
||||||
if (fgBitmap != null)
|
float svgScale = size * scale / Math.Max(cullRect.Width, cullRect.Height);
|
||||||
{
|
float offsetX = (size - cullRect.Width * svgScale) / 2f;
|
||||||
float scale = size * 0.65f / Math.Max(fgBitmap.Width, fgBitmap.Height);
|
float offsetY = (size - cullRect.Height * svgScale) / 2f;
|
||||||
float fgWidth = fgBitmap.Width * scale;
|
|
||||||
float fgHeight = fgBitmap.Height * scale;
|
|
||||||
float offsetX = (size - fgWidth) / 2f;
|
|
||||||
float offsetY = (size - fgHeight) / 2f;
|
|
||||||
|
|
||||||
var dstRect = new SKRect(offsetX, offsetY, offsetX + fgWidth, offsetY + fgHeight);
|
canvas.Save();
|
||||||
canvas.DrawBitmap(fgBitmap, dstRect);
|
canvas.Translate(offsetX, offsetY);
|
||||||
}
|
canvas.Scale(svgScale);
|
||||||
}
|
canvas.DrawPicture(svg.Picture);
|
||||||
catch (Exception ex)
|
canvas.Restore();
|
||||||
{
|
|
||||||
Console.WriteLine("[MauiIconGenerator] Failed to load foreground PNG: " + ex.Message);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
24
Services/NotificationAction.cs
Normal file
24
Services/NotificationAction.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
// 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.Linux.Services;
|
||||||
|
|
||||||
|
public class NotificationAction
|
||||||
|
{
|
||||||
|
public string Key { get; set; } = "";
|
||||||
|
|
||||||
|
public string Label { get; set; } = "";
|
||||||
|
|
||||||
|
public Action? Callback { get; set; }
|
||||||
|
|
||||||
|
public NotificationAction()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public NotificationAction(string key, string label, Action? callback = null)
|
||||||
|
{
|
||||||
|
Key = key;
|
||||||
|
Label = label;
|
||||||
|
Callback = callback;
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user