From a7f43f3f051de2e789e221f7ebcfd44d1a2f6276 Mon Sep 17 00:00:00 2001 From: Fraser Waters Date: Mon, 10 Jul 2017 16:57:40 +0100 Subject: [PATCH] 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. --- src/OpenTK/Platform/X11/X11GLNative.cs | 46 ++++++++++++++++++-------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/src/OpenTK/Platform/X11/X11GLNative.cs b/src/OpenTK/Platform/X11/X11GLNative.cs index 34db0102..8a2c5e1e 100644 --- a/src/OpenTK/Platform/X11/X11GLNative.cs +++ b/src/OpenTK/Platform/X11/X11GLNative.cs @@ -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(); + } } }