fixes for the focus handling: don't set back to back set/kill focus events

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@15714 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin
2002-05-31 13:51:43 +00:00
parent 94ccc2540c
commit 6cad4f1b21
4 changed files with 108 additions and 58 deletions

View File

@@ -210,10 +210,11 @@ public:
bool m_isRadioButton:1; // faster than IS_KIND_OF bool m_isRadioButton:1; // faster than IS_KIND_OF
bool m_isListBox:1; // faster than IS_KIND_OF bool m_isListBox:1; // faster than IS_KIND_OF
bool m_isFrame:1; // faster than IS_KIND_OF bool m_isFrame:1; // faster than IS_KIND_OF
bool m_acceptsFocus:1; // not wxStaticBox, not wxStaticBitmap etc. bool m_acceptsFocus:1; // true if not static
bool m_isScrolling; bool m_hasFocus:1; // true if == FindFocus()
bool m_clipPaintRegion; // TRUE after ScrollWindow() bool m_isScrolling:1; // dragging scrollbar thumb?
bool m_queuedFullRedraw; // TRUE after DoMoveWindow bool m_clipPaintRegion:1; // TRUE after ScrollWindow()
bool m_queuedFullRedraw:1; // TRUE after DoMoveWindow
// These are true if the style were set before the widget was realized // These are true if the style were set before the widget was realized
// (typcally in the constructor) but the actual GTK style must not be set // (typcally in the constructor) but the actual GTK style must not be set

View File

@@ -210,10 +210,11 @@ public:
bool m_isRadioButton:1; // faster than IS_KIND_OF bool m_isRadioButton:1; // faster than IS_KIND_OF
bool m_isListBox:1; // faster than IS_KIND_OF bool m_isListBox:1; // faster than IS_KIND_OF
bool m_isFrame:1; // faster than IS_KIND_OF bool m_isFrame:1; // faster than IS_KIND_OF
bool m_acceptsFocus:1; // not wxStaticBox, not wxStaticBitmap etc. bool m_acceptsFocus:1; // true if not static
bool m_isScrolling; bool m_hasFocus:1; // true if == FindFocus()
bool m_clipPaintRegion; // TRUE after ScrollWindow() bool m_isScrolling:1; // dragging scrollbar thumb?
bool m_queuedFullRedraw; // TRUE after DoMoveWindow bool m_clipPaintRegion:1; // TRUE after ScrollWindow()
bool m_queuedFullRedraw:1; // TRUE after DoMoveWindow
// These are true if the style were set before the widget was realized // These are true if the style were set before the widget was realized
// (typcally in the constructor) but the actual GTK style must not be set // (typcally in the constructor) but the actual GTK style must not be set

View File

@@ -274,6 +274,9 @@ extern bool g_mainThreadLocked;
#define DEBUG_MAIN_THREAD #define DEBUG_MAIN_THREAD
#endif // Debug #endif // Debug
// the trace mask used for the focus debugging messages
#define TRACE_FOCUS _T("focus")
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// missing gdk functions // missing gdk functions
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -1751,9 +1754,8 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget,
g_focusWindowLast = g_focusWindowLast =
g_focusWindow = win; g_focusWindow = win;
#if 0 wxLogTrace(TRACE_FOCUS,
printf( "OnSetFocus 2 from %s\n", win->GetName().c_str() ); _T("%s: focus in"), win->GetName().c_str());
#endif
#ifdef HAVE_XIM #ifdef HAVE_XIM
if (win->m_ic) if (win->m_ic)
@@ -1793,10 +1795,17 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget,
// return TRUE; // return TRUE;
} }
if ( DoSendFocusEvents(win) ) // does the window itself think that it has the focus?
if ( !win->m_hasFocus )
{ {
gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" ); // not yet, notify it
return TRUE; win->m_hasFocus = TRUE;
if ( DoSendFocusEvents(win) )
{
gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
return TRUE;
}
} }
return FALSE; return FALSE;
@@ -1816,9 +1825,8 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEventFocus *gdk
if (!win->m_hasVMT) return FALSE; if (!win->m_hasVMT) return FALSE;
if (g_blockEventsOnDrag) return FALSE; if (g_blockEventsOnDrag) return FALSE;
#if 0 wxLogTrace( TRACE_FOCUS,
wxLogDebug( wxT("OnKillFocus from %s"), win->GetName().c_str() ); _T("%s: focus out"), win->GetName().c_str() );
#endif
if ( !g_activeFrameLostFocus && g_activeFrame ) if ( !g_activeFrameLostFocus && g_activeFrame )
{ {
@@ -1858,13 +1866,20 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEventFocus *gdk
} }
#endif // wxUSE_CARET #endif // wxUSE_CARET
wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() ); // don't send the window a kill focus event if it thinks that it doesn't
event.SetEventObject( win ); // have focus already
if ( win->m_hasFocus )
if (win->GetEventHandler()->ProcessEvent( event ))
{ {
gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" ); win->m_hasFocus = FALSE;
return TRUE;
wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
event.SetEventObject( win );
if (win->GetEventHandler()->ProcessEvent( event ))
{
gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" );
return TRUE;
}
} }
return FALSE; return FALSE;
@@ -2318,8 +2333,7 @@ static void wxInsertChildInWindow( wxWindowGTK* parent, wxWindowGTK* child )
wxWindow *wxGetActiveWindow() wxWindow *wxGetActiveWindow()
{ {
// the cast is necessary when we compile in wxUniversal mode return wxWindow::FindFocus();
return (wxWindow *)g_focusWindow;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -2376,6 +2390,7 @@ void wxWindowGTK::Init()
m_isListBox = FALSE; m_isListBox = FALSE;
m_isFrame = FALSE; m_isFrame = FALSE;
m_acceptsFocus = FALSE; m_acceptsFocus = FALSE;
m_hasFocus = FALSE;
m_clipPaintRegion = FALSE; m_clipPaintRegion = FALSE;
@@ -3227,7 +3242,13 @@ void wxWindowGTK::GetTextExtent( const wxString& string,
void wxWindowGTK::SetFocus() void wxWindowGTK::SetFocus()
{ {
wxCHECK_RET( (m_widget != NULL), wxT("invalid window") ); wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
if ( m_hasFocus )
{
// don't do anything if we already have focus
return;
}
if (m_wxwindow) if (m_wxwindow)
{ {
@@ -3242,16 +3263,19 @@ void wxWindowGTK::SetFocus()
{ {
if (!GTK_WIDGET_REALIZED(m_widget)) if (!GTK_WIDGET_REALIZED(m_widget))
{ {
wxLogTrace(_T("focus"), // we can't set the focus to the widget now so we remember that
_T("Delaying setting focus to %s(%s)\n"), // it should be focused and will do it later, during the idle
// time, as soon as we can
wxLogTrace(TRACE_FOCUS,
_T("Delaying setting focus to %s(%s)"),
GetClassInfo()->GetClassName(), GetLabel().c_str()); GetClassInfo()->GetClassName(), GetLabel().c_str());
g_delayedFocus = this; g_delayedFocus = this;
} }
else else
{ {
wxLogTrace(_T("focus"), wxLogTrace(TRACE_FOCUS,
_T("Setting focus to %s(%s)\n"), _T("Setting focus to %s(%s)"),
GetClassInfo()->GetClassName(), GetLabel().c_str()); GetClassInfo()->GetClassName(), GetLabel().c_str());
gtk_widget_grab_focus (m_widget); gtk_widget_grab_focus (m_widget);
@@ -3263,11 +3287,11 @@ void wxWindowGTK::SetFocus()
} }
else else
{ {
// ? wxLogTrace(TRACE_FOCUS,
_T("Can't set focus to %s(%s)"),
GetClassInfo()->GetClassName(), GetLabel().c_str());
} }
} }
(void)DoSendFocusEvents((wxWindow*)this);
} }
bool wxWindowGTK::AcceptsFocus() const bool wxWindowGTK::AcceptsFocus() const

View File

@@ -274,6 +274,9 @@ extern bool g_mainThreadLocked;
#define DEBUG_MAIN_THREAD #define DEBUG_MAIN_THREAD
#endif // Debug #endif // Debug
// the trace mask used for the focus debugging messages
#define TRACE_FOCUS _T("focus")
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// missing gdk functions // missing gdk functions
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -1751,9 +1754,8 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget,
g_focusWindowLast = g_focusWindowLast =
g_focusWindow = win; g_focusWindow = win;
#if 0 wxLogTrace(TRACE_FOCUS,
printf( "OnSetFocus 2 from %s\n", win->GetName().c_str() ); _T("%s: focus in"), win->GetName().c_str());
#endif
#ifdef HAVE_XIM #ifdef HAVE_XIM
if (win->m_ic) if (win->m_ic)
@@ -1793,10 +1795,17 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget,
// return TRUE; // return TRUE;
} }
if ( DoSendFocusEvents(win) ) // does the window itself think that it has the focus?
if ( !win->m_hasFocus )
{ {
gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" ); // not yet, notify it
return TRUE; win->m_hasFocus = TRUE;
if ( DoSendFocusEvents(win) )
{
gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_in_event" );
return TRUE;
}
} }
return FALSE; return FALSE;
@@ -1816,9 +1825,8 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEventFocus *gdk
if (!win->m_hasVMT) return FALSE; if (!win->m_hasVMT) return FALSE;
if (g_blockEventsOnDrag) return FALSE; if (g_blockEventsOnDrag) return FALSE;
#if 0 wxLogTrace( TRACE_FOCUS,
wxLogDebug( wxT("OnKillFocus from %s"), win->GetName().c_str() ); _T("%s: focus out"), win->GetName().c_str() );
#endif
if ( !g_activeFrameLostFocus && g_activeFrame ) if ( !g_activeFrameLostFocus && g_activeFrame )
{ {
@@ -1858,13 +1866,20 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEventFocus *gdk
} }
#endif // wxUSE_CARET #endif // wxUSE_CARET
wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() ); // don't send the window a kill focus event if it thinks that it doesn't
event.SetEventObject( win ); // have focus already
if ( win->m_hasFocus )
if (win->GetEventHandler()->ProcessEvent( event ))
{ {
gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" ); win->m_hasFocus = FALSE;
return TRUE;
wxFocusEvent event( wxEVT_KILL_FOCUS, win->GetId() );
event.SetEventObject( win );
if (win->GetEventHandler()->ProcessEvent( event ))
{
gtk_signal_emit_stop_by_name( GTK_OBJECT(widget), "focus_out_event" );
return TRUE;
}
} }
return FALSE; return FALSE;
@@ -2318,8 +2333,7 @@ static void wxInsertChildInWindow( wxWindowGTK* parent, wxWindowGTK* child )
wxWindow *wxGetActiveWindow() wxWindow *wxGetActiveWindow()
{ {
// the cast is necessary when we compile in wxUniversal mode return wxWindow::FindFocus();
return (wxWindow *)g_focusWindow;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -2376,6 +2390,7 @@ void wxWindowGTK::Init()
m_isListBox = FALSE; m_isListBox = FALSE;
m_isFrame = FALSE; m_isFrame = FALSE;
m_acceptsFocus = FALSE; m_acceptsFocus = FALSE;
m_hasFocus = FALSE;
m_clipPaintRegion = FALSE; m_clipPaintRegion = FALSE;
@@ -3227,7 +3242,13 @@ void wxWindowGTK::GetTextExtent( const wxString& string,
void wxWindowGTK::SetFocus() void wxWindowGTK::SetFocus()
{ {
wxCHECK_RET( (m_widget != NULL), wxT("invalid window") ); wxCHECK_RET( m_widget != NULL, wxT("invalid window") );
if ( m_hasFocus )
{
// don't do anything if we already have focus
return;
}
if (m_wxwindow) if (m_wxwindow)
{ {
@@ -3242,16 +3263,19 @@ void wxWindowGTK::SetFocus()
{ {
if (!GTK_WIDGET_REALIZED(m_widget)) if (!GTK_WIDGET_REALIZED(m_widget))
{ {
wxLogTrace(_T("focus"), // we can't set the focus to the widget now so we remember that
_T("Delaying setting focus to %s(%s)\n"), // it should be focused and will do it later, during the idle
// time, as soon as we can
wxLogTrace(TRACE_FOCUS,
_T("Delaying setting focus to %s(%s)"),
GetClassInfo()->GetClassName(), GetLabel().c_str()); GetClassInfo()->GetClassName(), GetLabel().c_str());
g_delayedFocus = this; g_delayedFocus = this;
} }
else else
{ {
wxLogTrace(_T("focus"), wxLogTrace(TRACE_FOCUS,
_T("Setting focus to %s(%s)\n"), _T("Setting focus to %s(%s)"),
GetClassInfo()->GetClassName(), GetLabel().c_str()); GetClassInfo()->GetClassName(), GetLabel().c_str());
gtk_widget_grab_focus (m_widget); gtk_widget_grab_focus (m_widget);
@@ -3263,11 +3287,11 @@ void wxWindowGTK::SetFocus()
} }
else else
{ {
// ? wxLogTrace(TRACE_FOCUS,
_T("Can't set focus to %s(%s)"),
GetClassInfo()->GetClassName(), GetLabel().c_str());
} }
} }
(void)DoSendFocusEvents((wxWindow*)this);
} }
bool wxWindowGTK::AcceptsFocus() const bool wxWindowGTK::AcceptsFocus() const