///////////////////////////////////////////////////////////////////////////////
#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
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)
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);
}
}
}
}
+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);
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);
}
}