Improve WaitForPaint helper used in window unit tests

Unbind the event handler referencing a local variable, as leaving it
bound could result in a crash later if another paint event was generated
for the window for whatever reason.

Doing it like this requires using 2 different objects, but the
complexity can be still hidden inside WaitForPaint class, with the 2nd
object being just a member of it, and, in fact, makes the code using it
simpler as it doesn't need to use a boolean variable with it.
This commit is contained in:
Vadim Zeitlin
2019-10-17 17:07:00 +02:00
parent ed783b95f8
commit 7d6d514984

View File

@@ -51,13 +51,37 @@ protected:
class WaitForPaint class WaitForPaint
{ {
public: public:
// Note that we have to use a pointer here, i.e. we can't just store the explicit WaitForPaint(wxWindow* win)
// flag inside the class itself because it's going to be cloned inside wx : m_win(*win),
// and querying the flag of the original copy is not going to work. m_painted(false),
explicit WaitForPaint(bool* painted) m_handler(&m_painted)
{
m_win.Bind(wxEVT_PAINT, m_handler);
}
bool GotPaintEvent() const
{
return m_painted;
}
~WaitForPaint()
{
m_win.Unbind(wxEVT_PAINT, m_handler);
}
private:
wxWindow& m_win;
bool m_painted;
class PaintHandler
{
public:
// Note that we have to use a pointer here, i.e. we can't just store
// the flag inside the class itself because it's going to be cloned
// inside wx and querying the flag of the original copy wouldtn' work.
explicit PaintHandler(bool* painted)
: m_painted(*painted) : m_painted(*painted)
{ {
m_painted = false;
} }
void operator()(wxPaintEvent& event) void operator()(wxPaintEvent& event)
@@ -66,8 +90,9 @@ public:
m_painted = true; m_painted = true;
} }
private: private:
bool& m_painted; bool& m_painted;
} m_handler;
}; };
// This function should be used to show the window and wait until we can get // This function should be used to show the window and wait until we can get
@@ -79,14 +104,12 @@ void ShowAndWaitForPaint(wxWindow* w)
// geometry. And it's not clear how long should we wait, so we do it until // geometry. And it's not clear how long should we wait, so we do it until
// we get the first paint event -- by then the window really should have // we get the first paint event -- by then the window really should have
// its final size. // its final size.
bool painted; WaitForPaint waitForPaint(w);
WaitForPaint waitForPaint(&painted);
w->Bind(wxEVT_PAINT, waitForPaint);
w->Show(); w->Show();
wxStopWatch sw; wxStopWatch sw;
while ( !painted ) while ( !waitForPaint.GotPaintEvent() )
{ {
wxYield(); wxYield();