Gtk will temporarily unset my backing pixmap for a GtkDrawingArea when it is packed into a GtkScrolledWindow, is this a necessary behavior?

I have posted a message about using GdkDrawingArea with backing pixmap to gtk-app-devel-list mailing list yesterday.

After tracing into gtk and gdk for several hours, I think I find where the problem is.
However, I don't know whether this problem is an undocumented feature or a bug in gtk.

My attempt is to redraw parts of the contents of the GtkDrawingArea without using an expose_event signal handler.
That is to say, I want the X Window System to recover the old contents of the GtkDrawingArea by using the backing pixmap.
Because I want to acquire the max preformance without causing a round trip between the X Window Server and my own program.

Following is my original question:


I have some problems about the usage of GtkDrawingArea with backing
pixmap when I use it in a GtkScrolledWindow.

You can copy the following code segment into a c++ file (ex: ddd.cpp),
and compile with

g++ 'pkg-config gtkmm-2.0 --cflags --libs' ddd.cpp

and see what will happen.

I have no idea whether this result is the misuse of GtkDrawingArea or a
bug in gtk.

Althought I've implemented the following code segment by using gtkmm
(i.e. C++), but I think it is eqivalent to using gtk (i.e. C).

The container hierarchy is:

GtkWindow -> GtkScrolledWindow -> GtkTable -> GtkDrawingArea

And I use a backing pixmap with GtkDrawingArea to avoid the flicker,
thus I disable the default double buffered behavior with the

When I start the program and hit a keystoke, the DrawingArea will be
filled with red. This is OK.

However, when I try to resize the window by using the mouse, X window
not to update the drawing area with its backing pixmap.

Is this  a bug in gtk or the misuse of GtkDrawingArea with backing


And I find the problem is:

When I click the scrollbar (vertical or horizontal) in the GtkScrolledWindow,
the GtkAdjustment will send a change signal to trigger many side effects.

These side effects include moving the GtkViewport and invalidating the previous obscure portion in
GtkDrawingArea to trigger the X Window Server to send an expose event to the GtkDrawingArea.

But the problem is,

before the above side effect occurs, Gtk will first unset the background pixmap of the GtkDrawingArea
by using XSetWindowBackgroundPixmap(..., ..., NONE). Following are the calling sequences:

... -> _gdk_window_move_resize_child() -> gdk_window_clip_changed() -> gdk_window_tmp_unset_bg() -> XSetWindowBackgroundPixmap()

After that, gdk_window_clip_changed() will call gdk_window_invalidate_region() to trigger the X Window
to send an expose event to the GtkDrawingArea.

However, because of the absence of the background pixmap for the GtkDrawingArea,
the X Window Server will not redraw the background pixmap for the GtkDrawingArea.

After that, _gdk_window_move_resize_child() will call gdk_window_postmove() to reset the background pixmap
for the GtkDrawingArea.

Thus the previous obscure portions of the GtkDrawingArea will not be covered automatically by the backing pixmap I offered,
and the old contents of that part of the GtkDrawingArea will still be showed on the screen.

This is not what most programmers want in most situation.

The method to solve this problem is setting up an expose_event signal handler for the GtkDrawingArea,
and calls some clear_area function or draw_pixmap function to manually recover the backing pixmap for the GtkDrawingArea.

Thus my question is is this behavour (gdk_window_tmp_unset_bg() & gdk_window_tmp_reset_bg()) necessary in gtk & gdk?
And can I use a backing pixmap for the GtkDrawingArea when it is packed into a GtkScrolledWindow or I must to set up an expose_event
signal handler and unset the backing pixmap of the GtkDrawingArea.

Thanks for your help.


#include <gtkmm.h>

struct MainWindow : public Gtk::Window
  Gtk::ScrolledWindow mScrolledWindow;
  Gtk::DrawingArea mDrawingArea;
  Gtk::Table mTable;
  Glib::RefPtr<Gdk::Pixbuf> mpPixbuf;
  Glib::RefPtr<Gdk::Pixmap> mpPixmap;
    mTable.attach(mDrawingArea, 0, 1, 0, 1, Gtk::SHRINK, Gtk::SHRINK, 0,
  OnKeyPressEvent(GdkEventKey *event)
    mDrawingArea.set_size_request(400, 500);
  OnDrawingAreaSizeAllocate(GtkAllocation *allocate)
    if (true == mDrawingArea.is_realized())
      int width = allocate->width;
      int height = allocate->height;
      if (false == mpPixmap.is_null())
      if (false == mpPixbuf.is_null())
      mpPixbuf = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB,
                                     false, // has_alpha
                                     8, // bits_per_sample
      mpPixmap = Gdk::Pixmap::create(mDrawingArea.get_window(),
                                     height, -1);
      mpPixmap->draw_pixbuf(Glib::RefPtr<Gdk::GC>(), // an empty GC
                            0, 0, // src
                            0, 0, // dest
                            0, 0 // dither offset
                                                 false //

main(int argc, char *argv[])
  Gtk::Main kit(argc, argv);
  MainWindow main_window;
  return 0;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]