Re: Layer-hosting views and layer-backed scroll views

2010-05-25 Thread Kyle Sluder
On Mon, May 24, 2010 at 2:24 PM, Kyle Sluder  wrote:
> At this point, I don't think there's anything further I can do to work
> around this bug.

Well, Tim Wood gave me the idea to call -_updateLayerGeometryFromView
in an override of -viewWillDraw. This does the trick, and avoids the
single frame flicker of the layer in the wrong spot. So I think it's
as good as I'm going to get for now. I don't know if this workaround
works on 10.5, since -viewWillDraw is documented to not be called in
many cases of non-traditional drawing. But since we've publicly
announced that all new major versions of our apps will be 10.6-only, I
really don't care.

I do hope someone at Apple takes the time to fix this bug, and I hope
my workaround holds up.

--Kyle Sluder
___

Cocoa-dev mailing list (Cocoa-dev@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/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Layer-hosting views and layer-backed scroll views

2010-05-24 Thread Kyle Sluder
On Fri, May 21, 2010 at 3:20 PM, Kyle Sluder  wrote:
> I'm hoping I've done something wrong in setting up the layer. Is it
> perhaps because of the way I've turned off the redraw policy and set
> the layer resizing behavior? The documentation seems to imply that I
> have done the correct thing (setting the "resize independently"
> behavior and turning off layer redraw).

Nothing I do to -setLayerContentsPlacement: and/or
-setLayerContentsRedrawPolicy: (including doing nothing at all) is
able to fix the issue. The only thing I've gotten to work is to do a
delay-perform of -_updateLayerGeometryFromView, wrapped in a
CATransaction whose disableActions=YES. Even then, results are
suboptimal since the layer starts out positioned incorrectly and snaps
into the right spot on the next window refresh.

At this point, I don't think there's anything further I can do to work
around this bug.

--Kyle Sluder
___

Cocoa-dev mailing list (Cocoa-dev@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/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Layer-hosting views and layer-backed scroll views

2010-05-21 Thread Kyle Sluder
On Fri, May 21, 2010 at 11:06 AM, Troy Stephens  wrote:
> Sure.  Let us know if you run into further difficulty with this.

Unfortunately I have indeed hit more difficulty.  I've attached an
updated demo project to the Radar as well as uploaded it to
http://www.lanechng.com/ScrolledLayerHostingView.zip , and despite (I
believe) correctly handing over the layer to AppKit, it still has the
repositioning problem.

Instructions to trigger it:

1. Open the app.
2. Scroll the document around such that the scrollers are left at a
non-zero position.
3. Save the document.
4. Close the document.
5. Reopen the document.

The layer will be positioned incorrectly. :(

I'm hoping I've done something wrong in setting up the layer. Is it
perhaps because of the way I've turned off the redraw policy and set
the layer resizing behavior? The documentation seems to imply that I
have done the correct thing (setting the "resize independently"
behavior and turning off layer redraw).

Thanks,
--Kyle Sluder
___

Cocoa-dev mailing list (Cocoa-dev@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/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Layer-hosting views and layer-backed scroll views

2010-05-21 Thread Kyle Sluder
On Fri, May 21, 2010 at 11:06 AM, Troy Stephens  wrote:
> You can use geometryFlipped on your documentView's layer for this purpose, if 
> and only if your documentView isn't going to have any subviews.  If you 
> control all the content (build it out of your own layers) from there on down, 
> you're OK.  If AppKit has to position subview backing layers within the 
> documentView's layer, it won't take the geometryFlipped setting into account 
> and the positioning won't turn out right.

We're already following David's advice and putting our field editors
in a companion layer-backed view that is a peer of our document view
(but whose layer we don't disturb). But it was briefly funny when
field editors would appear upside down and at the opposite end of the
document from the content they were editing. :)

> You should never modify the anchorPoint of a view backing layer.  If you 
> modify your code to override -makeBackingLayer, AppKit will set the returned 
> layer's anchorPoint automatically the way it wants it (to (0,1) if the 
> superview is flipped, or (0,0) if the superview is unflipped).

Hmm. Are we free to move the bounds origin, though? We always want to
put the layer's bounds origin at the upper left, and for one instance
of this view we want to inset the origin by about 20px. This has
wreaked havoc with AppKit's custom layer content provider (which
apparently maps layer positions directly to CGImageSource points for
the purposes of calling -drawRect:, and has trouble when either
coordinate is negative). The result was a black 20px-wide stripe down
the left side of the view.

We did solve this at one point (when we were still abusing
layer-backed drawing) by turning off drawsBackground on the scroll
view, and inserting a custom sublayer with a background color. Then
AppKit's image source isn't invoked at all (or if it is, it doesn't
draw anything, and then our sublayer draws on top of it). I suppose if
I return my own layer from -makeBackingLayer, then AppKit won't attach
its image source since it won't be trying to hook up the -drawRect:
rendering path?

>>> Arguably it would actually be OK for us to modify the layer's position in 
>>> this case (and clearly our "hands off" policy isn't quite consistent about 
>>> this, since, as you noted, scrolling will "fix" the incorrect document 
>>> layer position).
>>
>> The inconsistency is what's so maddening. I thought I had just failed
>> to do something on initialization.
>
> We'll look at improving the consistency of this behavior.

Thanks.

> Once you're using -makeBackingLayer, just size the documentView the way you 
> want it, and let AppKit automatically resize the layer to match.

If AppKit does in fact try to attach an image source to the layer
returned by -makeBackingLayer, then we need to match our
background-fill sublayer's size, but that's made a heck of a lot
easier by being able to return a layer with a custom
-resizeSublayersWithOldSize: implementation. Or, at the very worst,
our background-fill layer could listen for bounds KVO from the
view-backing layer.

--Kyle Sluder
___

Cocoa-dev mailing list (Cocoa-dev@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/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Layer-hosting views and layer-backed scroll views

2010-05-21 Thread Troy Stephens
On May 21, 2010, at 10:52 AM, Kyle Sluder wrote:
> On Fri, May 21, 2010 at 10:37 AM, Troy Stephens  wrote:
>> CALayers don't support the same notion of "flippedness" that NSView's 
>> geometry model uses.  (CALayer's "geometryFlipped" property is recursive in 
>> its effect, so isn't semantically identical.)
> 
> Hmm. Perhaps instead of using geometryFlipped on our layer, we should
> manually calculate the bounds rectangle as appropriate? Or would
> setting the anchor point to (0,1) suffice? Basically, we want to lay
> out our contents like a text view would, which means that we want our
> first row of stuff (which is contained in a child layer) to appear at
> the upper left of the view, which should be at (0,0) in the layer's
> bounds coordinate space.

You can use geometryFlipped on your documentView's layer for this purpose, if 
and only if your documentView isn't going to have any subviews.  If you control 
all the content (build it out of your own layers) from there on down, you're 
OK.  If AppKit has to position subview backing layers within the documentView's 
layer, it won't take the geometryFlipped setting into account and the 
positioning won't turn out right.

You should never modify the anchorPoint of a view backing layer.  If you modify 
your code to override -makeBackingLayer, AppKit will set the returned layer's 
anchorPoint automatically the way it wants it (to (0,1) if the superview is 
flipped, or (0,0) if the superview is unflipped).

>> Therefore, whenever AppKit resizes the backing layer of a flipped NSView, we 
>> have to compute and assign new "position" values for its sublayers, to keep 
>> them in the same place relative to the top left.  (Don't count on this not 
>> changing in a future release, but for debugging purposes you can look for 
>> -_updateSublayerPositionsForFlippedSuperview, which gets invoked from 
>> -setFrameSize:)
>> 
>> We do this for sublayers that we created and therefore consider ourselves to 
>> "own", but in your test app you're instantiating and assigning a layer of 
>> your own to the documentView.  Therefore, when we resize the ClipView's 
>> backing layer (and the ClipView is flipped, because it always matches the 
>> flippedness of the ScrollView's documentView), we don't touch the position 
>> of your documentView's layer.  (If you modify your example to omit the 
>> custom layer creation and -setLayer:, and instead override -drawRect: to 
>> draw your content into the view's AppKit-provided backing layer, you'll see 
>> the problem goes away.)
> 
> Indeed it does. :) I had tested that, and was actually contemplating
> adding a button to toggle that behavior, but I wound up heading down
> the road of "rewrite NSScrollView using CAScrollLayer" instead.

There should be no need for that.  Just change your backing layer instantiation 
to user -makeBackingLayer.

>> Arguably it would actually be OK for us to modify the layer's position in 
>> this case (and clearly our "hands off" policy isn't quite consistent about 
>> this, since, as you noted, scrolling will "fix" the incorrect document layer 
>> position).
> 
> The inconsistency is what's so maddening. I thought I had just failed
> to do something on initialization.

We'll look at improving the consistency of this behavior.

>> Meanwhile, the simplest solution, if you require a custom backing layer, is 
>> to override NSView's -makeBackingLayer method (added in 10.6) to instantiate 
>> and return your (autoreleased) layer.  When layer instantiation goes through 
>> this path, AppKit considers the layer AppKit-owned, so you won't run into 
>> the positioning problem.
> 
> I can't believe we've overlooked this method. We do, however, need to
> resize the layer vertically as our document grows/shrinks, and we need
> it to always be at least as high as the visible area of the scroll
> view. Does this have the same potential for conflict with AppKit's
> layer resizing? (Or perhaps if we just resize the view to the
> appropriate size, this entire question just goes away. But that can't
> be right, it doesn't involve impossible contortions and overriding
> private methods! )

Once you're using -makeBackingLayer, just size the documentView the way you 
want it, and let AppKit automatically resize the layer to match.

For "document view should always be at least as big as the clip area" behavior, 
you'll want to monitor the ClipView for size changes, and resize the 
documentView as desired in response.

>> By the way: I don't know whether CAGradientLayer disregards -setNeedsDisplay 
>> (since the layer renders its content programmatically), possibly making this 
>> irrelevant in practice, but in cases like this, where you provide a layer of 
>> your own that already has content, and you don't want AppKit to ever invoke 
>> the view's -drawRect: to draw view content into the layer, it's a good idea 
>> to -setLayerContentsRedrawPolicy:NSViewLayerContentsRedrawNever on the view.
> 
> The CAGradientLayer is a red 

Re: Layer-hosting views and layer-backed scroll views

2010-05-21 Thread Kyle Sluder
On Fri, May 21, 2010 at 10:37 AM, Troy Stephens  wrote:
> CALayers don't support the same notion of "flippedness" that NSView's 
> geometry model uses.  (CALayer's "geometryFlipped" property is recursive in 
> its effect, so isn't semantically identical.)

Hmm. Perhaps instead of using geometryFlipped on our layer, we should
manually calculate the bounds rectangle as appropriate? Or would
setting the anchor point to (0,1) suffice? Basically, we want to lay
out our contents like a text view would, which means that we want our
first row of stuff (which is contained in a child layer) to appear at
the upper left of the view, which should be at (0,0) in the layer's
bounds coordinate space.

> Therefore, whenever AppKit resizes the backing layer of a flipped NSView, we 
> have to compute and assign new "position" values for its sublayers, to keep 
> them in the same place relative to the top left.  (Don't count on this not 
> changing in a future release, but for debugging purposes you can look for 
> -_updateSublayerPositionsForFlippedSuperview, which gets invoked from 
> -setFrameSize:)
>
> We do this for sublayers that we created and therefore consider ourselves to 
> "own", but in your test app you're instantiating and assigning a layer of 
> your own to the documentView.  Therefore, when we resize the ClipView's 
> backing layer (and the ClipView is flipped, because it always matches the 
> flippedness of the ScrollView's documentView), we don't touch the position of 
> your documentView's layer.  (If you modify your example to omit the custom 
> layer creation and -setLayer:, and instead override -drawRect: to draw your 
> content into the view's AppKit-provided backing layer, you'll see the problem 
> goes away.)

Indeed it does. :) I had tested that, and was actually contemplating
adding a button to toggle that behavior, but I wound up heading down
the road of "rewrite NSScrollView using CAScrollLayer" instead.

> Arguably it would actually be OK for us to modify the layer's position in 
> this case (and clearly our "hands off" policy isn't quite consistent about 
> this, since, as you noted, scrolling will "fix" the incorrect document layer 
> position).

The inconsistency is what's so maddening. I thought I had just failed
to do something on initialization.

> Meanwhile, the simplest solution, if you require a custom backing layer, is 
> to override NSView's -makeBackingLayer method (added in 10.6) to instantiate 
> and return your (autoreleased) layer.  When layer instantiation goes through 
> this path, AppKit considers the layer AppKit-owned, so you won't run into the 
> positioning problem.

I can't believe we've overlooked this method. We do, however, need to
resize the layer vertically as our document grows/shrinks, and we need
it to always be at least as high as the visible area of the scroll
view. Does this have the same potential for conflict with AppKit's
layer resizing? (Or perhaps if we just resize the view to the
appropriate size, this entire question just goes away. But that can't
be right, it doesn't involve impossible contortions and overriding
private methods! )

> By the way: I don't know whether CAGradientLayer disregards -setNeedsDisplay 
> (since the layer renders its content programmatically), possibly making this 
> irrelevant in practice, but in cases like this, where you provide a layer of 
> your own that already has content, and you don't want AppKit to ever invoke 
> the view's -drawRect: to draw view content into the layer, it's a good idea 
> to -setLayerContentsRedrawPolicy:NSViewLayerContentsRedrawNever on the view.

The CAGradientLayer is a red herring that I was using to visually
establish which end of the layer was "up."

You and David have been thoroughly amazing with your help. Thanks so much!

--Kyle Sluder
___

Cocoa-dev mailing list (Cocoa-dev@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/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Layer-hosting views and layer-backed scroll views

2010-05-21 Thread David Duncan
On May 21, 2010, at 10:37 AM, Troy Stephens wrote:

> By the way: I don't know whether CAGradientLayer disregards -setNeedsDisplay 
> (since the layer renders its content programmatically), possibly making this 
> irrelevant in practice, but in cases like this, where you provide a layer of 
> your own that already has content, and you don't want AppKit to ever invoke 
> the view's -drawRect: to draw view content into the layer, it's a good idea 
> to -setLayerContentsRedrawPolicy:NSViewLayerContentsRedrawNever on the view.


The CAGradientLayer (and the CAShapeLayer) both respect -setNeedsDisplay and go 
through the normal CG drawing path, so it would definitely be recommended to 
specify the never redraw policy.
--
David Duncan
Apple DTS Animation and Printing

___

Cocoa-dev mailing list (Cocoa-dev@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/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Layer-hosting views and layer-backed scroll views

2010-05-21 Thread Troy Stephens
Hi Kyle,

On May 20, 2010, at 12:12 PM, Kyle Sluder wrote:
> On Thu, May 20, 2010 at 9:52 AM, Kyle Sluder  wrote:
>> I have uploaded a sample project to
>> http://www.lanechng.com/ScrolledLayerHostingView.zip. Resize the
>> window to see the problem in action; then click one of the scroll
>> arrows to see it fix itself.
> 
> Well, I've filed rdar://problem/8009542 with this demo project
> attached. I've also been informed that IKImageBrowserView isn't
> flipped, perhaps because of this very same issue. It's also the only
> class besides NSView to implement _updateLayerGeometryFromView.
> Needless to say, I'm more than a little suspicious that scroll views
> are just plain broken.
> 
> --Kyle Sluder

CALayers don't support the same notion of "flippedness" that NSView's geometry 
model uses.  (CALayer's "geometryFlipped" property is recursive in its effect, 
so isn't semantically identical.)

Therefore, whenever AppKit resizes the backing layer of a flipped NSView, we 
have to compute and assign new "position" values for its sublayers, to keep 
them in the same place relative to the top left.  (Don't count on this not 
changing in a future release, but for debugging purposes you can look for 
-_updateSublayerPositionsForFlippedSuperview, which gets invoked from 
-setFrameSize:)

We do this for sublayers that we created and therefore consider ourselves to 
"own", but in your test app you're instantiating and assigning a layer of your 
own to the documentView.  Therefore, when we resize the ClipView's backing 
layer (and the ClipView is flipped, because it always matches the flippedness 
of the ScrollView's documentView), we don't touch the position of your 
documentView's layer.  (If you modify your example to omit the custom layer 
creation and -setLayer:, and instead override -drawRect: to draw your content 
into the view's AppKit-provided backing layer, you'll see the problem goes 
away.)

Arguably it would actually be OK for us to modify the layer's position in this 
case (and clearly our "hands off" policy isn't quite consistent about this, 
since, as you noted, scrolling will "fix" the incorrect document layer 
position).

Meanwhile, the simplest solution, if you require a custom backing layer, is to 
override NSView's -makeBackingLayer method (added in 10.6) to instantiate and 
return your (autoreleased) layer.  When layer instantiation goes through this 
path, AppKit considers the layer AppKit-owned, so you won't run into the 
positioning problem.

By the way: I don't know whether CAGradientLayer disregards -setNeedsDisplay 
(since the layer renders its content programmatically), possibly making this 
irrelevant in practice, but in cases like this, where you provide a layer of 
your own that already has content, and you don't want AppKit to ever invoke the 
view's -drawRect: to draw view content into the layer, it's a good idea to 
-setLayerContentsRedrawPolicy:NSViewLayerContentsRedrawNever on the view.

Troy Stephens
AppKit

___

Cocoa-dev mailing list (Cocoa-dev@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/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Re: Layer-hosting views and layer-backed scroll views

2010-05-20 Thread Kyle Sluder
On Thu, May 20, 2010 at 9:52 AM, Kyle Sluder  wrote:
> I have uploaded a sample project to
> http://www.lanechng.com/ScrolledLayerHostingView.zip. Resize the
> window to see the problem in action; then click one of the scroll
> arrows to see it fix itself.

Well, I've filed rdar://problem/8009542 with this demo project
attached. I've also been informed that IKImageBrowserView isn't
flipped, perhaps because of this very same issue. It's also the only
class besides NSView to implement _updateLayerGeometryFromView.
Needless to say, I'm more than a little suspicious that scroll views
are just plain broken.

--Kyle Sluder
___

Cocoa-dev mailing list (Cocoa-dev@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/archive%40mail-archive.com

This email sent to arch...@mail-archive.com


Layer-hosting views and layer-backed scroll views

2010-05-20 Thread Kyle Sluder
We have a layer-hosting document view that is contained in a
layer-backed scroll view. We have noticed that the scroll view does
some funky stuff to the layer if the view's -isFlipped returns YES.
This manifests itself in our app in the form of our document view
being scrolled by the correct amount but in the wrong direction at
startup. Everything gets fixed if the user scrolls the document.

Is there a known bug with NSScrollView and layer-hosting views? It
looks like NSClipView's implementation of
-_updateLayerGeometryFromView is at fault here. It is not being called
to correctly position the document view's layer within the clip view.

I have uploaded a sample project to
http://www.lanechng.com/ScrolledLayerHostingView.zip. Resize the
window to see the problem in action; then click one of the scroll
arrows to see it fix itself.

--Kyle Sluder
___

Cocoa-dev mailing list (Cocoa-dev@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/archive%40mail-archive.com

This email sent to arch...@mail-archive.com