Fix wrongly cached state of children focusability under Mac

Remove caching of whether any of the children accept focus in
wxControlContainer as it can change at any moment under Mac, due to full
keyboard access being turned on and off (which can be done using
Ctrl-F7, i.e. easily, and so this might be something users actually do
and not just a theoretical edge case). This also incidentally fixes
caching of the wrong focusability state during window initialization,
when its children are not yet shown, as [NSView canBecomeKeyView:] used
for AcceptsFocusFromKeyboard() implementation under Mac, apparently
always returns false for hidden windows.

The behaviour under the other platforms should remain the same, but
AcceptsFocus() is slower now as it always has to query children instead
of being able to avoid doing it when we know that none of them accepts
focus anyhow. OTOH this only happens to the windows that don't accept
focus themselves and, at least at some moment, don't have any children
accepting focus neither, which should be quite rare and optimizing this
case doesn't seem to be worth the extra code complexity due to extra
preprocessor platform checks.

Closes #18089.
This commit is contained in:
Vadim Zeitlin
2019-10-26 02:58:29 +02:00
parent 8648f839e7
commit 198a4e97a0
2 changed files with 10 additions and 17 deletions

View File

@@ -44,9 +44,6 @@ public:
// By default, we accept focus ourselves.
m_acceptsFocusSelf = true;
// But we don't have any children accepting it yet.
m_acceptsFocusChildren = false;
m_inSetFocus = false;
m_winLastFocused = NULL;
}
@@ -79,8 +76,7 @@ public:
// Returns whether we or one of our children accepts focus.
bool AcceptsFocusRecursively() const
{ return AcceptsFocus() ||
(m_acceptsFocusChildren && HasAnyChildrenAcceptingFocus()); }
{ return AcceptsFocus() || HasAnyChildrenAcceptingFocus(); }
// We accept focus from keyboard if we accept it at all.
bool AcceptsFocusFromKeyboard() const { return AcceptsFocusRecursively(); }
@@ -119,7 +115,11 @@ protected:
private:
// Update the window status to reflect whether it is getting focus or not.
void UpdateParentCanFocus();
void UpdateParentCanFocus(bool acceptsFocusChildren);
void UpdateParentCanFocus()
{
UpdateParentCanFocus(HasAnyFocusableChildren());
}
// Indicates whether the associated window can ever have focus itself.
//
@@ -129,9 +129,6 @@ private:
// ourselves and can only get it if we have any focusable children.
bool m_acceptsFocusSelf;
// Cached value remembering whether we have any children accepting focus.
bool m_acceptsFocusChildren;
// a guard against infinite recursion
bool m_inSetFocus;
};

View File

@@ -50,25 +50,21 @@
// wxControlContainerBase
// ----------------------------------------------------------------------------
void wxControlContainerBase::UpdateParentCanFocus()
void wxControlContainerBase::UpdateParentCanFocus(bool acceptsFocusChildren)
{
// In the ports where it does something non trivial, the parent window
// should only be focusable if it doesn't have any focusable children
// (e.g. native focus handling in wxGTK totally breaks down otherwise).
m_winParent->SetCanFocus(m_acceptsFocusSelf && !m_acceptsFocusChildren);
m_winParent->SetCanFocus(m_acceptsFocusSelf && !acceptsFocusChildren);
}
bool wxControlContainerBase::UpdateCanFocusChildren()
{
const bool acceptsFocusChildren = HasAnyFocusableChildren();
if ( acceptsFocusChildren != m_acceptsFocusChildren )
{
m_acceptsFocusChildren = acceptsFocusChildren;
UpdateParentCanFocus();
}
UpdateParentCanFocus(acceptsFocusChildren);
return m_acceptsFocusChildren;
return acceptsFocusChildren;
}
bool wxControlContainerBase::HasAnyFocusableChildren() const