Wait for XEvents when changing window size

Fixes #259

Reading from GameWindow.ClientSize after assigning a new value to it
could often return the old value on X systems.
This was due to ClientSize being set by a ConfigureNotify event sent
by the X server that we would sometimes not during the ProcessEvents
started by the ClientSize setter (due to the asynchronous nature or
client/server).

This commit adds a way to wait for a specific event type in
ProcessEvents. Just before calling ProcessEvents in the ClientSize
setter we set the wait type to ConfigureNotify. This should ensure
that ClientSize will not return until we've received the new size of
the window from the X server and updated our internal values for the
size of the window. Thus when ClientSize is then read immediately
after it is always the new size.

It's likely that some of the other property setters we have which call
ProcessEvents need a similar fix.
This commit is contained in:
Fraser Waters 2017-07-10 16:57:40 +01:00
parent 9ea1f55139
commit a7f43f3f05

View file

@ -147,6 +147,12 @@ namespace OpenTK.Platform.X11
readonly int xi2_version;
#pragma warning restore 414
// Used to wait for a specific type of event in ProcessEvents.
// Currently this is just used by ClientSize to wait for a
// ConfigureNotify event to ensure our size change has actually taken
// effect, see issue #259.
XEventName _waitForEvent = (XEventName)0;
public X11GLNative(int x, int y, int width, int height, string title,
GraphicsMode mode, GameWindowFlags options, DisplayDevice device)
: this()
@ -801,7 +807,21 @@ namespace OpenTK.Platform.X11
if (!Functions.XCheckWindowEvent(window.Display, window.Handle, window.EventMask, ref e) &&
!Functions.XCheckTypedWindowEvent(window.Display, window.Handle, XEventName.ClientMessage, ref e) &&
!Functions.XCheckTypedWindowEvent(window.Display, window.Handle, XEventName.SelectionNotify, ref e))
break;
{
if (_waitForEvent != (XEventName)0)
{
continue;
}
else
{
break;
}
}
}
if (_waitForEvent == e.type)
{
_waitForEvent = (XEventName)0;
}
// Respond to the event e
@ -1212,25 +1232,25 @@ namespace OpenTK.Platform.X11
set
{
bool is_size_changed = client_rectangle.Size != value;
int width = value.Width;
int height = value.Height;
if (WindowBorder != WindowBorder.Resizable)
if (is_size_changed)
{
SetWindowMinMax(width, height, width, height);
}
int width = value.Width;
int height = value.Height;
using (new XLock(window.Display))
{
if (is_size_changed)
if (WindowBorder != WindowBorder.Resizable)
{
SetWindowMinMax(width, height, width, height);
}
using (new XLock(window.Display))
{
Functions.XResizeWindow(window.Display, window.Handle,
width, height);
}
}
ProcessEvents();
_waitForEvent = XEventName.ConfigureNotify;
ProcessEvents();
}
}
}