Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of LayoutSwitchFocusFix v0.1.4
plugins/LayoutSwitchFocusFix.dll
Decompiled 4 days agousing System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.InputSystem; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("assembly_valheim")] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("LayoutSwitchFocusFix")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+355e16e810537e0a9c0b997378bcb685bb9b78c1")] [assembly: AssemblyProduct("LayoutSwitchFocusFix")] [assembly: AssemblyTitle("LayoutSwitchFocusFix")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace LayoutSwitchFocusFix { [HarmonyPatch] internal static class Diagnostics { public static void Init() { InputSystem.onDeviceChange += delegate(InputDevice device, InputDeviceChange change) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (Plugin.DebugLog.Value) { Keyboard val = (Keyboard)(object)((device is Keyboard) ? device : null); if (val != null) { Plugin.Log.LogInfo((object)$"keyboard {change}: layout '{val.keyboardLayout}', frame {Time.frameCount}"); } } }; } [HarmonyPrefix] [HarmonyPatch(typeof(TMP_InputField), "DeactivateInputField")] private static void Deactivate(TMP_InputField __instance) { if (Plugin.DebugLog.Value && __instance.isFocused) { Plugin.Log.LogInfo((object)$"DeactivateInputField {Path((Component)(object)__instance)}, frame {Time.frameCount}: {Stack()}"); } } [HarmonyPrefix] [HarmonyPatch(typeof(TMP_InputField), "OnDeselect")] private static void Deselect(TMP_InputField __instance) { if (Plugin.DebugLog.Value && __instance.isFocused) { Plugin.Log.LogInfo((object)$"OnDeselect {Path((Component)(object)__instance)}, frame {Time.frameCount}: {Stack()}"); } } public static string Path(Component c) { if ((Object)(object)c == (Object)null) { return "(gone)"; } Transform val = c.transform; string text = ((Object)val).name; for (int i = 0; i < 3; i++) { if (!((Object)(object)val.parent != (Object)null)) { break; } val = val.parent; text = ((Object)val).name + "/" + text; } return text; } private static string Stack() { StringBuilder stringBuilder = new StringBuilder(); StackFrame[] array = new StackTrace(2, fNeedFileInfo: false).GetFrames(); int num = 0; if (array == null) { array = new StackFrame[0]; } StackFrame[] array2 = array; for (int i = 0; i < array2.Length; i++) { MethodBase method = array2[i].GetMethod(); if (!(method == null)) { if (num++ > 0) { stringBuilder.Append(" < "); } stringBuilder.Append((method.DeclaringType != null) ? (method.DeclaringType.Name + ".") : "").Append(method.Name); if (num == 12) { break; } } } return stringBuilder.ToString(); } } [HarmonyPatch(typeof(BuildUi), "OnLayoutChanged")] internal static class KeepFocus { public static int Kept { get; private set; } private static bool Prefix(BuildUi __instance) { if (!Plugin.Enabled.Value || ZInput.IsGamepadActive()) { return true; } EventSystem current = EventSystem.current; GameObject val = (((Object)(object)current != (Object)null) ? current.currentSelectedGameObject : null); TMP_InputField val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<TMP_InputField>() : null); if ((Object)(object)val2 == (Object)null || !val2.isFocused) { return true; } if ((Object)(object)__instance.m_favoritesDropdown != (Object)null) { __instance.m_favoritesDropdown.Close(); } Kept++; if (Plugin.DebugLog.Value) { Plugin.Log.LogInfo((object)$"kept focus on {Diagnostics.Path((Component)(object)val2)} through an input layout change, frame {Time.frameCount}"); } return false; } } [BepInPlugin("rgeraskin.LayoutSwitchFocusFix", "LayoutSwitchFocusFix", "0.1.4")] public class Plugin : BaseUnityPlugin { public const string Guid = "rgeraskin.LayoutSwitchFocusFix"; public const string Name = "LayoutSwitchFocusFix"; public const string Version = "0.1.4"; internal static ManualLogSource Log; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> DebugLog; private void Awake() { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Keep keyboard focus in the text field you're typing in when you switch the keyboard layout."); DebugLog = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Log", false, "Log keyboard layout changes and every focus loss of a text field with what caused it (a short stack trace), for bug reports."); Harmony val = new Harmony("rgeraskin.LayoutSwitchFocusFix"); val.PatchAll(typeof(KeepFocus)); val.PatchAll(typeof(Diagnostics)); Diagnostics.Init(); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }