Exemple #1
0
        private RawKeyboardInputReport ExtractRawKeyboardInputReport(NotifyInputEventArgs e, RoutedEvent Event)
        {
            RawKeyboardInputReport keyboardInput = null;

            InputReportEventArgs input = e.StagingItem.Input as InputReportEventArgs;

            if (input != null)
            {
                if (input.Report.Type == InputType.Keyboard && input.RoutedEvent == Event)
                {
                    keyboardInput = input.Report as RawKeyboardInputReport;
                }
            }

            return(keyboardInput);
        }
Exemple #2
0
        private void PreProcessInput(object sender, PreProcessInputEventArgs e)
        {
            InputReportEventArgs input = e.StagingItem.Input as InputReportEventArgs;

            if (input != null)
            {
                if (input.Report.Type == InputType.Command)
                {
                    RawAppCommandInputReport rawAppCommandInputReport = input.Report as RawAppCommandInputReport;
                    if (rawAppCommandInputReport != null)
                    {
                        // Claim the input for the Command.
                        input.Device = this;

                        // Set the proper source
                        input.Source = GetSourceFromDevice(rawAppCommandInputReport.Device);
                    }
                }
            }
        }
Exemple #3
0
        /// <summary>
        ///     Reports input to the input manager.
        /// </summary>
        /// <returns>
        ///     Whether or not any event generated as a consequence of this
        ///     event was handled.
        /// </returns>
        /// <remarks>
        ///  Do we really need this?  Make the "providers" call InputManager.ProcessInput themselves.
        ///  we currently need to map back to providers for other reasons.
        /// </remarks>
        public bool ReportInput(InputReport inputReport)
        {
            if (IsDisposed)
            {
                throw new ObjectDisposedException(SR.Get(SRID.InputProviderSiteDisposed));
            }

            bool handled = false;

            InputReportEventArgs input = new InputReportEventArgs(null, inputReport);

            input.RoutedEvent = InputManager.PreviewInputReportEvent;

            if (_inputManager != null)
            {
                handled = _inputManager.Value.ProcessInput(input);
            }

            return(handled);
        }
Exemple #4
0
 private void PostProcessInput(object sender, ProcessInputEventArgs e)
 {
     if (e.StagingItem.Input.RoutedEvent == InputManager.InputReportEvent)
     {
         if (!e.StagingItem.Input.Handled)
         {
             InputReportEventArgs inputReportEventArgs = e.StagingItem.Input as InputReportEventArgs;
             if (inputReportEventArgs != null)
             {
                 RawAppCommandInputReport rawAppCommandInputReport = inputReportEventArgs.Report as RawAppCommandInputReport;
                 if (rawAppCommandInputReport != null)
                 {
                     IInputElement commandTarget = e.StagingItem.Input.OriginalSource as IInputElement;
                     if (commandTarget != null)
                     {
                         RoutedCommand command = GetRoutedCommand(rawAppCommandInputReport.AppCommand);
                         if (command != null)
                         {
                             // Send the app command to the tree to be handled by UIElements and ContentElements
                             // that will forward the event to CommandManager.
                             CommandDeviceEventArgs args = new CommandDeviceEventArgs(this, rawAppCommandInputReport.Timestamp, command);
                             args.RoutedEvent = CommandDeviceEvent;
                             args.Source      = commandTarget;
                             e.PushInput(args, e.StagingItem);
                         }
                     }
                 }
             }
         }
     }
     else if (e.StagingItem.Input.RoutedEvent == Keyboard.KeyUpEvent ||
              e.StagingItem.Input.RoutedEvent == Mouse.MouseUpEvent ||
              e.StagingItem.Input.RoutedEvent == Keyboard.GotKeyboardFocusEvent ||
              e.StagingItem.Input.RoutedEvent == Keyboard.LostKeyboardFocusEvent)
     {
         CommandManager.InvalidateRequerySuggested();
     }
 }
Exemple #5
0
        private void PostProcessInput(object sender, ProcessInputEventArgs e)
        {
            // KeyUp
            if (e.StagingItem.Input.RoutedEvent == Keyboard.KeyUpEvent)
            {
                KeyEventArgs keyArgs = (KeyEventArgs)e.StagingItem.Input;
                if (!keyArgs.Handled)
                {
                    if (keyArgs.RealKey == Key.LeftAlt || keyArgs.RealKey == Key.RightAlt)
                    {
                        // Make sure both Alt keys are up.
                        ModifierKeys modifiers = keyArgs.KeyboardDevice.Modifiers;
                        if ((modifiers & ModifierKeys.Alt) == 0)
                        {
                            if (_altNumpadEntryMode)
                            {
                                _altNumpadEntryMode = false;

                                // Generate the Unicode equivalent if we
                                // actually entered a number via the numpad.
                                if (_altNumpadEntry != 0)
                                {
                                    _altNumpadcomposition.ClearTexts();
                                    if (_altNumpadConversionMode == AltNumpadConversionMode.OEMCodePage)
                                    {
                                        _altNumpadcomposition.SetText(GetCurrentOEMCPEncoding(_altNumpadEntry));
                                    }
                                    else if ((_altNumpadConversionMode == AltNumpadConversionMode.DefaultCodePage) ||
                                             (_altNumpadConversionMode == AltNumpadConversionMode.HexDefaultCodePage))
                                    {
                                        _altNumpadcomposition.SetText(CharacterEncoding(InputLanguageManager.Current.CurrentInputLanguage.TextInfo.ANSICodePage, _altNumpadEntry));
                                    }
                                    else if (_altNumpadConversionMode == AltNumpadConversionMode.HexUnicode)
                                    {
                                        Char[] chars = new Char[1];
                                        chars[0] = (Char)_altNumpadEntry;
                                        _altNumpadcomposition.SetText(new string(chars));
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    // Someone handled Alt key up event, we cancel Alt-Numpad handling.
                    _altNumpadEntryMode      = false;
                    _altNumpadEntry          = 0;
                    _altNumpadConversionMode = AltNumpadConversionMode.OEMCodePage;
                }
            }

            // PreviewTextInputBegin --> TextInputStart
            else if (e.StagingItem.Input.RoutedEvent == TextCompositionManager.PreviewTextInputStartEvent)
            {
                TextCompositionEventArgs textArgs = (TextCompositionEventArgs)e.StagingItem.Input;
                if (!textArgs.Handled)
                {
                    TextCompositionEventArgs text = new TextCompositionEventArgs(textArgs.Device, textArgs.TextComposition);
                    text.RoutedEvent = TextCompositionManager.TextInputStartEvent;
                    text.Source      = textArgs.TextComposition.Source;
                    e.PushInput(text, e.StagingItem);
                }
            }

            // PreviewTextInputUpdate --> TextInputUpdate
            else if (e.StagingItem.Input.RoutedEvent == TextCompositionManager.PreviewTextInputUpdateEvent)
            {
                TextCompositionEventArgs textArgs = (TextCompositionEventArgs)e.StagingItem.Input;
                if (!textArgs.Handled)
                {
                    TextCompositionEventArgs text = new TextCompositionEventArgs(textArgs.Device, textArgs.TextComposition);
                    text.RoutedEvent = TextCompositionManager.TextInputUpdateEvent;
                    text.Source      = textArgs.TextComposition.Source;
                    e.PushInput(text, e.StagingItem);
                }
            }

            // PreviewTextInput --> TextInput
            else if (e.StagingItem.Input.RoutedEvent == TextCompositionManager.PreviewTextInputEvent)
            {
                TextCompositionEventArgs textArgs = (TextCompositionEventArgs)e.StagingItem.Input;
                if (!textArgs.Handled)
                {
                    TextCompositionEventArgs text = new TextCompositionEventArgs(textArgs.Device, textArgs.TextComposition);
                    text.RoutedEvent = TextCompositionManager.TextInputEvent;
                    text.Source      = textArgs.TextComposition.Source;
                    e.PushInput(text, e.StagingItem);
                }
            }

            // TextCompositioniBegin --> TextInput if this is AutomaticComplete.
            else if (e.StagingItem.Input.RoutedEvent == TextCompositionManager.TextInputStartEvent)
            {
                TextCompositionEventArgs textArgs = (TextCompositionEventArgs)e.StagingItem.Input;
                if (!textArgs.Handled)
                {
                    if (textArgs.TextComposition.AutoComplete == TextCompositionAutoComplete.On)
                    {
                        textArgs.Handled = UnsafeCompleteComposition(textArgs.TextComposition);
                    }
                }
            }

            // TextCompositionUpdate --> TextInput if this is AutomaticComplete.
            else if (e.StagingItem.Input.RoutedEvent == TextCompositionManager.TextInputUpdateEvent)
            {
                TextCompositionEventArgs textArgs = (TextCompositionEventArgs)e.StagingItem.Input;
                if (!textArgs.Handled)
                {
                    if ((textArgs.TextComposition == _deadCharTextComposition) &&
                        (_deadCharTextComposition.Composed))
                    {
                        //Clear the _deadCharTextComposition to handle re-entrant cases.
                        DeadCharTextComposition comp = _deadCharTextComposition;
                        _deadCharTextComposition = null;
                        textArgs.Handled         = UnsafeCompleteComposition(comp);
                    }
                }
            }


            // Raw to StartComposition.
            InputReportEventArgs input = e.StagingItem.Input as InputReportEventArgs;

            if (input != null)
            {
                if (input.Report.Type == InputType.Text && input.RoutedEvent == InputManager.InputReportEvent)
                {
                    RawTextInputReport textInput;
                    textInput = (RawTextInputReport)input.Report;

                    //
                    //



                    string inputText = new string(textInput.CharacterCode, 1);
                    bool   fDoneAltNumpadComposition = false;

                    if (_altNumpadcomposition != null)
                    {
                        // Generate TextInput event from WM_CHAR handler.
                        if (inputText.Equals(_altNumpadcomposition.Text))
                        {
                            fDoneAltNumpadComposition = true;
                        }
                        else
                        {
                            // The generated text from InputReport does not matched with _altNumpadcomposition.
                            // Cancel this composition and process the char from InputReport.
                            _altNumpadcomposition.ClearTexts();
                        }

                        _altNumpadcomposition.Complete();
                        ClearAltnumpadComposition();
                    }

                    if (!fDoneAltNumpadComposition)
                    {
                        if (textInput.IsDeadCharacter)
                        {
                            _deadCharTextComposition = new DeadCharTextComposition(_inputManager, (IInputElement)null, inputText, TextCompositionAutoComplete.Off, InputManager.Current.PrimaryKeyboardDevice);
                            if (textInput.IsSystemCharacter)
                            {
                                _deadCharTextComposition.MakeSystem();
                            }
                            else if (textInput.IsControlCharacter)
                            {
                                _deadCharTextComposition.MakeControl();
                            }

                            input.Handled = UnsafeStartComposition(_deadCharTextComposition);
                        }
                        else
                        {
                            if (_deadCharTextComposition != null)
                            {
                                input.Handled = CompleteDeadCharComposition(inputText,
                                                                            textInput.IsSystemCharacter,
                                                                            textInput.IsControlCharacter);
                            }
                            else
                            {
                                TextComposition composition = new TextComposition(_inputManager, (IInputElement)e.StagingItem.Input.Source, inputText, TextCompositionAutoComplete.On, InputManager.Current.PrimaryKeyboardDevice);
                                if (textInput.IsSystemCharacter)
                                {
                                    composition.MakeSystem();
                                }
                                else if (textInput.IsControlCharacter)
                                {
                                    composition.MakeControl();
                                }
                                input.Handled = UnsafeStartComposition(composition);
                            }
                        }
                    }
                }
            }
        }
        internal void PlayBackCachedDownInputReport(int timestamp)
        {
            if (_needToSendMouseDown)
            {
                // if we have marked this as handled we need to play the down otherwise we can ignore the down
                // as it will be process anyway and either way we need to clean up the cached down
                PresentationSource mouseInputSource = GetMousePresentationSource();

                if (mouseInputSource != null)
                {
                    Point pt = PointUtil.ScreenToClient(_lastMouseScreenLocation, mouseInputSource);

                    _needToSendMouseDown = false; // We've sent down, don't send again.

                    // Update the state we report to the mouse (GetButtonState).
                    _promotedMouseState = MouseButtonState.Pressed;

                    RawMouseActions actions = _fLeftButtonDownTrigger?RawMouseActions.Button1Press:RawMouseActions.Button2Press;

                    // StylusLogic manages the mouse state reported to the MouseDevice to deal with multiple stylusdevice input.
                    if (_stylusLogic.UpdateMouseButtonState(actions))
                    {
                        // See if we need to set the Mouse Activate flag.
                        InputManager inputManager = (InputManager)Dispatcher.InputManager;

                        if (inputManager != null)
                        {
                            if (inputManager.PrimaryMouseDevice.CriticalActiveSource != mouseInputSource)
                            {
                                actions |= RawMouseActions.Activate;
                            }               
                        }

                        // Update the last event we've sent through.
                        _stylusLogic.SetLastRawMouseActions(actions);
                        
                        RawMouseInputReport mouseInputReport = new RawMouseInputReport(
                                                     InputMode.Foreground, timestamp, mouseInputSource,
                                                     actions, 
                                                     (int)pt.X, (int)pt.Y, 0, IntPtr.Zero);

                        InputReportEventArgs inputReportArgs = new InputReportEventArgs(this, mouseInputReport);
                        inputReportArgs.RoutedEvent=InputManager.PreviewInputReportEvent;
                        _stylusLogic.InputManagerProcessInputEventArgs(inputReportArgs);
                    }
                }
                    
                _needToSendMouseDown = false; // so we don't try and resend it later.
                
            }
        }
Exemple #7
0
        private void PromoteMainToMouse(StagingAreaInputItem stagingItem)
        { 
            if(!stagingItem.Input.Handled) 
            {
                StylusEventArgs stylusArgs = stagingItem.Input as StylusEventArgs; 
                if (stylusArgs != null)
                {
                    StylusDevice stylusDevice = stylusArgs.StylusDevice;
 
                    // We only want to promote to mouse when we actually have real stylus input.
                    if (stylusDevice != null) 
                    { 
                        Debug.Assert(ShouldPromoteToMouse(stylusDevice) && stylusDevice.TouchDevice.PromotingToOther);
 
                        if (IgnoreGestureToMousePromotion(stylusArgs as StylusSystemGestureEventArgs, stylusDevice.TouchDevice))
                        {
                            return;
                        } 

                        RawMouseActions actions = stylusDevice.GetMouseActionsFromStylusEventAndPlaybackCachedDown(stagingItem.Input.RoutedEvent, stylusArgs); 
 
                        if (actions != RawMouseActions.None)
                        { 
                            PresentationSource mouseInputSource = stylusDevice.GetMousePresentationSource();

                            if (mouseInputSource != null)
                            { 
                                Point pt = PointUtil.ScreenToClient(stylusDevice.LastMouseScreenPoint, mouseInputSource);
 
                                // 
                                // use the dispatcher as a way of coalescing mouse *move* messages
                                // BUT don't flood the dispatcher with delegates if we're already 
                                // waiting for a callback
                                //
                                if ((actions & RawMouseActions.AbsoluteMove) != 0)
                                { 
                                    if (actions == _lastRawMouseAction && _waitingForDelegate)
                                    { 
                                        return; // We don't need to process this one. 
                                    }
                                    else 
                                    {
                                        //set the waiting bit so we won't enter here again
                                        //until we get the callback
                                        _waitingForDelegate = true; 

                                        Dispatcher.BeginInvoke(DispatcherPriority.Input, 
                                        (DispatcherOperationCallback)delegate(object unused) 
                                        {
                                            //reset our flags here in the callback. 
                                            _waitingForDelegate = false;
                                            return null;
                                        },
                                        null); 
                                    }
                                } 
 
                                // See if we need to set the Mouse Activate flag.
                                if (_inputManager.Value.PrimaryMouseDevice.CriticalActiveSource != mouseInputSource) 
                                {
                                    actions |= RawMouseActions.Activate;
                                }
 
                                _lastRawMouseAction = actions;
 
                                RawMouseInputReport mouseInputReport = new RawMouseInputReport( 
                                                                            InputMode.Foreground, stylusArgs.Timestamp, mouseInputSource,
                                                                            actions, (int)pt.X, (int)pt.Y, 0, IntPtr.Zero); 

                                InputReportEventArgs inputReportArgs = new InputReportEventArgs(stylusDevice, mouseInputReport);
                                inputReportArgs.RoutedEvent=InputManager.PreviewInputReportEvent;
                                _inputManager.Value.ProcessInput(inputReportArgs); 
                            }
                        } 
                    } 
                }
            } 
        }
Exemple #8
0
        private void PreProcessInput(object sender, PreProcessInputEventArgs e)
        { 
            if (_inputEnabled) 
            {
                if(e.StagingItem.Input.RoutedEvent == InputManager.PreviewInputReportEvent) 
                {
                    InputReportEventArgs input = e.StagingItem.Input as InputReportEventArgs;

                    if(input != null && !input.Handled) 
                    {
                        // See if we are in a DragDrop operation.  If so set our internal flag 
                        // which stops us from promoting Stylus or Mouse events! 
                        if (_inDragDrop != _inputManager.Value.InDragDrop)
                        { 
                            _inDragDrop = _inputManager.Value.InDragDrop;

                            // If we are going out of DragDrop then we need to re [....] the mouse state
                            // if we have a stylus device in range (otherwise we [....] on the next 
                            // stylus coming in range).
                            if (!_inDragDrop && _stylusDeviceInRange) 
                            { 
                                UpdateMouseState();
                            } 
                        }

                        if (input.Report.Type == InputType.Mouse)
                        { 
                            // If we see a non stylus mouse event (not triggered from stylus event)
                            if ((input.Device as StylusDevice) == null) 
                            { 
                                // And we only do work if we are enabled for stylus input (ie - have tablet devices)
                                if (TabletDevices.Count != 0) 
                                {
                                    RawMouseInputReport mouseInputReport = (RawMouseInputReport) input.Report;
                                    RawMouseActions actions = mouseInputReport.Actions;
                                    int mouseExtraInfo = NativeMethods.IntPtrToInt32(mouseInputReport.ExtraInformation); 
                                    bool fromWisptis = (mouseExtraInfo & 0xFFFFFF00) == 0xFF515700; // MI_WP_SIGNATURE
 
                                    // Grab the stylus info if from wisptis 
                                    if (fromWisptis)
                                    { 
                                        _lastMouseMoveFromStylus = true;

                                        // Grab the current stylus Id out of the extra info.
                                        _lastStylusDeviceId = (mouseExtraInfo & 0x000000FF); 
                                    }
 
                                    // If mouse is getting deactivated and StylusOver is non null then force stylusover to null. 
                                    if ((actions & RawMouseActions.Deactivate) == RawMouseActions.Deactivate)
                                    { 
                                        _seenRealMouseActivate = false;

                                        if (CurrentStylusDevice != null)
                                        { 
                                            PenContexts penContexts = GetPenContextsFromHwnd(mouseInputReport.InputSource);
 
                                            // If we are inRange still then defer the Deactivate call till we are OutOfRange. 
                                            if (_stylusDeviceInRange && !_inDragDrop && (penContexts == null || !penContexts.IsWindowDisabled))
                                            { 
                                                _mouseDeactivateInputReport = mouseInputReport;
                                                e.Cancel();
                                                input.Handled = true;
                                                return; 
                                            }
#if !MULTICAPTURE 
                                            else if (CurrentStylusDevice.DirectlyOver != null) 
#else
                                            else 
#endif
                                            {
                                                MouseDevice mouseDevice = _inputManager.Value.PrimaryMouseDevice;
 
                                                if (mouseDevice.CriticalActiveSource == mouseInputReport.InputSource)
                                                { 
#if !MULTICAPTURE 
                                                    // Update over to be null when deactivating.
                                                    CurrentStylusDevice.ChangeStylusOver(null); 
#else
                                                    lock (__stylusDeviceLock)
                                                    {
                                                        foreach (var pair in __stylusDeviceMap) 
                                                        {
                                                            var currentDevice = pair.Value; 
                                                            if (currentDevice.DirectlyOver != null) 
                                                            {
                                                                // Update over to be null when deactivating. 
                                                                currentDevice.ChangeStylusOver(null);
                                                            }
                                                        }
                                                    } 
#endif
                                                } 
                                            } 
                                        }
                                    } 
                                    // See if we got some mouse input we need to check for consistency (not tagged from wisptis)
                                    else if ((actions & RawMouseActions.CancelCapture) != 0)
                                    {
                                        // We need to resend this back through as coming from a stylusdevice if in range 
                                        if (CurrentStylusDevice != null && CurrentStylusDevice.InRange)
                                        { 
                                            RawMouseInputReport cancelCaptureInputReport = 
                                                        new RawMouseInputReport(mouseInputReport.Mode,
                                                                                mouseInputReport.Timestamp, 
                                                                                mouseInputReport.InputSource,
                                                                                mouseInputReport.Actions,
                                                                                0, // Rest of the parameters are not used...
                                                                                0, 
                                                                                0,
                                                                                IntPtr.Zero); 
 
                                            InputReportEventArgs args = new InputReportEventArgs(CurrentStylusDevice, cancelCaptureInputReport);
                                            args.RoutedEvent = InputManager.PreviewInputReportEvent; 
                                            e.Cancel();
                                            _inputManager.Value.ProcessInput(args);
                                        }
                                    } 
                                    // Handle the Mouse activation
                                    else if ((actions & RawMouseActions.Activate) != 0) 
                                    { 
                                        // If mouse is getting Activated and we ate a Deactivate then clear the cached Deactivate.
                                        _mouseDeactivateInputReport = null; 

                                        // We process Activate events and make sure to clear any other actions if we are resending
                                        // this from a StylusDevice.  This is so we don't get a move generated before we see the
                                        // StylusDevice InRange event and the following StylusMove which will generate a MouseMove. 
                                        StylusDevice activateStylusDevice = null;
                                        _seenRealMouseActivate = true; 
 
                                        // See if we need to process this event from us.
                                        if (CurrentStylusDevice != null && CurrentStylusDevice.InRange) 
                                            activateStylusDevice = CurrentStylusDevice;
                                        else if (fromWisptis || ShouldConsiderStylusInRange(mouseInputReport))
                                            activateStylusDevice = FindStylusDevice(_lastStylusDeviceId);
 
                                        // We need to resend this as coming from a stylusdevice if in range possibly.
                                        if (activateStylusDevice != null) 
                                        { 
                                            // Check to se if we have already Activated the mouse from a stylus event.
                                            // If not then we need to let this one go through marked from us if we are in range! 
                                            if (mouseInputReport.InputSource != _inputManager.Value.PrimaryMouseDevice.CriticalActiveSource)
                                            {
                                                Point pt;
 
                                                pt = activateStylusDevice.LastMouseScreenPoint; // Use last promoted mouse location.
                                                pt = PointUtil.ScreenToClient(pt, mouseInputReport.InputSource); 
 
                                                RawMouseInputReport activateInputReport =
                                                            new RawMouseInputReport(mouseInputReport.Mode, 
                                                                                    mouseInputReport.Timestamp,
                                                                                    mouseInputReport.InputSource,
                                                                                    RawMouseActions.Activate, // Only let activate happen.
                                                                                    (int)pt.X, 
                                                                                    (int)pt.Y,
                                                                                    mouseInputReport.Wheel, 
                                                                                    mouseInputReport.ExtraInformation); 

                                                InputReportEventArgs args = new InputReportEventArgs(activateStylusDevice, activateInputReport); 
                                                args.RoutedEvent = InputManager.PreviewInputReportEvent;
                                                _inputManager.Value.ProcessInput(args);
                                            }
 
                                            // If stylus is active then eat this since we'll send the activate.  We just cancel
                                            // to ensure the mouse event from HwndMouseInputProvider returns that it was not handled. 
                                            // The mouse device code will not do anything with the event during PreProcessInput and 
                                            // it will not see a PreNotifyInput event for this.
                                            e.Cancel(); 
                                        }
                                    }
                                    // Handle moves and button presses that might be from wisptis or in conflict with our current state
                                    else if ((actions & (RawMouseActions.AbsoluteMove | RawMouseActions.QueryCursor | 
                                                            RawMouseActions.Button1Press | RawMouseActions.Button1Release |
                                                            RawMouseActions.Button2Press | RawMouseActions.Button2Release)) != 0) 
                                    { 
                                        // If we see a mouse left down and stylus is inRange and we haven't sent a mouse down
                                        // then send it through. 
                                        if ((actions & RawMouseActions.Button1Press) != 0 && CurrentStylusDevice != null &&
                                            !CurrentStylusDevice.InAir)
                                        {
                                            // We can only Activate the window without flashing the tray icon for it when 
                                            // we are processing an Input message.  So we defer it till we see the mouse down.
                                            HwndSource hwndSource = mouseInputReport.InputSource as HwndSource; 
                                            IntPtr hwnd = hwndSource != null ? hwndSource.CriticalHandle : IntPtr.Zero; 

                                            // If we see a stylusdown and we are not the foreground window 
                                            // and there's no capture then make sure we get activated.
                                            // We only do this for top most windows.
                                            if (hwnd != IntPtr.Zero &&
                                                 _inputManager.Value.PrimaryMouseDevice.Captured != null && 
                                                 UnsafeNativeMethods.GetParent(new HandleRef(this, hwnd)) == IntPtr.Zero &&
                                                 hwnd != UnsafeNativeMethods.GetForegroundWindow()) 
                                            { 
                                                // Check to see if this window has the WS_EX_NOACTIVATE style set, if so don't do the activation work.
                                                int style = UnsafeNativeMethods.GetWindowLong(new HandleRef(this,hwnd), NativeMethods.GWL_EXSTYLE); 

                                                if ((style & NativeMethods.WS_EX_NOACTIVATE) == 0)
                                                {
                                                    UnsafeNativeMethods.SetForegroundWindow(new HandleRef(this,hwndSource.Handle)); 
                                                }
                                            } 
 
                                            // There are times we need to make sure we promote the left mouse down before we see a system gesture.
                                            // This is when the press and hold gesture is disabled and thus we can guarentee that sending the 
                                            // left mouse down is the correct thing to do.  This is critical for some controls such as repeat
                                            // buttons since in order get them in the pressed state (and start them repeating) we have to send the
                                            // left mouse down.  Note if you go down with the stylus and don't move it past the drag tolerance no
                                            // system gesture will be generated and the normal code to promote the mouse down will not happen otherwise. 
                                            //
                                            // This code will kick in on Vista with the new support to disable the press and hold gesture per element 
                                            // (via WM_TABLE_QUERYSYSTEMGESTURESTATUS message) and also on XP and Vista if the press and hold gesture is 
                                            // disabled in the tablet control panel.
                                            if (!CurrentStylusDevice.SentMouseDown && fromWisptis && ShouldPromoteToMouse(CurrentStylusDevice)) 
                                            {
                                                // left button down...lets replay the down at this time...
                                                // Note: We may wait till later if stylus is not down yet!
                                                // We will do it only when we are not manipulating and we will 
                                                // delay it if we know that manipulations are possible.
                                                StylusTouchDevice touchDevice = CurrentStylusDevice.TouchDevice; 
                                                if (touchDevice.PromotingToManipulation) 
                                                {
                                                    touchDevice.StoredStagingAreaItems.Add(e.StagingItem); 
                                                }
                                                else if (touchDevice.PromotingToOther)
                                                {
                                                    CurrentStylusDevice.PlayBackCachedDownInputReport(mouseInputReport.Timestamp); 
                                                }
                                            } 
                                        } 

                                        // We want to eat mouse messages with the wisptis injected signature except 
                                        // if the MouseDevice is getting activated or deactivated by it (filtered out
                                        // above).  We also want to eat any spurious mouse events recieved between the
                                        // stylus down and the stylus system gesture getting fired.
                                        if (fromWisptis) 
                                        {
                                            // eat mouse messages generated by stylus; 
                                            // these will be handled off the stylus event stream and promoted to a mouse input event 
                                            bool handled = true;
 
                                            // If the mouse is captured we need to validate that the mouse location
                                            // is actually inside the client area (we will only see those wisptis
                                            // events and can thus eat this one).
                                            Point ptMouse = new Point(mouseInputReport.X, mouseInputReport.Y); 
                                            bool stylusIsDown = (CurrentStylusDevice != null) ? !CurrentStylusDevice.InAir : false;
                                            if (!stylusIsDown && Mouse.Captured != null && !InWindowClientRect(ptMouse, mouseInputReport.InputSource)) 
                                            { 
                                                handled = false;
                                            } 

                                            // If the input has been marked as Handled, we want it to be cancelled at PreProcess stage.
                                            if (handled)
                                            { 
                                                // We can't mark left and right mouse buttons as handled since it will stop the
                                                // DefWindowProc from being processed but we Cancel it which stops mouse from processing 
                                                // it.  Move's though we need to eat. 
                                                if ((actions & (RawMouseActions.Button1Press | RawMouseActions.Button2Press)) == 0)
                                                { 
                                                    input.Handled = true;
                                                }
                                                e.Cancel();
 
                                                // If the stylus is in the up state when we see a mouse down then just note that we've
                                                // seen the mouse left down and wanted to send it but the stylus down 
                                                // has not been seen yet so we can't.  When we see the stylus down later we'll promote 
                                                // the left mouse down after processing the stylus down.
                                                if ((actions & RawMouseActions.Button1Press) != 0 && CurrentStylusDevice != null && 
                                                    CurrentStylusDevice.InAir)
                                                {
                                                    CurrentStylusDevice.SetSawMouseButton1Down(true);
                                                } 

                                                // Only try to process stylus events on wisptis generated mouse events and 
                                                // make sure we don't re-enter ourselves. 
                                                if (!_processingQueuedEvent)
                                                { 
                                                    // Make sure we process any pending Stylus Input before this mouse event.
                                                    InputManagerProcessInput(null);
                                                }
                                            } 
                                        }
                                        else 
                                        { 
                                            bool cancelMouseEvent = false;
                                            bool markHandled = true; 

                                            // If Stylus is in range then it will be driving the mouse.  Ignore any mouse input.
                                            if (_stylusDeviceInRange)
                                            { 
                                                cancelMouseEvent = true;
 
                                                // We can't mark left and right mouse buttons as handled since it will stop the 
                                                // DefWindowProc from being processed but we Cancel it which stops mouse from processing
                                                // it.  Move's though we need to eat. 
                                                if ((actions & (RawMouseActions.Button1Press | RawMouseActions.Button2Press)) == 0)
                                                {
                                                    markHandled = false;
                                                } 
                                            }
                                            // If we see only a mouse move related action while the stylus is in range then 
                                            // eat it or try to defer it if not currently in range to see if we come into range. 
                                            else if ((actions & ~(RawMouseActions.AbsoluteMove | RawMouseActions.QueryCursor)) == 0)
                                            { 
                                                if (DeferMouseMove(mouseInputReport))
                                                {
                                                    cancelMouseEvent = true;
                                                } 
                                                else
                                                { 
                                                    // If we now think we're going in range then eat this mouse event 
                                                    if (_lastMouseMoveFromStylus && ShouldConsiderStylusInRange(mouseInputReport))
                                                    { 
                                                        SendDeferredMouseEvent(false); // Make sure we clear any deferred mouse events now.
                                                        cancelMouseEvent = true;
                                                    }
                                                    // We're now allowing this mouse event (and deferred one) to be processed... 
                                                    else
                                                    { 
                                                        // It's a Synchronize that we are letting through so set stylus was not last move anymore. 
                                                        _lastMouseMoveFromStylus = false;
 
                                                        // See if we are dealing with a second mouse event,
                                                        // if so force the original one it to be processed first.
                                                        if (!_triedDeferringMouseMove)
                                                            SendDeferredMouseEvent(true); 

                                                        // CurrentStylusDevice is not in range and we're seeeing mouse messages 
                                                        // that are not from wisptis, time to set IsStylusOver to null 
                                                        if (CurrentStylusDevice != null)
                                                        { 
                                                            // No current stylus device anymore either.
                                                            SelectStylusDevice(null, null, true);
                                                        }
                                                    } 
                                                }
                                            } 
                                            // If we see a down and have a cached move then let them both go through 
                                            else
                                            { 
                                                // We see a mouse button 1 or 2 down/up.  If we have a cache then dump it and mark that we've
                                                // seen mouse input.
                                                _lastMouseMoveFromStylus = false;
                                                SendDeferredMouseEvent(true); 

                                                // CurrentStylusDevice is not in range and we're seeeing mouse messages 
                                                // that are not from wisptis, time to set IsStylusOver to null 
                                                if (CurrentStylusDevice != null)
                                                { 
                                                    // No current stylus device anymore either.
                                                    SelectStylusDevice(null, null, true);
                                                }
                                            } 

                                            // See if we wanted to eat this mouse event... 
                                            if (cancelMouseEvent) 
                                            {
                                                e.Cancel(); // abort this input 
                                                if (markHandled)
                                                {
                                                    input.Handled = true; // We also don't want MouseDevice processing this.
                                                } 
                                            }
                                        } 
                                    } 
                                    // Some other real mouse only generated event came through...
                                    else 
                                    {
                                        // Make sure it's only the ones we know should come through.
                                        Debug.Assert((actions & ~(RawMouseActions.Button3Press | RawMouseActions.Button3Release |
                                                                   RawMouseActions.Button4Press | RawMouseActions.Button4Release | 
                                                                   RawMouseActions.Button5Press | RawMouseActions.Button5Release |
                                                                   RawMouseActions.VerticalWheelRotate | 
                                                                   RawMouseActions.HorizontalWheelRotate)) == 0); 

                                        // If we are not in range then make sure we update our state. 
                                        // Otherwise we just let this event go through to the MouseDevice.
                                        if (!_stylusDeviceInRange)
                                        {
                                            // We are letting this move through so set stylus was not last move anymore. 
                                            _lastMouseMoveFromStylus = false;
 
                                            // Dump cache! 
                                            SendDeferredMouseEvent(true);
 
                                            // CurrentStylusDevice is not in range and we're seeeing mouse messages
                                            // that are not from wisptis, time to set IsStylusOver to null
                                            if (CurrentStylusDevice != null)
                                            { 
                                                // We now don't have a current stylus device.
                                                SelectStylusDevice(null, null, true); 
                                            } 
                                        }
                                        else 
                                        {
                                            // Make sure to dump the cached mouse event if we are in
                                            // range to make sure this mouse event is at the right spot!
                                            SendDeferredMouseEvent(true); 
                                        }
                                    } 
                                } 
                                else
                                { 
                                    _lastMouseMoveFromStylus = false;
                                }
                            }
                            else 
                            {
                                // This event is marked as coming from a StylusDevice so make sure we update flag that we saw mouse event from stylus. 
                                _lastMouseMoveFromStylus = true; 

                                RawMouseInputReport rawMouseInputReport = (RawMouseInputReport) input.Report; 
                                StylusDevice stylusDevice = (StylusDevice)input.Device;
                                if (!stylusDevice.InRange && rawMouseInputReport._isSynchronize)
                                {
                                    // eat this one because it is from an activate. 
                                    e.Cancel();
                                    input.Handled = true; 
                                } 
                            }
                        } 
                        else if (input.Report.Type == InputType.Stylus)
                        {
                            RawStylusInputReport stylusInputReport = (RawStylusInputReport) input.Report;
                            StylusDevice stylusDevice = stylusInputReport.StylusDevice; // RTI sets this if it finds StylusDevice based on Id. 
                            bool cancelInput = true; // Only process if we see we have valid input data.
 
                            if (stylusInputReport.InputSource != null && stylusInputReport.PenContext != null) 
                            {
                                if (stylusDevice == null) 
                                {
                                    // look up stylus device, select it in the Stylus, and claim input for it
                                    stylusDevice = FindStylusDevice(stylusInputReport.StylusDeviceId);
 
                                    // Try refreshing tablets if we failed to find this stylus device.
                                    if (stylusDevice == null) 
                                    { 
                                        stylusDevice = TabletDevices.UpdateStylusDevices(
                                                                    stylusInputReport.TabletDeviceId, 
                                                                    stylusInputReport.StylusDeviceId);
                                    }

                                    stylusInputReport.StylusDevice = stylusDevice; // update stylusdevice. 
                                }
 
                                _triedDeferringMouseMove = false; // reset anytime we see stylus input. 

                                // See if this is the special InRange input report that we use to track queued inrange 
                                // events so that we can better filter out bogus mouse input.
                                if (stylusInputReport.Actions == RawStylusActions.InRange && stylusInputReport.Data == null)
                                {
                                    stylusInputReport.PenContext.DecrementQueuedInRangeCount(); 
                                    e.Cancel();
                                    input.Handled = true; 
                                    _lastInRangeTime = Environment.TickCount; 
                                    return;
                                } 

                                // See if this is the special DoubleTap Gesture input report.  We use this
                                // event to know when we won't get the tap or drag gesture while the stylus
                                // is down.  This allows us to detect and generate the Drag gesture on our own. 
                                if (stylusInputReport.Actions == RawStylusActions.SystemGesture && stylusDevice != null)
                                { 
                                    RawStylusSystemGestureInputReport systemGestureReport = (RawStylusSystemGestureInputReport)stylusInputReport; 
                                    if (systemGestureReport.SystemGesture == RawStylusSystemGestureInputReport.InternalSystemGestureDoubleTap)
                                    { 
                                        stylusDevice.SeenDoubleTapGesture = true;
                                        e.Cancel();
                                        input.Handled = true;
                                        return; 
                                    }
                                } 
 
                                if (stylusDevice != null && IsValidStylusAction(stylusInputReport))
                                { 
                                    cancelInput = false; // We can process this event - don't cancel!

                                    // See if a static gesture can be generated
                                    TabletDevice tabletDevice = stylusDevice.TabletDevice; 
                                    if (tabletDevice != null)
                                    { 
                                        SystemGesture? systemGesture = tabletDevice.GenerateStaticGesture(stylusInputReport); 
                                        if (systemGesture != null)
                                        { 
                                            GenerateGesture(stylusInputReport, systemGesture.Value);
                                        }
                                    }
 
                                    // See if we need to generate a tap gesture.
                                    if (stylusInputReport.Actions == RawStylusActions.Up) 
                                    { 
                                        if (!stylusDevice.GestureWasFired)
                                        { 
                                            GenerateGesture(stylusInputReport, stylusDevice.LastTapBarrelDown ? SystemGesture.RightTap : SystemGesture.Tap);
                                        }

                                        if (!_inDragDrop && !stylusInputReport.PenContext.Contexts.IsWindowDisabled) 
                                        {
                                            // We need to process a MouseMove before promoting a MouseUp (in PromoteMainToMouse) 
                                            // since the stylus updates the button states for mouse to up then. 
                                            // Note: The Stylus Up is at the same location as the last stylus move so this is OK to do here.
                                            ProcessMouseMove(stylusDevice, stylusInputReport.Timestamp, false); 
                                        }
                                    }

                                    input.Device = stylusDevice; 
                                }
                            } 
 
                            if (cancelInput)
                            { 
                                e.Cancel();  // Don't process this bogus event any further.
                            }
                        }
                    } 
                }
            } 
        } 
        public bool ReportInput(InputReport inputReport)
        { 
            if(IsDisposed)
            { 
                throw new ObjectDisposedException(SR.Get(SRID.InputProviderSiteDisposed)); 
            }
 
            bool handled = false;

            InputReportEventArgs input = new InputReportEventArgs(null, inputReport);
            input.RoutedEvent=InputManager.PreviewInputReportEvent; 

            if(_inputManager != null) 
            { 
                handled = _inputManager.Value.ProcessInput(input);
            } 

            return handled;
        }
Exemple #10
0
        private void ProcessMouseMove(StylusDevice stylusDevice, int timestamp, bool isSynchronize)
        { 
            System.Diagnostics.Debug.Assert(stylusDevice != null);

            if (!ShouldPromoteToMouse(stylusDevice) || !stylusDevice.TouchDevice.PromotingToOther)
            { 
                return;
            } 
 
            PresentationSource mouseInputSource = stylusDevice.GetMousePresentationSource();
 
            if (mouseInputSource != null)
            {
                RawMouseActions actions = RawMouseActions.AbsoluteMove;
 
                // Don't set Activate flag if a synchronize is requested!
                if (!isSynchronize) 
                { 
                    if (_inputManager.Value.PrimaryMouseDevice.CriticalActiveSource != mouseInputSource)
                    { 
                        actions |= RawMouseActions.Activate;
                    }
                }
 
                Point pt = stylusDevice.LastMouseScreenPoint; // Use last promoted mouse location.
                pt = PointUtil.ScreenToClient(pt, mouseInputSource); 
 
                RawMouseInputReport mouseInputReport =
                            new RawMouseInputReport(InputMode.Foreground, 
                                                    timestamp,
                                                    mouseInputSource,
                                                    actions,
                                                    (int)pt.X, 
                                                    (int)pt.Y,
                                                    0, 
                                                    IntPtr.Zero); 

                if (isSynchronize) 
                {
                    mouseInputReport._isSynchronize = true;
                }
 
                _lastRawMouseAction = actions;
 
                InputReportEventArgs inputReportArgs = new InputReportEventArgs(stylusDevice, mouseInputReport); 
                inputReportArgs.RoutedEvent = InputManager.PreviewInputReportEvent;
 
                // Process this directly instead of doing a push. We want this event to get
                // to the user before the StylusUp and MouseUp event.
                InputManagerProcessInputEventArgs(inputReportArgs);
            } 
        }
Exemple #11
0
        private void SendDeferredMouseEvent(bool sendInput)
        {
            if (sendInput)
            { 
                _triedDeferringMouseMove = true;  // Only reset to not try again if we don't find we are in range.
 
                // Only send if we have valid PresentationSource and CompositionTarget. 
                if (_deferredMouseMove != null && _deferredMouseMove.InputSource != null &&
                    _deferredMouseMove.InputSource.CompositionTarget != null && 
                    !_deferredMouseMove.InputSource.CompositionTarget.IsDisposed)
                {
                    // Process mouse move now since nothing else from stylus came through...
                    InputReportEventArgs mouseArgs = new InputReportEventArgs(_inputManager.Value.PrimaryMouseDevice, _deferredMouseMove); 
                    mouseArgs.RoutedEvent = InputManager.PreviewInputReportEvent;
                    _deferredMouseMove = null; // Clear this out before sending. 
                    // This will cause _lastMoveFromStylus to be set to false. 
                    _inputManager.Value.ProcessInput(mouseArgs);
                } 
            }

            // We no longer need the ref on the cached input report.
            _deferredMouseMove = null; 
        }
Exemple #12
0
        private void GenerateGesture(RawStylusInputReport rawStylusInputReport, SystemGesture gesture) 
        {
            StylusDevice stylusDevice = rawStylusInputReport.StylusDevice; 
            System.Diagnostics.Debug.Assert(stylusDevice != null); 

            RawStylusSystemGestureInputReport inputReport = new RawStylusSystemGestureInputReport( 
                                                        InputMode.Foreground,
                                                        rawStylusInputReport.Timestamp,
                                                        rawStylusInputReport.InputSource,
                                                        rawStylusInputReport.PenContext, 
                                                        rawStylusInputReport.TabletDeviceId,
                                                        rawStylusInputReport.StylusDeviceId, 
                                                        gesture, 
                                                        0, // Gesture X location (only used for flicks)
                                                        0, // Gesture Y location (only used for flicks) 
                                                        0); // ButtonState (only used for flicks)
            inputReport.StylusDevice = stylusDevice;
            InputReportEventArgs input = new InputReportEventArgs(stylusDevice, inputReport);
            input.RoutedEvent=InputManager.PreviewInputReportEvent; 
            // Process this directly instead of doing a push. We want this event to get
            // to the user before the StylusUp and MouseUp event. 
            InputManagerProcessInputEventArgs(input); 
        }
Exemple #13
0
        internal object InputManagerProcessInput(object oInput)
        { 
            RawStylusInputReport rawStylusInputReport = null; 

            // Now grab the queued up Stylus input reports and process them. 
            lock(_stylusEventQueueLock)
            {
                if (_queueStylusEvents.Count > 0)
                { 
                    rawStylusInputReport = _queueStylusEvents.Dequeue();
                } 
            } 

            if (rawStylusInputReport != null) 
            {
                // Check to see if the Vista wisptis has set the IP_RECT_MAPPING_CHANGED bit in the packet status.
                // If so we need to trigger our mappings to be udpated just in case we processed this before wisptis.
                switch (rawStylusInputReport.Actions) 
                {
                    case RawStylusActions.InAirMove: 
                    case RawStylusActions.Down: 
                    //case RawStylusActions.Move: (note this can cause problems with TabletDevice.DoubleTapSize and CancelSize if handled so we don't do work here)
                    case RawStylusActions.Up: 
                        int packetStatusIndex = rawStylusInputReport.PenContext.StylusPointDescription.GetPropertyIndex(StylusPointProperties.PacketStatus.Id);
                        if (packetStatusIndex != -1 && rawStylusInputReport.StylusDevice != null)
                        {
                            int packetStatus = rawStylusInputReport.Data[packetStatusIndex]; // grab first packet to check. 
                            if ((packetStatus & 0x10) != 0) // Is IP_RECT_MAPPING_CHANGED (0x00000010) set?
                            { 
                                using(Dispatcher.DisableProcessing()) // make sure lock() doesn't cause re-entrancy. 
                                {
                                    // Update display mappings for this TabletDevice. 
                                    rawStylusInputReport.StylusDevice.TabletDevice.UpdateScreenMeasurements();
                                }
                            }
                        } 
                        break;
 
                    // we don't need to process any other types of actions. 

                } 

                // build InputReportEventArgs
                InputReportEventArgs input = new InputReportEventArgs(null, rawStylusInputReport);
                input.RoutedEvent=InputManager.PreviewInputReportEvent; 
                // Set flag to prevent reentrancy due to wisptis mouse event getting triggered
                // while processing this stylus event. 
                _processingQueuedEvent = true; 
                try
                { 
                    InputManagerProcessInputEventArgs(input);
                }
                finally
                { 
                    _processingQueuedEvent = false;
                } 
            } 

            return null; 
        }
Exemple #14
0
        private void GenerateInRange(RawStylusInputReport rawStylusInputReport)
        {
            StylusDevice stylusDevice = rawStylusInputReport.StylusDevice;
 
            RawStylusInputReport inputReport =
                new RawStylusInputReport(rawStylusInputReport.Mode, 
                                         rawStylusInputReport.Timestamp, 
                                         rawStylusInputReport.InputSource,
                                         rawStylusInputReport.PenContext, 
                                         RawStylusActions.InRange,
                                         stylusDevice.TabletDevice.Id,
                                         stylusDevice.Id,
                                         rawStylusInputReport.Data); 

            InputReportEventArgs input = new InputReportEventArgs(stylusDevice, inputReport); 
            input.RoutedEvent=InputManager.PreviewInputReportEvent; 
            _inputManager.Value.ProcessInput(input);
        } 
Exemple #15
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;
        }
Exemple #16
0
        private void PreProcessInput(object sender, PreProcessInputEventArgs e)
        {
            if (e.StagingItem.Input.RoutedEvent == InputManager.PreviewInputReportEvent)
            {
                InputReportEventArgs inputReportEventArgs = e.StagingItem.Input as InputReportEventArgs;

                if (!inputReportEventArgs.Handled && inputReportEventArgs.Report.Type == InputType.Mouse)
                {
                    RawMouseInputReport rawMouseInputReport = (RawMouseInputReport)inputReportEventArgs.Report;


                    // Normally we only process mouse input that is from our
                    // active visual manager.  The only exception to this is
                    // the activate report, which is how we change the visual
                    // manager that is active.
                    if ((rawMouseInputReport.Actions & RawMouseActions.Activate) == RawMouseActions.Activate)
                    {
                        // Console.WriteLine("RawMouseActions.Activate");

                        // If other actions are being reported besides the
                        // activate, separate them into different events.
                        if ((rawMouseInputReport.Actions & ~RawMouseActions.Activate) != 0)
                        {
                            // Cancel this event.  We'll push a new event for the activate.
                            e.Cancel();

                            // Push a new RawMouseInputReport for the non-activate actions.
                            RawMouseInputReport reportActions = new RawMouseInputReport(rawMouseInputReport.Mode,
                                                                                        rawMouseInputReport.Timestamp,
                                                                                        rawMouseInputReport.InputSource,
                                                                                        rawMouseInputReport.Actions & ~RawMouseActions.Activate,
                                                                                        rawMouseInputReport.X,
                                                                                        rawMouseInputReport.Y,
                                                                                        rawMouseInputReport.Wheel,
                                                                                        rawMouseInputReport.ExtraInformation);
                            InputReportEventArgs actionsArgs = new InputReportEventArgs(inputReportEventArgs.Device, reportActions);
                            actionsArgs.RoutedEvent=InputManager.PreviewInputReportEvent;
                            e.PushInput(actionsArgs, null);

                            // Create a new RawMouseInputReport for the activate.
                            RawMouseInputReport reportActivate = new RawMouseInputReport(rawMouseInputReport.Mode,
                                                                                         rawMouseInputReport.Timestamp,
                                                                                         rawMouseInputReport.InputSource,
                                                                                         RawMouseActions.Activate,
                                                                                         rawMouseInputReport.X,
                                                                                         rawMouseInputReport.Y,
                                                                                         rawMouseInputReport.Wheel,
                                                                                         rawMouseInputReport.ExtraInformation);

                            // Push a new RawMouseInputReport for the activate.
                            InputReportEventArgs activateArgs = new InputReportEventArgs(inputReportEventArgs.Device, reportActivate);
                            activateArgs.RoutedEvent=InputManager.PreviewInputReportEvent;
                            e.PushInput(activateArgs, null);
                        }
                    }
                    // Only process mouse input that is from our active PresentationSource.
                    else if ((_inputSource != null) && (rawMouseInputReport.InputSource == _inputSource.Value))
                    {
                        // We need to remember the StylusDevice that generated this input.  Use the _tagStylusDevice
                        // to store this in before we take over the inputReport Device and loose it.  Any
                        // input reports we re-push need to preserve this too.  This is used to set the StylusDevice
                        // property on MouseEventArgs.
                        InputDevice inputDevice = e.StagingItem.GetData(_tagStylusDevice) as StylusDevice;

                        if (inputDevice == null)
                        {
                            inputDevice = inputReportEventArgs.Device as StylusDevice;
                            if (inputDevice != null)
                            {
                                e.StagingItem.SetData(_tagStylusDevice, inputDevice);
                            }
                        }

                        // Claim the input for the mouse.
                        inputReportEventArgs.Device = this;

                        // If the input is reporting mouse deactivation, we need
                        // to ensure that the element receives a final leave.
                        // Note that activation could have been moved to another
                        // visual manager in our app, which means that the leave
                        // was already sent.  So only do this if the deactivate
                        // event is from the visual manager that we think is active.
                        if ((rawMouseInputReport.Actions & RawMouseActions.Deactivate) == RawMouseActions.Deactivate)
                        {
                            if (_mouseOver != null)
                            {
                                // Push back this event, and cancel the current processing.
                                e.PushInput(e.StagingItem);
                                e.Cancel();
                                _isPhysicallyOver = false;
                                ChangeMouseOver(null, e.StagingItem.Input.Timestamp);
                            }
                        }

                        // If the input is reporting mouse movement, we need to check
                        // if we need to update our sense of "mouse over".
                        // 
                        if ((rawMouseInputReport.Actions & RawMouseActions.AbsoluteMove) == RawMouseActions.AbsoluteMove)
                        {
                            // If other actions are being reported besides the
                            // move, separate them into different events.
                            if ((rawMouseInputReport.Actions & ~(RawMouseActions.AbsoluteMove | RawMouseActions.QueryCursor)) != 0)
                            {
                                // Cancel this event.  We'll push a new event for the move.
                                e.Cancel();

                                // Push a new RawMouseInputReport for the non-move actions.
                                RawMouseInputReport reportActions = new RawMouseInputReport(rawMouseInputReport.Mode,
                                                                                            rawMouseInputReport.Timestamp,
                                                                                            rawMouseInputReport.InputSource,
                                                                                            rawMouseInputReport.Actions & ~(RawMouseActions.AbsoluteMove | RawMouseActions.QueryCursor),
                                                                                            0,
                                                                                            0,
                                                                                            rawMouseInputReport.Wheel,
                                                                                            rawMouseInputReport.ExtraInformation);
                                InputReportEventArgs actionsArgs = new InputReportEventArgs(inputDevice, reportActions);
                                actionsArgs.RoutedEvent=InputManager.PreviewInputReportEvent;
                                e.PushInput(actionsArgs, null);

                                // Push a new RawMouseInputReport for the AbsoluteMove.
                                RawMouseInputReport reportMove = new RawMouseInputReport(rawMouseInputReport.Mode,
                                                                                         rawMouseInputReport.Timestamp,
                                                                                         rawMouseInputReport.InputSource,
                                                                                         rawMouseInputReport.Actions & (RawMouseActions.AbsoluteMove | RawMouseActions.QueryCursor),
                                                                                         rawMouseInputReport.X,
                                                                                         rawMouseInputReport.Y,
                                                                                         0,
                                                                                         IntPtr.Zero);
                                InputReportEventArgs moveArgs = new InputReportEventArgs(inputDevice, reportMove);
                                moveArgs.RoutedEvent=InputManager.PreviewInputReportEvent;
                                e.PushInput(moveArgs, null);
                            }
                            else
                            {
                                // Convert the point from client coordinates into "root" coordinates.
                                // We do this in the pre-process stage because it is possible that
                                // this conversion will fail, in which case we want to cancel the
                                // mouse move event.
                                bool success = true;
                                Point ptClient = new Point(rawMouseInputReport.X, rawMouseInputReport.Y);
                                Point ptRoot = PointUtil.TryClientToRoot(ptClient, rawMouseInputReport.InputSource, false, out success);
                                if(success)
                                {
                                    e.StagingItem.SetData(_tagRootPoint, ptRoot);
                                }
                                else
                                {
                                    e.Cancel();
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                // All mouse event processing should only happen if we still have an active input source.

                if (_inputSource != null)
                {
                    if (e.StagingItem.Input.RoutedEvent == Mouse.PreviewMouseDownEvent)
                    {
                        MouseButtonEventArgs mouseButtonEventArgs = e.StagingItem.Input as MouseButtonEventArgs;

                        if (_mouseCapture != null && !_isPhysicallyOver)
                        {
                            // The mouse is not physically over the capture point (or
                            // subtree), so raise the PreviewMouseDownOutsideCapturedElement
                            // event first.
                            MouseButtonEventArgs clickThrough = new MouseButtonEventArgs(this, mouseButtonEventArgs.Timestamp, mouseButtonEventArgs.ChangedButton, GetStylusDevice(e.StagingItem));
                            clickThrough.RoutedEvent=Mouse.PreviewMouseDownOutsideCapturedElementEvent;
                            //ProcessInput has a linkdemand
                            _inputManager.Value.ProcessInput(clickThrough);
                        }
                    }

                    else if (e.StagingItem.Input.RoutedEvent == Mouse.PreviewMouseUpEvent)
                    {
                        MouseButtonEventArgs mouseButtonEventArgs = e.StagingItem.Input as MouseButtonEventArgs;

                        if (_mouseCapture != null && !_isPhysicallyOver)
                        {
                            // The mouse is not physically over the capture point (or
                            // subtree), so raise the PreviewMouseUpOutsideCapturedElement
                            // event first.
                            MouseButtonEventArgs clickThrough = new MouseButtonEventArgs(this, mouseButtonEventArgs.Timestamp, mouseButtonEventArgs.ChangedButton, GetStylusDevice(e.StagingItem));
                            clickThrough.RoutedEvent=Mouse.PreviewMouseUpOutsideCapturedElementEvent;
                            //ProcessInput has a linkdemand
                            _inputManager.Value.ProcessInput(clickThrough);
                        }
                    }
                }
            }

        }
Exemple #17
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);
        }
Exemple #18
0
        public void Synchronize()
        {
            // System.Console.WriteLine("Synchronize");
//             VerifyAccess();

            // Simulate a mouse move
            PresentationSource activeSource = CriticalActiveSource;
            if (activeSource != null && activeSource.CompositionTarget != null && !activeSource.CompositionTarget.IsDisposed)
            {
                int timeStamp = Environment.TickCount;
                Point ptClient = GetClientPosition();

                RawMouseInputReport report = new RawMouseInputReport(InputMode.Foreground,
                                                                     timeStamp,
                                                                     activeSource,
                                                                     RawMouseActions.AbsoluteMove,
                                                                     (int) ptClient.X,
                                                                     (int) ptClient.Y,
                                                                     0,
                                                                     IntPtr.Zero);
                report._isSynchronize = true;

                InputReportEventArgs inputReportEventArgs;
                if (_stylusDevice != null)
                {
                    // if we have a current stylusdevice .. use it
                    inputReportEventArgs = new InputReportEventArgs(_stylusDevice, report);
                }
                else
                {
                    inputReportEventArgs = new InputReportEventArgs(this, report);
                }

                inputReportEventArgs.RoutedEvent=InputManager.PreviewInputReportEvent;

                //ProcessInput has a linkdemand
                _inputManager.Value.ProcessInput(inputReportEventArgs);
            }
        }
        public void Synchronize()
        {
            // Simulate a stylus move (if we are current stylus, inrange, visuals still valid to update
            // and has moved).
            if (InRange && _inputSource != null && _inputSource.Value != null &&
                _inputSource.Value.CompositionTarget != null && !_inputSource.Value.CompositionTarget.IsDisposed)
            {
                Point ptDevice = PointUtil.ScreenToClient(_lastScreenLocation, _inputSource.Value);
                
                // GlobalHitTest always returns an IInputElement, so we are sure to have one.
                IInputElement stylusOver = GlobalHitTest(_inputSource.Value, ptDevice);
                bool fOffsetChanged = false;

                if (_stylusOver == stylusOver)
                {
                    Point ptOffset = GetPosition(stylusOver);
                    fOffsetChanged = MS.Internal.DoubleUtil.AreClose(ptOffset.X, _rawElementRelativePosition.X) == false || MS.Internal.DoubleUtil.AreClose(ptOffset.Y, _rawElementRelativePosition.Y) == false;
                }

                if(fOffsetChanged || _stylusOver != stylusOver)
                {
                    int timeStamp = Environment.TickCount;
                    PenContext penContext = _stylusLogic.GetStylusPenContextForHwnd(_inputSource.Value,TabletDevice.Id);

                    if (_eventStylusPoints != null &&
                        _eventStylusPoints.Count > 0 &&
                        StylusPointDescription.AreCompatible(penContext.StylusPointDescription, _eventStylusPoints.Description))
                    {

                        StylusPoint stylusPoint = _eventStylusPoints[_eventStylusPoints.Count - 1];
                        int[] data = stylusPoint.GetPacketData();

                        // get back to the correct coordinate system
                        Matrix m = TabletDevice.TabletToScreen;
                        m.Invert();
                        Point ptTablet = ptDevice * m;

                        data[0] = (int)ptTablet.X;
                        data[1] = (int)ptTablet.Y;

                        RawStylusInputReport report = new RawStylusInputReport(InputMode.Foreground,
                                                                             timeStamp,
                                                                             _inputSource.Value,
                                                                             penContext,
                                                                             InAir?RawStylusActions.InAirMove:RawStylusActions.Move,
                                                                             TabletDevice.Id,
                                                                             Id,
                                                                             data);


                        report.Synchronized = true;

                        InputReportEventArgs inputReportEventArgs = new InputReportEventArgs(this, report);
                        inputReportEventArgs.RoutedEvent=InputManager.PreviewInputReportEvent;

                        _stylusLogic.InputManagerProcessInputEventArgs(inputReportEventArgs);
                    }
                }
            }
        }
Exemple #20
0
        private void PostProcessInput(object sender, ProcessInputEventArgs e)
        { 
            //only [....] with mouse capture if we're enabled, or else there are no tablet devices
            //hence no input.  We have to work around this because getting the
            //Tablet.TabletDevices will load Penimc.dll.
            if (_inputEnabled) 
            {
                // Watch the LostMouseCapture and GotMouseCapture events to keep stylus capture in [....]. 
                if(e.StagingItem.Input.RoutedEvent == Mouse.LostMouseCaptureEvent || 
                    e.StagingItem.Input.RoutedEvent == Mouse.GotMouseCaptureEvent)
                { 
#if MULTICAPTURE
                    var mouseStylusDevice = Mouse.PrimaryDevice.StylusDevice;
#endif
 
                    // Make sure mouse and stylus capture is the same.
                    foreach (TabletDevice tabletDevice in TabletDevices) 
                    { 
                        foreach (StylusDevice stylusDevice in tabletDevice.StylusDevices)
                        { 
#if MULTICAPTURE
                            if (stylusDevice == mouseStylusDevice)
                            {
#endif 
                                // We use the Mouse device state for each call just in case we
                                // get reentered in the middle of changing so when we continue 
                                // we'll use the current mouse capture state (which should NOP). 
                                stylusDevice.Capture(Mouse.Captured, Mouse.CapturedMode);
#if MULTICAPTURE 
                            }
#endif
                        }
                    } 
                }
            } 
 
            if(e.StagingItem.Input.RoutedEvent == InputManager.InputReportEvent && !_inDragDrop)
            { 
                InputReportEventArgs input = e.StagingItem.Input as InputReportEventArgs;
                if(!input.Handled && input.Report.Type == InputType.Stylus)
                {
                    RawStylusInputReport report = (RawStylusInputReport) input.Report; 
                    // Only promote if the window is enabled!
                    if (!report.PenContext.Contexts.IsWindowDisabled) 
                    { 
                        PromoteRawToPreview(report, e);
 
                        // Need to reset this flag at the end of StylusUp processing.
                        if (report.Actions == RawStylusActions.Up)
                        {
                            report.StylusDevice.IgnoreStroke = false; 
                        }
                    } 
                } 
            }
 
            // If we are processing an OutOfRange event then see if we need to update the over state.
            // We need to update it if mouse is already outside the window (MouseDevice.DirectlyOver
            // is null) since if it has already seen the WM_MOUSELEAVE we'll never update out over
            // state properly.  If the WM_MOUSELEAVE comes in after we see the OutOfRange then the 
            // code at the end of PreProcessInput will deal that case properly.
            if(e.StagingItem.Input.RoutedEvent == Stylus.StylusOutOfRangeEvent) 
            { 
                RawMouseInputReport mouseDeactivateInputReport = _mouseDeactivateInputReport;
                _mouseDeactivateInputReport = null; 
                StylusEventArgs eventArgsOutOfRange = (StylusEventArgs)e.StagingItem.Input;

                // If we have deferred mouse moves then make sure we process last one now.
                if (_lastRawMouseAction == RawMouseActions.AbsoluteMove && _waitingForDelegate) 
                {
                    ProcessMouseMove(eventArgsOutOfRange.StylusDevice, eventArgsOutOfRange.Timestamp, false); 
                } 

                // See if we need to set the Mouse Activate flag. 
                PresentationSource mouseSource = _inputManager.Value.PrimaryMouseDevice.CriticalActiveSource;

                // See if we need to change the stylus over state state and send a mouse deactivate.
                // We send the cached Deactivate through if we saw mouse deactivate before out of range event 
                // *or* for a quick move with the stylus over a window we may not even see any win32 mouse events
                // so in that case we also need to deactivate the mouse since we were the ones that activated it. 
                if (mouseDeactivateInputReport != null || (!_seenRealMouseActivate && mouseSource != null)) 
                {
                    // First update the StylusDevice DirectlyOver to null if the mouse device saw a Deactivate (means 
                    // the mouse left the window) or if it never saw a real activate (stylus mouse promotion
                    // caused it to be active).
                    eventArgsOutOfRange.StylusDevice.ChangeStylusOver(null);
 
                    // Now send the mouse deactivate
                    RawMouseInputReport newMouseInputReport = mouseDeactivateInputReport != null ? 
                                                    new RawMouseInputReport( 
                                                        mouseDeactivateInputReport.Mode,
                                                        eventArgsOutOfRange.Timestamp, // updated time 
                                                        mouseDeactivateInputReport.InputSource,
                                                        mouseDeactivateInputReport.Actions,
                                                        mouseDeactivateInputReport.X,
                                                        mouseDeactivateInputReport.Y, 
                                                        mouseDeactivateInputReport.Wheel,
                                                        mouseDeactivateInputReport.ExtraInformation) : 
                                                    new RawMouseInputReport( 
                                                        InputMode.Foreground,
                                                        eventArgsOutOfRange.Timestamp, // updated time 
                                                        mouseSource,
                                                        RawMouseActions.Deactivate,
                                                        0,
                                                        0, 
                                                        0,
                                                        IntPtr.Zero); 
 
                    InputReportEventArgs actionsArgs = new InputReportEventArgs(eventArgsOutOfRange.StylusDevice, newMouseInputReport);
                    actionsArgs.RoutedEvent=InputManager.PreviewInputReportEvent; 
                    _inputManager.Value.ProcessInput(actionsArgs);
                }
            }
 
            // Deal with sending mouse events to the plugins.
            // NOTE: We want to do this after the mousedevice has sent it's click through 
            // events (PreviewMouseDownOutsideCapturedElementEvent/PreviewMouseUpOutsideCapturedElementEvent) 
            // and PreviewMouse events so that we can route more accurately to where the Mouse events will
            // actually get routed. 
            CallPlugInsForMouse(e);

            PromotePreviewToMain(e);
 
            UpdateButtonStates(e);
 
            PromoteMainToOther(e); 

            // See if we need to generate a drag gesture. 
            if(e.StagingItem.Input.RoutedEvent == Stylus.StylusMoveEvent)
            {
                StylusEventArgs stylusMove = (StylusEventArgs)e.StagingItem.Input;
                if (stylusMove.StylusDevice.SeenDoubleTapGesture && !stylusMove.StylusDevice.GestureWasFired && 
                    stylusMove.StylusDevice.DetectedDrag)
                { 
                    GenerateGesture(stylusMove.InputReport, SystemGesture.Drag); 
                }
            } 

            // Process the flick scroll up/down system gesture now.
            if (e.StagingItem.Input.RoutedEvent == Stylus.StylusSystemGestureEvent)
            { 
                StylusSystemGestureEventArgs stylusSystemGesture = (StylusSystemGestureEventArgs)e.StagingItem.Input;
                if (stylusSystemGesture.SystemGesture == SystemGesture.Flick) 
                { 
                    HandleFlick(stylusSystemGesture.ButtonState, stylusSystemGesture.StylusDevice.DirectlyOver);
                } 
            }
        }