Fix compilation: restore clean RC1 codebase

- Restore clean BindableProperty.Create syntax from RC1 commit
- Remove decompiler artifacts with mangled delegate types
- Add Svg.Skia package reference for icon support
- Fix duplicate type definitions
- Library now compiles successfully (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:
2026-01-01 07:43:44 -05:00
parent 33914bf572
commit 2a4e35cd39
258 changed files with 35256 additions and 49900 deletions

View File

@@ -1,62 +1,64 @@
using Microsoft.Maui.Graphics;
// 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.Handlers;
using Microsoft.Maui.Graphics;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class ActivityIndicatorHandler : ViewHandler<IActivityIndicator, SkiaActivityIndicator>
/// <summary>
/// Handler for ActivityIndicator on Linux using Skia rendering.
/// Maps IActivityIndicator interface to SkiaActivityIndicator platform view.
/// </summary>
public partial class ActivityIndicatorHandler : ViewHandler<IActivityIndicator, SkiaActivityIndicator>
{
public static IPropertyMapper<IActivityIndicator, ActivityIndicatorHandler> Mapper = (IPropertyMapper<IActivityIndicator, ActivityIndicatorHandler>)(object)new PropertyMapper<IActivityIndicator, ActivityIndicatorHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["IsRunning"] = MapIsRunning,
["Color"] = MapColor,
["Background"] = MapBackground
};
public static IPropertyMapper<IActivityIndicator, ActivityIndicatorHandler> Mapper = new PropertyMapper<IActivityIndicator, ActivityIndicatorHandler>(ViewHandler.ViewMapper)
{
[nameof(IActivityIndicator.IsRunning)] = MapIsRunning,
[nameof(IActivityIndicator.Color)] = MapColor,
[nameof(IView.Background)] = MapBackground,
};
public static CommandMapper<IActivityIndicator, ActivityIndicatorHandler> CommandMapper = new CommandMapper<IActivityIndicator, ActivityIndicatorHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public static CommandMapper<IActivityIndicator, ActivityIndicatorHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
public ActivityIndicatorHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public ActivityIndicatorHandler() : base(Mapper, CommandMapper)
{
}
public ActivityIndicatorHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
public ActivityIndicatorHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override SkiaActivityIndicator CreatePlatformView()
{
return new SkiaActivityIndicator();
}
protected override SkiaActivityIndicator CreatePlatformView()
{
return new SkiaActivityIndicator();
}
public static void MapIsRunning(ActivityIndicatorHandler handler, IActivityIndicator activityIndicator)
{
if (((ViewHandler<IActivityIndicator, SkiaActivityIndicator>)(object)handler).PlatformView != null)
{
((ViewHandler<IActivityIndicator, SkiaActivityIndicator>)(object)handler).PlatformView.IsRunning = activityIndicator.IsRunning;
}
}
public static void MapIsRunning(ActivityIndicatorHandler handler, IActivityIndicator activityIndicator)
{
if (handler.PlatformView is null) return;
handler.PlatformView.IsRunning = activityIndicator.IsRunning;
}
public static void MapColor(ActivityIndicatorHandler handler, IActivityIndicator activityIndicator)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IActivityIndicator, SkiaActivityIndicator>)(object)handler).PlatformView != null && activityIndicator.Color != null)
{
((ViewHandler<IActivityIndicator, SkiaActivityIndicator>)(object)handler).PlatformView.Color = activityIndicator.Color.ToSKColor();
}
}
public static void MapColor(ActivityIndicatorHandler handler, IActivityIndicator activityIndicator)
{
if (handler.PlatformView is null) return;
public static void MapBackground(ActivityIndicatorHandler handler, IActivityIndicator activityIndicator)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IActivityIndicator, SkiaActivityIndicator>)(object)handler).PlatformView != null)
{
Paint background = ((IView)activityIndicator).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<IActivityIndicator, SkiaActivityIndicator>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
if (activityIndicator.Color is not null)
handler.PlatformView.Color = activityIndicator.Color.ToSKColor();
}
public static void MapBackground(ActivityIndicatorHandler handler, IActivityIndicator activityIndicator)
{
if (handler.PlatformView is null) return;
if (activityIndicator.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
}

View File

@@ -1,59 +1,137 @@
// 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.Handlers;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform.Linux.Hosting;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class ApplicationHandler : ElementHandler<IApplication, LinuxApplicationContext>
/// <summary>
/// Handler for MAUI Application on Linux.
/// Bridges the MAUI Application lifecycle with LinuxApplication.
/// </summary>
public partial class ApplicationHandler : ElementHandler<IApplication, LinuxApplicationContext>
{
public static IPropertyMapper<IApplication, ApplicationHandler> Mapper = (IPropertyMapper<IApplication, ApplicationHandler>)(object)new PropertyMapper<IApplication, ApplicationHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ElementHandler.ElementMapper });
public static IPropertyMapper<IApplication, ApplicationHandler> Mapper =
new PropertyMapper<IApplication, ApplicationHandler>(ElementHandler.ElementMapper)
{
};
public static CommandMapper<IApplication, ApplicationHandler> CommandMapper = new CommandMapper<IApplication, ApplicationHandler>((CommandMapper)(object)ElementHandler.ElementCommandMapper)
{
["OpenWindow"] = MapOpenWindow,
["CloseWindow"] = MapCloseWindow
};
public static CommandMapper<IApplication, ApplicationHandler> CommandMapper =
new(ElementHandler.ElementCommandMapper)
{
[nameof(IApplication.OpenWindow)] = MapOpenWindow,
[nameof(IApplication.CloseWindow)] = MapCloseWindow,
};
public ApplicationHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public ApplicationHandler() : base(Mapper, CommandMapper)
{
}
public ApplicationHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
public ApplicationHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override LinuxApplicationContext CreatePlatformElement()
{
return new LinuxApplicationContext();
}
protected override LinuxApplicationContext CreatePlatformElement()
{
return new LinuxApplicationContext();
}
protected override void ConnectHandler(LinuxApplicationContext platformView)
{
base.ConnectHandler(platformView);
platformView.Application = base.VirtualView;
}
protected override void ConnectHandler(LinuxApplicationContext platformView)
{
base.ConnectHandler(platformView);
platformView.Application = VirtualView;
}
protected override void DisconnectHandler(LinuxApplicationContext platformView)
{
platformView.Application = null;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(LinuxApplicationContext platformView)
{
platformView.Application = null;
base.DisconnectHandler(platformView);
}
public static void MapOpenWindow(ApplicationHandler handler, IApplication application, object? args)
{
IWindow val = (IWindow)((args is IWindow) ? args : null);
if (val != null)
{
((ElementHandler<IApplication, LinuxApplicationContext>)(object)handler).PlatformView?.OpenWindow(val);
}
}
public static void MapOpenWindow(ApplicationHandler handler, IApplication application, object? args)
{
if (args is IWindow window)
{
handler.PlatformView?.OpenWindow(window);
}
}
public static void MapCloseWindow(ApplicationHandler handler, IApplication application, object? args)
{
IWindow val = (IWindow)((args is IWindow) ? args : null);
if (val != null)
{
((ElementHandler<IApplication, LinuxApplicationContext>)(object)handler).PlatformView?.CloseWindow(val);
}
}
public static void MapCloseWindow(ApplicationHandler handler, IApplication application, object? args)
{
if (args is IWindow window)
{
handler.PlatformView?.CloseWindow(window);
}
}
}
/// <summary>
/// Platform context for the MAUI Application on Linux.
/// Manages windows and the application lifecycle.
/// </summary>
public class LinuxApplicationContext
{
private readonly List<IWindow> _windows = new();
private IApplication? _application;
/// <summary>
/// Gets or sets the MAUI Application.
/// </summary>
public IApplication? Application
{
get => _application;
set
{
_application = value;
if (_application != null)
{
// Initialize windows from the application
foreach (var window in _application.Windows)
{
if (!_windows.Contains(window))
{
_windows.Add(window);
}
}
}
}
}
/// <summary>
/// Gets the list of open windows.
/// </summary>
public IReadOnlyList<IWindow> Windows => _windows;
/// <summary>
/// Opens a window and creates its handler.
/// </summary>
public void OpenWindow(IWindow window)
{
if (!_windows.Contains(window))
{
_windows.Add(window);
}
}
/// <summary>
/// Closes a window and cleans up its handler.
/// </summary>
public void CloseWindow(IWindow window)
{
_windows.Remove(window);
if (_windows.Count == 0)
{
// Last window closed, stop the application
LinuxApplication.Current?.MainWindow?.Stop();
}
}
/// <summary>
/// Gets the main window of the application.
/// </summary>
public IWindow? MainWindow => _windows.Count > 0 ? _windows[0] : null;
}

View File

@@ -1,186 +1,158 @@
using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Shapes;
using Microsoft.Maui.Graphics;
// 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.Handlers;
using Microsoft.Maui.Platform.Linux.Hosting;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class BorderHandler : ViewHandler<IBorderView, SkiaBorder>
/// <summary>
/// Handler for Border on Linux using Skia rendering.
/// </summary>
public partial class BorderHandler : ViewHandler<IBorderView, SkiaBorder>
{
public static IPropertyMapper<IBorderView, BorderHandler> Mapper = (IPropertyMapper<IBorderView, BorderHandler>)(object)new PropertyMapper<IBorderView, BorderHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Content"] = MapContent,
["Stroke"] = MapStroke,
["StrokeThickness"] = MapStrokeThickness,
["StrokeShape"] = MapStrokeShape,
["Background"] = MapBackground,
["BackgroundColor"] = MapBackgroundColor,
["Padding"] = MapPadding
};
public static IPropertyMapper<IBorderView, BorderHandler> Mapper =
new PropertyMapper<IBorderView, BorderHandler>(ViewHandler.ViewMapper)
{
[nameof(IBorderView.Content)] = MapContent,
[nameof(IBorderStroke.Stroke)] = MapStroke,
[nameof(IBorderStroke.StrokeThickness)] = MapStrokeThickness,
["StrokeShape"] = MapStrokeShape, // StrokeShape is on Border, not IBorderStroke
[nameof(IView.Background)] = MapBackground,
["BackgroundColor"] = MapBackgroundColor,
[nameof(IPadding.Padding)] = MapPadding,
};
public static CommandMapper<IBorderView, BorderHandler> CommandMapper = new CommandMapper<IBorderView, BorderHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public static CommandMapper<IBorderView, BorderHandler> CommandMapper =
new(ViewHandler.ViewCommandMapper)
{
};
public BorderHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public BorderHandler() : base(Mapper, CommandMapper)
{
}
public BorderHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
public BorderHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override SkiaBorder CreatePlatformView()
{
return new SkiaBorder();
}
protected override SkiaBorder CreatePlatformView()
{
return new SkiaBorder();
}
protected override void ConnectHandler(SkiaBorder platformView)
{
base.ConnectHandler(platformView);
IBorderView virtualView = base.VirtualView;
View val = (View)(object)((virtualView is View) ? virtualView : null);
if (val != null)
{
platformView.MauiView = val;
}
platformView.Tapped += OnPlatformViewTapped;
}
protected override void ConnectHandler(SkiaBorder platformView)
{
base.ConnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaBorder platformView)
{
platformView.Tapped -= OnPlatformViewTapped;
platformView.MauiView = null;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaBorder platformView)
{
base.DisconnectHandler(platformView);
}
private void OnPlatformViewTapped(object? sender, EventArgs e)
{
IBorderView virtualView = base.VirtualView;
View val = (View)(object)((virtualView is View) ? virtualView : null);
if (val != null)
{
GestureManager.ProcessTap(val, 0.0, 0.0);
}
}
public static void MapContent(BorderHandler handler, IBorderView border)
{
if (handler.PlatformView is null || handler.MauiContext is null) return;
public static void MapContent(BorderHandler handler, IBorderView border)
{
if (((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView == null || ((ElementHandler)handler).MauiContext == null)
{
return;
}
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.ClearChildren();
IView presentedContent = ((IContentView)border).PresentedContent;
if (presentedContent != null)
{
if (presentedContent.Handler == null)
{
Console.WriteLine("[BorderHandler] Creating handler for content: " + ((object)presentedContent).GetType().Name);
presentedContent.Handler = presentedContent.ToViewHandler(((ElementHandler)handler).MauiContext);
}
IViewHandler handler2 = presentedContent.Handler;
if (((handler2 != null) ? ((IElementHandler)handler2).PlatformView : null) is SkiaView skiaView)
{
Console.WriteLine("[BorderHandler] Adding content: " + ((object)skiaView).GetType().Name);
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.AddChild(skiaView);
}
}
}
handler.PlatformView.ClearChildren();
public static void MapStroke(BorderHandler handler, IBorderView border)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView != null)
{
Paint stroke = ((IStroke)border).Stroke;
SolidPaint val = (SolidPaint)(object)((stroke is SolidPaint) ? stroke : null);
if (val != null && val.Color != null)
{
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.Stroke = val.Color.ToSKColor();
}
}
}
var content = border.PresentedContent;
if (content != null)
{
// Create handler for content if it doesn't exist
if (content.Handler == null)
{
Console.WriteLine($"[BorderHandler] Creating handler for content: {content.GetType().Name}");
content.Handler = content.ToHandler(handler.MauiContext);
}
public static void MapStrokeThickness(BorderHandler handler, IBorderView border)
{
if (((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView != null)
{
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.StrokeThickness = (float)((IStroke)border).StrokeThickness;
}
}
if (content.Handler?.PlatformView is SkiaView skiaContent)
{
Console.WriteLine($"[BorderHandler] Adding content: {skiaContent.GetType().Name}");
handler.PlatformView.AddChild(skiaContent);
}
}
}
public static void MapBackground(BorderHandler handler, IBorderView border)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView != null)
{
Paint background = ((IView)border).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
public static void MapStroke(BorderHandler handler, IBorderView border)
{
if (handler.PlatformView is null) return;
public static void MapBackgroundColor(BorderHandler handler, IBorderView border)
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView != null)
{
VisualElement val = (VisualElement)(object)((border is VisualElement) ? border : null);
if (val != null && val.BackgroundColor != null)
{
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.BackgroundColor = val.BackgroundColor.ToSKColor();
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.Invalidate();
}
}
}
if (border.Stroke is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.Stroke = solidPaint.Color.ToSKColor();
}
}
public static void MapPadding(BorderHandler handler, IBorderView border)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView != null)
{
Thickness padding = ((IPadding)border).Padding;
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.PaddingLeft = (float)((Thickness)(ref padding)).Left;
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.PaddingTop = (float)((Thickness)(ref padding)).Top;
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.PaddingRight = (float)((Thickness)(ref padding)).Right;
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.PaddingBottom = (float)((Thickness)(ref padding)).Bottom;
}
}
public static void MapStrokeThickness(BorderHandler handler, IBorderView border)
{
if (handler.PlatformView is null) return;
handler.PlatformView.StrokeThickness = (float)border.StrokeThickness;
}
public static void MapStrokeShape(BorderHandler handler, IBorderView border)
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView == null)
{
return;
}
Border val = (Border)(object)((border is Border) ? border : null);
if (val != null)
{
IShape strokeShape = val.StrokeShape;
RoundRectangle val2 = (RoundRectangle)(object)((strokeShape is RoundRectangle) ? strokeShape : null);
if (val2 != null)
{
CornerRadius cornerRadius = val2.CornerRadius;
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.CornerRadius = (float)((CornerRadius)(ref cornerRadius)).TopLeft;
}
else if (strokeShape is Rectangle)
{
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.CornerRadius = 0f;
}
else if (strokeShape is Ellipse)
{
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.CornerRadius = float.MaxValue;
}
((ViewHandler<IBorderView, SkiaBorder>)(object)handler).PlatformView.Invalidate();
}
}
public static void MapBackground(BorderHandler handler, IBorderView border)
{
if (handler.PlatformView is null) return;
if (border.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapBackgroundColor(BorderHandler handler, IBorderView border)
{
if (handler.PlatformView is null) return;
if (border is VisualElement ve && ve.BackgroundColor != null)
{
handler.PlatformView.BackgroundColor = ve.BackgroundColor.ToSKColor();
handler.PlatformView.Invalidate();
}
}
public static void MapPadding(BorderHandler handler, IBorderView border)
{
if (handler.PlatformView is null) return;
var padding = border.Padding;
handler.PlatformView.PaddingLeft = (float)padding.Left;
handler.PlatformView.PaddingTop = (float)padding.Top;
handler.PlatformView.PaddingRight = (float)padding.Right;
handler.PlatformView.PaddingBottom = (float)padding.Bottom;
}
public static void MapStrokeShape(BorderHandler handler, IBorderView border)
{
if (handler.PlatformView is null) return;
// StrokeShape is on the Border control class, not IBorderView interface
if (border is not Border borderControl) return;
var shape = borderControl.StrokeShape;
if (shape is Microsoft.Maui.Controls.Shapes.RoundRectangle roundRect)
{
// RoundRectangle can have different corner radii, but we use a uniform one
// Take the top-left corner as the uniform radius
var cornerRadius = roundRect.CornerRadius;
handler.PlatformView.CornerRadius = (float)cornerRadius.TopLeft;
}
else if (shape is Microsoft.Maui.Controls.Shapes.Rectangle)
{
handler.PlatformView.CornerRadius = 0;
}
else if (shape is Microsoft.Maui.Controls.Shapes.Ellipse)
{
// For ellipse, use half the min dimension as corner radius
// This will be applied during rendering when bounds are known
handler.PlatformView.CornerRadius = float.MaxValue; // Marker for "fully rounded"
}
handler.PlatformView.Invalidate();
}
}

View File

@@ -1,66 +1,67 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class BoxViewHandler : ViewHandler<BoxView, SkiaBoxView>
/// <summary>
/// Handler for BoxView on Linux.
/// </summary>
public partial class BoxViewHandler : ViewHandler<BoxView, SkiaBoxView>
{
public static IPropertyMapper<BoxView, BoxViewHandler> Mapper = (IPropertyMapper<BoxView, BoxViewHandler>)(object)new PropertyMapper<BoxView, BoxViewHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Color"] = MapColor,
["CornerRadius"] = MapCornerRadius,
["Background"] = MapBackground,
["BackgroundColor"] = MapBackgroundColor
};
public static IPropertyMapper<BoxView, BoxViewHandler> Mapper =
new PropertyMapper<BoxView, BoxViewHandler>(ViewMapper)
{
[nameof(BoxView.Color)] = MapColor,
[nameof(BoxView.CornerRadius)] = MapCornerRadius,
[nameof(IView.Background)] = MapBackground,
["BackgroundColor"] = MapBackgroundColor,
};
public BoxViewHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)null)
{
}
public BoxViewHandler() : base(Mapper)
{
}
protected override SkiaBoxView CreatePlatformView()
{
return new SkiaBoxView();
}
protected override SkiaBoxView CreatePlatformView()
{
return new SkiaBoxView();
}
public static void MapColor(BoxViewHandler handler, BoxView boxView)
{
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
if (boxView.Color != null)
{
((ViewHandler<BoxView, SkiaBoxView>)(object)handler).PlatformView.Color = new SKColor((byte)(boxView.Color.Red * 255f), (byte)(boxView.Color.Green * 255f), (byte)(boxView.Color.Blue * 255f), (byte)(boxView.Color.Alpha * 255f));
}
}
public static void MapColor(BoxViewHandler handler, BoxView boxView)
{
if (boxView.Color != null)
{
handler.PlatformView.Color = new SKColor(
(byte)(boxView.Color.Red * 255),
(byte)(boxView.Color.Green * 255),
(byte)(boxView.Color.Blue * 255),
(byte)(boxView.Color.Alpha * 255));
}
}
public static void MapCornerRadius(BoxViewHandler handler, BoxView boxView)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
SkiaBoxView platformView = ((ViewHandler<BoxView, SkiaBoxView>)(object)handler).PlatformView;
CornerRadius cornerRadius = boxView.CornerRadius;
platformView.CornerRadius = (float)((CornerRadius)(ref cornerRadius)).TopLeft;
}
public static void MapCornerRadius(BoxViewHandler handler, BoxView boxView)
{
handler.PlatformView.CornerRadius = (float)boxView.CornerRadius.TopLeft;
}
public static void MapBackground(BoxViewHandler handler, BoxView boxView)
{
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
Brush background = ((VisualElement)boxView).Background;
SolidColorBrush val = (SolidColorBrush)(object)((background is SolidColorBrush) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<BoxView, SkiaBoxView>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
((ViewHandler<BoxView, SkiaBoxView>)(object)handler).PlatformView.Invalidate();
}
}
public static void MapBackground(BoxViewHandler handler, BoxView boxView)
{
if (boxView.Background is SolidColorBrush solidBrush && solidBrush.Color != null)
{
handler.PlatformView.BackgroundColor = solidBrush.Color.ToSKColor();
handler.PlatformView.Invalidate();
}
}
public static void MapBackgroundColor(BoxViewHandler handler, BoxView boxView)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
if (((VisualElement)boxView).BackgroundColor != null)
{
((ViewHandler<BoxView, SkiaBoxView>)(object)handler).PlatformView.BackgroundColor = ((VisualElement)boxView).BackgroundColor.ToSKColor();
((ViewHandler<BoxView, SkiaBoxView>)(object)handler).PlatformView.Invalidate();
}
}
public static void MapBackgroundColor(BoxViewHandler handler, BoxView boxView)
{
if (boxView.BackgroundColor != null)
{
handler.PlatformView.BackgroundColor = boxView.BackgroundColor.ToSKColor();
handler.PlatformView.Invalidate();
}
}
}

View File

@@ -1,153 +1,198 @@
using System;
using Microsoft.Maui.Graphics;
// 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.Handlers;
using Microsoft.Maui.Graphics;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class ButtonHandler : ViewHandler<IButton, SkiaButton>
/// <summary>
/// Handler for Button on Linux using Skia rendering.
/// Maps IButton interface to SkiaButton platform view.
/// </summary>
public partial class ButtonHandler : ViewHandler<IButton, SkiaButton>
{
public static IPropertyMapper<IButton, ButtonHandler> Mapper = (IPropertyMapper<IButton, ButtonHandler>)(object)new PropertyMapper<IButton, ButtonHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["StrokeColor"] = MapStrokeColor,
["StrokeThickness"] = MapStrokeThickness,
["CornerRadius"] = MapCornerRadius,
["Background"] = MapBackground,
["Padding"] = MapPadding,
["IsEnabled"] = MapIsEnabled
};
public static IPropertyMapper<IButton, ButtonHandler> Mapper = new PropertyMapper<IButton, ButtonHandler>(ViewHandler.ViewMapper)
{
[nameof(IButtonStroke.StrokeColor)] = MapStrokeColor,
[nameof(IButtonStroke.StrokeThickness)] = MapStrokeThickness,
[nameof(IButtonStroke.CornerRadius)] = MapCornerRadius,
[nameof(IView.Background)] = MapBackground,
[nameof(IPadding.Padding)] = MapPadding,
[nameof(IView.IsEnabled)] = MapIsEnabled,
};
public static CommandMapper<IButton, ButtonHandler> CommandMapper = new CommandMapper<IButton, ButtonHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public static CommandMapper<IButton, ButtonHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
public ButtonHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public ButtonHandler() : base(Mapper, CommandMapper)
{
}
public ButtonHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
public ButtonHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override SkiaButton CreatePlatformView()
{
return new SkiaButton();
}
protected override SkiaButton CreatePlatformView()
{
var button = new SkiaButton();
return button;
}
protected override void ConnectHandler(SkiaButton platformView)
{
base.ConnectHandler(platformView);
platformView.Clicked += OnClicked;
platformView.Pressed += OnPressed;
platformView.Released += OnReleased;
if (base.VirtualView != null)
{
MapStrokeColor(this, base.VirtualView);
MapStrokeThickness(this, base.VirtualView);
MapCornerRadius(this, base.VirtualView);
MapBackground(this, base.VirtualView);
MapPadding(this, base.VirtualView);
MapIsEnabled(this, base.VirtualView);
}
}
protected override void ConnectHandler(SkiaButton platformView)
{
base.ConnectHandler(platformView);
platformView.Clicked += OnClicked;
platformView.Pressed += OnPressed;
platformView.Released += OnReleased;
protected override void DisconnectHandler(SkiaButton platformView)
{
platformView.Clicked -= OnClicked;
platformView.Pressed -= OnPressed;
platformView.Released -= OnReleased;
base.DisconnectHandler(platformView);
}
// Manually map all properties on connect since MAUI may not trigger updates
// for properties that were set before handler connection
if (VirtualView != null)
{
MapStrokeColor(this, VirtualView);
MapStrokeThickness(this, VirtualView);
MapCornerRadius(this, VirtualView);
MapBackground(this, VirtualView);
MapPadding(this, VirtualView);
MapIsEnabled(this, VirtualView);
}
}
private void OnClicked(object? sender, EventArgs e)
{
IButton virtualView = base.VirtualView;
if (virtualView != null)
{
virtualView.Clicked();
}
}
protected override void DisconnectHandler(SkiaButton platformView)
{
platformView.Clicked -= OnClicked;
platformView.Pressed -= OnPressed;
platformView.Released -= OnReleased;
base.DisconnectHandler(platformView);
}
private void OnPressed(object? sender, EventArgs e)
{
IButton virtualView = base.VirtualView;
if (virtualView != null)
{
virtualView.Pressed();
}
}
private void OnClicked(object? sender, EventArgs e) => VirtualView?.Clicked();
private void OnPressed(object? sender, EventArgs e) => VirtualView?.Pressed();
private void OnReleased(object? sender, EventArgs e) => VirtualView?.Released();
private void OnReleased(object? sender, EventArgs e)
{
IButton virtualView = base.VirtualView;
if (virtualView != null)
{
virtualView.Released();
}
}
public static void MapStrokeColor(ButtonHandler handler, IButton button)
{
if (handler.PlatformView is null) return;
public static void MapStrokeColor(ButtonHandler handler, IButton button)
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView != null)
{
Color strokeColor = ((IButtonStroke)button).StrokeColor;
if (strokeColor != null)
{
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.BorderColor = strokeColor.ToSKColor();
}
}
}
var strokeColor = button.StrokeColor;
if (strokeColor is not null)
handler.PlatformView.BorderColor = strokeColor.ToSKColor();
}
public static void MapStrokeThickness(ButtonHandler handler, IButton button)
{
if (((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView != null)
{
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.BorderWidth = (float)((IButtonStroke)button).StrokeThickness;
}
}
public static void MapStrokeThickness(ButtonHandler handler, IButton button)
{
if (handler.PlatformView is null) return;
handler.PlatformView.BorderWidth = (float)button.StrokeThickness;
}
public static void MapCornerRadius(ButtonHandler handler, IButton button)
{
if (((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView != null)
{
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.CornerRadius = ((IButtonStroke)button).CornerRadius;
}
}
public static void MapCornerRadius(ButtonHandler handler, IButton button)
{
if (handler.PlatformView is null) return;
handler.PlatformView.CornerRadius = button.CornerRadius;
}
public static void MapBackground(ButtonHandler handler, IButton button)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView != null)
{
Paint background = ((IView)button).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.ButtonBackgroundColor = val.Color.ToSKColor();
}
}
}
public static void MapBackground(ButtonHandler handler, IButton button)
{
if (handler.PlatformView is null) return;
public static void MapPadding(ButtonHandler handler, IButton button)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView != null)
{
Thickness padding = ((IPadding)button).Padding;
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.Padding = new SKRect((float)((Thickness)(ref padding)).Left, (float)((Thickness)(ref padding)).Top, (float)((Thickness)(ref padding)).Right, (float)((Thickness)(ref padding)).Bottom);
}
}
if (button.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
// Set ButtonBackgroundColor (used for rendering) not base BackgroundColor
handler.PlatformView.ButtonBackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapIsEnabled(ButtonHandler handler, IButton button)
{
if (((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView != null)
{
Console.WriteLine($"[ButtonHandler] MapIsEnabled - Text='{((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.Text}', IsEnabled={((IView)button).IsEnabled}");
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.IsEnabled = ((IView)button).IsEnabled;
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.Invalidate();
}
}
public static void MapPadding(ButtonHandler handler, IButton button)
{
if (handler.PlatformView is null) return;
var padding = button.Padding;
handler.PlatformView.Padding = new SKRect(
(float)padding.Left,
(float)padding.Top,
(float)padding.Right,
(float)padding.Bottom);
}
public static void MapIsEnabled(ButtonHandler handler, IButton button)
{
if (handler.PlatformView is null) return;
Console.WriteLine($"[ButtonHandler] MapIsEnabled - Text='{handler.PlatformView.Text}', IsEnabled={button.IsEnabled}");
handler.PlatformView.IsEnabled = button.IsEnabled;
handler.PlatformView.Invalidate();
}
}
/// <summary>
/// Handler for TextButton on Linux - extends ButtonHandler with text support.
/// Maps ITextButton interface (which includes IText properties).
/// </summary>
public partial class TextButtonHandler : ButtonHandler
{
public static new IPropertyMapper<ITextButton, TextButtonHandler> Mapper =
new PropertyMapper<ITextButton, TextButtonHandler>(ButtonHandler.Mapper)
{
[nameof(IText.Text)] = MapText,
[nameof(ITextStyle.TextColor)] = MapTextColor,
[nameof(ITextStyle.Font)] = MapFont,
[nameof(ITextStyle.CharacterSpacing)] = MapCharacterSpacing,
};
public TextButtonHandler() : base(Mapper)
{
}
protected override void ConnectHandler(SkiaButton platformView)
{
base.ConnectHandler(platformView);
// Manually map text properties on connect since MAUI may not trigger updates
// for properties that were set before handler connection
if (VirtualView is ITextButton textButton)
{
MapText(this, textButton);
MapTextColor(this, textButton);
MapFont(this, textButton);
MapCharacterSpacing(this, textButton);
}
}
public static void MapText(TextButtonHandler handler, ITextButton button)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Text = button.Text ?? string.Empty;
}
public static void MapTextColor(TextButtonHandler handler, ITextButton button)
{
if (handler.PlatformView is null) return;
if (button.TextColor is not null)
handler.PlatformView.TextColor = button.TextColor.ToSKColor();
}
public static void MapFont(TextButtonHandler handler, ITextButton button)
{
if (handler.PlatformView is null) return;
var font = button.Font;
if (font.Size > 0)
handler.PlatformView.FontSize = (float)font.Size;
if (!string.IsNullOrEmpty(font.Family))
handler.PlatformView.FontFamily = font.Family;
handler.PlatformView.IsBold = font.Weight >= FontWeight.Bold;
handler.PlatformView.IsItalic = font.Slant == FontSlant.Italic || font.Slant == FontSlant.Oblique;
}
public static void MapCharacterSpacing(TextButtonHandler handler, ITextButton button)
{
if (handler.PlatformView is null) return;
handler.PlatformView.CharacterSpacing = (float)button.CharacterSpacing;
}
}

View File

@@ -1,164 +1,116 @@
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
// 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.Handlers;
using Microsoft.Maui.Primitives;
using Microsoft.Maui.Graphics;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class CheckBoxHandler : ViewHandler<ICheckBox, SkiaCheckBox>
/// <summary>
/// Handler for CheckBox on Linux using Skia rendering.
/// Maps ICheckBox interface to SkiaCheckBox platform view.
/// </summary>
public partial class CheckBoxHandler : ViewHandler<ICheckBox, SkiaCheckBox>
{
public static IPropertyMapper<ICheckBox, CheckBoxHandler> Mapper = (IPropertyMapper<ICheckBox, CheckBoxHandler>)(object)new PropertyMapper<ICheckBox, CheckBoxHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["IsChecked"] = MapIsChecked,
["Foreground"] = MapForeground,
["Background"] = MapBackground,
["IsEnabled"] = MapIsEnabled,
["VerticalLayoutAlignment"] = MapVerticalLayoutAlignment,
["HorizontalLayoutAlignment"] = MapHorizontalLayoutAlignment
};
public static IPropertyMapper<ICheckBox, CheckBoxHandler> Mapper = new PropertyMapper<ICheckBox, CheckBoxHandler>(ViewHandler.ViewMapper)
{
[nameof(ICheckBox.IsChecked)] = MapIsChecked,
[nameof(ICheckBox.Foreground)] = MapForeground,
[nameof(IView.Background)] = MapBackground,
[nameof(IView.VerticalLayoutAlignment)] = MapVerticalLayoutAlignment,
[nameof(IView.HorizontalLayoutAlignment)] = MapHorizontalLayoutAlignment,
};
public static CommandMapper<ICheckBox, CheckBoxHandler> CommandMapper = new CommandMapper<ICheckBox, CheckBoxHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public static CommandMapper<ICheckBox, CheckBoxHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
public CheckBoxHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public CheckBoxHandler() : base(Mapper, CommandMapper)
{
}
public CheckBoxHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
public CheckBoxHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override SkiaCheckBox CreatePlatformView()
{
return new SkiaCheckBox();
}
protected override SkiaCheckBox CreatePlatformView()
{
return new SkiaCheckBox();
}
protected override void ConnectHandler(SkiaCheckBox platformView)
{
base.ConnectHandler(platformView);
platformView.CheckedChanged += OnCheckedChanged;
}
protected override void ConnectHandler(SkiaCheckBox platformView)
{
base.ConnectHandler(platformView);
platformView.CheckedChanged += OnCheckedChanged;
}
protected override void DisconnectHandler(SkiaCheckBox platformView)
{
platformView.CheckedChanged -= OnCheckedChanged;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaCheckBox platformView)
{
platformView.CheckedChanged -= OnCheckedChanged;
base.DisconnectHandler(platformView);
}
private void OnCheckedChanged(object? sender, CheckedChangedEventArgs e)
{
if (base.VirtualView != null && base.VirtualView.IsChecked != e.IsChecked)
{
base.VirtualView.IsChecked = e.IsChecked;
}
}
private void OnCheckedChanged(object? sender, Platform.CheckedChangedEventArgs e)
{
if (VirtualView is not null && VirtualView.IsChecked != e.IsChecked)
{
VirtualView.IsChecked = e.IsChecked;
}
}
public static void MapIsChecked(CheckBoxHandler handler, ICheckBox checkBox)
{
if (((ViewHandler<ICheckBox, SkiaCheckBox>)(object)handler).PlatformView != null)
{
((ViewHandler<ICheckBox, SkiaCheckBox>)(object)handler).PlatformView.IsChecked = checkBox.IsChecked;
}
}
public static void MapIsChecked(CheckBoxHandler handler, ICheckBox checkBox)
{
if (handler.PlatformView is null) return;
handler.PlatformView.IsChecked = checkBox.IsChecked;
}
public static void MapForeground(CheckBoxHandler handler, ICheckBox checkBox)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ICheckBox, SkiaCheckBox>)(object)handler).PlatformView != null)
{
Paint foreground = checkBox.Foreground;
SolidPaint val = (SolidPaint)(object)((foreground is SolidPaint) ? foreground : null);
if (val != null && val.Color != null)
{
((ViewHandler<ICheckBox, SkiaCheckBox>)(object)handler).PlatformView.CheckColor = val.Color.ToSKColor();
}
}
}
public static void MapForeground(CheckBoxHandler handler, ICheckBox checkBox)
{
if (handler.PlatformView is null) return;
public static void MapBackground(CheckBoxHandler handler, ICheckBox checkBox)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ICheckBox, SkiaCheckBox>)(object)handler).PlatformView != null)
{
Paint background = ((IView)checkBox).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<ICheckBox, SkiaCheckBox>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
if (checkBox.Foreground is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.CheckColor = solidPaint.Color.ToSKColor();
}
}
public static void MapIsEnabled(CheckBoxHandler handler, ICheckBox checkBox)
{
if (((ViewHandler<ICheckBox, SkiaCheckBox>)(object)handler).PlatformView != null)
{
((ViewHandler<ICheckBox, SkiaCheckBox>)(object)handler).PlatformView.IsEnabled = ((IView)checkBox).IsEnabled;
}
}
public static void MapBackground(CheckBoxHandler handler, ICheckBox checkBox)
{
if (handler.PlatformView is null) return;
public static void MapVerticalLayoutAlignment(CheckBoxHandler handler, ICheckBox checkBox)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Expected I4, but got Unknown
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ICheckBox, SkiaCheckBox>)(object)handler).PlatformView != null)
{
SkiaCheckBox platformView = ((ViewHandler<ICheckBox, SkiaCheckBox>)(object)handler).PlatformView;
LayoutAlignment verticalLayoutAlignment = ((IView)checkBox).VerticalLayoutAlignment;
platformView.VerticalOptions = (LayoutOptions)((int)verticalLayoutAlignment switch
{
1 => LayoutOptions.Start,
2 => LayoutOptions.Center,
3 => LayoutOptions.End,
0 => LayoutOptions.Fill,
_ => LayoutOptions.Fill,
});
}
}
if (checkBox.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapHorizontalLayoutAlignment(CheckBoxHandler handler, ICheckBox checkBox)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Expected I4, but got Unknown
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ICheckBox, SkiaCheckBox>)(object)handler).PlatformView != null)
{
SkiaCheckBox platformView = ((ViewHandler<ICheckBox, SkiaCheckBox>)(object)handler).PlatformView;
LayoutAlignment horizontalLayoutAlignment = ((IView)checkBox).HorizontalLayoutAlignment;
platformView.HorizontalOptions = (LayoutOptions)((int)horizontalLayoutAlignment switch
{
1 => LayoutOptions.Start,
2 => LayoutOptions.Center,
3 => LayoutOptions.End,
0 => LayoutOptions.Fill,
_ => LayoutOptions.Start,
});
}
}
public static void MapVerticalLayoutAlignment(CheckBoxHandler handler, ICheckBox checkBox)
{
if (handler.PlatformView is null) return;
handler.PlatformView.VerticalOptions = checkBox.VerticalLayoutAlignment switch
{
Primitives.LayoutAlignment.Start => LayoutOptions.Start,
Primitives.LayoutAlignment.Center => LayoutOptions.Center,
Primitives.LayoutAlignment.End => LayoutOptions.End,
Primitives.LayoutAlignment.Fill => LayoutOptions.Fill,
_ => LayoutOptions.Fill
};
}
public static void MapHorizontalLayoutAlignment(CheckBoxHandler handler, ICheckBox checkBox)
{
if (handler.PlatformView is null) return;
handler.PlatformView.HorizontalOptions = checkBox.HorizontalLayoutAlignment switch
{
Primitives.LayoutAlignment.Start => LayoutOptions.Start,
Primitives.LayoutAlignment.Center => LayoutOptions.Center,
Primitives.LayoutAlignment.End => LayoutOptions.End,
Primitives.LayoutAlignment.Fill => LayoutOptions.Fill,
_ => LayoutOptions.Start
};
}
}

View File

@@ -1,458 +1,374 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Maui.Controls;
// 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.Handlers;
using Microsoft.Maui.Platform.Linux.Hosting;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class CollectionViewHandler : ViewHandler<CollectionView, SkiaCollectionView>
/// <summary>
/// Handler for CollectionView on Linux using Skia rendering.
/// Maps CollectionView to SkiaCollectionView platform view.
/// </summary>
public partial class CollectionViewHandler : ViewHandler<CollectionView, SkiaCollectionView>
{
private bool _isUpdatingSelection;
private bool _isUpdatingSelection;
public static IPropertyMapper<CollectionView, CollectionViewHandler> Mapper = (IPropertyMapper<CollectionView, CollectionViewHandler>)(object)new PropertyMapper<CollectionView, CollectionViewHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["ItemsSource"] = MapItemsSource,
["ItemTemplate"] = MapItemTemplate,
["EmptyView"] = MapEmptyView,
["HorizontalScrollBarVisibility"] = MapHorizontalScrollBarVisibility,
["VerticalScrollBarVisibility"] = MapVerticalScrollBarVisibility,
["SelectedItem"] = MapSelectedItem,
["SelectedItems"] = MapSelectedItems,
["SelectionMode"] = MapSelectionMode,
["Header"] = MapHeader,
["Footer"] = MapFooter,
["ItemsLayout"] = MapItemsLayout,
["Background"] = MapBackground,
["BackgroundColor"] = MapBackgroundColor
};
public static IPropertyMapper<CollectionView, CollectionViewHandler> Mapper =
new PropertyMapper<CollectionView, CollectionViewHandler>(ViewHandler.ViewMapper)
{
// ItemsView properties
[nameof(ItemsView.ItemsSource)] = MapItemsSource,
[nameof(ItemsView.ItemTemplate)] = MapItemTemplate,
[nameof(ItemsView.EmptyView)] = MapEmptyView,
[nameof(ItemsView.HorizontalScrollBarVisibility)] = MapHorizontalScrollBarVisibility,
[nameof(ItemsView.VerticalScrollBarVisibility)] = MapVerticalScrollBarVisibility,
public static CommandMapper<CollectionView, CollectionViewHandler> CommandMapper = new CommandMapper<CollectionView, CollectionViewHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper) { ["ScrollTo"] = MapScrollTo };
// SelectableItemsView properties
[nameof(SelectableItemsView.SelectedItem)] = MapSelectedItem,
[nameof(SelectableItemsView.SelectedItems)] = MapSelectedItems,
[nameof(SelectableItemsView.SelectionMode)] = MapSelectionMode,
public CollectionViewHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
// StructuredItemsView properties
[nameof(StructuredItemsView.Header)] = MapHeader,
[nameof(StructuredItemsView.Footer)] = MapFooter,
[nameof(StructuredItemsView.ItemsLayout)] = MapItemsLayout,
public CollectionViewHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
[nameof(IView.Background)] = MapBackground,
[nameof(CollectionView.BackgroundColor)] = MapBackgroundColor,
};
protected override SkiaCollectionView CreatePlatformView()
{
return new SkiaCollectionView();
}
public static CommandMapper<CollectionView, CollectionViewHandler> CommandMapper =
new(ViewHandler.ViewCommandMapper)
{
["ScrollTo"] = MapScrollTo,
};
protected override void ConnectHandler(SkiaCollectionView platformView)
{
base.ConnectHandler(platformView);
platformView.SelectionChanged += OnSelectionChanged;
platformView.Scrolled += OnScrolled;
platformView.ItemTapped += OnItemTapped;
}
public CollectionViewHandler() : base(Mapper, CommandMapper)
{
}
protected override void DisconnectHandler(SkiaCollectionView platformView)
{
platformView.SelectionChanged -= OnSelectionChanged;
platformView.Scrolled -= OnScrolled;
platformView.ItemTapped -= OnItemTapped;
base.DisconnectHandler(platformView);
}
public CollectionViewHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
private void OnSelectionChanged(object? sender, CollectionSelectionChangedEventArgs e)
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Invalid comparison between Unknown and I4
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_0060: Invalid comparison between Unknown and I4
if (base.VirtualView == null || _isUpdatingSelection)
{
return;
}
try
{
_isUpdatingSelection = true;
if ((int)((SelectableItemsView)base.VirtualView).SelectionMode == 1)
{
object obj = e.CurrentSelection.FirstOrDefault();
if (!object.Equals(((SelectableItemsView)base.VirtualView).SelectedItem, obj))
{
((SelectableItemsView)base.VirtualView).SelectedItem = obj;
}
}
else
{
if ((int)((SelectableItemsView)base.VirtualView).SelectionMode != 2)
{
return;
}
((SelectableItemsView)base.VirtualView).SelectedItems.Clear();
{
foreach (object item in e.CurrentSelection)
{
((SelectableItemsView)base.VirtualView).SelectedItems.Add(item);
}
return;
}
}
}
finally
{
_isUpdatingSelection = false;
}
}
protected override SkiaCollectionView CreatePlatformView()
{
return new SkiaCollectionView();
}
private void OnScrolled(object? sender, ItemsScrolledEventArgs e)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Expected O, but got Unknown
CollectionView virtualView = base.VirtualView;
if (virtualView != null)
{
((ItemsView)virtualView).SendScrolled(new ItemsViewScrolledEventArgs
{
VerticalOffset = e.ScrollOffset,
VerticalDelta = 0.0,
HorizontalOffset = 0.0,
HorizontalDelta = 0.0
});
}
}
protected override void ConnectHandler(SkiaCollectionView platformView)
{
base.ConnectHandler(platformView);
platformView.SelectionChanged += OnSelectionChanged;
platformView.Scrolled += OnScrolled;
platformView.ItemTapped += OnItemTapped;
}
private void OnItemTapped(object? sender, ItemsViewItemTappedEventArgs e)
{
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
//IL_01d8: Invalid comparison between Unknown and I4
//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
//IL_01f9: Invalid comparison between Unknown and I4
if (base.VirtualView == null || _isUpdatingSelection)
{
return;
}
try
{
_isUpdatingSelection = true;
Console.WriteLine($"[CollectionViewHandler] OnItemTapped index={e.Index}, item={e.Item}, SelectionMode={((SelectableItemsView)base.VirtualView).SelectionMode}");
SkiaView skiaView = base.PlatformView?.GetItemView(e.Index);
Console.WriteLine($"[CollectionViewHandler] GetItemView({e.Index}) returned: {((object)skiaView)?.GetType().Name ?? "null"}, MauiView={((object)skiaView?.MauiView)?.GetType().Name ?? "null"}");
if (skiaView?.MauiView != null)
{
Console.WriteLine($"[CollectionViewHandler] Found MauiView: {((object)skiaView.MauiView).GetType().Name}, GestureRecognizers={skiaView.MauiView.GestureRecognizers?.Count ?? 0}");
if (GestureManager.ProcessTap(skiaView.MauiView, 0.0, 0.0))
{
Console.WriteLine("[CollectionViewHandler] Gesture processed successfully");
return;
}
}
if ((int)((SelectableItemsView)base.VirtualView).SelectionMode == 1)
{
((SelectableItemsView)base.VirtualView).SelectedItem = e.Item;
}
else if ((int)((SelectableItemsView)base.VirtualView).SelectionMode == 2)
{
if (((SelectableItemsView)base.VirtualView).SelectedItems.Contains(e.Item))
{
((SelectableItemsView)base.VirtualView).SelectedItems.Remove(e.Item);
}
else
{
((SelectableItemsView)base.VirtualView).SelectedItems.Add(e.Item);
}
}
}
finally
{
_isUpdatingSelection = false;
}
}
protected override void DisconnectHandler(SkiaCollectionView platformView)
{
platformView.SelectionChanged -= OnSelectionChanged;
platformView.Scrolled -= OnScrolled;
platformView.ItemTapped -= OnItemTapped;
base.DisconnectHandler(platformView);
}
public static void MapItemsSource(CollectionViewHandler handler, CollectionView collectionView)
{
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView != null)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.ItemsSource = ((ItemsView)collectionView).ItemsSource;
}
}
private void OnSelectionChanged(object? sender, CollectionSelectionChangedEventArgs e)
{
if (VirtualView is null || _isUpdatingSelection) return;
public static void MapItemTemplate(CollectionViewHandler handler, CollectionView collectionView)
{
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView == null || ((ElementHandler)handler).MauiContext == null)
{
return;
}
DataTemplate template = ((ItemsView)collectionView).ItemTemplate;
if (template != null)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.ItemViewCreator = delegate(object item)
{
try
{
object obj = ((ElementTemplate)template).CreateContent();
View val = (View)((obj is View) ? obj : null);
if (val != null)
{
((BindableObject)val).BindingContext = item;
PropagateBindingContext(val, item);
if (((VisualElement)val).Handler == null && ((ElementHandler)handler).MauiContext != null)
{
((VisualElement)val).Handler = ((IView)(object)val).ToViewHandler(((ElementHandler)handler).MauiContext);
}
IViewHandler handler2 = ((VisualElement)val).Handler;
if (((handler2 != null) ? ((IElementHandler)handler2).PlatformView : null) is SkiaView skiaView)
{
skiaView.MauiView = val;
Console.WriteLine($"[CollectionViewHandler.ItemViewCreator] Set MauiView={((object)val).GetType().Name} on {((object)skiaView).GetType().Name}, GestureRecognizers={val.GestureRecognizers?.Count ?? 0}");
return skiaView;
}
}
else
{
ViewCell val2 = (ViewCell)((obj is ViewCell) ? obj : null);
if (val2 != null)
{
((BindableObject)val2).BindingContext = item;
View view = val2.View;
if (view != null)
{
if (((VisualElement)view).Handler == null && ((ElementHandler)handler).MauiContext != null)
{
((VisualElement)view).Handler = ((IView)(object)view).ToViewHandler(((ElementHandler)handler).MauiContext);
}
IViewHandler handler3 = ((VisualElement)view).Handler;
if (((handler3 != null) ? ((IElementHandler)handler3).PlatformView : null) is SkiaView result)
{
return result;
}
}
}
}
}
catch
{
}
return (SkiaView?)null;
};
}
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.Invalidate();
}
try
{
_isUpdatingSelection = true;
public static void MapEmptyView(CollectionViewHandler handler, CollectionView collectionView)
{
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView != null)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.EmptyView = ((ItemsView)collectionView).EmptyView;
if (((ItemsView)collectionView).EmptyView is string emptyViewText)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.EmptyViewText = emptyViewText;
}
}
}
// Update virtual view selection
if (VirtualView.SelectionMode == SelectionMode.Single)
{
var newItem = e.CurrentSelection.FirstOrDefault();
if (!Equals(VirtualView.SelectedItem, newItem))
{
VirtualView.SelectedItem = newItem;
}
}
else if (VirtualView.SelectionMode == SelectionMode.Multiple)
{
// Clear and update selected items
VirtualView.SelectedItems.Clear();
foreach (var item in e.CurrentSelection)
{
VirtualView.SelectedItems.Add(item);
}
}
}
finally
{
_isUpdatingSelection = false;
}
}
public static void MapHorizontalScrollBarVisibility(CollectionViewHandler handler, CollectionView collectionView)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Expected I4, but got Unknown
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView != null)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.HorizontalScrollBarVisibility = (ScrollBarVisibility)((ItemsView)collectionView).HorizontalScrollBarVisibility;
}
}
private void OnScrolled(object? sender, ItemsScrolledEventArgs e)
{
VirtualView?.SendScrolled(new ItemsViewScrolledEventArgs
{
VerticalOffset = e.ScrollOffset,
VerticalDelta = 0,
HorizontalOffset = 0,
HorizontalDelta = 0
});
}
public static void MapVerticalScrollBarVisibility(CollectionViewHandler handler, CollectionView collectionView)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Expected I4, but got Unknown
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView != null)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.VerticalScrollBarVisibility = (ScrollBarVisibility)((ItemsView)collectionView).VerticalScrollBarVisibility;
}
}
private void OnItemTapped(object? sender, ItemsViewItemTappedEventArgs e)
{
// Item tap is handled through selection
}
public static void MapSelectedItem(CollectionViewHandler handler, CollectionView collectionView)
{
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView == null || handler._isUpdatingSelection)
{
return;
}
try
{
handler._isUpdatingSelection = true;
if (!object.Equals(((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.SelectedItem, ((SelectableItemsView)collectionView).SelectedItem))
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.SelectedItem = ((SelectableItemsView)collectionView).SelectedItem;
}
}
finally
{
handler._isUpdatingSelection = false;
}
}
public static void MapItemsSource(CollectionViewHandler handler, CollectionView collectionView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.ItemsSource = collectionView.ItemsSource;
}
public static void MapSelectedItems(CollectionViewHandler handler, CollectionView collectionView)
{
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView == null || handler._isUpdatingSelection)
{
return;
}
try
{
handler._isUpdatingSelection = true;
IList<object> selectedItems = ((SelectableItemsView)collectionView).SelectedItems;
if (selectedItems != null && selectedItems.Count > 0)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.SelectedItem = selectedItems.First();
}
}
finally
{
handler._isUpdatingSelection = false;
}
}
public static void MapItemTemplate(CollectionViewHandler handler, CollectionView collectionView)
{
if (handler.PlatformView is null || handler.MauiContext is null) return;
public static void MapSelectionMode(CollectionViewHandler handler, CollectionView collectionView)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected I4, but got Unknown
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView != null)
{
SkiaCollectionView platformView = ((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView;
SelectionMode selectionMode = ((SelectableItemsView)collectionView).SelectionMode;
platformView.SelectionMode = (int)selectionMode switch
{
0 => SkiaSelectionMode.None,
1 => SkiaSelectionMode.Single,
2 => SkiaSelectionMode.Multiple,
_ => SkiaSelectionMode.None,
};
}
}
var template = collectionView.ItemTemplate;
if (template != null)
{
// Set up a renderer that creates views from the DataTemplate
handler.PlatformView.ItemViewCreator = (item) =>
{
try
{
// Create view from template
var content = template.CreateContent();
if (content is View view)
{
// Set binding context FIRST so bindings evaluate
view.BindingContext = item;
public static void MapHeader(CollectionViewHandler handler, CollectionView collectionView)
{
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView != null)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.Header = ((StructuredItemsView)collectionView).Header;
}
}
// Force binding evaluation by accessing the visual tree
// This ensures child bindings are evaluated before handler creation
PropagateBindingContext(view, item);
public static void MapFooter(CollectionViewHandler handler, CollectionView collectionView)
{
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView != null)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.Footer = ((StructuredItemsView)collectionView).Footer;
}
}
// Create handler for the view
if (view.Handler == null && handler.MauiContext != null)
{
view.Handler = view.ToHandler(handler.MauiContext);
}
public static void MapItemsLayout(CollectionViewHandler handler, CollectionView collectionView)
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView == null)
{
return;
}
IItemsLayout itemsLayout = ((StructuredItemsView)collectionView).ItemsLayout;
LinearItemsLayout val = (LinearItemsLayout)(object)((itemsLayout is LinearItemsLayout) ? itemsLayout : null);
if (val != null)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.Orientation = (((int)((ItemsLayout)val).Orientation != 0) ? ItemsLayoutOrientation.Horizontal : ItemsLayoutOrientation.Vertical);
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.SpanCount = 1;
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.ItemSpacing = (float)val.ItemSpacing;
return;
}
GridItemsLayout val2 = (GridItemsLayout)(object)((itemsLayout is GridItemsLayout) ? itemsLayout : null);
if (val2 != null)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.Orientation = (((int)((ItemsLayout)val2).Orientation != 0) ? ItemsLayoutOrientation.Horizontal : ItemsLayoutOrientation.Vertical);
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.SpanCount = val2.Span;
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.ItemSpacing = (float)val2.VerticalItemSpacing;
}
}
if (view.Handler?.PlatformView is SkiaView skiaView)
{
return skiaView;
}
}
else if (content is ViewCell cell)
{
cell.BindingContext = item;
var cellView = cell.View;
if (cellView != null)
{
if (cellView.Handler == null && handler.MauiContext != null)
{
cellView.Handler = cellView.ToHandler(handler.MauiContext);
}
public static void MapBackground(CollectionViewHandler handler, CollectionView collectionView)
{
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView != null && ((VisualElement)collectionView).BackgroundColor == null)
{
Brush background = ((VisualElement)collectionView).Background;
SolidColorBrush val = (SolidColorBrush)(object)((background is SolidColorBrush) ? background : null);
if (val != null)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
if (cellView.Handler?.PlatformView is SkiaView skiaView)
{
return skiaView;
}
}
}
}
catch
{
// Ignore template creation errors
}
return null;
};
}
public static void MapBackgroundColor(CollectionViewHandler handler, CollectionView collectionView)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView != null && ((VisualElement)collectionView).BackgroundColor != null)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.BackgroundColor = ((VisualElement)collectionView).BackgroundColor.ToSKColor();
}
}
handler.PlatformView.Invalidate();
}
public static void MapScrollTo(CollectionViewHandler handler, CollectionView collectionView, object? args)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Invalid comparison between Unknown and I4
if (((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView == null)
{
return;
}
ScrollToRequestEventArgs e = (ScrollToRequestEventArgs)((args is ScrollToRequestEventArgs) ? args : null);
if (e != null)
{
if ((int)e.Mode == 1)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.ScrollToIndex(e.Index, e.IsAnimated);
}
else if (e.Item != null)
{
((ViewHandler<CollectionView, SkiaCollectionView>)(object)handler).PlatformView.ScrollToItem(e.Item, e.IsAnimated);
}
}
}
public static void MapEmptyView(CollectionViewHandler handler, CollectionView collectionView)
{
if (handler.PlatformView is null) return;
private static void PropagateBindingContext(View view, object? bindingContext)
{
((BindableObject)view).BindingContext = bindingContext;
Layout val = (Layout)(object)((view is Layout) ? view : null);
if (val != null)
{
foreach (IView child in val.Children)
{
View val2 = (View)(object)((child is View) ? child : null);
if (val2 != null)
{
PropagateBindingContext(val2, bindingContext);
}
}
return;
}
ContentView val3 = (ContentView)(object)((view is ContentView) ? view : null);
if (val3 != null && val3.Content != null)
{
PropagateBindingContext(val3.Content, bindingContext);
return;
}
Border val4 = (Border)(object)((view is Border) ? view : null);
if (val4 != null)
{
View content = val4.Content;
if (content != null)
{
PropagateBindingContext(content, bindingContext);
}
}
}
handler.PlatformView.EmptyView = collectionView.EmptyView;
if (collectionView.EmptyView is string text)
{
handler.PlatformView.EmptyViewText = text;
}
}
public static void MapHorizontalScrollBarVisibility(CollectionViewHandler handler, CollectionView collectionView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.HorizontalScrollBarVisibility = (ScrollBarVisibility)collectionView.HorizontalScrollBarVisibility;
}
public static void MapVerticalScrollBarVisibility(CollectionViewHandler handler, CollectionView collectionView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.VerticalScrollBarVisibility = (ScrollBarVisibility)collectionView.VerticalScrollBarVisibility;
}
public static void MapSelectedItem(CollectionViewHandler handler, CollectionView collectionView)
{
if (handler.PlatformView is null || handler._isUpdatingSelection) return;
try
{
handler._isUpdatingSelection = true;
if (!Equals(handler.PlatformView.SelectedItem, collectionView.SelectedItem))
{
handler.PlatformView.SelectedItem = collectionView.SelectedItem;
}
}
finally
{
handler._isUpdatingSelection = false;
}
}
public static void MapSelectedItems(CollectionViewHandler handler, CollectionView collectionView)
{
if (handler.PlatformView is null || handler._isUpdatingSelection) return;
try
{
handler._isUpdatingSelection = true;
// Sync selected items
var selectedItems = collectionView.SelectedItems;
if (selectedItems != null && selectedItems.Count > 0)
{
handler.PlatformView.SelectedItem = selectedItems.First();
}
}
finally
{
handler._isUpdatingSelection = false;
}
}
public static void MapSelectionMode(CollectionViewHandler handler, CollectionView collectionView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.SelectionMode = collectionView.SelectionMode switch
{
SelectionMode.None => SkiaSelectionMode.None,
SelectionMode.Single => SkiaSelectionMode.Single,
SelectionMode.Multiple => SkiaSelectionMode.Multiple,
_ => SkiaSelectionMode.None
};
}
public static void MapHeader(CollectionViewHandler handler, CollectionView collectionView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Header = collectionView.Header;
}
public static void MapFooter(CollectionViewHandler handler, CollectionView collectionView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Footer = collectionView.Footer;
}
public static void MapItemsLayout(CollectionViewHandler handler, CollectionView collectionView)
{
if (handler.PlatformView is null) return;
var layout = collectionView.ItemsLayout;
if (layout is LinearItemsLayout linearLayout)
{
handler.PlatformView.Orientation = linearLayout.Orientation == Controls.ItemsLayoutOrientation.Vertical
? Platform.ItemsLayoutOrientation.Vertical
: Platform.ItemsLayoutOrientation.Horizontal;
handler.PlatformView.SpanCount = 1;
handler.PlatformView.ItemSpacing = (float)linearLayout.ItemSpacing;
}
else if (layout is GridItemsLayout gridLayout)
{
handler.PlatformView.Orientation = gridLayout.Orientation == Controls.ItemsLayoutOrientation.Vertical
? Platform.ItemsLayoutOrientation.Vertical
: Platform.ItemsLayoutOrientation.Horizontal;
handler.PlatformView.SpanCount = gridLayout.Span;
handler.PlatformView.ItemSpacing = (float)gridLayout.VerticalItemSpacing;
}
}
public static void MapBackground(CollectionViewHandler handler, CollectionView collectionView)
{
if (handler.PlatformView is null) return;
// Don't override if BackgroundColor is explicitly set
if (collectionView.BackgroundColor is not null)
return;
if (collectionView.Background is SolidColorBrush solidBrush)
{
handler.PlatformView.BackgroundColor = solidBrush.Color.ToSKColor();
}
}
public static void MapBackgroundColor(CollectionViewHandler handler, CollectionView collectionView)
{
if (handler.PlatformView is null) return;
if (collectionView.BackgroundColor is not null)
{
handler.PlatformView.BackgroundColor = collectionView.BackgroundColor.ToSKColor();
}
}
public static void MapScrollTo(CollectionViewHandler handler, CollectionView collectionView, object? args)
{
if (handler.PlatformView is null || args is not ScrollToRequestEventArgs scrollArgs)
return;
if (scrollArgs.Mode == ScrollToMode.Position)
{
handler.PlatformView.ScrollToIndex(scrollArgs.Index, scrollArgs.IsAnimated);
}
else if (scrollArgs.Item != null)
{
handler.PlatformView.ScrollToItem(scrollArgs.Item, scrollArgs.IsAnimated);
}
}
/// <summary>
/// Recursively propagates binding context to all child views to force binding evaluation.
/// </summary>
private static void PropagateBindingContext(View view, object? bindingContext)
{
view.BindingContext = bindingContext;
// Propagate to children
if (view is Layout layout)
{
foreach (var child in layout.Children)
{
if (child is View childView)
{
PropagateBindingContext(childView, bindingContext);
}
}
}
else if (view is ContentView contentView && contentView.Content != null)
{
PropagateBindingContext(contentView.Content, bindingContext);
}
else if (view is Border border && border.Content is View borderContent)
{
PropagateBindingContext(borderContent, bindingContext);
}
}
}

View File

@@ -1,60 +0,0 @@
using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform.Linux.Hosting;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class ContentPageHandler : PageHandler
{
public new static IPropertyMapper<ContentPage, ContentPageHandler> Mapper = (IPropertyMapper<ContentPage, ContentPageHandler>)(object)new PropertyMapper<ContentPage, ContentPageHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)PageHandler.Mapper }) { ["Content"] = MapContent };
public new static CommandMapper<ContentPage, ContentPageHandler> CommandMapper = new CommandMapper<ContentPage, ContentPageHandler>((CommandMapper)(object)PageHandler.CommandMapper);
public ContentPageHandler()
: base((IPropertyMapper?)(object)Mapper, (CommandMapper?)(object)CommandMapper)
{
}
public ContentPageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper?)(((object)mapper) ?? ((object)Mapper)), (CommandMapper?)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override SkiaPage CreatePlatformView()
{
return new SkiaContentPage();
}
public static void MapContent(ContentPageHandler handler, ContentPage page)
{
if (((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView == null || ((ElementHandler)handler).MauiContext == null)
{
return;
}
View content = page.Content;
if (content != null)
{
if (((VisualElement)content).Handler == null)
{
Console.WriteLine("[ContentPageHandler] Creating handler for content: " + ((object)content).GetType().Name);
((VisualElement)content).Handler = ((IView)(object)content).ToViewHandler(((ElementHandler)handler).MauiContext);
}
IViewHandler handler2 = ((VisualElement)content).Handler;
if (((handler2 != null) ? ((IElementHandler)handler2).PlatformView : null) is SkiaView skiaView)
{
Console.WriteLine("[ContentPageHandler] Setting content: " + ((object)skiaView).GetType().Name);
((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView.Content = skiaView;
}
else
{
IViewHandler handler3 = ((VisualElement)content).Handler;
Console.WriteLine("[ContentPageHandler] Content handler PlatformView is not SkiaView: " + (((handler3 == null) ? null : ((IElementHandler)handler3).PlatformView?.GetType().Name) ?? "null"));
}
}
else
{
((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView.Content = null;
}
}
}

View File

@@ -1,133 +1,114 @@
using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
// 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.Handlers;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class DatePickerHandler : ViewHandler<IDatePicker, SkiaDatePicker>
/// <summary>
/// Handler for DatePicker on Linux using Skia rendering.
/// </summary>
public partial class DatePickerHandler : ViewHandler<IDatePicker, SkiaDatePicker>
{
public static IPropertyMapper<IDatePicker, DatePickerHandler> Mapper = (IPropertyMapper<IDatePicker, DatePickerHandler>)(object)new PropertyMapper<IDatePicker, DatePickerHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Date"] = MapDate,
["MinimumDate"] = MapMinimumDate,
["MaximumDate"] = MapMaximumDate,
["Format"] = MapFormat,
["TextColor"] = MapTextColor,
["CharacterSpacing"] = MapCharacterSpacing,
["Background"] = MapBackground
};
public static IPropertyMapper<IDatePicker, DatePickerHandler> Mapper =
new PropertyMapper<IDatePicker, DatePickerHandler>(ViewHandler.ViewMapper)
{
[nameof(IDatePicker.Date)] = MapDate,
[nameof(IDatePicker.MinimumDate)] = MapMinimumDate,
[nameof(IDatePicker.MaximumDate)] = MapMaximumDate,
[nameof(IDatePicker.Format)] = MapFormat,
[nameof(IDatePicker.TextColor)] = MapTextColor,
[nameof(IDatePicker.CharacterSpacing)] = MapCharacterSpacing,
[nameof(IView.Background)] = MapBackground,
};
public static CommandMapper<IDatePicker, DatePickerHandler> CommandMapper = new CommandMapper<IDatePicker, DatePickerHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public static CommandMapper<IDatePicker, DatePickerHandler> CommandMapper =
new(ViewHandler.ViewCommandMapper)
{
};
public DatePickerHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public DatePickerHandler() : base(Mapper, CommandMapper)
{
}
public DatePickerHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
public DatePickerHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override SkiaDatePicker CreatePlatformView()
{
return new SkiaDatePicker();
}
protected override SkiaDatePicker CreatePlatformView()
{
return new SkiaDatePicker();
}
protected override void ConnectHandler(SkiaDatePicker platformView)
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Invalid comparison between Unknown and I4
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
base.ConnectHandler(platformView);
platformView.DateSelected += OnDateSelected;
Application current = Application.Current;
if (current != null && (int)current.UserAppTheme == 2)
{
platformView.CalendarBackgroundColor = new SKColor((byte)30, (byte)30, (byte)30);
platformView.TextColor = new SKColor((byte)224, (byte)224, (byte)224);
platformView.BorderColor = new SKColor((byte)97, (byte)97, (byte)97);
platformView.DisabledDayColor = new SKColor((byte)97, (byte)97, (byte)97);
platformView.BackgroundColor = new SKColor((byte)45, (byte)45, (byte)45);
}
}
protected override void ConnectHandler(SkiaDatePicker platformView)
{
base.ConnectHandler(platformView);
platformView.DateSelected += OnDateSelected;
}
protected override void DisconnectHandler(SkiaDatePicker platformView)
{
platformView.DateSelected -= OnDateSelected;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaDatePicker platformView)
{
platformView.DateSelected -= OnDateSelected;
base.DisconnectHandler(platformView);
}
private void OnDateSelected(object? sender, EventArgs e)
{
if (base.VirtualView != null && base.PlatformView != null)
{
base.VirtualView.Date = base.PlatformView.Date;
}
}
private void OnDateSelected(object? sender, EventArgs e)
{
if (VirtualView is null || PlatformView is null) return;
public static void MapDate(DatePickerHandler handler, IDatePicker datePicker)
{
if (((ViewHandler<IDatePicker, SkiaDatePicker>)(object)handler).PlatformView != null)
{
((ViewHandler<IDatePicker, SkiaDatePicker>)(object)handler).PlatformView.Date = datePicker.Date;
}
}
VirtualView.Date = PlatformView.Date;
}
public static void MapMinimumDate(DatePickerHandler handler, IDatePicker datePicker)
{
if (((ViewHandler<IDatePicker, SkiaDatePicker>)(object)handler).PlatformView != null)
{
((ViewHandler<IDatePicker, SkiaDatePicker>)(object)handler).PlatformView.MinimumDate = datePicker.MinimumDate;
}
}
public static void MapDate(DatePickerHandler handler, IDatePicker datePicker)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Date = datePicker.Date;
}
public static void MapMaximumDate(DatePickerHandler handler, IDatePicker datePicker)
{
if (((ViewHandler<IDatePicker, SkiaDatePicker>)(object)handler).PlatformView != null)
{
((ViewHandler<IDatePicker, SkiaDatePicker>)(object)handler).PlatformView.MaximumDate = datePicker.MaximumDate;
}
}
public static void MapMinimumDate(DatePickerHandler handler, IDatePicker datePicker)
{
if (handler.PlatformView is null) return;
handler.PlatformView.MinimumDate = datePicker.MinimumDate;
}
public static void MapFormat(DatePickerHandler handler, IDatePicker datePicker)
{
if (((ViewHandler<IDatePicker, SkiaDatePicker>)(object)handler).PlatformView != null)
{
((ViewHandler<IDatePicker, SkiaDatePicker>)(object)handler).PlatformView.Format = datePicker.Format ?? "d";
}
}
public static void MapMaximumDate(DatePickerHandler handler, IDatePicker datePicker)
{
if (handler.PlatformView is null) return;
handler.PlatformView.MaximumDate = datePicker.MaximumDate;
}
public static void MapTextColor(DatePickerHandler handler, IDatePicker datePicker)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IDatePicker, SkiaDatePicker>)(object)handler).PlatformView != null && ((ITextStyle)datePicker).TextColor != null)
{
((ViewHandler<IDatePicker, SkiaDatePicker>)(object)handler).PlatformView.TextColor = ((ITextStyle)datePicker).TextColor.ToSKColor();
}
}
public static void MapFormat(DatePickerHandler handler, IDatePicker datePicker)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Format = datePicker.Format ?? "d";
}
public static void MapCharacterSpacing(DatePickerHandler handler, IDatePicker datePicker)
{
}
public static void MapTextColor(DatePickerHandler handler, IDatePicker datePicker)
{
if (handler.PlatformView is null) return;
if (datePicker.TextColor is not null)
{
handler.PlatformView.TextColor = datePicker.TextColor.ToSKColor();
}
}
public static void MapBackground(DatePickerHandler handler, IDatePicker datePicker)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IDatePicker, SkiaDatePicker>)(object)handler).PlatformView != null)
{
Paint background = ((IView)datePicker).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<IDatePicker, SkiaDatePicker>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
public static void MapCharacterSpacing(DatePickerHandler handler, IDatePicker datePicker)
{
// Character spacing would require custom text rendering
}
public static void MapBackground(DatePickerHandler handler, IDatePicker datePicker)
{
if (handler.PlatformView is null) return;
if (datePicker.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
}

View File

@@ -1,182 +1,181 @@
using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
// 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.Handlers;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class EditorHandler : ViewHandler<IEditor, SkiaEditor>
/// <summary>
/// Handler for Editor (multiline text) on Linux using Skia rendering.
/// </summary>
public partial class EditorHandler : ViewHandler<IEditor, SkiaEditor>
{
public static IPropertyMapper<IEditor, EditorHandler> Mapper = (IPropertyMapper<IEditor, EditorHandler>)(object)new PropertyMapper<IEditor, EditorHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Text"] = MapText,
["Placeholder"] = MapPlaceholder,
["PlaceholderColor"] = MapPlaceholderColor,
["TextColor"] = MapTextColor,
["CharacterSpacing"] = MapCharacterSpacing,
["IsReadOnly"] = MapIsReadOnly,
["IsTextPredictionEnabled"] = MapIsTextPredictionEnabled,
["MaxLength"] = MapMaxLength,
["CursorPosition"] = MapCursorPosition,
["SelectionLength"] = MapSelectionLength,
["Keyboard"] = MapKeyboard,
["HorizontalTextAlignment"] = MapHorizontalTextAlignment,
["VerticalTextAlignment"] = MapVerticalTextAlignment,
["Background"] = MapBackground,
["BackgroundColor"] = MapBackgroundColor
};
public static IPropertyMapper<IEditor, EditorHandler> Mapper =
new PropertyMapper<IEditor, EditorHandler>(ViewHandler.ViewMapper)
{
[nameof(IEditor.Text)] = MapText,
[nameof(IEditor.Placeholder)] = MapPlaceholder,
[nameof(IEditor.PlaceholderColor)] = MapPlaceholderColor,
[nameof(IEditor.TextColor)] = MapTextColor,
[nameof(IEditor.CharacterSpacing)] = MapCharacterSpacing,
[nameof(IEditor.IsReadOnly)] = MapIsReadOnly,
[nameof(IEditor.IsTextPredictionEnabled)] = MapIsTextPredictionEnabled,
[nameof(IEditor.MaxLength)] = MapMaxLength,
[nameof(IEditor.CursorPosition)] = MapCursorPosition,
[nameof(IEditor.SelectionLength)] = MapSelectionLength,
[nameof(IEditor.Keyboard)] = MapKeyboard,
[nameof(IEditor.HorizontalTextAlignment)] = MapHorizontalTextAlignment,
[nameof(IEditor.VerticalTextAlignment)] = MapVerticalTextAlignment,
[nameof(IView.Background)] = MapBackground,
["BackgroundColor"] = MapBackgroundColor,
};
public static CommandMapper<IEditor, EditorHandler> CommandMapper = new CommandMapper<IEditor, EditorHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public static CommandMapper<IEditor, EditorHandler> CommandMapper =
new(ViewHandler.ViewCommandMapper)
{
};
public EditorHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public EditorHandler() : base(Mapper, CommandMapper)
{
}
public EditorHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
public EditorHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override SkiaEditor CreatePlatformView()
{
return new SkiaEditor();
}
protected override SkiaEditor CreatePlatformView()
{
return new SkiaEditor();
}
protected override void ConnectHandler(SkiaEditor platformView)
{
base.ConnectHandler(platformView);
platformView.TextChanged += OnTextChanged;
platformView.Completed += OnCompleted;
}
protected override void ConnectHandler(SkiaEditor platformView)
{
base.ConnectHandler(platformView);
platformView.TextChanged += OnTextChanged;
platformView.Completed += OnCompleted;
}
protected override void DisconnectHandler(SkiaEditor platformView)
{
platformView.TextChanged -= OnTextChanged;
platformView.Completed -= OnCompleted;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaEditor platformView)
{
platformView.TextChanged -= OnTextChanged;
platformView.Completed -= OnCompleted;
base.DisconnectHandler(platformView);
}
private void OnTextChanged(object? sender, EventArgs e)
{
if (base.VirtualView != null && base.PlatformView != null)
{
((ITextInput)base.VirtualView).Text = base.PlatformView.Text;
}
}
private void OnTextChanged(object? sender, EventArgs e)
{
if (VirtualView is null || PlatformView is null) return;
private void OnCompleted(object? sender, EventArgs e)
{
}
VirtualView.Text = PlatformView.Text;
}
public static void MapText(EditorHandler handler, IEditor editor)
{
if (((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView != null)
{
((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView.Text = ((ITextInput)editor).Text ?? "";
((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView.Invalidate();
}
}
private void OnCompleted(object? sender, EventArgs e)
{
// Editor doesn't typically have a completed event, but we could trigger it
}
public static void MapPlaceholder(EditorHandler handler, IEditor editor)
{
if (((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView != null)
{
((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView.Placeholder = ((IPlaceholder)editor).Placeholder ?? "";
}
}
public static void MapText(EditorHandler handler, IEditor editor)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Text = editor.Text ?? "";
handler.PlatformView.Invalidate();
}
public static void MapPlaceholderColor(EditorHandler handler, IEditor editor)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView != null && ((IPlaceholder)editor).PlaceholderColor != null)
{
((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView.PlaceholderColor = ((IPlaceholder)editor).PlaceholderColor.ToSKColor();
}
}
public static void MapPlaceholder(EditorHandler handler, IEditor editor)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Placeholder = editor.Placeholder ?? "";
}
public static void MapTextColor(EditorHandler handler, IEditor editor)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView != null && ((ITextStyle)editor).TextColor != null)
{
((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView.TextColor = ((ITextStyle)editor).TextColor.ToSKColor();
}
}
public static void MapPlaceholderColor(EditorHandler handler, IEditor editor)
{
if (handler.PlatformView is null) return;
if (editor.PlaceholderColor is not null)
{
handler.PlatformView.PlaceholderColor = editor.PlaceholderColor.ToSKColor();
}
}
public static void MapCharacterSpacing(EditorHandler handler, IEditor editor)
{
}
public static void MapTextColor(EditorHandler handler, IEditor editor)
{
if (handler.PlatformView is null) return;
if (editor.TextColor is not null)
{
handler.PlatformView.TextColor = editor.TextColor.ToSKColor();
}
}
public static void MapIsReadOnly(EditorHandler handler, IEditor editor)
{
if (((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView != null)
{
((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView.IsReadOnly = ((ITextInput)editor).IsReadOnly;
}
}
public static void MapCharacterSpacing(EditorHandler handler, IEditor editor)
{
// Character spacing would require custom text rendering
}
public static void MapIsTextPredictionEnabled(EditorHandler handler, IEditor editor)
{
}
public static void MapIsReadOnly(EditorHandler handler, IEditor editor)
{
if (handler.PlatformView is null) return;
handler.PlatformView.IsReadOnly = editor.IsReadOnly;
}
public static void MapMaxLength(EditorHandler handler, IEditor editor)
{
if (((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView != null)
{
((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView.MaxLength = ((ITextInput)editor).MaxLength;
}
}
public static void MapIsTextPredictionEnabled(EditorHandler handler, IEditor editor)
{
// Text prediction not applicable to desktop
}
public static void MapCursorPosition(EditorHandler handler, IEditor editor)
{
if (((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView != null)
{
((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView.CursorPosition = ((ITextInput)editor).CursorPosition;
}
}
public static void MapMaxLength(EditorHandler handler, IEditor editor)
{
if (handler.PlatformView is null) return;
handler.PlatformView.MaxLength = editor.MaxLength;
}
public static void MapSelectionLength(EditorHandler handler, IEditor editor)
{
}
public static void MapCursorPosition(EditorHandler handler, IEditor editor)
{
if (handler.PlatformView is null) return;
handler.PlatformView.CursorPosition = editor.CursorPosition;
}
public static void MapKeyboard(EditorHandler handler, IEditor editor)
{
}
public static void MapSelectionLength(EditorHandler handler, IEditor editor)
{
// Selection would need to be added to SkiaEditor
}
public static void MapHorizontalTextAlignment(EditorHandler handler, IEditor editor)
{
}
public static void MapKeyboard(EditorHandler handler, IEditor editor)
{
// Virtual keyboard type not applicable to desktop
}
public static void MapVerticalTextAlignment(EditorHandler handler, IEditor editor)
{
}
public static void MapHorizontalTextAlignment(EditorHandler handler, IEditor editor)
{
// Text alignment would require changes to SkiaEditor drawing
}
public static void MapBackground(EditorHandler handler, IEditor editor)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView != null)
{
Paint background = ((IView)editor).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
public static void MapVerticalTextAlignment(EditorHandler handler, IEditor editor)
{
// Text alignment would require changes to SkiaEditor drawing
}
public static void MapBackgroundColor(EditorHandler handler, IEditor editor)
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView != null)
{
VisualElement val = (VisualElement)(object)((editor is VisualElement) ? editor : null);
if (val != null && val.BackgroundColor != null)
{
((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView.BackgroundColor = val.BackgroundColor.ToSKColor();
((ViewHandler<IEditor, SkiaEditor>)(object)handler).PlatformView.Invalidate();
}
}
}
public static void MapBackground(EditorHandler handler, IEditor editor)
{
if (handler.PlatformView is null) return;
if (editor.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapBackgroundColor(EditorHandler handler, IEditor editor)
{
if (handler.PlatformView is null) return;
if (editor is VisualElement ve && ve.BackgroundColor != null)
{
handler.PlatformView.BackgroundColor = ve.BackgroundColor.ToSKColor();
handler.PlatformView.Invalidate();
}
}
}

View File

@@ -1,280 +1,215 @@
using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
// 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.Handlers;
using Microsoft.Maui.Graphics;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class EntryHandler : ViewHandler<IEntry, SkiaEntry>
/// <summary>
/// Handler for Entry on Linux using Skia rendering.
/// Maps IEntry interface to SkiaEntry platform view.
/// </summary>
public partial class EntryHandler : ViewHandler<IEntry, SkiaEntry>
{
public static IPropertyMapper<IEntry, EntryHandler> Mapper = (IPropertyMapper<IEntry, EntryHandler>)(object)new PropertyMapper<IEntry, EntryHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Text"] = MapText,
["TextColor"] = MapTextColor,
["Font"] = MapFont,
["CharacterSpacing"] = MapCharacterSpacing,
["Placeholder"] = MapPlaceholder,
["PlaceholderColor"] = MapPlaceholderColor,
["IsReadOnly"] = MapIsReadOnly,
["MaxLength"] = MapMaxLength,
["CursorPosition"] = MapCursorPosition,
["SelectionLength"] = MapSelectionLength,
["IsPassword"] = MapIsPassword,
["ReturnType"] = MapReturnType,
["ClearButtonVisibility"] = MapClearButtonVisibility,
["HorizontalTextAlignment"] = MapHorizontalTextAlignment,
["VerticalTextAlignment"] = MapVerticalTextAlignment,
["Background"] = MapBackground,
["BackgroundColor"] = MapBackgroundColor
};
public static IPropertyMapper<IEntry, EntryHandler> Mapper = new PropertyMapper<IEntry, EntryHandler>(ViewHandler.ViewMapper)
{
[nameof(ITextInput.Text)] = MapText,
[nameof(ITextStyle.TextColor)] = MapTextColor,
[nameof(ITextStyle.Font)] = MapFont,
[nameof(ITextStyle.CharacterSpacing)] = MapCharacterSpacing,
[nameof(IPlaceholder.Placeholder)] = MapPlaceholder,
[nameof(IPlaceholder.PlaceholderColor)] = MapPlaceholderColor,
[nameof(ITextInput.IsReadOnly)] = MapIsReadOnly,
[nameof(ITextInput.MaxLength)] = MapMaxLength,
[nameof(ITextInput.CursorPosition)] = MapCursorPosition,
[nameof(ITextInput.SelectionLength)] = MapSelectionLength,
[nameof(IEntry.IsPassword)] = MapIsPassword,
[nameof(IEntry.ReturnType)] = MapReturnType,
[nameof(IEntry.ClearButtonVisibility)] = MapClearButtonVisibility,
[nameof(ITextAlignment.HorizontalTextAlignment)] = MapHorizontalTextAlignment,
[nameof(ITextAlignment.VerticalTextAlignment)] = MapVerticalTextAlignment,
[nameof(IView.Background)] = MapBackground,
};
public static CommandMapper<IEntry, EntryHandler> CommandMapper = new CommandMapper<IEntry, EntryHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public static CommandMapper<IEntry, EntryHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
public EntryHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public EntryHandler() : base(Mapper, CommandMapper)
{
}
public EntryHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
public EntryHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override SkiaEntry CreatePlatformView()
{
return new SkiaEntry();
}
protected override SkiaEntry CreatePlatformView()
{
return new SkiaEntry();
}
protected override void ConnectHandler(SkiaEntry platformView)
{
base.ConnectHandler(platformView);
platformView.TextChanged += OnTextChanged;
platformView.Completed += OnCompleted;
}
protected override void ConnectHandler(SkiaEntry platformView)
{
base.ConnectHandler(platformView);
platformView.TextChanged += OnTextChanged;
platformView.Completed += OnCompleted;
}
protected override void DisconnectHandler(SkiaEntry platformView)
{
platformView.TextChanged -= OnTextChanged;
platformView.Completed -= OnCompleted;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaEntry platformView)
{
platformView.TextChanged -= OnTextChanged;
platformView.Completed -= OnCompleted;
base.DisconnectHandler(platformView);
}
private void OnTextChanged(object? sender, TextChangedEventArgs e)
{
if (base.VirtualView != null && base.PlatformView != null && ((ITextInput)base.VirtualView).Text != e.NewTextValue)
{
((ITextInput)base.VirtualView).Text = e.NewTextValue ?? string.Empty;
}
}
private void OnTextChanged(object? sender, Platform.TextChangedEventArgs e)
{
if (VirtualView is null || PlatformView is null) return;
private void OnCompleted(object? sender, EventArgs e)
{
IEntry virtualView = base.VirtualView;
if (virtualView != null)
{
virtualView.Completed();
}
}
if (VirtualView.Text != e.NewTextValue)
{
VirtualView.Text = e.NewTextValue ?? string.Empty;
}
}
public static void MapText(EntryHandler handler, IEntry entry)
{
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null && ((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.Text != ((ITextInput)entry).Text)
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.Text = ((ITextInput)entry).Text ?? string.Empty;
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.Invalidate();
}
}
private void OnCompleted(object? sender, EventArgs e)
{
VirtualView?.Completed();
}
public static void MapTextColor(EntryHandler handler, IEntry entry)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null && ((ITextStyle)entry).TextColor != null)
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.TextColor = ((ITextStyle)entry).TextColor.ToSKColor();
}
}
public static void MapText(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
public static void MapFont(EntryHandler handler, IEntry entry)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Invalid comparison between Unknown and I4
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Invalid comparison between Unknown and I4
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Invalid comparison between Unknown and I4
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null)
{
Font font = ((ITextStyle)entry).Font;
if (((Font)(ref font)).Size > 0.0)
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.FontSize = (float)((Font)(ref font)).Size;
}
if (!string.IsNullOrEmpty(((Font)(ref font)).Family))
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.FontFamily = ((Font)(ref font)).Family;
}
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.IsBold = (int)((Font)(ref font)).Weight >= 700;
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.IsItalic = (int)((Font)(ref font)).Slant == 1 || (int)((Font)(ref font)).Slant == 2;
}
}
if (handler.PlatformView.Text != entry.Text)
{
handler.PlatformView.Text = entry.Text ?? string.Empty;
handler.PlatformView.Invalidate();
}
}
public static void MapCharacterSpacing(EntryHandler handler, IEntry entry)
{
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null)
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.CharacterSpacing = (float)((ITextStyle)entry).CharacterSpacing;
}
}
public static void MapTextColor(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
public static void MapPlaceholder(EntryHandler handler, IEntry entry)
{
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null)
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.Placeholder = ((IPlaceholder)entry).Placeholder ?? string.Empty;
}
}
if (entry.TextColor is not null)
handler.PlatformView.TextColor = entry.TextColor.ToSKColor();
}
public static void MapPlaceholderColor(EntryHandler handler, IEntry entry)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null && ((IPlaceholder)entry).PlaceholderColor != null)
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.PlaceholderColor = ((IPlaceholder)entry).PlaceholderColor.ToSKColor();
}
}
public static void MapFont(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
public static void MapIsReadOnly(EntryHandler handler, IEntry entry)
{
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null)
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.IsReadOnly = ((ITextInput)entry).IsReadOnly;
}
}
var font = entry.Font;
if (font.Size > 0)
handler.PlatformView.FontSize = (float)font.Size;
public static void MapMaxLength(EntryHandler handler, IEntry entry)
{
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null)
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.MaxLength = ((ITextInput)entry).MaxLength;
}
}
if (!string.IsNullOrEmpty(font.Family))
handler.PlatformView.FontFamily = font.Family;
public static void MapCursorPosition(EntryHandler handler, IEntry entry)
{
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null)
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.CursorPosition = ((ITextInput)entry).CursorPosition;
}
}
handler.PlatformView.IsBold = font.Weight >= FontWeight.Bold;
handler.PlatformView.IsItalic = font.Slant == FontSlant.Italic || font.Slant == FontSlant.Oblique;
}
public static void MapSelectionLength(EntryHandler handler, IEntry entry)
{
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null)
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.SelectionLength = ((ITextInput)entry).SelectionLength;
}
}
public static void MapCharacterSpacing(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
handler.PlatformView.CharacterSpacing = (float)entry.CharacterSpacing;
}
public static void MapIsPassword(EntryHandler handler, IEntry entry)
{
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null)
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.IsPassword = entry.IsPassword;
}
}
public static void MapPlaceholder(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Placeholder = entry.Placeholder ?? string.Empty;
}
public static void MapReturnType(EntryHandler handler, IEntry entry)
{
_ = ((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView;
}
public static void MapPlaceholderColor(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
public static void MapClearButtonVisibility(EntryHandler handler, IEntry entry)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Invalid comparison between Unknown and I4
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null)
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.ShowClearButton = (int)entry.ClearButtonVisibility == 1;
}
}
if (entry.PlaceholderColor is not null)
handler.PlatformView.PlaceholderColor = entry.PlaceholderColor.ToSKColor();
}
public static void MapHorizontalTextAlignment(EntryHandler handler, IEntry entry)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected I4, but got Unknown
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null)
{
SkiaEntry platformView = ((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView;
TextAlignment horizontalTextAlignment = ((ITextAlignment)entry).HorizontalTextAlignment;
platformView.HorizontalTextAlignment = (int)horizontalTextAlignment switch
{
0 => TextAlignment.Start,
1 => TextAlignment.Center,
2 => TextAlignment.End,
_ => TextAlignment.Start,
};
}
}
public static void MapIsReadOnly(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
handler.PlatformView.IsReadOnly = entry.IsReadOnly;
}
public static void MapVerticalTextAlignment(EntryHandler handler, IEntry entry)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected I4, but got Unknown
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null)
{
SkiaEntry platformView = ((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView;
TextAlignment verticalTextAlignment = ((ITextAlignment)entry).VerticalTextAlignment;
platformView.VerticalTextAlignment = (int)verticalTextAlignment switch
{
0 => TextAlignment.Start,
1 => TextAlignment.Center,
2 => TextAlignment.End,
_ => TextAlignment.Center,
};
}
}
public static void MapMaxLength(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
handler.PlatformView.MaxLength = entry.MaxLength;
}
public static void MapBackground(EntryHandler handler, IEntry entry)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView != null)
{
Paint background = ((IView)entry).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
public static void MapCursorPosition(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
handler.PlatformView.CursorPosition = entry.CursorPosition;
}
public static void MapBackgroundColor(EntryHandler handler, IEntry entry)
{
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView == null)
{
return;
}
Entry val = (Entry)(object)((entry is Entry) ? entry : null);
if (val != null)
{
Console.WriteLine($"[EntryHandler] MapBackgroundColor: {((VisualElement)val).BackgroundColor}");
if (((VisualElement)val).BackgroundColor != null)
{
SKColor val2 = ((VisualElement)val).BackgroundColor.ToSKColor();
Console.WriteLine($"[EntryHandler] Setting EntryBackgroundColor to: {val2}");
((ViewHandler<IEntry, SkiaEntry>)(object)handler).PlatformView.EntryBackgroundColor = val2;
}
}
}
public static void MapSelectionLength(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
handler.PlatformView.SelectionLength = entry.SelectionLength;
}
public static void MapIsPassword(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
handler.PlatformView.IsPassword = entry.IsPassword;
}
public static void MapReturnType(EntryHandler handler, IEntry entry)
{
// ReturnType affects keyboard behavior - stored for virtual keyboard integration
if (handler.PlatformView is null) return;
// handler.PlatformView.ReturnType = entry.ReturnType; // Would need property on SkiaEntry
}
public static void MapClearButtonVisibility(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
handler.PlatformView.ShowClearButton = entry.ClearButtonVisibility == ClearButtonVisibility.WhileEditing;
}
public static void MapHorizontalTextAlignment(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
handler.PlatformView.HorizontalTextAlignment = entry.HorizontalTextAlignment switch
{
Microsoft.Maui.TextAlignment.Start => Platform.TextAlignment.Start,
Microsoft.Maui.TextAlignment.Center => Platform.TextAlignment.Center,
Microsoft.Maui.TextAlignment.End => Platform.TextAlignment.End,
_ => Platform.TextAlignment.Start
};
}
public static void MapVerticalTextAlignment(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
handler.PlatformView.VerticalTextAlignment = entry.VerticalTextAlignment switch
{
Microsoft.Maui.TextAlignment.Start => Platform.TextAlignment.Start,
Microsoft.Maui.TextAlignment.Center => Platform.TextAlignment.Center,
Microsoft.Maui.TextAlignment.End => Platform.TextAlignment.End,
_ => Platform.TextAlignment.Center
};
}
public static void MapBackground(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
if (entry.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
}

View File

@@ -1,139 +0,0 @@
using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Layouts;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class FlexLayoutHandler : LayoutHandler
{
public new static IPropertyMapper<FlexLayout, FlexLayoutHandler> Mapper = (IPropertyMapper<FlexLayout, FlexLayoutHandler>)(object)new PropertyMapper<FlexLayout, FlexLayoutHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)LayoutHandler.Mapper })
{
["Direction"] = MapDirection,
["Wrap"] = MapWrap,
["JustifyContent"] = MapJustifyContent,
["AlignItems"] = MapAlignItems,
["AlignContent"] = MapAlignContent
};
public FlexLayoutHandler()
: base((IPropertyMapper?)(object)Mapper)
{
}
protected override SkiaLayoutView CreatePlatformView()
{
return new SkiaFlexLayout();
}
public static void MapDirection(FlexLayoutHandler handler, FlexLayout layout)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Expected I4, but got Unknown
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView is SkiaFlexLayout skiaFlexLayout)
{
SkiaFlexLayout skiaFlexLayout2 = skiaFlexLayout;
FlexDirection direction = layout.Direction;
skiaFlexLayout2.Direction = (int)direction switch
{
0 => FlexDirection.Row,
1 => FlexDirection.RowReverse,
2 => FlexDirection.Column,
3 => FlexDirection.ColumnReverse,
_ => FlexDirection.Row,
};
}
}
public static void MapWrap(FlexLayoutHandler handler, FlexLayout layout)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Expected I4, but got Unknown
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView is SkiaFlexLayout skiaFlexLayout)
{
SkiaFlexLayout skiaFlexLayout2 = skiaFlexLayout;
FlexWrap wrap = layout.Wrap;
skiaFlexLayout2.Wrap = (int)wrap switch
{
0 => FlexWrap.NoWrap,
1 => FlexWrap.Wrap,
2 => FlexWrap.WrapReverse,
_ => FlexWrap.NoWrap,
};
}
}
public static void MapJustifyContent(FlexLayoutHandler handler, FlexLayout layout)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Expected I4, but got Unknown
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView is SkiaFlexLayout skiaFlexLayout)
{
SkiaFlexLayout skiaFlexLayout2 = skiaFlexLayout;
FlexJustify justifyContent = layout.JustifyContent;
skiaFlexLayout2.JustifyContent = (justifyContent - 2) switch
{
1 => FlexJustify.Start,
0 => FlexJustify.Center,
2 => FlexJustify.End,
3 => FlexJustify.SpaceBetween,
4 => FlexJustify.SpaceAround,
5 => FlexJustify.SpaceEvenly,
_ => FlexJustify.Start,
};
}
}
public static void MapAlignItems(FlexLayoutHandler handler, FlexLayout layout)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Expected I4, but got Unknown
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView is SkiaFlexLayout skiaFlexLayout)
{
SkiaFlexLayout skiaFlexLayout2 = skiaFlexLayout;
FlexAlignItems alignItems = layout.AlignItems;
skiaFlexLayout2.AlignItems = (alignItems - 1) switch
{
2 => FlexAlignItems.Start,
1 => FlexAlignItems.Center,
3 => FlexAlignItems.End,
0 => FlexAlignItems.Stretch,
_ => FlexAlignItems.Stretch,
};
}
}
public static void MapAlignContent(FlexLayoutHandler handler, FlexLayout layout)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Expected I4, but got Unknown
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView is SkiaFlexLayout skiaFlexLayout)
{
SkiaFlexLayout skiaFlexLayout2 = skiaFlexLayout;
FlexAlignContent alignContent = layout.AlignContent;
skiaFlexLayout2.AlignContent = (alignContent - 1) switch
{
2 => FlexAlignContent.Start,
1 => FlexAlignContent.Center,
3 => FlexAlignContent.End,
0 => FlexAlignContent.Stretch,
4 => FlexAlignContent.SpaceBetween,
5 => FlexAlignContent.SpaceAround,
6 => FlexAlignContent.SpaceAround,
_ => FlexAlignContent.Stretch,
};
}
}
}

View File

@@ -1,94 +1,91 @@
using System;
// 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.Handlers;
using Microsoft.Maui.Graphics;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class FlyoutPageHandler : ViewHandler<IFlyoutView, SkiaFlyoutPage>
/// <summary>
/// Handler for FlyoutPage on Linux using Skia rendering.
/// Maps IFlyoutView interface to SkiaFlyoutPage platform view.
/// </summary>
public partial class FlyoutPageHandler : ViewHandler<IFlyoutView, SkiaFlyoutPage>
{
public static IPropertyMapper<IFlyoutView, FlyoutPageHandler> Mapper = (IPropertyMapper<IFlyoutView, FlyoutPageHandler>)(object)new PropertyMapper<IFlyoutView, FlyoutPageHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["IsPresented"] = MapIsPresented,
["FlyoutWidth"] = MapFlyoutWidth,
["IsGestureEnabled"] = MapIsGestureEnabled,
["FlyoutBehavior"] = MapFlyoutBehavior
};
public static IPropertyMapper<IFlyoutView, FlyoutPageHandler> Mapper = new PropertyMapper<IFlyoutView, FlyoutPageHandler>(ViewHandler.ViewMapper)
{
[nameof(IFlyoutView.IsPresented)] = MapIsPresented,
[nameof(IFlyoutView.FlyoutWidth)] = MapFlyoutWidth,
[nameof(IFlyoutView.IsGestureEnabled)] = MapIsGestureEnabled,
[nameof(IFlyoutView.FlyoutBehavior)] = MapFlyoutBehavior,
};
public static CommandMapper<IFlyoutView, FlyoutPageHandler> CommandMapper = new CommandMapper<IFlyoutView, FlyoutPageHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public static CommandMapper<IFlyoutView, FlyoutPageHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
public FlyoutPageHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public FlyoutPageHandler() : base(Mapper, CommandMapper)
{
}
public FlyoutPageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
public FlyoutPageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override SkiaFlyoutPage CreatePlatformView()
{
return new SkiaFlyoutPage();
}
protected override SkiaFlyoutPage CreatePlatformView()
{
return new SkiaFlyoutPage();
}
protected override void ConnectHandler(SkiaFlyoutPage platformView)
{
base.ConnectHandler(platformView);
platformView.IsPresentedChanged += OnIsPresentedChanged;
}
protected override void ConnectHandler(SkiaFlyoutPage platformView)
{
base.ConnectHandler(platformView);
platformView.IsPresentedChanged += OnIsPresentedChanged;
}
protected override void DisconnectHandler(SkiaFlyoutPage platformView)
{
platformView.IsPresentedChanged -= OnIsPresentedChanged;
platformView.Flyout = null;
platformView.Detail = null;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaFlyoutPage platformView)
{
platformView.IsPresentedChanged -= OnIsPresentedChanged;
platformView.Flyout = null;
platformView.Detail = null;
base.DisconnectHandler(platformView);
}
private void OnIsPresentedChanged(object? sender, EventArgs e)
{
}
private void OnIsPresentedChanged(object? sender, EventArgs e)
{
// Sync back to the virtual view
}
public static void MapIsPresented(FlyoutPageHandler handler, IFlyoutView flyoutView)
{
if (((ViewHandler<IFlyoutView, SkiaFlyoutPage>)(object)handler).PlatformView != null)
{
((ViewHandler<IFlyoutView, SkiaFlyoutPage>)(object)handler).PlatformView.IsPresented = flyoutView.IsPresented;
}
}
public static void MapIsPresented(FlyoutPageHandler handler, IFlyoutView flyoutView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.IsPresented = flyoutView.IsPresented;
}
public static void MapFlyoutWidth(FlyoutPageHandler handler, IFlyoutView flyoutView)
{
if (((ViewHandler<IFlyoutView, SkiaFlyoutPage>)(object)handler).PlatformView != null)
{
((ViewHandler<IFlyoutView, SkiaFlyoutPage>)(object)handler).PlatformView.FlyoutWidth = (float)flyoutView.FlyoutWidth;
}
}
public static void MapFlyoutWidth(FlyoutPageHandler handler, IFlyoutView flyoutView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.FlyoutWidth = (float)flyoutView.FlyoutWidth;
}
public static void MapIsGestureEnabled(FlyoutPageHandler handler, IFlyoutView flyoutView)
{
if (((ViewHandler<IFlyoutView, SkiaFlyoutPage>)(object)handler).PlatformView != null)
{
((ViewHandler<IFlyoutView, SkiaFlyoutPage>)(object)handler).PlatformView.GestureEnabled = flyoutView.IsGestureEnabled;
}
}
public static void MapIsGestureEnabled(FlyoutPageHandler handler, IFlyoutView flyoutView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.GestureEnabled = flyoutView.IsGestureEnabled;
}
public static void MapFlyoutBehavior(FlyoutPageHandler handler, IFlyoutView flyoutView)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected I4, but got Unknown
if (((ViewHandler<IFlyoutView, SkiaFlyoutPage>)(object)handler).PlatformView != null)
{
SkiaFlyoutPage platformView = ((ViewHandler<IFlyoutView, SkiaFlyoutPage>)(object)handler).PlatformView;
FlyoutBehavior flyoutBehavior = flyoutView.FlyoutBehavior;
platformView.FlyoutLayoutBehavior = (int)flyoutBehavior switch
{
0 => FlyoutLayoutBehavior.Default,
1 => FlyoutLayoutBehavior.Popover,
2 => FlyoutLayoutBehavior.Split,
_ => FlyoutLayoutBehavior.Default,
};
}
}
public static void MapFlyoutBehavior(FlyoutPageHandler handler, IFlyoutView flyoutView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.FlyoutLayoutBehavior = flyoutView.FlyoutBehavior switch
{
Microsoft.Maui.FlyoutBehavior.Disabled => FlyoutLayoutBehavior.Default,
Microsoft.Maui.FlyoutBehavior.Flyout => FlyoutLayoutBehavior.Popover,
Microsoft.Maui.FlyoutBehavior.Locked => FlyoutLayoutBehavior.Split,
_ => FlyoutLayoutBehavior.Default
};
}
}

View File

@@ -1,134 +1,104 @@
using System;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Controls;
using Microsoft.Maui.Controls.Compatibility;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform.Linux.Hosting;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class FrameHandler : ViewHandler<Frame, SkiaFrame>
/// <summary>
/// Handler for Frame on Linux using SkiaFrame.
/// </summary>
public partial class FrameHandler : ViewHandler<Frame, SkiaFrame>
{
public static IPropertyMapper<Frame, FrameHandler> Mapper = (IPropertyMapper<Frame, FrameHandler>)(object)new PropertyMapper<Frame, FrameHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["BorderColor"] = MapBorderColor,
["CornerRadius"] = MapCornerRadius,
["HasShadow"] = MapHasShadow,
["BackgroundColor"] = MapBackgroundColor,
["Padding"] = MapPadding,
["Content"] = MapContent
};
public static IPropertyMapper<Frame, FrameHandler> Mapper =
new PropertyMapper<Frame, FrameHandler>(ViewMapper)
{
[nameof(Frame.BorderColor)] = MapBorderColor,
[nameof(Frame.CornerRadius)] = MapCornerRadius,
[nameof(Frame.HasShadow)] = MapHasShadow,
[nameof(Frame.BackgroundColor)] = MapBackgroundColor,
[nameof(Frame.Padding)] = MapPadding,
[nameof(Frame.Content)] = MapContent,
};
public FrameHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)null)
{
}
public FrameHandler() : base(Mapper)
{
}
public FrameHandler(IPropertyMapper? mapper)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)null)
{
}
public FrameHandler(IPropertyMapper? mapper)
: base(mapper ?? Mapper)
{
}
protected override SkiaFrame CreatePlatformView()
{
return new SkiaFrame();
}
protected override SkiaFrame CreatePlatformView()
{
return new SkiaFrame();
}
protected override void ConnectHandler(SkiaFrame platformView)
{
base.ConnectHandler(platformView);
View virtualView = (View)(object)base.VirtualView;
if (virtualView != null)
{
platformView.MauiView = virtualView;
}
platformView.Tapped += OnPlatformViewTapped;
}
public static void MapBorderColor(FrameHandler handler, Frame frame)
{
if (frame.BorderColor != null)
{
handler.PlatformView.Stroke = new SKColor(
(byte)(frame.BorderColor.Red * 255),
(byte)(frame.BorderColor.Green * 255),
(byte)(frame.BorderColor.Blue * 255),
(byte)(frame.BorderColor.Alpha * 255));
}
}
protected override void DisconnectHandler(SkiaFrame platformView)
{
platformView.Tapped -= OnPlatformViewTapped;
platformView.MauiView = null;
base.DisconnectHandler(platformView);
}
public static void MapCornerRadius(FrameHandler handler, Frame frame)
{
handler.PlatformView.CornerRadius = frame.CornerRadius;
}
private void OnPlatformViewTapped(object? sender, EventArgs e)
{
View virtualView = (View)(object)base.VirtualView;
if (virtualView != null)
{
GestureManager.ProcessTap(virtualView, 0.0, 0.0);
}
}
public static void MapHasShadow(FrameHandler handler, Frame frame)
{
handler.PlatformView.HasShadow = frame.HasShadow;
}
public static void MapBorderColor(FrameHandler handler, Frame frame)
{
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
if (frame.BorderColor != null)
{
((ViewHandler<Frame, SkiaFrame>)(object)handler).PlatformView.Stroke = new SKColor((byte)(frame.BorderColor.Red * 255f), (byte)(frame.BorderColor.Green * 255f), (byte)(frame.BorderColor.Blue * 255f), (byte)(frame.BorderColor.Alpha * 255f));
}
}
public static void MapBackgroundColor(FrameHandler handler, Frame frame)
{
if (frame.BackgroundColor != null)
{
handler.PlatformView.BackgroundColor = new SKColor(
(byte)(frame.BackgroundColor.Red * 255),
(byte)(frame.BackgroundColor.Green * 255),
(byte)(frame.BackgroundColor.Blue * 255),
(byte)(frame.BackgroundColor.Alpha * 255));
}
}
public static void MapCornerRadius(FrameHandler handler, Frame frame)
{
((ViewHandler<Frame, SkiaFrame>)(object)handler).PlatformView.CornerRadius = frame.CornerRadius;
}
public static void MapPadding(FrameHandler handler, Frame frame)
{
handler.PlatformView.SetPadding(
(float)frame.Padding.Left,
(float)frame.Padding.Top,
(float)frame.Padding.Right,
(float)frame.Padding.Bottom);
}
public static void MapHasShadow(FrameHandler handler, Frame frame)
{
((ViewHandler<Frame, SkiaFrame>)(object)handler).PlatformView.HasShadow = frame.HasShadow;
}
public static void MapContent(FrameHandler handler, Frame frame)
{
if (handler.PlatformView is null || handler.MauiContext is null) return;
public static void MapBackgroundColor(FrameHandler handler, Frame frame)
{
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
if (((VisualElement)frame).BackgroundColor != null)
{
((ViewHandler<Frame, SkiaFrame>)(object)handler).PlatformView.BackgroundColor = new SKColor((byte)(((VisualElement)frame).BackgroundColor.Red * 255f), (byte)(((VisualElement)frame).BackgroundColor.Green * 255f), (byte)(((VisualElement)frame).BackgroundColor.Blue * 255f), (byte)(((VisualElement)frame).BackgroundColor.Alpha * 255f));
}
}
handler.PlatformView.ClearChildren();
public static void MapPadding(FrameHandler handler, Frame frame)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
SkiaFrame platformView = ((ViewHandler<Frame, SkiaFrame>)(object)handler).PlatformView;
Thickness padding = ((Layout)frame).Padding;
float left = (float)((Thickness)(ref padding)).Left;
padding = ((Layout)frame).Padding;
float top = (float)((Thickness)(ref padding)).Top;
padding = ((Layout)frame).Padding;
float right = (float)((Thickness)(ref padding)).Right;
padding = ((Layout)frame).Padding;
platformView.SetPadding(left, top, right, (float)((Thickness)(ref padding)).Bottom);
}
var content = frame.Content;
if (content != null)
{
// Create handler for content if it doesn't exist
if (content.Handler == null)
{
content.Handler = content.ToHandler(handler.MauiContext);
}
public static void MapContent(FrameHandler handler, Frame frame)
{
if (((ViewHandler<Frame, SkiaFrame>)(object)handler).PlatformView == null || ((ElementHandler)handler).MauiContext == null)
{
return;
}
((ViewHandler<Frame, SkiaFrame>)(object)handler).PlatformView.ClearChildren();
View content = ((ContentView)frame).Content;
if (content != null)
{
if (((VisualElement)content).Handler == null)
{
((VisualElement)content).Handler = ((IView)(object)content).ToViewHandler(((ElementHandler)handler).MauiContext);
}
IViewHandler handler2 = ((VisualElement)content).Handler;
if (((handler2 != null) ? ((IElementHandler)handler2).PlatformView : null) is SkiaView child)
{
((ViewHandler<Frame, SkiaFrame>)(object)handler).PlatformView.AddChild(child);
}
}
}
if (content.Handler?.PlatformView is SkiaView skiaContent)
{
handler.PlatformView.AddChild(skiaContent);
}
}
}
}

View File

@@ -1,547 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Windows.Input;
using Microsoft.Maui.Controls;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public static class GestureManager
{
private class GestureTrackingState
{
public double StartX { get; set; }
public double StartY { get; set; }
public double CurrentX { get; set; }
public double CurrentY { get; set; }
public DateTime StartTime { get; set; }
public bool IsPanning { get; set; }
public bool IsPressed { get; set; }
}
private enum PointerEventType
{
Entered,
Exited,
Pressed,
Moved,
Released
}
private static MethodInfo? _sendTappedMethod;
private static readonly Dictionary<View, (DateTime lastTap, int tapCount)> _tapTracking = new Dictionary<View, (DateTime, int)>();
private static readonly Dictionary<View, GestureTrackingState> _gestureState = new Dictionary<View, GestureTrackingState>();
private const double SwipeMinDistance = 50.0;
private const double SwipeMaxTime = 500.0;
private const double SwipeDirectionThreshold = 0.5;
private const double PanMinDistance = 10.0;
public static bool ProcessTap(View? view, double x, double y)
{
if (view == null)
{
return false;
}
View val = view;
while (val != null)
{
IList<IGestureRecognizer> gestureRecognizers = val.GestureRecognizers;
if (gestureRecognizers != null && gestureRecognizers.Count > 0 && ProcessTapOnView(val, x, y))
{
return true;
}
Element parent = ((Element)val).Parent;
val = (View)(object)((parent is View) ? parent : null);
}
return false;
}
private static bool ProcessTapOnView(View view, double x, double y)
{
//IL_031f: Unknown result type (might be due to invalid IL or missing references)
//IL_0326: Expected O, but got Unknown
//IL_03cb: Unknown result type (might be due to invalid IL or missing references)
//IL_03d2: Expected O, but got Unknown
//IL_026e: Unknown result type (might be due to invalid IL or missing references)
//IL_0275: Expected O, but got Unknown
IList<IGestureRecognizer> gestureRecognizers = view.GestureRecognizers;
if (gestureRecognizers == null || gestureRecognizers.Count == 0)
{
return false;
}
bool result = false;
foreach (IGestureRecognizer item in gestureRecognizers)
{
TapGestureRecognizer val = (TapGestureRecognizer)(object)((item is TapGestureRecognizer) ? item : null);
if (val == null)
{
continue;
}
Console.WriteLine($"[GestureManager] Processing TapGestureRecognizer on {((object)view).GetType().Name}, CommandParameter={val.CommandParameter}, NumberOfTapsRequired={val.NumberOfTapsRequired}");
int numberOfTapsRequired = val.NumberOfTapsRequired;
if (numberOfTapsRequired > 1)
{
DateTime utcNow = DateTime.UtcNow;
if (!_tapTracking.TryGetValue(view, out (DateTime, int) value))
{
_tapTracking[view] = (utcNow, 1);
Console.WriteLine($"[GestureManager] First tap 1/{numberOfTapsRequired}");
continue;
}
if (!((utcNow - value.Item1).TotalMilliseconds < 300.0))
{
_tapTracking[view] = (utcNow, 1);
Console.WriteLine($"[GestureManager] Tap timeout, reset to 1/{numberOfTapsRequired}");
continue;
}
int num = value.Item2 + 1;
if (num < numberOfTapsRequired)
{
_tapTracking[view] = (utcNow, num);
Console.WriteLine($"[GestureManager] Tap {num}/{numberOfTapsRequired}, waiting for more taps");
continue;
}
_tapTracking.Remove(view);
}
bool flag = false;
try
{
if ((object)_sendTappedMethod == null)
{
_sendTappedMethod = typeof(TapGestureRecognizer).GetMethod("SendTapped", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
}
if (_sendTappedMethod != null)
{
Console.WriteLine($"[GestureManager] Found SendTapped method with {_sendTappedMethod.GetParameters().Length} params");
TappedEventArgs e = new TappedEventArgs(val.CommandParameter);
_sendTappedMethod.Invoke(val, new object[2] { view, e });
Console.WriteLine("[GestureManager] SendTapped invoked successfully");
flag = true;
}
}
catch (Exception ex)
{
Console.WriteLine("[GestureManager] SendTapped failed: " + ex.Message);
}
if (!flag)
{
try
{
FieldInfo fieldInfo = typeof(TapGestureRecognizer).GetField("Tapped", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? typeof(TapGestureRecognizer).GetField("_tapped", BindingFlags.Instance | BindingFlags.NonPublic);
if (fieldInfo != null && fieldInfo.GetValue(val) is EventHandler<TappedEventArgs> eventHandler)
{
Console.WriteLine("[GestureManager] Invoking Tapped event directly");
TappedEventArgs e2 = new TappedEventArgs(val.CommandParameter);
eventHandler(val, e2);
flag = true;
}
}
catch (Exception ex2)
{
Console.WriteLine("[GestureManager] Direct event invoke failed: " + ex2.Message);
}
}
if (!flag)
{
try
{
string[] array = new string[3] { "TappedEvent", "_TappedHandler", "<Tapped>k__BackingField" };
foreach (string text in array)
{
FieldInfo field = typeof(TapGestureRecognizer).GetField(text, BindingFlags.Instance | BindingFlags.NonPublic);
if (field != null)
{
Console.WriteLine("[GestureManager] Found field: " + text);
if (field.GetValue(val) is EventHandler<TappedEventArgs> eventHandler2)
{
TappedEventArgs e3 = new TappedEventArgs(val.CommandParameter);
eventHandler2(val, e3);
Console.WriteLine("[GestureManager] Event fired via " + text);
flag = true;
break;
}
}
}
}
catch (Exception ex3)
{
Console.WriteLine("[GestureManager] Backing field approach failed: " + ex3.Message);
}
}
if (!flag)
{
Console.WriteLine("[GestureManager] Could not fire event, dumping type info...");
MethodInfo[] methods = typeof(TapGestureRecognizer).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (MethodInfo methodInfo in methods)
{
if (methodInfo.Name.Contains("Tap", StringComparison.OrdinalIgnoreCase) || methodInfo.Name.Contains("Send", StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine($"[GestureManager] Method: {methodInfo.Name}({string.Join(", ", from p in methodInfo.GetParameters()
select p.ParameterType.Name)})");
}
}
}
ICommand command = val.Command;
if (command != null && command.CanExecute(val.CommandParameter))
{
Console.WriteLine("[GestureManager] Executing Command");
val.Command.Execute(val.CommandParameter);
}
result = true;
}
return result;
}
public static bool HasGestureRecognizers(View? view)
{
if (view == null)
{
return false;
}
return view.GestureRecognizers?.Count > 0;
}
public static bool HasTapGestureRecognizer(View? view)
{
if (((view != null) ? view.GestureRecognizers : null) == null)
{
return false;
}
foreach (IGestureRecognizer gestureRecognizer in view.GestureRecognizers)
{
if (gestureRecognizer is TapGestureRecognizer)
{
return true;
}
}
return false;
}
public static void ProcessPointerDown(View? view, double x, double y)
{
if (view != null)
{
_gestureState[view] = new GestureTrackingState
{
StartX = x,
StartY = y,
CurrentX = x,
CurrentY = y,
StartTime = DateTime.UtcNow,
IsPanning = false,
IsPressed = true
};
ProcessPointerEvent(view, x, y, PointerEventType.Pressed);
}
}
public static void ProcessPointerMove(View? view, double x, double y)
{
if (view == null)
{
return;
}
if (!_gestureState.TryGetValue(view, out GestureTrackingState value))
{
ProcessPointerEvent(view, x, y, PointerEventType.Moved);
return;
}
value.CurrentX = x;
value.CurrentY = y;
if (!value.IsPressed)
{
ProcessPointerEvent(view, x, y, PointerEventType.Moved);
return;
}
double num = x - value.StartX;
double num2 = y - value.StartY;
if (Math.Sqrt(num * num + num2 * num2) >= 10.0)
{
ProcessPanGesture(view, num, num2, (GestureStatus)(value.IsPanning ? 1 : 0));
value.IsPanning = true;
}
ProcessPointerEvent(view, x, y, PointerEventType.Moved);
}
public static void ProcessPointerUp(View? view, double x, double y)
{
if (view == null)
{
return;
}
if (_gestureState.TryGetValue(view, out GestureTrackingState value))
{
value.CurrentX = x;
value.CurrentY = y;
double num = x - value.StartX;
double num2 = y - value.StartY;
double num3 = Math.Sqrt(num * num + num2 * num2);
double totalMilliseconds = (DateTime.UtcNow - value.StartTime).TotalMilliseconds;
if (num3 >= 50.0 && totalMilliseconds <= 500.0)
{
SwipeDirection swipeDirection = DetermineSwipeDirection(num, num2);
if (swipeDirection != SwipeDirection.Right)
{
ProcessSwipeGesture(view, swipeDirection);
}
else if (Math.Abs(num) > Math.Abs(num2) * 0.5)
{
ProcessSwipeGesture(view, (!(num > 0.0)) ? SwipeDirection.Left : SwipeDirection.Right);
}
}
if (value.IsPanning)
{
ProcessPanGesture(view, num, num2, (GestureStatus)2);
}
else if (num3 < 15.0 && totalMilliseconds < 500.0)
{
Console.WriteLine($"[GestureManager] Detected tap on {((object)view).GetType().Name} (distance={num3:F1}, elapsed={totalMilliseconds:F0}ms)");
ProcessTap(view, x, y);
}
_gestureState.Remove(view);
}
ProcessPointerEvent(view, x, y, PointerEventType.Released);
}
public static void ProcessPointerEntered(View? view, double x, double y)
{
if (view != null)
{
ProcessPointerEvent(view, x, y, PointerEventType.Entered);
}
}
public static void ProcessPointerExited(View? view, double x, double y)
{
if (view != null)
{
ProcessPointerEvent(view, x, y, PointerEventType.Exited);
}
}
private static SwipeDirection DetermineSwipeDirection(double deltaX, double deltaY)
{
double num = Math.Abs(deltaX);
double num2 = Math.Abs(deltaY);
if (num > num2 * 0.5)
{
if (!(deltaX > 0.0))
{
return SwipeDirection.Left;
}
return SwipeDirection.Right;
}
if (num2 > num * 0.5)
{
if (!(deltaY > 0.0))
{
return SwipeDirection.Up;
}
return SwipeDirection.Down;
}
if (!(deltaX > 0.0))
{
return SwipeDirection.Left;
}
return SwipeDirection.Right;
}
private static void ProcessSwipeGesture(View view, SwipeDirection direction)
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
IList<IGestureRecognizer> gestureRecognizers = view.GestureRecognizers;
if (gestureRecognizers == null)
{
return;
}
foreach (IGestureRecognizer item in gestureRecognizers)
{
SwipeGestureRecognizer val = (SwipeGestureRecognizer)(object)((item is SwipeGestureRecognizer) ? item : null);
if (val == null || !((Enum)val.Direction).HasFlag((Enum)direction))
{
continue;
}
Console.WriteLine($"[GestureManager] Swipe detected: {direction}");
try
{
MethodInfo method = typeof(SwipeGestureRecognizer).GetMethod("SendSwiped", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (method != null)
{
method.Invoke(val, new object[2] { view, direction });
Console.WriteLine("[GestureManager] SendSwiped invoked successfully");
}
}
catch (Exception ex)
{
Console.WriteLine("[GestureManager] SendSwiped failed: " + ex.Message);
}
ICommand command = val.Command;
if (command != null && command.CanExecute(val.CommandParameter))
{
val.Command.Execute(val.CommandParameter);
}
}
}
private static void ProcessPanGesture(View view, double totalX, double totalY, GestureStatus status)
{
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Expected I4, but got Unknown
IList<IGestureRecognizer> gestureRecognizers = view.GestureRecognizers;
if (gestureRecognizers == null)
{
return;
}
foreach (IGestureRecognizer item in gestureRecognizers)
{
PanGestureRecognizer val = (PanGestureRecognizer)(object)((item is PanGestureRecognizer) ? item : null);
if (val == null)
{
continue;
}
Console.WriteLine($"[GestureManager] Pan gesture: status={status}, totalX={totalX:F1}, totalY={totalY:F1}");
try
{
MethodInfo method = typeof(PanGestureRecognizer).GetMethod("SendPan", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (method != null)
{
method.Invoke(val, new object[4]
{
view,
totalX,
totalY,
(int)status
});
}
}
catch (Exception ex)
{
Console.WriteLine("[GestureManager] SendPan failed: " + ex.Message);
}
}
}
private static void ProcessPointerEvent(View view, double x, double y, PointerEventType eventType)
{
IList<IGestureRecognizer> gestureRecognizers = view.GestureRecognizers;
if (gestureRecognizers == null)
{
return;
}
foreach (IGestureRecognizer item in gestureRecognizers)
{
PointerGestureRecognizer val = (PointerGestureRecognizer)(object)((item is PointerGestureRecognizer) ? item : null);
if (val == null)
{
continue;
}
try
{
string text = eventType switch
{
PointerEventType.Entered => "SendPointerEntered",
PointerEventType.Exited => "SendPointerExited",
PointerEventType.Pressed => "SendPointerPressed",
PointerEventType.Moved => "SendPointerMoved",
PointerEventType.Released => "SendPointerReleased",
_ => null,
};
if (text != null)
{
MethodInfo method = typeof(PointerGestureRecognizer).GetMethod(text, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (method != null)
{
object obj = CreatePointerEventArgs(view, x, y);
method.Invoke(val, new object[2] { view, obj });
}
}
}
catch (Exception ex)
{
Console.WriteLine("[GestureManager] Pointer event failed: " + ex.Message);
}
}
}
private static object CreatePointerEventArgs(View view, double x, double y)
{
try
{
Type type = typeof(PointerGestureRecognizer).Assembly.GetType("Microsoft.Maui.Controls.PointerEventArgs");
if (type != null)
{
ConstructorInfo constructorInfo = type.GetConstructors().FirstOrDefault();
if (constructorInfo != null)
{
return constructorInfo.Invoke(new object[0]);
}
}
}
catch
{
}
return null;
}
public static bool HasSwipeGestureRecognizer(View? view)
{
if (((view != null) ? view.GestureRecognizers : null) == null)
{
return false;
}
foreach (IGestureRecognizer gestureRecognizer in view.GestureRecognizers)
{
if (gestureRecognizer is SwipeGestureRecognizer)
{
return true;
}
}
return false;
}
public static bool HasPanGestureRecognizer(View? view)
{
if (((view != null) ? view.GestureRecognizers : null) == null)
{
return false;
}
foreach (IGestureRecognizer gestureRecognizer in view.GestureRecognizers)
{
if (gestureRecognizer is PanGestureRecognizer)
{
return true;
}
}
return false;
}
public static bool HasPointerGestureRecognizer(View? view)
{
if (((view != null) ? view.GestureRecognizers : null) == null)
{
return false;
}
foreach (IGestureRecognizer gestureRecognizer in view.GestureRecognizers)
{
if (gestureRecognizer is PointerGestureRecognizer)
{
return true;
}
}
return false;
}
}

View File

@@ -1,57 +1,62 @@
using Microsoft.Maui.Graphics;
// 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.Handlers;
using Microsoft.Maui.Graphics;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class GraphicsViewHandler : ViewHandler<IGraphicsView, SkiaGraphicsView>
/// <summary>
/// Handler for GraphicsView on Linux using Skia rendering.
/// Maps IGraphicsView interface to SkiaGraphicsView platform view.
/// IGraphicsView has: Drawable, Invalidate()
/// </summary>
public partial class GraphicsViewHandler : ViewHandler<IGraphicsView, SkiaGraphicsView>
{
public static IPropertyMapper<IGraphicsView, GraphicsViewHandler> Mapper = (IPropertyMapper<IGraphicsView, GraphicsViewHandler>)(object)new PropertyMapper<IGraphicsView, GraphicsViewHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Drawable"] = MapDrawable,
["Background"] = MapBackground
};
public static IPropertyMapper<IGraphicsView, GraphicsViewHandler> Mapper = new PropertyMapper<IGraphicsView, GraphicsViewHandler>(ViewHandler.ViewMapper)
{
[nameof(IGraphicsView.Drawable)] = MapDrawable,
[nameof(IView.Background)] = MapBackground,
};
public static CommandMapper<IGraphicsView, GraphicsViewHandler> CommandMapper = new CommandMapper<IGraphicsView, GraphicsViewHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper) { ["Invalidate"] = MapInvalidate };
public static CommandMapper<IGraphicsView, GraphicsViewHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
[nameof(IGraphicsView.Invalidate)] = MapInvalidate,
};
public GraphicsViewHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public GraphicsViewHandler() : base(Mapper, CommandMapper)
{
}
public GraphicsViewHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
public GraphicsViewHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override SkiaGraphicsView CreatePlatformView()
{
return new SkiaGraphicsView();
}
protected override SkiaGraphicsView CreatePlatformView()
{
return new SkiaGraphicsView();
}
public static void MapDrawable(GraphicsViewHandler handler, IGraphicsView graphicsView)
{
if (((ViewHandler<IGraphicsView, SkiaGraphicsView>)(object)handler).PlatformView != null)
{
((ViewHandler<IGraphicsView, SkiaGraphicsView>)(object)handler).PlatformView.Drawable = graphicsView.Drawable;
}
}
public static void MapDrawable(GraphicsViewHandler handler, IGraphicsView graphicsView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Drawable = graphicsView.Drawable;
}
public static void MapBackground(GraphicsViewHandler handler, IGraphicsView graphicsView)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IGraphicsView, SkiaGraphicsView>)(object)handler).PlatformView != null)
{
Paint background = ((IView)graphicsView).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<IGraphicsView, SkiaGraphicsView>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
public static void MapBackground(GraphicsViewHandler handler, IGraphicsView graphicsView)
{
if (handler.PlatformView is null) return;
public static void MapInvalidate(GraphicsViewHandler handler, IGraphicsView graphicsView, object? args)
{
((ViewHandler<IGraphicsView, SkiaGraphicsView>)(object)handler).PlatformView?.Invalidate();
}
if (graphicsView.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapInvalidate(GraphicsViewHandler handler, IGraphicsView graphicsView, object? args)
{
handler.PlatformView?.Invalidate();
}
}

View File

@@ -1,170 +0,0 @@
using System;
using System.Collections.Generic;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform.Linux.Hosting;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class GridHandler : LayoutHandler
{
public new static IPropertyMapper<IGridLayout, GridHandler> Mapper = (IPropertyMapper<IGridLayout, GridHandler>)(object)new PropertyMapper<IGridLayout, GridHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)LayoutHandler.Mapper })
{
["RowSpacing"] = MapRowSpacing,
["ColumnSpacing"] = MapColumnSpacing,
["RowDefinitions"] = MapRowDefinitions,
["ColumnDefinitions"] = MapColumnDefinitions
};
public GridHandler()
: base((IPropertyMapper?)(object)Mapper)
{
}
protected override SkiaLayoutView CreatePlatformView()
{
return new SkiaGrid();
}
protected override void ConnectHandler(SkiaLayoutView platformView)
{
//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
try
{
ILayout virtualView = ((ViewHandler<ILayout, SkiaLayoutView>)(object)this).VirtualView;
IGridLayout val = (IGridLayout)(object)((virtualView is IGridLayout) ? virtualView : null);
if (val == null || ((ElementHandler)this).MauiContext == null || !(platformView is SkiaGrid skiaGrid))
{
return;
}
Console.WriteLine($"[GridHandler] ConnectHandler: {((ICollection<IView>)val).Count} children, {val.RowDefinitions.Count} rows, {val.ColumnDefinitions.Count} cols");
ILayout virtualView2 = ((ViewHandler<ILayout, SkiaLayoutView>)(object)this).VirtualView;
VisualElement val2 = (VisualElement)(object)((virtualView2 is VisualElement) ? virtualView2 : null);
if (val2 != null && val2.BackgroundColor != null)
{
platformView.BackgroundColor = val2.BackgroundColor.ToSKColor();
}
IPadding virtualView3 = (IPadding)(object)((ViewHandler<ILayout, SkiaLayoutView>)(object)this).VirtualView;
if (virtualView3 != null)
{
Thickness padding = virtualView3.Padding;
platformView.Padding = new SKRect((float)((Thickness)(ref padding)).Left, (float)((Thickness)(ref padding)).Top, (float)((Thickness)(ref padding)).Right, (float)((Thickness)(ref padding)).Bottom);
Console.WriteLine($"[GridHandler] Applied Padding: L={((Thickness)(ref padding)).Left}, T={((Thickness)(ref padding)).Top}, R={((Thickness)(ref padding)).Right}, B={((Thickness)(ref padding)).Bottom}");
}
MapRowDefinitions(this, val);
MapColumnDefinitions(this, val);
for (int i = 0; i < ((ICollection<IView>)val).Count; i++)
{
IView val3 = ((IList<IView>)val)[i];
if (val3 != null)
{
Console.WriteLine($"[GridHandler] Processing child {i}: {((object)val3).GetType().Name}");
if (val3.Handler == null)
{
val3.Handler = val3.ToViewHandler(((ElementHandler)this).MauiContext);
}
int num = 0;
int num2 = 0;
int rowSpan = 1;
int columnSpan = 1;
View val4 = (View)(object)((val3 is View) ? val3 : null);
if (val4 != null)
{
num = Grid.GetRow((BindableObject)(object)val4);
num2 = Grid.GetColumn((BindableObject)(object)val4);
rowSpan = Grid.GetRowSpan((BindableObject)(object)val4);
columnSpan = Grid.GetColumnSpan((BindableObject)(object)val4);
}
Console.WriteLine($"[GridHandler] Child {i} at row={num}, col={num2}, handler={((object)val3.Handler)?.GetType().Name}");
IViewHandler handler = val3.Handler;
if (((handler != null) ? ((IElementHandler)handler).PlatformView : null) is SkiaView child)
{
skiaGrid.AddChild(child, num, num2, rowSpan, columnSpan);
Console.WriteLine($"[GridHandler] Added child {i} to grid");
}
}
}
Console.WriteLine("[GridHandler] ConnectHandler complete");
}
catch (Exception ex)
{
Console.WriteLine("[GridHandler] EXCEPTION in ConnectHandler: " + ex.GetType().Name + ": " + ex.Message);
Console.WriteLine("[GridHandler] Stack trace: " + ex.StackTrace);
throw;
}
}
public static void MapRowSpacing(GridHandler handler, IGridLayout layout)
{
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView is SkiaGrid skiaGrid)
{
skiaGrid.RowSpacing = (float)layout.RowSpacing;
}
}
public static void MapColumnSpacing(GridHandler handler, IGridLayout layout)
{
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView is SkiaGrid skiaGrid)
{
skiaGrid.ColumnSpacing = (float)layout.ColumnSpacing;
}
}
public static void MapRowDefinitions(GridHandler handler, IGridLayout layout)
{
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
if (!(((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView is SkiaGrid skiaGrid))
{
return;
}
skiaGrid.RowDefinitions.Clear();
foreach (IGridRowDefinition rowDefinition in layout.RowDefinitions)
{
GridLength height = rowDefinition.Height;
if (((GridLength)(ref height)).IsAbsolute)
{
skiaGrid.RowDefinitions.Add(new GridLength((float)((GridLength)(ref height)).Value));
}
else if (((GridLength)(ref height)).IsAuto)
{
skiaGrid.RowDefinitions.Add(GridLength.Auto);
}
else
{
skiaGrid.RowDefinitions.Add(new GridLength((float)((GridLength)(ref height)).Value, GridUnitType.Star));
}
}
}
public static void MapColumnDefinitions(GridHandler handler, IGridLayout layout)
{
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
if (!(((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView is SkiaGrid skiaGrid))
{
return;
}
skiaGrid.ColumnDefinitions.Clear();
foreach (IGridColumnDefinition columnDefinition in layout.ColumnDefinitions)
{
GridLength width = columnDefinition.Width;
if (((GridLength)(ref width)).IsAbsolute)
{
skiaGrid.ColumnDefinitions.Add(new GridLength((float)((GridLength)(ref width)).Value));
}
else if (((GridLength)(ref width)).IsAuto)
{
skiaGrid.ColumnDefinitions.Add(GridLength.Auto);
}
else
{
skiaGrid.ColumnDefinitions.Add(new GridLength((float)((GridLength)(ref width)).Value, GridUnitType.Star));
}
}
}
}

View File

@@ -1,240 +0,0 @@
using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform.Linux.Native;
using Microsoft.Maui.Platform.Linux.Services;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class GtkWebViewHandler : ViewHandler<IWebView, GtkWebViewProxy>
{
private GtkWebViewPlatformView? _platformWebView;
private bool _isRegisteredWithHost;
private SKRect _lastBounds;
public static IPropertyMapper<IWebView, GtkWebViewHandler> Mapper = (IPropertyMapper<IWebView, GtkWebViewHandler>)(object)new PropertyMapper<IWebView, GtkWebViewHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper }) { ["Source"] = MapSource };
public static CommandMapper<IWebView, GtkWebViewHandler> CommandMapper = new CommandMapper<IWebView, GtkWebViewHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper)
{
["GoBack"] = MapGoBack,
["GoForward"] = MapGoForward,
["Reload"] = MapReload
};
public GtkWebViewHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public GtkWebViewHandler(IPropertyMapper? mapper = null, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override GtkWebViewProxy CreatePlatformView()
{
_platformWebView = new GtkWebViewPlatformView();
return new GtkWebViewProxy(this, _platformWebView);
}
protected override void ConnectHandler(GtkWebViewProxy platformView)
{
base.ConnectHandler(platformView);
if (_platformWebView != null)
{
_platformWebView.NavigationStarted += OnNavigationStarted;
_platformWebView.NavigationCompleted += OnNavigationCompleted;
}
Console.WriteLine("[GtkWebViewHandler] ConnectHandler - WebView ready");
}
protected override void DisconnectHandler(GtkWebViewProxy platformView)
{
if (_platformWebView != null)
{
_platformWebView.NavigationStarted -= OnNavigationStarted;
_platformWebView.NavigationCompleted -= OnNavigationCompleted;
UnregisterFromHost();
_platformWebView.Dispose();
_platformWebView = null;
}
base.DisconnectHandler(platformView);
}
private void OnNavigationStarted(object? sender, string uri)
{
Console.WriteLine("[GtkWebViewHandler] Navigation started: " + uri);
try
{
GLibNative.IdleAdd(delegate
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Expected O, but got Unknown
try
{
IWebView virtualView = base.VirtualView;
IWebViewController val = (IWebViewController)(object)((virtualView is IWebViewController) ? virtualView : null);
if (val != null)
{
WebNavigatingEventArgs e = new WebNavigatingEventArgs((WebNavigationEvent)3, (WebViewSource)null, uri);
val.SendNavigating(e);
Console.WriteLine("[GtkWebViewHandler] Sent Navigating event to VirtualView");
}
}
catch (Exception ex2)
{
Console.WriteLine("[GtkWebViewHandler] Error in SendNavigating: " + ex2.Message);
}
return false;
});
}
catch (Exception ex)
{
Console.WriteLine("[GtkWebViewHandler] Error dispatching navigation started: " + ex.Message);
}
}
private void OnNavigationCompleted(object? sender, (string Url, bool Success) e)
{
Console.WriteLine($"[GtkWebViewHandler] Navigation completed: {e.Url} (Success: {e.Success})");
try
{
GLibNative.IdleAdd(delegate
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Expected O, but got Unknown
try
{
IWebView virtualView = base.VirtualView;
IWebViewController val = (IWebViewController)(object)((virtualView is IWebViewController) ? virtualView : null);
if (val != null)
{
WebNavigationResult val2 = (WebNavigationResult)(e.Success ? 1 : 4);
WebNavigatedEventArgs e2 = new WebNavigatedEventArgs((WebNavigationEvent)3, (WebViewSource)null, e.Url, val2);
val.SendNavigated(e2);
bool flag = _platformWebView?.CanGoBack() ?? false;
bool flag2 = _platformWebView?.CanGoForward() ?? false;
val.CanGoBack = flag;
val.CanGoForward = flag2;
Console.WriteLine($"[GtkWebViewHandler] Sent Navigated, CanGoBack={flag}, CanGoForward={flag2}");
}
}
catch (Exception ex2)
{
Console.WriteLine("[GtkWebViewHandler] Error in SendNavigated: " + ex2.Message);
}
return false;
});
}
catch (Exception ex)
{
Console.WriteLine("[GtkWebViewHandler] Error dispatching navigation completed: " + ex.Message);
}
}
internal void RegisterWithHost(SKRect bounds)
{
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_011c: Unknown result type (might be due to invalid IL or missing references)
//IL_011e: Unknown result type (might be due to invalid IL or missing references)
//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
if (_platformWebView == null)
{
return;
}
GtkHostService instance = GtkHostService.Instance;
if (instance.HostWindow == null || instance.WebViewManager == null)
{
Console.WriteLine("[GtkWebViewHandler] Warning: GTK host not initialized, cannot register WebView");
return;
}
int num = (int)((SKRect)(ref bounds)).Left;
int num2 = (int)((SKRect)(ref bounds)).Top;
int num3 = (int)((SKRect)(ref bounds)).Width;
int num4 = (int)((SKRect)(ref bounds)).Height;
if (num3 <= 0 || num4 <= 0)
{
Console.WriteLine($"[GtkWebViewHandler] Skipping invalid bounds: {bounds}");
return;
}
if (!_isRegisteredWithHost)
{
instance.HostWindow.AddWebView(_platformWebView.Widget, num, num2, num3, num4);
_isRegisteredWithHost = true;
Console.WriteLine($"[GtkWebViewHandler] Registered WebView at ({num}, {num2}) size {num3}x{num4}");
}
else if (bounds != _lastBounds)
{
instance.HostWindow.MoveResizeWebView(_platformWebView.Widget, num, num2, num3, num4);
Console.WriteLine($"[GtkWebViewHandler] Updated WebView to ({num}, {num2}) size {num3}x{num4}");
}
_lastBounds = bounds;
}
private void UnregisterFromHost()
{
if (_isRegisteredWithHost && _platformWebView != null)
{
GtkHostService instance = GtkHostService.Instance;
if (instance.HostWindow != null)
{
instance.HostWindow.RemoveWebView(_platformWebView.Widget);
Console.WriteLine("[GtkWebViewHandler] Unregistered WebView from host");
}
_isRegisteredWithHost = false;
}
}
public static void MapSource(GtkWebViewHandler handler, IWebView webView)
{
if (handler._platformWebView == null)
{
return;
}
IWebViewSource source = webView.Source;
Console.WriteLine("[GtkWebViewHandler] MapSource: " + (((object)source)?.GetType().Name ?? "null"));
UrlWebViewSource val = (UrlWebViewSource)(object)((source is UrlWebViewSource) ? source : null);
if (val != null)
{
string url = val.Url;
if (!string.IsNullOrEmpty(url))
{
handler._platformWebView.Navigate(url);
}
return;
}
HtmlWebViewSource val2 = (HtmlWebViewSource)(object)((source is HtmlWebViewSource) ? source : null);
if (val2 != null)
{
string html = val2.Html;
if (!string.IsNullOrEmpty(html))
{
handler._platformWebView.LoadHtml(html, val2.BaseUrl);
}
}
}
public static void MapGoBack(GtkWebViewHandler handler, IWebView webView, object? args)
{
Console.WriteLine($"[GtkWebViewHandler] MapGoBack called, CanGoBack={handler._platformWebView?.CanGoBack()}");
handler._platformWebView?.GoBack();
}
public static void MapGoForward(GtkWebViewHandler handler, IWebView webView, object? args)
{
Console.WriteLine($"[GtkWebViewHandler] MapGoForward called, CanGoForward={handler._platformWebView?.CanGoForward()}");
handler._platformWebView?.GoForward();
}
public static void MapReload(GtkWebViewHandler handler, IWebView webView, object? args)
{
Console.WriteLine("[GtkWebViewHandler] MapReload called");
handler._platformWebView?.Reload();
}
}

View File

@@ -1,61 +0,0 @@
using System.Collections.Generic;
using Microsoft.Maui.Platform.Linux.Window;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public sealed class GtkWebViewManager
{
private readonly GtkHostWindow _host;
private readonly Dictionary<object, GtkWebViewPlatformView> _webViews = new Dictionary<object, GtkWebViewPlatformView>();
public GtkWebViewManager(GtkHostWindow host)
{
_host = host;
}
public GtkWebViewPlatformView CreateWebView(object key, int x, int y, int width, int height)
{
GtkWebViewPlatformView gtkWebViewPlatformView = new GtkWebViewPlatformView();
_webViews[key] = gtkWebViewPlatformView;
_host.AddWebView(gtkWebViewPlatformView.Widget, x, y, width, height);
return gtkWebViewPlatformView;
}
public void UpdateLayout(object key, int x, int y, int width, int height)
{
if (_webViews.TryGetValue(key, out GtkWebViewPlatformView value))
{
_host.MoveResizeWebView(value.Widget, x, y, width, height);
}
}
public GtkWebViewPlatformView? GetWebView(object key)
{
if (!_webViews.TryGetValue(key, out GtkWebViewPlatformView value))
{
return null;
}
return value;
}
public void RemoveWebView(object key)
{
if (_webViews.TryGetValue(key, out GtkWebViewPlatformView value))
{
_host.RemoveWebView(value.Widget);
value.Dispose();
_webViews.Remove(key);
}
}
public void Clear()
{
foreach (KeyValuePair<object, GtkWebViewPlatformView> webView in _webViews)
{
_host.RemoveWebView(webView.Value.Widget);
webView.Value.Dispose();
}
_webViews.Clear();
}
}

View File

@@ -1,183 +0,0 @@
using System;
using Microsoft.Maui.Platform.Linux.Native;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public sealed class GtkWebViewPlatformView : IDisposable
{
private IntPtr _widget;
private bool _disposed;
private string? _currentUri;
private ulong _loadChangedSignalId;
private WebKitNative.LoadChangedCallback? _loadChangedCallback;
public IntPtr Widget => _widget;
public string? CurrentUri => _currentUri;
public event EventHandler<string>? NavigationStarted;
public event EventHandler<(string Url, bool Success)>? NavigationCompleted;
public event EventHandler<string>? TitleChanged;
public GtkWebViewPlatformView()
{
if (!WebKitNative.Initialize())
{
throw new InvalidOperationException("Failed to initialize WebKitGTK. Is libwebkit2gtk-4.x installed?");
}
_widget = WebKitNative.WebViewNew();
if (_widget == IntPtr.Zero)
{
throw new InvalidOperationException("Failed to create WebKitWebView widget");
}
WebKitNative.ConfigureSettings(_widget);
_loadChangedCallback = OnLoadChanged;
_loadChangedSignalId = WebKitNative.ConnectLoadChanged(_widget, _loadChangedCallback);
Console.WriteLine("[GtkWebViewPlatformView] Created WebKitWebView widget");
}
private void OnLoadChanged(IntPtr webView, int loadEvent, IntPtr userData)
{
try
{
string text = WebKitNative.GetUri(webView) ?? _currentUri ?? "";
switch ((WebKitNative.WebKitLoadEvent)loadEvent)
{
case WebKitNative.WebKitLoadEvent.Started:
Console.WriteLine("[GtkWebViewPlatformView] Load started: " + text);
this.NavigationStarted?.Invoke(this, text);
break;
case WebKitNative.WebKitLoadEvent.Finished:
_currentUri = text;
Console.WriteLine("[GtkWebViewPlatformView] Load finished: " + text);
this.NavigationCompleted?.Invoke(this, (text, true));
break;
case WebKitNative.WebKitLoadEvent.Committed:
_currentUri = text;
Console.WriteLine("[GtkWebViewPlatformView] Load committed: " + text);
break;
case WebKitNative.WebKitLoadEvent.Redirected:
break;
}
}
catch (Exception ex)
{
Console.WriteLine("[GtkWebViewPlatformView] Error in OnLoadChanged: " + ex.Message);
Console.WriteLine("[GtkWebViewPlatformView] Stack trace: " + ex.StackTrace);
}
}
public void Navigate(string uri)
{
if (_widget != IntPtr.Zero)
{
WebKitNative.LoadUri(_widget, uri);
Console.WriteLine("[GtkWebViewPlatformView] Navigate to: " + uri);
}
}
public void LoadHtml(string html, string? baseUri = null)
{
if (_widget != IntPtr.Zero)
{
WebKitNative.LoadHtml(_widget, html, baseUri);
Console.WriteLine("[GtkWebViewPlatformView] Load HTML content");
}
}
public void GoBack()
{
if (_widget != IntPtr.Zero)
{
WebKitNative.GoBack(_widget);
}
}
public void GoForward()
{
if (_widget != IntPtr.Zero)
{
WebKitNative.GoForward(_widget);
}
}
public bool CanGoBack()
{
if (_widget == IntPtr.Zero)
{
return false;
}
return WebKitNative.CanGoBack(_widget);
}
public bool CanGoForward()
{
if (_widget == IntPtr.Zero)
{
return false;
}
return WebKitNative.CanGoForward(_widget);
}
public void Reload()
{
if (_widget != IntPtr.Zero)
{
WebKitNative.Reload(_widget);
}
}
public void Stop()
{
if (_widget != IntPtr.Zero)
{
WebKitNative.StopLoading(_widget);
}
}
public string? GetTitle()
{
if (_widget == IntPtr.Zero)
{
return null;
}
return WebKitNative.GetTitle(_widget);
}
public string? GetUri()
{
if (_widget == IntPtr.Zero)
{
return null;
}
return WebKitNative.GetUri(_widget);
}
public void SetJavascriptEnabled(bool enabled)
{
if (_widget != IntPtr.Zero)
{
WebKitNative.SetJavascriptEnabled(_widget, enabled);
}
}
public void Dispose()
{
if (!_disposed)
{
_disposed = true;
if (_widget != IntPtr.Zero)
{
WebKitNative.DisconnectLoadChanged(_widget);
}
_widget = IntPtr.Zero;
_loadChangedCallback = null;
}
}
}

View File

@@ -1,104 +0,0 @@
using System;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class GtkWebViewProxy : SkiaView
{
private readonly GtkWebViewHandler _handler;
private readonly GtkWebViewPlatformView _platformView;
public GtkWebViewPlatformView PlatformView => _platformView;
public bool CanGoBack => _platformView.CanGoBack();
public bool CanGoForward => _platformView.CanGoForward();
public GtkWebViewProxy(GtkWebViewHandler handler, GtkWebViewPlatformView platformView)
{
_handler = handler;
_platformView = platformView;
}
public override void Arrange(SKRect bounds)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
base.Arrange(bounds);
SKRect bounds2 = TransformToWindow(bounds);
_handler.RegisterWithHost(bounds2);
}
private SKRect TransformToWindow(SKRect localBounds)
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
float num = ((SKRect)(ref localBounds)).Left;
float num2 = ((SKRect)(ref localBounds)).Top;
for (SkiaView parent = base.Parent; parent != null; parent = parent.Parent)
{
float num3 = num;
SKRect bounds = parent.Bounds;
num = num3 + ((SKRect)(ref bounds)).Left;
float num4 = num2;
bounds = parent.Bounds;
num2 = num4 + ((SKRect)(ref bounds)).Top;
}
return new SKRect(num, num2, num + ((SKRect)(ref localBounds)).Width, num2 + ((SKRect)(ref localBounds)).Height);
}
public override void Draw(SKCanvas canvas)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Expected O, but got Unknown
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
SKPaint val = new SKPaint
{
Color = new SKColor((byte)0, (byte)0, (byte)0, (byte)0),
Style = (SKPaintStyle)0
};
try
{
canvas.DrawRect(base.Bounds, val);
}
finally
{
((IDisposable)val)?.Dispose();
}
}
public void Navigate(string url)
{
_platformView.Navigate(url);
}
public void LoadHtml(string html, string? baseUrl = null)
{
_platformView.LoadHtml(html, baseUrl);
}
public void GoBack()
{
_platformView.GoBack();
}
public void GoForward()
{
_platformView.GoForward();
}
public void Reload()
{
_platformView.Reload();
}
}

View File

@@ -1,275 +1,233 @@
using System;
using System.IO;
using System.Threading;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
// 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.Handlers;
using Microsoft.Maui.Graphics;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class ImageButtonHandler : ViewHandler<IImageButton, SkiaImageButton>
/// <summary>
/// Handler for ImageButton on Linux using Skia rendering.
/// Maps IImageButton interface to SkiaImageButton platform view.
/// IImageButton extends: IImage, IView, IButtonStroke, IPadding
/// </summary>
public partial class ImageButtonHandler : ViewHandler<IImageButton, SkiaImageButton>
{
internal class ImageSourceServiceResultManager
{
private readonly ImageButtonHandler _handler;
public static IPropertyMapper<IImageButton, ImageButtonHandler> Mapper = new PropertyMapper<IImageButton, ImageButtonHandler>(ViewHandler.ViewMapper)
{
[nameof(IImage.Aspect)] = MapAspect,
[nameof(IImage.IsOpaque)] = MapIsOpaque,
[nameof(IImageSourcePart.Source)] = MapSource,
[nameof(IButtonStroke.StrokeColor)] = MapStrokeColor,
[nameof(IButtonStroke.StrokeThickness)] = MapStrokeThickness,
[nameof(IButtonStroke.CornerRadius)] = MapCornerRadius,
[nameof(IPadding.Padding)] = MapPadding,
[nameof(IView.Background)] = MapBackground,
};
private CancellationTokenSource? _cts;
public static CommandMapper<IImageButton, ImageButtonHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
public ImageSourceServiceResultManager(ImageButtonHandler handler)
{
_handler = handler;
}
public ImageButtonHandler() : base(Mapper, CommandMapper)
{
}
public async void UpdateImageSourceAsync()
{
_cts?.Cancel();
_cts = new CancellationTokenSource();
CancellationToken token = _cts.Token;
try
{
IImageButton virtualView = ((ViewHandler<IImageButton, SkiaImageButton>)(object)_handler).VirtualView;
IImageSource val = ((virtualView != null) ? ((IImageSourcePart)virtualView).Source : null);
if (val == null)
{
((ViewHandler<IImageButton, SkiaImageButton>)(object)_handler).PlatformView?.LoadFromData(Array.Empty<byte>());
return;
}
IImageSourcePart virtualView2 = (IImageSourcePart)(object)((ViewHandler<IImageButton, SkiaImageButton>)(object)_handler).VirtualView;
if (virtualView2 != null)
{
virtualView2.UpdateIsLoading(true);
}
IFileImageSource val2 = (IFileImageSource)(object)((val is IFileImageSource) ? val : null);
if (val2 != null)
{
string file = val2.File;
if (!string.IsNullOrEmpty(file))
{
await ((ViewHandler<IImageButton, SkiaImageButton>)(object)_handler).PlatformView.LoadFromFileAsync(file);
}
return;
}
IUriImageSource val3 = (IUriImageSource)(object)((val is IUriImageSource) ? val : null);
if (val3 != null)
{
Uri uri = val3.Uri;
if (uri != null)
{
await ((ViewHandler<IImageButton, SkiaImageButton>)(object)_handler).PlatformView.LoadFromUriAsync(uri);
}
return;
}
IStreamImageSource val4 = (IStreamImageSource)(object)((val is IStreamImageSource) ? val : null);
if (val4 != null)
{
Stream stream = await val4.GetStreamAsync(token);
if (stream != null)
{
await ((ViewHandler<IImageButton, SkiaImageButton>)(object)_handler).PlatformView.LoadFromStreamAsync(stream);
}
}
}
catch (OperationCanceledException)
{
}
catch (Exception)
{
IImageSourcePart virtualView3 = (IImageSourcePart)(object)((ViewHandler<IImageButton, SkiaImageButton>)(object)_handler).VirtualView;
if (virtualView3 != null)
{
virtualView3.UpdateIsLoading(false);
}
}
}
}
public ImageButtonHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public static IPropertyMapper<IImageButton, ImageButtonHandler> Mapper = (IPropertyMapper<IImageButton, ImageButtonHandler>)(object)new PropertyMapper<IImageButton, ImageButtonHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Aspect"] = MapAspect,
["IsOpaque"] = MapIsOpaque,
["Source"] = MapSource,
["StrokeColor"] = MapStrokeColor,
["StrokeThickness"] = MapStrokeThickness,
["CornerRadius"] = MapCornerRadius,
["Padding"] = MapPadding,
["Background"] = MapBackground,
["BackgroundColor"] = MapBackgroundColor
};
protected override SkiaImageButton CreatePlatformView()
{
return new SkiaImageButton();
}
public static CommandMapper<IImageButton, ImageButtonHandler> CommandMapper = new CommandMapper<IImageButton, ImageButtonHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
protected override void ConnectHandler(SkiaImageButton platformView)
{
base.ConnectHandler(platformView);
platformView.Clicked += OnClicked;
platformView.Pressed += OnPressed;
platformView.Released += OnReleased;
platformView.ImageLoaded += OnImageLoaded;
platformView.ImageLoadingError += OnImageLoadingError;
}
private ImageSourceServiceResultManager _sourceLoader;
protected override void DisconnectHandler(SkiaImageButton platformView)
{
platformView.Clicked -= OnClicked;
platformView.Pressed -= OnPressed;
platformView.Released -= OnReleased;
platformView.ImageLoaded -= OnImageLoaded;
platformView.ImageLoadingError -= OnImageLoadingError;
base.DisconnectHandler(platformView);
}
private ImageSourceServiceResultManager SourceLoader => _sourceLoader ?? (_sourceLoader = new ImageSourceServiceResultManager(this));
private void OnClicked(object? sender, EventArgs e)
{
VirtualView?.Clicked();
}
public ImageButtonHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
private void OnPressed(object? sender, EventArgs e)
{
VirtualView?.Pressed();
}
public ImageButtonHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
private void OnReleased(object? sender, EventArgs e)
{
VirtualView?.Released();
}
protected override SkiaImageButton CreatePlatformView()
{
return new SkiaImageButton();
}
private void OnImageLoaded(object? sender, EventArgs e)
{
if (VirtualView is IImageSourcePart imageSourcePart)
{
imageSourcePart.UpdateIsLoading(false);
}
}
protected override void ConnectHandler(SkiaImageButton platformView)
{
base.ConnectHandler(platformView);
platformView.Clicked += OnClicked;
platformView.Pressed += OnPressed;
platformView.Released += OnReleased;
platformView.ImageLoaded += OnImageLoaded;
platformView.ImageLoadingError += OnImageLoadingError;
}
private void OnImageLoadingError(object? sender, ImageLoadingErrorEventArgs e)
{
if (VirtualView is IImageSourcePart imageSourcePart)
{
imageSourcePart.UpdateIsLoading(false);
}
}
protected override void DisconnectHandler(SkiaImageButton platformView)
{
platformView.Clicked -= OnClicked;
platformView.Pressed -= OnPressed;
platformView.Released -= OnReleased;
platformView.ImageLoaded -= OnImageLoaded;
platformView.ImageLoadingError -= OnImageLoadingError;
base.DisconnectHandler(platformView);
}
public static void MapAspect(ImageButtonHandler handler, IImageButton imageButton)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Aspect = imageButton.Aspect;
}
private void OnClicked(object? sender, EventArgs e)
{
IImageButton virtualView = base.VirtualView;
if (virtualView != null)
{
((IButton)virtualView).Clicked();
}
}
public static void MapIsOpaque(ImageButtonHandler handler, IImageButton imageButton)
{
if (handler.PlatformView is null) return;
handler.PlatformView.IsOpaque = imageButton.IsOpaque;
}
private void OnPressed(object? sender, EventArgs e)
{
IImageButton virtualView = base.VirtualView;
if (virtualView != null)
{
((IButton)virtualView).Pressed();
}
}
public static void MapSource(ImageButtonHandler handler, IImageButton imageButton)
{
if (handler.PlatformView is null) return;
handler.SourceLoader.UpdateImageSourceAsync();
}
private void OnReleased(object? sender, EventArgs e)
{
IImageButton virtualView = base.VirtualView;
if (virtualView != null)
{
((IButton)virtualView).Released();
}
}
public static void MapStrokeColor(ImageButtonHandler handler, IImageButton imageButton)
{
if (handler.PlatformView is null) return;
private void OnImageLoaded(object? sender, EventArgs e)
{
IImageSourcePart virtualView = (IImageSourcePart)(object)base.VirtualView;
if (virtualView != null)
{
virtualView.UpdateIsLoading(false);
}
}
if (imageButton.StrokeColor is not null)
handler.PlatformView.StrokeColor = imageButton.StrokeColor.ToSKColor();
}
private void OnImageLoadingError(object? sender, ImageLoadingErrorEventArgs e)
{
IImageSourcePart virtualView = (IImageSourcePart)(object)base.VirtualView;
if (virtualView != null)
{
virtualView.UpdateIsLoading(false);
}
}
public static void MapStrokeThickness(ImageButtonHandler handler, IImageButton imageButton)
{
if (handler.PlatformView is null) return;
handler.PlatformView.StrokeThickness = (float)imageButton.StrokeThickness;
}
public static void MapAspect(ImageButtonHandler handler, IImageButton imageButton)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView != null)
{
((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView.Aspect = ((IImage)imageButton).Aspect;
}
}
public static void MapCornerRadius(ImageButtonHandler handler, IImageButton imageButton)
{
if (handler.PlatformView is null) return;
handler.PlatformView.CornerRadius = imageButton.CornerRadius;
}
public static void MapIsOpaque(ImageButtonHandler handler, IImageButton imageButton)
{
if (((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView != null)
{
((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView.IsOpaque = ((IImage)imageButton).IsOpaque;
}
}
public static void MapPadding(ImageButtonHandler handler, IImageButton imageButton)
{
if (handler.PlatformView is null) return;
public static void MapSource(ImageButtonHandler handler, IImageButton imageButton)
{
if (((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView != null)
{
handler.SourceLoader.UpdateImageSourceAsync();
}
}
var padding = imageButton.Padding;
handler.PlatformView.PaddingLeft = (float)padding.Left;
handler.PlatformView.PaddingTop = (float)padding.Top;
handler.PlatformView.PaddingRight = (float)padding.Right;
handler.PlatformView.PaddingBottom = (float)padding.Bottom;
}
public static void MapStrokeColor(ImageButtonHandler handler, IImageButton imageButton)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView != null && ((IButtonStroke)imageButton).StrokeColor != null)
{
((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView.StrokeColor = ((IButtonStroke)imageButton).StrokeColor.ToSKColor();
}
}
public static void MapBackground(ImageButtonHandler handler, IImageButton imageButton)
{
if (handler.PlatformView is null) return;
public static void MapStrokeThickness(ImageButtonHandler handler, IImageButton imageButton)
{
if (((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView != null)
{
((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView.StrokeThickness = (float)((IButtonStroke)imageButton).StrokeThickness;
}
}
if (imageButton.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapCornerRadius(ImageButtonHandler handler, IImageButton imageButton)
{
if (((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView != null)
{
((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView.CornerRadius = ((IButtonStroke)imageButton).CornerRadius;
}
}
// Image source loading helper
private ImageSourceServiceResultManager _sourceLoader = null!;
public static void MapPadding(ImageButtonHandler handler, IImageButton imageButton)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView != null)
{
Thickness padding = ((IPadding)imageButton).Padding;
((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView.PaddingLeft = (float)((Thickness)(ref padding)).Left;
((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView.PaddingTop = (float)((Thickness)(ref padding)).Top;
((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView.PaddingRight = (float)((Thickness)(ref padding)).Right;
((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView.PaddingBottom = (float)((Thickness)(ref padding)).Bottom;
}
}
private ImageSourceServiceResultManager SourceLoader =>
_sourceLoader ??= new ImageSourceServiceResultManager(this);
public static void MapBackground(ImageButtonHandler handler, IImageButton imageButton)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView != null)
{
Paint background = ((IView)imageButton).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
internal class ImageSourceServiceResultManager
{
private readonly ImageButtonHandler _handler;
private CancellationTokenSource? _cts;
public static void MapBackgroundColor(ImageButtonHandler handler, IImageButton imageButton)
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView != null)
{
ImageButton val = (ImageButton)(object)((imageButton is ImageButton) ? imageButton : null);
if (val != null && ((VisualElement)val).BackgroundColor != null)
{
((ViewHandler<IImageButton, SkiaImageButton>)(object)handler).PlatformView.BackgroundColor = ((VisualElement)val).BackgroundColor.ToSKColor();
}
}
}
public ImageSourceServiceResultManager(ImageButtonHandler handler)
{
_handler = handler;
}
public async void UpdateImageSourceAsync()
{
_cts?.Cancel();
_cts = new CancellationTokenSource();
var token = _cts.Token;
try
{
var source = _handler.VirtualView?.Source;
if (source == null)
{
_handler.PlatformView?.LoadFromData(Array.Empty<byte>());
return;
}
if (_handler.VirtualView is IImageSourcePart imageSourcePart)
{
imageSourcePart.UpdateIsLoading(true);
}
// Handle different image source types
if (source is IFileImageSource fileSource)
{
var file = fileSource.File;
if (!string.IsNullOrEmpty(file))
{
await _handler.PlatformView!.LoadFromFileAsync(file);
}
}
else if (source is IUriImageSource uriSource)
{
var uri = uriSource.Uri;
if (uri != null)
{
await _handler.PlatformView!.LoadFromUriAsync(uri);
}
}
else if (source is IStreamImageSource streamSource)
{
var stream = await streamSource.GetStreamAsync(token);
if (stream != null)
{
await _handler.PlatformView!.LoadFromStreamAsync(stream);
}
}
}
catch (OperationCanceledException)
{
// Loading was cancelled
}
catch (Exception)
{
// Handle error
if (_handler.VirtualView is IImageSourcePart imageSourcePart)
{
imageSourcePart.UpdateIsLoading(false);
}
}
}
}
}

View File

@@ -1,342 +1,180 @@
using System;
using System.IO;
using System.Threading;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
// 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.Handlers;
using Microsoft.Maui.Graphics;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class ImageHandler : ViewHandler<IImage, SkiaImage>
/// <summary>
/// Handler for Image on Linux using Skia rendering.
/// Maps IImage interface to SkiaImage platform view.
/// IImage has: Aspect, IsOpaque (inherits from IImageSourcePart)
/// </summary>
public partial class ImageHandler : ViewHandler<IImage, SkiaImage>
{
internal class ImageSourceServiceResultManager
{
private readonly ImageHandler _handler;
public static IPropertyMapper<IImage, ImageHandler> Mapper = new PropertyMapper<IImage, ImageHandler>(ViewHandler.ViewMapper)
{
[nameof(IImage.Aspect)] = MapAspect,
[nameof(IImage.IsOpaque)] = MapIsOpaque,
[nameof(IImageSourcePart.Source)] = MapSource,
[nameof(IView.Background)] = MapBackground,
};
private CancellationTokenSource? _cts;
public static CommandMapper<IImage, ImageHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
public ImageSourceServiceResultManager(ImageHandler handler)
{
_handler = handler;
}
public ImageHandler() : base(Mapper, CommandMapper)
{
}
public async void UpdateImageSourceAsync()
{
_cts?.Cancel();
_cts = new CancellationTokenSource();
CancellationToken token = _cts.Token;
try
{
IImage virtualView = ((ViewHandler<IImage, SkiaImage>)(object)_handler).VirtualView;
IImageSource val = ((virtualView != null) ? ((IImageSourcePart)virtualView).Source : null);
if (val == null)
{
((ViewHandler<IImage, SkiaImage>)(object)_handler).PlatformView?.LoadFromData(Array.Empty<byte>());
return;
}
IImageSourcePart virtualView2 = (IImageSourcePart)(object)((ViewHandler<IImage, SkiaImage>)(object)_handler).VirtualView;
if (virtualView2 != null)
{
virtualView2.UpdateIsLoading(true);
}
IFileImageSource val2 = (IFileImageSource)(object)((val is IFileImageSource) ? val : null);
if (val2 != null)
{
string file = val2.File;
if (!string.IsNullOrEmpty(file))
{
await ((ViewHandler<IImage, SkiaImage>)(object)_handler).PlatformView.LoadFromFileAsync(file);
}
return;
}
IUriImageSource val3 = (IUriImageSource)(object)((val is IUriImageSource) ? val : null);
if (val3 != null)
{
Uri uri = val3.Uri;
if (uri != null)
{
await ((ViewHandler<IImage, SkiaImage>)(object)_handler).PlatformView.LoadFromUriAsync(uri);
}
return;
}
IStreamImageSource val4 = (IStreamImageSource)(object)((val is IStreamImageSource) ? val : null);
if (val4 != null)
{
Stream stream = await val4.GetStreamAsync(token);
if (stream != null)
{
await ((ViewHandler<IImage, SkiaImage>)(object)_handler).PlatformView.LoadFromStreamAsync(stream);
}
return;
}
FontImageSource val5 = (FontImageSource)(object)((val is FontImageSource) ? val : null);
if (val5 != null)
{
SKBitmap val6 = RenderFontImageSource(val5, ((ViewHandler<IImage, SkiaImage>)(object)_handler).PlatformView.WidthRequest, ((ViewHandler<IImage, SkiaImage>)(object)_handler).PlatformView.HeightRequest);
if (val6 != null)
{
((ViewHandler<IImage, SkiaImage>)(object)_handler).PlatformView.LoadFromBitmap(val6);
}
}
}
catch (OperationCanceledException)
{
}
catch (Exception)
{
IImageSourcePart virtualView3 = (IImageSourcePart)(object)((ViewHandler<IImage, SkiaImage>)(object)_handler).VirtualView;
if (virtualView3 != null)
{
virtualView3.UpdateIsLoading(false);
}
}
}
public ImageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
private static SKBitmap? RenderFontImageSource(FontImageSource fontSource, double requestedWidth, double requestedHeight)
{
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Expected O, but got Unknown
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0079: Expected O, but got Unknown
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_016a: Unknown result type (might be due to invalid IL or missing references)
//IL_0171: Expected O, but got Unknown
//IL_0173: Unknown result type (might be due to invalid IL or missing references)
//IL_0178: Unknown result type (might be due to invalid IL or missing references)
//IL_0179: Unknown result type (might be due to invalid IL or missing references)
//IL_017f: Unknown result type (might be due to invalid IL or missing references)
//IL_0186: Unknown result type (might be due to invalid IL or missing references)
//IL_018f: Expected O, but got Unknown
//IL_0191: Unknown result type (might be due to invalid IL or missing references)
string glyph = fontSource.Glyph;
if (string.IsNullOrEmpty(glyph))
{
return null;
}
int val = (int)Math.Max((requestedWidth > 0.0) ? requestedWidth : 24.0, (requestedHeight > 0.0) ? requestedHeight : 24.0);
val = Math.Max(val, 16);
SKColor color = fontSource.Color?.ToSKColor() ?? SKColors.Black;
SKBitmap val2 = new SKBitmap(val, val, false);
SKCanvas val3 = new SKCanvas(val2);
try
{
val3.Clear(SKColors.Transparent);
SKTypeface val4 = null;
if (!string.IsNullOrEmpty(fontSource.FontFamily))
{
string[] array = new string[4]
{
"/usr/share/fonts/truetype/" + fontSource.FontFamily + ".ttf",
"/usr/share/fonts/opentype/" + fontSource.FontFamily + ".otf",
"/usr/local/share/fonts/" + fontSource.FontFamily + ".ttf",
Path.Combine(AppContext.BaseDirectory, fontSource.FontFamily + ".ttf")
};
foreach (string text in array)
{
if (File.Exists(text))
{
val4 = SKTypeface.FromFile(text, 0);
if (val4 != null)
{
break;
}
}
}
if (val4 == null)
{
val4 = SKTypeface.FromFamilyName(fontSource.FontFamily);
}
}
if (val4 == null)
{
val4 = SKTypeface.Default;
}
float num = (float)val * 0.8f;
SKFont val5 = new SKFont(val4, num, 1f, 0f);
try
{
SKPaint val6 = new SKPaint(val5)
{
Color = color,
IsAntialias = true,
TextAlign = (SKTextAlign)1
};
try
{
SKRect val7 = default(SKRect);
val6.MeasureText(glyph, ref val7);
float num2 = (float)val / 2f;
float num3 = ((float)val - ((SKRect)(ref val7)).Top - ((SKRect)(ref val7)).Bottom) / 2f;
val3.DrawText(glyph, num2, num3, val6);
return val2;
}
finally
{
((IDisposable)val6)?.Dispose();
}
}
finally
{
((IDisposable)val5)?.Dispose();
}
}
finally
{
((IDisposable)val3)?.Dispose();
}
}
}
protected override SkiaImage CreatePlatformView()
{
return new SkiaImage();
}
public static IPropertyMapper<IImage, ImageHandler> Mapper = (IPropertyMapper<IImage, ImageHandler>)(object)new PropertyMapper<IImage, ImageHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Aspect"] = MapAspect,
["IsOpaque"] = MapIsOpaque,
["Source"] = MapSource,
["Background"] = MapBackground,
["Width"] = MapWidth,
["Height"] = MapHeight
};
protected override void ConnectHandler(SkiaImage platformView)
{
base.ConnectHandler(platformView);
platformView.ImageLoaded += OnImageLoaded;
platformView.ImageLoadingError += OnImageLoadingError;
}
public static CommandMapper<IImage, ImageHandler> CommandMapper = new CommandMapper<IImage, ImageHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
protected override void DisconnectHandler(SkiaImage platformView)
{
platformView.ImageLoaded -= OnImageLoaded;
platformView.ImageLoadingError -= OnImageLoadingError;
base.DisconnectHandler(platformView);
}
private ImageSourceServiceResultManager _sourceLoader;
private void OnImageLoaded(object? sender, EventArgs e)
{
// Notify that the image has been loaded
if (VirtualView is IImageSourcePart imageSourcePart)
{
imageSourcePart.UpdateIsLoading(false);
}
}
private ImageSourceServiceResultManager SourceLoader => _sourceLoader ?? (_sourceLoader = new ImageSourceServiceResultManager(this));
private void OnImageLoadingError(object? sender, ImageLoadingErrorEventArgs e)
{
// Handle loading error
if (VirtualView is IImageSourcePart imageSourcePart)
{
imageSourcePart.UpdateIsLoading(false);
}
}
public ImageHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public static void MapAspect(ImageHandler handler, IImage image)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Aspect = image.Aspect;
}
public ImageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
public static void MapIsOpaque(ImageHandler handler, IImage image)
{
if (handler.PlatformView is null) return;
handler.PlatformView.IsOpaque = image.IsOpaque;
}
protected override SkiaImage CreatePlatformView()
{
return new SkiaImage();
}
public static void MapSource(ImageHandler handler, IImage image)
{
if (handler.PlatformView is null) return;
protected override void ConnectHandler(SkiaImage platformView)
{
base.ConnectHandler(platformView);
platformView.ImageLoaded += OnImageLoaded;
platformView.ImageLoadingError += OnImageLoadingError;
}
handler.SourceLoader.UpdateImageSourceAsync();
}
protected override void DisconnectHandler(SkiaImage platformView)
{
platformView.ImageLoaded -= OnImageLoaded;
platformView.ImageLoadingError -= OnImageLoadingError;
base.DisconnectHandler(platformView);
}
public static void MapBackground(ImageHandler handler, IImage image)
{
if (handler.PlatformView is null) return;
private void OnImageLoaded(object? sender, EventArgs e)
{
IImageSourcePart virtualView = (IImageSourcePart)(object)base.VirtualView;
if (virtualView != null)
{
virtualView.UpdateIsLoading(false);
}
}
if (image.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
private void OnImageLoadingError(object? sender, ImageLoadingErrorEventArgs e)
{
IImageSourcePart virtualView = (IImageSourcePart)(object)base.VirtualView;
if (virtualView != null)
{
virtualView.UpdateIsLoading(false);
}
}
// Image source loading helper
private ImageSourceServiceResultManager _sourceLoader = null!;
public static void MapAspect(ImageHandler handler, IImage image)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView != null)
{
((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView.Aspect = image.Aspect;
}
}
private ImageSourceServiceResultManager SourceLoader =>
_sourceLoader ??= new ImageSourceServiceResultManager(this);
public static void MapIsOpaque(ImageHandler handler, IImage image)
{
if (((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView != null)
{
((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView.IsOpaque = image.IsOpaque;
}
}
internal class ImageSourceServiceResultManager
{
private readonly ImageHandler _handler;
private CancellationTokenSource? _cts;
public static void MapSource(ImageHandler handler, IImage image)
{
if (((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView == null)
{
return;
}
Image val = (Image)(object)((image is Image) ? image : null);
if (val != null)
{
if (((VisualElement)val).WidthRequest > 0.0)
{
((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView.WidthRequest = ((VisualElement)val).WidthRequest;
}
if (((VisualElement)val).HeightRequest > 0.0)
{
((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView.HeightRequest = ((VisualElement)val).HeightRequest;
}
}
handler.SourceLoader.UpdateImageSourceAsync();
}
public ImageSourceServiceResultManager(ImageHandler handler)
{
_handler = handler;
}
public static void MapBackground(ImageHandler handler, IImage image)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView != null)
{
Paint background = ((IView)image).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
public async void UpdateImageSourceAsync()
{
_cts?.Cancel();
_cts = new CancellationTokenSource();
var token = _cts.Token;
public static void MapWidth(ImageHandler handler, IImage image)
{
if (((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView != null)
{
Image val = (Image)(object)((image is Image) ? image : null);
if (val != null && ((VisualElement)val).WidthRequest > 0.0)
{
((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView.WidthRequest = ((VisualElement)val).WidthRequest;
Console.WriteLine($"[ImageHandler] MapWidth: {((VisualElement)val).WidthRequest}");
}
else if (((IView)image).Width > 0.0)
{
((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView.WidthRequest = ((IView)image).Width;
}
}
}
try
{
var source = _handler.VirtualView?.Source;
if (source == null)
{
_handler.PlatformView?.LoadFromData(Array.Empty<byte>());
return;
}
public static void MapHeight(ImageHandler handler, IImage image)
{
if (((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView != null)
{
Image val = (Image)(object)((image is Image) ? image : null);
if (val != null && ((VisualElement)val).HeightRequest > 0.0)
{
((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView.HeightRequest = ((VisualElement)val).HeightRequest;
Console.WriteLine($"[ImageHandler] MapHeight: {((VisualElement)val).HeightRequest}");
}
else if (((IView)image).Height > 0.0)
{
((ViewHandler<IImage, SkiaImage>)(object)handler).PlatformView.HeightRequest = ((IView)image).Height;
}
}
}
if (_handler.VirtualView is IImageSourcePart imageSourcePart)
{
imageSourcePart.UpdateIsLoading(true);
}
// Handle different image source types
if (source is IFileImageSource fileSource)
{
var file = fileSource.File;
if (!string.IsNullOrEmpty(file))
{
await _handler.PlatformView!.LoadFromFileAsync(file);
}
}
else if (source is IUriImageSource uriSource)
{
var uri = uriSource.Uri;
if (uri != null)
{
await _handler.PlatformView!.LoadFromUriAsync(uri);
}
}
else if (source is IStreamImageSource streamSource)
{
var stream = await streamSource.GetStreamAsync(token);
if (stream != null)
{
await _handler.PlatformView!.LoadFromStreamAsync(stream);
}
}
}
catch (OperationCanceledException)
{
// Loading was cancelled
}
catch (Exception)
{
// Handle error
if (_handler.VirtualView is IImageSourcePart imageSourcePart)
{
imageSourcePart.UpdateIsLoading(false);
}
}
}
}
}

View File

@@ -1,175 +1,164 @@
using Microsoft.Maui.Controls;
// 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.Handlers;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class ItemsViewHandler<TItemsView> : ViewHandler<TItemsView, SkiaItemsView> where TItemsView : ItemsView
/// <summary>
/// Base handler for ItemsView on Linux using Skia rendering.
/// Maps ItemsView to SkiaItemsView platform view.
/// </summary>
public partial class ItemsViewHandler<TItemsView> : ViewHandler<TItemsView, SkiaItemsView>
where TItemsView : ItemsView
{
public static IPropertyMapper<TItemsView, ItemsViewHandler<TItemsView>> ItemsViewMapper = (IPropertyMapper<TItemsView, ItemsViewHandler<TItemsView>>)(object)new PropertyMapper<TItemsView, ItemsViewHandler<TItemsView>>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["ItemsSource"] = MapItemsSource,
["ItemTemplate"] = MapItemTemplate,
["EmptyView"] = MapEmptyView,
["EmptyViewTemplate"] = MapEmptyViewTemplate,
["HorizontalScrollBarVisibility"] = MapHorizontalScrollBarVisibility,
["VerticalScrollBarVisibility"] = MapVerticalScrollBarVisibility,
["Background"] = MapBackground
};
public static IPropertyMapper<TItemsView, ItemsViewHandler<TItemsView>> ItemsViewMapper =
new PropertyMapper<TItemsView, ItemsViewHandler<TItemsView>>(ViewHandler.ViewMapper)
{
[nameof(ItemsView.ItemsSource)] = MapItemsSource,
[nameof(ItemsView.ItemTemplate)] = MapItemTemplate,
[nameof(ItemsView.EmptyView)] = MapEmptyView,
[nameof(ItemsView.EmptyViewTemplate)] = MapEmptyViewTemplate,
[nameof(ItemsView.HorizontalScrollBarVisibility)] = MapHorizontalScrollBarVisibility,
[nameof(ItemsView.VerticalScrollBarVisibility)] = MapVerticalScrollBarVisibility,
[nameof(IView.Background)] = MapBackground,
};
public static CommandMapper<TItemsView, ItemsViewHandler<TItemsView>> ItemsViewCommandMapper = new CommandMapper<TItemsView, ItemsViewHandler<TItemsView>>((CommandMapper)(object)ViewHandler.ViewCommandMapper) { ["ScrollTo"] = MapScrollTo };
public static CommandMapper<TItemsView, ItemsViewHandler<TItemsView>> ItemsViewCommandMapper =
new(ViewHandler.ViewCommandMapper)
{
["ScrollTo"] = MapScrollTo,
};
public ItemsViewHandler()
: base((IPropertyMapper)(object)ItemsViewMapper, (CommandMapper)(object)ItemsViewCommandMapper)
{
}
public ItemsViewHandler() : base(ItemsViewMapper, ItemsViewCommandMapper)
{
}
public ItemsViewHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)ItemsViewMapper)), (CommandMapper)(((object)commandMapper) ?? ((object)ItemsViewCommandMapper)))
{
}
public ItemsViewHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? ItemsViewMapper, commandMapper ?? ItemsViewCommandMapper)
{
}
protected override SkiaItemsView CreatePlatformView()
{
return new SkiaItemsView();
}
protected override SkiaItemsView CreatePlatformView()
{
return new SkiaItemsView();
}
protected override void ConnectHandler(SkiaItemsView platformView)
{
base.ConnectHandler(platformView);
platformView.Scrolled += OnScrolled;
platformView.ItemTapped += OnItemTapped;
platformView.ItemRenderer = RenderItem;
}
protected override void ConnectHandler(SkiaItemsView platformView)
{
base.ConnectHandler(platformView);
platformView.Scrolled += OnScrolled;
platformView.ItemTapped += OnItemTapped;
protected override void DisconnectHandler(SkiaItemsView platformView)
{
platformView.Scrolled -= OnScrolled;
platformView.ItemTapped -= OnItemTapped;
platformView.ItemRenderer = null;
base.DisconnectHandler(platformView);
}
// Set up item renderer
platformView.ItemRenderer = RenderItem;
}
private void OnScrolled(object? sender, ItemsScrolledEventArgs e)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Expected O, but got Unknown
object obj = base.VirtualView;
if (obj != null)
{
((ItemsView)obj).SendScrolled(new ItemsViewScrolledEventArgs
{
VerticalOffset = e.ScrollOffset,
VerticalDelta = 0.0,
HorizontalOffset = 0.0,
HorizontalDelta = 0.0
});
}
}
protected override void DisconnectHandler(SkiaItemsView platformView)
{
platformView.Scrolled -= OnScrolled;
platformView.ItemTapped -= OnItemTapped;
platformView.ItemRenderer = null;
base.DisconnectHandler(platformView);
}
private void OnItemTapped(object? sender, ItemsViewItemTappedEventArgs e)
{
}
private void OnScrolled(object? sender, ItemsScrolledEventArgs e)
{
// Fire scrolled event on virtual view
VirtualView?.SendScrolled(new ItemsViewScrolledEventArgs
{
VerticalOffset = e.ScrollOffset,
VerticalDelta = 0,
HorizontalOffset = 0,
HorizontalDelta = 0
});
}
protected virtual bool RenderItem(object item, int index, SKRect bounds, SKCanvas canvas, SKPaint paint)
{
object obj = base.VirtualView;
if (obj != null)
{
_ = ((ItemsView)obj).ItemTemplate;
}
else
_ = null;
return false;
}
private void OnItemTapped(object? sender, ItemsViewItemTappedEventArgs e)
{
// Item tap handling - can be extended for selection
}
public static void MapItemsSource(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
if (((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView != null)
{
((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView.ItemsSource = ((ItemsView)itemsView).ItemsSource;
}
}
protected virtual bool RenderItem(object item, int index, SKRect bounds, SKCanvas canvas, SKPaint paint)
{
// Check if we have an ItemTemplate
var template = VirtualView?.ItemTemplate;
if (template == null)
return false; // Use default rendering
public static void MapItemTemplate(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView?.Invalidate();
}
// For now, render based on item ToString
// Full DataTemplate support would require creating actual views
return false;
}
public static void MapEmptyView(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
if (((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView != null)
{
((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView.EmptyView = ((ItemsView)itemsView).EmptyView;
if (((ItemsView)itemsView).EmptyView is string emptyViewText)
{
((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView.EmptyViewText = emptyViewText;
}
}
}
public static void MapItemsSource(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.ItemsSource = itemsView.ItemsSource;
}
public static void MapEmptyViewTemplate(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView?.Invalidate();
}
public static void MapItemTemplate(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
// ItemTemplate affects how items are rendered
// The renderer will check this when drawing items
handler.PlatformView?.Invalidate();
}
public static void MapHorizontalScrollBarVisibility(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Expected I4, but got Unknown
if (((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView != null)
{
((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView.HorizontalScrollBarVisibility = (ScrollBarVisibility)((ItemsView)itemsView).HorizontalScrollBarVisibility;
}
}
public static void MapEmptyView(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
if (handler.PlatformView is null) return;
public static void MapVerticalScrollBarVisibility(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Expected I4, but got Unknown
if (((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView != null)
{
((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView.VerticalScrollBarVisibility = (ScrollBarVisibility)((ItemsView)itemsView).VerticalScrollBarVisibility;
}
}
handler.PlatformView.EmptyView = itemsView.EmptyView;
if (itemsView.EmptyView is string text)
{
handler.PlatformView.EmptyViewText = text;
}
}
public static void MapBackground(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView != null)
{
Brush background = ((VisualElement)(object)itemsView).Background;
SolidColorBrush val = (SolidColorBrush)(object)((background is SolidColorBrush) ? background : null);
if (val != null)
{
((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
public static void MapEmptyViewTemplate(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
// EmptyViewTemplate would be used to render custom empty view
handler.PlatformView?.Invalidate();
}
public static void MapScrollTo(ItemsViewHandler<TItemsView> handler, TItemsView itemsView, object? args)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Invalid comparison between Unknown and I4
if (((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView == null)
{
return;
}
ScrollToRequestEventArgs e = (ScrollToRequestEventArgs)((args is ScrollToRequestEventArgs) ? args : null);
if (e != null)
{
if ((int)e.Mode == 1)
{
((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView.ScrollToIndex(e.Index, e.IsAnimated);
}
else if (e.Item != null)
{
((ViewHandler<TItemsView, SkiaItemsView>)(object)handler).PlatformView.ScrollToItem(e.Item, e.IsAnimated);
}
}
}
public static void MapHorizontalScrollBarVisibility(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.HorizontalScrollBarVisibility = (ScrollBarVisibility)itemsView.HorizontalScrollBarVisibility;
}
public static void MapVerticalScrollBarVisibility(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
if (handler.PlatformView is null) return;
handler.PlatformView.VerticalScrollBarVisibility = (ScrollBarVisibility)itemsView.VerticalScrollBarVisibility;
}
public static void MapBackground(ItemsViewHandler<TItemsView> handler, TItemsView itemsView)
{
if (handler.PlatformView is null) return;
if (itemsView.Background is SolidColorBrush solidBrush)
{
handler.PlatformView.BackgroundColor = solidBrush.Color.ToSKColor();
}
}
public static void MapScrollTo(ItemsViewHandler<TItemsView> handler, TItemsView itemsView, object? args)
{
if (handler.PlatformView is null || args is not ScrollToRequestEventArgs scrollArgs)
return;
if (scrollArgs.Mode == ScrollToMode.Position)
{
handler.PlatformView.ScrollToIndex(scrollArgs.Index, scrollArgs.IsAnimated);
}
else if (scrollArgs.Item != null)
{
handler.PlatformView.ScrollToItem(scrollArgs.Item, scrollArgs.IsAnimated);
}
}
}

View File

@@ -1,388 +1,208 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
// 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.Handlers;
using Microsoft.Maui.Platform.Linux.Window;
using Microsoft.Maui.Primitives;
using Microsoft.Maui.Graphics;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class LabelHandler : ViewHandler<ILabel, SkiaLabel>
/// <summary>
/// Handler for Label on Linux using Skia rendering.
/// Maps ILabel interface to SkiaLabel platform view.
/// </summary>
public partial class LabelHandler : ViewHandler<ILabel, SkiaLabel>
{
public static IPropertyMapper<ILabel, LabelHandler> Mapper = (IPropertyMapper<ILabel, LabelHandler>)(object)new PropertyMapper<ILabel, LabelHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Text"] = MapText,
["TextColor"] = MapTextColor,
["Font"] = MapFont,
["CharacterSpacing"] = MapCharacterSpacing,
["HorizontalTextAlignment"] = MapHorizontalTextAlignment,
["VerticalTextAlignment"] = MapVerticalTextAlignment,
["TextDecorations"] = MapTextDecorations,
["LineHeight"] = MapLineHeight,
["LineBreakMode"] = MapLineBreakMode,
["MaxLines"] = MapMaxLines,
["Padding"] = MapPadding,
["Background"] = MapBackground,
["VerticalLayoutAlignment"] = MapVerticalLayoutAlignment,
["HorizontalLayoutAlignment"] = MapHorizontalLayoutAlignment,
["FormattedText"] = MapFormattedText
};
public static IPropertyMapper<ILabel, LabelHandler> Mapper = new PropertyMapper<ILabel, LabelHandler>(ViewHandler.ViewMapper)
{
[nameof(IText.Text)] = MapText,
[nameof(ITextStyle.TextColor)] = MapTextColor,
[nameof(ITextStyle.Font)] = MapFont,
[nameof(ITextStyle.CharacterSpacing)] = MapCharacterSpacing,
[nameof(ITextAlignment.HorizontalTextAlignment)] = MapHorizontalTextAlignment,
[nameof(ITextAlignment.VerticalTextAlignment)] = MapVerticalTextAlignment,
[nameof(ILabel.TextDecorations)] = MapTextDecorations,
[nameof(ILabel.LineHeight)] = MapLineHeight,
["LineBreakMode"] = MapLineBreakMode,
["MaxLines"] = MapMaxLines,
[nameof(IPadding.Padding)] = MapPadding,
[nameof(IView.Background)] = MapBackground,
[nameof(IView.VerticalLayoutAlignment)] = MapVerticalLayoutAlignment,
[nameof(IView.HorizontalLayoutAlignment)] = MapHorizontalLayoutAlignment,
};
public static CommandMapper<ILabel, LabelHandler> CommandMapper = new CommandMapper<ILabel, LabelHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public static CommandMapper<ILabel, LabelHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
public LabelHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public LabelHandler() : base(Mapper, CommandMapper)
{
}
public LabelHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
public LabelHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override SkiaLabel CreatePlatformView()
{
return new SkiaLabel();
}
protected override SkiaLabel CreatePlatformView()
{
return new SkiaLabel();
}
protected override void ConnectHandler(SkiaLabel platformView)
{
base.ConnectHandler(platformView);
ILabel virtualView = base.VirtualView;
View val = (View)(object)((virtualView is View) ? virtualView : null);
if (val != null)
{
platformView.MauiView = val;
if (val.GestureRecognizers.OfType<TapGestureRecognizer>().Any())
{
platformView.CursorType = CursorType.Hand;
}
}
platformView.Tapped += OnPlatformViewTapped;
}
public static void MapText(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Text = label.Text ?? string.Empty;
}
protected override void DisconnectHandler(SkiaLabel platformView)
{
platformView.Tapped -= OnPlatformViewTapped;
platformView.MauiView = null;
base.DisconnectHandler(platformView);
}
public static void MapTextColor(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
private void OnPlatformViewTapped(object? sender, EventArgs e)
{
ILabel virtualView = base.VirtualView;
View val = (View)(object)((virtualView is View) ? virtualView : null);
if (val != null)
{
GestureManager.ProcessTap(val, 0.0, 0.0);
}
}
if (label.TextColor is not null)
handler.PlatformView.TextColor = label.TextColor.ToSKColor();
}
public static void MapText(LabelHandler handler, ILabel label)
{
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null)
{
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.Text = ((IText)label).Text ?? string.Empty;
}
}
public static void MapFont(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
public static void MapTextColor(LabelHandler handler, ILabel label)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null && ((ITextStyle)label).TextColor != null)
{
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.TextColor = ((ITextStyle)label).TextColor.ToSKColor();
}
}
var font = label.Font;
if (font.Size > 0)
handler.PlatformView.FontSize = (float)font.Size;
public static void MapFont(LabelHandler handler, ILabel label)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Invalid comparison between Unknown and I4
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Invalid comparison between Unknown and I4
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Invalid comparison between Unknown and I4
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null)
{
Font font = ((ITextStyle)label).Font;
if (((Font)(ref font)).Size > 0.0)
{
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.FontSize = (float)((Font)(ref font)).Size;
}
if (!string.IsNullOrEmpty(((Font)(ref font)).Family))
{
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.FontFamily = ((Font)(ref font)).Family;
}
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.IsBold = (int)((Font)(ref font)).Weight >= 700;
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.IsItalic = (int)((Font)(ref font)).Slant == 1 || (int)((Font)(ref font)).Slant == 2;
}
}
if (!string.IsNullOrEmpty(font.Family))
handler.PlatformView.FontFamily = font.Family;
public static void MapCharacterSpacing(LabelHandler handler, ILabel label)
{
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null)
{
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.CharacterSpacing = (float)((ITextStyle)label).CharacterSpacing;
}
}
handler.PlatformView.IsBold = font.Weight >= FontWeight.Bold;
handler.PlatformView.IsItalic = font.Slant == FontSlant.Italic || font.Slant == FontSlant.Oblique;
}
public static void MapHorizontalTextAlignment(LabelHandler handler, ILabel label)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected I4, but got Unknown
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null)
{
SkiaLabel platformView = ((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView;
TextAlignment horizontalTextAlignment = ((ITextAlignment)label).HorizontalTextAlignment;
platformView.HorizontalTextAlignment = (int)horizontalTextAlignment switch
{
0 => TextAlignment.Start,
1 => TextAlignment.Center,
2 => TextAlignment.End,
_ => TextAlignment.Start,
};
}
}
public static void MapCharacterSpacing(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
handler.PlatformView.CharacterSpacing = (float)label.CharacterSpacing;
}
public static void MapVerticalTextAlignment(LabelHandler handler, ILabel label)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Expected I4, but got Unknown
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null)
{
SkiaLabel platformView = ((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView;
TextAlignment verticalTextAlignment = ((ITextAlignment)label).VerticalTextAlignment;
platformView.VerticalTextAlignment = (int)verticalTextAlignment switch
{
0 => TextAlignment.Start,
1 => TextAlignment.Center,
2 => TextAlignment.End,
_ => TextAlignment.Center,
};
}
}
public static void MapHorizontalTextAlignment(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
public static void MapTextDecorations(LabelHandler handler, ILabel label)
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Invalid comparison between Unknown and I4
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Invalid comparison between Unknown and I4
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null)
{
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.IsUnderline = (label.TextDecorations & 1) > 0;
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.IsStrikethrough = (label.TextDecorations & 2) > 0;
}
}
// Map MAUI TextAlignment to our internal TextAlignment
handler.PlatformView.HorizontalTextAlignment = label.HorizontalTextAlignment switch
{
Microsoft.Maui.TextAlignment.Start => Platform.TextAlignment.Start,
Microsoft.Maui.TextAlignment.Center => Platform.TextAlignment.Center,
Microsoft.Maui.TextAlignment.End => Platform.TextAlignment.End,
_ => Platform.TextAlignment.Start
};
}
public static void MapLineHeight(LabelHandler handler, ILabel label)
{
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null)
{
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.LineHeight = (float)label.LineHeight;
}
}
public static void MapVerticalTextAlignment(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
public static void MapLineBreakMode(LabelHandler handler, ILabel label)
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Expected I4, but got Unknown
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null)
{
Label val = (Label)(object)((label is Label) ? label : null);
if (val != null)
{
SkiaLabel platformView = ((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView;
LineBreakMode lineBreakMode = val.LineBreakMode;
platformView.LineBreakMode = (int)lineBreakMode switch
{
0 => LineBreakMode.NoWrap,
1 => LineBreakMode.WordWrap,
2 => LineBreakMode.CharacterWrap,
3 => LineBreakMode.HeadTruncation,
4 => LineBreakMode.TailTruncation,
5 => LineBreakMode.MiddleTruncation,
_ => LineBreakMode.TailTruncation,
};
}
}
}
handler.PlatformView.VerticalTextAlignment = label.VerticalTextAlignment switch
{
Microsoft.Maui.TextAlignment.Start => Platform.TextAlignment.Start,
Microsoft.Maui.TextAlignment.Center => Platform.TextAlignment.Center,
Microsoft.Maui.TextAlignment.End => Platform.TextAlignment.End,
_ => Platform.TextAlignment.Center
};
}
public static void MapMaxLines(LabelHandler handler, ILabel label)
{
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null)
{
Label val = (Label)(object)((label is Label) ? label : null);
if (val != null)
{
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.MaxLines = val.MaxLines;
}
}
}
public static void MapTextDecorations(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
public static void MapPadding(LabelHandler handler, ILabel label)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null)
{
Thickness padding = ((IPadding)label).Padding;
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.Padding = new SKRect((float)((Thickness)(ref padding)).Left, (float)((Thickness)(ref padding)).Top, (float)((Thickness)(ref padding)).Right, (float)((Thickness)(ref padding)).Bottom);
}
}
handler.PlatformView.IsUnderline = (label.TextDecorations & TextDecorations.Underline) != 0;
handler.PlatformView.IsStrikethrough = (label.TextDecorations & TextDecorations.Strikethrough) != 0;
}
public static void MapBackground(LabelHandler handler, ILabel label)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null)
{
Paint background = ((IView)label).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
public static void MapLineHeight(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
handler.PlatformView.LineHeight = (float)label.LineHeight;
}
public static void MapVerticalLayoutAlignment(LabelHandler handler, ILabel label)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Expected I4, but got Unknown
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null)
{
SkiaLabel platformView = ((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView;
LayoutAlignment verticalLayoutAlignment = ((IView)label).VerticalLayoutAlignment;
platformView.VerticalOptions = (LayoutOptions)((int)verticalLayoutAlignment switch
{
1 => LayoutOptions.Start,
2 => LayoutOptions.Center,
3 => LayoutOptions.End,
0 => LayoutOptions.Fill,
_ => LayoutOptions.Start,
});
}
}
public static void MapLineBreakMode(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
public static void MapHorizontalLayoutAlignment(LabelHandler handler, ILabel label)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Expected I4, but got Unknown
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView != null)
{
SkiaLabel platformView = ((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView;
LayoutAlignment horizontalLayoutAlignment = ((IView)label).HorizontalLayoutAlignment;
platformView.HorizontalOptions = (LayoutOptions)((int)horizontalLayoutAlignment switch
{
1 => LayoutOptions.Start,
2 => LayoutOptions.Center,
3 => LayoutOptions.End,
0 => LayoutOptions.Fill,
_ => LayoutOptions.Start,
});
}
}
// LineBreakMode is on Label control, not ILabel interface
if (label is Microsoft.Maui.Controls.Label mauiLabel)
{
handler.PlatformView.LineBreakMode = mauiLabel.LineBreakMode switch
{
Microsoft.Maui.LineBreakMode.NoWrap => Platform.LineBreakMode.NoWrap,
Microsoft.Maui.LineBreakMode.WordWrap => Platform.LineBreakMode.WordWrap,
Microsoft.Maui.LineBreakMode.CharacterWrap => Platform.LineBreakMode.CharacterWrap,
Microsoft.Maui.LineBreakMode.HeadTruncation => Platform.LineBreakMode.HeadTruncation,
Microsoft.Maui.LineBreakMode.TailTruncation => Platform.LineBreakMode.TailTruncation,
Microsoft.Maui.LineBreakMode.MiddleTruncation => Platform.LineBreakMode.MiddleTruncation,
_ => Platform.LineBreakMode.TailTruncation
};
}
}
public static void MapFormattedText(LabelHandler handler, ILabel label)
{
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
//IL_00c3: Invalid comparison between Unknown and I4
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
//IL_00d5: Invalid comparison between Unknown and I4
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_012d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView == null)
{
return;
}
Label val = (Label)(object)((label is Label) ? label : null);
if (val == null)
{
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.FormattedSpans = null;
return;
}
FormattedString formattedText = val.FormattedText;
if (formattedText == null || formattedText.Spans.Count == 0)
{
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.FormattedSpans = null;
return;
}
List<SkiaTextSpan> list = new List<SkiaTextSpan>();
foreach (Span span in formattedText.Spans)
{
SkiaTextSpan skiaTextSpan = new SkiaTextSpan
{
Text = (span.Text ?? ""),
IsBold = ((Enum)span.FontAttributes).HasFlag((Enum)(object)(FontAttributes)1),
IsItalic = ((Enum)span.FontAttributes).HasFlag((Enum)(object)(FontAttributes)2),
IsUnderline = ((span.TextDecorations & 1) > 0),
IsStrikethrough = ((span.TextDecorations & 2) > 0),
CharacterSpacing = (float)span.CharacterSpacing,
LineHeight = (float)span.LineHeight
};
if (span.TextColor != null)
{
skiaTextSpan.TextColor = span.TextColor.ToSKColor();
}
if (span.BackgroundColor != null)
{
skiaTextSpan.BackgroundColor = span.BackgroundColor.ToSKColor();
}
if (!string.IsNullOrEmpty(span.FontFamily))
{
skiaTextSpan.FontFamily = span.FontFamily;
}
if (span.FontSize > 0.0)
{
skiaTextSpan.FontSize = (float)span.FontSize;
}
list.Add(skiaTextSpan);
}
((ViewHandler<ILabel, SkiaLabel>)(object)handler).PlatformView.FormattedSpans = list;
}
public static void MapMaxLines(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
// MaxLines is on Label control, not ILabel interface
if (label is Microsoft.Maui.Controls.Label mauiLabel)
{
handler.PlatformView.MaxLines = mauiLabel.MaxLines;
}
}
public static void MapPadding(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
var padding = label.Padding;
handler.PlatformView.Padding = new SKRect(
(float)padding.Left,
(float)padding.Top,
(float)padding.Right,
(float)padding.Bottom);
}
public static void MapBackground(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
if (label.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapVerticalLayoutAlignment(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
handler.PlatformView.VerticalOptions = label.VerticalLayoutAlignment switch
{
Primitives.LayoutAlignment.Start => LayoutOptions.Start,
Primitives.LayoutAlignment.Center => LayoutOptions.Center,
Primitives.LayoutAlignment.End => LayoutOptions.End,
Primitives.LayoutAlignment.Fill => LayoutOptions.Fill,
_ => LayoutOptions.Start
};
}
public static void MapHorizontalLayoutAlignment(LabelHandler handler, ILabel label)
{
if (handler.PlatformView is null) return;
handler.PlatformView.HorizontalOptions = label.HorizontalLayoutAlignment switch
{
Primitives.LayoutAlignment.Start => LayoutOptions.Start,
Primitives.LayoutAlignment.Center => LayoutOptions.Center,
Primitives.LayoutAlignment.End => LayoutOptions.End,
Primitives.LayoutAlignment.Fill => LayoutOptions.Fill,
_ => LayoutOptions.Start
};
}
}

View File

@@ -1,166 +1,368 @@
using System.Collections.Generic;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
// 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.Handlers;
using Microsoft.Maui.Platform.Linux.Hosting;
using Microsoft.Maui.Graphics;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class LayoutHandler : ViewHandler<ILayout, SkiaLayoutView>
/// <summary>
/// Handler for Layout on Linux using Skia rendering.
/// Maps ILayout interface to SkiaLayoutView platform view.
/// </summary>
public partial class LayoutHandler : ViewHandler<ILayout, SkiaLayoutView>
{
public static IPropertyMapper<ILayout, LayoutHandler> Mapper = (IPropertyMapper<ILayout, LayoutHandler>)(object)new PropertyMapper<ILayout, LayoutHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["ClipsToBounds"] = MapClipsToBounds,
["Background"] = MapBackground,
["Padding"] = MapPadding
};
public static IPropertyMapper<ILayout, LayoutHandler> Mapper = new PropertyMapper<ILayout, LayoutHandler>(ViewHandler.ViewMapper)
{
[nameof(ILayout.ClipsToBounds)] = MapClipsToBounds,
[nameof(IView.Background)] = MapBackground,
[nameof(IPadding.Padding)] = MapPadding,
};
public static CommandMapper<ILayout, LayoutHandler> CommandMapper = new CommandMapper<ILayout, LayoutHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper)
{
["Add"] = MapAdd,
["Remove"] = MapRemove,
["Clear"] = MapClear,
["Insert"] = MapInsert,
["Update"] = MapUpdate
};
public static CommandMapper<ILayout, LayoutHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
["Add"] = MapAdd,
["Remove"] = MapRemove,
["Clear"] = MapClear,
["Insert"] = MapInsert,
["Update"] = MapUpdate,
};
public LayoutHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public LayoutHandler() : base(Mapper, CommandMapper)
{
}
public LayoutHandler(IPropertyMapper? mapper = null, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
public LayoutHandler(IPropertyMapper? mapper = null, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override SkiaLayoutView CreatePlatformView()
{
return new SkiaStackLayout();
}
protected override SkiaLayoutView CreatePlatformView()
{
return new SkiaStackLayout();
}
protected override void ConnectHandler(SkiaLayoutView platformView)
{
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
base.ConnectHandler(platformView);
if (base.VirtualView == null || ((ElementHandler)this).MauiContext == null)
{
return;
}
ILayout virtualView = base.VirtualView;
VisualElement val = (VisualElement)(object)((virtualView is VisualElement) ? virtualView : null);
if (val != null && val.BackgroundColor != null)
{
platformView.BackgroundColor = val.BackgroundColor.ToSKColor();
}
for (int i = 0; i < ((ICollection<IView>)base.VirtualView).Count; i++)
{
IView val2 = ((IList<IView>)base.VirtualView)[i];
if (val2 != null)
{
if (val2.Handler == null)
{
val2.Handler = val2.ToViewHandler(((ElementHandler)this).MauiContext);
}
IViewHandler handler = val2.Handler;
if (((handler != null) ? ((IElementHandler)handler).PlatformView : null) is SkiaView child)
{
platformView.AddChild(child);
}
}
}
}
protected override void ConnectHandler(SkiaLayoutView platformView)
{
base.ConnectHandler(platformView);
public static void MapClipsToBounds(LayoutHandler handler, ILayout layout)
{
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView != null)
{
((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView.ClipToBounds = layout.ClipsToBounds;
}
}
// Create handlers for all children and add them to the platform view
if (VirtualView == null || MauiContext == null) return;
public static void MapBackground(LayoutHandler handler, ILayout layout)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView != null)
{
Paint background = ((IView)layout).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
// Explicitly map BackgroundColor since it may be set before handler creation
if (VirtualView is Microsoft.Maui.Controls.VisualElement ve && ve.BackgroundColor != null)
{
platformView.BackgroundColor = ve.BackgroundColor.ToSKColor();
}
public static void MapAdd(LayoutHandler handler, ILayout layout, object? arg)
{
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView == null || !(arg is LayoutHandlerUpdate { Index: var index } layoutHandlerUpdate))
{
return;
}
IView? view = layoutHandlerUpdate.View;
object obj;
if (view == null)
{
obj = null;
}
else
{
IViewHandler handler2 = view.Handler;
obj = ((handler2 != null) ? ((IElementHandler)handler2).PlatformView : null);
}
if (obj is SkiaView child)
{
if (index >= 0 && index < ((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView.Children.Count)
{
((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView.InsertChild(index, child);
}
else
{
((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView.AddChild(child);
}
}
}
for (int i = 0; i < VirtualView.Count; i++)
{
var child = VirtualView[i];
if (child == null) continue;
public static void MapRemove(LayoutHandler handler, ILayout layout, object? arg)
{
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView != null && arg is LayoutHandlerUpdate { Index: var index } && index >= 0 && index < ((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView.Children.Count)
{
((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView.RemoveChildAt(index);
}
}
// Create handler for child if it doesn't exist
if (child.Handler == null)
{
child.Handler = child.ToHandler(MauiContext);
}
public static void MapClear(LayoutHandler handler, ILayout layout, object? arg)
{
((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView?.ClearChildren();
}
// Add child's platform view to our layout
if (child.Handler?.PlatformView is SkiaView skiaChild)
{
platformView.AddChild(skiaChild);
}
}
}
public static void MapInsert(LayoutHandler handler, ILayout layout, object? arg)
{
MapAdd(handler, layout, arg);
}
public static void MapClipsToBounds(LayoutHandler handler, ILayout layout)
{
if (handler.PlatformView == null) return;
handler.PlatformView.ClipToBounds = layout.ClipsToBounds;
}
public static void MapUpdate(LayoutHandler handler, ILayout layout, object? arg)
{
((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView?.InvalidateMeasure();
}
public static void MapBackground(LayoutHandler handler, ILayout layout)
{
if (handler.PlatformView is null) return;
public static void MapPadding(LayoutHandler handler, ILayout layout)
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView != null)
{
if (layout != null)
{
Thickness padding = ((IPadding)layout).Padding;
((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView.Padding = new SKRect((float)((Thickness)(ref padding)).Left, (float)((Thickness)(ref padding)).Top, (float)((Thickness)(ref padding)).Right, (float)((Thickness)(ref padding)).Bottom);
((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView.InvalidateMeasure();
((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView.Invalidate();
}
}
}
if (layout.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapAdd(LayoutHandler handler, ILayout layout, object? arg)
{
if (handler.PlatformView == null || arg is not LayoutHandlerUpdate update)
return;
var index = update.Index;
var child = update.View;
if (child?.Handler?.PlatformView is SkiaView skiaView)
{
if (index >= 0 && index < handler.PlatformView.Children.Count)
handler.PlatformView.InsertChild(index, skiaView);
else
handler.PlatformView.AddChild(skiaView);
}
}
public static void MapRemove(LayoutHandler handler, ILayout layout, object? arg)
{
if (handler.PlatformView == null || arg is not LayoutHandlerUpdate update)
return;
var index = update.Index;
if (index >= 0 && index < handler.PlatformView.Children.Count)
{
handler.PlatformView.RemoveChildAt(index);
}
}
public static void MapClear(LayoutHandler handler, ILayout layout, object? arg)
{
handler.PlatformView?.ClearChildren();
}
public static void MapInsert(LayoutHandler handler, ILayout layout, object? arg)
{
MapAdd(handler, layout, arg);
}
public static void MapUpdate(LayoutHandler handler, ILayout layout, object? arg)
{
// Force re-layout
handler.PlatformView?.InvalidateMeasure();
}
public static void MapPadding(LayoutHandler handler, ILayout layout)
{
if (handler.PlatformView == null) return;
if (layout is IPadding paddable)
{
var padding = paddable.Padding;
handler.PlatformView.Padding = new SKRect(
(float)padding.Left,
(float)padding.Top,
(float)padding.Right,
(float)padding.Bottom);
handler.PlatformView.InvalidateMeasure();
handler.PlatformView.Invalidate();
}
}
}
/// <summary>
/// Update payload for layout changes.
/// </summary>
public class LayoutHandlerUpdate
{
public int Index { get; }
public IView? View { get; }
public LayoutHandlerUpdate(int index, IView? view)
{
Index = index;
View = view;
}
}
/// <summary>
/// Handler for StackLayout on Linux.
/// </summary>
public partial class StackLayoutHandler : LayoutHandler
{
public static new IPropertyMapper<IStackLayout, StackLayoutHandler> Mapper = new PropertyMapper<IStackLayout, StackLayoutHandler>(LayoutHandler.Mapper)
{
[nameof(IStackLayout.Spacing)] = MapSpacing,
};
public StackLayoutHandler() : base(Mapper)
{
}
protected override SkiaLayoutView CreatePlatformView()
{
return new SkiaStackLayout();
}
protected override void ConnectHandler(SkiaLayoutView platformView)
{
// Set orientation first
if (platformView is SkiaStackLayout stackLayout && VirtualView is IStackLayout stackView)
{
// Determine orientation based on view type
if (VirtualView is Microsoft.Maui.Controls.HorizontalStackLayout)
{
stackLayout.Orientation = StackOrientation.Horizontal;
}
else if (VirtualView is Microsoft.Maui.Controls.VerticalStackLayout ||
VirtualView is Microsoft.Maui.Controls.StackLayout)
{
stackLayout.Orientation = StackOrientation.Vertical;
}
stackLayout.Spacing = (float)stackView.Spacing;
}
// Let base handle children
base.ConnectHandler(platformView);
}
public static void MapSpacing(StackLayoutHandler handler, IStackLayout layout)
{
if (handler.PlatformView is SkiaStackLayout stackLayout)
{
stackLayout.Spacing = (float)layout.Spacing;
}
}
}
/// <summary>
/// Handler for Grid on Linux.
/// </summary>
public partial class GridHandler : LayoutHandler
{
public static new IPropertyMapper<IGridLayout, GridHandler> Mapper = new PropertyMapper<IGridLayout, GridHandler>(LayoutHandler.Mapper)
{
[nameof(IGridLayout.RowSpacing)] = MapRowSpacing,
[nameof(IGridLayout.ColumnSpacing)] = MapColumnSpacing,
[nameof(IGridLayout.RowDefinitions)] = MapRowDefinitions,
[nameof(IGridLayout.ColumnDefinitions)] = MapColumnDefinitions,
};
public GridHandler() : base(Mapper)
{
}
protected override SkiaLayoutView CreatePlatformView()
{
return new SkiaGrid();
}
protected override void ConnectHandler(SkiaLayoutView platformView)
{
try
{
// Don't call base - we handle children specially for Grid
if (VirtualView is not IGridLayout gridLayout || MauiContext == null || platformView is not SkiaGrid grid) return;
Console.WriteLine($"[GridHandler] ConnectHandler: {gridLayout.Count} children, {gridLayout.RowDefinitions.Count} rows, {gridLayout.ColumnDefinitions.Count} cols");
// Explicitly map BackgroundColor since it may be set before handler creation
if (VirtualView is Microsoft.Maui.Controls.VisualElement ve && ve.BackgroundColor != null)
{
platformView.BackgroundColor = ve.BackgroundColor.ToSKColor();
}
// Explicitly map Padding since it may be set before handler creation
if (VirtualView is IPadding paddable)
{
var padding = paddable.Padding;
platformView.Padding = new SKRect(
(float)padding.Left,
(float)padding.Top,
(float)padding.Right,
(float)padding.Bottom);
Console.WriteLine($"[GridHandler] Applied Padding: L={padding.Left}, T={padding.Top}, R={padding.Right}, B={padding.Bottom}");
}
// Map row/column definitions first
MapRowDefinitions(this, gridLayout);
MapColumnDefinitions(this, gridLayout);
// Add each child with its row/column position
for (int i = 0; i < gridLayout.Count; i++)
{
var child = gridLayout[i];
if (child == null) continue;
Console.WriteLine($"[GridHandler] Processing child {i}: {child.GetType().Name}");
// Create handler for child if it doesn't exist
if (child.Handler == null)
{
child.Handler = child.ToHandler(MauiContext);
}
// Get grid position from attached properties
int row = 0, column = 0, rowSpan = 1, columnSpan = 1;
if (child is Microsoft.Maui.Controls.View mauiView)
{
row = Microsoft.Maui.Controls.Grid.GetRow(mauiView);
column = Microsoft.Maui.Controls.Grid.GetColumn(mauiView);
rowSpan = Microsoft.Maui.Controls.Grid.GetRowSpan(mauiView);
columnSpan = Microsoft.Maui.Controls.Grid.GetColumnSpan(mauiView);
}
Console.WriteLine($"[GridHandler] Child {i} at row={row}, col={column}, handler={child.Handler?.GetType().Name}");
// Add child's platform view to our grid
if (child.Handler?.PlatformView is SkiaView skiaChild)
{
grid.AddChild(skiaChild, row, column, rowSpan, columnSpan);
Console.WriteLine($"[GridHandler] Added child {i} to grid");
}
}
Console.WriteLine($"[GridHandler] ConnectHandler complete");
}
catch (Exception ex)
{
Console.WriteLine($"[GridHandler] EXCEPTION in ConnectHandler: {ex.GetType().Name}: {ex.Message}");
Console.WriteLine($"[GridHandler] Stack trace: {ex.StackTrace}");
throw;
}
}
public static void MapRowSpacing(GridHandler handler, IGridLayout layout)
{
if (handler.PlatformView is SkiaGrid grid)
{
grid.RowSpacing = (float)layout.RowSpacing;
}
}
public static void MapColumnSpacing(GridHandler handler, IGridLayout layout)
{
if (handler.PlatformView is SkiaGrid grid)
{
grid.ColumnSpacing = (float)layout.ColumnSpacing;
}
}
public static void MapRowDefinitions(GridHandler handler, IGridLayout layout)
{
if (handler.PlatformView is not SkiaGrid grid) return;
grid.RowDefinitions.Clear();
foreach (var rowDef in layout.RowDefinitions)
{
var height = rowDef.Height;
if (height.IsAbsolute)
grid.RowDefinitions.Add(new Microsoft.Maui.Platform.GridLength((float)height.Value, Microsoft.Maui.Platform.GridUnitType.Absolute));
else if (height.IsAuto)
grid.RowDefinitions.Add(Microsoft.Maui.Platform.GridLength.Auto);
else // Star
grid.RowDefinitions.Add(new Microsoft.Maui.Platform.GridLength((float)height.Value, Microsoft.Maui.Platform.GridUnitType.Star));
}
}
public static void MapColumnDefinitions(GridHandler handler, IGridLayout layout)
{
if (handler.PlatformView is not SkiaGrid grid) return;
grid.ColumnDefinitions.Clear();
foreach (var colDef in layout.ColumnDefinitions)
{
var width = colDef.Width;
if (width.IsAbsolute)
grid.ColumnDefinitions.Add(new Microsoft.Maui.Platform.GridLength((float)width.Value, Microsoft.Maui.Platform.GridUnitType.Absolute));
else if (width.IsAuto)
grid.ColumnDefinitions.Add(Microsoft.Maui.Platform.GridLength.Auto);
else // Star
grid.ColumnDefinitions.Add(new Microsoft.Maui.Platform.GridLength((float)width.Value, Microsoft.Maui.Platform.GridUnitType.Star));
}
}
}

View File

@@ -1,14 +0,0 @@
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class LayoutHandlerUpdate
{
public int Index { get; }
public IView? View { get; }
public LayoutHandlerUpdate(int index, IView? view)
{
Index = index;
View = view;
}
}

View File

@@ -1,64 +0,0 @@
using System.Collections.Generic;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class LinuxApplicationContext
{
private readonly List<IWindow> _windows = new List<IWindow>();
private IApplication? _application;
public IApplication? Application
{
get
{
return _application;
}
set
{
_application = value;
if (_application == null)
{
return;
}
foreach (IWindow window in _application.Windows)
{
if (!_windows.Contains(window))
{
_windows.Add(window);
}
}
}
}
public IReadOnlyList<IWindow> Windows => _windows;
public IWindow? MainWindow
{
get
{
if (_windows.Count <= 0)
{
return null;
}
return _windows[0];
}
}
public void OpenWindow(IWindow window)
{
if (!_windows.Contains(window))
{
_windows.Add(window);
}
}
public void CloseWindow(IWindow window)
{
_windows.Remove(window);
if (_windows.Count == 0)
{
LinuxApplication.Current?.MainWindow?.Stop();
}
}
}

View File

@@ -1,448 +1,381 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using Microsoft.Maui.Controls;
// 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.Handlers;
using Microsoft.Maui.Platform.Linux.Hosting;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using SkiaSharp;
using Svg.Skia;
using System.Collections.Specialized;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class NavigationPageHandler : ViewHandler<NavigationPage, SkiaNavigationPage>
/// <summary>
/// Handler for NavigationPage on Linux using Skia rendering.
/// </summary>
public partial class NavigationPageHandler : ViewHandler<NavigationPage, SkiaNavigationPage>
{
public static IPropertyMapper<NavigationPage, NavigationPageHandler> Mapper = (IPropertyMapper<NavigationPage, NavigationPageHandler>)(object)new PropertyMapper<NavigationPage, NavigationPageHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["BarBackgroundColor"] = MapBarBackgroundColor,
["BarBackground"] = MapBarBackground,
["BarTextColor"] = MapBarTextColor,
["Background"] = MapBackground
};
public static IPropertyMapper<NavigationPage, NavigationPageHandler> Mapper =
new PropertyMapper<NavigationPage, NavigationPageHandler>(ViewHandler.ViewMapper)
{
[nameof(NavigationPage.BarBackgroundColor)] = MapBarBackgroundColor,
[nameof(NavigationPage.BarBackground)] = MapBarBackground,
[nameof(NavigationPage.BarTextColor)] = MapBarTextColor,
[nameof(IView.Background)] = MapBackground,
};
public static CommandMapper<NavigationPage, NavigationPageHandler> CommandMapper = new CommandMapper<NavigationPage, NavigationPageHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper) { ["RequestNavigation"] = MapRequestNavigation };
public static CommandMapper<NavigationPage, NavigationPageHandler> CommandMapper =
new(ViewHandler.ViewCommandMapper)
{
[nameof(IStackNavigationView.RequestNavigation)] = MapRequestNavigation,
};
private readonly Dictionary<Page, (SkiaPage, INotifyCollectionChanged)> _toolbarSubscriptions = new Dictionary<Page, (SkiaPage, INotifyCollectionChanged)>();
public NavigationPageHandler() : base(Mapper, CommandMapper)
{
}
public NavigationPageHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public NavigationPageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
public NavigationPageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
protected override SkiaNavigationPage CreatePlatformView()
{
return new SkiaNavigationPage();
}
protected override SkiaNavigationPage CreatePlatformView()
{
return new SkiaNavigationPage();
}
protected override void ConnectHandler(SkiaNavigationPage platformView)
{
base.ConnectHandler(platformView);
platformView.Pushed += OnPushed;
platformView.Popped += OnPopped;
platformView.PoppedToRoot += OnPoppedToRoot;
protected override void ConnectHandler(SkiaNavigationPage platformView)
{
base.ConnectHandler(platformView);
platformView.Pushed += OnPushed;
platformView.Popped += OnPopped;
platformView.PoppedToRoot += OnPoppedToRoot;
if (base.VirtualView != null)
{
base.VirtualView.Pushed += OnVirtualViewPushed;
base.VirtualView.Popped += OnVirtualViewPopped;
base.VirtualView.PoppedToRoot += OnVirtualViewPoppedToRoot;
SetupNavigationStack();
}
}
// Subscribe to navigation events from virtual view
if (VirtualView != null)
{
VirtualView.Pushed += OnVirtualViewPushed;
VirtualView.Popped += OnVirtualViewPopped;
VirtualView.PoppedToRoot += OnVirtualViewPoppedToRoot;
protected override void DisconnectHandler(SkiaNavigationPage platformView)
{
platformView.Pushed -= OnPushed;
platformView.Popped -= OnPopped;
platformView.PoppedToRoot -= OnPoppedToRoot;
if (base.VirtualView != null)
{
base.VirtualView.Pushed -= OnVirtualViewPushed;
base.VirtualView.Popped -= OnVirtualViewPopped;
base.VirtualView.PoppedToRoot -= OnVirtualViewPoppedToRoot;
}
base.DisconnectHandler(platformView);
}
// Set up initial navigation stack
SetupNavigationStack();
}
}
private void SetupNavigationStack()
{
//IL_017a: Unknown result type (might be due to invalid IL or missing references)
//IL_018c: Unknown result type (might be due to invalid IL or missing references)
if (base.VirtualView == null || base.PlatformView == null || ((ElementHandler)this).MauiContext == null)
{
return;
}
List<Page> list = ((NavigableElement)base.VirtualView).Navigation.NavigationStack.ToList();
Console.WriteLine($"[NavigationPageHandler] Setting up {list.Count} pages");
if (list.Count == 0 && base.VirtualView.CurrentPage != null)
{
Console.WriteLine("[NavigationPageHandler] No pages in stack, using CurrentPage: " + base.VirtualView.CurrentPage.Title);
list.Add(base.VirtualView.CurrentPage);
}
foreach (Page item in list)
{
if (((VisualElement)item).Handler == null)
{
Console.WriteLine("[NavigationPageHandler] Creating handler for: " + item.Title);
((VisualElement)item).Handler = ((IView)(object)item).ToViewHandler(((ElementHandler)this).MauiContext);
}
Console.WriteLine("[NavigationPageHandler] Page handler type: " + ((object)((VisualElement)item).Handler)?.GetType().Name);
IViewHandler handler = ((VisualElement)item).Handler;
Console.WriteLine("[NavigationPageHandler] Page PlatformView type: " + ((handler == null) ? null : ((IElementHandler)handler).PlatformView?.GetType().Name));
IViewHandler handler2 = ((VisualElement)item).Handler;
if (((handler2 != null) ? ((IElementHandler)handler2).PlatformView : null) is SkiaPage skiaPage)
{
skiaPage.ShowNavigationBar = true;
skiaPage.TitleBarColor = base.PlatformView.BarBackgroundColor;
skiaPage.TitleTextColor = base.PlatformView.BarTextColor;
skiaPage.Title = item.Title ?? "";
Console.WriteLine("[NavigationPageHandler] SkiaPage content: " + (((object)skiaPage.Content)?.GetType().Name ?? "null"));
if (skiaPage.Content == null)
{
ContentPage val = (ContentPage)(object)((item is ContentPage) ? item : null);
if (val != null && val.Content != null)
{
Console.WriteLine("[NavigationPageHandler] Content is null, manually creating handler for: " + ((object)val.Content).GetType().Name);
if (((VisualElement)val.Content).Handler == null)
{
((VisualElement)val.Content).Handler = ((IView)(object)val.Content).ToViewHandler(((ElementHandler)this).MauiContext);
}
IViewHandler handler3 = ((VisualElement)val.Content).Handler;
if (((handler3 != null) ? ((IElementHandler)handler3).PlatformView : null) is SkiaView skiaView)
{
skiaPage.Content = skiaView;
Console.WriteLine("[NavigationPageHandler] Set content to: " + ((object)skiaView).GetType().Name);
}
}
}
MapToolbarItems(skiaPage, item);
if (base.PlatformView.StackDepth == 0)
{
Console.WriteLine("[NavigationPageHandler] Setting root page: " + item.Title);
base.PlatformView.SetRootPage(skiaPage);
}
else
{
Console.WriteLine("[NavigationPageHandler] Pushing page: " + item.Title);
base.PlatformView.Push(skiaPage, animated: false);
}
}
else
{
Console.WriteLine("[NavigationPageHandler] Failed to get SkiaPage for: " + item.Title);
}
}
}
protected override void DisconnectHandler(SkiaNavigationPage platformView)
{
platformView.Pushed -= OnPushed;
platformView.Popped -= OnPopped;
platformView.PoppedToRoot -= OnPoppedToRoot;
private void MapToolbarItems(SkiaPage skiaPage, Page page)
{
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
//IL_0119: Unknown result type (might be due to invalid IL or missing references)
//IL_011f: Invalid comparison between Unknown and I4
if (!(skiaPage is SkiaContentPage skiaContentPage))
{
return;
}
Console.WriteLine($"[NavigationPageHandler] MapToolbarItems for '{page.Title}', count={page.ToolbarItems.Count}");
skiaContentPage.ToolbarItems.Clear();
foreach (ToolbarItem toolbarItem2 in page.ToolbarItems)
{
Console.WriteLine($"[NavigationPageHandler] Adding toolbar item: '{((MenuItem)toolbarItem2).Text}', IconImageSource={((MenuItem)toolbarItem2).IconImageSource}, Order={toolbarItem2.Order}");
SkiaToolbarItemOrder order = (((int)toolbarItem2.Order == 2) ? SkiaToolbarItemOrder.Secondary : SkiaToolbarItemOrder.Primary);
ToolbarItem toolbarItem = toolbarItem2;
RelayCommand command = new RelayCommand(delegate
{
Console.WriteLine("[NavigationPageHandler] ToolbarItem '" + ((MenuItem)toolbarItem).Text + "' clicked, invoking...");
IMenuItemController val2 = (IMenuItemController)(object)toolbarItem;
if (val2 != null)
{
val2.Activate();
}
else
{
((MenuItem)toolbarItem).Command?.Execute(((MenuItem)toolbarItem).CommandParameter);
}
});
SKBitmap icon = null;
ImageSource iconImageSource = ((MenuItem)toolbarItem2).IconImageSource;
FileImageSource val = (FileImageSource)(object)((iconImageSource is FileImageSource) ? iconImageSource : null);
if (val != null && !string.IsNullOrEmpty(val.File))
{
icon = LoadToolbarIcon(val.File);
}
skiaContentPage.ToolbarItems.Add(new SkiaToolbarItem
{
Text = (((MenuItem)toolbarItem2).Text ?? ""),
Icon = icon,
Order = order,
Command = command
});
}
if (page.ToolbarItems is INotifyCollectionChanged notifyCollectionChanged && !_toolbarSubscriptions.ContainsKey(page))
{
Console.WriteLine("[NavigationPageHandler] Subscribing to ToolbarItems changes for '" + page.Title + "'");
notifyCollectionChanged.CollectionChanged += delegate(object? s, NotifyCollectionChangedEventArgs e)
{
Console.WriteLine($"[NavigationPageHandler] ToolbarItems changed for '{page.Title}', action={e.Action}");
MapToolbarItems(skiaPage, page);
skiaPage.Invalidate();
};
_toolbarSubscriptions[page] = (skiaPage, notifyCollectionChanged);
}
}
if (VirtualView != null)
{
VirtualView.Pushed -= OnVirtualViewPushed;
VirtualView.Popped -= OnVirtualViewPopped;
VirtualView.PoppedToRoot -= OnVirtualViewPoppedToRoot;
}
private SKBitmap? LoadToolbarIcon(string fileName)
{
//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: Expected O, but got Unknown
//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
//IL_0122: Expected O, but got Unknown
//IL_0124: Unknown result type (might be due to invalid IL or missing references)
//IL_012b: Expected O, but got Unknown
//IL_012d: Unknown result type (might be due to invalid IL or missing references)
try
{
string baseDirectory = AppContext.BaseDirectory;
string text = Path.Combine(baseDirectory, fileName);
string text2 = Path.Combine(baseDirectory, Path.ChangeExtension(fileName, ".svg"));
Console.WriteLine("[NavigationPageHandler] LoadToolbarIcon: Looking for " + fileName);
Console.WriteLine($"[NavigationPageHandler] Trying PNG: {text} (exists: {File.Exists(text)})");
Console.WriteLine($"[NavigationPageHandler] Trying SVG: {text2} (exists: {File.Exists(text2)})");
if (File.Exists(text2))
{
SKSvg val = new SKSvg();
try
{
val.Load(text2);
if (val.Picture != null)
{
SKRect cullRect = val.Picture.CullRect;
float num = 24f / Math.Max(((SKRect)(ref cullRect)).Width, ((SKRect)(ref cullRect)).Height);
SKBitmap val2 = new SKBitmap(24, 24, false);
SKCanvas val3 = new SKCanvas(val2);
try
{
val3.Clear(SKColors.Transparent);
val3.Scale(num);
val3.DrawPicture(val.Picture, (SKPaint)null);
Console.WriteLine("[NavigationPageHandler] Loaded SVG icon: " + text2);
return val2;
}
finally
{
((IDisposable)val3)?.Dispose();
}
}
}
finally
{
((IDisposable)val)?.Dispose();
}
}
if (File.Exists(text))
{
using (FileStream fileStream = File.OpenRead(text))
{
SKBitmap result = SKBitmap.Decode((Stream)fileStream);
Console.WriteLine("[NavigationPageHandler] Loaded PNG icon: " + text);
return result;
}
}
Console.WriteLine("[NavigationPageHandler] Icon not found: " + fileName);
return null;
}
catch (Exception ex)
{
Console.WriteLine("[NavigationPageHandler] Error loading icon " + fileName + ": " + ex.Message);
return null;
}
}
base.DisconnectHandler(platformView);
}
private void OnVirtualViewPushed(object? sender, NavigationEventArgs e)
{
//IL_0111: Unknown result type (might be due to invalid IL or missing references)
//IL_0122: Unknown result type (might be due to invalid IL or missing references)
try
{
Page page = e.Page;
Console.WriteLine("[NavigationPageHandler] VirtualView Pushed: " + ((page != null) ? page.Title : null));
if (e.Page == null || base.PlatformView == null || ((ElementHandler)this).MauiContext == null)
{
return;
}
if (((VisualElement)e.Page).Handler == null)
{
Console.WriteLine("[NavigationPageHandler] Creating handler for page: " + ((object)e.Page).GetType().Name);
((VisualElement)e.Page).Handler = ((IView)(object)e.Page).ToViewHandler(((ElementHandler)this).MauiContext);
Console.WriteLine("[NavigationPageHandler] Handler created: " + ((object)((VisualElement)e.Page).Handler)?.GetType().Name);
}
IViewHandler handler = ((VisualElement)e.Page).Handler;
if (((handler != null) ? ((IElementHandler)handler).PlatformView : null) is SkiaPage skiaPage)
{
Console.WriteLine("[NavigationPageHandler] Setting up skiaPage, content: " + (((object)skiaPage.Content)?.GetType().Name ?? "null"));
skiaPage.ShowNavigationBar = true;
skiaPage.TitleBarColor = base.PlatformView.BarBackgroundColor;
skiaPage.TitleTextColor = base.PlatformView.BarTextColor;
skiaPage.Title = e.Page.Title ?? "";
if (skiaPage.Content == null)
{
Page page2 = e.Page;
ContentPage val = (ContentPage)(object)((page2 is ContentPage) ? page2 : null);
if (val != null && val.Content != null)
{
Console.WriteLine("[NavigationPageHandler] Content is null, creating handler for: " + ((object)val.Content).GetType().Name);
if (((VisualElement)val.Content).Handler == null)
{
((VisualElement)val.Content).Handler = ((IView)(object)val.Content).ToViewHandler(((ElementHandler)this).MauiContext);
}
IViewHandler handler2 = ((VisualElement)val.Content).Handler;
if (((handler2 != null) ? ((IElementHandler)handler2).PlatformView : null) is SkiaView skiaView)
{
skiaPage.Content = skiaView;
Console.WriteLine("[NavigationPageHandler] Set content to: " + ((object)skiaView).GetType().Name);
}
}
}
Console.WriteLine("[NavigationPageHandler] Mapping toolbar items");
MapToolbarItems(skiaPage, e.Page);
Console.WriteLine("[NavigationPageHandler] Pushing page to platform");
base.PlatformView.Push(skiaPage, animated: false);
Console.WriteLine($"[NavigationPageHandler] Push complete, thread={Environment.CurrentManagedThreadId}");
}
Console.WriteLine("[NavigationPageHandler] OnVirtualViewPushed returning");
}
catch (Exception ex)
{
Console.WriteLine("[NavigationPageHandler] EXCEPTION in OnVirtualViewPushed: " + ex.GetType().Name + ": " + ex.Message);
Console.WriteLine("[NavigationPageHandler] Stack trace: " + ex.StackTrace);
throw;
}
}
private void SetupNavigationStack()
{
if (VirtualView == null || PlatformView == null || MauiContext == null) return;
private void OnVirtualViewPopped(object? sender, NavigationEventArgs e)
{
Page page = e.Page;
Console.WriteLine("[NavigationPageHandler] VirtualView Popped: " + ((page != null) ? page.Title : null));
base.PlatformView?.Pop();
}
// Get all pages in the navigation stack
var pages = VirtualView.Navigation.NavigationStack.ToList();
Console.WriteLine($"[NavigationPageHandler] Setting up {pages.Count} pages");
private void OnVirtualViewPoppedToRoot(object? sender, NavigationEventArgs e)
{
Console.WriteLine("[NavigationPageHandler] VirtualView PoppedToRoot");
base.PlatformView?.PopToRoot();
}
// If no pages in stack, check CurrentPage
if (pages.Count == 0 && VirtualView.CurrentPage != null)
{
Console.WriteLine($"[NavigationPageHandler] No pages in stack, using CurrentPage: {VirtualView.CurrentPage.Title}");
pages.Add(VirtualView.CurrentPage);
}
private void OnPushed(object? sender, NavigationEventArgs e)
{
}
foreach (var page in pages)
{
// Ensure the page has a handler
if (page.Handler == null)
{
Console.WriteLine($"[NavigationPageHandler] Creating handler for: {page.Title}");
page.Handler = page.ToHandler(MauiContext);
}
private void OnPopped(object? sender, NavigationEventArgs e)
{
NavigationPage virtualView = base.VirtualView;
if (virtualView != null && ((NavigableElement)virtualView).Navigation.NavigationStack.Count > 1)
{
((NavigableElement)base.VirtualView).Navigation.RemovePage(((NavigableElement)base.VirtualView).Navigation.NavigationStack.Last());
}
}
Console.WriteLine($"[NavigationPageHandler] Page handler type: {page.Handler?.GetType().Name}");
Console.WriteLine($"[NavigationPageHandler] Page PlatformView type: {page.Handler?.PlatformView?.GetType().Name}");
private void OnPoppedToRoot(object? sender, NavigationEventArgs e)
{
}
if (page.Handler?.PlatformView is SkiaPage skiaPage)
{
// Set navigation bar properties
skiaPage.ShowNavigationBar = true;
skiaPage.TitleBarColor = PlatformView.BarBackgroundColor;
skiaPage.TitleTextColor = PlatformView.BarTextColor;
skiaPage.Title = page.Title ?? "";
public static void MapBarBackgroundColor(NavigationPageHandler handler, NavigationPage navigationPage)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView != null && navigationPage.BarBackgroundColor != null)
{
((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView.BarBackgroundColor = navigationPage.BarBackgroundColor.ToSKColor();
}
}
Console.WriteLine($"[NavigationPageHandler] SkiaPage content: {skiaPage.Content?.GetType().Name ?? "null"}");
public static void MapBarBackground(NavigationPageHandler handler, NavigationPage navigationPage)
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView != null)
{
Brush barBackground = navigationPage.BarBackground;
SolidColorBrush val = (SolidColorBrush)(object)((barBackground is SolidColorBrush) ? barBackground : null);
if (val != null)
{
((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView.BarBackgroundColor = val.Color.ToSKColor();
}
}
}
// If content is null, try to get it from ContentPage
if (skiaPage.Content == null && page is ContentPage contentPage && contentPage.Content != null)
{
Console.WriteLine($"[NavigationPageHandler] Content is null, manually creating handler for: {contentPage.Content.GetType().Name}");
if (contentPage.Content.Handler == null)
{
contentPage.Content.Handler = contentPage.Content.ToHandler(MauiContext);
}
if (contentPage.Content.Handler?.PlatformView is SkiaView skiaContent)
{
skiaPage.Content = skiaContent;
Console.WriteLine($"[NavigationPageHandler] Set content to: {skiaContent.GetType().Name}");
}
}
public static void MapBarTextColor(NavigationPageHandler handler, NavigationPage navigationPage)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView != null && navigationPage.BarTextColor != null)
{
((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView.BarTextColor = navigationPage.BarTextColor.ToSKColor();
}
}
// Map toolbar items
MapToolbarItems(skiaPage, page);
public static void MapBackground(NavigationPageHandler handler, NavigationPage navigationPage)
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView != null)
{
Brush background = ((VisualElement)navigationPage).Background;
SolidColorBrush val = (SolidColorBrush)(object)((background is SolidColorBrush) ? background : null);
if (val != null)
{
((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
if (PlatformView.StackDepth == 0)
{
Console.WriteLine($"[NavigationPageHandler] Setting root page: {page.Title}");
PlatformView.SetRootPage(skiaPage);
}
else
{
Console.WriteLine($"[NavigationPageHandler] Pushing page: {page.Title}");
PlatformView.Push(skiaPage, false);
}
}
else
{
Console.WriteLine($"[NavigationPageHandler] Failed to get SkiaPage for: {page.Title}");
}
}
}
public static void MapRequestNavigation(NavigationPageHandler handler, NavigationPage navigationPage, object? args)
{
//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView == null || ((ElementHandler)handler).MauiContext == null)
{
return;
}
NavigationRequest val = (NavigationRequest)((args is NavigationRequest) ? args : null);
if (val == null)
{
return;
}
Console.WriteLine($"[NavigationPageHandler] MapRequestNavigation: {val.NavigationStack.Count} pages");
foreach (IView item in val.NavigationStack)
{
Page val2 = (Page)(object)((item is Page) ? item : null);
if (val2 == null)
{
continue;
}
if (((VisualElement)val2).Handler == null)
{
((VisualElement)val2).Handler = ((IView)(object)val2).ToViewHandler(((ElementHandler)handler).MauiContext);
}
IViewHandler handler2 = ((VisualElement)val2).Handler;
if (((handler2 != null) ? ((IElementHandler)handler2).PlatformView : null) is SkiaPage skiaPage)
{
skiaPage.ShowNavigationBar = true;
skiaPage.TitleBarColor = ((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView.BarBackgroundColor;
skiaPage.TitleTextColor = ((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView.BarTextColor;
handler.MapToolbarItems(skiaPage, val2);
if (((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView.StackDepth == 0)
{
((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView.SetRootPage(skiaPage);
}
else
{
((ViewHandler<NavigationPage, SkiaNavigationPage>)(object)handler).PlatformView.Push(skiaPage, val.Animated);
}
}
}
}
private readonly Dictionary<Page, (SkiaPage, INotifyCollectionChanged)> _toolbarSubscriptions = new();
private void MapToolbarItems(SkiaPage skiaPage, Page page)
{
if (skiaPage is SkiaContentPage contentPage)
{
Console.WriteLine($"[NavigationPageHandler] MapToolbarItems for '{page.Title}', count={page.ToolbarItems.Count}");
contentPage.ToolbarItems.Clear();
foreach (var item in page.ToolbarItems)
{
Console.WriteLine($"[NavigationPageHandler] Adding toolbar item: '{item.Text}', Order={item.Order}");
// Default and Primary should both be treated as Primary (shown in toolbar)
// Only Secondary goes to overflow menu
var order = item.Order == ToolbarItemOrder.Secondary
? SkiaToolbarItemOrder.Secondary
: SkiaToolbarItemOrder.Primary;
// Create a command that invokes the Clicked event
var toolbarItem = item; // Capture for closure
var clickCommand = new RelayCommand(() =>
{
Console.WriteLine($"[NavigationPageHandler] ToolbarItem '{toolbarItem.Text}' clicked, invoking...");
// Use IMenuItemController to send the click
if (toolbarItem is IMenuItemController menuController)
{
menuController.Activate();
}
else
{
// Fallback: invoke Command if set
toolbarItem.Command?.Execute(toolbarItem.CommandParameter);
}
});
contentPage.ToolbarItems.Add(new SkiaToolbarItem
{
Text = item.Text ?? "",
Order = order,
Command = clickCommand
});
}
// Subscribe to ToolbarItems changes if not already subscribed
if (page.ToolbarItems is INotifyCollectionChanged notifyCollection && !_toolbarSubscriptions.ContainsKey(page))
{
Console.WriteLine($"[NavigationPageHandler] Subscribing to ToolbarItems changes for '{page.Title}'");
notifyCollection.CollectionChanged += (s, e) =>
{
Console.WriteLine($"[NavigationPageHandler] ToolbarItems changed for '{page.Title}', action={e.Action}");
MapToolbarItems(skiaPage, page);
skiaPage.Invalidate();
};
_toolbarSubscriptions[page] = (skiaPage, notifyCollection);
}
}
}
private void OnVirtualViewPushed(object? sender, Microsoft.Maui.Controls.NavigationEventArgs e)
{
try
{
Console.WriteLine($"[NavigationPageHandler] VirtualView Pushed: {e.Page?.Title}");
if (e.Page == null || PlatformView == null || MauiContext == null) return;
// Ensure the page has a handler
if (e.Page.Handler == null)
{
Console.WriteLine($"[NavigationPageHandler] Creating handler for page: {e.Page.GetType().Name}");
e.Page.Handler = e.Page.ToHandler(MauiContext);
Console.WriteLine($"[NavigationPageHandler] Handler created: {e.Page.Handler?.GetType().Name}");
}
if (e.Page.Handler?.PlatformView is SkiaPage skiaPage)
{
Console.WriteLine($"[NavigationPageHandler] Setting up skiaPage, content: {skiaPage.Content?.GetType().Name ?? "null"}");
skiaPage.ShowNavigationBar = true;
skiaPage.TitleBarColor = PlatformView.BarBackgroundColor;
skiaPage.TitleTextColor = PlatformView.BarTextColor;
Console.WriteLine($"[NavigationPageHandler] Mapping toolbar items");
MapToolbarItems(skiaPage, e.Page);
Console.WriteLine($"[NavigationPageHandler] Pushing page to platform");
PlatformView.Push(skiaPage, true);
Console.WriteLine($"[NavigationPageHandler] Push complete");
}
}
catch (Exception ex)
{
Console.WriteLine($"[NavigationPageHandler] EXCEPTION in OnVirtualViewPushed: {ex.GetType().Name}: {ex.Message}");
Console.WriteLine($"[NavigationPageHandler] Stack trace: {ex.StackTrace}");
throw;
}
}
private void OnVirtualViewPopped(object? sender, Microsoft.Maui.Controls.NavigationEventArgs e)
{
Console.WriteLine($"[NavigationPageHandler] VirtualView Popped: {e.Page?.Title}");
// Pop on the platform side to sync with MAUI navigation
PlatformView?.Pop(true);
}
private void OnVirtualViewPoppedToRoot(object? sender, Microsoft.Maui.Controls.NavigationEventArgs e)
{
Console.WriteLine($"[NavigationPageHandler] VirtualView PoppedToRoot");
PlatformView?.PopToRoot(true);
}
private void OnPushed(object? sender, NavigationEventArgs e)
{
// Navigation was completed on platform side
}
private void OnPopped(object? sender, NavigationEventArgs e)
{
// Sync back to virtual view - pop from MAUI navigation stack
if (VirtualView?.Navigation.NavigationStack.Count > 1)
{
// Don't trigger another pop on platform side
VirtualView.Navigation.RemovePage(VirtualView.Navigation.NavigationStack.Last());
}
}
private void OnPoppedToRoot(object? sender, NavigationEventArgs e)
{
// Navigation was reset
}
public static void MapBarBackgroundColor(NavigationPageHandler handler, NavigationPage navigationPage)
{
if (handler.PlatformView is null) return;
if (navigationPage.BarBackgroundColor is not null)
{
handler.PlatformView.BarBackgroundColor = navigationPage.BarBackgroundColor.ToSKColor();
}
}
public static void MapBarBackground(NavigationPageHandler handler, NavigationPage navigationPage)
{
if (handler.PlatformView is null) return;
if (navigationPage.BarBackground is SolidColorBrush solidBrush)
{
handler.PlatformView.BarBackgroundColor = solidBrush.Color.ToSKColor();
}
}
public static void MapBarTextColor(NavigationPageHandler handler, NavigationPage navigationPage)
{
if (handler.PlatformView is null) return;
if (navigationPage.BarTextColor is not null)
{
handler.PlatformView.BarTextColor = navigationPage.BarTextColor.ToSKColor();
}
}
public static void MapBackground(NavigationPageHandler handler, NavigationPage navigationPage)
{
if (handler.PlatformView is null) return;
if (navigationPage.Background is SolidColorBrush solidBrush)
{
handler.PlatformView.BackgroundColor = solidBrush.Color.ToSKColor();
}
}
public static void MapRequestNavigation(NavigationPageHandler handler, NavigationPage navigationPage, object? args)
{
if (handler.PlatformView is null || handler.MauiContext is null || args is not NavigationRequest request)
return;
Console.WriteLine($"[NavigationPageHandler] MapRequestNavigation: {request.NavigationStack.Count} pages");
// Handle navigation request
foreach (var view in request.NavigationStack)
{
if (view is not Page page) continue;
// Ensure handler exists
if (page.Handler == null)
{
page.Handler = page.ToHandler(handler.MauiContext);
}
if (page.Handler?.PlatformView is SkiaPage skiaPage)
{
skiaPage.ShowNavigationBar = true;
skiaPage.TitleBarColor = handler.PlatformView.BarBackgroundColor;
skiaPage.TitleTextColor = handler.PlatformView.BarTextColor;
handler.MapToolbarItems(skiaPage, page);
if (handler.PlatformView.StackDepth == 0)
{
handler.PlatformView.SetRootPage(skiaPage);
}
else
{
handler.PlatformView.Push(skiaPage, request.Animated);
}
}
}
}
}
/// <summary>
/// Simple relay command for invoking actions.
/// </summary>
internal class RelayCommand : System.Windows.Input.ICommand
{
private readonly Action _execute;
private readonly Func<bool>? _canExecute;
public RelayCommand(Action execute, Func<bool>? canExecute = null)
{
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
_canExecute = canExecute;
}
public event EventHandler? CanExecuteChanged;
public bool CanExecute(object? parameter) => _canExecute?.Invoke() ?? true;
public void Execute(object? parameter) => _execute();
public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}

View File

@@ -1,124 +1,166 @@
using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
// 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.Handlers;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class PageHandler : ViewHandler<Page, SkiaPage>
/// <summary>
/// Base handler for Page on Linux using Skia rendering.
/// </summary>
public partial class PageHandler : ViewHandler<Page, SkiaPage>
{
public static IPropertyMapper<Page, PageHandler> Mapper = (IPropertyMapper<Page, PageHandler>)(object)new PropertyMapper<Page, PageHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Title"] = MapTitle,
["BackgroundImageSource"] = MapBackgroundImageSource,
["Padding"] = MapPadding,
["Background"] = MapBackground,
["BackgroundColor"] = MapBackgroundColor
};
public static IPropertyMapper<Page, PageHandler> Mapper =
new PropertyMapper<Page, PageHandler>(ViewHandler.ViewMapper)
{
[nameof(Page.Title)] = MapTitle,
[nameof(Page.BackgroundImageSource)] = MapBackgroundImageSource,
[nameof(Page.Padding)] = MapPadding,
[nameof(IView.Background)] = MapBackground,
};
public static CommandMapper<Page, PageHandler> CommandMapper = new CommandMapper<Page, PageHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public static CommandMapper<Page, PageHandler> CommandMapper =
new(ViewHandler.ViewCommandMapper)
{
};
public PageHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public PageHandler() : base(Mapper, CommandMapper)
{
}
public PageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
public PageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override SkiaPage CreatePlatformView()
{
return new SkiaPage();
}
protected override SkiaPage CreatePlatformView()
{
return new SkiaPage();
}
protected override void ConnectHandler(SkiaPage platformView)
{
base.ConnectHandler(platformView);
platformView.Appearing += OnAppearing;
platformView.Disappearing += OnDisappearing;
}
protected override void ConnectHandler(SkiaPage platformView)
{
base.ConnectHandler(platformView);
platformView.Appearing += OnAppearing;
platformView.Disappearing += OnDisappearing;
}
protected override void DisconnectHandler(SkiaPage platformView)
{
platformView.Appearing -= OnAppearing;
platformView.Disappearing -= OnDisappearing;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaPage platformView)
{
platformView.Appearing -= OnAppearing;
platformView.Disappearing -= OnDisappearing;
base.DisconnectHandler(platformView);
}
private void OnAppearing(object? sender, EventArgs e)
{
Page virtualView = base.VirtualView;
Console.WriteLine("[PageHandler] OnAppearing received for: " + ((virtualView != null) ? virtualView.Title : null));
Page virtualView2 = base.VirtualView;
if (virtualView2 != null)
{
((IPageController)virtualView2).SendAppearing();
}
}
private void OnAppearing(object? sender, EventArgs e)
{
Console.WriteLine($"[PageHandler] OnAppearing received for: {VirtualView?.Title}");
(VirtualView as IPageController)?.SendAppearing();
}
private void OnDisappearing(object? sender, EventArgs e)
{
Page virtualView = base.VirtualView;
if (virtualView != null)
{
((IPageController)virtualView).SendDisappearing();
}
}
private void OnDisappearing(object? sender, EventArgs e)
{
(VirtualView as IPageController)?.SendDisappearing();
}
public static void MapTitle(PageHandler handler, Page page)
{
if (((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView != null)
{
((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView.Title = page.Title ?? "";
}
}
public static void MapTitle(PageHandler handler, Page page)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Title = page.Title ?? "";
}
public static void MapBackgroundImageSource(PageHandler handler, Page page)
{
((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView?.Invalidate();
}
public static void MapBackgroundImageSource(PageHandler handler, Page page)
{
// Background image would be loaded and set here
// For now, we just invalidate
handler.PlatformView?.Invalidate();
}
public static void MapPadding(PageHandler handler, Page page)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView != null)
{
Thickness padding = page.Padding;
((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView.PaddingLeft = (float)((Thickness)(ref padding)).Left;
((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView.PaddingTop = (float)((Thickness)(ref padding)).Top;
((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView.PaddingRight = (float)((Thickness)(ref padding)).Right;
((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView.PaddingBottom = (float)((Thickness)(ref padding)).Bottom;
}
}
public static void MapPadding(PageHandler handler, Page page)
{
if (handler.PlatformView is null) return;
public static void MapBackground(PageHandler handler, Page page)
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView != null)
{
Brush background = ((VisualElement)page).Background;
SolidColorBrush val = (SolidColorBrush)(object)((background is SolidColorBrush) ? background : null);
if (val != null)
{
((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
var padding = page.Padding;
handler.PlatformView.PaddingLeft = (float)padding.Left;
handler.PlatformView.PaddingTop = (float)padding.Top;
handler.PlatformView.PaddingRight = (float)padding.Right;
handler.PlatformView.PaddingBottom = (float)padding.Bottom;
}
public static void MapBackgroundColor(PageHandler handler, Page page)
{
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView != null)
{
Color backgroundColor = ((VisualElement)page).BackgroundColor;
if (backgroundColor != null && backgroundColor != Colors.Transparent)
{
((ViewHandler<Page, SkiaPage>)(object)handler).PlatformView.BackgroundColor = backgroundColor.ToSKColor();
Console.WriteLine($"[PageHandler] MapBackgroundColor: {backgroundColor}");
}
}
}
public static void MapBackground(PageHandler handler, Page page)
{
if (handler.PlatformView is null) return;
if (page.Background is SolidColorBrush solidBrush)
{
handler.PlatformView.BackgroundColor = solidBrush.Color.ToSKColor();
}
}
}
/// <summary>
/// Handler for ContentPage on Linux using Skia rendering.
/// </summary>
public partial class ContentPageHandler : PageHandler
{
public static new IPropertyMapper<ContentPage, ContentPageHandler> Mapper =
new PropertyMapper<ContentPage, ContentPageHandler>(PageHandler.Mapper)
{
[nameof(ContentPage.Content)] = MapContent,
};
public static new CommandMapper<ContentPage, ContentPageHandler> CommandMapper =
new(PageHandler.CommandMapper)
{
};
public ContentPageHandler() : base(Mapper, CommandMapper)
{
}
public ContentPageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override SkiaPage CreatePlatformView()
{
return new SkiaContentPage();
}
public static void MapContent(ContentPageHandler handler, ContentPage page)
{
if (handler.PlatformView is null || handler.MauiContext is null) return;
// Get the platform view for the content
var content = page.Content;
if (content != null)
{
// Create handler for content if it doesn't exist
if (content.Handler == null)
{
Console.WriteLine($"[ContentPageHandler] Creating handler for content: {content.GetType().Name}");
content.Handler = content.ToHandler(handler.MauiContext);
}
// The content's handler should provide the platform view
if (content.Handler?.PlatformView is SkiaView skiaContent)
{
Console.WriteLine($"[ContentPageHandler] Setting content: {skiaContent.GetType().Name}");
handler.PlatformView.Content = skiaContent;
}
else
{
Console.WriteLine($"[ContentPageHandler] Content handler PlatformView is not SkiaView: {content.Handler?.PlatformView?.GetType().Name ?? "null"}");
}
}
else
{
handler.PlatformView.Content = null;
}
}
}

View File

@@ -1,175 +1,161 @@
using System;
using System.Collections.Specialized;
using System.Linq;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
// 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.Handlers;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using SkiaSharp;
using System.Collections.Specialized;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class PickerHandler : ViewHandler<IPicker, SkiaPicker>
/// <summary>
/// Handler for Picker on Linux using Skia rendering.
/// </summary>
public partial class PickerHandler : ViewHandler<IPicker, SkiaPicker>
{
public static IPropertyMapper<IPicker, PickerHandler> Mapper = (IPropertyMapper<IPicker, PickerHandler>)(object)new PropertyMapper<IPicker, PickerHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Title"] = MapTitle,
["TitleColor"] = MapTitleColor,
["SelectedIndex"] = MapSelectedIndex,
["TextColor"] = MapTextColor,
["Font"] = MapFont,
["CharacterSpacing"] = MapCharacterSpacing,
["HorizontalTextAlignment"] = MapHorizontalTextAlignment,
["VerticalTextAlignment"] = MapVerticalTextAlignment,
["Background"] = MapBackground,
["ItemsSource"] = MapItemsSource
};
public static IPropertyMapper<IPicker, PickerHandler> Mapper =
new PropertyMapper<IPicker, PickerHandler>(ViewHandler.ViewMapper)
{
[nameof(IPicker.Title)] = MapTitle,
[nameof(IPicker.TitleColor)] = MapTitleColor,
[nameof(IPicker.SelectedIndex)] = MapSelectedIndex,
[nameof(IPicker.TextColor)] = MapTextColor,
[nameof(IPicker.CharacterSpacing)] = MapCharacterSpacing,
[nameof(IPicker.HorizontalTextAlignment)] = MapHorizontalTextAlignment,
[nameof(IPicker.VerticalTextAlignment)] = MapVerticalTextAlignment,
[nameof(IView.Background)] = MapBackground,
[nameof(Picker.ItemsSource)] = MapItemsSource,
};
public static CommandMapper<IPicker, PickerHandler> CommandMapper = new CommandMapper<IPicker, PickerHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public static CommandMapper<IPicker, PickerHandler> CommandMapper =
new(ViewHandler.ViewCommandMapper)
{
};
private INotifyCollectionChanged? _itemsCollection;
private INotifyCollectionChanged? _itemsCollection;
public PickerHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public PickerHandler() : base(Mapper, CommandMapper)
{
}
public PickerHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
public PickerHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override SkiaPicker CreatePlatformView()
{
return new SkiaPicker();
}
protected override SkiaPicker CreatePlatformView()
{
return new SkiaPicker();
}
protected override void ConnectHandler(SkiaPicker platformView)
{
base.ConnectHandler(platformView);
platformView.SelectedIndexChanged += OnSelectedIndexChanged;
IPicker virtualView = base.VirtualView;
Picker val = (Picker)(object)((virtualView is Picker) ? virtualView : null);
if (val != null && val.Items is INotifyCollectionChanged itemsCollection)
{
_itemsCollection = itemsCollection;
_itemsCollection.CollectionChanged += OnItemsCollectionChanged;
}
ReloadItems();
}
protected override void ConnectHandler(SkiaPicker platformView)
{
base.ConnectHandler(platformView);
platformView.SelectedIndexChanged += OnSelectedIndexChanged;
protected override void DisconnectHandler(SkiaPicker platformView)
{
platformView.SelectedIndexChanged -= OnSelectedIndexChanged;
if (_itemsCollection != null)
{
_itemsCollection.CollectionChanged -= OnItemsCollectionChanged;
_itemsCollection = null;
}
base.DisconnectHandler(platformView);
}
// Subscribe to items collection changes
if (VirtualView is Picker picker && picker.Items is INotifyCollectionChanged items)
{
_itemsCollection = items;
_itemsCollection.CollectionChanged += OnItemsCollectionChanged;
}
private void OnItemsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
ReloadItems();
}
// Load items
ReloadItems();
}
private void OnSelectedIndexChanged(object? sender, EventArgs e)
{
if (base.VirtualView != null && base.PlatformView != null)
{
base.VirtualView.SelectedIndex = base.PlatformView.SelectedIndex;
}
}
protected override void DisconnectHandler(SkiaPicker platformView)
{
platformView.SelectedIndexChanged -= OnSelectedIndexChanged;
private void ReloadItems()
{
if (base.PlatformView != null && base.VirtualView != null)
{
string[] itemsAsArray = IPickerExtension.GetItemsAsArray(base.VirtualView);
base.PlatformView.SetItems(itemsAsArray.Select((string i) => i?.ToString() ?? ""));
}
}
if (_itemsCollection != null)
{
_itemsCollection.CollectionChanged -= OnItemsCollectionChanged;
_itemsCollection = null;
}
public static void MapTitle(PickerHandler handler, IPicker picker)
{
if (((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView != null)
{
((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView.Title = picker.Title ?? "";
}
}
base.DisconnectHandler(platformView);
}
public static void MapTitleColor(PickerHandler handler, IPicker picker)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView != null && picker.TitleColor != null)
{
((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView.TitleColor = picker.TitleColor.ToSKColor();
}
}
private void OnItemsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{
ReloadItems();
}
public static void MapSelectedIndex(PickerHandler handler, IPicker picker)
{
if (((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView != null)
{
((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView.SelectedIndex = picker.SelectedIndex;
}
}
private void OnSelectedIndexChanged(object? sender, EventArgs e)
{
if (VirtualView is null || PlatformView is null) return;
public static void MapTextColor(PickerHandler handler, IPicker picker)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView != null && ((ITextStyle)picker).TextColor != null)
{
((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView.TextColor = ((ITextStyle)picker).TextColor.ToSKColor();
}
}
VirtualView.SelectedIndex = PlatformView.SelectedIndex;
}
public static void MapFont(PickerHandler handler, IPicker picker)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView != null)
{
Font font = ((ITextStyle)picker).Font;
if (!string.IsNullOrEmpty(((Font)(ref font)).Family))
{
((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView.FontFamily = ((Font)(ref font)).Family;
}
if (((Font)(ref font)).Size > 0.0)
{
((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView.FontSize = (float)((Font)(ref font)).Size;
}
((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView.Invalidate();
}
}
private void ReloadItems()
{
if (PlatformView is null || VirtualView is null) return;
public static void MapCharacterSpacing(PickerHandler handler, IPicker picker)
{
}
var items = VirtualView.GetItemsAsArray();
PlatformView.SetItems(items.Select(i => i?.ToString() ?? ""));
}
public static void MapHorizontalTextAlignment(PickerHandler handler, IPicker picker)
{
}
public static void MapTitle(PickerHandler handler, IPicker picker)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Title = picker.Title ?? "";
}
public static void MapVerticalTextAlignment(PickerHandler handler, IPicker picker)
{
}
public static void MapTitleColor(PickerHandler handler, IPicker picker)
{
if (handler.PlatformView is null) return;
if (picker.TitleColor is not null)
{
handler.PlatformView.TitleColor = picker.TitleColor.ToSKColor();
}
}
public static void MapBackground(PickerHandler handler, IPicker picker)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView != null)
{
Paint background = ((IView)picker).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<IPicker, SkiaPicker>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
public static void MapSelectedIndex(PickerHandler handler, IPicker picker)
{
if (handler.PlatformView is null) return;
handler.PlatformView.SelectedIndex = picker.SelectedIndex;
}
public static void MapItemsSource(PickerHandler handler, IPicker picker)
{
handler.ReloadItems();
}
public static void MapTextColor(PickerHandler handler, IPicker picker)
{
if (handler.PlatformView is null) return;
if (picker.TextColor is not null)
{
handler.PlatformView.TextColor = picker.TextColor.ToSKColor();
}
}
public static void MapCharacterSpacing(PickerHandler handler, IPicker picker)
{
// Character spacing could be implemented with custom text rendering
}
public static void MapHorizontalTextAlignment(PickerHandler handler, IPicker picker)
{
// Text alignment would require changes to SkiaPicker drawing
}
public static void MapVerticalTextAlignment(PickerHandler handler, IPicker picker)
{
// Text alignment would require changes to SkiaPicker drawing
}
public static void MapBackground(PickerHandler handler, IPicker picker)
{
if (handler.PlatformView is null) return;
if (picker.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapItemsSource(PickerHandler handler, IPicker picker)
{
handler.ReloadItems();
}
}

View File

@@ -1,113 +1,65 @@
using System.ComponentModel;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
// 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.Handlers;
using Microsoft.Maui.Graphics;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class ProgressBarHandler : ViewHandler<IProgress, SkiaProgressBar>
/// <summary>
/// Handler for ProgressBar on Linux using Skia rendering.
/// Maps IProgress interface to SkiaProgressBar platform view.
/// IProgress has: Progress (0-1), ProgressColor
/// </summary>
public partial class ProgressBarHandler : ViewHandler<IProgress, SkiaProgressBar>
{
public static IPropertyMapper<IProgress, ProgressBarHandler> Mapper = (IPropertyMapper<IProgress, ProgressBarHandler>)(object)new PropertyMapper<IProgress, ProgressBarHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Progress"] = MapProgress,
["ProgressColor"] = MapProgressColor,
["IsEnabled"] = MapIsEnabled,
["Background"] = MapBackground,
["BackgroundColor"] = MapBackgroundColor
};
public static IPropertyMapper<IProgress, ProgressBarHandler> Mapper = new PropertyMapper<IProgress, ProgressBarHandler>(ViewHandler.ViewMapper)
{
[nameof(IProgress.Progress)] = MapProgress,
[nameof(IProgress.ProgressColor)] = MapProgressColor,
[nameof(IView.Background)] = MapBackground,
};
public static CommandMapper<IProgress, ProgressBarHandler> CommandMapper = new CommandMapper<IProgress, ProgressBarHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public static CommandMapper<IProgress, ProgressBarHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
public ProgressBarHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public ProgressBarHandler() : base(Mapper, CommandMapper)
{
}
protected override SkiaProgressBar CreatePlatformView()
{
return new SkiaProgressBar();
}
public ProgressBarHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override void ConnectHandler(SkiaProgressBar platformView)
{
base.ConnectHandler(platformView);
IProgress virtualView = base.VirtualView;
BindableObject val = (BindableObject)(object)((virtualView is BindableObject) ? virtualView : null);
if (val != null)
{
val.PropertyChanged += OnVirtualViewPropertyChanged;
}
IProgress virtualView2 = base.VirtualView;
VisualElement val2 = (VisualElement)(object)((virtualView2 is VisualElement) ? virtualView2 : null);
if (val2 != null)
{
platformView.IsVisible = val2.IsVisible;
}
}
protected override SkiaProgressBar CreatePlatformView()
{
return new SkiaProgressBar();
}
protected override void DisconnectHandler(SkiaProgressBar platformView)
{
IProgress virtualView = base.VirtualView;
BindableObject val = (BindableObject)(object)((virtualView is BindableObject) ? virtualView : null);
if (val != null)
{
val.PropertyChanged -= OnVirtualViewPropertyChanged;
}
base.DisconnectHandler(platformView);
}
public static void MapProgress(ProgressBarHandler handler, IProgress progress)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Progress = Math.Clamp(progress.Progress, 0.0, 1.0);
}
private void OnVirtualViewPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
IProgress virtualView = base.VirtualView;
VisualElement val = (VisualElement)(object)((virtualView is VisualElement) ? virtualView : null);
if (val != null && e.PropertyName == "IsVisible")
{
base.PlatformView.IsVisible = val.IsVisible;
base.PlatformView.Invalidate();
}
}
public static void MapProgressColor(ProgressBarHandler handler, IProgress progress)
{
if (handler.PlatformView is null) return;
public static void MapProgress(ProgressBarHandler handler, IProgress progress)
{
((ViewHandler<IProgress, SkiaProgressBar>)(object)handler).PlatformView.Progress = progress.Progress;
}
if (progress.ProgressColor is not null)
handler.PlatformView.ProgressColor = progress.ProgressColor.ToSKColor();
}
public static void MapProgressColor(ProgressBarHandler handler, IProgress progress)
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
if (progress.ProgressColor != null)
{
((ViewHandler<IProgress, SkiaProgressBar>)(object)handler).PlatformView.ProgressColor = progress.ProgressColor.ToSKColor();
}
((ViewHandler<IProgress, SkiaProgressBar>)(object)handler).PlatformView.Invalidate();
}
public static void MapBackground(ProgressBarHandler handler, IProgress progress)
{
if (handler.PlatformView is null) return;
public static void MapIsEnabled(ProgressBarHandler handler, IProgress progress)
{
((ViewHandler<IProgress, SkiaProgressBar>)(object)handler).PlatformView.IsEnabled = ((IView)progress).IsEnabled;
((ViewHandler<IProgress, SkiaProgressBar>)(object)handler).PlatformView.Invalidate();
}
public static void MapBackground(ProgressBarHandler handler, IProgress progress)
{
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
Paint background = ((IView)progress).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<IProgress, SkiaProgressBar>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
((ViewHandler<IProgress, SkiaProgressBar>)(object)handler).PlatformView.Invalidate();
}
}
public static void MapBackgroundColor(ProgressBarHandler handler, IProgress progress)
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
VisualElement val = (VisualElement)(object)((progress is VisualElement) ? progress : null);
if (val != null && val.BackgroundColor != null)
{
((ViewHandler<IProgress, SkiaProgressBar>)(object)handler).PlatformView.BackgroundColor = val.BackgroundColor.ToSKColor();
((ViewHandler<IProgress, SkiaProgressBar>)(object)handler).PlatformView.Invalidate();
}
}
if (progress.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
}

View File

@@ -1,111 +1,106 @@
using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
// 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.Handlers;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class RadioButtonHandler : ViewHandler<IRadioButton, SkiaRadioButton>
/// <summary>
/// Handler for RadioButton on Linux using Skia rendering.
/// </summary>
public partial class RadioButtonHandler : ViewHandler<IRadioButton, SkiaRadioButton>
{
public static IPropertyMapper<IRadioButton, RadioButtonHandler> Mapper = (IPropertyMapper<IRadioButton, RadioButtonHandler>)(object)new PropertyMapper<IRadioButton, RadioButtonHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["IsChecked"] = MapIsChecked,
["TextColor"] = MapTextColor,
["Font"] = MapFont,
["Background"] = MapBackground
};
public static IPropertyMapper<IRadioButton, RadioButtonHandler> Mapper =
new PropertyMapper<IRadioButton, RadioButtonHandler>(ViewHandler.ViewMapper)
{
[nameof(IRadioButton.IsChecked)] = MapIsChecked,
[nameof(ITextStyle.TextColor)] = MapTextColor,
[nameof(ITextStyle.Font)] = MapFont,
[nameof(IView.Background)] = MapBackground,
};
public static CommandMapper<IRadioButton, RadioButtonHandler> CommandMapper = new CommandMapper<IRadioButton, RadioButtonHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public static CommandMapper<IRadioButton, RadioButtonHandler> CommandMapper =
new(ViewHandler.ViewCommandMapper)
{
};
public RadioButtonHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public RadioButtonHandler() : base(Mapper, CommandMapper)
{
}
public RadioButtonHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
public RadioButtonHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override SkiaRadioButton CreatePlatformView()
{
return new SkiaRadioButton();
}
protected override SkiaRadioButton CreatePlatformView()
{
return new SkiaRadioButton();
}
protected override void ConnectHandler(SkiaRadioButton platformView)
{
base.ConnectHandler(platformView);
platformView.CheckedChanged += OnCheckedChanged;
IRadioButton virtualView = base.VirtualView;
RadioButton val = (RadioButton)(object)((virtualView is RadioButton) ? virtualView : null);
if (val != null)
{
platformView.Content = val.Content?.ToString() ?? "";
platformView.GroupName = val.GroupName;
platformView.Value = val.Value;
}
}
protected override void ConnectHandler(SkiaRadioButton platformView)
{
base.ConnectHandler(platformView);
platformView.CheckedChanged += OnCheckedChanged;
protected override void DisconnectHandler(SkiaRadioButton platformView)
{
platformView.CheckedChanged -= OnCheckedChanged;
base.DisconnectHandler(platformView);
}
// Set content if available
if (VirtualView is RadioButton rb)
{
platformView.Content = rb.Content?.ToString() ?? "";
platformView.GroupName = rb.GroupName;
platformView.Value = rb.Value;
}
}
private void OnCheckedChanged(object? sender, EventArgs e)
{
if (base.VirtualView != null && base.PlatformView != null)
{
base.VirtualView.IsChecked = base.PlatformView.IsChecked;
}
}
protected override void DisconnectHandler(SkiaRadioButton platformView)
{
platformView.CheckedChanged -= OnCheckedChanged;
base.DisconnectHandler(platformView);
}
public static void MapIsChecked(RadioButtonHandler handler, IRadioButton radioButton)
{
if (((ViewHandler<IRadioButton, SkiaRadioButton>)(object)handler).PlatformView != null)
{
((ViewHandler<IRadioButton, SkiaRadioButton>)(object)handler).PlatformView.IsChecked = radioButton.IsChecked;
}
}
private void OnCheckedChanged(object? sender, EventArgs e)
{
if (VirtualView is null || PlatformView is null) return;
VirtualView.IsChecked = PlatformView.IsChecked;
}
public static void MapTextColor(RadioButtonHandler handler, IRadioButton radioButton)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IRadioButton, SkiaRadioButton>)(object)handler).PlatformView != null && ((ITextStyle)radioButton).TextColor != null)
{
((ViewHandler<IRadioButton, SkiaRadioButton>)(object)handler).PlatformView.TextColor = ((ITextStyle)radioButton).TextColor.ToSKColor();
}
}
public static void MapIsChecked(RadioButtonHandler handler, IRadioButton radioButton)
{
if (handler.PlatformView is null) return;
handler.PlatformView.IsChecked = radioButton.IsChecked;
}
public static void MapFont(RadioButtonHandler handler, IRadioButton radioButton)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IRadioButton, SkiaRadioButton>)(object)handler).PlatformView != null)
{
Font font = ((ITextStyle)radioButton).Font;
if (((Font)(ref font)).Size > 0.0)
{
SkiaRadioButton platformView = ((ViewHandler<IRadioButton, SkiaRadioButton>)(object)handler).PlatformView;
font = ((ITextStyle)radioButton).Font;
platformView.FontSize = (float)((Font)(ref font)).Size;
}
}
}
public static void MapTextColor(RadioButtonHandler handler, IRadioButton radioButton)
{
if (handler.PlatformView is null) return;
public static void MapBackground(RadioButtonHandler handler, IRadioButton radioButton)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IRadioButton, SkiaRadioButton>)(object)handler).PlatformView != null)
{
Paint background = ((IView)radioButton).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<IRadioButton, SkiaRadioButton>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
if (radioButton.TextColor is not null)
{
handler.PlatformView.TextColor = radioButton.TextColor.ToSKColor();
}
}
public static void MapFont(RadioButtonHandler handler, IRadioButton radioButton)
{
if (handler.PlatformView is null) return;
if (radioButton.Font.Size > 0)
{
handler.PlatformView.FontSize = (float)radioButton.Font.Size;
}
}
public static void MapBackground(RadioButtonHandler handler, IRadioButton radioButton)
{
if (handler.PlatformView is null) return;
if (radioButton.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
}

View File

@@ -1,34 +0,0 @@
using System;
using System.Windows.Input;
namespace Microsoft.Maui.Platform.Linux.Handlers;
internal class RelayCommand : ICommand
{
private readonly Action _execute;
private readonly Func<bool>? _canExecute;
public event EventHandler? CanExecuteChanged;
public RelayCommand(Action execute, Func<bool>? canExecute = null)
{
_execute = execute ?? throw new ArgumentNullException("execute");
_canExecute = canExecute;
}
public bool CanExecute(object? parameter)
{
return _canExecute?.Invoke() ?? true;
}
public void Execute(object? parameter)
{
_execute();
}
public void RaiseCanExecuteChanged()
{
this.CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
}

View File

@@ -1,115 +1,109 @@
using System;
// 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.Handlers;
using Microsoft.Maui.Platform.Linux.Hosting;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class ScrollViewHandler : ViewHandler<IScrollView, SkiaScrollView>
/// <summary>
/// Handler for ScrollView on Linux using SkiaScrollView.
/// </summary>
public partial class ScrollViewHandler : ViewHandler<IScrollView, SkiaScrollView>
{
public static IPropertyMapper<IScrollView, ScrollViewHandler> Mapper = (IPropertyMapper<IScrollView, ScrollViewHandler>)(object)new PropertyMapper<IScrollView, ScrollViewHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Content"] = MapContent,
["HorizontalScrollBarVisibility"] = MapHorizontalScrollBarVisibility,
["VerticalScrollBarVisibility"] = MapVerticalScrollBarVisibility,
["Orientation"] = MapOrientation
};
public static IPropertyMapper<IScrollView, ScrollViewHandler> Mapper =
new PropertyMapper<IScrollView, ScrollViewHandler>(ViewMapper)
{
[nameof(IScrollView.Content)] = MapContent,
[nameof(IScrollView.HorizontalScrollBarVisibility)] = MapHorizontalScrollBarVisibility,
[nameof(IScrollView.VerticalScrollBarVisibility)] = MapVerticalScrollBarVisibility,
[nameof(IScrollView.Orientation)] = MapOrientation,
};
public static CommandMapper<IScrollView, ScrollViewHandler> CommandMapper = new CommandMapper<IScrollView, ScrollViewHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper) { ["RequestScrollTo"] = MapRequestScrollTo };
public static CommandMapper<IScrollView, ScrollViewHandler> CommandMapper =
new(ViewCommandMapper)
{
[nameof(IScrollView.RequestScrollTo)] = MapRequestScrollTo
};
public ScrollViewHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public ScrollViewHandler() : base(Mapper, CommandMapper)
{
}
public ScrollViewHandler(IPropertyMapper? mapper)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(object)CommandMapper)
{
}
public ScrollViewHandler(IPropertyMapper? mapper)
: base(mapper ?? Mapper, CommandMapper)
{
}
protected override SkiaScrollView CreatePlatformView()
{
return new SkiaScrollView();
}
protected override SkiaScrollView CreatePlatformView()
{
return new SkiaScrollView();
}
public static void MapContent(ScrollViewHandler handler, IScrollView scrollView)
{
if (((ViewHandler<IScrollView, SkiaScrollView>)(object)handler).PlatformView == null || ((ElementHandler)handler).MauiContext == null)
{
return;
}
IView presentedContent = ((IContentView)scrollView).PresentedContent;
if (presentedContent != null)
{
Console.WriteLine("[ScrollViewHandler] MapContent: " + ((object)presentedContent).GetType().Name);
if (presentedContent.Handler == null)
{
presentedContent.Handler = presentedContent.ToViewHandler(((ElementHandler)handler).MauiContext);
}
IViewHandler handler2 = presentedContent.Handler;
if (((handler2 != null) ? ((IElementHandler)handler2).PlatformView : null) is SkiaView skiaView)
{
Console.WriteLine("[ScrollViewHandler] Setting content: " + ((object)skiaView).GetType().Name);
((ViewHandler<IScrollView, SkiaScrollView>)(object)handler).PlatformView.Content = skiaView;
}
}
else
{
((ViewHandler<IScrollView, SkiaScrollView>)(object)handler).PlatformView.Content = null;
}
}
public static void MapContent(ScrollViewHandler handler, IScrollView scrollView)
{
if (handler.PlatformView == null || handler.MauiContext == null)
return;
public static void MapHorizontalScrollBarVisibility(ScrollViewHandler handler, IScrollView scrollView)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Invalid comparison between Unknown and I4
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Invalid comparison between Unknown and I4
SkiaScrollView platformView = ((ViewHandler<IScrollView, SkiaScrollView>)(object)handler).PlatformView;
ScrollBarVisibility horizontalScrollBarVisibility = scrollView.HorizontalScrollBarVisibility;
ScrollBarVisibility horizontalScrollBarVisibility2 = (((int)horizontalScrollBarVisibility == 1) ? ScrollBarVisibility.Always : (((int)horizontalScrollBarVisibility == 2) ? ScrollBarVisibility.Never : ScrollBarVisibility.Default));
platformView.HorizontalScrollBarVisibility = horizontalScrollBarVisibility2;
}
var content = scrollView.PresentedContent;
if (content != null)
{
Console.WriteLine($"[ScrollViewHandler] MapContent: {content.GetType().Name}");
public static void MapVerticalScrollBarVisibility(ScrollViewHandler handler, IScrollView scrollView)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Invalid comparison between Unknown and I4
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Invalid comparison between Unknown and I4
SkiaScrollView platformView = ((ViewHandler<IScrollView, SkiaScrollView>)(object)handler).PlatformView;
ScrollBarVisibility verticalScrollBarVisibility = scrollView.VerticalScrollBarVisibility;
ScrollBarVisibility verticalScrollBarVisibility2 = (((int)verticalScrollBarVisibility == 1) ? ScrollBarVisibility.Always : (((int)verticalScrollBarVisibility == 2) ? ScrollBarVisibility.Never : ScrollBarVisibility.Default));
platformView.VerticalScrollBarVisibility = verticalScrollBarVisibility2;
}
// Create handler for content if it doesn't exist
if (content.Handler == null)
{
content.Handler = content.ToHandler(handler.MauiContext);
}
public static void MapOrientation(ScrollViewHandler handler, IScrollView scrollView)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Expected I4, but got Unknown
SkiaScrollView platformView = ((ViewHandler<IScrollView, SkiaScrollView>)(object)handler).PlatformView;
ScrollOrientation orientation = scrollView.Orientation;
platformView.Orientation = (orientation - 1) switch
{
0 => ScrollOrientation.Horizontal,
1 => ScrollOrientation.Both,
2 => ScrollOrientation.Neither,
_ => ScrollOrientation.Vertical,
};
}
if (content.Handler?.PlatformView is SkiaView skiaContent)
{
Console.WriteLine($"[ScrollViewHandler] Setting content: {skiaContent.GetType().Name}");
handler.PlatformView.Content = skiaContent;
}
}
else
{
handler.PlatformView.Content = null;
}
}
public static void MapRequestScrollTo(ScrollViewHandler handler, IScrollView scrollView, object? args)
{
ScrollToRequest val = (ScrollToRequest)((args is ScrollToRequest) ? args : null);
if (val != null)
{
((ViewHandler<IScrollView, SkiaScrollView>)(object)handler).PlatformView.ScrollTo((float)val.HorizontalOffset, (float)val.VerticalOffset, !val.Instant);
}
}
public static void MapHorizontalScrollBarVisibility(ScrollViewHandler handler, IScrollView scrollView)
{
handler.PlatformView.HorizontalScrollBarVisibility = scrollView.HorizontalScrollBarVisibility switch
{
Microsoft.Maui.ScrollBarVisibility.Always => ScrollBarVisibility.Always,
Microsoft.Maui.ScrollBarVisibility.Never => ScrollBarVisibility.Never,
_ => ScrollBarVisibility.Default
};
}
public static void MapVerticalScrollBarVisibility(ScrollViewHandler handler, IScrollView scrollView)
{
handler.PlatformView.VerticalScrollBarVisibility = scrollView.VerticalScrollBarVisibility switch
{
Microsoft.Maui.ScrollBarVisibility.Always => ScrollBarVisibility.Always,
Microsoft.Maui.ScrollBarVisibility.Never => ScrollBarVisibility.Never,
_ => ScrollBarVisibility.Default
};
}
public static void MapOrientation(ScrollViewHandler handler, IScrollView scrollView)
{
handler.PlatformView.Orientation = scrollView.Orientation switch
{
Microsoft.Maui.ScrollOrientation.Horizontal => ScrollOrientation.Horizontal,
Microsoft.Maui.ScrollOrientation.Both => ScrollOrientation.Both,
Microsoft.Maui.ScrollOrientation.Neither => ScrollOrientation.Neither,
_ => ScrollOrientation.Vertical
};
}
public static void MapRequestScrollTo(ScrollViewHandler handler, IScrollView scrollView, object? args)
{
if (args is ScrollToRequest request)
{
// Instant means no animation, so we pass !Instant for animated parameter
handler.PlatformView.ScrollTo((float)request.HorizontalOffset, (float)request.VerticalOffset, !request.Instant);
}
}
}

View File

@@ -1,142 +1,135 @@
using System;
using Microsoft.Maui.Graphics;
// 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.Handlers;
using Microsoft.Maui.Graphics;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class SearchBarHandler : ViewHandler<ISearchBar, SkiaSearchBar>
/// <summary>
/// Handler for SearchBar on Linux using Skia rendering.
/// Maps ISearchBar interface to SkiaSearchBar platform view.
/// </summary>
public partial class SearchBarHandler : ViewHandler<ISearchBar, SkiaSearchBar>
{
public static IPropertyMapper<ISearchBar, SearchBarHandler> Mapper = (IPropertyMapper<ISearchBar, SearchBarHandler>)(object)new PropertyMapper<ISearchBar, SearchBarHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Text"] = MapText,
["TextColor"] = MapTextColor,
["Font"] = MapFont,
["Placeholder"] = MapPlaceholder,
["PlaceholderColor"] = MapPlaceholderColor,
["CancelButtonColor"] = MapCancelButtonColor,
["Background"] = MapBackground
};
public static IPropertyMapper<ISearchBar, SearchBarHandler> Mapper = new PropertyMapper<ISearchBar, SearchBarHandler>(ViewHandler.ViewMapper)
{
[nameof(ITextInput.Text)] = MapText,
[nameof(ITextStyle.TextColor)] = MapTextColor,
[nameof(ITextStyle.Font)] = MapFont,
[nameof(IPlaceholder.Placeholder)] = MapPlaceholder,
[nameof(IPlaceholder.PlaceholderColor)] = MapPlaceholderColor,
[nameof(ISearchBar.CancelButtonColor)] = MapCancelButtonColor,
[nameof(IView.Background)] = MapBackground,
};
public static CommandMapper<ISearchBar, SearchBarHandler> CommandMapper = new CommandMapper<ISearchBar, SearchBarHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public static CommandMapper<ISearchBar, SearchBarHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
public SearchBarHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public SearchBarHandler() : base(Mapper, CommandMapper)
{
}
public SearchBarHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
public SearchBarHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override SkiaSearchBar CreatePlatformView()
{
return new SkiaSearchBar();
}
protected override SkiaSearchBar CreatePlatformView()
{
return new SkiaSearchBar();
}
protected override void ConnectHandler(SkiaSearchBar platformView)
{
base.ConnectHandler(platformView);
platformView.TextChanged += OnTextChanged;
platformView.SearchButtonPressed += OnSearchButtonPressed;
}
protected override void ConnectHandler(SkiaSearchBar platformView)
{
base.ConnectHandler(platformView);
platformView.TextChanged += OnTextChanged;
platformView.SearchButtonPressed += OnSearchButtonPressed;
}
protected override void DisconnectHandler(SkiaSearchBar platformView)
{
platformView.TextChanged -= OnTextChanged;
platformView.SearchButtonPressed -= OnSearchButtonPressed;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaSearchBar platformView)
{
platformView.TextChanged -= OnTextChanged;
platformView.SearchButtonPressed -= OnSearchButtonPressed;
base.DisconnectHandler(platformView);
}
private void OnTextChanged(object? sender, TextChangedEventArgs e)
{
if (base.VirtualView != null && base.PlatformView != null && ((ITextInput)base.VirtualView).Text != e.NewTextValue)
{
((ITextInput)base.VirtualView).Text = e.NewTextValue ?? string.Empty;
}
}
private void OnTextChanged(object? sender, TextChangedEventArgs e)
{
if (VirtualView is null || PlatformView is null) return;
private void OnSearchButtonPressed(object? sender, EventArgs e)
{
ISearchBar virtualView = base.VirtualView;
if (virtualView != null)
{
virtualView.SearchButtonPressed();
}
}
if (VirtualView.Text != e.NewTextValue)
{
VirtualView.Text = e.NewTextValue ?? string.Empty;
}
}
public static void MapText(SearchBarHandler handler, ISearchBar searchBar)
{
if (((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView != null && ((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView.Text != ((ITextInput)searchBar).Text)
{
((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView.Text = ((ITextInput)searchBar).Text ?? string.Empty;
}
}
private void OnSearchButtonPressed(object? sender, EventArgs e)
{
VirtualView?.SearchButtonPressed();
}
public static void MapTextColor(SearchBarHandler handler, ISearchBar searchBar)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView != null && ((ITextStyle)searchBar).TextColor != null)
{
((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView.TextColor = ((ITextStyle)searchBar).TextColor.ToSKColor();
}
}
public static void MapText(SearchBarHandler handler, ISearchBar searchBar)
{
if (handler.PlatformView is null) return;
public static void MapFont(SearchBarHandler handler, ISearchBar searchBar)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView != null)
{
Font font = ((ITextStyle)searchBar).Font;
if (((Font)(ref font)).Size > 0.0)
{
((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView.FontSize = (float)((Font)(ref font)).Size;
}
if (!string.IsNullOrEmpty(((Font)(ref font)).Family))
{
((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView.FontFamily = ((Font)(ref font)).Family;
}
}
}
if (handler.PlatformView.Text != searchBar.Text)
handler.PlatformView.Text = searchBar.Text ?? string.Empty;
}
public static void MapPlaceholder(SearchBarHandler handler, ISearchBar searchBar)
{
if (((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView != null)
{
((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView.Placeholder = ((IPlaceholder)searchBar).Placeholder ?? string.Empty;
}
}
public static void MapTextColor(SearchBarHandler handler, ISearchBar searchBar)
{
if (handler.PlatformView is null) return;
public static void MapPlaceholderColor(SearchBarHandler handler, ISearchBar searchBar)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView != null && ((IPlaceholder)searchBar).PlaceholderColor != null)
{
((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView.PlaceholderColor = ((IPlaceholder)searchBar).PlaceholderColor.ToSKColor();
}
}
if (searchBar.TextColor is not null)
handler.PlatformView.TextColor = searchBar.TextColor.ToSKColor();
}
public static void MapCancelButtonColor(SearchBarHandler handler, ISearchBar searchBar)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView != null && searchBar.CancelButtonColor != null)
{
((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView.ClearButtonColor = searchBar.CancelButtonColor.ToSKColor();
}
}
public static void MapFont(SearchBarHandler handler, ISearchBar searchBar)
{
if (handler.PlatformView is null) return;
public static void MapBackground(SearchBarHandler handler, ISearchBar searchBar)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView != null)
{
Paint background = ((IView)searchBar).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<ISearchBar, SkiaSearchBar>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
var font = searchBar.Font;
if (font.Size > 0)
handler.PlatformView.FontSize = (float)font.Size;
if (!string.IsNullOrEmpty(font.Family))
handler.PlatformView.FontFamily = font.Family;
}
public static void MapPlaceholder(SearchBarHandler handler, ISearchBar searchBar)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Placeholder = searchBar.Placeholder ?? string.Empty;
}
public static void MapPlaceholderColor(SearchBarHandler handler, ISearchBar searchBar)
{
if (handler.PlatformView is null) return;
if (searchBar.PlaceholderColor is not null)
handler.PlatformView.PlaceholderColor = searchBar.PlaceholderColor.ToSKColor();
}
public static void MapCancelButtonColor(SearchBarHandler handler, ISearchBar searchBar)
{
if (handler.PlatformView is null) return;
// CancelButtonColor maps to ClearButtonColor
if (searchBar.CancelButtonColor is not null)
handler.PlatformView.ClearButtonColor = searchBar.CancelButtonColor.ToSKColor();
}
public static void MapBackground(SearchBarHandler handler, ISearchBar searchBar)
{
if (handler.PlatformView is null) return;
if (searchBar.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
}

View File

@@ -1,88 +1,93 @@
using System;
using System.Runtime.CompilerServices;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Graphics;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class ShellHandler : ViewHandler<Shell, SkiaShell>
/// <summary>
/// Handler for Shell on Linux using Skia rendering.
/// </summary>
public partial class ShellHandler : ViewHandler<Shell, SkiaShell>
{
public static IPropertyMapper<Shell, ShellHandler> Mapper = (IPropertyMapper<Shell, ShellHandler>)(object)new PropertyMapper<Shell, ShellHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper });
public static IPropertyMapper<Shell, ShellHandler> Mapper = new PropertyMapper<Shell, ShellHandler>(ViewHandler.ViewMapper)
{
};
public static CommandMapper<Shell, ShellHandler> CommandMapper = new CommandMapper<Shell, ShellHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public static CommandMapper<Shell, ShellHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
public ShellHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public ShellHandler() : base(Mapper, CommandMapper)
{
}
public ShellHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
public ShellHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override SkiaShell CreatePlatformView()
{
return new SkiaShell();
}
protected override SkiaShell CreatePlatformView()
{
return new SkiaShell();
}
protected override void ConnectHandler(SkiaShell platformView)
{
base.ConnectHandler(platformView);
platformView.FlyoutIsPresentedChanged += OnFlyoutIsPresentedChanged;
platformView.Navigated += OnNavigated;
if (base.VirtualView != null)
{
base.VirtualView.Navigating += OnShellNavigating;
base.VirtualView.Navigated += OnShellNavigated;
}
}
protected override void ConnectHandler(SkiaShell platformView)
{
base.ConnectHandler(platformView);
platformView.FlyoutIsPresentedChanged += OnFlyoutIsPresentedChanged;
platformView.Navigated += OnNavigated;
protected override void DisconnectHandler(SkiaShell platformView)
{
platformView.FlyoutIsPresentedChanged -= OnFlyoutIsPresentedChanged;
platformView.Navigated -= OnNavigated;
if (base.VirtualView != null)
{
base.VirtualView.Navigating -= OnShellNavigating;
base.VirtualView.Navigated -= OnShellNavigated;
}
base.DisconnectHandler(platformView);
}
// Subscribe to Shell navigation events
if (VirtualView != null)
{
VirtualView.Navigating += OnShellNavigating;
VirtualView.Navigated += OnShellNavigated;
}
}
private void OnFlyoutIsPresentedChanged(object? sender, EventArgs e)
{
}
protected override void DisconnectHandler(SkiaShell platformView)
{
platformView.FlyoutIsPresentedChanged -= OnFlyoutIsPresentedChanged;
platformView.Navigated -= OnNavigated;
private void OnNavigated(object? sender, ShellNavigationEventArgs e)
{
}
if (VirtualView != null)
{
VirtualView.Navigating -= OnShellNavigating;
VirtualView.Navigated -= OnShellNavigated;
}
private void OnShellNavigating(object? sender, ShellNavigatingEventArgs e)
{
DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(36, 1);
defaultInterpolatedStringHandler.AppendLiteral("[ShellHandler] Shell Navigating to: ");
ShellNavigationState target = e.Target;
defaultInterpolatedStringHandler.AppendFormatted((target != null) ? target.Location : null);
Console.WriteLine(defaultInterpolatedStringHandler.ToStringAndClear());
if (base.PlatformView != null)
{
ShellNavigationState target2 = e.Target;
if (((target2 != null) ? target2.Location : null) != null)
{
string text = e.Target.Location.ToString().TrimStart('/');
Console.WriteLine("[ShellHandler] Routing to: " + text);
base.PlatformView.GoToAsync(text);
}
}
}
base.DisconnectHandler(platformView);
}
private void OnShellNavigated(object? sender, ShellNavigatedEventArgs e)
{
DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(35, 1);
defaultInterpolatedStringHandler.AppendLiteral("[ShellHandler] Shell Navigated to: ");
ShellNavigationState current = e.Current;
defaultInterpolatedStringHandler.AppendFormatted((current != null) ? current.Location : null);
Console.WriteLine(defaultInterpolatedStringHandler.ToStringAndClear());
}
private void OnFlyoutIsPresentedChanged(object? sender, EventArgs e)
{
// Sync flyout state to virtual view
}
private void OnNavigated(object? sender, ShellNavigationEventArgs e)
{
// Handle platform navigation events
}
private void OnShellNavigating(object? sender, ShellNavigatingEventArgs e)
{
Console.WriteLine($"[ShellHandler] Shell Navigating to: {e.Target?.Location}");
// Route to platform view
if (PlatformView != null && e.Target?.Location != null)
{
var route = e.Target.Location.ToString().TrimStart('/');
Console.WriteLine($"[ShellHandler] Routing to: {route}");
PlatformView.GoToAsync(route);
}
}
private void OnShellNavigated(object? sender, ShellNavigatedEventArgs e)
{
Console.WriteLine($"[ShellHandler] Shell Navigated to: {e.Current?.Location}");
}
}

View File

@@ -1,16 +0,0 @@
using System;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class SizeChangedEventArgs : EventArgs
{
public int Width { get; }
public int Height { get; }
public SizeChangedEventArgs(int width, int height)
{
Width = width;
Height = height;
}
}

View File

@@ -1,184 +0,0 @@
using System;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class SkiaWindow
{
private SkiaView? _content;
private string _title = "MAUI Application";
private int _x;
private int _y;
private int _width = 800;
private int _height = 600;
private int _minWidth = 100;
private int _minHeight = 100;
private int _maxWidth = int.MaxValue;
private int _maxHeight = int.MaxValue;
public SkiaView? Content
{
get
{
return _content;
}
set
{
_content = value;
this.ContentChanged?.Invoke(this, EventArgs.Empty);
}
}
public string Title
{
get
{
return _title;
}
set
{
_title = value;
this.TitleChanged?.Invoke(this, EventArgs.Empty);
}
}
public int X
{
get
{
return _x;
}
set
{
_x = value;
this.PositionChanged?.Invoke(this, EventArgs.Empty);
}
}
public int Y
{
get
{
return _y;
}
set
{
_y = value;
this.PositionChanged?.Invoke(this, EventArgs.Empty);
}
}
public int Width
{
get
{
return _width;
}
set
{
_width = Math.Clamp(value, _minWidth, _maxWidth);
this.SizeChanged?.Invoke(this, new SizeChangedEventArgs(_width, _height));
}
}
public int Height
{
get
{
return _height;
}
set
{
_height = Math.Clamp(value, _minHeight, _maxHeight);
this.SizeChanged?.Invoke(this, new SizeChangedEventArgs(_width, _height));
}
}
public int MinWidth
{
get
{
return _minWidth;
}
set
{
_minWidth = value;
}
}
public int MinHeight
{
get
{
return _minHeight;
}
set
{
_minHeight = value;
}
}
public int MaxWidth
{
get
{
return _maxWidth;
}
set
{
_maxWidth = value;
}
}
public int MaxHeight
{
get
{
return _maxHeight;
}
set
{
_maxHeight = value;
}
}
public event EventHandler? ContentChanged;
public event EventHandler? TitleChanged;
public event EventHandler? PositionChanged;
public event EventHandler<SizeChangedEventArgs>? SizeChanged;
public event EventHandler? CloseRequested;
public void Render(SKCanvas canvas)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
canvas.Clear(SKColors.White);
if (_content != null)
{
_content.Measure(new SKSize((float)_width, (float)_height));
_content.Arrange(new SKRect(0f, 0f, (float)_width, (float)_height));
_content.Draw(canvas);
}
SkiaView.DrawPopupOverlays(canvas);
}
public void Close()
{
this.CloseRequested?.Invoke(this, EventArgs.Empty);
}
}

View File

@@ -1,160 +1,153 @@
using System;
using Microsoft.Maui.Graphics;
// 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.Handlers;
using Microsoft.Maui.Graphics;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class SliderHandler : ViewHandler<ISlider, SkiaSlider>
/// <summary>
/// Handler for Slider on Linux using Skia rendering.
/// Maps ISlider interface to SkiaSlider platform view.
/// </summary>
public partial class SliderHandler : ViewHandler<ISlider, SkiaSlider>
{
public static IPropertyMapper<ISlider, SliderHandler> Mapper = (IPropertyMapper<ISlider, SliderHandler>)(object)new PropertyMapper<ISlider, SliderHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Minimum"] = MapMinimum,
["Maximum"] = MapMaximum,
["Value"] = MapValue,
["MinimumTrackColor"] = MapMinimumTrackColor,
["MaximumTrackColor"] = MapMaximumTrackColor,
["ThumbColor"] = MapThumbColor,
["Background"] = MapBackground,
["IsEnabled"] = MapIsEnabled
};
public static IPropertyMapper<ISlider, SliderHandler> Mapper = new PropertyMapper<ISlider, SliderHandler>(ViewHandler.ViewMapper)
{
[nameof(IRange.Minimum)] = MapMinimum,
[nameof(IRange.Maximum)] = MapMaximum,
[nameof(IRange.Value)] = MapValue,
[nameof(ISlider.MinimumTrackColor)] = MapMinimumTrackColor,
[nameof(ISlider.MaximumTrackColor)] = MapMaximumTrackColor,
[nameof(ISlider.ThumbColor)] = MapThumbColor,
[nameof(IView.Background)] = MapBackground,
[nameof(IView.IsEnabled)] = MapIsEnabled,
};
public static CommandMapper<ISlider, SliderHandler> CommandMapper = new CommandMapper<ISlider, SliderHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public static CommandMapper<ISlider, SliderHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
public SliderHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public SliderHandler() : base(Mapper, CommandMapper)
{
}
public SliderHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
public SliderHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override SkiaSlider CreatePlatformView()
{
return new SkiaSlider();
}
protected override SkiaSlider CreatePlatformView()
{
return new SkiaSlider();
}
protected override void ConnectHandler(SkiaSlider platformView)
{
base.ConnectHandler(platformView);
platformView.ValueChanged += OnValueChanged;
platformView.DragStarted += OnDragStarted;
platformView.DragCompleted += OnDragCompleted;
if (base.VirtualView != null)
{
MapMinimum(this, base.VirtualView);
MapMaximum(this, base.VirtualView);
MapValue(this, base.VirtualView);
MapIsEnabled(this, base.VirtualView);
}
}
protected override void ConnectHandler(SkiaSlider platformView)
{
base.ConnectHandler(platformView);
platformView.ValueChanged += OnValueChanged;
platformView.DragStarted += OnDragStarted;
platformView.DragCompleted += OnDragCompleted;
protected override void DisconnectHandler(SkiaSlider platformView)
{
platformView.ValueChanged -= OnValueChanged;
platformView.DragStarted -= OnDragStarted;
platformView.DragCompleted -= OnDragCompleted;
base.DisconnectHandler(platformView);
}
// Sync properties that may have been set before handler connection
if (VirtualView != null)
{
MapMinimum(this, VirtualView);
MapMaximum(this, VirtualView);
MapValue(this, VirtualView);
MapIsEnabled(this, VirtualView);
}
}
private void OnValueChanged(object? sender, SliderValueChangedEventArgs e)
{
if (base.VirtualView != null && base.PlatformView != null && Math.Abs(((IRange)base.VirtualView).Value - e.NewValue) > 0.0001)
{
((IRange)base.VirtualView).Value = e.NewValue;
}
}
protected override void DisconnectHandler(SkiaSlider platformView)
{
platformView.ValueChanged -= OnValueChanged;
platformView.DragStarted -= OnDragStarted;
platformView.DragCompleted -= OnDragCompleted;
base.DisconnectHandler(platformView);
}
private void OnDragStarted(object? sender, EventArgs e)
{
ISlider virtualView = base.VirtualView;
if (virtualView != null)
{
virtualView.DragStarted();
}
}
private void OnValueChanged(object? sender, SliderValueChangedEventArgs e)
{
if (VirtualView is null || PlatformView is null) return;
private void OnDragCompleted(object? sender, EventArgs e)
{
ISlider virtualView = base.VirtualView;
if (virtualView != null)
{
virtualView.DragCompleted();
}
}
if (Math.Abs(VirtualView.Value - e.NewValue) > 0.0001)
{
VirtualView.Value = e.NewValue;
}
}
public static void MapMinimum(SliderHandler handler, ISlider slider)
{
if (((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView != null)
{
((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView.Minimum = ((IRange)slider).Minimum;
}
}
private void OnDragStarted(object? sender, EventArgs e)
{
VirtualView?.DragStarted();
}
public static void MapMaximum(SliderHandler handler, ISlider slider)
{
if (((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView != null)
{
((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView.Maximum = ((IRange)slider).Maximum;
}
}
private void OnDragCompleted(object? sender, EventArgs e)
{
VirtualView?.DragCompleted();
}
public static void MapValue(SliderHandler handler, ISlider slider)
{
if (((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView != null && Math.Abs(((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView.Value - ((IRange)slider).Value) > 0.0001)
{
((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView.Value = ((IRange)slider).Value;
}
}
public static void MapMinimum(SliderHandler handler, ISlider slider)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Minimum = slider.Minimum;
}
public static void MapMinimumTrackColor(SliderHandler handler, ISlider slider)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView != null && slider.MinimumTrackColor != null)
{
((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView.ActiveTrackColor = slider.MinimumTrackColor.ToSKColor();
}
}
public static void MapMaximum(SliderHandler handler, ISlider slider)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Maximum = slider.Maximum;
}
public static void MapMaximumTrackColor(SliderHandler handler, ISlider slider)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView != null && slider.MaximumTrackColor != null)
{
((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView.TrackColor = slider.MaximumTrackColor.ToSKColor();
}
}
public static void MapValue(SliderHandler handler, ISlider slider)
{
if (handler.PlatformView is null) return;
public static void MapThumbColor(SliderHandler handler, ISlider slider)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView != null && slider.ThumbColor != null)
{
((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView.ThumbColor = slider.ThumbColor.ToSKColor();
}
}
if (Math.Abs(handler.PlatformView.Value - slider.Value) > 0.0001)
handler.PlatformView.Value = slider.Value;
}
public static void MapBackground(SliderHandler handler, ISlider slider)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView != null)
{
Paint background = ((IView)slider).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
public static void MapMinimumTrackColor(SliderHandler handler, ISlider slider)
{
if (handler.PlatformView is null) return;
public static void MapIsEnabled(SliderHandler handler, ISlider slider)
{
if (((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView != null)
{
((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView.IsEnabled = ((IView)slider).IsEnabled;
((ViewHandler<ISlider, SkiaSlider>)(object)handler).PlatformView.Invalidate();
}
}
// MinimumTrackColor maps to ActiveTrackColor (the filled portion)
if (slider.MinimumTrackColor is not null)
handler.PlatformView.ActiveTrackColor = slider.MinimumTrackColor.ToSKColor();
}
public static void MapMaximumTrackColor(SliderHandler handler, ISlider slider)
{
if (handler.PlatformView is null) return;
// MaximumTrackColor maps to TrackColor (the unfilled portion)
if (slider.MaximumTrackColor is not null)
handler.PlatformView.TrackColor = slider.MaximumTrackColor.ToSKColor();
}
public static void MapThumbColor(SliderHandler handler, ISlider slider)
{
if (handler.PlatformView is null) return;
if (slider.ThumbColor is not null)
handler.PlatformView.ThumbColor = slider.ThumbColor.ToSKColor();
}
public static void MapBackground(SliderHandler handler, ISlider slider)
{
if (handler.PlatformView is null) return;
if (slider.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
public static void MapIsEnabled(SliderHandler handler, ISlider slider)
{
if (handler.PlatformView is null) return;
handler.PlatformView.IsEnabled = slider.IsEnabled;
handler.PlatformView.Invalidate();
}
}

View File

@@ -1,49 +0,0 @@
using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class StackLayoutHandler : LayoutHandler
{
public new static IPropertyMapper<IStackLayout, StackLayoutHandler> Mapper = (IPropertyMapper<IStackLayout, StackLayoutHandler>)(object)new PropertyMapper<IStackLayout, StackLayoutHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)LayoutHandler.Mapper }) { ["Spacing"] = MapSpacing };
public StackLayoutHandler()
: base((IPropertyMapper?)(object)Mapper)
{
}
protected override SkiaLayoutView CreatePlatformView()
{
return new SkiaStackLayout();
}
protected override void ConnectHandler(SkiaLayoutView platformView)
{
if (platformView is SkiaStackLayout skiaStackLayout)
{
ILayout virtualView = ((ViewHandler<ILayout, SkiaLayoutView>)(object)this).VirtualView;
IStackLayout val = (IStackLayout)(object)((virtualView is IStackLayout) ? virtualView : null);
if (val != null)
{
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)this).VirtualView is HorizontalStackLayout)
{
skiaStackLayout.Orientation = StackOrientation.Horizontal;
}
else if (((ViewHandler<ILayout, SkiaLayoutView>)(object)this).VirtualView is VerticalStackLayout || ((ViewHandler<ILayout, SkiaLayoutView>)(object)this).VirtualView is StackLayout)
{
skiaStackLayout.Orientation = StackOrientation.Vertical;
}
skiaStackLayout.Spacing = (float)val.Spacing;
}
}
base.ConnectHandler(platformView);
}
public static void MapSpacing(StackLayoutHandler handler, IStackLayout layout)
{
if (((ViewHandler<ILayout, SkiaLayoutView>)(object)handler).PlatformView is SkiaStackLayout skiaStackLayout)
{
skiaStackLayout.Spacing = (float)layout.Spacing;
}
}
}

View File

@@ -1,133 +1,89 @@
using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
// 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.Handlers;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Platform;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class StepperHandler : ViewHandler<IStepper, SkiaStepper>
/// <summary>
/// Handler for Stepper on Linux using Skia rendering.
/// </summary>
public partial class StepperHandler : ViewHandler<IStepper, SkiaStepper>
{
public static IPropertyMapper<IStepper, StepperHandler> Mapper = (IPropertyMapper<IStepper, StepperHandler>)(object)new PropertyMapper<IStepper, StepperHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Value"] = MapValue,
["Minimum"] = MapMinimum,
["Maximum"] = MapMaximum,
["Increment"] = MapIncrement,
["Background"] = MapBackground,
["IsEnabled"] = MapIsEnabled
};
public static IPropertyMapper<IStepper, StepperHandler> Mapper =
new PropertyMapper<IStepper, StepperHandler>(ViewHandler.ViewMapper)
{
[nameof(IStepper.Value)] = MapValue,
[nameof(IStepper.Minimum)] = MapMinimum,
[nameof(IStepper.Maximum)] = MapMaximum,
[nameof(IView.Background)] = MapBackground,
};
public static CommandMapper<IStepper, StepperHandler> CommandMapper = new CommandMapper<IStepper, StepperHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public static CommandMapper<IStepper, StepperHandler> CommandMapper =
new(ViewHandler.ViewCommandMapper)
{
};
public StepperHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public StepperHandler() : base(Mapper, CommandMapper)
{
}
public StepperHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
public StepperHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override SkiaStepper CreatePlatformView()
{
return new SkiaStepper();
}
protected override SkiaStepper CreatePlatformView()
{
return new SkiaStepper();
}
protected override void ConnectHandler(SkiaStepper platformView)
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Invalid comparison between Unknown and I4
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
base.ConnectHandler(platformView);
platformView.ValueChanged += OnValueChanged;
Application current = Application.Current;
if (current != null && (int)current.UserAppTheme == 2)
{
platformView.ButtonBackgroundColor = new SKColor((byte)66, (byte)66, (byte)66);
platformView.ButtonPressedColor = new SKColor((byte)97, (byte)97, (byte)97);
platformView.ButtonDisabledColor = new SKColor((byte)48, (byte)48, (byte)48);
platformView.SymbolColor = new SKColor((byte)224, (byte)224, (byte)224);
platformView.SymbolDisabledColor = new SKColor((byte)97, (byte)97, (byte)97);
platformView.BorderColor = new SKColor((byte)97, (byte)97, (byte)97);
}
}
protected override void ConnectHandler(SkiaStepper platformView)
{
base.ConnectHandler(platformView);
platformView.ValueChanged += OnValueChanged;
}
protected override void DisconnectHandler(SkiaStepper platformView)
{
platformView.ValueChanged -= OnValueChanged;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaStepper platformView)
{
platformView.ValueChanged -= OnValueChanged;
base.DisconnectHandler(platformView);
}
private void OnValueChanged(object? sender, EventArgs e)
{
if (base.VirtualView != null && base.PlatformView != null)
{
((IRange)base.VirtualView).Value = base.PlatformView.Value;
}
}
private void OnValueChanged(object? sender, EventArgs e)
{
if (VirtualView is null || PlatformView is null) return;
VirtualView.Value = PlatformView.Value;
}
public static void MapValue(StepperHandler handler, IStepper stepper)
{
if (((ViewHandler<IStepper, SkiaStepper>)(object)handler).PlatformView != null)
{
((ViewHandler<IStepper, SkiaStepper>)(object)handler).PlatformView.Value = ((IRange)stepper).Value;
}
}
public static void MapValue(StepperHandler handler, IStepper stepper)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Value = stepper.Value;
}
public static void MapMinimum(StepperHandler handler, IStepper stepper)
{
if (((ViewHandler<IStepper, SkiaStepper>)(object)handler).PlatformView != null)
{
((ViewHandler<IStepper, SkiaStepper>)(object)handler).PlatformView.Minimum = ((IRange)stepper).Minimum;
}
}
public static void MapMinimum(StepperHandler handler, IStepper stepper)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Minimum = stepper.Minimum;
}
public static void MapMaximum(StepperHandler handler, IStepper stepper)
{
if (((ViewHandler<IStepper, SkiaStepper>)(object)handler).PlatformView != null)
{
((ViewHandler<IStepper, SkiaStepper>)(object)handler).PlatformView.Maximum = ((IRange)stepper).Maximum;
}
}
public static void MapMaximum(StepperHandler handler, IStepper stepper)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Maximum = stepper.Maximum;
}
public static void MapBackground(StepperHandler handler, IStepper stepper)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IStepper, SkiaStepper>)(object)handler).PlatformView != null)
{
Paint background = ((IView)stepper).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<IStepper, SkiaStepper>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
public static void MapBackground(StepperHandler handler, IStepper stepper)
{
if (handler.PlatformView is null) return;
public static void MapIncrement(StepperHandler handler, IStepper stepper)
{
if (((ViewHandler<IStepper, SkiaStepper>)(object)handler).PlatformView != null)
{
Stepper val = (Stepper)(object)((stepper is Stepper) ? stepper : null);
if (val != null)
{
((ViewHandler<IStepper, SkiaStepper>)(object)handler).PlatformView.Increment = val.Increment;
}
}
}
public static void MapIsEnabled(StepperHandler handler, IStepper stepper)
{
if (((ViewHandler<IStepper, SkiaStepper>)(object)handler).PlatformView != null)
{
((ViewHandler<IStepper, SkiaStepper>)(object)handler).PlatformView.IsEnabled = ((IView)stepper).IsEnabled;
}
}
if (stepper.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
}

View File

@@ -1,107 +1,99 @@
using Microsoft.Maui.Graphics;
// 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.Handlers;
using Microsoft.Maui.Graphics;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class SwitchHandler : ViewHandler<ISwitch, SkiaSwitch>
/// <summary>
/// Handler for Switch on Linux using Skia rendering.
/// Maps ISwitch interface to SkiaSwitch platform view.
/// </summary>
public partial class SwitchHandler : ViewHandler<ISwitch, SkiaSwitch>
{
public static IPropertyMapper<ISwitch, SwitchHandler> Mapper = (IPropertyMapper<ISwitch, SwitchHandler>)(object)new PropertyMapper<ISwitch, SwitchHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["IsOn"] = MapIsOn,
["TrackColor"] = MapTrackColor,
["ThumbColor"] = MapThumbColor,
["Background"] = MapBackground,
["IsEnabled"] = MapIsEnabled
};
public static IPropertyMapper<ISwitch, SwitchHandler> Mapper = new PropertyMapper<ISwitch, SwitchHandler>(ViewHandler.ViewMapper)
{
[nameof(ISwitch.IsOn)] = MapIsOn,
[nameof(ISwitch.TrackColor)] = MapTrackColor,
[nameof(ISwitch.ThumbColor)] = MapThumbColor,
[nameof(IView.Background)] = MapBackground,
};
public static CommandMapper<ISwitch, SwitchHandler> CommandMapper = new CommandMapper<ISwitch, SwitchHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public static CommandMapper<ISwitch, SwitchHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
public SwitchHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public SwitchHandler() : base(Mapper, CommandMapper)
{
}
public SwitchHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
public SwitchHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override SkiaSwitch CreatePlatformView()
{
return new SkiaSwitch();
}
protected override SkiaSwitch CreatePlatformView()
{
return new SkiaSwitch();
}
protected override void ConnectHandler(SkiaSwitch platformView)
{
base.ConnectHandler(platformView);
platformView.Toggled += OnToggled;
}
protected override void ConnectHandler(SkiaSwitch platformView)
{
base.ConnectHandler(platformView);
platformView.Toggled += OnToggled;
}
protected override void DisconnectHandler(SkiaSwitch platformView)
{
platformView.Toggled -= OnToggled;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaSwitch platformView)
{
platformView.Toggled -= OnToggled;
base.DisconnectHandler(platformView);
}
private void OnToggled(object? sender, ToggledEventArgs e)
{
if (base.VirtualView != null && base.VirtualView.IsOn != e.Value)
{
base.VirtualView.IsOn = e.Value;
}
}
private void OnToggled(object? sender, Platform.ToggledEventArgs e)
{
if (VirtualView is not null && VirtualView.IsOn != e.Value)
{
VirtualView.IsOn = e.Value;
}
}
public static void MapIsOn(SwitchHandler handler, ISwitch @switch)
{
if (((ViewHandler<ISwitch, SkiaSwitch>)(object)handler).PlatformView != null)
{
((ViewHandler<ISwitch, SkiaSwitch>)(object)handler).PlatformView.IsOn = @switch.IsOn;
}
}
public static void MapIsOn(SwitchHandler handler, ISwitch @switch)
{
if (handler.PlatformView is null) return;
handler.PlatformView.IsOn = @switch.IsOn;
}
public static void MapTrackColor(SwitchHandler handler, ISwitch @switch)
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ISwitch, SkiaSwitch>)(object)handler).PlatformView != null && @switch.TrackColor != null)
{
SKColor onTrackColor = @switch.TrackColor.ToSKColor();
((ViewHandler<ISwitch, SkiaSwitch>)(object)handler).PlatformView.OnTrackColor = onTrackColor;
((ViewHandler<ISwitch, SkiaSwitch>)(object)handler).PlatformView.OffTrackColor = ((SKColor)(ref onTrackColor)).WithAlpha((byte)128);
}
}
public static void MapTrackColor(SwitchHandler handler, ISwitch @switch)
{
if (handler.PlatformView is null) return;
public static void MapThumbColor(SwitchHandler handler, ISwitch @switch)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ISwitch, SkiaSwitch>)(object)handler).PlatformView != null && @switch.ThumbColor != null)
{
((ViewHandler<ISwitch, SkiaSwitch>)(object)handler).PlatformView.ThumbColor = @switch.ThumbColor.ToSKColor();
}
}
// TrackColor sets both On and Off track colors
if (@switch.TrackColor is not null)
{
var color = @switch.TrackColor.ToSKColor();
handler.PlatformView.OnTrackColor = color;
// Off track could be a lighter version
handler.PlatformView.OffTrackColor = color.WithAlpha(128);
}
}
public static void MapBackground(SwitchHandler handler, ISwitch @switch)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ISwitch, SkiaSwitch>)(object)handler).PlatformView != null)
{
Paint background = ((IView)@switch).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<ISwitch, SkiaSwitch>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
public static void MapThumbColor(SwitchHandler handler, ISwitch @switch)
{
if (handler.PlatformView is null) return;
public static void MapIsEnabled(SwitchHandler handler, ISwitch @switch)
{
if (((ViewHandler<ISwitch, SkiaSwitch>)(object)handler).PlatformView != null)
{
((ViewHandler<ISwitch, SkiaSwitch>)(object)handler).PlatformView.IsEnabled = ((IView)@switch).IsEnabled;
}
}
if (@switch.ThumbColor is not null)
handler.PlatformView.ThumbColor = @switch.ThumbColor.ToSKColor();
}
public static void MapBackground(SwitchHandler handler, ISwitch @switch)
{
if (handler.PlatformView is null) return;
if (@switch.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
}

View File

@@ -1,43 +1,55 @@
using System;
// 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.Handlers;
using Microsoft.Maui.Graphics;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class TabbedPageHandler : ViewHandler<ITabbedView, SkiaTabbedPage>
/// <summary>
/// Handler for TabbedPage on Linux using Skia rendering.
/// Maps ITabbedView interface to SkiaTabbedPage platform view.
/// </summary>
public partial class TabbedPageHandler : ViewHandler<ITabbedView, SkiaTabbedPage>
{
public static IPropertyMapper<ITabbedView, TabbedPageHandler> Mapper = (IPropertyMapper<ITabbedView, TabbedPageHandler>)(object)new PropertyMapper<ITabbedView, TabbedPageHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper });
public static IPropertyMapper<ITabbedView, TabbedPageHandler> Mapper = new PropertyMapper<ITabbedView, TabbedPageHandler>(ViewHandler.ViewMapper)
{
};
public static CommandMapper<ITabbedView, TabbedPageHandler> CommandMapper = new CommandMapper<ITabbedView, TabbedPageHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public static CommandMapper<ITabbedView, TabbedPageHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
};
public TabbedPageHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public TabbedPageHandler() : base(Mapper, CommandMapper)
{
}
public TabbedPageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
public TabbedPageHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override SkiaTabbedPage CreatePlatformView()
{
return new SkiaTabbedPage();
}
protected override SkiaTabbedPage CreatePlatformView()
{
return new SkiaTabbedPage();
}
protected override void ConnectHandler(SkiaTabbedPage platformView)
{
base.ConnectHandler(platformView);
platformView.SelectedIndexChanged += OnSelectedIndexChanged;
}
protected override void ConnectHandler(SkiaTabbedPage platformView)
{
base.ConnectHandler(platformView);
platformView.SelectedIndexChanged += OnSelectedIndexChanged;
}
protected override void DisconnectHandler(SkiaTabbedPage platformView)
{
platformView.SelectedIndexChanged -= OnSelectedIndexChanged;
platformView.ClearTabs();
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaTabbedPage platformView)
{
platformView.SelectedIndexChanged -= OnSelectedIndexChanged;
platformView.ClearTabs();
base.DisconnectHandler(platformView);
}
private void OnSelectedIndexChanged(object? sender, EventArgs e)
{
}
private void OnSelectedIndexChanged(object? sender, EventArgs e)
{
// Notify the virtual view of selection change
}
}

View File

@@ -1,84 +0,0 @@
using Microsoft.Maui.Handlers;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class TextButtonHandler : ButtonHandler
{
public new static IPropertyMapper<ITextButton, TextButtonHandler> Mapper = (IPropertyMapper<ITextButton, TextButtonHandler>)(object)new PropertyMapper<ITextButton, TextButtonHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ButtonHandler.Mapper })
{
["Text"] = MapText,
["TextColor"] = MapTextColor,
["Font"] = MapFont,
["CharacterSpacing"] = MapCharacterSpacing
};
public TextButtonHandler()
: base((IPropertyMapper?)(object)Mapper)
{
}
protected override void ConnectHandler(SkiaButton platformView)
{
base.ConnectHandler(platformView);
IButton virtualView = ((ViewHandler<IButton, SkiaButton>)(object)this).VirtualView;
ITextButton val = (ITextButton)(object)((virtualView is ITextButton) ? virtualView : null);
if (val != null)
{
MapText(this, val);
MapTextColor(this, val);
MapFont(this, val);
MapCharacterSpacing(this, val);
}
}
public static void MapText(TextButtonHandler handler, ITextButton button)
{
if (((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView != null)
{
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.Text = ((IText)button).Text ?? string.Empty;
}
}
public static void MapTextColor(TextButtonHandler handler, ITextButton button)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView != null && ((ITextStyle)button).TextColor != null)
{
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.TextColor = ((ITextStyle)button).TextColor.ToSKColor();
}
}
public static void MapFont(TextButtonHandler handler, ITextButton button)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Invalid comparison between Unknown and I4
//IL_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Invalid comparison between Unknown and I4
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Invalid comparison between Unknown and I4
if (((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView != null)
{
Font font = ((ITextStyle)button).Font;
if (((Font)(ref font)).Size > 0.0)
{
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.FontSize = (float)((Font)(ref font)).Size;
}
if (!string.IsNullOrEmpty(((Font)(ref font)).Family))
{
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.FontFamily = ((Font)(ref font)).Family;
}
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.IsBold = (int)((Font)(ref font)).Weight >= 700;
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.IsItalic = (int)((Font)(ref font)).Slant == 1 || (int)((Font)(ref font)).Slant == 2;
}
}
public static void MapCharacterSpacing(TextButtonHandler handler, ITextButton button)
{
if (((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView != null)
{
((ViewHandler<IButton, SkiaButton>)(object)handler).PlatformView.CharacterSpacing = (float)((ITextStyle)button).CharacterSpacing;
}
}
}

View File

@@ -1,115 +1,100 @@
using System;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
// 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.Handlers;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class TimePickerHandler : ViewHandler<ITimePicker, SkiaTimePicker>
/// <summary>
/// Handler for TimePicker on Linux using Skia rendering.
/// </summary>
public partial class TimePickerHandler : ViewHandler<ITimePicker, SkiaTimePicker>
{
public static IPropertyMapper<ITimePicker, TimePickerHandler> Mapper = (IPropertyMapper<ITimePicker, TimePickerHandler>)(object)new PropertyMapper<ITimePicker, TimePickerHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper })
{
["Time"] = MapTime,
["Format"] = MapFormat,
["TextColor"] = MapTextColor,
["CharacterSpacing"] = MapCharacterSpacing,
["Background"] = MapBackground
};
public static IPropertyMapper<ITimePicker, TimePickerHandler> Mapper =
new PropertyMapper<ITimePicker, TimePickerHandler>(ViewHandler.ViewMapper)
{
[nameof(ITimePicker.Time)] = MapTime,
[nameof(ITimePicker.Format)] = MapFormat,
[nameof(ITimePicker.TextColor)] = MapTextColor,
[nameof(ITimePicker.CharacterSpacing)] = MapCharacterSpacing,
[nameof(IView.Background)] = MapBackground,
};
public static CommandMapper<ITimePicker, TimePickerHandler> CommandMapper = new CommandMapper<ITimePicker, TimePickerHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper);
public static CommandMapper<ITimePicker, TimePickerHandler> CommandMapper =
new(ViewHandler.ViewCommandMapper)
{
};
public TimePickerHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public TimePickerHandler() : base(Mapper, CommandMapper)
{
}
public TimePickerHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
public TimePickerHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override SkiaTimePicker CreatePlatformView()
{
return new SkiaTimePicker();
}
protected override SkiaTimePicker CreatePlatformView()
{
return new SkiaTimePicker();
}
protected override void ConnectHandler(SkiaTimePicker platformView)
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Invalid comparison between Unknown and I4
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
base.ConnectHandler(platformView);
platformView.TimeSelected += OnTimeSelected;
Application current = Application.Current;
if (current != null && (int)current.UserAppTheme == 2)
{
platformView.ClockBackgroundColor = new SKColor((byte)30, (byte)30, (byte)30);
platformView.ClockFaceColor = new SKColor((byte)45, (byte)45, (byte)45);
platformView.TextColor = new SKColor((byte)224, (byte)224, (byte)224);
platformView.BorderColor = new SKColor((byte)97, (byte)97, (byte)97);
platformView.BackgroundColor = new SKColor((byte)45, (byte)45, (byte)45);
}
}
protected override void ConnectHandler(SkiaTimePicker platformView)
{
base.ConnectHandler(platformView);
platformView.TimeSelected += OnTimeSelected;
}
protected override void DisconnectHandler(SkiaTimePicker platformView)
{
platformView.TimeSelected -= OnTimeSelected;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaTimePicker platformView)
{
platformView.TimeSelected -= OnTimeSelected;
base.DisconnectHandler(platformView);
}
private void OnTimeSelected(object? sender, EventArgs e)
{
if (base.VirtualView != null && base.PlatformView != null)
{
base.VirtualView.Time = base.PlatformView.Time;
}
}
private void OnTimeSelected(object? sender, EventArgs e)
{
if (VirtualView is null || PlatformView is null) return;
public static void MapTime(TimePickerHandler handler, ITimePicker timePicker)
{
if (((ViewHandler<ITimePicker, SkiaTimePicker>)(object)handler).PlatformView != null)
{
((ViewHandler<ITimePicker, SkiaTimePicker>)(object)handler).PlatformView.Time = timePicker.Time;
}
}
VirtualView.Time = PlatformView.Time;
}
public static void MapFormat(TimePickerHandler handler, ITimePicker timePicker)
{
if (((ViewHandler<ITimePicker, SkiaTimePicker>)(object)handler).PlatformView != null)
{
((ViewHandler<ITimePicker, SkiaTimePicker>)(object)handler).PlatformView.Format = timePicker.Format ?? "t";
}
}
public static void MapTime(TimePickerHandler handler, ITimePicker timePicker)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Time = timePicker.Time;
}
public static void MapTextColor(TimePickerHandler handler, ITimePicker timePicker)
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ITimePicker, SkiaTimePicker>)(object)handler).PlatformView != null && ((ITextStyle)timePicker).TextColor != null)
{
((ViewHandler<ITimePicker, SkiaTimePicker>)(object)handler).PlatformView.TextColor = ((ITextStyle)timePicker).TextColor.ToSKColor();
}
}
public static void MapFormat(TimePickerHandler handler, ITimePicker timePicker)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Format = timePicker.Format ?? "t";
}
public static void MapCharacterSpacing(TimePickerHandler handler, ITimePicker timePicker)
{
}
public static void MapTextColor(TimePickerHandler handler, ITimePicker timePicker)
{
if (handler.PlatformView is null) return;
if (timePicker.TextColor is not null)
{
handler.PlatformView.TextColor = timePicker.TextColor.ToSKColor();
}
}
public static void MapBackground(TimePickerHandler handler, ITimePicker timePicker)
{
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
if (((ViewHandler<ITimePicker, SkiaTimePicker>)(object)handler).PlatformView != null)
{
Paint background = ((IView)timePicker).Background;
SolidPaint val = (SolidPaint)(object)((background is SolidPaint) ? background : null);
if (val != null && val.Color != null)
{
((ViewHandler<ITimePicker, SkiaTimePicker>)(object)handler).PlatformView.BackgroundColor = val.Color.ToSKColor();
}
}
}
public static void MapCharacterSpacing(TimePickerHandler handler, ITimePicker timePicker)
{
// Character spacing would require custom text rendering
}
public static void MapBackground(TimePickerHandler handler, ITimePicker timePicker)
{
if (handler.PlatformView is null) return;
if (timePicker.Background is SolidPaint solidPaint && solidPaint.Color is not null)
{
handler.PlatformView.BackgroundColor = solidPaint.Color.ToSKColor();
}
}
}

View File

@@ -1,207 +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 Microsoft.Maui.Handlers;
namespace Microsoft.Maui.Platform;
/// <summary>
/// Linux handler for WebView control using WebKitGTK.
/// </summary>
public partial class WebViewHandler : ViewHandler<IWebView, LinuxWebView>
{
/// <summary>
/// Property mapper for WebView properties.
/// </summary>
public static IPropertyMapper<IWebView, WebViewHandler> Mapper = new PropertyMapper<IWebView, WebViewHandler>(ViewHandler.ViewMapper)
{
[nameof(IWebView.Source)] = MapSource,
[nameof(IWebView.UserAgent)] = MapUserAgent,
};
/// <summary>
/// Command mapper for WebView commands.
/// </summary>
public static CommandMapper<IWebView, WebViewHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
[nameof(IWebView.GoBack)] = MapGoBack,
[nameof(IWebView.GoForward)] = MapGoForward,
[nameof(IWebView.Reload)] = MapReload,
[nameof(IWebView.Eval)] = MapEval,
[nameof(IWebView.EvaluateJavaScriptAsync)] = MapEvaluateJavaScriptAsync,
};
public WebViewHandler() : base(Mapper, CommandMapper)
{
}
public WebViewHandler(IPropertyMapper? mapper)
: base(mapper ?? Mapper, CommandMapper)
{
}
public WebViewHandler(IPropertyMapper? mapper, CommandMapper? commandMapper)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override LinuxWebView CreatePlatformView()
{
Console.WriteLine("[WebViewHandler] Creating LinuxWebView");
return new LinuxWebView();
}
protected override void ConnectHandler(LinuxWebView platformView)
{
base.ConnectHandler(platformView);
platformView.Navigating += OnNavigating;
platformView.Navigated += OnNavigated;
// Map initial properties
if (VirtualView != null)
{
MapSource(this, VirtualView);
MapUserAgent(this, VirtualView);
}
Console.WriteLine("[WebViewHandler] Handler connected");
}
protected override void DisconnectHandler(LinuxWebView platformView)
{
platformView.Navigating -= OnNavigating;
platformView.Navigated -= OnNavigated;
base.DisconnectHandler(platformView);
Console.WriteLine("[WebViewHandler] Handler disconnected");
}
private void OnNavigating(object? sender, WebViewNavigatingEventArgs e)
{
if (VirtualView == null)
return;
// Notify the virtual view about navigation starting
VirtualView.Navigating(WebNavigationEvent.NewPage, e.Url);
}
private void OnNavigated(object? sender, WebViewNavigatedEventArgs e)
{
if (VirtualView == null)
return;
// Notify the virtual view about navigation completed
var result = e.Success ? WebNavigationResult.Success : WebNavigationResult.Failure;
VirtualView.Navigated(WebNavigationEvent.NewPage, e.Url, result);
}
#region Property Mappers
public static void MapSource(WebViewHandler handler, IWebView webView)
{
var source = webView.Source;
if (source == null)
return;
Console.WriteLine($"[WebViewHandler] MapSource: {source.GetType().Name}");
if (source is IUrlWebViewSource urlSource && !string.IsNullOrEmpty(urlSource.Url))
{
handler.PlatformView?.LoadUrl(urlSource.Url);
}
else if (source is IHtmlWebViewSource htmlSource && !string.IsNullOrEmpty(htmlSource.Html))
{
handler.PlatformView?.LoadHtml(htmlSource.Html, htmlSource.BaseUrl);
}
}
public static void MapUserAgent(WebViewHandler handler, IWebView webView)
{
if (handler.PlatformView != null && !string.IsNullOrEmpty(webView.UserAgent))
{
handler.PlatformView.UserAgent = webView.UserAgent;
Console.WriteLine($"[WebViewHandler] MapUserAgent: {webView.UserAgent}");
}
}
#endregion
#region Command Mappers
public static void MapGoBack(WebViewHandler handler, IWebView webView, object? args)
{
if (handler.PlatformView?.CanGoBack == true)
{
handler.PlatformView.GoBack();
Console.WriteLine("[WebViewHandler] GoBack");
}
}
public static void MapGoForward(WebViewHandler handler, IWebView webView, object? args)
{
if (handler.PlatformView?.CanGoForward == true)
{
handler.PlatformView.GoForward();
Console.WriteLine("[WebViewHandler] GoForward");
}
}
public static void MapReload(WebViewHandler handler, IWebView webView, object? args)
{
handler.PlatformView?.Reload();
Console.WriteLine("[WebViewHandler] Reload");
}
public static void MapEval(WebViewHandler handler, IWebView webView, object? args)
{
if (args is string script)
{
handler.PlatformView?.Eval(script);
Console.WriteLine($"[WebViewHandler] Eval: {script.Substring(0, Math.Min(50, script.Length))}...");
}
}
public static void MapEvaluateJavaScriptAsync(WebViewHandler handler, IWebView webView, object? args)
{
if (args is EvaluateJavaScriptAsyncRequest request)
{
var result = handler.PlatformView?.EvaluateJavaScriptAsync(request.Script);
if (result != null)
{
result.ContinueWith(t =>
{
request.SetResult(t.Result);
});
}
else
{
request.SetResult(null);
}
Console.WriteLine($"[WebViewHandler] EvaluateJavaScriptAsync: {request.Script.Substring(0, Math.Min(50, request.Script.Length))}...");
}
}
#endregion
}
/// <summary>
/// Request object for async JavaScript evaluation.
/// </summary>
public class EvaluateJavaScriptAsyncRequest
{
public string Script { get; }
private readonly TaskCompletionSource<string?> _tcs = new();
public EvaluateJavaScriptAsyncRequest(string script)
{
Script = script;
}
public Task<string?> Task => _tcs.Task;
public void SetResult(string? result)
{
_tcs.TrySetResult(result);
}
}

View File

@@ -1,120 +1,96 @@
using System;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class WebViewHandler : ViewHandler<IWebView, SkiaWebView>
/// <summary>
/// Handler for WebView control on Linux using WebKitGTK.
/// </summary>
public partial class WebViewHandler : ViewHandler<IWebView, SkiaWebView>
{
public static IPropertyMapper<IWebView, WebViewHandler> Mapper = (IPropertyMapper<IWebView, WebViewHandler>)(object)new PropertyMapper<IWebView, WebViewHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ViewHandler.ViewMapper }) { ["Source"] = MapSource };
public static IPropertyMapper<IWebView, WebViewHandler> Mapper = new PropertyMapper<IWebView, WebViewHandler>(ViewHandler.ViewMapper)
{
[nameof(IWebView.Source)] = MapSource,
};
public static CommandMapper<IWebView, WebViewHandler> CommandMapper = new CommandMapper<IWebView, WebViewHandler>((CommandMapper)(object)ViewHandler.ViewCommandMapper)
{
["GoBack"] = MapGoBack,
["GoForward"] = MapGoForward,
["Reload"] = MapReload
};
public static CommandMapper<IWebView, WebViewHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
{
[nameof(IWebView.GoBack)] = MapGoBack,
[nameof(IWebView.GoForward)] = MapGoForward,
[nameof(IWebView.Reload)] = MapReload,
};
public WebViewHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public WebViewHandler() : base(Mapper, CommandMapper)
{
}
public WebViewHandler(IPropertyMapper? mapper = null, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
public WebViewHandler(IPropertyMapper? mapper = null, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override SkiaWebView CreatePlatformView()
{
return new SkiaWebView();
}
protected override SkiaWebView CreatePlatformView()
{
return new SkiaWebView();
}
protected override void ConnectHandler(SkiaWebView platformView)
{
base.ConnectHandler(platformView);
platformView.Navigating += OnNavigating;
platformView.Navigated += OnNavigated;
}
protected override void ConnectHandler(SkiaWebView platformView)
{
base.ConnectHandler(platformView);
protected override void DisconnectHandler(SkiaWebView platformView)
{
platformView.Navigating -= OnNavigating;
platformView.Navigated -= OnNavigated;
base.DisconnectHandler(platformView);
}
platformView.Navigating += OnNavigating;
platformView.Navigated += OnNavigated;
}
private void OnNavigating(object? sender, WebNavigatingEventArgs e)
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Expected O, but got Unknown
IWebView virtualView = base.VirtualView;
IWebViewController val = (IWebViewController)(object)((virtualView is IWebViewController) ? virtualView : null);
if (val != null)
{
WebNavigatingEventArgs e2 = new WebNavigatingEventArgs((WebNavigationEvent)3, (WebViewSource)null, e.Url);
val.SendNavigating(e2);
}
}
protected override void DisconnectHandler(SkiaWebView platformView)
{
platformView.Navigating -= OnNavigating;
platformView.Navigated -= OnNavigated;
private void OnNavigated(object? sender, WebNavigatedEventArgs e)
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Expected O, but got Unknown
IWebView virtualView = base.VirtualView;
IWebViewController val = (IWebViewController)(object)((virtualView is IWebViewController) ? virtualView : null);
if (val != null)
{
WebNavigationResult val2 = (WebNavigationResult)(e.Success ? 1 : 4);
WebNavigatedEventArgs e2 = new WebNavigatedEventArgs((WebNavigationEvent)3, (WebViewSource)null, e.Url, val2);
val.SendNavigated(e2);
}
}
base.DisconnectHandler(platformView);
}
public static void MapSource(WebViewHandler handler, IWebView webView)
{
Console.WriteLine("[WebViewHandler] MapSource called");
if (((ViewHandler<IWebView, SkiaWebView>)(object)handler).PlatformView == null)
{
Console.WriteLine("[WebViewHandler] PlatformView is null!");
return;
}
IWebViewSource source = webView.Source;
Console.WriteLine("[WebViewHandler] Source type: " + (((object)source)?.GetType().Name ?? "null"));
UrlWebViewSource val = (UrlWebViewSource)(object)((source is UrlWebViewSource) ? source : null);
if (val != null)
{
Console.WriteLine("[WebViewHandler] Loading URL: " + val.Url);
((ViewHandler<IWebView, SkiaWebView>)(object)handler).PlatformView.Source = val.Url ?? "";
return;
}
HtmlWebViewSource val2 = (HtmlWebViewSource)(object)((source is HtmlWebViewSource) ? source : null);
if (val2 != null)
{
Console.WriteLine($"[WebViewHandler] Loading HTML ({val2.Html?.Length ?? 0} chars)");
Console.WriteLine("[WebViewHandler] HTML preview: " + val2.Html?.Substring(0, Math.Min(100, val2.Html?.Length ?? 0)) + "...");
((ViewHandler<IWebView, SkiaWebView>)(object)handler).PlatformView.Html = val2.Html ?? "";
}
else
{
Console.WriteLine("[WebViewHandler] Unknown source type or null");
}
}
private void OnNavigating(object? sender, WebNavigatingEventArgs e)
{
// Forward to virtual view if needed
}
public static void MapGoBack(WebViewHandler handler, IWebView webView, object? args)
{
((ViewHandler<IWebView, SkiaWebView>)(object)handler).PlatformView?.GoBack();
}
private void OnNavigated(object? sender, WebNavigatedEventArgs e)
{
// Forward to virtual view if needed
}
public static void MapGoForward(WebViewHandler handler, IWebView webView, object? args)
{
((ViewHandler<IWebView, SkiaWebView>)(object)handler).PlatformView?.GoForward();
}
public static void MapSource(WebViewHandler handler, IWebView webView)
{
if (handler.PlatformView == null) return;
public static void MapReload(WebViewHandler handler, IWebView webView, object? args)
{
((ViewHandler<IWebView, SkiaWebView>)(object)handler).PlatformView?.Reload();
}
var source = webView.Source;
if (source is UrlWebViewSource urlSource)
{
handler.PlatformView.Source = urlSource.Url ?? "";
}
else if (source is HtmlWebViewSource htmlSource)
{
handler.PlatformView.Html = htmlSource.Html ?? "";
}
}
public static void MapGoBack(WebViewHandler handler, IWebView webView, object? args)
{
handler.PlatformView?.GoBack();
}
public static void MapGoForward(WebViewHandler handler, IWebView webView, object? args)
{
handler.PlatformView?.GoForward();
}
public static void MapReload(WebViewHandler handler, IWebView webView, object? args)
{
handler.PlatformView?.Reload();
}
}

View File

@@ -1,166 +1,281 @@
using System;
using Microsoft.Maui.Graphics;
// 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.Handlers;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
public class WindowHandler : ElementHandler<IWindow, SkiaWindow>
/// <summary>
/// Handler for Window on Linux.
/// Maps IWindow to the Linux display window system.
/// </summary>
public partial class WindowHandler : ElementHandler<IWindow, SkiaWindow>
{
public static IPropertyMapper<IWindow, WindowHandler> Mapper = (IPropertyMapper<IWindow, WindowHandler>)(object)new PropertyMapper<IWindow, WindowHandler>((IPropertyMapper[])(object)new IPropertyMapper[1] { (IPropertyMapper)ElementHandler.ElementMapper })
{
["Title"] = MapTitle,
["Content"] = MapContent,
["X"] = MapX,
["Y"] = MapY,
["Width"] = MapWidth,
["Height"] = MapHeight,
["MinimumWidth"] = MapMinimumWidth,
["MinimumHeight"] = MapMinimumHeight,
["MaximumWidth"] = MapMaximumWidth,
["MaximumHeight"] = MapMaximumHeight
};
public static IPropertyMapper<IWindow, WindowHandler> Mapper =
new PropertyMapper<IWindow, WindowHandler>(ElementHandler.ElementMapper)
{
[nameof(IWindow.Title)] = MapTitle,
[nameof(IWindow.Content)] = MapContent,
[nameof(IWindow.X)] = MapX,
[nameof(IWindow.Y)] = MapY,
[nameof(IWindow.Width)] = MapWidth,
[nameof(IWindow.Height)] = MapHeight,
[nameof(IWindow.MinimumWidth)] = MapMinimumWidth,
[nameof(IWindow.MinimumHeight)] = MapMinimumHeight,
[nameof(IWindow.MaximumWidth)] = MapMaximumWidth,
[nameof(IWindow.MaximumHeight)] = MapMaximumHeight,
};
public static CommandMapper<IWindow, WindowHandler> CommandMapper = new CommandMapper<IWindow, WindowHandler>((CommandMapper)(object)ElementHandler.ElementCommandMapper);
public static CommandMapper<IWindow, WindowHandler> CommandMapper =
new(ElementHandler.ElementCommandMapper)
{
};
public WindowHandler()
: base((IPropertyMapper)(object)Mapper, (CommandMapper)(object)CommandMapper)
{
}
public WindowHandler() : base(Mapper, CommandMapper)
{
}
public WindowHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base((IPropertyMapper)(((object)mapper) ?? ((object)Mapper)), (CommandMapper)(((object)commandMapper) ?? ((object)CommandMapper)))
{
}
public WindowHandler(IPropertyMapper? mapper, CommandMapper? commandMapper = null)
: base(mapper ?? Mapper, commandMapper ?? CommandMapper)
{
}
protected override SkiaWindow CreatePlatformElement()
{
return new SkiaWindow();
}
protected override SkiaWindow CreatePlatformElement()
{
return new SkiaWindow();
}
protected override void ConnectHandler(SkiaWindow platformView)
{
base.ConnectHandler(platformView);
platformView.CloseRequested += OnCloseRequested;
platformView.SizeChanged += OnSizeChanged;
}
protected override void ConnectHandler(SkiaWindow platformView)
{
base.ConnectHandler(platformView);
platformView.CloseRequested += OnCloseRequested;
platformView.SizeChanged += OnSizeChanged;
}
protected override void DisconnectHandler(SkiaWindow platformView)
{
platformView.CloseRequested -= OnCloseRequested;
platformView.SizeChanged -= OnSizeChanged;
base.DisconnectHandler(platformView);
}
protected override void DisconnectHandler(SkiaWindow platformView)
{
platformView.CloseRequested -= OnCloseRequested;
platformView.SizeChanged -= OnSizeChanged;
base.DisconnectHandler(platformView);
}
private void OnCloseRequested(object? sender, EventArgs e)
{
IWindow virtualView = base.VirtualView;
if (virtualView != null)
{
virtualView.Destroying();
}
}
private void OnCloseRequested(object? sender, EventArgs e)
{
VirtualView?.Destroying();
}
private void OnSizeChanged(object? sender, SizeChangedEventArgs e)
{
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
IWindow virtualView = base.VirtualView;
if (virtualView != null)
{
virtualView.FrameChanged(new Rect(0.0, 0.0, (double)e.Width, (double)e.Height));
}
}
private void OnSizeChanged(object? sender, SizeChangedEventArgs e)
{
VirtualView?.FrameChanged(new Rect(0, 0, e.Width, e.Height));
}
public static void MapTitle(WindowHandler handler, IWindow window)
{
if (((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView != null)
{
((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView.Title = ((ITitledElement)window).Title ?? "MAUI Application";
}
}
public static void MapTitle(WindowHandler handler, IWindow window)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Title = window.Title ?? "MAUI Application";
}
public static void MapContent(WindowHandler handler, IWindow window)
{
if (((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView != null)
{
IView content = window.Content;
object obj;
if (content == null)
{
obj = null;
}
else
{
IViewHandler handler2 = content.Handler;
obj = ((handler2 != null) ? ((IElementHandler)handler2).PlatformView : null);
}
if (obj is SkiaView content2)
{
((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView.Content = content2;
}
}
}
public static void MapContent(WindowHandler handler, IWindow window)
{
if (handler.PlatformView is null) return;
public static void MapX(WindowHandler handler, IWindow window)
{
if (((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView != null)
{
((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView.X = (int)window.X;
}
}
var content = window.Content;
if (content?.Handler?.PlatformView is SkiaView skiaContent)
{
handler.PlatformView.Content = skiaContent;
}
}
public static void MapY(WindowHandler handler, IWindow window)
{
if (((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView != null)
{
((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView.Y = (int)window.Y;
}
}
public static void MapX(WindowHandler handler, IWindow window)
{
if (handler.PlatformView is null) return;
handler.PlatformView.X = (int)window.X;
}
public static void MapWidth(WindowHandler handler, IWindow window)
{
if (((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView != null)
{
((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView.Width = (int)window.Width;
}
}
public static void MapY(WindowHandler handler, IWindow window)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Y = (int)window.Y;
}
public static void MapHeight(WindowHandler handler, IWindow window)
{
if (((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView != null)
{
((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView.Height = (int)window.Height;
}
}
public static void MapWidth(WindowHandler handler, IWindow window)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Width = (int)window.Width;
}
public static void MapMinimumWidth(WindowHandler handler, IWindow window)
{
if (((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView != null)
{
((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView.MinWidth = (int)window.MinimumWidth;
}
}
public static void MapHeight(WindowHandler handler, IWindow window)
{
if (handler.PlatformView is null) return;
handler.PlatformView.Height = (int)window.Height;
}
public static void MapMinimumHeight(WindowHandler handler, IWindow window)
{
if (((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView != null)
{
((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView.MinHeight = (int)window.MinimumHeight;
}
}
public static void MapMinimumWidth(WindowHandler handler, IWindow window)
{
if (handler.PlatformView is null) return;
handler.PlatformView.MinWidth = (int)window.MinimumWidth;
}
public static void MapMaximumWidth(WindowHandler handler, IWindow window)
{
if (((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView != null)
{
((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView.MaxWidth = (int)window.MaximumWidth;
}
}
public static void MapMinimumHeight(WindowHandler handler, IWindow window)
{
if (handler.PlatformView is null) return;
handler.PlatformView.MinHeight = (int)window.MinimumHeight;
}
public static void MapMaximumHeight(WindowHandler handler, IWindow window)
{
if (((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView != null)
{
((ElementHandler<IWindow, SkiaWindow>)(object)handler).PlatformView.MaxHeight = (int)window.MaximumHeight;
}
}
public static void MapMaximumWidth(WindowHandler handler, IWindow window)
{
if (handler.PlatformView is null) return;
handler.PlatformView.MaxWidth = (int)window.MaximumWidth;
}
public static void MapMaximumHeight(WindowHandler handler, IWindow window)
{
if (handler.PlatformView is null) return;
handler.PlatformView.MaxHeight = (int)window.MaximumHeight;
}
}
/// <summary>
/// Skia window wrapper for Linux display servers.
/// Handles rendering of content and popup overlays automatically.
/// </summary>
public class SkiaWindow
{
private SkiaView? _content;
private string _title = "MAUI Application";
private int _x, _y;
private int _width = 800;
private int _height = 600;
private int _minWidth = 100;
private int _minHeight = 100;
private int _maxWidth = int.MaxValue;
private int _maxHeight = int.MaxValue;
public SkiaView? Content
{
get => _content;
set
{
_content = value;
ContentChanged?.Invoke(this, EventArgs.Empty);
}
}
/// <summary>
/// Renders the window content and popup overlays to the canvas.
/// This should be called by the platform rendering loop.
/// </summary>
public void Render(SKCanvas canvas)
{
// Clear background
canvas.Clear(SKColors.White);
// Draw main content
if (_content != null)
{
_content.Measure(new SKSize(_width, _height));
_content.Arrange(new SKRect(0, 0, _width, _height));
_content.Draw(canvas);
}
// Draw popup overlays on top (dropdowns, date pickers, etc.)
// This ensures popups always render above all other content
SkiaView.DrawPopupOverlays(canvas);
}
public string Title
{
get => _title;
set
{
_title = value;
TitleChanged?.Invoke(this, EventArgs.Empty);
}
}
public int X
{
get => _x;
set { _x = value; PositionChanged?.Invoke(this, EventArgs.Empty); }
}
public int Y
{
get => _y;
set { _y = value; PositionChanged?.Invoke(this, EventArgs.Empty); }
}
public int Width
{
get => _width;
set
{
_width = Math.Clamp(value, _minWidth, _maxWidth);
SizeChanged?.Invoke(this, new SizeChangedEventArgs(_width, _height));
}
}
public int Height
{
get => _height;
set
{
_height = Math.Clamp(value, _minHeight, _maxHeight);
SizeChanged?.Invoke(this, new SizeChangedEventArgs(_width, _height));
}
}
public int MinWidth
{
get => _minWidth;
set { _minWidth = value; }
}
public int MinHeight
{
get => _minHeight;
set { _minHeight = value; }
}
public int MaxWidth
{
get => _maxWidth;
set { _maxWidth = value; }
}
public int MaxHeight
{
get => _maxHeight;
set { _maxHeight = value; }
}
public event EventHandler? ContentChanged;
public event EventHandler? TitleChanged;
public event EventHandler? PositionChanged;
public event EventHandler<SizeChangedEventArgs>? SizeChanged;
public event EventHandler? CloseRequested;
public void Close()
{
CloseRequested?.Invoke(this, EventArgs.Empty);
}
}
/// <summary>
/// Event args for window size changes.
/// </summary>
public class SizeChangedEventArgs : EventArgs
{
public int Width { get; }
public int Height { get; }
public SizeChangedEventArgs(int width, int height)
{
Width = width;
Height = height;
}
}

View File

@@ -1,55 +0,0 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Maui.Animations;
using Microsoft.Maui.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
{
if (_animationManager == null)
{
_animationManager = (IAnimationManager?)(((object)_services.GetService<IAnimationManager>()) ?? ((object)new LinuxAnimationManager((ITicker)(object)new LinuxTicker())));
}
return _animationManager;
}
}
public IDispatcher Dispatcher
{
get
{
if (_dispatcher == null)
{
_dispatcher = (IDispatcher?)(((object)_services.GetService<IDispatcher>()) ?? ((object)new LinuxDispatcher()));
}
return _dispatcher;
}
}
public GtkMauiContext(IServiceProvider services)
{
_services = services ?? throw new ArgumentNullException("services");
_handlers = services.GetRequiredService<IMauiHandlersFactory>();
if (LinuxApplication.Current == null)
{
new LinuxApplication();
}
}
}

View File

@@ -1,12 +0,0 @@
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
{
MauiHandlersCollectionExtensions.AddHandler(handlers, typeof(TView), typeof(THandler));
return handlers;
}
}

View File

@@ -1,54 +0,0 @@
using System.Collections.Generic;
using Microsoft.Maui.Animations;
namespace Microsoft.Maui.Platform.Linux.Hosting;
internal class LinuxAnimationManager : IAnimationManager
{
private readonly List<Animation> _animations = new List<Animation>();
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()
{
Animation[] array = _animations.ToArray();
foreach (Animation val in array)
{
val.Tick(0.016 * SpeedModifier);
if (val.HasFinished)
{
Remove(val);
}
}
}
}

View File

@@ -1,75 +0,0 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Maui.Dispatching;
namespace Microsoft.Maui.Platform.Linux.Hosting;
internal class LinuxDispatcher : IDispatcher
{
private readonly object _lock = new object();
private readonly Queue<Action> _queue = new Queue<Action>();
private bool _isDispatching;
public bool IsDispatchRequired => false;
public IDispatcherTimer CreateTimer()
{
return (IDispatcherTimer)(object)new LinuxDispatcherTimer();
}
public bool Dispatch(Action action)
{
if (action == null)
{
return false;
}
lock (_lock)
{
_queue.Enqueue(action);
}
ProcessQueue();
return true;
}
public bool DispatchDelayed(TimeSpan delay, Action action)
{
if (action == null)
{
return false;
}
Task.Delay(delay).ContinueWith((Task _) => Dispatch(action));
return true;
}
private void ProcessQueue()
{
if (_isDispatching)
{
return;
}
_isDispatching = true;
try
{
while (true)
{
Action action;
lock (_lock)
{
if (_queue.Count == 0)
{
break;
}
action = _queue.Dequeue();
}
action?.Invoke();
}
}
finally
{
_isDispatching = false;
}
}
}

View File

@@ -1,69 +0,0 @@
using System;
using System.Threading;
using Microsoft.Maui.Dispatching;
namespace Microsoft.Maui.Platform.Linux.Hosting;
internal class LinuxDispatcherTimer : IDispatcherTimer
{
private Timer? _timer;
private TimeSpan _interval = TimeSpan.FromMilliseconds(16L, 0L);
private bool _isRunning;
private bool _isRepeating = true;
public TimeSpan Interval
{
get
{
return _interval;
}
set
{
_interval = value;
}
}
public bool IsRunning => _isRunning;
public bool IsRepeating
{
get
{
return _isRepeating;
}
set
{
_isRepeating = value;
}
}
public event EventHandler? Tick;
public void Start()
{
if (!_isRunning)
{
_isRunning = true;
_timer = new Timer(OnTimerCallback, null, _interval, _isRepeating ? _interval : Timeout.InfiniteTimeSpan);
}
}
public void Stop()
{
_isRunning = false;
_timer?.Dispose();
_timer = null;
}
private void OnTimerCallback(object? state)
{
this.Tick?.Invoke(this, EventArgs.Empty);
if (!_isRepeating)
{
Stop();
}
}
}

View File

@@ -1,105 +1,153 @@
using System;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.ComponentModel;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Maui.ApplicationModel;
using Microsoft.Maui.ApplicationModel.Communication;
using Microsoft.Maui.ApplicationModel.DataTransfer;
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.Platform.Linux.Converters;
using Microsoft.Maui.Storage;
using Microsoft.Maui.Platform.Linux.Handlers;
using Microsoft.Maui.Controls;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Hosting;
/// <summary>
/// Extension methods for configuring MAUI applications for Linux.
/// </summary>
public static class LinuxMauiAppBuilderExtensions
{
public static MauiAppBuilder UseLinux(this MauiAppBuilder builder)
{
return builder.UseLinux(null);
}
/// <summary>
/// Configures the MAUI application to run on Linux.
/// </summary>
public static MauiAppBuilder UseLinux(this MauiAppBuilder builder)
{
return builder.UseLinux(configure: null);
}
public static MauiAppBuilder UseLinux(this MauiAppBuilder builder, Action<LinuxApplicationOptions>? configure)
{
LinuxApplicationOptions linuxApplicationOptions = new LinuxApplicationOptions();
configure?.Invoke(linuxApplicationOptions);
builder.Services.TryAddSingleton<IDispatcherProvider>((IDispatcherProvider)(object)LinuxDispatcherProvider.Instance);
builder.Services.TryAddSingleton<IDeviceInfo>((IDeviceInfo)(object)DeviceInfoService.Instance);
builder.Services.TryAddSingleton<IDeviceDisplay>((IDeviceDisplay)(object)DeviceDisplayService.Instance);
builder.Services.TryAddSingleton<IAppInfo>((IAppInfo)(object)AppInfoService.Instance);
builder.Services.TryAddSingleton<IConnectivity>((IConnectivity)(object)ConnectivityService.Instance);
builder.Services.TryAddSingleton<ILauncher, LauncherService>();
builder.Services.TryAddSingleton<IPreferences, PreferencesService>();
builder.Services.TryAddSingleton<IFilePicker, FilePickerService>();
builder.Services.TryAddSingleton<IClipboard, ClipboardService>();
builder.Services.TryAddSingleton<IShare, ShareService>();
builder.Services.TryAddSingleton<ISecureStorage, SecureStorageService>();
builder.Services.TryAddSingleton<IVersionTracking, VersionTrackingService>();
builder.Services.TryAddSingleton<IAppActions, AppActionsService>();
builder.Services.TryAddSingleton<IBrowser, BrowserService>();
builder.Services.TryAddSingleton<IEmail, EmailService>();
builder.Services.TryAddSingleton((IServiceProvider _) => GtkHostService.Instance);
RegisterTypeConverters();
HandlerMauiAppBuilderExtensions.ConfigureMauiHandlers(builder, (Action<IMauiHandlersCollection>)delegate(IMauiHandlersCollection handlers)
{
handlers.AddHandler<IApplication, ApplicationHandler>();
handlers.AddHandler<BoxView, BoxViewHandler>();
handlers.AddHandler<Button, TextButtonHandler>();
handlers.AddHandler<Label, LabelHandler>();
handlers.AddHandler<Entry, EntryHandler>();
handlers.AddHandler<Editor, EditorHandler>();
handlers.AddHandler<CheckBox, CheckBoxHandler>();
handlers.AddHandler<Switch, SwitchHandler>();
handlers.AddHandler<Slider, SliderHandler>();
handlers.AddHandler<Stepper, StepperHandler>();
handlers.AddHandler<RadioButton, RadioButtonHandler>();
handlers.AddHandler<Grid, GridHandler>();
handlers.AddHandler<StackLayout, StackLayoutHandler>();
handlers.AddHandler<VerticalStackLayout, StackLayoutHandler>();
handlers.AddHandler<HorizontalStackLayout, StackLayoutHandler>();
handlers.AddHandler<AbsoluteLayout, LayoutHandler>();
handlers.AddHandler<FlexLayout, LayoutHandler>();
handlers.AddHandler<ScrollView, ScrollViewHandler>();
handlers.AddHandler<Frame, FrameHandler>();
handlers.AddHandler<Border, BorderHandler>();
handlers.AddHandler<ContentView, BorderHandler>();
handlers.AddHandler<Picker, PickerHandler>();
handlers.AddHandler<DatePicker, DatePickerHandler>();
handlers.AddHandler<TimePicker, TimePickerHandler>();
handlers.AddHandler<SearchBar, SearchBarHandler>();
handlers.AddHandler<ProgressBar, ProgressBarHandler>();
handlers.AddHandler<ActivityIndicator, ActivityIndicatorHandler>();
handlers.AddHandler<Image, ImageHandler>();
handlers.AddHandler<ImageButton, ImageButtonHandler>();
handlers.AddHandler<GraphicsView, GraphicsViewHandler>();
handlers.AddHandler<WebView, GtkWebViewHandler>();
handlers.AddHandler<CollectionView, CollectionViewHandler>();
handlers.AddHandler<ListView, CollectionViewHandler>();
handlers.AddHandler<Page, PageHandler>();
handlers.AddHandler<ContentPage, ContentPageHandler>();
handlers.AddHandler<NavigationPage, NavigationPageHandler>();
handlers.AddHandler<Shell, ShellHandler>();
handlers.AddHandler<FlyoutPage, FlyoutPageHandler>();
handlers.AddHandler<TabbedPage, TabbedPageHandler>();
handlers.AddHandler<Application, ApplicationHandler>();
handlers.AddHandler<Window, WindowHandler>();
});
builder.Services.AddSingleton(linuxApplicationOptions);
return builder;
}
/// <summary>
/// Configures the MAUI application to run on Linux with options.
/// </summary>
public static MauiAppBuilder UseLinux(this MauiAppBuilder builder, Action<LinuxApplicationOptions>? configure)
{
var options = new LinuxApplicationOptions();
configure?.Invoke(options);
private static void RegisterTypeConverters()
{
TypeDescriptor.AddAttributes(typeof(SKColor), new TypeConverterAttribute(typeof(SKColorTypeConverter)));
TypeDescriptor.AddAttributes(typeof(SKRect), new TypeConverterAttribute(typeof(SKRectTypeConverter)));
TypeDescriptor.AddAttributes(typeof(SKSize), new TypeConverterAttribute(typeof(SKSizeTypeConverter)));
TypeDescriptor.AddAttributes(typeof(SKPoint), new TypeConverterAttribute(typeof(SKPointTypeConverter)));
}
// Register platform services
builder.Services.TryAddSingleton<ILauncher, LauncherService>();
builder.Services.TryAddSingleton<IPreferences, PreferencesService>();
builder.Services.TryAddSingleton<IFilePicker, FilePickerService>();
builder.Services.TryAddSingleton<IClipboard, ClipboardService>();
builder.Services.TryAddSingleton<IShare, ShareService>();
builder.Services.TryAddSingleton<ISecureStorage, SecureStorageService>();
builder.Services.TryAddSingleton<IVersionTracking, VersionTrackingService>();
builder.Services.TryAddSingleton<IAppActions, AppActionsService>();
builder.Services.TryAddSingleton<IBrowser, BrowserService>();
builder.Services.TryAddSingleton<IEmail, EmailService>();
// Register type converters for XAML support
RegisterTypeConverters();
// Register Linux-specific handlers
builder.ConfigureMauiHandlers(handlers =>
{
// Application handler
handlers.AddHandler<IApplication, ApplicationHandler>();
// Core controls
handlers.AddHandler<BoxView, BoxViewHandler>();
handlers.AddHandler<Button, TextButtonHandler>();
handlers.AddHandler<Label, LabelHandler>();
handlers.AddHandler<Entry, EntryHandler>();
handlers.AddHandler<Editor, EditorHandler>();
handlers.AddHandler<CheckBox, CheckBoxHandler>();
handlers.AddHandler<Switch, SwitchHandler>();
handlers.AddHandler<Slider, SliderHandler>();
handlers.AddHandler<Stepper, StepperHandler>();
handlers.AddHandler<RadioButton, RadioButtonHandler>();
// Layout controls
handlers.AddHandler<Grid, GridHandler>();
handlers.AddHandler<StackLayout, StackLayoutHandler>();
handlers.AddHandler<VerticalStackLayout, StackLayoutHandler>();
handlers.AddHandler<HorizontalStackLayout, StackLayoutHandler>();
handlers.AddHandler<AbsoluteLayout, LayoutHandler>();
handlers.AddHandler<FlexLayout, LayoutHandler>();
handlers.AddHandler<ScrollView, ScrollViewHandler>();
handlers.AddHandler<Frame, FrameHandler>();
handlers.AddHandler<Border, BorderHandler>();
handlers.AddHandler<ContentView, BorderHandler>();
// Picker controls
handlers.AddHandler<Picker, PickerHandler>();
handlers.AddHandler<DatePicker, DatePickerHandler>();
handlers.AddHandler<TimePicker, TimePickerHandler>();
handlers.AddHandler<SearchBar, SearchBarHandler>();
// Progress & Activity
handlers.AddHandler<ProgressBar, ProgressBarHandler>();
handlers.AddHandler<ActivityIndicator, ActivityIndicatorHandler>();
// Image & Graphics
handlers.AddHandler<Image, ImageHandler>();
handlers.AddHandler<ImageButton, ImageButtonHandler>();
handlers.AddHandler<GraphicsView, GraphicsViewHandler>();
// Collection Views
handlers.AddHandler<CollectionView, CollectionViewHandler>();
handlers.AddHandler<ListView, CollectionViewHandler>();
// Pages & Navigation
handlers.AddHandler<Page, PageHandler>();
handlers.AddHandler<ContentPage, ContentPageHandler>();
handlers.AddHandler<NavigationPage, NavigationPageHandler>();
handlers.AddHandler<Shell, ShellHandler>();
handlers.AddHandler<FlyoutPage, FlyoutPageHandler>();
handlers.AddHandler<TabbedPage, TabbedPageHandler>();
// Application & Window
handlers.AddHandler<Application, ApplicationHandler>();
handlers.AddHandler<Microsoft.Maui.Controls.Window, WindowHandler>();
});
// Store options for later use
builder.Services.AddSingleton(options);
return builder;
}
/// <summary>
/// Registers custom type converters for Linux platform.
/// </summary>
private static void RegisterTypeConverters()
{
// Register SkiaSharp type converters for XAML styling support
TypeDescriptor.AddAttributes(typeof(SKColor), new TypeConverterAttribute(typeof(SKColorTypeConverter)));
TypeDescriptor.AddAttributes(typeof(SKRect), new TypeConverterAttribute(typeof(SKRectTypeConverter)));
TypeDescriptor.AddAttributes(typeof(SKSize), new TypeConverterAttribute(typeof(SKSizeTypeConverter)));
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;
}
}

View File

@@ -1,56 +1,299 @@
using System;
// 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;
using SkiaSharp;
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
{
private readonly IServiceProvider _services;
private readonly IServiceProvider _services;
private readonly IMauiHandlersFactory _handlers;
private readonly LinuxApplication _linuxApp;
private IAnimationManager? _animationManager;
private IDispatcher? _dispatcher;
private readonly IMauiHandlersFactory _handlers;
public LinuxMauiContext(IServiceProvider services, LinuxApplication linuxApp)
{
_services = services ?? throw new ArgumentNullException(nameof(services));
_linuxApp = linuxApp ?? throw new ArgumentNullException(nameof(linuxApp));
_handlers = services.GetRequiredService<IMauiHandlersFactory>();
}
private readonly LinuxApplication _linuxApp;
/// <inheritdoc />
public IServiceProvider Services => _services;
private IAnimationManager? _animationManager;
/// <inheritdoc />
public IMauiHandlersFactory Handlers => _handlers;
private IDispatcher? _dispatcher;
/// <summary>
/// Gets the Linux application instance.
/// </summary>
public LinuxApplication LinuxApp => _linuxApp;
public IServiceProvider Services => _services;
/// <summary>
/// Gets the animation manager.
/// </summary>
public IAnimationManager AnimationManager
{
get
{
_animationManager ??= _services.GetService<IAnimationManager>()
?? new LinuxAnimationManager(new LinuxTicker());
return _animationManager;
}
}
public IMauiHandlersFactory Handlers => _handlers;
public LinuxApplication LinuxApp => _linuxApp;
public IAnimationManager AnimationManager
{
get
{
if (_animationManager == null)
{
_animationManager = (IAnimationManager?)(((object)_services.GetService<IAnimationManager>()) ?? ((object)new LinuxAnimationManager((ITicker)(object)new LinuxTicker())));
}
return _animationManager;
}
}
public IDispatcher Dispatcher
{
get
{
if (_dispatcher == null)
{
_dispatcher = (IDispatcher?)(((object)_services.GetService<IDispatcher>()) ?? ((object)new LinuxDispatcher()));
}
return _dispatcher;
}
}
public LinuxMauiContext(IServiceProvider services, LinuxApplication linuxApp)
{
_services = services ?? throw new ArgumentNullException("services");
_linuxApp = linuxApp ?? throw new ArgumentNullException("linuxApp");
_handlers = services.GetRequiredService<IMauiHandlersFactory>();
}
/// <summary>
/// Gets the dispatcher for UI thread operations.
/// </summary>
public IDispatcher Dispatcher
{
get
{
_dispatcher ??= _services.GetService<IDispatcher>()
?? new LinuxDispatcher();
return _dispatcher;
}
}
}
/// <summary>
/// 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));
}
public IServiceProvider Services => _parent.Services;
public IMauiHandlersFactory Handlers => _parent.Handlers;
}
/// <summary>
/// Linux dispatcher for UI thread operations.
/// </summary>
internal class LinuxDispatcher : IDispatcher
{
private readonly object _lock = new();
private readonly Queue<Action> _queue = new();
private bool _isDispatching;
public bool IsDispatchRequired => false; // Linux uses single-threaded event loop
public IDispatcherTimer CreateTimer()
{
return new LinuxDispatcherTimer();
}
public bool Dispatch(Action action)
{
if (action == null)
return false;
lock (_lock)
{
_queue.Enqueue(action);
}
ProcessQueue();
return true;
}
public bool DispatchDelayed(TimeSpan delay, Action action)
{
if (action == null)
return false;
Task.Delay(delay).ContinueWith(_ => Dispatch(action));
return true;
}
private void ProcessQueue()
{
if (_isDispatching)
return;
_isDispatching = true;
try
{
while (true)
{
Action? action;
lock (_lock)
{
if (_queue.Count == 0)
break;
action = _queue.Dequeue();
}
action?.Invoke();
}
}
finally
{
_isDispatching = false;
}
}
}
/// <summary>
/// Linux dispatcher timer implementation.
/// </summary>
internal class LinuxDispatcherTimer : IDispatcherTimer
{
private Timer? _timer;
private TimeSpan _interval = TimeSpan.FromMilliseconds(16); // ~60fps default
private bool _isRunning;
private bool _isRepeating = true;
public TimeSpan Interval
{
get => _interval;
set => _interval = value;
}
public bool IsRunning => _isRunning;
public bool IsRepeating
{
get => _isRepeating;
set => _isRepeating = value;
}
public event EventHandler? Tick;
public void Start()
{
if (_isRunning)
return;
_isRunning = true;
_timer = new Timer(OnTimerCallback, null, _interval, _isRepeating ? _interval : Timeout.InfiniteTimeSpan);
}
public void Stop()
{
_isRunning = false;
_timer?.Dispose();
_timer = null;
}
private void OnTimerCallback(object? state)
{
Tick?.Invoke(this, EventArgs.Empty);
if (!_isRepeating)
{
Stop();
}
}
}
/// <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();
}
}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,54 +0,0 @@
using System;
using System.Threading;
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
{
return _maxFps;
}
set
{
_maxFps = Math.Max(1, Math.Min(120, value));
}
}
public Action? Fire { get; set; }
public void Start()
{
if (!_isRunning)
{
_isRunning = true;
TimeSpan period = TimeSpan.FromMilliseconds(1000.0 / (double)_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();
}
}

View File

@@ -1,470 +1,497 @@
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Platform;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Hosting;
/// <summary>
/// Renders MAUI views to Skia platform views.
/// Handles the conversion of the view hierarchy.
/// </summary>
public class LinuxViewRenderer
{
private readonly IMauiContext _mauiContext;
private readonly IMauiContext _mauiContext;
public static Shell? CurrentMauiShell { get; private set; }
/// <summary>
/// Static reference to the current MAUI Shell for navigation support.
/// Used when Shell.Current is not available through normal lifecycle.
/// </summary>
public static Shell? CurrentMauiShell { get; private set; }
public static SkiaShell? CurrentSkiaShell { get; private set; }
/// <summary>
/// Static reference to the current SkiaShell for navigation updates.
/// </summary>
public static SkiaShell? CurrentSkiaShell { get; private set; }
public static LinuxViewRenderer? CurrentRenderer { get; set; }
/// <summary>
/// Navigate to a route using the SkiaShell directly.
/// Use this instead of Shell.Current.GoToAsync on Linux.
/// </summary>
/// <param name="route">The route to navigate to (e.g., "Buttons" or "//Buttons")</param>
/// <returns>True if navigation succeeded</returns>
public static bool NavigateToRoute(string route)
{
if (CurrentSkiaShell == null)
{
Console.WriteLine($"[NavigateToRoute] CurrentSkiaShell is null");
return false;
}
public static bool NavigateToRoute(string route)
{
if (CurrentSkiaShell == null)
{
Console.WriteLine("[NavigateToRoute] CurrentSkiaShell is null");
return false;
}
string text = route.TrimStart('/');
Console.WriteLine("[NavigateToRoute] Navigating to: " + text);
for (int i = 0; i < CurrentSkiaShell.Sections.Count; i++)
{
ShellSection shellSection = CurrentSkiaShell.Sections[i];
if (shellSection.Route.Equals(text, StringComparison.OrdinalIgnoreCase) || shellSection.Title.Equals(text, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine($"[NavigateToRoute] Found section {i}: {shellSection.Title}");
CurrentSkiaShell.NavigateToSection(i);
return true;
}
}
Console.WriteLine("[NavigateToRoute] Route not found: " + text);
return false;
}
// Clean up the route - remove leading // or /
var cleanRoute = route.TrimStart('/');
Console.WriteLine($"[NavigateToRoute] Navigating to: {cleanRoute}");
public static bool PushPage(Page page)
{
Console.WriteLine("[PushPage] Pushing page: " + ((object)page).GetType().Name);
if (CurrentSkiaShell == null)
{
Console.WriteLine("[PushPage] CurrentSkiaShell is null");
return false;
}
if (CurrentRenderer == null)
{
Console.WriteLine("[PushPage] CurrentRenderer is null");
return false;
}
try
{
SkiaView skiaView = null;
ContentPage val = (ContentPage)(object)((page is ContentPage) ? page : null);
if (val != null && val.Content != null)
{
skiaView = CurrentRenderer.RenderView((IView)(object)val.Content);
}
if (skiaView == null)
{
Console.WriteLine("[PushPage] Failed to render page content");
return false;
}
if (!(skiaView is SkiaScrollView))
{
skiaView = new SkiaScrollView
{
Content = skiaView
};
}
CurrentSkiaShell.PushAsync(skiaView, page.Title ?? "Detail");
Console.WriteLine("[PushPage] Successfully pushed page");
return true;
}
catch (Exception ex)
{
Console.WriteLine("[PushPage] Error: " + ex.Message);
return false;
}
}
for (int i = 0; i < CurrentSkiaShell.Sections.Count; i++)
{
var section = CurrentSkiaShell.Sections[i];
if (section.Route.Equals(cleanRoute, StringComparison.OrdinalIgnoreCase) ||
section.Title.Equals(cleanRoute, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine($"[NavigateToRoute] Found section {i}: {section.Title}");
CurrentSkiaShell.NavigateToSection(i);
return true;
}
}
public static bool PopPage()
{
Console.WriteLine("[PopPage] Popping page");
if (CurrentSkiaShell == null)
{
Console.WriteLine("[PopPage] CurrentSkiaShell is null");
return false;
}
return CurrentSkiaShell.PopAsync();
}
Console.WriteLine($"[NavigateToRoute] Route not found: {cleanRoute}");
return false;
}
public LinuxViewRenderer(IMauiContext mauiContext)
{
_mauiContext = mauiContext ?? throw new ArgumentNullException("mauiContext");
CurrentRenderer = this;
}
/// <summary>
/// Current renderer instance for page rendering.
/// </summary>
public static LinuxViewRenderer? CurrentRenderer { get; set; }
public SkiaView? RenderPage(Page page)
{
if (page == null)
{
return null;
}
Shell val = (Shell)(object)((page is Shell) ? page : null);
if (val != null)
{
return RenderShell(val);
}
IViewHandler handler = ((VisualElement)page).Handler;
if (handler != null)
{
((IElementHandler)handler).DisconnectHandler();
}
if (((IElement)(object)page).ToHandler(_mauiContext).PlatformView is SkiaView skiaView)
{
ContentPage val2 = (ContentPage)(object)((page is ContentPage) ? page : null);
if (val2 != null && val2.Content != null)
{
SkiaView skiaView2 = RenderView((IView)(object)val2.Content);
if (skiaView is SkiaPage skiaPage && skiaView2 != null)
{
skiaPage.Content = skiaView2;
}
}
return skiaView;
}
return null;
}
/// <summary>
/// Pushes a page onto the navigation stack.
/// </summary>
/// <param name="page">The page to push</param>
/// <returns>True if successful</returns>
public static bool PushPage(Page page)
{
Console.WriteLine($"[PushPage] Pushing page: {page.GetType().Name}");
private SkiaShell RenderShell(Shell shell)
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Expected I4, but got Unknown
CurrentMauiShell = shell;
SkiaShell skiaShell = new SkiaShell();
skiaShell.Title = ((Page)shell).Title ?? "App";
SkiaShell skiaShell2 = skiaShell;
FlyoutBehavior flyoutBehavior = shell.FlyoutBehavior;
skiaShell2.FlyoutBehavior = (int)flyoutBehavior switch
{
1 => ShellFlyoutBehavior.Flyout,
2 => ShellFlyoutBehavior.Locked,
0 => ShellFlyoutBehavior.Disabled,
_ => ShellFlyoutBehavior.Flyout,
};
skiaShell.MauiShell = shell;
SkiaShell skiaShell3 = skiaShell;
ApplyShellColors(skiaShell3, shell);
object flyoutHeader = shell.FlyoutHeader;
View val = (View)((flyoutHeader is View) ? flyoutHeader : null);
if (val != null)
{
SkiaView skiaView = RenderView((IView)(object)val);
if (skiaView != null)
{
skiaShell3.FlyoutHeaderView = skiaView;
skiaShell3.FlyoutHeaderHeight = (float)((((VisualElement)val).HeightRequest > 0.0) ? ((VisualElement)val).HeightRequest : 140.0);
}
}
Version version = Assembly.GetEntryAssembly()?.GetName().Version;
skiaShell3.FlyoutFooterText = $"Version {version?.Major ?? 1}.{version?.Minor ?? 0}.{version?.Build ?? 0}";
foreach (ShellItem item in shell.Items)
{
ProcessShellItem(skiaShell3, item);
}
CurrentSkiaShell = skiaShell3;
skiaShell3.ContentRenderer = CreateShellContentPage;
skiaShell3.ColorRefresher = ApplyShellColors;
shell.Navigated += OnShellNavigated;
shell.Navigating += delegate(object? s, ShellNavigatingEventArgs e)
{
Console.WriteLine($"[Navigation] Navigating: {e.Target}");
};
Console.WriteLine($"[Navigation] Shell navigation events subscribed. Sections: {skiaShell3.Sections.Count}");
for (int num = 0; num < skiaShell3.Sections.Count; num++)
{
Console.WriteLine($"[Navigation] Section {num}: Route='{skiaShell3.Sections[num].Route}', Title='{skiaShell3.Sections[num].Title}'");
}
return skiaShell3;
}
if (CurrentSkiaShell == null)
{
Console.WriteLine($"[PushPage] CurrentSkiaShell is null");
return false;
}
private static void ApplyShellColors(SkiaShell skiaShell, Shell shell)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Invalid comparison between Unknown and I4
//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
//IL_0087: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_0105: Unknown result type (might be due to invalid IL or missing references)
//IL_013b: Unknown result type (might be due to invalid IL or missing references)
//IL_0125: Unknown result type (might be due to invalid IL or missing references)
//IL_015e: Unknown result type (might be due to invalid IL or missing references)
//IL_0194: Unknown result type (might be due to invalid IL or missing references)
//IL_0187: Unknown result type (might be due to invalid IL or missing references)
//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
//IL_0236: Unknown result type (might be due to invalid IL or missing references)
//IL_021e: Unknown result type (might be due to invalid IL or missing references)
Application current = Application.Current;
bool flag = current != null && (int)current.UserAppTheme == 2;
Console.WriteLine("[ApplyShellColors] Theme is: " + (flag ? "Dark" : "Light"));
if (shell.FlyoutBackgroundColor != null && shell.FlyoutBackgroundColor != Colors.Transparent)
{
Color flyoutBackgroundColor = shell.FlyoutBackgroundColor;
skiaShell.FlyoutBackgroundColor = new SKColor((byte)(flyoutBackgroundColor.Red * 255f), (byte)(flyoutBackgroundColor.Green * 255f), (byte)(flyoutBackgroundColor.Blue * 255f), (byte)(flyoutBackgroundColor.Alpha * 255f));
Console.WriteLine($"[ApplyShellColors] FlyoutBackgroundColor from MAUI: {skiaShell.FlyoutBackgroundColor}");
}
else
{
skiaShell.FlyoutBackgroundColor = (flag ? new SKColor((byte)30, (byte)30, (byte)30) : new SKColor(byte.MaxValue, byte.MaxValue, byte.MaxValue));
Console.WriteLine($"[ApplyShellColors] Using default FlyoutBackgroundColor: {skiaShell.FlyoutBackgroundColor}");
}
skiaShell.FlyoutTextColor = (flag ? new SKColor((byte)224, (byte)224, (byte)224) : new SKColor((byte)33, (byte)33, (byte)33));
Console.WriteLine($"[ApplyShellColors] FlyoutTextColor: {skiaShell.FlyoutTextColor}");
skiaShell.ContentBackgroundColor = (flag ? new SKColor((byte)18, (byte)18, (byte)18) : new SKColor((byte)250, (byte)250, (byte)250));
Console.WriteLine($"[ApplyShellColors] ContentBackgroundColor: {skiaShell.ContentBackgroundColor}");
if (((VisualElement)shell).BackgroundColor != null && ((VisualElement)shell).BackgroundColor != Colors.Transparent)
{
Color backgroundColor = ((VisualElement)shell).BackgroundColor;
skiaShell.NavBarBackgroundColor = new SKColor((byte)(backgroundColor.Red * 255f), (byte)(backgroundColor.Green * 255f), (byte)(backgroundColor.Blue * 255f), (byte)(backgroundColor.Alpha * 255f));
}
else
{
skiaShell.NavBarBackgroundColor = new SKColor((byte)33, (byte)150, (byte)243);
}
}
if (CurrentRenderer == null)
{
Console.WriteLine($"[PushPage] CurrentRenderer is null");
return false;
}
private static void OnShellNavigated(object? sender, ShellNavigatedEventArgs e)
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(70, 3);
defaultInterpolatedStringHandler.AppendLiteral("[Navigation] OnShellNavigated called - Source: ");
defaultInterpolatedStringHandler.AppendFormatted<ShellNavigationSource>(e.Source);
defaultInterpolatedStringHandler.AppendLiteral(", Current: ");
ShellNavigationState current = e.Current;
defaultInterpolatedStringHandler.AppendFormatted((current != null) ? current.Location : null);
defaultInterpolatedStringHandler.AppendLiteral(", Previous: ");
ShellNavigationState previous = e.Previous;
defaultInterpolatedStringHandler.AppendFormatted((previous != null) ? previous.Location : null);
Console.WriteLine(defaultInterpolatedStringHandler.ToStringAndClear());
if (CurrentSkiaShell == null || CurrentMauiShell == null)
{
Console.WriteLine("[Navigation] CurrentSkiaShell or CurrentMauiShell is null");
return;
}
ShellNavigationState currentState = CurrentMauiShell.CurrentState;
string text = ((currentState == null) ? null : currentState.Location?.OriginalString) ?? "";
Console.WriteLine($"[Navigation] Location: {text}, Sections: {CurrentSkiaShell.Sections.Count}");
for (int i = 0; i < CurrentSkiaShell.Sections.Count; i++)
{
ShellSection shellSection = CurrentSkiaShell.Sections[i];
Console.WriteLine($"[Navigation] Checking section {i}: Route='{shellSection.Route}', Title='{shellSection.Title}'");
if (!string.IsNullOrEmpty(shellSection.Route) && text.Contains(shellSection.Route, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine($"[Navigation] Match found by route! Navigating to section {i}");
if (i != CurrentSkiaShell.CurrentSectionIndex)
{
CurrentSkiaShell.NavigateToSection(i);
}
return;
}
if (!string.IsNullOrEmpty(shellSection.Title) && text.Contains(shellSection.Title, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine($"[Navigation] Match found by title! Navigating to section {i}");
if (i != CurrentSkiaShell.CurrentSectionIndex)
{
CurrentSkiaShell.NavigateToSection(i);
}
return;
}
}
Console.WriteLine("[Navigation] No matching section found for location: " + text);
}
try
{
// Render the page content
SkiaView? pageContent = null;
if (page is ContentPage contentPage && contentPage.Content != null)
{
pageContent = CurrentRenderer.RenderView(contentPage.Content);
}
private void ProcessShellItem(SkiaShell skiaShell, ShellItem item)
{
FlyoutItem val = (FlyoutItem)(object)((item is FlyoutItem) ? item : null);
if (val != null)
{
ShellSection shellSection = new ShellSection
{
Title = (((BaseShellItem)val).Title ?? ""),
Route = (((BaseShellItem)val).Route ?? ((BaseShellItem)val).Title ?? "")
};
foreach (ShellSection item2 in ((ShellItem)val).Items)
{
foreach (ShellContent item3 in item2.Items)
{
ShellContent shellContent = new ShellContent
{
Title = (((BaseShellItem)item3).Title ?? ((BaseShellItem)item2).Title ?? ((BaseShellItem)val).Title ?? ""),
Route = (((BaseShellItem)item3).Route ?? ""),
MauiShellContent = item3
};
SkiaView skiaView = CreateShellContentPage(item3);
if (skiaView != null)
{
shellContent.Content = skiaView;
}
shellSection.Items.Add(shellContent);
}
}
if (shellSection.Items.Count == 1)
{
shellSection.Title = shellSection.Items[0].Title;
}
skiaShell.AddSection(shellSection);
return;
}
TabBar val2 = (TabBar)(object)((item is TabBar) ? item : null);
if (val2 != null)
{
foreach (ShellSection item4 in ((ShellItem)val2).Items)
{
ShellSection shellSection2 = new ShellSection
{
Title = (((BaseShellItem)item4).Title ?? ""),
Route = (((BaseShellItem)item4).Route ?? "")
};
foreach (ShellContent item5 in item4.Items)
{
ShellContent shellContent2 = new ShellContent
{
Title = (((BaseShellItem)item5).Title ?? ((BaseShellItem)item4).Title ?? ""),
Route = (((BaseShellItem)item5).Route ?? ""),
MauiShellContent = item5
};
SkiaView skiaView2 = CreateShellContentPage(item5);
if (skiaView2 != null)
{
shellContent2.Content = skiaView2;
}
shellSection2.Items.Add(shellContent2);
}
skiaShell.AddSection(shellSection2);
}
return;
}
ShellSection shellSection3 = new ShellSection
{
Title = (((BaseShellItem)item).Title ?? ""),
Route = (((BaseShellItem)item).Route ?? "")
};
foreach (ShellSection item6 in item.Items)
{
foreach (ShellContent item7 in item6.Items)
{
ShellContent shellContent3 = new ShellContent
{
Title = (((BaseShellItem)item7).Title ?? ""),
Route = (((BaseShellItem)item7).Route ?? ""),
MauiShellContent = item7
};
SkiaView skiaView3 = CreateShellContentPage(item7);
if (skiaView3 != null)
{
shellContent3.Content = skiaView3;
}
shellSection3.Items.Add(shellContent3);
}
}
skiaShell.AddSection(shellSection3);
}
if (pageContent == null)
{
Console.WriteLine($"[PushPage] Failed to render page content");
return false;
}
private SkiaView? CreateShellContentPage(ShellContent content)
{
//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
//IL_0135: Unknown result type (might be due to invalid IL or missing references)
//IL_010a: Unknown result type (might be due to invalid IL or missing references)
try
{
Page val = null;
if (content.ContentTemplate != null)
{
object obj = ((ElementTemplate)content.ContentTemplate).CreateContent();
val = (Page)((obj is Page) ? obj : null);
}
if (val == null)
{
object content2 = content.Content;
Page val2 = (Page)((content2 is Page) ? content2 : null);
if (val2 != null)
{
val = val2;
}
}
ContentPage val3 = (ContentPage)(object)((val is ContentPage) ? val : null);
if (val3 != null && val3.Content != null)
{
SkiaView skiaView = RenderView((IView)(object)val3.Content);
if (skiaView != null)
{
SKColor? value = null;
if (((VisualElement)val3).BackgroundColor != null && ((VisualElement)val3).BackgroundColor != Colors.Transparent)
{
Color backgroundColor = ((VisualElement)val3).BackgroundColor;
value = new SKColor((byte)(backgroundColor.Red * 255f), (byte)(backgroundColor.Green * 255f), (byte)(backgroundColor.Blue * 255f), (byte)(backgroundColor.Alpha * 255f));
Console.WriteLine($"[CreateShellContentPage] Page BackgroundColor: {value}");
}
if (skiaView is SkiaScrollView skiaScrollView)
{
if (value.HasValue)
{
skiaScrollView.BackgroundColor = value.Value;
}
return skiaScrollView;
}
SkiaScrollView skiaScrollView2 = new SkiaScrollView
{
Content = skiaView
};
if (value.HasValue)
{
skiaScrollView2.BackgroundColor = value.Value;
}
return skiaScrollView2;
}
}
}
catch (Exception)
{
}
return null;
}
// Wrap in ScrollView if needed
if (pageContent is not SkiaScrollView)
{
var scrollView = new SkiaScrollView { Content = pageContent };
pageContent = scrollView;
}
public SkiaView? RenderView(IView view)
{
if (view == null)
{
return null;
}
try
{
Element val = (Element)(object)((view is Element) ? view : null);
if (val != null && val.Handler != null)
{
val.Handler.DisconnectHandler();
}
IElementHandler obj = ((IElement)(object)view).ToHandler(_mauiContext);
if (!(((obj != null) ? obj.PlatformView : null) is SkiaView result))
{
return CreateFallbackView(view);
}
return result;
}
catch (Exception)
{
return CreateFallbackView(view);
}
}
// Push onto SkiaShell's navigation stack
CurrentSkiaShell.PushAsync(pageContent, page.Title ?? "Detail");
Console.WriteLine($"[PushPage] Successfully pushed page");
return true;
}
catch (Exception ex)
{
Console.WriteLine($"[PushPage] Error: {ex.Message}");
return false;
}
}
private SkiaView CreateFallbackView(IView view)
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
return new SkiaLabel
{
Text = "[" + ((object)view).GetType().Name + "]",
TextColor = SKColors.Gray,
FontSize = 12f
};
}
/// <summary>
/// Pops the current page from the navigation stack.
/// </summary>
/// <returns>True if successful</returns>
public static bool PopPage()
{
Console.WriteLine($"[PopPage] Popping page");
if (CurrentSkiaShell == null)
{
Console.WriteLine($"[PopPage] CurrentSkiaShell is null");
return false;
}
return CurrentSkiaShell.PopAsync();
}
public LinuxViewRenderer(IMauiContext mauiContext)
{
_mauiContext = mauiContext ?? throw new ArgumentNullException(nameof(mauiContext));
// Store reference for push/pop navigation
CurrentRenderer = this;
}
/// <summary>
/// Renders a MAUI page and returns the corresponding SkiaView.
/// </summary>
public SkiaView? RenderPage(Page page)
{
if (page == null)
return null;
// Special handling for Shell - Shell is our navigation container
if (page is Shell shell)
{
return RenderShell(shell);
}
// Set handler context
page.Handler?.DisconnectHandler();
var handler = page.ToHandler(_mauiContext);
if (handler.PlatformView is SkiaView skiaPage)
{
// For ContentPage, render the content
if (page is ContentPage contentPage && contentPage.Content != null)
{
var contentView = RenderView(contentPage.Content);
if (skiaPage is SkiaPage sp && contentView != null)
{
sp.Content = contentView;
}
}
return skiaPage;
}
return null;
}
/// <summary>
/// Renders a MAUI Shell with all its navigation structure.
/// </summary>
private SkiaShell RenderShell(Shell shell)
{
// Store reference for navigation - Shell.Current is computed from Application.Current.Windows
// Our platform handles navigation through SkiaShell directly
CurrentMauiShell = shell;
var skiaShell = new SkiaShell
{
Title = shell.Title ?? "App",
FlyoutBehavior = shell.FlyoutBehavior switch
{
FlyoutBehavior.Flyout => ShellFlyoutBehavior.Flyout,
FlyoutBehavior.Locked => ShellFlyoutBehavior.Locked,
FlyoutBehavior.Disabled => ShellFlyoutBehavior.Disabled,
_ => ShellFlyoutBehavior.Flyout
}
};
// Process shell items into sections
foreach (var item in shell.Items)
{
ProcessShellItem(skiaShell, item);
}
// Store reference to SkiaShell for navigation
CurrentSkiaShell = skiaShell;
// Subscribe to MAUI Shell navigation events to update SkiaShell
shell.Navigated += OnShellNavigated;
shell.Navigating += (s, e) => Console.WriteLine($"[Navigation] Navigating: {e.Target}");
Console.WriteLine($"[Navigation] Shell navigation events subscribed. Sections: {skiaShell.Sections.Count}");
for (int i = 0; i < skiaShell.Sections.Count; i++)
{
Console.WriteLine($"[Navigation] Section {i}: Route='{skiaShell.Sections[i].Route}', Title='{skiaShell.Sections[i].Title}'");
}
return skiaShell;
}
/// <summary>
/// Handles MAUI Shell navigation events and updates SkiaShell accordingly.
/// </summary>
private static void OnShellNavigated(object? sender, ShellNavigatedEventArgs e)
{
Console.WriteLine($"[Navigation] OnShellNavigated called - Source: {e.Source}, Current: {e.Current?.Location}, Previous: {e.Previous?.Location}");
if (CurrentSkiaShell == null || CurrentMauiShell == null)
{
Console.WriteLine($"[Navigation] CurrentSkiaShell or CurrentMauiShell is null");
return;
}
// Get the current route from the Shell
var currentState = CurrentMauiShell.CurrentState;
var location = currentState?.Location?.OriginalString ?? "";
Console.WriteLine($"[Navigation] Location: {location}, Sections: {CurrentSkiaShell.Sections.Count}");
// Find the matching section in SkiaShell by route
for (int i = 0; i < CurrentSkiaShell.Sections.Count; i++)
{
var section = CurrentSkiaShell.Sections[i];
Console.WriteLine($"[Navigation] Checking section {i}: Route='{section.Route}', Title='{section.Title}'");
if (!string.IsNullOrEmpty(section.Route) && location.Contains(section.Route, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine($"[Navigation] Match found by route! Navigating to section {i}");
if (i != CurrentSkiaShell.CurrentSectionIndex)
{
CurrentSkiaShell.NavigateToSection(i);
}
return;
}
if (!string.IsNullOrEmpty(section.Title) && location.Contains(section.Title, StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine($"[Navigation] Match found by title! Navigating to section {i}");
if (i != CurrentSkiaShell.CurrentSectionIndex)
{
CurrentSkiaShell.NavigateToSection(i);
}
return;
}
}
Console.WriteLine($"[Navigation] No matching section found for location: {location}");
}
/// <summary>
/// Process a ShellItem (FlyoutItem, TabBar, etc.) into SkiaShell sections.
/// </summary>
private void ProcessShellItem(SkiaShell skiaShell, ShellItem item)
{
if (item is FlyoutItem flyoutItem)
{
// Each FlyoutItem becomes a section
var section = new ShellSection
{
Title = flyoutItem.Title ?? "",
Route = flyoutItem.Route ?? flyoutItem.Title ?? ""
};
// Process the items within the FlyoutItem
foreach (var shellSection in flyoutItem.Items)
{
foreach (var content in shellSection.Items)
{
var shellContent = new ShellContent
{
Title = content.Title ?? shellSection.Title ?? flyoutItem.Title ?? "",
Route = content.Route ?? ""
};
// Create the page content
var pageContent = CreateShellContentPage(content);
if (pageContent != null)
{
shellContent.Content = pageContent;
}
section.Items.Add(shellContent);
}
}
// If there's only one item, use it as the main section content
if (section.Items.Count == 1)
{
section.Title = section.Items[0].Title;
}
skiaShell.AddSection(section);
}
else if (item is TabBar tabBar)
{
// TabBar items get their own sections
foreach (var tab in tabBar.Items)
{
var section = new ShellSection
{
Title = tab.Title ?? "",
Route = tab.Route ?? ""
};
foreach (var content in tab.Items)
{
var shellContent = new ShellContent
{
Title = content.Title ?? tab.Title ?? "",
Route = content.Route ?? ""
};
var pageContent = CreateShellContentPage(content);
if (pageContent != null)
{
shellContent.Content = pageContent;
}
section.Items.Add(shellContent);
}
skiaShell.AddSection(section);
}
}
else
{
// Generic ShellItem
var section = new ShellSection
{
Title = item.Title ?? "",
Route = item.Route ?? ""
};
foreach (var shellSection in item.Items)
{
foreach (var content in shellSection.Items)
{
var shellContent = new ShellContent
{
Title = content.Title ?? "",
Route = content.Route ?? ""
};
var pageContent = CreateShellContentPage(content);
if (pageContent != null)
{
shellContent.Content = pageContent;
}
section.Items.Add(shellContent);
}
}
skiaShell.AddSection(section);
}
}
/// <summary>
/// Creates the page content for a ShellContent.
/// </summary>
private SkiaView? CreateShellContentPage(Controls.ShellContent content)
{
try
{
// Try to create the page from the content template
Page? page = null;
if (content.ContentTemplate != null)
{
page = content.ContentTemplate.CreateContent() as Page;
}
if (page == null && content.Content is Page contentPage)
{
page = contentPage;
}
if (page is ContentPage cp && cp.Content != null)
{
// Wrap in a scroll view if not already scrollable
var contentView = RenderView(cp.Content);
if (contentView != null)
{
if (contentView is SkiaScrollView)
{
return contentView;
}
else
{
var scrollView = new SkiaScrollView
{
Content = contentView
};
return scrollView;
}
}
}
}
catch (Exception)
{
// Silently handle template creation errors
}
return null;
}
/// <summary>
/// Renders a MAUI view and returns the corresponding SkiaView.
/// </summary>
public SkiaView? RenderView(IView view)
{
if (view == null)
return null;
try
{
// Disconnect any existing handler
if (view is Element element && element.Handler != null)
{
element.Handler.DisconnectHandler();
}
// Create handler for the view
// The handler's ConnectHandler and property mappers handle child views automatically
var handler = view.ToHandler(_mauiContext);
if (handler?.PlatformView is not SkiaView skiaView)
{
// If no Skia handler, create a fallback
return CreateFallbackView(view);
}
// Handlers manage their own children via ConnectHandler and property mappers
// No manual child rendering needed here - that caused "View already has a parent" errors
return skiaView;
}
catch (Exception)
{
return CreateFallbackView(view);
}
}
/// <summary>
/// Creates a fallback view for unsupported view types.
/// </summary>
private SkiaView CreateFallbackView(IView view)
{
// For views without handlers, create a placeholder
return new SkiaLabel
{
Text = $"[{view.GetType().Name}]",
TextColor = SKColors.Gray,
FontSize = 12
};
}
}
/// <summary>
/// Extension methods for MAUI handler creation.
/// </summary>
public static class MauiHandlerExtensions
{
/// <summary>
/// Creates a handler for the view and returns it.
/// </summary>
public static IElementHandler ToHandler(this IElement element, IMauiContext mauiContext)
{
var handler = mauiContext.Handlers.GetHandler(element.GetType());
if (handler != null)
{
handler.SetMauiContext(mauiContext);
handler.SetVirtualView(element);
}
return handler!;
}
}

View File

@@ -1,104 +0,0 @@
using System;
using System.Collections.Generic;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform.Linux.Handlers;
namespace Microsoft.Maui.Platform.Linux.Hosting;
public static class MauiHandlerExtensions
{
private static readonly Dictionary<Type, Func<IElementHandler>> LinuxHandlerMap = new Dictionary<Type, Func<IElementHandler>>
{
[typeof(Button)] = () => (IElementHandler)(object)new TextButtonHandler(),
[typeof(Label)] = () => (IElementHandler)(object)new LabelHandler(),
[typeof(Entry)] = () => (IElementHandler)(object)new EntryHandler(),
[typeof(Editor)] = () => (IElementHandler)(object)new EditorHandler(),
[typeof(CheckBox)] = () => (IElementHandler)(object)new CheckBoxHandler(),
[typeof(Switch)] = () => (IElementHandler)(object)new SwitchHandler(),
[typeof(Slider)] = () => (IElementHandler)(object)new SliderHandler(),
[typeof(Stepper)] = () => (IElementHandler)(object)new StepperHandler(),
[typeof(ProgressBar)] = () => (IElementHandler)(object)new ProgressBarHandler(),
[typeof(ActivityIndicator)] = () => (IElementHandler)(object)new ActivityIndicatorHandler(),
[typeof(Picker)] = () => (IElementHandler)(object)new PickerHandler(),
[typeof(DatePicker)] = () => (IElementHandler)(object)new DatePickerHandler(),
[typeof(TimePicker)] = () => (IElementHandler)(object)new TimePickerHandler(),
[typeof(SearchBar)] = () => (IElementHandler)(object)new SearchBarHandler(),
[typeof(RadioButton)] = () => (IElementHandler)(object)new RadioButtonHandler(),
[typeof(WebView)] = () => (IElementHandler)(object)new GtkWebViewHandler(),
[typeof(Image)] = () => (IElementHandler)(object)new ImageHandler(),
[typeof(ImageButton)] = () => (IElementHandler)(object)new ImageButtonHandler(),
[typeof(BoxView)] = () => (IElementHandler)(object)new BoxViewHandler(),
[typeof(Frame)] = () => (IElementHandler)(object)new FrameHandler(),
[typeof(Border)] = () => (IElementHandler)(object)new BorderHandler(),
[typeof(ContentView)] = () => (IElementHandler)(object)new BorderHandler(),
[typeof(ScrollView)] = () => (IElementHandler)(object)new ScrollViewHandler(),
[typeof(Grid)] = () => (IElementHandler)(object)new GridHandler(),
[typeof(StackLayout)] = () => (IElementHandler)(object)new StackLayoutHandler(),
[typeof(VerticalStackLayout)] = () => (IElementHandler)(object)new StackLayoutHandler(),
[typeof(HorizontalStackLayout)] = () => (IElementHandler)(object)new StackLayoutHandler(),
[typeof(AbsoluteLayout)] = () => (IElementHandler)(object)new LayoutHandler(),
[typeof(FlexLayout)] = () => (IElementHandler)(object)new LayoutHandler(),
[typeof(CollectionView)] = () => (IElementHandler)(object)new CollectionViewHandler(),
[typeof(ListView)] = () => (IElementHandler)(object)new CollectionViewHandler(),
[typeof(Page)] = () => (IElementHandler)(object)new PageHandler(),
[typeof(ContentPage)] = () => (IElementHandler)(object)new ContentPageHandler(),
[typeof(NavigationPage)] = () => (IElementHandler)(object)new NavigationPageHandler(),
[typeof(Shell)] = () => (IElementHandler)(object)new ShellHandler(),
[typeof(FlyoutPage)] = () => (IElementHandler)(object)new FlyoutPageHandler(),
[typeof(TabbedPage)] = () => (IElementHandler)(object)new TabbedPageHandler(),
[typeof(Application)] = () => (IElementHandler)(object)new ApplicationHandler(),
[typeof(Window)] = () => (IElementHandler)(object)new WindowHandler(),
[typeof(GraphicsView)] = () => (IElementHandler)(object)new GraphicsViewHandler()
};
public static IElementHandler ToHandler(this IElement element, IMauiContext mauiContext)
{
return CreateHandler(element, mauiContext);
}
public static IViewHandler? ToViewHandler(this IView view, IMauiContext mauiContext)
{
IElementHandler? obj = CreateHandler((IElement)(object)view, mauiContext);
return (IViewHandler?)(object)((obj is IViewHandler) ? obj : null);
}
private static IElementHandler? CreateHandler(IElement element, IMauiContext mauiContext)
{
Type type = ((object)element).GetType();
IElementHandler val = null;
if (LinuxHandlerMap.TryGetValue(type, out Func<IElementHandler> value))
{
val = value();
Console.WriteLine("[ToHandler] Using Linux handler for " + type.Name + ": " + ((object)val).GetType().Name);
}
else
{
Type type2 = null;
Func<IElementHandler> func = null;
foreach (KeyValuePair<Type, Func<IElementHandler>> item in LinuxHandlerMap)
{
if (item.Key.IsAssignableFrom(type) && (type2 == null || type2.IsAssignableFrom(item.Key)))
{
type2 = item.Key;
func = item.Value;
}
}
if (func != null)
{
val = func();
Console.WriteLine($"[ToHandler] Using Linux handler (via base {type2.Name}) for {type.Name}: {((object)val).GetType().Name}");
}
}
if (val == null)
{
val = mauiContext.Handlers.GetHandler(type);
Console.WriteLine("[ToHandler] Using MAUI handler for " + type.Name + ": " + (((object)val)?.GetType().Name ?? "null"));
}
if (val != null)
{
val.SetMauiContext(mauiContext);
val.SetVirtualView(element);
}
return val;
}
}

View File

@@ -1,17 +0,0 @@
using System;
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("parent");
}
}

View File

@@ -1,22 +0,0 @@
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;
}

View File

@@ -1,260 +0,0 @@
using System;
using System.Runtime.InteropServices;
namespace Microsoft.Maui.Platform.Linux.Interop;
public static class WebKitGtk
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void GCallback();
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void LoadChangedCallback(IntPtr webView, int loadEvent, IntPtr userData);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate bool DecidePolicyCallback(IntPtr webView, IntPtr decision, int decisionType, IntPtr userData);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void LoadFailedCallback(IntPtr webView, int loadEvent, IntPtr failingUri, IntPtr error, IntPtr userData);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void NotifyCallback(IntPtr webView, IntPtr paramSpec, IntPtr userData);
private const string WebKit2Lib = "libwebkit2gtk-4.1.so.0";
private const string GtkLib = "libgtk-3.so.0";
private const string GObjectLib = "libgobject-2.0.so.0";
private const string GLibLib = "libglib-2.0.so.0";
public const int WEBKIT_COOKIE_POLICY_ACCEPT_ALWAYS = 0;
public const int WEBKIT_COOKIE_POLICY_ACCEPT_NEVER = 1;
public const int WEBKIT_COOKIE_POLICY_ACCEPT_NO_THIRD_PARTY = 2;
public const int WEBKIT_COOKIE_PERSISTENT_STORAGE_TEXT = 0;
public const int WEBKIT_COOKIE_PERSISTENT_STORAGE_SQLITE = 1;
public const int WEBKIT_LOAD_STARTED = 0;
public const int WEBKIT_LOAD_REDIRECTED = 1;
public const int WEBKIT_LOAD_COMMITTED = 2;
public const int WEBKIT_LOAD_FINISHED = 3;
public const int WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION = 0;
public const int WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION = 1;
public const int WEBKIT_POLICY_DECISION_TYPE_RESPONSE = 2;
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern bool gtk_init_check(ref int argc, ref IntPtr argv);
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void gtk_main();
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void gtk_main_quit();
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern bool gtk_events_pending();
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void gtk_main_iteration();
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern bool gtk_main_iteration_do(bool blocking);
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr gtk_window_new(int type);
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void gtk_window_set_default_size(IntPtr window, int width, int height);
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void gtk_window_set_decorated(IntPtr window, bool decorated);
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void gtk_window_move(IntPtr window, int x, int y);
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void gtk_window_resize(IntPtr window, int width, int height);
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void gtk_widget_show_all(IntPtr widget);
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void gtk_widget_show(IntPtr widget);
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void gtk_widget_hide(IntPtr widget);
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void gtk_widget_destroy(IntPtr widget);
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void gtk_widget_set_size_request(IntPtr widget, int width, int height);
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void gtk_widget_realize(IntPtr widget);
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr gtk_widget_get_window(IntPtr widget);
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void gtk_widget_set_can_focus(IntPtr widget, bool canFocus);
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void gtk_container_add(IntPtr container, IntPtr widget);
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void gtk_container_remove(IntPtr container, IntPtr widget);
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr gtk_plug_new(ulong socketId);
[DllImport("libgtk-3.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern ulong gtk_plug_get_id(IntPtr plug);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr webkit_web_view_new();
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr webkit_web_view_new_with_context(IntPtr context);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void webkit_web_view_load_uri(IntPtr webView, [MarshalAs(UnmanagedType.LPUTF8Str)] string uri);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void webkit_web_view_load_html(IntPtr webView, [MarshalAs(UnmanagedType.LPUTF8Str)] string content, [MarshalAs(UnmanagedType.LPUTF8Str)] string? baseUri);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void webkit_web_view_reload(IntPtr webView);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void webkit_web_view_stop_loading(IntPtr webView);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void webkit_web_view_go_back(IntPtr webView);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void webkit_web_view_go_forward(IntPtr webView);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern bool webkit_web_view_can_go_back(IntPtr webView);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern bool webkit_web_view_can_go_forward(IntPtr webView);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr webkit_web_view_get_uri(IntPtr webView);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr webkit_web_view_get_title(IntPtr webView);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern double webkit_web_view_get_estimated_load_progress(IntPtr webView);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern bool webkit_web_view_is_loading(IntPtr webView);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void webkit_web_view_run_javascript(IntPtr webView, [MarshalAs(UnmanagedType.LPUTF8Str)] string script, IntPtr cancellable, IntPtr callback, IntPtr userData);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr webkit_web_view_run_javascript_finish(IntPtr webView, IntPtr result, out IntPtr error);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr webkit_web_view_get_settings(IntPtr webView);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void webkit_settings_set_enable_javascript(IntPtr settings, bool enabled);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void webkit_settings_set_user_agent(IntPtr settings, [MarshalAs(UnmanagedType.LPUTF8Str)] string userAgent);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr webkit_settings_get_user_agent(IntPtr settings);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void webkit_settings_set_enable_developer_extras(IntPtr settings, bool enabled);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void webkit_settings_set_javascript_can_access_clipboard(IntPtr settings, bool enabled);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void webkit_settings_set_enable_webgl(IntPtr settings, bool enabled);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void webkit_settings_set_allow_file_access_from_file_urls(IntPtr settings, bool enabled);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void webkit_settings_set_allow_universal_access_from_file_urls(IntPtr settings, bool enabled);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr webkit_web_context_get_default();
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr webkit_web_context_new();
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr webkit_web_context_get_cookie_manager(IntPtr context);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void webkit_cookie_manager_set_accept_policy(IntPtr cookieManager, int policy);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void webkit_cookie_manager_set_persistent_storage(IntPtr cookieManager, [MarshalAs(UnmanagedType.LPUTF8Str)] string filename, int storage);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr webkit_navigation_action_get_request(IntPtr action);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern int webkit_navigation_action_get_navigation_type(IntPtr action);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr webkit_uri_request_get_uri(IntPtr request);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void webkit_policy_decision_use(IntPtr decision);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void webkit_policy_decision_ignore(IntPtr decision);
[DllImport("libwebkit2gtk-4.1.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void webkit_policy_decision_download(IntPtr decision);
[DllImport("libgobject-2.0.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern ulong g_signal_connect_data(IntPtr instance, [MarshalAs(UnmanagedType.LPUTF8Str)] string detailedSignal, Delegate handler, IntPtr data, IntPtr destroyData, int connectFlags);
[DllImport("libgobject-2.0.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void g_signal_handler_disconnect(IntPtr instance, ulong handlerId);
[DllImport("libgobject-2.0.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void g_object_unref(IntPtr obj);
[DllImport("libglib-2.0.so.0", CallingConvention = CallingConvention.Cdecl)]
public static extern void g_free(IntPtr mem);
public static string? PtrToStringUtf8(IntPtr ptr)
{
if (ptr == IntPtr.Zero)
{
return null;
}
return Marshal.PtrToStringUTF8(ptr);
}
public static void ProcessGtkEvents()
{
while (gtk_events_pending())
{
gtk_main_iteration_do(blocking: false);
}
}
}

View File

@@ -1,442 +0,0 @@
using System;
using System.CodeDom.Compiler;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.Marshalling;
namespace Microsoft.Maui.Platform.Linux.Interop;
internal static class X11
{
private const string LibX11 = "libX11.so.6";
private const string LibXext = "libXext.so.6";
public const int ZPixmap = 2;
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern IntPtr XOpenDisplay(IntPtr displayName);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XCloseDisplay(IntPtr display);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XDefaultScreen(IntPtr display);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern IntPtr XRootWindow(IntPtr display, int screenNumber);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XDisplayWidth(IntPtr display, int screenNumber);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XDisplayHeight(IntPtr display, int screenNumber);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XDefaultDepth(IntPtr display, int screenNumber);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern IntPtr XDefaultVisual(IntPtr display, int screenNumber);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern IntPtr XDefaultColormap(IntPtr display, int screenNumber);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XFlush(IntPtr display);
[LibraryImport("libX11.so.6")]
[GeneratedCode("Microsoft.Interop.LibraryImportGenerator", "9.0.11.2809")]
[SkipLocalsInit]
public static int XSync(IntPtr display, [MarshalAs(UnmanagedType.Bool)] bool discard)
{
int _discard_native = (discard ? 1 : 0);
return __PInvoke(display, _discard_native);
[DllImport("libX11.so.6", EntryPoint = "XSync", ExactSpelling = true)]
static extern int __PInvoke(IntPtr __display_native, int __discard_native);
}
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern IntPtr XCreateSimpleWindow(IntPtr display, IntPtr parent, int x, int y, uint width, uint height, uint borderWidth, ulong border, ulong background);
[LibraryImport("libX11.so.6")]
[GeneratedCode("Microsoft.Interop.LibraryImportGenerator", "9.0.11.2809")]
[SkipLocalsInit]
public unsafe static 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)
{
IntPtr result;
fixed (XSetWindowAttributes* _attributes_native = &attributes)
{
result = __PInvoke(display, parent, x, y, width, height, borderWidth, depth, windowClass, visual, valueMask, _attributes_native);
}
return result;
[DllImport("libX11.so.6", EntryPoint = "XCreateWindow", ExactSpelling = true)]
static extern unsafe IntPtr __PInvoke(IntPtr __display_native, IntPtr __parent_native, int __x_native, int __y_native, uint __width_native, uint __height_native, uint __borderWidth_native, int __depth_native, uint __windowClass_native, IntPtr __visual_native, ulong __valueMask_native, XSetWindowAttributes* __attributes_native);
}
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XDestroyWindow(IntPtr display, IntPtr window);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XMapWindow(IntPtr display, IntPtr window);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XUnmapWindow(IntPtr display, IntPtr window);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XMoveWindow(IntPtr display, IntPtr window, int x, int y);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XResizeWindow(IntPtr display, IntPtr window, uint width, uint height);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XMoveResizeWindow(IntPtr display, IntPtr window, int x, int y, uint width, uint height);
[LibraryImport("libX11.so.6", StringMarshalling = StringMarshalling.Utf8)]
[GeneratedCode("Microsoft.Interop.LibraryImportGenerator", "9.0.11.2809")]
[SkipLocalsInit]
public unsafe static int XStoreName(IntPtr display, IntPtr window, string windowName)
{
byte* ptr = default(byte*);
int num = 0;
Utf8StringMarshaller.ManagedToUnmanagedIn managedToUnmanagedIn = default(Utf8StringMarshaller.ManagedToUnmanagedIn);
try
{
Span<byte> buffer = stackalloc byte[Utf8StringMarshaller.ManagedToUnmanagedIn.BufferSize];
managedToUnmanagedIn.FromManaged(windowName, buffer);
ptr = managedToUnmanagedIn.ToUnmanaged();
return __PInvoke(display, window, ptr);
}
finally
{
managedToUnmanagedIn.Free();
}
[DllImport("libX11.so.6", EntryPoint = "XStoreName", ExactSpelling = true)]
static extern unsafe int __PInvoke(IntPtr __display_native, IntPtr __window_native, byte* __windowName_native);
}
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XRaiseWindow(IntPtr display, IntPtr window);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XLowerWindow(IntPtr display, IntPtr window);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XSelectInput(IntPtr display, IntPtr window, long eventMask);
[LibraryImport("libX11.so.6")]
[GeneratedCode("Microsoft.Interop.LibraryImportGenerator", "9.0.11.2809")]
[SkipLocalsInit]
public unsafe static int XNextEvent(IntPtr display, out XEvent eventReturn)
{
eventReturn = default(XEvent);
int result;
fixed (XEvent* _eventReturn_native = &eventReturn)
{
result = __PInvoke(display, _eventReturn_native);
}
return result;
[DllImport("libX11.so.6", EntryPoint = "XNextEvent", ExactSpelling = true)]
static extern unsafe int __PInvoke(IntPtr __display_native, XEvent* __eventReturn_native);
}
[LibraryImport("libX11.so.6")]
[GeneratedCode("Microsoft.Interop.LibraryImportGenerator", "9.0.11.2809")]
[SkipLocalsInit]
public unsafe static int XPeekEvent(IntPtr display, out XEvent eventReturn)
{
eventReturn = default(XEvent);
int result;
fixed (XEvent* _eventReturn_native = &eventReturn)
{
result = __PInvoke(display, _eventReturn_native);
}
return result;
[DllImport("libX11.so.6", EntryPoint = "XPeekEvent", ExactSpelling = true)]
static extern unsafe int __PInvoke(IntPtr __display_native, XEvent* __eventReturn_native);
}
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XPending(IntPtr display);
[LibraryImport("libX11.so.6")]
[GeneratedCode("Microsoft.Interop.LibraryImportGenerator", "9.0.11.2809")]
[SkipLocalsInit]
[return: MarshalAs(UnmanagedType.Bool)]
public unsafe static bool XCheckTypedWindowEvent(IntPtr display, IntPtr window, int eventType, out XEvent eventReturn)
{
eventReturn = default(XEvent);
int num;
fixed (XEvent* _eventReturn_native = &eventReturn)
{
num = __PInvoke(display, window, eventType, _eventReturn_native);
}
return num != 0;
[DllImport("libX11.so.6", EntryPoint = "XCheckTypedWindowEvent", ExactSpelling = true)]
static extern unsafe int __PInvoke(IntPtr __display_native, IntPtr __window_native, int __eventType_native, XEvent* __eventReturn_native);
}
[LibraryImport("libX11.so.6")]
[GeneratedCode("Microsoft.Interop.LibraryImportGenerator", "9.0.11.2809")]
[SkipLocalsInit]
public unsafe static int XSendEvent(IntPtr display, IntPtr window, [MarshalAs(UnmanagedType.Bool)] bool propagate, long eventMask, ref XEvent eventSend)
{
int _propagate_native = (propagate ? 1 : 0);
int result;
fixed (XEvent* _eventSend_native = &eventSend)
{
result = __PInvoke(display, window, _propagate_native, eventMask, _eventSend_native);
}
return result;
[DllImport("libX11.so.6", EntryPoint = "XSendEvent", ExactSpelling = true)]
static extern unsafe int __PInvoke(IntPtr __display_native, IntPtr __window_native, int __propagate_native, long __eventMask_native, XEvent* __eventSend_native);
}
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern ulong XKeycodeToKeysym(IntPtr display, int keycode, int index);
[LibraryImport("libX11.so.6")]
[GeneratedCode("Microsoft.Interop.LibraryImportGenerator", "9.0.11.2809")]
[SkipLocalsInit]
public unsafe static int XLookupString(ref XKeyEvent keyEvent, IntPtr bufferReturn, int bytesBuffer, out ulong keysymReturn, IntPtr statusInOut)
{
keysymReturn = 0uL;
int result;
fixed (ulong* _keysymReturn_native = &keysymReturn)
{
fixed (XKeyEvent* _keyEvent_native = &keyEvent)
{
result = __PInvoke(_keyEvent_native, bufferReturn, bytesBuffer, _keysymReturn_native, statusInOut);
}
}
return result;
[DllImport("libX11.so.6", EntryPoint = "XLookupString", ExactSpelling = true)]
static extern unsafe int __PInvoke(XKeyEvent* __keyEvent_native, IntPtr __bufferReturn_native, int __bytesBuffer_native, ulong* __keysymReturn_native, IntPtr __statusInOut_native);
}
[LibraryImport("libX11.so.6")]
[GeneratedCode("Microsoft.Interop.LibraryImportGenerator", "9.0.11.2809")]
[SkipLocalsInit]
public static int XGrabKeyboard(IntPtr display, IntPtr grabWindow, [MarshalAs(UnmanagedType.Bool)] bool ownerEvents, int pointerMode, int keyboardMode, ulong time)
{
int _ownerEvents_native = (ownerEvents ? 1 : 0);
return __PInvoke(display, grabWindow, _ownerEvents_native, pointerMode, keyboardMode, time);
[DllImport("libX11.so.6", EntryPoint = "XGrabKeyboard", ExactSpelling = true)]
static extern int __PInvoke(IntPtr __display_native, IntPtr __grabWindow_native, int __ownerEvents_native, int __pointerMode_native, int __keyboardMode_native, ulong __time_native);
}
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XUngrabKeyboard(IntPtr display, ulong time);
[LibraryImport("libX11.so.6")]
[GeneratedCode("Microsoft.Interop.LibraryImportGenerator", "9.0.11.2809")]
[SkipLocalsInit]
public static int XGrabPointer(IntPtr display, IntPtr grabWindow, [MarshalAs(UnmanagedType.Bool)] bool ownerEvents, uint eventMask, int pointerMode, int keyboardMode, IntPtr confineTo, IntPtr cursor, ulong time)
{
int _ownerEvents_native = (ownerEvents ? 1 : 0);
return __PInvoke(display, grabWindow, _ownerEvents_native, eventMask, pointerMode, keyboardMode, confineTo, cursor, time);
[DllImport("libX11.so.6", EntryPoint = "XGrabPointer", ExactSpelling = true)]
static extern int __PInvoke(IntPtr __display_native, IntPtr __grabWindow_native, int __ownerEvents_native, uint __eventMask_native, int __pointerMode_native, int __keyboardMode_native, IntPtr __confineTo_native, IntPtr __cursor_native, ulong __time_native);
}
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XUngrabPointer(IntPtr display, ulong time);
[LibraryImport("libX11.so.6")]
[GeneratedCode("Microsoft.Interop.LibraryImportGenerator", "9.0.11.2809")]
[SkipLocalsInit]
[return: MarshalAs(UnmanagedType.Bool)]
public unsafe static 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)
{
rootReturn = (IntPtr)0;
childReturn = (IntPtr)0;
rootX = 0;
rootY = 0;
winX = 0;
winY = 0;
maskReturn = 0u;
int num;
fixed (uint* _maskReturn_native = &maskReturn)
{
fixed (int* _winY_native = &winY)
{
fixed (int* _winX_native = &winX)
{
fixed (int* _rootY_native = &rootY)
{
fixed (int* _rootX_native = &rootX)
{
fixed (IntPtr* _childReturn_native = &childReturn)
{
fixed (IntPtr* _rootReturn_native = &rootReturn)
{
num = __PInvoke(display, window, _rootReturn_native, _childReturn_native, _rootX_native, _rootY_native, _winX_native, _winY_native, _maskReturn_native);
}
}
}
}
}
}
}
return num != 0;
[DllImport("libX11.so.6", EntryPoint = "XQueryPointer", ExactSpelling = true)]
static extern unsafe int __PInvoke(IntPtr __display_native, IntPtr __window_native, IntPtr* __rootReturn_native, IntPtr* __childReturn_native, int* __rootX_native, int* __rootY_native, int* __winX_native, int* __winY_native, uint* __maskReturn_native);
}
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XWarpPointer(IntPtr display, IntPtr srcWindow, IntPtr destWindow, int srcX, int srcY, uint srcWidth, uint srcHeight, int destX, int destY);
[LibraryImport("libX11.so.6", StringMarshalling = StringMarshalling.Utf8)]
[GeneratedCode("Microsoft.Interop.LibraryImportGenerator", "9.0.11.2809")]
[SkipLocalsInit]
public unsafe static IntPtr XInternAtom(IntPtr display, string atomName, [MarshalAs(UnmanagedType.Bool)] bool onlyIfExists)
{
byte* ptr = default(byte*);
int num = 0;
nint num2 = 0;
Utf8StringMarshaller.ManagedToUnmanagedIn managedToUnmanagedIn = default(Utf8StringMarshaller.ManagedToUnmanagedIn);
try
{
num = (onlyIfExists ? 1 : 0);
Span<byte> buffer = stackalloc byte[Utf8StringMarshaller.ManagedToUnmanagedIn.BufferSize];
managedToUnmanagedIn.FromManaged(atomName, buffer);
ptr = managedToUnmanagedIn.ToUnmanaged();
return __PInvoke(display, ptr, num);
}
finally
{
managedToUnmanagedIn.Free();
}
[DllImport("libX11.so.6", EntryPoint = "XInternAtom", ExactSpelling = true)]
static extern unsafe IntPtr __PInvoke(IntPtr __display_native, byte* __atomName_native, int __onlyIfExists_native);
}
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XChangeProperty(IntPtr display, IntPtr window, IntPtr property, IntPtr type, int format, int mode, IntPtr data, int nelements);
[LibraryImport("libX11.so.6")]
[GeneratedCode("Microsoft.Interop.LibraryImportGenerator", "9.0.11.2809")]
[SkipLocalsInit]
public unsafe static 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)
{
actualTypeReturn = (IntPtr)0;
actualFormatReturn = 0;
nitemsReturn = (IntPtr)0;
bytesAfterReturn = (IntPtr)0;
propReturn = (IntPtr)0;
int _delete_native = (delete ? 1 : 0);
int result;
fixed (IntPtr* _propReturn_native = &propReturn)
{
fixed (IntPtr* _bytesAfterReturn_native = &bytesAfterReturn)
{
fixed (IntPtr* _nitemsReturn_native = &nitemsReturn)
{
fixed (int* _actualFormatReturn_native = &actualFormatReturn)
{
fixed (IntPtr* _actualTypeReturn_native = &actualTypeReturn)
{
result = __PInvoke(display, window, property, longOffset, longLength, _delete_native, reqType, _actualTypeReturn_native, _actualFormatReturn_native, _nitemsReturn_native, _bytesAfterReturn_native, _propReturn_native);
}
}
}
}
}
return result;
[DllImport("libX11.so.6", EntryPoint = "XGetWindowProperty", ExactSpelling = true)]
static extern unsafe int __PInvoke(IntPtr __display_native, IntPtr __window_native, IntPtr __property_native, long __longOffset_native, long __longLength_native, int __delete_native, IntPtr __reqType_native, IntPtr* __actualTypeReturn_native, int* __actualFormatReturn_native, IntPtr* __nitemsReturn_native, IntPtr* __bytesAfterReturn_native, IntPtr* __propReturn_native);
}
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XDeleteProperty(IntPtr display, IntPtr window, IntPtr property);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XSetSelectionOwner(IntPtr display, IntPtr selection, IntPtr owner, ulong time);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern IntPtr XGetSelectionOwner(IntPtr display, IntPtr selection);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XConvertSelection(IntPtr display, IntPtr selection, IntPtr target, IntPtr property, IntPtr requestor, ulong time);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XFree(IntPtr data);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern IntPtr XCreateGC(IntPtr display, IntPtr drawable, ulong valueMask, IntPtr values);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XFreeGC(IntPtr display, IntPtr gc);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XCopyArea(IntPtr display, IntPtr src, IntPtr dest, IntPtr gc, int srcX, int srcY, uint width, uint height, int destX, int destY);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern IntPtr XCreateFontCursor(IntPtr display, uint shape);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XFreeCursor(IntPtr display, IntPtr cursor);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XDefineCursor(IntPtr display, IntPtr window, IntPtr cursor);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XUndefineCursor(IntPtr display, IntPtr window);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XConnectionNumber(IntPtr display);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern IntPtr XCreateImage(IntPtr display, IntPtr visual, uint depth, int format, int offset, IntPtr data, uint width, uint height, int bitmapPad, int bytesPerLine);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XPutImage(IntPtr display, IntPtr drawable, IntPtr gc, IntPtr image, int srcX, int srcY, int destX, int destY, uint width, uint height);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern int XDestroyImage(IntPtr image);
[DllImport("libX11.so.6", ExactSpelling = true)]
[LibraryImport("libX11.so.6")]
public static extern IntPtr XDefaultGC(IntPtr display, int screen);
}

View File

@@ -1,36 +0,0 @@
using System;
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;
}

View File

@@ -1,22 +0,0 @@
using System;
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;
}

View File

@@ -1,32 +0,0 @@
using System;
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;
}

View File

@@ -1,40 +0,0 @@
using System;
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;
}

View File

@@ -1,14 +0,0 @@
namespace Microsoft.Maui.Platform.Linux.Interop;
public static class XCursorShape
{
public const uint XC_left_ptr = 68u;
public const uint XC_hand2 = 60u;
public const uint XC_xterm = 152u;
public const uint XC_watch = 150u;
public const uint XC_crosshair = 34u;
}

View File

@@ -1,34 +0,0 @@
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;
}

View File

@@ -1,24 +0,0 @@
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;
}

View File

@@ -1,28 +0,0 @@
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;
}

View File

@@ -1,26 +0,0 @@
using System;
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;
}

View File

@@ -1,20 +0,0 @@
using System;
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;
}

View File

@@ -1,36 +0,0 @@
using System;
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;
}

View File

@@ -1,36 +0,0 @@
using System;
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;
}

View File

@@ -1,36 +0,0 @@
using System;
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;
}

View File

@@ -1,8 +0,0 @@
namespace Microsoft.Maui.Platform.Linux.Interop;
public static class XWindowClass
{
public const uint InputOutput = 1u;
public const uint InputOnly = 2u;
}

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,20 +0,0 @@
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; }
}

View File

@@ -46,6 +46,9 @@
<!-- HarfBuzz for advanced text shaping -->
<PackageReference Include="HarfBuzzSharp" Version="7.3.0.3" />
<PackageReference Include="HarfBuzzSharp.NativeAssets.Linux" Version="7.3.0.3" />
<!-- SVG support for icon loading -->
<PackageReference Include="Svg.Skia" Version="2.0.0.4" />
</ItemGroup>
<!-- Include README and icon in package -->

View File

@@ -1,254 +1,232 @@
using System;
using System.Collections.Generic;
using System.Linq;
// 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;
/// <summary>
/// Manages dirty rectangles for optimized rendering.
/// Only redraws areas that have been invalidated.
/// </summary>
public class DirtyRectManager
{
private readonly List<SKRect> _dirtyRects = new List<SKRect>();
private readonly List<SKRect> _dirtyRects = new();
private readonly object _lock = new();
private bool _fullRedrawNeeded = true;
private SKRect _bounds;
private int _maxDirtyRects = 10;
private readonly object _lock = new object();
/// <summary>
/// Gets or sets the maximum number of dirty rectangles to track before
/// falling back to a full redraw.
/// </summary>
public int MaxDirtyRects
{
get => _maxDirtyRects;
set => _maxDirtyRects = Math.Max(1, value);
}
private bool _fullRedrawNeeded = true;
/// <summary>
/// Gets whether a full redraw is needed.
/// </summary>
public bool NeedsFullRedraw => _fullRedrawNeeded;
private SKRect _bounds;
/// <summary>
/// Gets the current dirty rectangles.
/// </summary>
public IReadOnlyList<SKRect> DirtyRects
{
get
{
lock (_lock)
{
return _dirtyRects.ToList();
}
}
}
private int _maxDirtyRects = 10;
/// <summary>
/// Gets whether there are any dirty regions.
/// </summary>
public bool HasDirtyRegions
{
get
{
lock (_lock)
{
return _fullRedrawNeeded || _dirtyRects.Count > 0;
}
}
}
public int MaxDirtyRects
{
get
{
return _maxDirtyRects;
}
set
{
_maxDirtyRects = Math.Max(1, value);
}
}
/// <summary>
/// Sets the rendering bounds.
/// </summary>
public void SetBounds(SKRect bounds)
{
if (_bounds != bounds)
{
_bounds = bounds;
InvalidateAll();
}
}
public bool NeedsFullRedraw => _fullRedrawNeeded;
/// <summary>
/// Invalidates a specific region.
/// </summary>
public void Invalidate(SKRect rect)
{
if (rect.IsEmpty) return;
public IReadOnlyList<SKRect> DirtyRects
{
get
{
lock (_lock)
{
return _dirtyRects.ToList();
}
}
}
lock (_lock)
{
if (_fullRedrawNeeded) return;
public bool HasDirtyRegions
{
get
{
lock (_lock)
{
return _fullRedrawNeeded || _dirtyRects.Count > 0;
}
}
}
// Clamp to bounds
rect = SKRect.Intersect(rect, _bounds);
if (rect.IsEmpty) return;
public void SetBounds(SKRect bounds)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
if (_bounds != bounds)
{
_bounds = bounds;
InvalidateAll();
}
}
// Try to merge with existing dirty rects
for (int i = 0; i < _dirtyRects.Count; i++)
{
if (_dirtyRects[i].Contains(rect))
{
// Already covered
return;
}
public void Invalidate(SKRect rect)
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_014f: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
//IL_00df: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_011c: Unknown result type (might be due to invalid IL or missing references)
//IL_0121: Unknown result type (might be due to invalid IL or missing references)
//IL_0122: Unknown result type (might be due to invalid IL or missing references)
if (((SKRect)(ref rect)).IsEmpty)
{
return;
}
lock (_lock)
{
if (_fullRedrawNeeded)
{
return;
}
rect = SKRect.Intersect(rect, _bounds);
if (((SKRect)(ref rect)).IsEmpty)
{
return;
}
for (int i = 0; i < _dirtyRects.Count; i++)
{
SKRect val = _dirtyRects[i];
if (((SKRect)(ref val)).Contains(rect))
{
return;
}
if (((SKRect)(ref rect)).Contains(_dirtyRects[i]))
{
_dirtyRects[i] = rect;
MergeDirtyRects();
return;
}
SKRect val2 = SKRect.Intersect(_dirtyRects[i], rect);
if (!((SKRect)(ref val2)).IsEmpty)
{
float num = ((SKRect)(ref val2)).Width * ((SKRect)(ref val2)).Height;
val = _dirtyRects[i];
float width = ((SKRect)(ref val)).Width;
val = _dirtyRects[i];
float num2 = Math.Min(width * ((SKRect)(ref val)).Height, ((SKRect)(ref rect)).Width * ((SKRect)(ref rect)).Height);
if (num > num2 * 0.5f)
{
_dirtyRects[i] = SKRect.Union(_dirtyRects[i], rect);
MergeDirtyRects();
return;
}
}
}
_dirtyRects.Add(rect);
if (_dirtyRects.Count > _maxDirtyRects)
{
_fullRedrawNeeded = true;
_dirtyRects.Clear();
}
}
}
if (rect.Contains(_dirtyRects[i]))
{
// New rect covers existing
_dirtyRects[i] = rect;
MergeDirtyRects();
return;
}
public void InvalidateAll()
{
lock (_lock)
{
_fullRedrawNeeded = true;
_dirtyRects.Clear();
}
}
// Check if they overlap significantly (50% overlap)
var intersection = SKRect.Intersect(_dirtyRects[i], rect);
if (!intersection.IsEmpty)
{
float intersectArea = intersection.Width * intersection.Height;
float smallerArea = Math.Min(
_dirtyRects[i].Width * _dirtyRects[i].Height,
rect.Width * rect.Height);
public void Clear()
{
lock (_lock)
{
_fullRedrawNeeded = false;
_dirtyRects.Clear();
}
}
if (intersectArea > smallerArea * 0.5f)
{
// Merge the rectangles
_dirtyRects[i] = SKRect.Union(_dirtyRects[i], rect);
MergeDirtyRects();
return;
}
}
}
public SKRect GetCombinedDirtyRect()
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
lock (_lock)
{
if (_fullRedrawNeeded || _dirtyRects.Count == 0)
{
return _bounds;
}
SKRect val = _dirtyRects[0];
for (int i = 1; i < _dirtyRects.Count; i++)
{
val = SKRect.Union(val, _dirtyRects[i]);
}
return val;
}
}
// Add as new dirty rect
_dirtyRects.Add(rect);
public void ApplyClipping(SKCanvas canvas)
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Expected O, but got Unknown
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
lock (_lock)
{
if (_fullRedrawNeeded || _dirtyRects.Count == 0)
{
return;
}
SKPath val = new SKPath();
try
{
foreach (SKRect dirtyRect in _dirtyRects)
{
val.AddRect(dirtyRect, (SKPathDirection)0);
}
canvas.ClipPath(val, (SKClipOperation)1, false);
}
finally
{
((IDisposable)val)?.Dispose();
}
}
}
// Check if we have too many dirty rects
if (_dirtyRects.Count > _maxDirtyRects)
{
// Fall back to full redraw
_fullRedrawNeeded = true;
_dirtyRects.Clear();
}
}
}
private void MergeDirtyRects()
{
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
bool flag;
do
{
flag = false;
for (int i = 0; i < _dirtyRects.Count - 1; i++)
{
for (int j = i + 1; j < _dirtyRects.Count; j++)
{
SKRect val = SKRect.Intersect(_dirtyRects[i], _dirtyRects[j]);
if (!((SKRect)(ref val)).IsEmpty)
{
_dirtyRects[i] = SKRect.Union(_dirtyRects[i], _dirtyRects[j]);
_dirtyRects.RemoveAt(j);
flag = true;
break;
}
}
if (flag)
{
break;
}
}
}
while (flag);
}
/// <summary>
/// Invalidates the entire rendering area.
/// </summary>
public void InvalidateAll()
{
lock (_lock)
{
_fullRedrawNeeded = true;
_dirtyRects.Clear();
}
}
/// <summary>
/// Clears all dirty regions after rendering.
/// </summary>
public void Clear()
{
lock (_lock)
{
_fullRedrawNeeded = false;
_dirtyRects.Clear();
}
}
/// <summary>
/// Gets the combined dirty region as a single rectangle.
/// </summary>
public SKRect GetCombinedDirtyRect()
{
lock (_lock)
{
if (_fullRedrawNeeded || _dirtyRects.Count == 0)
{
return _bounds;
}
var combined = _dirtyRects[0];
for (int i = 1; i < _dirtyRects.Count; i++)
{
combined = SKRect.Union(combined, _dirtyRects[i]);
}
return combined;
}
}
/// <summary>
/// Applies dirty region clipping to a canvas.
/// </summary>
public void ApplyClipping(SKCanvas canvas)
{
lock (_lock)
{
if (_fullRedrawNeeded || _dirtyRects.Count == 0)
{
// No clipping needed for full redraw
return;
}
// Create a path from all dirty rects
using var path = new SKPath();
foreach (var rect in _dirtyRects)
{
path.AddRect(rect);
}
canvas.ClipPath(path);
}
}
private void MergeDirtyRects()
{
// Simple merge pass - could be optimized
bool merged;
do
{
merged = false;
for (int i = 0; i < _dirtyRects.Count - 1; i++)
{
for (int j = i + 1; j < _dirtyRects.Count; j++)
{
var intersection = SKRect.Intersect(_dirtyRects[i], _dirtyRects[j]);
if (!intersection.IsEmpty)
{
_dirtyRects[i] = SKRect.Union(_dirtyRects[i], _dirtyRects[j]);
_dirtyRects.RemoveAt(j);
merged = true;
break;
}
}
if (merged) break;
}
} while (merged);
}
}

View File

@@ -1,376 +0,0 @@
using System;
using System.Collections.Generic;
using Microsoft.Maui.Platform.Linux.Window;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Rendering;
public class GpuRenderingEngine : IDisposable
{
private readonly X11Window _window;
private GRContext? _grContext;
private GRBackendRenderTarget? _renderTarget;
private SKSurface? _surface;
private SKCanvas? _canvas;
private bool _disposed;
private bool _gpuAvailable;
private int _width;
private int _height;
private SKBitmap? _softwareBitmap;
private SKCanvas? _softwareCanvas;
private readonly List<SKRect> _dirtyRegions = new List<SKRect>();
private readonly object _dirtyLock = new object();
private bool _fullRedrawNeeded = true;
private const int MaxDirtyRegions = 32;
public bool IsGpuAccelerated
{
get
{
if (_gpuAvailable)
{
return _grContext != null;
}
return false;
}
}
public string BackendName
{
get
{
if (!IsGpuAccelerated)
{
return "Software";
}
return "OpenGL";
}
}
public int Width => _width;
public int Height => _height;
public GpuRenderingEngine(X11Window window)
{
_window = window;
_width = window.Width;
_height = window.Height;
_gpuAvailable = TryInitializeGpu();
if (!_gpuAvailable)
{
Console.WriteLine("[GpuRenderingEngine] GPU not available, using software rendering");
InitializeSoftwareRendering();
}
_window.Resized += OnWindowResized;
_window.Exposed += OnWindowExposed;
}
private bool TryInitializeGpu()
{
try
{
GRGlInterface val = GRGlInterface.Create();
if (val == null)
{
Console.WriteLine("[GpuRenderingEngine] Failed to create GL interface");
return false;
}
_grContext = GRContext.CreateGl(val);
if (_grContext == null)
{
Console.WriteLine("[GpuRenderingEngine] Failed to create GR context");
((SKNativeObject)val).Dispose();
return false;
}
CreateGpuSurface();
Console.WriteLine("[GpuRenderingEngine] GPU acceleration enabled");
return true;
}
catch (Exception ex)
{
Console.WriteLine("[GpuRenderingEngine] GPU initialization failed: " + ex.Message);
return false;
}
}
private void CreateGpuSurface()
{
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Expected O, but got Unknown
if (_grContext != null)
{
GRBackendRenderTarget? renderTarget = _renderTarget;
if (renderTarget != null)
{
((SKNativeObject)renderTarget).Dispose();
}
SKSurface? surface = _surface;
if (surface != null)
{
((SKNativeObject)surface).Dispose();
}
int num = Math.Max(1, _width);
int num2 = Math.Max(1, _height);
GRGlFramebufferInfo val = default(GRGlFramebufferInfo);
((GRGlFramebufferInfo)(ref val))._002Ector(0u, SkiaExtensions.ToGlSizedFormat((SKColorType)4));
_renderTarget = new GRBackendRenderTarget(num, num2, 0, 8, val);
_surface = SKSurface.Create(_grContext, _renderTarget, (GRSurfaceOrigin)1, (SKColorType)4);
if (_surface == null)
{
Console.WriteLine("[GpuRenderingEngine] Failed to create GPU surface, falling back to software");
_gpuAvailable = false;
InitializeSoftwareRendering();
}
else
{
_canvas = _surface.Canvas;
}
}
}
private void InitializeSoftwareRendering()
{
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Expected O, but got Unknown
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Expected O, but got Unknown
int num = Math.Max(1, _width);
int num2 = Math.Max(1, _height);
SKBitmap? softwareBitmap = _softwareBitmap;
if (softwareBitmap != null)
{
((SKNativeObject)softwareBitmap).Dispose();
}
SKCanvas? softwareCanvas = _softwareCanvas;
if (softwareCanvas != null)
{
((SKNativeObject)softwareCanvas).Dispose();
}
SKImageInfo val = default(SKImageInfo);
((SKImageInfo)(ref val))._002Ector(num, num2, (SKColorType)6, (SKAlphaType)2);
_softwareBitmap = new SKBitmap(val);
_softwareCanvas = new SKCanvas(_softwareBitmap);
_canvas = _softwareCanvas;
}
private void OnWindowResized(object? sender, (int Width, int Height) size)
{
(_width, _height) = size;
if (_gpuAvailable && _grContext != null)
{
CreateGpuSurface();
}
else
{
InitializeSoftwareRendering();
}
_fullRedrawNeeded = true;
}
private void OnWindowExposed(object? sender, EventArgs e)
{
_fullRedrawNeeded = true;
}
public void InvalidateRegion(SKRect region)
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
if (((SKRect)(ref region)).IsEmpty || ((SKRect)(ref region)).Width <= 0f || ((SKRect)(ref region)).Height <= 0f)
{
return;
}
region = SKRect.Intersect(region, new SKRect(0f, 0f, (float)Width, (float)Height));
if (((SKRect)(ref region)).IsEmpty)
{
return;
}
lock (_dirtyLock)
{
if (_dirtyRegions.Count >= 32)
{
_fullRedrawNeeded = true;
_dirtyRegions.Clear();
}
else
{
_dirtyRegions.Add(region);
}
}
}
public void InvalidateAll()
{
_fullRedrawNeeded = true;
}
public void Render(SkiaView rootView)
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
//IL_0110: Unknown result type (might be due to invalid IL or missing references)
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
//IL_017a: Unknown result type (might be due to invalid IL or missing references)
if (_canvas == null)
{
return;
}
SKSize availableSize = default(SKSize);
((SKSize)(ref availableSize))._002Ector((float)Width, (float)Height);
rootView.Measure(availableSize);
rootView.Arrange(new SKRect(0f, 0f, (float)Width, (float)Height));
bool flag;
List<SKRect> list;
lock (_dirtyLock)
{
flag = _fullRedrawNeeded || _dirtyRegions.Count == 0;
if (flag)
{
list = new List<SKRect>
{
new SKRect(0f, 0f, (float)Width, (float)Height)
};
_dirtyRegions.Clear();
_fullRedrawNeeded = false;
}
else
{
list = new List<SKRect>(_dirtyRegions);
_dirtyRegions.Clear();
}
}
foreach (SKRect item in list)
{
_canvas.Save();
if (!flag)
{
_canvas.ClipRect(item, (SKClipOperation)1, false);
}
_canvas.Clear(SKColors.White);
rootView.Draw(_canvas);
_canvas.Restore();
}
SkiaView.DrawPopupOverlays(_canvas);
if (LinuxDialogService.HasActiveDialog)
{
LinuxDialogService.DrawDialogs(_canvas, new SKRect(0f, 0f, (float)Width, (float)Height));
}
_canvas.Flush();
if (_gpuAvailable && _grContext != null)
{
_grContext.Submit(false);
}
else if (_softwareBitmap != null)
{
IntPtr pixels = _softwareBitmap.GetPixels();
if (pixels != IntPtr.Zero)
{
_window.DrawPixels(pixels, Width, Height, _softwareBitmap.RowBytes);
}
}
}
public GpuStats GetStats()
{
if (_grContext == null)
{
return new GpuStats
{
IsGpuAccelerated = false
};
}
int num = default(int);
long resourceCacheLimitBytes = default(long);
_grContext.GetResourceCacheLimits(ref num, ref resourceCacheLimitBytes);
return new GpuStats
{
IsGpuAccelerated = true,
MaxTextureSize = 4096,
ResourceCacheUsedBytes = 0L,
ResourceCacheLimitBytes = resourceCacheLimitBytes
};
}
public void PurgeResources()
{
GRContext? grContext = _grContext;
if (grContext != null)
{
grContext.PurgeResources();
}
}
public SKCanvas? GetCanvas()
{
return _canvas;
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
{
return;
}
if (disposing)
{
_window.Resized -= OnWindowResized;
_window.Exposed -= OnWindowExposed;
SKSurface? surface = _surface;
if (surface != null)
{
((SKNativeObject)surface).Dispose();
}
GRBackendRenderTarget? renderTarget = _renderTarget;
if (renderTarget != null)
{
((SKNativeObject)renderTarget).Dispose();
}
GRContext? grContext = _grContext;
if (grContext != null)
{
((SKNativeObject)grContext).Dispose();
}
SKBitmap? softwareBitmap = _softwareBitmap;
if (softwareBitmap != null)
{
((SKNativeObject)softwareBitmap).Dispose();
}
SKCanvas? softwareCanvas = _softwareCanvas;
if (softwareCanvas != null)
{
((SKNativeObject)softwareCanvas).Dispose();
}
}
_disposed = true;
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}

View File

@@ -1,16 +0,0 @@
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 => (double)ResourceCacheUsedBytes / 1048576.0;
public double ResourceCacheLimitMB => (double)ResourceCacheLimitBytes / 1048576.0;
}

View File

@@ -1,455 +0,0 @@
using System;
using System.Runtime.InteropServices;
using Microsoft.Maui.Platform.Linux.Native;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Rendering;
public sealed class GtkSkiaSurfaceWidget : IDisposable
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate bool DrawCallback(IntPtr widget, IntPtr cairoContext, IntPtr userData);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate bool ConfigureCallback(IntPtr widget, IntPtr eventData, IntPtr userData);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate bool ButtonEventCallback(IntPtr widget, IntPtr eventData, IntPtr userData);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate bool MotionEventCallback(IntPtr widget, IntPtr eventData, IntPtr userData);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate bool KeyEventCallback(IntPtr widget, IntPtr eventData, IntPtr userData);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate bool ScrollEventCallback(IntPtr widget, IntPtr eventData, IntPtr userData);
private struct GdkEventButton
{
public int type;
public IntPtr window;
public sbyte send_event;
public uint time;
public double x;
public double y;
public IntPtr axes;
public uint state;
public uint button;
}
private struct GdkEventMotion
{
public int type;
public IntPtr window;
public sbyte send_event;
public uint time;
public double x;
public double y;
}
private struct GdkEventKey
{
public int type;
public IntPtr window;
public sbyte send_event;
public uint time;
public uint state;
public uint keyval;
public int length;
public IntPtr str;
public ushort hardware_keycode;
}
private struct GdkEventScroll
{
public int type;
public IntPtr window;
public sbyte send_event;
public uint time;
public double x;
public double y;
public uint state;
public int direction;
public IntPtr device;
public double x_root;
public double y_root;
public double delta_x;
public double delta_y;
}
private IntPtr _widget;
private SKImageInfo _imageInfo;
private SKBitmap? _bitmap;
private SKCanvas? _canvas;
private IntPtr _cairoSurface;
private readonly DrawCallback _drawCallback;
private readonly ConfigureCallback _configureCallback;
private ulong _drawSignalId;
private ulong _configureSignalId;
private bool _isTransparent;
private readonly ButtonEventCallback _buttonPressCallback;
private readonly ButtonEventCallback _buttonReleaseCallback;
private readonly MotionEventCallback _motionCallback;
private readonly KeyEventCallback _keyPressCallback;
private readonly KeyEventCallback _keyReleaseCallback;
private readonly ScrollEventCallback _scrollCallback;
public IntPtr Widget => _widget;
public SKCanvas? Canvas => _canvas;
public SKImageInfo ImageInfo => _imageInfo;
public int Width => ((SKImageInfo)(ref _imageInfo)).Width;
public int Height => ((SKImageInfo)(ref _imageInfo)).Height;
public bool IsTransparent => _isTransparent;
public event EventHandler? DrawRequested;
public event EventHandler<(int Width, int Height)>? Resized;
public event EventHandler<(double X, double Y, int Button)>? PointerPressed;
public event EventHandler<(double X, double Y, int Button)>? PointerReleased;
public event EventHandler<(double X, double Y)>? PointerMoved;
public event EventHandler<(uint KeyVal, uint KeyCode, uint State)>? KeyPressed;
public event EventHandler<(uint KeyVal, uint KeyCode, uint State)>? KeyReleased;
public event EventHandler<(double X, double Y, double DeltaX, double DeltaY)>? Scrolled;
public event EventHandler<string>? TextInput;
public GtkSkiaSurfaceWidget(int width, int height)
{
_widget = GtkNative.gtk_drawing_area_new();
if (_widget == IntPtr.Zero)
{
throw new InvalidOperationException("Failed to create GTK drawing area");
}
GtkNative.gtk_widget_set_size_request(_widget, width, height);
GtkNative.gtk_widget_add_events(_widget, 10551046);
GtkNative.gtk_widget_set_can_focus(_widget, canFocus: true);
CreateBuffer(width, height);
_drawCallback = OnDraw;
_configureCallback = OnConfigure;
_buttonPressCallback = OnButtonPress;
_buttonReleaseCallback = OnButtonRelease;
_motionCallback = OnMotion;
_keyPressCallback = OnKeyPress;
_keyReleaseCallback = OnKeyRelease;
_scrollCallback = OnScroll;
_drawSignalId = GtkNative.g_signal_connect_data(_widget, "draw", Marshal.GetFunctionPointerForDelegate(_drawCallback), IntPtr.Zero, IntPtr.Zero, 0);
_configureSignalId = GtkNative.g_signal_connect_data(_widget, "configure-event", Marshal.GetFunctionPointerForDelegate(_configureCallback), IntPtr.Zero, IntPtr.Zero, 0);
GtkNative.g_signal_connect_data(_widget, "button-press-event", Marshal.GetFunctionPointerForDelegate(_buttonPressCallback), IntPtr.Zero, IntPtr.Zero, 0);
GtkNative.g_signal_connect_data(_widget, "button-release-event", Marshal.GetFunctionPointerForDelegate(_buttonReleaseCallback), IntPtr.Zero, IntPtr.Zero, 0);
GtkNative.g_signal_connect_data(_widget, "motion-notify-event", Marshal.GetFunctionPointerForDelegate(_motionCallback), IntPtr.Zero, IntPtr.Zero, 0);
GtkNative.g_signal_connect_data(_widget, "key-press-event", Marshal.GetFunctionPointerForDelegate(_keyPressCallback), IntPtr.Zero, IntPtr.Zero, 0);
GtkNative.g_signal_connect_data(_widget, "key-release-event", Marshal.GetFunctionPointerForDelegate(_keyReleaseCallback), IntPtr.Zero, IntPtr.Zero, 0);
GtkNative.g_signal_connect_data(_widget, "scroll-event", Marshal.GetFunctionPointerForDelegate(_scrollCallback), IntPtr.Zero, IntPtr.Zero, 0);
Console.WriteLine($"[GtkSkiaSurfaceWidget] Created with size {width}x{height}");
}
private void CreateBuffer(int width, int height)
{
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0077: Expected O, but got Unknown
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Expected O, but got Unknown
width = Math.Max(1, width);
height = Math.Max(1, height);
SKCanvas? canvas = _canvas;
if (canvas != null)
{
((SKNativeObject)canvas).Dispose();
}
SKBitmap? bitmap = _bitmap;
if (bitmap != null)
{
((SKNativeObject)bitmap).Dispose();
}
if (_cairoSurface != IntPtr.Zero)
{
CairoNative.cairo_surface_destroy(_cairoSurface);
_cairoSurface = IntPtr.Zero;
}
_imageInfo = new SKImageInfo(width, height, (SKColorType)6, (SKAlphaType)2);
_bitmap = new SKBitmap(_imageInfo);
_canvas = new SKCanvas(_bitmap);
IntPtr pixels = _bitmap.GetPixels();
_cairoSurface = CairoNative.cairo_image_surface_create_for_data(pixels, CairoNative.cairo_format_t.CAIRO_FORMAT_ARGB32, ((SKImageInfo)(ref _imageInfo)).Width, ((SKImageInfo)(ref _imageInfo)).Height, ((SKImageInfo)(ref _imageInfo)).RowBytes);
Console.WriteLine($"[GtkSkiaSurfaceWidget] Created buffer {width}x{height}, stride={((SKImageInfo)(ref _imageInfo)).RowBytes}");
}
public void Resize(int width, int height)
{
if (width != ((SKImageInfo)(ref _imageInfo)).Width || height != ((SKImageInfo)(ref _imageInfo)).Height)
{
CreateBuffer(width, height);
this.Resized?.Invoke(this, (width, height));
}
}
public void RenderFrame(Action<SKCanvas, SKImageInfo> render)
{
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
if (_canvas != null && _bitmap != null)
{
render(_canvas, _imageInfo);
_canvas.Flush();
CairoNative.cairo_surface_flush(_cairoSurface);
CairoNative.cairo_surface_mark_dirty(_cairoSurface);
GtkNative.gtk_widget_queue_draw(_widget);
}
}
public void Invalidate()
{
GtkNative.gtk_widget_queue_draw(_widget);
}
public void SetTransparent(bool transparent)
{
_isTransparent = transparent;
}
private bool OnDraw(IntPtr widget, IntPtr cairoContext, IntPtr userData)
{
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
if (_cairoSurface == IntPtr.Zero || cairoContext == IntPtr.Zero)
{
return false;
}
if (_isTransparent)
{
SKCanvas? canvas = _canvas;
if (canvas != null)
{
canvas.Clear(SKColors.Transparent);
}
}
this.DrawRequested?.Invoke(this, EventArgs.Empty);
SKCanvas? canvas2 = _canvas;
if (canvas2 != null)
{
canvas2.Flush();
}
CairoNative.cairo_surface_flush(_cairoSurface);
CairoNative.cairo_surface_mark_dirty(_cairoSurface);
CairoNative.cairo_set_source_surface(cairoContext, _cairoSurface, 0.0, 0.0);
CairoNative.cairo_paint(cairoContext);
return true;
}
private bool OnConfigure(IntPtr widget, IntPtr eventData, IntPtr userData)
{
GtkNative.gtk_widget_get_allocation(widget, out var allocation);
if (allocation.Width > 0 && allocation.Height > 0 && (allocation.Width != ((SKImageInfo)(ref _imageInfo)).Width || allocation.Height != ((SKImageInfo)(ref _imageInfo)).Height))
{
Resize(allocation.Width, allocation.Height);
}
return false;
}
private bool OnButtonPress(IntPtr widget, IntPtr eventData, IntPtr userData)
{
GtkNative.gtk_widget_grab_focus(_widget);
var (num, num2, num3) = ParseButtonEvent(eventData);
Console.WriteLine($"[GtkSkiaSurfaceWidget] ButtonPress at ({num}, {num2}), button={num3}");
this.PointerPressed?.Invoke(this, (num, num2, num3));
return true;
}
private bool OnButtonRelease(IntPtr widget, IntPtr eventData, IntPtr userData)
{
var (item, item2, item3) = ParseButtonEvent(eventData);
this.PointerReleased?.Invoke(this, (item, item2, item3));
return true;
}
private bool OnMotion(IntPtr widget, IntPtr eventData, IntPtr userData)
{
var (item, item2) = ParseMotionEvent(eventData);
this.PointerMoved?.Invoke(this, (item, item2));
return true;
}
public void RaisePointerPressed(double x, double y, int button)
{
Console.WriteLine($"[GtkSkiaSurfaceWidget] RaisePointerPressed at ({x}, {y}), button={button}");
this.PointerPressed?.Invoke(this, (x, y, button));
}
public void RaisePointerReleased(double x, double y, int button)
{
this.PointerReleased?.Invoke(this, (x, y, button));
}
public void RaisePointerMoved(double x, double y)
{
this.PointerMoved?.Invoke(this, (x, y));
}
private bool OnKeyPress(IntPtr widget, IntPtr eventData, IntPtr userData)
{
var (num, item, item2) = ParseKeyEvent(eventData);
this.KeyPressed?.Invoke(this, (num, item, item2));
uint num2 = GdkNative.gdk_keyval_to_unicode(num);
if (num2 != 0 && num2 < 65536)
{
char c = (char)num2;
if (!char.IsControl(c) || c == '\r' || c == '\n' || c == '\t')
{
string text = c.ToString();
Console.WriteLine($"[GtkSkiaSurfaceWidget] TextInput: '{text}' (keyval={num}, unicode={num2})");
this.TextInput?.Invoke(this, text);
}
}
return true;
}
private bool OnKeyRelease(IntPtr widget, IntPtr eventData, IntPtr userData)
{
var (item, item2, item3) = ParseKeyEvent(eventData);
this.KeyReleased?.Invoke(this, (item, item2, item3));
return true;
}
private bool OnScroll(IntPtr widget, IntPtr eventData, IntPtr userData)
{
var (item, item2, item3, item4) = ParseScrollEvent(eventData);
this.Scrolled?.Invoke(this, (item, item2, item3, item4));
return true;
}
private static (double x, double y, int button) ParseButtonEvent(IntPtr eventData)
{
GdkEventButton gdkEventButton = Marshal.PtrToStructure<GdkEventButton>(eventData);
return (x: gdkEventButton.x, y: gdkEventButton.y, button: (int)gdkEventButton.button);
}
private static (double x, double y) ParseMotionEvent(IntPtr eventData)
{
GdkEventMotion gdkEventMotion = Marshal.PtrToStructure<GdkEventMotion>(eventData);
return (x: gdkEventMotion.x, y: gdkEventMotion.y);
}
private static (uint keyval, uint keycode, uint state) ParseKeyEvent(IntPtr eventData)
{
GdkEventKey gdkEventKey = Marshal.PtrToStructure<GdkEventKey>(eventData);
return (keyval: gdkEventKey.keyval, keycode: gdkEventKey.hardware_keycode, state: gdkEventKey.state);
}
private static (double x, double y, double deltaX, double deltaY) ParseScrollEvent(IntPtr eventData)
{
GdkEventScroll gdkEventScroll = Marshal.PtrToStructure<GdkEventScroll>(eventData);
double item = 0.0;
double item2 = 0.0;
if (gdkEventScroll.direction == 4)
{
item = gdkEventScroll.delta_x;
item2 = gdkEventScroll.delta_y;
}
else
{
switch (gdkEventScroll.direction)
{
case 0:
item2 = -1.0;
break;
case 1:
item2 = 1.0;
break;
case 2:
item = -1.0;
break;
case 3:
item = 1.0;
break;
}
}
return (x: gdkEventScroll.x, y: gdkEventScroll.y, deltaX: item, deltaY: item2);
}
public void GrabFocus()
{
GtkNative.gtk_widget_grab_focus(_widget);
}
public void Dispose()
{
SKCanvas? canvas = _canvas;
if (canvas != null)
{
((SKNativeObject)canvas).Dispose();
}
_canvas = null;
SKBitmap? bitmap = _bitmap;
if (bitmap != null)
{
((SKNativeObject)bitmap).Dispose();
}
_bitmap = null;
if (_cairoSurface != IntPtr.Zero)
{
CairoNative.cairo_surface_destroy(_cairoSurface);
_cairoSurface = IntPtr.Zero;
}
}
}

View File

@@ -1,80 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Rendering;
public class LayeredRenderer : IDisposable
{
private readonly Dictionary<int, RenderLayer> _layers = new Dictionary<int, RenderLayer>();
private readonly object _lock = new object();
private bool _disposed;
public RenderLayer GetLayer(int zIndex)
{
lock (_lock)
{
if (!_layers.TryGetValue(zIndex, out RenderLayer value))
{
value = new RenderLayer(zIndex);
_layers[zIndex] = value;
}
return value;
}
}
public void RemoveLayer(int zIndex)
{
lock (_lock)
{
if (_layers.TryGetValue(zIndex, out RenderLayer value))
{
value.Dispose();
_layers.Remove(zIndex);
}
}
}
public void Composite(SKCanvas canvas, SKRect bounds)
{
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
lock (_lock)
{
foreach (RenderLayer item in _layers.Values.OrderBy((RenderLayer l) => l.ZIndex))
{
item.DrawTo(canvas, bounds);
}
}
}
public void InvalidateAll()
{
lock (_lock)
{
foreach (RenderLayer value in _layers.Values)
{
value.Invalidate();
}
}
}
public void Dispose()
{
if (_disposed)
{
return;
}
_disposed = true;
lock (_lock)
{
foreach (RenderLayer value in _layers.Values)
{
value.Dispose();
}
_layers.Clear();
}
}
}

View File

@@ -1,230 +1,526 @@
using System;
using System.Collections.Generic;
using System.Linq;
// 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;
/// <summary>
/// Caches rendered content for views that don't change frequently.
/// Improves performance by avoiding redundant rendering.
/// </summary>
public class RenderCache : IDisposable
{
private class CacheEntry
{
public string Key { get; set; } = string.Empty;
private readonly Dictionary<string, CacheEntry> _cache = new();
private readonly object _lock = new();
private long _maxCacheSize = 50 * 1024 * 1024; // 50 MB default
private long _currentCacheSize;
private bool _disposed;
public SKBitmap? Bitmap { get; set; }
/// <summary>
/// Gets or sets the maximum cache size in bytes.
/// </summary>
public long MaxCacheSize
{
get => _maxCacheSize;
set
{
_maxCacheSize = Math.Max(1024 * 1024, value); // Minimum 1 MB
TrimCache();
}
}
public long Size { get; set; }
/// <summary>
/// Gets the current cache size in bytes.
/// </summary>
public long CurrentCacheSize => _currentCacheSize;
public DateTime Created { get; set; }
/// <summary>
/// Gets the number of cached items.
/// </summary>
public int CachedItemCount
{
get
{
lock (_lock)
{
return _cache.Count;
}
}
}
public DateTime LastAccessed { get; set; }
/// <summary>
/// Tries to get a cached bitmap for the given key.
/// </summary>
public bool TryGet(string key, out SKBitmap? bitmap)
{
lock (_lock)
{
if (_cache.TryGetValue(key, out var entry))
{
entry.LastAccessed = DateTime.UtcNow;
entry.AccessCount++;
bitmap = entry.Bitmap;
return true;
}
}
public int AccessCount { get; set; }
}
bitmap = null;
return false;
}
private readonly Dictionary<string, CacheEntry> _cache = new Dictionary<string, CacheEntry>();
/// <summary>
/// Caches a bitmap with the given key.
/// </summary>
public void Set(string key, SKBitmap bitmap)
{
if (bitmap == null) return;
private readonly object _lock = new object();
long bitmapSize = bitmap.ByteCount;
private long _maxCacheSize = 52428800L;
// Don't cache if bitmap is larger than max size
if (bitmapSize > _maxCacheSize)
{
return;
}
private long _currentCacheSize;
lock (_lock)
{
// Remove existing entry if present
if (_cache.TryGetValue(key, out var existing))
{
_currentCacheSize -= existing.Size;
existing.Bitmap?.Dispose();
}
private bool _disposed;
// Create copy of bitmap for cache
var cachedBitmap = bitmap.Copy();
if (cachedBitmap == null) return;
public long MaxCacheSize
{
get
{
return _maxCacheSize;
}
set
{
_maxCacheSize = Math.Max(1048576L, value);
TrimCache();
}
}
var entry = new CacheEntry
{
Key = key,
Bitmap = cachedBitmap,
Size = bitmapSize,
Created = DateTime.UtcNow,
LastAccessed = DateTime.UtcNow,
AccessCount = 1
};
public long CurrentCacheSize => _currentCacheSize;
_cache[key] = entry;
_currentCacheSize += bitmapSize;
public int CachedItemCount
{
get
{
lock (_lock)
{
return _cache.Count;
}
}
}
// Trim cache if needed
TrimCache();
}
}
public bool TryGet(string key, out SKBitmap? bitmap)
{
lock (_lock)
{
if (_cache.TryGetValue(key, out CacheEntry value))
{
value.LastAccessed = DateTime.UtcNow;
value.AccessCount++;
bitmap = value.Bitmap;
return true;
}
}
bitmap = null;
return false;
}
/// <summary>
/// Invalidates a cached entry.
/// </summary>
public void Invalidate(string key)
{
lock (_lock)
{
if (_cache.TryGetValue(key, out var entry))
{
_currentCacheSize -= entry.Size;
entry.Bitmap?.Dispose();
_cache.Remove(key);
}
}
}
public void Set(string key, SKBitmap bitmap)
{
if (bitmap == null)
{
return;
}
long num = bitmap.ByteCount;
if (num > _maxCacheSize)
{
return;
}
lock (_lock)
{
if (_cache.TryGetValue(key, out CacheEntry value))
{
_currentCacheSize -= value.Size;
SKBitmap? bitmap2 = value.Bitmap;
if (bitmap2 != null)
{
((SKNativeObject)bitmap2).Dispose();
}
}
SKBitmap val = bitmap.Copy();
if (val != null)
{
CacheEntry value2 = new CacheEntry
{
Key = key,
Bitmap = val,
Size = num,
Created = DateTime.UtcNow,
LastAccessed = DateTime.UtcNow,
AccessCount = 1
};
_cache[key] = value2;
_currentCacheSize += num;
TrimCache();
}
}
}
/// <summary>
/// Invalidates all entries matching a prefix.
/// </summary>
public void InvalidatePrefix(string prefix)
{
lock (_lock)
{
var keysToRemove = _cache.Keys
.Where(k => k.StartsWith(prefix, StringComparison.Ordinal))
.ToList();
public void Invalidate(string key)
{
lock (_lock)
{
if (_cache.TryGetValue(key, out CacheEntry value))
{
_currentCacheSize -= value.Size;
SKBitmap? bitmap = value.Bitmap;
if (bitmap != null)
{
((SKNativeObject)bitmap).Dispose();
}
_cache.Remove(key);
}
}
}
foreach (var key in keysToRemove)
{
if (_cache.TryGetValue(key, out var entry))
{
_currentCacheSize -= entry.Size;
entry.Bitmap?.Dispose();
_cache.Remove(key);
}
}
}
}
public void InvalidatePrefix(string prefix)
{
lock (_lock)
{
foreach (string item in _cache.Keys.Where((string k) => k.StartsWith(prefix, StringComparison.Ordinal)).ToList())
{
if (_cache.TryGetValue(item, out CacheEntry value))
{
_currentCacheSize -= value.Size;
SKBitmap? bitmap = value.Bitmap;
if (bitmap != null)
{
((SKNativeObject)bitmap).Dispose();
}
_cache.Remove(item);
}
}
}
}
/// <summary>
/// Clears all cached content.
/// </summary>
public void Clear()
{
lock (_lock)
{
foreach (var entry in _cache.Values)
{
entry.Bitmap?.Dispose();
}
_cache.Clear();
_currentCacheSize = 0;
}
}
public void Clear()
{
lock (_lock)
{
foreach (CacheEntry value in _cache.Values)
{
SKBitmap? bitmap = value.Bitmap;
if (bitmap != null)
{
((SKNativeObject)bitmap).Dispose();
}
}
_cache.Clear();
_currentCacheSize = 0L;
}
}
/// <summary>
/// Renders content with caching.
/// </summary>
public SKBitmap GetOrCreate(string key, int width, int height, Action<SKCanvas> render)
{
// Check cache first
if (TryGet(key, out var cached) && cached != null &&
cached.Width == width && cached.Height == height)
{
return cached;
}
public SKBitmap GetOrCreate(string key, int width, int height, Action<SKCanvas> render)
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Expected O, but got Unknown
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Expected O, but got Unknown
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
if (TryGet(key, out SKBitmap bitmap) && bitmap != null && bitmap.Width == width && bitmap.Height == height)
{
return bitmap;
}
SKBitmap val = new SKBitmap(width, height, (SKColorType)4, (SKAlphaType)2);
SKCanvas val2 = new SKCanvas(val);
try
{
val2.Clear(SKColors.Transparent);
render(val2);
}
finally
{
((IDisposable)val2)?.Dispose();
}
Set(key, val);
return val;
}
// Create new bitmap
var bitmap = new SKBitmap(width, height, SKColorType.Rgba8888, SKAlphaType.Premul);
using (var canvas = new SKCanvas(bitmap))
{
canvas.Clear(SKColors.Transparent);
render(canvas);
}
private void TrimCache()
{
if (_currentCacheSize <= _maxCacheSize)
{
return;
}
foreach (CacheEntry item in (from e in _cache.Values
orderby e.LastAccessed, e.AccessCount
select e).ToList())
{
if ((double)_currentCacheSize <= (double)_maxCacheSize * 0.8)
{
break;
}
_currentCacheSize -= item.Size;
SKBitmap? bitmap = item.Bitmap;
if (bitmap != null)
{
((SKNativeObject)bitmap).Dispose();
}
_cache.Remove(item.Key);
}
}
// Cache it
Set(key, bitmap);
public void Dispose()
{
if (!_disposed)
{
_disposed = true;
Clear();
}
}
return bitmap;
}
private void TrimCache()
{
if (_currentCacheSize <= _maxCacheSize) return;
// Remove least recently used entries until under limit
var entries = _cache.Values
.OrderBy(e => e.LastAccessed)
.ThenBy(e => e.AccessCount)
.ToList();
foreach (var entry in entries)
{
if (_currentCacheSize <= _maxCacheSize * 0.8) // Target 80% usage
{
break;
}
_currentCacheSize -= entry.Size;
entry.Bitmap?.Dispose();
_cache.Remove(entry.Key);
}
}
public void Dispose()
{
if (_disposed) return;
_disposed = true;
Clear();
}
private class CacheEntry
{
public string Key { get; set; } = string.Empty;
public SKBitmap? Bitmap { get; set; }
public long Size { get; set; }
public DateTime Created { get; set; }
public DateTime LastAccessed { 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;
}
}

View File

@@ -1,111 +0,0 @@
using System;
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)
{
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Expected O, but got Unknown
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Expected O, but got Unknown
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
if (_bitmap == null || _bounds != bounds)
{
SKBitmap? bitmap = _bitmap;
if (bitmap != null)
{
((SKNativeObject)bitmap).Dispose();
}
SKCanvas? canvas = _canvas;
if (canvas != null)
{
((SKNativeObject)canvas).Dispose();
}
int num = Math.Max(1, (int)((SKRect)(ref bounds)).Width);
int num2 = Math.Max(1, (int)((SKRect)(ref bounds)).Height);
_bitmap = new SKBitmap(num, num2, (SKColorType)4, (SKAlphaType)2);
_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)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Expected O, but got Unknown
if (!IsVisible || _bitmap == null)
{
return;
}
SKPaint val = new SKPaint
{
Color = ((SKColor)(ref SKColors.White)).WithAlpha((byte)(Opacity * 255f))
};
try
{
canvas.DrawBitmap(_bitmap, ((SKRect)(ref bounds)).Left, ((SKRect)(ref bounds)).Top, val);
}
finally
{
((IDisposable)val)?.Dispose();
}
}
public void Dispose()
{
if (!_disposed)
{
_disposed = true;
SKCanvas? canvas = _canvas;
if (canvas != null)
{
((SKNativeObject)canvas).Dispose();
}
SKBitmap? bitmap = _bitmap;
if (bitmap != null)
{
((SKNativeObject)bitmap).Dispose();
}
}
}
}

View File

@@ -1,42 +0,0 @@
using System;
using System.Collections.Generic;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Rendering;
public class ResourceCache : IDisposable
{
private readonly Dictionary<string, SKTypeface> _typefaces = new Dictionary<string, SKTypeface>();
private bool _disposed;
public SKTypeface GetTypeface(string fontFamily, SKFontStyle style)
{
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
string key = $"{fontFamily}_{style.Weight}_{style.Width}_{style.Slant}";
if (!_typefaces.TryGetValue(key, out SKTypeface value))
{
value = SKTypeface.FromFamilyName(fontFamily, style) ?? SKTypeface.Default;
_typefaces[key] = value;
}
return value;
}
public void Clear()
{
foreach (SKTypeface value in _typefaces.Values)
{
((SKNativeObject)value).Dispose();
}
_typefaces.Clear();
}
public void Dispose()
{
if (!_disposed)
{
Clear();
_disposed = true;
}
}
}

View File

@@ -1,372 +1,165 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Maui.Platform.Linux.Window;
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using SkiaSharp;
using Microsoft.Maui.Platform.Linux.Window;
using Microsoft.Maui.Platform;
using System.Runtime.InteropServices;
namespace Microsoft.Maui.Platform.Linux.Rendering;
/// <summary>
/// Manages Skia rendering to an X11 window.
/// </summary>
public class SkiaRenderingEngine : IDisposable
{
private readonly X11Window _window;
private readonly X11Window _window;
private SKBitmap? _bitmap;
private SKCanvas? _canvas;
private SKImageInfo _imageInfo;
private bool _disposed;
private bool _fullRedrawNeeded = true;
private SKBitmap? _bitmap;
public static SkiaRenderingEngine? Current { get; private set; }
public ResourceCache ResourceCache { get; }
public int Width => _imageInfo.Width;
public int Height => _imageInfo.Height;
private SKBitmap? _backBuffer;
public SkiaRenderingEngine(X11Window window)
{
_window = window;
ResourceCache = new ResourceCache();
Current = this;
private SKCanvas? _canvas;
CreateSurface(window.Width, window.Height);
private SKImageInfo _imageInfo;
_window.Resized += OnWindowResized;
_window.Exposed += OnWindowExposed;
}
private bool _disposed;
private void CreateSurface(int width, int height)
{
_bitmap?.Dispose();
_canvas?.Dispose();
private bool _fullRedrawNeeded = true;
_imageInfo = new SKImageInfo(
Math.Max(1, width),
Math.Max(1, height),
SKColorType.Bgra8888,
SKAlphaType.Premul);
private readonly List<SKRect> _dirtyRegions = new List<SKRect>();
_bitmap = new SKBitmap(_imageInfo);
_canvas = new SKCanvas(_bitmap);
_fullRedrawNeeded = true;
}
private readonly object _dirtyLock = new object();
private void OnWindowResized(object? sender, (int Width, int Height) size)
{
CreateSurface(size.Width, size.Height);
}
private const int MaxDirtyRegions = 32;
private void OnWindowExposed(object? sender, EventArgs e)
{
_fullRedrawNeeded = true;
}
private const float RegionMergeThreshold = 0.3f;
public void InvalidateAll()
{
_fullRedrawNeeded = true;
}
public static SkiaRenderingEngine? Current { get; private set; }
public void Render(SkiaView rootView)
{
if (_canvas == null || _bitmap == null)
return;
public ResourceCache ResourceCache { get; }
_canvas.Clear(SKColors.White);
// Measure first, then arrange
var availableSize = new SKSize(Width, Height);
rootView.Measure(availableSize);
rootView.Arrange(new SKRect(0, 0, Width, Height));
// Draw the view tree
rootView.Draw(_canvas);
// Draw popup overlays (dropdowns, calendars, etc.) on top
SkiaView.DrawPopupOverlays(_canvas);
public int Width => ((SKImageInfo)(ref _imageInfo)).Width;
// Draw modal dialogs on top of everything
if (LinuxDialogService.HasActiveDialog)
{
LinuxDialogService.DrawDialogs(_canvas, new SKRect(0, 0, Width, Height));
}
public int Height => ((SKImageInfo)(ref _imageInfo)).Height;
_canvas.Flush();
public bool EnableDirtyRegionOptimization { get; set; } = true;
// Present to X11 window
PresentToWindow();
}
public int DirtyRegionCount
{
get
{
lock (_dirtyLock)
{
return _dirtyRegions.Count;
}
}
}
private void PresentToWindow()
{
if (_bitmap == null) return;
public SkiaRenderingEngine(X11Window window)
{
_window = window;
ResourceCache = new ResourceCache();
Current = this;
CreateSurface(window.Width, window.Height);
_window.Resized += OnWindowResized;
_window.Exposed += OnWindowExposed;
}
var pixels = _bitmap.GetPixels();
if (pixels == IntPtr.Zero) return;
private void CreateSurface(int width, int height)
{
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Expected O, but got Unknown
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Expected O, but got Unknown
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Expected O, but got Unknown
SKBitmap? bitmap = _bitmap;
if (bitmap != null)
{
((SKNativeObject)bitmap).Dispose();
}
SKBitmap? backBuffer = _backBuffer;
if (backBuffer != null)
{
((SKNativeObject)backBuffer).Dispose();
}
SKCanvas? canvas = _canvas;
if (canvas != null)
{
((SKNativeObject)canvas).Dispose();
}
_imageInfo = new SKImageInfo(Math.Max(1, width), Math.Max(1, height), (SKColorType)6, (SKAlphaType)2);
_bitmap = new SKBitmap(_imageInfo);
_backBuffer = new SKBitmap(_imageInfo);
_canvas = new SKCanvas(_bitmap);
_fullRedrawNeeded = true;
lock (_dirtyLock)
{
_dirtyRegions.Clear();
}
}
_window.DrawPixels(pixels, _imageInfo.Width, _imageInfo.Height, _imageInfo.RowBytes);
}
private void OnWindowResized(object? sender, (int Width, int Height) size)
{
CreateSurface(size.Width, size.Height);
}
public SKCanvas? GetCanvas() => _canvas;
private void OnWindowExposed(object? sender, EventArgs e)
{
_fullRedrawNeeded = true;
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
_window.Resized -= OnWindowResized;
_window.Exposed -= OnWindowExposed;
_canvas?.Dispose();
_bitmap?.Dispose();
ResourceCache.Dispose();
if (Current == this) Current = null;
}
_disposed = true;
}
}
public void InvalidateAll()
{
_fullRedrawNeeded = true;
}
public void InvalidateRegion(SKRect region)
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
if (((SKRect)(ref region)).IsEmpty || ((SKRect)(ref region)).Width <= 0f || ((SKRect)(ref region)).Height <= 0f)
{
return;
}
region = SKRect.Intersect(region, new SKRect(0f, 0f, (float)Width, (float)Height));
if (((SKRect)(ref region)).IsEmpty)
{
return;
}
lock (_dirtyLock)
{
if (_dirtyRegions.Count >= 32)
{
_fullRedrawNeeded = true;
_dirtyRegions.Clear();
return;
}
for (int i = 0; i < _dirtyRegions.Count; i++)
{
SKRect val = _dirtyRegions[i];
if (ShouldMergeRegions(val, region))
{
_dirtyRegions[i] = SKRect.Union(val, region);
return;
}
}
_dirtyRegions.Add(region);
}
}
private bool ShouldMergeRegions(SKRect a, SKRect b)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
SKRect val = SKRect.Intersect(a, b);
if (((SKRect)(ref val)).IsEmpty)
{
SKRect val2 = default(SKRect);
((SKRect)(ref val2))._002Ector(((SKRect)(ref a)).Left - 4f, ((SKRect)(ref a)).Top - 4f, ((SKRect)(ref a)).Right + 4f, ((SKRect)(ref a)).Bottom + 4f);
return ((SKRect)(ref val2)).IntersectsWith(b);
}
float num = ((SKRect)(ref val)).Width * ((SKRect)(ref val)).Height;
float val3 = ((SKRect)(ref a)).Width * ((SKRect)(ref a)).Height;
float val4 = ((SKRect)(ref b)).Width * ((SKRect)(ref b)).Height;
float num2 = Math.Min(val3, val4);
return num / num2 >= 0.3f;
}
public void Render(SkiaView rootView)
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_0100: Unknown result type (might be due to invalid IL or missing references)
//IL_0105: Unknown result type (might be due to invalid IL or missing references)
//IL_0109: Unknown result type (might be due to invalid IL or missing references)
//IL_015a: Unknown result type (might be due to invalid IL or missing references)
if (_canvas == null || _bitmap == null)
{
return;
}
SKSize availableSize = default(SKSize);
((SKSize)(ref availableSize))._002Ector((float)Width, (float)Height);
rootView.Measure(availableSize);
rootView.Arrange(new SKRect(0f, 0f, (float)Width, (float)Height));
bool flag = _fullRedrawNeeded || !EnableDirtyRegionOptimization;
List<SKRect> list;
lock (_dirtyLock)
{
if (flag)
{
list = new List<SKRect>
{
new SKRect(0f, 0f, (float)Width, (float)Height)
};
_dirtyRegions.Clear();
_fullRedrawNeeded = false;
}
else
{
if (_dirtyRegions.Count == 0)
{
return;
}
list = MergeOverlappingRegions(_dirtyRegions.ToList());
_dirtyRegions.Clear();
}
}
foreach (SKRect item in list)
{
RenderRegion(rootView, item, flag);
}
SkiaView.DrawPopupOverlays(_canvas);
if (LinuxDialogService.HasActiveDialog)
{
LinuxDialogService.DrawDialogs(_canvas, new SKRect(0f, 0f, (float)Width, (float)Height));
}
_canvas.Flush();
PresentToWindow();
}
private void RenderRegion(SkiaView rootView, SKRect region, bool isFullRedraw)
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Expected O, but got Unknown
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
if (_canvas == null)
{
return;
}
_canvas.Save();
if (!isFullRedraw)
{
_canvas.ClipRect(region, (SKClipOperation)1, false);
}
SKPaint val = new SKPaint
{
Color = SKColors.White,
Style = (SKPaintStyle)0
};
try
{
_canvas.DrawRect(region, val);
rootView.Draw(_canvas);
_canvas.Restore();
}
finally
{
((IDisposable)val)?.Dispose();
}
}
private List<SKRect> MergeOverlappingRegions(List<SKRect> regions)
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Unknown result type (might be due to invalid IL or missing references)
if (regions.Count <= 1)
{
return regions;
}
List<SKRect> list = new List<SKRect>();
bool[] array = new bool[regions.Count];
for (int i = 0; i < regions.Count; i++)
{
if (array[i])
{
continue;
}
SKRect val = regions[i];
array[i] = true;
bool flag;
do
{
flag = false;
for (int j = i + 1; j < regions.Count; j++)
{
if (!array[j] && ShouldMergeRegions(val, regions[j]))
{
val = SKRect.Union(val, regions[j]);
array[j] = true;
flag = true;
}
}
}
while (flag);
list.Add(val);
}
return list;
}
private void PresentToWindow()
{
if (_bitmap != null)
{
IntPtr pixels = _bitmap.GetPixels();
if (pixels != IntPtr.Zero)
{
_window.DrawPixels(pixels, ((SKImageInfo)(ref _imageInfo)).Width, ((SKImageInfo)(ref _imageInfo)).Height, ((SKImageInfo)(ref _imageInfo)).RowBytes);
}
}
}
public SKCanvas? GetCanvas()
{
return _canvas;
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
{
return;
}
if (disposing)
{
_window.Resized -= OnWindowResized;
_window.Exposed -= OnWindowExposed;
SKCanvas? canvas = _canvas;
if (canvas != null)
{
((SKNativeObject)canvas).Dispose();
}
SKBitmap? bitmap = _bitmap;
if (bitmap != null)
{
((SKNativeObject)bitmap).Dispose();
}
SKBitmap? backBuffer = _backBuffer;
if (backBuffer != null)
{
((SKNativeObject)backBuffer).Dispose();
}
ResourceCache.Dispose();
if (Current == this)
{
Current = null;
}
}
_disposed = true;
}
public void Dispose()
{
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
public void Dispose()
{
Dispose(true);
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; }
}
}

View File

@@ -1,142 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
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)
{
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
_text = text;
_textSize = paint.TextSize;
_color = paint.Color;
SKTypeface typeface = paint.Typeface;
_weight = ((typeface != null) ? typeface.FontWeight : 400);
_hashCode = HashCode.Combine<string, float, SKColor, int>(_text, _textSize, _color, _weight);
}
public bool Equals(TextCacheKey other)
{
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
if (_text == other._text && Math.Abs(_textSize - other._textSize) < 0.001f && _color == other._color)
{
return _weight == other._weight;
}
return false;
}
public override bool Equals(object? obj)
{
if (obj is TextCacheKey other)
{
return Equals(other);
}
return false;
}
public override int GetHashCode()
{
return _hashCode;
}
}
private readonly Dictionary<TextCacheKey, SKBitmap> _cache = new Dictionary<TextCacheKey, SKBitmap>();
private readonly object _lock = new object();
private int _maxEntries = 500;
private bool _disposed;
public int MaxEntries
{
get
{
return _maxEntries;
}
set
{
_maxEntries = Math.Max(10, value);
}
}
public SKBitmap GetOrCreate(string text, SKPaint paint)
{
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Expected O, but got Unknown
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Expected O, but got Unknown
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
TextCacheKey key = new TextCacheKey(text, paint);
lock (_lock)
{
if (_cache.TryGetValue(key, out SKBitmap value))
{
return value;
}
SKRect val = default(SKRect);
paint.MeasureText(text, ref val);
int num = Math.Max(1, (int)Math.Ceiling(((SKRect)(ref val)).Width) + 2);
int num2 = Math.Max(1, (int)Math.Ceiling(((SKRect)(ref val)).Height) + 2);
SKBitmap val2 = new SKBitmap(num, num2, (SKColorType)4, (SKAlphaType)2);
SKCanvas val3 = new SKCanvas(val2);
try
{
val3.Clear(SKColors.Transparent);
val3.DrawText(text, 0f - ((SKRect)(ref val)).Left + 1f, 0f - ((SKRect)(ref val)).Top + 1f, paint);
}
finally
{
((IDisposable)val3)?.Dispose();
}
if (_cache.Count >= _maxEntries)
{
KeyValuePair<TextCacheKey, SKBitmap> keyValuePair = _cache.First();
((SKNativeObject)keyValuePair.Value).Dispose();
_cache.Remove(keyValuePair.Key);
}
_cache[key] = val2;
return val2;
}
}
public void Clear()
{
lock (_lock)
{
foreach (SKBitmap value in _cache.Values)
{
((SKNativeObject)value).Dispose();
}
_cache.Clear();
}
}
public void Dispose()
{
if (!_disposed)
{
_disposed = true;
Clear();
}
}
}

View File

@@ -1,25 +0,0 @@
using System.Collections.Generic;
namespace Microsoft.Maui.Platform.Linux.Services;
internal class _003CFontFallbackManager_003EFAC9D2911A2850E174CCA7662C668F37C2FBBA325CAF5C11AFE3FA59C16CC64ED__StringBuilder
{
private readonly List<char> _chars = new List<char>();
public int Length => _chars.Count;
public void Append(string s)
{
_chars.AddRange(s);
}
public void Clear()
{
_chars.Clear();
}
public override string ToString()
{
return new string(_chars.ToArray());
}
}

View File

@@ -1,52 +0,0 @@
using System;
namespace Microsoft.Maui.Platform.Linux.Services;
public static class AccessibilityServiceFactory
{
private static IAccessibilityService? _instance;
private static readonly object _lock = new object();
public static IAccessibilityService Instance
{
get
{
if (_instance == null)
{
lock (_lock)
{
if (_instance == null)
{
_instance = CreateService();
}
}
}
return _instance;
}
}
private static IAccessibilityService CreateService()
{
try
{
AtSpi2AccessibilityService atSpi2AccessibilityService = new AtSpi2AccessibilityService();
atSpi2AccessibilityService.Initialize();
return atSpi2AccessibilityService;
}
catch (Exception ex)
{
Console.WriteLine("AccessibilityServiceFactory: Failed to create AT-SPI2 service - " + ex.Message);
return new NullAccessibilityService();
}
}
public static void Reset()
{
lock (_lock)
{
_instance?.Shutdown();
_instance = null;
}
}
}

View File

@@ -1,10 +0,0 @@
namespace Microsoft.Maui.Platform.Linux.Services;
public class AccessibleAction
{
public string Name { get; set; } = string.Empty;
public string Description { get; set; } = string.Empty;
public string? KeyBinding { get; set; }
}

View File

@@ -1,11 +0,0 @@
namespace Microsoft.Maui.Platform.Linux.Services;
public enum AccessibleProperty
{
Name,
Description,
Role,
Value,
Parent,
Children
}

View File

@@ -1,20 +0,0 @@
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;
}
}

View File

@@ -1,49 +0,0 @@
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
}

View File

@@ -1,38 +0,0 @@
namespace Microsoft.Maui.Platform.Linux.Services;
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
}

View File

@@ -1,50 +0,0 @@
using System;
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
}

View File

@@ -1,7 +0,0 @@
namespace Microsoft.Maui.Platform.Linux.Services;
public enum AnnouncementPriority
{
Polite,
Assertive
}

Some files were not shown because too many files have changed in this diff Show More