Don't change MDI children order after showing a file dialog in wxMSW.

Don't use the generic focus saving/restoring code for wxMDIParentFrame in
wxMSW as it already saves and restores the active MDI child on its own and we
should let it do it, as our code could change the active child when restoring
focus if it hadn't been saved correctly previously.

The fact that it is isn't saved is another bug, but even if it is fixed, we
should let MSW MDI implementation handle activation as we can't do it any
better -- but can do worse, as the bug described in #16635 shows.

Closes #16635.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@78341 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2015-01-03 01:07:53 +00:00
parent 8509ce2358
commit f3833aa067
3 changed files with 41 additions and 2 deletions

View File

@@ -127,6 +127,7 @@ wxMSW:
- Fix updating wxSpinCtrlDouble tooltip text (Laurent Poujoulat). - Fix updating wxSpinCtrlDouble tooltip text (Laurent Poujoulat).
- Fix appearance of checked disabled wxToolBar tools with custom images. - Fix appearance of checked disabled wxToolBar tools with custom images.
- Fix reading of not NUL-terminated strings using wxRegKey (Steffen Olszewski). - Fix reading of not NUL-terminated strings using wxRegKey (Steffen Olszewski).
- Fix unexpected change in MDI children order after showing a file dialog.
wxOSX/Cocoa: wxOSX/Cocoa:

View File

@@ -91,6 +91,7 @@ public:
// Responds to colour changes // Responds to colour changes
void OnSysColourChanged(wxSysColourChangedEvent& event); void OnSysColourChanged(wxSysColourChangedEvent& event);
void OnActivate(wxActivateEvent& event);
void OnSize(wxSizeEvent& event); void OnSize(wxSizeEvent& event);
void OnIconized(wxIconizeEvent& event); void OnIconized(wxIconizeEvent& event);
@@ -145,6 +146,10 @@ private:
// return the number of child frames we currently have (maybe 0) // return the number of child frames we currently have (maybe 0)
int GetChildFramesCount() const; int GetChildFramesCount() const;
// if true, indicates whether the event wasn't really processed even though
// it was "handled", see OnActivate() and HandleActivate()
bool m_activationNotHandled;
friend class WXDLLIMPEXP_FWD_CORE wxMDIChildFrame; friend class WXDLLIMPEXP_FWD_CORE wxMDIChildFrame;

View File

@@ -121,6 +121,7 @@ IMPLEMENT_DYNAMIC_CLASS(wxMDIChildFrame, wxFrame)
IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow, wxWindow) IMPLEMENT_DYNAMIC_CLASS(wxMDIClientWindow, wxWindow)
BEGIN_EVENT_TABLE(wxMDIParentFrame, wxFrame) BEGIN_EVENT_TABLE(wxMDIParentFrame, wxFrame)
EVT_ACTIVATE(wxMDIParentFrame::OnActivate)
EVT_SIZE(wxMDIParentFrame::OnSize) EVT_SIZE(wxMDIParentFrame::OnSize)
EVT_ICONIZE(wxMDIParentFrame::OnIconized) EVT_ICONIZE(wxMDIParentFrame::OnIconized)
EVT_SYS_COLOUR_CHANGED(wxMDIParentFrame::OnSysColourChanged) EVT_SYS_COLOUR_CHANGED(wxMDIParentFrame::OnSysColourChanged)
@@ -152,6 +153,8 @@ void wxMDIParentFrame::Init()
// the default menu doesn't have any accelerators (even if we have it) // the default menu doesn't have any accelerators (even if we have it)
m_accelWindowMenu = NULL; m_accelWindowMenu = NULL;
#endif // wxUSE_MENUS && wxUSE_ACCEL #endif // wxUSE_MENUS && wxUSE_ACCEL
m_activationNotHandled = false;
} }
bool wxMDIParentFrame::Create(wxWindow *parent, bool wxMDIParentFrame::Create(wxWindow *parent,
@@ -626,14 +629,44 @@ WXLRESULT wxMDIParentFrame::MSWWindowProc(WXUINT message,
return rc; return rc;
} }
void wxMDIParentFrame::OnActivate(wxActivateEvent& WXUNUSED(event))
{
// The base class version saves the current focus when we are being
// deactivated and restores it when the window is activated again, but this
// is not necessary here as DefWindowProc() for MDI parent frame already
// takes care of re-activating the MDI child that had been active the last
// time, and MDI children remember their own last focused child already,
// being subclasses of wxTLW.
//
// Moreover, in addition to being unnecessary, this can be actively harmful
// if we somehow don't have the focus any more at the moment of activation
// loss as happens when showing a standard file dialog under Windows 7, see
// #16635: in this case the base class just gives the focus to its first
// child, meaning that we can switch to a different MDI child, which is
// worse than losing focus inside the current child.
//
// So we don't let the base class have this event to prevent this from
// happening. But the event is not really processed, so we set a flag here
// which is used in HandleActivate() below to check if the event was really
// processed (and not skipped) in the user code or just reached this dummy
// handler.
m_activationNotHandled = true;
}
bool wxMDIParentFrame::HandleActivate(int state, bool minimized, WXHWND activate) bool wxMDIParentFrame::HandleActivate(int state, bool minimized, WXHWND activate)
{ {
bool processed = false; bool processed = false;
// Set the flag before testing it to ensure the only way for it to be true
// is to be set in our OnActivate() -- and not just remain set from the
// last time.
m_activationNotHandled = false;
if ( wxWindow::HandleActivate(state, minimized, activate) ) if ( wxWindow::HandleActivate(state, minimized, activate) )
{ {
// already processed // already processed, unless we artificially marked the event as
processed = true; // handled in our own handler without really processing it
processed = !m_activationNotHandled;
} }
// If this window is an MDI parent, we must also send an OnActivate message // If this window is an MDI parent, we must also send an OnActivate message