Home | History | Annotate | Download | only in cocoa
      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