I think I finally fixed activation behaviour under MSW - now focus is not given
to random window after you switch to/from a frame git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@5582 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
54cd433261
commit
00c4e8974d
@ -92,6 +92,9 @@ protected:
|
||||
// common part of all ctors
|
||||
void Init();
|
||||
|
||||
// set the focus to the child which had it the last time
|
||||
bool SetFocusToChild();
|
||||
|
||||
// the child which had the focus last time this panel was activated
|
||||
wxWindow *m_winLastFocused;
|
||||
|
||||
|
@ -179,6 +179,8 @@ public:
|
||||
|
||||
// event handlers
|
||||
// --------------
|
||||
|
||||
void OnSetFocus(wxFocusEvent& event);
|
||||
void OnEraseBackground(wxEraseEvent& event);
|
||||
void OnIdle(wxIdleEvent& event);
|
||||
|
||||
|
@ -178,9 +178,23 @@ void wxLogVerbose(const wxChar *szFormat, ...)
|
||||
if ( pLog != NULL && wxLog::IsAllowedTraceMask(mask) ) {
|
||||
wxCRIT_SECT_LOCKER(locker, gs_csLogBuf);
|
||||
|
||||
wxChar *p = s_szBuf;
|
||||
size_t len = WXSIZEOF(s_szBuf);
|
||||
strncpy(s_szBuf, _T("Trace ("), len);
|
||||
len -= 7; // strlen("Trace (")
|
||||
p += 7;
|
||||
strncat(p, mask, len);
|
||||
size_t lenMask = wxStrlen(mask);
|
||||
len -= lenMask;
|
||||
p += lenMask;
|
||||
|
||||
strncat(p, _T("): "), len);
|
||||
len -= 3;
|
||||
p += 3;
|
||||
|
||||
va_list argptr;
|
||||
va_start(argptr, szFormat);
|
||||
wxVsnprintf(s_szBuf, WXSIZEOF(s_szBuf), szFormat, argptr);
|
||||
wxVsnprintf(p, len, szFormat, argptr);
|
||||
va_end(argptr);
|
||||
|
||||
wxLog::OnLog(wxLOG_Trace, s_szBuf, time(NULL));
|
||||
|
@ -186,59 +186,83 @@ void wxPanel::OnSize(wxSizeEvent& WXUNUSED(event))
|
||||
|
||||
void wxPanel::SetFocus()
|
||||
{
|
||||
wxLogTrace(_T("focus"), _T("SetFocus on wxPanel 0x%08x."), GetHandle());
|
||||
|
||||
// If the panel gets the focus *by way of getting it set directly*
|
||||
// we move the focus to the first window that can get it.
|
||||
|
||||
wxNode *node = GetChildren().First();
|
||||
while (node)
|
||||
// VZ: no, we set the focus to the last window too. I don't understand why
|
||||
// should we make this distinction: if an app wants to set focus to
|
||||
// some precise control, it may always do it directly, but if we don't
|
||||
// use m_winLastFocused here, the focus won't be set correctly after a
|
||||
// notebook page change nor after frame activation under MSW (it calls
|
||||
// SetFocus too)
|
||||
//
|
||||
// If you still want to have old behaviour for wxGTK, edit the
|
||||
// following line
|
||||
#if 0 // def __WXGTK__
|
||||
m_winLastFocused = (wxWindow *)NULL;
|
||||
#endif // 0
|
||||
|
||||
if ( !SetFocusToChild() )
|
||||
{
|
||||
wxWindow *child = (wxWindow*) node->Data();
|
||||
if (child->AcceptsFocus())
|
||||
{
|
||||
m_winLastFocused = child; // should be redundant, but it is not
|
||||
child->SetFocus();
|
||||
return;
|
||||
}
|
||||
node = node->Next();
|
||||
wxWindow::SetFocus();
|
||||
}
|
||||
|
||||
m_winLastFocused = (wxWindow*) NULL;
|
||||
|
||||
wxWindow::SetFocus();
|
||||
}
|
||||
|
||||
void wxPanel::OnFocus(wxFocusEvent& event)
|
||||
{
|
||||
wxLogTrace(_T("focus"), _T("OnFocus on wxPanel 0x%08x."), GetHandle());
|
||||
|
||||
// If the panel gets the focus *by way of getting clicked on*
|
||||
// we move the focus to either the last window that had the
|
||||
// focus or the first one that can get it.
|
||||
|
||||
if (m_winLastFocused)
|
||||
{
|
||||
// It might happen that the window got reparented or no longer
|
||||
// accepts the focus.
|
||||
if ((m_winLastFocused->GetParent() == this) &&
|
||||
(m_winLastFocused->AcceptsFocus()))
|
||||
{
|
||||
m_winLastFocused->SetFocus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
wxNode *node = GetChildren().First();
|
||||
while (node)
|
||||
{
|
||||
wxWindow *child = (wxWindow*) node->Data();
|
||||
if (child->AcceptsFocus())
|
||||
{
|
||||
m_winLastFocused = child; // should be redundant, but it is not
|
||||
child->SetFocus();
|
||||
return;
|
||||
}
|
||||
node = node->Next();
|
||||
}
|
||||
|
||||
m_winLastFocused = (wxWindow*) NULL;
|
||||
(void)SetFocusToChild();
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
bool wxPanel::SetFocusToChild()
|
||||
{
|
||||
if ( m_winLastFocused )
|
||||
{
|
||||
// It might happen that the window got reparented or no longer accepts
|
||||
// the focus.
|
||||
if ( (m_winLastFocused->GetParent() == this) &&
|
||||
m_winLastFocused->AcceptsFocus() )
|
||||
{
|
||||
wxLogTrace(_T("focus"),
|
||||
_T("SetFocusToChild() => last child (0x%08x)."),
|
||||
m_winLastFocused->GetHandle());
|
||||
|
||||
m_winLastFocused->SetFocus();
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// it doesn't count as such any more
|
||||
m_winLastFocused = (wxWindow *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// set the focus to the first child who wants it
|
||||
wxWindowList::Node *node = GetChildren().GetFirst();
|
||||
while ( node )
|
||||
{
|
||||
wxWindow *child = node->GetData();
|
||||
if ( child->AcceptsFocus() )
|
||||
{
|
||||
wxLogTrace(_T("focus"),
|
||||
_T("SetFocusToChild() => first child (0x%08x)."),
|
||||
child->GetHandle());
|
||||
|
||||
m_winLastFocused = child; // should be redundant, but it is not
|
||||
child->SetFocus();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
node = node->GetNext();
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -559,6 +559,15 @@ bool wxFrame::MSWCreate(int id, wxWindow *parent, const wxChar *wclass, wxWindow
|
||||
// subwindow found.
|
||||
void wxFrame::OnActivate(wxActivateEvent& event)
|
||||
{
|
||||
if ( !event.GetActive() )
|
||||
{
|
||||
event.Skip();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
wxLogTrace(_T("focus"), _T("wxFrame %08x activated."), m_hWnd);
|
||||
|
||||
for ( wxWindowList::Node *node = GetChildren().GetFirst();
|
||||
node;
|
||||
node = node->GetNext() )
|
||||
@ -579,7 +588,7 @@ void wxFrame::OnActivate(wxActivateEvent& event)
|
||||
)
|
||||
{
|
||||
child->SetFocus();
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -141,13 +141,14 @@ wxWindow *wxFindWinFromHandle(WXHWND hWnd);
|
||||
// event tables
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
|
||||
IMPLEMENT_DYNAMIC_CLASS(wxWindow, wxWindowBase)
|
||||
|
||||
BEGIN_EVENT_TABLE(wxWindow, wxWindowBase)
|
||||
EVT_ERASE_BACKGROUND(wxWindow::OnEraseBackground)
|
||||
EVT_SYS_COLOUR_CHANGED(wxWindow::OnSysColourChanged)
|
||||
EVT_INIT_DIALOG(wxWindow::OnInitDialog)
|
||||
EVT_IDLE(wxWindow::OnIdle)
|
||||
EVT_SET_FOCUS(wxWindow::OnSetFocus)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
// ===========================================================================
|
||||
@ -2519,6 +2520,33 @@ bool wxWindow::HandleDestroy()
|
||||
// activation/focus
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
void wxWindow::OnSetFocus(wxFocusEvent& event)
|
||||
{
|
||||
// panel wants to track the window which was the last to have focus in it,
|
||||
// so we want to set ourselves as the window which last had focus
|
||||
//
|
||||
// notice that it's also important to do it upwards the tree becaus
|
||||
// otherwise when the top level panel gets focus, it won't set it back to
|
||||
// us, but to some other sibling
|
||||
wxWindow *win = this;
|
||||
while ( win )
|
||||
{
|
||||
wxWindow *parent = win->GetParent();
|
||||
wxPanel *panel = wxDynamicCast(parent, wxPanel);
|
||||
if ( panel )
|
||||
{
|
||||
panel->SetLastFocus(win);
|
||||
}
|
||||
|
||||
win = parent;
|
||||
}
|
||||
|
||||
wxLogTrace(_T("focus"), _T("%s (0x%08x) gets focus"),
|
||||
GetClassInfo()->GetClassName(), GetHandle());
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
bool wxWindow::HandleActivate(int state,
|
||||
bool WXUNUSED(minimized),
|
||||
WXHWND WXUNUSED(activate))
|
||||
@ -2541,13 +2569,6 @@ bool wxWindow::HandleSetFocus(WXHWND WXUNUSED(hwnd))
|
||||
}
|
||||
#endif // wxUSE_CARET
|
||||
|
||||
// panel wants to track the window which was the last to have focus in it
|
||||
wxPanel *panel = wxDynamicCast(GetParent(), wxPanel);
|
||||
if ( panel )
|
||||
{
|
||||
panel->SetLastFocus(this);
|
||||
}
|
||||
|
||||
wxFocusEvent event(wxEVT_SET_FOCUS, m_windowId);
|
||||
event.SetEventObject(this);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user