From 33e9eeef784c85009e7867c5497181304554ce4c Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Fri, 22 May 2026 13:51:53 -0400 Subject: [PATCH] fix(launcher): retry activate in post-script loop to beat macOS focus-stealing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All app post-scripts called activate once before the poll loop, then only checked `frontmost` passively. When Electron retains focus (common when the app is spawned via run_cmd), macOS focus-stealing prevention blocks the one- shot activate and VLC/PowerPoint/etc. never come to front. The poll loop times out and fires the keystroke at Electron instead. Fix: move activate inside the repeat loop so it re-fires every 0.5s until macOS yields focus. Also bumped VLC post_delay_ms 1000→2000 and iterations 15→20 for slow conference machines. Affected profiles: VLC (mac), PowerPoint (mac), LibreOffice (mac+win), Acrobat (mac+win). Co-Authored-By: Claude Sonnet 4.6 --- .../ae_launcher__default_launch_profiles.ts | 57 ++++++++++--------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/src/lib/ae_events/ae_launcher__default_launch_profiles.ts b/src/lib/ae_events/ae_launcher__default_launch_profiles.ts index d488225d..0b8a2f8c 100644 --- a/src/lib/ae_events/ae_launcher__default_launch_profiles.ts +++ b/src/lib/ae_events/ae_launcher__default_launch_profiles.ts @@ -63,14 +63,15 @@ function make_vlc_mirror_mac_profile(): LaunchProfile { // Direct binary path ensures VLC receives media file + flags reliably. // `--no-play-and-exit` prevents closing on end, `--play-and-pause` holds final frame. open_cmd: '/Applications/VLC.app/Contents/MacOS/VLC --no-play-and-exit --play-and-pause "{{path}}"', - post_delay_ms: 1000, - // Poll until VLC is frontmost before sending Cmd+F. A fixed delay is unreliable because - // VLC cold-start on a loaded conference Mac can take 3-5 seconds. - // Polling (15 × 0.5 s = up to 7.5 s after the initial wait) fires as soon as VLC is ready. - post_script: `tell application "VLC" - activate -end tell -repeat 15 times + post_delay_ms: 2000, + // Poll until VLC is frontmost before sending Cmd+F. Re-activate on every iteration — + // a single activate at the top is blocked by macOS focus-stealing prevention when VLC + // is spawned as a child of Electron (which stays frontmost). Retrying activate each loop + // keeps nudging macOS until it yields focus. Max wait: 20 × 0.5s = 10s after initial delay. + post_script: `repeat 20 times + tell application "VLC" + activate + end tell delay 0.5 tell application "System Events" if frontmost of process "VLC" is true then exit repeat @@ -104,10 +105,10 @@ const POWERPOINT_MAC_EXTEND_PROFILE: LaunchProfile = { display_mode: 'extend', open_cmd: 'open -a "Microsoft PowerPoint" "{{path}}"', post_delay_ms: 1000, - post_script: `tell application "Microsoft PowerPoint" - activate -end tell -repeat 15 times + post_script: `repeat 20 times + tell application "Microsoft PowerPoint" + activate + end tell delay 0.5 tell application "System Events" if frontmost of process "Microsoft PowerPoint" is true then exit repeat @@ -148,10 +149,10 @@ const LIBREOFFICE_MAC_EXTEND_PROFILE: LaunchProfile = { display_mode: 'extend', open_cmd: 'open -a "LibreOffice" "{{path}}"', post_delay_ms: 1000, - post_script: `tell application "LibreOffice" - activate -end tell -repeat 15 times + post_script: `repeat 20 times + tell application "LibreOffice" + activate + end tell delay 0.5 tell application "System Events" if frontmost of process "soffice" is true then exit repeat @@ -170,10 +171,10 @@ const ACROBAT_MAC_MIRROR_PROFILE: LaunchProfile = { display_mode: 'mirror', open_cmd: 'open -a "Adobe Acrobat Reader DC" "{{path}}"', post_delay_ms: 1000, - post_script: `tell application "Adobe Acrobat Reader DC" - activate -end tell -repeat 15 times + post_script: `repeat 20 times + tell application "Adobe Acrobat Reader DC" + activate + end tell delay 0.5 tell application "System Events" if frontmost of process "AdobeReader" is true then exit repeat @@ -215,10 +216,10 @@ const LIBREOFFICE_WIN_EXTEND_PROFILE: LaunchProfile = { display_mode: 'extend', open_cmd: 'open -a "LibreOffice" "{{path}}"', post_delay_ms: 1500, - post_script: `tell application "LibreOffice" - activate -end tell -repeat 15 times + post_script: `repeat 20 times + tell application "LibreOffice" + activate + end tell delay 0.5 tell application "System Events" if frontmost of process "soffice" is true then exit repeat @@ -237,10 +238,10 @@ const ACROBAT_WIN_MIRROR_PROFILE: LaunchProfile = { display_mode: 'mirror', open_cmd: 'open -a "Acrobat Reader Windows" "{{path}}"', post_delay_ms: 1500, - post_script: `tell application "Acrobat Reader Windows" - activate -end tell -repeat 15 times + post_script: `repeat 20 times + tell application "Acrobat Reader Windows" + activate + end tell delay 0.5 tell application "System Events" if frontmost of process "Acrobat Reader Windows" is true then exit repeat