From: Vadim Zeitlin Date: Thu, 13 Jun 2002 00:04:22 +0000 (+0000) Subject: moved OnActivate() logic from wxFrame to wxDialog -- this fixes infinite loop when... X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/085ad68651cd624a11331f5ab2cb2720bd7162aa?ds=inline 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 --- diff --git a/include/wx/msw/frame.h b/include/wx/msw/frame.h index b3f81e6c79..4b4b657d2f 100644 --- a/include/wx/msw/frame.h +++ b/include/wx/msw/frame.h @@ -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 diff --git a/include/wx/msw/toplevel.h b/include/wx/msw/toplevel.h index 6f14456c2e..d09a48ce0a 100644 --- a/include/wx/msw/toplevel.h +++ b/include/wx/msw/toplevel.h @@ -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 diff --git a/src/common/wincmn.cpp b/src/common/wincmn.cpp index faa3837b1c..1d70eebd62 100644 --- a/src/common/wincmn.cpp +++ b/src/common/wincmn.cpp @@ -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 ) { diff --git a/src/msw/frame.cpp b/src/msw/frame.cpp index 98c8c7eacd..10896a17f6 100644 --- a/src/msw/frame.cpp +++ b/src/msw/frame.cpp @@ -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,58 +391,8 @@ 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(); - } + return wxFrameBase::ShowFullScreen(show, style); } // ---------------------------------------------------------------------------- diff --git a/src/msw/toplevel.cpp b/src/msw/toplevel.cpp index 842a8a587b..3a25093115 100644 --- a/src/msw/toplevel.cpp +++ b/src/msw/toplevel.cpp @@ -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(); + } +} + diff --git a/src/msw/window.cpp b/src/msw/window.cpp index ff531d4eaa..af673944c3 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -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; } } }