diff --git a/include/wx/aui/floatpane.h b/include/wx/aui/floatpane.h index ea4ee3d9a1..889d2deb73 100644 --- a/include/wx/aui/floatpane.h +++ b/include/wx/aui/floatpane.h @@ -44,7 +44,7 @@ public: wxAuiManager* GetOwnerManager() const; // Allow processing accelerators to the parent frame - virtual bool IsTopNavigationDomain() const wxOVERRIDE { return false; } + virtual bool IsTopNavigationDomain(NavigationKind kind) const wxOVERRIDE; protected: virtual void OnMoveStart(); diff --git a/include/wx/mdi.h b/include/wx/mdi.h index 3ef3864730..4be67abda9 100644 --- a/include/wx/mdi.h +++ b/include/wx/mdi.h @@ -182,7 +182,21 @@ public: // In all ports keyboard navigation must stop at MDI child frame level and // can't cross its boundary. Indicate this by overriding this function to // return true. - virtual bool IsTopNavigationDomain() const wxOVERRIDE { return true; } + virtual bool IsTopNavigationDomain(NavigationKind kind) const wxOVERRIDE + { + switch ( kind ) + { + case Navigation_Tab: + return true; + + case Navigation_Accel: + // Parent frame accelerators should work inside MDI child, so + // don't block their processing by returning true for them. + break; + } + + return false; + } // Raising any frame is supposed to show it but wxFrame Raise() // implementation doesn't work for MDI child frames in most forms so diff --git a/include/wx/toplevel.h b/include/wx/toplevel.h index 1f9cb01b0b..47c5798ebc 100644 --- a/include/wx/toplevel.h +++ b/include/wx/toplevel.h @@ -246,7 +246,7 @@ public: // override some base class virtuals virtual bool Destroy() wxOVERRIDE; virtual bool IsTopLevel() const wxOVERRIDE { return true; } - virtual bool IsTopNavigationDomain() const wxOVERRIDE { return true; } + virtual bool IsTopNavigationDomain(NavigationKind kind) const wxOVERRIDE; virtual bool IsVisible() const { return IsShown(); } // event handlers diff --git a/include/wx/window.h b/include/wx/window.h index 2bd4a8a779..80938e9fb1 100644 --- a/include/wx/window.h +++ b/include/wx/window.h @@ -1537,13 +1537,23 @@ public: virtual wxWindow *GetMainWindowOfCompositeControl() { return (wxWindow*)this; } - // If this function returns true, keyboard navigation events shouldn't + enum NavigationKind + { + Navigation_Tab, + Navigation_Accel + }; + + // If this function returns true, keyboard events of the given kind can't // escape from it. A typical example of such "navigation domain" is a top // level window because pressing TAB in one of them must not transfer focus // to a different top level window. But it's not limited to them, e.g. MDI // children frames are not top level windows (and their IsTopLevel() - // returns false) but still are self-contained navigation domains as well. - virtual bool IsTopNavigationDomain() const { return false; } + // returns false) but still are self-contained navigation domains for the + // purposes of TAB navigation -- but not for the accelerators. + virtual bool IsTopNavigationDomain(NavigationKind WXUNUSED(kind)) const + { + return false; + } protected: diff --git a/src/aui/floatpane.cpp b/src/aui/floatpane.cpp index fbbbc05560..adebf5f7c7 100644 --- a/src/aui/floatpane.cpp +++ b/src/aui/floatpane.cpp @@ -165,6 +165,22 @@ wxAuiManager* wxAuiFloatingFrame::GetOwnerManager() const return m_ownerMgr; } +bool wxAuiFloatingFrame::IsTopNavigationDomain(NavigationKind kind) const +{ + switch ( kind ) + { + case Navigation_Tab: + break; + + case Navigation_Accel: + // Floating frames are often used as tool palettes and it's + // convenient for the accelerators defined in the parent frame to + // work in them, so don't block their propagation. + return false; + } + + return wxAuiFloatingFrameBaseClass::IsTopNavigationDomain(kind); +} void wxAuiFloatingFrame::OnSize(wxSizeEvent& WXUNUSED(event)) { diff --git a/src/common/containr.cpp b/src/common/containr.cpp index 50bbd6aefa..c663417043 100644 --- a/src/common/containr.cpp +++ b/src/common/containr.cpp @@ -505,7 +505,7 @@ void wxControlContainer::HandleOnNavigationKey( wxNavigationKeyEvent& event ) // even an MDI child frame, so test for this explicitly // (and in particular don't just use IsTopLevel() which // would return false in the latter case). - if ( focusedParent->IsTopNavigationDomain() ) + if ( focusedParent->IsTopNavigationDomain(wxWindow::Navigation_Tab) ) break; event.SetCurrentFocus( focusedParent ); diff --git a/src/common/toplvcmn.cpp b/src/common/toplvcmn.cpp index dd90760697..58581f6d8a 100644 --- a/src/common/toplvcmn.cpp +++ b/src/common/toplvcmn.cpp @@ -370,6 +370,22 @@ void wxTopLevelWindowBase::SetIcon(const wxIcon& icon) // event handlers // ---------------------------------------------------------------------------- +bool wxTopLevelWindowBase::IsTopNavigationDomain(NavigationKind kind) const +{ + // This switch only exists to generate a compiler warning and force us to + // revisit this code if any new kinds of navigation are added in the + // future, but for now we block of them by default (some derived classes + // relax this however). + switch ( kind ) + { + case Navigation_Tab: + case Navigation_Accel: + break; + } + + return true; +} + // default resizing behaviour - if only ONE subwindow, resize to fill the // whole client area void wxTopLevelWindowBase::DoLayout() diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index f5c91d545d..f86dbe21d3 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -1109,7 +1109,7 @@ gtk_window_key_press_callback( GtkWidget *WXUNUSED(widget), break; } - if (ancestor->IsTopNavigationDomain()) + if (ancestor->IsTopNavigationDomain(wxWindow::Navigation_Accel)) break; ancestor = ancestor->GetParent(); } diff --git a/src/msw/evtloop.cpp b/src/msw/evtloop.cpp index cb2bae0d5f..eb053cd33d 100644 --- a/src/msw/evtloop.cpp +++ b/src/msw/evtloop.cpp @@ -134,10 +134,8 @@ bool wxGUIEventLoop::PreProcessMessage(WXMSG *msg) if ( wnd->MSWTranslateMessage((WXMSG *)msg)) return true; - // stop at first top level window, i.e. don't try to process the key - // strokes originating in a dialog using the accelerators of the parent - // frame - this doesn't make much sense - if ( wnd->IsTopNavigationDomain() ) + // stop at top navigation domain, i.e. typically a top level window + if ( wnd->IsTopNavigationDomain(wxWindow::Navigation_Accel) ) break; } @@ -151,7 +149,7 @@ bool wxGUIEventLoop::PreProcessMessage(WXMSG *msg) // if we don't do this, pressing ESC on a modal dialog shown as child // of a modal dialog with wxID_CANCEL will cause the parent dialog to // be closed, for example - if ( wnd->IsTopNavigationDomain() ) + if ( wnd->IsTopNavigationDomain(wxWindow::Navigation_Accel) ) break; } diff --git a/src/osx/window_osx.cpp b/src/osx/window_osx.cpp index d067b0c27f..f12c025753 100644 --- a/src/osx/window_osx.cpp +++ b/src/osx/window_osx.cpp @@ -2662,7 +2662,7 @@ bool wxWindowMac::OSXHandleKeyEvent( wxKeyEvent& event ) break; } - if (ancestor->IsTopNavigationDomain()) + if (ancestor->IsTopNavigationDomain(wxWindow::Navigation_Accel)) break; ancestor = ancestor->GetParent();