Open wxtrac opened 12 years ago
panel_children_focus_issue.py
(1.1 KiB)Demo of the bug
window.patch
(0.4 KiB)A fix
I have attached a fix which seems to resolve this problem. It is a modification of some code that has removed since wxPython2.8
Although this patch solves the problem demonstrated in the demo of the bug, I am completely uncertain of what adverse effect that this may have.
I have posted this here for someone with a little more experience of this codebase to take a look at.
We clearly do need to allow SetFocusIgnoringChildren()
to work but the patch actually doesn't seem to solve the problem for me. If I do this:
#!diff
diff --git a/samples/minimal/minimal.cpp b/samples/minimal/minimal.cpp
index a78e462..8b001dc 100644
--- a/samples/minimal/minimal.cpp
+++ b/samples/minimal/minimal.cpp
@@ -141,6 +141,8 @@ bool MyApp::OnInit()
// main frame
// ----------------------------------------------------------------------------
+wxPanel* p;
+
// frame constructor
MyFrame::MyFrame(const wxString& title)
: wxFrame(NULL, wxID_ANY, title)
@@ -167,6 +169,10 @@ bool MyApp::OnInit()
SetMenuBar(menuBar);
#endif // wxUSE_MENUS
+ p = new wxPanel(this);
+ new wxStaticText(p, wxID_ANY, "Label", wxPoint(5, 5));
+ new wxButton(p, wxID_OK, "", wxPoint(5, 35));
+
#if wxUSE_STATUSBAR
// create a status bar just for fun (by default with 1 pane only)
CreateStatusBar(2);
@@ -185,6 +191,9 @@ void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event))
void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event))
{
+ p->SetFocusIgnoringChildren();
+ return;
+
wxMessageBox(wxString::Format
(
"Welcome to %s!\n"
And run the program as WXTRACE=focus ./minimal
I see that the focus is being set to the panel but actually the button still remains focused, so it looks like we're missing something (gtk_widget_set_can_focus()
call?) at GTK level.
Paul, any idea about how to make this work?
Since 52473, SetFocus()
on a plain wxWindow
(or similar, such as wxPanel
) does not work unless you call SetCanFocus(true)
. The documentation for SetCanFocus()
says "A call to this does not disable or change the effect of programmatically calling SetFocus()", so that's currently wrong.
We could call gtk_widget_set_can_focus(m_wxwindow, true)
in Create()
. I'm a little nervous about what other effects that might have though. And it doesn't address SetCanFocus()
. This focus code is a mess.
It turns out wxWindowGTK::Create()
already calls SetCanFocus(AcceptsFocus())
, so focus is enabled for wxPanel
, but when a child is added, wxControlContainerBase::UpdateParentCanFocus()
turns it back off. Which means SetFocusIgnoringChildren()
won't work.
And plain wxWindow
is not affected, I was fooled by wxScrolledWindow, which is not (any more?) a scrolled wxWindow
but a scrolled wxPanel
.
The problem here is that for me all "can focus" stuff originally meant "can be given focus by the user", but for GTK+ it clearly means "can be focused at all". We need to decide which interpretation does wx API really implement. If it's impossible to have a window accept focus without accepting it from the user, then, I guess, the decision is already made and we just need to update the documentation and maybe ensure that SetFocus()
doesn't work for unfocusable windows in wxMSW and the other ports neither.
What do you think?
Issue migrated from trac ticket # 14263
component: wxGTK | priority: normal
2012-05-02 17:41:44: Chuddah (Damien Ruscoe) created the issue
The behaviour of SetFocusIgnoringChildren now boils down to wxWindow::SetFocus which calls gtk_widget_child_focus(widget, GTK_DIR_TAB_FORWARD)
In other words; trying to explicitly set focus to a panel [not a child control] with child windows causes a tab traversal to take place.
Attached is a demo of this problem