diff --git a/src/Gtk/Avalonia.Gtk3/FramebufferManager.cs b/src/Gtk/Avalonia.Gtk3/FramebufferManager.cs index 455b63b89e..a673047e8c 100644 --- a/src/Gtk/Avalonia.Gtk3/FramebufferManager.cs +++ b/src/Gtk/Avalonia.Gtk3/FramebufferManager.cs @@ -40,7 +40,7 @@ namespace Avalonia.Gtk3 return new ImageSurfaceFramebuffer(_window, width, height, _window.LastKnownScaleFactor); } - private static int X11ErrorHandler(IntPtr d, IntPtr e) + private static int X11ErrorHandler(IntPtr d, ref X11.XErrorEvent e) { return 0; } diff --git a/src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs b/src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs index 81ff2e9a45..2cf893346f 100644 --- a/src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs +++ b/src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs @@ -30,6 +30,10 @@ namespace Avalonia.Gtk3 { if (!s_gtkInitialized) { + try + { + X11.XInitThreads(); + }catch{} Resolver.Resolve(); Native.GtkInit(0, IntPtr.Zero); var disp = Native.GdkGetDefaultDisplay(); diff --git a/src/Gtk/Avalonia.Gtk3/X11.cs b/src/Gtk/Avalonia.Gtk3/X11.cs index 6708ece17b..4677114bdb 100644 --- a/src/Gtk/Avalonia.Gtk3/X11.cs +++ b/src/Gtk/Avalonia.Gtk3/X11.cs @@ -5,9 +5,18 @@ 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); @@ -23,13 +32,28 @@ namespace Avalonia.Gtk3 [DllImport("libX11.so.6")] public static extern IntPtr XSetErrorHandler(XErrorHandler handler); - public delegate int XErrorHandler(IntPtr display, IntPtr error); + [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 */ diff --git a/src/Gtk/Avalonia.Gtk3/X11Framebuffer.cs b/src/Gtk/Avalonia.Gtk3/X11Framebuffer.cs index 2bf08bddf1..4b27920d64 100644 --- a/src/Gtk/Avalonia.Gtk3/X11Framebuffer.cs +++ b/src/Gtk/Avalonia.Gtk3/X11Framebuffer.cs @@ -38,10 +38,13 @@ namespace Avalonia.Gtk3 image.depth = 24; image.bytes_per_line = RowBytes - 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) Width, (uint) Height); X11.XFreeGC(_display, gc); + X11.XSync(_display, true); + X11.XUnlockDisplay(_display); _blob.Dispose(); }