Browse Source
Merge pull request #8538 from AvaloniaUI/feature/expose-gtk-thread-invoke
Introduced GtkInteropHelper.RunOnGlibThread, fixed demos
pull/8540/head
Dan Walmsley
4 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with
42 additions and
12 deletions
-
samples/ControlCatalog.NetCore/NativeControls/Gtk/EmbedSample.Gtk.cs
-
samples/ControlCatalog.NetCore/NativeControls/Gtk/GtkHelper.cs
-
src/Avalonia.X11/Interop/GtkInteropHelper.cs
-
src/Avalonia.X11/NativeDialogs/Gtk.cs
|
|
|
@ -22,8 +22,7 @@ public class EmbedSampleGtk : INativeDemoControl |
|
|
|
|
|
|
|
var control = createDefault(); |
|
|
|
var nodes = Path.GetFullPath(Path.Combine(typeof(EmbedSample).Assembly.GetModules()[0].FullyQualifiedName, |
|
|
|
"..", |
|
|
|
"nodes.mp4")); |
|
|
|
"..", "NativeControls", "Gtk", "nodes.mp4")); |
|
|
|
_mplayer = Process.Start(new ProcessStartInfo("mplayer", |
|
|
|
$"-vo x11 -zoom -loop 0 -wid {control.Handle.ToInt64()} \"{nodes}\"") |
|
|
|
{ |
|
|
|
|
|
|
|
@ -2,6 +2,7 @@ using System; |
|
|
|
using System.Threading.Tasks; |
|
|
|
using Avalonia.Controls.Platform; |
|
|
|
using Avalonia.Platform.Interop; |
|
|
|
using Avalonia.X11.Interop; |
|
|
|
using Avalonia.X11.NativeDialogs; |
|
|
|
using static Avalonia.X11.NativeDialogs.Gtk; |
|
|
|
using static Avalonia.X11.NativeDialogs.Glib; |
|
|
|
@ -10,8 +11,6 @@ namespace ControlCatalog.NetCore; |
|
|
|
|
|
|
|
internal class GtkHelper |
|
|
|
{ |
|
|
|
private static Task<bool> s_gtkTask; |
|
|
|
|
|
|
|
class FileChooser : INativeControlHostDestroyableControlHandle |
|
|
|
{ |
|
|
|
private readonly IntPtr _widget; |
|
|
|
@ -38,11 +37,7 @@ internal class GtkHelper |
|
|
|
|
|
|
|
public static INativeControlHostDestroyableControlHandle CreateGtkFileChooser(IntPtr parentXid) |
|
|
|
{ |
|
|
|
if (s_gtkTask == null) |
|
|
|
s_gtkTask = StartGtk(); |
|
|
|
if (!s_gtkTask.Result) |
|
|
|
return null; |
|
|
|
return RunOnGlibThread(() => |
|
|
|
return GtkInteropHelper.RunOnGlibThread(() => |
|
|
|
{ |
|
|
|
using (var title = new Utf8Buffer("Embedded")) |
|
|
|
{ |
|
|
|
|
|
|
|
@ -0,0 +1,15 @@ |
|
|
|
using System; |
|
|
|
using System.ComponentModel; |
|
|
|
using System.Threading.Tasks; |
|
|
|
|
|
|
|
namespace Avalonia.X11.Interop; |
|
|
|
|
|
|
|
public class GtkInteropHelper |
|
|
|
{ |
|
|
|
public static async Task<T> RunOnGlibThread<T>(Func<T> cb) |
|
|
|
{ |
|
|
|
if (!await NativeDialogs.Gtk.StartGtk().ConfigureAwait(false)) |
|
|
|
throw new Win32Exception("Unable to initialize GTK"); |
|
|
|
return await NativeDialogs.Glib.RunOnGlibThread(cb).ConfigureAwait(false); |
|
|
|
} |
|
|
|
} |
|
|
|
@ -3,6 +3,8 @@ using System.Runtime.InteropServices; |
|
|
|
using System.Threading; |
|
|
|
using System.Threading.Tasks; |
|
|
|
using Avalonia.Platform.Interop; |
|
|
|
using JetBrains.Annotations; |
|
|
|
|
|
|
|
// ReSharper disable IdentifierTypo
|
|
|
|
namespace Avalonia.X11.NativeDialogs |
|
|
|
{ |
|
|
|
@ -256,10 +258,19 @@ namespace Avalonia.X11.NativeDialogs |
|
|
|
|
|
|
|
public static IntPtr GetForeignWindow(IntPtr xid) => gdk_x11_window_foreign_new_for_display(s_display, xid); |
|
|
|
|
|
|
|
static object s_startGtkLock = new(); |
|
|
|
static Task<bool> s_startGtkTask; |
|
|
|
|
|
|
|
public static Task<bool> StartGtk() |
|
|
|
{ |
|
|
|
var tcs = new TaskCompletionSource<bool>(); |
|
|
|
new Thread(() => |
|
|
|
return StartGtkCore(); |
|
|
|
lock (s_startGtkLock) |
|
|
|
return s_startGtkTask ??= StartGtkCore(); |
|
|
|
} |
|
|
|
|
|
|
|
private static void GtkThread(TaskCompletionSource<bool> tcs) |
|
|
|
{ |
|
|
|
try |
|
|
|
{ |
|
|
|
try |
|
|
|
{ |
|
|
|
@ -293,7 +304,17 @@ namespace Avalonia.X11.NativeDialogs |
|
|
|
tcs.SetResult(true); |
|
|
|
while (true) |
|
|
|
gtk_main_iteration(); |
|
|
|
}) {Name = "GTK3THREAD", IsBackground = true}.Start(); |
|
|
|
} |
|
|
|
catch |
|
|
|
{ |
|
|
|
tcs.SetResult(false); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private static Task<bool> StartGtkCore() |
|
|
|
{ |
|
|
|
var tcs = new TaskCompletionSource<bool>(); |
|
|
|
new Thread(() => GtkThread(tcs)) {Name = "GTK3THREAD", IsBackground = true}.Start(); |
|
|
|
return tcs.Task; |
|
|
|
} |
|
|
|
} |
|
|
|
|