electron: "backgroundThrottling: false" no longer affects requestAnimationFrame() in background applications

  • Electron version: 1.5.0 thru 8.0.0
  • Operating system: Mac OS Sierra 10.12.4, El Capitan 10.11.6, 11.2.3 Mac OS Big Sur

Expected behavior

Disabling background throttling should prevent the slowdowns/pausing of both animation frames and intervals/timeouts when the window is in the background.

For instance,

  mainWindow = new BrowserWindow({
   ...
    webPreferences: {
      pageVisibility: true,
      backgroundThrottling: false,
    },
    ...
  })

… should allow RAF to run without getting stopped or otherwise throttled when the window is in the background (minimized or completely obscured by other windows). Behavior specific to RAF on this issue was added in 0.37.6 (https://github.com/electron/electron/issues/4925)

Actual behavior

Behavior that depends on RAF calls will slow to a crawl when the window becomes obscured by other windows or is otherwise made a “background” window, behaving no differently whether backgroundThrottling is set to true or false. It reverts to normal behavior as soon as it becomes a foreground window again.

How to reproduce

Easiest to just use the test repo I put together.

git clone https://github.com/stickywes/test-electron-background-throttle.git
npm install
npm start

Workaround(s)

Use an older version of electron.

Versions below 1.5.0, such as 1.4.16, do not have this issue. The regression on this issue appears to begin with 1.5.0 onward.

Use setInterval()

westoncbb says: “setInterval() does work in the background with backgroundThrottling: false —so that may be a workaround for some.”

About this issue

  • Original URL
  • State: closed
  • Created 7 years ago
  • Reactions: 17
  • Comments: 46 (7 by maintainers)

Most upvoted comments

requestAnimationFrame is designed to run animations on screen, and as such is heavily linked to on-screen behaviour in chromium code (e.g. being tied to the refresh rate of the display that the frame is currently displayed on). If you need timers to run unthrottled in the background, use setTimeout or setInterval, with the disable-background-timer-throttling switch. requestAnimationFrame is not a timer.

Hey, although @stickywes case may be more on the fringe I think my case is actually legitimate. I’m using captureStream to send a canvas through a WebRTC peer connection, which is blending some videos together to send it to the other peers. Previously I used backgroundThrottling set to false and a RAF loop to update the canvas. This no longer works and breaks my implementation. I would really prefer not to use an interval as it wouldn’t match the display refresh rate. Is there any alternative here?

I’d like to develop html canvas game. Multiplayer one at it too. Turn based. While opponents will wait for each others move, they will surely like to do a quick peek, into someone else’s websites. This breaks animation. Breaks my game too! And this bug is closed!? Oh no, it is alive, well, kicking and breaking peoples dreams! Edit: Its not just OS, Firefox has it too

is this problem fixed … I am also facing this in 6.1.11 I am capturing my app screen when its minimize the animation paused any way to fix this

Any updates on this issue?

This is the same using Electron version 4.0.6

@nornagon setTimeout isn’t a good enough workaround for this. requestAnimationFrame is designed to sync to screen refresh rates (source: article from 2012). setTimeout does not have this ability.

For applications which deal with realtime graphic rendering or @pedromcunha’s WebRTC case, setTimeout is not “appropriate” and that suggestion completely nerfs the point of having rAF in the first place.

I’m in the process of porting my application modV from NW.js to Electron - I was really enjoying the Electron experience until I encountered this road bump.

My application runs an rAF loop in the main Window and draws to Canvas Elements in child Windows. If the main Window becomes obscured on macOS the main rAF loop is halted and output is not drawn to the child Windows.

Two potential solutions which are a little less than ideal (may help others):

  • Making the child Windows have their own rAF loop

    • Impractical in my use-case because of the variable nature of what the child Windows are drawing. I’d have to maintain a loop in each Window and instances of the draw code for each also
  • Moving the draw loop to a Worker then using OffscreenCanvas to keep the loop running regardless of Window visibility

    • This is a solution, though one which is much further down the line for me

As you’ve said this was intended behaviour, would this be better off as a feature request (NW.js has a --disable-raf-throttling flag, for example) rather than an issue?

After doing some research:

In commit https://github.com/electron/electron/commit/497f5a11994a1c9858afd6ab04ea3ae9b3b77b34 (a part of Electron v1.5.0), osr_render_widget_host_view_mac.mm was changed to reflect Chromium API changes. This could be what introduced the bug. But I might be wrong here because I don’t know low level Electron well enough. 😄

This is the associated Chromium change. Search for browser_compositor_view_mac.mm.

Additionally, the member variable disable_hidden_ set in atom_api_web_contents.cc is not found in the corresponding Chromium class or any class it inherits from, which is a little mind boggling. Where does Chromium use the disable_hidden_ property?

If anyone can drop some knowledge on this, that’d be awesome.

Same problem here:

I have tried the webPreferences option ‘backgroundThrottling: false’, app.commandLine.appendSwitch(‘disable-renderer-backgrounding’), and win.setMinimizable(true) —in all cases requestAnimationFrame stops getting called when the window is inactive.

electron version: 1.6.11 OS: macOS El Capitan 10.11.6

Edit: setInterval() does work in the background with backgroundThrottling: false —so that may be a workaround for some.

One step toward a solution would be to provide an example that demonstrates the issue, and provide details like the Operating System and OS version you’re using.

It’s still not fixed! Using latest electron. This issue is so annoying. Aslo the lack of ownership of all the issues electron has. Literally every second feature has issues…

I pushed several updates and new releases of the demo project today, in order to support more modern Electron APIs since the original issue was posted.

I incremented major versions (eg. npm install --save-dev electron@v^7.0.0) several steps and tested at each step, and the issue appears to have stopped at electron@^8.0.0 and above. I am not able to reproduce the issue from that point on (and when throttling is enabled, I get the expected error result).

These tests were run on Mac OS Big Sur 11.2.3

Why is every second feature of electron not working properly? Its so annoying. Better not read the docs and get exited about features which don’t even exist.

And I don’t read any statement that the team is intending to fix this.

@Littlebigdondon Not sure, I never got round to making a patch file.

Will need to fork Electron, create the patch, push that to the fork and then follow the build instructions but pull from your fork instead.

I got busy between then and now with moving house so I haven’t had time to properly check this.

setInterval is an appropriate function to use for that use case; there’s nothing tying your LED display to the refresh rate of your monitor. rAF is for when you want to be embedded in the browser’s paint cycle, which is irrelevant for your use case.

Confirmed to reproduce on 2.0.x and 3.0.x, and disable-background-timer-throttling doesn’t work around the issue.

Any news of this issue? I currently still using electron 1.4.x but my user encounter some cpu/ram problem with webGL, wich are better managed in the 1.7/8. However my app has to still working during a workspace change or when it is minimized, i can’t sacrifice this feature for mac users.

I have tried :

app.commandLine.appendSwitch("disable-renderer-backgrounding");
app.commandLine.appendSwitch("disable-background-timer-throttling");

without success.

It’s really annoying and this regression was introduced a long time ago. So if you can fix it ❤️

Don’t know if this will help, but I tried the repro on two environments:

Can’t reproduce on Windows 8 Can reproduce on El Capitan 10.11.6