]> git.saurik.com Git - wxWidgets.git/blobdiff - src/gtk/win_gtk.cpp
Applied patch from Ticket #9563. Use just the rectangle of the widget with the focus...
[wxWidgets.git] / src / gtk / win_gtk.cpp
index 12b5be929084db33f682d2fb087e7cd40b123014..30576aa367b60abcfb375be53d880ba7674e2b0f 100644 (file)
@@ -8,7 +8,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 #include "wx/defs.h"
-#include "wx/gtk/win_gtk.h"
+#include "wx/gtk/private/win_gtk.h"
 
 /*
 wxPizza is a custom GTK+ widget derived from GtkFixed.  A custom widget
@@ -64,29 +64,28 @@ static void size_allocate(GtkWidget* widget, GtkAllocation* alloc)
 
         if (pizza->m_is_scrollable)
         {
-            // backing window is inside border
+            // two windows, both same size
             gdk_window_move_resize(pizza->m_backing_window,
                 alloc->x + border_x, alloc->y + border_y, w, h);
+            if (is_resize)
+                gdk_window_resize(widget->window, w, h);
+        }
+        else if (pizza->m_backing_window)
+        {
+            // two windows, widget->window is smaller by border widths (need to
+            // move widget->window as well as resize because border can change)
+            gdk_window_move_resize(pizza->m_backing_window,
+                alloc->x, alloc->y, alloc->width, alloc->height);
+            gdk_window_move_resize(widget->window, border_x, border_y, w, h);
         }
         else
         {
-            // border window (or only window if
-            // no-scroll no-border) is full size
-            GdkWindow* window = pizza->m_backing_window;
-            if (window == NULL)
-                window = widget->window;
-            gdk_window_move_resize(
-                window, alloc->x, alloc->y, alloc->width, alloc->height);
+            // one window
+            gdk_window_move_resize(widget->window,
+                alloc->x, alloc->y, alloc->width, alloc->height);
         }
         if (is_resize && pizza->m_backing_window)
         {
-            // main window is inside border
-            if (pizza->m_is_scrollable)
-                gdk_window_resize(widget->window, w, h);
-            else
-                // need move as well as resize because border can change
-                gdk_window_move_resize(widget->window, border_x, border_y, w, h);
-
             // wxWidgets turns off redraw-on-allocate by default,
             // so border area needs to be invalidated
             if (border_x > 1 || border_y > 1)
@@ -166,6 +165,11 @@ static void realize(GtkWidget* widget)
         else
             gdk_window_reparent(widget->window, pizza->m_backing_window, border_x, border_y);
         gdk_window_resize(widget->window, w, h);
+
+        // Parts of m_backing_window which are supposed to be obscured may be
+        // exposed temporarily while resizing. Setting the backing pixmap to
+        // None prevents those areas from being briefly painted black.
+        gdk_window_set_back_pixmap(pizza->m_backing_window, NULL, false);
     }
 }
 
@@ -298,8 +302,8 @@ GtkWidget* wxPizza::New(long windowStyle)
     pizza->m_scroll_x = 0;
     pizza->m_scroll_y = 0;
     pizza->m_is_scrollable = (windowStyle & (wxHSCROLL | wxVSCROLL)) != 0;
-    pizza->m_border_style =
-        int(windowStyle & (wxBORDER_SIMPLE | wxBORDER_RAISED | wxBORDER_SUNKEN));
+    // mask off border styles not useable with wxPizza
+    pizza->m_border_style = int(windowStyle & BORDER_STYLES);
     gtk_fixed_set_has_window(GTK_FIXED(widget), true);
     gtk_widget_add_events(widget,
         GDK_EXPOSURE_MASK |
@@ -317,7 +321,6 @@ GtkWidget* wxPizza::New(long windowStyle)
         GDK_ENTER_NOTIFY_MASK |
         GDK_LEAVE_NOTIFY_MASK |
         GDK_FOCUS_CHANGE_MASK);
-    gtk_container_set_resize_mode(GTK_CONTAINER(widget), GTK_RESIZE_QUEUE);
     return widget;
 }
 
@@ -338,6 +341,30 @@ void wxPizza::move(GtkWidget* widget, int x, int y)
     }
 }
 
+struct AdjustData {
+    GdkWindow* window;
+    int dx, dy;
+};
+
+// Adjust allocations for all widgets using the GdkWindow which was just scrolled
+extern "C" {
+static void scroll_adjust(GtkWidget* widget, void* data)
+{
+    const AdjustData* p = static_cast<AdjustData*>(data);
+    if (widget->window == p->window)
+    {
+        widget->allocation.x += p->dx;
+        widget->allocation.y += p->dy;
+        // GtkFrame requires a queue_resize, otherwise parts of
+        // the frame newly exposed by the scroll are not drawn.
+        // To be safe, do it for all widgets.
+        gtk_widget_queue_resize_no_redraw(widget);
+        if (GTK_IS_CONTAINER(widget))
+            gtk_container_forall(GTK_CONTAINER(widget), scroll_adjust, data);
+    }
+}
+}
+
 void wxPizza::scroll(int dx, int dy)
 {
     GtkWidget* widget = GTK_WIDGET(this);
@@ -346,16 +373,17 @@ void wxPizza::scroll(int dx, int dy)
     m_scroll_x -= dx;
     m_scroll_y -= dy;
     if (widget->window)
-        gdk_window_scroll(widget->window, dx, dy);
-    const GList* list = m_fixed.children;
-    if (list)
     {
-        const GtkFixedChild* child = static_cast<GtkFixedChild*>(list->data);
-        // queueing a resize on any child will update them all
-        gtk_widget_queue_resize(child->widget);
+        gdk_window_scroll(widget->window, dx, dy);
+        // Adjust child allocations. Doing a queue_resize on the children is not
+        // enough, sometimes they redraw in the wrong place during fast scrolling.
+        AdjustData data = { widget->window, dx, dy };
+        gtk_container_forall(GTK_CONTAINER(widget), scroll_adjust, &data);
     }
 }
 
+extern GtkWidget *GetEntryWidget();
+
 void wxPizza::get_border_widths(int& x, int& y)
 {
     x = y = 0;
@@ -363,13 +391,11 @@ void wxPizza::get_border_widths(int& x, int& y)
         x = y = 1;
     else if (m_border_style)
     {
-        GtkWidget* widget = GTK_WIDGET(this);
-        if (widget->style)
+        GtkWidget *entry_widget = GetEntryWidget();
+        if (entry_widget->style)
         {
-            x = widget->style->xthickness;
-            y = widget->style->ythickness;
-            x = 1;
-            y = 1;
+            x = entry_widget->style->xthickness;
+            y = entry_widget->style->ythickness;
         }
     }
 }