Skip to content

Commit e1865d9

Browse files
authored
WPF - Use WpfImeKeyboardHandler for supported KeyboardLayoutIds (#4439)
* WPF - Use WpfImeKeyboardHandler for supported KeyboardLayoutIds --------- Co-authored-by: amaitland <[email protected]>
1 parent c565f50 commit e1865d9

File tree

2 files changed

+118
-2
lines changed

2 files changed

+118
-2
lines changed

CefSharp.Wpf/ChromiumWebBrowser.cs

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
44

55
using System;
6+
using System.Diagnostics;
67
using System.Runtime.CompilerServices;
78
using System.Threading;
89
using System.Threading.Tasks;
@@ -604,7 +605,12 @@ private void NoInliningConstructor()
604605

605606
browserSettings = Core.ObjectFactory.CreateBrowserSettings(autoDispose: true);
606607

607-
WpfKeyboardHandler = new WpfKeyboardHandler(this);
608+
SetupWpfKeyboardHandler();
609+
610+
if (WpfKeyboardHandler == null)
611+
{
612+
WpfKeyboardHandler = new WpfKeyboardHandler(this);
613+
}
608614

609615
PresentationSource.AddSourceChangedHandler(this, PresentationSourceChangedHandler);
610616

@@ -753,6 +759,8 @@ private void InternalDispose(bool disposing)
753759
// is called.
754760
LifeSpanHandler = null;
755761

762+
UnsubscribeInputLanguageChanged();
763+
756764
WpfKeyboardHandler?.Dispose();
757765
WpfKeyboardHandler = null;
758766

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

780+
/// <summary>
781+
/// Setup the <see cref="WpfKeyboardHandler"/> used by this <see cref="ChromiumWebBrowser"/> instance.
782+
/// There are two main keyboard handler implementations currently <see cref="WpfImeKeyboardHandler"/>
783+
/// and <see cref="Internals.WpfKeyboardHandler"/>. If <see cref="WpfImeKeyboardHandler.UseImeKeyboardHandler"/>
784+
/// returns true for the current <see cref="System.Globalization.CultureInfo.KeyboardLayoutId"/>
785+
/// then the <see cref="WpfImeKeyboardHandler"/> instance will be used, otherwise the older
786+
/// <see cref="Internals.WpfKeyboardHandler"/> instance will be used.
787+
/// Override to provide your own custom keyboard handler.
788+
/// </summary>
789+
protected virtual void SetupWpfKeyboardHandler()
790+
{
791+
try
792+
{
793+
var inputLang = InputLanguageManager.Current.CurrentInputLanguage;
794+
795+
var useImeKeyboardHandler = WpfImeKeyboardHandler.UseImeKeyboardHandler(inputLang.KeyboardLayoutId);
796+
797+
if (useImeKeyboardHandler)
798+
{
799+
WpfKeyboardHandler = new WpfImeKeyboardHandler(this);
800+
}
801+
else
802+
{
803+
InputLanguageManager.Current.InputLanguageChanged += OnInputLanguageChanged;
804+
805+
WpfKeyboardHandler = new WpfKeyboardHandler(this);
806+
}
807+
}
808+
catch (Exception ex)
809+
{
810+
//For now we'll ignore any errors
811+
Trace.TraceError($"Error initializing keyboard handler: {ex.ToString()}");
812+
813+
// For now we'll ignore any errors and just use the default keyboard handler
814+
WpfKeyboardHandler = new WpfKeyboardHandler(this);
815+
}
816+
}
817+
772818
/// <summary>
773819
/// Gets the ScreenInfo - currently used to get the DPI scale factor.
774820
/// </summary>
@@ -1750,6 +1796,26 @@ private void OnDragEnter(object sender, DragEventArgs e)
17501796
}
17511797
}
17521798

1799+
private void OnInputLanguageChanged(object sender, InputLanguageEventArgs e)
1800+
{
1801+
// If we are already using the WpfImeKeyboardHandler then we'll ignore any changes
1802+
if (WpfKeyboardHandler?.GetType() == typeof(WpfImeKeyboardHandler))
1803+
{
1804+
return;
1805+
}
1806+
1807+
var useImeKeyboardHandler = WpfImeKeyboardHandler.UseImeKeyboardHandler(e.NewLanguage.KeyboardLayoutId);
1808+
1809+
if (useImeKeyboardHandler)
1810+
{
1811+
var oldKeyboardHandler = WpfKeyboardHandler;
1812+
WpfKeyboardHandler = new WpfImeKeyboardHandler(this);
1813+
oldKeyboardHandler?.Dispose();
1814+
1815+
InputLanguageManager.Current.InputLanguageChanged -= OnInputLanguageChanged;
1816+
}
1817+
}
1818+
17531819
/// <summary>
17541820
/// PresentationSource changed handler.
17551821
/// </summary>
@@ -2858,5 +2924,35 @@ private async Task ResizeHackRun()
28582924
}
28592925
}
28602926
}
2927+
2928+
private void UnsubscribeInputLanguageChanged()
2929+
{
2930+
// If we are using WpfImeKeyboardHandler then we
2931+
// shouldn't need to unsubsribe from the handler
2932+
if (WpfKeyboardHandler?.GetType() == typeof(WpfImeKeyboardHandler))
2933+
{
2934+
return;
2935+
}
2936+
2937+
try
2938+
{
2939+
// Dispose can be called on non UI thread, InputLanguageManager.Current
2940+
// is thread specific
2941+
UiThreadRunAsync(() =>
2942+
{
2943+
var inputLangManager = InputLanguageManager.Current;
2944+
2945+
if (inputLangManager != null)
2946+
{
2947+
inputLangManager.InputLanguageChanged -= OnInputLanguageChanged;
2948+
}
2949+
});
2950+
}
2951+
catch (Exception ex)
2952+
{
2953+
//For now we'll ignore any errors
2954+
Trace.TraceError($"Error unsubscribing from InputLanguageChanged {ex.ToString()}");
2955+
}
2956+
}
28612957
}
28622958
}

CefSharp.Wpf/Experimental/WpfIMEKeyboardHandler.cs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ private void CreateImeWindow(IntPtr hwnd)
354354
}
355355
}
356356

357-
private int PrimaryLangId(int lgid)
357+
private static int PrimaryLangId(int lgid)
358358
{
359359
return lgid & 0x3ff;
360360
}
@@ -467,5 +467,25 @@ private FrameworkElement GetOutermostElement(FrameworkElement control)
467467

468468
return current as FrameworkElement;
469469
}
470+
471+
/// <summary>
472+
/// Based on the <paramref name="keyboardLayoutId"/> determine if we
473+
/// should be using IME.
474+
/// </summary>
475+
/// <param name="keyboardLayoutId">Keyboard Layout Id (obtained from <see cref="System.Globalization.CultureInfo.KeyboardLayoutId"/>)</param>
476+
/// <returns>
477+
/// returns true if the keyboard layout matches one of our listed that support IME, otherwise false.
478+
/// </returns>
479+
public static bool UseImeKeyboardHandler(int keyboardLayoutId)
480+
{
481+
var langId = PrimaryLangId(keyboardLayoutId);
482+
483+
if (langId == ImeNative.LANG_KOREAN || langId == ImeNative.LANG_JAPANESE || langId == ImeNative.LANG_CHINESE)
484+
{
485+
return true;
486+
}
487+
488+
return false;
489+
}
470490
}
471491
}

0 commit comments

Comments
 (0)