moved OnActivate() logic from wxFrame to wxDialog -- this fixes infinite loop when handling WM_ACTIVATE in DefDlgProc in some crazy situations
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@15816 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
7cc3cec9a7
commit
085ad68651
@ -52,7 +52,6 @@ public:
|
||||
// -------------------------------
|
||||
|
||||
// event handlers
|
||||
void OnActivate(wxActivateEvent& event);
|
||||
void OnSysColourChanged(wxSysColourChangedEvent& event);
|
||||
|
||||
// Toolbar
|
||||
@ -103,10 +102,6 @@ public:
|
||||
// current size - this has an effect of refreshing the window layout
|
||||
void SendSizeEvent();
|
||||
|
||||
// called by wxWindow whenever it gets focus
|
||||
void SetLastFocus(wxWindow *win) { m_winLastFocused = win; }
|
||||
wxWindow *GetLastFocus() const { return m_winLastFocused; }
|
||||
|
||||
protected:
|
||||
// common part of all ctors
|
||||
void Init();
|
||||
@ -142,14 +137,10 @@ protected:
|
||||
static bool m_useNativeStatusBar;
|
||||
#endif // wxUSE_STATUSBAR
|
||||
|
||||
// the last focused child: we restore focus to it on activation
|
||||
wxWindow *m_winLastFocused;
|
||||
|
||||
// Data to save/restore when calling ShowFullScreen
|
||||
int m_fsStatusBarFields; // 0 for no status bar
|
||||
int m_fsStatusBarHeight;
|
||||
int m_fsToolBarHeight;
|
||||
// WXHMENU m_fsMenu;
|
||||
|
||||
private:
|
||||
#if wxUSE_TOOLTIPS
|
||||
|
@ -70,6 +70,13 @@ public:
|
||||
// implementation from now on
|
||||
// --------------------------
|
||||
|
||||
// event handlers
|
||||
void OnActivate(wxActivateEvent& event);
|
||||
|
||||
// called by wxWindow whenever it gets focus
|
||||
void SetLastFocus(wxWindow *win) { m_winLastFocused = win; }
|
||||
wxWindow *GetLastFocus() const { return m_winLastFocused; }
|
||||
|
||||
protected:
|
||||
// common part of all ctors
|
||||
void Init();
|
||||
@ -89,10 +96,6 @@ protected:
|
||||
// common part of Iconize(), Maximize() and Restore()
|
||||
void DoShowWindow(int nShowCmd);
|
||||
|
||||
// prevent the window from being deactivated sometimes (see comments in the
|
||||
// code)
|
||||
long HandleNcActivate(bool activate);
|
||||
|
||||
// translate wxWindows flags to Windows ones
|
||||
virtual WXDWORD MSWGetStyle(long flags, WXDWORD *exstyle) const;
|
||||
|
||||
@ -113,9 +116,14 @@ protected:
|
||||
bool m_fsIsMaximized;
|
||||
bool m_fsIsShowing;
|
||||
|
||||
// the last focused child: we restore focus to it on activation
|
||||
wxWindow *m_winLastFocused;
|
||||
|
||||
// the hidden parent window for the frames which shouldn't appear in the
|
||||
// taskbar
|
||||
static wxWindow *ms_hiddenParent;
|
||||
|
||||
DECLARE_EVENT_TABLE()
|
||||
};
|
||||
|
||||
// list of all frames and modeless dialogs
|
||||
|
@ -364,6 +364,17 @@ void wxWindowBase::Centre(int direction)
|
||||
}
|
||||
}
|
||||
|
||||
// we shouldn't center the dialog on the iconized window: under
|
||||
// Windows, for example, this places it completely off the screen
|
||||
if ( parent )
|
||||
{
|
||||
wxTopLevelWindow *winTop = wxDynamicCast(parent, wxTopLevelWindow);
|
||||
if ( winTop && winTop->IsIconized() )
|
||||
{
|
||||
parent = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// did we find the parent?
|
||||
if ( !parent )
|
||||
{
|
||||
|
@ -72,7 +72,6 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
BEGIN_EVENT_TABLE(wxFrame, wxFrameBase)
|
||||
EVT_ACTIVATE(wxFrame::OnActivate)
|
||||
EVT_SYS_COLOUR_CHANGED(wxFrame::OnSysColourChanged)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
@ -108,11 +107,8 @@ void wxFrame::Init()
|
||||
m_fsStatusBarFields = 0;
|
||||
m_fsStatusBarHeight = 0;
|
||||
m_fsToolBarHeight = 0;
|
||||
// m_fsMenu = 0;
|
||||
|
||||
m_wasMinimized = FALSE;
|
||||
|
||||
m_winLastFocused = (wxWindow *)NULL;
|
||||
}
|
||||
|
||||
bool wxFrame::Create(wxWindow *parent,
|
||||
@ -324,7 +320,7 @@ void wxFrame::OnSysColourChanged(wxSysColourChangedEvent& event)
|
||||
// Pass TRUE to show full screen, FALSE to restore.
|
||||
bool wxFrame::ShowFullScreen(bool show, long style)
|
||||
{
|
||||
if ( IsFullScreen() == show )
|
||||
if ( IsFullScreen() == show )
|
||||
return FALSE;
|
||||
|
||||
if (show)
|
||||
@ -395,60 +391,10 @@ bool wxFrame::ShowFullScreen(bool show, long style)
|
||||
SetMenu((HWND)GetHWND(), (HMENU)m_hMenu);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
return wxFrameBase::ShowFullScreen(show, style);
|
||||
}
|
||||
|
||||
// Default activation behaviour - set the focus for the first child
|
||||
// subwindow found.
|
||||
void wxFrame::OnActivate(wxActivateEvent& event)
|
||||
{
|
||||
if ( event.GetActive() )
|
||||
{
|
||||
// restore focus to the child which was last focused
|
||||
wxLogTrace(_T("focus"), _T("wxFrame %08x activated."), m_hWnd);
|
||||
|
||||
wxWindow *parent = m_winLastFocused ? m_winLastFocused->GetParent()
|
||||
: NULL;
|
||||
if ( !parent )
|
||||
{
|
||||
parent = this;
|
||||
}
|
||||
|
||||
wxSetFocusToChild(parent, &m_winLastFocused);
|
||||
}
|
||||
else // deactivating
|
||||
{
|
||||
// remember the last focused child if it is our child
|
||||
m_winLastFocused = FindFocus();
|
||||
|
||||
// so we NULL it out if it's a child from some other frame
|
||||
wxWindow *win = m_winLastFocused;
|
||||
while ( win )
|
||||
{
|
||||
if ( win->IsTopLevel() )
|
||||
{
|
||||
if ( win != this )
|
||||
{
|
||||
m_winLastFocused = NULL;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
win = win->GetParent();
|
||||
}
|
||||
|
||||
wxLogTrace(_T("focus"),
|
||||
_T("wxFrame %08x deactivated, last focused: %08x."),
|
||||
m_hWnd,
|
||||
m_winLastFocused ? GetHwndOf(m_winLastFocused)
|
||||
: NULL);
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// tool/status bar stuff
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -77,6 +77,10 @@ wxWindow *wxTopLevelWindowMSW::ms_hiddenParent = NULL;
|
||||
// wxTopLevelWindowMSW implementation
|
||||
// ============================================================================
|
||||
|
||||
BEGIN_EVENT_TABLE(wxTopLevelWindowMSW, wxTopLevelWindowBase)
|
||||
EVT_ACTIVATE(wxTopLevelWindowMSW::OnActivate)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxDialog helpers
|
||||
// ----------------------------------------------------------------------------
|
||||
@ -116,6 +120,8 @@ void wxTopLevelWindowMSW::Init()
|
||||
m_fsOldWindowStyle = 0;
|
||||
m_fsIsMaximized = FALSE;
|
||||
m_fsIsShowing = FALSE;
|
||||
|
||||
m_winLastFocused = (wxWindow *)NULL;
|
||||
}
|
||||
|
||||
WXDWORD wxTopLevelWindowMSW::MSWGetStyle(long style, WXDWORD *exflags) const
|
||||
@ -740,3 +746,57 @@ bool wxTopLevelWindowMSW::EnableCloseButton(bool enable)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// wxTopLevelWindow event handling
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// Default activation behaviour - set the focus for the first child
|
||||
// subwindow found.
|
||||
void wxTopLevelWindowMSW::OnActivate(wxActivateEvent& event)
|
||||
{
|
||||
if ( event.GetActive() )
|
||||
{
|
||||
// restore focus to the child which was last focused
|
||||
wxLogTrace(_T("focus"), _T("wxTLW %08x activated."), m_hWnd);
|
||||
|
||||
wxWindow *parent = m_winLastFocused ? m_winLastFocused->GetParent()
|
||||
: NULL;
|
||||
if ( !parent )
|
||||
{
|
||||
parent = this;
|
||||
}
|
||||
|
||||
wxSetFocusToChild(parent, &m_winLastFocused);
|
||||
}
|
||||
else // deactivating
|
||||
{
|
||||
// remember the last focused child if it is our child
|
||||
m_winLastFocused = FindFocus();
|
||||
|
||||
// so we NULL it out if it's a child from some other frame
|
||||
wxWindow *win = m_winLastFocused;
|
||||
while ( win )
|
||||
{
|
||||
if ( win->IsTopLevel() )
|
||||
{
|
||||
if ( win != this )
|
||||
{
|
||||
m_winLastFocused = NULL;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
win = win->GetParent();
|
||||
}
|
||||
|
||||
wxLogTrace(_T("focus"),
|
||||
_T("wxTLW %08x deactivated, last focused: %08x."),
|
||||
m_hWnd,
|
||||
m_winLastFocused ? GetHwndOf(m_winLastFocused)
|
||||
: NULL);
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -348,12 +348,12 @@ wxWindowMSW::~wxWindowMSW()
|
||||
// VS: make sure there's no wxFrame with last focus set to us:
|
||||
for ( wxWindow *win = GetParent(); win; win = win->GetParent() )
|
||||
{
|
||||
wxFrame *frame = wxDynamicCast(win, wxFrame);
|
||||
wxTopLevelWindow *frame = wxDynamicCast(win, wxTopLevelWindow);
|
||||
if ( frame )
|
||||
{
|
||||
if ( frame->GetLastFocus() == this )
|
||||
{
|
||||
frame->SetLastFocus((wxWindow*)NULL);
|
||||
frame->SetLastFocus(NULL);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -2083,15 +2083,27 @@ bool wxWindowMSW::MSWProcessMessage(WXMSG* pMsg)
|
||||
// ::IsDialogMessage() can enter in an infinite loop when
|
||||
// WS_EX_CONTROLPARENT is specified and the currently focused
|
||||
// window is disabled or hidden, so don't call it in this case
|
||||
bool canSafelyCallIsDlgMsg = TRUE;
|
||||
|
||||
HWND hwndFocus = ::GetFocus();
|
||||
if ( !hwndFocus ||
|
||||
::IsWindowEnabled(hwndFocus) && ::IsWindowVisible(hwndFocus) )
|
||||
while ( hwndFocus )
|
||||
{
|
||||
if ( ::IsDialogMessage(GetHwnd(), msg) )
|
||||
if ( !::IsWindowEnabled(hwndFocus) ||
|
||||
!::IsWindowVisible(hwndFocus) )
|
||||
{
|
||||
// IsDialogMessage() did something...
|
||||
return TRUE;
|
||||
// it would enter an infinite loop if we do this!
|
||||
canSafelyCallIsDlgMsg = FALSE;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
hwndFocus = ::GetParent(hwndFocus);
|
||||
}
|
||||
|
||||
if ( canSafelyCallIsDlgMsg && ::IsDialogMessage(GetHwnd(), msg) )
|
||||
{
|
||||
// IsDialogMessage() did something...
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user