# Patch created by loga3870
# Date: Sun May 30 18:10:02 MDT 2004
# Repository: pnetlib
# Comments:
# Completed development: System.Windows.Forms BeginInvoke, EndInvoke and Invoke
# is functional on X platforms and Win32 platforms.
#### 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	31 May 2004 00:10:05 -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	31 May 2004 00:10:15 -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	31 May 2004 00:10:17 -0000
***************
*** 117,122 ****
--- 117,127 ----
  		}
  	}
  
+ 	private void IToolkitWindow.SendBeginInvoke(IntPtr i_gch)
+ 	{
+ 		StaticSendBeginInvoke(hwnd,i_gch);
+ 	}
+ 
  
  }; // 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	31 May 2004 00:10:20 -0000
***************
*** 86,101 ****
  		}
  	}
  
! 	protected internal override void MouseMove(int msg, int wParam, int lParam)
! 	{
! 		// Another popup window could grab the capture from this control. When we move back onto this control, we need to make sure that we regain the capture.
! 		IToolkitWindow window = (this as IToolkitWindow);
! 		if (window.Capture != visible)
! 		{
! 			window.Capture = base.IsMapped;
! 		}
! 		base.MouseMove (msg, wParam, lParam);
! 	}
  
  }
  }
--- 86,106 ----
  		}
  	}
  
! 	protected internal override void MouseMove(int msg, int wParam, int lParam)
! 	{
! 		// Another popup window could grab the capture from this control. When we move back onto this control, we need to make sure that we regain the capture.
! 		IToolkitWindow window = (this as IToolkitWindow);
! 		if (window.Capture != visible)
! 		{
! 			window.Capture = base.IsMapped;
! 		}
! 		base.MouseMove (msg, wParam, lParam);
! 	}
! 
! 	private void IToolkitWindow.SendBeginInvoke(IntPtr i_gch)
! 	{
! 		StaticSendBeginInvoke(hwnd,i_gch);
! 	}
  
  }
  }
Index: System.Drawing.Win32/DrawingToolkit.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/System.Drawing.Win32/DrawingToolkit.cs,v
retrieving revision 1.30
diff -c -r1.30 DrawingToolkit.cs
*** System.Drawing.Win32/DrawingToolkit.cs	25 Jan 2004 19:51:48 -0000	1.30
--- System.Drawing.Win32/DrawingToolkit.cs	31 May 2004 00:10:25 -0000
***************
*** 34,39 ****
--- 34,40 ----
  	private static ArrayList timers = new ArrayList();
  	internal DrawingWindow[] windows = new DrawingWindow[64];
  	internal int windowCount = 0;
+ 	internal Win32.Api.WindowsMessages registeredBeginInvokeMessage;
  	// The child window or control that has captured or null for none
  	internal DrawingWindow capturedWindow;
  	// The top level window that has the capture.
***************
*** 50,55 ****
--- 51,57 ----
  		hiddenWindow = new DrawingHiddenWindow(this, "DrawingHiddenWindow",0,0,null);
  		AddWindow(hiddenWindow, null);
  		hiddenWindow.CreateWindow();
+ 		registeredBeginInvokeMessage = Win32.Api.RegisterWindowMessageA("DOTNET_BEGIN_INVOKE_MESSAGE");
  	}
  
  	// Process events in the event queue.  If "waitForEvent" is true,
***************
*** 699,704 ****
--- 701,711 ----
  				return DrawingWindow(hwnd).MouseActivate(DrawingWindow(new IntPtr(wParam)));
  
  			default:
+ 				if((Win32.Api.WindowsMessages)msg == registeredBeginInvokeMessage)
+ 				{
+ 					DrawingWindow(hwnd).SendBeginInvoke(wParam);
+ 					return 0;
+ 				}
  				retval = Win32.Api.DefWindowProcA(hwnd, msg, wParam, lParam);
  				break;
  		}
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	31 May 2004 00:10:37 -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)
+ 	{
+ 		StaticSendBeginInvoke(hwnd,i_gch);
+ 	}
+ 
  }; // 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	31 May 2004 00:10:42 -0000
***************
*** 31,36 ****
--- 31,39 ----
  	protected internal IntPtr hwnd;
  	protected internal IntPtr hdc;
  	protected internal DrawingWindow parent;
+ 	
+ 	private static Win32.Api.WindowsMessages registeredBeginInvokeMessage = 0;
+ 
  	// The window at the top of the hierarchy
  	protected internal DrawingWindow topOfhierarchy;
  	private Color background;
***************
*** 59,64 ****
--- 62,70 ----
  	protected DrawingWindow( DrawingToolkit toolkit )
  	{
  		this.toolkit = toolkit;
+ 		if( registeredBeginInvokeMessage == 0 )
+ 			registeredBeginInvokeMessage =
+ 				Win32.Api.RegisterWindowMessageA("DOTNET_BEGIN_INVOKE_MESSAGE");
  	}
  
  	// Move this window underneath the last window with the same parent.
***************
*** 599,610 ****
  		return FindDeepestChild(lParam, out x, out y, out actual);
  	}
  
! 	internal bool KeyDown( int wParam, int lParam)
  	{
  		//Console.WriteLine("DrawingWindow.KeyDown " + sink +", " + (MapKeyToToolkitKeys( wParam)).ToString() + " " + wParam);
  		return sink.ToolkitKeyDown(MapKeyToToolkitKeys( wParam));
  	}
  
  	internal bool Char( int wParam, int lParam)
  	{
  		//Console.WriteLine("DrawingWindow.Char " + sink +", "+ ((char)wParam).ToString());
--- 605,622 ----
  		return FindDeepestChild(lParam, out x, out y, out actual);
  	}
  
!   	internal bool KeyDown( int wParam, int lParam)
  	{
  		//Console.WriteLine("DrawingWindow.KeyDown " + sink +", " + (MapKeyToToolkitKeys( wParam)).ToString() + " " + wParam);
  		return sink.ToolkitKeyDown(MapKeyToToolkitKeys( wParam));
  	}
  
+ 	internal bool SendBeginInvoke( int wParam )
+ 	{
+ 		sink.ToolkitBeginInvoke( (IntPtr)wParam );
+ 		return true;
+ 	}
+ 
  	internal bool Char( int wParam, int lParam)
  	{
  		//Console.WriteLine("DrawingWindow.Char " + sink +", "+ ((char)wParam).ToString());
***************
*** 907,912 ****
--- 919,936 ----
  			if (w == this)
  				return true;
  		return false;
+ 	}
+ 
+ 	private void IToolkitWindow.SendBeginInvoke(IntPtr i_gch)
+ 	{
+ 		StaticSendBeginInvoke(hwnd,i_gch);
+ 	}
+ 
+ 	public static void StaticSendBeginInvoke(IntPtr hwnd_rcv, IntPtr i_gch)
+ 	{
+ 		Win32.Api.PostMessageA(hwnd_rcv,
+ 			registeredBeginInvokeMessage,
+ 			(int)i_gch,(int)0);
  	}
  
  }
Index: System.Drawing.Win32/Win32.cs
===================================================================
RCS file: /cvsroot/dotgnu-pnet/pnetlib/System.Drawing.Win32/Win32.cs,v
retrieving revision 1.22
diff -c -r1.22 Win32.cs
*** System.Drawing.Win32/Win32.cs	26 Jan 2004 20:31:12 -0000	1.22
--- System.Drawing.Win32/Win32.cs	31 May 2004 00:10:47 -0000
***************
*** 819,826 ****
  	[DllImport("user32")] //ANSI
  	public static extern bool PostMessageA(IntPtr hwnd, WindowsMessages Msg, int wParam, int lParam);
  
! 	[DllImport("user32")] //ANSI
  	public static extern int SendMessageA( IntPtr hWnd, WindowsMessages Msg, int wParam, IntPtr lParam);
  
  	[DllImport("user32")]
  	public static extern int GetSystemMetrics (SystemMetricsType nIndex);
--- 819,829 ----
  	[DllImport("user32")] //ANSI
  	public static extern bool PostMessageA(IntPtr hwnd, WindowsMessages Msg, int wParam, int lParam);
  
!   	[DllImport("user32")] //ANSI
  	public static extern int SendMessageA( IntPtr hWnd, WindowsMessages Msg, int wParam, IntPtr lParam);
+ 
+ 	[DllImport("user32")]
+ 	public static extern WindowsMessages RegisterWindowMessageA (string msgName);
  
  	[DllImport("user32")]
  	public static extern int GetSystemMetrics (SystemMetricsType nIndex);
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	31 May 2004 00:10:57 -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	31 May 2004 00:11:01 -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	31 May 2004 00:11:05 -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	31 May 2004 00:11:17 -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	31 May 2004 00:11:20 -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	31 May 2004 00:11:24 -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
  			{
***************
*** 2214,2227 ****
  	// Process a command key.
  	protected virtual bool ProcessCmdKey(ref Message msg, Keys keyData)
  			{
! 				if (contextMenu != null && contextMenu.ProcessCmdKey(ref msg, keyData))
! 				{
! 					return true; 
! 				}
! 				if (parent != null)
! 				{
! 					return parent.ProcessCmdKey(ref msg, keyData);
! 				}
  				return false;
  			}
  
--- 2333,2346 ----
  	// Process a command key.
  	protected virtual bool ProcessCmdKey(ref Message msg, Keys keyData)
  			{
! 				if (contextMenu != null && contextMenu.ProcessCmdKey(ref msg, keyData))
! 				{
! 					return true; 
! 				}
! 				if (parent != null)
! 				{
! 					return parent.ProcessCmdKey(ref msg, keyData);
! 				}
  				return false;
  			}
  
***************
*** 2708,2721 ****
  				{
  					if (!value)
  					{
! 						if (ContainsFocus && Parent != null)
! 						{
! 							Control container = Parent.GetContainerControl() as Control;
! 							if (container != null)
! 							{
! 									container.SelectNextControl(this, true, true, true, true);
! 							}
! 						}
  					}
  					// Update the visible state.
  					visible = value;
--- 2827,2840 ----
  				{
  					if (!value)
  					{
! 						if (ContainsFocus && Parent != null)
! 						{
! 							Control container = Parent.GetContainerControl() as Control;
! 							if (container != null)
! 							{
! 									container.SelectNextControl(this, true, true, true, true);
! 							}
! 						}
  					}
  					// Update the visible state.
  					visible = value;
***************
*** 4297,4307 ****
  				if(toolkitWindow != null)
  				{
  					toolkitWindow.IsMapped = visible;
! 					// May as well release the double buffer resource if its being used.
! 					if (!visible && buffer != null)
! 					{
! 						buffer.Dispose();
! 						buffer = null;
  					}
  				}
  				else if(visible && !disposed && (parent == null || parent.IsHandleCreated) )
--- 4416,4426 ----
  				if(toolkitWindow != null)
  				{
  					toolkitWindow.IsMapped = visible;
! 					// May as well release the double buffer resource if its being used.
! 					if (!visible && buffer != null)
! 					{
! 						buffer.Dispose();
! 						buffer = null;
  					}
  				}
  				else if(visible && !disposed && (parent == null || parent.IsHandleCreated) )
***************
*** 4849,4855 ****
  							gFull.Dispose();
  						}
  						if (g != null)
! 						{
  							g.Dispose();
  						}
  					}
--- 4968,4974 ----
  							gFull.Dispose();
  						}
  						if (g != null)
! 						{
  							g.Dispose();
  						}
  					}
***************
*** 4900,4905 ****
--- 5019,5032 ----
  				}
  			}
  
+ 	// 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.
  	void IToolkitEventSink.ToolkitMouseEnter()
  			{
***************
*** 5167,5176 ****
  	// Create a brush that can be used to fill with the background color/image.
  	internal Brush CreateBackgroundBrush()
  			{
! 				if(backgroundImage != null)
! 				{
! 					return new TextureBrush(backgroundImage);
! 				}
  				return new SolidBrush(BackColor);
  			}
  
--- 5294,5303 ----
  	// Create a brush that can be used to fill with the background color/image.
  	internal Brush CreateBackgroundBrush()
  			{
! 				if(backgroundImage != null)
! 				{
! 					return new TextureBrush(backgroundImage);
! 				}
  				return new SolidBrush(BackColor);
  			}
  
***************
*** 5242,5249 ****
  
  	protected internal bool DoValidating()
  	{
! 		CancelEventArgs args = new CancelEventArgs();
! 		OnValidating(args);
  		return args.Cancel;
  	}
  
--- 5369,5376 ----
  
  	protected internal bool DoValidating()
  	{
! 		CancelEventArgs args = new CancelEventArgs();
! 		OnValidating(args);
  		return args.Cancel;
  	}
  
***************
*** 5252,5260 ****
  		OnValidated(EventArgs.Empty);
  	}
  
! 	internal virtual void DoValidationCancel(bool cancelled)
! 	{
! 			this.validationCancelled = cancelled;
  	}
  
  
--- 5379,5387 ----
  		OnValidated(EventArgs.Empty);
  	}
  
! 	internal virtual void DoValidationCancel(bool cancelled)
! 	{
! 			this.validationCancelled = cancelled;
  	}
  
  
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	31 May 2004 00:11:28 -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	31 May 2004 00:11:40 -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	31 May 2004 00:11:44 -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 ####
