33// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
44
55using System ;
6+ using System . Diagnostics ;
67using System . Runtime . CompilerServices ;
78using System . Threading ;
89using 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}
0 commit comments