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
release/0.10.15
Dan Walmsley 4 years ago
parent
commit
4aedf52935
  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_WM_PING;
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_ORIENTATION;
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 XVisualInfo? TransparentVisualInfo { get; set; }
public bool HasXim { get; set; }
public bool HasXSync { get; set; }
public IntPtr DefaultFontSet { get; set; }
public unsafe X11Info(IntPtr display, IntPtr deferredDisplay, bool useXim)
@ -101,6 +102,15 @@ namespace Avalonia.X11
{
//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 _xic;
private IntPtr _renderHandle;
private IntPtr _xSyncCounter;
private XSyncValue _xSyncValue;
private bool _mapped;
private bool _wasMappedAtLeastOnce = false;
private double? _scalingOverride;
@ -188,6 +190,16 @@ namespace Avalonia.X11
NativeMenuExporter = DBusMenuExporter.TryCreateTopLevelNativeMenu(_handle);
NativeControlHost = new X11NativeControlHost(_platform, this);
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
@ -381,15 +393,7 @@ namespace Avalonia.X11
(ev.type == XEventName.VisibilityNotify &&
ev.VisibilityEvent.state < 2))
{
if (!_triggeredExpose)
{
_triggeredExpose = true;
Dispatcher.UIThread.Post(() =>
{
_triggeredExpose = false;
DoPaint();
}, DispatcherPriority.Render);
}
EnqueuePaint();
}
else if (ev.type == XEventName.FocusIn)
{
@ -501,6 +505,7 @@ namespace Avalonia.X11
if (_useRenderWindow)
XConfigureResizeWindow(_x11.Display, _renderHandle, ev.ConfigureEvent.width,
ev.ConfigureEvent.height);
EnqueuePaint();
}
else if (ev.type == XEventName.DestroyNotify
&& ev.DestroyWindowEvent.window == _handle)
@ -516,7 +521,11 @@ namespace Avalonia.X11
if (Closing?.Invoke() != true)
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)
@ -728,9 +737,24 @@ namespace Avalonia.X11
ScheduleInput(mev, ref ev);
}
void EnqueuePaint()
{
if (!_triggeredExpose)
{
_triggeredExpose = true;
Dispatcher.UIThread.Post(() =>
{
_triggeredExpose = false;
DoPaint();
}, DispatcherPriority.Render);
}
}
void DoPaint()
{
Paint?.Invoke(new Rect());
if (_xSyncCounter != IntPtr.Zero)
XSyncSetCounter(_x11.Display, _xSyncCounter, _xSyncValue);
}
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,
out int event_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)]
public static extern int XRRQueryVersion(IntPtr dpy,
@ -627,6 +639,11 @@ namespace Avalonia.X11
public int bw;
public int d;
}
public struct XSyncValue {
public int Hi;
public uint Lo;
}
public static bool XGetGeometry(IntPtr display, IntPtr window, out XGeometry geo)
{

Loading…
Cancel
Save