4

I need to draw a transparent overlay over another NSView, specifically, a WebView. The goal is to display some notification text with a semi-transparent background. For my first experiment I created an Overlay view that just displays a green square:

class Overlay: NSView {
    override func drawRect(dirtyRect: NSRect) {
        NSColor.greenColor().setFill()
        NSBezierPath(rect: CGRect(x: 10, y: 10, width: 1000, height: 1000)).fill()
    }
}

and then, in my code, I instantiate them and add them like this:

webView = WebView(frame: bounds)
overlay = Overlay(frame: bounds)

addSubview(webView)
addSubview(overlay)

To my surprise, that only works with some pages. For example, if you go to https://twitter.com/screensavrninja, it grayes out the whole page and shows you a sign out pop-in. Both the graying out and the pop-in happen on top of the green square.

Why is that happening? What's the appropriate way to have an overlay and have it remain on top?

Pablo Fernandez
  • 279,434
  • 135
  • 377
  • 622

1 Answers1

2

In AppKit, the order of subviews does not necessarily determine the order that they will be drawn in.

For performance reasons, Cocoa does not enforce clipping among sibling views or guarantee correct invalidation and drawing behavior when sibling views overlap. If you want a view to be drawn in front of another view, you should make the front view a subview (or descendant) of the rear view.

Reference

However, if you make the view layer-backed, they respect the ordering. So you could try enabling that.

Otherwise, you could use a child window to show the overlay. This has the advantage of being able to extend beyond the bounds of the parent, and is fairly common in Cocoa. See the documentation for NSWindow.

Community
  • 1
  • 1
joerick
  • 16,078
  • 4
  • 53
  • 57
  • The context of this is a screensaver, so, another Window is out of the question as far as I understand windows. I'll look into layer-backed views. – Pablo Fernandez Apr 10 '15 at 13:13
  • OS X screensavers are curious beasts. Good luck! – joerick Apr 10 '15 at 14:09
  • I'm not sure how to square this up with what the docs for [`NSView.subviews`](https://developer.apple.com/documentation/appkit/nsview/1483539-subviews) says: "The current view acts as the superview for each subview. The order of the subviews may be considered as being back-to-front, but this does not imply invalidation and drawing behavior." Which is correct? – Alexander Oct 11 '21 at 21:22