void ICyclicBrush.RenderForCyclicBrush(DUCE.Channel channel, bool skipChannelCheck) { Visual vVisual = Visual; // The Visual may have been registered for an asynchronous render, but may have been // disconnected from the VisualBrush since then. If so, don't bother to render here, if // the Visual is visible it will be rendered elsewhere. if (vVisual != null && vVisual.CheckFlagsAnd(VisualFlags.NodeIsCyclicBrushRoot)) { // ------------------------------------------------------------------------------------ // 1) Prepare the visual for rendering. // // Updates bounding boxes. // vVisual.Precompute(); // ------------------------------------------------------------------------------------ // 2) Prepare the render context. // RenderContext rc = new RenderContext(); rc.Initialize(channel, DUCE.ResourceHandle.Null); // ------------------------------------------------------------------------------------ // 3) Compile the scene. if (channel.IsConnected) { vVisual.Render(rc, 0); } else { // We can issue the release here instead of putting it in queue // since we are already in Render walk. ((DUCE.IResource)vVisual).ReleaseOnChannel(channel); } } _isAsyncRenderRegistered = false; }
/// <summary> /// Propagates the flags up to the root. /// </summary> /// <remarks> /// The walk stops on a node with all of the required flags set. /// </remarks> internal static void PropagateFlags( Visual e, VisualFlags flags, VisualProxyFlags proxyFlags) { while ((e != null) && (!e.CheckFlagsAnd(flags) || !e.CheckFlagsOnAllChannels(proxyFlags))) { if (e.CheckFlagsOr(VisualFlags.ShouldPostRender)) { MediaContext mctx = MediaContext.From(e.Dispatcher); if (mctx.Channel != null) { mctx.PostRender(); } } else if (e.CheckFlagsAnd(VisualFlags.NodeIsCyclicBrushRoot)) { // // For visuals that are root nodes in visual brushes we // need to fire OnChanged on the owning brushes. // Dictionary<ICyclicBrush, int> cyclicBrushToChannelsMap = CyclicBrushToChannelsMapField.GetValue(e); Debug.Assert(cyclicBrushToChannelsMap != null, "Visual brush roots need to have the visual brush to channels map!"); // // Iterate over the visual brushes and fire the OnChanged event. // foreach (ICyclicBrush cyclicBrush in cyclicBrushToChannelsMap.Keys) { cyclicBrush.FireOnChanged(); } } e.SetFlags(true, flags); e.SetFlagsOnAllChannels(true, proxyFlags); if (e._parent == null) { // Stop propagating. We are at the root of the 2D subtree. return; } Visual parentAsVisual = e._parent as Visual; if (parentAsVisual == null) { // if the parent is not null (saw this with earlier null check) and is not a Visual // it must be a Visual3D - continue the propagation Visual3D.PropagateFlags((Visual3D)e._parent, flags, proxyFlags); return; } e = parentAsVisual; } }
/// <summary> /// DisconnectChild /// /// Derived classes must call this method to notify the Visual layer that a /// child was removed from the children collection. The Visual layer will then call /// GetChildren to find out which child has been removed. /// /// </summary> protected void RemoveVisualChild(Visual child) { if (child == null || child._parent == null) { return; } if (child._parent != this) { throw new ArgumentException(SR.Get(SRID.Visual_NotChild)); } if(InternalVisual2DOr3DChildrenCount == 0) { SetFlags(false, VisualFlags.HasChildren); } // // Remove the child on all channels its current parent is marshalled to. // for (int i = 0; i < _proxy.Count; i++) { DUCE.Channel channel = _proxy.GetChannel(i); if (child.CheckFlagsAnd(channel, VisualProxyFlags.IsConnectedToParent)) { child.SetFlags(channel, false, VisualProxyFlags.IsConnectedToParent); DUCE.IResource childResource = (DUCE.IResource)child; childResource.RemoveChildFromParent(this, channel); childResource.ReleaseOnChannel(channel); } } // Set the parent pointer to null. child._parent = null; Visual.PropagateFlags( this, VisualFlags.IsSubtreeDirtyForPrecompute, VisualProxyFlags.IsSubtreeDirtyForRender); UIElement.PropagateSuspendLayout(child); // Fire notifications child.FireOnVisualParentChanged(this); OnVisualChildrenChanged(null /* no child added */, child); }
private void markTreeDirtyHelper(Visual v) { //now walk down and mark all UIElements dirty if(v != null) { if(v.CheckFlagsAnd(VisualFlags.IsUIElement)) { UIElement uie = ((UIElement)v); uie.InvalidateMeasureInternal(); uie.InvalidateArrangeInternal(); } //walk children doing the same, don't stop if they are already dirty since there can //be insulated dirty islands below int cnt = v.InternalVisualChildrenCount; for(int i=0; i<cnt; i++) { Visual child = v.InternalGetVisualChild(i); if (child != null) markTreeDirtyHelper(child); } } }
private static IntPtr CriticalHandleWMGetobject(IntPtr wparam, IntPtr lparam, Visual root, IntPtr handle) { try { if (root == null) { // Valid case, but need to handle separately. For now, return 0 to avoid exceptions // in referencing this later on. Real solution is more complex, see WindowsClient#873800. return IntPtr.Zero; } AutomationPeer peer = null; if (root.CheckFlagsAnd(VisualFlags.IsUIElement)) { UIElement uiroot = (UIElement)root; peer = UIElementAutomationPeer.CreatePeerForElement(uiroot); //there si no specific peer for this UIElement, create a generic root if(peer == null) peer = uiroot.CreateGenericRootAutomationPeer(); if(peer != null) peer.Hwnd = handle; } // This can happen if the root visual is not UIElement. In this case, // attempt to find one in the visual tree. if (peer == null) { peer = UIElementAutomationPeer.GetRootAutomationPeer(root, handle); } if (peer == null) { return IntPtr.Zero; } // get the element proxy // it's ok to pass the same peer as reference connected peer here because // it's guaranteed to be a connected one (it's initialized as root already) IRawElementProviderSimple el = ElementProxy.StaticWrap(peer, peer); peer.AddToAutomationEventList(); // The assert here is considered OK // as we're assuming the WM_GETOBJECT is coming only from a PostMessage of an Hwnd. // to do the post message - you needed to have Unmanaged code permission // PermissionSet unpackPermissionSet = new PermissionSet(PermissionState.None); // below permissions needed to unpack an object. unpackPermissionSet.AddPermission(new SecurityPermission(SecurityPermissionFlag.SerializationFormatter | SecurityPermissionFlag.UnmanagedCode | SecurityPermissionFlag.RemotingConfiguration)); unpackPermissionSet.AddPermission(new System.Net.DnsPermission(PermissionState.Unrestricted)); unpackPermissionSet.AddPermission(new System.Net.SocketPermission(PermissionState.Unrestricted)); unpackPermissionSet.Assert(); try { return AutomationInteropProvider.ReturnRawElementProvider(handle, wparam, lparam, el); } finally { CodeAccessPermission.RevertAll(); } } #pragma warning disable 56500 catch (Exception e) { if(CriticalExceptions.IsCriticalException(e)) { throw; } return new IntPtr(Marshal.GetHRForException(e)); } #pragma warning restore 56500 }
/// <summary> /// Recursively resets IsLayoutSuspended flag on all visuals of the whole v's sub tree. /// For UIElements also re-inserts the UIElement into Measure and / or Arrange update queues /// if necessary. /// </summary> internal static void PropagateResumeLayout(Visual parent, Visual v) { if(v.CheckFlagsAnd(VisualFlags.IsLayoutIslandRoot)) return; //the subtree is already active - happens when new elements are added to the active tree //elements are created layout-active so they don't need to be specifically unsuspended //no need to walk down in this case //if(!v.CheckFlagsAnd(VisualFlags.IsLayoutSuspended)) return; //that can be true only on top of recursion, if suspended v is being connected to suspended parent. bool parentIsSuspended = parent == null ? false : parent.CheckFlagsAnd(VisualFlags.IsLayoutSuspended); uint parentTreeLevel = parent == null ? 0 : parent.TreeLevel; if(parentIsSuspended) return; v.SetFlags(false, VisualFlags.IsLayoutSuspended); v.TreeLevel = parentTreeLevel + 1; if (v.CheckFlagsAnd(VisualFlags.IsUIElement)) { // re-insert UIElement into the update queues UIElement e = (UIElement)v; Invariant.Assert(!e.MeasureInProgress && !e.ArrangeInProgress); bool requireMeasureUpdate = e.MeasureDirty && !e.NeverMeasured && (e.MeasureRequest == null); bool requireArrangeUpdate = e.ArrangeDirty && !e.NeverArranged && (e.ArrangeRequest == null); ContextLayoutManager contextLayoutManager = (requireMeasureUpdate || requireArrangeUpdate) ? ContextLayoutManager.From(e.Dispatcher) : null; if (requireMeasureUpdate) { contextLayoutManager.MeasureQueue.Add(e); } if (requireArrangeUpdate) { contextLayoutManager.ArrangeQueue.Add(e); } } int count = v.InternalVisualChildrenCount; for (int i = 0; i < count; i++) { Visual cv = v.InternalGetVisualChild(i); if (cv != null) { PropagateResumeLayout(v, cv); } } }
/// <summary> /// Recursively propagates IsLayoutSuspended flag down to the whole v's sub tree. /// </summary> internal static void PropagateSuspendLayout(Visual v) { if(v.CheckFlagsAnd(VisualFlags.IsLayoutIslandRoot)) return; //the subtree is already suspended - happens when already suspended tree is further disassembled //no need to walk down in this case if(v.CheckFlagsAnd(VisualFlags.IsLayoutSuspended)) return; // (bug # 1623922) assert that a UIElement has not being // removed from the visual tree while updating layout. if ( Invariant.Strict && v.CheckFlagsAnd(VisualFlags.IsUIElement) ) { UIElement e = (UIElement)v; Invariant.Assert(!e.MeasureInProgress && !e.ArrangeInProgress); } v.SetFlags(true, VisualFlags.IsLayoutSuspended); v.TreeLevel = 0; int count = v.InternalVisualChildrenCount; for (int i = 0; i < count; i++) { Visual cv = v.InternalGetVisualChild(i); if (cv != null) { PropagateSuspendLayout(cv); } } }