private void PostProcessInput(object sender, ProcessInputEventArgs e) { InputReportEventArgs input = e.StagingItem.Input as InputReportEventArgs; if (input != null && input.RoutedEvent == InputManager.InputReportEvent) { RawGenericInputReport report = input.Report as RawGenericInputReport; if (report != null) { if (!e.StagingItem.Input.Handled) { GenericEvent ge = (GenericEvent)report.InternalEvent; GenericEventArgs args = new GenericEventArgs( this, report.InternalEvent); args.RoutedEvent = GenericEvents.GenericStandardEvent; if (report.Target != null) { args.Source = report.Target; } e.PushInput(args, e.StagingItem); } } } }
private RawButtonInputReport ExtractRawButtonInputReport(NotifyInputEventArgs e, RoutedEvent Event) { RawButtonInputReport buttonInput = null; InputReportEventArgs input = e.StagingItem.Input as InputReportEventArgs; if (input != null) { if (input.Report is RawButtonInputReport && input.RoutedEvent == Event) { buttonInput = (RawButtonInputReport)input.Report; } } return(buttonInput); }
private void PostProcessInput(object sender, ProcessInputEventArgs e) { if (!e.StagingItem.Input.Handled) { RoutedEvent routedEvent = e.StagingItem.Input.RoutedEvent; if (routedEvent == InputManager.InputReportEvent) { InputReportEventArgs input = e.StagingItem.Input as InputReportEventArgs; if (input != null) { RawTouchInputReport report = input.Report as RawTouchInputReport; if (report != null) { TouchEventArgs args = new TouchEventArgs( this, report.Timestamp, report.Touches); UIElement target = report.Target; if (report.EventMessage == (byte)TouchMessages.Down) { args.RoutedEvent = TouchEvents.TouchDownEvent; } else if (report.EventMessage == (byte)TouchMessages.Up) { args.RoutedEvent = TouchEvents.TouchUpEvent; } else if (report.EventMessage == (byte)TouchMessages.Move) { args.RoutedEvent = TouchEvents.TouchMoveEvent; } else { throw new Exception("Unknown touch event."); } args.Source = (target == null ? _focus : target); e.PushInput(args, e.StagingItem); } } } } }
/// <summary> /// Reports input to the input manager. /// </summary> /// <returns> /// Whether or not any event generated as a consequence of this /// event was handled. /// </returns> // do we really need this? Make the "providers" call InputManager.ProcessInput themselves. // we currently need to map back to providers for other reasons. public bool ReportInput(InputDevice device, InputReport inputReport) { if (_isDisposed) { throw new InvalidOperationException(); } bool handled = false; InputReportEventArgs input = new InputReportEventArgs(device, inputReport); input.RoutedEvent = InputManager.PreviewInputReportEvent; if (_inputManager != null) { handled = _inputManager.ProcessInput(input); } return(handled); }
private object ProcessStagingArea(object frame) { bool handled = false; // NOTE -- avalon caches the XXXEventArgs. In our system, the costs are different, // so it is probably cheaper for us to just create them, since everything gets created // on the heap anyways, and IL is expensive. we should reconsider this if // its a performance impact. // 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. try { while (_stagingArea.Count > 0) { _currentStagingStack = _stagingArea.Dequeue() as Stack; do { StagingAreaInputItem item = (StagingAreaInputItem)_currentStagingStack.Pop(); // Pre-Process the input. This could modify the staging // area, and it could cancel the processing of this // input event. // bool fCanceled = false; int devType = (int)item.Input._inputDevice.DeviceType; if (InputDeviceEvents[devType]._preProcessInput != null) { PreProcessInputEventArgs preProcessInputEventArgs; InputDeviceEvents[devType]._preProcessInput(this, preProcessInputEventArgs = new PreProcessInputEventArgs(item)); fCanceled = preProcessInputEventArgs._canceled; } if (!fCanceled) { // Pre-Notify the input. // if (InputDeviceEvents[devType]._preNotifyInput != null) { InputDeviceEvents[devType]._preNotifyInput(this, new NotifyInputEventArgs(item)); } // Raise the input event being processed. InputEventArgs input = item.Input; // Some input events are explicitly associated with // an element. Those that are not instead are associated with // the target of the input device for this event. UIElement eventSource = input._source as UIElement; if (eventSource == null && input._inputDevice != null) { eventSource = input._inputDevice.Target; } if (eventSource != null) { eventSource.RaiseEvent(input); } // Post-Notify the input. // if (InputDeviceEvents[devType]._postNotifyInput != null) { InputDeviceEvents[devType]._postNotifyInput(this, new NotifyInputEventArgs(item)); } // Post-Process the input. This could modify the staging // area. if (InputDeviceEvents[devType]._postProcessInput != null) { InputDeviceEvents[devType]._postProcessInput(this, new ProcessInputEventArgs(item)); } // 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; _currentStagingStack.Push(new StagingAreaInputItem(inputReport, item)); } } if (input.Handled) { handled = true; } } } while (_currentStagingStack.Count > 0); } } finally { // It is possible that we can be re-entered by a nested // dispatcher frame. Continue processing the staging // area if we need to. if (_stagingArea.Count > 0) { // Before we actually start to drain the staging area, we need // to post a work item to process more input. This enables us // to process more input if we enter a nested pump. Dispatcher.BeginInvoke(_continueProcessingStagingAreaCallback, Dispatcher.CurrentFrame); } _frameStagingArea.Remove(frame); } return handled; }
private object ProcessStagingArea(object postContinue) { bool handled = false; // NOTE -- avalon caches the XXXEventArgs. In our system, the costs are different, // so it is probably cheaper for us to just create them, since everything gets created // on the heap anyways, and IL is expensive. we should reconsider this if // its a performance impact. // 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. while (_stagingArea.Count > 0) { StagingAreaInputItem item = (StagingAreaInputItem)_stagingArea.Pop(); // 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. // 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 you 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. // bool fCanceled = false; int devType = (int)item.Input._inputDevice.DeviceType; if (InputDeviceEvents[devType]._preProcessInput != null) { PreProcessInputEventArgs preProcessInputEventArgs; InputDeviceEvents[devType]._preProcessInput(this, preProcessInputEventArgs = new PreProcessInputEventArgs(item)); fCanceled = preProcessInputEventArgs._canceled; } if (!fCanceled) { // Pre-Notify the input. // if (InputDeviceEvents[devType]._preNotifyInput != null) { InputDeviceEvents[devType]._preNotifyInput(this, new NotifyInputEventArgs(item)); } // Raise the input event being processed. InputEventArgs input = item.Input; // Some input events are explicitly associated with // an element. Those that are not instead are associated with // the target of the input device for this event. UIElement eventSource = input._source as UIElement; if (eventSource == null && input._inputDevice != null) { eventSource = input._inputDevice.Target; } if (eventSource != null) { eventSource.RaiseEvent(input); } // Post-Notify the input. // if (InputDeviceEvents[devType]._postNotifyInput != null) { InputDeviceEvents[devType]._postNotifyInput(this, new NotifyInputEventArgs(item)); } // Post-Process the input. This could modify the staging // area. if (InputDeviceEvents[devType]._postProcessInput != null) { InputDeviceEvents[devType]._postProcessInput(this, new ProcessInputEventArgs(item)); // 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; _stagingArea.Push(new StagingAreaInputItem(false, inputReport, item)); } } } if (input.Handled) { handled = true; } } } if ((bool)postContinue == true) { _continueProcessingStagingArea = false; // It is possible that we can be re-entered by a nested // dispatcher frame. Continue processing the staging // area if we need to. if (_stagingArea.Count > 0) { // Before we actually start to drain the staging area, we need // to post a work item to process more input. This enables us // to process more input if we enter a nested pump. Dispatcher.BeginInvoke(_continueProcessingStagingAreaCallback, true); _continueProcessingStagingArea = true; // Now fall through to synchronously drain the staging area. } } return handled; }
/// <summary> /// Reports input to the input manager. /// </summary> /// <returns> /// Whether or not any event generated as a consequence of this /// event was handled. /// </returns> // do we really need this? Make the "providers" call InputManager.ProcessInput themselves. // we currently need to map back to providers for other reasons. public bool ReportInput(InputDevice device, InputReport inputReport) { if (_isDisposed) { throw new InvalidOperationException(); } bool handled = false; InputReportEventArgs input = new InputReportEventArgs(device, inputReport); input.RoutedEvent = InputManager.PreviewInputReportEvent; if (_inputManager != null) { handled = _inputManager.ProcessInput(input); } return handled; }
private object ProcessStagingArea(object postContinue) { bool handled = false; // NOTE -- avalon caches the XXXEventArgs. In our system, the costs are different, // so it is probably cheaper for us to just create them, since everything gets created // on the heap anyways, and IL is expensive. we should reconsider this if // its a performance impact. // 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. _continueProcessingStagingArea = true; try { while (_stagingArea.Count > 0) { _currentStagingStack = _stagingArea.Dequeue() as Stack; do { StagingAreaInputItem item = (StagingAreaInputItem)_currentStagingStack.Pop(); // Pre-Process the input. This could modify the staging // area, and it could cancel the processing of this // input event. // bool fCanceled = false; int devType = (int)item.Input._inputDevice.DeviceType; if (InputDeviceEvents[devType]._preProcessInput != null) { PreProcessInputEventArgs preProcessInputEventArgs; InputDeviceEvents[devType]._preProcessInput(this, preProcessInputEventArgs = new PreProcessInputEventArgs(item)); fCanceled = preProcessInputEventArgs._canceled; } if (!fCanceled) { // Pre-Notify the input. // if (InputDeviceEvents[devType]._preNotifyInput != null) { InputDeviceEvents[devType]._preNotifyInput(this, new NotifyInputEventArgs(item)); } // Raise the input event being processed. InputEventArgs input = item.Input; // Some input events are explicitly associated with // an element. Those that are not instead are associated with // the target of the input device for this event. UIElement eventSource = input._source as UIElement; if (eventSource == null && input._inputDevice != null) { eventSource = input._inputDevice.Target; } if (eventSource != null) { eventSource.RaiseEvent(input); } // Post-Notify the input. // if (InputDeviceEvents[devType]._postNotifyInput != null) { InputDeviceEvents[devType]._postNotifyInput(this, new NotifyInputEventArgs(item)); } // Post-Process the input. This could modify the staging // area. if (InputDeviceEvents[devType]._postProcessInput != null) { InputDeviceEvents[devType]._postProcessInput(this, new ProcessInputEventArgs(item)); } // 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; _currentStagingStack.Push(new StagingAreaInputItem(inputReport, item)); } } if (input.Handled) { handled = true; } } }while(_currentStagingStack.Count > 0); } } finally { _continueProcessingStagingArea = false; // It is possible that we can be re-entered by a nested // dispatcher frame. Continue processing the staging // area if we need to. if (_stagingArea.Count > 0) { _continueProcessingStagingArea = true; // Before we actually start to drain the staging area, we need // to post a work item to process more input. This enables us // to process more input if we enter a nested pump. Dispatcher.BeginInvoke(_continueProcessingStagingAreaCallback, true); } } return(handled); }
private object ProcessStagingArea(object postContinue) { bool handled = false; // NOTE -- avalon caches the XXXEventArgs. In our system, the costs are different, // so it is probably cheaper for us to just create them, since everything gets created // on the heap anyways, and IL is expensive. we should reconsider this if // its a performance impact. // 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. while (_stagingArea.Count > 0) { StagingAreaInputItem item = (StagingAreaInputItem)_stagingArea.Pop(); // 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. // 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 you 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. // bool fCanceled = false; int devType = (int)item.Input._inputDevice.DeviceType; if (InputDeviceEvents[devType]._preProcessInput != null) { PreProcessInputEventArgs preProcessInputEventArgs; InputDeviceEvents[devType]._preProcessInput(this, preProcessInputEventArgs = new PreProcessInputEventArgs(item)); fCanceled = preProcessInputEventArgs._canceled; } if (!fCanceled) { // Pre-Notify the input. // if (InputDeviceEvents[devType]._preNotifyInput != null) { InputDeviceEvents[devType]._preNotifyInput(this, new NotifyInputEventArgs(item)); } // Raise the input event being processed. InputEventArgs input = item.Input; // Some input events are explicitly associated with // an element. Those that are not instead are associated with // the target of the input device for this event. UIElement eventSource = input._source as UIElement; if (eventSource == null && input._inputDevice != null) { eventSource = input._inputDevice.Target; } if (eventSource != null) { eventSource.RaiseEvent(input); } // Post-Notify the input. // if (InputDeviceEvents[devType]._postNotifyInput != null) { InputDeviceEvents[devType]._postNotifyInput(this, new NotifyInputEventArgs(item)); } // Post-Process the input. This could modify the staging // area. if (InputDeviceEvents[devType]._postProcessInput != null) { InputDeviceEvents[devType]._postProcessInput(this, new ProcessInputEventArgs(item)); // 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; _stagingArea.Push(new StagingAreaInputItem(false, inputReport, item)); } } } if (input.Handled) { handled = true; } } } if ((bool)postContinue == true) { _continueProcessingStagingArea = false; // It is possible that we can be re-entered by a nested // dispatcher frame. Continue processing the staging // area if we need to. if (_stagingArea.Count > 0) { // Before we actually start to drain the staging area, we need // to post a work item to process more input. This enables us // to process more input if we enter a nested pump. Dispatcher.BeginInvoke(_continueProcessingStagingAreaCallback, true); _continueProcessingStagingArea = true; // Now fall through to synchronously drain the staging area. } } return(handled); }