diff --git a/docs/point-scan.md b/docs/point-scan.md
index 7a0ea5fe..82e6aaa1 100644
--- a/docs/point-scan.md
+++ b/docs/point-scan.md
@@ -2,15 +2,15 @@
Point scan ports the Android line-only and grid-then-line techniques to Switchify PC. The reference source is `switchifyapp/switchify-android` commit `856720d8747e2f3d1724a572bf754ffae05df299`, especially `PointScanLineManager`, `PointScanBlockManager`, and `ContinuousLineSpeedUtils`.
-Open **Settings → Switches** to add named keyboard switches and assign normal and hold actions. Then enable scanning in **Settings → Scanning**. Fresh installs have no assignments; old point-scan keys migrate once. See [switch assignments](switches.md). Scanning stays off at startup.
+Open **Settings → Switches** to add named keyboard switches and assign normal and hold actions. There is no on/off control: scanning is armed whenever the saved switches cover the current mode (Select for automatic scanning; Select, Next and Previous for manual) and the environment allows it. The runtime re-arms after a save, after key learning, after Escape, when an Android session ends, and retries a failed key reservation every two seconds. Fresh installs have no assignments; old point-scan keys migrate once. See [switch assignments](switches.md). Scanning arms at startup, so assigned keys are reserved from launch.
Focus the intended application and press Select to start. Line mode chooses X, then Y, and clicks once. Grid mode chooses a row, then a cell, before the same line sequence. Selecting happens on switch release; holding any switch freezes the position and repeat keydowns do not select again. The scan resets after a click and waits for the next Select. Movement wraps at the selected region's edges. Automatic movement stops after three full passes of the current phase without a selection; the scan resets and waits for the next Select. Manual steps never trigger this limit, and each Select starts a fresh count for the next phase. Android's five speeds are 45, 75, 120, 180, and 270 logical units per second, with delayed ticks capped at 250 ms.
The scan uses the monitor under the pointer when it starts. Windows uses native physical coordinates and display scaling; macOS uses Core Graphics display units and converts overlay rectangles to AppKit coordinates. A monitor geometry change cancels scanning. Native overlay strips are topmost, click-through, and nonactivating. The pointer moves only for the final click.
-This first port uses switches attached to the computer. Android must be disconnected before enabling it, and an Android connection cancels local scanning. Existing authenticated Bluetooth commands and switch-forwarding profiles are unchanged. Input permission is still required on macOS. Point settings use a separate `point-scan.json` in the existing Tauri application configuration directory, so old settings and pairing schemas remain unchanged.
+This first port uses switches attached to the computer. An Android connection pauses local scanning, which resumes when the connection ends. Existing authenticated Bluetooth commands and switch-forwarding profiles are unchanged. Input permission is still required on macOS. Point settings use a separate `point-scan.json` in the existing Tauri application configuration directory, so old settings and pairing schemas remain unchanged.
-Changes save automatically, including when you leave Settings. Enabling waits for pending saves; a failed save keeps your edits and offers Retry save. Configuration is locked while scanning is enabled. Navigating away does not stop scanning.
+Changes save automatically, including when you leave Settings, and apply straight away: saving pauses scanning and the runtime re-arms it with the new settings. A failed save keeps your edits and offers Retry save. Navigating away does not stop scanning.
The engine is independent of OS input. Activation uses the existing `InputInjector` adapter. Automated tests use a fake adapter and never move the real pointer. Switchify's local `switch_input` adapter supplies press/release events on both platforms. See `switches.md` for Windows capture limitations. Only the main window can configure scanning through IPC.
diff --git a/docs/switches.md b/docs/switches.md
index 3d0d27d8..ec7033ad 100644
--- a/docs/switches.md
+++ b/docs/switches.md
@@ -1,16 +1,16 @@
# Switch assignments
-In Settings → Switches, each switch is a row showing its name, key and actions; Edit expands it. Add switch starts learning immediately: press and release the physical key, then enter a name and choose actions, then save. Learning can also be restarted from Change key. Assign Select, Next, Previous, Reverse direction, Stop scanning or Pause / resume. Each key belongs to one switch; several switches can run the same action. Existing assignments save automatically. Disable scanning before editing. While learning, a modal dialog holds keyboard focus and swallows key events so a switch press cannot scroll Settings or activate a button; Cancel capture is mouse-only and Escape cancels through the backend. Learning ends when Settings loses focus, the panel closes, or Escape is pressed.
+In Settings → Switches, each switch is a row showing its name, key and actions; Edit expands it. Add switch starts learning immediately: press and release the physical key, then enter a name and choose actions, then save. Learning can also be restarted from Change key. Assign Select, Next, Previous, Reverse direction, Stop scanning or Pause / resume. Each key belongs to one switch; several switches can run the same action. Existing assignments save automatically and apply straight away; saving or learning pauses scanning until it finishes. While learning, a modal dialog holds keyboard focus and swallows key events so a switch press cannot scroll Settings or activate a button; Cancel capture is mouse-only and Escape cancels through the backend. Learning ends when Settings loses focus, the panel closes, or Escape is pressed.
The normal action runs on release. Hold actions are offered in their configured order. The interval defaults to 1 second and accepts 250–5000 milliseconds; five presets are shown and the rest sit behind an exact-interval select. The editor shows the time at which each hold action is offered. Each interval offers the next action in a nonactivating desktop prompt; the last remains selected. Release executes only the offered action. Movement freezes while any switch is held. The first pressed switch owns the gesture; overlapping presses do not activate additional actions.
-Stop resets the scan but leaves switches enabled. Select starts again. Pause preserves position. Reverse changes direction without stepping. Automatic scanning requires Select; manual scanning also requires Next and Previous. Hold assignments count toward those requirements.
+Stop resets the scan and leaves the keys reserved. Select starts again. Pause preserves position. Reverse changes direction without stepping. Automatic scanning requires Select; manual scanning also requires Next and Previous. Hold assignments count toward those requirements.
-Escape disables capture immediately. The emergency hold timeout is at least 4 seconds and extends to (longest hold list + 2) × interval when hold actions exist. Settings shows the resulting duration. Heartbeat loss, capture failure, overflow, Android connection and shutdown cancel gestures without executing release actions.
+Escape and the emergency hold reset the scan and release the keys; the runtime re-arms them on its next tick. The emergency hold timeout is at least 4 seconds and extends to (longest hold list + 2) × interval when hold actions exist. Settings shows the resulting duration. Heartbeat loss, capture failure, overflow, Android connection and shutdown cancel gestures without executing release actions.
## Storage and integration
-The separate switch-settings.json uses schema version 1. Existing point-scan keys migrate once into four named assignments with empty hold lists. Fresh installs persist an empty list. Malformed or unsupported settings are reported without overwriting them. Saves use atomic replacement. Scanning stays off at startup.
+The separate switch-settings.json uses schema version 1. Existing point-scan keys migrate once into four named assignments with empty hold lists. Fresh installs persist an empty list. Malformed or unsupported settings are reported without overwriting them. Saves use atomic replacement. Scanning arms at startup whenever the saved switches allow.
Existing point-scan commands and event fields remain compatible for geometry and automatic mode. Legacy key fields remain readable; changing them is rejected with a direction to Settings → Switches. New settings and learning commands are restricted to the main window capability and check its label. On Windows the learning command checks that the main window is the foreground window rather than tao's focus flag, which turns false once keyboard focus moves into the WebView2 child.
diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs
index 6148a35a..23d6784d 100644
--- a/src-tauri/src/lib.rs
+++ b/src-tauri/src/lib.rs
@@ -209,8 +209,8 @@ pub(crate) fn sync_tray_state(app: &AppHandle, state: &AppState) {
}
fn finish_app_exit(app: &AppHandle) {
+ scanning_runtime::halt(app);
app.state::
- Switch keys are reserved while enabled. Escape stops scanning and - releases them. Disconnect Android before enabling local point scan. + Scanning is on whenever a switch has the Select action, and its keys + stay reserved while Switchify runs. Escape resets the scan. Android + connections pause local scanning until they end.
On Windows, use switch keys without Shift, Ctrl, Alt or Windows held. @@ -60,18 +51,6 @@ export function ScanningSection({ : (state?.message ?? "Loading point scan...")}
- -
{pending
? "Saving scanning settings..."
@@ -118,7 +97,7 @@ export function ScanningSection({
Settings are saved, but scanning stays off when the app restarts. Settings are saved and scanning resumes when the app restarts.