Search code examples
layoutcalayerautolayoutnswindow

How to pin layer in window (view)


Imagine a yellow box (CALayer instance) drawn in the its parent layer (which is the root layer of a layer-backing NSView).

When the frame of the parent view changes, the yellow box should remain at the same position on the screen. When i set up autoresizing masks to NSViewMinXMarging and NSViewMaxXMarging the yellow box move on the screen proportionally between changing view width...

How can I adjust the frame of the NSWindow (NSView) while keeping the child layer at its initial position?

I know about - (void)layoutSublayersOfLayer:(CALayer *)layer CALayerDelegate method but i did not have an idea how to implement this behavior.

Here is demo:

enter image description here


Solution

  • This is my approach. Subclass NSWindow.

    .h-file:

    #import <Cocoa/Cocoa.h>
    #import <QuartzCore/QuartzCore.h>
    
    @interface NNMainWindow : NSWindow <NSWindowDelegate> {
    
        CALayer* yellowLayer;
    
        NSRect leftEdge;
        NSRect rightEdge;
        NSRect topEdge;
        NSRect bottomEdge;
    }
    @end
    

    .m-file:

    #import "NNMainWindow.h"
    
    @implementation NNMainWindow
    
    - (void)awakeFromNib {
    
        //Add yellow layer here....
    
        [self setAcceptsMouseMovedEvents:YES];
    
        [self updateResizingMarkers];
    }
    
    - (void)updateResizingMarkers {
        NSSize horizontalRectSize = NSMakeSize(NSWidth(self.frame), 8.f);
        horizontalRectSize.width += 10.f;
        NSSize verticalRectSize = NSMakeSize(8.f, NSHeight(self.frame));
        verticalRectSize.height += 10.f;
    
        leftEdge = NSZeroRect;
        leftEdge.size = verticalRectSize;
        leftEdge.origin = NSMakePoint(-5.f, -5.f);
    
        rightEdge = NSZeroRect;
        rightEdge.size = verticalRectSize;
        rightEdge.origin = NSMakePoint(horizontalRectSize.width - 10.f - 3.f, -5.f);
    }
    
    - (void)mouseMoved:(NSEvent *)theEvent {
    
        NSPoint currentLocation = [theEvent locationInWindow];
    
        if (NSPointInRect(currentLocation, leftEdge))
            yellowLayer.autoresizingMask = kCALayerMinXMargin;
    
        if (NSPointInRect(currentLocation, rightEdge))
            yellowLayer.autoresizingMask = kCALayerMaxXMargin;
    }
    
    - (void)windowDidResize:(NSNotification *)notification {
        [self updateResizingMarkers];
    }
    
    @end