Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 97 additions & 1 deletion CefSharp.Wpf/ChromiumWebBrowser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -753,6 +759,8 @@ private void InternalDispose(bool disposing)
// is called.
LifeSpanHandler = null;

UnsubscribeInputLanguageChanged();

WpfKeyboardHandler?.Dispose();
WpfKeyboardHandler = null;

Expand All @@ -769,6 +777,44 @@ private void InternalDispose(bool disposing)
Cef.RemoveDisposable(this);
}

/// <summary>
/// Setup the <see cref="WpfKeyboardHandler"/> used by this <see cref="ChromiumWebBrowser"/> instance.
/// There are two main keyboard handler implementations currently <see cref="WpfImeKeyboardHandler"/>
/// and <see cref="Internals.WpfKeyboardHandler"/>. If <see cref="WpfImeKeyboardHandler.UseImeKeyboardHandler"/>
/// returns true for the current <see cref="System.Globalization.CultureInfo.KeyboardLayoutId"/>
/// then the <see cref="WpfImeKeyboardHandler"/> instance will be used, otherwise the older
/// <see cref="Internals.WpfKeyboardHandler"/> instance will be used.
/// Override to provide your own custom keyboard handler.
/// </summary>
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);
}
}

/// <summary>
/// Gets the ScreenInfo - currently used to get the DPI scale factor.
/// </summary>
Expand Down Expand Up @@ -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;
}
}

/// <summary>
/// PresentationSource changed handler.
/// </summary>
Expand Down Expand Up @@ -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()}");
}
}
}
}
22 changes: 21 additions & 1 deletion CefSharp.Wpf/Experimental/WpfIMEKeyboardHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ private void CreateImeWindow(IntPtr hwnd)
}
}

private int PrimaryLangId(int lgid)
private static int PrimaryLangId(int lgid)
{
return lgid & 0x3ff;
}
Expand Down Expand Up @@ -467,5 +467,25 @@ private FrameworkElement GetOutermostElement(FrameworkElement control)

return current as FrameworkElement;
}

/// <summary>
/// Based on the <paramref name="keyboardLayoutId"/> determine if we
/// should be using IME.
/// </summary>
/// <param name="keyboardLayoutId">Keyboard Layout Id (obtained from <see cref="System.Globalization.CultureInfo.KeyboardLayoutId"/>)</param>
/// <returns>
/// returns true if the keyboard layout matches one of our listed that support IME, otherwise false.
/// </returns>
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;
}
}
}