Bring Front the CALayer over the the NSView in Xamarin.Forms.macOS.

Dinesh4693Dinesh4693 INMember ✭✭

Hi Team,

We experiencing a atypical behavior in our application which is developed in Xamarin.Forms.macOS project.

Application Scenario:
We are using a custom NSView class which holds the ListViewItems and added a NSView as SubView for Selection (Changing the background color) in it (named as SelectionView) and to draw the border over the item, we have used a four CALayers (left, right, bottom and top) around the it and added it as SubLayers.

Experiencing Issue:
When the background color is defined to SelectionView, the color gets applied to view. But the border layers (i.e., CALayers) gets invisible nothing but the SelectionView gets overlapped with the borders. If the SelectionView background color is Transparent, the border layers are shown as expected.

Note:
This issue occurs only in macOS sierra version 10.13 and working fine in macOS sierra version 10.11 and 10.12.

Analysis details:
On referencing the macOS sierra release notes, they have made a backing layer behavioral change but we could not able to understand it (not sufficient information is there) and no examples or code snippets are found.
Documentation: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreAnimation_guide/SettingUpLayerObjects/SettingUpLayerObjects.html
Release Notes: https://developer.apple.com/library/archive/releasenotes/AppKit/RN-AppKit/index.html

Regards,
Dinesh Babu Yadav

Answers

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    Without an example, I can only speak in generals.

    The difference between NSViews and CALayers is an important distinction and I would dig into the documentation listed until you understand it. In additional to the documentation you linked, https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CoreAnimation_guide/BuildingaLayerHierarchy/BuildingaLayerHierarchy.html is a reasonable bit of documentation.

    At a high level though, NSView can own CALayers that are objects that are drawn into and handled by graphics hardware. On older macOS/SDKs views don't default to have layers (layer backed/owned) but that's changed in recent release. In 10.14 all layers are backed by default. This has "broke" some view customization, which is why these changes only generally hit when you link against newer SDKs. However, view customization on macOS can sometimes hit implementation specific details and need to be reworked (or dropped).

    Often Cocoa does not play well with view customization. Sometimes, you need to either accept the default view or draw the entire thing yourself.

  • ShammyLevvaShammyLevva Member ✭✭
    edited November 2018

    I have encountered a similar issue and note that in 10.14 I can create a custom NSView and set Layer attribute and it works however the same code running in 10.11 crashes with this error. Sample code:

    tableview = new NSTableView();
    tableview.Layer = new CoreAnimation.CALayer();
    

    works in 10.14 but fails in 10.11.6 with
    *** Terminating app due to uncaught exception 'CALayerInvalidGeometry', reason: 'CALayer bounds contains NaN: [nan nan; nan nan]'
    abort() called terminating with uncaught exception of type NSException
    but

    tableview = new NSTableView();
    tableview.Layer = new CoreAnimation.CALayer();
    tableview.Layer.Bounds = new CoreGraphics.CGRect(0,0,0,0);
    

    prevents the error in 10.11.6. So it would seem something about 10.11.6 as ChrisHamons suggests is leaving the Layer.Bounds unset and crashing.

    Note even just
    tableview = new NSTableView();
    works in 10.14 but you need to set the layer and bounds for the same code to also run on 10.11.6.

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    You may need to call new NSTableView with a CGRect, say the Frame of it's parent. Or you could just set WantsLayer = True and see if that handles it.

    In any case, this is Cocoa crashing directly as we pass your API invocation across.

  • ShammyLevvaShammyLevva Member ✭✭

    I had tried WantsLayer = true but no joy with that either. I'd not tried an an alternate view constructor call so that may have worked.

    My solution of adding a Layer.Bounds works so I thought it may be of use to someone else in future or might be a candidate for a fix within Visual Studio ie: could be checked within the VS code for a missing Bounds and adding a dummy one before passed to Cocoa? This is after all what MacOS 10.14 seems to be doing. ie: in 10.14 if you don't set a bounds it sets a default one of CGRect(0,0,0,0). It's prior MacOS versions that have the NaN bug.

    I struggled with this as I'm on 10.14.2 (beta) so it just worked in my dev environment. It was an end user who was using an old MacBook circa 2009 that is limited to 10.11.6 that had the issue.

    Anyway hopefully my observation may help someone googling the issue in future.

  • ChrisHamonsChrisHamons USForum Administrator, Xamarin Team Xamurai

    In general Xamarin.Mac tries to be a "thin layer" over the Cocoa API, with a 1-to-1 reflection of the native API where possible. It is extremely likely if you replicated your code in Objective-C and ran it on 10.11 you'd see the exact same behavior.

    I agree that behavior is sub-optimal, and think posting your results for future people's googling is reasonable. :)

Sign In or Register to comment.