Beispiel #1
0
		private static void OnSourceRootElementChanged (IAutomationSource source)
		{
			if (inSourceRootElementChanged) {
				pendingRootChangeSources.Enqueue (source);
				return;
			}

			lock (RawViewWalker.directChildrenLock) {
				inSourceRootElementChanged = true;
				List<AutomationElement> rootElements = new List<AutomationElement> ();
				var pidElementMapping = new Dictionary<int, IElement> ();
				foreach (AutomationElement element in RawViewWalker.directChildren) {
					if (element.SourceElement.AutomationSource != source) {
						try {
							pidElementMapping [element.Current.ProcessId] = element.SourceElement;
						} catch { continue; } // TODO: ElementNotAvailableException
						rootElements.Add (element);
					}
				}
				// We don't handle the cleanup of AutomationElements here, they're
				// handled by each AutomationSource.
				// "Clean up" includes removing event handlers etc.
				AddUniqueRootElements (rootElements, source, pidElementMapping);
				RawViewWalker.directChildren = rootElements;
				inSourceRootElementChanged = false;
			}
			Log.Debug ("Root elements are refreshed, Count: {0}", RawViewWalker.directChildren.Count);
			while (pendingRootChangeSources.Count > 0)
				OnSourceRootElementChanged (pendingRootChangeSources.Dequeue ());
		}
Beispiel #2
0
        private static void OnSourceRootElementChanged(IAutomationSource source)
        {
            if (inSourceRootElementChanged)
            {
                pendingRootChangeSources.Enqueue(source);
                return;
            }

            lock (RawViewWalker.directChildrenLock) {
                inSourceRootElementChanged = true;
                List <AutomationElement> rootElements = new List <AutomationElement> ();
                var pidElementMapping = new Dictionary <int, IElement> ();
                foreach (AutomationElement element in RawViewWalker.directChildren)
                {
                    if (element.SourceElement.AutomationSource != source)
                    {
                        try {
                            pidElementMapping [element.Current.ProcessId] = element.SourceElement;
                        } catch { continue; }                         // TODO: ElementNotAvailableException
                        rootElements.Add(element);
                    }
                }
                // We don't handle the cleanup of AutomationElements here, they're
                // handled by each AutomationSource.
                // "Clean up" includes removing event handlers etc.
                AddUniqueRootElements(rootElements, source, pidElementMapping);
                RawViewWalker.directChildren = rootElements;
                inSourceRootElementChanged   = false;
            }
            Log.Debug("Root elements are refreshed, Count: {0}", RawViewWalker.directChildren.Count);
            while (pendingRootChangeSources.Count > 0)
            {
                OnSourceRootElementChanged(pendingRootChangeSources.Dequeue());
            }
        }
Beispiel #3
0
        // TODO: This approach will completely break when the
        //       MoonUiaDbusBridge work is committed. This code
        //       will be replaced with proper source tree merging,
        //       which requires updates to gtk-sharp.
        private static void AddUniqueRootElements(List <AutomationElement> rootElements,
                                                  IAutomationSource source,
                                                  Dictionary <int, IElement> pidElementMapping)
        {
            const string at_spi = "at-spi";

            foreach (IElement sourceElement in source.GetRootElements())
            {
                int    pid;
                string sourceFid;
                try {
                    pid       = sourceElement.ProcessId;
                    sourceFid = sourceElement.FrameworkId;
                } catch { continue; }                 // TODO: ElementNotAvailableException

                // NOTE: This is not a complete mapping, since
                //       one process could generate multiple root
                //       elements. But it's sufficient to catch
                //       that at least one element exists for
                //       a given PID.
                if (pidElementMapping.TryGetValue(pid, out IElement found))
                {
                    string foundFid;
                    try {
                        foundFid = found.FrameworkId;
                    } catch { continue; }                     // TODO: ElementNotAvailableException

                    // Ignore at-spi elements when elements
                    // for this process from a preferred
                    // framework exist
                    if (sourceFid == at_spi &&
                        foundFid != at_spi)
                    {
                        continue;
                    }
                    // Remove at-spi elements when elements
                    // for this process from a preferred
                    // framework exist
                    else if (sourceFid != at_spi &&
                             foundFid == at_spi)
                    {
                        // TODO: When we fix ElementNotAvailableException,
                        //       we'll need to mark these
                        //       elements as unavailable.
                        rootElements.RemoveAll(e => e.Current.ProcessId == pid &&
                                               e.Current.FrameworkId == at_spi);
                    }
                }

                rootElements.Add(SourceManager.GetOrCreateAutomationElement(sourceElement));
                pidElementMapping [pid] = sourceElement;
            }
        }
Beispiel #4
0
        private static IAutomationSource GetAutomationSource(string sourceAssemblyName)
        {
            Assembly sourceAssembly = null;

            try {
                sourceAssembly = Assembly.Load(sourceAssemblyName);
            } catch (Exception e) {
                Log.Warn(string.Format("Error loading UIA source ({0}): {1}",
                                       sourceAssemblyName,
                                       e));
                return(null);
            }

            Type sourceType = null;

            // Quickie inefficent implementation
            Type sourceInterfaceType = typeof(IAutomationSource);

            foreach (Type type in sourceAssembly.GetTypes())
            {
                if (sourceInterfaceType.IsAssignableFrom(type))
                {
                    sourceType = type;
                    break;
                }
            }
            if (sourceType == null)
            {
                Log.Error("No UIA source found in assembly: " +
                          sourceAssemblyName);
                return(null);
            }

            try {
                IAutomationSource source
                    = (IAutomationSource)Activator.CreateInstance(sourceType);
                if (!source.IsAccessibilityEnabled)
                {
                    return(null);
                }

                source.Initialize();
                return(source);
            } catch (Exception e) {
                Log.Error("Failed to load UIA source: " + e);
                return(null);
            }
        }
Beispiel #5
0
        internal static IAutomationSource [] GetAutomationSources()
        {
            if (sources == null)
            {
                lock (sourcesLock) {
                    if (sources == null)
                    {
                        var sourcesList = new List <IAutomationSource> ();

                        // Let MONO_UIA_SOURCE env var override default source
                        string sourceAssemblyNames =
                            Environment.GetEnvironmentVariable("MONO_UIA_SOURCE");

                        if (string.IsNullOrEmpty(sourceAssemblyNames))
                        {
                            sourceAssemblyNames =
                                UiaDbusSourceAssembly + ";" + AtspiUiaSourceAssembly;
                        }

                        foreach (string sourceAssembly in sourceAssemblyNames.Split(';'))
                        {
                            if (string.IsNullOrEmpty(sourceAssembly))
                            {
                                continue;
                            }
                            IAutomationSource source = GetAutomationSource(sourceAssembly);
                            if (source != null)
                            {
                                sourcesList.Add(source);
                            }
                        }
                        sourcesList.Add(ClientAutomationSource.Instance);
                        sources = sourcesList.ToArray();
                    }
                }
            }
            return(sources);
        }
Beispiel #6
0
		// TODO: This approach will completely break when the
		//       MoonUiaDbusBridge work is committed. This code
		//       will be replaced with proper source tree merging,
		//       which requires updates to gtk-sharp.
		private static void AddUniqueRootElements (List<AutomationElement> rootElements,
		                                           IAutomationSource source,
		                                           Dictionary<int, IElement> pidElementMapping)
		{
			const string at_spi = "at-spi";
			foreach (IElement sourceElement in source.GetRootElements ()) {
				int pid;
				try {
					pid = sourceElement.ProcessId;
				} catch { continue; } // TODO: ElementNotAvailableException

				IElement found;
				// NOTE: This is not a complete mapping, since
				//       one process could generate multiple root
				//       elements. But it's sufficient to catch
				//       that at least one element exists for
				//       a given PID.
				if (pidElementMapping.TryGetValue (pid, out found)) {
					var sourceFid = sourceElement.FrameworkId;
					var foundFid = found.FrameworkId;
					// Ignore at-spi elements when elements
					// for this process from a preferred
					// framework exist
					if (sourceFid == at_spi &&
					    foundFid != at_spi)
						continue;
					// Remove at-spi elements when elements
					// for this process from a preferred
					// framework exist
					else if (sourceFid != at_spi &&
					         foundFid == at_spi) {
						// TODO: When we fix ElementNotAvailableException,
						//       we'll need to mark these
						//       elements as unavailable.
						rootElements.RemoveAll (e => e.Current.ProcessId == pid &&
						                        e.Current.FrameworkId == at_spi);
					}
				}

				rootElements.Add (
					SourceManager.GetOrCreateAutomationElement (sourceElement));
				pidElementMapping [pid] = sourceElement;
			}
		}