public void Event_Should_Be_Routed_To_Device_Target()
        {
            InputElement element = new InputElement();
            TestEventArgs e = new TestEventArgs(element);
            e.RoutedEvent = InputElement.RawEvent;
            InputManager.Current.ProcessInput(e);

            Assert.IsTrue(element.RawEventRaised);
        }
        public void Event_Should_Not_Be_Routed_If_Cancelled()
        {
            PreProcessInputEventHandler preProcess = (sender, ev) =>
            {
                ev.Cancel();
            };

            InputElement element = new InputElement();
            TestEventArgs e = new TestEventArgs(element);
            e.RoutedEvent = InputElement.RawEvent;

            InputManager.Current.PreProcessInput += preProcess;
            InputManager.Current.ProcessInput(e);
            InputManager.Current.PreProcessInput -= preProcess;

            Assert.IsFalse(element.RawEventRaised);
        }
        public void PreNotifyInput_Should_Be_Called()
        {
            bool notified = false;

            NotifyInputEventHandler preNotify = (sender, ev) =>
            {
                notified = true;
            };

            InputElement element = new InputElement();
            TestEventArgs e = new TestEventArgs(element);
            e.RoutedEvent = InputElement.RawEvent;

            InputManager.Current.PreNotifyInput += preNotify;
            InputManager.Current.ProcessInput(e);
            InputManager.Current.PreNotifyInput -= preNotify;

            Assert.IsTrue(notified);
        }
示例#4
0
        private void ChangeFocus(DependencyObject focus, int timestamp)
        {
            DependencyObject o = null;

            if (focus != _focus)
            {
                // Update the critical pieces of data.
                DependencyObject oldFocus = _focus;
                _focus           = focus;
                _focusRootVisual = InputElement.GetRootVisual(focus);

                using (Dispatcher.DisableProcessing()) // Disable reentrancy due to locks taken
                {
                    // Adjust the handlers we use to track everything.
                    if (oldFocus != null)
                    {
                        o = oldFocus;
                        if (InputElement.IsUIElement(o))
                        {
                            ((UIElement)o).IsEnabledChanged -= _isEnabledChangedEventHandler;
                            ((UIElement)o).IsVisibleChanged -= _isVisibleChangedEventHandler;
                            ((UIElement)o).FocusableChanged -= _focusableChangedEventHandler;
                        }
                        else if (InputElement.IsContentElement(o))
                        {
                            ((ContentElement)o).IsEnabledChanged -= _isEnabledChangedEventHandler;
                            // NOTE: there is no IsVisible property for ContentElements.
                            ((ContentElement)o).FocusableChanged -= _focusableChangedEventHandler;
                        }
                        else
                        {
                            ((UIElement3D)o).IsEnabledChanged -= _isEnabledChangedEventHandler;
                            ((UIElement3D)o).IsVisibleChanged -= _isVisibleChangedEventHandler;
                            ((UIElement3D)o).FocusableChanged -= _focusableChangedEventHandler;
                        }
                    }
                    if (_focus != null)
                    {
                        o = _focus;
                        if (InputElement.IsUIElement(o))
                        {
                            ((UIElement)o).IsEnabledChanged += _isEnabledChangedEventHandler;
                            ((UIElement)o).IsVisibleChanged += _isVisibleChangedEventHandler;
                            ((UIElement)o).FocusableChanged += _focusableChangedEventHandler;
                        }
                        else if (InputElement.IsContentElement(o))
                        {
                            ((ContentElement)o).IsEnabledChanged += _isEnabledChangedEventHandler;
                            // NOTE: there is no IsVisible property for ContentElements.
                            ((ContentElement)o).FocusableChanged += _focusableChangedEventHandler;
                        }
                        else
                        {
                            ((UIElement3D)o).IsEnabledChanged += _isEnabledChangedEventHandler;
                            ((UIElement3D)o).IsVisibleChanged += _isVisibleChangedEventHandler;
                            ((UIElement3D)o).FocusableChanged += _focusableChangedEventHandler;
                        }
                    }
                }

                // Oddly enough, update the FocusWithinProperty properties first.  This is
                // so any callbacks will see the more-common FocusWithinProperty properties
                // set correctly.
                UIElement.FocusWithinProperty.OnOriginValueChanged(oldFocus, _focus, ref _focusTreeState);

                // Invalidate the IsKeyboardFocused properties.
                if (oldFocus != null)
                {
                    o = oldFocus;
                    o.SetValue(UIElement.IsKeyboardFocusedPropertyKey, false); // Same property for ContentElements
                }
                if (_focus != null)
                {
                    // Invalidate the IsKeyboardFocused property.
                    o = _focus;
                    o.SetValue(UIElement.IsKeyboardFocusedPropertyKey, true); // Same property for ContentElements
                }

                // Call TestServicesManager change the focus of the InputMethod is enable/disabled accordingly
                // so it's ready befere the GotKeyboardFocusEvent handler is invoked.
                if (_TsfManager != null)
                {
                    _TsfManager.Value.Focus(_focus);
                }

                // InputLanguageManager checks the preferred input languages.
                // This should before GotEvent because the preferred input language
                // should be set at the event handler.
                InputLanguageManager.Current.Focus(_focus, oldFocus);

                // Send the LostKeyboardFocus and GotKeyboardFocus events.
                if (oldFocus != null)
                {
                    KeyboardFocusChangedEventArgs lostFocus = new KeyboardFocusChangedEventArgs(this, timestamp, (IInputElement)oldFocus, (IInputElement)focus);
                    lostFocus.RoutedEvent = Keyboard.LostKeyboardFocusEvent;
                    lostFocus.Source      = oldFocus;
                    if (_inputManager != null)
                    {
                        _inputManager.Value.ProcessInput(lostFocus);
                    }
                }
                if (_focus != null)
                {
                    KeyboardFocusChangedEventArgs gotFocus = new KeyboardFocusChangedEventArgs(this, timestamp, (IInputElement)oldFocus, (IInputElement)_focus);
                    gotFocus.RoutedEvent = Keyboard.GotKeyboardFocusEvent;
                    gotFocus.Source      = _focus;
                    if (_inputManager != null)
                    {
                        _inputManager.Value.ProcessInput(gotFocus);
                    }
                }

                // InputMethod checks the preferred ime state.
                // The preferred input methods should be applied after Cicero TIP gots SetFocus callback.
                InputMethod.Current.GotKeyboardFocus(_focus);

                //Could be also built-in into IsKeyboardFocused_Changed static on UIElement and ContentElement
                //However the Automation likes to go immediately back on us so it would be better be last one...
                AutomationPeer.RaiseFocusChangedEventHelper((IInputElement)_focus);
            }
        }
        public void ProcessInput_Should_Return_True_If_One_Event_Handled()
        {
            PreProcessInputEventHandler preProcess = (sender, ev) =>
            {
                if (ev.StagingItem.Input.RoutedEvent == InputElement.RawEvent)
                {
                    TestEventArgs mutated = new TestEventArgs(ev.StagingItem.Input.Device.Target);
                    mutated.RoutedEvent = InputElement.MutatedEvent;
                    StagingAreaInputItem stagingItem = CreateStagingItem(mutated);
                    ev.PushInput(stagingItem);
                }
            };

            InputElement element = new InputElement();
            element.SetMutatedEventHandled = true;

            TestEventArgs e = new TestEventArgs(element);
            e.RoutedEvent = InputElement.RawEvent;

            InputManager.Current.PreProcessInput += preProcess;
            bool result = InputManager.Current.ProcessInput(e);
            InputManager.Current.PreProcessInput -= preProcess;

            // This goes against the documentation which says should return true if all events handled.
            Assert.IsTrue(element.RawEventRaised);
            Assert.IsTrue(element.MutatedEventRaised);
            Assert.IsTrue(result);
        }
        public void Mutated_Event_Should_Be_Raised_With_Nested_ProcessInput()
        {
            bool calledWithMutated = false;

            PreProcessInputEventHandler preProcess = (sender, ev) =>
            {
                if (ev.StagingItem.Input.RoutedEvent == InputElement.RawEvent)
                {
                    TestEventArgs mutated = new TestEventArgs(ev.StagingItem.Input.Device.Target);
                    mutated.RoutedEvent = InputElement.MutatedEvent;
                    InputManager.Current.ProcessInput(mutated);
                }
                else if (ev.StagingItem.Input.RoutedEvent == InputElement.MutatedEvent)
                {
                    calledWithMutated = true;
                }
            };

            InputElement element = new InputElement();
            TestEventArgs e = new TestEventArgs(element);
            e.RoutedEvent = InputElement.RawEvent;

            InputManager.Current.PreProcessInput += preProcess;
            InputManager.Current.ProcessInput(e);
            InputManager.Current.PreProcessInput -= preProcess;

            Assert.IsTrue(element.RawEventRaised);
            Assert.IsTrue(element.MutatedEventRaised);
            Assert.IsTrue(calledWithMutated);
        }
        public void PostProcess_Event_Should_Be_Called_With_Mutated_Event()
        {
            bool calledWithMutated = false;

            PreProcessInputEventHandler preProcess = (sender, ev) =>
            {
                if (ev.StagingItem.Input.RoutedEvent == InputElement.RawEvent)
                {
                    TestEventArgs mutated = new TestEventArgs(ev.StagingItem.Input.Device.Target);
                    mutated.RoutedEvent = InputElement.MutatedEvent;
                    StagingAreaInputItem stagingItem = CreateStagingItem(mutated);
                    ev.PushInput(stagingItem);
                    ev.Cancel();
                }
            };

            ProcessInputEventHandler postProcess = (sender, ev) =>
            {
                if (ev.StagingItem.Input.RoutedEvent == InputElement.MutatedEvent)
                {
                    calledWithMutated = true;
                }
            };

            InputElement element = new InputElement();
            TestEventArgs e = new TestEventArgs(element);
            e.RoutedEvent = InputElement.RawEvent;

            InputManager.Current.PreProcessInput += preProcess;
            InputManager.Current.PostProcessInput += postProcess;
            InputManager.Current.ProcessInput(e);
            InputManager.Current.PostProcessInput += postProcess;
            InputManager.Current.PreProcessInput -= preProcess;

            Assert.IsTrue(calledWithMutated);
        }
        public void ProcessInput_Should_Return_False_If_No_Events_Handled()
        {
            PreProcessInputEventHandler preProcess = (sender, ev) =>
            {
                if (ev.StagingItem.Input.RoutedEvent == InputElement.RawEvent)
                {
                    TestEventArgs mutated = new TestEventArgs(ev.StagingItem.Input.Device.Target);
                    mutated.RoutedEvent = InputElement.MutatedEvent;
                    StagingAreaInputItem stagingItem = CreateStagingItem(mutated);
                    ev.PushInput(stagingItem);
                }
            };

            InputElement element = new InputElement();
            TestEventArgs e = new TestEventArgs(element);
            e.RoutedEvent = InputElement.RawEvent;

            InputManager.Current.PreProcessInput += preProcess;
            bool result = InputManager.Current.ProcessInput(e);
            InputManager.Current.PreProcessInput -= preProcess;

            Assert.IsFalse(result);
        }
        public void Mutated_Event_Should_Still_Be_Raised_When_Raw_Event_Cancelled()
        {
            PreProcessInputEventHandler preProcess = (sender, ev) =>
            {
                if (ev.StagingItem.Input.RoutedEvent == InputElement.RawEvent)
                {
                    TestEventArgs mutated = new TestEventArgs(ev.StagingItem.Input.Device.Target);
                    mutated.RoutedEvent = InputElement.MutatedEvent;
                    StagingAreaInputItem stagingItem = CreateStagingItem(mutated);
                    ev.PushInput(stagingItem);
                    ev.Cancel();
                }
            };

            InputElement element = new InputElement();
            TestEventArgs e = new TestEventArgs(element);
            e.RoutedEvent = InputElement.RawEvent;

            InputManager.Current.PreProcessInput += preProcess;
            InputManager.Current.ProcessInput(e);
            InputManager.Current.PreProcessInput -= preProcess;

            Assert.IsFalse(element.RawEventRaised);
            Assert.IsTrue(element.MutatedEventRaised);
        }
示例#10
0
 /// <summary>
 ///     Retrieves the history of intermediate Points up to 64 previous coordinates of the mouse or pen.
 /// </summary>
 /// <param name="relativeTo">
 ///     The element relative which the points need to be returned.
 /// </param>
 /// <param name="points">
 ///     Points relative to the first parameter are returned.
 /// </param>
 public static int GetIntermediatePoints(IInputElement relativeTo, Point[] points)
 {
     // Security Mitigation: do not give out input state if the device is not active.
     if (Mouse.PrimaryDevice.IsActive)
     {
         if (relativeTo != null)
         {
             PresentationSource inputSource = PresentationSource.FromDependencyObject(InputElement.GetContainingVisual(relativeTo as DependencyObject));
             if (inputSource != null)
             {
                 IMouseInputProvider mouseInputProvider = inputSource.GetInputProvider(typeof(MouseDevice)) as IMouseInputProvider;
                 if (null != mouseInputProvider)
                 {
                     return(mouseInputProvider.GetIntermediatePoints(relativeTo, points));
                 }
             }
         }
     }
     return(-1);
 }
示例#11
0
        /// <summary>
        ///     Determines if we can remain focused on the element we think has focus
        /// </summary>
        /// <remarks>
        ///     Invoked asynchronously by ReevaluateFocusAsync.
        ///     Confirms that the element we think has focus is:
        ///         - still enabled
        ///         - still visible
        ///         - still in the tree
        /// </remarks>
        private object ReevaluateFocusCallback(object arg)
        {
            _reevaluateFocusOperation = null;

            if (_focus == null)
            {
                return(null);
            }

            //
            // Reevaluate the eligability of the focused element to actually
            // have focus.  If that element is no longer focusable, then search
            // for an ancestor that is.
            //
            DependencyObject element = _focus;

            while (element != null)
            {
                if (Keyboard.IsFocusable(element))
                {
                    break;
                }

                // Walk the current tree structure.
                element = DeferredElementTreeState.GetCoreParent(element, null);
            }

            // Get the PresentationSource that contains the element to be focused.
            PresentationSource presentationSource = null;
            DependencyObject   visualContainer    = InputElement.GetContainingVisual(element);

            if (visualContainer != null)
            {
                presentationSource = PresentationSource.CriticalFromVisual(visualContainer);
            }

            // The default action is to reset focus to the root element
            // of the active presentation source.
            bool             moveFocus   = true;
            DependencyObject moveFocusTo = null;

            if (presentationSource != null)
            {
                IKeyboardInputProvider keyboardProvider = presentationSource.GetInputProvider(typeof(KeyboardDevice)) as IKeyboardInputProvider;
                if (keyboardProvider != null)
                {
                    // Confirm with the keyboard provider for this
                    // presentation source that it has acquired focus.
                    if (keyboardProvider.AcquireFocus(true))
                    {
                        if (element == _focus)
                        {
                            // The focus element is still good.
                            moveFocus = false;
                        }
                        else
                        {
                            // The focus element is no longer focusable, but we found
                            // an ancestor that is, so move focus there.
                            moveFocus   = true;
                            moveFocusTo = element;
                        }
                    }
                }
            }

            if (moveFocus)
            {
                if (moveFocusTo == null && _activeSource != null)
                {
                    moveFocusTo = _activeSource.Value.RootVisual as DependencyObject;
                }


                Focus(moveFocusTo, /*askOld=*/ false, /*askNew=*/ true, /*forceToNullIfFailed=*/ true);
            }
            else
            {
                // Refresh FocusWithinProperty so that ReverseInherited Flags are updated.
                //
                // We only need to do this if there is any information about the old
                // tree structure.
                if (_focusTreeState != null && !_focusTreeState.IsEmpty)
                {
                    UIElement.FocusWithinProperty.OnOriginValueChanged(_focus, _focus, ref _focusTreeState);
                }
            }

            return(null);
        }
        public void PostProcessInput_Should_Not_Be_Called_If_Cancelled()
        {
            bool notified = false;

            PreProcessInputEventHandler preProcess = (sender, ev) =>
            {
                ev.Cancel();
            };

            ProcessInputEventHandler postProcess = (sender, ev) =>
            {
                notified = true;
            };

            InputElement element = new InputElement();
            TestEventArgs e = new TestEventArgs(element);
            e.RoutedEvent = InputElement.RawEvent;

            InputManager.Current.PreProcessInput += preProcess;
            InputManager.Current.PostProcessInput += postProcess;
            InputManager.Current.ProcessInput(e);
            InputManager.Current.PostProcessInput += postProcess;
            InputManager.Current.PreProcessInput -= preProcess;

            Assert.IsFalse(notified);
        }
示例#13
0
        private bool ProcessStagingArea()
        {
            bool handled = false;

            // For performance reasons, try to reuse the input event args.
            // If we are reentrered, we have to start over with fresh event
            // args, so we clear the member variables before continuing.
            // Also, we cannot simply make an single instance of the
            // PreProcessedInputEventArgs and cast it to NotifyInputEventArgs
            // or ProcessInputEventArgs because a malicious user could upcast
            // the object and call inappropriate methods.
            NotifyInputEventArgs     notifyInputEventArgs     = (_notifyInputEventArgs != null) ? _notifyInputEventArgs : new NotifyInputEventArgs();
            ProcessInputEventArgs    processInputEventArgs    = (_processInputEventArgs != null) ? _processInputEventArgs : new ProcessInputEventArgs();
            PreProcessInputEventArgs preProcessInputEventArgs = (_preProcessInputEventArgs != null) ? _preProcessInputEventArgs : new PreProcessInputEventArgs();

            _notifyInputEventArgs     = null;
            _processInputEventArgs    = null;
            _preProcessInputEventArgs = null;

            // Because we can be reentered, we can't just enumerate over the
            // staging area - that could throw an exception if the queue
            // changes underneath us.  Instead, just loop until we find a
            // frame marker or until the staging area is empty.
            StagingAreaInputItem item = null;

            while ((item = PopInput()) != null)
            {
                // If we found a marker, we have reached the end of a
                // "section" of the staging area.  We just return from
                // the synchronous processing of the staging area.
                // If a dispatcher frame has been pushed by someone, this
                // will not return to the original ProcessInput.  Instead
                // it will unwind to the dispatcher and since we have
                // already pushed a work item to continue processing the
                // input, it will simply call back into us to do more
                // processing.  At which point we will continue to drain
                // the staging area.  This could cause strage behavior,
                // but it is deemed more acceptable than stalling input
                // processing.
                //



                if (item.IsMarker)
                {
                    break;
                }

                // Pre-Process the input.  This could modify the staging
                // area, and it could cancel the processing of this
                // input event.
                //
                // Because we use multi-cast delegates, we always have to
                // create a new multi-cast delegate when we add or remove
                // a handler.  This means we can just call the current
                // multi-cast delegate instance, and it is safe to iterate
                // over, even if we get reentered.
                if (_preProcessInput != null)
                {
                    preProcessInputEventArgs.Reset(item, this);

                    // Invoke the handlers in reverse order so that handlers that
                    // users add are invoked before handlers in the system.
                    Delegate[] handlers = _preProcessInput.GetInvocationList();
                    for (int i = (handlers.Length - 1); i >= 0; i--)
                    {
                        PreProcessInputEventHandler handler = (PreProcessInputEventHandler)handlers[i];
                        handler(this, preProcessInputEventArgs);
                    }
                }

                if (!preProcessInputEventArgs.Canceled)
                {
                    // Pre-Notify the input.
                    //
                    // Because we use multi-cast delegates, we always have to
                    // create a new multi-cast delegate when we add or remove
                    // a handler.  This means we can just call the current
                    // multi-cast delegate instance, and it is safe to iterate
                    // over, even if we get reentered.
                    if (_preNotifyInput != null)
                    {
                        notifyInputEventArgs.Reset(item, this);

                        // Invoke the handlers in reverse order so that handlers that
                        // users add are invoked before handlers in the system.
                        Delegate[] handlers = _preNotifyInput.GetInvocationList();
                        for (int i = (handlers.Length - 1); i >= 0; i--)
                        {
                            NotifyInputEventHandler handler = (NotifyInputEventHandler)handlers[i];
                            handler(this, notifyInputEventArgs);
                        }
                    }

                    // Raise the input event being processed.
                    InputEventArgs input = item.Input;

                    // Some input events are explicitly associated with
                    // an element.  Those that are not are associated with
                    // the target of the input device for this event.
                    DependencyObject eventSource = input.Source as DependencyObject;
                    if (eventSource == null || !InputElement.IsValid(eventSource as IInputElement))
                    {
                        if (input.Device != null)
                        {
                            eventSource = input.Device.Target as DependencyObject;
                        }
                    }

                    // During synchronized input processing, event should be discarded if not listening for this input type.
                    if (_isSynchronizedInput &&
                        SynchronizedInputHelper.IsMappedEvent(input) &&
                        Array.IndexOf(SynchronizedInputEvents, input.RoutedEvent) < 0 &&
                        Array.IndexOf(PairedSynchronizedInputEvents, input.RoutedEvent) < 0)
                    {
                        if (!SynchronizedInputHelper.ShouldContinueListening(input))
                        {
                            // Discard the event
                            _synchronizedInputState = SynchronizedInputStates.Discarded;
                            SynchronizedInputHelper.RaiseAutomationEvents();
                            CancelSynchronizedInput();
                        }
                        else
                        {
                            _synchronizedInputAsyncClearOperation = Dispatcher.BeginInvoke((Action) delegate
                            {
                                // Discard the event
                                _synchronizedInputState = SynchronizedInputStates.Discarded;
                                SynchronizedInputHelper.RaiseAutomationEvents();
                                CancelSynchronizedInput();
                            },
                                                                                           DispatcherPriority.Background);
                        }
                    }
                    else
                    {
                        if (eventSource != null)
                        {
                            if (InputElement.IsUIElement(eventSource))
                            {
                                UIElement e = (UIElement)eventSource;

                                e.RaiseEvent(input, true); // Call the "trusted" flavor of RaiseEvent.
                            }
                            else if (InputElement.IsContentElement(eventSource))
                            {
                                ContentElement ce = (ContentElement)eventSource;

                                ce.RaiseEvent(input, true);// Call the "trusted" flavor of RaiseEvent.
                            }
                            else if (InputElement.IsUIElement3D(eventSource))
                            {
                                UIElement3D e3D = (UIElement3D)eventSource;

                                e3D.RaiseEvent(input, true); // Call the "trusted" flavor of RaiseEvent
                            }

                            // If synchronized input raise appropriate automation event.

                            if (_isSynchronizedInput && SynchronizedInputHelper.IsListening(_listeningElement, input))
                            {
                                if (!SynchronizedInputHelper.ShouldContinueListening(input))
                                {
                                    SynchronizedInputHelper.RaiseAutomationEvents();
                                    CancelSynchronizedInput();
                                }
                                else
                                {
                                    _synchronizedInputAsyncClearOperation = Dispatcher.BeginInvoke((Action) delegate
                                    {
                                        SynchronizedInputHelper.RaiseAutomationEvents();
                                        CancelSynchronizedInput();
                                    },
                                                                                                   DispatcherPriority.Background);
                                }
                            }
                        }
                    }

                    // Post-Notify the input.
                    //
                    // Because we use multi-cast delegates, we always have to
                    // create a new multi-cast delegate when we add or remove
                    // a handler.  This means we can just call the current
                    // multi-cast delegate instance, and it is safe to iterate
                    // over, even if we get reentered.
                    if (_postNotifyInput != null)
                    {
                        notifyInputEventArgs.Reset(item, this);

                        // Invoke the handlers in reverse order so that handlers that
                        // users add are invoked before handlers in the system.
                        Delegate[] handlers = _postNotifyInput.GetInvocationList();
                        for (int i = (handlers.Length - 1); i >= 0; i--)
                        {
                            NotifyInputEventHandler handler = (NotifyInputEventHandler)handlers[i];
                            handler(this, notifyInputEventArgs);
                        }
                    }

                    // Post-Process the input.  This could modify the staging
                    // area.
                    //
                    // Because we use multi-cast delegates, we always have to
                    // create a new multi-cast delegate when we add or remove
                    // a handler.  This means we can just call the current
                    // multi-cast delegate instance, and it is safe to iterate
                    // over, even if we get reentered.
                    if (_postProcessInput != null)
                    {
                        processInputEventArgs.Reset(item, this);

                        RaiseProcessInputEventHandlers(_postProcessInput, processInputEventArgs);

                        // PreviewInputReport --> InputReport
                        if (item.Input.RoutedEvent == InputManager.PreviewInputReportEvent)
                        {
                            if (!item.Input.Handled)
                            {
                                InputReportEventArgs previewInputReport = (InputReportEventArgs)item.Input;

                                InputReportEventArgs inputReport = new InputReportEventArgs(previewInputReport.Device, previewInputReport.Report);
                                inputReport.RoutedEvent = InputManager.InputReportEvent;
                                PushInput(inputReport, item);
                            }
                        }
                    }

                    if (input.Handled)
                    {
                        handled = true;
                    }
                }
            }

            // Store our input event args so that we can use them again, and
            // avoid having to allocate more.
            _notifyInputEventArgs     = notifyInputEventArgs;
            _processInputEventArgs    = processInputEventArgs;
            _preProcessInputEventArgs = preProcessInputEventArgs;

            // Make sure to throw away the contents of the event args so
            // we don't keep refs around to things we don't mean to.
            _notifyInputEventArgs.Reset(null, null);
            _processInputEventArgs.Reset(null, null);
            _preProcessInputEventArgs.Reset(null, null);

            return(handled);
        }
示例#14
0
        private IInputElement CriticalHitTest(Point point, bool isSynchronize)
        {
            IInputElement over = null;

            if (_activeSource != null)
            {
                switch (_captureMode)
                {
                case CaptureMode.None:
                    // No capture, do a regular hit-test.
                    if (_isDown)
                    {
                        if (isSynchronize)
                        {
                            // In a synchronize call, we need to hit-test the window in addition to the element
                            over = GlobalHitTest(point, _activeSource);
                        }
                        else
                        {
                            // Just hit-test the element
                            over = LocalHitTest(point, _activeSource);
                        }

                        EnsureValid(ref over);
                    }
                    break;

                case CaptureMode.Element:
                    // Capture is to a specific element, so the device will always be over that element.
                    over = _captured;
                    break;

                case CaptureMode.SubTree:
                    // Capture is set to an entire subtree. Hit-test to determine the element (and window)
                    // the device is over. If the element is within the captured sub-tree (which can span
                    // multiple windows), then the device is over that element. If the element is not within
                    // the sub-tree, then the device is over the captured element.
                {
                    IInputElement capture = InputElement.GetContainingInputElement(_captured as DependencyObject);
                    if (capture != null)
                    {
                        // We need to re-hit-test to get the "real" UIElement we are over.
                        // This allows us to have our capture-to-subtree span multiple windows.

                        // GlobalHitTest always returns an IInputElement, so we are sure to have one.
                        over = GlobalHitTest(point, _activeSource);
                    }

                    EnsureValid(ref over);

                    // Make sure that the element we hit is acutally underneath
                    // our captured element.  Because we did a global hit test, we
                    // could have hit an element in a completely different window.
                    //
                    // Note that we support the child being in a completely different window.
                    // So we use the GetUIParent method instead of just looking at
                    // visual/content parents.
                    if (over != null)
                    {
                        IInputElement ieTest = over;
                        while ((ieTest != null) && (ieTest != _captured))
                        {
                            UIElement eTest = ieTest as UIElement;

                            if (eTest != null)
                            {
                                ieTest = InputElement.GetContainingInputElement(eTest.GetUIParent(true));
                            }
                            else
                            {
                                ContentElement ceTest = ieTest as ContentElement;

                                if (ceTest != null)
                                {
                                    ieTest = InputElement.GetContainingInputElement(ceTest.GetUIParent(true));
                                }
                                else
                                {
                                    UIElement3D e3DTest = (UIElement3D)ieTest;
                                    ieTest = InputElement.GetContainingInputElement(e3DTest.GetUIParent(true));
                                }
                            }
                        }

                        if (ieTest != _captured)
                        {
                            // If we missed the capture point, consider the device over the capture point.
                            over = _captured;
                        }
                    }
                    else
                    {
                        // If we didn't hit anything, consider the device over the capture point.
                        over = _captured;
                    }
                }
                break;
                }
            }

            return(over);
        }
示例#15
0
        private static void FindCommandBinding(object sender, RoutedEventArgs e, ICommand command, bool execute)
        {
            // Check local command bindings
            CommandBindingCollection commandBindings = null;
            DependencyObject         senderAsDO      = sender as DependencyObject;

            if (InputElement.IsUIElement(senderAsDO))
            {
                commandBindings = ((UIElement)senderAsDO).CommandBindingsInternal;
            }
            else if (InputElement.IsContentElement(senderAsDO))
            {
                commandBindings = ((ContentElement)senderAsDO).CommandBindingsInternal;
            }
            else if (InputElement.IsUIElement3D(senderAsDO))
            {
                commandBindings = ((UIElement3D)senderAsDO).CommandBindingsInternal;
            }
            if (commandBindings != null)
            {
                FindCommandBinding(commandBindings, sender, e, command, execute);
            }

            // If no command binding is found, check class command bindings
            // First find the relevant command bindings, under the lock.
            // Most of the time there are no such bindings;  most of the rest of
            // the time there is only one.   Lazy-allocate with this in mind.
            Tuple <Type, CommandBinding>         tuple = null; // zero or one binding
            List <Tuple <Type, CommandBinding> > list  = null; // more than one

            lock (_classCommandBindings.SyncRoot)
            {
                // Check from the current type to all the base types
                Type classType = sender.GetType();
                while (classType != null)
                {
                    CommandBindingCollection classCommandBindings = _classCommandBindings[classType] as CommandBindingCollection;
                    if (classCommandBindings != null)
                    {
                        int index = 0;
                        while (true)
                        {
                            CommandBinding commandBinding = classCommandBindings.FindMatch(command, ref index);
                            if (commandBinding != null)
                            {
                                if (tuple == null)
                                {
                                    tuple = new Tuple <Type, CommandBinding>(classType, commandBinding);
                                }
                                else
                                {
                                    if (list == null)
                                    {
                                        list = new List <Tuple <Type, CommandBinding> >();
                                        list.Add(tuple);
                                    }
                                    list.Add(new Tuple <Type, CommandBinding>(classType, commandBinding));
                                }
                            }
                            else
                            {
                                break;
                            }
                        }
                    }
                    classType = classType.BaseType;
                }
            }

            // execute the bindings.  This can call into user code, so it must
            // be done outside the lock to avoid deadlock.
            if (list != null)
            {
                // more than one binding
                ExecutedRoutedEventArgs   exArgs    = execute ? (ExecutedRoutedEventArgs)e : null;
                CanExecuteRoutedEventArgs canExArgs = execute ? null : (CanExecuteRoutedEventArgs)e;
                for (int i = 0; i < list.Count; ++i)
                {
                    // invoke the binding
                    if ((execute && ExecuteCommandBinding(sender, exArgs, list[i].Item2)) ||
                        (!execute && CanExecuteCommandBinding(sender, canExArgs, list[i].Item2)))
                    {
                        // if it succeeds, advance past the remaining bindings for this type
                        Type classType = list[i].Item1;
                        while (++i < list.Count && list[i].Item1 == classType)
                        {
                            // no body needed
                        }
                        --i;    // back up, so that the outer for-loop advances to the right place
                    }
                }
            }
            else if (tuple != null)
            {
                // only one binding
                if (execute)
                {
                    ExecuteCommandBinding(sender, (ExecutedRoutedEventArgs)e, tuple.Item2);
                }
                else
                {
                    CanExecuteCommandBinding(sender, (CanExecuteRoutedEventArgs)e, tuple.Item2);
                }
            }
        }
示例#16
0
        /// <summary>
        ///     Scans input and command bindings for matching gestures and executes the appropriate command
        /// </summary>
        /// <remarks>
        ///     Scans for command to execute in the following order:
        ///     - input bindings associated with the targetElement instance
        ///     - input bindings associated with the targetElement class
        ///     - command bindings associated with the targetElement instance
        ///     - command bindings associated with the targetElement class
        /// </remarks>
        /// <param name="targetElement">UIElement/ContentElement to be scanned for input and command bindings</param>
        /// <param name="inputEventArgs">InputEventArgs to be matched against for gestures</param>
        internal static void TranslateInput(IInputElement targetElement, InputEventArgs inputEventArgs)
        {
            if ((targetElement == null) || (inputEventArgs == null))
            {
                return;
            }

            ICommand      command   = null;
            IInputElement target    = null;
            object        parameter = null;

            // Determine UIElement/ContentElement/Neither type
            DependencyObject targetElementAsDO = targetElement as DependencyObject;
            bool             isUIElement       = InputElement.IsUIElement(targetElementAsDO);
            bool             isContentElement  = !isUIElement && InputElement.IsContentElement(targetElementAsDO);
            bool             isUIElement3D     = !isUIElement && !isContentElement && InputElement.IsUIElement3D(targetElementAsDO);

            // Step 1: Check local input bindings
            InputBindingCollection localInputBindings = null;

            if (isUIElement)
            {
                localInputBindings = ((UIElement)targetElement).InputBindingsInternal;
            }
            else if (isContentElement)
            {
                localInputBindings = ((ContentElement)targetElement).InputBindingsInternal;
            }
            else if (isUIElement3D)
            {
                localInputBindings = ((UIElement3D)targetElement).InputBindingsInternal;
            }
            if (localInputBindings != null)
            {
                InputBinding inputBinding = localInputBindings.FindMatch(targetElement, inputEventArgs);
                if (inputBinding != null)
                {
                    command   = inputBinding.Command;
                    target    = inputBinding.CommandTarget;
                    parameter = inputBinding.CommandParameter;
                }
            }

            // Step 2: If no command, check class input bindings
            if (command == null)
            {
                lock (_classInputBindings.SyncRoot)
                {
                    Type classType = targetElement.GetType();
                    while (classType != null)
                    {
                        InputBindingCollection classInputBindings = _classInputBindings[classType] as InputBindingCollection;
                        if (classInputBindings != null)
                        {
                            InputBinding inputBinding = classInputBindings.FindMatch(targetElement, inputEventArgs);
                            if (inputBinding != null)
                            {
                                command   = inputBinding.Command;
                                target    = inputBinding.CommandTarget;
                                parameter = inputBinding.CommandParameter;
                                break;
                            }
                        }
                        classType = classType.BaseType;
                    }
                }
            }

            // Step 3: If no command, check local command bindings
            if (command == null)
            {
                // Check for the instance level ones Next
                CommandBindingCollection localCommandBindings = null;
                if (isUIElement)
                {
                    localCommandBindings = ((UIElement)targetElement).CommandBindingsInternal;
                }
                else if (isContentElement)
                {
                    localCommandBindings = ((ContentElement)targetElement).CommandBindingsInternal;
                }
                else if (isUIElement3D)
                {
                    localCommandBindings = ((UIElement3D)targetElement).CommandBindingsInternal;
                }
                if (localCommandBindings != null)
                {
                    command = localCommandBindings.FindMatch(targetElement, inputEventArgs);
                }
            }

            // Step 4: If no command, look at class command bindings
            if (command == null)
            {
                lock (_classCommandBindings.SyncRoot)
                {
                    Type classType = targetElement.GetType();
                    while (classType != null)
                    {
                        CommandBindingCollection classCommandBindings = _classCommandBindings[classType] as CommandBindingCollection;
                        if (classCommandBindings != null)
                        {
                            command = classCommandBindings.FindMatch(targetElement, inputEventArgs);
                            if (command != null)
                            {
                                break;
                            }
                        }
                        classType = classType.BaseType;
                    }
                }
            }

            // Step 5: If found a command, then execute it (unless it is
            // the special "NotACommand" command, which we simply ignore without
            // setting Handled=true, so that the input bubbles up to the parent)
            if (command != null && command != ApplicationCommands.NotACommand)
            {
                // We currently do not support declaring the element with focus as the target
                // element by setting target == null.  Instead, we interpret a null target to indicate
                // the element that we are routing the event through, e.g. the targetElement parameter.
                if (target == null)
                {
                    target = targetElement;
                }

                bool continueRouting = false;

                RoutedCommand routedCommand = command as RoutedCommand;
                if (routedCommand != null)
                {
                    if (routedCommand.CriticalCanExecute(parameter,
                                                         target,
                                                         inputEventArgs.UserInitiated /*trusted*/,
                                                         out continueRouting))
                    {
                        // If the command can be executed, we never continue to route the
                        // input event.
                        continueRouting = false;

                        ExecuteCommand(routedCommand, parameter, target, inputEventArgs);
                    }
                }
                else
                {
                    if (command.CanExecute(parameter))
                    {
                        command.Execute(parameter);
                    }
                }

                // If we mapped an input event to a command, we should always
                // handle the input event - regardless of whether the command
                // was executed or not.  Unless the CanExecute handler told us
                // to continue the route.
                inputEventArgs.Handled = !continueRouting;
            }
        }
示例#17
0
        internal static Point TranslatePoint(Point pt, DependencyObject from, DependencyObject to, out bool translated)
        {
            translated = false;

            Point ptTranslated = pt;

            // Get the containing and root visuals we are coming from.
            DependencyObject vFromAsDO = InputElement.GetContainingVisual(from);
            Visual           rootFrom  = InputElement.GetRootVisual(from) as Visual;

            Visual vFrom = vFromAsDO as Visual;

            if (vFromAsDO != null && vFrom == null)
            {
                // must be a Visual3D - get it's 2D visual parent
                vFrom = VisualTreeHelper.GetContainingVisual2D(vFromAsDO);
            }

            if (vFrom != null && rootFrom != null)
            {
                GeneralTransform gUp;
                Matrix           mUp;

                bool isUpSimple = false;
                isUpSimple = vFrom.TrySimpleTransformToAncestor(rootFrom,
                                                                false, /* do not apply inverse */
                                                                out gUp,
                                                                out mUp);
                if (isUpSimple)
                {
                    ptTranslated = mUp.Transform(ptTranslated);
                }
                else if (gUp.TryTransform(ptTranslated, out ptTranslated) == false)
                {
                    // Error.  Out parameter has been set false.
                    return(new Point());
                }

                // If no element was specified to translate to, we leave the coordinates
                // translated to the root.
                if (to != null)
                {
                    // Get the containing and root visuals we are going to.
                    DependencyObject vTo    = InputElement.GetContainingVisual(to);
                    Visual           rootTo = InputElement.GetRootVisual(to) as Visual;

                    if (vTo != null && rootTo != null)
                    {
                        // If both are under the same root visual, we can easily translate the point
                        // between them by translating up to the root, and then back down.
                        //
                        // However, if both are under different roots, we can only translate
                        // between them if we know how to relate the two root visuals.  Currently
                        // we only know how to do that if both roots are sourced in HwndSources.
                        if (rootFrom != rootTo)
                        {
                            HwndSource sourceFrom = PresentationSource.CriticalFromVisual(rootFrom) as HwndSource;
                            HwndSource sourceTo   = PresentationSource.CriticalFromVisual(rootTo) as HwndSource;


                            if (sourceFrom != null && sourceFrom.CriticalHandle != IntPtr.Zero && sourceFrom.CompositionTarget != null &&
                                sourceTo != null && sourceTo.CriticalHandle != IntPtr.Zero && sourceTo.CompositionTarget != null)
                            {
                                // Translate the point into client coordinates.
                                ptTranslated = PointUtil.RootToClient(ptTranslated, sourceFrom);

                                // Translate the point into screen coordinates.
                                Point ptScreen = PointUtil.ClientToScreen(ptTranslated, sourceFrom);

                                // Translate the point back the the client coordinates of the To window.
                                ptTranslated = PointUtil.ScreenToClient(ptScreen, sourceTo);

                                // Translate the point back to the root element.
                                ptTranslated = PointUtil.ClientToRoot(ptTranslated, sourceTo);
                            }
                            else
                            {
                                // Error.  Out parameter has been set false.
                                return(new Point());
                            }
                        }

                        // Translate the point from the root to the visual.
                        GeneralTransform gDown;
                        Matrix           mDown;

                        Visual vToAsVisual = vTo as Visual;
                        if (vToAsVisual == null)
                        {
                            // must be a Visual3D
                            vToAsVisual = VisualTreeHelper.GetContainingVisual2D(vTo);
                        }

                        bool isDownSimple = vToAsVisual.TrySimpleTransformToAncestor(rootTo,
                                                                                     true, /* apply inverse */
                                                                                     out gDown,
                                                                                     out mDown);

                        if (isDownSimple)
                        {
                            ptTranslated = mDown.Transform(ptTranslated);
                        }
                        else if (gDown != null)
                        {
                            if (gDown.TryTransform(ptTranslated, out ptTranslated) == false)
                            {
                                // Error.  Out parameter has been set false.
                                return(new Point());
                            }
                        }
                        else
                        {
                            // Error.  Out parameter has been set false.
                            return(new Point());
                        }
                    }
                    else
                    {
                        // Error.  Out parameter has been set false.
                        return(new Point());
                    }
                }
            }
            else
            {
                // Error.  Out parameter has been set false.
                return(new Point());
            }

            translated = true;
            return(ptTranslated);
        }