From: Vadim Zeitlin Date: Sat, 20 Apr 2002 13:53:11 +0000 (+0000) Subject: fixed initial focus handling in the dialog and made SetFocus() send the focus X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/6aeb6f2a5810694b5241eb267d71dab4848cf8bb fixed initial focus handling in the dialog and made SetFocus() send the focus events as under wxMSW git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@15218 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/include/wx/gtk/toplevel.h b/include/wx/gtk/toplevel.h index a3b842add3..1f4a35c268 100644 --- a/include/wx/gtk/toplevel.h +++ b/include/wx/gtk/toplevel.h @@ -92,13 +92,18 @@ public: long m_fsSaveGdkFunc, m_fsSaveGdkDecor; long m_fsSaveFlag; wxRect m_fsSaveFrame; - - long m_gdkFunc, m_gdkDecor; // m_windowStyle translated to GDK's terms + + // m_windowStyle translated to GDK's terms + long m_gdkFunc, + m_gdkDecor; protected: // common part of all ctors void Init(); + // focus event handler + void OnSetFocus(wxFocusEvent& event); + // override wxWindow methods to take into account tool/menu/statusbars virtual void DoSetSize(int x, int y, int width, int height, @@ -109,6 +114,8 @@ protected: // is the frame currently iconized? bool m_isIconized; + + DECLARE_EVENT_TABLE() }; #endif // __GTKTOPLEVELH__ diff --git a/include/wx/gtk1/toplevel.h b/include/wx/gtk1/toplevel.h index a3b842add3..1f4a35c268 100644 --- a/include/wx/gtk1/toplevel.h +++ b/include/wx/gtk1/toplevel.h @@ -92,13 +92,18 @@ public: long m_fsSaveGdkFunc, m_fsSaveGdkDecor; long m_fsSaveFlag; wxRect m_fsSaveFrame; - - long m_gdkFunc, m_gdkDecor; // m_windowStyle translated to GDK's terms + + // m_windowStyle translated to GDK's terms + long m_gdkFunc, + m_gdkDecor; protected: // common part of all ctors void Init(); + // focus event handler + void OnSetFocus(wxFocusEvent& event); + // override wxWindow methods to take into account tool/menu/statusbars virtual void DoSetSize(int x, int y, int width, int height, @@ -109,6 +114,8 @@ protected: // is the frame currently iconized? bool m_isIconized; + + DECLARE_EVENT_TABLE() }; #endif // __GTKTOPLEVELH__ diff --git a/src/common/containr.cpp b/src/common/containr.cpp index b76ec648d6..c387c5da20 100644 --- a/src/common/containr.cpp +++ b/src/common/containr.cpp @@ -50,6 +50,12 @@ wxControlContainer::wxControlContainer(wxWindow *winParent) void wxControlContainer::SetLastFocus(wxWindow *win) { + // the panel itself should never get the focus at all but if it does happen + // temporarily (as it seems to do under wxGTK), at the very least don't + // forget our previous m_winLastFocused + if ( win == m_winParent ) + return; + // if we're setting the focus if ( win ) { @@ -70,6 +76,17 @@ void wxControlContainer::SetLastFocus(wxWindow *win) } m_winLastFocused = win; + + if ( win ) + { + wxLogTrace(_T("focus"), _T("Set last focus to %s(%s)"), + win->GetClassInfo()->GetClassName(), + win->GetLabel().c_str()); + } + else + { + wxLogTrace(_T("focus"), _T("No more last focus")); + } } // ---------------------------------------------------------------------------- diff --git a/src/gtk/notebook.cpp b/src/gtk/notebook.cpp index 9d70d97f45..08fc2ca89d 100644 --- a/src/gtk/notebook.cpp +++ b/src/gtk/notebook.cpp @@ -46,16 +46,6 @@ extern bool g_isIdle; extern bool g_blockEventsOnDrag; -//----------------------------------------------------------------------------- -// debug -//----------------------------------------------------------------------------- - -#ifdef __WXDEBUG__ - -extern void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window ); - -#endif - //----------------------------------------------------------------------------- // wxGtkNotebookPage //----------------------------------------------------------------------------- @@ -291,10 +281,6 @@ bool wxNotebook::Create(wxWindow *parent, wxWindowID id, m_widget = gtk_notebook_new(); -#ifdef __WXDEBUG__ - debug_focus_in( m_widget, wxT("wxNotebook::m_widget"), name ); -#endif - gtk_notebook_set_scrollable( GTK_NOTEBOOK(m_widget), 1 ); gtk_signal_connect( GTK_OBJECT(m_widget), "switch_page", diff --git a/src/gtk/toplevel.cpp b/src/gtk/toplevel.cpp index b2045d79d4..9f5beeea7c 100644 --- a/src/gtk/toplevel.cpp +++ b/src/gtk/toplevel.cpp @@ -56,16 +56,6 @@ extern wxList wxPendingDelete; extern int g_openDialogs; extern wxWindowGTK *g_delayedFocus; -// ---------------------------------------------------------------------------- -// debug -// ---------------------------------------------------------------------------- - -#ifdef __WXDEBUG__ - -extern void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window ); - -#endif - //----------------------------------------------------------------------------- // "focus" from m_window //----------------------------------------------------------------------------- @@ -154,18 +144,6 @@ gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WX return FALSE; } -//----------------------------------------------------------------------------- -// local code -//----------------------------------------------------------------------------- - -static wxWindow* wxGetTopLevelParent(wxWindow *win) -{ - wxWindow *p = win; - while (p && !p->IsTopLevel()) - p = p->GetParent(); - return p; -} - //----------------------------------------------------------------------------- // "realize" from m_widget //----------------------------------------------------------------------------- @@ -174,7 +152,8 @@ static wxWindow* wxGetTopLevelParent(wxWindow *win) // so we do this directly after realization static void -gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget), wxTopLevelWindowGTK *win ) +gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget), + wxTopLevelWindowGTK *win ) { if (g_isIdle) wxapp_install_idle_handler(); @@ -194,50 +173,11 @@ gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget), wxTopLevelWindowGTK * // reset the icon wxIconBundle iconsOld = win->GetIcons(); - wxIcon tmp = iconsOld.GetIcon( -1 ); // operator != is not-const - if ( tmp != wxNullIcon ) + if ( iconsOld.GetIcon(-1).Ok() ) { - // wxIconBundle icon( iconOld ); win->SetIcon( wxNullIcon ); win->SetIcons( iconsOld ); } - - // We need to set the focus to some child. Either, this - // has been done already or will be done in the next - // idle cycle, or we will set it ourselves. - - if (g_delayedFocus) - { - if (wxGetTopLevelParent(g_delayedFocus)) - return; - else - g_delayedFocus = NULL; - } - - wxWindow *currentFocus = wxWindow::FindFocus(); - if (currentFocus) - { - // I am not sure if this ever can happen, - // since the TLW is just about to get - // created and its children probably don't - // have any focus. - if (wxGetTopLevelParent(currentFocus) == win) - return; - } - - // We set the focus to the child that accepts the focus. - wxWindowList::Node *node = win->GetChildren().GetFirst(); - while (node) - { - wxWindow *child = node->GetData(); - if (child->AcceptsFocus()) - { - child->SetFocus(); - break; - } - - node = node->GetNext(); - } } //----------------------------------------------------------------------------- @@ -308,6 +248,10 @@ static void gtk_window_draw_callback( GtkWidget *widget, GdkRectangle *rect, wxW // wxTopLevelWindowGTK itself // ---------------------------------------------------------------------------- +BEGIN_EVENT_TABLE(wxTopLevelWindowGTK, wxTopLevelWindowBase) + EVT_SET_FOCUS(wxTopLevelWindowGTK::OnSetFocus) +END_EVENT_TABLE() + //----------------------------------------------------------------------------- // InsertChild for wxTopLevelWindowGTK //----------------------------------------------------------------------------- @@ -388,7 +332,7 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, wxTopLevelWindows.Append( this ); m_needParent = FALSE; - + if (!PreCreation( parent, pos, size ) || !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name )) { @@ -426,10 +370,6 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, if (!name.IsEmpty()) gtk_window_set_wmclass( GTK_WINDOW(m_widget), name.mb_str(), name.mb_str() ); -#ifdef __WXDEBUG__ - debug_focus_in( m_widget, wxT("wxTopLevelWindowGTK::m_widget"), name ); -#endif - gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() ); GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS ); @@ -450,19 +390,11 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this ); #endif -#ifdef __WXDEBUG__ - debug_focus_in( m_mainWidget, wxT("wxTopLevelWindowGTK::m_mainWidget"), name ); -#endif - // m_wxwindow only represents the client area without toolbar and menubar m_wxwindow = gtk_pizza_new(); gtk_widget_show( m_wxwindow ); gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow ); -#ifdef __WXDEBUG__ - debug_focus_in( m_wxwindow, wxT("wxTopLevelWindowGTK::m_wxwindow"), name ); -#endif - // we donm't allow the frame to get the focus as otherwise // the frame will grab it at arbitrary focus changes GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS ); @@ -477,7 +409,7 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, if ((m_x != -1) || (m_y != -1)) gtk_widget_set_uposition( m_widget, m_x, m_y ); - + gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height ); // we cannot set MWM hints and icons before the widget has @@ -546,7 +478,7 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, wxTopLevelWindowGTK::~wxTopLevelWindowGTK() { m_isBeingDeleted = TRUE; - + // it may also be GtkScrolledWindow in the case of an MDI child if (GTK_IS_WINDOW(m_widget)) { @@ -830,9 +762,31 @@ void wxTopLevelWindowGTK::OnInternalIdle() return; } + // set the focus if not done yet and if we can already do it + if ( GTK_WIDGET_REALIZED(m_wxwindow) ) + { + if ( g_delayedFocus && wxGetTopLevelParent(g_delayedFocus) == this ) + { + g_delayedFocus->SetFocus(); + g_delayedFocus = NULL; + } + } + wxWindow::OnInternalIdle(); } +void wxTopLevelWindowGTK::OnSetFocus(wxFocusEvent& event) +{ +#if 0 + if ( !g_delayedFocus || wxGetTopLevelParent(g_delayedFocus) != this ) + { + // let the base class version set the focus to the first child which + // accepts it + event.Skip(); + } + //else: the focus will be really set from OnInternalIdle() later +#endif +} // ---------------------------------------------------------------------------- // frame title/icon diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index c15e735d2b..7460101617 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -270,43 +270,6 @@ extern bool g_mainThreadLocked; #else # define DEBUG_MAIN_THREAD #endif - -static gint gtk_debug_focus_in_callback( GtkWidget *WXUNUSED(widget), - GdkEvent *WXUNUSED(event), - const wxChar *WXUNUSED(name) ) -{ -/* - static bool s_done = FALSE; - if ( !s_done ) - { - wxLog::AddTraceMask("focus"); - s_done = TRUE; - } - wxLogTrace(wxT("FOCUS NOW AT: %s"), name); -*/ - - return FALSE; -} - -void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window ) -{ - // suppress warnings about gtk_debug_focus_in_callback being unused with - // this "if ( 0 )" - if ( 0 ) - { - wxString tmp = name; - tmp += wxT(" FROM "); - tmp += window; - - wxChar *s = new wxChar[tmp.Length()+1]; - - wxStrcpy( s, tmp ); - - gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event", - GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback), (gpointer)s ); - } -} - #else #define DEBUG_MAIN_THREAD #endif // Debug @@ -385,15 +348,6 @@ wxWindow *wxFindFocusedChild(wxWindowGTK *win) return (wxWindow *)NULL; } -// Returns toplevel grandparent of given window: -static wxWindowGTK* wxGetTopLevelParent(wxWindowGTK *win) -{ - wxWindowGTK *p = win; - while (p && !p->IsTopLevel()) - p = p->GetParent(); - return p; -} - static void draw_frame( GtkWidget *widget, wxWindowGTK *win ) { // wxUniversal widgets draw the borders and scrollbars themselves @@ -1749,6 +1703,21 @@ static gint gtk_window_motion_notify_callback( GtkWidget *widget, // "focus_in_event" //----------------------------------------------------------------------------- +// send the wxChildFocusEvent and wxFocusEvent, common code of +// gtk_window_focus_in_callback() and SetFocus() +static bool DoSendFocusEvents(wxWindow *win) +{ + // Notify the parent keeping track of focus for the kbd navigation + // purposes that we got it. + wxChildFocusEvent eventChildFocus(win); + (void)win->GetEventHandler()->ProcessEvent(eventChildFocus); + + wxFocusEvent eventFocus(wxEVT_SET_FOCUS, win->GetId()); + eventFocus.SetEventObject(win); + + return win->GetEventHandler()->ProcessEvent(eventFocus); +} + static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win ) @@ -1782,11 +1751,6 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget, printf( "OnSetFocus 2 from %s\n", win->GetName().c_str() ); #endif - // Notify the parent keeping track of focus for the kbd navigation - // purposes that we got it. - wxChildFocusEvent eventFocus(win); - (void)win->GetEventHandler()->ProcessEvent(eventFocus); - #ifdef HAVE_XIM if (win->m_ic) gdk_im_begin(win->m_ic, win->m_wxwindow->window); @@ -1825,11 +1789,7 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget, // return TRUE; } - - wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() ); - event.SetEventObject( win ); - - if (win->GetEventHandler()->ProcessEvent( event )) + if ( DoSendFocusEvents(win) ) { gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" ); return TRUE; @@ -2906,15 +2866,6 @@ void wxWindowGTK::OnInternalIdle() g_activeFrameLostFocus = FALSE; } - if (g_delayedFocus == this) - { - if (GTK_WIDGET_REALIZED(m_widget)) - { - gtk_widget_grab_focus( m_widget ); - g_delayedFocus = NULL; - } - } - wxCursor cursor = m_cursor; if (g_globalCursor.Ok()) cursor = g_globalCursor; @@ -3281,9 +3232,21 @@ void wxWindowGTK::SetFocus() if (GTK_WIDGET_CAN_FOCUS(m_widget) && !GTK_WIDGET_HAS_FOCUS (m_widget) ) { if (!GTK_WIDGET_REALIZED(m_widget)) + { + wxLogTrace(_T("focus"), + _T("Delaying setting focus to %s(%s)\n"), + GetClassInfo()->GetClassName(), GetLabel().c_str()); + g_delayedFocus = this; + } else + { + wxLogTrace(_T("focus"), + _T("Setting focus to %s(%s)\n"), + GetClassInfo()->GetClassName(), GetLabel().c_str()); + gtk_widget_grab_focus (m_widget); + } } else if (GTK_IS_CONTAINER(m_widget)) { @@ -3294,6 +3257,8 @@ void wxWindowGTK::SetFocus() // ? } } + + (void)DoSendFocusEvents(this); } bool wxWindowGTK::AcceptsFocus() const diff --git a/src/gtk1/notebook.cpp b/src/gtk1/notebook.cpp index 9d70d97f45..08fc2ca89d 100644 --- a/src/gtk1/notebook.cpp +++ b/src/gtk1/notebook.cpp @@ -46,16 +46,6 @@ extern bool g_isIdle; extern bool g_blockEventsOnDrag; -//----------------------------------------------------------------------------- -// debug -//----------------------------------------------------------------------------- - -#ifdef __WXDEBUG__ - -extern void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window ); - -#endif - //----------------------------------------------------------------------------- // wxGtkNotebookPage //----------------------------------------------------------------------------- @@ -291,10 +281,6 @@ bool wxNotebook::Create(wxWindow *parent, wxWindowID id, m_widget = gtk_notebook_new(); -#ifdef __WXDEBUG__ - debug_focus_in( m_widget, wxT("wxNotebook::m_widget"), name ); -#endif - gtk_notebook_set_scrollable( GTK_NOTEBOOK(m_widget), 1 ); gtk_signal_connect( GTK_OBJECT(m_widget), "switch_page", diff --git a/src/gtk1/toplevel.cpp b/src/gtk1/toplevel.cpp index b2045d79d4..9f5beeea7c 100644 --- a/src/gtk1/toplevel.cpp +++ b/src/gtk1/toplevel.cpp @@ -56,16 +56,6 @@ extern wxList wxPendingDelete; extern int g_openDialogs; extern wxWindowGTK *g_delayedFocus; -// ---------------------------------------------------------------------------- -// debug -// ---------------------------------------------------------------------------- - -#ifdef __WXDEBUG__ - -extern void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window ); - -#endif - //----------------------------------------------------------------------------- // "focus" from m_window //----------------------------------------------------------------------------- @@ -154,18 +144,6 @@ gtk_frame_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WX return FALSE; } -//----------------------------------------------------------------------------- -// local code -//----------------------------------------------------------------------------- - -static wxWindow* wxGetTopLevelParent(wxWindow *win) -{ - wxWindow *p = win; - while (p && !p->IsTopLevel()) - p = p->GetParent(); - return p; -} - //----------------------------------------------------------------------------- // "realize" from m_widget //----------------------------------------------------------------------------- @@ -174,7 +152,8 @@ static wxWindow* wxGetTopLevelParent(wxWindow *win) // so we do this directly after realization static void -gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget), wxTopLevelWindowGTK *win ) +gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget), + wxTopLevelWindowGTK *win ) { if (g_isIdle) wxapp_install_idle_handler(); @@ -194,50 +173,11 @@ gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget), wxTopLevelWindowGTK * // reset the icon wxIconBundle iconsOld = win->GetIcons(); - wxIcon tmp = iconsOld.GetIcon( -1 ); // operator != is not-const - if ( tmp != wxNullIcon ) + if ( iconsOld.GetIcon(-1).Ok() ) { - // wxIconBundle icon( iconOld ); win->SetIcon( wxNullIcon ); win->SetIcons( iconsOld ); } - - // We need to set the focus to some child. Either, this - // has been done already or will be done in the next - // idle cycle, or we will set it ourselves. - - if (g_delayedFocus) - { - if (wxGetTopLevelParent(g_delayedFocus)) - return; - else - g_delayedFocus = NULL; - } - - wxWindow *currentFocus = wxWindow::FindFocus(); - if (currentFocus) - { - // I am not sure if this ever can happen, - // since the TLW is just about to get - // created and its children probably don't - // have any focus. - if (wxGetTopLevelParent(currentFocus) == win) - return; - } - - // We set the focus to the child that accepts the focus. - wxWindowList::Node *node = win->GetChildren().GetFirst(); - while (node) - { - wxWindow *child = node->GetData(); - if (child->AcceptsFocus()) - { - child->SetFocus(); - break; - } - - node = node->GetNext(); - } } //----------------------------------------------------------------------------- @@ -308,6 +248,10 @@ static void gtk_window_draw_callback( GtkWidget *widget, GdkRectangle *rect, wxW // wxTopLevelWindowGTK itself // ---------------------------------------------------------------------------- +BEGIN_EVENT_TABLE(wxTopLevelWindowGTK, wxTopLevelWindowBase) + EVT_SET_FOCUS(wxTopLevelWindowGTK::OnSetFocus) +END_EVENT_TABLE() + //----------------------------------------------------------------------------- // InsertChild for wxTopLevelWindowGTK //----------------------------------------------------------------------------- @@ -388,7 +332,7 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, wxTopLevelWindows.Append( this ); m_needParent = FALSE; - + if (!PreCreation( parent, pos, size ) || !CreateBase( parent, id, pos, size, style, wxDefaultValidator, name )) { @@ -426,10 +370,6 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, if (!name.IsEmpty()) gtk_window_set_wmclass( GTK_WINDOW(m_widget), name.mb_str(), name.mb_str() ); -#ifdef __WXDEBUG__ - debug_focus_in( m_widget, wxT("wxTopLevelWindowGTK::m_widget"), name ); -#endif - gtk_window_set_title( GTK_WINDOW(m_widget), title.mbc_str() ); GTK_WIDGET_UNSET_FLAGS( m_widget, GTK_CAN_FOCUS ); @@ -450,19 +390,11 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, GTK_SIGNAL_FUNC(gtk_window_draw_callback), (gpointer)this ); #endif -#ifdef __WXDEBUG__ - debug_focus_in( m_mainWidget, wxT("wxTopLevelWindowGTK::m_mainWidget"), name ); -#endif - // m_wxwindow only represents the client area without toolbar and menubar m_wxwindow = gtk_pizza_new(); gtk_widget_show( m_wxwindow ); gtk_container_add( GTK_CONTAINER(m_mainWidget), m_wxwindow ); -#ifdef __WXDEBUG__ - debug_focus_in( m_wxwindow, wxT("wxTopLevelWindowGTK::m_wxwindow"), name ); -#endif - // we donm't allow the frame to get the focus as otherwise // the frame will grab it at arbitrary focus changes GTK_WIDGET_UNSET_FLAGS( m_wxwindow, GTK_CAN_FOCUS ); @@ -477,7 +409,7 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, if ((m_x != -1) || (m_y != -1)) gtk_widget_set_uposition( m_widget, m_x, m_y ); - + gtk_window_set_default_size( GTK_WINDOW(m_widget), m_width, m_height ); // we cannot set MWM hints and icons before the widget has @@ -546,7 +478,7 @@ bool wxTopLevelWindowGTK::Create( wxWindow *parent, wxTopLevelWindowGTK::~wxTopLevelWindowGTK() { m_isBeingDeleted = TRUE; - + // it may also be GtkScrolledWindow in the case of an MDI child if (GTK_IS_WINDOW(m_widget)) { @@ -830,9 +762,31 @@ void wxTopLevelWindowGTK::OnInternalIdle() return; } + // set the focus if not done yet and if we can already do it + if ( GTK_WIDGET_REALIZED(m_wxwindow) ) + { + if ( g_delayedFocus && wxGetTopLevelParent(g_delayedFocus) == this ) + { + g_delayedFocus->SetFocus(); + g_delayedFocus = NULL; + } + } + wxWindow::OnInternalIdle(); } +void wxTopLevelWindowGTK::OnSetFocus(wxFocusEvent& event) +{ +#if 0 + if ( !g_delayedFocus || wxGetTopLevelParent(g_delayedFocus) != this ) + { + // let the base class version set the focus to the first child which + // accepts it + event.Skip(); + } + //else: the focus will be really set from OnInternalIdle() later +#endif +} // ---------------------------------------------------------------------------- // frame title/icon diff --git a/src/gtk1/window.cpp b/src/gtk1/window.cpp index c15e735d2b..7460101617 100644 --- a/src/gtk1/window.cpp +++ b/src/gtk1/window.cpp @@ -270,43 +270,6 @@ extern bool g_mainThreadLocked; #else # define DEBUG_MAIN_THREAD #endif - -static gint gtk_debug_focus_in_callback( GtkWidget *WXUNUSED(widget), - GdkEvent *WXUNUSED(event), - const wxChar *WXUNUSED(name) ) -{ -/* - static bool s_done = FALSE; - if ( !s_done ) - { - wxLog::AddTraceMask("focus"); - s_done = TRUE; - } - wxLogTrace(wxT("FOCUS NOW AT: %s"), name); -*/ - - return FALSE; -} - -void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar *window ) -{ - // suppress warnings about gtk_debug_focus_in_callback being unused with - // this "if ( 0 )" - if ( 0 ) - { - wxString tmp = name; - tmp += wxT(" FROM "); - tmp += window; - - wxChar *s = new wxChar[tmp.Length()+1]; - - wxStrcpy( s, tmp ); - - gtk_signal_connect( GTK_OBJECT(widget), "focus_in_event", - GTK_SIGNAL_FUNC(gtk_debug_focus_in_callback), (gpointer)s ); - } -} - #else #define DEBUG_MAIN_THREAD #endif // Debug @@ -385,15 +348,6 @@ wxWindow *wxFindFocusedChild(wxWindowGTK *win) return (wxWindow *)NULL; } -// Returns toplevel grandparent of given window: -static wxWindowGTK* wxGetTopLevelParent(wxWindowGTK *win) -{ - wxWindowGTK *p = win; - while (p && !p->IsTopLevel()) - p = p->GetParent(); - return p; -} - static void draw_frame( GtkWidget *widget, wxWindowGTK *win ) { // wxUniversal widgets draw the borders and scrollbars themselves @@ -1749,6 +1703,21 @@ static gint gtk_window_motion_notify_callback( GtkWidget *widget, // "focus_in_event" //----------------------------------------------------------------------------- +// send the wxChildFocusEvent and wxFocusEvent, common code of +// gtk_window_focus_in_callback() and SetFocus() +static bool DoSendFocusEvents(wxWindow *win) +{ + // Notify the parent keeping track of focus for the kbd navigation + // purposes that we got it. + wxChildFocusEvent eventChildFocus(win); + (void)win->GetEventHandler()->ProcessEvent(eventChildFocus); + + wxFocusEvent eventFocus(wxEVT_SET_FOCUS, win->GetId()); + eventFocus.SetEventObject(win); + + return win->GetEventHandler()->ProcessEvent(eventFocus); +} + static gint gtk_window_focus_in_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindow *win ) @@ -1782,11 +1751,6 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget, printf( "OnSetFocus 2 from %s\n", win->GetName().c_str() ); #endif - // Notify the parent keeping track of focus for the kbd navigation - // purposes that we got it. - wxChildFocusEvent eventFocus(win); - (void)win->GetEventHandler()->ProcessEvent(eventFocus); - #ifdef HAVE_XIM if (win->m_ic) gdk_im_begin(win->m_ic, win->m_wxwindow->window); @@ -1825,11 +1789,7 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget, // return TRUE; } - - wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() ); - event.SetEventObject( win ); - - if (win->GetEventHandler()->ProcessEvent( event )) + if ( DoSendFocusEvents(win) ) { gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" ); return TRUE; @@ -2906,15 +2866,6 @@ void wxWindowGTK::OnInternalIdle() g_activeFrameLostFocus = FALSE; } - if (g_delayedFocus == this) - { - if (GTK_WIDGET_REALIZED(m_widget)) - { - gtk_widget_grab_focus( m_widget ); - g_delayedFocus = NULL; - } - } - wxCursor cursor = m_cursor; if (g_globalCursor.Ok()) cursor = g_globalCursor; @@ -3281,9 +3232,21 @@ void wxWindowGTK::SetFocus() if (GTK_WIDGET_CAN_FOCUS(m_widget) && !GTK_WIDGET_HAS_FOCUS (m_widget) ) { if (!GTK_WIDGET_REALIZED(m_widget)) + { + wxLogTrace(_T("focus"), + _T("Delaying setting focus to %s(%s)\n"), + GetClassInfo()->GetClassName(), GetLabel().c_str()); + g_delayedFocus = this; + } else + { + wxLogTrace(_T("focus"), + _T("Setting focus to %s(%s)\n"), + GetClassInfo()->GetClassName(), GetLabel().c_str()); + gtk_widget_grab_focus (m_widget); + } } else if (GTK_IS_CONTAINER(m_widget)) { @@ -3294,6 +3257,8 @@ void wxWindowGTK::SetFocus() // ? } } + + (void)DoSendFocusEvents(this); } bool wxWindowGTK::AcceptsFocus() const