refactor: replace Console.WriteLine with DiagnosticLog service
All checks were successful
CI / Build (Linux) (push) Successful in 21s

Replace 495+ Console.WriteLine debug statements across handlers, dispatching, services, views, and window components with centralized DiagnosticLog service for proper logging infrastructure. Add new DiagnosticLog.cs service with Debug/Error methods to eliminate debug logging pollution in production code.
This commit is contained in:
2026-03-06 22:06:08 -05:00
parent 08e0c4d2b9
commit e55230c441
70 changed files with 814 additions and 638 deletions

View File

@@ -6,6 +6,7 @@ using Microsoft.Maui.Graphics;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using Microsoft.Maui.Platform.Linux.Hosting;
using Microsoft.Maui.Platform.Linux.Services;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
@@ -111,13 +112,13 @@ public partial class BorderHandler : ViewHandler<IBorderView, SkiaBorder>
// Create handler for content if it doesn't exist
if (content.Handler == null)
{
Console.WriteLine($"[BorderHandler] Creating handler for content: {content.GetType().Name}");
DiagnosticLog.Debug("BorderHandler", $"Creating handler for content: {content.GetType().Name}");
content.Handler = content.ToViewHandler(handler.MauiContext);
}
if (content.Handler?.PlatformView is SkiaView skiaContent)
{
Console.WriteLine($"[BorderHandler] Adding content: {skiaContent.GetType().Name}");
DiagnosticLog.Debug("BorderHandler", $"Adding content: {skiaContent.GetType().Name}");
handler.PlatformView.AddChild(skiaContent);
}
}
@@ -156,7 +157,7 @@ public partial class BorderHandler : ViewHandler<IBorderView, SkiaBorder>
if (border is VisualElement ve)
{
var bgColor = ve.BackgroundColor;
Console.WriteLine($"[BorderHandler] MapBackgroundColor: {bgColor}");
DiagnosticLog.Debug("BorderHandler", $"MapBackgroundColor: {bgColor}");
if (bgColor != null)
{
handler.PlatformView.BackgroundColor = bgColor;

View File

@@ -4,6 +4,7 @@
using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Platform.Linux.Services;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
@@ -64,7 +65,7 @@ public partial class ButtonHandler : ViewHandler<IButton, SkiaButton>
// Map size requests from MAUI Button
if (VirtualView is Microsoft.Maui.Controls.Button mauiButton)
{
Console.WriteLine($"[ButtonHandler] MapSize Text='{platformView.Text}' WReq={mauiButton.WidthRequest} HReq={mauiButton.HeightRequest}");
DiagnosticLog.Debug("ButtonHandler", $"MapSize Text='{platformView.Text}' WReq={mauiButton.WidthRequest} HReq={mauiButton.HeightRequest}");
if (mauiButton.WidthRequest >= 0)
platformView.WidthRequest = mauiButton.WidthRequest;
if (mauiButton.HeightRequest >= 0)
@@ -72,7 +73,7 @@ public partial class ButtonHandler : ViewHandler<IButton, SkiaButton>
}
else
{
Console.WriteLine($"[ButtonHandler] VirtualView is NOT Microsoft.Maui.Controls.Button, type={VirtualView?.GetType().Name}");
DiagnosticLog.Debug("ButtonHandler", $"VirtualView is NOT Microsoft.Maui.Controls.Button, type={VirtualView?.GetType().Name}");
}
}
}
@@ -162,7 +163,7 @@ public partial class TextButtonHandler : ButtonHandler
protected override void ConnectHandler(SkiaButton platformView)
{
Console.WriteLine($"[TextButtonHandler] ConnectHandler START");
DiagnosticLog.Debug("TextButtonHandler", "ConnectHandler START");
base.ConnectHandler(platformView);
// Manually map text properties on connect since MAUI may not trigger updates
@@ -178,13 +179,13 @@ public partial class TextButtonHandler : ButtonHandler
// Map size requests from MAUI Button
if (VirtualView is Microsoft.Maui.Controls.Button mauiButton)
{
Console.WriteLine($"[TextButtonHandler] MapSize Text='{platformView.Text}' WReq={mauiButton.WidthRequest} HReq={mauiButton.HeightRequest}");
DiagnosticLog.Debug("TextButtonHandler", $"MapSize Text='{platformView.Text}' WReq={mauiButton.WidthRequest} HReq={mauiButton.HeightRequest}");
if (mauiButton.WidthRequest >= 0)
platformView.WidthRequest = mauiButton.WidthRequest;
if (mauiButton.HeightRequest >= 0)
platformView.HeightRequest = mauiButton.HeightRequest;
}
Console.WriteLine($"[TextButtonHandler] ConnectHandler DONE");
DiagnosticLog.Debug("TextButtonHandler", "ConnectHandler DONE");
}
public static void MapText(TextButtonHandler handler, ITextButton button)

View File

@@ -6,6 +6,7 @@ using Microsoft.Maui.Graphics;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using Microsoft.Maui.Platform.Linux.Hosting;
using Microsoft.Maui.Platform.Linux.Services;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
@@ -130,18 +131,18 @@ public partial class CollectionViewHandler : ViewHandler<CollectionView, SkiaCol
{
_isUpdatingSelection = true;
Console.WriteLine($"[CollectionViewHandler] OnItemTapped index={e.Index}, item={e.Item}, SelectionMode={VirtualView.SelectionMode}");
DiagnosticLog.Debug("CollectionViewHandler", $"OnItemTapped index={e.Index}, item={e.Item}, SelectionMode={VirtualView.SelectionMode}");
// Try to get the item view and process gestures
var skiaView = PlatformView?.GetItemView(e.Index);
Console.WriteLine($"[CollectionViewHandler] GetItemView({e.Index}) returned: {skiaView?.GetType().Name ?? "null"}, MauiView={skiaView?.MauiView?.GetType().Name ?? "null"}");
DiagnosticLog.Debug("CollectionViewHandler", $"GetItemView({e.Index}) returned: {skiaView?.GetType().Name ?? "null"}, MauiView={skiaView?.MauiView?.GetType().Name ?? "null"}");
if (skiaView?.MauiView != null)
{
Console.WriteLine($"[CollectionViewHandler] Found MauiView: {skiaView.MauiView.GetType().Name}, GestureRecognizers={skiaView.MauiView.GestureRecognizers?.Count ?? 0}");
DiagnosticLog.Debug("CollectionViewHandler", $"Found MauiView: {skiaView.MauiView.GetType().Name}, GestureRecognizers={skiaView.MauiView.GestureRecognizers?.Count ?? 0}");
if (GestureManager.ProcessTap(skiaView.MauiView, 0, 0))
{
Console.WriteLine("[CollectionViewHandler] Gesture processed successfully");
DiagnosticLog.Debug("CollectionViewHandler", "Gesture processed successfully");
return;
}
}
@@ -208,7 +209,7 @@ public partial class CollectionViewHandler : ViewHandler<CollectionView, SkiaCol
{
// Set MauiView so gestures can be processed
skiaView.MauiView = view;
Console.WriteLine($"[CollectionViewHandler.ItemViewCreator] Set MauiView={view.GetType().Name} on {skiaView.GetType().Name}, GestureRecognizers={view.GestureRecognizers?.Count ?? 0}");
DiagnosticLog.Debug("CollectionViewHandler", $"ItemViewCreator: Set MauiView={view.GetType().Name} on {skiaView.GetType().Name}, GestureRecognizers={view.GestureRecognizers?.Count ?? 0}");
return skiaView;
}
}

View File

@@ -70,13 +70,23 @@ public partial class EntryHandler : ViewHandler<IEntry, SkiaEntry>
base.DisconnectHandler(platformView);
}
private bool _isUpdatingText;
private void OnTextChanged(object? sender, Platform.TextChangedEventArgs e)
{
if (VirtualView is null || PlatformView is null) return;
if (VirtualView is null || PlatformView is null || _isUpdatingText) return;
if (VirtualView.Text != e.NewTextValue)
{
VirtualView.Text = e.NewTextValue ?? string.Empty;
_isUpdatingText = true;
try
{
VirtualView.Text = e.NewTextValue ?? string.Empty;
}
finally
{
_isUpdatingText = false;
}
}
}
@@ -87,7 +97,7 @@ public partial class EntryHandler : ViewHandler<IEntry, SkiaEntry>
public static void MapText(EntryHandler handler, IEntry entry)
{
if (handler.PlatformView is null) return;
if (handler.PlatformView is null || handler._isUpdatingText) return;
if (handler.PlatformView.Text != entry.Text)
{

View File

@@ -4,6 +4,7 @@ using System.Linq;
using System.Reflection;
using System.Windows.Input;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform.Linux.Services;
namespace Microsoft.Maui.Platform.Linux.Handlers;
@@ -13,6 +14,8 @@ namespace Microsoft.Maui.Platform.Linux.Handlers;
/// </summary>
public static class GestureManager
{
private const string Tag = "GestureManager";
private class GestureTrackingState
{
public double StartX { get; set; }
@@ -35,16 +38,54 @@ public static class GestureManager
Released
}
// Cached reflection MethodInfo for internal MAUI methods
private static MethodInfo? _sendTappedMethod;
private static MethodInfo? _sendSwipedMethod;
private static MethodInfo? _sendPanMethod;
private static MethodInfo? _sendPinchMethod;
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 static MethodInfo? _sendDragStartingMethod;
private static MethodInfo? _sendDragOverMethod;
private static MethodInfo? _sendDropMethod;
private static readonly Dictionary<PointerEventType, MethodInfo?> _pointerMethodCache = new();
private const double SwipeMinDistance = 50.0;
private const double SwipeMaxTime = 500.0;
private const double SwipeDirectionThreshold = 0.5;
private const double PanMinDistance = 10.0;
private const double PinchScrollScale = 0.1; // Scale factor per scroll unit
private static readonly Dictionary<View, (DateTime lastTap, int tapCount)> _tapTracking = new();
private static readonly Dictionary<View, GestureTrackingState> _gestureState = new();
/// <summary>
/// Minimum distance in pixels for a swipe gesture to be recognized.
/// </summary>
public static double SwipeMinDistance { get; set; } = 50.0;
/// <summary>
/// Maximum time in milliseconds for a swipe gesture to be recognized.
/// </summary>
public static double SwipeMaxTime { get; set; } = 500.0;
/// <summary>
/// Ratio threshold for determining swipe direction dominance.
/// </summary>
public static double SwipeDirectionThreshold { get; set; } = 0.5;
/// <summary>
/// Minimum distance in pixels before a pan gesture is recognized.
/// </summary>
public static double PanMinDistance { get; set; } = 10.0;
/// <summary>
/// Scale factor per scroll unit for pinch-via-scroll gestures.
/// </summary>
public static double PinchScrollScale { get; set; } = 0.1;
/// <summary>
/// Removes tracking entries for the specified view, preventing memory leaks
/// when views are disconnected from the visual tree.
/// </summary>
public static void CleanupView(View view)
{
if (view == null) return;
_tapTracking.Remove(view);
_gestureState.Remove(view);
}
/// <summary>
/// Processes a tap gesture on the specified view.
@@ -79,12 +120,13 @@ public static class GestureManager
bool result = false;
foreach (var item in recognizers)
{
var tapRecognizer = (item is TapGestureRecognizer) ? (TapGestureRecognizer)item : null;
if (tapRecognizer == null)
if (item is not TapGestureRecognizer tapRecognizer)
{
continue;
}
Console.WriteLine($"[GestureManager] Processing TapGestureRecognizer on {view.GetType().Name}, CommandParameter={tapRecognizer.CommandParameter}, NumberOfTapsRequired={tapRecognizer.NumberOfTapsRequired}");
DiagnosticLog.Debug(Tag,
$"Processing TapGestureRecognizer on {view.GetType().Name}, CommandParameter={tapRecognizer.CommandParameter}, NumberOfTapsRequired={tapRecognizer.NumberOfTapsRequired}");
int numberOfTapsRequired = tapRecognizer.NumberOfTapsRequired;
if (numberOfTapsRequired > 1)
{
@@ -92,108 +134,58 @@ public static class GestureManager
if (!_tapTracking.TryGetValue(view, out var tracking))
{
_tapTracking[view] = (utcNow, 1);
Console.WriteLine($"[GestureManager] First tap 1/{numberOfTapsRequired}");
DiagnosticLog.Debug(Tag, $"First tap 1/{numberOfTapsRequired}");
continue;
}
if (!((utcNow - tracking.lastTap).TotalMilliseconds < 300.0))
{
_tapTracking[view] = (utcNow, 1);
Console.WriteLine($"[GestureManager] Tap timeout, reset to 1/{numberOfTapsRequired}");
DiagnosticLog.Debug(Tag, $"Tap timeout, reset to 1/{numberOfTapsRequired}");
continue;
}
int tapCount = tracking.tapCount + 1;
if (tapCount < numberOfTapsRequired)
{
_tapTracking[view] = (utcNow, tapCount);
Console.WriteLine($"[GestureManager] Tap {tapCount}/{numberOfTapsRequired}, waiting for more taps");
DiagnosticLog.Debug(Tag, $"Tap {tapCount}/{numberOfTapsRequired}, waiting for more taps");
continue;
}
_tapTracking.Remove(view);
}
// Try to raise the Tapped event via cached reflection
bool eventFired = false;
try
{
if (_sendTappedMethod == null)
{
_sendTappedMethod = typeof(TapGestureRecognizer).GetMethod("SendTapped", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
_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");
var args = new TappedEventArgs(tapRecognizer.CommandParameter);
_sendTappedMethod.Invoke(tapRecognizer, new object[] { view, args });
Console.WriteLine("[GestureManager] SendTapped invoked successfully");
DiagnosticLog.Debug(Tag, "SendTapped invoked successfully");
eventFired = true;
}
}
catch (Exception ex)
{
Console.WriteLine("[GestureManager] SendTapped failed: " + ex.Message);
DiagnosticLog.Error(Tag, "SendTapped failed", ex);
}
// Always invoke the Command if available (SendTapped may or may not invoke it internally)
if (!eventFired)
{
try
ICommand? command = tapRecognizer.Command;
if (command != null && command.CanExecute(tapRecognizer.CommandParameter))
{
var field = typeof(TapGestureRecognizer).GetField("Tapped", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
?? typeof(TapGestureRecognizer).GetField("_tapped", BindingFlags.Instance | BindingFlags.NonPublic);
if (field != null && field.GetValue(tapRecognizer) is EventHandler<TappedEventArgs> handler)
{
Console.WriteLine("[GestureManager] Invoking Tapped event directly");
var args = new TappedEventArgs(tapRecognizer.CommandParameter);
handler(tapRecognizer, args);
eventFired = true;
}
}
catch (Exception ex)
{
Console.WriteLine("[GestureManager] Direct event invoke failed: " + ex.Message);
DiagnosticLog.Debug(Tag, "Executing TapGestureRecognizer Command");
command.Execute(tapRecognizer.CommandParameter);
}
}
if (!eventFired)
{
try
{
string[] fieldNames = new string[] { "TappedEvent", "_TappedHandler", "<Tapped>k__BackingField" };
foreach (string fieldName in fieldNames)
{
var field = typeof(TapGestureRecognizer).GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
if (field != null)
{
Console.WriteLine("[GestureManager] Found field: " + fieldName);
if (field.GetValue(tapRecognizer) is EventHandler<TappedEventArgs> handler)
{
var args = new TappedEventArgs(tapRecognizer.CommandParameter);
handler(tapRecognizer, args);
Console.WriteLine("[GestureManager] Event fired via " + fieldName);
eventFired = true;
break;
}
}
}
}
catch (Exception ex)
{
Console.WriteLine("[GestureManager] Backing field approach failed: " + ex.Message);
}
}
if (!eventFired)
{
Console.WriteLine("[GestureManager] Could not fire event, dumping type info...");
var methods = typeof(TapGestureRecognizer).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (var method in methods)
{
if (method.Name.Contains("Tap", StringComparison.OrdinalIgnoreCase) || method.Name.Contains("Send", StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine($"[GestureManager] Method: {method.Name}({string.Join(", ", from p in method.GetParameters() select p.ParameterType.Name)})");
}
}
}
ICommand? command = tapRecognizer.Command;
if (command != null && command.CanExecute(tapRecognizer.CommandParameter))
{
Console.WriteLine("[GestureManager] Executing Command");
command.Execute(tapRecognizer.CommandParameter);
}
result = true;
}
return result;
@@ -274,7 +266,7 @@ public static class GestureManager
}
double deltaX = x - state.StartX;
double deltaY = y - state.StartY;
if (Math.Sqrt(deltaX * deltaX + deltaY * deltaY) >= 10.0)
if (Math.Sqrt(deltaX * deltaX + deltaY * deltaY) >= PanMinDistance)
{
ProcessPanGesture(view, deltaX, deltaY, (GestureStatus)(state.IsPanning ? 1 : 0));
state.IsPanning = true;
@@ -299,14 +291,14 @@ public static class GestureManager
double deltaY = y - state.StartY;
double distance = Math.Sqrt(deltaX * deltaX + deltaY * deltaY);
double elapsed = (DateTime.UtcNow - state.StartTime).TotalMilliseconds;
if (distance >= 50.0 && elapsed <= 500.0)
if (distance >= SwipeMinDistance && elapsed <= SwipeMaxTime)
{
var direction = DetermineSwipeDirection(deltaX, deltaY);
if (direction != SwipeDirection.Right)
{
ProcessSwipeGesture(view, direction);
}
else if (Math.Abs(deltaX) > Math.Abs(deltaY) * 0.5)
else if (Math.Abs(deltaX) > Math.Abs(deltaY) * SwipeDirectionThreshold)
{
ProcessSwipeGesture(view, (deltaX > 0.0) ? SwipeDirection.Right : SwipeDirection.Left);
}
@@ -315,9 +307,9 @@ public static class GestureManager
{
ProcessPanGesture(view, deltaX, deltaY, (GestureStatus)2);
}
else if (distance < 15.0 && elapsed < 500.0)
else if (distance < 15.0 && elapsed < SwipeMaxTime)
{
Console.WriteLine($"[GestureManager] Detected tap on {view.GetType().Name} (distance={distance:F1}, elapsed={elapsed:F0}ms)");
DiagnosticLog.Debug(Tag, $"Detected tap on {view.GetType().Name} (distance={distance:F1}, elapsed={elapsed:F0}ms)");
ProcessTap(view, x, y);
}
_gestureState.Remove(view);
@@ -351,7 +343,7 @@ public static class GestureManager
{
double absX = Math.Abs(deltaX);
double absY = Math.Abs(deltaY);
if (absX > absY * 0.5)
if (absX > absY * SwipeDirectionThreshold)
{
if (deltaX > 0.0)
{
@@ -359,7 +351,7 @@ public static class GestureManager
}
return SwipeDirection.Left;
}
if (absY > absX * 0.5)
if (absY > absX * SwipeDirectionThreshold)
{
if (deltaY > 0.0)
{
@@ -383,29 +375,34 @@ public static class GestureManager
}
foreach (var item in recognizers)
{
var swipeRecognizer = (item is SwipeGestureRecognizer) ? (SwipeGestureRecognizer)item : null;
if (swipeRecognizer == null || !swipeRecognizer.Direction.HasFlag(direction))
if (item is not SwipeGestureRecognizer swipeRecognizer || !swipeRecognizer.Direction.HasFlag(direction))
{
continue;
}
Console.WriteLine($"[GestureManager] Swipe detected: {direction}");
DiagnosticLog.Debug(Tag, $"Swipe detected: {direction}");
try
{
var method = typeof(SwipeGestureRecognizer).GetMethod("SendSwiped", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (method != null)
if (_sendSwipedMethod == null)
{
method.Invoke(swipeRecognizer, new object[] { view, direction });
Console.WriteLine("[GestureManager] SendSwiped invoked successfully");
_sendSwipedMethod = typeof(SwipeGestureRecognizer).GetMethod(
"SendSwiped", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
}
if (_sendSwipedMethod != null)
{
_sendSwipedMethod.Invoke(swipeRecognizer, new object[] { view, direction });
DiagnosticLog.Debug(Tag, "SendSwiped invoked successfully");
}
}
catch (Exception ex)
{
Console.WriteLine("[GestureManager] SendSwiped failed: " + ex.Message);
DiagnosticLog.Error(Tag, "SendSwiped failed", ex);
}
ICommand? command = swipeRecognizer.Command;
if (command != null && command.CanExecute(swipeRecognizer.CommandParameter))
{
swipeRecognizer.Command.Execute(swipeRecognizer.CommandParameter);
command.Execute(swipeRecognizer.CommandParameter);
}
}
}
@@ -419,18 +416,22 @@ public static class GestureManager
}
foreach (var item in recognizers)
{
var panRecognizer = (item is PanGestureRecognizer) ? (PanGestureRecognizer)item : null;
if (panRecognizer == null)
if (item is not PanGestureRecognizer panRecognizer)
{
continue;
}
Console.WriteLine($"[GestureManager] Pan gesture: status={status}, totalX={totalX:F1}, totalY={totalY:F1}");
DiagnosticLog.Debug(Tag, $"Pan gesture: status={status}, totalX={totalX:F1}, totalY={totalY:F1}");
try
{
var method = typeof(PanGestureRecognizer).GetMethod("SendPan", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (method != null)
if (_sendPanMethod == null)
{
method.Invoke(panRecognizer, new object[]
_sendPanMethod = typeof(PanGestureRecognizer).GetMethod(
"SendPan", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
}
if (_sendPanMethod != null)
{
_sendPanMethod.Invoke(panRecognizer, new object[]
{
view,
totalX,
@@ -441,7 +442,7 @@ public static class GestureManager
}
catch (Exception ex)
{
Console.WriteLine("[GestureManager] SendPan failed: " + ex.Message);
DiagnosticLog.Error(Tag, "SendPan failed", ex);
}
}
}
@@ -455,8 +456,7 @@ public static class GestureManager
}
foreach (var item in recognizers)
{
var pointerRecognizer = (item is PointerGestureRecognizer) ? (PointerGestureRecognizer)item : null;
if (pointerRecognizer == null)
if (item is not PointerGestureRecognizer pointerRecognizer)
{
continue;
}
@@ -471,19 +471,27 @@ public static class GestureManager
PointerEventType.Released => "SendPointerReleased",
_ => null,
};
if (methodName != null)
if (methodName == null)
{
var method = typeof(PointerGestureRecognizer).GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (method != null)
{
var args = CreatePointerEventArgs(view, x, y);
method.Invoke(pointerRecognizer, new object[] { view, args });
}
continue;
}
if (!_pointerMethodCache.TryGetValue(eventType, out var method))
{
method = typeof(PointerGestureRecognizer).GetMethod(
methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
_pointerMethodCache[eventType] = method;
}
if (method != null)
{
var args = CreatePointerEventArgs(view, x, y);
method.Invoke(pointerRecognizer, new object[] { view, args });
}
}
catch (Exception ex)
{
Console.WriteLine("[GestureManager] Pointer event failed: " + ex.Message);
DiagnosticLog.Error(Tag, $"Pointer event {eventType} failed", ex);
}
}
}
@@ -587,26 +595,23 @@ public static class GestureManager
foreach (var item in recognizers)
{
var pinchRecognizer = item as PinchGestureRecognizer;
if (pinchRecognizer == null)
if (item is not PinchGestureRecognizer pinchRecognizer)
{
continue;
}
Console.WriteLine($"[GestureManager] Pinch gesture: status={status}, scale={scale:F2}, origin=({originX:F0},{originY:F0})");
DiagnosticLog.Debug(Tag, $"Pinch gesture: status={status}, scale={scale:F2}, origin=({originX:F0},{originY:F0})");
try
{
// Cache the method lookup
if (_sendPinchMethod == null)
{
_sendPinchMethod = typeof(PinchGestureRecognizer).GetMethod("SendPinch",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
_sendPinchMethod = typeof(PinchGestureRecognizer).GetMethod(
"SendPinch", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
}
if (_sendPinchMethod != null)
{
// SendPinch(IView sender, double scale, Point scaleOrigin, GestureStatus status)
var scaleOrigin = new Point(originX / view.Width, originY / view.Height);
_sendPinchMethod.Invoke(pinchRecognizer, new object[]
{
@@ -615,12 +620,12 @@ public static class GestureManager
scaleOrigin,
status
});
Console.WriteLine("[GestureManager] SendPinch invoked successfully");
DiagnosticLog.Debug(Tag, "SendPinch invoked successfully");
}
}
catch (Exception ex)
{
Console.WriteLine($"[GestureManager] SendPinch failed: {ex.Message}");
DiagnosticLog.Error(Tag, "SendPinch failed", ex);
}
}
}
@@ -751,26 +756,27 @@ public static class GestureManager
foreach (var item in recognizers)
{
var dragRecognizer = item as DragGestureRecognizer;
if (dragRecognizer == null) continue;
if (item is not DragGestureRecognizer dragRecognizer) continue;
Console.WriteLine($"[GestureManager] Starting drag from {view.GetType().Name}");
DiagnosticLog.Debug(Tag, $"Starting drag from {view.GetType().Name}");
try
{
// Create DragStartingEventArgs and invoke SendDragStarting
var method = typeof(DragGestureRecognizer).GetMethod("SendDragStarting",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (method != null)
if (_sendDragStartingMethod == null)
{
method.Invoke(dragRecognizer, new object[] { view });
Console.WriteLine("[GestureManager] SendDragStarting invoked successfully");
_sendDragStartingMethod = typeof(DragGestureRecognizer).GetMethod(
"SendDragStarting", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
}
if (_sendDragStartingMethod != null)
{
_sendDragStartingMethod.Invoke(dragRecognizer, new object[] { view });
DiagnosticLog.Debug(Tag, "SendDragStarting invoked successfully");
}
}
catch (Exception ex)
{
Console.WriteLine($"[GestureManager] SendDragStarting failed: {ex.Message}");
DiagnosticLog.Error(Tag, "SendDragStarting failed", ex);
}
}
}
@@ -787,24 +793,26 @@ public static class GestureManager
foreach (var item in recognizers)
{
var dropRecognizer = item as DropGestureRecognizer;
if (dropRecognizer == null) continue;
if (item is not DropGestureRecognizer dropRecognizer) continue;
Console.WriteLine($"[GestureManager] Drag enter on {view.GetType().Name}");
DiagnosticLog.Debug(Tag, $"Drag enter on {view.GetType().Name}");
try
{
var method = typeof(DropGestureRecognizer).GetMethod("SendDragOver",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (method != null)
if (_sendDragOverMethod == null)
{
method.Invoke(dropRecognizer, new object[] { view });
_sendDragOverMethod = typeof(DropGestureRecognizer).GetMethod(
"SendDragOver", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
}
if (_sendDragOverMethod != null)
{
_sendDragOverMethod.Invoke(dropRecognizer, new object[] { view });
}
}
catch (Exception ex)
{
Console.WriteLine($"[GestureManager] SendDragOver failed: {ex.Message}");
DiagnosticLog.Error(Tag, "SendDragOver failed", ex);
}
}
}
@@ -821,24 +829,26 @@ public static class GestureManager
foreach (var item in recognizers)
{
var dropRecognizer = item as DropGestureRecognizer;
if (dropRecognizer == null) continue;
if (item is not DropGestureRecognizer dropRecognizer) continue;
Console.WriteLine($"[GestureManager] Drop on {view.GetType().Name}");
DiagnosticLog.Debug(Tag, $"Drop on {view.GetType().Name}");
try
{
var method = typeof(DropGestureRecognizer).GetMethod("SendDrop",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (method != null)
if (_sendDropMethod == null)
{
method.Invoke(dropRecognizer, new object[] { view });
_sendDropMethod = typeof(DropGestureRecognizer).GetMethod(
"SendDrop", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
}
if (_sendDropMethod != null)
{
_sendDropMethod.Invoke(dropRecognizer, new object[] { view });
}
}
catch (Exception ex)
{
Console.WriteLine($"[GestureManager] SendDrop failed: {ex.Message}");
DiagnosticLog.Error(Tag, "SendDrop failed", ex);
}
}
}

View File

@@ -55,7 +55,7 @@ public class GtkWebViewHandler : ViewHandler<IWebView, GtkWebViewProxy>
_platformWebView.NavigationCompleted += OnNavigationCompleted;
_platformWebView.ScriptDialogRequested += OnScriptDialogRequested;
}
Console.WriteLine("[GtkWebViewHandler] ConnectHandler - WebView ready");
DiagnosticLog.Debug("GtkWebViewHandler", "ConnectHandler - WebView ready");
}
protected override void DisconnectHandler(GtkWebViewProxy platformView)
@@ -75,7 +75,7 @@ public class GtkWebViewHandler : ViewHandler<IWebView, GtkWebViewProxy>
private async void OnScriptDialogRequested(object? sender,
(ScriptDialogType Type, string Message, Action<bool> Callback) e)
{
Console.WriteLine($"[GtkWebViewHandler] Script dialog requested: type={e.Type}, message={e.Message}");
DiagnosticLog.Debug("GtkWebViewHandler", $"Script dialog requested: type={e.Type}, message={e.Message}");
string title = e.Type switch
{
@@ -92,18 +92,18 @@ public class GtkWebViewHandler : ViewHandler<IWebView, GtkWebViewProxy>
{
bool result = await LinuxDialogService.ShowAlertAsync(title, e.Message, acceptButton, cancelButton);
e.Callback(result);
Console.WriteLine($"[GtkWebViewHandler] Dialog result: {result}");
DiagnosticLog.Debug("GtkWebViewHandler", $"Dialog result: {result}");
}
catch (Exception ex)
{
Console.WriteLine($"[GtkWebViewHandler] Error showing dialog: {ex.Message}");
DiagnosticLog.Error("GtkWebViewHandler", $"Error showing dialog: {ex.Message}", ex);
e.Callback(false);
}
}
private void OnNavigationStarted(object? sender, string uri)
{
Console.WriteLine($"[GtkWebViewHandler] Navigation started: {uri}");
DiagnosticLog.Debug("GtkWebViewHandler", $"Navigation started: {uri}");
try
{
GLibNative.IdleAdd(() =>
@@ -115,25 +115,25 @@ public class GtkWebViewHandler : ViewHandler<IWebView, GtkWebViewProxy>
var args = new Microsoft.Maui.Controls.WebNavigatingEventArgs(
WebNavigationEvent.NewPage, null, uri);
controller.SendNavigating(args);
Console.WriteLine("[GtkWebViewHandler] Sent Navigating event to VirtualView");
DiagnosticLog.Debug("GtkWebViewHandler", "Sent Navigating event to VirtualView");
}
}
catch (Exception ex)
{
Console.WriteLine($"[GtkWebViewHandler] Error in SendNavigating: {ex.Message}");
DiagnosticLog.Error("GtkWebViewHandler", $"Error in SendNavigating: {ex.Message}", ex);
}
return false;
});
}
catch (Exception ex)
{
Console.WriteLine($"[GtkWebViewHandler] Error dispatching navigation started: {ex.Message}");
DiagnosticLog.Error("GtkWebViewHandler", $"Error dispatching navigation started: {ex.Message}", ex);
}
}
private void OnNavigationCompleted(object? sender, (string Url, bool Success) e)
{
Console.WriteLine($"[GtkWebViewHandler] Navigation completed: {e.Url} (Success: {e.Success})");
DiagnosticLog.Debug("GtkWebViewHandler", $"Navigation completed: {e.Url} (Success: {e.Success})");
try
{
GLibNative.IdleAdd(() =>
@@ -151,19 +151,19 @@ public class GtkWebViewHandler : ViewHandler<IWebView, GtkWebViewProxy>
bool canGoForward = _platformWebView?.CanGoForward() ?? false;
controller.CanGoBack = canGoBack;
controller.CanGoForward = canGoForward;
Console.WriteLine($"[GtkWebViewHandler] Sent Navigated, CanGoBack={canGoBack}, CanGoForward={canGoForward}");
DiagnosticLog.Debug("GtkWebViewHandler", $"Sent Navigated, CanGoBack={canGoBack}, CanGoForward={canGoForward}");
}
}
catch (Exception ex)
{
Console.WriteLine($"[GtkWebViewHandler] Error in SendNavigated: {ex.Message}");
DiagnosticLog.Error("GtkWebViewHandler", $"Error in SendNavigated: {ex.Message}", ex);
}
return false;
});
}
catch (Exception ex)
{
Console.WriteLine($"[GtkWebViewHandler] Error dispatching navigation completed: {ex.Message}");
DiagnosticLog.Error("GtkWebViewHandler", $"Error dispatching navigation completed: {ex.Message}", ex);
}
}
@@ -175,7 +175,7 @@ public class GtkWebViewHandler : ViewHandler<IWebView, GtkWebViewProxy>
var hostService = GtkHostService.Instance;
if (hostService.HostWindow == null || hostService.WebViewManager == null)
{
Console.WriteLine("[GtkWebViewHandler] Warning: GTK host not initialized, cannot register WebView");
DiagnosticLog.Warn("GtkWebViewHandler", "GTK host not initialized, cannot register WebView");
return;
}
@@ -186,7 +186,7 @@ public class GtkWebViewHandler : ViewHandler<IWebView, GtkWebViewProxy>
if (width <= 0 || height <= 0)
{
Console.WriteLine($"[GtkWebViewHandler] Skipping invalid bounds: {bounds}");
DiagnosticLog.Warn("GtkWebViewHandler", $"Skipping invalid bounds: {bounds}");
return;
}
@@ -194,12 +194,12 @@ public class GtkWebViewHandler : ViewHandler<IWebView, GtkWebViewProxy>
{
hostService.HostWindow.AddWebView(_platformWebView.Widget, x, y, width, height);
_isRegisteredWithHost = true;
Console.WriteLine($"[GtkWebViewHandler] Registered WebView at ({x}, {y}) size {width}x{height}");
DiagnosticLog.Debug("GtkWebViewHandler", $"Registered WebView at ({x}, {y}) size {width}x{height}");
}
else if (bounds != _lastBounds)
{
hostService.HostWindow.MoveResizeWebView(_platformWebView.Widget, x, y, width, height);
Console.WriteLine($"[GtkWebViewHandler] Updated WebView to ({x}, {y}) size {width}x{height}");
DiagnosticLog.Debug("GtkWebViewHandler", $"Updated WebView to ({x}, {y}) size {width}x{height}");
}
_lastBounds = bounds;
@@ -213,7 +213,7 @@ public class GtkWebViewHandler : ViewHandler<IWebView, GtkWebViewProxy>
if (hostService.HostWindow != null)
{
hostService.HostWindow.RemoveWebView(_platformWebView.Widget);
Console.WriteLine("[GtkWebViewHandler] Unregistered WebView from host");
DiagnosticLog.Debug("GtkWebViewHandler", "Unregistered WebView from host");
}
_isRegisteredWithHost = false;
}
@@ -225,7 +225,7 @@ public class GtkWebViewHandler : ViewHandler<IWebView, GtkWebViewProxy>
return;
var source = webView.Source;
Console.WriteLine($"[GtkWebViewHandler] MapSource: {source?.GetType().Name ?? "null"}");
DiagnosticLog.Debug("GtkWebViewHandler", $"MapSource: {source?.GetType().Name ?? "null"}");
if (source is UrlWebViewSource urlSource)
{
@@ -247,19 +247,19 @@ public class GtkWebViewHandler : ViewHandler<IWebView, GtkWebViewProxy>
public static void MapGoBack(GtkWebViewHandler handler, IWebView webView, object? args)
{
Console.WriteLine($"[GtkWebViewHandler] MapGoBack called, CanGoBack={handler._platformWebView?.CanGoBack()}");
DiagnosticLog.Debug("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()}");
DiagnosticLog.Debug("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");
DiagnosticLog.Debug("GtkWebViewHandler", "MapReload called");
handler._platformWebView?.Reload();
}
}

View File

@@ -74,7 +74,7 @@ public sealed class GtkWebViewPlatformView : IDisposable
Microsoft.Maui.Controls.Application.Current.RequestedThemeChanged += _themeChangedHandler;
}
Console.WriteLine("[GtkWebViewPlatformView] Created WebKitWebView widget");
DiagnosticLog.Debug("GtkWebViewPlatformView", "Created WebKitWebView widget");
}
/// <summary>
@@ -105,7 +105,7 @@ public sealed class GtkWebViewPlatformView : IDisposable
var dialogType = (ScriptDialogType)(int)webkitDialogType;
var message = WebKitNative.GetScriptDialogMessage(dialog) ?? "";
Console.WriteLine($"[GtkWebViewPlatformView] Script dialog: type={dialogType}, message={message}");
DiagnosticLog.Debug("GtkWebViewPlatformView", $"Script dialog: type={dialogType}, message={message}");
// Get the parent window for proper modal behavior
IntPtr parentWindow = GtkHostService.Instance.HostWindow?.Window ?? IntPtr.Zero;
@@ -166,7 +166,7 @@ public sealed class GtkWebViewPlatformView : IDisposable
// Run the dialog synchronously - this blocks until user responds
int response = GtkNative.gtk_dialog_run(gtkDialog);
Console.WriteLine($"[GtkWebViewPlatformView] Dialog response: {response}");
DiagnosticLog.Debug("GtkWebViewPlatformView", $"Dialog response: {response}");
// Set the confirmed state for confirm dialogs
if (dialogType == ScriptDialogType.Confirm || dialogType == ScriptDialogType.BeforeUnloadConfirm)
@@ -184,7 +184,7 @@ public sealed class GtkWebViewPlatformView : IDisposable
}
catch (Exception ex)
{
Console.WriteLine($"[GtkWebViewPlatformView] Error in OnScriptDialog: {ex.Message}");
DiagnosticLog.Error("GtkWebViewPlatformView", $"Error in OnScriptDialog: {ex.Message}", ex);
// Return false on error to let WebKitGTK try its default handling
return false;
}
@@ -210,7 +210,7 @@ public sealed class GtkWebViewPlatformView : IDisposable
if (gtkDialog == IntPtr.Zero)
{
Console.WriteLine("[GtkWebViewPlatformView] Failed to create prompt dialog");
DiagnosticLog.Error("GtkWebViewPlatformView", "Failed to create prompt dialog");
return false;
}
@@ -251,7 +251,7 @@ public sealed class GtkWebViewPlatformView : IDisposable
// Run the dialog
int response = GtkNative.gtk_dialog_run(gtkDialog);
Console.WriteLine($"[GtkWebViewPlatformView] Prompt dialog response: {response}");
DiagnosticLog.Debug("GtkWebViewPlatformView", $"Prompt dialog response: {response}");
if (response == GtkNative.GTK_RESPONSE_OK)
{
@@ -261,7 +261,7 @@ public sealed class GtkWebViewPlatformView : IDisposable
? System.Runtime.InteropServices.Marshal.PtrToStringUTF8(textPtr)
: "";
Console.WriteLine($"[GtkWebViewPlatformView] Prompt text: {enteredText}");
DiagnosticLog.Debug("GtkWebViewPlatformView", $"Prompt text: {enteredText}");
// Set the prompt response
WebKitNative.SetScriptDialogPromptText(webkitDialog, enteredText ?? "");
@@ -278,7 +278,7 @@ public sealed class GtkWebViewPlatformView : IDisposable
}
catch (Exception ex)
{
Console.WriteLine($"[GtkWebViewPlatformView] Error in HandlePromptDialog: {ex.Message}");
DiagnosticLog.Error("GtkWebViewPlatformView", $"Error in HandlePromptDialog: {ex.Message}", ex);
return false;
}
}
@@ -299,7 +299,7 @@ public sealed class GtkWebViewPlatformView : IDisposable
isDark = Microsoft.Maui.Controls.Application.Current?.RequestedTheme == Microsoft.Maui.ApplicationModel.AppTheme.Dark;
}
Console.WriteLine($"[GtkWebViewPlatformView] ApplyDialogTheme: isDark={isDark}, UserAppTheme={Microsoft.Maui.Controls.Application.Current?.UserAppTheme}");
DiagnosticLog.Debug("GtkWebViewPlatformView", $"ApplyDialogTheme: isDark={isDark}, UserAppTheme={Microsoft.Maui.Controls.Application.Current?.UserAppTheme}");
// Create comprehensive CSS based on the theme - targeting all dialog elements
string css = isDark
@@ -407,7 +407,7 @@ public sealed class GtkWebViewPlatformView : IDisposable
}
catch (Exception ex)
{
Console.WriteLine($"[GtkWebViewPlatformView] Error applying dialog theme: {ex.Message}");
DiagnosticLog.Error("GtkWebViewPlatformView", $"Error applying dialog theme: {ex.Message}", ex);
}
}
@@ -419,17 +419,17 @@ public sealed class GtkWebViewPlatformView : IDisposable
switch ((WebKitNative.WebKitLoadEvent)loadEvent)
{
case WebKitNative.WebKitLoadEvent.Started:
Console.WriteLine("[GtkWebViewPlatformView] Load started: " + uri);
DiagnosticLog.Debug("GtkWebViewPlatformView", "Load started: " + uri);
NavigationStarted?.Invoke(this, uri);
break;
case WebKitNative.WebKitLoadEvent.Finished:
_currentUri = uri;
Console.WriteLine("[GtkWebViewPlatformView] Load finished: " + uri);
DiagnosticLog.Debug("GtkWebViewPlatformView", "Load finished: " + uri);
NavigationCompleted?.Invoke(this, (uri, true));
break;
case WebKitNative.WebKitLoadEvent.Committed:
_currentUri = uri;
Console.WriteLine("[GtkWebViewPlatformView] Load committed: " + uri);
DiagnosticLog.Debug("GtkWebViewPlatformView", "Load committed: " + uri);
break;
case WebKitNative.WebKitLoadEvent.Redirected:
break;
@@ -437,8 +437,7 @@ public sealed class GtkWebViewPlatformView : IDisposable
}
catch (Exception ex)
{
Console.WriteLine("[GtkWebViewPlatformView] Error in OnLoadChanged: " + ex.Message);
Console.WriteLine("[GtkWebViewPlatformView] Stack trace: " + ex.StackTrace);
DiagnosticLog.Error("GtkWebViewPlatformView", "Error in OnLoadChanged: " + ex.Message, ex);
}
}
@@ -447,7 +446,7 @@ public sealed class GtkWebViewPlatformView : IDisposable
if (_widget != IntPtr.Zero)
{
WebKitNative.LoadUri(_widget, uri);
Console.WriteLine("[GtkWebViewPlatformView] Navigate to: " + uri);
DiagnosticLog.Debug("GtkWebViewPlatformView", "Navigate to: " + uri);
}
}
@@ -456,7 +455,7 @@ public sealed class GtkWebViewPlatformView : IDisposable
if (_widget != IntPtr.Zero)
{
WebKitNative.LoadHtml(_widget, html, baseUri);
Console.WriteLine("[GtkWebViewPlatformView] Load HTML content");
DiagnosticLog.Debug("GtkWebViewPlatformView", "Load HTML content");
}
}

View File

@@ -5,6 +5,7 @@ using System.IO;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Platform.Linux.Services;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
@@ -127,7 +128,7 @@ public partial class ImageHandler : ViewHandler<IImage, SkiaImage>
if (image is Image img && img.WidthRequest > 0)
{
handler.PlatformView.WidthRequest = img.WidthRequest;
Console.WriteLine($"[ImageHandler] MapWidth: {img.WidthRequest}");
DiagnosticLog.Debug("ImageHandler", $"MapWidth: {img.WidthRequest}");
}
else if (image.Width > 0)
{
@@ -142,7 +143,7 @@ public partial class ImageHandler : ViewHandler<IImage, SkiaImage>
if (image is Image img && img.HeightRequest > 0)
{
handler.PlatformView.HeightRequest = img.HeightRequest;
Console.WriteLine($"[ImageHandler] MapHeight: {img.HeightRequest}");
DiagnosticLog.Debug("ImageHandler", $"MapHeight: {img.HeightRequest}");
}
else if (image.Height > 0)
{

View File

@@ -3,6 +3,7 @@
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform.Linux.Hosting;
using Microsoft.Maui.Platform.Linux.Services;
using SkiaSharp;
namespace Microsoft.Maui.Platform;
@@ -279,13 +280,13 @@ public partial class GridHandler : LayoutHandler
protected override void ConnectHandler(SkiaLayoutView platformView)
{
Console.WriteLine($"[GridHandler.ConnectHandler] Called! VirtualView={VirtualView?.GetType().Name}, PlatformView={platformView?.GetType().Name}, MauiContext={(MauiContext != null ? "set" : "null")}");
DiagnosticLog.Debug("GridHandler", $"ConnectHandler Called! VirtualView={VirtualView?.GetType().Name}, PlatformView={platformView?.GetType().Name}, MauiContext={(MauiContext != null ? "set" : "null")}");
base.ConnectHandler(platformView);
// Map definitions on connect
if (VirtualView is IGridLayout gridLayout && platformView is SkiaGrid grid && MauiContext != null)
{
Console.WriteLine($"[GridHandler.ConnectHandler] Grid has {gridLayout.Count} children, RowDefs={gridLayout.RowDefinitions?.Count ?? 0}");
DiagnosticLog.Debug("GridHandler", $"ConnectHandler Grid has {gridLayout.Count} children, RowDefs={gridLayout.RowDefinitions?.Count ?? 0}");
UpdateRowDefinitions(grid, gridLayout);
UpdateColumnDefinitions(grid, gridLayout);
@@ -295,13 +296,13 @@ public partial class GridHandler : LayoutHandler
var child = gridLayout[i];
if (child == null) continue;
Console.WriteLine($"[GridHandler.ConnectHandler] Child[{i}]: {child.GetType().Name}, Handler={child.Handler?.GetType().Name ?? "null"}");
DiagnosticLog.Debug("GridHandler", $"ConnectHandler Child[{i}]: {child.GetType().Name}, Handler={child.Handler?.GetType().Name ?? "null"}");
// Create handler for child if it doesn't exist
if (child.Handler == null)
{
child.Handler = child.ToViewHandler(MauiContext);
Console.WriteLine($"[GridHandler.ConnectHandler] Created handler for child[{i}]: {child.Handler?.GetType().Name ?? "failed"}");
DiagnosticLog.Debug("GridHandler", $"ConnectHandler Created handler for child[{i}]: {child.Handler?.GetType().Name ?? "failed"}");
}
if (child.Handler?.PlatformView is SkiaView skiaChild)
@@ -315,11 +316,11 @@ public partial class GridHandler : LayoutHandler
rowSpan = Microsoft.Maui.Controls.Grid.GetRowSpan(mauiView);
columnSpan = Microsoft.Maui.Controls.Grid.GetColumnSpan(mauiView);
}
Console.WriteLine($"[GridHandler.ConnectHandler] Adding child[{i}] at row={row}, col={column}");
DiagnosticLog.Debug("GridHandler", $"ConnectHandler Adding child[{i}] at row={row}, col={column}");
grid.AddChild(skiaChild, row, column, rowSpan, columnSpan);
}
}
Console.WriteLine($"[GridHandler.ConnectHandler] Grid now has {grid.Children.Count} SkiaView children");
DiagnosticLog.Debug("GridHandler", $"ConnectHandler Grid now has {grid.Children.Count} SkiaView children");
}
}

View File

@@ -4,6 +4,7 @@
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Platform.Linux.Hosting;
using Microsoft.Maui.Platform.Linux.Services;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
@@ -245,7 +246,7 @@ public partial class GridHandler : LayoutHandler
// 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");
DiagnosticLog.Debug("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)
@@ -258,7 +259,7 @@ public partial class GridHandler : LayoutHandler
{
var padding = paddable.Padding;
platformView.Padding = padding;
Console.WriteLine($"[GridHandler] Applied Padding: L={padding.Left}, T={padding.Top}, R={padding.Right}, B={padding.Bottom}");
DiagnosticLog.Debug("GridHandler", $"Applied Padding: L={padding.Left}, T={padding.Top}, R={padding.Right}, B={padding.Bottom}");
}
// Map row/column definitions first
@@ -271,7 +272,7 @@ public partial class GridHandler : LayoutHandler
var child = gridLayout[i];
if (child == null) continue;
Console.WriteLine($"[GridHandler] Processing child {i}: {child.GetType().Name}");
DiagnosticLog.Debug("GridHandler", $"Processing child {i}: {child.GetType().Name}");
// Create handler for child if it doesn't exist
if (child.Handler == null)
@@ -289,21 +290,20 @@ public partial class GridHandler : LayoutHandler
columnSpan = Microsoft.Maui.Controls.Grid.GetColumnSpan(mauiView);
}
Console.WriteLine($"[GridHandler] Child {i} at row={row}, col={column}, handler={child.Handler?.GetType().Name}");
DiagnosticLog.Debug("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");
DiagnosticLog.Debug("GridHandler", $"Added child {i} to grid");
}
}
Console.WriteLine($"[GridHandler] ConnectHandler complete");
DiagnosticLog.Debug("GridHandler", "ConnectHandler complete");
}
catch (Exception ex)
{
Console.WriteLine($"[GridHandler] EXCEPTION in ConnectHandler: {ex.GetType().Name}: {ex.Message}");
Console.WriteLine($"[GridHandler] Stack trace: {ex.StackTrace}");
DiagnosticLog.Error("GridHandler", $"EXCEPTION in ConnectHandler: {ex.GetType().Name}: {ex.Message}", ex);
throw;
}
}

View File

@@ -7,6 +7,7 @@ using Microsoft.Maui.Graphics;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using Microsoft.Maui.Platform.Linux.Hosting;
using Microsoft.Maui.Platform.Linux.Services;
using SkiaSharp;
using Svg.Skia;
using System.Collections.Specialized;
@@ -88,12 +89,12 @@ public partial class NavigationPageHandler : ViewHandler<NavigationPage, SkiaNav
// Get all pages in the navigation stack
var pages = VirtualView.Navigation.NavigationStack.ToList();
Console.WriteLine($"[NavigationPageHandler] Setting up {pages.Count} pages");
DiagnosticLog.Debug("NavigationPageHandler", $"Setting up {pages.Count} pages");
// 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}");
DiagnosticLog.Debug("NavigationPageHandler", $"No pages in stack, using CurrentPage: {VirtualView.CurrentPage.Title}");
pages.Add(VirtualView.CurrentPage);
}
@@ -102,12 +103,12 @@ public partial class NavigationPageHandler : ViewHandler<NavigationPage, SkiaNav
// Ensure the page has a handler
if (page.Handler == null)
{
Console.WriteLine($"[NavigationPageHandler] Creating handler for: {page.Title}");
DiagnosticLog.Debug("NavigationPageHandler", $"Creating handler for: {page.Title}");
page.Handler = page.ToViewHandler(MauiContext);
}
Console.WriteLine($"[NavigationPageHandler] Page handler type: {page.Handler?.GetType().Name}");
Console.WriteLine($"[NavigationPageHandler] Page PlatformView type: {page.Handler?.PlatformView?.GetType().Name}");
DiagnosticLog.Debug("NavigationPageHandler", $"Page handler type: {page.Handler?.GetType().Name}");
DiagnosticLog.Debug("NavigationPageHandler", $"Page PlatformView type: {page.Handler?.PlatformView?.GetType().Name}");
if (page.Handler?.PlatformView is SkiaPage skiaPage)
{
@@ -117,12 +118,12 @@ public partial class NavigationPageHandler : ViewHandler<NavigationPage, SkiaNav
skiaPage.TitleTextColor = PlatformView.BarTextColor;
skiaPage.Title = page.Title ?? "";
Console.WriteLine($"[NavigationPageHandler] SkiaPage content: {skiaPage.Content?.GetType().Name ?? "null"}");
DiagnosticLog.Debug("NavigationPageHandler", $"SkiaPage content: {skiaPage.Content?.GetType().Name ?? "null"}");
// 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}");
DiagnosticLog.Debug("NavigationPageHandler", $"Content is null, manually creating handler for: {contentPage.Content.GetType().Name}");
if (contentPage.Content.Handler == null)
{
contentPage.Content.Handler = contentPage.Content.ToViewHandler(MauiContext);
@@ -130,7 +131,7 @@ public partial class NavigationPageHandler : ViewHandler<NavigationPage, SkiaNav
if (contentPage.Content.Handler?.PlatformView is SkiaView skiaContent)
{
skiaPage.Content = skiaContent;
Console.WriteLine($"[NavigationPageHandler] Set content to: {skiaContent.GetType().Name}");
DiagnosticLog.Debug("NavigationPageHandler", $"Set content to: {skiaContent.GetType().Name}");
}
}
@@ -139,18 +140,18 @@ public partial class NavigationPageHandler : ViewHandler<NavigationPage, SkiaNav
if (PlatformView.StackDepth == 0)
{
Console.WriteLine($"[NavigationPageHandler] Setting root page: {page.Title}");
DiagnosticLog.Debug("NavigationPageHandler", $"Setting root page: {page.Title}");
PlatformView.SetRootPage(skiaPage);
}
else
{
Console.WriteLine($"[NavigationPageHandler] Pushing page: {page.Title}");
DiagnosticLog.Debug("NavigationPageHandler", $"Pushing page: {page.Title}");
PlatformView.Push(skiaPage, false);
}
}
else
{
Console.WriteLine($"[NavigationPageHandler] Failed to get SkiaPage for: {page.Title}");
DiagnosticLog.Warn("NavigationPageHandler", $"Failed to get SkiaPage for: {page.Title}");
}
}
}
@@ -161,12 +162,12 @@ public partial class NavigationPageHandler : ViewHandler<NavigationPage, SkiaNav
{
if (skiaPage is SkiaContentPage contentPage)
{
Console.WriteLine($"[NavigationPageHandler] MapToolbarItems for '{page.Title}', count={page.ToolbarItems.Count}");
DiagnosticLog.Debug("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}', IconImageSource={item.IconImageSource}, Order={item.Order}");
DiagnosticLog.Debug("NavigationPageHandler", $"Adding toolbar item: '{item.Text}', IconImageSource={item.IconImageSource}, 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
@@ -177,7 +178,7 @@ public partial class NavigationPageHandler : ViewHandler<NavigationPage, SkiaNav
var toolbarItem = item; // Capture for closure
var clickCommand = new RelayCommand(() =>
{
Console.WriteLine($"[NavigationPageHandler] ToolbarItem '{toolbarItem.Text}' clicked, invoking...");
DiagnosticLog.Debug("NavigationPageHandler", $"ToolbarItem '{toolbarItem.Text}' clicked, invoking...");
// Use IMenuItemController to send the click
if (toolbarItem is IMenuItemController menuController)
{
@@ -209,10 +210,10 @@ public partial class NavigationPageHandler : ViewHandler<NavigationPage, SkiaNav
// 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}'");
DiagnosticLog.Debug("NavigationPageHandler", $"Subscribing to ToolbarItems changes for '{page.Title}'");
notifyCollection.CollectionChanged += (s, e) =>
{
Console.WriteLine($"[NavigationPageHandler] ToolbarItems changed for '{page.Title}', action={e.Action}");
DiagnosticLog.Debug("NavigationPageHandler", $"ToolbarItems changed for '{page.Title}', action={e.Action}");
MapToolbarItems(skiaPage, page);
skiaPage.Invalidate();
};
@@ -229,9 +230,9 @@ public partial class NavigationPageHandler : ViewHandler<NavigationPage, SkiaNav
string pngPath = Path.Combine(baseDirectory, fileName);
string svgPath = Path.Combine(baseDirectory, Path.ChangeExtension(fileName, ".svg"));
Console.WriteLine($"[NavigationPageHandler] LoadToolbarIcon: Looking for {fileName}");
Console.WriteLine($"[NavigationPageHandler] Trying PNG: {pngPath} (exists: {File.Exists(pngPath)})");
Console.WriteLine($"[NavigationPageHandler] Trying SVG: {svgPath} (exists: {File.Exists(svgPath)})");
DiagnosticLog.Debug("NavigationPageHandler", $"LoadToolbarIcon: Looking for {fileName}");
DiagnosticLog.Debug("NavigationPageHandler", $" Trying PNG: {pngPath} (exists: {File.Exists(pngPath)})");
DiagnosticLog.Debug("NavigationPageHandler", $" Trying SVG: {svgPath} (exists: {File.Exists(svgPath)})");
// Try SVG first
if (File.Exists(svgPath))
@@ -247,7 +248,7 @@ public partial class NavigationPageHandler : ViewHandler<NavigationPage, SkiaNav
canvas.Clear(SKColors.Transparent);
canvas.Scale(scale);
canvas.DrawPicture(svg.Picture, null);
Console.WriteLine($"[NavigationPageHandler] Loaded SVG icon: {svgPath}");
DiagnosticLog.Debug("NavigationPageHandler", $"Loaded SVG icon: {svgPath}");
return bitmap;
}
}
@@ -257,16 +258,16 @@ public partial class NavigationPageHandler : ViewHandler<NavigationPage, SkiaNav
{
using var stream = File.OpenRead(pngPath);
var result = SKBitmap.Decode(stream);
Console.WriteLine($"[NavigationPageHandler] Loaded PNG icon: {pngPath}");
DiagnosticLog.Debug("NavigationPageHandler", $"Loaded PNG icon: {pngPath}");
return result;
}
Console.WriteLine($"[NavigationPageHandler] Icon not found: {fileName}");
DiagnosticLog.Warn("NavigationPageHandler", $"Icon not found: {fileName}");
return null;
}
catch (Exception ex)
{
Console.WriteLine($"[NavigationPageHandler] Error loading icon {fileName}: {ex.Message}");
DiagnosticLog.Error("NavigationPageHandler", $"Error loading icon {fileName}: {ex.Message}", ex);
return null;
}
}
@@ -275,20 +276,20 @@ public partial class NavigationPageHandler : ViewHandler<NavigationPage, SkiaNav
{
try
{
Console.WriteLine($"[NavigationPageHandler] VirtualView Pushed: {e.Page?.Title}");
DiagnosticLog.Debug("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}");
DiagnosticLog.Debug("NavigationPageHandler", $"Creating handler for page: {e.Page.GetType().Name}");
e.Page.Handler = e.Page.ToViewHandler(MauiContext);
Console.WriteLine($"[NavigationPageHandler] Handler created: {e.Page.Handler?.GetType().Name}");
DiagnosticLog.Debug("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"}");
DiagnosticLog.Debug("NavigationPageHandler", $"Setting up skiaPage, content: {skiaPage.Content?.GetType().Name ?? "null"}");
skiaPage.ShowNavigationBar = true;
skiaPage.TitleBarColor = PlatformView.BarBackgroundColor;
skiaPage.TitleTextColor = PlatformView.BarTextColor;
@@ -297,7 +298,7 @@ public partial class NavigationPageHandler : ViewHandler<NavigationPage, SkiaNav
// Handle content if null
if (skiaPage.Content == null && e.Page is ContentPage contentPage && contentPage.Content != null)
{
Console.WriteLine($"[NavigationPageHandler] Content is null, creating handler for: {contentPage.Content.GetType().Name}");
DiagnosticLog.Debug("NavigationPageHandler", $"Content is null, creating handler for: {contentPage.Content.GetType().Name}");
if (contentPage.Content.Handler == null)
{
contentPage.Content.Handler = contentPage.Content.ToViewHandler(MauiContext);
@@ -305,36 +306,35 @@ public partial class NavigationPageHandler : ViewHandler<NavigationPage, SkiaNav
if (contentPage.Content.Handler?.PlatformView is SkiaView skiaContent)
{
skiaPage.Content = skiaContent;
Console.WriteLine($"[NavigationPageHandler] Set content to: {skiaContent.GetType().Name}");
DiagnosticLog.Debug("NavigationPageHandler", $"Set content to: {skiaContent.GetType().Name}");
}
}
Console.WriteLine($"[NavigationPageHandler] Mapping toolbar items");
DiagnosticLog.Debug("NavigationPageHandler", "Mapping toolbar items");
MapToolbarItems(skiaPage, e.Page);
Console.WriteLine($"[NavigationPageHandler] Pushing page to platform");
DiagnosticLog.Debug("NavigationPageHandler", "Pushing page to platform");
PlatformView.Push(skiaPage, false);
Console.WriteLine($"[NavigationPageHandler] Push complete, thread={Environment.CurrentManagedThreadId}");
DiagnosticLog.Debug("NavigationPageHandler", $"Push complete, thread={Environment.CurrentManagedThreadId}");
}
Console.WriteLine("[NavigationPageHandler] OnVirtualViewPushed returning");
DiagnosticLog.Debug("NavigationPageHandler", "OnVirtualViewPushed returning");
}
catch (Exception ex)
{
Console.WriteLine($"[NavigationPageHandler] EXCEPTION in OnVirtualViewPushed: {ex.GetType().Name}: {ex.Message}");
Console.WriteLine($"[NavigationPageHandler] Stack trace: {ex.StackTrace}");
DiagnosticLog.Error("NavigationPageHandler", $"EXCEPTION in OnVirtualViewPushed: {ex.GetType().Name}: {ex.Message}", ex);
throw;
}
}
private void OnVirtualViewPopped(object? sender, Microsoft.Maui.Controls.NavigationEventArgs e)
{
Console.WriteLine($"[NavigationPageHandler] VirtualView Popped: {e.Page?.Title}");
DiagnosticLog.Debug("NavigationPageHandler", $"VirtualView Popped: {e.Page?.Title}");
// Pop on the platform side to sync with MAUI navigation
PlatformView?.Pop();
}
private void OnVirtualViewPoppedToRoot(object? sender, Microsoft.Maui.Controls.NavigationEventArgs e)
{
Console.WriteLine($"[NavigationPageHandler] VirtualView PoppedToRoot");
DiagnosticLog.Debug("NavigationPageHandler", "VirtualView PoppedToRoot");
PlatformView?.PopToRoot();
}
@@ -403,7 +403,7 @@ public partial class NavigationPageHandler : ViewHandler<NavigationPage, SkiaNav
if (handler.PlatformView is null || handler.MauiContext is null || args is not NavigationRequest request)
return;
Console.WriteLine($"[NavigationPageHandler] MapRequestNavigation: {request.NavigationStack.Count} pages");
DiagnosticLog.Debug("NavigationPageHandler", $"MapRequestNavigation: {request.NavigationStack.Count} pages");
// Handle navigation request
foreach (var view in request.NavigationStack)

View File

@@ -6,6 +6,7 @@ using Microsoft.Maui.Graphics;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using Microsoft.Maui.Platform.Linux.Hosting;
using Microsoft.Maui.Platform.Linux.Services;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
@@ -67,7 +68,7 @@ public partial class PageHandler : ViewHandler<Page, SkiaPage>
private void OnAppearing(object? sender, EventArgs e)
{
Console.WriteLine($"[PageHandler] OnAppearing received for: {VirtualView?.Title}");
DiagnosticLog.Debug("PageHandler", $"OnAppearing received for: {VirtualView?.Title}");
(VirtualView as IPageController)?.SendAppearing();
}
@@ -118,7 +119,7 @@ public partial class PageHandler : ViewHandler<Page, SkiaPage>
if (backgroundColor != null && backgroundColor != Colors.Transparent)
{
handler.PlatformView.BackgroundColor = backgroundColor;
Console.WriteLine($"[PageHandler] MapBackgroundColor: {backgroundColor}");
DiagnosticLog.Debug("PageHandler", $"MapBackgroundColor: {backgroundColor}");
}
}
@@ -189,19 +190,19 @@ public partial class ContentPageHandler : PageHandler
// Create handler for content if it doesn't exist
if (content.Handler == null)
{
Console.WriteLine($"[ContentPageHandler] Creating handler for content: {content.GetType().Name}");
DiagnosticLog.Debug("ContentPageHandler", $"Creating handler for content: {content.GetType().Name}");
content.Handler = content.ToViewHandler(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}");
DiagnosticLog.Debug("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"}");
DiagnosticLog.Warn("ContentPageHandler", $"Content handler PlatformView is not SkiaView: {content.Handler?.PlatformView?.GetType().Name ?? "null"}");
}
}
else
@@ -235,7 +236,7 @@ public partial class ContentPageHandler : PageHandler
if (item.IconImageSource is FileImageSource fileSource)
{
// Icon loading would be async - simplified for now
Console.WriteLine($"[ContentPageHandler] Toolbar item icon: {fileSource.File}");
DiagnosticLog.Debug("ContentPageHandler", $"Toolbar item icon: {fileSource.File}");
}
platformView.ToolbarItems.Add(skiaItem);

View File

@@ -3,6 +3,7 @@
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform.Linux.Hosting;
using Microsoft.Maui.Platform.Linux.Services;
namespace Microsoft.Maui.Platform.Linux.Handlers;
@@ -48,7 +49,7 @@ public partial class ScrollViewHandler : ViewHandler<IScrollView, SkiaScrollView
var content = scrollView.PresentedContent;
if (content != null)
{
Console.WriteLine($"[ScrollViewHandler] MapContent: {content.GetType().Name}");
DiagnosticLog.Debug("ScrollViewHandler", $"MapContent: {content.GetType().Name}");
// Create handler for content if it doesn't exist
if (content.Handler == null)
@@ -58,7 +59,7 @@ public partial class ScrollViewHandler : ViewHandler<IScrollView, SkiaScrollView
if (content.Handler?.PlatformView is SkiaView skiaContent)
{
Console.WriteLine($"[ScrollViewHandler] Setting content: {skiaContent.GetType().Name}");
DiagnosticLog.Debug("ScrollViewHandler", $"Setting content: {skiaContent.GetType().Name}");
handler.PlatformView.Content = skiaContent;
}
}

View File

@@ -5,6 +5,7 @@ using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Platform.Linux.Hosting;
using Microsoft.Maui.Platform.Linux.Services;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
@@ -48,13 +49,13 @@ public partial class ShellHandler : ViewHandler<Shell, SkiaShell>
protected override SkiaShell CreatePlatformView()
{
Console.WriteLine("[ShellHandler] CreatePlatformView - creating SkiaShell");
DiagnosticLog.Debug("ShellHandler", "CreatePlatformView - creating SkiaShell");
return new SkiaShell();
}
protected override void ConnectHandler(SkiaShell platformView)
{
Console.WriteLine("[ShellHandler] ConnectHandler - connecting to SkiaShell");
DiagnosticLog.Debug("ShellHandler", "ConnectHandler - connecting to SkiaShell");
base.ConnectHandler(platformView);
platformView.FlyoutIsPresentedChanged += OnFlyoutIsPresentedChanged;
platformView.Navigated += OnNavigated;
@@ -116,20 +117,20 @@ public partial class ShellHandler : ViewHandler<Shell, SkiaShell>
private void OnShellNavigating(object? sender, ShellNavigatingEventArgs e)
{
Console.WriteLine($"[ShellHandler] Shell Navigating to: {e.Target?.Location}");
DiagnosticLog.Debug("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}");
DiagnosticLog.Debug("ShellHandler", $"Routing to: {route}");
PlatformView.GoToAsync(route);
}
}
private void OnShellNavigated(object? sender, ShellNavigatedEventArgs e)
{
Console.WriteLine($"[ShellHandler] Shell Navigated to: {e.Current?.Location}");
DiagnosticLog.Debug("ShellHandler", $"Shell Navigated to: {e.Current?.Location}");
}
private void SyncShellItems()
@@ -230,7 +231,7 @@ public partial class ShellHandler : ViewHandler<Shell, SkiaShell>
}
catch (Exception ex)
{
Console.WriteLine($"[ShellHandler] Error rendering content: {ex.Message}");
DiagnosticLog.Error("ShellHandler", $"Error rendering content: {ex.Message}", ex);
}
return null;

View File

@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform.Linux.Services;
namespace Microsoft.Maui.Platform;
@@ -47,7 +48,7 @@ public partial class WebViewHandler : ViewHandler<IWebView, LinuxWebView>
protected override LinuxWebView CreatePlatformView()
{
Console.WriteLine("[WebViewHandler] Creating LinuxWebView");
DiagnosticLog.Debug("WebViewHandler", "Creating LinuxWebView");
return new LinuxWebView();
}
@@ -65,7 +66,7 @@ public partial class WebViewHandler : ViewHandler<IWebView, LinuxWebView>
MapUserAgent(this, VirtualView);
}
Console.WriteLine("[WebViewHandler] Handler connected");
DiagnosticLog.Debug("WebViewHandler", "Handler connected");
}
protected override void DisconnectHandler(LinuxWebView platformView)
@@ -74,7 +75,7 @@ public partial class WebViewHandler : ViewHandler<IWebView, LinuxWebView>
platformView.Navigated -= OnNavigated;
base.DisconnectHandler(platformView);
Console.WriteLine("[WebViewHandler] Handler disconnected");
DiagnosticLog.Debug("WebViewHandler", "Handler disconnected");
}
private void OnNavigating(object? sender, WebViewNavigatingEventArgs e)
@@ -104,7 +105,7 @@ public partial class WebViewHandler : ViewHandler<IWebView, LinuxWebView>
if (source == null)
return;
Console.WriteLine($"[WebViewHandler] MapSource: {source.GetType().Name}");
DiagnosticLog.Debug("WebViewHandler", $"MapSource: {source.GetType().Name}");
if (source is IUrlWebViewSource urlSource && !string.IsNullOrEmpty(urlSource.Url))
{
@@ -121,7 +122,7 @@ public partial class WebViewHandler : ViewHandler<IWebView, LinuxWebView>
if (handler.PlatformView != null && !string.IsNullOrEmpty(webView.UserAgent))
{
handler.PlatformView.UserAgent = webView.UserAgent;
Console.WriteLine($"[WebViewHandler] MapUserAgent: {webView.UserAgent}");
DiagnosticLog.Debug("WebViewHandler", $"MapUserAgent: {webView.UserAgent}");
}
}
@@ -134,7 +135,7 @@ public partial class WebViewHandler : ViewHandler<IWebView, LinuxWebView>
if (handler.PlatformView?.CanGoBack == true)
{
handler.PlatformView.GoBack();
Console.WriteLine("[WebViewHandler] GoBack");
DiagnosticLog.Debug("WebViewHandler", "GoBack");
}
}
@@ -143,14 +144,14 @@ public partial class WebViewHandler : ViewHandler<IWebView, LinuxWebView>
if (handler.PlatformView?.CanGoForward == true)
{
handler.PlatformView.GoForward();
Console.WriteLine("[WebViewHandler] GoForward");
DiagnosticLog.Debug("WebViewHandler", "GoForward");
}
}
public static void MapReload(WebViewHandler handler, IWebView webView, object? args)
{
handler.PlatformView?.Reload();
Console.WriteLine("[WebViewHandler] Reload");
DiagnosticLog.Debug("WebViewHandler", "Reload");
}
public static void MapEval(WebViewHandler handler, IWebView webView, object? args)
@@ -158,7 +159,7 @@ public partial class WebViewHandler : ViewHandler<IWebView, LinuxWebView>
if (args is string script)
{
handler.PlatformView?.Eval(script);
Console.WriteLine($"[WebViewHandler] Eval: {script.Substring(0, Math.Min(50, script.Length))}...");
DiagnosticLog.Debug("WebViewHandler", $"Eval: {script.Substring(0, Math.Min(50, script.Length))}...");
}
}
@@ -178,7 +179,7 @@ public partial class WebViewHandler : ViewHandler<IWebView, LinuxWebView>
{
request.SetResult(null);
}
Console.WriteLine($"[WebViewHandler] EvaluateJavaScriptAsync: {request.Script.Substring(0, Math.Min(50, request.Script.Length))}...");
DiagnosticLog.Debug("WebViewHandler", $"EvaluateJavaScriptAsync: {request.Script.Substring(0, Math.Min(50, request.Script.Length))}...");
}
}

View File

@@ -4,6 +4,7 @@
using Microsoft.Maui.Controls;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform;
using Microsoft.Maui.Platform.Linux.Services;
namespace Microsoft.Maui.Platform.Linux.Handlers;
@@ -89,30 +90,30 @@ public partial class WebViewHandler : ViewHandler<IWebView, SkiaWebView>
public static void MapSource(WebViewHandler handler, IWebView webView)
{
Console.WriteLine("[WebViewHandler] MapSource called");
DiagnosticLog.Debug("WebViewHandler", "MapSource called");
if (handler.PlatformView == null)
{
Console.WriteLine("[WebViewHandler] PlatformView is null!");
DiagnosticLog.Warn("WebViewHandler", "PlatformView is null!");
return;
}
var source = webView.Source;
Console.WriteLine($"[WebViewHandler] Source type: {source?.GetType().Name ?? "null"}");
DiagnosticLog.Debug("WebViewHandler", $"Source type: {source?.GetType().Name ?? "null"}");
if (source is UrlWebViewSource urlSource)
{
Console.WriteLine($"[WebViewHandler] Loading URL: {urlSource.Url}");
DiagnosticLog.Debug("WebViewHandler", $"Loading URL: {urlSource.Url}");
handler.PlatformView.Source = urlSource.Url ?? "";
}
else if (source is HtmlWebViewSource htmlSource)
{
Console.WriteLine($"[WebViewHandler] Loading HTML ({htmlSource.Html?.Length ?? 0} chars)");
Console.WriteLine($"[WebViewHandler] HTML preview: {htmlSource.Html?.Substring(0, Math.Min(100, htmlSource.Html?.Length ?? 0))}...");
DiagnosticLog.Debug("WebViewHandler", $"Loading HTML ({htmlSource.Html?.Length ?? 0} chars)");
DiagnosticLog.Debug("WebViewHandler", $"HTML preview: {htmlSource.Html?.Substring(0, Math.Min(100, htmlSource.Html?.Length ?? 0))}...");
handler.PlatformView.Html = htmlSource.Html ?? "";
}
else
{
Console.WriteLine("[WebViewHandler] Unknown source type or null");
DiagnosticLog.Debug("WebViewHandler", "Unknown source type or null");
}
}

View File

@@ -5,6 +5,7 @@ using Microsoft.Maui.Handlers;
using Microsoft.Maui.Graphics;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Platform;
using Microsoft.Maui.Platform.Linux.Services;
using SkiaSharp;
namespace Microsoft.Maui.Platform.Linux.Handlers;
@@ -81,19 +82,19 @@ public partial class WindowHandler : ElementHandler<IWindow, SkiaWindow>
public static void MapContent(WindowHandler handler, IWindow window)
{
Console.Error.WriteLine($"[WindowHandler] MapContent - PlatformView={handler.PlatformView != null}");
DiagnosticLog.Debug("WindowHandler", $"MapContent - PlatformView={handler.PlatformView != null}");
if (handler.PlatformView is null) return;
var content = window.Content;
Console.Error.WriteLine($"[WindowHandler] MapContent - content type={content?.GetType().Name}, handler={content?.Handler?.GetType().Name}");
DiagnosticLog.Debug("WindowHandler", $"MapContent - content type={content?.GetType().Name}, handler={content?.Handler?.GetType().Name}");
if (content?.Handler?.PlatformView is SkiaView skiaContent)
{
Console.Error.WriteLine($"[WindowHandler] MapContent - setting SkiaView content: {skiaContent.GetType().Name}");
DiagnosticLog.Debug("WindowHandler", $"MapContent - setting SkiaView content: {skiaContent.GetType().Name}");
handler.PlatformView.Content = skiaContent;
}
else
{
Console.Error.WriteLine($"[WindowHandler] MapContent - content has no SkiaView! Handler={content?.Handler}, PlatformView={content?.Handler?.PlatformView}");
DiagnosticLog.Warn("WindowHandler", $"MapContent - content has no SkiaView! Handler={content?.Handler}, PlatformView={content?.Handler?.PlatformView}");
}
}