]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/window.cpp
Fix item selection/focus drawing in generic wxListCtrl.
[wxWidgets.git] / src / gtk / window.cpp
index 8d8154f246c8e4bcafe748cb75297d931b96b4b5..e44324e21054be33d3432bc0bfed81034590949d 100644 (file)
 
    Cursors, too, have been a constant source of pleasure. The main difficulty
    is that a GdkWindow inherits a cursor if the programmer sets a new cursor
-   for the parent. To prevent this from doing too much harm, I use idle time
-   to set the cursor over and over again, starting from the toplevel windows
-   and ending with the youngest generation (speaking of parent and child windows).
+   for the parent. To prevent this from doing too much harm, SetCursor calls
+   GTKUpdateCursor, which will recursively re-set the cursors of all child windows.
    Also don't forget that cursors (like much else) are connected to GdkWindows,
    not GtkWidgets and that the "window" field of a GtkWidget might very well
    point to the GdkWindow of the parent widget (-> "window-less widget") and
    that the two obviously have very different meanings.
-
 */
 
 //-----------------------------------------------------------------------------
@@ -281,11 +279,11 @@ wxgtk_window_size_request_callback(GtkWidget * WXUNUSED(widget),
 
 extern "C" {
 static gboolean
-gtk_window_expose_callback( GtkWidget* widget,
+gtk_window_expose_callback( GtkWidget*,
                             GdkEventExpose *gdk_event,
                             wxWindow *win )
 {
-    if (gdk_event->window == widget->window)
+    if (gdk_event->window == win->GTKGetDrawingWindow())
     {
         win->GetUpdateRegion() = wxRegion( gdk_event->region );
         win->GtkSendPaintEvents();
@@ -304,7 +302,10 @@ extern "C" {
 static gboolean
 expose_event_border(GtkWidget* widget, GdkEventExpose* gdk_event, wxWindow* win)
 {
-    if (gdk_event->window != widget->window)
+    if (gdk_event->window != gtk_widget_get_parent_window(win->m_wxwindow))
+        return false;
+
+    if (!win->IsShown())
         return false;
 
     const GtkAllocation& alloc = win->m_wxwindow->allocation;
@@ -1831,7 +1832,7 @@ gtk_window_realized_callback(GtkWidget* widget, wxWindow* win)
     if (win->m_imData)
     {
         gtk_im_context_set_client_window( win->m_imData->context,
-                                          widget->window);
+            win->m_wxwindow ? win->GTKGetDrawingWindow() : widget->window);
     }
 
     // We cannot set colours and fonts before the widget
@@ -1847,6 +1848,8 @@ gtk_window_realized_callback(GtkWidget* widget, wxWindow* win)
     wxWindowCreateEvent event( win );
     event.SetEventObject( win );
     win->GTKProcessEvent( event );
+
+    win->GTKUpdateCursor(true, false);
 }
 
 //-----------------------------------------------------------------------------
@@ -1949,8 +1952,7 @@ void wxWindowGTK::AddChildGTK(wxWindowGTK* child)
 
     gtk_widget_set_size_request(
         child->m_widget, child->m_width, child->m_height);
-    gtk_fixed_put(
-        GTK_FIXED(m_wxwindow), child->m_widget, child->m_x, child->m_y);
+    pizza->put(child->m_widget, child->m_x, child->m_y);
 }
 
 //-----------------------------------------------------------------------------
@@ -2088,7 +2090,7 @@ bool wxWindowGTK::Create( wxWindow *parent,
 #endif
 
 
-    m_wxwindow = wxPizza::New(m_windowStyle,this);
+    m_wxwindow = wxPizza::New(m_windowStyle);
 #ifndef __WXUNIVERSAL__
     if (HasFlag(wxPizza::BORDER_STYLES))
     {
@@ -2211,6 +2213,12 @@ wxWindowGTK::~wxWindowGTK()
     // delete before the widgets to avoid a crash on solaris
     delete m_imData;
 
+    // avoid problem with GTK+ 2.18 where a frozen window causes the whole
+    // TLW to be frozen, and if the window is then destroyed, nothing ever
+    // gets painted again
+    if (IsFrozen())
+        DoThaw();
+
     if (m_widget)
     {
         // Note that gtk_widget_destroy() does not destroy the widget, it just
@@ -2560,38 +2568,6 @@ void wxWindowGTK::OnInternalIdle()
         m_needsStyleChange = false;
     }
 
-    wxCursor cursor = m_cursor;
-    if (g_globalCursor.Ok()) cursor = g_globalCursor;
-
-    if (cursor.Ok())
-    {
-        /* I now set the cursor anew in every OnInternalIdle call
-           as setting the cursor in a parent window also effects the
-           windows above so that checking for the current cursor is
-           not possible. */
-
-        if (m_wxwindow && (m_wxwindow != m_widget))
-        {
-            GdkWindow *window = m_wxwindow->window;
-            if (window)
-                gdk_window_set_cursor( window, cursor.GetCursor() );
-
-            if (!g_globalCursor.Ok())
-                cursor = *wxSTANDARD_CURSOR;
-
-            window = m_widget->window;
-            if ((window) && !(GTK_WIDGET_NO_WINDOW(m_widget)))
-                gdk_window_set_cursor( window, cursor.GetCursor() );
-
-        }
-        else if ( m_widget )
-        {
-            GdkWindow *window = m_widget->window;
-            if ( window && !GTK_WIDGET_NO_WINDOW(m_widget) )
-               gdk_window_set_cursor( window, cursor.GetCursor() );
-        }
-    }
-
     if (wxUpdateUIEvent::CanUpdate(this) && IsShownOnScreen())
         UpdateWindowUI(wxUPDATE_UI_FROMIDLE);
 }
@@ -3424,33 +3400,40 @@ bool wxWindowGTK::SetCursor( const wxCursor &cursor )
     return true;
 }
 
-void wxWindowGTK::GTKUpdateCursor()
+void wxWindowGTK::GTKUpdateCursor(bool update_self /*=true*/, bool recurse /*=true*/)
 {
-    wxCursor cursor(g_globalCursor.Ok() ? g_globalCursor : GetCursor());
-    if ( cursor.Ok() )
+    if (update_self)
     {
-        wxArrayGdkWindows windowsThis;
-        GdkWindow * const winThis = GTKGetWindow(windowsThis);
-        if ( winThis )
-        {
-            gdk_window_set_cursor(winThis, cursor.GetCursor());
-        }
-        else
+        wxCursor cursor(g_globalCursor.Ok() ? g_globalCursor : GetCursor());
+        if ( cursor.Ok() )
         {
-            const size_t count = windowsThis.size();
-            for ( size_t n = 0; n < count; n++ )
+            wxArrayGdkWindows windowsThis;
+            GdkWindow* window = GTKGetWindow(windowsThis);
+            if (window)
+                gdk_window_set_cursor( window, cursor.GetCursor() );
+            else
             {
-                GdkWindow *win = windowsThis[n];
-                if ( !win )
+                const size_t count = windowsThis.size();
+                for ( size_t n = 0; n < count; n++ )
                 {
-                    wxFAIL_MSG(wxT("NULL window returned by GTKGetWindow()?"));
-                    continue;
+                    GdkWindow *win = windowsThis[n];
+                    // It can be zero if the window has not been realized yet.
+                    if ( win )
+                    {
+                        gdk_window_set_cursor(win, cursor.GetCursor());
+                    }
                 }
-
-                gdk_window_set_cursor(win, cursor.GetCursor());
             }
         }
     }
+
+    if (recurse)
+    {
+        for (wxWindowList::iterator it = GetChildren().begin(); it != GetChildren().end(); ++it)
+        {
+            (*it)->GTKUpdateCursor( true );
+        }
+    }
 }
 
 void wxWindowGTK::WarpPointer( int x, int y )
@@ -3538,6 +3521,7 @@ void wxWindowGTK::Refresh(bool WXUNUSED(eraseBackground),
             if (!GTK_WIDGET_MAPPED (w))
                 return;
 
+        GdkWindow* window = GTKGetDrawingWindow();
         if (rect)
         {
             int x = rect->x;
@@ -3548,23 +3532,26 @@ void wxWindowGTK::Refresh(bool WXUNUSED(eraseBackground),
             r.y = rect->y;
             r.width = rect->width;
             r.height = rect->height;
-            gdk_window_invalidate_rect( m_wxwindow->window, &r, TRUE );
+            gdk_window_invalidate_rect(window, &r, true);
         }
         else
-            gdk_window_invalidate_rect( m_wxwindow->window, NULL, TRUE );
+            gdk_window_invalidate_rect(window, NULL, true);
     }
 }
 
 void wxWindowGTK::Update()
 {
-    if (m_widget && m_widget->window)
+    if (m_widget && GTK_WIDGET_MAPPED(m_widget))
     {
         GdkDisplay* display = gtk_widget_get_display(m_widget);
         // Flush everything out to the server, and wait for it to finish.
         // This ensures nothing will overwrite the drawing we are about to do.
         gdk_display_sync(display);
 
-        gdk_window_process_updates(m_widget->window, TRUE);
+        GdkWindow* window = GTKGetDrawingWindow();
+        if (window == NULL)
+            window = m_widget->window;
+        gdk_window_process_updates(window, true);
 
         // Flush again, but no need to wait for it to finish
         gdk_display_flush(display);
@@ -3669,7 +3656,7 @@ void wxWindowGTK::GtkSendPaintEvents()
                         rect.height = upd.GetHeight();
 
                         gtk_paint_flat_box( parent->m_widget->style,
-                                    m_wxwindow->window,
+                                    GTKGetDrawingWindow(),
                                     (GtkStateType)GTK_WIDGET_STATE(m_wxwindow),
                                     GTK_SHADOW_NONE,
                                     &rect,
@@ -3918,7 +3905,7 @@ bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style)
         GdkWindow *window;
         if ( m_wxwindow )
         {
-            window = m_wxwindow->window;
+            window = GTKGetDrawingWindow();
         }
         else
         {
@@ -3961,23 +3948,6 @@ bool wxWindowGTK::SetBackgroundStyle(wxBackgroundStyle style)
 
 #if wxUSE_MENUS_NATIVE
 
-static void SetInvokingWindow( wxMenu *menu, wxWindow* win )
-{
-    menu->SetInvokingWindow( win );
-
-    wxMenuItemList::compatibility_iterator node = menu->GetMenuItems().GetFirst();
-    while (node)
-    {
-        wxMenuItem *menuitem = node->GetData();
-        if (menuitem->IsSubMenu())
-        {
-            SetInvokingWindow( menuitem->GetSubMenu(), win );
-        }
-
-        node = node->GetNext();
-    }
-}
-
 extern "C" {
 static
 void wxPopupMenuPositionCallback( GtkMenu *menu,
@@ -4004,10 +3974,6 @@ bool wxWindowGTK::DoPopupMenu( wxMenu *menu, int x, int y )
 {
     wxCHECK_MSG( m_widget != NULL, false, wxT("invalid window") );
 
-    wxCHECK_MSG( menu != NULL, false, wxT("invalid popup-menu") );
-
-    SetInvokingWindow( menu, this );
-
     menu->UpdateUI();
 
     wxPoint pos;
@@ -4084,7 +4050,7 @@ bool wxWindowGTK::GTKIsOwnWindow(GdkWindow *window) const
 
 GdkWindow *wxWindowGTK::GTKGetWindow(wxArrayGdkWindows& WXUNUSED(windows)) const
 {
-    return m_wxwindow ? m_wxwindow->window : m_widget->window;
+    return m_wxwindow ? GTKGetDrawingWindow() : m_widget->window;
 }
 
 bool wxWindowGTK::SetFont( const wxFont &font )
@@ -4107,7 +4073,7 @@ void wxWindowGTK::DoCaptureMouse()
 
     GdkWindow *window = NULL;
     if (m_wxwindow)
-        window = m_wxwindow->window;
+        window = GTKGetDrawingWindow();
     else
         window = GetConnectWidget()->window;
 
@@ -4140,7 +4106,7 @@ void wxWindowGTK::DoReleaseMouse()
 
     GdkWindow *window = NULL;
     if (m_wxwindow)
-        window = m_wxwindow->window;
+        window = GTKGetDrawingWindow();
     else
         window = GetConnectWidget()->window;
 
@@ -4425,7 +4391,7 @@ extern "C"
 
 // this is called if we attempted to freeze unrealized widget when it finally
 // is realized (and so can be frozen):
-static void wx_frozen_widget_realize(GtkWidget* w, void* WXUNUSED(data))
+static void wx_frozen_widget_realize(GtkWidget* w, wxWindowGTK* win)
 {
     wxASSERT( w && !GTK_WIDGET_NO_WINDOW(w) );
     wxASSERT( GTK_WIDGET_REALIZED(w) );
@@ -4434,10 +4400,13 @@ static void wx_frozen_widget_realize(GtkWidget* w, void* WXUNUSED(data))
     (
         w,
         (void*)wx_frozen_widget_realize,
-        NULL
+        win
     );
 
-    gdk_window_freeze_updates(w->window);
+    GdkWindow* window = w->window;
+    if (w == win->m_wxwindow)
+        window = win->GTKGetDrawingWindow();
+    gdk_window_freeze_updates(window);
 }
 
 } // extern "C"
@@ -4456,12 +4425,15 @@ void wxWindowGTK::GTKFreezeWidget(GtkWidget *w)
             w,
             "realize",
             G_CALLBACK(wx_frozen_widget_realize),
-            NULL
+            this
         );
         return;
     }
 
-    gdk_window_freeze_updates(w->window);
+    GdkWindow* window = w->window;
+    if (w == m_wxwindow)
+        window = GTKGetDrawingWindow();
+    gdk_window_freeze_updates(window);
 }
 
 void wxWindowGTK::GTKThawWidget(GtkWidget *w)
@@ -4476,12 +4448,15 @@ void wxWindowGTK::GTKThawWidget(GtkWidget *w)
         (
             w,
             (void*)wx_frozen_widget_realize,
-            NULL
+            this
         );
         return;
     }
 
-    gdk_window_thaw_updates(w->window);
+    GdkWindow* window = w->window;
+    if (w == m_wxwindow)
+        window = GTKGetDrawingWindow();
+    gdk_window_thaw_updates(window);
 }
 
 void wxWindowGTK::DoFreeze()