/// <summary>
        /// Enqueues an operation to remove the root view.
        /// </summary>
        /// <param name="rootViewTag">The root view tag.</param>
        public void EnqueueRemoveRootView(int rootViewTag)
        {
            // Called on layout manager thread

            UIViewOperationQueueInstance queue = GetQueueByTag(rootViewTag);

            // Send forward
            queue.EnqueueRemoveRootView(rootViewTag);

            // Do some maintenance/cleanup if needed.
            // Find the queue info
            var pair = _dispatcherToOperationQueueInfo.First(p => p.Value.queueInstance == queue);

            // Decrement number of root views
            pair.Value.rootViewCount--;

            if (queue != MainUIViewOperationQueue)
            {
                if (pair.Value.rootViewCount == 0)
                {
                    // We can remove this queue and then destroy
                    _dispatcherToOperationQueueInfo.Remove(pair.Key);

                    // Simulate an OnDestroy from the correct dispatcher thread
                    // (OnResume/OnSuspend/OnDestroy have this thread affinity, all other methods do enqueuings in a thread safe manner)
                    DispatcherHelpers.RunOnDispatcher(pair.Key, queue.OnDestroy);
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Enqueues an operation to remove the root view.
        /// </summary>
        /// <param name="rootViewTag">The root view tag.</param>
        public Task RemoveRootViewAsync(int rootViewTag)
        {
            // Called on layout manager thread

            UIViewOperationQueueInstance queue = GetQueueByTag(rootViewTag);

            // Send forward
            queue.EnqueueRemoveRootView(rootViewTag);

            // Do some maintenance/cleanup if needed.
            // Find the queue info
            KeyValuePair <CoreDispatcher, QueueInstanceInfo> pair;

            lock (_lock)
            {
                pair = _dispatcherToOperationQueueInfo.First(p => p.Value.queueInstance == queue);
            }

            // Decrement number of root views
            pair.Value.rootViewCount--;

            if (queue != MainUIViewOperationQueue)
            {
                if (pair.Value.rootViewCount == 0)
                {
                    lock (_lock)
                    {
                        // We can remove this queue and then destroy
                        _dispatcherToOperationQueueInfo.Remove(pair.Key);
                    }

                    // Simulate an OnDestroy from the correct dispatcher thread
                    // (OnResume/OnSuspend/OnDestroy have this thread affinity, all other methods do enqueuings in a thread safe manner)
                    return(DispatcherHelpers.CallOnDispatcher(pair.Key, () =>
                    {
                        queue.OnDestroy();

                        return true;
                    }));
                }
                else
                {
                    return(Task.CompletedTask);
                }
            }
            else
            {
                return(Task.CompletedTask);
            }
        }
예제 #3
0
        /// <summary>
        /// Enqueues an operation to measure the view relative to the window.
        /// </summary>
        /// <param name="tag">The tag of the view to measure.</param>
        /// <param name="callback">The measurement result callback.</param>
        public void EnqueueMeasureInWindow(int tag, ICallback callback)
        {
            // Called on layout manager thread

            UIViewOperationQueueInstance queue = GetQueueByTag(tag, true);

            if (queue == null)
            {
                // This is called bypassing the optimizer, so we need to fake a result for layout only nodes.
                callback.Invoke();
                return;
            }

            queue.EnqueueMeasureInWindow(tag, callback);
        }
예제 #4
0
        /// <summary>
        /// Enqueues an operation to create a view.
        /// </summary>
        /// <param name="themedContext">The React context.</param>
        /// <param name="viewReactTag">The view React tag.</param>
        /// <param name="viewClassName">The view class name.</param>
        /// <param name="initialProps">The initial props.</param>
        /// <param name="rootViewTag">Root view tag.</param>
        public void EnqueueCreateView(
            ThemedReactContext themedContext,
            int viewReactTag,
            string viewClassName,
            JObject initialProps,
            int rootViewTag)
        {
            // Called on layout manager thread

            UIViewOperationQueueInstance queue = GetQueueByTag(rootViewTag);

            _reactTagToOperationQueue.Add(viewReactTag, queue);

            queue.EnqueueCreateView(themedContext, viewReactTag, viewClassName, initialProps);
        }
예제 #5
0
        /// <summary>
        /// Enqueues an operation to find a touch target.
        /// </summary>
        /// <param name="tag">The parent view to search from.</param>
        /// <param name="targetX">The x-coordinate of the touch event.</param>
        /// <param name="targetY">The y-coordinate of the touch event.</param>
        /// <param name="callback">The callback.</param>
        public void EnqueueFindTargetForTouch(
            int tag,
            double targetX,
            double targetY,
            ICallback callback)
        {
            // Called on layout manager thread

            UIViewOperationQueueInstance queue = GetQueueByTag(tag, true);

            if (queue == null)
            {
                // This is called bypassing the optimizer, so we need to fake a result for layout only nodes.
                callback.Invoke();
                return;
            }

            queue.EnqueueFindTargetForTouch(tag, targetX, targetY, callback);
        }
예제 #6
0
        /// <summary>
        /// Used by the native animated module to bypass the process of
        /// updating the values through the shadow view hierarchy. This method
        /// will directly update the native views, which means that updates for
        /// layout-related props won't be handled properly.
        /// </summary>
        /// <param name="tag">The view tag.</param>
        /// <param name="props">The props.</param>
        /// <remarks>
        /// Make sure you know what you're doing before calling this method :)
        /// </remarks>
        public bool SynchronouslyUpdateViewOnDispatcherThread(int tag, JObject props)
        {
            // The native animations module is a single threaded implementation affinitized to the "main" dispatcher thread.
            // As a result all calls of this method are on main dispatcher thread.
            // Yet, for secondary views we have to dispatch to correct dispatcher as fast as possible
            DispatcherHelpers.AssertOnDispatcher();

            UIViewOperationQueueInstance queue = GetQueueByTag(tag, true);

            if (queue == null)
            {
                // Returns false as per the caller's expectation
                return(false);
            }

            if (queue == MainUIViewOperationQueue)
            {
                // Main queue case. Just forward.
                if (!MainUIViewOperationQueue.NativeViewHierarchyManager.ViewExists(tag))
                {
                    return(false);
                }

                MainUIViewOperationQueue.NativeViewHierarchyManager.UpdateProps(tag, props);
            }
            else
            {
                // Dispatch to the correct thread.
                DispatcherHelpers.RunOnDispatcher(queue.Dispatcher, CoreDispatcherPriority.High, () =>
                {
                    if (queue.NativeViewHierarchyManager.ViewExists(tag))
                    {
                        queue.NativeViewHierarchyManager.UpdateProps(tag, props);
                    }
                    else
                    {
                        Debug.WriteLine($"View with tag {tag} not found due to race condition");
                    }
                });
            }
            return(true);
        }
예제 #7
0
        /// <summary>
        /// Instantiates the <see cref="UIViewOperationQueue"/>.
        /// </summary>
        /// <param name="reactContext">The React context.</param>
        /// <param name="viewManagerRegistry">
        /// The view manager registry.
        /// </param>
        public UIViewOperationQueue(ReactContext reactContext, ViewManagerRegistry viewManagerRegistry)
        {
            _reactContext        = reactContext;
            _viewManagerRegistry = viewManagerRegistry;
            _active = false;

            // Corner case: UWP scenarios that start with no main window.
            // We create the UIViewOperationQueueInstance for main dispatcher thread ahead of time so animations
            // in secondary windows can work.
            var queueInfo = new QueueInstanceInfo()
            {
                queueInstance = new UIViewOperationQueueInstance(
                    _reactContext,
                    new NativeViewHierarchyManager(_viewManagerRegistry, DispatcherHelpers.MainDispatcher, OnViewsDropped),
                    ReactChoreographer.Instance)
            };

            _dispatcherToOperationQueueInfo.Add(DispatcherHelpers.MainDispatcher, queueInfo);
            _mainUiViewOperationsQueueInstance = queueInfo.queueInstance;
        }