Initial start
This commit is contained in:
@@ -27,22 +27,9 @@ public class GtkWebViewProxy : SkiaView
|
|||||||
public override void Arrange(SKRect bounds)
|
public override void Arrange(SKRect bounds)
|
||||||
{
|
{
|
||||||
base.Arrange(bounds);
|
base.Arrange(bounds);
|
||||||
var windowBounds = TransformToWindow(bounds);
|
// Bounds are already in absolute window coordinates - use them directly
|
||||||
_handler.RegisterWithHost(windowBounds);
|
// The Skia layout system uses absolute coordinates throughout
|
||||||
}
|
_handler.RegisterWithHost(Bounds);
|
||||||
|
|
||||||
private SKRect TransformToWindow(SKRect localBounds)
|
|
||||||
{
|
|
||||||
float x = localBounds.Left;
|
|
||||||
float y = localBounds.Top;
|
|
||||||
|
|
||||||
for (var parent = Parent; parent != null; parent = parent.Parent)
|
|
||||||
{
|
|
||||||
x += parent.Bounds.Left;
|
|
||||||
y += parent.Bounds.Top;
|
|
||||||
}
|
|
||||||
|
|
||||||
return new SKRect(x, y, x + localBounds.Width, y + localBounds.Height);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Draw(SKCanvas canvas)
|
public override void Draw(SKCanvas canvas)
|
||||||
|
|||||||
@@ -25,6 +25,8 @@ public partial class ImageButtonHandler : ViewHandler<IImageButton, SkiaImageBut
|
|||||||
[nameof(IPadding.Padding)] = MapPadding,
|
[nameof(IPadding.Padding)] = MapPadding,
|
||||||
[nameof(IView.Background)] = MapBackground,
|
[nameof(IView.Background)] = MapBackground,
|
||||||
["BackgroundColor"] = MapBackgroundColor,
|
["BackgroundColor"] = MapBackgroundColor,
|
||||||
|
[nameof(IView.Width)] = MapWidth,
|
||||||
|
[nameof(IView.Height)] = MapHeight,
|
||||||
};
|
};
|
||||||
|
|
||||||
public static CommandMapper<IImageButton, ImageButtonHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
|
public static CommandMapper<IImageButton, ImageButtonHandler> CommandMapper = new(ViewHandler.ViewCommandMapper)
|
||||||
@@ -165,6 +167,28 @@ public partial class ImageButtonHandler : ViewHandler<IImageButton, SkiaImageBut
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void MapWidth(ImageButtonHandler handler, IImageButton imageButton)
|
||||||
|
{
|
||||||
|
if (handler.PlatformView is null) return;
|
||||||
|
|
||||||
|
// Map WidthRequest from the MAUI ImageButton to the platform view
|
||||||
|
if (imageButton is Microsoft.Maui.Controls.ImageButton imgBtn && imgBtn.WidthRequest > 0)
|
||||||
|
{
|
||||||
|
handler.PlatformView.WidthRequest = imgBtn.WidthRequest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void MapHeight(ImageButtonHandler handler, IImageButton imageButton)
|
||||||
|
{
|
||||||
|
if (handler.PlatformView is null) return;
|
||||||
|
|
||||||
|
// Map HeightRequest from the MAUI ImageButton to the platform view
|
||||||
|
if (imageButton is Microsoft.Maui.Controls.ImageButton imgBtn && imgBtn.HeightRequest > 0)
|
||||||
|
{
|
||||||
|
handler.PlatformView.HeightRequest = imgBtn.HeightRequest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Image source loading helper
|
// Image source loading helper
|
||||||
private ImageSourceServiceResultManager _sourceLoader = null!;
|
private ImageSourceServiceResultManager _sourceLoader = null!;
|
||||||
|
|
||||||
|
|||||||
@@ -219,6 +219,21 @@ public class LinuxApplication : IDisposable
|
|||||||
/// <param name="configure">Optional configuration action.</param>
|
/// <param name="configure">Optional configuration action.</param>
|
||||||
public static void Run(MauiApp app, string[] args, Action<LinuxApplicationOptions>? configure)
|
public static void Run(MauiApp app, string[] args, Action<LinuxApplicationOptions>? configure)
|
||||||
{
|
{
|
||||||
|
// Force X11 backend for GTK/WebKitGTK - MUST be set before any GTK code runs
|
||||||
|
Environment.SetEnvironmentVariable("GDK_BACKEND", "x11");
|
||||||
|
|
||||||
|
// Pre-initialize GTK for WebView compatibility (even when using X11 mode)
|
||||||
|
int argc = 0;
|
||||||
|
IntPtr argv = IntPtr.Zero;
|
||||||
|
if (!GtkNative.gtk_init_check(ref argc, ref argv))
|
||||||
|
{
|
||||||
|
Console.WriteLine("[LinuxApplication] Warning: GTK initialization failed - WebView may not work");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine("[LinuxApplication] GTK pre-initialized for WebView support");
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize dispatcher
|
// Initialize dispatcher
|
||||||
LinuxDispatcher.Initialize();
|
LinuxDispatcher.Initialize();
|
||||||
DispatcherProvider.SetCurrent(LinuxDispatcherProvider.Instance);
|
DispatcherProvider.SetCurrent(LinuxDispatcherProvider.Instance);
|
||||||
|
|||||||
@@ -433,6 +433,51 @@ public class SkiaImage : SkiaView
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override SKRect ArrangeOverride(SKRect bounds)
|
||||||
|
{
|
||||||
|
// If we have explicit size requests, constrain to desired size
|
||||||
|
// This follows MAUI standard behavior - controls respect WidthRequest/HeightRequest
|
||||||
|
var desiredWidth = DesiredSize.Width;
|
||||||
|
var desiredHeight = DesiredSize.Height;
|
||||||
|
|
||||||
|
// If desired size is smaller than available bounds, align within bounds
|
||||||
|
if (desiredWidth > 0 && desiredHeight > 0 &&
|
||||||
|
(desiredWidth < bounds.Width || desiredHeight < bounds.Height))
|
||||||
|
{
|
||||||
|
float finalWidth = Math.Min(desiredWidth, bounds.Width);
|
||||||
|
float finalHeight = Math.Min(desiredHeight, bounds.Height);
|
||||||
|
|
||||||
|
// Calculate position based on HorizontalOptions
|
||||||
|
// LayoutAlignment: Start=0, Center=1, End=2, Fill=3
|
||||||
|
float x = bounds.Left;
|
||||||
|
var hAlignValue = (int)HorizontalOptions.Alignment;
|
||||||
|
if (hAlignValue == 1) // Center
|
||||||
|
{
|
||||||
|
x = bounds.Left + (bounds.Width - finalWidth) / 2;
|
||||||
|
}
|
||||||
|
else if (hAlignValue == 2) // End
|
||||||
|
{
|
||||||
|
x = bounds.Right - finalWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate position based on VerticalOptions
|
||||||
|
float y = bounds.Top;
|
||||||
|
var vAlignValue = (int)VerticalOptions.Alignment;
|
||||||
|
if (vAlignValue == 1) // Center
|
||||||
|
{
|
||||||
|
y = bounds.Top + (bounds.Height - finalHeight) / 2;
|
||||||
|
}
|
||||||
|
else if (vAlignValue == 2) // End
|
||||||
|
{
|
||||||
|
y = bounds.Bottom - finalHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new SKRect(x, y, x + finalWidth, y + finalHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
protected override SKSize MeasureOverride(SKSize availableSize)
|
protected override SKSize MeasureOverride(SKSize availableSize)
|
||||||
{
|
{
|
||||||
double widthRequest = base.WidthRequest;
|
double widthRequest = base.WidthRequest;
|
||||||
|
|||||||
@@ -269,12 +269,14 @@ public class SkiaImageButton : SkiaView
|
|||||||
bool hasWidth = WidthRequest > 0;
|
bool hasWidth = WidthRequest > 0;
|
||||||
bool hasHeight = HeightRequest > 0;
|
bool hasHeight = HeightRequest > 0;
|
||||||
|
|
||||||
|
// Default to 24x24 for icons when no size specified
|
||||||
|
const float DefaultIconSize = 24f;
|
||||||
float targetWidth = hasWidth
|
float targetWidth = hasWidth
|
||||||
? (float)(WidthRequest - PaddingLeft - PaddingRight)
|
? (float)(WidthRequest - PaddingLeft - PaddingRight)
|
||||||
: cullRect.Width;
|
: DefaultIconSize;
|
||||||
float targetHeight = hasHeight
|
float targetHeight = hasHeight
|
||||||
? (float)(HeightRequest - PaddingTop - PaddingBottom)
|
? (float)(HeightRequest - PaddingTop - PaddingBottom)
|
||||||
: cullRect.Height;
|
: DefaultIconSize;
|
||||||
|
|
||||||
float scale = Math.Min(targetWidth / cullRect.Width, targetHeight / cullRect.Height);
|
float scale = Math.Min(targetWidth / cullRect.Width, targetHeight / cullRect.Height);
|
||||||
int width = Math.Max(1, (int)(cullRect.Width * scale));
|
int width = Math.Max(1, (int)(cullRect.Width * scale));
|
||||||
@@ -472,6 +474,29 @@ public class SkiaImageButton : SkiaView
|
|||||||
|
|
||||||
protected override SKSize MeasureOverride(SKSize availableSize)
|
protected override SKSize MeasureOverride(SKSize availableSize)
|
||||||
{
|
{
|
||||||
|
// Respect explicit WidthRequest/HeightRequest first (MAUI standard behavior)
|
||||||
|
if (WidthRequest > 0 && HeightRequest > 0)
|
||||||
|
{
|
||||||
|
return new SKSize((float)WidthRequest, (float)HeightRequest);
|
||||||
|
}
|
||||||
|
if (WidthRequest > 0)
|
||||||
|
{
|
||||||
|
// Fixed width, calculate height from aspect ratio or use width
|
||||||
|
float height = HeightRequest > 0 ? (float)HeightRequest
|
||||||
|
: _image != null ? (float)WidthRequest * _image.Height / _image.Width
|
||||||
|
: (float)WidthRequest;
|
||||||
|
return new SKSize((float)WidthRequest, height);
|
||||||
|
}
|
||||||
|
if (HeightRequest > 0)
|
||||||
|
{
|
||||||
|
// Fixed height, calculate width from aspect ratio or use height
|
||||||
|
float width = WidthRequest > 0 ? (float)WidthRequest
|
||||||
|
: _image != null ? (float)HeightRequest * _image.Width / _image.Height
|
||||||
|
: (float)HeightRequest;
|
||||||
|
return new SKSize(width, (float)HeightRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
// No explicit size - calculate from content
|
||||||
var padding = new SKSize(PaddingLeft + PaddingRight, PaddingTop + PaddingBottom);
|
var padding = new SKSize(PaddingLeft + PaddingRight, PaddingTop + PaddingBottom);
|
||||||
|
|
||||||
if (_image == null)
|
if (_image == null)
|
||||||
@@ -504,6 +529,53 @@ public class SkiaImageButton : SkiaView
|
|||||||
return new SKSize(imageWidth + padding.Width, imageHeight + padding.Height);
|
return new SKSize(imageWidth + padding.Width, imageHeight + padding.Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override SKRect ArrangeOverride(SKRect bounds)
|
||||||
|
{
|
||||||
|
// If we have explicit size requests, constrain to desired size
|
||||||
|
// This follows MAUI standard behavior - controls respect WidthRequest/HeightRequest
|
||||||
|
var desiredWidth = DesiredSize.Width;
|
||||||
|
var desiredHeight = DesiredSize.Height;
|
||||||
|
|
||||||
|
// If desired size is smaller than available bounds, align within bounds
|
||||||
|
if (desiredWidth > 0 && desiredHeight > 0 &&
|
||||||
|
(desiredWidth < bounds.Width || desiredHeight < bounds.Height))
|
||||||
|
{
|
||||||
|
float finalWidth = Math.Min(desiredWidth, bounds.Width);
|
||||||
|
float finalHeight = Math.Min(desiredHeight, bounds.Height);
|
||||||
|
|
||||||
|
// Calculate position based on HorizontalOptions
|
||||||
|
// LayoutAlignment: Start=0, Center=1, End=2, Fill=3
|
||||||
|
float x = bounds.Left;
|
||||||
|
var hAlignValue = (int)HorizontalOptions.Alignment;
|
||||||
|
if (hAlignValue == 1) // Center
|
||||||
|
{
|
||||||
|
x = bounds.Left + (bounds.Width - finalWidth) / 2;
|
||||||
|
}
|
||||||
|
else if (hAlignValue == 2) // End
|
||||||
|
{
|
||||||
|
x = bounds.Right - finalWidth;
|
||||||
|
}
|
||||||
|
// Fill (3) and Start (0) both use x = bounds.Left
|
||||||
|
|
||||||
|
// Calculate position based on VerticalOptions
|
||||||
|
float y = bounds.Top;
|
||||||
|
var vAlignValue = (int)VerticalOptions.Alignment;
|
||||||
|
if (vAlignValue == 1) // Center
|
||||||
|
{
|
||||||
|
y = bounds.Top + (bounds.Height - finalHeight) / 2;
|
||||||
|
}
|
||||||
|
else if (vAlignValue == 2) // End
|
||||||
|
{
|
||||||
|
y = bounds.Bottom - finalHeight;
|
||||||
|
}
|
||||||
|
// Fill (3) and Start (0) both use y = bounds.Top
|
||||||
|
|
||||||
|
return new SKRect(x, y, x + finalWidth, y + finalHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
|
|||||||
Reference in New Issue
Block a user