Merge branch 'tlw-geom'

Improve saving/restoring TLW geometry under MSW.

See https://github.com/wxWidgets/wxWidgets/pull/795
This commit is contained in:
Vadim Zeitlin
2018-05-02 15:27:04 +02:00
9 changed files with 597 additions and 94 deletions

View File

@@ -88,6 +88,7 @@ wxMSW:
- Fix hang after clearing wxTAB_TRAVERSAL style on a window with children.
- Fix handling of AUX2 mouse button events (Trylz).
- Fix saving/restoring window position for maximized windows.
3.1.1: (released 2018-02-19)

View File

@@ -0,0 +1,77 @@
///////////////////////////////////////////////////////////////////////////////
// Name: wx/gtk/private/tlwgeom.h
// Purpose: wxGTK-specific wxTLWGeometry class.
// Author: Vadim Zeitlin
// Created: 2018-04-29
// Copyright: (c) 2018 Vadim Zeitlin <vadim@wxwidgets.org>
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#ifndef _WX_GTK_PRIVATE_TLWGEOM_H_
#define _WX_GTK_PRIVATE_TLWGEOM_H_
class wxTLWGeometry : public wxTLWGeometryGeneric
{
public:
virtual bool Save(const Serializer& ser) const wxOVERRIDE
{
if ( !wxTLWGeometryGeneric::Save(ser) )
return false;
// Don't save the decoration sizes if we don't really have any values
// for them.
if ( m_decorSize.left || m_decorSize.right ||
m_decorSize.top || m_decorSize.bottom )
{
ser.SaveField("decor_l", m_decorSize.left);
ser.SaveField("decor_r", m_decorSize.right);
ser.SaveField("decor_t", m_decorSize.top);
ser.SaveField("decor_b", m_decorSize.bottom);
}
return true;
}
virtual bool Restore(Serializer& ser) wxOVERRIDE
{
if ( !wxTLWGeometryGeneric::Restore(ser) )
return false;
ser.RestoreField("decor_l", &m_decorSize.left);
ser.RestoreField("decor_r", &m_decorSize.right);
ser.RestoreField("decor_t", &m_decorSize.top);
ser.RestoreField("decor_b", &m_decorSize.bottom);
return true;
}
virtual bool GetFrom(const wxTopLevelWindow* tlw) wxOVERRIDE
{
if ( !wxTLWGeometryGeneric::GetFrom(tlw) )
return false;
m_decorSize = tlw->m_decorSize;
return true;
}
virtual bool ApplyTo(wxTopLevelWindow* tlw) wxOVERRIDE
{
if ( !wxTLWGeometryGeneric::ApplyTo(tlw) )
return false;
// Don't overwrite the current decoration size if we already have it.
if ( !tlw->m_decorSize.left && !tlw->m_decorSize.right &&
!tlw->m_decorSize.top && !tlw->m_decorSize.bottom )
{
tlw->m_decorSize = m_decorSize;
}
return true;
}
private:
wxTopLevelWindow::DecorSize m_decorSize;
};
#endif // _WX_GTK_PRIVATE_TLWGEOM_H_

View File

@@ -0,0 +1,126 @@
///////////////////////////////////////////////////////////////////////////////
// Name: wx/msw/private/tlwgeom.h
// Purpose: wxMSW-specific wxTLWGeometry class.
// Author: Vadim Zeitlin
// Created: 2018-04-29
// Copyright: (c) 2018 Vadim Zeitlin <vadim@wxwidgets.org>
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#ifndef _WX_MSW_PRIVATE_TLWGEOM_H_
#define _WX_MSW_PRIVATE_TLWGEOM_H_
#include "wx/log.h"
#include "wx/msw/private.h"
// names for MSW-specific options
#define wxPERSIST_TLW_MAX_X "xmax"
#define wxPERSIST_TLW_MAX_Y "ymax"
class wxTLWGeometry : public wxTLWGeometryBase
{
public:
wxTLWGeometry()
{
wxZeroMemory(m_placement);
m_placement.length = sizeof(m_placement);
}
virtual bool Save(const Serializer& ser) const wxOVERRIDE
{
// For compatibility with the existing saved positions/sizes, use the
// same keys as the generic version (which was previously used under
// MSW too).
// Normal position and size.
const RECT& rc = m_placement.rcNormalPosition;
if ( !ser.SaveField(wxPERSIST_TLW_X, rc.left) ||
!ser.SaveField(wxPERSIST_TLW_Y, rc.top) )
return false;
if ( !ser.SaveField(wxPERSIST_TLW_W, rc.right - rc.left) ||
!ser.SaveField(wxPERSIST_TLW_H, rc.bottom - rc.top) )
return false;
// Maximized/minimized state.
UINT show = m_placement.showCmd;
if ( !ser.SaveField(wxPERSIST_TLW_MAXIMIZED, show == SW_SHOWMAXIMIZED) )
return false;
if ( !ser.SaveField(wxPERSIST_TLW_ICONIZED, show == SW_SHOWMINIMIZED) )
return false;
// Maximized window position.
const POINT pt = m_placement.ptMaxPosition;
if ( !ser.SaveField(wxPERSIST_TLW_MAX_X, pt.x) ||
!ser.SaveField(wxPERSIST_TLW_MAX_Y, pt.y) )
return false;
// We don't currently save the minimized window position, it doesn't
// seem useful for anything and is probably just a left over from
// Windows 3.1 days, when icons were positioned on the desktop instead
// of being located in the taskbar.
return true;
}
virtual bool Restore(Serializer& ser) wxOVERRIDE
{
// Normal position and size.
wxRect r;
if ( !ser.RestoreField(wxPERSIST_TLW_X, &r.x) ||
!ser.RestoreField(wxPERSIST_TLW_Y, &r.y) ||
!ser.RestoreField(wxPERSIST_TLW_W, &r.width) ||
!ser.RestoreField(wxPERSIST_TLW_H, &r.height) )
return false;
wxCopyRectToRECT(r, m_placement.rcNormalPosition);
// Maximized/minimized state.
int tmp;
UINT& show = m_placement.showCmd;
if ( ser.RestoreField(wxPERSIST_TLW_MAXIMIZED, &tmp) && tmp )
show = SW_SHOWMAXIMIZED;
else if ( ser.RestoreField(wxPERSIST_TLW_ICONIZED, &tmp) && tmp )
show = SW_SHOWMINIMIZED;
else
show = SW_SHOWNORMAL;
// Maximized window position.
if ( ser.RestoreField(wxPERSIST_TLW_MAX_X, &r.x) &&
ser.RestoreField(wxPERSIST_TLW_MAX_Y, &r.y) )
{
m_placement.ptMaxPosition.x = r.x;
m_placement.ptMaxPosition.y = r.y;
}
return true;
}
virtual bool GetFrom(const wxTopLevelWindow* tlw) wxOVERRIDE
{
if ( !::GetWindowPlacement(GetHwndOf(tlw), &m_placement) )
{
wxLogLastError(wxS("GetWindowPlacement"));
return false;
}
return true;
}
virtual bool ApplyTo(wxTopLevelWindow* tlw) wxOVERRIDE
{
if ( !::SetWindowPlacement(GetHwndOf(tlw), &m_placement) )
{
wxLogLastError(wxS("SetWindowPlacement"));
return false;
}
return true;
}
private:
WINDOWPLACEMENT m_placement;
};
#endif // _WX_MSW_PRIVATE_TLWGEOM_H_

View File

@@ -13,7 +13,6 @@
#include "wx/persist/window.h"
#include "wx/toplevel.h"
#include "wx/display.h"
// ----------------------------------------------------------------------------
// string constants used by wxPersistentTLW
@@ -24,21 +23,13 @@
// windows, just persistent controls which have their own specific kind strings
#define wxPERSIST_TLW_KIND "Window"
// names for various persistent options
#define wxPERSIST_TLW_X "x"
#define wxPERSIST_TLW_Y "y"
#define wxPERSIST_TLW_W "w"
#define wxPERSIST_TLW_H "h"
#define wxPERSIST_TLW_MAXIMIZED "Maximized"
#define wxPERSIST_TLW_ICONIZED "Iconized"
// ----------------------------------------------------------------------------
// wxPersistentTLW: supports saving/restoring window position and size as well
// as maximized/iconized/restore state
// ----------------------------------------------------------------------------
class wxPersistentTLW : public wxPersistentWindow<wxTopLevelWindow>
class wxPersistentTLW : public wxPersistentWindow<wxTopLevelWindow>,
private wxTopLevelWindow::GeometrySerializer
{
public:
wxPersistentTLW(wxTopLevelWindow *tlw)
@@ -50,96 +41,28 @@ public:
{
const wxTopLevelWindow * const tlw = Get();
const wxPoint pos = tlw->GetScreenPosition();
SaveValue(wxPERSIST_TLW_X, pos.x);
SaveValue(wxPERSIST_TLW_Y, pos.y);
// notice that we use GetSize() here and not GetClientSize() because
// the latter doesn't return correct results for the minimized windows
// (at least not under Windows)
//
// of course, it shouldn't matter anyhow usually, the client size
// should be preserved as well unless the size of the decorations
// changed between the runs
const wxSize size = tlw->GetSize();
SaveValue(wxPERSIST_TLW_W, size.x);
SaveValue(wxPERSIST_TLW_H, size.y);
SaveValue(wxPERSIST_TLW_MAXIMIZED, tlw->IsMaximized());
SaveValue(wxPERSIST_TLW_ICONIZED, tlw->IsIconized());
#ifdef __WXGTK20__
SaveValue("decor_l", tlw->m_decorSize.left);
SaveValue("decor_r", tlw->m_decorSize.right);
SaveValue("decor_t", tlw->m_decorSize.top);
SaveValue("decor_b", tlw->m_decorSize.bottom);
#endif
tlw->SaveGeometry(*this);
}
virtual bool Restore() wxOVERRIDE
{
wxTopLevelWindow * const tlw = Get();
wxPoint pos;
wxSize size;
const bool hasPos = RestoreValue(wxPERSIST_TLW_X, &pos.x) &&
RestoreValue(wxPERSIST_TLW_Y, &pos.y);
const bool hasSize = RestoreValue(wxPERSIST_TLW_W, &size.x) &&
RestoreValue(wxPERSIST_TLW_H, &size.y);
#ifdef __WXGTK20__
wxTopLevelWindowGTK::DecorSize decorSize;
if (tlw->m_decorSize.top == 0 &&
RestoreValue("decor_l", &decorSize.left) &&
RestoreValue("decor_r", &decorSize.right) &&
RestoreValue("decor_t", &decorSize.top) &&
RestoreValue("decor_b", &decorSize.bottom))
{
tlw->m_decorSize = decorSize;
}
#endif
if ( hasPos )
{
// to avoid making the window completely invisible if it had been
// shown on a monitor which was disconnected since the last run
// (this is pretty common for notebook with external displays)
//
// NB: we should allow window position to be (slightly) off screen,
// it's not uncommon to position the window so that its upper
// left corner has slightly negative coordinate
if ( wxDisplay::GetFromPoint(pos) != wxNOT_FOUND ||
(hasSize && wxDisplay::GetFromPoint(pos + size) != wxNOT_FOUND) )
{
tlw->Move(pos, wxSIZE_ALLOW_MINUS_ONE);
}
//else: should we try to adjust position/size somehow?
}
if ( hasSize )
{
// a previous version of the program could have saved the window
// size which used to be big enough, but which is not big enough
// any more for the new version, so check that the size we restore
// doesn't cut off parts of the window
size.IncTo(tlw->GetBestSize());
tlw->SetSize(size);
}
// note that the window can be both maximized and iconized
bool maximized;
if ( RestoreValue(wxPERSIST_TLW_MAXIMIZED, &maximized) && maximized )
tlw->Maximize();
bool iconized;
if ( RestoreValue(wxPERSIST_TLW_ICONIZED, &iconized) && iconized )
tlw->Iconize();
// the most important property of the window that we restore is its
// size, so disregard the value of hasPos here
return hasSize;
return tlw->RestoreToGeometry(*this);
}
virtual wxString GetKind() const wxOVERRIDE { return wxPERSIST_TLW_KIND; }
private:
virtual bool SaveField(const wxString& name, int value) const wxOVERRIDE
{
return SaveValue(name, value);
}
virtual bool RestoreField(const wxString& name, int* value) wxOVERRIDE
{
return RestoreValue(name, value);
}
};
inline wxPersistentObject *wxCreatePersistentObject(wxTopLevelWindow *tlw)

View File

@@ -0,0 +1,184 @@
///////////////////////////////////////////////////////////////////////////////
// Name: wx/private/tlwgeom.h
// Purpose: Declaration of platform-specific and private wxTLWGeometry.
// Author: Vadim Zeitlin
// Created: 2018-04-29
// Copyright: (c) 2018 Vadim Zeitlin <vadim@wxwidgets.org>
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#ifndef _WX_PRIVATE_TLWGEOM_H_
#define _WX_PRIVATE_TLWGEOM_H_
#include "wx/display.h"
#include "wx/toplevel.h"
// ----------------------------------------------------------------------------
// wxTLWGeometryBase: abstract base class for platform-specific classes
// ----------------------------------------------------------------------------
// wxTLWGeometry contains full information about the window geometry, which may
// include things other than the obvious ones like its current position and
// size (e.g. under MSW it also stores the position of the maximized window,
// under GTK the size of non-client decorations etc). It is private to wx and
// is only used indirectly, via wxTopLevelWindow::SaveGeometry() and
// RestoreToGeometry() methods, in the public API.
class wxTLWGeometryBase
{
public:
typedef wxTopLevelWindow::GeometrySerializer Serializer;
wxTLWGeometryBase() {}
virtual ~wxTLWGeometryBase() {}
// Initialize from the given window.
virtual bool GetFrom(const wxTopLevelWindow* tlw) = 0;
// Resize the window to use this geometry.
virtual bool ApplyTo(wxTopLevelWindow* tlw) = 0;
// Serialize or deserialize the object by using the provided object for
// writing/reading the values of the different fields of this object.
virtual bool Save(const Serializer& ser) const = 0;
virtual bool Restore(Serializer& ser) = 0;
};
// ----------------------------------------------------------------------------
// wxTLWGeometryGeneric: simplest possible generic implementation
// ----------------------------------------------------------------------------
// names for various persistent options
#define wxPERSIST_TLW_X "x"
#define wxPERSIST_TLW_Y "y"
#define wxPERSIST_TLW_W "w"
#define wxPERSIST_TLW_H "h"
#define wxPERSIST_TLW_MAXIMIZED "Maximized"
#define wxPERSIST_TLW_ICONIZED "Iconized"
// MSW has its own native implementation and doesn't use this class.
#ifndef __WXMSW__
class wxTLWGeometryGeneric : public wxTLWGeometryBase
{
public:
wxTLWGeometryGeneric()
{
m_hasPos =
m_hasSize =
m_iconized =
m_maximized = false;
}
virtual bool Save(const Serializer& ser) const wxOVERRIDE
{
if ( !ser.SaveField(wxPERSIST_TLW_X, m_rectScreen.x) ||
!ser.SaveField(wxPERSIST_TLW_Y, m_rectScreen.y) )
return false;
if ( !ser.SaveField(wxPERSIST_TLW_W, m_rectScreen.width) ||
!ser.SaveField(wxPERSIST_TLW_H, m_rectScreen.height) )
return false;
if ( !ser.SaveField(wxPERSIST_TLW_MAXIMIZED, m_maximized) )
return false;
if ( !ser.SaveField(wxPERSIST_TLW_ICONIZED, m_iconized) )
return false;
return true;
}
virtual bool Restore(Serializer& ser) wxOVERRIDE
{
m_hasPos = ser.RestoreField(wxPERSIST_TLW_X, &m_rectScreen.x) &&
ser.RestoreField(wxPERSIST_TLW_Y, &m_rectScreen.y);
m_hasSize = ser.RestoreField(wxPERSIST_TLW_W, &m_rectScreen.width) &&
ser.RestoreField(wxPERSIST_TLW_H, &m_rectScreen.height);
int tmp;
if ( ser.RestoreField(wxPERSIST_TLW_MAXIMIZED, &tmp) )
m_maximized = tmp != 0;
if ( ser.RestoreField(wxPERSIST_TLW_ICONIZED, &tmp) )
m_iconized = tmp != 0;
// If we restored at least something, return true.
return m_hasPos || m_hasSize || m_maximized || m_iconized;
}
virtual bool GetFrom(const wxTopLevelWindow* tlw) wxOVERRIDE
{
m_rectScreen = tlw->GetScreenRect();
m_hasPos =
m_hasSize = true;
m_iconized = tlw->IsIconized();
m_maximized = tlw->IsMaximized();
return true;
}
virtual bool ApplyTo(wxTopLevelWindow* tlw) wxOVERRIDE
{
if ( m_hasPos )
{
// to avoid making the window completely invisible if it had been
// shown on a monitor which was disconnected since the last run
// (this is pretty common for notebook with external displays)
//
// NB: we should allow window position to be (slightly) off screen,
// it's not uncommon to position the window so that its upper
// left corner has slightly negative coordinate
if ( wxDisplay::GetFromPoint(m_rectScreen.GetTopLeft()) != wxNOT_FOUND ||
(m_hasSize &&
wxDisplay::GetFromPoint(m_rectScreen.GetBottomRight()) != wxNOT_FOUND) )
{
tlw->Move(m_rectScreen.GetTopLeft(), wxSIZE_ALLOW_MINUS_ONE);
}
//else: should we try to adjust position/size somehow?
}
if ( m_hasSize )
{
// a previous version of the program could have saved the window
// size which used to be big enough, but which is not big enough
// any more for the new version, so check that the size we restore
// doesn't cut off parts of the window
wxSize size = m_rectScreen.GetSize();
size.IncTo(tlw->GetBestSize());
tlw->SetSize(size);
}
// note that the window can be both maximized and iconized
if ( m_maximized )
tlw->Maximize();
if ( m_iconized )
tlw->Iconize();
return true;
}
private:
wxRect m_rectScreen;
bool m_hasPos;
bool m_hasSize;
bool m_iconized;
bool m_maximized;
};
#endif // !__WXMSW__
#ifdef __WXGTK20__
#include "wx/gtk/private/tlwgeom.h"
#elif defined(__WXMSW__)
#include "wx/msw/private/tlwgeom.h"
#else
class wxTLWGeometry : public wxTLWGeometryGeneric
{
};
#endif
#endif // _WX_PRIVATE_TLWGEOM_H_

View File

@@ -24,8 +24,6 @@
// the default names for various classes
extern WXDLLIMPEXP_DATA_CORE(const char) wxFrameNameStr[];
class WXDLLIMPEXP_FWD_CORE wxTopLevelWindowBase;
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
@@ -240,6 +238,35 @@ public:
wxWindow *SetTmpDefaultItem(wxWindow *win)
{ wxWindow *old = GetDefaultItem(); m_winTmpDefault = win; return old; }
// Class for saving/restoring fields describing the window geometry.
//
// This class is used by the functions below to allow saving the geometry
// of the window and restoring it later. The components describing geometry
// are platform-dependent, so there is no struct containing them and
// instead the methods of this class are used to save or [try to] restore
// whichever components are used under the current platform.
class GeometrySerializer
{
public:
virtual ~GeometrySerializer() {}
// If saving a field returns false, it's fatal error and SaveGeometry()
// will return false.
virtual bool SaveField(const wxString& name, int value) const = 0;
// If restoring a field returns false, it just means that the field is
// not present and RestoreToGeometry() still continues with restoring
// the other values.
virtual bool RestoreField(const wxString& name, int* value) = 0;
};
// Save the current window geometry using the provided serializer and
// restore the window to the previously saved geometry.
bool SaveGeometry(const GeometrySerializer& ser) const;
bool RestoreToGeometry(GeometrySerializer& ser);
// implementation only from now on
// -------------------------------

View File

@@ -350,6 +350,94 @@ public:
*/
void Restore();
/**
Class used with SaveGeometry() and RestoreToGeometry().
This is an abstract base class, i.e. to use it you must define a
derived class implementing the pure virtual SaveField() and
RestoreField() methods.
For example, if you wished to store the window geometry in a database,
you could derive a class saving fields such as "width" or "height" in a
table in this database and restoring them from it later.
@since 3.1.2
*/
class GeometrySerializer
{
/**
Save a single field with the given value.
Note that if this function returns @false, SaveGeometry() supposes
that saving the geometry failed and returns @false itself, without
even trying to save anything else.
@param name uniquely identifies the field but is otherwise
arbitrary.
@param value value of the field (can be positive or negative, i.e.
it can't be assumed that a value like -1 is invalid).
@return @true if the field was saved or @false if saving it failed,
resulting in wxTopLevelWindow::SaveGeometry() failure.
*/
virtual bool SaveField(const wxString& name, int value) const = 0;
/**
Try to restore a single field.
Unlike for SaveField(), returning @false from this function may
indicate that the value simply wasn't present and doesn't prevent
RestoreToGeometry() from continuing with trying to restore the
other values.
@param name uniquely identifies the field
@param value non-@NULL pointer to the value to be filled by this
function
@return @true if the value was retrieved or @false if it wasn't
found or an error occurred.
*/
virtual bool RestoreField(const wxString& name, int* value) = 0;
};
/**
Restores the window to the previously saved geometry.
This is a companion function to SaveGeometry() and can be called later
to restore the window to the geometry it had when it was saved.
@param ser An object implementing GeometrySerializer virtual methods.
@return @true if any (and, usually, but not necessarily, all) of the
window geometry attributes were restored or @false if there was no
saved geometry information at all or restoring it failed.
@since 3.1.2
*/
bool RestoreToGeometry(GeometrySerializer& ser);
/**
Save the current window geometry to allow restoring it later.
After calling this function, window geometry is saved in the provided
serializer and calling RestoreToGeometry() with the same serializer
later (i.e. usually during a subsequent program execution) would
restore the window to the same position, size, maximized/minimized
state etc.
This function is used by wxPersistentTLW, so it is not necessary to use
it if the goal is to just save and restore window geometry in the
simplest possible way. However is more flexibility is required, it can
be also used directly with a custom serializer object.
@param ser An object implementing GeometrySerializer virtual methods.
@return @true if the geometry was saved, @false if doing it failed
@since 3.1.2
*/
bool SaveGeometry(const GeometrySerializer& ser) const;
/**
Changes the default item for the panel, usually @a win is a button.

View File

@@ -31,6 +31,8 @@
#include "wx/display.h"
#include "wx/private/tlwgeom.h"
// ----------------------------------------------------------------------------
// event table
// ----------------------------------------------------------------------------
@@ -310,6 +312,28 @@ void wxTopLevelWindowBase::DoCentre(int dir)
SetSize(rect, wxSIZE_ALLOW_MINUS_ONE);
}
// ----------------------------------------------------------------------------
// Saving/restoring geometry
// ----------------------------------------------------------------------------
bool wxTopLevelWindowBase::SaveGeometry(const GeometrySerializer& ser) const
{
wxTLWGeometry geom;
if ( !geom.GetFrom(static_cast<const wxTopLevelWindow*>(this)) )
return false;
return geom.Save(ser);
}
bool wxTopLevelWindowBase::RestoreToGeometry(GeometrySerializer& ser)
{
wxTLWGeometry geom;
if ( !geom.Restore(ser) )
return false;
return geom.ApplyTo(static_cast<wxTopLevelWindow*>(this));
}
// ----------------------------------------------------------------------------
// wxTopLevelWindow size management: we exclude the areas taken by
// menu/status/toolbars from the client area, so the client area is what's

View File

@@ -101,6 +101,59 @@ TEST_CASE_METHOD(PersistenceTests, "wxPersistTLW", "[persist][tlw]")
CHECK(!frame->IsMaximized());
CHECK(!frame->IsIconized());
// Next try that restoring a minimized frame works correctly: for
// Iconize() to have effect, we must show the frame first.
frame->Iconize();
frame->Show();
delete frame;
}
// Check geometry after restoring the minimized frame.
{
wxFrame* const frame = CreatePersistenceTestFrame();
CHECK(wxPersistenceManager::Get().RegisterAndRestore(frame));
CHECK(!frame->IsMaximized());
CHECK(frame->IsIconized());
frame->Restore();
CHECK(pos.x == frame->GetPosition().x);
CHECK(pos.y == frame->GetPosition().y);
CHECK(size.x == frame->GetSize().GetWidth());
CHECK(size.y == frame->GetSize().GetHeight());
// Next try that restoring a maximized frame works correctly: again,
// for it to be really maximized, it must be shown.
frame->Maximize();
frame->Show();
delete frame;
}
// Check geometry after restoring the maximized frame.
//
// This test currently fails under non-MSW platforms as they only save the
// maximized frame size, and its normal size is lost and can't be restored.
#ifdef __WXMSW__
{
wxFrame* const frame = CreatePersistenceTestFrame();
CHECK(wxPersistenceManager::Get().RegisterAndRestore(frame));
CHECK(frame->IsMaximized());
CHECK(!frame->IsIconized());
frame->Restore();
CHECK(pos.x == frame->GetPosition().x);
CHECK(pos.y == frame->GetPosition().y);
CHECK(size.x == frame->GetSize().GetWidth());
CHECK(size.y == frame->GetSize().GetHeight());
delete frame;
}
#endif // __WXMSW__
}