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); } }