fix(launcher): retry activate in post-script loop to beat macOS focus-stealing

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 <noreply@anthropic.com>
This commit is contained in:
Scott Idem
2026-05-22 13:51:53 -04:00
parent 172ea994c7
commit 33e9eeef78

View File

@@ -63,14 +63,15 @@ function make_vlc_mirror_mac_profile(): LaunchProfile {
// Direct binary path ensures VLC receives media file + flags reliably. // Direct binary path ensures VLC receives media file + flags reliably.
// `--no-play-and-exit` prevents closing on end, `--play-and-pause` holds final frame. // `--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}}"', open_cmd: '/Applications/VLC.app/Contents/MacOS/VLC --no-play-and-exit --play-and-pause "{{path}}"',
post_delay_ms: 1000, post_delay_ms: 2000,
// Poll until VLC is frontmost before sending Cmd+F. A fixed delay is unreliable because // Poll until VLC is frontmost before sending Cmd+F. Re-activate on every iteration —
// VLC cold-start on a loaded conference Mac can take 3-5 seconds. // a single activate at the top is blocked by macOS focus-stealing prevention when VLC
// Polling (15 × 0.5 s = up to 7.5 s after the initial wait) fires as soon as VLC is ready. // is spawned as a child of Electron (which stays frontmost). Retrying activate each loop
post_script: `tell application "VLC" // keeps nudging macOS until it yields focus. Max wait: 20 × 0.5s = 10s after initial delay.
activate post_script: `repeat 20 times
end tell tell application "VLC"
repeat 15 times activate
end tell
delay 0.5 delay 0.5
tell application "System Events" tell application "System Events"
if frontmost of process "VLC" is true then exit repeat if frontmost of process "VLC" is true then exit repeat
@@ -104,10 +105,10 @@ const POWERPOINT_MAC_EXTEND_PROFILE: LaunchProfile = {
display_mode: 'extend', display_mode: 'extend',
open_cmd: 'open -a "Microsoft PowerPoint" "{{path}}"', open_cmd: 'open -a "Microsoft PowerPoint" "{{path}}"',
post_delay_ms: 1000, post_delay_ms: 1000,
post_script: `tell application "Microsoft PowerPoint" post_script: `repeat 20 times
activate tell application "Microsoft PowerPoint"
end tell activate
repeat 15 times end tell
delay 0.5 delay 0.5
tell application "System Events" tell application "System Events"
if frontmost of process "Microsoft PowerPoint" is true then exit repeat if frontmost of process "Microsoft PowerPoint" is true then exit repeat
@@ -148,10 +149,10 @@ const LIBREOFFICE_MAC_EXTEND_PROFILE: LaunchProfile = {
display_mode: 'extend', display_mode: 'extend',
open_cmd: 'open -a "LibreOffice" "{{path}}"', open_cmd: 'open -a "LibreOffice" "{{path}}"',
post_delay_ms: 1000, post_delay_ms: 1000,
post_script: `tell application "LibreOffice" post_script: `repeat 20 times
activate tell application "LibreOffice"
end tell activate
repeat 15 times end tell
delay 0.5 delay 0.5
tell application "System Events" tell application "System Events"
if frontmost of process "soffice" is true then exit repeat if frontmost of process "soffice" is true then exit repeat
@@ -170,10 +171,10 @@ const ACROBAT_MAC_MIRROR_PROFILE: LaunchProfile = {
display_mode: 'mirror', display_mode: 'mirror',
open_cmd: 'open -a "Adobe Acrobat Reader DC" "{{path}}"', open_cmd: 'open -a "Adobe Acrobat Reader DC" "{{path}}"',
post_delay_ms: 1000, post_delay_ms: 1000,
post_script: `tell application "Adobe Acrobat Reader DC" post_script: `repeat 20 times
activate tell application "Adobe Acrobat Reader DC"
end tell activate
repeat 15 times end tell
delay 0.5 delay 0.5
tell application "System Events" tell application "System Events"
if frontmost of process "AdobeReader" is true then exit repeat if frontmost of process "AdobeReader" is true then exit repeat
@@ -215,10 +216,10 @@ const LIBREOFFICE_WIN_EXTEND_PROFILE: LaunchProfile = {
display_mode: 'extend', display_mode: 'extend',
open_cmd: 'open -a "LibreOffice" "{{path}}"', open_cmd: 'open -a "LibreOffice" "{{path}}"',
post_delay_ms: 1500, post_delay_ms: 1500,
post_script: `tell application "LibreOffice" post_script: `repeat 20 times
activate tell application "LibreOffice"
end tell activate
repeat 15 times end tell
delay 0.5 delay 0.5
tell application "System Events" tell application "System Events"
if frontmost of process "soffice" is true then exit repeat if frontmost of process "soffice" is true then exit repeat
@@ -237,10 +238,10 @@ const ACROBAT_WIN_MIRROR_PROFILE: LaunchProfile = {
display_mode: 'mirror', display_mode: 'mirror',
open_cmd: 'open -a "Acrobat Reader Windows" "{{path}}"', open_cmd: 'open -a "Acrobat Reader Windows" "{{path}}"',
post_delay_ms: 1500, post_delay_ms: 1500,
post_script: `tell application "Acrobat Reader Windows" post_script: `repeat 20 times
activate tell application "Acrobat Reader Windows"
end tell activate
repeat 15 times end tell
delay 0.5 delay 0.5
tell application "System Events" tell application "System Events"
if frontmost of process "Acrobat Reader Windows" is true then exit repeat if frontmost of process "Acrobat Reader Windows" is true then exit repeat