RE: Re: Re: Getting a Cairo context





24.03.2015, 18:59:07 пользователь Emmanuele Bassi (ebassi gmail com) написал:

    1. create the widget instance
    2. realize it
    3. create a similar Cairo surface from the GdkWindow of the widget
    4. store Cairo surface on the widget instance; you can use a
subclass or g_object_set_data(), with a preference for the former
    5. connect a callback to/override the class closure of the ::draw signal
        a. in the draw signal handler, you take the surface and use it a
source to draw on the cairo_t given to you; you can use a boolean flag
to know whether or not the contents of the surface are okay to use
    6. fire off a thread, and pass the pointer to widget to the thread function
    7. inside the thread function, draw on the surface
    8. at the end of the thread, schedule a redraw in the main thread
        a. use gdk_threads_add_idle() with a callback and pass the widget
pointer as the data
        b. from within the callback, set the boolean flag that tells the
::draw callback to use the surface as a source, and call
gtk_widget_queue_draw()

It's safe to draw on Cairo surfaces from different threads, assuming
only a thread at a time does it; it's not safe to use GTK API from
different threads, though. That's why you can create a surface from
the main thread, and draw on it in a separate thread — as long as you
ensure that all the operations involving GTK happen on the main
thread.

Ok. I am going to try it all out but I have a few questions:

1) do you know any example code that does what you are describing?
2) there is something I do not understand in (5). Do you mean something like this:

plotwindow_surface = gdk_window_create_similar_surface(gtk_widget_get_window(gcu.plotwindow),
                                                         CAIRO_CONTENT_COLOR,_DISPLAY_X,_DISPLAY_Y/2);
 g_object_set_data(G_OBJECT(gcu.plotwindow),"plotwindow",(gpointer)plotwindow_surface);
 g_signal_connect( G_OBJECT( gcu.plotwindow ), "draw", G_CALLBACK( ev_plotwindow_draw ), NULL );

in the ev_plotwindow_draw() I extract data (i.e. the surface) from gcu.plotwindow and use cairo drawing 
functions to draw in it. This is going to be my setup draw (axes, tickmarks, etc). Then because I use 
g_timeout_add_seconds() to fire up the thread, I'd have to change it to something like that

g_timeout_add_seconds(MODBUS_WAKEUP_SECS,update_from_modbus,gcu.plotwindow)

But the call g_signal_connect to a "draw" will create another surface. Will it not? And would need to pass a widget in 
g_timeout_seconds() if gcu.plotwindow is global in my code? I could get rid of this "gobality" though.

-- Sergei



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