using System.Runtime.InteropServices; namespace CursorLang.Core.Services; /// /// Tells the agent that settings.json has changed. /// /// /// The message carries nothing but the fact. The temptation to send the changed values /// along has to be resisted: the file would stop being the only source of truth, and /// the two would part company the first time somebody edits it by hand. Nothing else /// tells the agent — it does not watch the file — so a message that goes missing means /// settings it does not pick up until it is restarted. /// /// Order is what makes it safe. The settings window writes the file whole, moves it /// into place in one step and only then signals, so by the time the agent reads there /// is nothing half-written to read. /// /// A registered message rather than WM_APP + n: the identifier is unique across /// the system, so it cannot be confused with anything else that finds its way to that /// window. /// internal static class SettingsSignal { /// The window class the agent registers for its hidden window. internal const string AgentWindowClass = "CursorLang.Agent.Window"; /// The message both sides agree on. internal static uint Message { get; } = RegisterWindowMessage("CursorLang.SettingsChanged"); /// /// Wakes the agent, if one is running in this session. Silence is a normal /// answer: the settings window is perfectly usable with no agent behind it. /// internal static void NotifyAgent() { IntPtr agent = FindWindow(AgentWindowClass, null); if (agent != IntPtr.Zero) { PostMessage(agent, Message, IntPtr.Zero, IntPtr.Zero); } } [DllImport("user32.dll", CharSet = CharSet.Unicode, EntryPoint = "RegisterWindowMessageW")] private static extern uint RegisterWindowMessage(string lpString); [DllImport("user32.dll", CharSet = CharSet.Unicode, EntryPoint = "FindWindowW")] private static extern IntPtr FindWindow(string lpClassName, string? lpWindowName); [DllImport("user32.dll", CharSet = CharSet.Unicode, EntryPoint = "PostMessageW")] private static extern bool PostMessage(IntPtr hWnd, uint message, IntPtr wParam, IntPtr lParam); }