Skip to content

Add option to pause breaks when another app is in full screen#1781

Open
dkumankov wants to merge 3 commits into
hovancik:trunkfrom
dkumankov:feat/pause-on-fullscreen-app
Open

Add option to pause breaks when another app is in full screen#1781
dkumankov wants to merge 3 commits into
hovancik:trunkfrom
dkumankov:feat/pause-on-fullscreen-app

Conversation

@dkumankov
Copy link
Copy Markdown

Issue: #355

Requirements

  • issue was opened to discuss proposed changes before starting implementation. (See discussion in Full screen applications disable Stretchly #355; design proposal posted as comment before opening this PR.)
  • during development, node version specified in package.json was used (ie using nvm).
  • package versions and package-lock.json were not changed (npm install --no-save).
  • app version number was not changed.
  • all new code has tests to ensure against regressions.
  • npm run lint reports no offenses.
  • npm run test is error-free.
  • README and CHANGELOG were updated accordingly.
  • after PR is approved, all commits in it are squashed (will squash on approval)

Description of the Change

Adds an opt-in setting "Pause breaks while another app is in full screen" (monitorFullscreenApp, default false) under Settings, right below the existing "Show breaks even in Do Not Disturb mode" toggle.

When enabled, break scheduling is paused while another application is presenting in fullscreen, and resumes when fullscreen ends — symmetrical to how monitorDnd works today.

Architecture. A new FullscreenAppManager (app/utils/fullscreenAppManager.js) mirrors DndManager:

  • extends EventEmitter
  • interval polling (2s)
  • start() / stop() lifecycle
  • exposes isOnFullscreenApp boolean
  • emits fullscreenAppStarted / fullscreenAppFinished

BreaksPlanner constructs it, subscribes to its events, and exposes a fullscreenApp(shouldUse) method symmetrical to doNotDisturb(shouldUse). main.js adds isOnFullscreenApp to the existing guard expressions (onSuspendOrLock, trayIconPath, the two tray-menu branches, resumeBreaks) so the manager participates in all the same "is Stretchly currently suppressed" checks as DND and app exclusions.

Cross-platform detection — no new dependencies:

Platform Mechanism
Windows getFocusAssist() from the already-present windows-focus-assist (state 3 = D3D fullscreen, 4 = presentation mode) OR a persistent PowerShell worker that compares the foreground window's GetWindowRect to its monitor's rcMonitor — catches borderless-windowed games and browser F11 that the notification-state API alone reports as BUSY.
macOS osascript reading AXFullScreen of the frontmost window — same shell-out pattern as dndManager's macOS path.
Linux (X11) xdotool getactivewindow + xprop _NET_WM_STATE looking for _NET_WM_STATE_FULLSCREEN.
Linux (Wayland) Graceful no-op (logged once at startup); no portable client API for inspecting other windows' fullscreen state.
Other Logs an "unsupported" notice once and returns false.

i18n strings added across all 49 locales that currently expose the preferences.settings namespace (5 incomplete locales — arz, bn, cy, eu, sr — fall back to English at runtime, matching Stretchly's existing pattern).

Verification Process

Automated

  • npm run lint — clean.
  • npm run test — passes, including 8 new unit tests in test/fullscreenAppManager.js covering: default-off state, start()/stop() lifecycle, start() idempotency, rising-edge / falling-edge emission, _detectFullscreen no-op when disabled, log-once behavior on detection errors.
  • Locale JSON validation (test/translations.js) — all 54 files valid.

Manual (Windows 11)

Action Expected Observed
Enable monitorFullscreenApp in Preferences log shows starting fullscreen app monitoring
Open a borderless-fullscreen app (Crimson Desert) log shows pausing breaks because a fullscreen app is active within ~2 s; tray icon switches to paused style
Exit the fullscreen app log shows resuming breaks after fullscreen app is no longer active; tray icon returns to normal
Start a Stretchly break while the setting is on, with a fullscreen app already open break still shows; fullscreen-app handler bails because scheduler.reference === 'finishBreak'
Toggle the setting off while a fullscreen app is active manager stops polling; planner resumes (mirrors doNotDisturb(false))

Regression checks: the existing DND / app-exclusion / suspend-lock paths continue to behave the same way — all guards that previously read isPaused || isOnDnd || isSchedulerCleared now additionally include isOnFullscreenApp, but the OR-of-booleans is purely additive.

Other information

  • The persistent PowerShell worker is only spawned on Windows when the setting is enabled; it's terminated by stop(). No process is created at all on macOS/Linux.
  • The two-signal detection on Windows (SHQueryUserNotificationState OR bounds-equals-monitor) was added after observing that modern games like Crimson Desert run in borderless-windowed mode rather than exclusive D3D fullscreen, so the notification-state API alone misses them.
  • Open to switching to the "0-fullscreen"-token-inside-appExclusions design you sketched in issue #355's 2023 comment if you prefer that integration; the manager itself stays the same, only the wiring changes.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 25, 2026

Codecov Report

❌ Patch coverage is 43.80165% with 68 lines in your changes missing coverage. Please review.
✅ Project coverage is 62.83%. Comparing base (5372a0c) to head (5ab322c).
⚠️ Report is 19 commits behind head on trunk.

Files with missing lines Patch % Lines
app/utils/fullscreenAppManager.js 43.80% 68 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##            trunk    #1781      +/-   ##
==========================================
- Coverage   68.21%   62.83%   -5.38%     
==========================================
  Files          15       17       +2     
  Lines         494      627     +133     
==========================================
+ Hits          337      394      +57     
- Misses        157      233      +76     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread app/utils/fullscreenAppManager.js Outdated
dkumankov and others added 2 commits May 26, 2026 09:32
Replaces inline PowerShell + Add-Type C# fullscreen detection with the
windows-notification-state native addon (same author as windows-focus-assist
already used here for DND).

Also match QUNS_BUSY (2) alongside QUNS_RUNNING_D3D_FULL_SCREEN (3) and
QUNS_PRESENTATION_MODE (4) — empirically what modern Windows returns for
Chrome F11, fullscreen video and most games.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants