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 PreNotifyInput_Should_Not_Be_Called_If_Cancelled()
        {
            bool notified = false;

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

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

            InputElement  element = new InputElement();
            TestEventArgs e       = new TestEventArgs(element);

            e.RoutedEvent = InputElement.RawEvent;

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

            Assert.IsFalse(notified);
        }
        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 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 PreProcess_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();
                }
                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(calledWithMutated);
        }
        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);
        }
示例#7
0
        /// <summary>
        /// To prevent contaminating the system with test side effects
        /// (basically, to prevent our MockKeyboardDevice from listening and reacting to real
        /// keyboard input), we need to undo the damage done by the
        /// base KeyboardDevice's constructor where it subscribes to some events.
        /// By unsubscribing from these events we make sure our KeyboardDevice
        /// won't respond to real input and will be used solely to provide the
        /// desired state of the Shift, Alt and Ctrl modifier keys when asked for.
        /// </summary>
        private MockKeyboardDevice()
            : base(InputManager.Current)
        {
            // There's only one global input manager in the system
            InputManager inputManager = InputManager.Current;

            // First, unsubscribe our 3 handlers from the InputManager.

            // 1)
            // Undo the effect of the following line in the KeyboardDevice ctor:
            // this._inputManager.Value.PreProcessInput += new PreProcessInputEventHandler(this.PreProcessInput);
            PreProcessInputEventHandler preProcessInputHandler =
                GetDelegateForMethod <PreProcessInputEventHandler>(this, "PreProcessInput");

            inputManager.PreProcessInput -= preProcessInputHandler;

            // 2)
            // Undo the effect of the following line in the KeyboardDevice ctor:
            // this._inputManager.Value.PreNotifyInput += new NotifyInputEventHandler(this.PreNotifyInput);
            NotifyInputEventHandler preNotifyInputHandler =
                GetDelegateForMethod <NotifyInputEventHandler>(this, "PreNotifyInput");

            inputManager.PreNotifyInput -= preNotifyInputHandler;

            // 3)
            // Undo the effect of the following line in the KeyboardDevice ctor:
            // this._inputManager.Value.PostProcessInput += new ProcessInputEventHandler(this.PostProcessInput);
            ProcessInputEventHandler postProcessInputHandler =
                GetDelegateForMethod <ProcessInputEventHandler>(this, "PostProcessInput");

            inputManager.PostProcessInput -= postProcessInputHandler;

            // Now undo the damage done by creating a new TextServicesManager

            // this._TsfManager = new SecurityCriticalDataClass<TextServicesManager>(new TextServicesManager(inputManager));
            var textServicesManager = this.GetFieldValue("_TsfManager").GetFieldValue("_value");

            // this._inputManager.PreProcessInput += new PreProcessInputEventHandler(this.PreProcessInput);
            preProcessInputHandler        = GetDelegateForMethod <PreProcessInputEventHandler>(textServicesManager, "PreProcessInput");
            inputManager.PreProcessInput -= preProcessInputHandler;

            // this._inputManager.PostProcessInput += new ProcessInputEventHandler(this.PostProcessInput);
            postProcessInputHandler        = GetDelegateForMethod <ProcessInputEventHandler>(textServicesManager, "PostProcessInput");
            inputManager.PostProcessInput -= postProcessInputHandler;

            // And finally, revert the changes done by creating a new TextCompositionManager

            // this._textcompositionManager = new SecurityCriticalData<TextCompositionManager>(new TextCompositionManager(inputManager));
            var textCompositionManager = this.GetFieldValue("_textcompositionManager").GetFieldValue("_value");

            // this._inputManager.PreProcessInput += new PreProcessInputEventHandler(this.PreProcessInput);
            preProcessInputHandler        = GetDelegateForMethod <PreProcessInputEventHandler>(textCompositionManager, "PreProcessInput");
            inputManager.PreProcessInput -= preProcessInputHandler;

            // his._inputManager.PostProcessInput += new ProcessInputEventHandler(this.PostProcessInput);
            postProcessInputHandler        = GetDelegateForMethod <ProcessInputEventHandler>(textCompositionManager, "PostProcessInput");
            inputManager.PostProcessInput -= postProcessInputHandler;
        }
        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 PreProcessInput_Should_Be_Called()
        {
            bool called = false;

            PreProcessInputEventHandler preProcess = (sender, ev) =>
            {
                called = 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(called);
        }
示例#10
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.

                // In the future, in ordre to
                // make sure we all agree on this.  We could also
                // just delay the rest of the staging area until
                // the dispatcher frame finishes.  Unfortunately,
                // this means one could receive an input event for
                // something that happened a long time ago.
                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);
        }