Browse Source

[X11] Changed event loop to avoid handling events too late

pull/2011/head
Nikita Tsukanov 7 years ago
committed by Dan Walmsley
parent
commit
22acc5147e
  1. 126
      src/Avalonia.X11/X11PlatformThreading.cs

126
src/Avalonia.X11/X11PlatformThreading.cs

@ -141,6 +141,64 @@ namespace Avalonia.X11
{
return t2.Priority - t1.Priority;
}
void CheckSignaled()
{
int buf = 0;
while (read(_sigread, &buf, new IntPtr(4)).ToInt64() > 0)
{
}
DispatcherPriority prio;
lock (_lock)
{
if (!_signaled)
return;
_signaled = false;
prio = _signaledPriority;
_signaledPriority = DispatcherPriority.MinValue;
}
Signaled?.Invoke(prio);
}
void HandleX11(CancellationToken cancellationToken)
{
while (true)
{
var pending = XPending(_display);
if (pending == 0)
break;
while (pending > 0)
{
if (cancellationToken.IsCancellationRequested)
return;
XNextEvent(_display, out var xev);
if (xev.type == XEventName.GenericEvent)
XGetEventData(_display, &xev.GenericEventCookie);
pending--;
try
{
if (xev.type == XEventName.GenericEvent)
{
if (_platform.XI2 != null && _platform.Info.XInputOpcode ==
xev.GenericEventCookie.extension)
{
_platform.XI2.OnEvent((XIEvent*)xev.GenericEventCookie.data);
}
}
else if (_eventHandlers.TryGetValue(xev.AnyEvent.window, out var handler))
handler(xev);
}
finally
{
if (xev.type == XEventName.GenericEvent && xev.GenericEventCookie.data != null)
XFreeEventData(_display, &xev.GenericEventCookie);
}
}
}
Dispatcher.UIThread.RunJobs();
}
public void RunLoop(CancellationToken cancellationToken)
{
@ -179,71 +237,13 @@ namespace Avalonia.X11
//Flush whatever requests were made to XServer
XFlush(_display);
epoll_event ev;
var len = epoll_wait(_epoll, &ev, 1,
nextTick == null ? -1 : Math.Max(1, (int)(nextTick.Value - _clock.Elapsed).TotalMilliseconds));
if (XPending(_display) == 0)
epoll_wait(_epoll, &ev, 1,
nextTick == null ? -1 : Math.Max(1, (int)(nextTick.Value - _clock.Elapsed).TotalMilliseconds));
if (cancellationToken.IsCancellationRequested)
return;
if (len == 0)
{
// We handle timer-related stuff at the beginning of the loop
continue;
}
else
{
if (ev.data.u32 == (int)EventCodes.Signal)
{
int buf = 0;
while (read(_sigread, &buf, new IntPtr(4)).ToInt64() > 0)
{
}
DispatcherPriority prio;
lock (_lock)
{
_signaled = false;
prio = _signaledPriority;
_signaledPriority = DispatcherPriority.MinValue;
}
Signaled?.Invoke(prio);
}
else
{
while (true)
{
var pending = XPending(_display);
if (pending == 0)
break;
while (pending > 0)
{
if (cancellationToken.IsCancellationRequested)
return;
XNextEvent(_display, out var xev);
if (xev.type == XEventName.GenericEvent)
XGetEventData(_display, &xev.GenericEventCookie);
pending--;
try
{
if (xev.type == XEventName.GenericEvent)
{
if (_platform.XI2 != null && _platform.Info.XInputOpcode ==
xev.GenericEventCookie.extension)
{
_platform.XI2.OnEvent((XIEvent*)xev.GenericEventCookie.data);
}
}
else if (_eventHandlers.TryGetValue(xev.AnyEvent.window, out var handler))
handler(xev);
}
finally
{
if (xev.type == XEventName.GenericEvent && xev.GenericEventCookie.data != null)
XFreeEventData(_display, &xev.GenericEventCookie);
}
}
}
Dispatcher.UIThread.RunJobs();
}
}
CheckSignaled();
HandleX11(cancellationToken);
}
}

Loading…
Cancel
Save