Migrating to gtkmm3 (Gdk::Window::scroll, drawing outside draw signal)

Hello. I have a viewer of raster data written on gtkmm2. Data is arranged in tiles which are produced slowly in a separate thread, cached, and put on Gtk::DrawingArea on expose_event handler. I am trying to switch it to gtkmm3 (3.24.1) (idea of using Cairo surfaces everywhere looks very good for me!). There are two questions:

  1. Previously, Gdk::Window::scroll method produced expose_event with only changed area (two small rectangles for small shifts). Now it invalidates the whole window. I tried also Gdk::Window::move_region with same effect. (I am getting the rectangles using Cairo::Context::copy_clip_rectangle_list. If I cover my window with another one and open a small portion, I get correct rectangles which have to be redrawn ). What is a problem with Gdk::Window::scroll()?

  2. In my viewer I also draw some marks attached to the cursor which are updated on motion_notify_event, button_press_event, etc. Previously it was done in a natural way: I was just continue drawing on the window. I used XOR operator do draw on top of existing data and then erase marks. How can I do it with gtk3? I tried to use Gdk::Window::begin_draw_frame, obtain Gdk context, extract Cairo context from it, draw, and then do end_draw_frame. This does not work: the Cairo context does not contain old data; window is not updated after end_draw_frame, it waits until some areas will be invalidated and draw signal emitted. What is correct way to do this kind of drawing? How can I get access to the old buffer (where to get cairo context?) and how can I redraw the modified buffer on the screen without firing draw signal?

There is nothing natural about it: you were just relying on side effects of the X11 windowing system and implementation details of GTK. Even in GTK2 you should always ever only draw inside the GtkWidget::expose-event and never outside of it.

You can only draw the contents of a widget in the GtkWidget::draw signal handler.

There is no “old buffer”: once you finish drawing, the contents are submitted to the display server, and are then released.

You can draw on a separate buffer any time you want by using a Cairo image surface (see: gdk_window_create_similar_image_surface()) you keep around and use as a source in the Cairo context provided to you in the draw signal handler.

1 Like

Thanks for the answer!

I also found explanation why scroll() invalidates the whole window (“Scroll” section in The GTK+ Drawing Model text, https://developer.gnome.org/gtk3/stable/chap-drawing-model.html ). As I understand, it is done to support semi-transparent windows.

Because I already have some buffering (tiles with data), I just implemented everything in the most straightforward way: all drawing functions are connected to the draw signal, and if something needs to be redrawn the window (or its region) is invalidated.

Looks not so efficient as before (maybe I’ll try to measure it somehow), but code now is shorter and simpler.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.