From: Vadim Zeitlin Date: Mon, 24 Sep 2001 18:46:13 +0000 (+0000) Subject: added workaround for GTK+ focus_out bug (and removed Vaclav's mouse capture stack... X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/b231914f6abe2c148193b006a0919d60575f9a20 added workaround for GTK+ focus_out bug (and removed Vaclav's mouse capture stack - sorry!) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@11691 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/src/gtk/window.cpp b/src/gtk/window.cpp index 254545aa5b..ca9543b11e 100644 --- a/src/gtk/window.cpp +++ b/src/gtk/window.cpp @@ -208,7 +208,6 @@ extern wxCursor g_globalCursor; // inside it static wxWindowGTK *g_captureWindow = (wxWindowGTK*) NULL; static bool g_captureWindowHasMouse = FALSE; -static wxWindowList g_capturedWindows; /* extern */ wxWindowGTK *g_focusWindow = (wxWindowGTK*) NULL; @@ -1736,6 +1735,8 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget, // "focus_out_event" //----------------------------------------------------------------------------- +static GtkWidget *gs_widgetLastFocus = NULL; + static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindowGTK *win ) { DEBUG_MAIN_THREAD @@ -1746,6 +1747,18 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED if (!win->m_hasVMT) return FALSE; if (g_blockEventsOnDrag) return FALSE; + // VZ: this is really weird but GTK+ seems to call us from inside + // gtk_widget_grab_focus(), i.e. it first sends "focus_out" signal to + // this widget and then "focus_in". This is totally unexpected and + // completely breaks wxUniv code so ignore this dummy event (we can't + // be losing focus if we're about to acquire it!) + if ( widget == gs_widgetLastFocus ) + { + gs_widgetLastFocus = NULL; + + return; + } + // if the focus goes out of our app alltogether, OnIdle() will send // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset // g_sendActivateEvent to -1 @@ -2475,8 +2488,6 @@ bool wxWindowGTK::Create( wxWindow *parent, wxWindowGTK::~wxWindowGTK() { - wxASSERT_MSG( g_capturedWindows.IndexOf(this) == wxNOT_FOUND, wxT("trying to destroy window that didn't release focus") ); - if (g_focusWindow == this) g_focusWindow = NULL; @@ -3168,11 +3179,13 @@ void wxWindowGTK::SetFocus() if (m_wxwindow) { if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow)) + { + // see comment in gtk_window_focus_out_callback() + gs_widgetLastFocus = m_wxwindow; gtk_widget_grab_focus (m_wxwindow); - return; + } } - - if (m_widget) + else if (m_widget) { if (GTK_WIDGET_CAN_FOCUS(m_widget) && !GTK_WIDGET_HAS_FOCUS (m_widget) ) { @@ -3754,17 +3767,19 @@ bool wxWindowGTK::SetFont( const wxFont &font ) return TRUE; } -static void wxDoCaptureMouse(wxWindowGTK *wnd) +void wxWindowGTK::CaptureMouse() { + wxCHECK_RET( m_widget != NULL, wxT("invalid window") ); + GdkWindow *window = (GdkWindow*) NULL; - if (wnd->m_wxwindow) - window = GTK_PIZZA(wnd->m_wxwindow)->bin_window; + if (m_wxwindow) + window = GTK_PIZZA(m_wxwindow)->bin_window; else - window = wnd->GetConnectWidget()->window; + window = GetConnectWidget()->window; wxCHECK_RET( window, _T("CaptureMouse() failed") ); - wxCursor* cursor = &wnd->GetCursor(); + wxCursor* cursor = & m_cursor; if (!cursor->Ok()) cursor = wxSTANDARD_CURSOR; @@ -3777,54 +3792,27 @@ static void wxDoCaptureMouse(wxWindowGTK *wnd) (GdkWindow *) NULL, cursor->GetCursor(), (guint32)GDK_CURRENT_TIME ); - g_captureWindow = wnd; + g_captureWindow = this; g_captureWindowHasMouse = TRUE; - wxLogDebug("captured %p", wnd); } -static void wxDoReleaseMouse(wxWindowGTK *wnd) +void wxWindowGTK::ReleaseMouse() { - wxLogDebug("trying to release %p", wnd); + wxCHECK_RET( m_widget != NULL, wxT("invalid window") ); + wxCHECK_RET( g_captureWindow, wxT("can't release mouse - not captured") ); GdkWindow *window = (GdkWindow*) NULL; - if (wnd->m_wxwindow) - window = GTK_PIZZA(wnd->m_wxwindow)->bin_window; + if (m_wxwindow) + window = GTK_PIZZA(m_wxwindow)->bin_window; else - window = wnd->GetConnectWidget()->window; + window = GetConnectWidget()->window; if (!window) return; gdk_pointer_ungrab ( (guint32)GDK_CURRENT_TIME ); g_captureWindow = (wxWindowGTK*) NULL; - wxLogDebug("released %p", wnd); -} - -void wxWindowGTK::CaptureMouse() -{ - wxCHECK_RET( m_widget != NULL, wxT("invalid window") ); - - wxLogDebug("CAPTURE %p", this); - wxWindowList::Node *last = g_capturedWindows.GetLast(); - if (last) - wxDoReleaseMouse(last->GetData()); - - g_capturedWindows.Append(this); - wxDoCaptureMouse(this); -} - -void wxWindowGTK::ReleaseMouse() -{ - wxCHECK_RET( m_widget != NULL, wxT("invalid window") ); - - wxLogDebug("RELEASE %p", this); - wxDoReleaseMouse(this); - g_capturedWindows.DeleteObject(this); - - wxWindowList::Node *last = g_capturedWindows.GetLast(); - if (last) - wxDoCaptureMouse(last->GetData()); } /* static */ diff --git a/src/gtk1/window.cpp b/src/gtk1/window.cpp index 254545aa5b..ca9543b11e 100644 --- a/src/gtk1/window.cpp +++ b/src/gtk1/window.cpp @@ -208,7 +208,6 @@ extern wxCursor g_globalCursor; // inside it static wxWindowGTK *g_captureWindow = (wxWindowGTK*) NULL; static bool g_captureWindowHasMouse = FALSE; -static wxWindowList g_capturedWindows; /* extern */ wxWindowGTK *g_focusWindow = (wxWindowGTK*) NULL; @@ -1736,6 +1735,8 @@ static gint gtk_window_focus_in_callback( GtkWidget *widget, // "focus_out_event" //----------------------------------------------------------------------------- +static GtkWidget *gs_widgetLastFocus = NULL; + static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED(event), wxWindowGTK *win ) { DEBUG_MAIN_THREAD @@ -1746,6 +1747,18 @@ static gint gtk_window_focus_out_callback( GtkWidget *widget, GdkEvent *WXUNUSED if (!win->m_hasVMT) return FALSE; if (g_blockEventsOnDrag) return FALSE; + // VZ: this is really weird but GTK+ seems to call us from inside + // gtk_widget_grab_focus(), i.e. it first sends "focus_out" signal to + // this widget and then "focus_in". This is totally unexpected and + // completely breaks wxUniv code so ignore this dummy event (we can't + // be losing focus if we're about to acquire it!) + if ( widget == gs_widgetLastFocus ) + { + gs_widgetLastFocus = NULL; + + return; + } + // if the focus goes out of our app alltogether, OnIdle() will send // wxActivateEvent, otherwise gtk_window_focus_in_callback() will reset // g_sendActivateEvent to -1 @@ -2475,8 +2488,6 @@ bool wxWindowGTK::Create( wxWindow *parent, wxWindowGTK::~wxWindowGTK() { - wxASSERT_MSG( g_capturedWindows.IndexOf(this) == wxNOT_FOUND, wxT("trying to destroy window that didn't release focus") ); - if (g_focusWindow == this) g_focusWindow = NULL; @@ -3168,11 +3179,13 @@ void wxWindowGTK::SetFocus() if (m_wxwindow) { if (!GTK_WIDGET_HAS_FOCUS (m_wxwindow)) + { + // see comment in gtk_window_focus_out_callback() + gs_widgetLastFocus = m_wxwindow; gtk_widget_grab_focus (m_wxwindow); - return; + } } - - if (m_widget) + else if (m_widget) { if (GTK_WIDGET_CAN_FOCUS(m_widget) && !GTK_WIDGET_HAS_FOCUS (m_widget) ) { @@ -3754,17 +3767,19 @@ bool wxWindowGTK::SetFont( const wxFont &font ) return TRUE; } -static void wxDoCaptureMouse(wxWindowGTK *wnd) +void wxWindowGTK::CaptureMouse() { + wxCHECK_RET( m_widget != NULL, wxT("invalid window") ); + GdkWindow *window = (GdkWindow*) NULL; - if (wnd->m_wxwindow) - window = GTK_PIZZA(wnd->m_wxwindow)->bin_window; + if (m_wxwindow) + window = GTK_PIZZA(m_wxwindow)->bin_window; else - window = wnd->GetConnectWidget()->window; + window = GetConnectWidget()->window; wxCHECK_RET( window, _T("CaptureMouse() failed") ); - wxCursor* cursor = &wnd->GetCursor(); + wxCursor* cursor = & m_cursor; if (!cursor->Ok()) cursor = wxSTANDARD_CURSOR; @@ -3777,54 +3792,27 @@ static void wxDoCaptureMouse(wxWindowGTK *wnd) (GdkWindow *) NULL, cursor->GetCursor(), (guint32)GDK_CURRENT_TIME ); - g_captureWindow = wnd; + g_captureWindow = this; g_captureWindowHasMouse = TRUE; - wxLogDebug("captured %p", wnd); } -static void wxDoReleaseMouse(wxWindowGTK *wnd) +void wxWindowGTK::ReleaseMouse() { - wxLogDebug("trying to release %p", wnd); + wxCHECK_RET( m_widget != NULL, wxT("invalid window") ); + wxCHECK_RET( g_captureWindow, wxT("can't release mouse - not captured") ); GdkWindow *window = (GdkWindow*) NULL; - if (wnd->m_wxwindow) - window = GTK_PIZZA(wnd->m_wxwindow)->bin_window; + if (m_wxwindow) + window = GTK_PIZZA(m_wxwindow)->bin_window; else - window = wnd->GetConnectWidget()->window; + window = GetConnectWidget()->window; if (!window) return; gdk_pointer_ungrab ( (guint32)GDK_CURRENT_TIME ); g_captureWindow = (wxWindowGTK*) NULL; - wxLogDebug("released %p", wnd); -} - -void wxWindowGTK::CaptureMouse() -{ - wxCHECK_RET( m_widget != NULL, wxT("invalid window") ); - - wxLogDebug("CAPTURE %p", this); - wxWindowList::Node *last = g_capturedWindows.GetLast(); - if (last) - wxDoReleaseMouse(last->GetData()); - - g_capturedWindows.Append(this); - wxDoCaptureMouse(this); -} - -void wxWindowGTK::ReleaseMouse() -{ - wxCHECK_RET( m_widget != NULL, wxT("invalid window") ); - - wxLogDebug("RELEASE %p", this); - wxDoReleaseMouse(this); - g_capturedWindows.DeleteObject(this); - - wxWindowList::Node *last = g_capturedWindows.GetLast(); - if (last) - wxDoCaptureMouse(last->GetData()); } /* static */