// at the moment we don't have a good way of detecting when an // element gets deleted from the tree (logical or visual). The // best we can do right now is clear out the focus if we detect // that the tree containing the focus was disconnected. private bool CheckForDisconnectedFocus() { bool wasDisconnected = false; if (InputElement.GetRootVisual(_focus as DependencyObject) != _focusRootVisual) { wasDisconnected = true; Focus(null); } return(wasDisconnected); }
/// <summary> /// Gets the transform relative to a particular element in the visual tree. /// </summary> internal static GeneralTransform GetElementTransform(IInputElement relativeTo) { GeneralTransform elementTransform = Transform.Identity; DependencyObject doRelativeTo = relativeTo as DependencyObject; if (doRelativeTo != null) { Visual visualFirstAncestor = VisualTreeHelper.GetContainingVisual2D(InputElement.GetContainingVisual(doRelativeTo)); Visual visualRoot = VisualTreeHelper.GetContainingVisual2D(InputElement.GetRootVisual(doRelativeTo)); GeneralTransform g = visualRoot.TransformToDescendant(visualFirstAncestor); if (g != null) { elementTransform = g; } } return(elementTransform); }
private void ChangeFocus(DependencyObject focus, int timestamp) { DependencyObject o = null; if (focus != _focus) { // Update the critical pieces of data. DependencyObject oldFocus = _focus; _focus = focus; _focusRootVisual = InputElement.GetRootVisual(focus); using (Dispatcher.DisableProcessing()) // Disable reentrancy due to locks taken { // Adjust the handlers we use to track everything. if (oldFocus != null) { o = oldFocus; if (InputElement.IsUIElement(o)) { ((UIElement)o).IsEnabledChanged -= _isEnabledChangedEventHandler; ((UIElement)o).IsVisibleChanged -= _isVisibleChangedEventHandler; ((UIElement)o).FocusableChanged -= _focusableChangedEventHandler; } else if (InputElement.IsContentElement(o)) { ((ContentElement)o).IsEnabledChanged -= _isEnabledChangedEventHandler; // NOTE: there is no IsVisible property for ContentElements. ((ContentElement)o).FocusableChanged -= _focusableChangedEventHandler; } else { ((UIElement3D)o).IsEnabledChanged -= _isEnabledChangedEventHandler; ((UIElement3D)o).IsVisibleChanged -= _isVisibleChangedEventHandler; ((UIElement3D)o).FocusableChanged -= _focusableChangedEventHandler; } } if (_focus != null) { o = _focus; if (InputElement.IsUIElement(o)) { ((UIElement)o).IsEnabledChanged += _isEnabledChangedEventHandler; ((UIElement)o).IsVisibleChanged += _isVisibleChangedEventHandler; ((UIElement)o).FocusableChanged += _focusableChangedEventHandler; } else if (InputElement.IsContentElement(o)) { ((ContentElement)o).IsEnabledChanged += _isEnabledChangedEventHandler; // NOTE: there is no IsVisible property for ContentElements. ((ContentElement)o).FocusableChanged += _focusableChangedEventHandler; } else { ((UIElement3D)o).IsEnabledChanged += _isEnabledChangedEventHandler; ((UIElement3D)o).IsVisibleChanged += _isVisibleChangedEventHandler; ((UIElement3D)o).FocusableChanged += _focusableChangedEventHandler; } } } // Oddly enough, update the FocusWithinProperty properties first. This is // so any callbacks will see the more-common FocusWithinProperty properties // set correctly. UIElement.FocusWithinProperty.OnOriginValueChanged(oldFocus, _focus, ref _focusTreeState); // Invalidate the IsKeyboardFocused properties. if (oldFocus != null) { o = oldFocus; o.SetValue(UIElement.IsKeyboardFocusedPropertyKey, false); // Same property for ContentElements } if (_focus != null) { // Invalidate the IsKeyboardFocused property. o = _focus; o.SetValue(UIElement.IsKeyboardFocusedPropertyKey, true); // Same property for ContentElements } // Call TestServicesManager change the focus of the InputMethod is enable/disabled accordingly // so it's ready befere the GotKeyboardFocusEvent handler is invoked. if (_TsfManager != null) { _TsfManager.Value.Focus(_focus); } // InputLanguageManager checks the preferred input languages. // This should before GotEvent because the preferred input language // should be set at the event handler. InputLanguageManager.Current.Focus(_focus, oldFocus); // Send the LostKeyboardFocus and GotKeyboardFocus events. if (oldFocus != null) { KeyboardFocusChangedEventArgs lostFocus = new KeyboardFocusChangedEventArgs(this, timestamp, (IInputElement)oldFocus, (IInputElement)focus); lostFocus.RoutedEvent = Keyboard.LostKeyboardFocusEvent; lostFocus.Source = oldFocus; if (_inputManager != null) { _inputManager.Value.ProcessInput(lostFocus); } } if (_focus != null) { KeyboardFocusChangedEventArgs gotFocus = new KeyboardFocusChangedEventArgs(this, timestamp, (IInputElement)oldFocus, (IInputElement)_focus); gotFocus.RoutedEvent = Keyboard.GotKeyboardFocusEvent; gotFocus.Source = _focus; if (_inputManager != null) { _inputManager.Value.ProcessInput(gotFocus); } } // InputMethod checks the preferred ime state. // The preferred input methods should be applied after Cicero TIP gots SetFocus callback. InputMethod.Current.GotKeyboardFocus(_focus); //Could be also built-in into IsKeyboardFocused_Changed static on UIElement and ContentElement //However the Automation likes to go immediately back on us so it would be better be last one... AutomationPeer.RaiseFocusChangedEventHelper((IInputElement)_focus); } }
internal static Point TranslatePoint(Point pt, DependencyObject from, DependencyObject to, out bool translated) { translated = false; Point ptTranslated = pt; // Get the containing and root visuals we are coming from. DependencyObject vFromAsDO = InputElement.GetContainingVisual(from); Visual rootFrom = InputElement.GetRootVisual(from) as Visual; Visual vFrom = vFromAsDO as Visual; if (vFromAsDO != null && vFrom == null) { // must be a Visual3D - get it's 2D visual parent vFrom = VisualTreeHelper.GetContainingVisual2D(vFromAsDO); } if (vFrom != null && rootFrom != null) { GeneralTransform gUp; Matrix mUp; bool isUpSimple = false; isUpSimple = vFrom.TrySimpleTransformToAncestor(rootFrom, false, /* do not apply inverse */ out gUp, out mUp); if (isUpSimple) { ptTranslated = mUp.Transform(ptTranslated); } else if (gUp.TryTransform(ptTranslated, out ptTranslated) == false) { // Error. Out parameter has been set false. return(new Point()); } // If no element was specified to translate to, we leave the coordinates // translated to the root. if (to != null) { // Get the containing and root visuals we are going to. DependencyObject vTo = InputElement.GetContainingVisual(to); Visual rootTo = InputElement.GetRootVisual(to) as Visual; if (vTo != null && rootTo != null) { // If both are under the same root visual, we can easily translate the point // between them by translating up to the root, and then back down. // // However, if both are under different roots, we can only translate // between them if we know how to relate the two root visuals. Currently // we only know how to do that if both roots are sourced in HwndSources. if (rootFrom != rootTo) { HwndSource sourceFrom = PresentationSource.CriticalFromVisual(rootFrom) as HwndSource; HwndSource sourceTo = PresentationSource.CriticalFromVisual(rootTo) as HwndSource; if (sourceFrom != null && sourceFrom.CriticalHandle != IntPtr.Zero && sourceFrom.CompositionTarget != null && sourceTo != null && sourceTo.CriticalHandle != IntPtr.Zero && sourceTo.CompositionTarget != null) { // Translate the point into client coordinates. ptTranslated = PointUtil.RootToClient(ptTranslated, sourceFrom); // Translate the point into screen coordinates. Point ptScreen = PointUtil.ClientToScreen(ptTranslated, sourceFrom); // Translate the point back the the client coordinates of the To window. ptTranslated = PointUtil.ScreenToClient(ptScreen, sourceTo); // Translate the point back to the root element. ptTranslated = PointUtil.ClientToRoot(ptTranslated, sourceTo); } else { // Error. Out parameter has been set false. return(new Point()); } } // Translate the point from the root to the visual. GeneralTransform gDown; Matrix mDown; Visual vToAsVisual = vTo as Visual; if (vToAsVisual == null) { // must be a Visual3D vToAsVisual = VisualTreeHelper.GetContainingVisual2D(vTo); } bool isDownSimple = vToAsVisual.TrySimpleTransformToAncestor(rootTo, true, /* apply inverse */ out gDown, out mDown); if (isDownSimple) { ptTranslated = mDown.Transform(ptTranslated); } else if (gDown != null) { if (gDown.TryTransform(ptTranslated, out ptTranslated) == false) { // Error. Out parameter has been set false. return(new Point()); } } else { // Error. Out parameter has been set false. return(new Point()); } } else { // Error. Out parameter has been set false. return(new Point()); } } } else { // Error. Out parameter has been set false. return(new Point()); } translated = true; return(ptTranslated); }