]> git.saurik.com Git - wxWidgets.git/commitdiff
added workaround for GTK+ focus_out bug (and removed Vaclav's mouse capture stack...
authorVadim Zeitlin <vadim@wxwidgets.org>
Mon, 24 Sep 2001 18:46:13 +0000 (18:46 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Mon, 24 Sep 2001 18:46:13 +0000 (18:46 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@11691 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

src/gtk/window.cpp
src/gtk1/window.cpp

index 254545aa5bd8088fd6fa12ca17a8d3f5c558daa1..ca9543b11ea632f4c3e7300958ff73c8a13e4f28 100644 (file)
@@ -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 */
index 254545aa5bd8088fd6fa12ca17a8d3f5c558daa1..ca9543b11ea632f4c3e7300958ff73c8a13e4f28 100644 (file)
@@ -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 */