私自身が解決策を見つけました。
ここにある:
using Cairo;
using Gtk;
public class Canvas : Gtk.DrawingArea{
public Canvas(MainWindow mw){
stdout.printf("-> Canvas\n");
main_window = mw;
is_pressed_down = false;
add_events(Gdk.EventMask.BUTTON_PRESS_MASK |
Gdk.EventMask.BUTTON_RELEASE_MASK |
Gdk.EventMask.POINTER_MOTION_MASK);
set_size_request(400, 300);
}
~Canvas(){
stdout.printf("<- Canvas\n");
}
public override void realize(){
base.realize();
stdout.printf("realize\n");
}
protected override bool configure_event(Gdk.EventConfigure event){
int x, y;
window.get_size(out x, out y);
offscreen_surface = new Cairo.ImageSurface(Cairo.Format.RGB24, x, y);
gc = new Cairo.Context(offscreen_surface);
gc.set_antialias(Antialias.NONE);
gc.set_line_width(1);
gc.set_source_rgb(1, 1, 1);
gc.paint(); // it will make trouble if user resize the window
string msg = "x: " + x.to_string() + ", y: " + y.to_string();
main_window.set_statusbar(msg);
return true;
}
protected override bool expose_event(Gdk.EventExpose event){
var tgc = Gdk.cairo_create(window); //!!!
tgc.set_source_rgb(1, 1, 1);
tgc.paint();
tgc.set_source_surface(offscreen_surface, 0, 0);
tgc.paint();
return true;
}
public override bool motion_notify_event(Gdk.EventMotion event)
{
string msg = "x: " + event.x.to_string() + ", y: " + event.y.to_string();
main_window.set_statusbar(msg);
if(is_pressed_down){
//gc.set_source_rgb(1, 1, 1);
//gc.paint();
gc.set_source_rgb(1, 0.5, 0);
//gc.move_to(event.x, event.x);
gc.arc(event.x, event.y, 1, 0, 360);
gc.stroke();
weak Gdk.Region region = this.window.get_clip_region();
this.window.invalidate_region(region, true);
this.window.process_updates(true);
}
return true;
}
public override bool button_press_event(Gdk.EventButton event)
{
stdout.printf("Canvas.button_press_event\n");
is_pressed_down = true;
return true;
}
public override bool button_release_event(Gdk.EventButton event)
{
stdout.printf("Canvas.button_release_event\n");
is_pressed_down = false;
return true;
}
public Cairo.Context get_context(){
return gc;
}
private Cairo.Context gc;
private weak MainWindow main_window;
private Cairo.ImageSurface offscreen_surface;
private bool is_pressed_down;
}