committed by
GitHub
63 changed files with 1874 additions and 243 deletions
@ -0,0 +1,42 @@ |
|||||
|
<UserControl xmlns="https://github.com/avaloniaui" |
||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |
||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |
||||
|
mc:Ignorable="d" d:DesignWidth="400" d:DesignHeight="250" |
||||
|
x:Class="ControlCatalog.Pages.LabelsPage" |
||||
|
x:Name="_labelsPage"> |
||||
|
<UserControl.Styles> |
||||
|
<Style Selector="Label"> |
||||
|
<Setter Property="VerticalAlignment" Value="Center"/> |
||||
|
<Setter Property="Margin" Value="6,3,0,3"/> |
||||
|
</Style> |
||||
|
<Style Selector="TextBox"> |
||||
|
<Setter Property="VerticalAlignment" Value="Center"/> |
||||
|
<Setter Property="Margin" Value="0,3,6,3"/> |
||||
|
</Style> |
||||
|
<Style Selector="CheckBox"> |
||||
|
<Setter Property="VerticalAlignment" Value="Center"/> |
||||
|
<Setter Property="Margin" Value="0,3,6,3"/> |
||||
|
</Style> |
||||
|
<Style Selector="Button[IsDefault=true]"> |
||||
|
<Setter Property="Background" Value="{DynamicResource HighlightBrush}"/> |
||||
|
</Style> |
||||
|
</UserControl.Styles> |
||||
|
<ScrollViewer VerticalScrollBarVisibility="Auto" |
||||
|
HorizontalScrollBarVisibility="Hidden"> |
||||
|
<Grid HorizontalAlignment="Left" VerticalAlignment="Top" RowDefinitions="Auto,Auto,Auto,Auto,Auto,*" ColumnDefinitions="Auto,6,*" Width="246"> |
||||
|
<Label Target="{Binding #firstNameEdit}" Grid.Row="0" Grid.Column="0">_First name</Label> |
||||
|
<TextBox Name="firstNameEdit" Grid.Column="2" Grid.Row="0" Text="{Binding FirstName}"></TextBox> |
||||
|
<Label Target="{Binding #lastNameEdit}" Grid.Row="1" Grid.Column="0">_Last name</Label> |
||||
|
<TextBox Name="lastNameEdit" Grid.Column="2" Grid.Row="1" Text="{Binding LastName}"></TextBox> |
||||
|
<Label Target="{Binding #bannedCheck}" Grid.Row="2" Grid.Column="0">_Banned</Label> |
||||
|
<CheckBox Name="bannedCheck" Grid.Column="2" Grid.Row="2" IsChecked="{Binding IsBanned}"></CheckBox> |
||||
|
<GridSplitter Grid.Column="1" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Grid.RowSpan="3" > |
||||
|
</GridSplitter> |
||||
|
<StackPanel Grid.Column="0" Grid.Row="4" Grid.ColumnSpan="3" Orientation="Horizontal" HorizontalAlignment="Right"> |
||||
|
<Button IsCancel="True" Command="{Binding #_labelsPage.DoCancel}">Cancel</Button> |
||||
|
<Button IsDefault="True" Command="{Binding #_labelsPage.DoSave}">Save</Button> |
||||
|
</StackPanel> |
||||
|
</Grid> |
||||
|
</ScrollViewer> |
||||
|
</UserControl> |
||||
@ -0,0 +1,43 @@ |
|||||
|
using Avalonia; |
||||
|
using Avalonia.Controls; |
||||
|
using Avalonia.Markup.Xaml; |
||||
|
using ControlCatalog.Models; |
||||
|
using ReactiveUI; |
||||
|
|
||||
|
namespace ControlCatalog.Pages |
||||
|
{ |
||||
|
public class LabelsPage : UserControl |
||||
|
{ |
||||
|
private Person _person; |
||||
|
|
||||
|
public LabelsPage() |
||||
|
{ |
||||
|
CreateDefaultPerson(); |
||||
|
this.InitializeComponent(); |
||||
|
} |
||||
|
|
||||
|
private void CreateDefaultPerson() |
||||
|
{ |
||||
|
DataContext = _person = new Person |
||||
|
{ |
||||
|
FirstName = "John", |
||||
|
LastName = "Doe", |
||||
|
IsBanned = true, |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
private void InitializeComponent() |
||||
|
{ |
||||
|
AvaloniaXamlLoader.Load(this); |
||||
|
} |
||||
|
|
||||
|
public void DoSave() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
public void DoCancel() |
||||
|
{ |
||||
|
CreateDefaultPerson(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,74 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Runtime.CompilerServices; |
||||
|
using System.Text; |
||||
|
using Avalonia.Controls.Primitives; |
||||
|
using Avalonia.Controls.Templates; |
||||
|
using Avalonia.Data; |
||||
|
using Avalonia.Input; |
||||
|
using Avalonia.Interactivity; |
||||
|
|
||||
|
namespace Avalonia.Controls |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Label control. Focuses <see cref="Target"/> on pointer click or access key press (Alt + accessKey)
|
||||
|
/// </summary>
|
||||
|
public class Label : ContentControl |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Defines the <see cref="Target"/> Direct property
|
||||
|
/// </summary>
|
||||
|
public static readonly DirectProperty<Label, IInputElement> TargetProperty = |
||||
|
AvaloniaProperty.RegisterDirect<Label, IInputElement>(nameof(Target), lbl => lbl.Target, (lbl, inp) => lbl.Target = inp); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Label focus target storage field
|
||||
|
/// </summary>
|
||||
|
private IInputElement _target; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Label focus Target
|
||||
|
/// </summary>
|
||||
|
public IInputElement Target |
||||
|
{ |
||||
|
get => _target; |
||||
|
set => SetAndRaise(TargetProperty, ref _target, value); |
||||
|
} |
||||
|
|
||||
|
static Label() |
||||
|
{ |
||||
|
AccessKeyHandler.AccessKeyPressedEvent.AddClassHandler<Label>((lbl, args) => lbl.LabelActivated(args)); |
||||
|
// IsTabStopProperty.OverrideDefaultValue<Label>(false)
|
||||
|
FocusableProperty.OverrideDefaultValue<Label>(false); |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes instance of <see cref="Label"/> control
|
||||
|
/// </summary>
|
||||
|
public Label() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Method which focuses <see cref="Target"/> input element
|
||||
|
/// </summary>
|
||||
|
private void LabelActivated(RoutedEventArgs args) |
||||
|
{ |
||||
|
Target?.Focus(); |
||||
|
args.Handled = Target != null; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Handler of <see cref="IInputElement.PointerPressed"/> event
|
||||
|
/// </summary>
|
||||
|
/// <param name="e">Event Arguments</param>
|
||||
|
protected override void OnPointerPressed(PointerPressedEventArgs e) |
||||
|
{ |
||||
|
if (e.GetCurrentPoint(this).Properties.PointerUpdateKind == PointerUpdateKind.LeftButtonPressed) |
||||
|
{ |
||||
|
LabelActivated(e); |
||||
|
} |
||||
|
base.OnPointerPressed(e); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1 @@ |
|||||
|
Total Issues: 0 |
||||
@ -0,0 +1,17 @@ |
|||||
|
<Style xmlns="https://github.com/avaloniaui" Selector="Label"> |
||||
|
<Setter Property="Padding" Value="3"/> |
||||
|
<Setter Property="Template"> |
||||
|
<ControlTemplate> |
||||
|
<ContentPresenter Name="PART_ContentPresenter" |
||||
|
Background="{TemplateBinding Background}" |
||||
|
BorderBrush="{TemplateBinding BorderBrush}" |
||||
|
BorderThickness="{TemplateBinding BorderThickness}" |
||||
|
ContentTemplate="{TemplateBinding ContentTemplate}" |
||||
|
Content="{TemplateBinding Content}" |
||||
|
Padding="{TemplateBinding Padding}" |
||||
|
RecognizesAccessKey="True" |
||||
|
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" |
||||
|
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"/> |
||||
|
</ControlTemplate> |
||||
|
</Setter> |
||||
|
</Style> |
||||
@ -0,0 +1,17 @@ |
|||||
|
<Style xmlns="https://github.com/avaloniaui" Selector="Label"> |
||||
|
<Setter Property="Padding" Value="3"/> |
||||
|
<Setter Property="Template"> |
||||
|
<ControlTemplate> |
||||
|
<ContentPresenter Name="PART_ContentPresenter" |
||||
|
Background="{TemplateBinding Background}" |
||||
|
BorderBrush="{TemplateBinding BorderBrush}" |
||||
|
BorderThickness="{TemplateBinding BorderThickness}" |
||||
|
ContentTemplate="{TemplateBinding ContentTemplate}" |
||||
|
Content="{TemplateBinding Content}" |
||||
|
Padding="{TemplateBinding Padding}" |
||||
|
RecognizesAccessKey="True" |
||||
|
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" |
||||
|
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"/> |
||||
|
</ControlTemplate> |
||||
|
</Setter> |
||||
|
</Style> |
||||
@ -0,0 +1,18 @@ |
|||||
|
namespace Avalonia.Win32 |
||||
|
{ |
||||
|
internal class CompositionBlurHost : IBlurHost |
||||
|
{ |
||||
|
Windows.UI.Composition.Visual _blurVisual; |
||||
|
|
||||
|
public CompositionBlurHost(Windows.UI.Composition.Visual blurVisual) |
||||
|
{ |
||||
|
_blurVisual = blurVisual; |
||||
|
} |
||||
|
|
||||
|
public void SetBlur(bool enabled) |
||||
|
{ |
||||
|
_blurVisual.IsVisible = enabled; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,143 @@ |
|||||
|
using System; |
||||
|
using System.Runtime.InteropServices; |
||||
|
using Avalonia.OpenGL; |
||||
|
using Avalonia.OpenGL.Angle; |
||||
|
using Avalonia.OpenGL.Egl; |
||||
|
using Windows.UI.Composition; |
||||
|
using Windows.UI.Composition.Interop; |
||||
|
using WinRT; |
||||
|
|
||||
|
namespace Avalonia.Win32 |
||||
|
{ |
||||
|
internal class CompositionConnector |
||||
|
{ |
||||
|
private Compositor _compositor; |
||||
|
private Windows.System.DispatcherQueueController _dispatcherQueueController; |
||||
|
private CompositionGraphicsDevice _graphicsDevice; |
||||
|
|
||||
|
internal enum DISPATCHERQUEUE_THREAD_APARTMENTTYPE |
||||
|
{ |
||||
|
DQTAT_COM_NONE = 0, |
||||
|
DQTAT_COM_ASTA = 1, |
||||
|
DQTAT_COM_STA = 2 |
||||
|
}; |
||||
|
|
||||
|
internal enum DISPATCHERQUEUE_THREAD_TYPE |
||||
|
{ |
||||
|
DQTYPE_THREAD_DEDICATED = 1, |
||||
|
DQTYPE_THREAD_CURRENT = 2, |
||||
|
}; |
||||
|
|
||||
|
[StructLayout(LayoutKind.Sequential)] |
||||
|
internal struct DispatcherQueueOptions |
||||
|
{ |
||||
|
public int dwSize; |
||||
|
|
||||
|
[MarshalAs(UnmanagedType.I4)] |
||||
|
public DISPATCHERQUEUE_THREAD_TYPE threadType; |
||||
|
|
||||
|
[MarshalAs(UnmanagedType.I4)] |
||||
|
public DISPATCHERQUEUE_THREAD_APARTMENTTYPE apartmentType; |
||||
|
}; |
||||
|
|
||||
|
[DllImport("coremessaging.dll", EntryPoint = "CreateDispatcherQueueController", CharSet = CharSet.Unicode)] |
||||
|
internal static extern IntPtr CreateDispatcherQueueController(DispatcherQueueOptions options, out IntPtr dispatcherQueueController); |
||||
|
|
||||
|
public CompositionConnector(EglPlatformOpenGlInterface egl) |
||||
|
{ |
||||
|
EnsureDispatcherQueue(); |
||||
|
|
||||
|
if (_dispatcherQueueController != null) |
||||
|
_compositor = new Compositor(); |
||||
|
|
||||
|
var interop = _compositor.As<ICompositorInterop>(); |
||||
|
|
||||
|
var display = egl.Display as AngleWin32EglDisplay; |
||||
|
|
||||
|
_graphicsDevice = interop.CreateGraphicsDevice(display.GetDirect3DDevice()); |
||||
|
} |
||||
|
|
||||
|
public ICompositionDrawingSurfaceInterop InitialiseWindowCompositionTree(IntPtr hwnd, out Windows.UI.Composition.Visual surfaceVisual, out IBlurHost blurHost) |
||||
|
{ |
||||
|
var target = CreateDesktopWindowTarget(hwnd); |
||||
|
|
||||
|
var surface = _graphicsDevice.CreateDrawingSurface(new Windows.Foundation.Size(0, 0), |
||||
|
Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized, |
||||
|
Windows.Graphics.DirectX.DirectXAlphaMode.Premultiplied); |
||||
|
|
||||
|
var surfaceInterop = surface.As<ICompositionDrawingSurfaceInterop>(); |
||||
|
|
||||
|
var brush = _compositor.CreateSurfaceBrush(surface); |
||||
|
var visual = _compositor.CreateSpriteVisual(); |
||||
|
|
||||
|
visual.Brush = brush; |
||||
|
visual.RelativeSizeAdjustment = new System.Numerics.Vector2(1, 1); |
||||
|
|
||||
|
var container = _compositor.CreateContainerVisual(); |
||||
|
|
||||
|
target.Root = container; |
||||
|
|
||||
|
var blur = CreateBlur(); |
||||
|
|
||||
|
blurHost = new CompositionBlurHost(blur); |
||||
|
|
||||
|
container.Children.InsertAtTop(blur); |
||||
|
|
||||
|
container.Children.InsertAtTop(visual); |
||||
|
|
||||
|
visual.CompositeMode = CompositionCompositeMode.SourceOver; |
||||
|
|
||||
|
surfaceVisual = container; |
||||
|
|
||||
|
return surfaceInterop; |
||||
|
} |
||||
|
|
||||
|
private SpriteVisual CreateBlur() |
||||
|
{ |
||||
|
var blurEffect = new GaussianBlurEffect(new CompositionEffectSourceParameter("backdrop")); |
||||
|
var blurEffectFactory = _compositor.CreateEffectFactory(blurEffect); |
||||
|
|
||||
|
var blurBrush = blurEffectFactory.CreateBrush(); |
||||
|
var backDropBrush = _compositor.CreateBackdropBrush(); |
||||
|
|
||||
|
blurBrush.SetSourceParameter("backdrop", backDropBrush); |
||||
|
|
||||
|
var saturateEffect = new SaturationEffect(blurEffect); |
||||
|
var satEffectFactory = _compositor.CreateEffectFactory(saturateEffect); |
||||
|
|
||||
|
var satBrush = satEffectFactory.CreateBrush(); |
||||
|
satBrush.SetSourceParameter("backdrop", backDropBrush); |
||||
|
|
||||
|
var visual = _compositor.CreateSpriteVisual(); |
||||
|
visual.IsVisible = false; |
||||
|
|
||||
|
visual.RelativeSizeAdjustment = new System.Numerics.Vector2(1.0f, 1.0f); |
||||
|
visual.Brush = satBrush; |
||||
|
|
||||
|
return visual; |
||||
|
} |
||||
|
|
||||
|
private CompositionTarget CreateDesktopWindowTarget(IntPtr window) |
||||
|
{ |
||||
|
var interop = _compositor.As<global::Windows.UI.Composition.Desktop.ICompositorDesktopInterop>(); |
||||
|
|
||||
|
interop.CreateDesktopWindowTarget(window, false, out var windowTarget); |
||||
|
return Windows.UI.Composition.Desktop.DesktopWindowTarget.FromAbi(windowTarget); |
||||
|
} |
||||
|
|
||||
|
private void EnsureDispatcherQueue() |
||||
|
{ |
||||
|
if (_dispatcherQueueController == null) |
||||
|
{ |
||||
|
DispatcherQueueOptions options = new DispatcherQueueOptions(); |
||||
|
options.apartmentType = DISPATCHERQUEUE_THREAD_APARTMENTTYPE.DQTAT_COM_NONE; |
||||
|
options.threadType = DISPATCHERQUEUE_THREAD_TYPE.DQTYPE_THREAD_CURRENT; |
||||
|
options.dwSize = Marshal.SizeOf(typeof(DispatcherQueueOptions)); |
||||
|
|
||||
|
CreateDispatcherQueueController(options, out var queue); |
||||
|
_dispatcherQueueController = Windows.System.DispatcherQueueController.FromAbi(queue); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,96 @@ |
|||||
|
using System; |
||||
|
using System.Runtime.InteropServices; |
||||
|
using Avalonia.OpenGL; |
||||
|
using Avalonia.OpenGL.Angle; |
||||
|
using Avalonia.OpenGL.Egl; |
||||
|
using Avalonia.OpenGL.Surfaces; |
||||
|
using Windows.UI.Composition.Interop; |
||||
|
|
||||
|
namespace Avalonia.Win32 |
||||
|
{ |
||||
|
internal class CompositionEglGlPlatformSurface : EglGlPlatformSurfaceBase |
||||
|
{ |
||||
|
private EglPlatformOpenGlInterface _egl; |
||||
|
private readonly IEglWindowGlPlatformSurfaceInfo _info; |
||||
|
private ICompositionDrawingSurfaceInterop _surfaceInterop; |
||||
|
private Windows.UI.Composition.Visual _surface; |
||||
|
|
||||
|
public CompositionEglGlPlatformSurface(EglPlatformOpenGlInterface egl, IEglWindowGlPlatformSurfaceInfo info) : base() |
||||
|
{ |
||||
|
_egl = egl; |
||||
|
_info = info; |
||||
|
} |
||||
|
|
||||
|
public IBlurHost AttachToCompositionTree(CompositionConnector connector, IntPtr hwnd) |
||||
|
{ |
||||
|
using (_egl.PrimaryContext.MakeCurrent()) |
||||
|
{ |
||||
|
_surfaceInterop = connector.InitialiseWindowCompositionTree(hwnd, out _surface, out var blurHost); |
||||
|
return blurHost; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public override IGlPlatformSurfaceRenderTarget CreateGlRenderTarget() |
||||
|
{ |
||||
|
return new CompositionRenderTarget(_egl, _surface, _surfaceInterop, _info); |
||||
|
} |
||||
|
|
||||
|
class CompositionRenderTarget : EglPlatformSurfaceRenderTargetBase |
||||
|
{ |
||||
|
private readonly EglPlatformOpenGlInterface _egl; |
||||
|
private readonly IEglWindowGlPlatformSurfaceInfo _info; |
||||
|
private PixelSize _currentSize; |
||||
|
private readonly ICompositionDrawingSurfaceInterop _surfaceInterop; |
||||
|
private static Guid s_Iid = Guid.Parse("6f15aaf2-d208-4e89-9ab4-489535d34f9c"); |
||||
|
private Windows.UI.Composition.Visual _compositionVisual; |
||||
|
|
||||
|
public CompositionRenderTarget(EglPlatformOpenGlInterface egl, |
||||
|
Windows.UI.Composition.Visual compositionVisual, |
||||
|
ICompositionDrawingSurfaceInterop interopSurface, |
||||
|
IEglWindowGlPlatformSurfaceInfo info) |
||||
|
: base(egl) |
||||
|
{ |
||||
|
_egl = egl; |
||||
|
_surfaceInterop = interopSurface; |
||||
|
_info = info; |
||||
|
_currentSize = info.Size; |
||||
|
_compositionVisual = compositionVisual; |
||||
|
|
||||
|
using (_egl.PrimaryContext.MakeCurrent()) |
||||
|
{ |
||||
|
_surfaceInterop.Resize(new POINT { X = _info.Size.Width, Y = _info.Size.Height }); |
||||
|
} |
||||
|
|
||||
|
_compositionVisual.Size = new System.Numerics.Vector2(_info.Size.Width, _info.Size.Height); |
||||
|
} |
||||
|
|
||||
|
public override IGlPlatformSurfaceRenderingSession BeginDraw() |
||||
|
{ |
||||
|
IntPtr texture; |
||||
|
EglSurface surface; |
||||
|
|
||||
|
using (_egl.PrimaryEglContext.EnsureCurrent()) |
||||
|
{ |
||||
|
if (_info.Size != _currentSize) |
||||
|
{ |
||||
|
_surfaceInterop.Resize(new POINT { X = _info.Size.Width, Y = _info.Size.Height }); |
||||
|
_compositionVisual.Size = new System.Numerics.Vector2(_info.Size.Width, _info.Size.Height); |
||||
|
_currentSize = _info.Size; |
||||
|
} |
||||
|
|
||||
|
var offset = new POINT(); |
||||
|
|
||||
|
_surfaceInterop.BeginDraw( |
||||
|
IntPtr.Zero, |
||||
|
ref s_Iid, |
||||
|
out texture, ref offset); |
||||
|
|
||||
|
surface = (_egl.Display as AngleWin32EglDisplay).WrapDirect3D11Texture(_egl, texture, offset.X, offset.Y, _info.Size.Width, _info.Size.Height); |
||||
|
} |
||||
|
|
||||
|
return base.BeginDraw(surface, _info, () => { _surfaceInterop.EndDraw(); Marshal.Release(texture); surface.Dispose(); }, true); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,91 @@ |
|||||
|
using System; |
||||
|
|
||||
|
|
||||
|
namespace Avalonia.Win32 |
||||
|
{ |
||||
|
class D2DEffects |
||||
|
{ |
||||
|
public static readonly Guid CLSID_D2D12DAffineTransform = new Guid(0x6AA97485, 0x6354, 0x4CFC, 0x90, 0x8C, 0xE4, 0xA7, 0x4F, 0x62, 0xC9, 0x6C); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D13DPerspectiveTransform = new Guid(0xC2844D0B, 0x3D86, 0x46E7, 0x85, 0xBA, 0x52, 0x6C, 0x92, 0x40, 0xF3, 0xFB); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D13DTransform = new Guid(0xE8467B04, 0xEC61, 0x4B8A, 0xB5, 0xDE, 0xD4, 0xD7, 0x3D, 0xEB, 0xEA, 0x5A); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1ArithmeticComposite = new Guid(0xFC151437, 0x049A, 0x4784, 0xA2, 0x4A, 0xF1, 0xC4, 0xDA, 0xF2, 0x09, 0x87); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1Atlas = new Guid(0x913E2BE4, 0xFDCF, 0x4FE2, 0xA5, 0xF0, 0x24, 0x54, 0xF1, 0x4F, 0xF4, 0x08); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1BitmapSource = new Guid(0x5FB6C24D, 0xC6DD, 0x4231, 0x94, 0x4, 0x50, 0xF4, 0xD5, 0xC3, 0x25, 0x2D); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1Blend = new Guid(0x81C5B77B, 0x13F8, 0x4CDD, 0xAD, 0x20, 0xC8, 0x90, 0x54, 0x7A, 0xC6, 0x5D); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1Border = new Guid(0x2A2D49C0, 0x4ACF, 0x43C7, 0x8C, 0x6A, 0x7C, 0x4A, 0x27, 0x87, 0x4D, 0x27); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1Brightness = new Guid(0x8CEA8D1E, 0x77B0, 0x4986, 0xB3, 0xB9, 0x2F, 0x0C, 0x0E, 0xAE, 0x78, 0x87); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1ColorManagement = new Guid(0x1A28524C, 0xFDD6, 0x4AA4, 0xAE, 0x8F, 0x83, 0x7E, 0xB8, 0x26, 0x7B, 0x37); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1ColorMatrix = new Guid(0x921F03D6, 0x641C, 0x47DF, 0x85, 0x2D, 0xB4, 0xBB, 0x61, 0x53, 0xAE, 0x11); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1Composite = new Guid(0x48FC9F51, 0xF6AC, 0x48F1, 0x8B, 0x58, 0x3B, 0x28, 0xAC, 0x46, 0xF7, 0x6D); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1ConvolveMatrix = new Guid(0x407F8C08, 0x5533, 0x4331, 0xA3, 0x41, 0x23, 0xCC, 0x38, 0x77, 0x84, 0x3E); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1Crop = new Guid(0xE23F7110, 0x0E9A, 0x4324, 0xAF, 0x47, 0x6A, 0x2C, 0x0C, 0x46, 0xF3, 0x5B); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1DirectionalBlur = new Guid(0x174319A6, 0x58E9, 0x49B2, 0xBB, 0x63, 0xCA, 0xF2, 0xC8, 0x11, 0xA3, 0xDB); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1DiscreteTransfer = new Guid(0x90866FCD, 0x488E, 0x454B, 0xAF, 0x06, 0xE5, 0x04, 0x1B, 0x66, 0xC3, 0x6C); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1DisplacementMap = new Guid(0xEDC48364, 0x417, 0x4111, 0x94, 0x50, 0x43, 0x84, 0x5F, 0xA9, 0xF8, 0x90); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1DistantDiffuse = new Guid(0x3E7EFD62, 0xA32D, 0x46D4, 0xA8, 0x3C, 0x52, 0x78, 0x88, 0x9A, 0xC9, 0x54); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1DistantSpecular = new Guid(0x428C1EE5, 0x77B8, 0x4450, 0x8A, 0xB5, 0x72, 0x21, 0x9C, 0x21, 0xAB, 0xDA); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1DpiCompensation = new Guid(0x6C26C5C7, 0x34E0, 0x46FC, 0x9C, 0xFD, 0xE5, 0x82, 0x37, 0x6, 0xE2, 0x28); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1Flood = new Guid(0x61C23C20, 0xAE69, 0x4D8E, 0x94, 0xCF, 0x50, 0x07, 0x8D, 0xF6, 0x38, 0xF2); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1GammaTransfer = new Guid(0x409444C4, 0xC419, 0x41A0, 0xB0, 0xC1, 0x8C, 0xD0, 0xC0, 0xA1, 0x8E, 0x42); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1GaussianBlur = new Guid(0x1FEB6D69, 0x2FE6, 0x4AC9, 0x8C, 0x58, 0x1D, 0x7F, 0x93, 0xE7, 0xA6, 0xA5); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1Scale = new Guid(0x9DAF9369, 0x3846, 0x4D0E, 0xA4, 0x4E, 0xC, 0x60, 0x79, 0x34, 0xA5, 0xD7); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1Histogram = new Guid(0x881DB7D0, 0xF7EE, 0x4D4D, 0xA6, 0xD2, 0x46, 0x97, 0xAC, 0xC6, 0x6E, 0xE8); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1HueRotation = new Guid(0x0F4458EC, 0x4B32, 0x491B, 0x9E, 0x85, 0xBD, 0x73, 0xF4, 0x4D, 0x3E, 0xB6); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1LinearTransfer = new Guid(0xAD47C8FD, 0x63EF, 0x4ACC, 0x9B, 0x51, 0x67, 0x97, 0x9C, 0x03, 0x6C, 0x06); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1LuminanceToAlpha = new Guid(0x41251AB7, 0x0BEB, 0x46F8, 0x9D, 0xA7, 0x59, 0xE9, 0x3F, 0xCC, 0xE5, 0xDE); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1Morphology = new Guid(0xEAE6C40D, 0x626A, 0x4C2D, 0xBF, 0xCB, 0x39, 0x10, 0x01, 0xAB, 0xE2, 0x02); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1OpacityMetadata = new Guid(0x6C53006A, 0x4450, 0x4199, 0xAA, 0x5B, 0xAD, 0x16, 0x56, 0xFE, 0xCE, 0x5E); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1PointDiffuse = new Guid(0xB9E303C3, 0xC08C, 0x4F91, 0x8B, 0x7B, 0x38, 0x65, 0x6B, 0xC4, 0x8C, 0x20); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1PointSpecular = new Guid(0x09C3CA26, 0x3AE2, 0x4F09, 0x9E, 0xBC, 0xED, 0x38, 0x65, 0xD5, 0x3F, 0x22); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1Premultiply = new Guid(0x06EAB419, 0xDEED, 0x4018, 0x80, 0xD2, 0x3E, 0x1D, 0x47, 0x1A, 0xDE, 0xB2); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1Saturation = new Guid(0x5CB2D9CF, 0x327D, 0x459F, 0xA0, 0xCE, 0x40, 0xC0, 0xB2, 0x08, 0x6B, 0xF7); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1Shadow = new Guid(0xC67EA361, 0x1863, 0x4E69, 0x89, 0xDB, 0x69, 0x5D, 0x3E, 0x9A, 0x5B, 0x6B); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1SpotDiffuse = new Guid(0x818A1105, 0x7932, 0x44F4, 0xAA, 0x86, 0x08, 0xAE, 0x7B, 0x2F, 0x2C, 0x93); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1SpotSpecular = new Guid(0xEDAE421E, 0x7654, 0x4A37, 0x9D, 0xB8, 0x71, 0xAC, 0xC1, 0xBE, 0xB3, 0xC1); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1TableTransfer = new Guid(0x5BF818C3, 0x5E43, 0x48CB, 0xB6, 0x31, 0x86, 0x83, 0x96, 0xD6, 0xA1, 0xD4); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1Tile = new Guid(0xB0784138, 0x3B76, 0x4BC5, 0xB1, 0x3B, 0x0F, 0xA2, 0xAD, 0x02, 0x65, 0x9F); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1Turbulence = new Guid(0xCF2BB6AE, 0x889A, 0x4AD7, 0xBA, 0x29, 0xA2, 0xFD, 0x73, 0x2C, 0x9F, 0xC9); |
||||
|
|
||||
|
public static readonly Guid CLSID_D2D1UnPremultiply = new Guid(0xFB9AC489, 0xAD8D, 0x41ED, 0x99, 0x99, 0xBB, 0x63, 0x47, 0xD1, 0x10, 0xF7); |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,45 @@ |
|||||
|
using System; |
||||
|
using Windows.Graphics.Effects; |
||||
|
using Windows.Graphics.Effects.Interop; |
||||
|
|
||||
|
|
||||
|
namespace Avalonia.Win32 |
||||
|
{ |
||||
|
abstract class EffectBase : IGraphicsEffect, IGraphicsEffectSource, global::Windows.Graphics.Effects.Interop.IGraphicsEffectD2D1Interop |
||||
|
{ |
||||
|
private IGraphicsEffectSource[] _sources; |
||||
|
|
||||
|
public EffectBase(params IGraphicsEffectSource[] sources) |
||||
|
{ |
||||
|
_sources = sources; |
||||
|
} |
||||
|
|
||||
|
private IGraphicsEffectSource _source; |
||||
|
|
||||
|
public virtual string Name { get; set; } |
||||
|
|
||||
|
public abstract Guid EffectId { get; } |
||||
|
|
||||
|
public abstract uint PropertyCount { get; } |
||||
|
|
||||
|
public uint SourceCount => (uint)_sources.Length; |
||||
|
|
||||
|
public IGraphicsEffectSource GetSource(uint index) |
||||
|
{ |
||||
|
if(index < _sources.Length) |
||||
|
{ |
||||
|
return _sources[index]; |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
public uint GetNamedPropertyMapping(string name, out GRAPHICS_EFFECT_PROPERTY_MAPPING mapping) |
||||
|
{ |
||||
|
throw new NotImplementedException(); |
||||
|
} |
||||
|
|
||||
|
public abstract object GetProperty(uint index); |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,18 @@ |
|||||
|
namespace Windows.Graphics.Effects.Interop |
||||
|
{ |
||||
|
public enum GRAPHICS_EFFECT_PROPERTY_MAPPING |
||||
|
{ |
||||
|
GRAPHICS_EFFECT_PROPERTY_MAPPING_UNKNOWN, |
||||
|
GRAPHICS_EFFECT_PROPERTY_MAPPING_DIRECT, |
||||
|
GRAPHICS_EFFECT_PROPERTY_MAPPING_VECTORX, |
||||
|
GRAPHICS_EFFECT_PROPERTY_MAPPING_VECTORY, |
||||
|
GRAPHICS_EFFECT_PROPERTY_MAPPING_VECTORZ, |
||||
|
GRAPHICS_EFFECT_PROPERTY_MAPPING_VECTORW, |
||||
|
GRAPHICS_EFFECT_PROPERTY_MAPPING_RECT_TO_VECTOR4, |
||||
|
GRAPHICS_EFFECT_PROPERTY_MAPPING_RADIANS_TO_DEGREES, |
||||
|
GRAPHICS_EFFECT_PROPERTY_MAPPING_COLORMATRIX_ALPHA_MODE, |
||||
|
GRAPHICS_EFFECT_PROPERTY_MAPPING_COLOR_TO_VECTOR3, |
||||
|
GRAPHICS_EFFECT_PROPERTY_MAPPING_COLOR_TO_VECTOR4 |
||||
|
}; |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,57 @@ |
|||||
|
using System; |
||||
|
using Windows.Graphics.Effects; |
||||
|
|
||||
|
namespace Avalonia.Win32 |
||||
|
{ |
||||
|
class GaussianBlurEffect : EffectBase |
||||
|
{ |
||||
|
public GaussianBlurEffect(IGraphicsEffectSource source) : base(source) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
enum D2D1_GAUSSIANBLUR_OPTIMIZATION |
||||
|
{ |
||||
|
D2D1_GAUSSIANBLUR_OPTIMIZATION_SPEED, |
||||
|
D2D1_GAUSSIANBLUR_OPTIMIZATION_BALANCED, |
||||
|
D2D1_GAUSSIANBLUR_OPTIMIZATION_QUALITY, |
||||
|
D2D1_GAUSSIANBLUR_OPTIMIZATION_FORCE_DWORD |
||||
|
}; |
||||
|
|
||||
|
enum D2D1_BORDER_MODE |
||||
|
{ |
||||
|
D2D1_BORDER_MODE_SOFT, |
||||
|
D2D1_BORDER_MODE_HARD, |
||||
|
D2D1_BORDER_MODE_FORCE_DWORD |
||||
|
}; |
||||
|
|
||||
|
enum D2D1GaussianBlurProp |
||||
|
{ |
||||
|
D2D1_GAUSSIANBLUR_PROP_STANDARD_DEVIATION, |
||||
|
D2D1_GAUSSIANBLUR_PROP_OPTIMIZATION, |
||||
|
D2D1_GAUSSIANBLUR_PROP_BORDER_MODE, |
||||
|
D2D1_GAUSSIANBLUR_PROP_FORCE_DWORD |
||||
|
}; |
||||
|
|
||||
|
public override Guid EffectId => D2DEffects.CLSID_D2D1GaussianBlur; |
||||
|
|
||||
|
public override uint PropertyCount => 3; |
||||
|
|
||||
|
public override object GetProperty(uint index) |
||||
|
{ |
||||
|
switch ((D2D1GaussianBlurProp)index) |
||||
|
{ |
||||
|
case D2D1GaussianBlurProp.D2D1_GAUSSIANBLUR_PROP_STANDARD_DEVIATION: |
||||
|
return 30.0f; |
||||
|
|
||||
|
case D2D1GaussianBlurProp.D2D1_GAUSSIANBLUR_PROP_OPTIMIZATION: |
||||
|
return (uint)D2D1_GAUSSIANBLUR_OPTIMIZATION.D2D1_GAUSSIANBLUR_OPTIMIZATION_BALANCED; |
||||
|
|
||||
|
case D2D1GaussianBlurProp.D2D1_GAUSSIANBLUR_PROP_BORDER_MODE: |
||||
|
return (uint)D2D1_BORDER_MODE.D2D1_BORDER_MODE_HARD; |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,8 @@ |
|||||
|
namespace Avalonia.Win32 |
||||
|
{ |
||||
|
internal interface IBlurHost |
||||
|
{ |
||||
|
void SetBlur(bool enabled); |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,152 @@ |
|||||
|
using System; |
||||
|
using System.Runtime.InteropServices; |
||||
|
using WinRT; |
||||
|
|
||||
|
namespace Windows.UI.Composition.Interop |
||||
|
{ |
||||
|
public struct POINT |
||||
|
{ |
||||
|
public int X; |
||||
|
public int Y; |
||||
|
} |
||||
|
|
||||
|
public struct RECT |
||||
|
{ |
||||
|
public int left; |
||||
|
public int top; |
||||
|
public int right; |
||||
|
public int bottom; |
||||
|
|
||||
|
public int Width => right - left; |
||||
|
public int Height => bottom - top; |
||||
|
} |
||||
|
|
||||
|
[WindowsRuntimeType] |
||||
|
[Guid("FD04E6E3-FE0C-4C3C-AB19-A07601A576EE")] |
||||
|
public interface ICompositionDrawingSurfaceInterop |
||||
|
{ |
||||
|
void BeginDraw(IntPtr updateRect, ref Guid iid, out IntPtr updateObject, ref POINT point); |
||||
|
|
||||
|
void EndDraw(); |
||||
|
|
||||
|
void Resize(POINT sizePixels); |
||||
|
|
||||
|
void ResumeDraw(); |
||||
|
|
||||
|
void Scroll(RECT scrollRect, RECT clipRect, int offsetX, int offsetY); |
||||
|
|
||||
|
void SuspendDraw(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
namespace ABI.Windows.UI.Composition.Interop |
||||
|
{ |
||||
|
using global::System; |
||||
|
using global::System.Runtime.InteropServices; |
||||
|
using global::Windows.UI.Composition; |
||||
|
using global::Windows.UI.Composition.Interop; |
||||
|
|
||||
|
[Guid("FD04E6E3-FE0C-4C3C-AB19-A07601A576EE")] |
||||
|
internal class ICompositionDrawingSurfaceInterop : global::Windows.UI.Composition.Interop.ICompositionDrawingSurfaceInterop |
||||
|
|
||||
|
{ |
||||
|
[Guid("FD04E6E3-FE0C-4C3C-AB19-A07601A576EE")] |
||||
|
public unsafe struct Vftbl |
||||
|
{ |
||||
|
public delegate int _BeginDraw(IntPtr ThisPtr, IntPtr updateRect, ref Guid iid, out IntPtr updateObject, ref POINT updateOffset); |
||||
|
public delegate int _EndDraw(IntPtr ThisPtr); |
||||
|
public delegate int _Resize(IntPtr ThisPtr, POINT sizePixels); |
||||
|
public delegate int _ResumeDraw(IntPtr ThisPtr); |
||||
|
public delegate int _Scroll(IntPtr ThisPtr, RECT scrollRect, RECT clipRect, int offsetX, int offsetY); |
||||
|
public delegate int _SuspendDraw(IntPtr ThisPtr); |
||||
|
|
||||
|
internal global::WinRT.Interop.IUnknownVftbl IUnknownVftbl; |
||||
|
public _BeginDraw BeginDraw; |
||||
|
public _EndDraw EndDraw; |
||||
|
public _Resize Resize; |
||||
|
public _ResumeDraw ResumeDraw; |
||||
|
public _Scroll Scroll; |
||||
|
public _SuspendDraw SuspendDraw; |
||||
|
|
||||
|
public static readonly Vftbl AbiToProjectionVftable; |
||||
|
public static readonly IntPtr AbiToProjectionVftablePtr; |
||||
|
|
||||
|
static Vftbl() |
||||
|
{ |
||||
|
AbiToProjectionVftable = new Vftbl |
||||
|
{ |
||||
|
IUnknownVftbl = global::WinRT.Interop.IUnknownVftbl.AbiToProjectionVftbl, |
||||
|
|
||||
|
BeginDraw = Do_Abi_BeginDraw, |
||||
|
EndDraw = Do_Abi_EndDraw, |
||||
|
Resize = Do_Abi_Resize |
||||
|
|
||||
|
|
||||
|
}; |
||||
|
AbiToProjectionVftablePtr = Marshal.AllocHGlobal(Marshal.SizeOf<Vftbl>()); |
||||
|
Marshal.StructureToPtr(AbiToProjectionVftable, AbiToProjectionVftablePtr, false); |
||||
|
} |
||||
|
|
||||
|
private static int Do_Abi_BeginDraw(IntPtr ThisPtr, IntPtr updateRect, ref Guid iid, out IntPtr updateObject, ref POINT updateOffset) |
||||
|
{ |
||||
|
updateObject = IntPtr.Zero; |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
private static int Do_Abi_EndDraw(IntPtr ThisPtr) |
||||
|
{ |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
private static int Do_Abi_Resize(IntPtr ThisPtr, POINT sizePixels) |
||||
|
{ |
||||
|
return 0; |
||||
|
} |
||||
|
} |
||||
|
internal static ObjectReference<Vftbl> FromAbi(IntPtr thisPtr) => ObjectReference<Vftbl>.FromAbi(thisPtr); |
||||
|
|
||||
|
public static implicit operator ICompositionDrawingSurfaceInterop(IObjectReference obj) => (obj != null) ? new ICompositionDrawingSurfaceInterop(obj) : null; |
||||
|
protected readonly ObjectReference<Vftbl> _obj; |
||||
|
public IObjectReference ObjRef { get => _obj; } |
||||
|
public IntPtr ThisPtr => _obj.ThisPtr; |
||||
|
public ObjectReference<I> AsInterface<I>() => _obj.As<I>(); |
||||
|
public A As<A>() => _obj.AsType<A>(); |
||||
|
|
||||
|
public ICompositionDrawingSurfaceInterop(IObjectReference obj) : this(obj.As<Vftbl>()) { } |
||||
|
internal ICompositionDrawingSurfaceInterop(ObjectReference<Vftbl> obj) |
||||
|
{ |
||||
|
_obj = obj; |
||||
|
} |
||||
|
|
||||
|
public void BeginDraw(IntPtr updateRect, ref Guid iid, out IntPtr updateObject, ref POINT point) |
||||
|
{ |
||||
|
Marshal.ThrowExceptionForHR(_obj.Vftbl.BeginDraw(ThisPtr, updateRect, ref iid, out updateObject, ref point)); |
||||
|
} |
||||
|
|
||||
|
public void EndDraw() |
||||
|
{ |
||||
|
Marshal.ThrowExceptionForHR(_obj.Vftbl.EndDraw(ThisPtr)); |
||||
|
} |
||||
|
|
||||
|
public void Resize(POINT sizePixels) |
||||
|
{ |
||||
|
Marshal.ThrowExceptionForHR(_obj.Vftbl.Resize(ThisPtr, sizePixels)); |
||||
|
} |
||||
|
|
||||
|
public void ResumeDraw() |
||||
|
{ |
||||
|
throw new NotImplementedException(); |
||||
|
} |
||||
|
|
||||
|
public void Scroll(RECT scrollRect, RECT clipRect, int offsetX, int offsetY) |
||||
|
{ |
||||
|
throw new NotImplementedException(); |
||||
|
} |
||||
|
|
||||
|
public void SuspendDraw() |
||||
|
{ |
||||
|
throw new NotImplementedException(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,14 @@ |
|||||
|
using System; |
||||
|
using System.Runtime.InteropServices; |
||||
|
using WinRT; |
||||
|
|
||||
|
namespace Windows.UI.Composition.Desktop |
||||
|
{ |
||||
|
[WindowsRuntimeType] |
||||
|
[Guid("29E691FA-4567-4DCA-B319-D0F207EB6807")] |
||||
|
public interface ICompositorDesktopInterop |
||||
|
{ |
||||
|
void CreateDesktopWindowTarget(IntPtr hwndTarget, bool isTopmost, out IntPtr test); |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,69 @@ |
|||||
|
using WinRT; |
||||
|
|
||||
|
namespace ABI.Windows.UI.Composition.Desktop |
||||
|
{ |
||||
|
using global::System; |
||||
|
using global::System.Runtime.InteropServices; |
||||
|
|
||||
|
[Guid("29E691FA-4567-4DCA-B319-D0F207EB6807")] |
||||
|
internal class ICompositorDesktopInterop : global::Windows.UI.Composition.Desktop.ICompositorDesktopInterop |
||||
|
|
||||
|
{ |
||||
|
[Guid("29E691FA-4567-4DCA-B319-D0F207EB6807")] |
||||
|
public struct Vftbl |
||||
|
{ |
||||
|
public delegate int _CreateDesktopWindowTarget(IntPtr thisPtr, IntPtr hwndTarget, byte isTopMost, out IntPtr desktopWindowTarget); |
||||
|
|
||||
|
internal global::WinRT.Interop.IUnknownVftbl IUnknownVftbl; |
||||
|
public _CreateDesktopWindowTarget CreateDesktopWindowTarget; |
||||
|
|
||||
|
|
||||
|
public static readonly Vftbl AbiToProjectionVftable; |
||||
|
public static readonly IntPtr AbiToProjectionVftablePtr; |
||||
|
|
||||
|
static Vftbl() |
||||
|
{ |
||||
|
AbiToProjectionVftable = new Vftbl |
||||
|
{ |
||||
|
IUnknownVftbl = global::WinRT.Interop.IUnknownVftbl.AbiToProjectionVftbl, |
||||
|
CreateDesktopWindowTarget = Do_Abi_Create_Desktop_Window_Target |
||||
|
}; |
||||
|
AbiToProjectionVftablePtr = Marshal.AllocHGlobal(Marshal.SizeOf<Vftbl>()); |
||||
|
Marshal.StructureToPtr(AbiToProjectionVftable, AbiToProjectionVftablePtr, false); |
||||
|
} |
||||
|
|
||||
|
private static int Do_Abi_Create_Desktop_Window_Target(IntPtr thisPtr, IntPtr hwndTarget, byte isTopMost, out IntPtr desktopWindowTarget) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
ComWrappersSupport.FindObject<global::Windows.UI.Composition.Desktop.ICompositorDesktopInterop>(thisPtr).CreateDesktopWindowTarget(hwndTarget, isTopMost != 0, out desktopWindowTarget); |
||||
|
return 0; |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
desktopWindowTarget = IntPtr.Zero; |
||||
|
return Marshal.GetHRForException(ex); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
internal static ObjectReference<Vftbl> FromAbi(IntPtr thisPtr) => ObjectReference<Vftbl>.FromAbi(thisPtr); |
||||
|
|
||||
|
public static implicit operator ICompositorDesktopInterop(IObjectReference obj) => (obj != null) ? new ICompositorDesktopInterop(obj) : null; |
||||
|
protected readonly ObjectReference<Vftbl> _obj; |
||||
|
public IObjectReference ObjRef { get => _obj; } |
||||
|
public IntPtr ThisPtr => _obj.ThisPtr; |
||||
|
public ObjectReference<I> AsInterface<I>() => _obj.As<I>(); |
||||
|
public A As<A>() => _obj.AsType<A>(); |
||||
|
public ICompositorDesktopInterop(IObjectReference obj) : this(obj.As<Vftbl>()) { } |
||||
|
internal ICompositorDesktopInterop(ObjectReference<Vftbl> obj) |
||||
|
{ |
||||
|
_obj = obj; |
||||
|
} |
||||
|
|
||||
|
public void CreateDesktopWindowTarget(IntPtr hwndTarget, bool isTopmost, out IntPtr test) |
||||
|
{ |
||||
|
Marshal.ThrowExceptionForHR(_obj.Vftbl.CreateDesktopWindowTarget(ThisPtr, hwndTarget, isTopmost ? (byte)1 : (byte)0, out test)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,139 @@ |
|||||
|
using System; |
||||
|
using System.Runtime.InteropServices; |
||||
|
using WinRT; |
||||
|
|
||||
|
namespace Windows.UI.Composition.Interop |
||||
|
{ |
||||
|
[WindowsRuntimeType] |
||||
|
[Guid("25297D5C-3AD4-4C9C-B5CF-E36A38512330")] |
||||
|
public interface ICompositorInterop |
||||
|
{ |
||||
|
ICompositionSurface CreateCompositionSurfaceForHandle(IntPtr swapChain); |
||||
|
|
||||
|
ICompositionSurface CreateCompositionSurfaceForSwapChain(IntPtr swapChain); |
||||
|
|
||||
|
CompositionGraphicsDevice CreateGraphicsDevice(IntPtr renderingDevice); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
namespace ABI.Windows.UI.Composition.Interop |
||||
|
{ |
||||
|
using global::System; |
||||
|
using global::System.Runtime.InteropServices; |
||||
|
using global::Windows.UI.Composition; |
||||
|
|
||||
|
[Guid("25297D5C-3AD4-4C9C-B5CF-E36A38512330")] |
||||
|
internal class ICompositorInterop : global::Windows.UI.Composition.Interop.ICompositorInterop |
||||
|
|
||||
|
{ |
||||
|
[Guid("25297D5C-3AD4-4C9C-B5CF-E36A38512330")] |
||||
|
public struct Vftbl |
||||
|
{ |
||||
|
public delegate int _CreateCompositionSurfaceForHandle(IntPtr ThisPtr, IntPtr swapChain, out IntPtr result); |
||||
|
public delegate int _CreateCompositionSurfaceForSwapChain(IntPtr ThisPtr, IntPtr swapChain, out IntPtr result); |
||||
|
public delegate int _CreateGraphicsDevice(IntPtr ThisPtr, IntPtr renderingDevice, out IntPtr result); |
||||
|
|
||||
|
internal global::WinRT.Interop.IUnknownVftbl IUnknownVftbl; |
||||
|
public _CreateCompositionSurfaceForHandle CreateCompositionSurfaceForHandle; |
||||
|
public _CreateCompositionSurfaceForSwapChain CreateCompositionSurfaceForSwapChain; |
||||
|
public _CreateGraphicsDevice CreateGraphicsDevice; |
||||
|
|
||||
|
|
||||
|
public static readonly Vftbl AbiToProjectionVftable; |
||||
|
public static readonly IntPtr AbiToProjectionVftablePtr; |
||||
|
|
||||
|
static Vftbl() |
||||
|
{ |
||||
|
AbiToProjectionVftable = new Vftbl |
||||
|
{ |
||||
|
IUnknownVftbl = global::WinRT.Interop.IUnknownVftbl.AbiToProjectionVftbl, |
||||
|
|
||||
|
CreateCompositionSurfaceForHandle = Do_Abi_Create_Composition_Surface_For_Handle, |
||||
|
CreateCompositionSurfaceForSwapChain = Do_Abi_Create_Composition_Surface_For_SwapChain, |
||||
|
CreateGraphicsDevice= Do_Abi_Create_Graphics_Device |
||||
|
}; |
||||
|
AbiToProjectionVftablePtr = Marshal.AllocHGlobal(Marshal.SizeOf<Vftbl>()); |
||||
|
Marshal.StructureToPtr(AbiToProjectionVftable, AbiToProjectionVftablePtr, false); |
||||
|
} |
||||
|
|
||||
|
private static int Do_Abi_Create_Composition_Surface_For_Handle(IntPtr thisPtr, IntPtr swapChain, out IntPtr surface) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
surface = IntPtr.Zero; |
||||
|
//surface = ComWrappersSupport.FindObject<global::Windows.UI.Composition.Interop.ICompositorInterop>(thisPtr).CreateCompositionSurfaceForHandle(swapChain);
|
||||
|
return 0; |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
surface = IntPtr.Zero; |
||||
|
return Marshal.GetHRForException(ex); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private static int Do_Abi_Create_Composition_Surface_For_SwapChain(IntPtr thisPtr, IntPtr swapChain, out IntPtr surface) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
surface = IntPtr.Zero; |
||||
|
//surface = ComWrappersSupport.FindObject<global::Windows.UI.Composition.Interop.ICompositorInterop>(thisPtr).CreateCompositionSurfaceForSwapChain(swapChain);
|
||||
|
return 0; |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
surface = IntPtr.Zero; |
||||
|
return Marshal.GetHRForException(ex); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private static int Do_Abi_Create_Graphics_Device(IntPtr thisPtr, IntPtr renderingDevice, out IntPtr graphicsDevice) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
graphicsDevice = ComWrappersSupport.FindObject<global::Windows.UI.Composition.Interop.ICompositorInterop>(thisPtr).CreateGraphicsDevice(renderingDevice).ThisPtr; |
||||
|
return 0; |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
graphicsDevice = IntPtr.Zero; |
||||
|
return Marshal.GetHRForException(ex); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
internal static ObjectReference<Vftbl> FromAbi(IntPtr thisPtr) => ObjectReference<Vftbl>.FromAbi(thisPtr); |
||||
|
|
||||
|
public static implicit operator ICompositorInterop(IObjectReference obj) => (obj != null) ? new ICompositorInterop(obj) : null; |
||||
|
protected readonly ObjectReference<Vftbl> _obj; |
||||
|
public IObjectReference ObjRef { get => _obj; } |
||||
|
public IntPtr ThisPtr => _obj.ThisPtr; |
||||
|
public ObjectReference<I> AsInterface<I>() => _obj.As<I>(); |
||||
|
public A As<A>() => _obj.AsType<A>(); |
||||
|
public ICompositorInterop(IObjectReference obj) : this(obj.As<Vftbl>()) { } |
||||
|
internal ICompositorInterop(ObjectReference<Vftbl> obj) |
||||
|
{ |
||||
|
_obj = obj; |
||||
|
} |
||||
|
|
||||
|
public ICompositionSurface CreateCompositionSurfaceForHandle(IntPtr swapChain) |
||||
|
{ |
||||
|
Marshal.ThrowExceptionForHR(_obj.Vftbl.CreateCompositionSurfaceForHandle(ThisPtr, swapChain, out var compositionSurface)); |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
public ICompositionSurface CreateCompositionSurfaceForSwapChain(IntPtr swapChain) |
||||
|
{ |
||||
|
Marshal.ThrowExceptionForHR(_obj.Vftbl.CreateCompositionSurfaceForSwapChain(ThisPtr, swapChain, out var compositionSurface)); |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
public CompositionGraphicsDevice CreateGraphicsDevice(IntPtr renderingDevice) |
||||
|
{ |
||||
|
Marshal.ThrowExceptionForHR(_obj.Vftbl.CreateGraphicsDevice(ThisPtr, renderingDevice, out var graphicsDevice)); |
||||
|
|
||||
|
return CompositionGraphicsDevice.FromAbi(graphicsDevice); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,24 @@ |
|||||
|
using System; |
||||
|
using System.Runtime.InteropServices; |
||||
|
using WinRT; |
||||
|
|
||||
|
namespace Windows.Graphics.Effects.Interop |
||||
|
{ |
||||
|
[WindowsRuntimeType] |
||||
|
[Guid("2FC57384-A068-44D7-A331-30982FCF7177")] |
||||
|
public interface IGraphicsEffectD2D1Interop |
||||
|
{ |
||||
|
Guid EffectId { get; } |
||||
|
|
||||
|
uint GetNamedPropertyMapping(string name, out GRAPHICS_EFFECT_PROPERTY_MAPPING mapping); |
||||
|
|
||||
|
object GetProperty(uint index); |
||||
|
|
||||
|
uint PropertyCount { get; } |
||||
|
|
||||
|
IGraphicsEffectSource GetSource(uint index); |
||||
|
|
||||
|
uint SourceCount { get; } |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,217 @@ |
|||||
|
using WinRT; |
||||
|
|
||||
|
namespace ABI.Windows.Graphics.Effects.Interop |
||||
|
{ |
||||
|
using global::System; |
||||
|
using global::System.Runtime.InteropServices; |
||||
|
|
||||
|
[Guid("2FC57384-A068-44D7-A331-30982FCF7177")] |
||||
|
internal class IGraphicsEffectD2D1Interop : global::Windows.Graphics.Effects.Interop.IGraphicsEffectD2D1Interop |
||||
|
|
||||
|
{ |
||||
|
[Guid("2FC57384-A068-44D7-A331-30982FCF7177")] |
||||
|
public struct Vftbl |
||||
|
{ |
||||
|
public delegate int _GetEffectId(IntPtr thisPtr, out Guid guid); |
||||
|
public delegate int _GetNamedPropertyMapping(IntPtr thisPtr, IntPtr name, IntPtr index, IntPtr mapping); |
||||
|
public delegate int _GetProperty(IntPtr thisPtr, uint index, out IntPtr value); |
||||
|
public unsafe delegate int _GetPropertyCount(IntPtr thisPtr, uint* count); |
||||
|
public delegate int _GetSource(IntPtr thisPtr, uint index, out IntPtr source); |
||||
|
public delegate int _GetSourceCount(IntPtr thisPtr, out uint count); |
||||
|
|
||||
|
internal global::WinRT.Interop.IUnknownVftbl IUnknownVftbl; |
||||
|
public _GetEffectId GetEffectId; |
||||
|
public _GetNamedPropertyMapping GetNamedPropertyMapping; |
||||
|
public _GetPropertyCount GetPropertyCount; |
||||
|
public _GetProperty GetProperty; |
||||
|
public _GetSource GetSource; |
||||
|
public _GetSourceCount GetSourceCount; |
||||
|
|
||||
|
public static readonly Vftbl AbiToProjectionVftable; |
||||
|
public static readonly IntPtr AbiToProjectionVftablePtr; |
||||
|
|
||||
|
unsafe static Vftbl() |
||||
|
{ |
||||
|
AbiToProjectionVftable = new Vftbl |
||||
|
{ |
||||
|
IUnknownVftbl = global::WinRT.Interop.IUnknownVftbl.AbiToProjectionVftbl, |
||||
|
GetEffectId = Do_Abi_Get_Effect_Id, |
||||
|
GetNamedPropertyMapping = Do_Abi_Get_Property_Mapping, |
||||
|
GetPropertyCount = Do_Abi_Get_Property_Count, |
||||
|
GetProperty = Do_Abi_Get_Property, |
||||
|
GetSource = Do_Abi_Get_Source, |
||||
|
GetSourceCount = Do_Abi_Get_Source_Count |
||||
|
|
||||
|
}; |
||||
|
AbiToProjectionVftablePtr = Marshal.AllocHGlobal(Marshal.SizeOf<Vftbl>()); |
||||
|
Marshal.StructureToPtr(AbiToProjectionVftable, AbiToProjectionVftablePtr, false); |
||||
|
} |
||||
|
|
||||
|
private static int Do_Abi_Get_Effect_Id(IntPtr thisPtr, out Guid guid) |
||||
|
{ |
||||
|
guid = default; |
||||
|
|
||||
|
try |
||||
|
{ |
||||
|
guid = ComWrappersSupport.FindObject<global::Windows.Graphics.Effects.Interop.IGraphicsEffectD2D1Interop>(thisPtr).EffectId; |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
return Marshal.GetHRForException(ex); |
||||
|
} |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
private static int Do_Abi_Get_Property_Mapping(IntPtr thisPtr, IntPtr name, IntPtr index, IntPtr mapping) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
ComWrappersSupport.FindObject<global::Windows.Graphics.Effects.Interop.IGraphicsEffectD2D1Interop>(thisPtr).GetNamedPropertyMapping(MarshalString.FromAbi(name), out var mappingResult); |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
return Marshal.GetHRForException(ex); |
||||
|
} |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
private static int Do_Abi_Get_Property(IntPtr thisPtr, uint index, out IntPtr value) |
||||
|
{ |
||||
|
value = default; |
||||
|
|
||||
|
try |
||||
|
{ |
||||
|
value = MarshalInspectable.CreateMarshaler( |
||||
|
ComWrappersSupport.FindObject<global::Windows.Graphics.Effects.Interop.IGraphicsEffectD2D1Interop>(thisPtr).GetProperty(index)) |
||||
|
.As(Guid.Parse("4BD682DD-7554-40E9-9A9B-82654EDE7E62")) |
||||
|
.GetRef(); |
||||
|
|
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
return Marshal.GetHRForException(ex); |
||||
|
} |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
unsafe private static int Do_Abi_Get_Property_Count(IntPtr thisPtr, uint* count) |
||||
|
{ |
||||
|
|
||||
|
try |
||||
|
{ |
||||
|
var res = ComWrappersSupport.FindObject<global::Windows.Graphics.Effects.Interop.IGraphicsEffectD2D1Interop>(thisPtr).PropertyCount; |
||||
|
|
||||
|
if (count != null) |
||||
|
{ |
||||
|
*count = res; |
||||
|
} |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
return Marshal.GetHRForException(ex); |
||||
|
} |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
private static int Do_Abi_Get_Source(IntPtr thisPtr, uint index, out IntPtr value) |
||||
|
{ |
||||
|
value = default; |
||||
|
|
||||
|
try |
||||
|
{ |
||||
|
var source = ComWrappersSupport.FindObject<global::Windows.Graphics.Effects.Interop.IGraphicsEffectD2D1Interop>(thisPtr).GetSource(index); |
||||
|
|
||||
|
value = MarshalInterface<global::Windows.Graphics.Effects.IGraphicsEffectSource>.FromManaged(source); |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
return Marshal.GetHRForException(ex); |
||||
|
} |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
private static int Do_Abi_Get_Source_Count(IntPtr thisPtr, out uint count) |
||||
|
{ |
||||
|
count = default; |
||||
|
|
||||
|
try |
||||
|
{ |
||||
|
count = ComWrappersSupport.FindObject<global::Windows.Graphics.Effects.Interop.IGraphicsEffectD2D1Interop>(thisPtr).SourceCount; |
||||
|
} |
||||
|
catch (Exception ex) |
||||
|
{ |
||||
|
return Marshal.GetHRForException(ex); |
||||
|
} |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
} |
||||
|
internal static ObjectReference<Vftbl> FromAbi(IntPtr thisPtr) => ObjectReference<Vftbl>.FromAbi(thisPtr); |
||||
|
|
||||
|
public static implicit operator IGraphicsEffectD2D1Interop(IObjectReference obj) => (obj != null) ? new IGraphicsEffectD2D1Interop(obj) : null; |
||||
|
protected readonly ObjectReference<Vftbl> _obj; |
||||
|
public IObjectReference ObjRef { get => _obj; } |
||||
|
public IntPtr ThisPtr => _obj.ThisPtr; |
||||
|
|
||||
|
public ObjectReference<I> AsInterface<I>() => _obj.As<I>(); |
||||
|
public A As<A>() => _obj.AsType<A>(); |
||||
|
public IGraphicsEffectD2D1Interop(IObjectReference obj) : this(obj.As<Vftbl>()) { } |
||||
|
internal IGraphicsEffectD2D1Interop(ObjectReference<Vftbl> obj) |
||||
|
{ |
||||
|
_obj = obj; |
||||
|
} |
||||
|
|
||||
|
public Guid EffectId |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
Marshal.ThrowExceptionForHR(_obj.Vftbl.GetEffectId(ThisPtr, out Guid guid)); |
||||
|
return guid; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public uint PropertyCount |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
unsafe |
||||
|
{ |
||||
|
uint count = default; |
||||
|
Marshal.ThrowExceptionForHR(_obj.Vftbl.GetPropertyCount(ThisPtr, &count)); |
||||
|
return count; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public uint SourceCount |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
Marshal.ThrowExceptionForHR(_obj.Vftbl.GetSourceCount(ThisPtr, out uint count)); |
||||
|
return count; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public uint GetNamedPropertyMapping(string name, out global::Windows.Graphics.Effects.Interop.GRAPHICS_EFFECT_PROPERTY_MAPPING mapping) |
||||
|
{ |
||||
|
throw new NotImplementedException(); |
||||
|
} |
||||
|
|
||||
|
public object GetProperty(uint index) |
||||
|
{ |
||||
|
// Marshal.ThrowExceptionForHR(_obj.Vftbl.GetProperty(ThisPtr, index, out IntPtr value));
|
||||
|
throw new NotImplementedException(); |
||||
|
} |
||||
|
|
||||
|
public global::Windows.Graphics.Effects.IGraphicsEffectSource GetSource(uint index) |
||||
|
{ |
||||
|
throw new NotImplementedException(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,35 @@ |
|||||
|
using System; |
||||
|
using Windows.Graphics.Effects; |
||||
|
|
||||
|
|
||||
|
namespace Avalonia.Win32 |
||||
|
{ |
||||
|
class SaturationEffect : EffectBase |
||||
|
{ |
||||
|
public SaturationEffect(IGraphicsEffect source) : base(source) |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
enum D2D1_SATURATION_PROP |
||||
|
{ |
||||
|
D2D1_SATURATION_PROP_SATURATION, |
||||
|
D2D1_SATURATION_PROP_FORCE_DWORD |
||||
|
}; |
||||
|
|
||||
|
public override Guid EffectId => D2DEffects.CLSID_D2D1Saturation; |
||||
|
|
||||
|
public override uint PropertyCount => 1; |
||||
|
|
||||
|
public override object GetProperty(uint index) |
||||
|
{ |
||||
|
switch ((D2D1_SATURATION_PROP)index) |
||||
|
{ |
||||
|
case D2D1_SATURATION_PROP.D2D1_SATURATION_PROP_SATURATION: |
||||
|
return 2.0f; |
||||
|
} |
||||
|
|
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
@ -1,41 +1,191 @@ |
|||||
using System; |
using System; |
||||
|
using System.Threading; |
||||
using Avalonia.Controls.Platform.Surfaces; |
using Avalonia.Controls.Platform.Surfaces; |
||||
using Avalonia.Platform; |
using Avalonia.Platform; |
||||
using Avalonia.Win32.Interop; |
using Avalonia.Win32.Interop; |
||||
|
|
||||
|
#nullable enable |
||||
|
|
||||
namespace Avalonia.Win32 |
namespace Avalonia.Win32 |
||||
{ |
{ |
||||
class FramebufferManager : IFramebufferPlatformSurface, IDisposable |
internal class FramebufferManager : IFramebufferPlatformSurface, IDisposable |
||||
{ |
{ |
||||
|
private const int _bytesPerPixel = 4; |
||||
|
private const PixelFormat _format = PixelFormat.Bgra8888; |
||||
|
|
||||
private readonly IntPtr _hwnd; |
private readonly IntPtr _hwnd; |
||||
private WindowFramebuffer _fb; |
private readonly object _lock; |
||||
|
private readonly Action _onDisposeAction; |
||||
|
|
||||
|
private FramebufferData? _framebufferData; |
||||
|
|
||||
public FramebufferManager(IntPtr hwnd) |
public FramebufferManager(IntPtr hwnd) |
||||
{ |
{ |
||||
_hwnd = hwnd; |
_hwnd = hwnd; |
||||
|
_lock = new object(); |
||||
|
_onDisposeAction = DrawAndUnlock; |
||||
} |
} |
||||
|
|
||||
public ILockedFramebuffer Lock() |
public ILockedFramebuffer Lock() |
||||
{ |
{ |
||||
UnmanagedMethods.GetClientRect(_hwnd, out var rc); |
Monitor.Enter(_lock); |
||||
|
|
||||
var width = Math.Max(1, rc.right - rc.left); |
LockedFramebuffer? fb = null; |
||||
var height = Math.Max(1, rc.bottom - rc.top); |
|
||||
|
|
||||
if ((_fb == null || _fb.Size.Width != width || _fb.Size.Height != height)) |
try |
||||
{ |
{ |
||||
_fb?.Deallocate(); |
UnmanagedMethods.GetClientRect(_hwnd, out var rc); |
||||
_fb = null; |
|
||||
_fb = new WindowFramebuffer(_hwnd, new PixelSize(width, height)); |
var width = Math.Max(1, rc.right - rc.left); |
||||
} |
var height = Math.Max(1, rc.bottom - rc.top); |
||||
|
|
||||
|
if (_framebufferData is null || _framebufferData?.Size.Width != width || _framebufferData?.Size.Height != height) |
||||
|
{ |
||||
|
_framebufferData?.Dispose(); |
||||
|
|
||||
|
_framebufferData = AllocateFramebufferData(width, height); |
||||
|
} |
||||
|
|
||||
|
var framebufferData = _framebufferData.Value; |
||||
|
|
||||
return _fb; |
return fb = new LockedFramebuffer( |
||||
|
framebufferData.Data.Address, framebufferData.Size, framebufferData.RowBytes, |
||||
|
GetCurrentDpi(), _format, _onDisposeAction); |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
// We free the lock when for whatever reason framebuffer was not created.
|
||||
|
// This allows for a potential retry later.
|
||||
|
if (fb is null) |
||||
|
{ |
||||
|
Monitor.Exit(_lock); |
||||
|
} |
||||
|
} |
||||
} |
} |
||||
|
|
||||
public void Dispose() |
public void Dispose() |
||||
{ |
{ |
||||
_fb?.Deallocate(); |
lock (_lock) |
||||
_fb = null; |
{ |
||||
|
_framebufferData?.Dispose(); |
||||
|
_framebufferData = null; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void DrawAndUnlock() |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
if (_framebufferData.HasValue) |
||||
|
DrawToWindow(_hwnd, _framebufferData.Value); |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
Monitor.Exit(_lock); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private Vector GetCurrentDpi() |
||||
|
{ |
||||
|
if (UnmanagedMethods.ShCoreAvailable) |
||||
|
{ |
||||
|
var monitor = |
||||
|
UnmanagedMethods.MonitorFromWindow(_hwnd, UnmanagedMethods.MONITOR.MONITOR_DEFAULTTONEAREST); |
||||
|
|
||||
|
if (UnmanagedMethods.GetDpiForMonitor( |
||||
|
monitor, |
||||
|
UnmanagedMethods.MONITOR_DPI_TYPE.MDT_EFFECTIVE_DPI, |
||||
|
out var dpix, |
||||
|
out var dpiy) == 0) |
||||
|
{ |
||||
|
return new Vector(dpix, dpiy); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return new Vector(96, 96); |
||||
|
} |
||||
|
|
||||
|
private static FramebufferData AllocateFramebufferData(int width, int height) |
||||
|
{ |
||||
|
var bitmapBlob = AvaloniaLocator.Current.GetService<IRuntimePlatform>().AllocBlob(width * height * _bytesPerPixel); |
||||
|
|
||||
|
return new FramebufferData(bitmapBlob, width, height); |
||||
|
} |
||||
|
|
||||
|
private static void DrawToDevice(FramebufferData framebufferData, IntPtr hDC, int destX = 0, int destY = 0, int srcX = 0, |
||||
|
int srcY = 0, int width = -1, |
||||
|
int height = -1) |
||||
|
{ |
||||
|
if (width == -1) |
||||
|
width = framebufferData.Size.Width; |
||||
|
if (height == -1) |
||||
|
height = framebufferData.Size.Height; |
||||
|
|
||||
|
var bmpInfo = framebufferData.Header; |
||||
|
|
||||
|
UnmanagedMethods.SetDIBitsToDevice(hDC, destX, destY, (uint)width, (uint)height, srcX, srcY, |
||||
|
0, (uint)framebufferData.Size.Height, framebufferData.Data.Address, ref bmpInfo, 0); |
||||
|
} |
||||
|
|
||||
|
private static bool DrawToWindow(IntPtr hWnd, FramebufferData framebufferData, int destX = 0, int destY = 0, int srcX = 0, |
||||
|
int srcY = 0, int width = -1, |
||||
|
int height = -1) |
||||
|
{ |
||||
|
if (framebufferData.Data.IsDisposed) |
||||
|
throw new ObjectDisposedException("Framebuffer"); |
||||
|
|
||||
|
if (hWnd == IntPtr.Zero) |
||||
|
return false; |
||||
|
|
||||
|
var hDC = UnmanagedMethods.GetDC(hWnd); |
||||
|
|
||||
|
if (hDC == IntPtr.Zero) |
||||
|
return false; |
||||
|
|
||||
|
try |
||||
|
{ |
||||
|
DrawToDevice(framebufferData, hDC, destX, destY, srcX, srcY, width, height); |
||||
|
} |
||||
|
finally |
||||
|
{ |
||||
|
UnmanagedMethods.ReleaseDC(hWnd, hDC); |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
private readonly struct FramebufferData |
||||
|
{ |
||||
|
public IUnmanagedBlob Data { get; } |
||||
|
|
||||
|
public PixelSize Size { get; } |
||||
|
|
||||
|
public int RowBytes => Size.Width * _bytesPerPixel; |
||||
|
|
||||
|
public UnmanagedMethods.BITMAPINFOHEADER Header { get; } |
||||
|
|
||||
|
public FramebufferData(IUnmanagedBlob data, int width, int height) |
||||
|
{ |
||||
|
Data = data; |
||||
|
Size = new PixelSize(width, height); |
||||
|
|
||||
|
var header = new UnmanagedMethods.BITMAPINFOHEADER(); |
||||
|
header.Init(); |
||||
|
|
||||
|
header.biPlanes = 1; |
||||
|
header.biBitCount = _bytesPerPixel * 8; |
||||
|
header.Init(); |
||||
|
|
||||
|
header.biWidth = width; |
||||
|
header.biHeight = -height; |
||||
|
|
||||
|
Header = header; |
||||
|
} |
||||
|
|
||||
|
public void Dispose() |
||||
|
{ |
||||
|
Data.Dispose(); |
||||
|
} |
||||
} |
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -1,100 +0,0 @@ |
|||||
using System; |
|
||||
using Avalonia.Platform; |
|
||||
using Avalonia.Win32.Interop; |
|
||||
using PixelFormat = Avalonia.Platform.PixelFormat; |
|
||||
|
|
||||
namespace Avalonia.Win32 |
|
||||
{ |
|
||||
public class WindowFramebuffer : ILockedFramebuffer |
|
||||
{ |
|
||||
private readonly IntPtr _handle; |
|
||||
private IUnmanagedBlob _bitmapBlob; |
|
||||
private UnmanagedMethods.BITMAPINFOHEADER _bmpInfo; |
|
||||
|
|
||||
public WindowFramebuffer(IntPtr handle, PixelSize size) |
|
||||
{ |
|
||||
|
|
||||
if (size.Width <= 0) |
|
||||
throw new ArgumentException("Width is less than zero"); |
|
||||
if (size.Height <= 0) |
|
||||
throw new ArgumentException("Height is less than zero"); |
|
||||
_handle = handle; |
|
||||
_bmpInfo.Init(); |
|
||||
_bmpInfo.biPlanes = 1; |
|
||||
_bmpInfo.biBitCount = 32; |
|
||||
_bmpInfo.Init(); |
|
||||
_bmpInfo.biWidth = size.Width; |
|
||||
_bmpInfo.biHeight = -size.Height; |
|
||||
_bitmapBlob = AvaloniaLocator.Current.GetService<IRuntimePlatform>().AllocBlob(size.Width * size.Height * 4); |
|
||||
} |
|
||||
|
|
||||
~WindowFramebuffer() |
|
||||
{ |
|
||||
Deallocate(); |
|
||||
} |
|
||||
|
|
||||
public IntPtr Address => _bitmapBlob.Address; |
|
||||
public int RowBytes => Size.Width * 4; |
|
||||
public PixelFormat Format => PixelFormat.Bgra8888; |
|
||||
|
|
||||
public Vector Dpi |
|
||||
{ |
|
||||
get |
|
||||
{ |
|
||||
if (UnmanagedMethods.ShCoreAvailable) |
|
||||
{ |
|
||||
uint dpix, dpiy; |
|
||||
|
|
||||
var monitor = UnmanagedMethods.MonitorFromWindow(_handle, |
|
||||
UnmanagedMethods.MONITOR.MONITOR_DEFAULTTONEAREST); |
|
||||
|
|
||||
if (UnmanagedMethods.GetDpiForMonitor( |
|
||||
monitor, |
|
||||
UnmanagedMethods.MONITOR_DPI_TYPE.MDT_EFFECTIVE_DPI, |
|
||||
out dpix, |
|
||||
out dpiy) == 0) |
|
||||
{ |
|
||||
return new Vector(dpix, dpiy); |
|
||||
} |
|
||||
} |
|
||||
return new Vector(96, 96); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public PixelSize Size => new PixelSize(_bmpInfo.biWidth, -_bmpInfo.biHeight); |
|
||||
|
|
||||
public void DrawToDevice(IntPtr hDC, int destX = 0, int destY = 0, int srcX = 0, int srcY = 0, int width = -1, |
|
||||
int height = -1) |
|
||||
{ |
|
||||
if (width == -1) |
|
||||
width = Size.Width; |
|
||||
if (height == -1) |
|
||||
height = Size.Height; |
|
||||
UnmanagedMethods.SetDIBitsToDevice(hDC, destX, destY, (uint) width, (uint) height, srcX, srcY, |
|
||||
0, (uint)Size.Height, _bitmapBlob.Address, ref _bmpInfo, 0); |
|
||||
} |
|
||||
|
|
||||
public bool DrawToWindow(IntPtr hWnd, int destX = 0, int destY = 0, int srcX = 0, int srcY = 0, int width = -1, |
|
||||
int height = -1) |
|
||||
{ |
|
||||
if (_bitmapBlob.IsDisposed) |
|
||||
throw new ObjectDisposedException("Framebuffer"); |
|
||||
if (hWnd == IntPtr.Zero) |
|
||||
return false; |
|
||||
IntPtr hDC = UnmanagedMethods.GetDC(hWnd); |
|
||||
if (hDC == IntPtr.Zero) |
|
||||
return false; |
|
||||
DrawToDevice(hDC, destX, destY, srcX, srcY, width, height); |
|
||||
UnmanagedMethods.ReleaseDC(hWnd, hDC); |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
public void Dispose() |
|
||||
{ |
|
||||
//It's not an *actual* dispose. This call means "We are done drawing"
|
|
||||
DrawToWindow(_handle); |
|
||||
} |
|
||||
|
|
||||
public void Deallocate() => _bitmapBlob.Dispose(); |
|
||||
} |
|
||||
} |
|
||||
|
After Width: | Height: | Size: 527 B |
|
After Width: | Height: | Size: 527 B |
Loading…
Reference in new issue