Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create OS X window without Cocoa

Just out of curiosity I started trying to figure out how Cocoa creates windows. All of the libs I have found use Cocoa at the core, and I can't seem to find anything online.

I tried using Carbon, but it does not do anything but give me a warning about functions not being declared.

I guess what I am really looking for is a way to interface with Quartz Compositor.

Is there any way for me to get a look at the real window creation code?

like image 258
Justin Avatar asked Dec 07 '25 03:12

Justin


2 Answers

I haven't much detail to give you, but I may be able to point you in a direction.

There is one level down, which is Quartz Window Services. That's what both NSWindow and Carbon's Window Manager are based on.

It peeks through occasionally, even in the public API. You can ask any window for its window number (and likewise in Carbon), and with that, you can use anything in the public Quartz Window Services API. That doesn't get you very far, though: There's not much you can do with that besides take screenshots.

If you were to create a window with Quartz, though, it would (probably—I've never tried this) be blank. The title bar and background are drawn separately.

To do that, NSWindow has a second view ivar for a view called the frame view, which presumably uses HITheme. (Surprising amounts of it are even public—there is, for example, a HIThemeDrawWindowFrame! And it's public!) Window Manager probably does something similar.

[Added] Here's a test app that draws a window using HITheme (inside of a regular NSView).

Screenshot of the real window containing the fake window.

As you can see, it's not perfect: among other things, the shadow radius and title bar height are hard-coded. But it's a start, and a decent demonstration as it is.

Quick summary:

  • HIThemeDrawWindowFrame currently just draws the title bar and stoplight. No title text (it doesn't take a string, so it can't draw it), and no window background, frame outline, or shadow.
  • To draw the window background, set the window background brush as your context's fill color using HIThemeSetFill. Then, get the HIShape for the window's structure region using HIThemeGetWindowShape (note: despite the name, you need to CFRelease the shape you get from this), and then set that shape as your context's current path using HIShapeReplacePathInCGContext. Then, CGContextFillPath, as normal.
  • If you want a shadow behind your window, you'll want to wrap all of the above in a transparency layer. In particular, if you don't, the stoplight gets its own shadow behind each button, which looks majorly weird.
  • To draw the title text, use HIThemeDrawTextBox. You should be able to get the title text shape using HIThemeGetWindowShape, but, as of Lion, that returns an empty shape.
like image 52
Peter Hosey Avatar answered Dec 08 '25 20:12

Peter Hosey


The Quartz Window Services API also has a private part, which defines the following functions:

// Creating Windows
extern CGError CGSNewWindowWithOpaqueShape(CGSConnection cid, int always2, float x, float y, CGSRegionRef shape, CGSRegionRef opaqueShape, int unknown1, void *unknownPtr, int always32, CGSWindowID *outWID);
extern CGError CGSReleaseWindow(CGSConnection cid, CGSWindowID wid);
extern CGContextRef CGWindowContextCreate(CGSConnection cid, CGSWindowID wid, void *unknown);

You can find these and many more functions documented (not sure if the whole private API is documented here) at the undocumented goodness project.

like image 41
bwindels Avatar answered Dec 08 '25 20:12

bwindels



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!