Window animation not working on Big Sur and sheet windows

I’ve a strange problem on Big Sur while using “setFrame:display:animate:” to animate the change in height of a window. It has worked for many years on any type of window. Suddenly in Big Sur often fails on sheet windows.

When I say it often fails, it works correctly the first time for a given window and then after that it changes size but it happens very fast. It doesn’t matter if the initial change is an increase in height or a decrease it always works first time and not after that. It’s almost as if the time for the animation gets greatly shortened after the first call. It works a treat for other window types, but not sheets. I’ve also half a thought that it’s because sheets are vertically centred on Big Sur, so in effect it’s not just the height that changing it’s also the top.

The Pushbutton action event as follows:

If Self.Height = 500 then
   ChangeHeightTo( 700 )
Else
   ChangeHeightTo( 500 )
End if
Sub ChangeHeightTo( nHeight as Integer )
If Self.Height <> nHeight Then
  #If TargetMacOS
    #If Target64Bit
      Dim newRect As NSRect64
      Dim contentRect As NSRect64
      Declare Sub setFrameDisplayAnimate Lib "Cocoa" selector "setFrame:display:animate:" (windowRef As Integer, rect As NSRect64, display As Boolean, animate As Boolean)
      Declare Function contentRectForFrameRect Lib "Cocoa" Selector "contentRectForFrameRect:" (id As Integer, windowFrame As NSRect64) As NSRect64
    #Else
      Dim newRect As NSRect32
      Dim contentRect As NSRect32
      Declare Sub setFrameDisplayAnimate Lib "Cocoa" selector "setFrame:display:animate:" (windowRef As Integer, rect As NSRect32, display As Boolean, animate As Boolean)
      Declare Function contentRectForFrameRect Lib "Cocoa" Selector "contentRectForFrameRect:" (id As Integer, windowFrame As NSRect32) As NSRect32
    #EndIf
    
    newRect.Origin.x = Self.Left
    newRect.Origin.y = Self.Top
    newrect.Dimen.width = Self.width
    newrect.Dimen.height = nHeight
    
    contentRect = contentRectForFrameRect(Me.Handle, newRect)
    
    newRect.Origin.y = Screen(0).Height - (newRect.Origin.Y + Me.Height) - (newRect.Dimen.Height - Me.Height)
    newRect.Dimen.Height = newRect.Dimen.Height - (contentRect.Dimen.Height - newRect.Dimen.Height)  // adjust for the titlebar/toolbar
    
    setFrameDisplayAnimate Me.Handle, newRect, True, True
    
  #Else
    nNewHeight = nHeight
    nChange = ( nHeight - Self.Height ) / 2
    StartTimer
  #EndIf
End If

The Apple docs for animationResizeTime: say:

The NSWindow implementation uses the value from the NSWindowResizeTime user default as the time in seconds to resize by 150 pixels. If this value is unspecified, NSWindowResizeTime is 0.20 seconds (this default value may be different in different releases of macOS).

Well it doesn’t seems to be the “animationResizeTime:”, on each call the result is the same 0.235 seconds.

I think this is a macBS bug as it works every single time on a regular window, but on a sheet window, it only works once.

It might be because you’re altering the origin of the sheet window?
Edit: Nope, I just tested that and it still only does it once.

I would suggest using declares to find the screen of the window and adjusting the origin based of the screen that the window is actually on, rather than the first screen.

Instead: grab the top co-ordinate from the unadjusted frame
Dim macWindowTop as double = frameRect.origin.y + frameRect.area.height

Then adjust the new frame’s original so that it is flush with macWindowTop.
frameRect.origin.y = macWindowTop - frameRect.area.height

Edit 2: You should also convert the content rect back to a frame rect before adjusting the frame.

I was testing my application in macOS 10.14.6 and the sheet window resized smoothly every single time, so I suspect that this is simply another glitch with macBS.

This is now working correctly on Monterey.