gfx/nsview_component.h
NSViewComponentWithParent: a native NSView inside an editor's component tree, on macOS.
#include <sonore/gfx/nsview_component.h>- 1type
- 5other declarations
- Guides: The native editor
On this page
Design notes
What it is for
Everything else in gfx is drawn by the software rasteriser into the one NSView the Cocoa peer owns. Some things cannot be: a hosted plugin's own editor (host_au.h hands one back as an NSView), a system control, a video layer. This component gives such a view a place in the tree -- it moves with the component, hides with it, and is clipped to nothing but its own frame, because it is a real subview drawn by AppKit on top of the peer.
"With parent"
The view handed over is not put straight into the peer's view. The component makes a PARENT NSView of its own, puts that in the peer's view where the component sits, and puts the child inside it, filling it. Every placement decision -- frame, hidden, which window -- is made on the parent, so the child is never repositioned behind its owner's back: a plugin view that lays itself out against its superview sees one stable superview for its whole life, whatever the editor does with the component. And when the CHILD resizes itself -- plugin editors do, when a user picks a larger size in them -- the component follows it (setFollowsViewSize), which is what the reference's NSViewComponentWithParent exists to do for a hosted plugin's view.
How it finds the window
A component knows its root and nothing about windows. NativeWindowCocoa keeps a list of the peers that are open and answers viewShowing(root); the parent view is moved into that view whenever the answer changes, and taken out when there is none. That is checked on every resize and by a 30 Hz timer, which also catches moves and visibility changes -- the component tree has no listener for either, and polling a frame is cheap next to the peer's own 30 Hz tick.
Coordinates need no flip: the peer's view is flipped (y down), as the component tree is, so a component at (x, y) in root coordinates is a frame at (x, y) in that view, in points.
Other platforms, and what was run
An NSView exists only on macOS. Elsewhere the class still exists, so code that names it compiles everywhere, but setView() refuses and lastError() says why. The placement arithmetic (detail::nativeEmbedPlacement) is portable and tested on Windows by tests/mac_host_test.cpp; the Cocoa half is COMPILED for macOS (tests/mac_syntax_mac_host.cpp) and has never run -- there is no Mac in this loop. tests/mac_host_selftest.cpp makes one with a plain NSView and prints where it went.
Types 1
class NSViewComponentWithParent : public Component
A child NSView, held in a parent NSView this component owns and places.
setView() takes any NSView* and retains it; null removes it. The component paints nothing of its own -- AppKit draws the view above the editor. Main thread only, like everything in a component tree.
Functions 5
- fn
inline NSViewComponentWithParent* nsViewParentOwner(id view)The owner, from the parent view's instance variable.gfx::nsViewParentOwner · nsview_component.h:165 - fn
inline BOOL nsViewParentIsFlipped(id, SEL)gfx::nsViewParentIsFlipped · nsview_component.h:171 - fn
inline void nsViewParentSync(id self, SEL, id)gfx::nsViewParentSync · nsview_component.h:173 - fn
inline void nsViewParentChildChanged(id self, SEL, id)gfx::nsViewParentChildChanged · nsview_component.h:177 - fn
inline Class nsViewParentClass()The parent view's class: an NSView, flipped like the peer's, carrying a pointer to its component and the two methods its timer and its notification call. Unique to this binary, for the reason the peer's view class gives -- two plugins in one host share one runtime.gfx::nsViewParentClass · nsview_component.h:185