Cleanup: Update the path to insets and point headers.
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / custom_frame_view.mm
blob3628c1a29fbf83e24d4acabdaf0cbcb510ef9fc3
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.
5 #import "chrome/browser/ui/cocoa/custom_frame_view.h"
7 #import <Carbon/Carbon.h>
8 #include <crt_externs.h>
9 #import <objc/runtime.h>
10 #include <string.h>
12 #include "base/logging.h"
13 #include "base/mac/mac_util.h"
14 #include "base/mac/scoped_nsautorelease_pool.h"
16 namespace {
17 BOOL gCanDrawTitle = NO;
18 BOOL gCanGetCornerRadius = NO;
19 }  // namespace
21 @interface NSView (Swizzles)
22 - (void)drawRectOriginal:(NSRect)rect;
23 - (NSPoint)_fullScreenButtonOriginOriginal;
24 @end
26 @interface NSWindow (FramedBrowserWindow)
27 - (NSPoint)fullScreenButtonOriginAdjustment;
28 @end
30 @implementation NSWindow (CustomFrameView)
31 - (void)drawCustomFrameRect:(NSRect)rect forView:(NSView*)view {
32   [view drawRectOriginal:rect];
34 @end
36 @interface CustomFrameView : NSView
38 @end
40 @implementation CustomFrameView
42 // This is where we swizzle drawRect, and add in two methods that we
43 // need. If any of these fail it shouldn't affect the functionality of the
44 // others. If they all fail, we will lose window frame theming and
45 // roll overs for our close widgets, but things should still function
46 // correctly.
47 + (void)load {
48   // Swizzling should only happen in the browser process. Interacting with
49   // AppKit will run +[borderViewClass initialize] in the renderer, which
50   // may establish Mach IPC with com.apple.windowserver.
51   // Note that CommandLine has not been initialized yet, since this is running
52   // as a module initializer.
53   const char* const* const argv = *_NSGetArgv();
54   const int argc = *_NSGetArgc();
55   const char kType[] = "--type=";
56   for (int i = 1; i < argc; ++i) {
57     const char* arg = argv[i];
58     if (strncmp(arg, kType, strlen(kType)) == 0)
59       return;
60   }
62   base::mac::ScopedNSAutoreleasePool pool;
64   // On 10.8+ the background for textured windows are no longer drawn by
65   // NSGrayFrame, and NSThemeFrame is used instead <http://crbug.com/114745>.
66   Class borderViewClass = NSClassFromString(
67       base::mac::IsOSMountainLionOrLater() ? @"NSThemeFrame" : @"NSGrayFrame");
68   DCHECK(borderViewClass);
69   if (!borderViewClass) return;
71   // Exchange draw rect.
72   Method m0 = class_getInstanceMethod([self class], @selector(drawRect:));
73   DCHECK(m0);
74   if (m0) {
75     BOOL didAdd = class_addMethod(borderViewClass,
76                                   @selector(drawRectOriginal:),
77                                   method_getImplementation(m0),
78                                   method_getTypeEncoding(m0));
79     DCHECK(didAdd);
80     if (didAdd) {
81       Method m1 = class_getInstanceMethod(borderViewClass,
82                                           @selector(drawRect:));
83       Method m2 = class_getInstanceMethod(borderViewClass,
84                                           @selector(drawRectOriginal:));
85       DCHECK(m1 && m2);
86       if (m1 && m2) {
87         method_exchangeImplementations(m1, m2);
88       }
89     }
90   }
92   // In Yosemite, the fullscreen button replaces the zoom button. We no longer
93   // need to swizzle out this AppKit private method.
94   if (base::mac::IsOSMavericksOrEarlier()) {
95     // Swizzle the method that sets the origin for the Lion fullscreen button.
96     // Do nothing if it cannot be found.
97     m0 = class_getInstanceMethod([self class],
98                                  @selector(_fullScreenButtonOrigin));
99     if (m0) {
100       BOOL didAdd = class_addMethod(borderViewClass,
101                                     @selector(_fullScreenButtonOriginOriginal),
102                                     method_getImplementation(m0),
103                                     method_getTypeEncoding(m0));
104       if (didAdd) {
105         Method m1 = class_getInstanceMethod(borderViewClass,
106                                             @selector(_fullScreenButtonOrigin));
107         Method m2 = class_getInstanceMethod(
108             borderViewClass, @selector(_fullScreenButtonOriginOriginal));
109         if (m1 && m2) {
110           method_exchangeImplementations(m1, m2);
111         }
112       }
113     }
114   }
117 + (BOOL)canDrawTitle {
118   return gCanDrawTitle;
121 + (BOOL)canGetCornerRadius {
122   return gCanGetCornerRadius;
125 - (id)initWithFrame:(NSRect)frame {
126   // This class is not for instantiating.
127   [self doesNotRecognizeSelector:_cmd];
128   return nil;
131 - (id)initWithCoder:(NSCoder*)coder {
132   // This class is not for instantiating.
133   [self doesNotRecognizeSelector:_cmd];
134   return nil;
137 // Here is our custom drawing for our frame.
138 - (void)drawRect:(NSRect)rect {
139   // Delegate drawing to the window, whose default implementation (above) is to
140   // call into the original implementation.
141   [[self window] drawCustomFrameRect:rect forView:self];
144 // Override to move the fullscreen button to the left of the profile avatar.
145 - (NSPoint)_fullScreenButtonOrigin {
146   NSWindow* window = [self window];
147   NSPoint offset = NSZeroPoint;
149   if ([window respondsToSelector:@selector(fullScreenButtonOriginAdjustment)])
150     offset = [window fullScreenButtonOriginAdjustment];
152   NSPoint origin = [self _fullScreenButtonOriginOriginal];
153   origin.x += offset.x;
154   origin.y += offset.y;
155   return origin;
158 @end