Browse Source

Merge pull request #8268 from AvaloniaUI/feature/x11-xsync-counter

[X11] Added support for the basic version of _NET_WM_SYNC_REQUEST protocol
pull/8272/head
Dan Walmsley 4 years ago
committed by GitHub
parent
commit
e4e0ba1652
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      src/Avalonia.X11/X11Atoms.cs
  2. 10
      src/Avalonia.X11/X11Info.cs
  3. 44
      src/Avalonia.X11/X11Window.cs
  4. 17
      src/Avalonia.X11/XLib.cs

1
src/Avalonia.X11/X11Atoms.cs

@ -155,6 +155,7 @@ namespace Avalonia.X11
public readonly IntPtr _NET_FRAME_EXTENTS; public readonly IntPtr _NET_FRAME_EXTENTS;
public readonly IntPtr _NET_WM_PING; public readonly IntPtr _NET_WM_PING;
public readonly IntPtr _NET_WM_SYNC_REQUEST; public readonly IntPtr _NET_WM_SYNC_REQUEST;
public readonly IntPtr _NET_WM_SYNC_REQUEST_COUNTER;
public readonly IntPtr _NET_SYSTEM_TRAY_S; public readonly IntPtr _NET_SYSTEM_TRAY_S;
public readonly IntPtr _NET_SYSTEM_TRAY_ORIENTATION; public readonly IntPtr _NET_SYSTEM_TRAY_ORIENTATION;
public readonly IntPtr _NET_SYSTEM_TRAY_OPCODE; public readonly IntPtr _NET_SYSTEM_TRAY_OPCODE;

10
src/Avalonia.X11/X11Info.cs

@ -33,6 +33,7 @@ namespace Avalonia.X11
public IntPtr LastActivityTimestamp { get; set; } public IntPtr LastActivityTimestamp { get; set; }
public XVisualInfo? TransparentVisualInfo { get; set; } public XVisualInfo? TransparentVisualInfo { get; set; }
public bool HasXim { get; set; } public bool HasXim { get; set; }
public bool HasXSync { get; set; }
public IntPtr DefaultFontSet { get; set; } public IntPtr DefaultFontSet { get; set; }
public unsafe X11Info(IntPtr display, IntPtr deferredDisplay, bool useXim) public unsafe X11Info(IntPtr display, IntPtr deferredDisplay, bool useXim)
@ -101,6 +102,15 @@ namespace Avalonia.X11
{ {
//Ignore, XI is not supported //Ignore, XI is not supported
} }
try
{
HasXSync = XSyncInitialize(display, out _, out _) != Status.Success;
}
catch
{
//Ignore, XSync is not supported
}
} }
} }
} }

44
src/Avalonia.X11/X11Window.cs

@ -45,6 +45,8 @@ namespace Avalonia.X11
private IntPtr _handle; private IntPtr _handle;
private IntPtr _xic; private IntPtr _xic;
private IntPtr _renderHandle; private IntPtr _renderHandle;
private IntPtr _xSyncCounter;
private XSyncValue _xSyncValue;
private bool _mapped; private bool _mapped;
private bool _wasMappedAtLeastOnce = false; private bool _wasMappedAtLeastOnce = false;
private double? _scalingOverride; private double? _scalingOverride;
@ -190,6 +192,16 @@ namespace Avalonia.X11
NativeMenuExporter = DBusMenuExporter.TryCreateTopLevelNativeMenu(_handle); NativeMenuExporter = DBusMenuExporter.TryCreateTopLevelNativeMenu(_handle);
NativeControlHost = new X11NativeControlHost(_platform, this); NativeControlHost = new X11NativeControlHost(_platform, this);
InitializeIme(); InitializeIme();
XChangeProperty(_x11.Display, _handle, _x11.Atoms.WM_PROTOCOLS, _x11.Atoms.XA_ATOM, 32,
PropertyMode.Replace, new[] { _x11.Atoms.WM_DELETE_WINDOW, _x11.Atoms._NET_WM_SYNC_REQUEST }, 2);
if (_x11.HasXSync)
{
_xSyncCounter = XSyncCreateCounter(_x11.Display, _xSyncValue);
XChangeProperty(_x11.Display, _handle, _x11.Atoms._NET_WM_SYNC_REQUEST_COUNTER,
_x11.Atoms.XA_CARDINAL, 32, PropertyMode.Replace, ref _xSyncCounter, 1);
}
} }
class SurfaceInfo : EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo class SurfaceInfo : EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo
@ -383,15 +395,7 @@ namespace Avalonia.X11
(ev.type == XEventName.VisibilityNotify && (ev.type == XEventName.VisibilityNotify &&
ev.VisibilityEvent.state < 2)) ev.VisibilityEvent.state < 2))
{ {
if (!_triggeredExpose) EnqueuePaint();
{
_triggeredExpose = true;
Dispatcher.UIThread.Post(() =>
{
_triggeredExpose = false;
DoPaint();
}, DispatcherPriority.Render);
}
} }
else if (ev.type == XEventName.FocusIn) else if (ev.type == XEventName.FocusIn)
{ {
@ -503,6 +507,7 @@ namespace Avalonia.X11
if (_useRenderWindow) if (_useRenderWindow)
XConfigureResizeWindow(_x11.Display, _renderHandle, ev.ConfigureEvent.width, XConfigureResizeWindow(_x11.Display, _renderHandle, ev.ConfigureEvent.width,
ev.ConfigureEvent.height); ev.ConfigureEvent.height);
EnqueuePaint();
} }
else if (ev.type == XEventName.DestroyNotify else if (ev.type == XEventName.DestroyNotify
&& ev.DestroyWindowEvent.window == _handle) && ev.DestroyWindowEvent.window == _handle)
@ -518,7 +523,11 @@ namespace Avalonia.X11
if (Closing?.Invoke() != true) if (Closing?.Invoke() != true)
Dispose(); Dispose();
} }
else if (ev.ClientMessageEvent.ptr1 == _x11.Atoms._NET_WM_SYNC_REQUEST)
{
_xSyncValue.Lo = new UIntPtr(ev.ClientMessageEvent.ptr3.ToPointer()).ToUInt32();
_xSyncValue.Hi = ev.ClientMessageEvent.ptr4.ToInt32();
}
} }
} }
else if (ev.type == XEventName.KeyPress || ev.type == XEventName.KeyRelease) else if (ev.type == XEventName.KeyPress || ev.type == XEventName.KeyRelease)
@ -730,9 +739,24 @@ namespace Avalonia.X11
ScheduleInput(mev, ref ev); ScheduleInput(mev, ref ev);
} }
void EnqueuePaint()
{
if (!_triggeredExpose)
{
_triggeredExpose = true;
Dispatcher.UIThread.Post(() =>
{
_triggeredExpose = false;
DoPaint();
}, DispatcherPriority.Render);
}
}
void DoPaint() void DoPaint()
{ {
Paint?.Invoke(new Rect()); Paint?.Invoke(new Rect());
if (_xSyncCounter != IntPtr.Zero)
XSyncSetCounter(_x11.Display, _xSyncCounter, _xSyncValue);
} }
public void Invalidate(Rect rect) public void Invalidate(Rect rect)

17
src/Avalonia.X11/XLib.cs

@ -542,6 +542,18 @@ namespace Avalonia.X11
public static extern int XRRQueryExtension (IntPtr dpy, public static extern int XRRQueryExtension (IntPtr dpy,
out int event_base_return, out int event_base_return,
out int error_base_return); out int error_base_return);
[DllImport(libX11Ext)]
public static extern Status XSyncInitialize(IntPtr dpy, out int event_base_return, out int error_base_return);
[DllImport(libX11Ext)]
public static extern IntPtr XSyncCreateCounter(IntPtr dpy, XSyncValue initialValue);
[DllImport(libX11Ext)]
public static extern int XSyncDestroyCounter(IntPtr dpy, IntPtr counter);
[DllImport(libX11Ext)]
public static extern int XSyncSetCounter(IntPtr dpy, IntPtr counter, XSyncValue value);
[DllImport(libX11Randr)] [DllImport(libX11Randr)]
public static extern int XRRQueryVersion(IntPtr dpy, public static extern int XRRQueryVersion(IntPtr dpy,
@ -627,6 +639,11 @@ namespace Avalonia.X11
public int bw; public int bw;
public int d; public int d;
} }
public struct XSyncValue {
public int Hi;
public uint Lo;
}
public static bool XGetGeometry(IntPtr display, IntPtr window, out XGeometry geo) public static bool XGetGeometry(IntPtr display, IntPtr window, out XGeometry geo)
{ {

Loading…
Cancel
Save