# Patch created by root
# Date: Sun May 30 11:59:25 MDT 2004
# Repository: pnetlib
# Comments:
# SWF BeginInvoke and EndInvoke implentation on X (only). Win32 is still coming.
#### End of Preamble ####

#### Patch data follows ####
Index: System.Drawing/Toolkit/IToolkitEventSink.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/System.Drawing/Toolkit/IToolkitEventSink.cs,v
retrieving revision 1.9
diff -c -r1.9 IToolkitEventSink.cs
*** System.Drawing/Toolkit/IToolkitEventSink.cs	23 Dec 2003 22:07:07 -0000	1.9
--- System.Drawing/Toolkit/IToolkitEventSink.cs	30 May 2004 17:59:24 -0000
***************
*** 109,114 ****
--- 109,120 ----
  	// The "child" parameter is null if a window has been deactivated.
  	void ToolkitMdiActivate(IToolkitWindow child);
  
+ 	// Event that is emitted when a custom messages comes in. This
+ 	// custom message is sent by another thread, telling the controlling
+ 	// thread to Invoke a delegate (which is eventually pointed to by this
+ 	// IntPtr)
+ 	void ToolkitBeginInvoke(IntPtr i_gch);
+ 
  }; // interface IToolkitEventSink
  
  }; // namespace System.Drawing.Toolkit
Index: System.Drawing/Toolkit/IToolkitWindow.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/System.Drawing/Toolkit/IToolkitWindow.cs,v
retrieving revision 1.12
diff -c -r1.12 IToolkitWindow.cs
*** System.Drawing/Toolkit/IToolkitWindow.cs	23 Dec 2003 22:07:07 -0000	1.12
--- System.Drawing/Toolkit/IToolkitWindow.cs	30 May 2004 17:59:25 -0000
***************
*** 100,105 ****
--- 100,107 ----
  	// the cursor to be the same as the parent window's.
  	void SetCursor(ToolkitCursorType cursorType, Frame frame);
  
+ 	void SendBeginInvoke(IntPtr i_gch);
+ 
  }; // interface IToolkitWindow
  
  }; // namespace System.Drawing.Toolkit
Index: System.Drawing.Win32/DrawingControlWindow.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/System.Drawing.Win32/DrawingControlWindow.cs,v
retrieving revision 1.8
diff -c -r1.8 DrawingControlWindow.cs
*** System.Drawing.Win32/DrawingControlWindow.cs	23 Dec 2003 22:07:07 -0000	1.8
--- System.Drawing.Win32/DrawingControlWindow.cs	30 May 2004 17:59:27 -0000
***************
*** 117,122 ****
--- 117,127 ----
  		}
  	}
  
+ 	private void IToolkitWindow.SendBeginInvoke(IntPtr i_gch)
+ 	{
+ 		//djl
+ 	}
+ 
  
  }; // class DrawingControlWindow
  
Index: System.Drawing.Win32/DrawingPopupWindow.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/System.Drawing.Win32/DrawingPopupWindow.cs,v
retrieving revision 1.9
diff -c -r1.9 DrawingPopupWindow.cs
*** System.Drawing.Win32/DrawingPopupWindow.cs	15 Jan 2004 22:44:24 -0000	1.9
--- System.Drawing.Win32/DrawingPopupWindow.cs	30 May 2004 17:59:28 -0000
***************
*** 97,101 ****
--- 97,106 ----
  		base.MouseMove (msg, wParam, lParam);
  	}
  
+ 	private void IToolkitWindow.SendBeginInvoke(IntPtr i_gch)
+ 	{
+ 		//djl
+ 	}
+ 
  }
  }
Index: System.Drawing.Win32/DrawingTopLevelWindow.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/System.Drawing.Win32/DrawingTopLevelWindow.cs,v
retrieving revision 1.11
diff -c -r1.11 DrawingTopLevelWindow.cs
*** System.Drawing.Win32/DrawingTopLevelWindow.cs	26 Jan 2004 20:31:07 -0000	1.11
--- System.Drawing.Win32/DrawingTopLevelWindow.cs	30 May 2004 17:59:30 -0000
***************
*** 324,329 ****
--- 324,335 ----
  		sink.ToolkitExternalResize( dimensions.Width, dimensions.Height );
  		//Console.WriteLine( "DrawingTopLevelWindow.CreateWindow, "+sink+", [" + dimensions.Size + "]" );
  	}
+ 
+ 	private void IToolkitWindow.SendBeginInvoke(IntPtr i_gch)
+ 	{
+ 		//djl
+ 	}
+ 
  }; // class DrawingTopLevelWindow
  
  }; // namespace System.Drawing.Toolkit
Index: System.Drawing.Win32/DrawingWindow.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/System.Drawing.Win32/DrawingWindow.cs,v
retrieving revision 1.30
diff -c -r1.30 DrawingWindow.cs
*** System.Drawing.Win32/DrawingWindow.cs	25 Jan 2004 19:51:48 -0000	1.30
--- System.Drawing.Win32/DrawingWindow.cs	30 May 2004 17:59:31 -0000
***************
*** 909,913 ****
--- 909,918 ----
  		return false;
  	}
  
+ 	private void IToolkitWindow.SendBeginInvoke(IntPtr i_gch)
+ 	{
+ 		//djl
+ 	}
+ 
  }
  }
Index: System.Drawing.Xsharp/DrawingMdiClient.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/System.Drawing.Xsharp/DrawingMdiClient.cs,v
retrieving revision 1.4
diff -c -r1.4 DrawingMdiClient.cs
*** System.Drawing.Xsharp/DrawingMdiClient.cs	27 Apr 2004 10:59:46 -0000	1.4
--- System.Drawing.Xsharp/DrawingMdiClient.cs	30 May 2004 17:59:32 -0000
***************
*** 429,434 ****
--- 429,439 ----
  				}
  			}
  	
+ 	private void IToolkitWindow.SendBeginInvoke(IntPtr i_gch)
+ 			{
+ 				base.SendBeginInvoke(i_gch);
+ 			}
+ 
  }; // class DrawingMdiClient
  
  }; // namespace System.Drawing.Toolkit
Index: System.Drawing.Xsharp/DrawingPopupWindow.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/System.Drawing.Xsharp/DrawingPopupWindow.cs,v
retrieving revision 1.10
diff -c -r1.10 DrawingPopupWindow.cs
*** System.Drawing.Xsharp/DrawingPopupWindow.cs	27 Apr 2004 10:59:46 -0000	1.10
--- System.Drawing.Xsharp/DrawingPopupWindow.cs	30 May 2004 17:59:44 -0000
***************
*** 389,394 ****
--- 389,399 ----
  			}
  
  
+ 	private void IToolkitWindow.SendBeginInvoke(IntPtr i_gch)
+ 		{
+ 			base.SendBeginInvoke(i_gch);
+ 		}
+ 
  }; // class DrawingPopupWindow
  
  }; // namespace System.Drawing.Toolkit
Index: System.Drawing.Xsharp/DrawingToolkit.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/System.Drawing.Xsharp/DrawingToolkit.cs,v
retrieving revision 1.30
diff -c -r1.30 DrawingToolkit.cs
*** System.Drawing.Xsharp/DrawingToolkit.cs	23 Jan 2004 00:25:52 -0000	1.30
--- System.Drawing.Xsharp/DrawingToolkit.cs	30 May 2004 17:59:46 -0000
***************
*** 24,29 ****
--- 24,30 ----
  using System;
  using System.Globalization;
  using System.Collections;
+ using System.Diagnostics;
  using System.Drawing;
  using System.Drawing.Drawing2D;
  using System.Drawing.Toolkit;
Index: System.Drawing.Xsharp/DrawingTopLevelWindow.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/System.Drawing.Xsharp/DrawingTopLevelWindow.cs,v
retrieving revision 1.25
diff -c -r1.25 DrawingTopLevelWindow.cs
*** System.Drawing.Xsharp/DrawingTopLevelWindow.cs	27 Apr 2004 10:59:46 -0000	1.25
--- System.Drawing.Xsharp/DrawingTopLevelWindow.cs	30 May 2004 17:59:48 -0000
***************
*** 408,413 ****
--- 408,419 ----
  				OtherHints = otherHints;
  			}
  
+ 	protected override void OnBeginInvokeMessage(IntPtr i_gch)
+ 			{
+ 				if( sink != null )
+ 					sink.ToolkitBeginInvoke(i_gch);
+ 			}
+ 
  	// Override the button press event from Xsharp.
  	protected override void OnButtonPress(int x, int y, ButtonName button,
  									      ModifierMask modifiers)
***************
*** 646,651 ****
--- 652,662 ----
  	protected override void OnMaximizedStateChanged(bool value)
  			{
  				WindowStateChanged();
+ 			}
+ 
+ 			private void IToolkitWindow.SendBeginInvoke(IntPtr i_gch)
+ 			{
+ 				base.SendBeginInvoke(i_gch);
  			}
  
  }; // class DrawingTopLevelWindow
Index: System.Drawing.Xsharp/DrawingWindow.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/System.Drawing.Xsharp/DrawingWindow.cs,v
retrieving revision 1.24
diff -c -r1.24 DrawingWindow.cs
*** System.Drawing.Xsharp/DrawingWindow.cs	27 Apr 2004 10:59:46 -0000	1.24
--- System.Drawing.Xsharp/DrawingWindow.cs	30 May 2004 17:59:49 -0000
***************
*** 731,736 ****
--- 731,741 ----
  				}
  			}
  
+ 			private void IToolkitWindow.SendBeginInvoke(IntPtr i_gch)
+ 			{
+ 				base.SendBeginInvoke(i_gch);
+ 			}
+ 
  }; // class DrawingWindow
  
  }; // namespace System.Drawing.Toolkit
Index: System.Windows.Forms/Control.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/System.Windows.Forms/Control.cs,v
retrieving revision 1.61
diff -c -r1.61 Control.cs
*** System.Windows.Forms/Control.cs	21 May 2004 09:16:33 -0000	1.61
--- System.Windows.Forms/Control.cs	30 May 2004 17:59:51 -0000
***************
*** 24,29 ****
--- 24,30 ----
  {
  
  using System.ComponentModel;
+ using System.Diagnostics;
  using System.Drawing;
  using System.Drawing.Toolkit;
  using System.Drawing.Text;
***************
*** 31,36 ****
--- 32,40 ----
  using System.Threading;
  using System.Reflection;
  using System.Drawing.Drawing2D;
+ using System.Runtime.InteropServices;
+ 
+ delegate Object InvokeDelegate(Object[] args);
  
  #if CONFIG_COMPONENT_MODEL
  public class Control : Component, ISynchronizeInvoke, IWin32Window
***************
*** 89,94 ****
--- 93,183 ----
  	private bool validationCancelled = false;
  	private IToolkitWindowBuffer buffer;
  
+ 	//
+ 	// Implentation of classes and variables for Invoke/BeginInvoke/EndInvoke
+ 	//
+ 	//
+ 	// This is the IAsyncResult class associated with a BeginInvoke
+ 	//
+ 	internal class InvokeAsyncResult: IAsyncResult
+ 	{
+ 		private bool bComplete;
+ 		private bool bWaiting;
+ 		private Mutex waitHandle;			// The waithandle for EndInvoke
+ 		public Object retObject;
+ 
+ 		public InvokeAsyncResult()
+ 		{
+ 			bComplete = false;						// This event hasn't completed
+ 			bWaiting = false;							// Nobody waiting for this to complete
+ 			waitHandle = new Mutex(true);	// Initially locked (i.e. not complete!)
+ 		}
+ 
+ 		public void WaitToComplete()
+ 		{
+ 			lock(this)										// Lock ourselve for thread safety
+ 			{
+ 				if( bComplete )						// If we have already completed
+ 					return;										// just blow out of here
+ 				bWaiting = true;						// Else tell thread 2 we are waiting
+ 			}
+ 			waitHandle.WaitOne();					// and do so
+ 		}
+ 
+ 		public void SetComplete()
+ 		{
+ 			lock(this)										// Lock ourselves for thread safety
+ 			{
+ 				bComplete = true;						// Mark event as complete
+ 				if( !bWaiting )							// If nobody is waiting
+ 					return;										// no point in signalling
+ 			}
+ 			waitHandle.ReleaseMutex();		// else wake up sleeper waiting for us
+ 		}
+ 
+ 		public Object AsyncState
+ 		{
+ 			get
+ 			{
+ 				return null;
+ 			}
+ 		}
+ 		public WaitHandle AsyncWaitHandle
+ 		{
+ 			get
+ 			{
+ 				return waitHandle;
+ 			}
+ 		}
+ 		public bool CompletedSynchronously
+ 		{
+ 			get
+ 			{
+ 				return false;
+ 			}
+ 		}
+ 		public bool IsCompleted
+ 		{
+ 			get
+ 			{
+ 				lock( this )
+ 					return bComplete;
+ 			}
+ 		}
+ 	}
+ 
+ 	//
+ 	// This is the class that keeps the delegate, the parameters,
+ 	// and a weak reference to the IAsyncResult (InvokeAsyncResult)
+ 	// InvokeAsyncresult ar = wr.Target
+ 	//
+ 	internal class InvokeParameters
+ 	{
+ 		public Delegate method;
+ 		public Object[] args;
+ 		public WeakReference wr;	// to the InvokeAsyncResult
+ 	}
+ 
  	// Constructors.
  	public Control()
  			{
***************
*** 188,214 ****
  #if CONFIG_COMPONENT_MODEL
  
  	// Implement the ISynchronizeInvoke interface.
! 	[TODO]
  	public IAsyncResult BeginInvoke(Delegate method, Object[] args)
  			{
! 				// TODO
! 				return null;
  			}
  	public IAsyncResult BeginInvoke(Delegate method)
  			{
  				return BeginInvoke(method, null);
  			}
! 	[TODO]
  	public Object EndInvoke(IAsyncResult result)
  			{
! 				// TODO
! 				return null;
  			}
! 	[TODO]
  	public Object Invoke(Delegate method, Object[] args)
  			{
! 				// TODO
! 				return null;
  			}
  	public bool InvokeRequired
  			{
--- 277,333 ----
  #if CONFIG_COMPONENT_MODEL
  
  	// Implement the ISynchronizeInvoke interface.
! /////////////////////////////////////////////////////////////////////////////////////////////////////////
! 	private void ProcessInvokeEvent(IntPtr i_gch)	
! 	{
! 		GCHandle gch = (GCHandle)i_gch;
! 		InvokeParameters iParm = (InvokeParameters)gch.Target;
! 
! 		Delegate dg = iParm.method;
! 		Object ro = dg.DynamicInvoke(iParm.args);
! 
! 		InvokeAsyncResult ar = (InvokeAsyncResult)iParm.wr.Target;
! 		if( ar != null )
! 		{
! 			ar.retObject = ro;
! 			ar.SetComplete();
! 		}
! 		gch.Free();
! 	}
! /////////////////////////////////////////////////////////////////////////////////////////////////////////
  	public IAsyncResult BeginInvoke(Delegate method, Object[] args)
  			{
! 				InvokeParameters iParm = new InvokeParameters();
! 				InvokeAsyncResult ar = new InvokeAsyncResult();
! 				GCHandle gch = GCHandle.Alloc(iParm);
! 				IntPtr i_gch = (IntPtr)gch;
! 
! 				iParm.method = method;
! 				iParm.args   = args;
! 				iParm.wr = new WeakReference(ar);
! 
! 				lock(this)	// this may not be necessary
! 					toolkitWindow.SendBeginInvoke(i_gch);
! 
! 				return ar;
  			}
+ 
  	public IAsyncResult BeginInvoke(Delegate method)
  			{
  				return BeginInvoke(method, null);
  			}
! 
  	public Object EndInvoke(IAsyncResult result)
  			{
! 				InvokeAsyncResult ar = (result as InvokeAsyncResult);
! 				ar.WaitToComplete();
! 				return ar.retObject;
  			}
! 
  	public Object Invoke(Delegate method, Object[] args)
  			{
! 				IAsyncResult ar = this.BeginInvoke(method,args);
! 				return this.EndInvoke(ar);
  			}
  	public bool InvokeRequired
  			{
***************
*** 4898,4903 ****
--- 5017,5030 ----
  						}
  						break;
  				}
+ 			}
+ 
+ 	// Toolkit event that is emitted when a "BeginInvoke" generated message is
+ 	// send to this window
+ 	// i_gch is a pointer to an InvokeParms class defined elsewhere in here
+ 	void IToolkitEventSink.ToolkitBeginInvoke(IntPtr i_gch)
+ 			{
+ 				ProcessInvokeEvent(i_gch);
  			}
  
  	// Toolkit event that is emitted when the mouse enters this window.
Index: Xsharp/Display.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/Xsharp/Display.cs,v
retrieving revision 1.24
diff -c -r1.24 Display.cs
*** Xsharp/Display.cs	4 Feb 2004 07:27:07 -0000	1.24
--- Xsharp/Display.cs	30 May 2004 17:59:52 -0000
***************
*** 59,64 ****
--- 59,65 ----
  	internal XAtom wmState;
  	internal XAtom wmNetState;
  	internal XAtom wmPing;
+ 	internal XAtom internalBeginInvoke;
  	internal ButtonName selectButton;
  	internal ButtonName menuButton;
  	internal Hashtable fonts;
***************
*** 117,122 ****
--- 118,125 ----
  					(dpy, "_NET_WM_STATE", XBool.False);
  				wmPing = Xlib.XInternAtom
  					(dpy, "_NET_WM_PING", XBool.False);
+ 				internalBeginInvoke = Xlib.XInternAtom
+ 					(dpy, "INTERNAL_BEGIN_INVOKE", XBool.False);
  
  				// Which buttons should we use for "Select" and "Menu"?
  				byte[] buttons = new byte [5];
Index: Xsharp/TopLevelWindow.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/Xsharp/TopLevelWindow.cs,v
retrieving revision 1.23
diff -c -r1.23 TopLevelWindow.cs
*** Xsharp/TopLevelWindow.cs	4 Feb 2004 07:27:07 -0000	1.23
--- Xsharp/TopLevelWindow.cs	30 May 2004 17:59:54 -0000
***************
*** 1489,1494 ****
--- 1489,1504 ----
  			}
  
  	/// <summary>
+ 	/// <para>Method that is called when a custom "BeginInvoke" message comes in
+ 	/// changes.</para>
+ 	/// </summary>
+ 	protected virtual void OnBeginInvokeMessage(IntPtr i_gch)
+ 			{
+ 				// Nothing to do in this base class.
+ 			}
+ 
+ 
+ 	/// <summary>
  	/// <para>Method that is called when the window's iconic state
  	/// changes.</para>
  	/// </summary>
***************
*** 1802,1821 ****
  						// Handle messages from the window manager.
  						if(xevent.xclient.message_type == dpy.wmProtocols)
  						{
! 							if(xevent.xclient.l(0) ==
! 									(int)(dpy.wmDeleteWindow))
  							{
  								// User wants the window to close.
  								Close();
  							}
! 							else if(xevent.xclient.l(0) ==
! 										(int)(dpy.wmTakeFocus))
  							{
  								// We were given the primary input focus.
  								PrimaryFocusIn();
  							}
! 							else if(xevent.xclient.l(0) ==
! 										(int)(dpy.wmContextHelp))
  							{
  								// The user pressed the "help" button.
  								OnHelp();
--- 1812,1828 ----
  						// Handle messages from the window manager.
  						if(xevent.xclient.message_type == dpy.wmProtocols)
  						{
! 							if(xevent.xclient.l(0) == (int)(dpy.wmDeleteWindow))
  							{
  								// User wants the window to close.
  								Close();
  							}
! 							else if(xevent.xclient.l(0) == (int)(dpy.wmTakeFocus))
  							{
  								// We were given the primary input focus.
  								PrimaryFocusIn();
  							}
! 							else if(xevent.xclient.l(0) == (int)(dpy.wmContextHelp))
  							{
  								// The user pressed the "help" button.
  								OnHelp();
***************
*** 1828,1835 ****
  								try
  								{
  									IntPtr display = dpy.Lock();
! 									xevent.xany.window =
! 										screen.RootWindow.GetWidgetHandle();
  									Xlib.XSendEvent
  										(display, xevent.xany.window,
  										 XBool.False,
--- 1835,1841 ----
  								try
  								{
  									IntPtr display = dpy.Lock();
! 									xevent.xany.window = screen.RootWindow.GetWidgetHandle();
  									Xlib.XSendEvent
  										(display, xevent.xany.window,
  										 XBool.False,
***************
*** 1842,1847 ****
--- 1848,1857 ----
  								}
  							}
  						}
+ 						else if(xevent.xclient.message_type == dpy.internalBeginInvoke)
+ 						{
+ 							OnBeginInvokeMessage((IntPtr)xevent.xclient.l(0));
+ 						}
  					}
  					break;
  
***************
*** 1919,1924 ****
--- 1929,1938 ----
  									OnMaximizedStateChanged(false);
  								}
  							}
+ 						}
+ 						else if(xevent.xclient.message_type == dpy.internalBeginInvoke)
+ 						{
+ 							OnBeginInvokeMessage((IntPtr)xevent.xclient.l(0));
  						}
  					}
  					break;
Index: Xsharp/Widget.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/Xsharp/Widget.cs,v
retrieving revision 1.16
diff -c -r1.16 Widget.cs
*** Xsharp/Widget.cs	21 May 2004 16:29:46 -0000	1.16
--- Xsharp/Widget.cs	30 May 2004 18:00:07 -0000
***************
*** 1578,1583 ****
--- 1578,1606 ----
  				return new Point(x, y);
  			}
  
+ 	protected void SendBeginInvoke(IntPtr i_gch)
+ 		{
+ 			XEvent xevent = new XEvent();
+ 			xevent.xany.type = (int)(EventType.ClientMessage);
+ 			xevent.xany.window = GetWidgetHandle();
+ 			xevent.xclient.format = 32;
+ 			xevent.xclient.setl(0,(int)i_gch);
+ 
+ 			try
+ 			{
+ 				IntPtr display = dpy.Lock();
+ 				xevent.xclient.message_type = Xlib.XInternAtom
+ 						(display, "INTERNAL_BEGIN_INVOKE", XBool.False);
+ 				Xlib.XSendEvent (display, GetWidgetHandle(),
+ 						XBool.False, (int)(EventMask.NoEventMask), ref xevent);
+ 				Xlib.XFlush(display);
+ 			}
+ 			finally
+ 			{
+ 				dpy.Unlock();
+ 			}
+ 	}
+ 
  } // class Widget
  
  } // namespace Xsharp
#### End of Patch data ####
