Browse Source

[GTK3] FÜER

pull/2677/head
Nikita Tsukanov 7 years ago
parent
commit
998ef86a68
  1. 29
      Avalonia.sln
  2. 11
      src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj
  3. 51
      src/Gtk/Avalonia.Gtk3/ClipboardImpl.cs
  4. 84
      src/Gtk/Avalonia.Gtk3/CursorFactory.cs
  5. 62
      src/Gtk/Avalonia.Gtk3/FramebufferManager.cs
  6. 86
      src/Gtk/Avalonia.Gtk3/GdkCursor.cs
  7. 1341
      src/Gtk/Avalonia.Gtk3/GdkKey.cs
  8. 115
      src/Gtk/Avalonia.Gtk3/Gtk3ForeignX11SystemDialog.cs
  9. 168
      src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs
  10. 24
      src/Gtk/Avalonia.Gtk3/GtkScreen.cs
  11. 9
      src/Gtk/Avalonia.Gtk3/IDeferredRenderOperation.cs
  12. 144
      src/Gtk/Avalonia.Gtk3/ImageSurfaceFramebuffer.cs
  13. 20
      src/Gtk/Avalonia.Gtk3/Interop/CairoSurface.cs
  14. 30
      src/Gtk/Avalonia.Gtk3/Interop/GException.cs
  15. 87
      src/Gtk/Avalonia.Gtk3/Interop/GObject.cs
  16. 46
      src/Gtk/Avalonia.Gtk3/Interop/GlibPriority.cs
  17. 58
      src/Gtk/Avalonia.Gtk3/Interop/GlibTimeout.cs
  18. 12
      src/Gtk/Avalonia.Gtk3/Interop/ICustomGtk3NativeLibraryResolver.cs
  19. 37
      src/Gtk/Avalonia.Gtk3/Interop/ManagedCairoSurface.cs
  20. 790
      src/Gtk/Avalonia.Gtk3/Interop/Native.cs
  21. 20
      src/Gtk/Avalonia.Gtk3/Interop/NativeException.cs
  22. 65
      src/Gtk/Avalonia.Gtk3/Interop/Pixbuf.cs
  23. 156
      src/Gtk/Avalonia.Gtk3/Interop/Resolver.cs
  24. 47
      src/Gtk/Avalonia.Gtk3/Interop/Signal.cs
  25. 230
      src/Gtk/Avalonia.Gtk3/KeyTransform.cs
  26. 20
      src/Gtk/Avalonia.Gtk3/PlatformIconLoader.cs
  27. 19
      src/Gtk/Avalonia.Gtk3/PopupImpl.cs
  28. 10
      src/Gtk/Avalonia.Gtk3/Properties/AssemblyInfo.cs
  29. 8
      src/Gtk/Avalonia.Gtk3/README.md
  30. 56
      src/Gtk/Avalonia.Gtk3/ScreenImpl.cs
  31. 110
      src/Gtk/Avalonia.Gtk3/SystemDialogs.cs
  32. 527
      src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs
  33. 102
      src/Gtk/Avalonia.Gtk3/WindowImpl.cs
  34. 78
      src/Gtk/Avalonia.Gtk3/X11.cs
  35. 55
      src/Gtk/Avalonia.Gtk3/X11Framebuffer.cs

29
Avalonia.sln

@ -63,8 +63,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{A689DE
src\Shared\SharedAssemblyInfo.cs = src\Shared\SharedAssemblyInfo.cs
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Gtk", "Gtk", "{B9894058-278A-46B5-B6ED-AD613FCC03B3}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.ReactiveUI", "src\Avalonia.ReactiveUI\Avalonia.ReactiveUI.csproj", "{6417B24E-49C2-4985-8DB2-3AB9D898EC91}"
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "PlatformSupport", "src\Shared\PlatformSupport\PlatformSupport.shproj", "{E4D9629C-F168-4224-3F51-A5E482FFBC42}"
@ -123,8 +121,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.Android", "s
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Skia", "src\Skia\Avalonia.Skia\Avalonia.Skia.csproj", "{7D2D3083-71DD-4CC9-8907-39A0D86FB322}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Gtk3", "src\Gtk\Avalonia.Gtk3\Avalonia.Gtk3.csproj", "{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.NetCore", "samples\ControlCatalog.NetCore\ControlCatalog.NetCore.csproj", "{39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1-27F5-4255-9AFC-04ABFD11683A}"
@ -1318,30 +1314,6 @@ Global
{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Release|iPhone.Build.0 = Release|Any CPU
{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{7D2D3083-71DD-4CC9-8907-39A0D86FB322}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.AppStore|Any CPU.Build.0 = Release|Any CPU
{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.AppStore|iPhone.ActiveCfg = Release|Any CPU
{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.AppStore|iPhone.Build.0 = Release|Any CPU
{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Debug|iPhone.Build.0 = Debug|Any CPU
{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Release|Any CPU.Build.0 = Release|Any CPU
{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Release|iPhone.ActiveCfg = Release|Any CPU
{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Release|iPhone.Build.0 = Release|Any CPU
{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{BB1F7BB5-6AD4-4776-94D9-C09D0A972658}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{39D7B147-1A5B-47C2-9D01-21FB7C47C4B3}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
@ -1911,7 +1883,6 @@ Global
{F1FDC5B0-4654-416F-AE69-E3E9BBD87801} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{29132311-1848-4FD6-AE0C-4FF841151BD3} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{7D2D3083-71DD-4CC9-8907-39A0D86FB322} = {3743B0F2-CC41-4F14-A8C8-267F579BF91E}
{BB1F7BB5-6AD4-4776-94D9-C09D0A972658} = {B9894058-278A-46B5-B6ED-AD613FCC03B3}
{39D7B147-1A5B-47C2-9D01-21FB7C47C4B3} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{854568D5-13D1-4B4F-B50D-534DC7EFD3C9} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
{638580B0-7910-40EF-B674-DCB34DA308CD} = {A0CC0258-D18C-4AB3-854F-7101680FC3F9}

11
src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj

@ -1,11 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<DefineConstants>$(DefineConstants);GTK3_PINVOKE</DefineConstants>
<PackageId>Avalonia.Gtk3</PackageId>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\packages\Avalonia\Avalonia.csproj" />
</ItemGroup>
</Project>

51
src/Gtk/Avalonia.Gtk3/ClipboardImpl.cs

@ -1,51 +0,0 @@
using System;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Avalonia.Gtk3.Interop;
using Avalonia.Input.Platform;
using Avalonia.Platform.Interop;
namespace Avalonia.Gtk3
{
class ClipboardImpl : IClipboard
{
IntPtr GetClipboard() => Native.GtkClipboardGetForDisplay(Native.GdkGetDefaultDisplay(), IntPtr.Zero);
static void OnText(IntPtr clipboard, IntPtr utf8string, IntPtr userdata)
{
var handle = GCHandle.FromIntPtr(userdata);
((TaskCompletionSource<string>) handle.Target)
.TrySetResult(Utf8Buffer.StringFromPtr(utf8string));
handle.Free();
}
private static readonly Native.D.GtkClipboardTextReceivedFunc OnTextDelegate = OnText;
static ClipboardImpl()
{
GCHandle.Alloc(OnTextDelegate);
}
public Task<string> GetTextAsync()
{
var tcs = new TaskCompletionSource<string>();
Native.GtkClipboardRequestText(GetClipboard(), OnTextDelegate, GCHandle.ToIntPtr(GCHandle.Alloc(tcs)));
return tcs.Task;
}
public Task SetTextAsync(string text)
{
using (var buf = new Utf8Buffer(text))
Native.GtkClipboardSetText(GetClipboard(), buf, buf.ByteLen);
return Task.FromResult(0);
}
public Task ClearAsync()
{
Native.GtkClipboardRequestClear(GetClipboard());
return Task.FromResult(0);
}
}
}

84
src/Gtk/Avalonia.Gtk3/CursorFactory.cs

@ -1,84 +0,0 @@
using System;
using System.Collections.Generic;
using Avalonia.Gtk3.Interop;
using Avalonia.Input;
using Avalonia.Platform;
using Avalonia.Platform.Interop;
using CursorType = Avalonia.Gtk3.GdkCursorType;
namespace Avalonia.Gtk3
{
class CursorFactory : IStandardCursorFactory
{
private static readonly Dictionary<StandardCursorType, object> CursorTypeMapping = new Dictionary
<StandardCursorType, object>
{
{StandardCursorType.None, CursorType.Blank},
{StandardCursorType.AppStarting, CursorType.Watch},
{StandardCursorType.Arrow, CursorType.LeftPtr},
{StandardCursorType.Cross, CursorType.Cross},
{StandardCursorType.Hand, CursorType.Hand1},
{StandardCursorType.Ibeam, CursorType.Xterm},
{StandardCursorType.No, "gtk-cancel"},
{StandardCursorType.SizeAll, CursorType.Sizing},
//{ StandardCursorType.SizeNorthEastSouthWest, 32643 },
{StandardCursorType.SizeNorthSouth, CursorType.SbVDoubleArrow},
//{ StandardCursorType.SizeNorthWestSouthEast, 32642 },
{StandardCursorType.SizeWestEast, CursorType.SbHDoubleArrow},
{StandardCursorType.UpArrow, CursorType.BasedArrowUp},
{StandardCursorType.Wait, CursorType.Watch},
{StandardCursorType.Help, "gtk-help"},
{StandardCursorType.TopSide, CursorType.TopSide},
{StandardCursorType.BottomSize, CursorType.BottomSide},
{StandardCursorType.LeftSide, CursorType.LeftSide},
{StandardCursorType.RightSide, CursorType.RightSide},
{StandardCursorType.TopLeftCorner, CursorType.TopLeftCorner},
{StandardCursorType.TopRightCorner, CursorType.TopRightCorner},
{StandardCursorType.BottomLeftCorner, CursorType.BottomLeftCorner},
{StandardCursorType.BottomRightCorner, CursorType.BottomRightCorner},
{StandardCursorType.DragCopy, CursorType.CenterPtr},
{StandardCursorType.DragMove, CursorType.Fleur},
{StandardCursorType.DragLink, CursorType.Cross},
};
private static readonly Dictionary<StandardCursorType, IPlatformHandle> Cache =
new Dictionary<StandardCursorType, IPlatformHandle>();
private IntPtr GetCursor(object desc)
{
IntPtr rv;
var name = desc as string;
if (name != null)
{
var theme = Native.GtkIconThemeGetDefault();
IntPtr icon, error;
using (var u = new Utf8Buffer(name))
icon = Native.GtkIconThemeLoadIcon(theme, u, 32, 0, out error);
rv = icon == IntPtr.Zero
? Native.GdkCursorNew(GdkCursorType.XCursor)
: Native.GdkCursorNewFromPixbuf(Native.GdkGetDefaultDisplay(), icon, 0, 0);
}
else
{
rv = Native.GdkCursorNew((CursorType)desc);
}
return rv;
}
public IPlatformHandle GetCursor(StandardCursorType cursorType)
{
IPlatformHandle rv;
if (!Cache.TryGetValue(cursorType, out rv))
{
Cache[cursorType] =
rv =
new PlatformHandle(
GetCursor(CursorTypeMapping[cursorType]),
"GTKCURSOR");
}
return rv;
}
}
}

62
src/Gtk/Avalonia.Gtk3/FramebufferManager.cs

@ -1,62 +0,0 @@
using System;
using Avalonia.Controls.Platform.Surfaces;
using Avalonia.Platform;
using Avalonia.Threading;
namespace Avalonia.Gtk3
{
class FramebufferManager : IFramebufferPlatformSurface, IDisposable
{
private readonly WindowBaseImpl _window;
public FramebufferManager(WindowBaseImpl window)
{
_window = window;
}
public void Dispose()
{
//
}
public ILockedFramebuffer Lock()
{
// This method may be called from non-UI thread, don't touch anything that calls back to GTK/GDK
var s = _window.ClientSize;
var width = Math.Max(1, (int) s.Width);
var height = Math.Max(1, (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, ref X11.XErrorEvent 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);
}
}
}

86
src/Gtk/Avalonia.Gtk3/GdkCursor.cs

@ -1,86 +0,0 @@
namespace Avalonia.Gtk3
{
enum GdkCursorType
{
Blank = -2,
CursorIsPixmap = -1,
XCursor = 0,
Arrow = 2,
BasedArrowDown = 4,
BasedArrowUp = 6,
Boat = 8,
Bogosity = 10,
BottomLeftCorner = 12,
BottomRightCorner = 14,
BottomSide = 16,
BottomTee = 18,
BoxSpiral = 20,
CenterPtr = 22,
Circle = 24,
Clock = 26,
CoffeeMug = 28,
Cross = 30,
CrossReverse = 32,
Crosshair = 34,
DiamondCross = 36,
Dot = 38,
Dotbox = 40,
DoubleArrow = 42,
DraftLarge = 44,
DraftSmall = 46,
DrapedBox = 48,
Exchange = 50,
Fleur = 52,
Gobbler = 54,
Gumby = 56,
Hand1 = 58,
Hand2 = 60,
Heart = 62,
Icon = 64,
IronCross = 66,
LeftPtr = 68,
LeftSide = 70,
LeftTee = 72,
Leftbutton = 74,
LlAngle = 76,
LrAngle = 78,
Man = 80,
Middlebutton = 82,
Mouse = 84,
Pencil = 86,
Pirate = 88,
Plus = 90,
QuestionArrow = 92,
RightPtr = 94,
RightSide = 96,
RightTee = 98,
Rightbutton = 100,
RtlLogo = 102,
Sailboat = 104,
SbDownArrow = 106,
SbHDoubleArrow = 108,
SbLeftArrow = 110,
SbRightArrow = 112,
SbUpArrow = 114,
SbVDoubleArrow = 116,
Shuttle = 118,
Sizing = 120,
Spider = 122,
Spraycan = 124,
Star = 126,
Target = 128,
Tcross = 130,
TopLeftArrow = 132,
TopLeftCorner = 134,
TopRightCorner = 136,
TopSide = 138,
TopTee = 140,
Trek = 142,
UlAngle = 144,
Umbrella = 146,
UrAngle = 148,
Watch = 150,
Xterm = 152,
LastCursor = 153,
}
}

1341
src/Gtk/Avalonia.Gtk3/GdkKey.cs

File diff suppressed because it is too large

115
src/Gtk/Avalonia.Gtk3/Gtk3ForeignX11SystemDialog.cs

@ -1,115 +0,0 @@
using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Controls.Platform;
using Avalonia.Gtk3.Interop;
using Avalonia.Platform;
using Avalonia.Platform.Interop;
namespace Avalonia.Gtk3
{
public class Gtk3ForeignX11SystemDialog : ISystemDialogImpl
{
private Task<bool> _initialized;
private SystemDialogBase _inner = new SystemDialogBase();
public async Task<string[]> ShowFileDialogAsync(FileDialog dialog, IWindowImpl parent)
{
await EnsureInitialized();
var xid = parent.Handle.Handle;
return await await RunOnGtkThread(
() => _inner.ShowFileDialogAsync(dialog, GtkWindow.Null, chooser => UpdateParent(chooser, xid)));
}
public async Task<string> ShowFolderDialogAsync(OpenFolderDialog dialog, IWindowImpl parent)
{
await EnsureInitialized();
var xid = parent.Handle.Handle;
return await await RunOnGtkThread(
() => _inner.ShowFolderDialogAsync(dialog, GtkWindow.Null, chooser => UpdateParent(chooser, xid)));
}
void UpdateParent(GtkFileChooser chooser, IntPtr xid)
{
Native.GtkWidgetRealize(chooser);
var window = Native.GtkWidgetGetWindow(chooser);
var parent = Native.GdkWindowForeignNewForDisplay(GdkDisplay, xid);
if (window != IntPtr.Zero && parent != IntPtr.Zero)
Native.GdkWindowSetTransientFor(window, parent);
}
async Task EnsureInitialized()
{
if (_initialized == null)
{
var tcs = new TaskCompletionSource<bool>();
_initialized = tcs.Task;
new Thread(() => GtkThread(tcs))
{
IsBackground = true
}.Start();
}
if (!(await _initialized))
throw new Exception("Unable to initialize GTK on separate thread");
}
Task<T> RunOnGtkThread<T>(Func<T> action)
{
var tcs = new TaskCompletionSource<T>();
GlibTimeout.Add(0, 0, () =>
{
try
{
tcs.SetResult(action());
}
catch (Exception e)
{
tcs.TrySetException(e);
}
return false;
});
return tcs.Task;
}
void GtkThread(TaskCompletionSource<bool> tcs)
{
try
{
X11.XInitThreads();
}catch{}
Resolver.Resolve();
if (Native.GdkWindowForeignNewForDisplay == null)
throw new Exception("gdk_x11_window_foreign_new_for_display is not found in your libgdk-3.so");
using (var backends = new Utf8Buffer("x11"))
Native.GdkSetAllowedBackends?.Invoke(backends);
if (!Native.GtkInitCheck(0, IntPtr.Zero))
{
tcs.SetResult(false);
return;
}
using (var utf = new Utf8Buffer($"avalonia.app.a{Guid.NewGuid().ToString("N")}"))
App = Native.GtkApplicationNew(utf, 0);
if (App == IntPtr.Zero)
{
tcs.SetResult(false);
return;
}
GdkDisplay = Native.GdkGetDefaultDisplay();
tcs.SetResult(true);
while (true)
Native.GtkMainIteration();
}
private IntPtr GdkDisplay { get; set; }
private IntPtr App { get; set; }
}
}

168
src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs

@ -1,168 +0,0 @@
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");
}
}
}

24
src/Gtk/Avalonia.Gtk3/GtkScreen.cs

@ -1,24 +0,0 @@
using Avalonia.Platform;
namespace Avalonia.Gtk3
{
public class GtkScreen : Screen
{
private readonly int _screenId;
public GtkScreen(PixelRect bounds, PixelRect workingArea, bool primary, int screenId) : base(bounds, workingArea, primary)
{
this._screenId = screenId;
}
public override int GetHashCode()
{
return _screenId;
}
public override bool Equals(object obj)
{
return (obj is GtkScreen screen) ? this._screenId == screen._screenId : base.Equals(obj);
}
}
}

9
src/Gtk/Avalonia.Gtk3/IDeferredRenderOperation.cs

@ -1,9 +0,0 @@
using System;
namespace Avalonia.Gtk3
{
public interface IDeferredRenderOperation : IDisposable
{
void RenderNow(IntPtr? ctx);
}
}

144
src/Gtk/Avalonia.Gtk3/ImageSurfaceFramebuffer.cs

@ -1,144 +0,0 @@
using System;
using Avalonia.Gtk3.Interop;
using Avalonia.Platform;
using Avalonia.Threading;
namespace Avalonia.Gtk3
{
class ImageSurfaceFramebuffer : ILockedFramebuffer
{
private readonly WindowBaseImpl _impl;
private readonly GtkWidget _widget;
private ManagedCairoSurface _surface;
private int _factor;
private object _lock = new object();
public ImageSurfaceFramebuffer(WindowBaseImpl impl, int width, int height, int factor)
{
_impl = impl;
_widget = impl.GtkWidget;
_factor = factor;
width *= _factor;
height *= _factor;
_surface = new ManagedCairoSurface(width, height);
Size = new PixelSize(width, height);
Address = _surface.Buffer;
RowBytes = _surface.Stride;
Native.CairoSurfaceFlush(_surface.Surface);
}
static void Draw(IntPtr context, CairoSurface surface, double factor)
{
Native.CairoSurfaceMarkDirty(surface);
Native.CairoScale(context, 1d / factor, 1d / factor);
Native.CairoSetSourceSurface(context, surface, 0, 0);
Native.CairoPaint(context);
}
/*
static Stopwatch St =Stopwatch.StartNew();
private static int _frames;
private static int _fps;*/
static void DrawToWidget(GtkWidget widget, CairoSurface surface, int width, int height, double factor)
{
if(surface == null || widget.IsClosed)
return;
var window = Native.GtkWidgetGetWindow(widget);
if(window == IntPtr.Zero)
return;
var rc = new GdkRectangle {Width = width, Height = height};
Native.GdkWindowBeginPaintRect(window, ref rc);
var context = Native.GdkCairoCreate(window);
Draw(context, surface, factor);
/*
_frames++;
var el = St.Elapsed;
if (el.TotalSeconds > 1)
{
_fps = (int) (_frames / el.TotalSeconds);
_frames = 0;
St = Stopwatch.StartNew();
}
Native.CairoSetSourceRgba(context, 1, 0, 0, 1);
Native.CairoMoveTo(context, 20, 20);
Native.CairoSetFontSize(context, 30);
using (var txt = new Utf8Buffer("FPS: " + _fps))
Native.CairoShowText(context, txt);
*/
Native.CairoDestroy(context);
Native.GdkWindowEndPaint(window);
}
class RenderOp : IDeferredRenderOperation
{
private readonly GtkWidget _widget;
private ManagedCairoSurface _surface;
private readonly double _factor;
private readonly int _width;
private readonly int _height;
public RenderOp(GtkWidget widget, ManagedCairoSurface surface, double factor, int width, int height)
{
_widget = widget;
_surface = surface ?? throw new ArgumentNullException(nameof(surface));
_factor = factor;
_width = width;
_height = height;
}
public void Dispose()
{
_surface?.Dispose();
_surface = null;
}
public void RenderNow(IntPtr? ctx)
{
if(ctx.HasValue)
Draw(ctx.Value, _surface.Surface, _factor);
else
DrawToWidget(_widget, _surface.Surface, _width, _height, _factor);
}
}
public void Dispose()
{
lock (_lock)
{
if (Dispatcher.UIThread.CheckAccess())
{
if (_impl.CurrentCairoContext != IntPtr.Zero)
Draw(_impl.CurrentCairoContext, _surface.Surface, _factor);
else
DrawToWidget(_widget, _surface.Surface, Size.Width, Size.Height, _factor);
_surface.Dispose();
}
else
_impl.SetNextRenderOperation(new RenderOp(_widget, _surface, _factor, Size.Width, Size.Height));
_surface = null;
}
}
public IntPtr Address { get; }
public PixelSize Size { get; }
public int RowBytes { get; }
public Vector Dpi
{
get
{
return new Vector(96, 96) * _factor;
}
}
public PixelFormat Format => PixelFormat.Bgra8888;
}
}

20
src/Gtk/Avalonia.Gtk3/Interop/CairoSurface.cs

@ -1,20 +0,0 @@
using System;
using System.Runtime.InteropServices;
namespace Avalonia.Gtk3.Interop
{
class CairoSurface : SafeHandle
{
public CairoSurface() : base(IntPtr.Zero, true)
{
}
protected override bool ReleaseHandle()
{
Native.CairoSurfaceDestroy(handle);
return true;
}
public override bool IsInvalid => handle == IntPtr.Zero;
}
}

30
src/Gtk/Avalonia.Gtk3/Interop/GException.cs

@ -1,30 +0,0 @@
using System;
using System.Runtime.InteropServices;
using Avalonia.Platform.Interop;
namespace Avalonia.Gtk3.Interop
{
public class GException : Exception
{
[StructLayout(LayoutKind.Sequential)]
struct GError
{
UInt32 domain;
int code;
public IntPtr message;
};
static unsafe string GetError(IntPtr error)
{
if (error == IntPtr.Zero)
return "Unknown error";
return Utf8Buffer.StringFromPtr(((GError*) error)->message);
}
public GException(IntPtr error) : base(GetError(error))
{
}
}
}

87
src/Gtk/Avalonia.Gtk3/Interop/GObject.cs

@ -1,87 +0,0 @@
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Avalonia.Gtk3.Interop
{
class GObject : SafeHandle
{
public GObject() : base(IntPtr.Zero, true)
{
}
public GObject(IntPtr handle, bool owned = true) : base(IntPtr.Zero, owned)
{
this.handle = handle;
}
protected override bool ReleaseHandle()
{
if (handle != IntPtr.Zero)
{
Debug.Assert(Native.GTypeCheckInstanceIsFundamentallyA(handle, new IntPtr(Native.G_TYPE_OBJECT)),
"Handle is not a GObject");
Native.GObjectUnref(handle);
}
handle = IntPtr.Zero;
return true;
}
public override bool IsInvalid => handle == IntPtr.Zero;
}
class GInputStream : GObject
{
}
class GtkWidget : GObject
{
}
class GtkWindow : GtkWidget
{
public static GtkWindow Null { get; } = new GtkWindow();
}
class GtkImContext : GObject
{
}
class GdkScreen : GObject
{
public GdkScreen() : base(IntPtr.Zero, false)
{
}
public GdkScreen(IntPtr handle, bool owned = true) : base(handle, owned)
{
this.handle = handle;
}
}
class UnownedGdkScreen : GdkScreen
{
public UnownedGdkScreen() : base(IntPtr.Zero, false)
{
}
public UnownedGdkScreen(IntPtr handle, bool owned = true) : base(IntPtr.Zero, false)
{
this.handle = handle;
}
}
class GtkDialog : GtkWindow
{
}
class GtkFileChooser : GtkDialog
{
}
}

46
src/Gtk/Avalonia.Gtk3/Interop/GlibPriority.cs

@ -1,46 +0,0 @@
using System;
using Avalonia.Threading;
namespace Avalonia.Gtk3.Interop
{
static class GlibPriority
{
public static int High = -100;
public static int Default = 0;
public static int HighIdle = 100;
public static int GtkResize = HighIdle + 10;
public static int GtkPaint = HighIdle + 20;
public static int DefaultIdle = 200;
public static int Low = 300;
public static int GdkEvents = Default;
public static int GdkRedraw = HighIdle + 20;
public static int FromDispatcherPriority(DispatcherPriority prio)
{
if (prio == DispatcherPriority.Send)
return High;
if (prio == DispatcherPriority.Normal)
return Default;
if (prio == DispatcherPriority.DataBind)
return Default + 1;
if (prio == DispatcherPriority.Layout)
return Default + 2;
if (prio == DispatcherPriority.Render)
return Default + 3;
if (prio == DispatcherPriority.Loaded)
return GtkPaint + 20;
if (prio == DispatcherPriority.Input)
return GtkPaint + 21;
if (prio == DispatcherPriority.Background)
return DefaultIdle + 1;
if (prio == DispatcherPriority.ContextIdle)
return DefaultIdle + 2;
if (prio == DispatcherPriority.ApplicationIdle)
return DefaultIdle + 3;
if (prio == DispatcherPriority.SystemIdle)
return DefaultIdle + 4;
throw new ArgumentException("Unknown priority");
}
}
}

58
src/Gtk/Avalonia.Gtk3/Interop/GlibTimeout.cs

@ -1,58 +0,0 @@
using System;
using System.Runtime.InteropServices;
namespace Avalonia.Gtk3.Interop
{
static class GlibTimeout
{
static bool Handler(IntPtr data)
{
var handle = GCHandle.FromIntPtr(data);
var cb = (Func<bool>) handle.Target;
if (!cb())
{
handle.Free();
return false;
}
return true;
}
private static readonly Native.D.timeout_callback PinnedHandler;
static GlibTimeout()
{
PinnedHandler = Handler;
}
public static void Add(int priority, uint interval, Func<bool> callback)
{
var handle = GCHandle.Alloc(callback);
Native.GTimeoutAddFull(priority, interval, PinnedHandler, GCHandle.ToIntPtr(handle), IntPtr.Zero);
}
class Timer : IDisposable
{
public bool Stopped;
public void Dispose()
{
Stopped = true;
}
}
public static IDisposable StartTimer(int priority, uint interval, Action tick)
{
var timer = new Timer ();
GlibTimeout.Add(priority, interval,
() =>
{
if (timer.Stopped)
return false;
tick();
return !timer.Stopped;
});
return timer;
}
}
}

12
src/Gtk/Avalonia.Gtk3/Interop/ICustomGtk3NativeLibraryResolver.cs

@ -1,12 +0,0 @@
using Avalonia.Gtk3.Interop;
namespace Avalonia.Gtk3
{
public interface ICustomGtk3NativeLibraryResolver
{
string GetName(GtkDll dll);
string BasePath { get; }
bool TrySystemFirst { get; }
string Lookup(GtkDll dll);
}
}

37
src/Gtk/Avalonia.Gtk3/Interop/ManagedCairoSurface.cs

@ -1,37 +0,0 @@
using System;
using Avalonia.Platform;
namespace Avalonia.Gtk3.Interop
{
class ManagedCairoSurface : IDisposable
{
public IntPtr Buffer { get; private set; }
public CairoSurface Surface { get; private set; }
public int Stride { get; private set; }
private int _size;
private IRuntimePlatform _plat;
private IUnmanagedBlob _blob;
public ManagedCairoSurface(int width, int height)
{
_plat = AvaloniaLocator.Current.GetService<IRuntimePlatform>();
Stride = width * 4;
_size = height * Stride;
_blob = _plat.AllocBlob(_size * 2);
Buffer = _blob.Address;
Surface = Native.CairoImageSurfaceCreateForData(Buffer, 1, width, height, Stride);
}
public void Dispose()
{
if (Buffer != IntPtr.Zero)
{
Surface.Dispose();
_blob.Dispose();
Buffer = IntPtr.Zero;
}
}
}
}

790
src/Gtk/Avalonia.Gtk3/Interop/Native.cs

@ -1,790 +0,0 @@
#pragma warning disable 649
using System;
using System.Runtime.InteropServices;
using Avalonia.Controls;
using Avalonia.Platform.Interop;
using gdouble = System.Double;
using gint = System.Int32;
using gint16 = System.Int16;
using gint8 = System.Byte;
using guint = System.UInt32;
using guint16 = System.UInt16;
using guint32 = System.UInt32;
namespace Avalonia.Gtk3.Interop
{
static class Native
{
public static class D
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate gint16 gdk_display_get_n_screens(IntPtr display);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate UnownedGdkScreen gdk_display_get_screen(IntPtr display, gint16 num);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate UnownedGdkScreen gdk_display_get_default_screen (IntPtr display);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate gint16 gdk_screen_get_n_monitors(GdkScreen screen);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate gint16 gdk_screen_get_primary_monitor(GdkScreen screen);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate void gdk_screen_get_monitor_geometry(GdkScreen screen, gint16 num, ref GdkRectangle rect);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate void gdk_screen_get_monitor_workarea(GdkScreen screen, gint16 num, ref GdkRectangle rect);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate IntPtr gtk_application_new(Utf8Buffer appId, int flags);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_main_iteration();
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate GtkWindow gtk_window_new(GtkWindowType windowType);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate IntPtr gtk_init(int argc, IntPtr argv);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate bool gtk_init_check(int argc, IntPtr argv);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk, optional: true)]
public delegate IntPtr gdk_set_allowed_backends (Utf8Buffer backends);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_window_present(GtkWindow gtkWindow);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_widget_hide(GtkWidget gtkWidget);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_widget_show(GtkWidget gtkWidget);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_window_set_icon(GtkWindow window, Pixbuf pixbuf);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_window_set_modal(GtkWindow window, bool modal);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_window_set_transient_for(GtkWindow window, IntPtr parent);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] //No manual import
public delegate IntPtr gdk_get_native_handle(IntPtr gdkWindow);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate IntPtr gtk_widget_get_window(GtkWidget gtkWidget);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk, optional: true)]
public delegate uint gtk_widget_get_scale_factor(GtkWidget gtkWidget);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate IntPtr gtk_widget_get_screen(GtkWidget gtkWidget);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate IntPtr gtk_widget_set_double_buffered(GtkWidget gtkWidget, bool value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate IntPtr gtk_widget_set_events(GtkWidget gtkWidget, uint flags);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate int gdk_screen_get_height(IntPtr screen);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate int gdk_screen_get_width(IntPtr screen);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate IntPtr gdk_display_get_default();
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate int gdk_window_get_origin(IntPtr gdkWindow, out int x, out int y);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate void gdk_window_resize(IntPtr gtkWindow, int width, int height);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate void gdk_window_set_override_redirect(IntPtr gdkWindow, bool value);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_widget_realize(GtkWidget gtkWidget);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_window_set_title(GtkWindow gtkWindow, Utf8Buffer title);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_window_set_resizable(GtkWindow gtkWindow, bool resizable);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_window_set_decorated(GtkWindow gtkWindow, bool decorated);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_window_set_skip_taskbar_hint(GtkWindow gtkWindow, bool setting);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate bool gtk_window_get_skip_taskbar_hint(GtkWindow gtkWindow);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_window_set_skip_pager_hint(GtkWindow gtkWindow, bool setting);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate bool gtk_window_get_skip_pager_hint(GtkWindow gtkWindow);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_window_get_size(GtkWindow gtkWindow, out int width, out int height);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_window_resize(GtkWindow gtkWindow, int width, int height);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_widget_set_size_request(GtkWidget widget, int width, int height);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_window_set_default_size(GtkWindow gtkWindow, int width, int height);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_window_get_position(GtkWindow gtkWindow, out int x, out int y);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_window_move(GtkWindow gtkWindow, int x, int y);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate GtkFileChooser gtk_file_chooser_dialog_new(Utf8Buffer title, GtkWindow parent, GtkFileChooserAction action, IntPtr ignore);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public unsafe delegate GSList* gtk_file_chooser_get_filenames(GtkFileChooser chooser);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_file_chooser_set_select_multiple(GtkFileChooser chooser, bool allow);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_file_chooser_set_filename(GtkFileChooser chooser, Utf8Buffer file);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_dialog_add_button(GtkDialog raw, Utf8Buffer button_text, GtkResponseType response_id);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
public delegate CairoSurface cairo_image_surface_create(int format, int width, int height);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
public delegate CairoSurface cairo_image_surface_create_for_data(IntPtr data, int format, int width, int height, int stride);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
public delegate IntPtr cairo_image_surface_get_data(CairoSurface surface);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
public delegate int cairo_image_surface_get_stride(CairoSurface surface);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
public delegate void cairo_surface_mark_dirty(CairoSurface surface);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
public delegate void cairo_surface_write_to_png(CairoSurface surface, Utf8Buffer path);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
public delegate void cairo_surface_flush(CairoSurface surface);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
public delegate void cairo_surface_destroy(IntPtr surface);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
public delegate void cairo_set_source_surface(IntPtr cr, CairoSurface surface, double x, double y);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
public delegate void cairo_set_source_rgba(IntPtr cr, double r, double g, double b, double a);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
public delegate void cairo_scale(IntPtr context, double sx, double sy);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
public delegate void cairo_paint(IntPtr context);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
public delegate void cairo_show_text(IntPtr context, Utf8Buffer text);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
public delegate void cairo_set_font_size(IntPtr context, double size);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
public delegate void cairo_select_font_face(IntPtr context, Utf8Buffer face, int slant, int weight);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
public delegate void cairo_move_to(IntPtr context, double x, double y);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Cairo)]
public delegate void cairo_destroy(IntPtr context);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_widget_queue_draw_area(GtkWidget widget, int x, int y, int width, int height);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate uint gtk_widget_add_tick_callback(GtkWidget widget, TickCallback callback, IntPtr userData, IntPtr destroy);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate uint gtk_widget_remove_tick_callback(GtkWidget widget, uint id);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate GtkImContext gtk_im_multicontext_new();
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate IntPtr gtk_im_context_set_client_window(GtkImContext context, IntPtr window);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate bool gtk_im_context_filter_keypress(GtkImContext context, IntPtr ev);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_widget_activate(GtkWidget widget);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate IntPtr gdk_screen_get_root_window(IntPtr screen);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate IntPtr gdk_cursor_new(GdkCursorType type);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate IntPtr gdk_window_get_pointer(IntPtr raw, out int x, out int y, out int mask);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate GdkWindowState gdk_window_get_state(IntPtr window);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_window_iconify(GtkWindow window);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_window_deiconify(GtkWindow window);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_window_maximize(GtkWindow window);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_window_unmaximize(GtkWindow window);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_window_close(GtkWindow window);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_window_set_keep_above(GtkWindow gtkWindow, bool setting);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_window_set_geometry_hints(GtkWindow window, IntPtr geometry_widget, ref GdkGeometry geometry, GdkWindowHints geom_mask);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate void gdk_window_invalidate_rect(IntPtr window, ref GdkRectangle rect, bool invalidate_children);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate void gdk_window_begin_move_drag(IntPtr window, gint button, gint root_x, gint root_y, guint32 timestamp);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate void gdk_window_begin_resize_drag(IntPtr window, WindowEdge edge, gint button, gint root_x, gint root_y, guint32 timestamp);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate void gdk_window_process_updates(IntPtr window, bool updateChildren);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate void gdk_window_begin_paint_rect(IntPtr window, ref GdkRectangle rect);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate void gdk_window_end_paint(IntPtr window);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk, optional: true)]
public delegate IntPtr gdk_x11_window_foreign_new_for_display(IntPtr display, IntPtr xid);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate void gdk_window_set_transient_for(IntPtr window, IntPtr parent);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate void gdk_event_request_motions(IntPtr ev);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate IntPtr gtk_clipboard_get_for_display(IntPtr display, IntPtr atom);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_clipboard_request_text(IntPtr clipboard, GtkClipboardTextReceivedFunc callback, IntPtr user_data);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_clipboard_set_text(IntPtr clipboard, Utf8Buffer text, int len);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate void gtk_clipboard_clear(IntPtr clipboard);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.GdkPixBuf)]
public delegate IntPtr gdk_pixbuf_new_from_file(Utf8Buffer filename, out IntPtr error);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate IntPtr gtk_icon_theme_get_default();
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gtk)]
public delegate IntPtr gtk_icon_theme_load_icon(IntPtr icon_theme, Utf8Buffer icon_name, gint size, int flags,out IntPtr error);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate IntPtr gdk_cursor_new_from_pixbuf(IntPtr disp, IntPtr pixbuf, int x, int y);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate IntPtr gdk_window_set_cursor(IntPtr window, IntPtr cursor);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.GdkPixBuf)]
public delegate IntPtr gdk_pixbuf_new_from_stream(GInputStream stream, IntPtr cancel, out IntPtr error);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.GdkPixBuf)]
public delegate bool gdk_pixbuf_save_to_bufferv(Pixbuf pixbuf, out IntPtr buffer, out IntPtr buffer_size,
Utf8Buffer type, IntPtr option_keys, IntPtr option_values, out IntPtr error);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gdk)]
public delegate IntPtr gdk_cairo_create(IntPtr window);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gobject)]
public delegate void g_object_unref(IntPtr instance);
[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);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gobject)]
public delegate ulong g_signal_handler_disconnect(GObject instance, ulong connectionId);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Glib)]
public delegate ulong g_timeout_add(uint interval, timeout_callback callback, IntPtr data);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Glib)]
public delegate ulong g_timeout_add_full(int prio, uint interval, timeout_callback callback, IntPtr data, IntPtr destroy);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Glib)]
public delegate ulong g_free(IntPtr data);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gobject)]
public delegate bool g_type_check_instance_is_fundamentally_a(IntPtr instance, IntPtr type);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Glib)]
public unsafe delegate void g_slist_free(GSList* data);
[UnmanagedFunctionPointer(CallingConvention.Cdecl), GtkImport(GtkDll.Gio)]
public delegate GInputStream g_memory_input_stream_new_from_data(IntPtr ptr, IntPtr len, IntPtr destroyCallback);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate bool signal_widget_draw(IntPtr gtkWidget, IntPtr cairoContext, IntPtr userData);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate bool signal_generic(IntPtr gtkWidget, IntPtr userData);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate bool signal_dialog_response(IntPtr gtkWidget, GtkResponseType response, IntPtr userData);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate bool signal_onevent(IntPtr gtkWidget, IntPtr ev, IntPtr userData);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void monitors_changed(IntPtr screen, IntPtr userData);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate bool signal_commit(IntPtr gtkWidget, IntPtr utf8string, IntPtr userData);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate bool timeout_callback(IntPtr data);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void GtkClipboardTextReceivedFunc(IntPtr clipboard, IntPtr utf8string, IntPtr userdata);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate bool TickCallback(IntPtr widget, IntPtr clock, IntPtr userdata);
}
public static D.gdk_display_get_n_screens GdkDisplayGetNScreens;
public static D.gdk_display_get_screen GdkDisplayGetScreen;
public static D.gdk_display_get_default_screen GdkDisplayGetDefaultScreen;
public static D.gdk_screen_get_n_monitors GdkScreenGetNMonitors;
public static D.gdk_screen_get_primary_monitor GdkScreenGetPrimaryMonitor;
public static D.gdk_screen_get_monitor_geometry GdkScreenGetMonitorGeometry;
public static D.gdk_screen_get_monitor_workarea GdkScreenGetMonitorWorkarea;
public static D.gtk_window_set_decorated GtkWindowSetDecorated;
public static D.gtk_window_set_resizable GtkWindowSetResizable;
public static D.gtk_window_set_skip_taskbar_hint GtkWindowSetSkipTaskbarHint;
public static D.gtk_window_get_skip_taskbar_hint GtkWindowGetSkipTaskbarHint;
public static D.gtk_window_set_skip_pager_hint GtkWindowSetSkipPagerHint;
public static D.gtk_window_get_skip_pager_hint GtkWindowGetSkipPagerHint;
public static D.gtk_window_set_title GtkWindowSetTitle;
public static D.gtk_application_new GtkApplicationNew;
public static D.gtk_main_iteration GtkMainIteration;
public static D.gtk_window_new GtkWindowNew;
public static D.gtk_window_set_icon GtkWindowSetIcon;
public static D.gtk_window_set_modal GtkWindowSetModal;
public static D.gtk_window_set_transient_for GtkWindowSetTransientFor;
public static D.gdk_set_allowed_backends GdkSetAllowedBackends;
public static D.gtk_init GtkInit;
public static D.gtk_init_check GtkInitCheck;
public static D.gtk_window_present GtkWindowPresent;
public static D.gtk_widget_hide GtkWidgetHide;
public static D.gtk_widget_show GtkWidgetShow;
public static D.gdk_get_native_handle GetNativeGdkWindowHandle;
public static D.gtk_widget_get_window GtkWidgetGetWindow;
public static D.gtk_widget_get_scale_factor GtkWidgetGetScaleFactor;
public static D.gtk_widget_get_screen GtkWidgetGetScreen;
public static D.gtk_widget_realize GtkWidgetRealize;
public static D.gtk_window_get_size GtkWindowGetSize;
public static D.gtk_window_resize GtkWindowResize;
public static D.gdk_window_resize GdkWindowResize;
public static D.gdk_window_set_override_redirect GdkWindowSetOverrideRedirect;
public static D.gtk_widget_set_size_request GtkWindowSetSizeRequest;
public static D.gtk_window_set_default_size GtkWindowSetDefaultSize;
public static D.gtk_window_set_geometry_hints GtkWindowSetGeometryHints;
public static D.gtk_window_get_position GtkWindowGetPosition;
public static D.gtk_window_move GtkWindowMove;
public static D.gtk_file_chooser_dialog_new GtkFileChooserDialogNew;
public static D.gtk_file_chooser_set_select_multiple GtkFileChooserSetSelectMultiple;
public static D.gtk_file_chooser_set_filename GtkFileChooserSetFilename;
public static D.gtk_file_chooser_get_filenames GtkFileChooserGetFilenames;
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;
public static D.g_timeout_add_full GTimeoutAddFull;
public static D.g_free GFree;
public static D.g_type_check_instance_is_fundamentally_a GTypeCheckInstanceIsFundamentallyA;
public static D.g_slist_free GSlistFree;
public static D.g_memory_input_stream_new_from_data GMemoryInputStreamNewFromData;
public static D.gtk_widget_set_double_buffered GtkWidgetSetDoubleBuffered;
public static D.gtk_widget_set_events GtkWidgetSetEvents;
public static D.gdk_window_invalidate_rect GdkWindowInvalidateRect;
public static D.gtk_widget_queue_draw_area GtkWidgetQueueDrawArea;
public static D.gtk_widget_add_tick_callback GtkWidgetAddTickCallback;
public static D.gtk_widget_remove_tick_callback GtkWidgetRemoveTickCallback;
public static D.gtk_widget_activate GtkWidgetActivate;
public static D.gtk_clipboard_get_for_display GtkClipboardGetForDisplay;
public static D.gtk_clipboard_request_text GtkClipboardRequestText;
public static D.gtk_clipboard_set_text GtkClipboardSetText;
public static D.gtk_clipboard_clear GtkClipboardRequestClear;
public static D.gtk_im_multicontext_new GtkImMulticontextNew;
public static D.gtk_im_context_filter_keypress GtkImContextFilterKeypress;
public static D.gtk_im_context_set_client_window GtkImContextSetClientWindow;
public static D.gdk_screen_get_height GdkScreenGetHeight;
public static D.gdk_display_get_default GdkGetDefaultDisplay;
public static D.gdk_screen_get_width GdkScreenGetWidth;
public static D.gdk_screen_get_root_window GdkScreenGetRootWindow;
public static D.gdk_cursor_new GdkCursorNew;
public static D.gdk_window_get_origin GdkWindowGetOrigin;
public static D.gdk_window_get_pointer GdkWindowGetPointer;
public static D.gdk_window_get_state GdkWindowGetState;
public static D.gtk_window_iconify GtkWindowIconify;
public static D.gtk_window_deiconify GtkWindowDeiconify;
public static D.gtk_window_maximize GtkWindowMaximize;
public static D.gtk_window_unmaximize GtkWindowUnmaximize;
public static D.gtk_window_close GtkWindowClose;
public static D.gtk_window_set_keep_above GtkWindowSetKeepAbove;
public static D.gdk_window_begin_move_drag GdkWindowBeginMoveDrag;
public static D.gdk_window_begin_resize_drag GdkWindowBeginResizeDrag;
public static D.gdk_event_request_motions GdkEventRequestMotions;
public static D.gdk_window_process_updates GdkWindowProcessUpdates;
public static D.gdk_window_begin_paint_rect GdkWindowBeginPaintRect;
public static D.gdk_window_end_paint GdkWindowEndPaint;
public static D.gdk_x11_window_foreign_new_for_display GdkWindowForeignNewForDisplay;
public static D.gdk_window_set_transient_for GdkWindowSetTransientFor;
public static D.gdk_pixbuf_new_from_file GdkPixbufNewFromFile;
public static D.gtk_icon_theme_get_default GtkIconThemeGetDefault;
public static D.gtk_icon_theme_load_icon GtkIconThemeLoadIcon;
public static D.gdk_cursor_new_from_pixbuf GdkCursorNewFromPixbuf;
public static D.gdk_window_set_cursor GdkWindowSetCursor;
public static D.gdk_pixbuf_new_from_stream GdkPixbufNewFromStream;
public static D.gdk_pixbuf_save_to_bufferv GdkPixbufSaveToBufferv;
public static D.gdk_cairo_create GdkCairoCreate;
public static D.cairo_image_surface_create CairoImageSurfaceCreate;
public static D.cairo_image_surface_create_for_data CairoImageSurfaceCreateForData;
public static D.cairo_image_surface_get_data CairoImageSurfaceGetData;
public static D.cairo_image_surface_get_stride CairoImageSurfaceGetStride;
public static D.cairo_surface_mark_dirty CairoSurfaceMarkDirty;
public static D.cairo_surface_write_to_png CairoSurfaceWriteToPng;
public static D.cairo_surface_flush CairoSurfaceFlush;
public static D.cairo_surface_destroy CairoSurfaceDestroy;
public static D.cairo_set_source_surface CairoSetSourceSurface;
public static D.cairo_set_source_rgba CairoSetSourceRgba;
public static D.cairo_scale CairoScale;
public static D.cairo_paint CairoPaint;
public static D.cairo_show_text CairoShowText;
public static D.cairo_select_font_face CairoSelectFontFace;
public static D.cairo_set_font_size CairoSetFontSize;
public static D.cairo_move_to CairoMoveTo;
public static D.cairo_destroy CairoDestroy;
public const int G_TYPE_OBJECT = 80;
}
public enum GtkWindowType
{
TopLevel,
Popup
}
[StructLayout(LayoutKind.Sequential)]
public struct GdkRectangle
{
public int X, Y, Width, Height;
public static GdkRectangle FromRect(Rect rect)
{
return new GdkRectangle
{
X = (int) rect.X,
Y = (int) rect.Y,
Width = (int) rect.Width,
Height = (int) rect.Height
};
}
}
enum GdkEventType
{
Nothing = -1,
Delete = 0,
Destroy = 1,
Expose = 2,
MotionNotify = 3,
ButtonPress = 4,
TwoButtonPress = 5,
ThreeButtonPress = 6,
ButtonRelease = 7,
KeyPress = 8,
KeyRelease = 9,
EnterNotify = 10,
LeaveNotify = 11,
FocusChange = 12,
Configure = 13,
Map = 14,
Unmap = 15,
PropertyNotify = 16,
SelectionClear = 17,
SelectionRequest = 18,
SelectionNotify = 19,
ProximityIn = 20,
ProximityOut = 21,
DragEnter = 22,
DragLeave = 23,
DragMotion = 24,
DragStatus = 25,
DropStart = 26,
DropFinished = 27,
ClientEvent = 28,
VisibilityNotify = 29,
NoExpose = 30,
Scroll = 31,
WindowState = 32,
Setting = 33,
OwnerChange = 34,
GrabBroken = 35,
}
enum GdkModifierType
{
ShiftMask = 1,
LockMask = 2,
ControlMask = 4,
Mod1Mask = 8,
Mod2Mask = 16,
Mod3Mask = 32,
Mod4Mask = 64,
Mod5Mask = 128,
Button1Mask = 256,
Button2Mask = 512,
Button3Mask = 1024,
Button4Mask = 2048,
Button5Mask = 4096,
SuperMask = 67108864,
HyperMask = 134217728,
MetaMask = 268435456,
ReleaseMask = 1073741824,
ModifierMask = ReleaseMask | Button5Mask | Button4Mask | Button3Mask | Button2Mask | Button1Mask | Mod5Mask | Mod4Mask | Mod3Mask | Mod2Mask | Mod1Mask | ControlMask | LockMask | ShiftMask,
None = 0,
}
enum GdkScrollDirection
{
Up,
Down,
Left,
Right,
Smooth
}
[StructLayout(LayoutKind.Sequential)]
unsafe struct GdkEventButton
{
public GdkEventType type;
public IntPtr window;
public gint8 send_event;
public guint32 time;
public gdouble x;
public gdouble y;
public gdouble* axes;
public GdkModifierType state;
public guint button;
public IntPtr device;
public gdouble x_root, y_root;
}
[StructLayout(LayoutKind.Sequential)]
unsafe struct GdkEventMotion
{
public GdkEventType type;
public IntPtr window;
public gint8 send_event;
public guint32 time;
public gdouble x;
public gdouble y;
public gdouble* axes;
public GdkModifierType state;
public gint16 is_hint;
public IntPtr device;
public gdouble x_root, y_root;
}
[StructLayout(LayoutKind.Sequential)]
unsafe struct GdkEventScroll
{
public GdkEventType type;
public IntPtr window;
public gint8 send_event;
public guint32 time;
public gdouble x;
public gdouble y;
public GdkModifierType state;
public GdkScrollDirection direction;
public IntPtr device;
public gdouble x_root, y_root;
public gdouble delta_x;
public gdouble delta_y;
}
[StructLayout(LayoutKind.Sequential)]
unsafe struct GdkEventCrossing
{
public GdkEventType type;
public IntPtr window;
public gint8 send_event;
public IntPtr subwindow;
public guint32 time;
public gdouble x;
public gdouble y;
public gdouble x_root;
public gdouble y_root;
public int mode;
public int detail;
public bool focus;
public GdkModifierType state;
};
[StructLayout(LayoutKind.Sequential)]
unsafe struct GdkEventWindowState
{
public GdkEventType type;
public IntPtr window;
gint8 send_event;
public GdkWindowState changed_mask;
public GdkWindowState new_window_state;
}
[StructLayout(LayoutKind.Sequential)]
unsafe struct GdkEventKey
{
public GdkEventType type;
public IntPtr window;
public gint8 send_event;
public guint32 time;
public guint state;
public guint keyval;
public gint length;
public IntPtr pstring;
public guint16 hardware_keycode;
public byte group;
public guint is_modifier;
}
[StructLayout(LayoutKind.Sequential)]
unsafe struct GSList
{
public IntPtr Data;
public GSList* Next;
}
[Flags]
public enum GdkWindowState
{
Withdrawn = 1,
Iconified = 2,
Maximized = 4,
Sticky = 8,
Fullscreen = 16,
Above = 32,
Below = 64,
Focused = 128,
Ttiled = 256
}
public enum GtkResponseType
{
Help = -11,
Apply = -10,
No = -9,
Yes = -8,
Close = -7,
Cancel = -6,
Ok = -5,
DeleteEvent = -4,
Accept = -3,
Reject = -2,
None = -1,
}
public enum GtkFileChooserAction
{
Open,
Save,
SelectFolder,
CreateFolder,
}
[StructLayout(LayoutKind.Sequential)]
public struct GdkGeometry
{
public gint min_width;
public gint min_height;
public gint max_width;
public gint max_height;
public gint base_width;
public gint base_height;
public gint width_inc;
public gint height_inc;
public gdouble min_aspect;
public gdouble max_aspect;
public gint win_gravity;
}
enum GdkWindowHints
{
GDK_HINT_POS = 1 << 0,
GDK_HINT_MIN_SIZE = 1 << 1,
GDK_HINT_MAX_SIZE = 1 << 2,
GDK_HINT_BASE_SIZE = 1 << 3,
GDK_HINT_ASPECT = 1 << 4,
GDK_HINT_RESIZE_INC = 1 << 5,
GDK_HINT_WIN_GRAVITY = 1 << 6,
GDK_HINT_USER_POS = 1 << 7,
GDK_HINT_USER_SIZE = 1 << 8
}
}

20
src/Gtk/Avalonia.Gtk3/Interop/NativeException.cs

@ -1,20 +0,0 @@
using System;
namespace Avalonia.Gtk3.Interop
{
public class NativeException : Exception
{
public NativeException()
{
}
public NativeException(string message) : base(message)
{
}
public NativeException(string message, Exception inner) : base(message, inner)
{
}
}
}

65
src/Gtk/Avalonia.Gtk3/Interop/Pixbuf.cs

@ -1,65 +0,0 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
using Avalonia.Platform;
using Avalonia.Platform.Interop;
namespace Avalonia.Gtk3.Interop
{
internal class Pixbuf : GObject, IWindowIconImpl
{
Pixbuf(IntPtr handle) : base(handle)
{
}
public static Pixbuf NewFromFile(string filename)
{
using (var ub = new Utf8Buffer(filename))
{
IntPtr err;
var rv = Native.GdkPixbufNewFromFile(ub, out err);
if(rv != IntPtr.Zero)
return new Pixbuf(rv);
throw new GException(err);
}
}
public static unsafe Pixbuf NewFromBytes(byte[] data)
{
fixed (void* bytes = data)
{
using (var stream = Native.GMemoryInputStreamNewFromData(new IntPtr(bytes), new IntPtr(data.Length), IntPtr.Zero))
{
IntPtr err;
var rv = Native.GdkPixbufNewFromStream(stream, IntPtr.Zero, out err);
if (rv != IntPtr.Zero)
return new Pixbuf(rv);
throw new GException(err);
}
}
}
public static Pixbuf NewFromStream(Stream s)
{
if (s is MemoryStream)
return NewFromBytes(((MemoryStream) s).ToArray());
var ms = new MemoryStream();
s.CopyTo(ms);
return NewFromBytes(ms.ToArray());
}
public void Save(Stream outputStream)
{
IntPtr buffer, bufferLen, error;
using (var png = new Utf8Buffer("png"))
if (!Native.GdkPixbufSaveToBufferv(this, out buffer, out bufferLen, png,
IntPtr.Zero, IntPtr.Zero, out error))
throw new GException(error);
var data = new byte[bufferLen.ToInt32()];
Marshal.Copy(buffer, data, 0, bufferLen.ToInt32());
Native.GFree(buffer);
outputStream.Write(data, 0, data.Length);
}
}
}

156
src/Gtk/Avalonia.Gtk3/Interop/Resolver.cs

@ -1,156 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using Avalonia.Platform;
using Avalonia.Platform.Interop;
namespace Avalonia.Gtk3.Interop
{
internal class GtkImportAttribute : Attribute
{
public GtkDll Dll { get; set; }
public string Name { get; set; }
public bool Optional { get; set; }
public GtkImportAttribute(GtkDll dll, string name = null, bool optional = false)
{
Dll = dll;
Name = name;
Optional = optional;
}
}
public enum GtkDll
{
Gdk,
Gtk,
Glib,
Gio,
Gobject,
Cairo,
GdkPixBuf
}
static class Resolver
{
private static Lazy<OperatingSystemType> Platform =
new Lazy<OperatingSystemType>(
() => AvaloniaLocator.Current.GetService<IRuntimePlatform>().GetRuntimeInfo().OperatingSystem);
public static ICustomGtk3NativeLibraryResolver Custom { get; set; }
static string FormatName(string name, int version = 0)
{
if (Platform.Value == OperatingSystemType.WinNT)
return "lib" + name + "-" + version + ".dll";
if (Platform.Value == OperatingSystemType.Linux)
return "lib" + name + ".so" + "." + version;
if (Platform.Value == OperatingSystemType.OSX)
return "lib" + name + "." + version + ".dylib";
throw new Exception("Unknown platform, use custom name resolver");
}
static string GetDllName(GtkDll dll)
{
var name = Custom?.GetName(dll);
if (name != null)
return name;
switch (dll)
{
case GtkDll.Cairo:
return FormatName("cairo", 2);
case GtkDll.Gdk:
return FormatName("gdk-3");
case GtkDll.Glib:
return FormatName("glib-2.0");
case GtkDll.Gio:
return FormatName("gio-2.0");
case GtkDll.Gtk:
return FormatName("gtk-3");
case GtkDll.Gobject:
return FormatName("gobject-2.0");
case GtkDll.GdkPixBuf:
return FormatName("gdk_pixbuf-2.0");
default:
throw new ArgumentException("Unknown lib: " + dll);
}
}
static IntPtr LoadDll(IDynamicLibraryLoader loader, GtkDll dll)
{
var exceptions = new List<Exception>();
var name = GetDllName(dll);
if (Custom?.TrySystemFirst != false)
{
try
{
return loader.LoadLibrary(name);
}
catch (Exception e)
{
exceptions.Add(e);
}
}
var path = Custom?.Lookup(dll);
if (path == null && Custom?.BasePath != null)
path = Path.Combine(Custom.BasePath, name);
if (path != null)
{
try
{
return loader.LoadLibrary(path);
}
catch (Exception e)
{
exceptions.Add(e);
}
}
throw new AggregateException("Unable to load " + dll, exceptions);
}
public static void Resolve(string basePath = null)
{
var loader = AvaloniaLocator.Current.GetService<IDynamicLibraryLoader>();
var dlls = Enum.GetValues(typeof(GtkDll)).Cast<GtkDll>().ToDictionary(x => x, x => LoadDll(loader, x));
foreach (var fieldInfo in typeof(Native).GetTypeInfo().DeclaredFields)
{
var import = fieldInfo.FieldType.GetTypeInfo().GetCustomAttributes(typeof(GtkImportAttribute), true).Cast<GtkImportAttribute>().FirstOrDefault();
if(import == null)
continue;
IntPtr lib = dlls[import.Dll];
var funcPtr = loader.GetProcAddress(lib, import.Name ?? fieldInfo.FieldType.Name, import.Optional);
if (funcPtr != IntPtr.Zero)
fieldInfo.SetValue(null, Marshal.GetDelegateForFunctionPointer(funcPtr, fieldInfo.FieldType));
}
var nativeHandleNames = new[] { "gdk_win32_window_get_handle", "gdk_x11_window_get_xid", "gdk_quartz_window_get_nswindow" };
foreach (var name in nativeHandleNames)
{
var ptr = loader.GetProcAddress(dlls[GtkDll.Gdk], name, true);
if (ptr == IntPtr.Zero)
continue;
Native.GetNativeGdkWindowHandle = (Native.D.gdk_get_native_handle) Marshal
.GetDelegateForFunctionPointer(ptr, typeof(Native.D.gdk_get_native_handle));
}
if (Native.GetNativeGdkWindowHandle == null)
throw new Exception($"Unable to locate any of [{string.Join(", ", nativeHandleNames)}] in libgdk");
}
}
}

47
src/Gtk/Avalonia.Gtk3/Interop/Signal.cs

@ -1,47 +0,0 @@
using System;
using System.Runtime.InteropServices;
using Avalonia.Platform.Interop;
namespace Avalonia.Gtk3.Interop
{
class Signal
{
class ConnectedSignal : IDisposable
{
private readonly GObject _instance;
private GCHandle _handle;
private readonly ulong _id;
public ConnectedSignal(GObject instance, GCHandle handle, ulong id)
{
_instance = instance;
Native.GObjectRef(instance);
_handle = handle;
_id = id;
}
public void Dispose()
{
if (_handle.IsAllocated)
{
Native.GObjectUnref(_instance.DangerousGetHandle());
Native.GSignalHandlerDisconnect(_instance, _id);
_handle.Free();
}
}
}
public static IDisposable Connect<T>(GObject obj, string name, T handler)
{
var handle = GCHandle.Alloc(handler);
var ptr = Marshal.GetFunctionPointerForDelegate((Delegate)(object)handler);
using (var utf = new Utf8Buffer(name))
{
var id = Native.GSignalConnectObject(obj, utf, ptr, IntPtr.Zero, 0);
if (id == 0)
throw new ArgumentException("Unable to connect to signal " + name);
return new ConnectedSignal(obj, handle, id);
}
}
}
}

230
src/Gtk/Avalonia.Gtk3/KeyTransform.cs

@ -1,230 +0,0 @@
using System.Collections.Generic;
using Avalonia.Gtk3;
using Avalonia.Input;
namespace Avalonia.Gtk.Common
{
static class KeyTransform
{
private static readonly Dictionary<GdkKey, Key> KeyDic = new Dictionary<GdkKey, Key>
{
{ GdkKey.Cancel, Key.Cancel },
{ GdkKey.BackSpace, Key.Back },
{ GdkKey.Tab, Key.Tab },
{ GdkKey.Linefeed, Key.LineFeed },
{ GdkKey.Clear, Key.Clear },
{ GdkKey.Return, Key.Return },
{ GdkKey.KP_Enter, Key.Return },
{ GdkKey.Pause, Key.Pause },
{ GdkKey.Caps_Lock, Key.CapsLock },
//{ GdkKey.?, Key.HangulMode }
//{ GdkKey.?, Key.JunjaMode }
//{ GdkKey.?, Key.FinalMode }
//{ GdkKey.?, Key.KanjiMode }
{ GdkKey.Escape, Key.Escape },
//{ GdkKey.?, Key.ImeConvert }
//{ GdkKey.?, Key.ImeNonConvert }
//{ GdkKey.?, Key.ImeAccept }
//{ GdkKey.?, Key.ImeModeChange }
{ GdkKey.space, Key.Space },
{ GdkKey.Prior, Key.Prior },
{ GdkKey.KP_Prior, Key.Prior },
{ GdkKey.Page_Down, Key.PageDown },
{ GdkKey.KP_Page_Down, Key.PageDown },
{ GdkKey.End, Key.End },
{ GdkKey.KP_End, Key.End },
{ GdkKey.Home, Key.Home },
{ GdkKey.KP_Home, Key.Home },
{ GdkKey.Left, Key.Left },
{ GdkKey.KP_Left, Key.Left },
{ GdkKey.Up, Key.Up },
{ GdkKey.KP_Up, Key.Up },
{ GdkKey.Right, Key.Right },
{ GdkKey.KP_Right, Key.Right },
{ GdkKey.Down, Key.Down },
{ GdkKey.KP_Down, Key.Down },
{ GdkKey.Select, Key.Select },
{ GdkKey.Print, Key.Print },
{ GdkKey.Execute, Key.Execute },
//{ GdkKey.?, Key.Snapshot }
{ GdkKey.Insert, Key.Insert },
{ GdkKey.KP_Insert, Key.Insert },
{ GdkKey.Delete, Key.Delete },
{ GdkKey.KP_Delete, Key.Delete },
{ GdkKey.Help, Key.Help },
{ GdkKey.Key_0, Key.D0 },
{ GdkKey.Key_1, Key.D1 },
{ GdkKey.Key_2, Key.D2 },
{ GdkKey.Key_3, Key.D3 },
{ GdkKey.Key_4, Key.D4 },
{ GdkKey.Key_5, Key.D5 },
{ GdkKey.Key_6, Key.D6 },
{ GdkKey.Key_7, Key.D7 },
{ GdkKey.Key_8, Key.D8 },
{ GdkKey.Key_9, Key.D9 },
{ GdkKey.A, Key.A },
{ GdkKey.B, Key.B },
{ GdkKey.C, Key.C },
{ GdkKey.D, Key.D },
{ GdkKey.E, Key.E },
{ GdkKey.F, Key.F },
{ GdkKey.G, Key.G },
{ GdkKey.H, Key.H },
{ GdkKey.I, Key.I },
{ GdkKey.J, Key.J },
{ GdkKey.K, Key.K },
{ GdkKey.L, Key.L },
{ GdkKey.M, Key.M },
{ GdkKey.N, Key.N },
{ GdkKey.O, Key.O },
{ GdkKey.P, Key.P },
{ GdkKey.Q, Key.Q },
{ GdkKey.R, Key.R },
{ GdkKey.S, Key.S },
{ GdkKey.T, Key.T },
{ GdkKey.U, Key.U },
{ GdkKey.V, Key.V },
{ GdkKey.W, Key.W },
{ GdkKey.X, Key.X },
{ GdkKey.Y, Key.Y },
{ GdkKey.Z, Key.Z },
{ GdkKey.a, Key.A },
{ GdkKey.b, Key.B },
{ GdkKey.c, Key.C },
{ GdkKey.d, Key.D },
{ GdkKey.e, Key.E },
{ GdkKey.f, Key.F },
{ GdkKey.g, Key.G },
{ GdkKey.h, Key.H },
{ GdkKey.i, Key.I },
{ GdkKey.j, Key.J },
{ GdkKey.k, Key.K },
{ GdkKey.l, Key.L },
{ GdkKey.m, Key.M },
{ GdkKey.n, Key.N },
{ GdkKey.o, Key.O },
{ GdkKey.p, Key.P },
{ GdkKey.q, Key.Q },
{ GdkKey.r, Key.R },
{ GdkKey.s, Key.S },
{ GdkKey.t, Key.T },
{ GdkKey.u, Key.U },
{ GdkKey.v, Key.V },
{ GdkKey.w, Key.W },
{ GdkKey.x, Key.X },
{ GdkKey.y, Key.Y },
{ GdkKey.z, Key.Z },
//{ GdkKey.?, Key.LWin }
//{ GdkKey.?, Key.RWin }
{ GdkKey.Menu, Key.Apps },
//{ GdkKey.?, Key.Sleep }
{ GdkKey.KP_0, Key.NumPad0 },
{ GdkKey.KP_1, Key.NumPad1 },
{ GdkKey.KP_2, Key.NumPad2 },
{ GdkKey.KP_3, Key.NumPad3 },
{ GdkKey.KP_4, Key.NumPad4 },
{ GdkKey.KP_5, Key.NumPad5 },
{ GdkKey.KP_6, Key.NumPad6 },
{ GdkKey.KP_7, Key.NumPad7 },
{ GdkKey.KP_8, Key.NumPad8 },
{ GdkKey.KP_9, Key.NumPad9 },
{ GdkKey.multiply, Key.Multiply },
{ GdkKey.KP_Multiply, Key.Multiply },
{ GdkKey.KP_Add, Key.Add },
//{ GdkKey.?, Key.Separator }
{ GdkKey.KP_Subtract, Key.Subtract },
{ GdkKey.KP_Decimal, Key.Decimal },
{ GdkKey.KP_Divide, Key.Divide },
{ GdkKey.F1, Key.F1 },
{ GdkKey.F2, Key.F2 },
{ GdkKey.F3, Key.F3 },
{ GdkKey.F4, Key.F4 },
{ GdkKey.F5, Key.F5 },
{ GdkKey.F6, Key.F6 },
{ GdkKey.F7, Key.F7 },
{ GdkKey.F8, Key.F8 },
{ GdkKey.F9, Key.F9 },
{ GdkKey.F10, Key.F10 },
{ GdkKey.F11, Key.F11 },
{ GdkKey.F12, Key.F12 },
{ GdkKey.L3, Key.F13 },
{ GdkKey.F14, Key.F14 },
{ GdkKey.L5, Key.F15 },
{ GdkKey.F16, Key.F16 },
{ GdkKey.F17, Key.F17 },
{ GdkKey.L8, Key.F18 },
{ GdkKey.L9, Key.F19 },
{ GdkKey.L10, Key.F20 },
{ GdkKey.R1, Key.F21 },
{ GdkKey.R2, Key.F22 },
{ GdkKey.F23, Key.F23 },
{ GdkKey.R4, Key.F24 },
{ GdkKey.Num_Lock, Key.NumLock },
{ GdkKey.Scroll_Lock, Key.Scroll },
{ GdkKey.Shift_L, Key.LeftShift },
{ GdkKey.Shift_R, Key.RightShift },
{ GdkKey.Control_L, Key.LeftCtrl },
{ GdkKey.Control_R, Key.RightCtrl },
{ GdkKey.Alt_L, Key.LeftAlt },
{ GdkKey.Alt_R, Key.RightAlt },
//{ GdkKey.?, Key.BrowserBack }
//{ GdkKey.?, Key.BrowserForward }
//{ GdkKey.?, Key.BrowserRefresh }
//{ GdkKey.?, Key.BrowserStop }
//{ GdkKey.?, Key.BrowserSearch }
//{ GdkKey.?, Key.BrowserFavorites }
//{ GdkKey.?, Key.BrowserHome }
//{ GdkKey.?, Key.VolumeMute }
//{ GdkKey.?, Key.VolumeDown }
//{ GdkKey.?, Key.VolumeUp }
//{ GdkKey.?, Key.MediaNextTrack }
//{ GdkKey.?, Key.MediaPreviousTrack }
//{ GdkKey.?, Key.MediaStop }
//{ GdkKey.?, Key.MediaPlayPause }
//{ GdkKey.?, Key.LaunchMail }
//{ GdkKey.?, Key.SelectMedia }
//{ GdkKey.?, Key.LaunchApplication1 }
//{ GdkKey.?, Key.LaunchApplication2 }
{ GdkKey.semicolon, Key.OemSemicolon },
{ GdkKey.plus, Key.OemPlus },
{ GdkKey.equal, Key.OemPlus },
{ GdkKey.comma, Key.OemComma },
{ GdkKey.minus, Key.OemMinus },
{ GdkKey.period, Key.OemPeriod },
{ GdkKey.slash, Key.Oem2 },
{ GdkKey.grave, Key.OemTilde },
//{ GdkKey.?, Key.AbntC1 }
//{ GdkKey.?, Key.AbntC2 }
{ GdkKey.bracketleft, Key.OemOpenBrackets },
{ GdkKey.backslash, Key.OemPipe },
{ GdkKey.bracketright, Key.OemCloseBrackets },
{ GdkKey.apostrophe, Key.OemQuotes },
//{ GdkKey.?, Key.Oem8 }
//{ GdkKey.?, Key.Oem102 }
//{ GdkKey.?, Key.ImeProcessed }
//{ GdkKey.?, Key.System }
//{ GdkKey.?, Key.OemAttn }
//{ GdkKey.?, Key.OemFinish }
//{ GdkKey.?, Key.DbeHiragana }
//{ GdkKey.?, Key.OemAuto }
//{ GdkKey.?, Key.DbeDbcsChar }
//{ GdkKey.?, Key.OemBackTab }
//{ GdkKey.?, Key.Attn }
//{ GdkKey.?, Key.DbeEnterWordRegisterMode }
//{ GdkKey.?, Key.DbeEnterImeConfigureMode }
//{ GdkKey.?, Key.EraseEof }
//{ GdkKey.?, Key.Play }
//{ GdkKey.?, Key.Zoom }
//{ GdkKey.?, Key.NoName }
//{ GdkKey.?, Key.DbeEnterDialogConversionMode }
//{ GdkKey.?, Key.OemClear }
//{ GdkKey.?, Key.DeadCharProcessed }
};
public static Key ConvertKey(GdkKey key)
{
Key result;
return KeyDic.TryGetValue(key, out result) ? result : Key.None;
}
}
}

20
src/Gtk/Avalonia.Gtk3/PlatformIconLoader.cs

@ -1,20 +0,0 @@
using System.IO;
using Avalonia.Gtk3.Interop;
using Avalonia.Platform;
namespace Avalonia.Gtk3
{
class PlatformIconLoader : IPlatformIconLoader
{
public IWindowIconImpl LoadIcon(string fileName) => Pixbuf.NewFromFile(fileName);
public IWindowIconImpl LoadIcon(Stream stream) => Pixbuf.NewFromStream(stream);
public IWindowIconImpl LoadIcon(IBitmapImpl bitmap)
{
var ms = new MemoryStream();
bitmap.Save(ms);
return Pixbuf.NewFromBytes(ms.ToArray());
}
}
}

19
src/Gtk/Avalonia.Gtk3/PopupImpl.cs

@ -1,19 +0,0 @@
using Avalonia.Gtk3.Interop;
using Avalonia.Platform;
namespace Avalonia.Gtk3
{
class PopupImpl : WindowBaseImpl, IPopupImpl
{
static GtkWindow CreateWindow()
{
var window = Native.GtkWindowNew(GtkWindowType.Popup);
return window;
}
public PopupImpl() : base(CreateWindow())
{
OverrideRedirect = true;
}
}
}

10
src/Gtk/Avalonia.Gtk3/Properties/AssemblyInfo.cs

@ -1,10 +0,0 @@
using System.Reflection;
using Avalonia.Gtk3;
using Avalonia.Platform;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: ExportWindowingSubsystem(OperatingSystemType.WinNT, 2, "GTK3", typeof(Gtk3Platform), nameof(Gtk3Platform.Initialize))]
[assembly: ExportWindowingSubsystem(OperatingSystemType.Linux, 1, "GTK3", typeof(Gtk3Platform), nameof(Gtk3Platform.Initialize))]
[assembly: ExportWindowingSubsystem(OperatingSystemType.OSX, 2, "GTK3", typeof(Gtk3Platform), nameof(Gtk3Platform.Initialize))]

8
src/Gtk/Avalonia.Gtk3/README.md

@ -1,8 +0,0 @@
P/Invoke based GTK3 backend
===========================
Code is EXPERIMENTAL at this point. It also needs Direct2D/Skia for rendering.
Windows GTK3 binaries aren't included in the repo, you need to download them from https://sourceforge.net/projects/gtk3win/
On Linux it should work out of the box with system-provided GTK3. On OSX you should be able to wire GTK3 using DYLD_LIBRARY_PATH environment variable.

56
src/Gtk/Avalonia.Gtk3/ScreenImpl.cs

@ -1,56 +0,0 @@
using System;
using System.Collections.Generic;
using Avalonia.Gtk3.Interop;
using Avalonia.Platform;
namespace Avalonia.Gtk3
{
internal class ScreenImpl : IScreenImpl
{
public int ScreenCount
{
get => _allScreens.Length;
}
private Screen[] _allScreens;
public IReadOnlyList<Screen> AllScreens
{
get
{
if (_allScreens == null)
{
IntPtr display = Native.GdkGetDefaultDisplay();
GdkScreen screen = Native.GdkDisplayGetDefaultScreen(display);
short primary = Native.GdkScreenGetPrimaryMonitor(screen);
Screen[] screens = new Screen[Native.GdkScreenGetNMonitors(screen)];
for (short i = 0; i < screens.Length; i++)
{
GdkRectangle workArea = new GdkRectangle(), geometry = new GdkRectangle();
Native.GdkScreenGetMonitorGeometry(screen, i, ref geometry);
Native.GdkScreenGetMonitorWorkarea(screen, i, ref workArea);
PixelRect workAreaRect = new PixelRect(workArea.X, workArea.Y, workArea.Width, workArea.Height);
PixelRect geometryRect = new PixelRect(geometry.X, geometry.Y, geometry.Width, geometry.Height);
GtkScreen s = new GtkScreen(geometryRect, workAreaRect, i == primary, i);
screens[i] = s;
}
_allScreens = screens;
}
return _allScreens;
}
}
public ScreenImpl()
{
IntPtr display = Native.GdkGetDefaultDisplay();
GdkScreen screen = Native.GdkDisplayGetDefaultScreen(display);
Signal.Connect<Native.D.monitors_changed>(screen, "monitors-changed", MonitorsChanged);
}
private unsafe void MonitorsChanged(IntPtr screen, IntPtr userData)
{
_allScreens = null;
}
}
}

110
src/Gtk/Avalonia.Gtk3/SystemDialogs.cs

@ -1,110 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Controls.Platform;
using Avalonia.Gtk3.Interop;
using Avalonia.Platform;
using Avalonia.Platform.Interop;
namespace Avalonia.Gtk3
{
class SystemDialogBase
{
public unsafe static Task<string[]> ShowDialog(string title, GtkWindow parent, GtkFileChooserAction action,
bool multiselect, string initialFileName, Action<GtkFileChooser> modify)
{
GtkFileChooser dlg;
parent = parent ?? GtkWindow.Null;
using (var name = new Utf8Buffer(title))
dlg = Native.GtkFileChooserDialogNew(name, parent, action, IntPtr.Zero);
modify?.Invoke(dlg);
if (multiselect)
Native.GtkFileChooserSetSelectMultiple(dlg, true);
Native.GtkWindowSetModal(dlg, true);
var tcs = new TaskCompletionSource<string[]>();
List<IDisposable> disposables = null;
Action dispose = () =>
{
// ReSharper disable once PossibleNullReferenceException
foreach (var d in disposables)
d.Dispose();
disposables.Clear();
};
disposables = new List<IDisposable>
{
Signal.Connect<Native.D.signal_generic>(dlg, "close", delegate
{
tcs.TrySetResult(null);
dispose();
return false;
}),
Signal.Connect<Native.D.signal_dialog_response>(dlg, "response", (_, resp, __) =>
{
string[] result = null;
if (resp == GtkResponseType.Accept)
{
var rlst = new List<string>();
var gs = Native.GtkFileChooserGetFilenames(dlg);
var cgs = gs;
while (cgs != null)
{
if (cgs->Data != IntPtr.Zero)
rlst.Add(Utf8Buffer.StringFromPtr(cgs->Data));
cgs = cgs->Next;
}
Native.GSlistFree(gs);
result = rlst.ToArray();
}
Native.GtkWidgetHide(dlg);
dispose();
tcs.TrySetResult(result);
return false;
}),
dlg
};
using (var open = new Utf8Buffer("Open"))
Native.GtkDialogAddButton(dlg, open, GtkResponseType.Accept);
using (var open = new Utf8Buffer("Cancel"))
Native.GtkDialogAddButton(dlg, open, GtkResponseType.Cancel);
if (initialFileName != null)
using (var fn = new Utf8Buffer(initialFileName))
Native.GtkFileChooserSetFilename(dlg, fn);
Native.GtkWindowPresent(dlg);
return tcs.Task;
}
public Task<string[]> ShowFileDialogAsync(FileDialog dialog, GtkWindow parent,
Action<GtkFileChooser> modify = null)
{
return ShowDialog(dialog.Title, parent,
dialog is OpenFileDialog ? GtkFileChooserAction.Open : GtkFileChooserAction.Save,
(dialog as OpenFileDialog)?.AllowMultiple ?? false,
Path.Combine(string.IsNullOrEmpty(dialog.InitialDirectory) ? "" : dialog.InitialDirectory,
string.IsNullOrEmpty(dialog.InitialFileName) ? "" : dialog.InitialFileName), modify);
}
public async Task<string> ShowFolderDialogAsync(OpenFolderDialog dialog, GtkWindow parent,
Action<GtkFileChooser> modify = null)
{
var res = await ShowDialog(dialog.Title, parent,
GtkFileChooserAction.SelectFolder, false, dialog.InitialDirectory, modify);
return res?.FirstOrDefault();
}
}
class SystemDialog : SystemDialogBase, ISystemDialogImpl
{
public Task<string> ShowFolderDialogAsync(OpenFolderDialog dialog, IWindowImpl parent)
=> ShowFolderDialogAsync(dialog, ((WindowBaseImpl)parent)?.GtkWidget);
public Task<string[]> ShowFileDialogAsync(FileDialog dialog, IWindowImpl parent)
=> ShowFileDialogAsync(dialog, ((WindowBaseImpl)parent)?.GtkWidget);
}
}

527
src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs

@ -1,527 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using Avalonia.Controls;
using Avalonia.Gtk3.Interop;
using Avalonia.Input;
using Avalonia.Input.Raw;
using Avalonia.OpenGL;
using Avalonia.Platform;
using Avalonia.Platform.Interop;
using Avalonia.Rendering;
using Avalonia.Threading;
namespace Avalonia.Gtk3
{
abstract class WindowBaseImpl : IWindowBaseImpl, IPlatformHandle, EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo
{
public readonly GtkWindow GtkWidget;
private IInputRoot _inputRoot;
private readonly GtkImContext _imContext;
private readonly FramebufferManager _framebuffer;
private readonly EglGlPlatformSurface _egl;
protected readonly List<IDisposable> Disposables = new List<IDisposable>();
private Size _lastSize;
private PixelPoint _lastPosition;
private double _lastScaling;
private uint _lastKbdEvent;
private uint _lastSmoothScrollEvent;
private GCHandle _gcHandle;
private object _lock = new object();
private IDeferredRenderOperation _nextRenderOperation;
private readonly AutoResetEvent _canSetNextOperation = new AutoResetEvent(true);
internal IntPtr? GdkWindowHandle;
private bool _overrideRedirect;
private uint? _tickCallback;
public WindowBaseImpl(GtkWindow gtkWidget)
{
GtkWidget = gtkWidget;
var glf = AvaloniaLocator.Current.GetService<IWindowingPlatformGlFeature>() as EglGlPlatformFeature;
if (glf != null)
_egl = new EglGlPlatformSurface((EglDisplay)glf.Display, glf.DeferredContext, this);
else
_framebuffer = new FramebufferManager(this);
_imContext = Native.GtkImMulticontextNew();
Disposables.Add(_imContext);
Native.GtkWidgetSetEvents(gtkWidget, 0xFFFFFE);
Disposables.Add(Signal.Connect<Native.D.signal_commit>(_imContext, "commit", OnCommit));
Connect<Native.D.signal_widget_draw>("draw", OnDraw);
Connect<Native.D.signal_generic>("realize", OnRealized);
ConnectEvent("configure-event", OnConfigured);
ConnectEvent("button-press-event", OnButton);
ConnectEvent("button-release-event", OnButton);
ConnectEvent("motion-notify-event", OnMotion);
ConnectEvent("scroll-event", OnScroll);
ConnectEvent("window-state-event", OnStateChanged);
ConnectEvent("key-press-event", OnKeyEvent);
ConnectEvent("key-release-event", OnKeyEvent);
ConnectEvent("leave-notify-event", OnLeaveNotifyEvent);
ConnectEvent("delete-event", OnClosingEvent);
Connect<Native.D.signal_generic>("destroy", OnDestroy);
Native.GtkWidgetRealize(gtkWidget);
GdkWindowHandle = this.Handle.Handle;
_lastSize = ClientSize;
if (_egl != null)
Native.GtkWidgetSetDoubleBuffered(gtkWidget, false);
else if (Gtk3Platform.UseDeferredRendering)
{
Native.GtkWidgetSetDoubleBuffered(gtkWidget, false);
_gcHandle = GCHandle.Alloc(this);
_tickCallback = Native.GtkWidgetAddTickCallback(GtkWidget, PinnedStaticCallback,
GCHandle.ToIntPtr(_gcHandle), IntPtr.Zero);
}
}
private bool OnConfigured(IntPtr gtkwidget, IntPtr ev, IntPtr userdata)
{
int w, h;
if (!OverrideRedirect)
{
Native.GtkWindowGetSize(GtkWidget, out w, out h);
var size = ClientSize = new Size(w, h);
if (_lastSize != size)
{
Resized?.Invoke(size);
_lastSize = size;
}
}
var pos = Position;
if (_lastPosition != pos)
{
PositionChanged?.Invoke(pos);
_lastPosition = pos;
}
var scaling = Scaling;
if (_lastScaling != scaling)
{
ScalingChanged?.Invoke(scaling);
_lastScaling = scaling;
}
return false;
}
private bool OnRealized(IntPtr gtkwidget, IntPtr userdata)
{
Native.GtkImContextSetClientWindow(_imContext, Native.GtkWidgetGetWindow(GtkWidget));
return false;
}
private bool OnDestroy(IntPtr gtkwidget, IntPtr userdata)
{
DoDispose(true);
return false;
}
private static InputModifiers GetModifierKeys(GdkModifierType state)
{
var rv = InputModifiers.None;
if (state.HasFlag(GdkModifierType.ControlMask))
rv |= InputModifiers.Control;
if (state.HasFlag(GdkModifierType.ShiftMask))
rv |= InputModifiers.Shift;
if (state.HasFlag(GdkModifierType.Mod1Mask))
rv |= InputModifiers.Alt;
if (state.HasFlag(GdkModifierType.Button1Mask))
rv |= InputModifiers.LeftMouseButton;
if (state.HasFlag(GdkModifierType.Button2Mask))
rv |= InputModifiers.RightMouseButton;
if (state.HasFlag(GdkModifierType.Button3Mask))
rv |= InputModifiers.MiddleMouseButton;
return rv;
}
private unsafe bool OnClosingEvent(IntPtr w, IntPtr ev, IntPtr userdata)
{
bool? preventClosing = Closing?.Invoke();
return preventClosing ?? false;
}
private unsafe bool OnButton(IntPtr w, IntPtr ev, IntPtr userdata)
{
var evnt = (GdkEventButton*)ev;
var e = new RawPointerEventArgs(
Gtk3Platform.Mouse,
evnt->time,
_inputRoot,
evnt->type == GdkEventType.ButtonRelease
? evnt->button == 1
? RawPointerEventType.LeftButtonUp
: evnt->button == 3 ? RawPointerEventType.RightButtonUp : RawPointerEventType.MiddleButtonUp
: evnt->button == 1
? RawPointerEventType.LeftButtonDown
: evnt->button == 3 ? RawPointerEventType.RightButtonDown : RawPointerEventType.MiddleButtonDown,
new Point(evnt->x, evnt->y), GetModifierKeys(evnt->state));
OnInput(e);
return true;
}
protected virtual unsafe bool OnStateChanged(IntPtr w, IntPtr pev, IntPtr userData)
{
var ev = (GdkEventWindowState*) pev;
if (ev->changed_mask.HasFlag(GdkWindowState.Focused))
{
if(ev->new_window_state.HasFlag(GdkWindowState.Focused))
Activated?.Invoke();
else
Deactivated?.Invoke();
}
return true;
}
private unsafe bool OnMotion(IntPtr w, IntPtr ev, IntPtr userdata)
{
var evnt = (GdkEventMotion*)ev;
var position = new Point(evnt->x, evnt->y);
Native.GdkEventRequestMotions(ev);
var e = new RawPointerEventArgs(
Gtk3Platform.Mouse,
evnt->time,
_inputRoot,
RawPointerEventType.Move,
position, GetModifierKeys(evnt->state));
OnInput(e);
return true;
}
private unsafe bool OnScroll(IntPtr w, IntPtr ev, IntPtr userdata)
{
var evnt = (GdkEventScroll*)ev;
//Ignore duplicates
if (evnt->time - _lastSmoothScrollEvent < 10 && evnt->direction != GdkScrollDirection.Smooth)
return true;
var delta = new Vector();
const double step = (double) 1;
if (evnt->direction == GdkScrollDirection.Down)
delta = new Vector(0, -step);
else if (evnt->direction == GdkScrollDirection.Up)
delta = new Vector(0, step);
else if (evnt->direction == GdkScrollDirection.Right)
delta = new Vector(-step, 0);
else if (evnt->direction == GdkScrollDirection.Left)
delta = new Vector(step, 0);
else if (evnt->direction == GdkScrollDirection.Smooth)
{
delta = new Vector(-evnt->delta_x, -evnt->delta_y);
_lastSmoothScrollEvent = evnt->time;
}
var e = new RawMouseWheelEventArgs(Gtk3Platform.Mouse, evnt->time, _inputRoot,
new Point(evnt->x, evnt->y), delta, GetModifierKeys(evnt->state));
OnInput(e);
return true;
}
private unsafe bool OnKeyEvent(IntPtr w, IntPtr pev, IntPtr userData)
{
var evnt = (GdkEventKey*) pev;
_lastKbdEvent = evnt->time;
var e = new RawKeyEventArgs(
Gtk3Platform.Keyboard,
evnt->time,
evnt->type == GdkEventType.KeyPress ? RawKeyEventType.KeyDown : RawKeyEventType.KeyUp,
Avalonia.Gtk.Common.KeyTransform.ConvertKey((GdkKey)evnt->keyval), GetModifierKeys((GdkModifierType)evnt->state));
OnInput(e);
if (Native.GtkImContextFilterKeypress(_imContext, pev))
return true;
return true;
}
private unsafe bool OnLeaveNotifyEvent(IntPtr w, IntPtr pev, IntPtr userData)
{
var evnt = (GdkEventCrossing*) pev;
var position = new Point(evnt->x, evnt->y);
OnInput(new RawPointerEventArgs(Gtk3Platform.Mouse,
evnt->time,
_inputRoot,
RawPointerEventType.Move,
position, GetModifierKeys(evnt->state)));
return true;
}
private unsafe bool OnCommit(IntPtr gtkwidget, IntPtr utf8string, IntPtr userdata)
{
OnInput(new RawTextInputEventArgs(Gtk3Platform.Keyboard, _lastKbdEvent, Utf8Buffer.StringFromPtr(utf8string)));
return true;
}
protected void ConnectEvent(string name, Native.D.signal_onevent handler)
=> Disposables.Add(Signal.Connect<Native.D.signal_onevent>(GtkWidget, name, handler));
void Connect<T>(string name, T handler) => Disposables.Add(Signal.Connect(GtkWidget, name, handler));
internal IntPtr CurrentCairoContext { get; private set; }
private bool OnDraw(IntPtr gtkwidget, IntPtr cairocontext, IntPtr userdata)
{
if (!Gtk3Platform.UseDeferredRendering)
{
CurrentCairoContext = cairocontext;
Paint?.Invoke(new Rect(ClientSize));
CurrentCairoContext = IntPtr.Zero;
}
else
Paint?.Invoke(new Rect(ClientSize));
return true;
}
private static Native.D.TickCallback PinnedStaticCallback = StaticTickCallback;
static bool StaticTickCallback(IntPtr widget, IntPtr clock, IntPtr userData)
{
var impl = (WindowBaseImpl) GCHandle.FromIntPtr(userData).Target;
impl.OnRenderTick();
return true;
}
public void SetNextRenderOperation(IDeferredRenderOperation op)
{
while (true)
{
lock (_lock)
{
if (_nextRenderOperation == null)
{
_nextRenderOperation = op;
return;
}
}
_canSetNextOperation.WaitOne();
}
}
private void OnRenderTick()
{
IDeferredRenderOperation op = null;
lock (_lock)
{
if (_nextRenderOperation != null)
{
op = _nextRenderOperation;
_nextRenderOperation = null;
}
_canSetNextOperation.Set();
}
if (op != null)
{
op?.RenderNow(null);
op?.Dispose();
}
}
public void Dispose() => DoDispose(false);
void DoDispose(bool fromDestroy)
{
if (_tickCallback.HasValue)
{
if (!GtkWidget.IsClosed)
Native.GtkWidgetRemoveTickCallback(GtkWidget, _tickCallback.Value);
_tickCallback = null;
}
//We are calling it here, since signal handler will be detached
if (!GtkWidget.IsClosed)
Closed?.Invoke();
foreach(var d in Disposables.AsEnumerable().Reverse())
d.Dispose();
Disposables.Clear();
if (!fromDestroy && !GtkWidget.IsClosed)
Native.GtkWindowClose(GtkWidget);
GtkWidget.Dispose();
if (_gcHandle.IsAllocated)
{
_gcHandle.Free();
}
}
public Size MaxClientSize
{
get
{
var s = Native.GtkWidgetGetScreen(GtkWidget);
return new Size(Native.GdkScreenGetWidth(s), Native.GdkScreenGetHeight(s));
}
}
public void SetMinMaxSize(Size minSize, Size maxSize)
{
if (GtkWidget.IsClosed)
return;
GdkGeometry geometry = new GdkGeometry();
geometry.min_width = minSize.Width > 0 ? (int)minSize.Width : -1;
geometry.min_height = minSize.Height > 0 ? (int)minSize.Height : -1;
geometry.max_width = !Double.IsInfinity(maxSize.Width) && maxSize.Width > 0 ? (int)maxSize.Width : 999999;
geometry.max_height = !Double.IsInfinity(maxSize.Height) && maxSize.Height > 0 ? (int)maxSize.Height : 999999;
Native.GtkWindowSetGeometryHints(GtkWidget, IntPtr.Zero, ref geometry, GdkWindowHints.GDK_HINT_MIN_SIZE | GdkWindowHints.GDK_HINT_MAX_SIZE);
}
public IMouseDevice MouseDevice => Gtk3Platform.Mouse;
public double Scaling => LastKnownScaleFactor = (int) (Native.GtkWidgetGetScaleFactor?.Invoke(GtkWidget) ?? 1);
public IPlatformHandle Handle => this;
string IPlatformHandle.HandleDescriptor => "HWND";
public Action Activated { get; set; }
public Func<bool> Closing { get; set; }
public Action Closed { get; set; }
public Action Deactivated { get; set; }
public Action<RawInputEventArgs> Input { get; set; }
public Action<Rect> Paint { get; set; }
public Action<Size> Resized { get; set; }
public Action<double> ScalingChanged { get; set; } //TODO
public Action<PixelPoint> PositionChanged { get; set; }
public void Activate() => Native.GtkWidgetActivate(GtkWidget);
public void Invalidate(Rect rect)
{
if(GtkWidget.IsClosed)
return;
var s = ClientSize;
Native.GtkWidgetQueueDrawArea(GtkWidget, 0, 0, (int) s.Width, (int) s.Height);
}
public void SetInputRoot(IInputRoot inputRoot) => _inputRoot = inputRoot;
void OnInput(RawInputEventArgs args)
{
Dispatcher.UIThread.Post(() => Input?.Invoke(args), DispatcherPriority.Input);
}
public Point PointToClient(PixelPoint point)
{
int x, y;
Native.GdkWindowGetOrigin(Native.GtkWidgetGetWindow(GtkWidget), out x, out y);
return new Point(point.X - x, point.Y - y);
}
public PixelPoint PointToScreen(Point point)
{
int x, y;
Native.GdkWindowGetOrigin(Native.GtkWidgetGetWindow(GtkWidget), out x, out y);
return new PixelPoint((int)(point.X + x), (int)(point.Y + y));
}
public void SetCursor(IPlatformHandle cursor)
{
if (GtkWidget.IsClosed)
return;
Native.GdkWindowSetCursor(Native.GtkWidgetGetWindow(GtkWidget), cursor?.Handle ?? IntPtr.Zero);
}
public virtual void Show() => Native.GtkWindowPresent(GtkWidget);
public void Hide() => Native.GtkWidgetHide(GtkWidget);
public void SetTopmost(bool value) => Native.GtkWindowSetKeepAbove(GtkWidget, value);
void GetGlobalPointer(out int x, out int y)
{
int mask;
Native.GdkWindowGetPointer(Native.GdkScreenGetRootWindow(Native.GtkWidgetGetScreen(GtkWidget)),
out x, out y, out mask);
}
public void BeginMoveDrag()
{
int x, y;
GetGlobalPointer(out x, out y);
Native.GdkWindowBeginMoveDrag(Native.GtkWidgetGetWindow(GtkWidget), 1, x, y, 0);
}
public void BeginResizeDrag(WindowEdge edge)
{
int x, y;
GetGlobalPointer(out x, out y);
Native.GdkWindowBeginResizeDrag(Native.GtkWidgetGetWindow(GtkWidget), edge, 1, x, y, 0);
}
public Size ClientSize { get; private set; }
public int LastKnownScaleFactor { get; private set; }
public void Resize(Size value)
{
if (GtkWidget.IsClosed)
return;
Native.GtkWindowResize(GtkWidget, (int)value.Width, (int)value.Height);
if (OverrideRedirect)
{
var size = ClientSize = value;
if (_lastSize != size)
{
Resized?.Invoke(size);
_lastSize = size;
}
}
}
public bool OverrideRedirect
{
get => _overrideRedirect;
set
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
Native.GdkWindowSetOverrideRedirect(Native.GtkWidgetGetWindow(GtkWidget), value);
_overrideRedirect = value;
}
}
}
public IScreenImpl Screen
{
get;
} = new ScreenImpl();
public PixelPoint Position
{
get
{
int x, y;
Native.GtkWindowGetPosition(GtkWidget, out x, out y);
return new PixelPoint(x, y);
}
set { Native.GtkWindowMove(GtkWidget, (int)value.X, (int)value.Y); }
}
IntPtr IPlatformHandle.Handle => Native.GetNativeGdkWindowHandle(Native.GtkWidgetGetWindow(GtkWidget));
public IEnumerable<object> Surfaces => new object[] {Handle, _egl, _framebuffer};
public IRenderer CreateRenderer(IRenderRoot root)
{
var loop = AvaloniaLocator.Current.GetService<IRenderLoop>();
return Gtk3Platform.UseDeferredRendering
? (IRenderer) new DeferredRenderer(root, loop)
: new ImmediateRenderer(root);
}
PixelSize EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo.Size
{
get
{
var cs = ClientSize;
return new PixelSize((int)Math.Max(1, LastKnownScaleFactor * cs.Width),
(int)Math.Max(1, LastKnownScaleFactor * ClientSize.Height));
}
}
double EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo.Scaling => LastKnownScaleFactor;
IntPtr EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo.Handle => Handle.Handle;
}
}

102
src/Gtk/Avalonia.Gtk3/WindowImpl.cs

@ -1,102 +0,0 @@
using System;
using Avalonia.Controls;
using Avalonia.Gtk3.Interop;
using Avalonia.Platform;
using Avalonia.Platform.Interop;
namespace Avalonia.Gtk3
{
class WindowImpl : WindowBaseImpl, IWindowImpl
{
private WindowState _lastWindowState;
public WindowImpl() : base(Native.GtkWindowNew(GtkWindowType.TopLevel))
{
}
protected unsafe override bool OnStateChanged(IntPtr w, IntPtr pev, IntPtr userData)
{
var windowStateEvent = (GdkEventWindowState*)pev;
var newWindowState = windowStateEvent->new_window_state;
var windowState = newWindowState.HasFlag(GdkWindowState.Iconified) ? WindowState.Minimized
: (newWindowState.HasFlag(GdkWindowState.Maximized) ? WindowState.Maximized : WindowState.Normal);
if (windowState != _lastWindowState)
{
_lastWindowState = windowState;
WindowStateChanged?.Invoke(windowState);
}
return base.OnStateChanged(w, pev, userData);
}
public void SetTitle(string title)
{
using (var t = new Utf8Buffer(title))
Native.GtkWindowSetTitle(GtkWidget, t);
}
public WindowState WindowState
{
get
{
var state = Native.GdkWindowGetState(Native.GtkWidgetGetWindow(GtkWidget));
if (state.HasFlag(GdkWindowState.Iconified))
return WindowState.Minimized;
if (state.HasFlag(GdkWindowState.Maximized))
return WindowState.Maximized;
return WindowState.Normal;
}
set
{
if (value == WindowState.Minimized)
Native.GtkWindowIconify(GtkWidget);
else if (value == WindowState.Maximized)
Native.GtkWindowMaximize(GtkWidget);
else
{
Native.GtkWindowUnmaximize(GtkWidget);
Native.GtkWindowDeiconify(GtkWidget);
}
}
}
public Action<WindowState> WindowStateChanged { get; set; }
public void ShowDialog(IWindowImpl parent)
{
Native.GtkWindowSetModal(GtkWidget, true);
Native.GtkWindowSetTransientFor(GtkWidget, ((WindowImpl)parent).GtkWidget.DangerousGetHandle());
Native.GtkWindowPresent(GtkWidget);
}
public override void Show()
{
Native.GtkWindowSetModal(GtkWidget, false);
Native.GtkWindowSetTransientFor(GtkWidget, IntPtr.Zero);
Native.GtkWindowPresent(GtkWidget);
}
public void SetSystemDecorations(bool enabled) => Native.GtkWindowSetDecorated(GtkWidget, enabled);
public void SetIcon(IWindowIconImpl icon) => Native.GtkWindowSetIcon(GtkWidget, (Pixbuf) icon);
public void SetCoverTaskbarWhenMaximized(bool enable)
{
//Why do we even have that?
}
public void ShowTaskbarIcon(bool value) => Native.GtkWindowSetSkipTaskbarHint(GtkWidget, !value);
public void CanResize(bool value) => Native.GtkWindowSetResizable(GtkWidget, value);
class EmptyDisposable : IDisposable
{
public void Dispose()
{
}
}
}
}

78
src/Gtk/Avalonia.Gtk3/X11.cs

@ -1,78 +0,0 @@
using System;
using System.Runtime.InteropServices;
namespace Avalonia.Gtk3
{
class X11
{
[DllImport("libX11.so.6")]
public static extern IntPtr XInitThreads();
[DllImport("libX11.so.6")]
public static extern IntPtr XOpenDisplay(IntPtr name);
[DllImport("libX11.so.6")]
public static extern IntPtr XLockDisplay(IntPtr display);
[DllImport("libX11.so.6")]
public static extern IntPtr XUnlockDisplay(IntPtr display);
[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);
[DllImport("libX11.so.6")]
public static extern int XSync(IntPtr display, bool discard);
public delegate int XErrorHandler(IntPtr display, ref XErrorEvent 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);
[StructLayout(LayoutKind.Sequential)]
public unsafe struct XErrorEvent
{
public int type;
public IntPtr* display; /* Display the event was read from */
public ulong serial; /* serial number of failed request */
public byte error_code; /* error code of failed request */
public byte request_code; /* Major op-code of failed request */
public byte minor_code; /* Minor op-code of failed request */
public IntPtr resourceid; /* resource id */
}
[StructLayout(LayoutKind.Sequential)]
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];
}
}
}

55
src/Gtk/Avalonia.Gtk3/X11Framebuffer.cs

@ -1,55 +0,0 @@
using System;
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;
Size = new PixelSize(width * factor, height * factor);
RowBytes = Size.Width * 4;
Dpi = new Vector(96, 96) * factor;
Format = PixelFormat.Bgra8888;
_blob = AvaloniaLocator.Current.GetService<IRuntimePlatform>().AllocBlob(RowBytes * Size.Height);
Address = _blob.Address;
}
public void Dispose()
{
var image = new X11.XImage();
int bitsPerPixel = 32;
image.width = Size.Width;
image.height = Size.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 - Size.Width * 4;
image.bits_per_pixel = bitsPerPixel;
X11.XLockDisplay(_display);
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)Size.Width, (uint)Size.Height);
X11.XFreeGC(_display, gc);
X11.XSync(_display, true);
X11.XUnlockDisplay(_display);
_blob.Dispose();
}
public IntPtr Address { get; }
public PixelSize Size { get; }
public int RowBytes { get; }
public Vector Dpi { get; }
public PixelFormat Format { get; }
}
}
Loading…
Cancel
Save