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
This commit is contained in:
parent
7c54578678
commit
319fefa910
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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.
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user