From edc09871744140f16b2ef6b7abaa2289d7deb260 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Thu, 28 Jun 2007 12:04:06 +0000 Subject: [PATCH 1/1] CanAcceptFocus() now returns true if either the window itself or one of its children accepts focus; added new IsFocusable() to test whether the window itself accepts focus git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@46994 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- include/wx/containr.h | 21 ++++++++++++++++++--- include/wx/window.h | 24 +++++++++++++++++++++--- src/common/containr.cpp | 26 +++++++++----------------- src/gtk/window.cpp | 4 ++-- src/gtk1/window.cpp | 2 +- src/msw/window.cpp | 2 +- 6 files changed, 52 insertions(+), 27 deletions(-) diff --git a/include/wx/containr.h b/include/wx/containr.h index 375caff127..e738d67907 100644 --- a/include/wx/containr.h +++ b/include/wx/containr.h @@ -57,12 +57,21 @@ public: // returns whether we should accept focus ourselves or not bool AcceptsFocus() const { return m_acceptsFocus; } + // returns whether we or one of our children accepts focus: we always do + // because if we don't have any focusable children it probably means that + // we're not being used as a container at all (think of wxGrid or generic + // wxListCtrl) and so should get focus for ourselves + bool AcceptsFocusRecursively() const { return true; } + // call this when the number of children of the window changes - void UpdateCanFocus() { SetCanFocus(ShouldAcceptFocus()); } + // + // note that we have any children, this panel (used just as container for + // them) shouldn't get focus for itself + void UpdateCanFocus() { SetCanFocus(!HasAnyFocusableChildren()); } protected: - // return true if we should be focusable - bool ShouldAcceptFocus() const; + // return true if we have any children accepting focus + bool HasAnyFocusableChildren() const; // the parent window we manage the children for wxWindow *m_winParent; @@ -78,6 +87,7 @@ private: #define WX_DECLARE_CONTROL_CONTAINER_BASE() \ public: \ virtual bool AcceptsFocus() const; \ + virtual bool AcceptsFocusRecursively() const; \ virtual void AddChild(wxWindowBase *child); \ virtual void RemoveChild(wxWindowBase *child); \ void SetFocusIgnoringChildren(); \ @@ -103,6 +113,11 @@ protected: \ m_container.UpdateCanFocus(); \ } \ \ + bool classname::AcceptsFocusRecursively() const \ + { \ + return m_container.AcceptsFocusRecursively(); \ + } \ + \ bool classname::AcceptsFocus() const \ { \ return m_container.AcceptsFocus(); \ diff --git a/include/wx/window.h b/include/wx/window.h index 80c4b0961e..a9a881c8a8 100644 --- a/include/wx/window.h +++ b/include/wx/window.h @@ -582,17 +582,35 @@ public: // this class clients and take into account the current window state virtual bool AcceptsFocus() const { return true; } - // can this window have focus right now? - bool CanAcceptFocus() const { return AcceptsFocus() && IsShown() && IsEnabled(); } + // can this window or one of its children accept focus? + // + // usually it's the same as AcceptsFocus() but is overridden for + // container windows + virtual bool AcceptsFocusRecursively() const { return AcceptsFocus(); } // can this window be given focus by keyboard navigation? if not, the // only way to give it focus (provided it accepts it at all) is to // click it virtual bool AcceptsFocusFromKeyboard() const { return AcceptsFocus(); } + + // this is mostly a helper for the various functions using it below + bool CanBeFocused() const { return IsShown() && IsEnabled(); } + + // can this window itself have focus? + bool IsFocusable() const { return AcceptsFocus() && CanBeFocused(); } + + // can this window have focus right now? + // + // if this method returns true, it means that calling SetFocus() will + // put focus either to this window or one of its children, if you need + // to know whether this window accepts focus itself, use IsFocusable() + bool CanAcceptFocus() const + { return AcceptsFocusRecursively() && CanBeFocused(); } + // can this window be assigned focus from keyboard right now? bool CanAcceptFocusFromKeyboard() const - { return AcceptsFocusFromKeyboard() && CanAcceptFocus(); } + { return AcceptsFocusFromKeyboard() && CanBeFocused(); } // call this when the return value of AcceptsFocus() changes virtual void SetCanFocus(bool WXUNUSED(canFocus)) { } diff --git a/src/common/containr.cpp b/src/common/containr.cpp index 16fda35e9d..f2d237a36d 100644 --- a/src/common/containr.cpp +++ b/src/common/containr.cpp @@ -57,32 +57,24 @@ void wxControlContainerBase::SetCanFocus(bool acceptsFocus) m_winParent->SetCanFocus(m_acceptsFocus); } -// if the window has a focusable child, it shouldn't be focusable itself (think -// of wxPanel used for grouping different controls) but if it doesn't have any -// (focusable) children, then it should be possible to give it focus (think of -// wxGrid or generic wxListCtrl) -bool wxControlContainerBase::ShouldAcceptFocus() const +bool wxControlContainerBase::HasAnyFocusableChildren() const { - // we can accept focus either if we have no children at all (in this case - // we're probably not used as a container) or only when at least one child - // accepts focus - wxWindowList::compatibility_iterator node = m_winParent->GetChildren().GetFirst(); - if ( !node ) - return true; - - while ( node ) + const wxWindowList& children = m_winParent->GetChildren(); + for ( wxWindowList::const_iterator i = children.begin(), + end = children.end(); + i != end; + ++i ) { - wxWindow *child = node->GetData(); - node = node->GetNext(); + const wxWindow * const child = *i; if ( !m_winParent->IsClientAreaChild(child) ) continue; if ( child->CanAcceptFocus() ) - return false; + return true; } - return true; + return false; } #ifndef wxHAS_NATIVE_TAB_TRAVERSAL diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index 9dcf7a83d8..4bb50f4586 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -1434,7 +1434,7 @@ gtk_window_button_press_callback( GtkWidget *widget, g_lastButtonNumber = gdk_event->button; - if (win->m_wxwindow && (g_focusWindow != win) && win->CanAcceptFocus()) + if (win->m_wxwindow && (g_focusWindow != win) && win->IsFocusable()) { gtk_widget_grab_focus( win->m_wxwindow ); } @@ -1570,7 +1570,7 @@ gtk_window_button_press_callback( GtkWidget *widget, return TRUE; if ((event_type == wxEVT_LEFT_DOWN) && !win->IsOfStandardClass() && - (g_focusWindow != win) && win->CanAcceptFocus()) + (g_focusWindow != win) && win->IsFocusable()) { gtk_widget_grab_focus( win->m_wxwindow ); } diff --git a/src/gtk1/window.cpp b/src/gtk1/window.cpp index eb6d484896..d74a0e0e3f 100644 --- a/src/gtk1/window.cpp +++ b/src/gtk1/window.cpp @@ -1475,7 +1475,7 @@ static gint gtk_window_button_press_callback( GtkWidget *widget, g_lastButtonNumber = gdk_event->button; - if (win->m_wxwindow && (g_focusWindow != win) && win->CanAcceptFocus()) + if (win->m_wxwindow && (g_focusWindow != win) && win->IsFocusable()) { gtk_widget_grab_focus( win->m_wxwindow ); /* diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 4617bdd7b3..484177c102 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -2742,7 +2742,7 @@ WXLRESULT wxWindowMSW::MSWWindowProc(WXUINT message, WXWPARAM wParam, WXLPARAM l // problems, so don't do it for them (unnecessary anyhow) if ( !win->IsOfStandardClass() ) { - if ( message == WM_LBUTTONDOWN && win->CanAcceptFocus() ) + if ( message == WM_LBUTTONDOWN && win->IsFocusable() ) win->SetFocus(); } } -- 2.45.2