Ejemplo n.º 1
0
            private void CoreWindow_PointerWheelChanged(CoreWindow sender, PointerEventArgs args)
            {
                var source = FindOriginalSource(args);

                if (source.element is null)
                {
                    if (this.Log().IsEnabled(LogLevel.Trace))
                    {
                        this.Log().Trace($"CoreWindow_PointerPressed ({args.CurrentPoint.Position}) **undispatched**");
                    }

                    return;
                }

                if (this.Log().IsEnabled(LogLevel.Trace))
                {
                    this.Log().Trace($"CoreWindow_PointerPressed [{source.element.GetDebugName()}");
                }

                var routedArgs = new PointerRoutedEventArgs(args, source.element);

                // Second raise the event, either on the OriginalSource or on the capture owners if any
                if (PointerCapture.TryGet(routedArgs.Pointer, out var capture))
                {
                    foreach (var target in capture.Targets.ToArray())
                    {
                        target.Element.OnNativePointerWheel(routedArgs);
                    }
                }
                else
                {
                    source.element.OnNativePointerWheel(routedArgs);
                }
            }
Ejemplo n.º 2
0
 private void ReleaseCaptures(PointerRoutedEventArgs routedArgs)
 {
     if (PointerCapture.TryGet(routedArgs.Pointer, out var capture))
     {
         foreach (var target in capture.Targets)
         {
             target.Element.ReleasePointerCapture(capture.Pointer);
         }
     }
 }
Ejemplo n.º 3
0
 private static void ReleaseCaptures(PointerRoutedEventArgs routedArgs)
 {
     if (PointerCapture.TryGet(routedArgs.Pointer, out var capture))
     {
         foreach (var target in capture.Targets.ToList())
         {
             target.Element.ReleasePointerCapture(capture.Pointer.UniqueId, kinds: PointerCaptureKind.Any);
         }
     }
 }
Ejemplo n.º 4
0
            private void CoreWindow_PointerMoved(CoreWindow sender, PointerEventArgs args)
            {
                var(originalSource, staleBranch) = VisualTreeHelper.HitTest(args.CurrentPoint.Position, isStale: _isOver);

                // This is how UWP behaves: when out of the bounds of the Window, the root element is use.
                // Note that if another app covers your app, then the OriginalSource on UWP is still the element of your app at the pointer's location.
                originalSource ??= Windows.UI.Xaml.Window.Current.Content;

                if (originalSource is null)
                {
                    if (this.Log().IsEnabled(LogLevel.Trace))
                    {
                        this.Log().Trace($"CoreWindow_PointerMoved ({args.CurrentPoint.Position}) **undispatched**");
                    }

                    return;
                }

                if (this.Log().IsEnabled(LogLevel.Trace))
                {
                    this.Log().Trace($"CoreWindow_PointerMoved [{originalSource.GetDebugName()}");
                }

                var routedArgs = new PointerRoutedEventArgs(args, originalSource);

                // First raise the PointerExited events on the stale branch
                if (staleBranch.HasValue)
                {
                    var(root, leaf) = staleBranch.Value;

                    ClearPointerState(routedArgs, root, leaf);
                }

                // Second (try to) raise the PointerEnter on the OriginalSource
                // Note: This won't do anything if already over.
                routedArgs.Handled = false;
                originalSource.OnNativePointerEnter(routedArgs);

                // Finally raise the event, either on the OriginalSource or on the capture owners if any
                if (PointerCapture.TryGet(routedArgs.Pointer, out var capture))
                {
                    foreach (var target in capture.Targets.ToArray())
                    {
                        routedArgs.Handled = false;
                        target.Element.OnNativePointerMove(routedArgs);
                    }
                }
                else
                {
                    // Note: We prefer to use the "WithOverCheck" overload as we already know that the pointer is effectively over
                    routedArgs.Handled = false;
                    originalSource.OnNativePointerMoveWithOverCheck(routedArgs, isOver: true);
                }
            }
Ejemplo n.º 5
0
            private void CoreWindow_PointerReleased(CoreWindow sender, PointerEventArgs args)
            {
                var(originalSource, _) = VisualTreeHelper.HitTest(args.CurrentPoint.Position);

                // Even if impossible for the Release, we are fallbacking on the RootElement for safety
                // This is how UWP behaves: when out of the bounds of the Window, the root element is use.
                // Note that if another app covers your app, then the OriginalSource on UWP is still the element of your app at the pointer's location.
                originalSource ??= Windows.UI.Xaml.Window.Current.Content;

                if (originalSource is null)
                {
                    if (this.Log().IsEnabled(LogLevel.Trace))
                    {
                        this.Log().Trace($"CoreWindow_PointerPressed ({args.CurrentPoint.Position}) **undispatched**");
                    }

                    return;
                }

                if (this.Log().IsEnabled(LogLevel.Trace))
                {
                    this.Log().Trace($"CoreWindow_PointerPressed [{originalSource.GetDebugName()}");
                }

                var routedArgs = new PointerRoutedEventArgs(args, originalSource);

                // Second raise the event, either on the OriginalSource or on the capture owners if any
                if (PointerCapture.TryGet(routedArgs.Pointer, out var capture))
                {
                    foreach (var target in capture.Targets.ToArray())
                    {
                        target.Element.OnNativePointerUp(routedArgs);
                    }
                }
                else
                {
                    originalSource.OnNativePointerUp(routedArgs);
                }

                if (_pressedElements.TryGetValue(routedArgs.Pointer, out var pressedLeaf))
                {
                    // We must make sure to clear the pressed state on all elements that was flagged as pressed.
                    // This is required as the current originalSource might not be the same as when we pressed (pointer moved),
                    // ** OR ** the pointer has been captured by a parent element so we didn't raised to released on the sub elements.

                    _pressedElements.Remove(routedArgs.Pointer);
                    ClearPointerState(routedArgs, root: null, pressedLeaf, clearOver: false);
                }
            }
Ejemplo n.º 6
0
        private void OnSwipeManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
        {
#if !DEBUG
            // On UWP, SwipeControl works only with touch.
            // We do allow other pointers in DEBUG ... well, because it easier to debug on a PC :)
            if (e.PointerDeviceType != PointerDeviceType.Touch)
            {
                e.Complete();
                return;
            }
#endif

            if (m_isIdle)
            {
                m_isIdle = false;
            }

            m_lastActionWasClosing = false;
            m_lastActionWasOpening = false;
            m_isInteracting        = true;

            //Once the user has started interacting with a SwipeControl in the closed state we are free to unblock contents.
            //Contents of items opposite the currently opened ones will not be created.
            if (!m_isOpen)
            {
                m_blockNearContent = false;
                m_blockFarContent  = false;
            }

            _positionWhenCaptured = new Vector2((float)_transform.X, (float)_transform.Y);

            // As soon as manipulation starts, we make sure to abort any pending explicit pointer capture,
            // so button nested (or containing) this SwipeControl won't fire their commands.
            // It's not the common behavior for buttons, but this has been observed in SwipeControl on UWP as of 2021-07-27.
            foreach (var pointer in e.Pointers)
            {
                if (PointerCapture.TryGet(pointer, out var capture))
                {
                    var targets = capture.GetTargets(PointerCaptureKind.Explicit).ToList();
                    global::System.Diagnostics.Debug.Assert(targets.Count <= 1);
                    foreach (var target in targets)
                    {
                        target.Element.ReleasePointerCapture(capture.Pointer);
                    }
                }
            }
        }
Ejemplo n.º 7
0
        internal static void ProcessPointerUp(PointerRoutedEventArgs args, bool isAfterHandledUp = false)
        {
            // We don't want handled events raised on RootVisual,
            // instead we wait for the element that handled it to directly forward it to us,
            // but only ** AFTER ** the up has been fully processed (with isAfterHandledUp = true).
            // This is required to be sure that element process gestures and manipulations before we raise the exit
            // (e.g. the 'tapped' event on a Button would be fired after the 'exit').
            var isHandled           = args.Handled;   // Capture here as args might be reset before checked for focus
            var isUpFullyDispatched = isAfterHandledUp || !isHandled;

            if (!isUpFullyDispatched)
            {
                return;
            }

#if __ANDROID__ || __WASM__ || __IOS__
#if __ANDROID__ || __IOS__ // Not needed on WASM as we do have native support of the exit event
                           // On Android and iOS we use the RootVisual to raise the UWP only exit event (in managed only)

            if (args.Pointer.PointerDeviceType is PointerDeviceType.Touch &&
                args.OriginalSource is UIElement src)
            {
                // It's acceptable to use only the OriginalSource on Android and iOS:
                // since those platforms have "implicit capture" and captures are propagated to the OS,
                // the OriginalSource will be the element that has capture (if any).

                src.RedispatchPointerExited(args.Reset(canBubbleNatively: false));
            }
#endif

            // Uno specific: To ensure focus is properly lost when clicking "outside" app's content,
            // we set focus here. In case UWP, focus is set to the root ScrollViewer instead,
            // but Uno does not have it on all targets yet.
            if (!isHandled &&          // so isAfterHandledUp is false!
                args.GetCurrentPoint(null).Properties.PointerUpdateKind is PointerUpdateKind.LeftButtonReleased &&
                !PointerCapture.TryGet(args.Pointer, out _) &&
                FocusManager.GetFocusedElement() is UIElement uiElement)
            {
                uiElement.Unfocus();
                args.Handled = true;
            }

            ReleaseCaptures(args.Reset(canBubbleNatively: false));
#endif
        }
Ejemplo n.º 8
0
            private void CoreWindow_PointerWheelChanged(CoreWindow sender, PointerEventArgs args)
            {
                var(originalSource, _) = VisualTreeHelper.HitTest(args.CurrentPoint.Position);

                // Even if impossible for the Release, we are fallbacking on the RootElement for safety
                // This is how UWP behaves: when out of the bounds of the Window, the root element is use.
                // Note that if another app covers your app, then the OriginalSource on UWP is still the element of your app at the pointer's location.
                originalSource ??= Windows.UI.Xaml.Window.Current.Content;

                if (originalSource is null)
                {
                    if (this.Log().IsEnabled(LogLevel.Trace))
                    {
                        this.Log().Trace($"CoreWindow_PointerPressed ({args.CurrentPoint.Position}) **undispatched**");
                    }

                    return;
                }

                if (this.Log().IsEnabled(LogLevel.Trace))
                {
                    this.Log().Trace($"CoreWindow_PointerPressed [{originalSource.GetDebugName()}");
                }

                var routedArgs = new PointerRoutedEventArgs(args, originalSource);

                // Second raise the event, either on the OriginalSource or on the capture owners if any
                if (PointerCapture.TryGet(routedArgs.Pointer, out var capture))
                {
                    foreach (var target in capture.Targets.ToArray())
                    {
                        target.Element.OnNativePointerWheel(routedArgs);
                    }
                }
                else
                {
                    originalSource.OnNativePointerWheel(routedArgs);
                }
            }
Ejemplo n.º 9
0
            private static void RaiseUsingCaptures(RaisePointerEventArgs raise, UIElement originalSource, PointerRoutedEventArgs routedArgs)
            {
                if (PointerCapture.TryGet(routedArgs.Pointer, out var capture))
                {
                    var targets = capture.Targets.ToList();
                    if (capture.IsImplicitOnly)
                    {
                        raise(originalSource, routedArgs, BubblingContext.Bubble);

                        foreach (var target in targets)
                        {
                            routedArgs.Handled = false;
                            raise(target.Element, routedArgs, BubblingContext.NoBubbling);
                        }
                    }
                    else
                    {
                        var explicitTarget = targets.Find(c => c.Kind == PointerCaptureKind.Explicit) !;

                        raise(explicitTarget.Element, routedArgs, BubblingContext.Bubble);

                        foreach (var target in targets)
                        {
                            if (target == explicitTarget)
                            {
                                continue;
                            }

                            routedArgs.Handled = false;
                            raise(target.Element, routedArgs, BubblingContext.NoBubbling);
                        }
                    }
                }
                else
                {
                    raise(originalSource, routedArgs, BubblingContext.Bubble);
                }
            }
Ejemplo n.º 10
0
 public static bool TryGet(Pointer pointer, out PointerCapture capture)
 => _actives.TryGetValue(pointer.UniqueId, out capture);
Ejemplo n.º 11
0
                                        : new PointerCapture(pointer); // The capture will be added to the _actives only when a target is added to it.

            public static bool TryGet(PointerIdentifier pointer, out PointerCapture capture)
            => _actives.TryGetValue(pointer, out capture);