title: Simple paint application: Referencing Cairo Context on mouse movement
body: <p>I am attempting to use Cairo with GTK# to create a simple painting application. The feature that is giving me trouble is the one of drawing a line between two points. After clicking on the drawing area, a line should appear, and follow the cursor until the mouse button is released, at which point the drawing area is updated and another line can be drawn. It should be a familiar feature from programs such as MS Paint.</p>
  
  <p>Now, <a href="http://www.mono-project.com/Mono.Cairo" rel="nofollow noreferrer">I am told</a> the way to perform such updates in Cairo is to use the Cairo Context's <code>.Save();</code> and <code>.Restore()</code> methods to handle the states. Problem is that I can't find a way to continue to reference the same Context in an event handler other than the one that created it, so all my attempts to restore the state after drawing a line have been less than fruitful.</p>
  
  <p>In the minimum (but still kind of humongous, sorry) working code example below, the non-solution is to create a new Context on each Draw. This gives results as below:
   <img src="https://i.stack.imgur.com/AvvJ0.png" alt="Current state of the Painting application"></p>
  
  <p>The pen (on the left) behaves all right. The line obviously doesn't, as there's no way to restore to the previous state after moving the mouse, so they all remain on the screen to make the pictured fan-pattern.</p>
  
  <pre><code>using Gtk;
  using Cairo;
  using System;
  
  public class Paint : Gtk.Window
  {
  
      bool isDrawing = false;
      bool isDrawingLine = false;
      bool isDrawingWithPen = false;
  
      double Point_l1x;
      double Point_l1y;
      double Point_l2x;
      double Point_l2y;
  
      double Point_p1x;
      double Point_p1y;
  
      Button line;
      Button pen;
  
      static DrawingArea area;
      Cairo.Context ctx;
  
      void OnDrawingAreaExposed (object source, ExposeEventArgs args)
      {   
          DrawingArea area = (DrawingArea) source;
          ctx = Gdk.CairoHelper.Create (area.GdkWindow);
  
          ((IDisposable) ctx.Target).Dispose();
          ((IDisposable) ctx).Dispose ();
      }
  
      public void DrawImage ()
      {
          //Shouldn't this be referencing an external context?
          using (Cairo.Context ctx = Gdk.CairoHelper.Create (area.GdkWindow))
          {
              ctx.Color = new Cairo.Color (0, 0, 0);
  
              if(isDrawingLine)
              {
                  ctx.MoveTo (new PointD (Point_l1x, Point_l1y));
                  ctx.LineTo (new PointD (Point_l2x, Point_l2y));
                  ctx.Stroke ();
              }
  
              else if(isDrawingWithPen)
              {
                  ctx.Rectangle(Point_p1x, Point_p1y, 1, 1);
                  ctx.Stroke();
              }
          }
      }
  
      public void LineClicked(object sender, EventArgs args)
      {
          isDrawingLine = true;
          isDrawingWithPen = false;
      }
  
      public void PenClicked(object sender, EventArgs args)
      {
          isDrawingLine = false;
          isDrawingWithPen = true;
      }
  
      void OnMousePress (object source, ButtonPressEventArgs args)
      {
          isDrawing = true;
          if (isDrawingLine)
          {
              Point_l1x = args.Event.X;
              Point_l1y = args.Event.Y;
          }
          else if (isDrawingWithPen)
          {
              Point_p1x = args.Event.X;
              Point_p1y = args.Event.Y;
          }
      }
  
      void OnMouseRelease (object source, ButtonReleaseEventArgs args)
      {
          isDrawing = false;
          DrawImage ();
      }
  
      void OnMouseMotion (object source, MotionNotifyEventArgs args)
      {
          if (!isDrawing)
          {
              return;
          }
  
          if (isDrawingLine)
          {
              Point_l2x = args.Event.X;
              Point_l2y = args.Event.Y;
          }
          else if (isDrawingWithPen)
          {
              Point_p1x = args.Event.X;
              Point_p1y = args.Event.Y;
          }
          DrawImage();
      }
  
      public Paint () : base("Painting application")
      {   
          area = new DrawingArea ();
          area.ExposeEvent += OnDrawingAreaExposed;
  
          area.AddEvents (
                  (int)Gdk.EventMask.PointerMotionMask
                  | (int)Gdk.EventMask.ButtonPressMask
                  | (int)Gdk.EventMask.ButtonReleaseMask);
  
          area.ButtonPressEvent += OnMousePress;
          area.ButtonReleaseEvent += OnMouseRelease;
          area.MotionNotifyEvent += OnMouseMotion;
  
          DeleteEvent += delegate { Application.Quit(); };
  
          SetDefaultSize(500, 500);
          SetPosition(WindowPosition.Center);
  
          VBox vbox = new VBox();
          vbox.Add(area);
          HBox hbox = new HBox();
  
          line = new Button("Line");
          pen = new Button("Pen");
          hbox.Add(line);
          hbox.Add(pen);
  
          Alignment halign = new Alignment(1, 0, 0, 0);
          halign.Add(hbox);
  
          vbox.Add(hbox);
          vbox.PackStart(halign, false, false, 3);
  
          line.Clicked += LineClicked;
          pen.Clicked += PenClicked;
  
          Add(vbox);
          ShowAll();
      }
  
      public static void Main()
      {
          Application.Init();
          new Paint();
          Application.Run();
      }
  }
  </code></pre>
  
  <p>If I modify the DrawImage method to reference the Context defined in OnDrawingAreaExposed, the whole thing crashes, offering a stack trace that I can't really understand:</p>
  
  <pre><code>Stacktrace:
  
  at (wrapper managed-to-native) Cairo.NativeMethods.cairo_set_source_rgba (intptr,double,double,double,double) &lt;0xffffffff&gt;
  at Cairo.Context.set_Color (Cairo.Color) &lt;0x0002b&gt;
  at Paint.DrawImage () &lt;0x000a3&gt;
  at Paint.OnMouseMotion (object,Gtk.MotionNotifyEventArgs) &lt;0x001af&gt;
  at (wrapper runtime-invoke) &lt;Module&gt;.runtime_invoke_void__this___object_object (object,intptr,intptr,intptr) &lt;0xffffffff&gt;
  at (wrapper managed-to-native) System.Reflection.MonoMethod.InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&amp;) &lt;0xffffffff&gt;
  at System.Reflection.MonoMethod.Invoke (object,System.Reflection.BindingFlags,System.Reflection.Binder,object[],System.Globalization.CultureInfo) &lt;0x0018b&gt;
  at System.Reflection.MethodBase.Invoke (object,object[]) &lt;0x0002a&gt;
  at System.Delegate.DynamicInvokeImpl (object[]) &lt;0x001a3&gt;
  at System.MulticastDelegate.DynamicInvokeImpl (object[]) &lt;0x0003b&gt;
  at System.Delegate.DynamicInvoke (object[]) &lt;0x00018&gt;
  at GLib.Signal.ClosureInvokedCB (object,GLib.ClosureInvokedArgs) &lt;0x0014f&gt;
  at GLib.SignalClosure.Invoke (GLib.ClosureInvokedArgs) &lt;0x0002f&gt;
  at GLib.SignalClosure.MarshalCallback (intptr,intptr,uint,intptr,intptr,intptr) &lt;0x0050b&gt;
  at (wrapper native-to-managed) GLib.SignalClosure.MarshalCallback (intptr,intptr,uint,intptr,intptr,intptr) &lt;0xffffffff&gt;
  at (wrapper managed-to-native) Gtk.Application.gtk_main () &lt;0xffffffff&gt;
  at Gtk.Application.Run () &lt;0x0000b&gt;
  at Paint.Main () &lt;0x00027&gt;
  at (wrapper runtime-invoke) object.runtime_invoke_void (object,intptr,intptr,intptr) &lt;0xffffffff&gt;
  
  Native stacktrace:
  
          mono() [0x4961e9]
          mono() [0x4e6d1f]
          mono() [0x41dcb7]
          /lib/x86_64-linux-gnu/libpthread.so.0(+0xfcb0) [0x7f3fd2f07cb0]
          /usr/lib/x86_64-linux-gnu/libcairo.so.2(cairo_set_source_rgba+0x1) [0x7f3fcaaccc71]
          [0x41a28dbd]
  </code></pre>
  
  <p>Am I on the right track here, trying to reference that Context? Do Cairo Contexts even work that way? If not, how can I make the line continuously re-render?</p>