Disable implicit animations in layer backed NSScrollViews?

338 views
Skip to first unread message

Daniel Waylonis

unread,
Jun 20, 2011, 6:52:37 PM6/20/11
to Cocoa-Dev Mail
I'm stuck on a weird bug with NSTableViews and CALayers. I tried to ask up at WWDC in one of the labs, but didn't get an answer.

I have a auto-resizing NSTableView subclass in NSScrollView in a layer backed view. I'm using the 10.6 SDK and targeting 10.5 as well.

When I resize, the contents "jump" in the table view. I believe it is because there's an implicit animation to move the bounds and/or position. Or maybe something in the clip? I'd also not like it to fade in if I toggle between layer-backed and not.

I've searched on the mailing lists, StackOverflow, and Google in general for this, but I haven't found a solution.

I've tried the following but without any change to the behavior:

1. Custom NSScrollView and NSTableView, each of which implement what I believe should disable animations:
- (id<CAAction>)actionForLayer:(CALayer *)layer forKey:(NSString *)key {
return (id<CAAction>)[NSNull null];
}

I also tried returning nil as well.

2. Setting the actions (position, bounds, frame, hidden, onOrderIn) on the layers to NSNull.
3. Bracketing live resize methods with a CATransaction to disable animations. The results were not pretty.

I have a small sample project available: <http://nekotech.com/Code/Splitter.zip>

Oddly enough, when the view is small and the scroll bar is present, the "jumping" doesn't occur.

Thoughts and suggestions welcomed!

Dan
-----------------------------------------
Dan Waylonis | nekotech.com
650.887.3711

_______________________________________________

Cocoa-dev mailing list (Coco...@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/cocoa-dev/cocoa-dev-garchive-98506%40googlegroups.com

This email sent to cocoa-dev-ga...@googlegroups.com

Kyle Sluder

unread,
Jun 20, 2011, 7:55:13 PM6/20/11
to Daniel Waylonis, Cocoa-Dev Mail
On Mon, Jun 20, 2011 at 3:52 PM, Daniel Waylonis <da...@nekotech.com> wrote:
> When I resize, the contents "jump" in the table view.  I believe it is because there's an implicit animation to move the bounds and/or position.  Or maybe something in the clip?  I'd also not like it to fade in if I toggle between layer-backed and not.

Make sure that in your implementation of -resizeWithOldSuperviewSize:
that you call super's implementation. This bit us for a long time, but
apparently that's one of the places where the layer glue fixes up the
layer's geometry to match the AppKit geometry. You need to do this
even if you have custom logic in this method that will completely
nullify what super did. You may need to wrap the call to super in a
CATransaction with +setDisableActions:YES.

rdar://problem/8659667

--Kyle Sluder

Kyle Sluder

unread,
Jun 21, 2011, 12:53:40 AM6/21/11
to Daniel Waylonis, Cocoa-Dev Apple
On Jun 20, 2011, at 9:47 PM, Daniel Waylonis <da...@nekotech.com> wrote:

> Hi Kyle,
>
> Thanks for the suggestion.
>
> Unfortunately:
>
> - (void)resizeWithOldSuperviewSize:(NSSize)oldSize {
> [CATransaction begin];
> [CATransaction setDisableActions:YES];
> [super resizeWithOldSuperviewSize:oldSize];
> [CATransaction commit];
> }
>
> is still exhibiting the jumpy behavior.

Does it only happen on live resize?

>
> Perhaps I'm not overriding the right action? I'm returning "[NSNull null]" for the "onLayout" key in my actionForLayer:forKey: method as well as setting the layer's actions to have [NSNull null] for: position, bounds, frame, hidden, sublayers, onLayout, anchorPoint, onOrderOut, onOrderIn.
>
> If you happen to have a sample that work for you, I'd really appreciate you sending it my way!

Unfortunately I'm about to board a plane for a week of vacation, so you might have better luck bringing this back on list.

I don't have any code handy, but we do have a public beta of OmniPlan 2 that has a custom view (not NSTableView) that has had all the kinks worked out of it. I might be forgetting another important fix we implemented.

--Kyle Sluder_______________________________________________

Kyle Sluder

unread,
Jul 25, 2011, 1:29:48 AM7/25/11
to Daniel Waylonis, coco...@lists.apple.com
On Sun, Jul 24, 2011 at 10:00 PM, Daniel Waylonis <da...@nekotech.com> wrote:
> Hi Kyle,
> If you're back from vacation, could you describe how things were fixed in
> OmniPlan?

I've got a blog post in the editing phase describing all the things we
do to get NSScrollViews working, but the only other thing we do that I
can think of is to swizzle -[NSClipView scrollToPoint:] to look like
the following:

- (void)scrollToPoint:(NSPoint)newOrigin {
originalScrollToPoint(self, _cmd, newOrigin);

[self fixLayerGeometry];
[[self subviews] makeObjectsPerformSelector:@selector(fixLayerGeometry)];
}

-[NSView(LayerBackedFix) fixLayerGeometry] is defined like this:

- (void)fixLayerGeometry {
if (![self layer])
return;

[CATransaction begin];
[CATransaction setDisableActions:YES];

for (NSView *subview in [self subviews]) {
CALayer *layer = [subview layer];
CGPoint layerPosition = NSPointToCGPoint([self
convertPointToBase:[subview frame].origin]); // note: on Lion, we want
to use -convertPointToBacking: instead.
layer.position = layerPosition;
}

[CATransaction commit];
}

Pay attention to that note, since on Lion base coordinate systems
don't mean the same thing as backing coordinate systems.

I'm going to CC this to the list, since it's helpful information.

Hope that helps!

--Kyle Sluder

Reply all
Reply to author
Forward
0 new messages