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);
        }
Beispiel #2
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 PostNotifyInput_Should_Be_Called()
        {
            bool notified = false;

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

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

            e.RoutedEvent = InputElement.RawEvent;

            InputManager.Current.PostNotifyInput += postNotify;
            InputManager.Current.ProcessInput(e);
            InputManager.Current.PostNotifyInput -= postNotify;

            Assert.IsTrue(notified);
        }
        public void PostNotify_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();
                }
            };

            NotifyInputEventHandler postNotify = (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.PostNotifyInput += postNotify;
            InputManager.Current.ProcessInput(e);
            InputManager.Current.PostNotifyInput += postNotify;
            InputManager.Current.PreProcessInput -= preProcess;

            Assert.IsTrue(calledWithMutated);
        }
Beispiel #5
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);
        }
Beispiel #6
0
        private object ProcessStagingArea(object frame)
        {
            bool flag1 = false;

            try
            {
label_21:
                if (this._stagingArea.Count > 0)
                {
                    this._currentStagingStack = this._stagingArea.Dequeue() as Stack;
                    do
                    {
                        StagingAreaInputItem stagingAreaInputItem = (StagingAreaInputItem)this._currentStagingStack.Pop();
                        bool flag2      = false;
                        int  deviceType = (int)stagingAreaInputItem.Input._inputDevice.DeviceType;
                        if (this.InputDeviceEvents[deviceType]._preProcessInput != null)
                        {
                            PreProcessInputEventArgs processInputEventArgs;
                            this.InputDeviceEvents[deviceType]._preProcessInput((object)this, processInputEventArgs = new PreProcessInputEventArgs(stagingAreaInputItem));
                            flag2 = processInputEventArgs._canceled;
                        }
                        if (!flag2)
                        {
                            NotifyInputEventHandler preNotifyInput = this.InputDeviceEvents[deviceType]._preNotifyInput;
                            if (preNotifyInput != null)
                            {
                                preNotifyInput((object)this, new NotifyInputEventArgs(stagingAreaInputItem));
                            }
                            InputEventArgs input1    = stagingAreaInputItem.Input;
                            UIElement      uiElement = input1._source as UIElement;
                            if (uiElement == null && input1._inputDevice != null)
                            {
                                uiElement = input1._inputDevice.Target;
                            }
                            uiElement?.RaiseEvent((RoutedEventArgs)input1);
                            NotifyInputEventHandler postNotifyInput = this.InputDeviceEvents[deviceType]._postNotifyInput;
                            if (postNotifyInput != null)
                            {
                                postNotifyInput((object)this, new NotifyInputEventArgs(stagingAreaInputItem));
                            }
                            ProcessInputEventHandler postProcessInput = this.InputDeviceEvents[deviceType]._postProcessInput;
                            if (postProcessInput != null)
                            {
                                postProcessInput((object)this, new ProcessInputEventArgs(stagingAreaInputItem));
                            }
                            if (stagingAreaInputItem.Input._routedEvent == InputManager.PreviewInputReportEvent && !stagingAreaInputItem.Input.Handled)
                            {
                                InputReportEventArgs input2 = (InputReportEventArgs)stagingAreaInputItem.Input;
                                InputReportEventArgs inputReportEventArgs = new InputReportEventArgs(input2.Device, input2.Report);
                                inputReportEventArgs.RoutedEvent = InputManager.InputReportEvent;
                                this._currentStagingStack.Push((object)new StagingAreaInputItem((InputEventArgs)inputReportEventArgs, stagingAreaInputItem));
                            }
                            if (input1.Handled)
                            {
                                flag1 = true;
                            }
                        }
                    }while (this._currentStagingStack.Count > 0);
                    goto label_21;
                }
            }
            finally
            {
                if (this._stagingArea.Count > 0)
                {
                    this.Dispatcher.BeginInvoke(this._continueProcessingStagingAreaCallback, (object)this.Dispatcher.CurrentFrame);
                }
                this._frameStagingArea.Remove(frame);
            }
            return((object)flag1);
        }