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
- BaseTemplateBuildProvider.cs
- Soap12FormatExtensions.cs
- BounceEase.cs
- ALinqExpressionVisitor.cs
- DataPagerField.cs
- ADRoleFactory.cs
- TableItemStyle.cs
- CollectionViewGroupInternal.cs
- ObjectViewListener.cs
- Buffer.cs
- LazyTextWriterCreator.cs
- ProbeDuplexCD1AsyncResult.cs
- SqlDataSourceCommandEventArgs.cs
- ColorConverter.cs
- HttpConfigurationContext.cs
- shaperfactory.cs
- ClientOptions.cs
- InputLangChangeEvent.cs
- XmlTypeAttribute.cs
- TimelineGroup.cs
- BitmapSizeOptions.cs
- SchemaImporterExtensionElement.cs
- AnnotationAdorner.cs
- UriGenerator.cs
- DynamicRenderer.cs
- SettingsProviderCollection.cs
- UserPersonalizationStateInfo.cs
- GridProviderWrapper.cs
- ManifestResourceInfo.cs
- BaseServiceProvider.cs
- MethodBuilderInstantiation.cs
- SelectionRange.cs
- ConfigPathUtility.cs
- URLMembershipCondition.cs
- ProfilePropertySettings.cs
- ParseHttpDate.cs
- RenderingEventArgs.cs
- ConsumerConnectionPoint.cs
- StringUtil.cs
- CaseInsensitiveHashCodeProvider.cs
- PreProcessor.cs
- DbQueryCommandTree.cs
- ReliableRequestSessionChannel.cs
- PeerNameRecord.cs
- TrackBar.cs
- InkCanvas.cs
- updatecommandorderer.cs
- CalendarModeChangedEventArgs.cs
- configsystem.cs
- WebSysDisplayNameAttribute.cs
- Region.cs
- LinqDataSourceSelectEventArgs.cs
- BoundingRectTracker.cs
- UInt16Storage.cs
- RegexBoyerMoore.cs
- DataSvcMapFileSerializer.cs
- prompt.cs
- FormViewDeleteEventArgs.cs
- Debug.cs
- MailWriter.cs
- TextEndOfParagraph.cs
- ObjectReferenceStack.cs
- IDataContractSurrogate.cs
- SelectedDatesCollection.cs
- IntSecurity.cs
- ObjectParameter.cs
- TriggerCollection.cs
- TemplatePartAttribute.cs
- TextFormatter.cs
- ProfileGroupSettingsCollection.cs
- HttpRuntimeSection.cs
- ImageClickEventArgs.cs
- InvalidComObjectException.cs
- GridViewCommandEventArgs.cs
- Setter.cs
- Bitmap.cs
- _AutoWebProxyScriptHelper.cs
- MdImport.cs
- DesignerImageAdapter.cs
- InfoCardTraceRecord.cs
- Int32RectConverter.cs
- MissingMemberException.cs
- WindowsAuthenticationModule.cs
- ActivityCodeDomSerializer.cs
- AssemblySettingAttributes.cs
- ByteRangeDownloader.cs
- DataGrid.cs
- DeadLetterQueue.cs
- DocumentXPathNavigator.cs
- PackageRelationshipSelector.cs
- SecurityContext.cs
- AssemblyCache.cs
- PeerCollaboration.cs
- UriExt.cs
- PixelFormatConverter.cs
- DateTime.cs
- SessionStateItemCollection.cs
- MexBindingBindingCollectionElement.cs
- PrintingPermissionAttribute.cs
- DataGridHelper.cs