Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Core / System / Windows / Media / HostVisual.cs / 2 / HostVisual.cs
//------------------------------------------------------------------------------
//
//
// Copyright (C) Microsoft Corporation. All rights reserved.
//
//
// Description:
// Host visual.
//
//-----------------------------------------------------------------------------
namespace System.Windows.Media
{
using System;
using System.Windows.Threading;
using System.Windows.Media;
using System.Windows.Media.Composition;
using System.Diagnostics;
using System.Collections;
using System.Collections.Generic;
using MS.Internal;
using System.Resources;
using System.Runtime.InteropServices;
using MS.Win32;
using System.Threading;
using SR=MS.Internal.PresentationCore.SR;
using SRID=MS.Internal.PresentationCore.SRID;
///
/// Host visual.
///
public class HostVisual : ContainerVisual
{
//---------------------------------------------------------------------
//
// Constructors
//
//---------------------------------------------------------------------
#region Constructors
///
///
///
public HostVisual()
{
//
// Set NodeUsesRealizationCaches flag, so that UpdateRealizations
// will be called when change affecting realizations occurred in
// the ancestor. UpdateRealizations override will propagate this
// infromation to the hosted visual tree.
//
SetFlags(true, VisualFlags.NodeUsesRealizationCaches);
}
#endregion Constructors
//----------------------------------------------------------------------
//
// Protected Methods
//
//---------------------------------------------------------------------
#region Protected Methods
///
/// HitTestCore
///
protected override HitTestResult HitTestCore(
PointHitTestParameters hitTestParameters)
{
//
// HostVisual never reports itself as being hit. To change this
// behavior clients should derive from HostVisual and override
// HitTestCore methods.
//
return null;
}
///
/// HitTestCore
///
protected override GeometryHitTestResult HitTestCore(
GeometryHitTestParameters hitTestParameters)
{
//
// HostVisual never reports itself as being hit. To change this
// behavior clients should derive from HostVisual and override
// HitTestCore methods.
//
return null;
}
#endregion Protected Methods
//----------------------------------------------------------------------
//
// Internal Methods
//
//----------------------------------------------------------------------
#region Internal Methods
///
///
///
internal override Rect GetContentBounds()
{
return Rect.Empty;
}
///
///
///
internal override void RenderContent(RenderContext ctx, bool isOnChannel)
{
//
// Create and register RenderComplete event handler
// that will be used to propagate state changes to
// the hosted visual target.
//
if (_propagateState == null)
{
_propagateState = new EventHandler(PropagateState);
MediaContext.From(Dispatcher).RenderComplete += _propagateState;
}
//
// Make sure that the visual target is properly hosted.
//
EnsureHostedVisualConnected(ctx.Channel);
}
///
///
///
internal override void FreeContent(DUCE.Channel channel)
{
if (!channel.IsLayeredWindowChannel)
{
//
// Unregister RenderComplete event handler if one is registered.
//
if (_propagateState != null)
{
MediaContext.From(Dispatcher).RenderComplete -= _propagateState;
_propagateState = null;
}
//
// Disconnect hosted visual from this channel.
//
using (CompositionEngineLock.Acquire())
{
DisconnectHostedVisual(
channel,
/* removeChannelFromCollection */ true);
}
base.FreeContent(channel);
}
}
///
///
///
internal override void UpdateRealizations(RealizationContext ctx)
{
//
// If transform in one of the the ancestors has chnaged,
// propagate transform information in order to correclty
// compute realizations in the hosted visual tree. State
// change will be propagated when channel is committed.
//
Matrix transform = ctx.TransformStack.Peek();
if (_state.worldTransform != transform)
{
_state.flags |= CompositionTarget.HostStateFlags.WorldTransform;
_state.worldTransform = transform;
}
//
//
}
///
///
///
internal void PropagateState(object sender, EventArgs e)
{
//
// If state has changed, propagate the change to the
// visual target and reset the state.
//
if (_state.flags != 0)
{
VisualTarget.HostState state = _state;
using (CompositionEngineLock.Acquire())
{
if (_target != null)
{
_target.PropagateState(ref state);
}
}
_state.flags = 0;
}
}
///
///
///
internal void BeginHosting(VisualTarget target)
{
//
// This method is executed on the visual target thread.
//
Debug.Assert(target != null);
Debug.Assert(target.Dispatcher.Thread == Thread.CurrentThread);
using (CompositionEngineLock.Acquire())
{
//
// Check if another target is already hosted by this
// visual and throw exception if this is the case.
//
if (_target != null)
{
throw new InvalidOperationException(
SR.Get(SRID.VisualTarget_AnotherTargetAlreadyConnected)
);
}
_target = target;
//
// If HostVisual and VisualTarget on same thread, then call Invalidate
// directly. Otherwise post invalidate message to the host visual thread
// indicating that content update is required.
//
if (this.CheckAccess())
{
Invalidate();
}
else
{
Dispatcher.BeginInvoke(
DispatcherPriority.Normal,
(DispatcherOperationCallback)delegate(object args)
{
Invalidate();
return null;
},
null
);
}
}
}
///
///
///
internal void EndHosting()
{
//
// This method is executed on the visual target thread.
//
using (CompositionEngineLock.Acquire())
{
Debug.Assert(_target != null);
Debug.Assert(_target.Dispatcher.Thread == Thread.CurrentThread);
DisconnectHostedVisualOnAllChannels();
_target = null;
}
}
///
/// Should be called from the VisualTarget thread
/// when it is safe to access the composition node
/// and out of band channel from the VisualTarget thread
/// to allow for the handle duplication/channel commit
///
internal object DoHandleDuplication(object parameters)
{
ArrayList paramArray = parameters as ArrayList;
DUCE.ResourceHandle targetsHandle = DUCE.ResourceHandle.Null;
DUCE.Channel channel = paramArray[0] as DUCE.Channel;
long _requestingGenerationId = (long)paramArray[1];
using (CompositionEngineLock.Acquire())
{
//
// We need to ensure that the generation Id is the same now as
// it was when this Invoke was posted. There are certain situations
// in which Connect/Disconnect may have occurred on one thread and
// not the other, which would mean we'd try to duplicate a handle from
// or to a stale channel. We use the generation Id to determine if both
// threads are using the same transport. If they're not, we can safely
// noop, because the last thread to process the Connect/Disconnect message
// will remarshal itself to the new channel, causing this Invoke to
// eventually be called again
//
if (_requestingGenerationId == MediaSystem.GenerationId)
{
targetsHandle = _target._contentRoot.DuplicateHandle(_target.OutOfBandChannel, channel);
Debug.Assert(!targetsHandle.IsNull);
_target.OutOfBandChannel.Commit();
}
}
return targetsHandle;
}
#endregion Internal Methods
//---------------------------------------------------------------------
//
// Private Methods
//
//----------------------------------------------------------------------
#region Private Methods
///
/// Connects the hosted visual on a channel if necessary.
///
private void EnsureHostedVisualConnected(DUCE.Channel channel)
{
//
// Conditions for connecting VisualTarget to Host Visual:-
// 1. The channel on which we are rendering should not be synchronous. This
// scenario is not supported currently.
// 2. VisualTarget should not be null.
// 3. They should not be already connected.
//
if (!(channel.IsSynchronous)
&& _target != null
&& !_connectedChannels.Contains(channel)
&& !channel.IsLayeredWindowChannel)
{
Debug.Assert(IsOnChannel(channel));
DUCE.ResourceHandle targetsHandle = DUCE.ResourceHandle.Null;
bool doDuplication = true;
//
// If HostVisual and VisualTarget are on same thread, then we just addref
// VisualTarget. Otherwise, if on different threads, then we duplicate
// VisualTarget onto Hostvisual's channel.
//
if (_target.CheckAccess())
{
Debug.Assert(_target._contentRoot.IsOnChannel(channel));
Debug.Assert(_target.OutOfBandChannel == MediaContext.CurrentMediaContext.OutOfBandChannel);
bool created = _target._contentRoot.CreateOrAddRefOnChannel(channel, VisualTarget.s_contentRootType);
Debug.Assert(!created);
targetsHandle = _target._contentRoot.GetHandle(channel);
}
else
{
//
// Duplicate the target's handle onto our channel.
//
// We must wait synchronously for the _targets Dispatcher to call
// back and do handle duplication. We can't do handle duplication
// on this thread because access to the _target CompositionNode
// is not synchronized. If we duplicated here, we could potentially
// corrupt the _target OutOfBandChannel or the CompositionNode
// MultiChannelResource. We have to wait synchronously because
// we need the resulting duplicated handle to hook up as a child
// to this HostVisual.
//
ArrayList parameters = new ArrayList(2);
parameters.Add(channel);
parameters.Add((object)MediaSystem.GenerationId);
object returnValue = _target.Dispatcher.Invoke(
DispatcherPriority.Normal,
TimeSpan.FromMilliseconds(1000),
new DispatcherOperationCallback(DoHandleDuplication),
parameters
);
//
// Duplication and flush is complete, we can resume processing
// Only if the Invoke succeeded will we have a handle returned.
//
if (returnValue != null)
{
targetsHandle = (DUCE.ResourceHandle)returnValue;
}
else
{
// The Invoke didn't complete
doDuplication = false;
}
}
if (doDuplication)
{
if (!targetsHandle.IsNull)
{
using (CompositionEngineLock.Acquire())
{
DUCE.CompositionNode.InsertChildAt(
_proxy.GetHandle(channel),
targetsHandle,
0,
channel);
}
_connectedChannels.Add(channel);
//
// Indicate that that content composition root has been
// connected, this needs to be taken into account to
// properly manage children of this visual.
//
SetFlags(channel, true, VisualProxyFlags.IsContentNodeConnected);
}
}
else
{
//
// We didn't get a handle, because _target belongs to a
// different thread, and the Invoke operation failed. We can't do
// anything except try again in the next render pass. We can't
// call Invalidate during the render pass because it pushes up
// flags that are being modified within the render pass, so get
// the local Dispatcher to do it for us later.
//
Dispatcher.BeginInvoke(
DispatcherPriority.Normal,
(DispatcherOperationCallback)delegate(object args)
{
Invalidate();
return null;
},
null
);
}
}
}
///
/// Disconnects the hosted visual on all channels we have
/// connected it to.
///
private void DisconnectHostedVisualOnAllChannels()
{
foreach (DUCE.Channel channel in _connectedChannels)
{
DisconnectHostedVisual(
channel,
/* removeChannelFromCollection */ false);
}
_connectedChannels.Clear();
}
///
/// Disconnects the hosted visual on a channel.
///
private void DisconnectHostedVisual(
DUCE.Channel channel,
bool removeChannelFromCollection)
{
if (_target != null && _connectedChannels.Contains(channel))
{
DUCE.CompositionNode.RemoveChild(
_proxy.GetHandle(channel),
_target._contentRoot.GetHandle(channel),
channel
);
//
// Release the targets handle. If we had duplicated the handle,
// then this removes the duplicated handle, otherwise just decrease
// the ref count for VisualTarget.
//
_target._contentRoot.ReleaseOnChannel(channel);
SetFlags(channel, false, VisualProxyFlags.IsContentNodeConnected);
if (removeChannelFromCollection)
{
_connectedChannels.Remove(channel);
}
}
}
///
/// Invalidate this visual.
///
private void Invalidate()
{
SetFlagsOnAllChannels(true, VisualProxyFlags.IsContentDirty);
PropagateChangedFlags();
}
#endregion Private Methods
//---------------------------------------------------------------------
//
// Private Fields
//
//---------------------------------------------------------------------
#region Private Fields
private EventHandler _propagateState;
private VisualTarget.HostState _state;
///
/// The hosted visual target.
///
///
/// This field is free-threaded and should be accessed from under a lock.
///
private VisualTarget _target;
///
/// The channels we have marshalled the visual target composition root.
///
///
/// This field is free-threaded and should be accessed from under a lock.
///
private List _connectedChannels = new List();
#endregion Private Fields
}
}
// 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
- TextElementEnumerator.cs
- UntrustedRecipientException.cs
- QilChoice.cs
- AudioBase.cs
- CompilerScope.cs
- EventLogPermission.cs
- StylusPointProperty.cs
- SerialStream.cs
- HtmlFormAdapter.cs
- KeysConverter.cs
- DrawingAttributesDefaultValueFactory.cs
- Merger.cs
- MiniMapControl.xaml.cs
- ParameterToken.cs
- ControlDesigner.cs
- SmtpDigestAuthenticationModule.cs
- ProcessStartInfo.cs
- Wizard.cs
- Errors.cs
- DelegatedStream.cs
- AutoGeneratedFieldProperties.cs
- CryptoKeySecurity.cs
- DataGridTextBox.cs
- documentsequencetextview.cs
- SHA256Managed.cs
- MenuBase.cs
- WebPartDisplayModeCancelEventArgs.cs
- Polygon.cs
- WebBrowserNavigatingEventHandler.cs
- TemplatedWizardStep.cs
- HybridObjectCache.cs
- CLRBindingWorker.cs
- SqlMetaData.cs
- CompilationUnit.cs
- HttpRequestTraceRecord.cs
- EntityClientCacheKey.cs
- CollectionChangedEventManager.cs
- BitmapCacheBrush.cs
- HandlerWithFactory.cs
- AssemblyNameProxy.cs
- PointCollectionConverter.cs
- CalendarTable.cs
- XmlUtilWriter.cs
- StylusTouchDevice.cs
- XmlMembersMapping.cs
- SiteMapDataSource.cs
- DebugView.cs
- FontUnit.cs
- DisableDpiAwarenessAttribute.cs
- DesignTimeParseData.cs
- ChtmlTextWriter.cs
- BeginSelectCardRequest.cs
- TableRowGroup.cs
- basemetadatamappingvisitor.cs
- PeerResolverMode.cs
- RelatedCurrencyManager.cs
- ObjectQueryExecutionPlan.cs
- Point3D.cs
- UnsafeNativeMethods.cs
- ServicePoint.cs
- AssociationSetEnd.cs
- RichTextBoxAutomationPeer.cs
- TextBoxBaseDesigner.cs
- ObjectListCommand.cs
- ProcessModule.cs
- ChildrenQuery.cs
- WebPartCollection.cs
- TableDetailsCollection.cs
- BevelBitmapEffect.cs
- UpdatePanel.cs
- CompoundFileStorageReference.cs
- CodeTypeDelegate.cs
- Mutex.cs
- SmtpFailedRecipientException.cs
- GroupQuery.cs
- HttpDictionary.cs
- InputScope.cs
- EventHandlerList.cs
- AppDomain.cs
- login.cs
- ThemeInfoAttribute.cs
- KnowledgeBase.cs
- Peer.cs
- AsymmetricSignatureDeformatter.cs
- MethodBuilderInstantiation.cs
- InfoCardRSAPKCS1KeyExchangeDeformatter.cs
- FragmentQuery.cs
- CredentialManagerDialog.cs
- CharacterBuffer.cs
- DocumentPageViewAutomationPeer.cs
- ObjectDisposedException.cs
- SqlBuilder.cs
- IPHostEntry.cs
- WindowsImpersonationContext.cs
- TableMethodGenerator.cs
- ToolStripPanelRenderEventArgs.cs
- DropDownButton.cs
- ColumnHeaderConverter.cs
- CDSCollectionETWBCLProvider.cs
- Int32Storage.cs