macOS: Avoid automatic resizing of layers by fixing them to top-left

When a layer is resized, e.g. during a window resize, the contents of
the layer may lag behind if the client doesn't fill the layer in
response to the window resize and corresponding expose event.

The default behavior is for Core Animation to stretch the content
to fill the layer, but this results in the content "jumping" back
and forth when the content then picks up the new size and fills
the layer.

Instead we tell Core Animation to fix the content to the top left
corner. If a layer is sized up without a corresponding layer contents
update this will result in missing/transparent pixels in the bottom
or right part of the layer, explicitly showing what the result of
the missing paint is. During debugging we also highlight this area
by adding a magenta background color to the layer.

Conversely, if the layer is sized down we don't need to resize it,
we can just keep the fixed top left position, and the content will
stay in place during the resize. This allows for optimizations
during window resizing, where we don't need to allocate new
buffers if the old buffer is larger than the new one.

Change-Id: I265b57e3a0ddff8bbcda3af5d670cd8c3b00b181
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
Tor Arne Vestbø 2019-09-26 12:05:57 +02:00
parent 4fade3c3b8
commit 72dd9de283

View File

@ -175,6 +175,14 @@
// the scale is up to date.
if (self.superview)
[self updateLayerContentsScale];
if (self.opaque && lcQpaDrawing().isDebugEnabled()) {
// If the view claims to be opaque we expect it to fill the entire
// layer with content, in which case we want to detect any areas
// where it doesn't.
layer.backgroundColor = NSColor.magentaColor.CGColor;
}
}
// ----------------------- Layer updates -----------------------
@ -186,14 +194,14 @@
return NSViewLayerContentsRedrawDuringViewResize;
}
#if 0 // Disabled until we enable lazy backingstore resizing
- (NSViewLayerContentsPlacement)layerContentsPlacement
{
// Always place the layer at top left without any automatic scaling,
// so that we can re-use larger layers when resizing a window down.
// Always place the layer at top left without any automatic scaling.
// This will highlight situations where we're missing content for the
// layer by not responding to the displayLayer: request synchronously.
// It also allows us to re-use larger layers when resizing a window down.
return NSViewLayerContentsPlacementTopLeft;
}
#endif
- (void)viewDidChangeBackingProperties
{