kasper / phoenix

A lightweight macOS window and app manager scriptable with JavaScript
https://kasper.github.io/phoenix/
Other
4.36k stars 128 forks source link

window.setFrame intermittently unsuccessful when setting for a different screen #297

Closed tobias-edwards closed 2 years ago

tobias-edwards commented 2 years ago

Calling window.setFrame such that the focused window is moved to another screen will intermittently fail: https://github.com/kasper/phoenix/blob/39094643b939e5735f0e1d724139ba66190dc2b6/Phoenix/PHWindow.m#L305-L312

I made a prototype for my monitor setup:

    Screen 2       Screen 1
|---------------|-------------|
|   2560x1440   |  1792x1120  |
|               |-------------|
|---------------|
// Left-side of screen 2
Key.on('a', ['ctrl', 'option'], () => {
  const worked = Window.focused().setFrame({
    x: -2560,
    y: 23,
    width: 1280,
    height: 1417,
  });
  Phoenix.log(worked);
});

// Left-side of screen 1
Key.on('b', ['ctrl', 'option'], () => {
  const worked = Window.focused().setFrame({
    x: 0,
    y: 23,
    width: 896,
    height: 1097,
  });
  Phoenix.log(worked);
});

window.setFrame will intermittently fail when moving the window from screen 1 to screen 2. The result is the window having the correct location and width, except the height is incorrect (it seems to keep the smaller height of screen 1?).

Currently, I'm either having to put up with the issue, or run a loop to keep calling window.setFrame until it succeeds:

Window.prototype.setFrame_ = function (args) {
  let attempts = 0;
  let success = false;
  do {
    success = Window.prototype.setFrame.call(this, args);
    attempts += 1;
  // Attempts typically between 1-5, but can be as high as 24!
  } while (!success && attempts < 30);
  return success;
};

Any advice on handling this issue and why it might occur only sometimes?

tobias-edwards commented 2 years ago

Interestingly, the same issue occurs in other window managers e.g. Rectangle

kasper commented 2 years ago

@tobias-edwards Hello! Does this happen to you with every app or only particular ones?

tobias-edwards commented 2 years ago

@tobias-edwards Hello! Does this happen to you with every app or only particular ones?

Interesting! The issue affects:

But does not affect:

kasper commented 2 years ago

@tobias-edwards Got it, thanks! So I think the underlying thing is that resizing the window is also quite heavily impacted by how the app handles view rendering and what types of constraints the app sets for its views. (Also slight behavioural changes between macOS versions.)

In the end, resizing the window is more of an ask to resize the window and the app may or may not fully comply. That’s why you see retrying do the trick here. In some cases an app also has a minimum size defined and will for example never resize smaller than this.

One option might be to have more retrying logic built in to Phoenix, but that might also lead to other side effects.

tobias-edwards commented 2 years ago

I'll stick with my workaround, thanks for the insight. Apps having minimum window sizes is a pain!

Thank you very much for Phoenix, it's awesome.

kasper commented 2 years ago

Thanks for the kind words! 🙌