- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / cocoa / custom_frame_view.mm
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 "chrome/browser/ui/cocoa/custom_frame_view.h"
6
7 #import <objc/runtime.h>
8 #import <Carbon/Carbon.h>
9
10 #include "base/logging.h"
11 #include "base/mac/mac_util.h"
12 #include "base/mac/scoped_nsautorelease_pool.h"
13
14 namespace {
15 BOOL gCanDrawTitle = NO;
16 BOOL gCanGetCornerRadius = NO;
17 }  // namespace
18
19 @interface NSView (Swizzles)
20 - (void)drawRectOriginal:(NSRect)rect;
21 - (NSPoint)_fullScreenButtonOriginOriginal;
22 @end
23
24 @interface NSWindow (FramedBrowserWindow)
25 - (NSPoint)fullScreenButtonOriginAdjustment;
26 @end
27
28 @implementation NSWindow (CustomFrameView)
29 - (void)drawCustomFrameRect:(NSRect)rect forView:(NSView*)view {
30   [view drawRectOriginal:rect];
31 }
32 @end
33
34 @interface CustomFrameView : NSView
35
36 @end
37
38 @implementation CustomFrameView
39
40 // This is where we swizzle drawRect, and add in two methods that we
41 // need. If any of these fail it shouldn't affect the functionality of the
42 // others. If they all fail, we will lose window frame theming and
43 // roll overs for our close widgets, but things should still function
44 // correctly.
45 + (void)load {
46   base::mac::ScopedNSAutoreleasePool pool;
47
48   // On 10.8+ the background for textured windows are no longer drawn by
49   // NSGrayFrame, and NSThemeFrame is used instead <http://crbug.com/114745>.
50   Class borderViewClass = NSClassFromString(
51       base::mac::IsOSMountainLionOrLater() ? @"NSThemeFrame" : @"NSGrayFrame");
52   DCHECK(borderViewClass);
53   if (!borderViewClass) return;
54
55   // Exchange draw rect.
56   Method m0 = class_getInstanceMethod([self class], @selector(drawRect:));
57   DCHECK(m0);
58   if (m0) {
59     BOOL didAdd = class_addMethod(borderViewClass,
60                                   @selector(drawRectOriginal:),
61                                   method_getImplementation(m0),
62                                   method_getTypeEncoding(m0));
63     DCHECK(didAdd);
64     if (didAdd) {
65       Method m1 = class_getInstanceMethod(borderViewClass,
66                                           @selector(drawRect:));
67       Method m2 = class_getInstanceMethod(borderViewClass,
68                                           @selector(drawRectOriginal:));
69       DCHECK(m1 && m2);
70       if (m1 && m2) {
71         method_exchangeImplementations(m1, m2);
72       }
73     }
74   }
75
76   // Swizzle the method that sets the origin for the Lion fullscreen button. Do
77   // nothing if it cannot be found.
78   m0 = class_getInstanceMethod([self class],
79                                @selector(_fullScreenButtonOrigin));
80   if (m0) {
81     BOOL didAdd = class_addMethod(borderViewClass,
82                                   @selector(_fullScreenButtonOriginOriginal),
83                                   method_getImplementation(m0),
84                                   method_getTypeEncoding(m0));
85     if (didAdd) {
86       Method m1 = class_getInstanceMethod(borderViewClass,
87                                           @selector(_fullScreenButtonOrigin));
88       Method m2 = class_getInstanceMethod(borderViewClass,
89           @selector(_fullScreenButtonOriginOriginal));
90       if (m1 && m2) {
91         method_exchangeImplementations(m1, m2);
92       }
93     }
94   }
95 }
96
97 + (BOOL)canDrawTitle {
98   return gCanDrawTitle;
99 }
100
101 + (BOOL)canGetCornerRadius {
102   return gCanGetCornerRadius;
103 }
104
105 - (id)initWithFrame:(NSRect)frame {
106   // This class is not for instantiating.
107   [self doesNotRecognizeSelector:_cmd];
108   return nil;
109 }
110
111 - (id)initWithCoder:(NSCoder*)coder {
112   // This class is not for instantiating.
113   [self doesNotRecognizeSelector:_cmd];
114   return nil;
115 }
116
117 // Here is our custom drawing for our frame.
118 - (void)drawRect:(NSRect)rect {
119   // Delegate drawing to the window, whose default implementation (above) is to
120   // call into the original implementation.
121   [[self window] drawCustomFrameRect:rect forView:self];
122 }
123
124 // Override to move the fullscreen button to the left of the profile avatar.
125 - (NSPoint)_fullScreenButtonOrigin {
126   NSWindow* window = [self window];
127   NSPoint offset = NSZeroPoint;
128
129   if ([window respondsToSelector:@selector(fullScreenButtonOriginAdjustment)])
130     offset = [window fullScreenButtonOriginAdjustment];
131
132   NSPoint origin = [self _fullScreenButtonOriginOriginal];
133   origin.x += offset.x;
134   origin.y += offset.y;
135   return origin;
136 }
137
138 @end