private void InputDeviceEvents_PreProcessInput(object sender, PreProcessInputEventArgs e) { if (e.StagingItem.Input.Device is TouchDevice) { InputReportEventArgs irea = e.StagingItem.Input as InputReportEventArgs; if (irea != null) { RawTouchInputReport rtir = irea.Report as RawTouchInputReport; if (rtir != null) { int x = rtir.Touches[0].X; int y = rtir.Touches[0].Y; PointToClient(ref x, ref y); if (!Utils.IsWithinRectangle(x, y, ActualWidth, ActualWidth)) e.Cancel(); } } } }
private void InputDeviceEvents_PreProcessInput(object sender, PreProcessInputEventArgs e) { if (e.StagingItem.Input.Device is TouchDevice) { InputReportEventArgs irea = e.StagingItem.Input as InputReportEventArgs; if (irea != null) { RawTouchInputReport rtir = irea.Report as RawTouchInputReport; if (rtir != null) { // cancel any touch event that does not start within the modal window //if (!this.ContainsPoint(rtir.Touches[0].X, rtir.Touches[0].Y)) // e.Cancel(); int x = rtir.Touches[0].X; int y = rtir.Touches[0].Y; PointToClient(ref x, ref y); if (!Utils.IsWithinRectangle(x, y, ActualWidth, ActualWidth)) e.Cancel(); } } } }
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; }
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); }