Merge branch 'msw-tlw-state'

Fix showing TLWs under MSW when restoring their geometry.

See https://github.com/wxWidgets/wxWidgets/pull/842
This commit is contained in:
Vadim Zeitlin
2018-06-22 19:46:44 +02:00
6 changed files with 101 additions and 64 deletions

View File

@@ -321,7 +321,7 @@ WXLRESULT wxDialog::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lPar
switch ( wParam )
{
case SIZE_MINIMIZED:
m_iconized = true;
m_showCmd = SW_MINIMIZE;
break;
case SIZE_MAXIMIZED:
@@ -331,9 +331,9 @@ WXLRESULT wxDialog::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM lPar
if ( m_hGripper )
ShowGripper( wParam == SIZE_RESTORED );
if ( m_iconized )
if ( m_showCmd == SW_MINIMIZE )
(void)SendIconizeEvent(false);
m_iconized = false;
m_showCmd = SW_RESTORE;
break;
}

View File

@@ -261,7 +261,7 @@ void wxFrame::DoGetClientSize(int *x, int *y) const
// generate an artificial resize event
void wxFrame::SendSizeEvent(int flags)
{
if ( !m_iconized )
if ( !MSWIsIconized() )
{
RECT r = wxGetWindowRect(GetHwnd());
@@ -667,7 +667,7 @@ void wxFrame::PositionToolBar()
// on the desktop, but are iconized/restored with it
void wxFrame::IconizeChildFrames(bool bIconize)
{
m_iconized = bIconize;
m_showCmd = bIconize ? SW_MINIMIZE : SW_RESTORE;
for ( wxWindowList::compatibility_iterator node = GetChildren().GetFirst();
node;
@@ -743,6 +743,12 @@ bool wxFrame::MSWDoTranslateMessage(wxFrame *frame, WXMSG *pMsg)
bool wxFrame::HandleSize(int WXUNUSED(x), int WXUNUSED(y), WXUINT id)
{
// We can get a WM_SIZE when restoring a hidden window using
// SetWindowPlacement(), don't do anything in this case as our state will
// be really updated later, when (and if) we're shown.
if ( !IsShown() )
return true;
switch ( id )
{
case SIZE_RESTORED:
@@ -750,7 +756,7 @@ bool wxFrame::HandleSize(int WXUNUSED(x), int WXUNUSED(y), WXUINT id)
// only do it it if we were iconized before, otherwise resizing the
// parent frame has a curious side effect of bringing it under it's
// children
if ( !m_iconized )
if ( m_showCmd != SW_MINIMIZE )
break;
// restore all child frames too
@@ -765,7 +771,7 @@ bool wxFrame::HandleSize(int WXUNUSED(x), int WXUNUSED(y), WXUINT id)
break;
}
if ( !m_iconized )
if ( m_showCmd != SW_MINIMIZE )
{
#if wxUSE_STATUSBAR
PositionStatusBar();

View File

@@ -95,8 +95,7 @@ wxEND_EVENT_TABLE()
void wxTopLevelWindowMSW::Init()
{
m_iconized =
m_maximizeOnShow = false;
m_showCmd = SW_SHOWNORMAL;
// Data to save/restore when calling ShowFullScreen
m_fsStyle = 0;
@@ -522,14 +521,6 @@ void wxTopLevelWindowMSW::DoShowWindow(int nShowCmd)
{
::ShowWindow(GetHwnd(), nShowCmd);
// Hiding the window doesn't change its iconized state.
if ( nShowCmd != SW_HIDE )
{
// Otherwise restoring, maximizing or showing the window normally also
// makes it not iconized and only minimizing it does make it iconized.
m_iconized = nShowCmd == SW_MINIMIZE;
}
#if wxUSE_TOOLTIPS
// Don't leave a tooltip hanging around if TLW is hidden now.
wxToolTip::UpdateVisibility();
@@ -541,7 +532,12 @@ void wxTopLevelWindowMSW::ShowWithoutActivating()
if ( !wxWindowBase::Show(true) )
return;
DoShowWindow(SW_SHOWNA);
// We can't show the window in a maximized state without activating it, so
// the sequence of hiding the window, calling Maximize() and this function
// will end up with the window not being maximized -- but this is arguably
// better than activating it and is compatible with the historical
// behaviour of this function.
DoShowWindow(m_showCmd == SW_MINIMIZE ? SW_SHOWMINNOACTIVE : SW_SHOWNA);
}
bool wxTopLevelWindowMSW::Show(bool show)
@@ -553,18 +549,10 @@ bool wxTopLevelWindowMSW::Show(bool show)
int nShowCmd;
if ( show )
{
if ( m_maximizeOnShow )
// If we need to minimize or maximize the window, do it now.
if ( m_showCmd == SW_MAXIMIZE || m_showCmd == SW_MINIMIZE )
{
// show and maximize
nShowCmd = SW_MAXIMIZE;
m_maximizeOnShow = false;
}
else if ( m_iconized )
{
// We were iconized while we were hidden, so now we need to show
// the window in iconized state.
nShowCmd = SW_MINIMIZE;
nShowCmd = m_showCmd;
}
else if ( ::IsIconic(GetHwnd()) )
{
@@ -622,16 +610,19 @@ void wxTopLevelWindowMSW::Raise()
void wxTopLevelWindowMSW::Maximize(bool maximize)
{
// Update m_showCmd to ensure that the window is maximized when it's shown
// later even if it's currently hidden.
m_showCmd = maximize ? SW_MAXIMIZE : SW_RESTORE;
if ( IsShown() )
{
// just maximize it directly
DoShowWindow(maximize ? SW_MAXIMIZE : SW_RESTORE);
DoShowWindow(m_showCmd);
}
else // hidden
{
// we can't maximize the hidden frame because it shows it as well,
// so just remember that we should do it later in this case
m_maximizeOnShow = maximize;
// so don't do anything other than updating m_showCmd for now
#if wxUSE_DEFERRED_SIZING
// after calling Maximize() the client code expects to get the frame
@@ -659,45 +650,66 @@ bool wxTopLevelWindowMSW::IsMaximized() const
{
return IsAlwaysMaximized() ||
(::IsZoomed(GetHwnd()) != 0) ||
m_maximizeOnShow;
m_showCmd == SW_MAXIMIZE;
}
void wxTopLevelWindowMSW::Iconize(bool iconize)
{
if ( iconize == m_iconized )
if ( iconize == MSWIsIconized() )
{
// Do nothing, in particular don't restore non-iconized windows when
// Iconize(false) is called as this would wrongly un-maximize them.
return;
}
// Note that we can't change m_showCmd yet as wxFrame WM_SIZE handler uses
// its value to determine whether the frame had been iconized before or not
// and this handler will be called from inside DoShowWindow() below.
const UINT showCmd = iconize ? SW_MINIMIZE : SW_RESTORE;
// We can't actually iconize the window if it's currently hidden, as this
// would also show it unexpectedly.
if ( IsShown() )
{
// change the window state immediately
DoShowWindow(iconize ? SW_MINIMIZE : SW_RESTORE);
}
else // hidden
{
// iconizing the window shouldn't show it so just update the internal
// state (otherwise it's done by DoShowWindow() itself)
m_iconized = iconize;
DoShowWindow(showCmd);
}
// Update the internal flag in any case, so that IsIconized() returns the
// correct value, for example. And if the window is currently hidden, this
// also ensures that the next call to Show() will show it in an iconized
// state instead of showing it normally.
m_showCmd = showCmd;
}
bool wxTopLevelWindowMSW::IsIconized() const
{
if ( !IsShown() )
return m_iconized;
{
// Hidden windows are never actually iconized at MSW level, but can be
// in wx, so use m_showCmd to determine our status.
return m_showCmd == SW_MINIMIZE;
}
// don't use m_iconized, it may be briefly out of sync with the real state
// don't use m_showCmd, it may be briefly out of sync with the real state
// as it's only modified when we receive a WM_SIZE and we could be called
// from an event handler from one of the messages we receive before it,
// such as WM_MOVE
return MSWIsIconized();
}
bool wxTopLevelWindowMSW::MSWIsIconized() const
{
return ::IsIconic(GetHwnd()) != 0;
}
void wxTopLevelWindowMSW::Restore()
{
// Forget any previous minimized/maximized status.
m_showCmd = SW_SHOW;
// And actually restore the window to its normal state. Note that here,
// unlike in Maximize() and Iconize(), we do it even if the window is
// currently hidden, i.e. Restore() is supposed to show it in this case.
DoShowWindow(SW_RESTORE);
}
@@ -1181,7 +1193,7 @@ void wxTopLevelWindowMSW::DoThaw()
void wxTopLevelWindowMSW::DoSaveLastFocus()
{
if ( m_iconized )
if ( MSWIsIconized() )
return;
// remember the last focused child if it is our child
@@ -1211,7 +1223,7 @@ void wxTopLevelWindowMSW::OnActivate(wxActivateEvent& event)
// We get WM_ACTIVATE before being restored from iconized state, so we
// can be still iconized here. In this case, avoid restoring the focus
// as it doesn't work anyhow and we will do when we're really restored.
if ( m_iconized )
if ( MSWIsIconized() )
{
event.Skip();
return;