From: Vadim Zeitlin Date: Sun, 20 Jun 1999 21:51:15 +0000 (+0000) Subject: keyboard/focus handling improved a bit more: X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/319fefa9109ef95cab9f6dcbd46e3f3edbcff8c9 keyboard/focus handling improved a bit more: 1. wxFrame doesn't give focus to anything at all on activation 2. last control restored more often (some problems still persist) 3. buttons process enter 4. text controls with wxTE_PROCESS_TAB still leave TAB work as dialog navigation key if the event wasn't processed git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@2842 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/generic/panelg.h b/include/wx/generic/panelg.h index 5a813e3ddf..f47c9afc41 100644 --- a/include/wx/generic/panelg.h +++ b/include/wx/generic/panelg.h @@ -79,15 +79,15 @@ public: void OnFocus(wxFocusEvent& event); // called by wxWindow whenever it gets focus - void SetLastFocus(long focus) { m_lastFocus = focus; } - long GetLastFocus() const { return m_lastFocus; } + void SetLastFocus(wxWindow *win) { m_winLastFocused = win; } + wxWindow *GetLastFocus() const { return m_winLastFocused; } protected: // common part of all ctors void Init(); // the child which had the focus last time this panel was activated - long m_lastFocus; + wxWindow *m_winLastFocused; // a default button or NULL wxButton *m_btnDefault; diff --git a/src/common/wincmn.cpp b/src/common/wincmn.cpp index 87709ad66a..2665e8d0ec 100644 --- a/src/common/wincmn.cpp +++ b/src/common/wincmn.cpp @@ -191,6 +191,16 @@ wxWindowBase::~wxWindowBase() wxASSERT_MSG( GetChildren().GetCount() == 0, _T("children not destroyed") ); + // make sure that there are no dangling pointers left pointing to us + wxPanel *panel = wxDynamicCast(GetParent(), wxPanel); + if ( panel ) + { + if ( panel->GetLastFocus() == this ) + { + panel->SetLastFocus((wxWindow *)NULL); + } + } + #if wxUSE_CARET if ( m_caret ) delete m_caret; diff --git a/src/generic/panelg.cpp b/src/generic/panelg.cpp index 9ae2865482..9f719780e4 100644 --- a/src/generic/panelg.cpp +++ b/src/generic/panelg.cpp @@ -42,7 +42,7 @@ END_EVENT_TABLE() void wxPanel::Init() { - m_lastFocus = 0; + m_winLastFocused = (wxWindow *)NULL; m_btnDefault = (wxButton *)NULL; } @@ -144,11 +144,13 @@ void wxPanel::OnNavigationKey( wxNavigationKeyEvent& event ) void wxPanel::OnFocus(wxFocusEvent& event) { - if (m_lastFocus != 0) + if ( m_winLastFocused ) { - wxWindow* child = FindWindow(m_lastFocus); - if (child) - child->SetFocus(); + // it might happen that the window got reparented... + if ( m_winLastFocused->GetParent() != this ) + m_winLastFocused = (wxWindow *)NULL; + else + m_winLastFocused->SetFocus(); } else event.Skip(); diff --git a/src/msw/frame.cpp b/src/msw/frame.cpp index 48d39d7495..4cba2dd81f 100644 --- a/src/msw/frame.cpp +++ b/src/msw/frame.cpp @@ -86,9 +86,6 @@ bool wxFrame::Create(wxWindow *parent, m_hwndToolTip = 0; #endif - if (!parent) - wxTopLevelWindows.Append(this); - SetName(name); m_windowStyle = style; m_frameMenuBar = NULL; @@ -119,6 +116,9 @@ bool wxFrame::Create(wxWindow *parent, if ((m_windowStyle & wxFRAME_FLOAT_ON_PARENT) == 0) parent = NULL; + if (!parent) + wxTopLevelWindows.Append(this); + MSWCreate(m_windowId, parent, wxFrameClassName, this, title, x, y, width, height, style); @@ -609,17 +609,29 @@ void wxFrame::OnSize(wxSizeEvent& event) // subwindow found. void wxFrame::OnActivate(wxActivateEvent& event) { - for(wxNode *node = GetChildren().First(); node; node = node->Next()) - { - // Find a child that's a subwindow, but not a dialog box. - wxWindow *child = (wxWindow *)node->Data(); - if (!child->IsKindOf(CLASSINFO(wxFrame)) && - !child->IsKindOf(CLASSINFO(wxDialog))) + for ( wxWindowList::Node *node = GetChildren().GetFirst(); + node; + node = node->GetNext() ) { - child->SetFocus(); - return; + // FIXME all this is totally bogus - we need to do the same as wxPanel, + // but how to do it without duplicating the code? + + // restore focus + wxWindow *child = node->GetData(); + + if ( !child->IsTopLevel() +#if wxUSE_TOOLBAR + && !wxDynamicCast(child, wxToolBar) +#endif // wxUSE_TOOLBAR +#if wxUSE_STATUSBAR + && !wxDynamicCast(child, wxStatusBar) +#endif // wxUSE_STATUSBAR + ) + { + child->SetFocus(); + return; + } } - } } // The default implementation for the close window event. diff --git a/src/msw/textctrl.cpp b/src/msw/textctrl.cpp index db6f5009c4..d166ede2c2 100644 --- a/src/msw/textctrl.cpp +++ b/src/msw/textctrl.cpp @@ -1107,13 +1107,13 @@ void wxTextCtrl::OnChar(wxKeyEvent& event) break; case WXK_TAB: - // only produce navigation event if we don't process TAB ourself or - // if it's a Shift-Tab keypress (we assume nobody will ever need - // this key combo for himself) + // always produce navigation event - even if we process TAB + // ourselves the fact that we got here means that the user code + // decided to skip processing of this TAB - probably to let it + // do its default job. // // NB: Notice that Ctrl-Tab is handled elsewhere and Alt-Tab is // handled by Windows - if ( event.ShiftDown() || !(m_windowStyle & wxTE_PROCESS_TAB) ) { wxNavigationKeyEvent eventNav; eventNav.SetDirection(!event.ShiftDown()); diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 5a5d8f6434..a4bfa94f2a 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -246,6 +246,11 @@ void wxWindow::Init() // wxWnd m_hMenu = 0; + m_hWnd = 0; + + // pass WM_GETDLGCODE to DefWindowProc() + m_lDlgCode = 0; + m_xThumbSize = 0; m_yThumbSize = 0; m_backgroundTransparent = FALSE; @@ -325,11 +330,6 @@ bool wxWindow::Create(wxWindow *parent, wxWindowID id, DLGC_WANTTAB | DLGC_WANTMESSAGE; } - else - { - // default behaviour - m_lDlgCode = 0; - } MSWCreate(m_windowId, parent, wxCanvasClassName, this, NULL, pos.x, pos.y, @@ -1382,6 +1382,7 @@ bool wxWindow::MSWProcessMessage(WXMSG* pMsg) if ( bProcess ) { bool bCtrlDown = (::GetKeyState(VK_CONTROL) & 0x100) != 0; + bool bShiftDown = (::GetKeyState(VK_SHIFT) & 0x100) != 0; // WM_GETDLGCODE: ask the control if it wants the key for itself, // don't process it if it's the case (except for Ctrl-Tab/Enter @@ -1398,13 +1399,16 @@ bool wxWindow::MSWProcessMessage(WXMSG* pMsg) switch ( msg->wParam ) { case VK_TAB: - if ( lDlgCode & DLGC_WANTTAB ) { + // assume that nobody wants Shift-TAB for himself - if we + // don't do it there is no easy way for a control to grab + // TABs but still let Shift-TAB work as navugation key + if ( (lDlgCode & DLGC_WANTTAB) && !bShiftDown ) { bProcess = FALSE; } else { // Ctrl-Tab cycles thru notebook pages bWindowChange = bCtrlDown; - bForward = !(::GetKeyState(VK_SHIFT) & 0x100); + bForward = !bShiftDown; } break; @@ -1431,6 +1435,11 @@ bool wxWindow::MSWProcessMessage(WXMSG* pMsg) // it return FALSE; } + else if ( lDlgCode & DLGC_BUTTON ) + { + // buttons want process Enter themselevs + bProcess = FALSE; + } // else: but if it does not it makes sense to make it // work like a TAB - and that's what we do. // Note that Ctrl-Enter always works this way. @@ -2318,10 +2327,10 @@ bool wxWindow::HandleSetFocus(WXHWND WXUNUSED(hwnd)) #endif // wxUSE_CARET // panel wants to track the window which was the last to have focus in it - wxWindow *parent = GetParent(); - if ( parent && parent->IsKindOf(CLASSINFO(wxPanel)) ) + wxPanel *panel = wxDynamicCast(GetParent(), wxPanel); + if ( panel ) { - ((wxPanel *)parent)->SetLastFocus(GetId()); + panel->SetLastFocus(this); } wxFocusEvent event(wxEVT_SET_FOCUS, m_windowId);