diff --git a/CefSharp.Wpf/ChromiumWebBrowser.cs b/CefSharp.Wpf/ChromiumWebBrowser.cs index 7c1c9732e8..7ba1bfe8ca 100644 --- a/CefSharp.Wpf/ChromiumWebBrowser.cs +++ b/CefSharp.Wpf/ChromiumWebBrowser.cs @@ -3,6 +3,7 @@ // Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. using System; +using System.Diagnostics; using System.Runtime.CompilerServices; using System.Threading; using System.Threading.Tasks; @@ -604,7 +605,12 @@ private void NoInliningConstructor() browserSettings = Core.ObjectFactory.CreateBrowserSettings(autoDispose: true); - WpfKeyboardHandler = new WpfKeyboardHandler(this); + SetupWpfKeyboardHandler(); + + if (WpfKeyboardHandler == null) + { + WpfKeyboardHandler = new WpfKeyboardHandler(this); + } PresentationSource.AddSourceChangedHandler(this, PresentationSourceChangedHandler); @@ -753,6 +759,8 @@ private void InternalDispose(bool disposing) // is called. LifeSpanHandler = null; + UnsubscribeInputLanguageChanged(); + WpfKeyboardHandler?.Dispose(); WpfKeyboardHandler = null; @@ -769,6 +777,44 @@ private void InternalDispose(bool disposing) Cef.RemoveDisposable(this); } + /// + /// Setup the used by this instance. + /// There are two main keyboard handler implementations currently + /// and . If + /// returns true for the current + /// then the instance will be used, otherwise the older + /// instance will be used. + /// Override to provide your own custom keyboard handler. + /// + protected virtual void SetupWpfKeyboardHandler() + { + try + { + var inputLang = InputLanguageManager.Current.CurrentInputLanguage; + + var useImeKeyboardHandler = WpfImeKeyboardHandler.UseImeKeyboardHandler(inputLang.KeyboardLayoutId); + + if (useImeKeyboardHandler) + { + WpfKeyboardHandler = new WpfImeKeyboardHandler(this); + } + else + { + InputLanguageManager.Current.InputLanguageChanged += OnInputLanguageChanged; + + WpfKeyboardHandler = new WpfKeyboardHandler(this); + } + } + catch (Exception ex) + { + //For now we'll ignore any errors + Trace.TraceError($"Error initializing keyboard handler: {ex.ToString()}"); + + // For now we'll ignore any errors and just use the default keyboard handler + WpfKeyboardHandler = new WpfKeyboardHandler(this); + } + } + /// /// Gets the ScreenInfo - currently used to get the DPI scale factor. /// @@ -1750,6 +1796,26 @@ private void OnDragEnter(object sender, DragEventArgs e) } } + private void OnInputLanguageChanged(object sender, InputLanguageEventArgs e) + { + // If we are already using the WpfImeKeyboardHandler then we'll ignore any changes + if (WpfKeyboardHandler?.GetType() == typeof(WpfImeKeyboardHandler)) + { + return; + } + + var useImeKeyboardHandler = WpfImeKeyboardHandler.UseImeKeyboardHandler(e.NewLanguage.KeyboardLayoutId); + + if (useImeKeyboardHandler) + { + var oldKeyboardHandler = WpfKeyboardHandler; + WpfKeyboardHandler = new WpfImeKeyboardHandler(this); + oldKeyboardHandler?.Dispose(); + + InputLanguageManager.Current.InputLanguageChanged -= OnInputLanguageChanged; + } + } + /// /// PresentationSource changed handler. /// @@ -2858,5 +2924,35 @@ private async Task ResizeHackRun() } } } + + private void UnsubscribeInputLanguageChanged() + { + // If we are using WpfImeKeyboardHandler then we + // shouldn't need to unsubsribe from the handler + if (WpfKeyboardHandler?.GetType() == typeof(WpfImeKeyboardHandler)) + { + return; + } + + try + { + // Dispose can be called on non UI thread, InputLanguageManager.Current + // is thread specific + UiThreadRunAsync(() => + { + var inputLangManager = InputLanguageManager.Current; + + if (inputLangManager != null) + { + inputLangManager.InputLanguageChanged -= OnInputLanguageChanged; + } + }); + } + catch (Exception ex) + { + //For now we'll ignore any errors + Trace.TraceError($"Error unsubscribing from InputLanguageChanged {ex.ToString()}"); + } + } } } diff --git a/CefSharp.Wpf/Experimental/WpfIMEKeyboardHandler.cs b/CefSharp.Wpf/Experimental/WpfIMEKeyboardHandler.cs index 852a056ea2..c92a382b66 100644 --- a/CefSharp.Wpf/Experimental/WpfIMEKeyboardHandler.cs +++ b/CefSharp.Wpf/Experimental/WpfIMEKeyboardHandler.cs @@ -354,7 +354,7 @@ private void CreateImeWindow(IntPtr hwnd) } } - private int PrimaryLangId(int lgid) + private static int PrimaryLangId(int lgid) { return lgid & 0x3ff; } @@ -467,5 +467,25 @@ private FrameworkElement GetOutermostElement(FrameworkElement control) return current as FrameworkElement; } + + /// + /// Based on the determine if we + /// should be using IME. + /// + /// Keyboard Layout Id (obtained from ) + /// + /// returns true if the keyboard layout matches one of our listed that support IME, otherwise false. + /// + public static bool UseImeKeyboardHandler(int keyboardLayoutId) + { + var langId = PrimaryLangId(keyboardLayoutId); + + if (langId == ImeNative.LANG_KOREAN || langId == ImeNative.LANG_JAPANESE || langId == ImeNative.LANG_CHINESE) + { + return true; + } + + return false; + } } }