1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "chrome/browser/ui/cocoa/custom_frame_view.h"
#import <Carbon/Carbon.h>
#include <crt_externs.h>
#import <objc/runtime.h>
#include <string.h>
#include "base/logging.h"
#include "base/mac/mac_util.h"
#include "base/mac/scoped_nsautorelease_pool.h"
@interface NSView (Swizzles)
- (NSPoint)_fullScreenButtonOriginOriginal;
@end
@interface NSWindow (FramedBrowserWindow)
- (NSPoint)fullScreenButtonOriginAdjustment;
@end
@interface CustomFrameView : NSView
// Clang emits a warning if designated initializers don't call the super
// initializer, even if the method raises an exception.
// http://www.crbug.com/479019.
- (id)initWithFrame:(NSRect)frame UNAVAILABLE_ATTRIBUTE;
- (id)initWithCoder:(NSCoder*)coder UNAVAILABLE_ATTRIBUTE;
@end
@implementation CustomFrameView
+ (void)load {
// Swizzling should only happen in the browser process. Interacting with
// AppKit will run +[borderViewClass initialize] in the renderer, which
// may establish Mach IPC with com.apple.windowserver.
// Note that CommandLine has not been initialized yet, since this is running
// as a module initializer.
const char* const* const argv = *_NSGetArgv();
const int argc = *_NSGetArgc();
const char kType[] = "--type=";
for (int i = 1; i < argc; ++i) {
const char* arg = argv[i];
if (strncmp(arg, kType, strlen(kType)) == 0)
return;
}
// In Yosemite, the fullscreen button replaces the zoom button. We no longer
// need to swizzle out this AppKit private method.
if (!base::mac::IsOSMavericksOrEarlier())
return;
base::mac::ScopedNSAutoreleasePool pool;
// On 10.8+ the background for textured windows are no longer drawn by
// NSGrayFrame, and NSThemeFrame is used instead <http://crbug.com/114745>.
Class borderViewClass = NSClassFromString(
base::mac::IsOSMountainLionOrLater() ? @"NSThemeFrame" : @"NSGrayFrame");
DCHECK(borderViewClass);
if (!borderViewClass) return;
// Swizzle the method that sets the origin for the Lion fullscreen button.
// Do nothing if it cannot be found.
Method m0 = class_getInstanceMethod([self class],
@selector(_fullScreenButtonOrigin));
if (m0) {
BOOL didAdd = class_addMethod(borderViewClass,
@selector(_fullScreenButtonOriginOriginal),
method_getImplementation(m0),
method_getTypeEncoding(m0));
if (didAdd) {
Method m1 = class_getInstanceMethod(borderViewClass,
@selector(_fullScreenButtonOrigin));
Method m2 = class_getInstanceMethod(
borderViewClass, @selector(_fullScreenButtonOriginOriginal));
if (m1 && m2) {
method_exchangeImplementations(m1, m2);
}
}
}
}
- (id)initWithFrame:(NSRect)frame {
// This class is not for instantiating.
[self doesNotRecognizeSelector:_cmd];
return nil;
}
- (id)initWithCoder:(NSCoder*)coder {
// This class is not for instantiating.
[self doesNotRecognizeSelector:_cmd];
return nil;
}
// Override to move the fullscreen button to the left of the profile avatar.
- (NSPoint)_fullScreenButtonOrigin {
NSWindow* window = [self window];
NSPoint offset = NSZeroPoint;
if ([window respondsToSelector:@selector(fullScreenButtonOriginAdjustment)])
offset = [window fullScreenButtonOriginAdjustment];
NSPoint origin = [self _fullScreenButtonOriginOriginal];
origin.x += offset.x;
origin.y += offset.y;
return origin;
}
@end
|