Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / fullscreen_mode_controller.mm
blobc4043511a433dce710d387b1b1811d44dc9cba74
1 // Copyright 2013 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/fullscreen_mode_controller.h"
7 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
8 #import "chrome/browser/ui/cocoa/browser_window_controller_private.h"
9 #import "chrome/browser/ui/cocoa/fast_resize_view.h"
11 @interface FullscreenModeController (Private)
12 - (void)startAnimationToState:(FullscreenToolbarState)state;
13 - (void)setMenuBarRevealProgress:(CGFloat)progress;
14 - (void)setRevealAnimationProgress:(NSAnimationProgress)progress;
15 @end
17 namespace {
19 OSStatus MenuBarRevealHandler(EventHandlerCallRef handler,
20                               EventRef event,
21                               void* context) {
22   FullscreenModeController* self =
23       static_cast<FullscreenModeController*>(context);
24   CGFloat revealFraction = 0;
25   GetEventParameter(event, FOUR_CHAR_CODE('rvlf'), typeCGFloat, NULL,
26       sizeof(CGFloat), NULL, &revealFraction);
27   [self setMenuBarRevealProgress:revealFraction];
28   return CallNextEventHandler(handler, event);
31 // The duration of the animation to bring down the tabstrip.
32 const NSTimeInterval kAnimationDuration = 0.35;
34 // The height of the tracking area in which mouse entered/exit events will
35 // reveal the tabstrip.
36 const NSUInteger kTrackingAreaHeight = 100;
38 // There is a tiny gap between the window's max Y and the top of the screen,
39 // which will produce a mouse exit event when the menu bar should be revealed.
40 // This factor is the size of that gap plus padding.
41 const CGFloat kTrackingAreaMaxYEpsilon = 15;
43 }  // namespace
45 // Animation ///////////////////////////////////////////////////////////////////
47 @interface FullscreenModeDropDownAnimation : NSAnimation {
48   FullscreenModeController* controller_;
50 @end
52 @implementation FullscreenModeDropDownAnimation
54 - (id)initWithFullscreenModeController:(FullscreenModeController*)controller {
55   if ((self = [super initWithDuration:kAnimationDuration
56                        animationCurve:NSAnimationEaseInOut])) {
57     controller_ = controller;
58     [self setAnimationBlockingMode:NSAnimationNonblocking];
59     [self setDelegate:controller_];
60   }
61   return self;
64 - (void)setCurrentProgress:(NSAnimationProgress)progress {
65   [controller_ setRevealAnimationProgress:progress];
68 @end
70 // Implementation //////////////////////////////////////////////////////////////
72 @implementation FullscreenModeController
74 - (id)initWithBrowserWindowController:(BrowserWindowController*)bwc {
75   if ((self = [super init])) {
76     controller_ = bwc;
78     currentState_ = kFullscreenToolbarOnly;
79     destinationState_ = kFullscreenToolbarOnly;
81     // Create the tracking area at the top of the window.
82     NSRect windowFrame = [[bwc window] frame];
83     NSRect trackingRect = NSMakeRect(
84         0, NSHeight(windowFrame) - kTrackingAreaHeight,
85         NSWidth(windowFrame), kTrackingAreaHeight);
86     trackingArea_.reset(
87         [[CrTrackingArea alloc] initWithRect:trackingRect
88                                      options:NSTrackingMouseEnteredAndExited |
89                                              NSTrackingActiveAlways
90                                        owner:self
91                                     userInfo:nil]);
92     [[[bwc window] contentView] addTrackingArea:trackingArea_.get()];
94     // Install the Carbon event handler for the undocumented menu bar show/hide
95     // event.
96     EventTypeSpec eventSpec = { kEventClassMenu, 2004 };
97     InstallApplicationEventHandler(NewEventHandlerUPP(&MenuBarRevealHandler),
98                                    1, &eventSpec,
99                                    self, &menuBarTrackingHandler_);
100   }
101   return self;
104 - (void)dealloc {
105   RemoveEventHandler(menuBarTrackingHandler_);
106   [[[controller_ window] contentView] removeTrackingArea:trackingArea_.get()];
107   [super dealloc];
110 - (CGFloat)menuBarHeight {
111   // -[NSMenu menuBarHeight] will return 0 when the menu bar is hidden, so
112   // use the status bar API instead, which always returns a constant value.
113   return [[NSStatusBar systemStatusBar] thickness] * menuBarRevealFraction_;
116 - (void)mouseEntered:(NSEvent*)event {
117   if (animation_ || currentState_ == kFullscreenToolbarAndTabstrip)
118     return;
120   [self startAnimationToState:kFullscreenToolbarAndTabstrip];
123 - (void)mouseExited:(NSEvent*)event {
124   if (animation_ || currentState_ == kFullscreenToolbarOnly)
125     return;
127   // Take allowance for the small gap between the window max Y and top edge of
128   // the screen.
129   NSPoint mousePoint = [NSEvent mouseLocation];
130   NSRect screenRect = [[[controller_ window] screen] frame];
131   if (mousePoint.y >= NSMaxY(screenRect) - kTrackingAreaMaxYEpsilon)
132     return;
134   [self startAnimationToState:kFullscreenToolbarOnly];
137 - (void)startAnimationToState:(FullscreenToolbarState)state {
138   DCHECK_NE(currentState_, state);
140   destinationState_ = state;
142   // Turn on fast resize mode to ensure a smooth web contents animation.
143   // TODO(rsesek): This makes the animation jump at the end.
144   [[controller_ tabContentArea] setFastResizeMode:YES];
146   animation_.reset([[FullscreenModeDropDownAnimation alloc]
147       initWithFullscreenModeController:self]);
148   [animation_ startAnimation];
151 - (void)setMenuBarRevealProgress:(CGFloat)progress {
152   menuBarRevealFraction_ = progress;
154   // If an animation is not running, then -layoutSubviews will not be called
155   // for each tick of the menu bar reveal. Do that manually.
156   // TODO(rsesek): This is kind of hacky and janky.
157   if (!animation_)
158     [controller_ layoutSubviews];
161 - (void)setRevealAnimationProgress:(NSAnimationProgress)progress {
162   // When hiding the tabstrip, invert the fraction.
163   if (destinationState_ == kFullscreenToolbarOnly)
164     progress = 1.0 - progress;
165   [controller_ setFloatingBarShownFraction:progress];
168 - (void)animationDidEnd:(NSAnimation*)animation {
169   DCHECK_EQ(animation_.get(), animation);
171   currentState_ = destinationState_;
173   [animation_ setDelegate:nil];
174   animation_.reset();
176   [[controller_ tabContentArea] setFastResizeMode:NO];
179 @end