NSWindow Content Border messing with CALayer's geometry - cocoa

I have an NSWindow with a 32px bottom content border. Inside the window's view, I have two custom subviews. Each of them are layer backed, and I'm tracking the mouse with an NSTrackingArea. Part of what I'm doing is some mouseOver effects with CoreAnimation. This is not a problem in general, but I noticed something kind of strange and wondered if anyone knows why this is happening.
When setting up the trackingArea and mouseOver method, I hitTest the root layer and log the layer's name so I can see if the geometry of the various sublayers hold water when I resize the window. Internally, they seem (and look) fine. Visually, they are in the right place, but when I move the mouse, I notice that the though the mouse is physically over a layer, hitTest is returning whatever layer is 32 px above it. However, if I remove the content border, it works as you would expect and the correct layer is returned.
I obviously need the content border, so I have a very simple workaround which involves offsetting the hitTest point by 32px. This works fine, but it just seems weird that the presence of a content border seems to skewing the co-ordinate system of these subviews. Does anyone know why this could be happening?

NSEvent returns mouse locations relative to the window's coordinate system, not the targeted view's. You probably need to call convertRect:fromView: to get the correct coordinates.

Related

NSWindow shadow with transparency, how to clip certain area

In our OS X application, we have enabled window shadow by view.window?.hasShadow = true. This will create a fine shadow over NSWindow. We have created a hole in the application by a custom view to see the background through it, via its mask layer.
Our problem is that the shadow is visible in the hole region too. Can we make the shadow not appear in the transparent region. We have searched, but didn't get anything to clip window shadow at certain area.
This shadow is creating some problem in the application
We have given a button to collapse/expand the view which have the hole. So the hole will enlarge and shrink according to that. At this time window will not recalculate the shadow. We have tried the view.window?.invalidateShadow(). But it doesn't has any effect.
We are drawing some texts over the transparent region. When the expand collapse happens we can see the traces of the text drawn. It will always be there.
Every thing comes fine if we resize the application, which will recalculate the shadow. How we can overcome these issue. What will be the work around.

Hiding Titlebar in NSWindow, rounding the corners and keeping the shadow

I like the way the developers behind Vox.app have created a custom titlebar and still kept the original shadow.
If you set the styleMask = NSBorderlessWindowMask it will create another kind of shadow, and the rounded corners are gone.
And it doesn't seem to be that easy to recreate those shadows especially when you also want rounded corners.
I have taken a window shot of the app that I like. Look at the drop shadows and the title bar.
Is it possible (I assume) to do this? And if so, how?
Is it possible (I assume) to do this?
Yes, this is possible.
And if so, how?
You need to subclass the NSWindow and NSView, set the background color, use custom buttons etc.
For curvy-corners, you need to draw using bezier path. I tried reached somewhat near, however titlebar's color is not changed in this screenshot... but I hope you can do it from here:

Padding at top of NSView in an NSScrollView

I have an NSView as the document of an NSScrollView. I would like to have a few pixels of padding at the top and bottom of the visible part of the view, regardless of where the scroller is positioned (not just at the top and bottom of the document as described here). For an example of an app that does this, look at Terminal.app. Regardless of the background color of the text, the top two visible rows of pixels are always the default background color.
I know I could simply draw everything two pixels lower and draw a rectangle at the top and bottom of the document-visible rect, but that will require changing a lot of complex code that I didn't write. Simpler ideas are welcomed!
The answer to the question you linked is actually a good solution for this problem too. In fact if your view is anything but an NSTextView, I'd say it's easier to implement.
Specifically: make your actual document view a subview of some other view, leaving room around the edges and make that view the scroll view's document view. If your content view (the one you wish to pad) changes sizes, have your "padding view" observe it for frame changes and resize to maintain the padding.
2015 Update
Content inset has been added to NSScrollView as of 10.10, making my older answer obsolete.

Glow around Button

How can I draw a slight white 'glow' around a button or label in 10.5 and later? I have seen some apps do it, but I am still confused how I should do this.
See NSShadow. You'd create and set a shadow (saving your graphics context beforehand), then draw the basic shape of your button, unset it (by restoring your graphics context), then continue drawing as usual.
In the case of a ready-made control like NSButton, you will need to subclass and override its cell drawing (and possibly make the host NSButton control itself a bit larger to accommodate the larger area needed to encompass the "glow" of the cell).
You might be able to avoid this with a label by setting its font shadow, but I don't think IB lets you do this, so you'd programmatically give the label an attributed string (via its -setAttributedString: method). The attributes would include the NSShadow (configured as desired) as the NSShadowAttributeName.

NSView leaves artifacts on another NSView when the first is moved across the second

I have an NSView subclass that can be dragged around in its superview. I move the views by calling NSView's setFrameOrigin and setFrameRotation methods in my mouseDragged event handler. The views are both moved and rotated with each call.
I have multiple instances of these views contained by a single superview. The problem I'm having is that, as one view is dragged over another, it leaves artifacts behind on the view it's eclipsing. I recorded a short video of this in action. Unfortunately, due to the video compression the artifacts aren't very visible.
I strongly suspect that this is related to the simultaneous translation and rotation. Quartz Debug reveals that a rectangle of the occluding (or occluded) view is updated as another view is dragged across it (video here); somehow this rectangle is getting miscalculated by the drawing engine, so part of the view that should be redrawn isn't.
The kicker is I have no idea how to fix this. I can't find any way to manually specify the update rect in the docs, nor am I sure that's what needs to happen. Any ideas? Thanks!
You might also consider using CALayers instead of views. Unlike views, layers are intended to be stacked with their siblings.
For a possible least-effort solution, try making the views layer-backed; it may or may not solve this problem, but it's worth a try.
Views aren't really designed to be stacked in an interactive fashion. Can be done, but edge cases abound.
Generally, for this kind of thing you would use a Cell like infrastructure if you want to do in-view dragging (See the Sketch example) and you would use the drag-n-drop infrastructure if you want to drag between views or windows (or apps).
If you really want to drag a transformed view over the top, you'll need to invalidate a rectangle of the view underneath the view being dragged. The rectangle will need to be bigger by a few pixels than the total area (unrotated/untransformed) that is obscured by the view being dragged. The artifacts are, effectively, caused by rounding error; diagonal lines are just an estimate on a raster drawing system.
See the method:
- (void)setNeedsDisplayInRect:(NSRect)invalidRect;

Resources