зеркало из https://github.com/AvaloniaUI/Avalonia.git
Merge branch 'master' into fixes/1178-rendering-artifacts
This commit is contained in:
Коммит
1888b04ee2
|
@ -170,6 +170,15 @@ namespace Avalonia.Controls
|
|||
}
|
||||
}
|
||||
|
||||
if (Orientation == Orientation.Vertical)
|
||||
{
|
||||
measuredHeight -= gap;
|
||||
}
|
||||
else
|
||||
{
|
||||
measuredWidth -= gap;
|
||||
}
|
||||
|
||||
return new Size(measuredWidth, measuredHeight);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ using System.Text;
|
|||
using System.Threading.Tasks;
|
||||
using Avalonia.Controls.Platform.Surfaces;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Threading;
|
||||
|
||||
namespace Avalonia.Gtk3
|
||||
{
|
||||
|
@ -27,7 +28,38 @@ namespace Avalonia.Gtk3
|
|||
var s = _window.ClientSize;
|
||||
var width = (int) s.Width;
|
||||
var height = (int) s.Height;
|
||||
|
||||
if (!Dispatcher.UIThread.CheckAccess() && Gtk3Platform.DisplayClassName.ToLower().Contains("x11"))
|
||||
{
|
||||
var x11 = LockX11Framebuffer(width, height);
|
||||
if (x11 != null)
|
||||
return x11;
|
||||
}
|
||||
|
||||
|
||||
return new ImageSurfaceFramebuffer(_window, width, height, _window.LastKnownScaleFactor);
|
||||
}
|
||||
|
||||
private static int X11ErrorHandler(IntPtr d, IntPtr e)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static X11.XErrorHandler X11ErrorHandlerDelegate = X11ErrorHandler;
|
||||
|
||||
private static IntPtr X11Display;
|
||||
private ILockedFramebuffer LockX11Framebuffer(int width, int height)
|
||||
{
|
||||
if (!_window.GdkWindowHandle.HasValue)
|
||||
return null;
|
||||
if (X11Display == IntPtr.Zero)
|
||||
{
|
||||
X11Display = X11.XOpenDisplay(IntPtr.Zero);
|
||||
if (X11Display == IntPtr.Zero)
|
||||
return null;
|
||||
X11.XSetErrorHandler(X11ErrorHandlerDelegate);
|
||||
}
|
||||
return new X11Framebuffer(X11Display, _window.GdkWindowHandle.Value, width, height, _window.LastKnownScaleFactor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -22,11 +23,15 @@ namespace Avalonia.Gtk3
|
|||
internal static readonly MouseDevice Mouse = new MouseDevice();
|
||||
internal static readonly KeyboardDevice Keyboard = new KeyboardDevice();
|
||||
internal static IntPtr App { get; set; }
|
||||
internal static string DisplayClassName;
|
||||
public static bool UseDeferredRendering = true;
|
||||
public static void Initialize()
|
||||
{
|
||||
Resolver.Resolve();
|
||||
Native.GtkInit(0, IntPtr.Zero);
|
||||
var disp = Native.GdkGetDefaultDisplay();
|
||||
DisplayClassName = Utf8Buffer.StringFromPtr(Native.GTypeName(Marshal.ReadIntPtr(Marshal.ReadIntPtr(disp))));
|
||||
|
||||
using (var utf = new Utf8Buffer("avalonia.app." + Guid.NewGuid()))
|
||||
App = Native.GtkApplicationNew(utf, 0);
|
||||
//Mark current thread as UI thread
|
||||
|
|
|
@ -318,6 +318,9 @@ namespace Avalonia.Gtk3.Interop
|
|||
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gobject)]
|
||||
public delegate void g_object_ref(GObject instance);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gobject)]
|
||||
public delegate IntPtr g_type_name(IntPtr instance);
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gobject)]
|
||||
public delegate ulong g_signal_connect_object(GObject instance, Utf8Buffer signal, IntPtr handler, IntPtr userData, int flags);
|
||||
|
||||
|
@ -410,6 +413,7 @@ namespace Avalonia.Gtk3.Interop
|
|||
public static D.gtk_dialog_add_button GtkDialogAddButton;
|
||||
public static D.g_object_unref GObjectUnref;
|
||||
public static D.g_object_ref GObjectRef;
|
||||
public static D.g_type_name GTypeName;
|
||||
public static D.g_signal_connect_object GSignalConnectObject;
|
||||
public static D.g_signal_handler_disconnect GSignalHandlerDisconnect;
|
||||
public static D.g_timeout_add GTimeoutAdd;
|
||||
|
|
|
@ -31,7 +31,7 @@ namespace Avalonia.Gtk3
|
|||
private object _lock = new object();
|
||||
private IDeferredRenderOperation _nextRenderOperation;
|
||||
private readonly AutoResetEvent _canSetNextOperation = new AutoResetEvent(true);
|
||||
|
||||
internal IntPtr? GdkWindowHandle;
|
||||
public WindowBaseImpl(GtkWindow gtkWidget)
|
||||
{
|
||||
|
||||
|
@ -55,6 +55,7 @@ namespace Avalonia.Gtk3
|
|||
ConnectEvent("leave-notify-event", OnLeaveNotifyEvent);
|
||||
Connect<Native.D.signal_generic>("destroy", OnDestroy);
|
||||
Native.GtkWidgetRealize(gtkWidget);
|
||||
GdkWindowHandle = this.Handle.Handle;
|
||||
_lastSize = ClientSize;
|
||||
if (Gtk3Platform.UseDeferredRendering)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Avalonia.Gtk3
|
||||
{
|
||||
class X11
|
||||
{
|
||||
[DllImport("libX11.so.6")]
|
||||
public static extern IntPtr XOpenDisplay(IntPtr name);
|
||||
|
||||
[DllImport("libX11.so.6")]
|
||||
public static extern IntPtr XFreeGC(IntPtr display, IntPtr gc);
|
||||
|
||||
[DllImport("libX11.so.6")]
|
||||
public static extern IntPtr XCreateGC(IntPtr display, IntPtr drawable, ulong valuemask, IntPtr values);
|
||||
|
||||
[DllImport("libX11.so.6")]
|
||||
public static extern int XInitImage(ref XImage image);
|
||||
|
||||
[DllImport("libX11.so.6")]
|
||||
public static extern int XDestroyImage(ref XImage image);
|
||||
|
||||
[DllImport("libX11.so.6")]
|
||||
public static extern IntPtr XSetErrorHandler(XErrorHandler handler);
|
||||
|
||||
public delegate int XErrorHandler(IntPtr display, IntPtr error);
|
||||
|
||||
[DllImport("libX11.so.6")]
|
||||
public static extern int XPutImage(IntPtr display, IntPtr drawable, IntPtr gc, ref XImage image,
|
||||
int srcx, int srcy, int destx, int desty, uint width, uint height);
|
||||
|
||||
|
||||
public unsafe struct XImage
|
||||
{
|
||||
public int width, height; /* size of image */
|
||||
public int xoffset; /* number of pixels offset in X direction */
|
||||
public int format; /* XYBitmap, XYPixmap, ZPixmap */
|
||||
public IntPtr data; /* pointer to image data */
|
||||
public int byte_order; /* data byte order, LSBFirst, MSBFirst */
|
||||
public int bitmap_unit; /* quant. of scanline 8, 16, 32 */
|
||||
public int bitmap_bit_order; /* LSBFirst, MSBFirst */
|
||||
public int bitmap_pad; /* 8, 16, 32 either XY or ZPixmap */
|
||||
public int depth; /* depth of image */
|
||||
public int bytes_per_line; /* accelerator to next scanline */
|
||||
public int bits_per_pixel; /* bits per pixel (ZPixmap) */
|
||||
public ulong red_mask; /* bits in z arrangement */
|
||||
public ulong green_mask;
|
||||
public ulong blue_mask;
|
||||
private fixed byte funcs[128];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using Avalonia.Platform;
|
||||
|
||||
namespace Avalonia.Gtk3
|
||||
{
|
||||
class X11Framebuffer : ILockedFramebuffer
|
||||
{
|
||||
private readonly IntPtr _display;
|
||||
private readonly IntPtr _xid;
|
||||
private IUnmanagedBlob _blob;
|
||||
|
||||
public X11Framebuffer(IntPtr display, IntPtr xid, int width, int height, int factor)
|
||||
{
|
||||
_display = display;
|
||||
_xid = xid;
|
||||
Width = width*factor;
|
||||
Height = height*factor;
|
||||
RowBytes = Width * 4;
|
||||
Dpi = new Vector(96, 96) * factor;
|
||||
Format = PixelFormat.Bgra8888;
|
||||
_blob = AvaloniaLocator.Current.GetService<IRuntimePlatform>().AllocBlob(RowBytes * Height);
|
||||
Address = _blob.Address;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
var image = new X11.XImage();
|
||||
int bitsPerPixel = 32;
|
||||
image.width = Width;
|
||||
image.height = Height;
|
||||
image.format = 2; //ZPixmap;
|
||||
image.data = Address;
|
||||
image.byte_order = 0;// LSBFirst;
|
||||
image.bitmap_unit = bitsPerPixel;
|
||||
image.bitmap_bit_order = 0;// LSBFirst;
|
||||
image.bitmap_pad = bitsPerPixel;
|
||||
image.depth = 24;
|
||||
image.bytes_per_line = RowBytes - Width * 4;
|
||||
image.bits_per_pixel = bitsPerPixel;
|
||||
X11.XInitImage(ref image);
|
||||
var gc = X11.XCreateGC(_display, _xid, 0, IntPtr.Zero);
|
||||
X11.XPutImage(_display, _xid, gc, ref image, 0, 0, 0, 0, (uint) Width, (uint) Height);
|
||||
X11.XFreeGC(_display, gc);
|
||||
_blob.Dispose();
|
||||
}
|
||||
|
||||
public IntPtr Address { get; }
|
||||
public int Width { get; }
|
||||
public int Height { get; }
|
||||
public int RowBytes { get; }
|
||||
public Vector Dpi { get; }
|
||||
public PixelFormat Format { get; }
|
||||
}
|
||||
}
|
|
@ -70,7 +70,7 @@ namespace Avalonia.Controls.UnitTests
|
|||
target.Measure(Size.Infinity);
|
||||
target.Arrange(new Rect(target.DesiredSize));
|
||||
|
||||
Assert.Equal(new Size(120, 130), target.Bounds.Size);
|
||||
Assert.Equal(new Size(120, 120), target.Bounds.Size);
|
||||
Assert.Equal(new Rect(0, 0, 120, 20), target.Children[0].Bounds);
|
||||
Assert.Equal(new Rect(0, 30, 120, 30), target.Children[1].Bounds);
|
||||
Assert.Equal(new Rect(0, 70, 120, 50), target.Children[2].Bounds);
|
||||
|
@ -94,7 +94,7 @@ namespace Avalonia.Controls.UnitTests
|
|||
target.Measure(Size.Infinity);
|
||||
target.Arrange(new Rect(target.DesiredSize));
|
||||
|
||||
Assert.Equal(new Size(130, 120), target.Bounds.Size);
|
||||
Assert.Equal(new Size(120, 120), target.Bounds.Size);
|
||||
Assert.Equal(new Rect(0, 0, 20, 120), target.Children[0].Bounds);
|
||||
Assert.Equal(new Rect(30, 0, 30, 120), target.Children[1].Bounds);
|
||||
Assert.Equal(new Rect(70, 0, 50, 120), target.Children[2].Bounds);
|
||||
|
|
Загрузка…
Ссылка в новой задаче