1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#import <Cocoa/Cocoa.h>
6
7// CustomFrameView is a class whose methods we swizzle into NSGrayFrame
8// on 10.7 and below, or NSThemeFrame on 10.8 and above, so that we can
9// support custom frame drawing. This is used with a textured window so that
10// AppKit does not draw a title bar.
11// This class is never to be instantiated on its own.
12// We explored a variety of ways to support custom frame drawing and custom
13// window widgets.
14// Our requirements were:
15// a) that we could fall back on standard system drawing at any time for the
16//    "default theme"
17// b) We needed to be able to draw both a background pattern, and an overlay
18//    graphic, and we need to be able to set the pattern phase of our background
19//    window.
20// c) We had to be able to support "transparent" themes, so that you could see
21//    through to the underlying windows in places without the system theme
22//    getting in the way.
23//
24// Since we want "A" we couldn't just do a transparent borderless window. At
25// least I couldn't find the right combination of HITheme calls to make it draw
26// nicely, and I don't trust that the HITheme calls are going to exist in future
27// system versions.
28// "C" precluded us from inserting a view between the system frame and the
29// the content frame in Z order. To get the transparency we actually need to
30// replace the drawing of the system frame.
31// "B" precluded us from just setting a background color on the window.
32//
33// Originally we tried overriding the private API +frameViewForStyleMask: to
34// add our own subclass of NSGrayView to our window. Turns out that if you
35// subclass NSGrayView it does not draw correctly when you call NSGrayView's
36// drawRect. It appears that NSGrayView's drawRect: method (and that of its
37// superclasses) do lots of "isMemberOfClass/isKindOfClass" calls, and if your
38// class is NOT an instance of NSGrayView (as opposed to a subclass of
39// NSGrayView) then the system drawing will not work correctly.
40//
41// Given all of the above, we found swizzling drawRect in _load to be the
42// easiest and safest method of achieving our goals. We do the best we can to
43// check that everything is safe, and attempt to fallback gracefully if it is
44// not.
45
46@interface NSWindow (CustomFrameView)
47
48// To define custom window drawing behaviour, override this method on an
49// NSWindow subclass. Call the default method (on super) to draw the
50// default frame.
51// NOTE: Always call the default implementation (even if you just immediately
52// draw over it), otherwise the top-left and top-right corners of the window
53// won't be drawn correctly.
54- (void)drawCustomFrameRect:(NSRect)rect forView:(NSView*)view;
55
56@end
57