private LayoutName GetBestAvailableKeyboardName(InputLanguage inputLanguage) { try { var profilesEnumerator = ProfileManager.EnumProfiles((short)inputLanguage.Culture.KeyboardLayoutId); TfInputProcessorProfile[] profiles = new TfInputProcessorProfile[1]; while (profilesEnumerator.Next(1, profiles) == 1) { // We only deal with keyboards; skip other input methods if (profiles[0].CatId != Guids.Consts.TfcatTipKeyboard) { continue; } if ((profiles[0].Flags & TfIppFlags.Enabled) == 0) { continue; } if (profiles[0].Hkl == IntPtr.Zero && profiles[0].ProfileType != TfProfileType.Illegal) { return(new LayoutName(inputLanguage.LayoutName, ProcessorProfiles.GetLanguageProfileDescription(ref profiles[0].ClsId, profiles[0].LangId, ref profiles[0].GuidProfile))); } } } catch (Exception e) { Debug.WriteLine($"Error looking up keyboards for language {inputLanguage.Culture.Name} - {(short)inputLanguage.Culture.KeyboardLayoutId}"); } return(new LayoutName(inputLanguage.LayoutName, inputLanguage.Culture.DisplayName)); }
private IEnumerable <LayoutName> GetAvailableKeyboardNames(InputLanguage inputLanguage) { IEnumTfInputProcessorProfiles profilesEnumerator; try { profilesEnumerator = ProfileManager.EnumProfiles((short)inputLanguage.Culture.KeyboardLayoutId); } catch (Exception e) { Debug.WriteLine($"Error looking up keyboards for language {inputLanguage.Culture.Name} - {(short)inputLanguage.Culture.KeyboardLayoutId}"); yield break; } TfInputProcessorProfile[] profiles = new TfInputProcessorProfile[1]; bool returnedLanguage = false; while (profilesEnumerator.Next(1, profiles) == 1) { // We only deal with keyboards; skip other input methods if (profiles[0].CatId != Guids.Consts.TfcatTipKeyboard) { continue; } if ((profiles[0].Flags & TfIppFlags.Enabled) == 0) { continue; } if (profiles[0].ProfileType == TfProfileType.Illegal) { continue; } LayoutName layoutName; if (profiles[0].Hkl == IntPtr.Zero) { returnedLanguage = true; layoutName = new LayoutName(inputLanguage.LayoutName, ProcessorProfiles.GetLanguageProfileDescription(ref profiles[0].ClsId, profiles[0].LangId, ref profiles[0].GuidProfile), profiles[0]); yield return(layoutName); } else { layoutName = WinKeyboardUtils.GetLayoutNameEx(profiles[0].Hkl); if (layoutName.Name != string.Empty) { layoutName.Profile = profiles[0]; returnedLanguage = true; yield return(layoutName); } } } if (!returnedLanguage) { yield return(new LayoutName(inputLanguage.LayoutName, inputLanguage.Culture.DisplayName)); } }
private WinKeyboardDescription ActivateKeyboard(WinKeyboardDescription winKeyboard) { try { if (UseWindowsApiForKeyboardSwitching(winKeyboard)) { // Win XP with regular keyboard, or TSF disabled Win32.ActivateKeyboardLayout(new HandleRef(this, winKeyboard.InputLanguage.Handle), 0); return(winKeyboard); } var profile = winKeyboard.InputProcessorProfile; if ((profile.Flags & TfIppFlags.Enabled) == 0) { return(winKeyboard); } ProcessorProfiles.ChangeCurrentLanguage(profile.LangId); if (ProfileMgr == null) { // Win XP with TIP (TSF Input Processor) ProcessorProfiles.ActivateLanguageProfile(ref profile.ClsId, profile.LangId, ref profile.GuidProfile); } else { // Windows >= Vista with either TIP or regular keyboard ProfileMgr.ActivateProfile(profile.ProfileType, profile.LangId, ref profile.ClsId, ref profile.GuidProfile, profile.Hkl, TfIppMf.DontCareCurrentInputLanguage); } } catch (ArgumentException) { // throws exception for non-supported culture, though seems to set it OK. } catch (COMException e) { var profile = winKeyboard.InputProcessorProfile; var msg = string.Format("Got COM exception trying to activate IM:" + Environment.NewLine + "LangId={0}, clsId={1}, hkl={2}, guidProfile={3}, flags={4}, type={5}, catId={6}", profile.LangId, profile.ClsId, profile.Hkl, profile.GuidProfile, profile.Flags, profile.ProfileType, profile.CatId); throw new ApplicationException(msg, e); } return(winKeyboard); }
private IEnumerable <LayoutName> GetAvailableKeyboardNames(InputLanguage inputLanguage) { IEnumTfInputProcessorProfiles profilesEnumerator; string cultureName; var culture = GetCultureInfoFromInputLanguage(inputLanguage, out cultureName); if (cultureName == UnknownLanguage) { Debug.WriteLine($"Error looking up keyboards with layout {inputLanguage.LayoutName} - invalid culture"); yield break; } try { profilesEnumerator = ProfileManager.EnumProfiles((short)culture.KeyboardLayoutId); } catch { Debug.WriteLine($"Error looking up keyboards for language {culture.Name} - {(short)culture.KeyboardLayoutId}"); yield break; } TfInputProcessorProfile[] profiles = new TfInputProcessorProfile[1]; bool returnedLanguage = false; while (profilesEnumerator.Next(1, profiles) == 1) { // We only deal with keyboards; skip other input methods if (profiles[0].CatId != Guids.Consts.TfcatTipKeyboard) { continue; } if ((profiles[0].Flags & TfIppFlags.Enabled) == 0) { continue; } if (profiles[0].ProfileType == TfProfileType.Illegal) { continue; } LayoutName layoutName; if (profiles[0].Hkl == IntPtr.Zero) { try { layoutName = new LayoutName(inputLanguage.LayoutName, ProcessorProfiles.GetLanguageProfileDescription(ref profiles[0].ClsId, profiles[0].LangId, ref profiles[0].GuidProfile), profiles[0]); } catch { // this exception has happened in testing, doesn't seem to be anything we can do // except just ignore this keyboard continue; } returnedLanguage = true; yield return(layoutName); } else { layoutName = WinKeyboardUtils.GetLayoutNameEx(profiles[0].Hkl); if (layoutName.Name != string.Empty) { layoutName.Profile = profiles[0]; returnedLanguage = true; yield return(layoutName); } } } if (!returnedLanguage) { yield return(new LayoutName(inputLanguage.LayoutName, culture.DisplayName)); } }
private void GetInputMethods() { IEnumerable <Tuple <TfInputProcessorProfile, ushort, IntPtr> > imes; if (ProfileMgr != null) { // Windows >= Vista imes = GetInputMethodsThroughTsf(); } else { // Windows XP imes = GetInputMethodsThroughWinApi(); } var allKeyboards = KeyboardController.Instance.Keyboards; Dictionary <string, WinKeyboardDescription> curKeyboards = allKeyboards.OfType <WinKeyboardDescription>().ToDictionary(kd => kd.Id); foreach (Tuple <TfInputProcessorProfile, ushort, IntPtr> ime in imes) { TfInputProcessorProfile profile = ime.Item1; ushort langId = ime.Item2; IntPtr hkl = ime.Item3; CultureInfo culture; string locale; string cultureName; try { culture = new CultureInfo(langId); cultureName = culture.DisplayName; locale = culture.Name; } catch (CultureNotFoundException) { // This can happen for old versions of Keyman that created a custom culture that is invalid to .Net. // Also see http://stackoverflow.com/a/24820530/4953232 culture = new CultureInfo("en-US"); cultureName = "[Unknown Language]"; locale = "en-US"; } try { LayoutName layoutName; if (profile.Hkl == IntPtr.Zero && profile.ProfileType != TfProfileType.Illegal) { layoutName = new LayoutName(ProcessorProfiles.GetLanguageProfileDescription( ref profile.ClsId, profile.LangId, ref profile.GuidProfile)); } else { layoutName = GetLayoutNameEx(hkl); } string id = GetId(layoutName.Name, locale); WinKeyboardDescription existingKeyboard; if (curKeyboards.TryGetValue(id, out existingKeyboard)) { if (!existingKeyboard.IsAvailable) { existingKeyboard.SetIsAvailable(true); existingKeyboard.InputProcessorProfile = profile; existingKeyboard.SetLocalizedName(GetDisplayName(layoutName.LocalizedName, cultureName)); } curKeyboards.Remove(id); } else { // Prevent a keyboard with this id from being registered again. // Potentially, id's are duplicated. e.g. A Keyman keyboard linked to a windows one. // For now we simply ignore this second registration. // A future enhancement would be to include knowledge of the driver in the Keyboard definition so // we could choose the best one to register. KeyboardDescription keyboard; if (!allKeyboards.TryGet(id, out keyboard)) { KeyboardController.Instance.Keyboards.Add( new WinKeyboardDescription(id, GetDisplayName(layoutName.Name, cultureName), layoutName.Name, locale, true, new InputLanguageWrapper(culture, hkl, layoutName.Name), this, GetDisplayName(layoutName.LocalizedName, cultureName), profile)); } } } catch (COMException) { // this can happen when the user changes the language associated with a // Keyman keyboard (LT-16172) } } foreach (WinKeyboardDescription existingKeyboard in curKeyboards.Values) { existingKeyboard.SetIsAvailable(false); } }