| 1255 | |
| 1256 | |
| 1257 | bool Script::IsPersistent() |
| 1258 | { |
| 1259 | // Consider the script "persistent" if any of the following conditions are true: |
| 1260 | if (Hotkey::sHotkeyCount || Hotstring::sHotstringCount // At least one hotkey or hotstring exists. |
| 1261 | // No attempt is made to determine if the hotkeys/hotstrings are enabled, since even if they |
| 1262 | // are, it's impossible to detect whether #HotIf will allow them to ever execute. |
| 1263 | || g_persistent // Persistent() has been used somewhere in the script. |
| 1264 | || g_script.mTimerEnabledCount // At least one script timer is currently enabled. |
| 1265 | || mOnClipboardChange.Count() // The script is monitoring clipboard changes. |
| 1266 | || g_input // At least one active InputHook. |
| 1267 | || IsWindowVisible(g_hWnd)) |
| 1268 | return true; |
| 1269 | // OnMessage does not make the script persistent because: |
| 1270 | // 1) It has too many uses to assume that the author would want the script to be persistent |
| 1271 | // (which would probably only be in cases where OnMessage is the main purpose of the script, |
| 1272 | // such as if it just idles until a command is received via WM_COPYDATA or other message). |
| 1273 | // 2) It's often used in conjunction with a GUI, and in such cases it's probably more convenient |
| 1274 | // to rely on other logic to keep the script running while the GUI is visible, and allow it to |
| 1275 | // exit when the GUI is closed. |
| 1276 | // 3) Message monitors that are intended to keep the script running probably won't be removed, |
| 1277 | // so checking the number of active monitors here at runtime doesn't offer much benefit vs. |
| 1278 | // requiring the script to call Persistent() if needed. |
| 1279 | // 4) The only alternatives to OnMessage are generally window subclassing and hooks, which come |
| 1280 | // with various problems, such as spamming ListLines, interacting badly with Pause/A_IsPaused |
| 1281 | // (due to thread-starting messages passing through the window proc), and others. |
| 1282 | // Adding custom items to A_TrayMenu does not make the script persistent because: |
| 1283 | // 1) It could be something like a slight modification to a standard item's behaviour, |
| 1284 | // or something else that isn't intended to keep the script running. |
| 1285 | // 2) Custom items usually aren't removed, so having checks for them at runtime is not as helpful |
| 1286 | // as some of the conditions above, like timers and visible windows. When they are removed, it |
| 1287 | // is always a direct action of the code, not some external event. |
| 1288 | // 3) If adding custom items made the script persistent, it can be worked around by intercepting |
| 1289 | // right-clicks on the tray icon and showing some other menu, but replicating the Pause/Suspend |
| 1290 | // checkmarks and AddStandard() behaviour is surprisingly complicated. By contrast, calling |
| 1291 | // Persistent() before/after adding the custom items is trivial. |
| 1292 | for (GuiType* gui = g_firstGui; gui; gui = gui->mNextGui) |
| 1293 | if (IsWindowVisible(gui->mHwnd)) // A GUI is visible. |
| 1294 | return true; |
| 1295 | // Otherwise, none of the above conditions are true; but there might still be |
| 1296 | // one or more script threads running. Caller is responsible for checking that. |
| 1297 | return false; |
| 1298 | } |
| 1299 | |
| 1300 | |
| 1301 | |