Avalonia 처음 써봤는데 힘드네요. WPF랑 비슷하다고 생각했는데 구조가 꽤 많이 다른거같습니다.
자잘한 버그성 문제들이 있는거같고 윈도우랑 리눅스가 약간의 차이를 보이긴합니다.
구현 참고 : 주관적 판단을 배제하라 - 매일 전진하자: Rendering Video in Avalonia's NativeControlHost with SDL2.
Avalonia 처음 써봤는데 힘드네요. WPF랑 비슷하다고 생각했는데 구조가 꽤 많이 다른거같습니다.
자잘한 버그성 문제들이 있는거같고 윈도우랑 리눅스가 약간의 차이를 보이긴합니다.
구현 참고 : 주관적 판단을 배제하라 - 매일 전진하자: Rendering Video in Avalonia's NativeControlHost with SDL2.
간단한 샘플을 봤을땐 비슷하다 생각했었는데…
막상 들어가보려고하니…이것저것 공부해둬야할게 많더라구요~
"자잘한 버그성 문제들이"라고 하셨는데 구체적으로 말씀해주실 수 있나요? Avalonia 를 좀 깊이 있게 공부하고 있어서 살펴보고 싶습니다. 다른 분들도 Avalonia 가 버그가 있다고 말씀하시는데, 저는 아직 발견을 못해서 궁금합니다.
내용이 좀 복잡한데 최대한 간단하게 설명하자면
public class NativeEmbeddingControl : NativeControlHost
{
public IntPtr Handle { get; private set; }
protected override IPlatformHandle CreateNativeControlCore(IPlatformHandle parent)
{
var handle = base.CreateNativeControlCore(parent);
Handle = handle.Handle;
Console.WriteLine($"Handle : {Handle}");
return handle;
}
}
<Window 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"
xmlns:nec="clr-namespace:AvaloniaDXPlayer"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="600"
x:Class="AvaloniaDXPlayer.MainWindow"
Width="800" Height="600" Title="AvaloniaDXPlayer">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="100"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Background="Black">
<TextBlock Text="테스트입니다" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center" />
<nec:NativeEmbeddingControl x:Name="host" Grid.Row="0" IsVisible="True" SizeChanged="Host_SizeChanged" />
</Grid>
<Canvas Grid.Row="1">
<TextBox x:Name="textURL" Margin="10" Width="300" Height="20" FontSize="14" Text="rtsp://admin:!QAZants@192.168.140.46/0"/>
<Button x:Name="btnConnect" Content="Connect" Margin="320,10,0,0" />
<Button x:Name="btnClose" Content="Close" Margin="400,10,0,0" />
<Button x:Name="btnTest" Content="Test" Margin="460,10,0,0" />
</Canvas>
</Grid>
</Window>
이렇게 해서 NativeEmbeddingControl 을 MainWindow 에 삽입했습니다.
이후에 host 에 SDL2 로 렌더링을 하기위해 NativeEmbeddingControl의 Handle 을 사용했습니다.
아래는 SDL2 를 사용하는 c++ 코드입니다.
m_pWindow = SDL_CreateWindowFrom(hwnd); // hwnd == host.Handle(NativeEmbeddingControl.Handle)
m_pWindow 는 SDL_Window* 타입입니다.
이때 렌더링 하기전 m_pWindow의 크기를 얻어오기 위해
SDL_GetWindowSize(m_pWindow, &targetWidth, &targetHeight);
하는데 targetWidth/targetHeight 값이 m_pWindow 즉, host 의 크기여야 하는데 유저가 수동으로 화면을 변경시키기 전까지 엉뚱한 값이 들어옵니다.
똑같은 코드를 윈도우에서 실행하면 잘되는데 리눅스에서는 크기값을 제대로 못 얻어오는 문제가 있습니다.
그리고 host 의 크기를 변경시키면 이전 마지막 변경값이 적용되는 문제도 있는거같습니다.(역시 윈도우에서는 괜찮습니다)
SDL2 버전 문제인가 싶어 최신 SDL2 를 적용해봤는데 같은 현상이네요.
이건 Avalonia 의 버그로 보기 힘들 거 같은데…
일단 제 생각은, CreateNativeControlCore 의 호출 시점 즉, handle 을 넘겨줘서 SDL2 에서 사용하는 시점의 차이에서 발생하는 문제점일 거 같습니다.
즉, 윈도우에서는 초기화가 먼저 일어나서 handle 이 안정적으로 가져올 수 있었고 그 이후에 SDL2 에서 사용하니 문제가 없었지만, 리눅스에서는 그렇게 되지 않는 문제가 발생한 것이라 생각이 듭니다.
이건 사용자 이벤트를 하나더 만들어서, 처리하면 어떨까 생각이 듭니다.
public event EventHandler HandleCreated;
protected override IPlatformHandle CreateNativeControlCore(IPlatformHandle parent)
{
var handle = base.CreateNativeControlCore(parent);
Handle = handle.Handle;
**HandleCreated?.Invoke(this, EventArgs.Empty);**
return handle;
}
nativeEmbeddingControl.HandleCreated += (sender, args) =>
{
** // Handle이 할당된 후에 실행할 로직**
};