Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Core / CSharp / System / Windows / PresentationSource.cs / 1 / PresentationSource.cs
using System;
using System.Collections;
using System.Diagnostics;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Windows.Threading;
using System.Security;
using System.Security.Permissions;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using System.Windows.Markup;
using System.Windows.Input;
using MS.Win32;
using MS.Utility;
using MS.Internal;
using MS.Internal.PresentationCore; // SecurityHelper
using SR=MS.Internal.PresentationCore.SR;
using SRID=MS.Internal.PresentationCore.SRID;
namespace System.Windows
{
///
/// PresentationSource is the abstract base for classes that
/// present content in another technology. In addition, this
/// class provides static methods for working with these sources.
///
///
/// We currently have one implementation - HwndSource - that
/// presents content in a Win32 HWND.
///
///
/// Keep this from being derived from in partial-trust code.
///
[UIPermissionAttribute(SecurityAction.InheritanceDemand,Unrestricted=true)]
public abstract class PresentationSource : DispatcherObject
{
//------------------------------------------------------
//
// Constructors
//
//-----------------------------------------------------
#region Constructors
///
/// Constructs an instance of the PresentationSource object.
///
///
/// This is protected since this is an abstract base class.
///
protected PresentationSource()
{
}
///
/// This constructor exists since the code gen for managed code generates a static constructor
/// and in that code it initializes a critical field which causes an fxcop violation for the codegen
/// constructor.
///
[SecurityCritical]
static PresentationSource()
{
}
#endregion
//-----------------------------------------------------
//
// Public Methods
//
//-----------------------------------------------------
#region Public Methods
///
/// InputProvider given the Device type.
///
///
/// Critical: Sub classing this can let you provide fake input providers which
/// can compromise the input system
///
[SecurityCritical]
[UIPermissionAttribute(SecurityAction.InheritanceDemand, Unrestricted = true)]
internal virtual IInputProvider GetInputProvider(Type inputDevice)
{
return null;
}
#endregion
//------------------------------------------------------
//
// Public Static Methods
//
//-----------------------------------------------------
#region Public Static Methods
///
/// Returns the source in which the visual is being presented.
///
/// The visual to find the source for.
/// The source in which the visual is being presented.
///
/// Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
///
///
/// Critical - calls CriticalFromVisual. and returns the PresentationSource
/// PublicOK: There exists a demand
///
[SecurityCritical]
public static PresentationSource FromVisual(Visual visual)
{
SecurityHelper.DemandUIWindowPermission();
return CriticalFromVisual(visual);
}
///
/// Returns the source in which the Visual or Visual3D is being presented.
///
/// The dependency object to find the source for.
/// The source in which the dependency object is being presented.
///
/// Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
///
///
/// Critical - calls CriticalFromVisual. and returns the PresentationSource
/// PublicOK: There exists a demand
///
[SecurityCritical]
public static PresentationSource FromDependencyObject(DependencyObject dependencyObject)
{
SecurityHelper.DemandUIWindowPermission();
return CriticalFromVisual(dependencyObject);
}
///
/// Adds a handler for the SourceChanged event to the element.
///
/// The element to add the handler too.
/// The hander to add.
///
/// Even though this is a routed event handler, there are special
/// restrictions placed on this event.
/// 1) You cannot use the UIElement or ContentElement AddHandler() method.
/// 2) Class handlers are not allowed.
/// 3) The handlers will receive the SourceChanged event even if it was handled.
/// Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
///
///
/// Critical: This code lets you get access to a presentationSource object. Here the link demand
/// is defense in depth since , the object by itself has all public properties blocked off. Also this
/// is part of startup code.
///
[SecurityCritical]
[UIPermissionAttribute(SecurityAction.LinkDemand,Window=UIPermissionWindow.AllWindows)]
public static void AddSourceChangedHandler(IInputElement element, SourceChangedEventHandler handler)
{
if (element == null)
{
throw new ArgumentNullException("element");
}
// Either UIElement or ContentElement
if (!InputElement.IsValid(element))
{
throw new ArgumentException(SR.Get(SRID.Invalid_IInputElement), "element");
}
DependencyObject o = (DependencyObject)element;
// o.VerifyAccess();
// I would rather throw an exception here, but the CLR doesn't
// so we won't either.
if (handler != null)
{
FrugalObjectList info;
if (InputElement.IsUIElement(o))
{
UIElement uie = o as UIElement;
uie.AddHandler(SourceChangedEvent, handler);
info = uie.EventHandlersStore[SourceChangedEvent];
if (1 == info.Count)
{
uie.VisualAncestorChanged += new Visual.AncestorChangedEventHandler(uie.OnVisualAncestorChanged);
AddElementToWatchList(uie);
}
}
else if (InputElement.IsUIElement3D(o))
{
UIElement3D uie3D = o as UIElement3D;
uie3D.AddHandler(SourceChangedEvent, handler);
info = uie3D.EventHandlersStore[SourceChangedEvent];
if (1 == info.Count)
{
uie3D.VisualAncestorChanged += new Visual.AncestorChangedEventHandler(uie3D.OnVisualAncestorChanged);
AddElementToWatchList(uie3D);
}
}
else
{
ContentElement ce = o as ContentElement;
ce.AddHandler(SourceChangedEvent, handler);
info = ce.EventHandlersStore[SourceChangedEvent];
if (1 == info.Count)
AddElementToWatchList(ce);
}
}
}
///
/// Removes a handler for the SourceChanged event to the element.
///
/// The element to remove the handler from.
/// The hander to remove.
///
/// Even though this is a routed event handler, there are special
/// restrictions placed on this event.
/// 1) You cannot use the UIElement or ContentElement RemoveHandler() method.
///
public static void RemoveSourceChangedHandler(IInputElement e, SourceChangedEventHandler handler)
{
if (e == null)
{
throw new ArgumentNullException("e");
}
if (!InputElement.IsValid(e))
{
throw new ArgumentException(SR.Get(SRID.Invalid_IInputElement), "e");
}
DependencyObject o = (DependencyObject)e;
// o.VerifyAccess();
// I would rather throw an exception here, but the CLR doesn't
// so we won't either.
if (handler != null)
{
FrugalObjectList info = null;
EventHandlersStore store;
// Either UIElement or ContentElement.
if (InputElement.IsUIElement(o))
{
UIElement uie = o as UIElement;
uie.RemoveHandler(SourceChangedEvent, handler);
store = uie.EventHandlersStore;
if (store != null)
{
info = store[SourceChangedEvent];
}
if (info == null || info.Count == 0)
{
uie.VisualAncestorChanged -= new Visual.AncestorChangedEventHandler(uie.OnVisualAncestorChanged); ;
RemoveElementFromWatchList(uie);
}
}
else if (InputElement.IsUIElement3D(o))
{
UIElement3D uie3D = o as UIElement3D;
uie3D.RemoveHandler(SourceChangedEvent, handler);
store = uie3D.EventHandlersStore;
if (store != null)
{
info = store[SourceChangedEvent];
}
if (info == null || info.Count == 0)
{
uie3D.VisualAncestorChanged -= new Visual.AncestorChangedEventHandler(uie3D.OnVisualAncestorChanged); ;
RemoveElementFromWatchList(uie3D);
}
}
else
{
ContentElement ce = o as ContentElement;
ce.RemoveHandler(SourceChangedEvent, handler);
store = ce.EventHandlersStore;
if (store != null)
{
info = store[SourceChangedEvent];
}
if (info == null || info.Count == 0)
{
RemoveElementFromWatchList(ce);
}
}
}
}
///
/// Called by FrameworkElements when a framework ancenstor link of
/// ContentElement has changed.
///
///
/// The element whose ancestory may have changed.
///
///
/// This API is not available in the internet zone.It was protected
/// as defense in depth since we did not want the PresentationSource
/// surface to be exposed.
///
[SecurityCritical]
[UIPermissionAttribute(SecurityAction.LinkDemand,Window=UIPermissionWindow.AllWindows)]
[FriendAccessAllowed] // Built into Core, also used by Framework.
internal static void OnAncestorChanged(ContentElement ce)
{
if (ce == null)
{
throw new ArgumentNullException("ce");
}
if (true == (bool)ce.GetValue(GetsSourceChangedEventProperty))
{
UpdateSourceOfElement(ce, null, null);
}
}
#endregion
//------------------------------------------------------
//
// Public Properties
//
//------------------------------------------------------
#region Public Properties
///
/// The visual target for the visuals being presented in the source.
///
///
/// Critical: Calls GetCompositionTargetCore() and returns a CompositionTarget object, which is considered critical.
/// PublicOk: Protected by a LinkDemand
///
public CompositionTarget CompositionTarget
{
[UIPermissionAttribute(SecurityAction.LinkDemand,Window=UIPermissionWindow.AllWindows)]
[SecurityCritical]
get
{
return GetCompositionTargetCore();
}
}
///
/// The root visual being presented in the source.
///
///
/// Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
///
///
/// Critical: This code is not safe to expose publicly since it lets you
/// change rootvisual which puts popup code at risk
/// PublicOK: Inheritance demand prevents random subclassing in partial trust
/// and Linkdemand prevents unauthorized public callers
///
public abstract Visual RootVisual
{
get;
[SecurityCritical]
[UIPermissionAttribute(SecurityAction.InheritanceDemand, Window = UIPermissionWindow.AllWindows)]
[UIPermissionAttribute(SecurityAction.LinkDemand, Window = UIPermissionWindow.AllWindows)]
set;
}
///
/// Whether or not the object is disposed.
///
public abstract bool IsDisposed
{
get;
}
#endregion
//-----------------------------------------------------
//
// Public Static Properties
//
//------------------------------------------------------
#region Public Static Properties
///
/// Return a WeakReferenceList which supports returning an Enumerator
/// over a ReadOnly SnapShot of the List of sources. The Enumerator
/// skips over the any dead weak references in the list.
///
///
/// Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
///
///
/// Critical: This code exposes the sources which are deemed as critical. This is defense in depth.
/// PublicOK: There exists a demand in this code
///
public static IEnumerable CurrentSources
{
[SecurityCritical]
get
{
SecurityHelper.DemandUIWindowPermission();
return CriticalCurrentSources;
}
}
#endregion
//-----------------------------------------------------
//
// Public Events
//
//-----------------------------------------------------
#region Public Events
///
/// This event fires when content is rendered and ready for user interaction.
///
public event EventHandler ContentRendered;
#endregion
//-----------------------------------------------------
//
// Protected Methods
//
//------------------------------------------------------
#region Protected Methods
///
/// Returns visual target for the given source. Implemented by
/// the derived class.
///
protected abstract CompositionTarget GetCompositionTargetCore();
//
[SecurityCritical, SecurityTreatAsSafe]
protected void RootChanged(Visual oldRoot, Visual newRoot)
{
PresentationSource oldSource = null;
if (oldRoot == newRoot)
{
return;
}
// Always clear the RootSourceProperty on the old root.
if (oldRoot != null)
{
oldSource = CriticalGetPresentationSourceFromElement(oldRoot, RootSourceProperty);
oldRoot.ClearValue(RootSourceProperty);
}
// Always set the SourceProperty on the new root.
if (newRoot != null)
{
newRoot.SetValue(RootSourceProperty, new SecurityCriticalDataForMultipleGetAndSet(this));
}
UIElement oldRootUIElement = oldRoot as UIElement;
UIElement newRootUIElement = newRoot as UIElement;
// The IsVisible property can only be true if root visual is connected to a presentation source.
// For Read-Only force-inherited properties, use a private update method.
if(oldRootUIElement != null)
{
oldRootUIElement.UpdateIsVisibleCache();
}
if(newRootUIElement != null)
{
newRootUIElement.UpdateIsVisibleCache();
}
// Broadcast the Unloaded event starting at the old root visual
if (oldRootUIElement != null)
{
oldRootUIElement.OnPresentationSourceChanged(false);
}
// Broadcast the Loaded event starting at the root visual
if (newRootUIElement != null)
{
newRootUIElement.OnPresentationSourceChanged(true);
}
// To fire PresentationSourceChanged when the RootVisual changes;
// rather than simulate a "parent" pointer change, we just walk the
// collection of all nodes that need the event.
foreach (DependencyObject element in _watchers)
{
// We only need to update those elements that are in the
// same context as this presentation source.
if (element.Dispatcher == Dispatcher)
{
PresentationSource testSource = CriticalGetPresentationSourceFromElement(element,CachedSourceProperty);
// 1) If we are removing the rootvisual, then fire on any node whos old
// PresetationSource was the oldSource.
// 2) If we are attaching a rootvisual then fire on any node whos old
// PresentationSource is null;
if (oldSource == testSource || null == testSource)
{
UpdateSourceOfElement(element, null, null);
}
}
}
}
///
/// Called by derived classes to indicate that they need to be tracked.
///
protected void AddSource()
{
_sources.Add(this);
}
///
/// Called by derived classes to indicate that they no longer need to be tracked.
///
protected void RemoveSource()
{
_sources.Remove(this);
}
///
/// Sets the ContentRendered event to null.
///
protected void ClearContentRenderedListeners()
{
ContentRendered = null;
}
#endregion
//-----------------------------------------------------
//
// Internal Methods
//
//------------------------------------------------------
// None
//------------------------------------------------------
//
// Internal Static Methods
//
//-----------------------------------------------------
#region Internal Static Methods
///
/// Called by UIElement(3D)s when a visual ancestor link has changed.
///
/// The UIElement whose ancestory may have changed.
/// Event Args.
///
/// Critical: This code calls into a critical code path UpdateSourceOfElement.
/// TreatAsSafe: This code does not access any critical data itself and does not expose
/// anything
///
[SecurityCritical, SecurityTreatAsSafe]
internal static void OnVisualAncestorChanged(DependencyObject uie, AncestorChangedEventArgs e)
{
Debug.Assert(InputElement.IsUIElement3D(uie) || InputElement.IsUIElement(uie));
if (true == (bool)uie.GetValue(GetsSourceChangedEventProperty))
{
UpdateSourceOfElement(uie, e.Ancestor, e.OldParent);
}
}
///
/// Critical - Returns the PresentationSource
///
[FriendAccessAllowed] // To allow internal code paths to access this function
[SecurityCritical]
internal static PresentationSource CriticalFromVisual(DependencyObject v)
{
return CriticalFromVisual(v, true /* enable2DTo3DTransition */);
}
///
/// Critical - uses RootSourceProperty. and returns the PresentationSource
///
/// The dependency object to find the source for
///
/// Determines whether when walking the tree to enable transitioning from a 2D child
/// to a 3D parent or to stop once a 3D parent is encountered.
///
[FriendAccessAllowed] // To allow internal code paths to access this function
[SecurityCritical]
internal static PresentationSource CriticalFromVisual(DependencyObject v, bool enable2DTo3DTransition)
{
if (v == null)
{
throw new ArgumentNullException("v");
}
PresentationSource source = FindSource(v, enable2DTo3DTransition);
// Don't hand out a disposed source.
if (null != source && source.IsDisposed)
{
source = null;
}
return source;
}
///
/// Fire the event when content is rendered and ready for user interaction.
///
///
internal static object FireContentRendered(object arg)
{
PresentationSource ps = (PresentationSource)arg;
if (ps.ContentRendered != null)
{
ps.ContentRendered(arg, EventArgs.Empty);
}
return null;
}
#endregion
//------------------------------------------------------
//
// Internal Properties
//
//-----------------------------------------------------
// None
//-----------------------------------------------------
//
// Internal Events
//
//-----------------------------------------------------
// None
//------------------------------------------------------
//
// Private Static Methods
//
//-----------------------------------------------------
#region Private Static Methods
///
/// Return a WeakReferenceList which supports returning an Enumerator
/// over a ReadOnly SnapShot of the List of sources. The Enumerator
/// skips over the any dead weak references in the list.
///
///
/// Critical: This code exposes the sources which are deemed as critical. This is internal access point.
/// Public consumers should use CurrentSources
///
internal static IEnumerable CriticalCurrentSources
{
[SecurityCritical]
get
{
return (IEnumerable)_sources;
}
}
///
/// Critical: Returns a presentationsource given a canister
///
[SecurityCritical]
private static PresentationSource CriticalGetPresentationSourceFromElement(DependencyObject dObject,DependencyProperty dp)
{
PresentationSource testSource;
SecurityCriticalDataForMultipleGetAndSet tempCriticalDataWrapper =
(SecurityCriticalDataForMultipleGetAndSet < PresentationSource > )
dObject.GetValue(dp);
if (tempCriticalDataWrapper == null || tempCriticalDataWrapper.Value == null)
{
testSource = null;
}
else
{
testSource = tempCriticalDataWrapper.Value;
}
return testSource;
}
///
/// Critical: This code acceses PresentationSource and stores it.
///
[SecurityCritical]
private static void AddElementToWatchList(DependencyObject element)
{
if(_watchers.Add(element))
{
element.SetValue(CachedSourceProperty,new
SecurityCriticalDataForMultipleGetAndSet(PresentationSource.FindSource(element)));
element.SetValue(GetsSourceChangedEventProperty, true);
}
}
///
/// Critical: This code acceses PresentationSource
/// TreatAsSafe: This code is safe to expose.
///
[SecurityCritical,SecurityTreatAsSafe]
private static void RemoveElementFromWatchList(DependencyObject element)
{
if(_watchers.Remove(element))
{
element.ClearValue(CachedSourceProperty);
element.ClearValue(GetsSourceChangedEventProperty);
}
}
///
/// Critical - Returns a PresentationSource.
///
[SecurityCritical]
private static PresentationSource FindSource(DependencyObject o)
{
return FindSource(o, true /* enable2DTo3DTransition */);
}
///
/// Critical - uses RootSourceProperty and returns the PresentationSource
///
/// The dependency object to find the source for
///
/// Determines whether when walking the tree to enable transitioning from a 2D child
/// to a 3D parent or to stop once a 3D parent is encountered.
///
[SecurityCritical]
private static PresentationSource FindSource(DependencyObject o, bool enable2DTo3DTransition)
{
PresentationSource source = null;
// For "Visual" nodes GetRootVisual() climbs to the top of the
// visual tree (parent==null)
// For "ContentElements" it climbs the logical parent until it
// reaches a visual then climbs to the top of the visual tree.
DependencyObject v = InputElement.GetRootVisual(o, enable2DTo3DTransition);
if (v != null)
{
source = CriticalGetPresentationSourceFromElement(v, RootSourceProperty);
}
return source;
}
///
/// Critical: This code accesses PresentationSource which is a critical resource. It then
/// packages it into an event args and fires it into the tree.
///
[SecurityCritical]
private static bool UpdateSourceOfElement(DependencyObject doTarget,
DependencyObject doAncestor,
DependencyObject doOldParent)
{
bool calledOut = false;
PresentationSource realSource = FindSource(doTarget);
PresentationSource cachedSource = CriticalGetPresentationSourceFromElement(doTarget, CachedSourceProperty);
if (cachedSource != realSource)
{
doTarget.SetValue(CachedSourceProperty, new SecurityCriticalDataForMultipleGetAndSet(realSource));
SourceChangedEventArgs args = new SourceChangedEventArgs(cachedSource, realSource);
args.RoutedEvent=SourceChangedEvent;
if (InputElement.IsUIElement(doTarget))
{
((UIElement)doTarget).RaiseEvent(args);
}
else if (InputElement.IsContentElement(doTarget))
{
((ContentElement)doTarget).RaiseEvent(args);
}
else
{
((UIElement3D)doTarget).RaiseEvent(args);
}
calledOut = true;
}
return calledOut;
}
#endregion
//------------------------------------------------------
//
// Private Static Members
//
//------------------------------------------------------
#region Private Static Members
// We use a private DP for the RootSource (the connection from the root
// element in a tree to the source it is displayed in). Use the public
// API FromVisual to get the source that a visual is displayed in.
///
/// Critical - used to store PresentationSource
///
[SecurityCritical]
private static readonly DependencyProperty RootSourceProperty
= DependencyProperty.RegisterAttached("RootSource", typeof(SecurityCriticalDataForMultipleGetAndSet), typeof(PresentationSource),
new PropertyMetadata((SecurityCriticalDataForMultipleGetAndSet)null));
// We use a private DP for the CachedSource (stored on the elements
// that we are watching, so that we can send a change notification).
// Use the public API FromVisual to get the source that a visual is
// displayed in.
///
/// Critical - used to store PresentationSource
///
[SecurityCritical]
private static readonly DependencyProperty CachedSourceProperty
= DependencyProperty.RegisterAttached("CachedSource", typeof(SecurityCriticalDataForMultipleGetAndSet), typeof(PresentationSource),
new PropertyMetadata((SecurityCriticalDataForMultipleGetAndSet)null));
// We use a private DP to mark elements that we are watchin.
private static readonly DependencyProperty GetsSourceChangedEventProperty = DependencyProperty.RegisterAttached("IsBeingWatched", typeof(bool), typeof(PresentationSource), new PropertyMetadata((bool)false));
// We use a private direct-only event to notify elements of when the
// source changes. Use the public APIs AddSourceChangedHandler and
// RemoveSourceChangedHandler to listen to this event.
private static readonly RoutedEvent SourceChangedEvent = EventManager.RegisterRoutedEvent("SourceChanged", RoutingStrategy.Direct, typeof(SourceChangedEventHandler), typeof(PresentationSource));
// The lock we use to protect our static data.
private static object _globalLock = new object();
// An array of weak-references to sources that we know about.
private static WeakReferenceList _sources = new WeakReferenceList(_globalLock);
// An array of weak-references to elements that need to know
// about source changes.
private static WeakReferenceList _watchers = new WeakReferenceList(_globalLock);
#endregion
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
using System;
using System.Collections;
using System.Diagnostics;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Windows.Threading;
using System.Security;
using System.Security.Permissions;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using System.Windows.Markup;
using System.Windows.Input;
using MS.Win32;
using MS.Utility;
using MS.Internal;
using MS.Internal.PresentationCore; // SecurityHelper
using SR=MS.Internal.PresentationCore.SR;
using SRID=MS.Internal.PresentationCore.SRID;
namespace System.Windows
{
///
/// PresentationSource is the abstract base for classes that
/// present content in another technology. In addition, this
/// class provides static methods for working with these sources.
///
///
/// We currently have one implementation - HwndSource - that
/// presents content in a Win32 HWND.
///
///
/// Keep this from being derived from in partial-trust code.
///
[UIPermissionAttribute(SecurityAction.InheritanceDemand,Unrestricted=true)]
public abstract class PresentationSource : DispatcherObject
{
//------------------------------------------------------
//
// Constructors
//
//-----------------------------------------------------
#region Constructors
///
/// Constructs an instance of the PresentationSource object.
///
///
/// This is protected since this is an abstract base class.
///
protected PresentationSource()
{
}
///
/// This constructor exists since the code gen for managed code generates a static constructor
/// and in that code it initializes a critical field which causes an fxcop violation for the codegen
/// constructor.
///
[SecurityCritical]
static PresentationSource()
{
}
#endregion
//-----------------------------------------------------
//
// Public Methods
//
//-----------------------------------------------------
#region Public Methods
///
/// InputProvider given the Device type.
///
///
/// Critical: Sub classing this can let you provide fake input providers which
/// can compromise the input system
///
[SecurityCritical]
[UIPermissionAttribute(SecurityAction.InheritanceDemand, Unrestricted = true)]
internal virtual IInputProvider GetInputProvider(Type inputDevice)
{
return null;
}
#endregion
//------------------------------------------------------
//
// Public Static Methods
//
//-----------------------------------------------------
#region Public Static Methods
///
/// Returns the source in which the visual is being presented.
///
/// The visual to find the source for.
/// The source in which the visual is being presented.
///
/// Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
///
///
/// Critical - calls CriticalFromVisual. and returns the PresentationSource
/// PublicOK: There exists a demand
///
[SecurityCritical]
public static PresentationSource FromVisual(Visual visual)
{
SecurityHelper.DemandUIWindowPermission();
return CriticalFromVisual(visual);
}
///
/// Returns the source in which the Visual or Visual3D is being presented.
///
/// The dependency object to find the source for.
/// The source in which the dependency object is being presented.
///
/// Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
///
///
/// Critical - calls CriticalFromVisual. and returns the PresentationSource
/// PublicOK: There exists a demand
///
[SecurityCritical]
public static PresentationSource FromDependencyObject(DependencyObject dependencyObject)
{
SecurityHelper.DemandUIWindowPermission();
return CriticalFromVisual(dependencyObject);
}
///
/// Adds a handler for the SourceChanged event to the element.
///
/// The element to add the handler too.
/// The hander to add.
///
/// Even though this is a routed event handler, there are special
/// restrictions placed on this event.
/// 1) You cannot use the UIElement or ContentElement AddHandler() method.
/// 2) Class handlers are not allowed.
/// 3) The handlers will receive the SourceChanged event even if it was handled.
/// Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
///
///
/// Critical: This code lets you get access to a presentationSource object. Here the link demand
/// is defense in depth since , the object by itself has all public properties blocked off. Also this
/// is part of startup code.
///
[SecurityCritical]
[UIPermissionAttribute(SecurityAction.LinkDemand,Window=UIPermissionWindow.AllWindows)]
public static void AddSourceChangedHandler(IInputElement element, SourceChangedEventHandler handler)
{
if (element == null)
{
throw new ArgumentNullException("element");
}
// Either UIElement or ContentElement
if (!InputElement.IsValid(element))
{
throw new ArgumentException(SR.Get(SRID.Invalid_IInputElement), "element");
}
DependencyObject o = (DependencyObject)element;
// o.VerifyAccess();
// I would rather throw an exception here, but the CLR doesn't
// so we won't either.
if (handler != null)
{
FrugalObjectList info;
if (InputElement.IsUIElement(o))
{
UIElement uie = o as UIElement;
uie.AddHandler(SourceChangedEvent, handler);
info = uie.EventHandlersStore[SourceChangedEvent];
if (1 == info.Count)
{
uie.VisualAncestorChanged += new Visual.AncestorChangedEventHandler(uie.OnVisualAncestorChanged);
AddElementToWatchList(uie);
}
}
else if (InputElement.IsUIElement3D(o))
{
UIElement3D uie3D = o as UIElement3D;
uie3D.AddHandler(SourceChangedEvent, handler);
info = uie3D.EventHandlersStore[SourceChangedEvent];
if (1 == info.Count)
{
uie3D.VisualAncestorChanged += new Visual.AncestorChangedEventHandler(uie3D.OnVisualAncestorChanged);
AddElementToWatchList(uie3D);
}
}
else
{
ContentElement ce = o as ContentElement;
ce.AddHandler(SourceChangedEvent, handler);
info = ce.EventHandlersStore[SourceChangedEvent];
if (1 == info.Count)
AddElementToWatchList(ce);
}
}
}
///
/// Removes a handler for the SourceChanged event to the element.
///
/// The element to remove the handler from.
/// The hander to remove.
///
/// Even though this is a routed event handler, there are special
/// restrictions placed on this event.
/// 1) You cannot use the UIElement or ContentElement RemoveHandler() method.
///
public static void RemoveSourceChangedHandler(IInputElement e, SourceChangedEventHandler handler)
{
if (e == null)
{
throw new ArgumentNullException("e");
}
if (!InputElement.IsValid(e))
{
throw new ArgumentException(SR.Get(SRID.Invalid_IInputElement), "e");
}
DependencyObject o = (DependencyObject)e;
// o.VerifyAccess();
// I would rather throw an exception here, but the CLR doesn't
// so we won't either.
if (handler != null)
{
FrugalObjectList info = null;
EventHandlersStore store;
// Either UIElement or ContentElement.
if (InputElement.IsUIElement(o))
{
UIElement uie = o as UIElement;
uie.RemoveHandler(SourceChangedEvent, handler);
store = uie.EventHandlersStore;
if (store != null)
{
info = store[SourceChangedEvent];
}
if (info == null || info.Count == 0)
{
uie.VisualAncestorChanged -= new Visual.AncestorChangedEventHandler(uie.OnVisualAncestorChanged); ;
RemoveElementFromWatchList(uie);
}
}
else if (InputElement.IsUIElement3D(o))
{
UIElement3D uie3D = o as UIElement3D;
uie3D.RemoveHandler(SourceChangedEvent, handler);
store = uie3D.EventHandlersStore;
if (store != null)
{
info = store[SourceChangedEvent];
}
if (info == null || info.Count == 0)
{
uie3D.VisualAncestorChanged -= new Visual.AncestorChangedEventHandler(uie3D.OnVisualAncestorChanged); ;
RemoveElementFromWatchList(uie3D);
}
}
else
{
ContentElement ce = o as ContentElement;
ce.RemoveHandler(SourceChangedEvent, handler);
store = ce.EventHandlersStore;
if (store != null)
{
info = store[SourceChangedEvent];
}
if (info == null || info.Count == 0)
{
RemoveElementFromWatchList(ce);
}
}
}
}
///
/// Called by FrameworkElements when a framework ancenstor link of
/// ContentElement has changed.
///
///
/// The element whose ancestory may have changed.
///
///
/// This API is not available in the internet zone.It was protected
/// as defense in depth since we did not want the PresentationSource
/// surface to be exposed.
///
[SecurityCritical]
[UIPermissionAttribute(SecurityAction.LinkDemand,Window=UIPermissionWindow.AllWindows)]
[FriendAccessAllowed] // Built into Core, also used by Framework.
internal static void OnAncestorChanged(ContentElement ce)
{
if (ce == null)
{
throw new ArgumentNullException("ce");
}
if (true == (bool)ce.GetValue(GetsSourceChangedEventProperty))
{
UpdateSourceOfElement(ce, null, null);
}
}
#endregion
//------------------------------------------------------
//
// Public Properties
//
//------------------------------------------------------
#region Public Properties
///
/// The visual target for the visuals being presented in the source.
///
///
/// Critical: Calls GetCompositionTargetCore() and returns a CompositionTarget object, which is considered critical.
/// PublicOk: Protected by a LinkDemand
///
public CompositionTarget CompositionTarget
{
[UIPermissionAttribute(SecurityAction.LinkDemand,Window=UIPermissionWindow.AllWindows)]
[SecurityCritical]
get
{
return GetCompositionTargetCore();
}
}
///
/// The root visual being presented in the source.
///
///
/// Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
///
///
/// Critical: This code is not safe to expose publicly since it lets you
/// change rootvisual which puts popup code at risk
/// PublicOK: Inheritance demand prevents random subclassing in partial trust
/// and Linkdemand prevents unauthorized public callers
///
public abstract Visual RootVisual
{
get;
[SecurityCritical]
[UIPermissionAttribute(SecurityAction.InheritanceDemand, Window = UIPermissionWindow.AllWindows)]
[UIPermissionAttribute(SecurityAction.LinkDemand, Window = UIPermissionWindow.AllWindows)]
set;
}
///
/// Whether or not the object is disposed.
///
public abstract bool IsDisposed
{
get;
}
#endregion
//-----------------------------------------------------
//
// Public Static Properties
//
//------------------------------------------------------
#region Public Static Properties
///
/// Return a WeakReferenceList which supports returning an Enumerator
/// over a ReadOnly SnapShot of the List of sources. The Enumerator
/// skips over the any dead weak references in the list.
///
///
/// Callers must have UIPermission(UIPermissionWindow.AllWindows) to call this API.
///
///
/// Critical: This code exposes the sources which are deemed as critical. This is defense in depth.
/// PublicOK: There exists a demand in this code
///
public static IEnumerable CurrentSources
{
[SecurityCritical]
get
{
SecurityHelper.DemandUIWindowPermission();
return CriticalCurrentSources;
}
}
#endregion
//-----------------------------------------------------
//
// Public Events
//
//-----------------------------------------------------
#region Public Events
///
/// This event fires when content is rendered and ready for user interaction.
///
public event EventHandler ContentRendered;
#endregion
//-----------------------------------------------------
//
// Protected Methods
//
//------------------------------------------------------
#region Protected Methods
///
/// Returns visual target for the given source. Implemented by
/// the derived class.
///
protected abstract CompositionTarget GetCompositionTargetCore();
//
[SecurityCritical, SecurityTreatAsSafe]
protected void RootChanged(Visual oldRoot, Visual newRoot)
{
PresentationSource oldSource = null;
if (oldRoot == newRoot)
{
return;
}
// Always clear the RootSourceProperty on the old root.
if (oldRoot != null)
{
oldSource = CriticalGetPresentationSourceFromElement(oldRoot, RootSourceProperty);
oldRoot.ClearValue(RootSourceProperty);
}
// Always set the SourceProperty on the new root.
if (newRoot != null)
{
newRoot.SetValue(RootSourceProperty, new SecurityCriticalDataForMultipleGetAndSet(this));
}
UIElement oldRootUIElement = oldRoot as UIElement;
UIElement newRootUIElement = newRoot as UIElement;
// The IsVisible property can only be true if root visual is connected to a presentation source.
// For Read-Only force-inherited properties, use a private update method.
if(oldRootUIElement != null)
{
oldRootUIElement.UpdateIsVisibleCache();
}
if(newRootUIElement != null)
{
newRootUIElement.UpdateIsVisibleCache();
}
// Broadcast the Unloaded event starting at the old root visual
if (oldRootUIElement != null)
{
oldRootUIElement.OnPresentationSourceChanged(false);
}
// Broadcast the Loaded event starting at the root visual
if (newRootUIElement != null)
{
newRootUIElement.OnPresentationSourceChanged(true);
}
// To fire PresentationSourceChanged when the RootVisual changes;
// rather than simulate a "parent" pointer change, we just walk the
// collection of all nodes that need the event.
foreach (DependencyObject element in _watchers)
{
// We only need to update those elements that are in the
// same context as this presentation source.
if (element.Dispatcher == Dispatcher)
{
PresentationSource testSource = CriticalGetPresentationSourceFromElement(element,CachedSourceProperty);
// 1) If we are removing the rootvisual, then fire on any node whos old
// PresetationSource was the oldSource.
// 2) If we are attaching a rootvisual then fire on any node whos old
// PresentationSource is null;
if (oldSource == testSource || null == testSource)
{
UpdateSourceOfElement(element, null, null);
}
}
}
}
///
/// Called by derived classes to indicate that they need to be tracked.
///
protected void AddSource()
{
_sources.Add(this);
}
///
/// Called by derived classes to indicate that they no longer need to be tracked.
///
protected void RemoveSource()
{
_sources.Remove(this);
}
///
/// Sets the ContentRendered event to null.
///
protected void ClearContentRenderedListeners()
{
ContentRendered = null;
}
#endregion
//-----------------------------------------------------
//
// Internal Methods
//
//------------------------------------------------------
// None
//------------------------------------------------------
//
// Internal Static Methods
//
//-----------------------------------------------------
#region Internal Static Methods
///
/// Called by UIElement(3D)s when a visual ancestor link has changed.
///
/// The UIElement whose ancestory may have changed.
/// Event Args.
///
/// Critical: This code calls into a critical code path UpdateSourceOfElement.
/// TreatAsSafe: This code does not access any critical data itself and does not expose
/// anything
///
[SecurityCritical, SecurityTreatAsSafe]
internal static void OnVisualAncestorChanged(DependencyObject uie, AncestorChangedEventArgs e)
{
Debug.Assert(InputElement.IsUIElement3D(uie) || InputElement.IsUIElement(uie));
if (true == (bool)uie.GetValue(GetsSourceChangedEventProperty))
{
UpdateSourceOfElement(uie, e.Ancestor, e.OldParent);
}
}
///
/// Critical - Returns the PresentationSource
///
[FriendAccessAllowed] // To allow internal code paths to access this function
[SecurityCritical]
internal static PresentationSource CriticalFromVisual(DependencyObject v)
{
return CriticalFromVisual(v, true /* enable2DTo3DTransition */);
}
///
/// Critical - uses RootSourceProperty. and returns the PresentationSource
///
/// The dependency object to find the source for
///
/// Determines whether when walking the tree to enable transitioning from a 2D child
/// to a 3D parent or to stop once a 3D parent is encountered.
///
[FriendAccessAllowed] // To allow internal code paths to access this function
[SecurityCritical]
internal static PresentationSource CriticalFromVisual(DependencyObject v, bool enable2DTo3DTransition)
{
if (v == null)
{
throw new ArgumentNullException("v");
}
PresentationSource source = FindSource(v, enable2DTo3DTransition);
// Don't hand out a disposed source.
if (null != source && source.IsDisposed)
{
source = null;
}
return source;
}
///
/// Fire the event when content is rendered and ready for user interaction.
///
///
internal static object FireContentRendered(object arg)
{
PresentationSource ps = (PresentationSource)arg;
if (ps.ContentRendered != null)
{
ps.ContentRendered(arg, EventArgs.Empty);
}
return null;
}
#endregion
//------------------------------------------------------
//
// Internal Properties
//
//-----------------------------------------------------
// None
//-----------------------------------------------------
//
// Internal Events
//
//-----------------------------------------------------
// None
//------------------------------------------------------
//
// Private Static Methods
//
//-----------------------------------------------------
#region Private Static Methods
///
/// Return a WeakReferenceList which supports returning an Enumerator
/// over a ReadOnly SnapShot of the List of sources. The Enumerator
/// skips over the any dead weak references in the list.
///
///
/// Critical: This code exposes the sources which are deemed as critical. This is internal access point.
/// Public consumers should use CurrentSources
///
internal static IEnumerable CriticalCurrentSources
{
[SecurityCritical]
get
{
return (IEnumerable)_sources;
}
}
///
/// Critical: Returns a presentationsource given a canister
///
[SecurityCritical]
private static PresentationSource CriticalGetPresentationSourceFromElement(DependencyObject dObject,DependencyProperty dp)
{
PresentationSource testSource;
SecurityCriticalDataForMultipleGetAndSet tempCriticalDataWrapper =
(SecurityCriticalDataForMultipleGetAndSet < PresentationSource > )
dObject.GetValue(dp);
if (tempCriticalDataWrapper == null || tempCriticalDataWrapper.Value == null)
{
testSource = null;
}
else
{
testSource = tempCriticalDataWrapper.Value;
}
return testSource;
}
///
/// Critical: This code acceses PresentationSource and stores it.
///
[SecurityCritical]
private static void AddElementToWatchList(DependencyObject element)
{
if(_watchers.Add(element))
{
element.SetValue(CachedSourceProperty,new
SecurityCriticalDataForMultipleGetAndSet(PresentationSource.FindSource(element)));
element.SetValue(GetsSourceChangedEventProperty, true);
}
}
///
/// Critical: This code acceses PresentationSource
/// TreatAsSafe: This code is safe to expose.
///
[SecurityCritical,SecurityTreatAsSafe]
private static void RemoveElementFromWatchList(DependencyObject element)
{
if(_watchers.Remove(element))
{
element.ClearValue(CachedSourceProperty);
element.ClearValue(GetsSourceChangedEventProperty);
}
}
///
/// Critical - Returns a PresentationSource.
///
[SecurityCritical]
private static PresentationSource FindSource(DependencyObject o)
{
return FindSource(o, true /* enable2DTo3DTransition */);
}
///
/// Critical - uses RootSourceProperty and returns the PresentationSource
///
/// The dependency object to find the source for
///
/// Determines whether when walking the tree to enable transitioning from a 2D child
/// to a 3D parent or to stop once a 3D parent is encountered.
///
[SecurityCritical]
private static PresentationSource FindSource(DependencyObject o, bool enable2DTo3DTransition)
{
PresentationSource source = null;
// For "Visual" nodes GetRootVisual() climbs to the top of the
// visual tree (parent==null)
// For "ContentElements" it climbs the logical parent until it
// reaches a visual then climbs to the top of the visual tree.
DependencyObject v = InputElement.GetRootVisual(o, enable2DTo3DTransition);
if (v != null)
{
source = CriticalGetPresentationSourceFromElement(v, RootSourceProperty);
}
return source;
}
///
/// Critical: This code accesses PresentationSource which is a critical resource. It then
/// packages it into an event args and fires it into the tree.
///
[SecurityCritical]
private static bool UpdateSourceOfElement(DependencyObject doTarget,
DependencyObject doAncestor,
DependencyObject doOldParent)
{
bool calledOut = false;
PresentationSource realSource = FindSource(doTarget);
PresentationSource cachedSource = CriticalGetPresentationSourceFromElement(doTarget, CachedSourceProperty);
if (cachedSource != realSource)
{
doTarget.SetValue(CachedSourceProperty, new SecurityCriticalDataForMultipleGetAndSet(realSource));
SourceChangedEventArgs args = new SourceChangedEventArgs(cachedSource, realSource);
args.RoutedEvent=SourceChangedEvent;
if (InputElement.IsUIElement(doTarget))
{
((UIElement)doTarget).RaiseEvent(args);
}
else if (InputElement.IsContentElement(doTarget))
{
((ContentElement)doTarget).RaiseEvent(args);
}
else
{
((UIElement3D)doTarget).RaiseEvent(args);
}
calledOut = true;
}
return calledOut;
}
#endregion
//------------------------------------------------------
//
// Private Static Members
//
//------------------------------------------------------
#region Private Static Members
// We use a private DP for the RootSource (the connection from the root
// element in a tree to the source it is displayed in). Use the public
// API FromVisual to get the source that a visual is displayed in.
///
/// Critical - used to store PresentationSource
///
[SecurityCritical]
private static readonly DependencyProperty RootSourceProperty
= DependencyProperty.RegisterAttached("RootSource", typeof(SecurityCriticalDataForMultipleGetAndSet), typeof(PresentationSource),
new PropertyMetadata((SecurityCriticalDataForMultipleGetAndSet)null));
// We use a private DP for the CachedSource (stored on the elements
// that we are watching, so that we can send a change notification).
// Use the public API FromVisual to get the source that a visual is
// displayed in.
///
/// Critical - used to store PresentationSource
///
[SecurityCritical]
private static readonly DependencyProperty CachedSourceProperty
= DependencyProperty.RegisterAttached("CachedSource", typeof(SecurityCriticalDataForMultipleGetAndSet), typeof(PresentationSource),
new PropertyMetadata((SecurityCriticalDataForMultipleGetAndSet)null));
// We use a private DP to mark elements that we are watchin.
private static readonly DependencyProperty GetsSourceChangedEventProperty = DependencyProperty.RegisterAttached("IsBeingWatched", typeof(bool), typeof(PresentationSource), new PropertyMetadata((bool)false));
// We use a private direct-only event to notify elements of when the
// source changes. Use the public APIs AddSourceChangedHandler and
// RemoveSourceChangedHandler to listen to this event.
private static readonly RoutedEvent SourceChangedEvent = EventManager.RegisterRoutedEvent("SourceChanged", RoutingStrategy.Direct, typeof(SourceChangedEventHandler), typeof(PresentationSource));
// The lock we use to protect our static data.
private static object _globalLock = new object();
// An array of weak-references to sources that we know about.
private static WeakReferenceList _sources = new WeakReferenceList(_globalLock);
// An array of weak-references to elements that need to know
// about source changes.
private static WeakReferenceList _watchers = new WeakReferenceList(_globalLock);
#endregion
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- SchemaImporterExtensionsSection.cs
- ExtensibleSyndicationObject.cs
- SocketInformation.cs
- Part.cs
- ColorConverter.cs
- DispatcherFrame.cs
- FillRuleValidation.cs
- XmlDictionaryReaderQuotas.cs
- HealthMonitoringSection.cs
- CursorConverter.cs
- ReferenceEqualityComparer.cs
- CalculatedColumn.cs
- StreamWriter.cs
- WebPartMovingEventArgs.cs
- ListenerTraceUtility.cs
- SystemInformation.cs
- VarInfo.cs
- Matrix3D.cs
- CollectionsUtil.cs
- StringFunctions.cs
- TabControl.cs
- SecurityElement.cs
- PerformanceCounterCategory.cs
- FixedBufferAttribute.cs
- Int32Rect.cs
- MappingModelBuildProvider.cs
- XslVisitor.cs
- Int32EqualityComparer.cs
- SoapCodeExporter.cs
- CompModSwitches.cs
- _emptywebproxy.cs
- OperandQuery.cs
- MembershipPasswordException.cs
- XmlDocumentType.cs
- PixelShader.cs
- sqlser.cs
- MetabaseServerConfig.cs
- SourceFileInfo.cs
- CharacterMetricsDictionary.cs
- ColorConvertedBitmap.cs
- ScriptReferenceEventArgs.cs
- SharedRuntimeState.cs
- MdiWindowListStrip.cs
- ValidatorCollection.cs
- AnnotationHighlightLayer.cs
- DataGridHeaderBorder.cs
- RadioButtonStandardAdapter.cs
- ContentValidator.cs
- TypedElement.cs
- CssClassPropertyAttribute.cs
- OleDbPermission.cs
- ViewBase.cs
- StateBag.cs
- filewebresponse.cs
- XPathDocumentNavigator.cs
- FrameworkElementFactory.cs
- EntityTypeEmitter.cs
- QilPatternVisitor.cs
- HttpListenerContext.cs
- ArglessEventHandlerProxy.cs
- MulticastNotSupportedException.cs
- SelectionEditor.cs
- EntityTransaction.cs
- UIElement.cs
- OSFeature.cs
- ApplicationServiceManager.cs
- TemplateBindingExtensionConverter.cs
- RegexWorker.cs
- XmlSchemaResource.cs
- DocumentEventArgs.cs
- RestClientProxyHandler.cs
- SelectionProviderWrapper.cs
- ValueType.cs
- KerberosSecurityTokenAuthenticator.cs
- EvidenceTypeDescriptor.cs
- DesignerDataColumn.cs
- EntityContainerAssociationSet.cs
- ReachDocumentReferenceSerializer.cs
- HttpHandlerActionCollection.cs
- ServicePoint.cs
- XDeferredAxisSource.cs
- MetadataArtifactLoaderCompositeFile.cs
- RuntimeDelegateArgument.cs
- XmlQueryRuntime.cs
- InternalBufferOverflowException.cs
- SettingsPropertyWrongTypeException.cs
- WindowsStatic.cs
- SourceElementsCollection.cs
- HorizontalAlignConverter.cs
- UncommonField.cs
- InstanceDescriptor.cs
- CodeTypeDelegate.cs
- TransformerConfigurationWizardBase.cs
- RedirectionProxy.cs
- HasCopySemanticsAttribute.cs
- WebBrowserContainer.cs
- UrlMapping.cs
- InputLanguageCollection.cs
- ControlBuilder.cs
- XmlSchemaAnyAttribute.cs