Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #import "chrome/browser/ui/cocoa/custom_frame_view.h" | 5 #import "chrome/browser/ui/cocoa/custom_frame_view.h" |
| 6 | 6 |
| 7 #import <Carbon/Carbon.h> | 7 #import <Carbon/Carbon.h> |
| 8 #include <crt_externs.h> | 8 #include <crt_externs.h> |
| 9 #import <objc/runtime.h> | 9 #import <objc/runtime.h> |
| 10 #include <string.h> | 10 #include <string.h> |
| 11 | 11 |
| 12 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/mac/mac_util.h" | 13 #include "base/mac/mac_util.h" |
| 14 #include "base/mac/scoped_nsautorelease_pool.h" | 14 #include "base/mac/scoped_nsautorelease_pool.h" |
| 15 | 15 |
| 16 namespace { | |
| 17 BOOL gCanDrawTitle = NO; | |
| 18 BOOL gCanGetCornerRadius = NO; | |
| 19 } // namespace | |
| 20 | |
| 21 @interface NSView (Swizzles) | 16 @interface NSView (Swizzles) |
| 22 - (void)drawRectOriginal:(NSRect)rect; | |
| 23 - (NSPoint)_fullScreenButtonOriginOriginal; | 17 - (NSPoint)_fullScreenButtonOriginOriginal; |
| 24 @end | 18 @end |
| 25 | 19 |
| 26 @interface NSWindow (FramedBrowserWindow) | 20 @interface NSWindow (FramedBrowserWindow) |
| 27 - (NSPoint)fullScreenButtonOriginAdjustment; | 21 - (NSPoint)fullScreenButtonOriginAdjustment; |
| 28 @end | 22 @end |
| 29 | 23 |
| 30 @implementation NSWindow (CustomFrameView) | |
| 31 - (void)drawCustomFrameRect:(NSRect)rect forView:(NSView*)view { | |
| 32 [view drawRectOriginal:rect]; | |
| 33 } | |
| 34 @end | |
| 35 | |
| 36 @interface CustomFrameView : NSView | 24 @interface CustomFrameView : NSView |
| 37 | 25 |
| 38 @end | 26 @end |
| 39 | 27 |
| 40 @implementation CustomFrameView | 28 @implementation CustomFrameView |
| 41 | 29 |
| 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 { | 30 + (void)load { |
| 48 // Swizzling should only happen in the browser process. Interacting with | 31 // Swizzling should only happen in the browser process. Interacting with |
| 49 // AppKit will run +[borderViewClass initialize] in the renderer, which | 32 // AppKit will run +[borderViewClass initialize] in the renderer, which |
| 50 // may establish Mach IPC with com.apple.windowserver. | 33 // may establish Mach IPC with com.apple.windowserver. |
| 51 // Note that CommandLine has not been initialized yet, since this is running | 34 // Note that CommandLine has not been initialized yet, since this is running |
| 52 // as a module initializer. | 35 // as a module initializer. |
| 53 const char* const* const argv = *_NSGetArgv(); | 36 const char* const* const argv = *_NSGetArgv(); |
| 54 const int argc = *_NSGetArgc(); | 37 const int argc = *_NSGetArgc(); |
| 55 const char kType[] = "--type="; | 38 const char kType[] = "--type="; |
| 56 for (int i = 1; i < argc; ++i) { | 39 for (int i = 1; i < argc; ++i) { |
| 57 const char* arg = argv[i]; | 40 const char* arg = argv[i]; |
| 58 if (strncmp(arg, kType, strlen(kType)) == 0) | 41 if (strncmp(arg, kType, strlen(kType)) == 0) |
| 59 return; | 42 return; |
| 60 } | 43 } |
| 61 | 44 |
| 62 base::mac::ScopedNSAutoreleasePool pool; | 45 base::mac::ScopedNSAutoreleasePool pool; |
| 63 | 46 |
| 64 // On 10.8+ the background for textured windows are no longer drawn by | 47 // On 10.8+ the background for textured windows are no longer drawn by |
| 65 // NSGrayFrame, and NSThemeFrame is used instead <http://crbug.com/114745>. | 48 // NSGrayFrame, and NSThemeFrame is used instead <http://crbug.com/114745>. |
| 66 Class borderViewClass = NSClassFromString( | 49 Class borderViewClass = NSClassFromString( |
| 67 base::mac::IsOSMountainLionOrLater() ? @"NSThemeFrame" : @"NSGrayFrame"); | 50 base::mac::IsOSMountainLionOrLater() ? @"NSThemeFrame" : @"NSGrayFrame"); |
| 68 DCHECK(borderViewClass); | 51 DCHECK(borderViewClass); |
| 69 if (!borderViewClass) return; | 52 if (!borderViewClass) return; |
| 70 | 53 |
| 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 } | |
| 91 | |
| 92 // In Yosemite, the fullscreen button replaces the zoom button. We no longer | 54 // In Yosemite, the fullscreen button replaces the zoom button. We no longer |
| 93 // need to swizzle out this AppKit private method. | 55 // need to swizzle out this AppKit private method. |
| 94 if (base::mac::IsOSMavericksOrEarlier()) { | 56 if (base::mac::IsOSMavericksOrEarlier()) { |
|
Robert Sesek
2015/03/04 19:16:26
Since we only swizzle in this case, you can move t
jackhou1
2015/03/05 04:28:08
Done.
| |
| 95 // Swizzle the method that sets the origin for the Lion fullscreen button. | 57 // Swizzle the method that sets the origin for the Lion fullscreen button. |
| 96 // Do nothing if it cannot be found. | 58 // Do nothing if it cannot be found. |
| 97 m0 = class_getInstanceMethod([self class], | 59 Method m0 = class_getInstanceMethod([self class], |
| 98 @selector(_fullScreenButtonOrigin)); | 60 @selector(_fullScreenButtonOrigin)); |
| 99 if (m0) { | 61 if (m0) { |
| 100 BOOL didAdd = class_addMethod(borderViewClass, | 62 BOOL didAdd = class_addMethod(borderViewClass, |
| 101 @selector(_fullScreenButtonOriginOriginal), | 63 @selector(_fullScreenButtonOriginOriginal), |
| 102 method_getImplementation(m0), | 64 method_getImplementation(m0), |
| 103 method_getTypeEncoding(m0)); | 65 method_getTypeEncoding(m0)); |
| 104 if (didAdd) { | 66 if (didAdd) { |
| 105 Method m1 = class_getInstanceMethod(borderViewClass, | 67 Method m1 = class_getInstanceMethod(borderViewClass, |
| 106 @selector(_fullScreenButtonOrigin)); | 68 @selector(_fullScreenButtonOrigin)); |
| 107 Method m2 = class_getInstanceMethod( | 69 Method m2 = class_getInstanceMethod( |
| 108 borderViewClass, @selector(_fullScreenButtonOriginOriginal)); | 70 borderViewClass, @selector(_fullScreenButtonOriginOriginal)); |
| 109 if (m1 && m2) { | 71 if (m1 && m2) { |
| 110 method_exchangeImplementations(m1, m2); | 72 method_exchangeImplementations(m1, m2); |
| 111 } | 73 } |
| 112 } | 74 } |
| 113 } | 75 } |
| 114 } | 76 } |
| 115 } | 77 } |
| 116 | 78 |
| 117 + (BOOL)canDrawTitle { | |
| 118 return gCanDrawTitle; | |
| 119 } | |
| 120 | |
| 121 + (BOOL)canGetCornerRadius { | |
| 122 return gCanGetCornerRadius; | |
| 123 } | |
| 124 | |
| 125 - (id)initWithFrame:(NSRect)frame { | 79 - (id)initWithFrame:(NSRect)frame { |
| 126 // This class is not for instantiating. | 80 // This class is not for instantiating. |
| 127 [self doesNotRecognizeSelector:_cmd]; | 81 [self doesNotRecognizeSelector:_cmd]; |
| 128 return nil; | 82 return nil; |
| 129 } | 83 } |
| 130 | 84 |
| 131 - (id)initWithCoder:(NSCoder*)coder { | 85 - (id)initWithCoder:(NSCoder*)coder { |
| 132 // This class is not for instantiating. | 86 // This class is not for instantiating. |
| 133 [self doesNotRecognizeSelector:_cmd]; | 87 [self doesNotRecognizeSelector:_cmd]; |
| 134 return nil; | 88 return nil; |
| 135 } | 89 } |
| 136 | 90 |
| 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]; | |
| 142 } | |
| 143 | |
| 144 // Override to move the fullscreen button to the left of the profile avatar. | 91 // Override to move the fullscreen button to the left of the profile avatar. |
| 145 - (NSPoint)_fullScreenButtonOrigin { | 92 - (NSPoint)_fullScreenButtonOrigin { |
| 146 NSWindow* window = [self window]; | 93 NSWindow* window = [self window]; |
| 147 NSPoint offset = NSZeroPoint; | 94 NSPoint offset = NSZeroPoint; |
| 148 | 95 |
| 149 if ([window respondsToSelector:@selector(fullScreenButtonOriginAdjustment)]) | 96 if ([window respondsToSelector:@selector(fullScreenButtonOriginAdjustment)]) |
| 150 offset = [window fullScreenButtonOriginAdjustment]; | 97 offset = [window fullScreenButtonOriginAdjustment]; |
| 151 | 98 |
| 152 NSPoint origin = [self _fullScreenButtonOriginOriginal]; | 99 NSPoint origin = [self _fullScreenButtonOriginOriginal]; |
| 153 origin.x += offset.x; | 100 origin.x += offset.x; |
| 154 origin.y += offset.y; | 101 origin.y += offset.y; |
| 155 return origin; | 102 return origin; |
| 156 } | 103 } |
| 157 | 104 |
| 158 @end | 105 @end |
| OLD | NEW |