| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- using System;
- using System.Runtime.InteropServices;
- using System.Threading;
- using Avalonia.Controls;
- using Avalonia.Controls.Platform;
- using Avalonia.Gtk3;
- using Avalonia.Gtk3.Interop;
- using Avalonia.Input;
- using Avalonia.Input.Platform;
- using Avalonia.OpenGL;
- using Avalonia.Platform;
- using Avalonia.Platform.Interop;
- using Avalonia.Rendering;
- using Avalonia.Threading;
- namespace Avalonia.Gtk3
- {
- public class Gtk3Platform : IWindowingPlatform, IPlatformSettings, IPlatformThreadingInterface
- {
- internal static readonly Gtk3Platform Instance = new Gtk3Platform();
- 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;
- private static bool s_gtkInitialized;
- static bool EnvOption(string option, bool def, bool? specified)
- {
- bool? Parse(string env)
- {
- var v = Environment.GetEnvironmentVariable("AVALONIA_GTK3_" + env);
- if (v == null)
- return null;
- if (v.ToLowerInvariant() == "false" || v == "0")
- return false;
- return true;
- }
- var overridden = Parse(option + "_OVERRIDE");
- if (overridden.HasValue)
- return overridden.Value;
- if (specified.HasValue)
- return specified.Value;
- var envValue = Parse(option);
- return envValue ?? def;
- }
-
- public static void Initialize(Gtk3PlatformOptions options)
- {
- Resolver.Custom = options.CustomResolver;
- UseDeferredRendering = EnvOption("USE_DEFERRED_RENDERING", true, options.UseDeferredRendering);
- var useGpu = EnvOption("USE_GPU", true, options.UseGpuAcceleration);
- if (!s_gtkInitialized)
- {
- try
- {
- X11.XInitThreads();
- }catch{}
- Resolver.Resolve();
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
- using (var backends = new Utf8Buffer("x11"))
- Native.GdkSetAllowedBackends?.Invoke(backends);
- 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.a{Guid.NewGuid().ToString("N")}"))
- App = Native.GtkApplicationNew(utf, 0);
- //Mark current thread as UI thread
- s_tlsMarker = true;
- s_gtkInitialized = true;
- }
- AvaloniaLocator.CurrentMutable.Bind<IWindowingPlatform>().ToConstant(Instance)
- .Bind<IClipboard>().ToSingleton<ClipboardImpl>()
- .Bind<IStandardCursorFactory>().ToConstant(new CursorFactory())
- .Bind<IKeyboardDevice>().ToConstant(Keyboard)
- .Bind<IPlatformSettings>().ToConstant(Instance)
- .Bind<IPlatformThreadingInterface>().ToConstant(Instance)
- .Bind<ISystemDialogImpl>().ToSingleton<SystemDialog>()
- .Bind<IRenderLoop>().ToConstant(new RenderLoop())
- .Bind<IRenderTimer>().ToConstant(new DefaultRenderTimer(60))
- .Bind<PlatformHotkeyConfiguration>().ToSingleton<PlatformHotkeyConfiguration>()
- .Bind<IPlatformIconLoader>().ToConstant(new PlatformIconLoader());
- if (useGpu)
- EglGlPlatformFeature.TryInitialize();
- }
- public IWindowImpl CreateWindow() => new WindowImpl();
- public IEmbeddableWindowImpl CreateEmbeddableWindow()
- {
- throw new NotImplementedException();
- }
- public IPopupImpl CreatePopup() => new PopupImpl();
- public Size DoubleClickSize => new Size(4, 4);
- public TimeSpan DoubleClickTime => TimeSpan.FromMilliseconds(100); //STUB
- public double RenderScalingFactor { get; } = 1;
- public double LayoutScalingFactor { get; } = 1;
- public void RunLoop(CancellationToken cancellationToken)
- {
- while (!cancellationToken.IsCancellationRequested)
- Native.GtkMainIteration();
- }
- public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick)
- {
- var msec = interval.TotalMilliseconds;
- var imsec = (uint) msec;
- if (imsec == 0)
- imsec = 1;
- return GlibTimeout.StartTimer(GlibPriority.FromDispatcherPriority(priority), imsec, tick);
- }
- private bool[] _signaled = new bool[(int) DispatcherPriority.MaxValue + 1];
- object _lock = new object();
- public void Signal(DispatcherPriority prio)
- {
- var idx = (int) prio;
- lock(_lock)
- if (!_signaled[idx])
- {
- _signaled[idx] = true;
- GlibTimeout.Add(GlibPriority.FromDispatcherPriority(prio), 0, () =>
- {
- lock (_lock)
- {
- _signaled[idx] = false;
- }
- Signaled?.Invoke(prio);
- return false;
- });
- }
- }
- public event Action<DispatcherPriority?> Signaled;
- [ThreadStatic]
- private static bool s_tlsMarker;
- public bool CurrentThreadIsLoopThread => s_tlsMarker;
- }
- public class Gtk3PlatformOptions
- {
- public bool? UseDeferredRendering { get; set; }
- public bool? UseGpuAcceleration { get; set; }
- public ICustomGtk3NativeLibraryResolver CustomResolver { get; set; }
- }
- }
- namespace Avalonia
- {
- public static class Gtk3AppBuilderExtensions
- {
- public static T UseGtk3<T>(this AppBuilderBase<T> builder, Gtk3PlatformOptions options = null)
- where T : AppBuilderBase<T>, new()
- {
- return builder.UseWindowingSubsystem(() => Gtk3Platform.Initialize(options ?? new Gtk3PlatformOptions()),
- "GTK3");
- }
- }
- }
|