From d7fa7eaa2dc8ef4154ac4d9d739bcfb6be1669ac Mon Sep 17 00:00:00 2001 From: Robert Roebling Date: Wed, 17 Apr 2002 22:44:31 +0000 Subject: [PATCH 1/1] Various changes to focus handling when TLW start. Changed wxWindow::Clear() to use m_clearRegion. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@15191 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- src/generic/filedlgg.cpp | 2 ++ src/gtk/checkbox.cpp | 14 +++++++-- src/gtk/listbox.cpp | 16 ++++++++-- src/gtk/radiobox.cpp | 13 ++++++-- src/gtk/radiobut.cpp | 14 +++++++-- src/gtk/textctrl.cpp | 10 ++++++ src/gtk/tglbtn.cpp | 3 +- src/gtk/toplevel.cpp | 58 ++++++++++++++++++++++++---------- src/gtk/window.cpp | 68 +++++++++++++++++++++++++--------------- src/gtk1/checkbox.cpp | 14 +++++++-- src/gtk1/listbox.cpp | 16 ++++++++-- src/gtk1/radiobox.cpp | 13 ++++++-- src/gtk1/radiobut.cpp | 14 +++++++-- src/gtk1/textctrl.cpp | 10 ++++++ src/gtk1/tglbtn.cpp | 3 +- src/gtk1/toplevel.cpp | 58 ++++++++++++++++++++++++---------- src/gtk1/window.cpp | 68 +++++++++++++++++++++++++--------------- 17 files changed, 286 insertions(+), 108 deletions(-) diff --git a/src/generic/filedlgg.cpp b/src/generic/filedlgg.cpp index 3b81bef0dc..bc618a2345 100644 --- a/src/generic/filedlgg.cpp +++ b/src/generic/filedlgg.cpp @@ -1403,6 +1403,8 @@ void wxFileDialog::OnHome( wxCommandEvent &WXUNUSED(event) ) wxString dir; m_list->GetDir( dir ); m_static->SetLabel( dir ); + + m_text->SetFocus(); } void wxFileDialog::OnNew( wxCommandEvent &WXUNUSED(event) ) diff --git a/src/gtk/checkbox.cpp b/src/gtk/checkbox.cpp index 225f9df18e..5e0dcb88f2 100644 --- a/src/gtk/checkbox.cpp +++ b/src/gtk/checkbox.cpp @@ -31,8 +31,9 @@ extern bool g_isIdle; // data //----------------------------------------------------------------------------- -extern bool g_blockEventsOnDrag; -extern wxCursor g_globalCursor; +extern bool g_blockEventsOnDrag; +extern wxCursor g_globalCursor; +extern wxWindowGTK *g_delayedFocus; //----------------------------------------------------------------------------- // "clicked" @@ -206,6 +207,15 @@ void wxCheckBox::OnInternalIdle() gdk_window_set_cursor( event_window, cursor.GetCursor() ); } + if (g_delayedFocus == this) + { + if (GTK_WIDGET_REALIZED(m_widget)) + { + gtk_widget_grab_focus( m_widget ); + g_delayedFocus = NULL; + } + } + UpdateWindowUI(); } diff --git a/src/gtk/listbox.cpp b/src/gtk/listbox.cpp index afdac34650..4eefc235d3 100644 --- a/src/gtk/listbox.cpp +++ b/src/gtk/listbox.cpp @@ -59,9 +59,10 @@ extern bool g_isIdle; // data //----------------------------------------------------------------------------- -extern bool g_blockEventsOnDrag; -extern bool g_blockEventsOnScroll; -extern wxCursor g_globalCursor; +extern bool g_blockEventsOnDrag; +extern bool g_blockEventsOnScroll; +extern wxCursor g_globalCursor; +extern wxWindowGTK *g_delayedFocus; static bool g_hasDoubleClicked = FALSE; @@ -1023,6 +1024,15 @@ void wxListBox::OnInternalIdle() } } + if (g_delayedFocus == this) + { + if (GTK_WIDGET_REALIZED(m_widget)) + { + gtk_widget_grab_focus( m_widget ); + g_delayedFocus = NULL; + } + } + UpdateWindowUI(); } diff --git a/src/gtk/radiobox.cpp b/src/gtk/radiobox.cpp index cd422ade2b..98e57717ad 100644 --- a/src/gtk/radiobox.cpp +++ b/src/gtk/radiobox.cpp @@ -37,7 +37,8 @@ extern bool g_isIdle; // data //----------------------------------------------------------------------------- -extern bool g_blockEventsOnDrag; +extern bool g_blockEventsOnDrag; +extern wxWindowGTK *g_delayedFocus; //----------------------------------------------------------------------------- // "clicked" @@ -455,7 +456,6 @@ void wxRadioBox::SetFocus() } node = node->Next(); } - } void wxRadioBox::SetSelection( int n ) @@ -711,6 +711,15 @@ void wxRadioBox::OnInternalIdle() (void)GetEventHandler()->ProcessEvent( event ); } + + if (g_delayedFocus == this) + { + if (GTK_WIDGET_REALIZED(m_widget)) + { + g_delayedFocus = NULL; + SetFocus(); + } + } } #endif // wxUSE_RADIOBOX diff --git a/src/gtk/radiobut.cpp b/src/gtk/radiobut.cpp index 7d2557692f..92b78d4223 100644 --- a/src/gtk/radiobut.cpp +++ b/src/gtk/radiobut.cpp @@ -31,8 +31,9 @@ extern bool g_isIdle; // data //----------------------------------------------------------------------------- -extern bool g_blockEventsOnDrag; -extern wxCursor g_globalCursor; +extern bool g_blockEventsOnDrag; +extern wxCursor g_globalCursor; +extern wxWindowGTK *g_delayedFocus; //----------------------------------------------------------------------------- // "clicked" @@ -219,6 +220,15 @@ void wxRadioButton::OnInternalIdle() gdk_window_set_cursor( win, cursor.GetCursor() ); } + if (g_delayedFocus == this) + { + if (GTK_WIDGET_REALIZED(m_widget)) + { + gtk_widget_grab_focus( m_widget ); + g_delayedFocus = NULL; + } + } + UpdateWindowUI(); } diff --git a/src/gtk/textctrl.cpp b/src/gtk/textctrl.cpp index b7dd3a877d..84aca5d404 100644 --- a/src/gtk/textctrl.cpp +++ b/src/gtk/textctrl.cpp @@ -44,6 +44,7 @@ extern bool g_isIdle; extern bool g_blockEventsOnDrag; extern wxCursor g_globalCursor; +extern wxWindowGTK *g_delayedFocus; // ---------------------------------------------------------------------------- // helpers @@ -1245,6 +1246,15 @@ void wxTextCtrl::OnInternalIdle() gdk_window_set_cursor( window, cursor.GetCursor() ); } + if (g_delayedFocus == this) + { + if (GTK_WIDGET_REALIZED(m_widget)) + { + gtk_widget_grab_focus( m_widget ); + g_delayedFocus = NULL; + } + } + UpdateWindowUI(); } diff --git a/src/gtk/tglbtn.cpp b/src/gtk/tglbtn.cpp index c5a05ec578..e6ca7ff17c 100644 --- a/src/gtk/tglbtn.cpp +++ b/src/gtk/tglbtn.cpp @@ -21,9 +21,8 @@ extern void wxapp_install_idle_handler(); extern bool g_isIdle; extern bool g_blockEventsOnDrag; extern wxCursor g_globalCursor; +extern wxWindowGTK *g_delayedFocus; -// void gtk_togglebutton_clicked_callback(GtkWidget *widget, wxToggleButton *cb) -// Callback function given to gtk. static void gtk_togglebutton_clicked_callback(GtkWidget *WXUNUSED(widget), wxToggleButton *cb) { if (g_isIdle) diff --git a/src/gtk/toplevel.cpp b/src/gtk/toplevel.cpp index a32d659c2f..b2045d79d4 100644 --- a/src/gtk/toplevel.cpp +++ b/src/gtk/toplevel.cpp @@ -46,17 +46,15 @@ extern void wxapp_install_idle_handler(); extern bool g_isIdle; -extern int g_openDialogs; - -// ---------------------------------------------------------------------------- -// event tables -// ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // data // ---------------------------------------------------------------------------- -extern wxList wxPendingDelete; +extern wxList wxPendingDelete; + +extern int g_openDialogs; +extern wxWindowGTK *g_delayedFocus; // ---------------------------------------------------------------------------- // debug @@ -68,14 +66,6 @@ extern void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar #endif -// ============================================================================ -// implementation -// ============================================================================ - -// ---------------------------------------------------------------------------- -// GTK callbacks -// ---------------------------------------------------------------------------- - //----------------------------------------------------------------------------- // "focus" from m_window //----------------------------------------------------------------------------- @@ -164,6 +154,18 @@ 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 //----------------------------------------------------------------------------- @@ -200,8 +202,30 @@ gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget), wxTopLevelWindowGTK * win->SetIcons( iconsOld ); } - // we set the focus to the child that accepts the focus. this - // doesn't really have to be done in "realize" but why not? + // 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) { @@ -211,7 +235,7 @@ gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget), wxTopLevelWindowGTK * child->SetFocus(); break; } - + node = node->GetNext(); } } diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index fd113b072c..efc124ac8d 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -232,13 +232,17 @@ static bool g_captureWindowHasMouse = FALSE; // the last window which had the focus - this is normally never NULL (except // if we never had focus at all) as even when g_focusWindow is NULL it still // keeps its previous value -static wxWindowGTK *g_focusWindowLast = (wxWindowGTK *)NULL; +static wxWindowGTK *g_focusWindowLast = (wxWindowGTK*) NULL; // the frame that is currently active (i.e. its child has focus). It is // used to generate wxActivateEvents -static wxWindowGTK *g_activeFrame = (wxWindowGTK *)NULL; +static wxWindowGTK *g_activeFrame = (wxWindowGTK*) NULL; static bool g_activeFrameLostFocus = FALSE; +// If a window get the focus set but has not been realized +// yet, defer setting the focus to idle time. +wxWindowGTK *g_delayedFocus = (wxWindowGTK*) NULL; + // if we detect that the app has got/lost the focus, we set this variable to // either TRUE or FALSE and an activate event will be sent during the next // OnIdle() call and it is reset to -1: this value means that we shouldn't @@ -534,8 +538,8 @@ static int gtk_window_expose_callback( GtkWidget *widget, if (g_isIdle) wxapp_install_idle_handler(); -/* - if (win->GetName() == wxT("panel")) +#if 0 + if (win->GetName()) { wxPrintf( wxT("OnExpose from ") ); if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) @@ -545,7 +549,7 @@ static int gtk_window_expose_callback( GtkWidget *widget, (int)gdk_event->area.width, (int)gdk_event->area.height ); } -*/ +#endif #ifndef __WXUNIVERSAL__ GtkPizza *pizza = GTK_PIZZA (widget); @@ -635,8 +639,8 @@ static void gtk_window_draw_callback( GtkWidget *widget, return; } -/* - if (win->GetName() == wxT("panel")) +#if 0 + if (win->GetName()) { wxPrintf( wxT("OnDraw from ") ); if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) @@ -646,7 +650,7 @@ static void gtk_window_draw_callback( GtkWidget *widget, (int)rect->width, (int)rect->height ); } -*/ +#endif #ifndef __WXUNIVERSAL__ GtkPizza *pizza = GTK_PIZZA (widget); @@ -1797,11 +1801,11 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget, g_focusWindow = win; #if 0 - wxLogDebug( wxT("OnSetFocus from %s\n"), win->GetName().c_str() ); + 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 + // Notify the parent keeping track of focus for the kbd navigation + // purposes that we got it. wxChildFocusEvent eventFocus(win); (void)win->GetEventHandler()->ProcessEvent(eventFocus); @@ -1819,6 +1823,8 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget, } #endif // wxUSE_CARET + g_activeFrameLostFocus = FALSE; + wxWindowGTK *active = wxGetTopLevelParent(win); if ( active != g_activeFrame ) { @@ -1835,8 +1841,11 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget, wxActivateEvent event(wxEVT_ACTIVATE, TRUE, g_activeFrame->GetId()); event.SetEventObject(g_activeFrame); g_activeFrame->GetEventHandler()->ProcessEvent(event); + + // Don't send focus events in addition to activate + // if (win == g_activeFrame) + // return TRUE; } - g_activeFrameLostFocus = FALSE; wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() ); @@ -1848,7 +1857,6 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget, return TRUE; } - return FALSE; } @@ -2919,6 +2927,15 @@ 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; @@ -3274,13 +3291,6 @@ void wxWindowGTK::SetFocus() { wxCHECK_RET( (m_widget != NULL), wxT("invalid window") ); -#if 0 - wxPrintf( "SetFocus from " ); - if (GetClassInfo() && GetClassInfo()->GetClassName()) - wxPrintf( GetClassInfo()->GetClassName() ); - wxPrintf( ".\n" ); -#endif - if (m_wxwindow) { if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow)) @@ -3292,7 +3302,10 @@ void wxWindowGTK::SetFocus() { if (GTK_WIDGET_CAN_FOCUS(m_widget) && !GTK_WIDGET_HAS_FOCUS (m_widget) ) { - gtk_widget_grab_focus (m_widget); + if (!GTK_WIDGET_REALIZED(m_widget)) + g_delayedFocus = this; + else + gtk_widget_grab_focus (m_widget); } else if (GTK_IS_CONTAINER(m_widget)) { @@ -3507,7 +3520,7 @@ void wxWindowGTK::GtkSendPaintEvents() } m_clipPaintRegion = TRUE; - + // if (!m_clearRegion.IsEmpty()) // always send an erase event { wxWindowDC dc( (wxWindow*)this ); @@ -3559,7 +3572,7 @@ void wxWindowGTK::GtkSendPaintEvents() { GtkPizzaChild *child = (GtkPizzaChild*) children->data; children = children->next; - + if (GTK_WIDGET_NO_WINDOW (child->widget) && GTK_WIDGET_DRAWABLE (child->widget)) { @@ -3599,11 +3612,14 @@ void wxWindowGTK::Clear() { wxCHECK_RET( m_widget != NULL, wxT("invalid window") ); - if (!m_widget->window) return; - if (m_wxwindow && m_wxwindow->window) { - gdk_window_clear( m_wxwindow->window ); + m_clearRegion.Clear(); + wxSize size( GetClientSize() ); + m_clearRegion.Union( 0,0,size.x,size.y ); + + // Better do this in idle? + Update(); } } diff --git a/src/gtk1/checkbox.cpp b/src/gtk1/checkbox.cpp index 225f9df18e..5e0dcb88f2 100644 --- a/src/gtk1/checkbox.cpp +++ b/src/gtk1/checkbox.cpp @@ -31,8 +31,9 @@ extern bool g_isIdle; // data //----------------------------------------------------------------------------- -extern bool g_blockEventsOnDrag; -extern wxCursor g_globalCursor; +extern bool g_blockEventsOnDrag; +extern wxCursor g_globalCursor; +extern wxWindowGTK *g_delayedFocus; //----------------------------------------------------------------------------- // "clicked" @@ -206,6 +207,15 @@ void wxCheckBox::OnInternalIdle() gdk_window_set_cursor( event_window, cursor.GetCursor() ); } + if (g_delayedFocus == this) + { + if (GTK_WIDGET_REALIZED(m_widget)) + { + gtk_widget_grab_focus( m_widget ); + g_delayedFocus = NULL; + } + } + UpdateWindowUI(); } diff --git a/src/gtk1/listbox.cpp b/src/gtk1/listbox.cpp index afdac34650..4eefc235d3 100644 --- a/src/gtk1/listbox.cpp +++ b/src/gtk1/listbox.cpp @@ -59,9 +59,10 @@ extern bool g_isIdle; // data //----------------------------------------------------------------------------- -extern bool g_blockEventsOnDrag; -extern bool g_blockEventsOnScroll; -extern wxCursor g_globalCursor; +extern bool g_blockEventsOnDrag; +extern bool g_blockEventsOnScroll; +extern wxCursor g_globalCursor; +extern wxWindowGTK *g_delayedFocus; static bool g_hasDoubleClicked = FALSE; @@ -1023,6 +1024,15 @@ void wxListBox::OnInternalIdle() } } + if (g_delayedFocus == this) + { + if (GTK_WIDGET_REALIZED(m_widget)) + { + gtk_widget_grab_focus( m_widget ); + g_delayedFocus = NULL; + } + } + UpdateWindowUI(); } diff --git a/src/gtk1/radiobox.cpp b/src/gtk1/radiobox.cpp index cd422ade2b..98e57717ad 100644 --- a/src/gtk1/radiobox.cpp +++ b/src/gtk1/radiobox.cpp @@ -37,7 +37,8 @@ extern bool g_isIdle; // data //----------------------------------------------------------------------------- -extern bool g_blockEventsOnDrag; +extern bool g_blockEventsOnDrag; +extern wxWindowGTK *g_delayedFocus; //----------------------------------------------------------------------------- // "clicked" @@ -455,7 +456,6 @@ void wxRadioBox::SetFocus() } node = node->Next(); } - } void wxRadioBox::SetSelection( int n ) @@ -711,6 +711,15 @@ void wxRadioBox::OnInternalIdle() (void)GetEventHandler()->ProcessEvent( event ); } + + if (g_delayedFocus == this) + { + if (GTK_WIDGET_REALIZED(m_widget)) + { + g_delayedFocus = NULL; + SetFocus(); + } + } } #endif // wxUSE_RADIOBOX diff --git a/src/gtk1/radiobut.cpp b/src/gtk1/radiobut.cpp index 7d2557692f..92b78d4223 100644 --- a/src/gtk1/radiobut.cpp +++ b/src/gtk1/radiobut.cpp @@ -31,8 +31,9 @@ extern bool g_isIdle; // data //----------------------------------------------------------------------------- -extern bool g_blockEventsOnDrag; -extern wxCursor g_globalCursor; +extern bool g_blockEventsOnDrag; +extern wxCursor g_globalCursor; +extern wxWindowGTK *g_delayedFocus; //----------------------------------------------------------------------------- // "clicked" @@ -219,6 +220,15 @@ void wxRadioButton::OnInternalIdle() gdk_window_set_cursor( win, cursor.GetCursor() ); } + if (g_delayedFocus == this) + { + if (GTK_WIDGET_REALIZED(m_widget)) + { + gtk_widget_grab_focus( m_widget ); + g_delayedFocus = NULL; + } + } + UpdateWindowUI(); } diff --git a/src/gtk1/textctrl.cpp b/src/gtk1/textctrl.cpp index b7dd3a877d..84aca5d404 100644 --- a/src/gtk1/textctrl.cpp +++ b/src/gtk1/textctrl.cpp @@ -44,6 +44,7 @@ extern bool g_isIdle; extern bool g_blockEventsOnDrag; extern wxCursor g_globalCursor; +extern wxWindowGTK *g_delayedFocus; // ---------------------------------------------------------------------------- // helpers @@ -1245,6 +1246,15 @@ void wxTextCtrl::OnInternalIdle() gdk_window_set_cursor( window, cursor.GetCursor() ); } + if (g_delayedFocus == this) + { + if (GTK_WIDGET_REALIZED(m_widget)) + { + gtk_widget_grab_focus( m_widget ); + g_delayedFocus = NULL; + } + } + UpdateWindowUI(); } diff --git a/src/gtk1/tglbtn.cpp b/src/gtk1/tglbtn.cpp index c5a05ec578..e6ca7ff17c 100644 --- a/src/gtk1/tglbtn.cpp +++ b/src/gtk1/tglbtn.cpp @@ -21,9 +21,8 @@ extern void wxapp_install_idle_handler(); extern bool g_isIdle; extern bool g_blockEventsOnDrag; extern wxCursor g_globalCursor; +extern wxWindowGTK *g_delayedFocus; -// void gtk_togglebutton_clicked_callback(GtkWidget *widget, wxToggleButton *cb) -// Callback function given to gtk. static void gtk_togglebutton_clicked_callback(GtkWidget *WXUNUSED(widget), wxToggleButton *cb) { if (g_isIdle) diff --git a/src/gtk1/toplevel.cpp b/src/gtk1/toplevel.cpp index a32d659c2f..b2045d79d4 100644 --- a/src/gtk1/toplevel.cpp +++ b/src/gtk1/toplevel.cpp @@ -46,17 +46,15 @@ extern void wxapp_install_idle_handler(); extern bool g_isIdle; -extern int g_openDialogs; - -// ---------------------------------------------------------------------------- -// event tables -// ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // data // ---------------------------------------------------------------------------- -extern wxList wxPendingDelete; +extern wxList wxPendingDelete; + +extern int g_openDialogs; +extern wxWindowGTK *g_delayedFocus; // ---------------------------------------------------------------------------- // debug @@ -68,14 +66,6 @@ extern void debug_focus_in( GtkWidget* widget, const wxChar* name, const wxChar #endif -// ============================================================================ -// implementation -// ============================================================================ - -// ---------------------------------------------------------------------------- -// GTK callbacks -// ---------------------------------------------------------------------------- - //----------------------------------------------------------------------------- // "focus" from m_window //----------------------------------------------------------------------------- @@ -164,6 +154,18 @@ 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 //----------------------------------------------------------------------------- @@ -200,8 +202,30 @@ gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget), wxTopLevelWindowGTK * win->SetIcons( iconsOld ); } - // we set the focus to the child that accepts the focus. this - // doesn't really have to be done in "realize" but why not? + // 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) { @@ -211,7 +235,7 @@ gtk_frame_realized_callback( GtkWidget * WXUNUSED(widget), wxTopLevelWindowGTK * child->SetFocus(); break; } - + node = node->GetNext(); } } diff --git a/src/gtk1/window.cpp b/src/gtk1/window.cpp index fd113b072c..efc124ac8d 100644 --- a/src/gtk1/window.cpp +++ b/src/gtk1/window.cpp @@ -232,13 +232,17 @@ static bool g_captureWindowHasMouse = FALSE; // the last window which had the focus - this is normally never NULL (except // if we never had focus at all) as even when g_focusWindow is NULL it still // keeps its previous value -static wxWindowGTK *g_focusWindowLast = (wxWindowGTK *)NULL; +static wxWindowGTK *g_focusWindowLast = (wxWindowGTK*) NULL; // the frame that is currently active (i.e. its child has focus). It is // used to generate wxActivateEvents -static wxWindowGTK *g_activeFrame = (wxWindowGTK *)NULL; +static wxWindowGTK *g_activeFrame = (wxWindowGTK*) NULL; static bool g_activeFrameLostFocus = FALSE; +// If a window get the focus set but has not been realized +// yet, defer setting the focus to idle time. +wxWindowGTK *g_delayedFocus = (wxWindowGTK*) NULL; + // if we detect that the app has got/lost the focus, we set this variable to // either TRUE or FALSE and an activate event will be sent during the next // OnIdle() call and it is reset to -1: this value means that we shouldn't @@ -534,8 +538,8 @@ static int gtk_window_expose_callback( GtkWidget *widget, if (g_isIdle) wxapp_install_idle_handler(); -/* - if (win->GetName() == wxT("panel")) +#if 0 + if (win->GetName()) { wxPrintf( wxT("OnExpose from ") ); if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) @@ -545,7 +549,7 @@ static int gtk_window_expose_callback( GtkWidget *widget, (int)gdk_event->area.width, (int)gdk_event->area.height ); } -*/ +#endif #ifndef __WXUNIVERSAL__ GtkPizza *pizza = GTK_PIZZA (widget); @@ -635,8 +639,8 @@ static void gtk_window_draw_callback( GtkWidget *widget, return; } -/* - if (win->GetName() == wxT("panel")) +#if 0 + if (win->GetName()) { wxPrintf( wxT("OnDraw from ") ); if (win->GetClassInfo() && win->GetClassInfo()->GetClassName()) @@ -646,7 +650,7 @@ static void gtk_window_draw_callback( GtkWidget *widget, (int)rect->width, (int)rect->height ); } -*/ +#endif #ifndef __WXUNIVERSAL__ GtkPizza *pizza = GTK_PIZZA (widget); @@ -1797,11 +1801,11 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget, g_focusWindow = win; #if 0 - wxLogDebug( wxT("OnSetFocus from %s\n"), win->GetName().c_str() ); + 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 + // Notify the parent keeping track of focus for the kbd navigation + // purposes that we got it. wxChildFocusEvent eventFocus(win); (void)win->GetEventHandler()->ProcessEvent(eventFocus); @@ -1819,6 +1823,8 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget, } #endif // wxUSE_CARET + g_activeFrameLostFocus = FALSE; + wxWindowGTK *active = wxGetTopLevelParent(win); if ( active != g_activeFrame ) { @@ -1835,8 +1841,11 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget, wxActivateEvent event(wxEVT_ACTIVATE, TRUE, g_activeFrame->GetId()); event.SetEventObject(g_activeFrame); g_activeFrame->GetEventHandler()->ProcessEvent(event); + + // Don't send focus events in addition to activate + // if (win == g_activeFrame) + // return TRUE; } - g_activeFrameLostFocus = FALSE; wxFocusEvent event( wxEVT_SET_FOCUS, win->GetId() ); @@ -1848,7 +1857,6 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget, return TRUE; } - return FALSE; } @@ -2919,6 +2927,15 @@ 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; @@ -3274,13 +3291,6 @@ void wxWindowGTK::SetFocus() { wxCHECK_RET( (m_widget != NULL), wxT("invalid window") ); -#if 0 - wxPrintf( "SetFocus from " ); - if (GetClassInfo() && GetClassInfo()->GetClassName()) - wxPrintf( GetClassInfo()->GetClassName() ); - wxPrintf( ".\n" ); -#endif - if (m_wxwindow) { if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow)) @@ -3292,7 +3302,10 @@ void wxWindowGTK::SetFocus() { if (GTK_WIDGET_CAN_FOCUS(m_widget) && !GTK_WIDGET_HAS_FOCUS (m_widget) ) { - gtk_widget_grab_focus (m_widget); + if (!GTK_WIDGET_REALIZED(m_widget)) + g_delayedFocus = this; + else + gtk_widget_grab_focus (m_widget); } else if (GTK_IS_CONTAINER(m_widget)) { @@ -3507,7 +3520,7 @@ void wxWindowGTK::GtkSendPaintEvents() } m_clipPaintRegion = TRUE; - + // if (!m_clearRegion.IsEmpty()) // always send an erase event { wxWindowDC dc( (wxWindow*)this ); @@ -3559,7 +3572,7 @@ void wxWindowGTK::GtkSendPaintEvents() { GtkPizzaChild *child = (GtkPizzaChild*) children->data; children = children->next; - + if (GTK_WIDGET_NO_WINDOW (child->widget) && GTK_WIDGET_DRAWABLE (child->widget)) { @@ -3599,11 +3612,14 @@ void wxWindowGTK::Clear() { wxCHECK_RET( m_widget != NULL, wxT("invalid window") ); - if (!m_widget->window) return; - if (m_wxwindow && m_wxwindow->window) { - gdk_window_clear( m_wxwindow->window ); + m_clearRegion.Clear(); + wxSize size( GetClientSize() ); + m_clearRegion.Union( 0,0,size.x,size.y ); + + // Better do this in idle? + Update(); } } -- 2.45.2