[Pkg-mono-svn-commits] [SCM] mono-uia branch, master, updated. debian/2.1-2

Jo Shields directhex at apebox.org
Mon Jan 23 19:18:02 UTC 2012


The following commit has been merged in the master branch:
commit e4c547fed9b3dc2d6bb5edde43c2b100b2babdc6
Author: Jo Shields <directhex at apebox.org>
Date:   Mon Jan 23 19:02:09 2012 +0000

    Add a stripped down version of upstream 379d89f7ab15ee443d9a164d193f5e9bf3285b69 to fix building with Mono 2.8+

diff --git a/debian/patches/0001-UIAutomationClient-AutomationElement.FromLocalProvid.patch b/debian/patches/0001-UIAutomationClient-AutomationElement.FromLocalProvid.patch
new file mode 100644
index 0000000..abb9491
--- /dev/null
+++ b/debian/patches/0001-UIAutomationClient-AutomationElement.FromLocalProvid.patch
@@ -0,0 +1,1814 @@
+From 379d89f7ab15ee443d9a164d193f5e9bf3285b69 Mon Sep 17 00:00:00 2001
+From: Mario Carrion <mcarrion at novell.com>
+Date: Tue, 16 Nov 2010 17:01:32 -0500
+Subject: [UIAutomationClient] AutomationElement.FromLocalProvider
+ implementation.
+
+Fixes BNC #489388 and building with Mono 2.8
+---
+ MoonAtkBridge/MoonAtkBridge.sln                    |    5 +-
+ UIAutomation/UIAutomationBridge/Makefile.am        |    1 +
+ .../Mono.UIAutomation.Services/ArgumentCheck.cs    |   42 ++
+ .../UIAutomationBridge/UIAutomationBridge.csproj   |    1 +
+ UIAutomation/UIAutomationClient/Makefile.am        |    7 +
+ .../ClientAutomationBridge.cs                      |   87 ++++
+ .../ClientAutomationSource.cs                      |  184 +++++++
+ .../ClientElement.cs                               |  514 ++++++++++++++++++++
+ .../ClientEventManager.cs                          |  250 ++++++++++
+ .../ClientInvokePattern.cs                         |   50 ++
+ .../System.Windows.Automation/Automation.cs        |   60 +--
+ .../System.Windows.Automation/AutomationElement.cs |   14 +-
+ .../System.Windows.Automation/ClientSettings.cs    |    4 +-
+ .../ClientSideProviderDescription.cs               |   26 +-
+ .../System.Windows.Automation/SourceManager.cs     |    2 +
+ .../UIAutomationClient/UIAutomationClient.csproj   |    8 +
+ .../UIAutomationClientTests/BaseTest.cs            |    2 +
+ .../UIAutomationClientTests/LocalProviderTest.cs   |  172 ++++++-
+ .../UIAutomationClientTests.csproj                 |   15 +-
+ .../AutomationInteropProvider.cs                   |    7 +-
+ .../AutomationIdentifier.cs                        |    6 +-
+ UiaAtkBridge/Test/AtkTest/AtkTest.csproj           |    1 +
+ UiaAtkBridge/Test/GailTestApp/gtk-gui/generated.cs |   55 +--
+ .../Wrappers/ProviderElementWrapper.cs             |   16 +-
+ UiaDbus/UiaDbusSource/UiaDbusElement.cs            |    2 +-
+ uia2atk.mdw                                        |    2 +-
+ 26 files changed, 1419 insertions(+), 114 deletions(-)
+ create mode 100644 UIAutomation/UIAutomationBridge/Mono.UIAutomation.Services/ArgumentCheck.cs
+ create mode 100644 UIAutomation/UIAutomationClient/Mono.UIAutomation.ClientSource/ClientAutomationBridge.cs
+ create mode 100644 UIAutomation/UIAutomationClient/Mono.UIAutomation.ClientSource/ClientAutomationSource.cs
+ create mode 100644 UIAutomation/UIAutomationClient/Mono.UIAutomation.ClientSource/ClientElement.cs
+ create mode 100644 UIAutomation/UIAutomationClient/Mono.UIAutomation.ClientSource/ClientEventManager.cs
+ create mode 100644 UIAutomation/UIAutomationClient/Mono.UIAutomation.ClientSource/ClientInvokePattern.cs
+
+Index: mono-uia.git/UIAutomationBridge/Makefile.am
+===================================================================
+--- mono-uia.git.orig/UIAutomationBridge/Makefile.am	2012-01-23 18:58:34.192473338 +0000
++++ mono-uia.git/UIAutomationBridge/Makefile.am	2012-01-23 18:58:44.776520265 +0000
+@@ -28,6 +28,7 @@
+ PROJECT_SOURCE_FILES =  \
+ 	Mono.UIAutomation.Bridge/IAutomationBridge.cs \
+ 	Mono.UIAutomation.Bridge/IHypertext.cs \
++	Mono.UIAutomation.Services/ArgumentCheck.cs \
+ 	Mono.UIAutomation.Services/Log.cs
+ 
+ FILES =  \
+Index: mono-uia.git/UIAutomationBridge/Mono.UIAutomation.Services/ArgumentCheck.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ mono-uia.git/UIAutomationBridge/Mono.UIAutomation.Services/ArgumentCheck.cs	2012-01-23 18:58:44.776520265 +0000
+@@ -0,0 +1,42 @@
++// Permission is hereby granted, free of charge, to any person obtaining 
++// a copy of this software and associated documentation files (the 
++// "Software"), to deal in the Software without restriction, including 
++// without limitation the rights to use, copy, modify, merge, publish, 
++// distribute, sublicense, and/or sell copies of the Software, and to 
++// permit persons to whom the Software is furnished to do so, subject to 
++// the following conditions: 
++//  
++// The above copyright notice and this permission notice shall be 
++// included in all copies or substantial portions of the Software. 
++//  
++// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
++// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
++// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
++// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
++// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
++// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
++// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
++// 
++// Copyright (c) 2010 Novell, Inc. (http://www.novell.com) 
++// 
++// Authors: 
++//      Matt Guo <matt at mattguo.com>
++// 
++
++using System;
++
++namespace Mono.UIAutomation.Services
++{
++	public static class ArgumentCheck
++	{
++		public static void NotNull<T> (T arg, string argName) where T : class {
++			if (arg == null)
++				throw new ArgumentNullException (argName);
++		}
++
++		public static void Assert<T> (T arg, Predicate<T> condition, string errorMessage) {
++			if (!condition (arg))
++				throw new ArgumentException (errorMessage);
++		}
++	}
++}
+Index: mono-uia.git/UIAutomationClient/Makefile.am
+===================================================================
+--- mono-uia.git.orig/UIAutomationClient/Makefile.am	2012-01-23 18:58:34.192473338 +0000
++++ mono-uia.git/UIAutomationClient/Makefile.am	2012-01-23 18:58:44.780520283 +0000
+@@ -31,6 +31,11 @@
+ all: $(ASSEMBLY) $(PROGRAMFILES)
+ 
+ PROJECT_SOURCE_FILES =  \
++	Mono.UIAutomation.ClientSource/ClientAutomationBridge.cs \
++	Mono.UIAutomation.ClientSource/ClientAutomationSource.cs \
++	Mono.UIAutomation.ClientSource/ClientElement.cs \
++	Mono.UIAutomation.ClientSource/ClientEventManager.cs \
++	Mono.UIAutomation.ClientSource/ClientInvokePattern.cs \
+ 	System.Windows.Automation.Text/TextPatternRange.cs \
+ 	System.Windows.Automation/AndCondition.cs \
+ 	System.Windows.Automation/Automation.cs \
+@@ -84,6 +89,8 @@
+ REFERENCES =  \
+ 	WindowsBase \
+ 	System \
++	System.Core \
++	Mono.Posix \
+ 	$(GTK_SHARP_20_LIBS)
+ 
+ DLL_REFERENCES = 
+Index: mono-uia.git/UIAutomationClient/Mono.UIAutomation.ClientSource/ClientAutomationBridge.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ mono-uia.git/UIAutomationClient/Mono.UIAutomation.ClientSource/ClientAutomationBridge.cs	2012-01-23 18:58:44.780520283 +0000
+@@ -0,0 +1,87 @@
++// Permission is hereby granted, free of charge, to any person obtaining 
++// a copy of this software and associated documentation files (the 
++// "Software"), to deal in the Software without restriction, including 
++// without limitation the rights to use, copy, modify, merge, publish, 
++// distribute, sublicense, and/or sell copies of the Software, and to 
++// permit persons to whom the Software is furnished to do so, subject to 
++// the following conditions: 
++//  
++// The above copyright notice and this permission notice shall be 
++// included in all copies or substantial portions of the Software. 
++//  
++// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
++// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
++// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
++// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
++// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
++// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
++// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
++// 
++// Copyright (c) 2010 Novell, Inc. (http://www.novell.com) 
++// 
++// Authors: 
++//     Matt Guo <matt at mattguo.com>
++// 
++
++using System;
++using System.Windows.Automation;
++using System.Windows.Automation.Provider;
++using Mono.UIAutomation.Bridge;
++
++namespace Mono.UIAutomation.ClientSource
++{
++	internal class ClientAutomationBridge : IAutomationBridge
++	{
++		#region IAutomationBridge implementation
++		public object HostProviderFromHandle (IntPtr hwnd)
++		{
++			return null;
++		}
++
++		public void RaiseAutomationEvent (AutomationEvent eventId, object provider, AutomationEventArgs e)
++		{
++			var providerSimple = provider as IRawElementProviderSimple;
++			if (providerSimple == null)
++				return;
++			ClientEventManager.RaiseAutomationEvent (eventId, providerSimple, e);
++		}
++
++		public void RaiseAutomationPropertyChangedEvent (object provider, AutomationPropertyChangedEventArgs e)
++		{
++			var providerSimple = provider as IRawElementProviderSimple;
++			if (providerSimple == null)
++				return;
++			ClientEventManager.RaiseAutomationPropertyChangedEvent (providerSimple, e);
++		}
++
++		public void RaiseStructureChangedEvent (object provider, StructureChangedEventArgs e)
++		{
++			var providerSimple = provider as IRawElementProviderSimple;
++			if (providerSimple == null)
++				return;
++			ClientEventManager.RaiseStructureChangedEvent (providerSimple, e);
++		}
++
++		public void Initialize ()
++		{
++		}
++
++		public void Terminate ()
++		{
++		}
++
++		public bool IsAccessibilityEnabled {
++			get {
++				return true;
++			}
++		}
++
++		public bool ClientsAreListening {
++			get {
++				return true;
++			}
++		}
++
++		#endregion
++	}
++}
+Index: mono-uia.git/UIAutomationClient/Mono.UIAutomation.ClientSource/ClientAutomationSource.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ mono-uia.git/UIAutomationClient/Mono.UIAutomation.ClientSource/ClientAutomationSource.cs	2012-01-23 18:58:44.780520283 +0000
+@@ -0,0 +1,184 @@
++// Permission is hereby granted, free of charge, to any person obtaining 
++// a copy of this software and associated documentation files (the 
++// "Software"), to deal in the Software without restriction, including 
++// without limitation the rights to use, copy, modify, merge, publish, 
++// distribute, sublicense, and/or sell copies of the Software, and to 
++// permit persons to whom the Software is furnished to do so, subject to 
++// the following conditions: 
++//  
++// The above copyright notice and this permission notice shall be 
++// included in all copies or substantial portions of the Software. 
++//  
++// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
++// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
++// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
++// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
++// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
++// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
++// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
++// 
++// Copyright (c) 2010 Novell, Inc. (http://www.novell.com) 
++// 
++// Authors: 
++//     Matt Guo <matt at mattguo.com>
++// 
++
++using System;
++using System.Threading;
++using System.Windows.Automation;
++using System.Windows.Automation.Provider;
++using Mono.UIAutomation.Source;
++using Mono.UIAutomation.Services;
++
++namespace Mono.UIAutomation.ClientSource
++{
++	internal class ClientAutomationSource : IAutomationSource
++	{
++		private static ClientAutomationSource instance = null;
++		private static object staticLock = new object ();
++		public static ClientAutomationSource Instance {
++			get {
++				if (instance == null)
++					lock (staticLock)
++						if (instance == null)
++							instance = new ClientAutomationSource ();
++				return instance;
++			}
++		}
++
++		#region IAutomationSource implementation
++		public event EventHandler RootElementsChanged;
++
++		public void Initialize ()
++		{
++		}
++
++		public IElement [] GetRootElements ()
++		{
++			return new IElement [0];
++		}
++
++		public IElement GetFocusedElement ()
++		{
++			return null;
++		}
++
++		public IElement GetElementFromHandle (IntPtr handle)
++		{
++			return null;
++		}
++
++		public void AddAutomationEventHandler (AutomationEvent eventId, IElement element, TreeScope scope, AutomationEventHandler eventHandler)
++		{
++			if (element == null)
++				// elements from local providers are not descendants of the RootElement.
++				return;
++			ClientElement clientElement = element as ClientElement;
++			if (clientElement == null) {
++				Log.Error ("[ClientAutomationSource.AddAutomationEventHandler] Not ClientElement");
++				return;
++			}
++			ClientEventManager.AddAutomationEventHandler (eventId,
++				clientElement.Provider, scope, eventHandler);
++		}
++
++		public void AddAutomationPropertyChangedEventHandler (IElement element, TreeScope scope, AutomationPropertyChangedEventHandler eventHandler, AutomationProperty[] properties)
++		{
++			if (element == null)
++				return;
++			ClientElement clientElement = element as ClientElement;
++			if (clientElement == null) {
++				Log.Error ("[ClientAutomationSource.AddAutomationPropertyChangedEventHandler] Not ClientElement");
++				return;
++			}
++			int [] propertyIds = Array.ConvertAll (properties, p => p.Id);
++			ClientEventManager.AddAutomationPropertyChangedEventHandler (
++				clientElement.Provider, scope, eventHandler, propertyIds);
++		}
++
++		public void AddStructureChangedEventHandler (IElement element, TreeScope scope, StructureChangedEventHandler eventHandler)
++		{
++			if (element == null)
++				return;
++			ClientElement clientElement = element as ClientElement;
++			if (clientElement == null) {
++				Log.Error ("[ClientAutomationSource.AddStructureChangedEventHandler] Not ClientElement");
++				return;
++			}
++			ClientEventManager.AddStructureChangedEventHandler (clientElement.Provider,
++				scope, eventHandler);
++		}
++
++		public void AddAutomationFocusChangedEventHandler (FocusChangedEventHandler eventHandler)
++		{
++			// client provider never fires FocusChangedEvent.
++			return;
++		}
++
++		public void RemoveAutomationEventHandler (AutomationEvent eventId, IElement element, AutomationEventHandler eventHandler)
++		{
++			if (element == null)
++				return;
++			ClientElement clientElement = element as ClientElement;
++			if (clientElement == null) {
++				Log.Error ("[ClientAutomationSource.RemoveAutomationEventHandler] Not ClientElement");
++				return;
++			}
++			ClientEventManager.RemoveAutomationEventHandler (eventId,
++				clientElement.Provider, eventHandler);
++		}
++
++		public void RemoveAutomationPropertyChangedEventHandler (IElement element, AutomationPropertyChangedEventHandler eventHandler)
++		{
++			if (element == null)
++				return;
++			ClientElement clientElement = element as ClientElement;
++			if (clientElement == null) {
++				Log.Error ("[ClientAutomationSource.RemoveAutomationPropertyChangedEventHandler] Not ClientElement");
++				return;
++			}
++			ClientEventManager.RemoveAutomationPropertyChangedEventHandler (
++				clientElement.Provider, eventHandler);
++		}
++
++		public void RemoveStructureChangedEventHandler (IElement element, StructureChangedEventHandler eventHandler)
++		{
++			if (element == null)
++				return;
++			ClientElement clientElement = element as ClientElement;
++			if (clientElement == null) {
++				Log.Error ("[ClientAutomationSource.RemoveStructureChangedEventHandler] Not ClientElement");
++				return;
++			}
++			ClientEventManager.RemoveStructureChangedEventHandler (
++				clientElement.Provider, eventHandler);
++		}
++
++		public void RemoveAutomationFocusChangedEventHandler (FocusChangedEventHandler eventHandler)
++		{
++			// client provider never fires FocusChangedEvent.
++			return;
++		}
++
++		public void RemoveAllEventHandlers ()
++		{
++			ClientEventManager.RemoveAllEventHandlers ();
++		}
++
++		public bool IsAccessibilityEnabled {
++			get {
++				return true;
++			}
++		}
++
++		#endregion
++
++		public ClientElement GetOrCreateElement (IRawElementProviderSimple provider)
++		{
++			if (provider == null)
++				return null;
++			//?????
++			return new ClientElement (this, provider);
++		}
++	}
++}
+\ No newline at end of file
+Index: mono-uia.git/UIAutomationClient/Mono.UIAutomation.ClientSource/ClientElement.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ mono-uia.git/UIAutomationClient/Mono.UIAutomation.ClientSource/ClientElement.cs	2012-01-23 18:58:44.780520283 +0000
+@@ -0,0 +1,514 @@
++// Permission is hereby granted, free of charge, to any person obtaining 
++// a copy of this software and associated documentation files (the 
++// "Software"), to deal in the Software without restriction, including 
++// without limitation the rights to use, copy, modify, merge, publish, 
++// distribute, sublicense, and/or sell copies of the Software, and to 
++// permit persons to whom the Software is furnished to do so, subject to 
++// the following conditions: 
++//  
++// The above copyright notice and this permission notice shall be 
++// included in all copies or substantial portions of the Software. 
++//  
++// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
++// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
++// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
++// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
++// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
++// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
++// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
++// 
++// Copyright (c) 2010 Novell, Inc. (http://www.novell.com) 
++// 
++// Authors: 
++//     Matt Guo <matt at mattguo.com>
++// 
++
++using System;
++using System.Windows;
++using System.Windows.Automation;
++using System.Windows.Automation.Provider;
++using Mono.UIAutomation.Source;
++using AEIds = System.Windows.Automation.AutomationElementIdentifiers;
++using System.Collections.Generic;
++using Mono.Unix;
++using Mono.UIAutomation.Services;
++using System.Linq;
++
++namespace Mono.UIAutomation.ClientSource
++{
++	// TODO the ClientElement class shares many common code with UiaDbusBridge.ProviderElementWrapper,
++	// Any change to refactor and merge these code?
++	internal class ClientElement : IElement
++	{
++		#region All patterns and properties
++		private static int [] allPatternIds = {
++			ExpandCollapsePatternIdentifiers.Pattern.Id,
++			GridItemPatternIdentifiers.Pattern.Id,
++			GridPatternIdentifiers.Pattern.Id,
++			InvokePatternIdentifiers.Pattern.Id,
++			MultipleViewPatternIdentifiers.Pattern.Id,
++			RangeValuePatternIdentifiers.Pattern.Id,
++			ScrollPatternIdentifiers.Pattern.Id,
++			SelectionItemPatternIdentifiers.Pattern.Id,
++			SelectionPatternIdentifiers.Pattern.Id,
++			TablePatternIdentifiers.Pattern.Id,
++			TextPatternIdentifiers.Pattern.Id,
++			TogglePatternIdentifiers.Pattern.Id,
++			TransformPatternIdentifiers.Pattern.Id,
++			ValuePatternIdentifiers.Pattern.Id,
++			WindowPatternIdentifiers.Pattern.Id,
++			ScrollItemPatternIdentifiers.Pattern.Id,
++			DockPatternIdentifiers.Pattern.Id,
++			TableItemPatternIdentifiers.Pattern.Id
++		};
++
++		private static int [] allPropertyIds = {
++			AutomationElementIdentifiers.IsControlElementProperty.Id,
++			AutomationElementIdentifiers.ControlTypeProperty.Id,
++			AutomationElementIdentifiers.IsContentElementProperty.Id,
++			AutomationElementIdentifiers.LabeledByProperty.Id,
++			AutomationElementIdentifiers.NativeWindowHandleProperty.Id,
++			AutomationElementIdentifiers.AutomationIdProperty.Id,
++			AutomationElementIdentifiers.ItemTypeProperty.Id,
++			AutomationElementIdentifiers.IsPasswordProperty.Id,
++			AutomationElementIdentifiers.LocalizedControlTypeProperty.Id,
++			AutomationElementIdentifiers.NameProperty.Id,
++			AutomationElementIdentifiers.AcceleratorKeyProperty.Id,
++			AutomationElementIdentifiers.AccessKeyProperty.Id,
++			AutomationElementIdentifiers.HasKeyboardFocusProperty.Id,
++			AutomationElementIdentifiers.IsKeyboardFocusableProperty.Id,
++			AutomationElementIdentifiers.IsEnabledProperty.Id,
++			AutomationElementIdentifiers.BoundingRectangleProperty.Id,
++			AutomationElementIdentifiers.ProcessIdProperty.Id,
++			AutomationElementIdentifiers.RuntimeIdProperty.Id,
++			AutomationElementIdentifiers.ClassNameProperty.Id,
++			AutomationElementIdentifiers.HelpTextProperty.Id,
++			AutomationElementIdentifiers.ClickablePointProperty.Id,
++			AutomationElementIdentifiers.CultureProperty.Id,
++			AutomationElementIdentifiers.IsOffscreenProperty.Id,
++			AutomationElementIdentifiers.OrientationProperty.Id,
++			AutomationElementIdentifiers.FrameworkIdProperty.Id,
++			AutomationElementIdentifiers.IsRequiredForFormProperty.Id,
++			AutomationElementIdentifiers.ItemStatusProperty.Id,
++			// Comment Is*PatternAvailableProperty since MS.Net never include those
++			// properties in the return value of AutomationElement.GetSupportedProperties ()
++			//AutomationElementIdentifiers.IsDockPatternAvailableProperty.Id,
++			//AutomationElementIdentifiers.IsExpandCollapsePatternAvailableProperty.Id,
++			//AutomationElementIdentifiers.IsGridItemPatternAvailableProperty.Id,
++			//AutomationElementIdentifiers.IsGridPatternAvailableProperty.Id,
++			//AutomationElementIdentifiers.IsInvokePatternAvailableProperty.Id,
++			//AutomationElementIdentifiers.IsMultipleViewPatternAvailableProperty.Id,
++			//AutomationElementIdentifiers.IsRangeValuePatternAvailableProperty.Id,
++			//AutomationElementIdentifiers.IsSelectionItemPatternAvailableProperty.Id,
++			//AutomationElementIdentifiers.IsSelectionPatternAvailableProperty.Id,
++			//AutomationElementIdentifiers.IsScrollPatternAvailableProperty.Id,
++			//AutomationElementIdentifiers.IsScrollItemPatternAvailableProperty.Id,
++			//AutomationElementIdentifiers.IsTablePatternAvailableProperty.Id,
++			//AutomationElementIdentifiers.IsTableItemPatternAvailableProperty.Id,
++			//AutomationElementIdentifiers.IsTextPatternAvailableProperty.Id,
++			//AutomationElementIdentifiers.IsTogglePatternAvailableProperty.Id,
++			//AutomationElementIdentifiers.IsTransformPatternAvailableProperty.Id,
++			//AutomationElementIdentifiers.IsValuePatternAvailableProperty.Id,
++			//AutomationElementIdentifiers.IsWindowPatternAvailableProperty.Id,
++			ExpandCollapsePatternIdentifiers.ExpandCollapseStateProperty.Id,
++			GridItemPatternIdentifiers.RowProperty.Id,
++			GridItemPatternIdentifiers.ColumnProperty.Id,
++			GridItemPatternIdentifiers.RowSpanProperty.Id,
++			GridItemPatternIdentifiers.ColumnSpanProperty.Id,
++			GridItemPatternIdentifiers.ContainingGridProperty.Id,
++			GridPatternIdentifiers.RowCountProperty.Id,
++			GridPatternIdentifiers.ColumnCountProperty.Id,
++			MultipleViewPatternIdentifiers.CurrentViewProperty.Id,
++			MultipleViewPatternIdentifiers.SupportedViewsProperty.Id,
++			RangeValuePatternIdentifiers.ValueProperty.Id,
++			RangeValuePatternIdentifiers.IsReadOnlyProperty.Id,
++			RangeValuePatternIdentifiers.MinimumProperty.Id,
++			RangeValuePatternIdentifiers.MaximumProperty.Id,
++			RangeValuePatternIdentifiers.LargeChangeProperty.Id,
++			RangeValuePatternIdentifiers.SmallChangeProperty.Id,
++			ScrollPatternIdentifiers.HorizontalScrollPercentProperty.Id,
++			ScrollPatternIdentifiers.HorizontalViewSizeProperty.Id,
++			ScrollPatternIdentifiers.VerticalScrollPercentProperty.Id,
++			ScrollPatternIdentifiers.VerticalViewSizeProperty.Id,
++			ScrollPatternIdentifiers.HorizontallyScrollableProperty.Id,
++			ScrollPatternIdentifiers.VerticallyScrollableProperty.Id,
++			SelectionItemPatternIdentifiers.IsSelectedProperty.Id,
++			SelectionItemPatternIdentifiers.SelectionContainerProperty.Id,
++			SelectionPatternIdentifiers.SelectionProperty.Id,
++			SelectionPatternIdentifiers.CanSelectMultipleProperty.Id,
++			SelectionPatternIdentifiers.IsSelectionRequiredProperty.Id,
++			TablePatternIdentifiers.RowHeadersProperty.Id,
++			TablePatternIdentifiers.ColumnHeadersProperty.Id,
++			TablePatternIdentifiers.RowOrColumnMajorProperty.Id,
++			TogglePatternIdentifiers.ToggleStateProperty.Id,
++			TransformPatternIdentifiers.CanMoveProperty.Id,
++			TransformPatternIdentifiers.CanResizeProperty.Id,
++			TransformPatternIdentifiers.CanRotateProperty.Id,
++			ValuePatternIdentifiers.ValueProperty.Id,
++			ValuePatternIdentifiers.IsReadOnlyProperty.Id,
++			WindowPatternIdentifiers.CanMaximizeProperty.Id,
++			WindowPatternIdentifiers.CanMinimizeProperty.Id,
++			WindowPatternIdentifiers.IsModalProperty.Id,
++			WindowPatternIdentifiers.WindowVisualStateProperty.Id,
++			WindowPatternIdentifiers.WindowInteractionStateProperty.Id,
++			WindowPatternIdentifiers.IsTopmostProperty.Id,
++			DockPatternIdentifiers.DockPositionProperty.Id,
++			TableItemPatternIdentifiers.RowHeaderItemsProperty.Id,
++			TableItemPatternIdentifiers.ColumnHeaderItemsProperty.Id
++		};
++		#endregion
++
++		#region Private FIelds
++
++		private ClientAutomationSource source = null;
++		private IRawElementProviderSimple provider = null;
++		private IRawElementProviderFragment providerFragment = null;
++		private IRawElementProviderFragmentRoot providerFragmentRoot = null;
++
++		#endregion
++
++		#region Constructor
++
++		public ClientElement (ClientAutomationSource source, IRawElementProviderSimple provider)
++		{
++			ArgumentCheck.NotNull (source, "source");
++			ArgumentCheck.NotNull (provider, "provider");
++
++			this.source = source;
++			this.provider = provider;
++			providerFragment = provider as IRawElementProviderFragment;
++			providerFragmentRoot = provider as IRawElementProviderFragmentRoot;
++		}
++
++		#endregion
++
++		internal IRawElementProviderSimple Provider {
++			get { return provider; }
++		}
++
++		#region IElement implementation
++
++		public bool SupportsProperty (AutomationProperty property)
++		{
++			ArgumentCheck.NotNull (property, "property");
++
++			object val = provider.GetPropertyValue (property.Id);
++			return val != null && val != AEIds.NotSupported;
++		}
++
++		public object GetCurrentPattern (AutomationPattern pattern)
++		{
++			ArgumentCheck.NotNull (pattern, "pattern");
++
++			var patternProvider = provider.GetPatternProvider (pattern.Id);
++			if (patternProvider == null)
++				throw new InvalidOperationException ();
++			object ret = null;
++			if (pattern == InvokePattern.Pattern)
++				ret = new ClientInvokePattern ((IInvokeProvider) patternProvider);
++			// TODO implement
++			// we still have more pattern to implement
++			else
++				throw new System.InvalidOperationException ();
++			return ret;
++		}
++
++		public AutomationPattern[] GetSupportedPatterns ()
++		{
++			return (from patternId in allPatternIds
++				where provider.GetPatternProvider (patternId) != null
++				select AutomationPattern.LookupById (patternId)).ToArray ();
++		}
++
++		public AutomationProperty[] GetSupportedProperties ()
++		{
++			return (from propertyId in allPropertyIds
++			        let val = provider.GetPropertyValue (propertyId)
++				where val != null && val != AEIds.NotSupported
++				select AutomationProperty.LookupById (propertyId)).ToArray ();
++		}
++
++		public void SetFocus ()
++		{
++			if (!IsKeyboardFocusable)
++				// as tested on Windows, the InvalidOperationException hasn't any error message 
++				throw new InvalidOperationException ();
++			if (providerFragment != null)
++				providerFragment.SetFocus ();
++		}
++
++		public IElement GetDescendantFromPoint (double x, double y)
++		{
++			if (providerFragmentRoot != null) {
++				var childProvider =
++					providerFragmentRoot.ElementProviderFromPoint (x, y);
++				return source.GetOrCreateElement (childProvider);
++			}
++			return null;
++		}
++
++		public string AcceleratorKey {
++			get {
++				return provider.GetPropertyValue (AEIds.AcceleratorKeyProperty.Id)
++					as string ?? string.Empty;
++			}
++		}
++
++		public string AccessKey {
++			get {
++				return provider.GetPropertyValue (AEIds.AccessKeyProperty.Id)
++					as string ?? string.Empty;
++			}
++		}
++
++		public string AutomationId {
++			get {
++				return provider.GetPropertyValue (AEIds.AutomationIdProperty.Id)
++					as string ?? string.Empty;
++			}
++		}
++
++		public Rect BoundingRectangle {
++			get {
++				// As tested on Windows, runtime id is solely decided
++				// by providerFragment.BoundingRectangle, and is irrelevant with
++				// IRawElementProviderSimple.GetPropertyValue (AEIds.BoundingRectangleProperty)
++
++				if (providerFragment != null)
++					return providerFragment.BoundingRectangle;
++				else
++					return Rect.Empty;
++			}
++		}
++
++		public string ClassName {
++			get {
++				return provider.GetPropertyValue (AEIds.ClassNameProperty.Id)
++					as string ?? string.Empty;
++			}
++		}
++
++		public Point ClickablePoint {
++			get {
++				object obj = provider.GetPropertyValue (AEIds.ClickablePointProperty.Id);
++				return (obj != null) ? (Point) obj :
++					new Point (double.NegativeInfinity, double.NegativeInfinity);
++			}
++		}
++
++		public ControlType ControlType {
++			get {
++				object obj = provider.GetPropertyValue (AEIds.ControlTypeProperty.Id);
++				return (obj != null) ? ControlType.LookupById ((int) obj) : ControlType.Custom;
++			}
++		}
++
++		public string FrameworkId {
++			get {
++				return provider.GetPropertyValue (AEIds.FrameworkIdProperty.Id)
++					as string ?? string.Empty;
++			}
++		}
++
++		public bool HasKeyboardFocus {
++			get {
++				object obj = provider.GetPropertyValue (AEIds.HasKeyboardFocusProperty.Id);
++				return (obj != null) ? (bool) obj : false;
++			}
++		}
++
++		public string HelpText {
++			get {
++				return provider.GetPropertyValue (AEIds.HelpTextProperty.Id)
++					as string ?? string.Empty;
++			}
++		}
++
++		public bool IsContentElement {
++			get {
++				object obj = provider.GetPropertyValue (AEIds.IsContentElementProperty.Id);
++				return (obj != null) ? (bool) obj : false;
++			}
++		}
++
++		public bool IsControlElement {
++			get {
++				object obj = provider.GetPropertyValue (AEIds.IsControlElementProperty.Id);
++				return (obj != null) ? (bool) obj : false;
++			}
++		}
++
++		public bool IsEnabled {
++			get {
++				object obj = provider.GetPropertyValue (AEIds.IsEnabledProperty.Id);
++				return (obj != null) ? (bool) obj : false;
++			}
++		}
++
++		public bool IsKeyboardFocusable {
++			get {
++				object obj = provider.GetPropertyValue (AEIds.IsKeyboardFocusableProperty.Id);
++				return (obj != null) ? (bool) obj : false;
++			}
++		}
++
++		public bool IsOffscreen {
++			get {
++				object obj = provider.GetPropertyValue (AEIds.IsOffscreenProperty.Id);
++				return (obj != null) ? (bool) obj : false;
++			}
++		}
++
++		public bool IsPassword {
++			get {
++				object obj = provider.GetPropertyValue (AEIds.IsPasswordProperty.Id);
++				return (obj != null) ? (bool) obj : false;
++			}
++		}
++
++		public bool IsRequiredForForm {
++			get {
++				object obj = provider.GetPropertyValue (AEIds.IsRequiredForFormProperty.Id);
++				return (obj != null) ? (bool) obj : false;
++			}
++		}
++
++		public string ItemStatus {
++			get {
++				return provider.GetPropertyValue (AEIds.ItemStatusProperty.Id)
++					as string ?? string.Empty;
++			}
++		}
++
++		public string ItemType {
++			get {
++				return provider.GetPropertyValue (AEIds.ItemTypeProperty.Id)
++					as string ?? string.Empty;
++			}
++		}
++
++		public IElement LabeledBy {
++			get {
++				var labeledBy = provider.GetPropertyValue (AEIds.LabeledByProperty.Id)
++					as IRawElementProviderSimple;
++				return (labeledBy != null) ? source.GetOrCreateElement (labeledBy) : null;
++			}
++		}
++
++		public string LocalizedControlType {
++			get {
++				var controlType = this.ControlType;
++				if (controlType == ControlType.DataGrid)
++					return Catalog.GetString ("data grid");
++				else if (controlType == ControlType.DataItem)
++					return Catalog.GetString ("data item");
++				else if (controlType == ControlType.List)
++					return Catalog.GetString ("list");
++				else
++					return controlType.LocalizedControlType;
++			}
++		}
++
++		public string Name {
++			get {
++				return provider.GetPropertyValue (AEIds.NameProperty.Id)
++					as string ?? string.Empty;
++			}
++		}
++
++		public int NativeWindowHandle {
++			get {
++				object obj = provider.GetPropertyValue (AEIds.NativeWindowHandleProperty.Id);
++				return (obj != null) ? (int) obj : 0;
++			}
++		}
++
++		public OrientationType Orientation {
++			get {
++				object obj = provider.GetPropertyValue (AEIds.OrientationProperty.Id);
++				return (obj != null) ? (OrientationType) obj : OrientationType.None;
++			}
++		}
++
++		public int ProcessId {
++			get {
++				object obj = provider.GetPropertyValue (AEIds.ProcessIdProperty.Id);
++				return (obj != null) ? (int) obj : 0;
++			}
++		}
++
++		public int[] RuntimeId {
++			get {
++				// As tested on Windows, runtime id is solely decided
++				// by providerFragment.GetRuntimeId, and is irrelevant with
++				// IRawElementProviderSimple.GetPropertyValue (AEIds.RuntimeIdProperty)
++				//
++				// An expcetion: if the runtime id is not explicitly provided, while
++				// native handle is provided, then UIA will generate a runtime id for the provider,
++				// on Windows 7 the runtime id is [42, NativeHandleValue]
++				int [] runtimeId = null;
++				if (providerFragment != null)
++					runtimeId = providerFragment.GetRuntimeId ();
++				else {
++					int hwnd = this.NativeWindowHandle;
++					if (hwnd != 0)
++						runtimeId = new int [] {42, hwnd};
++				}
++				return runtimeId;
++			}
++		}
++
++		public IElement Parent {
++			get {
++				if (providerFragment == null)
++					return null;
++				return source.GetOrCreateElement (
++					providerFragment.Navigate (NavigateDirection.Parent));
++			}
++		}
++
++		public IElement FirstChild {
++			get {
++				if (providerFragment == null)
++					return null;
++				return source.GetOrCreateElement (
++					providerFragment.Navigate (NavigateDirection.FirstChild));
++			}
++		}
++
++		public IElement LastChild {
++			get {
++				if (providerFragment == null)
++					return null;
++				return source.GetOrCreateElement (
++					providerFragment.Navigate (NavigateDirection.LastChild));
++			}
++		}
++
++		public IElement NextSibling {
++			get {
++				if (providerFragment == null)
++					return null;
++				return source.GetOrCreateElement (
++					providerFragment.Navigate (NavigateDirection.NextSibling));
++			}
++		}
++
++		public IElement PreviousSibling {
++			get {
++				if (providerFragment == null)
++					return null;
++				return source.GetOrCreateElement (
++					providerFragment.Navigate (NavigateDirection.PreviousSibling));
++			}
++		}
++
++		public IAutomationSource AutomationSource {
++			get {
++				return source;
++			}
++		}
++
++		#endregion
++	}
++}
+Index: mono-uia.git/UIAutomationClient/Mono.UIAutomation.ClientSource/ClientEventManager.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ mono-uia.git/UIAutomationClient/Mono.UIAutomation.ClientSource/ClientEventManager.cs	2012-01-23 18:58:44.780520283 +0000
+@@ -0,0 +1,250 @@
++// Permission is hereby granted, free of charge, to any person obtaining 
++// a copy of this software and associated documentation files (the 
++// "Software"), to deal in the Software without restriction, including 
++// without limitation the rights to use, copy, modify, merge, publish, 
++// distribute, sublicense, and/or sell copies of the Software, and to 
++// permit persons to whom the Software is furnished to do so, subject to 
++// the following conditions: 
++//  
++// The above copyright notice and this permission notice shall be 
++// included in all copies or substantial portions of the Software. 
++//  
++// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
++// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
++// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
++// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
++// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
++// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
++// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
++// 
++// Copyright (c) 2010 Novell, Inc. (http://www.novell.com) 
++// 
++// Authors: 
++//     Matt Guo <matt at mattguo.com>
++// 
++
++using System;
++using System.Collections.Generic;
++using System.Windows.Automation;
++using System.Windows.Automation.Provider;
++using Mono.UIAutomation.Source;
++
++namespace Mono.UIAutomation.ClientSource
++{
++	internal static class ClientEventManager
++	{
++		private static List<PropertyChangedEventEntry> propertyChangedEventEntries
++			= new List<PropertyChangedEventEntry> ();
++		private static List<AutomationEventEntry> automationEventEntries
++			= new List<AutomationEventEntry> ();
++		private static List<StructureChangedEventEntry> structureChangedEventEntries
++			= new List<StructureChangedEventEntry> ();
++
++		public static void AddAutomationEventHandler (AutomationEvent eventId,
++			IRawElementProviderSimple provider, TreeScope scope,
++			AutomationEventHandler eventHandler)
++		{
++			var entry = new AutomationEventEntry (eventId, provider, scope, eventHandler);
++			lock (automationEventEntries)
++				automationEventEntries.Add (entry);
++		}
++
++		public static void AddAutomationPropertyChangedEventHandler (
++			IRawElementProviderSimple provider, TreeScope scope,
++			AutomationPropertyChangedEventHandler eventHandler,
++			int [] properties)
++		{
++			var entry = new PropertyChangedEventEntry (provider, scope, properties, eventHandler);
++			lock (propertyChangedEventEntries)
++				propertyChangedEventEntries.Add (entry);
++		}
++
++		public static void AddStructureChangedEventHandler (
++			IRawElementProviderSimple provider, TreeScope scope,
++			StructureChangedEventHandler eventHandler)
++		{
++			var entry = new StructureChangedEventEntry (provider, scope, eventHandler);
++			lock (structureChangedEventEntries)
++				structureChangedEventEntries.Add (entry);
++		}
++
++		public static void RemoveAutomationEventHandler (AutomationEvent eventId, IRawElementProviderSimple provider, AutomationEventHandler eventHandler)
++		{
++			lock (automationEventEntries)
++				automationEventEntries.RemoveAll (e =>
++					e.EventId == eventId &&
++					e.Provider == provider &&
++					e.Handler == eventHandler);
++		}
++
++		public static void RemoveAutomationPropertyChangedEventHandler (IRawElementProviderSimple provider, AutomationPropertyChangedEventHandler eventHandler)
++		{
++			lock (propertyChangedEventEntries)
++				propertyChangedEventEntries.RemoveAll (e =>
++					e.Provider == provider &&
++					e.Handler == eventHandler);
++		}
++
++		public static void RemoveStructureChangedEventHandler (IRawElementProviderSimple provider, StructureChangedEventHandler eventHandler)
++		{
++			lock (structureChangedEventEntries)
++				structureChangedEventEntries.RemoveAll (e =>
++					e.Provider == provider &&
++					e.Handler == eventHandler);
++		}
++
++		public static void RemoveAllEventHandlers ()
++		{
++			lock (automationEventEntries)
++				automationEventEntries.Clear ();
++			lock (structureChangedEventEntries)
++				structureChangedEventEntries.Clear ();
++			lock (propertyChangedEventEntries)
++				propertyChangedEventEntries.Clear ();
++		}
++
++		public static void RaiseAutomationEvent (AutomationEvent eventId,
++			IRawElementProviderSimple provider, AutomationEventArgs e)
++		{
++			lock (automationEventEntries)
++				foreach (var entry in automationEventEntries)
++					if (entry.EventId == eventId &&
++						IsProviderInScope (provider, entry.Provider, entry.Scope)) {
++						var clientElement =
++							ClientAutomationSource.Instance.GetOrCreateElement (provider);
++						var element = SourceManager.GetOrCreateAutomationElement (clientElement);
++						entry.Handler (element, e);
++					}
++		}
++
++		public static void RaiseAutomationPropertyChangedEvent (IRawElementProviderSimple provider,
++			AutomationPropertyChangedEventArgs e)
++		{
++			lock (propertyChangedEventEntries)
++				foreach (var entry in propertyChangedEventEntries)
++					if (IsProviderInScope (provider, entry.Provider, entry.Scope) &&
++						Array.Exists (entry.Properties, i => i == e.Property.Id)) {
++						var clientElement =
++							ClientAutomationSource.Instance.GetOrCreateElement (provider);
++						var element = SourceManager.GetOrCreateAutomationElement (clientElement);
++						// TODO implement
++						// Translate e.NewValue && e.OldValue
++						entry.Handler (element, e);
++					}
++		}
++
++		public static void RaiseStructureChangedEvent (IRawElementProviderSimple provider,
++			StructureChangedEventArgs e)
++		{
++			lock (structureChangedEventEntries)
++				foreach (var entry in structureChangedEventEntries)
++					if (IsProviderInScope (provider, entry.Provider, entry.Scope)) {
++						var clientElement =
++							ClientAutomationSource.Instance.GetOrCreateElement (provider);
++						var element = SourceManager.GetOrCreateAutomationElement (clientElement);
++						entry.Handler (element, e);
++					}
++		}
++
++		private static bool IsProviderInScope (IRawElementProviderSimple target,
++			IRawElementProviderSimple element, TreeScope scope)
++		{
++			if ((scope & TreeScope.Element) == TreeScope.Element && target == element)
++				return true;
++
++			IRawElementProviderFragment targetFragment = target as IRawElementProviderFragment;
++			IRawElementProviderFragment elementFragment = element as IRawElementProviderFragment;
++			if (targetFragment == null || elementFragment == null)
++				return false;
++
++			IRawElementProviderFragment targetFragmentRoot =
++				targetFragment.Navigate (NavigateDirection.Parent);
++			if ((scope & TreeScope.Children) == TreeScope.Children &&
++			    targetFragmentRoot != null &&
++			    targetFragmentRoot == elementFragment)
++				return true;
++			if ((scope & TreeScope.Descendants) == TreeScope.Descendants) {
++				while (targetFragmentRoot != null) {
++					if (targetFragmentRoot == elementFragment)
++						return true;
++					targetFragmentRoot = targetFragmentRoot.Navigate (NavigateDirection.Parent);
++				}
++			}
++
++			IRawElementProviderFragment elementFragmentRoot =
++				elementFragment.Navigate (NavigateDirection.Parent);
++			if ((scope & TreeScope.Parent) == TreeScope.Parent &&
++			    elementFragmentRoot != null &&
++			    elementFragmentRoot == targetFragment)
++				return true;
++			if ((scope & TreeScope.Ancestors) == TreeScope.Ancestors) {
++				while (elementFragmentRoot != null) {
++					if (elementFragmentRoot == targetFragment)
++						return true;
++					elementFragmentRoot = elementFragmentRoot.Navigate (NavigateDirection.Parent);
++				}
++			}
++
++			return false;
++		}
++#region Internal Classes
++
++		private class AutomationEventEntryBase
++		{
++			public AutomationEventEntryBase (IRawElementProviderSimple provider,
++			                                 TreeScope scope)
++			{
++				this.Provider = provider;
++				this.Scope = scope;
++			}
++
++			public IRawElementProviderSimple Provider { get; private set; }
++			public TreeScope Scope { get; private set; }
++		}
++
++		private class StructureChangedEventEntry : AutomationEventEntryBase
++		{
++			public StructureChangedEventEntry (IRawElementProviderSimple provider,
++			                                   TreeScope scope,
++			                                   StructureChangedEventHandler handler)
++				: base (provider, scope)
++			{
++				this.Handler = handler;
++			}
++			public StructureChangedEventHandler Handler { get; private set; }
++		}
++
++		private class AutomationEventEntry : AutomationEventEntryBase
++		{
++			public AutomationEventEntry (AutomationEvent eventId,
++			                             IRawElementProviderSimple provider,
++			                             TreeScope scope,
++			                             AutomationEventHandler handler)
++				: base (provider, scope)
++			{
++				this.EventId = eventId;
++				this.Handler = handler;
++			}
++
++			public AutomationEvent EventId { get; private set; }
++			public AutomationEventHandler Handler { get; private set; }
++		}
++
++		private class PropertyChangedEventEntry : AutomationEventEntryBase
++		{
++			public PropertyChangedEventEntry (IRawElementProviderSimple provider,
++			                                  TreeScope scope,
++			                                  int [] properties,
++			                                  AutomationPropertyChangedEventHandler handler)
++				: base (provider, scope)
++			{
++				this.Properties = properties;
++				this.Handler = handler;
++			}
++
++			public int [] Properties { get; private set; }
++			public AutomationPropertyChangedEventHandler Handler { get; private set; }
++		}
++#endregion
++	}
++}
+Index: mono-uia.git/UIAutomationClient/Mono.UIAutomation.ClientSource/ClientInvokePattern.cs
+===================================================================
+--- /dev/null	1970-01-01 00:00:00.000000000 +0000
++++ mono-uia.git/UIAutomationClient/Mono.UIAutomation.ClientSource/ClientInvokePattern.cs	2012-01-23 18:58:44.780520283 +0000
+@@ -0,0 +1,50 @@
++// Permission is hereby granted, free of charge, to any person obtaining 
++// a copy of this software and associated documentation files (the 
++// "Software"), to deal in the Software without restriction, including 
++// without limitation the rights to use, copy, modify, merge, publish, 
++// distribute, sublicense, and/or sell copies of the Software, and to 
++// permit persons to whom the Software is furnished to do so, subject to 
++// the following conditions: 
++//  
++// The above copyright notice and this permission notice shall be 
++// included in all copies or substantial portions of the Software. 
++//  
++// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
++// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
++// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
++// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
++// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
++// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
++// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
++// 
++// Copyright (c) 2010 Novell, Inc. (http://www.novell.com) 
++// 
++// Authors: 
++//     Matt Guo <matt at mattguo.com>
++// 
++
++using System;
++using System.Windows.Automation;
++using System.Windows.Automation.Provider;
++using Mono.UIAutomation.Source;
++
++namespace Mono.UIAutomation.ClientSource
++{
++	internal class ClientInvokePattern : IInvokePattern
++	{
++		private IInvokeProvider provider = null;
++
++		public ClientInvokePattern (IInvokeProvider provider)
++		{
++			this.provider = provider;
++		}
++
++		#region IInvokePattern implementation
++		public void Invoke ()
++		{
++			provider.Invoke ();
++		}
++
++		#endregion
++	}
++}
+Index: mono-uia.git/UIAutomationClient/System.Windows.Automation/Automation.cs
+===================================================================
+--- mono-uia.git.orig/UIAutomationClient/System.Windows.Automation/Automation.cs	2011-03-06 12:25:27.000000000 +0000
++++ mono-uia.git/UIAutomationClient/System.Windows.Automation/Automation.cs	2012-01-23 18:58:44.780520283 +0000
+@@ -28,6 +28,7 @@
+ 
+ using AEIds = System.Windows.Automation.AutomationElementIdentifiers;
+ using MUS = Mono.UIAutomation.Source;
++using Mono.UIAutomation.Services;
+ 
+ namespace System.Windows.Automation
+ {
+@@ -309,14 +310,13 @@
+ 		                                       TreeScope scope,
+ 		                                       AutomationEventHandler eventHandler)
+ 		{
+-			if (element == null)
+-				throw new ArgumentNullException ("element");
+-			if (eventHandler == null)
+-				throw new ArgumentNullException ("eventHandler");
++			CheckAutomationEventId (eventId);
++			ArgumentCheck.NotNull (element, "element");
++			ArgumentCheck.NotNull (eventHandler, "eventHandler");
++
+ 			//TODO In theory we shall also check scope not equals to Parent or Ancestors,
+ 			//but .Net didn't test/throw exceptions for "scope"
+ 
+-			CheckAutomationEventId (eventId.Id);
+ 			if (element == AutomationElement.RootElement)
+ 				foreach (var source in SourceManager.GetAutomationSources ())
+ 					source.AddAutomationEventHandler (
+@@ -330,8 +330,7 @@
+ 
+ 		public static void AddAutomationFocusChangedEventHandler (AutomationFocusChangedEventHandler eventHandler)
+ 		{
+-			if (eventHandler == null)
+-				throw new ArgumentNullException ("eventHandler");
++			ArgumentCheck.NotNull (eventHandler, "eventHandler");
+ 
+ 			MUS.FocusChangedEventHandler sourceHandler;
+ 			//according to the spec, all static methods in the UIA lib shall be thread safe.
+@@ -352,10 +351,8 @@
+ 		                                                      AutomationPropertyChangedEventHandler eventHandler,
+ 		                                                      params AutomationProperty [] properties)
+ 		{
+-			if (element == null)
+-				throw new ArgumentNullException ("element");
+-			if (eventHandler == null)
+-				throw new ArgumentNullException ("eventHandler");
++			ArgumentCheck.NotNull (element, "element");
++			ArgumentCheck.NotNull (eventHandler, "eventHandler");
+ 
+ 			if (element == AutomationElement.RootElement)
+ 				foreach (var source in SourceManager.GetAutomationSources ())
+@@ -372,10 +369,8 @@
+ 		                                             TreeScope scope,
+ 		                                             StructureChangedEventHandler eventHandler)
+ 		{
+-			if (element == null)
+-				throw new ArgumentNullException ("element");
+-			if (eventHandler == null)
+-				throw new ArgumentNullException ("eventHandler");
++			ArgumentCheck.NotNull (element, "element");
++			ArgumentCheck.NotNull (eventHandler, "eventHandler");
+ 
+ 			if (element == AutomationElement.RootElement)
+ 				foreach (var source in SourceManager.GetAutomationSources ())
+@@ -402,12 +397,9 @@
+ 			AutomationElement element,
+ 			AutomationEventHandler eventHandler)
+ 		{
+-			if (element == null)
+-				throw new ArgumentNullException ("element");
+-			if (eventHandler == null)
+-				throw new ArgumentNullException ("eventHandler");
+-
+-			CheckAutomationEventId (eventId.Id);
++			CheckAutomationEventId (eventId);
++			ArgumentCheck.NotNull (element, "element");
++			ArgumentCheck.NotNull (eventHandler, "eventHandler");
+ 
+ 			if (element == AutomationElement.RootElement)
+ 				foreach (var source in SourceManager.GetAutomationSources ())
+@@ -421,8 +413,7 @@
+ 
+ 		public static void RemoveAutomationFocusChangedEventHandler (AutomationFocusChangedEventHandler eventHandler)
+ 		{
+-			if (eventHandler == null)
+-				throw new ArgumentNullException ("eventHandler");
++			ArgumentCheck.NotNull (eventHandler, "eventHandler");
+ 
+ 			MUS.FocusChangedEventHandler sourceHandler;
+ 			lock (focusHandlerMapping) {
+@@ -437,10 +428,8 @@
+ 		public static void RemoveAutomationPropertyChangedEventHandler (
+ 			AutomationElement element, AutomationPropertyChangedEventHandler eventHandler)
+ 		{
+-			if (element == null)
+-				throw new ArgumentNullException ("element");
+-			if (eventHandler == null)
+-				throw new ArgumentNullException ("eventHandler");
++			ArgumentCheck.NotNull (element, "element");
++			ArgumentCheck.NotNull (eventHandler, "eventHandler");
+ 
+ 			if (element == AutomationElement.RootElement)
+ 				foreach (var source in SourceManager.GetAutomationSources ())
+@@ -456,10 +445,8 @@
+ 		public static void RemoveStructureChangedEventHandler (
+ 			AutomationElement element, StructureChangedEventHandler eventHandler)
+ 		{
+-			if (element == null)
+-				throw new ArgumentNullException ("element");
+-			if (eventHandler == null)
+-				throw new ArgumentNullException ("eventHandler");
++			ArgumentCheck.NotNull (element, "element");
++			ArgumentCheck.NotNull (eventHandler, "eventHandler");
+ 
+ 			if (element == AutomationElement.RootElement)
+ 				foreach (var source in SourceManager.GetAutomationSources ())
+@@ -472,12 +459,13 @@
+ 			}
+ 		}
+ 
+-		private static void CheckAutomationEventId (int eventId)
++		private static void CheckAutomationEventId (AutomationEvent eventId)
+ 		{
+-			if (AutomationElementIdentifiers.AutomationFocusChangedEvent.Id == eventId
+-				|| AutomationElementIdentifiers.AutomationFocusChangedEvent.Id == eventId
+-				|| AutomationElementIdentifiers.AutomationPropertyChangedEvent.Id == eventId
+-				|| AutomationElementIdentifiers.StructureChangedEvent.Id == eventId)
++			ArgumentCheck.NotNull (eventId, "eventId");
++			if (AutomationElementIdentifiers.AutomationFocusChangedEvent == eventId
++				|| AutomationElementIdentifiers.AutomationFocusChangedEvent == eventId
++				|| AutomationElementIdentifiers.AutomationPropertyChangedEvent == eventId
++				|| AutomationElementIdentifiers.StructureChangedEvent == eventId)
+ 				throw new ArgumentException ("eventId");
+ 		}
+ 
+Index: mono-uia.git/UIAutomationClient/System.Windows.Automation/AutomationElement.cs
+===================================================================
+--- mono-uia.git.orig/UIAutomationClient/System.Windows.Automation/AutomationElement.cs	2011-03-06 12:25:27.000000000 +0000
++++ mono-uia.git/UIAutomationClient/System.Windows.Automation/AutomationElement.cs	2012-01-23 18:58:44.780520283 +0000
+@@ -523,8 +523,7 @@
+ #region Public Static Methods
+ 		public static AutomationElement FromHandle (IntPtr hwnd)
+ 		{
+-			if (hwnd == (IntPtr) null || hwnd == IntPtr.Zero)
+-				throw new ArgumentException ("hwnd");
++			ArgumentCheck.Assert (hwnd, (h => h != IntPtr.Zero), "hwnd");
+ 			if (hwnd == NativeMethods.RootWindowHandle)
+ 				return RootElement;
+ 			AutomationElement element = null;
+@@ -542,7 +541,9 @@
+ 
+ 		public static AutomationElement FromLocalProvider (IRawElementProviderSimple localImpl)
+ 		{
+-			throw new NotImplementedException ();
++			IElement sourceElement = Mono.UIAutomation.ClientSource.ClientAutomationSource.Instance
++				.GetOrCreateElement (localImpl);
++			return new AutomationElement (sourceElement);
+ 		}
+ 
+ 		public static AutomationElement FromPoint (Point pt)
+@@ -550,7 +551,12 @@
+ 			IntPtr handle = NativeMethods.WindowAtPosition ((int) pt.X, (int) pt.Y);
+ 			if (handle == IntPtr.Zero)
+ 				return RootElement;
+-			AutomationElement startElement = FromHandle (handle);
++			AutomationElement startElement = null;
++			try {
++				startElement = FromHandle (handle);
++			} catch (ElementNotAvailableException) {
++				return RootElement;
++			}
+ 			if (startElement == RootElement)
+ 				return RootElement;
+ 			//Keep searching the descendant element which are not native window
+Index: mono-uia.git/UIAutomationClient/System.Windows.Automation/ClientSettings.cs
+===================================================================
+--- mono-uia.git.orig/UIAutomationClient/System.Windows.Automation/ClientSettings.cs	2011-03-06 12:25:27.000000000 +0000
++++ mono-uia.git/UIAutomationClient/System.Windows.Automation/ClientSettings.cs	2012-01-23 18:58:44.780520283 +0000
+@@ -26,6 +26,7 @@
+ using System;
+ using System.Reflection;
+ using System.IO;
++using Mono.UIAutomation.Services;
+ 
+ namespace System.Windows.Automation
+ {
+@@ -33,8 +34,7 @@
+ 	{
+ 		public static void RegisterClientSideProviderAssembly (AssemblyName assemblyName)
+ 		{
+-			if (assemblyName == null)
+-				throw new ArgumentNullException ("assemblyName");
++			ArgumentCheck.NotNull (assemblyName, "assemblyName");
+ 
+ 			Assembly assembly = null;
+ 			// TODO, wrap exception messages into Catalog.GetString
+Index: mono-uia.git/UIAutomationClient/System.Windows.Automation/ClientSideProviderDescription.cs
+===================================================================
+--- mono-uia.git.orig/UIAutomationClient/System.Windows.Automation/ClientSideProviderDescription.cs	2011-03-06 12:25:27.000000000 +0000
++++ mono-uia.git/UIAutomationClient/System.Windows.Automation/ClientSideProviderDescription.cs	2012-01-23 18:58:44.780520283 +0000
+@@ -44,16 +44,23 @@
+ 			string imageName,
+ 			ClientSideProviderMatchIndicator flags)
+ 		{
+-			this.ClientSideProviderFactoryCallback = clientSideProviderFactoryCallback;
+-			this.ClassName = className;
+-			this.ImageName = imageName;
+-			this.Flags = flags;
++			this.clientSideProviderFactoryCallback = clientSideProviderFactoryCallback;
++			this.className = className;
++			this.imageName = imageName;
++			this.flags = flags;
+ 		}
+ 
+-		public string ClassName { get; private set; }
+-		public ClientSideProviderMatchIndicator Flags { get; private set; }
+-		public string ImageName { get; private set; }
+-		public ClientSideProviderFactoryCallback ClientSideProviderFactoryCallback { get; private set; }
++		public string ClassName { get { return className; } }
++		public ClientSideProviderMatchIndicator Flags { get { return flags; } }
++		public string ImageName { get { return imageName; } }
++		public ClientSideProviderFactoryCallback ClientSideProviderFactoryCallback { 
++			get { return clientSideProviderFactoryCallback; }
++		}
++
++		private string className;
++		private ClientSideProviderFactoryCallback clientSideProviderFactoryCallback;
++		private ClientSideProviderMatchIndicator flags;
++		private string imageName;
+ 	}
+ 
+ 	[Flags]
+@@ -64,5 +71,6 @@
+ 		DisallowBaseClassNameMatch
+ 	}
+ 
+-	public delegate IRawElementProviderSimple ClientSideProviderFactoryCallback (IntPtr hwnd, int idChild, int idObject);
++	public delegate IRawElementProviderSimple ClientSideProviderFactoryCallback (
++		IntPtr hwnd, int idChild, int idObject);
+ }
+Index: mono-uia.git/UIAutomationClient/System.Windows.Automation/SourceManager.cs
+===================================================================
+--- mono-uia.git.orig/UIAutomationClient/System.Windows.Automation/SourceManager.cs	2011-03-06 12:25:27.000000000 +0000
++++ mono-uia.git/UIAutomationClient/System.Windows.Automation/SourceManager.cs	2012-01-23 18:58:44.780520283 +0000
+@@ -29,6 +29,7 @@
+ 
+ using Mono.UIAutomation.Source;
+ using Mono.UIAutomation.Services;
++using Mono.UIAutomation.ClientSource;
+ 
+ namespace System.Windows.Automation
+ {
+@@ -63,6 +64,7 @@
+ 							if (source != null)
+ 								sourcesList.Add (source);
+ 						}
++						sourcesList.Add (ClientAutomationSource.Instance);
+ 						sources = sourcesList.ToArray ();
+ 					}
+ 				}
+Index: mono-uia.git/UIAutomationClientTests/UIAutomationClientTests/BaseTest.cs
+===================================================================
+--- mono-uia.git.orig/UIAutomationClientTests/UIAutomationClientTests/BaseTest.cs	2011-03-06 12:25:27.000000000 +0000
++++ mono-uia.git/UIAutomationClientTests/UIAutomationClientTests/BaseTest.cs	2012-01-23 18:58:44.780520283 +0000
+@@ -471,6 +471,8 @@
+ 
+ 		public static string PrintRuntimeId (int [] runtimeId)
+ 		{
++			if (runtimeId == null)
++				return "(null)";
+ 			StringBuilder sb = new StringBuilder();
+ 			sb.Append ("[");
+ 			foreach (int id in runtimeId)
+Index: mono-uia.git/UIAutomationClientTests/UIAutomationClientTests/LocalProviderTest.cs
+===================================================================
+--- mono-uia.git.orig/UIAutomationClientTests/UIAutomationClientTests/LocalProviderTest.cs	2011-03-06 12:25:27.000000000 +0000
++++ mono-uia.git/UIAutomationClientTests/UIAutomationClientTests/LocalProviderTest.cs	2012-01-23 19:01:38.121289614 +0000
+@@ -38,17 +38,27 @@
+ 	[TestFixture]
+ 	public class LocalProviderTest
+ 	{
++		const int FakeHandle = 12345;
++
++		private AutomationElement simple = null;
++		private AutomationElement simple2 = null;
+ 		private AutomationElement child = null;
+ 		private AutomationElement root = null;
++		private CustomProviderSimple simpleProvider =null;
++		private CustomProviderSimple simpleProvider2 =null;
+ 		private CustomProviderFragment childProvider =null;
+ 		private CustomProviderRoot rootProvider =null;
+ 
+ 		[TestFixtureSetUp]
+ 		public virtual void FixtureSetUp ()
+ 		{
++			simpleProvider = new CustomProviderSimple ();
++			simpleProvider2 = new CustomProviderSimple (FakeHandle);
+ 			childProvider = new CustomProviderFragment (null);
+-			rootProvider = new CustomProviderRoot(childProvider);
++			rootProvider = new CustomProviderRoot (childProvider);
+ 			childProvider.Root = rootProvider;
++			simple = AutomationElement.FromLocalProvider (simpleProvider);
++			simple2 = AutomationElement.FromLocalProvider (simpleProvider2);
+ 			child = AutomationElement.FromLocalProvider(childProvider);
+ 			root = AutomationElement.FromLocalProvider(rootProvider);
+ 		}
+@@ -57,12 +67,93 @@
+ 		[Test]
+ 		public void PropertyTest ()
+ 		{
+-			Assert.AreEqual ("Custom Simple", child.Current.Name);
++			Assert.AreEqual ("Custom Child", child.Current.Name);
+ 			Assert.AreEqual (ControlType.TabItem, child.Current.ControlType);
+ 			Assert.AreEqual ("Custom Root", root.Current.Name);
+ 			Assert.AreEqual (ControlType.Tab, root.Current.ControlType);
+ 		}
+ 
++		// IRawElementFragment's GetRuntimeId method will override
++		// the value returned by GetPropertyValue
++		[Test]
++		public void RuntimeIdOverrideTest ()
++		{
++			var rid1 = root.GetRuntimeId ();
++			var rid2 = (int []) root.GetCurrentPropertyValue (AEIds.RuntimeIdProperty);
++			Assert.AreEqual (rid1, rid2, "rid1 == rid2");
++			Assert.AreEqual (CustomProviderBase.CustomRuntimeIdPrefix, rid1 [0], "Check rid1");
++			Assert.AreEqual (CustomProviderBase.CustomRuntimeIdPrefix, rid2 [0], "Check rid2");
++
++			// RuntimeId is null even if it is explicitly returned by
++			// IRawElementSimple.GetPropertyValue
++			Assert.IsNull (simple.GetRuntimeId (), "simple.GetRuntimeId ()" );
++			Assert.IsNull (simple.GetCurrentPropertyValue (AEIds.RuntimeIdProperty),
++			               "simple.GetGetCurrentPropertyValue (RuntimeId)" );
++
++			// However if the IRawElementSimple has NativeHandleProperty,
++			// then UIA will generate a runtime id for the provider,
++			// on Windows 7 the runtime id is [42, NativeHandleValue]
++			Assert.IsNotNull (simple2.GetRuntimeId (), "simple2.GetRuntimeId ()" );
++		}
++
++		// IRawElementFragment's BoundingRectangle property will override
++		// the value returned by GetPropertyValue
++		[Test]
++		public void BoundingRectangleOverrideTest ()
++		{
++			var bound = root.Current.BoundingRectangle;
++			Assert.AreEqual (200.0, bound.Width, "bound.Width");
++
++			// BoundingRectangle is empty even if it is explicitly returned by
++			// IRawElementSimple.GetPropertyValue
++			Assert.IsTrue (simple.Current.BoundingRectangle.IsEmpty);
++		}
++
++		[Test]
++		public void DefaultPropertyValueTest ()
++		{
++			// LocalizedControlType is compatible with the ControlType though
++			// LocalizedControlType is not explicitly returned by ControlType
++			Assert.AreEqual (ControlType.Tab.LocalizedControlType, root.Current.LocalizedControlType,
++				"root.LocalizedControlType");
++			// IsInvokePatternAvailableProperty is automatically set to true as long as
++			// the pattern can be returned by GetPatternProvider
++			Assert.IsTrue ((bool) child.GetCurrentPropertyValue (AEIds.IsInvokePatternAvailableProperty),
++				"child.IsInvokePatternAvailable");
++			Assert.IsFalse ((bool) root.GetCurrentPropertyValue (AEIds.IsInvokePatternAvailableProperty),
++				"root.IsInvokePatternAvailable");
++		}
++
++		[Test]
++		public void FromPointTest ()
++		{
++			var element = AutomationElement.FromPoint (new SW.Point (100, 100));
++			// though child and root defined their bounds, they won't be returned by
++			// AutomationElement.FromPoint, actually on Windows what returned is the
++			// "Desktop" element.
++			Assert.AreNotEqual (element, child, "child is never returned by FromPoint");
++			Assert.AreNotEqual (element, root, "root is never returned by FromPoint");
++		}
++
++		[Test]
++		public void FromHandleTest ()
++		{
++			BaseTest.AssertRaises <ElementNotAvailableException> (
++				() =>  AutomationElement.FromHandle (new IntPtr (FakeHandle)),
++				"simple2 is never returned by FromHandle");
++		}
++
++		[Test]
++		public void FocusedElementTest ()
++		{
++			BaseTest.AssertRaises <InvalidOperationException> (
++				() => child.SetFocus (), "child.IsKeyboardFocusable is not set");
++			// root.IsKeyboardFocusable is set to ture, so no exception
++			root.SetFocus ();
++			Assert.AreNotEqual (AutomationElement.FocusedElement, root,
++				"root is never returned by FocusedElement");
++		}
++
+ 		[Test]
+ 		public void PatternTest ()
+ 		{
+@@ -112,10 +203,58 @@
+ 		#endregion
+ 	}
+ 
++	internal class CustomProviderSimple : IRawElementProviderSimple
++	{
++		private int handle = -1;
++
++		public CustomProviderSimple ()
++		{
++		}
++
++		public CustomProviderSimple (int handle)
++		{
++			this.handle = handle;
++		}
++
++		#region IRawElementProviderSimple Members
++
++		public virtual object GetPatternProvider (int patternId)
++		{
++			return null;
++		}
++
++		public virtual object GetPropertyValue (int propertyId)
++		{
++			if (propertyId == AEIds.NameProperty.Id)
++				return "Custom Simple";
++			if (propertyId == AEIds.ControlTypeProperty.Id)
++				return ControlType.Pane.Id;
++			else if (propertyId == AEIds.RuntimeIdProperty.Id)
++				return new int[] {1, 2, 3, 4, 5};
++			else if (propertyId == AEIds.BoundingRectangleProperty.Id)
++				return new SW.Rect (0, 0, 1000, 1000);
++			else if (propertyId == AEIds.NativeWindowHandleProperty.Id && handle != -1)
++				return handle;
++			else
++				return null;
++		}
++
++		public IRawElementProviderSimple HostRawElementProvider {
++			get { return null; }
++		}
++
++		public ProviderOptions ProviderOptions {
++			get { return ProviderOptions.ClientSideProvider; }
++		}
++
++		#endregion
++	}
++
+ 	internal class CustomProviderBase : IRawElementProviderFragment
+ 	{
++		public const int CustomRuntimeIdPrefix = 8888;
+ 		private int[] runtimeId = null;
+-		private SW.Rect rect = new SW.Rect (100.0, 100.0, 200.0, 200.0);
++		private SW.Rect bound = new SW.Rect (50.0, 50.0, 200.0, 200.0);
+ 
+ 		public CustomProviderBase (IRawElementProviderFragmentRoot root)
+ 		{
+@@ -127,7 +266,7 @@
+ 		#region IRawElementProviderFragment Members
+ 
+ 		public SW.Rect BoundingRectangle {
+-			get { return rect; }
++			get { return bound; }
+ 		}
+ 
+ 		public IRawElementProviderFragmentRoot FragmentRoot {
+@@ -139,13 +278,12 @@
+ 			return new IRawElementProviderSimple[0];
+ 		}
+ 
+-		public int [] GetRuntimeId ()
++		public int[] GetRuntimeId ()
+ 		{
+-			const int CustomPrefix = 8888;
+ 			if (runtimeId == null) {
+-				byte [] bytes = new Guid ().ToByteArray ();
++				byte [] bytes = Guid.NewGuid ().ToByteArray ();
+ 				runtimeId = new int [bytes.Length + 1];
+-				runtimeId [0] = CustomPrefix;
++				runtimeId [0] = CustomRuntimeIdPrefix;
+ 				for (int i = 0; i < bytes.Length; i++)
+ 					runtimeId [i + 1] = bytes [i];
+ 			}
+@@ -198,11 +336,10 @@
+ 		}
+ 
+ 		public int ClickCount { get; set; }
+-
+-		public void PerformInvoke ()
++		public void PerformInvoke()
+ 		{
+ 			ClickCount++;
+-			AutomationInteropProvider.RaiseAutomationEvent(InvokePattern.InvokedEvent, this,
++			AutomationInteropProvider.RaiseAutomationEvent (InvokePattern.InvokedEvent, this,
+ 				new AutomationEventArgs(InvokePattern.InvokedEvent));
+ 		}
+ 
+@@ -216,7 +353,7 @@
+ 		public override object GetPropertyValue (int propertyId)
+ 		{
+ 			if (propertyId == AEIds.NameProperty.Id)
+-				return "Custom Simple";
++				return "Custom Child";
+ 			else if (propertyId == AEIds.ControlTypeProperty.Id)
+ 				return ControlType.TabItem.Id;
+ 			else
+@@ -283,6 +420,14 @@
+ 				return "Custom Root";
+ 			else if (propertyId == AEIds.ControlTypeProperty.Id)
+ 				return ControlType.Tab.Id;
++			else if (propertyId == AEIds.RuntimeIdProperty.Id)
++				// this return value won't be effective since the base class defined GetRuntimeId method
++				return new int[] {1, 2, 3, 4, 5};
++			else if (propertyId == AEIds.BoundingRectangleProperty.Id)
++				// this return value won't be effective since the base class defined BoundingRectangle property
++				return new SW.Rect (0, 0, 1000, 1000);
++			else if (propertyId == AEIds.IsKeyboardFocusableProperty.Id)
++				return true;
+ 			else
+ 				return base.GetPropertyValue (propertyId);
+ 		}
+Index: mono-uia.git/UIAutomationProvider/System.Windows.Automation.Provider/AutomationInteropProvider.cs
+===================================================================
+--- mono-uia.git.orig/UIAutomationProvider/System.Windows.Automation.Provider/AutomationInteropProvider.cs	2011-03-06 12:25:27.000000000 +0000
++++ mono-uia.git/UIAutomationProvider/System.Windows.Automation.Provider/AutomationInteropProvider.cs	2012-01-23 18:58:44.784520301 +0000
+@@ -123,11 +123,13 @@
+ 			"UiaAtkBridge, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f4ceacb585d99812";
+ 		private static string UiaDbusBridgeAssembly =
+ 			"UiaDbusBridge, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f4ceacb585d99812";
++		private static string clientBridgeAssembly =
++			"UIAutomationClient, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
+ 
+ 		public static IList<IAutomationBridge> GetAutomationBridges ()
+ 		{
+ 			List<IAutomationBridge> bridges = new List<IAutomationBridge> ();
+-			
++
+ 			// Let MONO_UIA_BRIDGE env var override default bridge
+ 			string bridgeAssemblyNames =
+ 				Environment.GetEnvironmentVariable ("MONO_UIA_BRIDGE");
+@@ -135,7 +137,8 @@
+ 			if (string.IsNullOrEmpty (bridgeAssemblyNames))
+ 				bridgeAssemblyNames =
+ 					UiaAtkBridgeAssembly + ";" + UiaDbusBridgeAssembly;
+-			
++			bridgeAssemblyNames += ";" + clientBridgeAssembly;
++
+ 			foreach (string bridgeAssembly in bridgeAssemblyNames.Split (';')) {
+ 				if (string.IsNullOrEmpty (bridgeAssembly))
+ 					continue;
+Index: mono-uia.git/UIAutomationTypes/System.Windows.Automation/AutomationIdentifier.cs
+===================================================================
+--- mono-uia.git.orig/UIAutomationTypes/System.Windows.Automation/AutomationIdentifier.cs	2011-03-06 12:25:27.000000000 +0000
++++ mono-uia.git/UIAutomationTypes/System.Windows.Automation/AutomationIdentifier.cs	2012-01-23 18:58:44.784520301 +0000
+@@ -57,10 +57,14 @@
+ 
+ 		public int CompareTo (object obj)
+ 		{
++			if (obj == null)
++				throw new ArgumentNullException ("obj");
+ 			AutomationIdentifier other =
+ 				obj as AutomationIdentifier;
+ 			if (other == null)
+-				return 1; // TODO: What?
++				// As tested on Windows, when the object is not an AutomationIdentifier,
++				// a strange large integer will be returned, so we just return the MaxValue.
++				return int.MaxValue;
+ 			return id.CompareTo (other.Id);
+ 		}
+ 		
diff --git a/debian/patches/series b/debian/patches/series
index 44313aa..d868d09 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1 +1,2 @@
 0001-uia-Fix-building-with-Mono-2.8.patch
+0001-UIAutomationClient-AutomationElement.FromLocalProvid.patch

-- 
mono-uia



More information about the Pkg-mono-svn-commits mailing list