Skip to content

Calling setFrame triggers window animation for some apps, and window ends up with incorrect frame #369

@DanielGibbsNZ

Description

@DanielGibbsNZ

This is a bit of a strange one, but in the last few days I've noticed that some apps now animate when window.setFrame is called, and this animation often results in the window ending up in the wrong place. So far I've only noticed this on a couple of Chromium-based browsers as well as the default macOS Mail and Notes apps.

I have a setup where I can press Ctrl+Alt+Left and Ctrl+Alt+Right to move a window to the left and right side of the screen respectively, and Ctrl+Alt+Up to make a window fill the screen.

In the affected apps, if I move a window to the right side of the screen, and then press Ctrl+Alt+Up, it will animate to the left side instead of filling the screen. Yet the Phoenix logs confirm that setFrame was called with the correct frame for the whole screen. It seems that the animation is somehow interfering with the resulting location of the window.

Is this some sort of new OS behaviour that these apps have opted into? Or is it something that I need to change in my config?

Versions

  • macOS: 15.5 (24F74)
  • Phoenix: Version 4.0.1 (137)
  • Apps affected:
    • Mail (Version 16.0 (3826.600.51.1.1))
    • Notes (Version 4.12.6 (2998.56)), Brave
    • Brave (1.85.111 (Official Build) (x86_64) Chromium: 143.0.7499.40)
    • Helium (Version 0.9.4.1 (Official Build, Chromium 145.0.7632.116) (x86_64))

On my work laptop, I have macOS 15.3.1 with the same apps and same Phoenix config, but this issue does not occur, so possibly an OS thing?

Reproduction steps

I'm not sure if this will be easily reproducible to others, but here's my attempt for reproduction steps, and a video showing the problem.

  1. Use the Phoenix config below
  2. Open one of the affected apps (Brave is used in the video)
  3. Press Ctrl+Alt+Left to move the app to the left side of the screen
  4. Press Ctrl+Alt+Right to move the app to the right side of the screen
  5. Press Ctrl+Alt+Up to make the app fill the screen
  6. Watch the app animate to the left side of the screen instead

You can also verify in the Phoenix logs at this point that setFrame is called with the correct frame.

Video

Screen.Recording.2026-03-05.at.11.30.25.PM.mov

Phoenix config

var FULL_SCREEN = function(screen) {
  return screen.flippedVisibleFrame();
};

var LEFT_HALF = function(screen) {
  var screenFrame = screen.flippedVisibleFrame();
  return { x: screenFrame.x, y: screenFrame.y, width: screenFrame.width / 2, height: screenFrame.height };
};

var RIGHT_HALF = function(screen) {
  var screenFrame = screen.flippedVisibleFrame();
  return { x: screenFrame.x + (screenFrame.width / 2), y: screenFrame.y, width: screenFrame.width / 2, height: screenFrame.height };
};

function stringFromRect(rect) {
  return `${rect.x},${rect.y},${rect.width},${rect.height}`
}

function moveWindow(window, screen, frameFunc) {
  var frame = frameFunc(screen);
  Phoenix.log(stringFromRect(frame));
  window.setFrame(frame);
}

Key.on('up', [ 'ctrl', 'alt' ], function () {
  var window = Window.focused();
  if (window) {
    var screen = window.screen();
    Phoenix.log('Full screen');
    moveWindow(window, screen, FULL_SCREEN);
  }
});

Key.on('left', [ 'ctrl', 'alt' ], function () {
  var window = Window.focused();
  if (window) {
    var screen = window.screen();
    Phoenix.log('Left half');
    moveWindow(window, screen, LEFT_HALF);
  }
});

Key.on('right', [ 'ctrl', 'alt' ], function () {
  var window = Window.focused();
  if (window) {
    var screen = window.screen();
    Phoenix.log('Right half');
    moveWindow(window, screen, RIGHT_HALF);
  }
});

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions