panel_window_controller_cocoa.mm revision 010d83a9304c5a91596085d917d248abff47903a
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/cocoa/panels/panel_window_controller_cocoa.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#import <Cocoa/Cocoa.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/auto_reset.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/mac/bundle_locations.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/mac/mac_util.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/mac/scoped_nsautorelease_pool.h"
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/sys_string_conversions.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/app/chrome_command_ids.h"  // IDC_*
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chrome_browser_application_mac.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#import "chrome/browser/ui/cocoa/browser_command_executor.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#import "chrome/browser/ui/cocoa/browser_window_utils.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#import "chrome/browser/ui/cocoa/panels/mouse_drag_controller.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#import "chrome/browser/ui/cocoa/panels/panel_cocoa.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#import "chrome/browser/ui/cocoa/panels/panel_titlebar_view_cocoa.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#import "chrome/browser/ui/cocoa/panels/panel_utils_cocoa.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#import "chrome/browser/ui/cocoa/tab_contents/favicon_util_mac.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#import "chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.h"
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#import "chrome/browser/ui/cocoa/sprite_view.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/panels/panel_bounds_animation.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/panels/panel_collection.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/panels/panel_constants.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/panels/panel_manager.h"
3158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/ui/panels/stacked_panel_collection.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/toolbar/encoding_menu_controller.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/render_widget_host_view.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/ui_resources.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMinimumWindowSize = 1;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const double kBoundsAnimationSpeedPixelsPerSecond = 1000;
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const double kBoundsAnimationMaxDurationSeconds = 0.18;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Edge thickness to trigger user resizing via system, in screen pixels.
4758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const double kWidthOfMouseResizeArea = 15.0;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@interface PanelWindowControllerCocoa (PanelsCanBecomeKey)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Internal helper method for extracting the total number of panel windows
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from the panel manager. Used to decide if panel can become the key window.
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (int)numPanels;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@end
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@implementation PanelWindowCocoaImpl
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The panels cannot be reduced to 3-px windows on the edge of the screen
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// active area (above Dock). Default constraining logic makes at least a height
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of the titlebar visible, so the user could still grab it. We do 'restore'
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// differently, and minimize panels to 3 px. Hence the need to override the
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// constraining logic.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen *)screen {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return frameRect;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Prevent panel window from becoming key - for example when it is minimized.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Panel windows use a higher priority NSWindowLevel to ensure they are always
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// visible, causing the OS to prefer panel windows when selecting a window
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to make the key window. To counter this preference, we override
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -[NSWindow:canBecomeKeyWindow] to restrict when the panel can become the
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// key window to a limited set of scenarios, such as when cycling through
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// windows, when panels are the only remaining windows, when an event
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// triggers window activation, etc. The panel may also be prevented from
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// becoming the key window, regardless of the above scenarios, such as when
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a panel is minimized.
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (BOOL)canBecomeKeyWindow {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Give precedence to controller preventing activation of the window.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PanelWindowControllerCocoa* controller =
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::mac::ObjCCast<PanelWindowControllerCocoa>([self windowController]);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (![controller canBecomeKeyWindow])
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NO;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserCrApplication* app = base::mac::ObjCCast<BrowserCrApplication>(
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      [BrowserCrApplication sharedApplication]);
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A Panel window can become the key window only in limited scenarios.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This prevents the system from always preferring a Panel window due
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to its higher priority NSWindowLevel when selecting a window to make key.
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ([app isHandlingSendEvent]  && [[app currentEvent] window] == self) ||
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      [controller activationRequestedByPanel] ||
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      [app isCyclingWindows] ||
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      [app previousKeyWindow] == self ||
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      [[app windows] count] == static_cast<NSUInteger>([controller numPanels]);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch- (void)performMiniaturize:(id)sender {
96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  [[self windowController] minimizeButtonClicked:0];
97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
98eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Ignore key events if window cannot become key window to fix problem
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// where keyboard input is still going into a minimized panel even though
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the app has been deactivated in -[PanelWindowControllerCocoa deactivate:].
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)sendEvent:(NSEvent*)anEvent {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSEventType eventType = [anEvent type];
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((eventType == NSKeyDown || eventType == NSKeyUp) &&
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ![self canBecomeKeyWindow])
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [super sendEvent:anEvent];
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)- (void)mouseMoved:(NSEvent*)event {
11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Cocoa does not support letting the application determine the edges that
11258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // can trigger the user resizing. To work around this, we track the mouse
11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // location. When it is close to the edge/corner where the user resizing
11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // is not desired, we force the min and max size of the window to be same
11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // as current window size. For all other cases, we restore the min and max
11658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // size.
11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  PanelWindowControllerCocoa* controller =
11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      base::mac::ObjCCast<PanelWindowControllerCocoa>([self windowController]);
11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  NSRect frame = [self frame];
12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if ([controller canResizeByMouseAtCurrentLocation]) {
12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Mac window server limits window sizes to 10000.
12258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    NSSize maxSize = NSMakeSize(10000, 10000);
12358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
12458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // If the user is resizing a stacked panel by its bottom edge, make sure its
12558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // height cannot grow more than what the panel below it could offer. This is
12658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // because growing a stacked panel by y amount will shrink the panel below
12758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // it by same amount and we do not want the panel below it being shrunk to
12858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // be smaller than the titlebar.
12958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    Panel* panel = [controller panel];
13058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    NSPoint point = [NSEvent mouseLocation];
13158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (point.y < NSMinY(frame) + kWidthOfMouseResizeArea && panel->stack()) {
13258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      Panel* belowPanel = panel->stack()->GetPanelBelow(panel);
13358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      if (belowPanel && !belowPanel->IsMinimized()) {
13458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        maxSize.height = panel->GetBounds().height() +
13558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            belowPanel->GetBounds().height() - panel::kTitlebarHeight;
13658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      }
13758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Enable the user-resizing by setting both min and max size to the right
14058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // values.
14158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    [self setMinSize:NSMakeSize(panel::kPanelMinWidth,
14258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                panel::kPanelMinHeight)];
14358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    [self setMaxSize:maxSize];
14458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  } else {
14558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Disable the user-resizing by setting both min and max size to be same as
14658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // current window size.
14758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    [self setMinSize:frame.size];
14858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    [self setMaxSize:frame.size];
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  [super mouseMoved:event];
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@end
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ChromeEventProcessingWindow expects its controller to implement the
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BrowserCommandExecutor protocol.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@interface PanelWindowControllerCocoa (InternalAPI) <BrowserCommandExecutor>
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BrowserCommandExecutor methods.
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)executeCommand:(int)command;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@end
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@implementation PanelWindowControllerCocoa (InternalAPI)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This gets called whenever a browser-specific keyboard shortcut is performed
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the Panel window. We simply swallow all those events.
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)executeCommand:(int)command {}
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@end
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@implementation PanelWindowControllerCocoa
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (id)initWithPanel:(PanelCocoa*)window {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSString* nibpath =
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      [base::mac::FrameworkBundle() pathForResource:@"Panel" ofType:@"nib"];
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((self = [super initWithWindowNibPath:nibpath owner:self])) {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    windowShim_.reset(window);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    animateOnBoundsChange_ = YES;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    canBecomeKeyWindow_ = YES;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    activationRequestedByPanel_ = NO;
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return self;
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)- (Panel*)panel {
18758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return windowShim_->panel();
18858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
18958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)awakeFromNib {
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSWindow* window = [self window];
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(window);
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(titlebar_view_);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(self, [window delegate]);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [self updateWindowLevel];
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  [self updateWindowCollectionBehavior];
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [titlebar_view_ attach];
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set initial size of the window to match the size of the panel to give
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the renderer the proper size to work with earlier, avoiding a resize
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // after the window is revealed.
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect panelBounds = windowShim_->panel()->GetBounds();
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSRect frame = [window frame];
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame.size.width = panelBounds.width();
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  frame.size.height = panelBounds.height();
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [window setFrame:frame display:NO];
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // MacOS will turn the user-resizing to the user-dragging if the direction of
21358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // the dragging is orthogonal to the direction of the arrow cursor. We do not
21458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // want this since it will bypass our dragging logic. The panel window is
21558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // still draggable because we track and handle the dragging in our custom way.
21658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  [[self window] setMovable:NO];
21758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
21858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  [self updateTrackingArea];
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)- (void)updateWebContentsViewFrame {
222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  content::WebContents* webContents = windowShim_->panel()->GetWebContents();
223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!webContents)
224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Compute the size of the web contents view. Don't assume it's similar to the
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // size of the contentView, because the contentView is managed by the Cocoa
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to be (window - standard titlebar), while we have taller custom titlebar
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // instead. In coordinate system of window's contentView.
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSRect contentFrame = [self contentRectForFrameRect:[[self window] frame]];
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  contentFrame.origin = NSZeroPoint;
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
233010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  NSView* contentView = webContents->GetNativeView();
234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!NSEqualRects([contentView frame], contentFrame))
235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    [contentView setFrame:contentFrame];
236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)- (void)disableWebContentsViewAutosizing {
239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  [[[self window] contentView] setAutoresizesSubviews:NO];
240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)- (void)enableWebContentsViewAutosizing {
243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  [self updateWebContentsViewFrame];
244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  [[[self window] contentView] setAutoresizesSubviews:YES];
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)revealAnimatedWithFrame:(const NSRect&)frame {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSWindow* window = [self window];  // This ensures loading the nib.
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Disable subview resizing while resizing the window to avoid renderer
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // resizes during intermediate stages of animation.
252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  [self disableWebContentsViewAutosizing];
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We grow the window from the bottom up to produce a 'reveal' animation.
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSRect startFrame = NSMakeRect(NSMinX(frame), NSMinY(frame),
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 NSWidth(frame), kMinimumWindowSize);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [window setFrame:startFrame display:NO animate:NO];
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Shows the window without making it key, on top of its layer, even if
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Chromium is not an active app.
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [window orderFrontRegardless];
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(dcheng): Temporary hack to work around the fact that
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // orderFrontRegardless causes us to become the first responder. The usual
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Chrome assumption is that becoming the first responder = you have focus, so
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we always deactivate the controls here. If we're created as an active
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // panel, we'll get a NSWindowDidBecomeKeyNotification and reactivate the web
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // view properly. See crbug.com/97831 for more details.
267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  WebContents* web_contents = windowShim_->panel()->GetWebContents();
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RWHV may be NULL in unit tests.
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (web_contents && web_contents->GetRenderWidgetHostView())
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    web_contents->GetRenderWidgetHostView()->SetActive(false);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This will re-enable the content resizing after it finishes.
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [self setPanelFrame:frame animate:YES];
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)updateTitleBar {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSString* newTitle = base::SysUTF16ToNSString(
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      windowShim_->panel()->GetWindowTitle());
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pendingWindowTitle_.reset(
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      [BrowserWindowUtils scheduleReplaceOldTitle:pendingWindowTitle_.get()
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     withNewTitle:newTitle
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        forWindow:[self window]]);
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [titlebar_view_ setTitle:newTitle];
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [self updateIcon];
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)updateIcon {
288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::scoped_nsobject<NSView> iconView;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (throbberShouldSpin_) {
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If the throbber is spinning now, no need to replace it.
291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if ([[titlebar_view_ icon] isKindOfClass:[SpriteView class]])
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NSImage* iconImage =
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ResourceBundle::GetSharedInstance().GetNativeImageNamed(
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            IDR_THROBBER).ToNSImage();
297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    SpriteView* spriteView = [[SpriteView alloc] init];
298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    [spriteView setImage:iconImage];
299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    iconView.reset(spriteView);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gfx::Image& page_icon = windowShim_->panel()->GetCurrentPageIcon();
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    NSRect iconFrame = [[titlebar_view_ icon] frame];
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NSImage* iconImage = page_icon.IsEmpty() ?
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        rb.GetNativeImageNamed(IDR_DEFAULT_FAVICON).ToNSImage() :
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        page_icon.ToNSImage();
307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    NSImageView* imageView = [[NSImageView alloc] initWithFrame:iconFrame];
308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    [imageView setImage:iconImage];
309a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    iconView.reset(imageView);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  [titlebar_view_ setIcon:iconView];
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)updateThrobber:(BOOL)shouldSpin {
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (throbberShouldSpin_ == shouldSpin)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  throbberShouldSpin_ = shouldSpin;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the titlebar view has not been attached, bail out.
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!titlebar_view_)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [self updateIcon];
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)updateTitleBarMinimizeRestoreButtonVisibility {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Panel* panel = windowShim_->panel();
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  [titlebar_view_ setMinimizeButtonVisibility:panel->CanShowMinimizeButton()];
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  [titlebar_view_ setRestoreButtonVisibility:panel->CanShowRestoreButton()];
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)webContentsInserted:(WebContents*)contents {
333010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  NSView* view = contents->GetNativeView();
334868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  [[[self window] contentView] addSubview:view];
335868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  [view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
336868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
337868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  [self enableWebContentsViewAutosizing];
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)webContentsDetached:(WebContents*)contents {
341010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  [contents->GetNativeView() removeFromSuperview];
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (PanelTitlebarViewCocoa*)titlebarView {
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return titlebar_view_;
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Called to validate menu and toolbar items when this window is key. All the
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// items we care about have been set with the |-commandDispatch:|
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// action and a target of FirstResponder in IB.
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Delegate to the NSApp delegate if Panel does not care about the command or
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// shortcut, to make sure the global items in Chrome main app menu still work.
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item {
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if ([item action] == @selector(commandDispatch:)) {
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NSInteger tag = [item tag];
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CommandUpdater* command_updater = windowShim_->panel()->command_updater();
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (command_updater->SupportsCommand(tag))
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return command_updater->IsCommandEnabled(tag);
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return [[NSApp delegate] validateUserInterfaceItem:item];
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return NO;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Called when the user picks a menu or toolbar item when this window is key.
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Calls through to the panel object to execute the command or delegates up.
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)commandDispatch:(id)sender {
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(sender);
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NSInteger tag = [sender tag];
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CommandUpdater* command_updater = windowShim_->panel()->command_updater();
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (command_updater->SupportsCommand(tag))
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    windowShim_->panel()->ExecuteCommandIfEnabled(tag);
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    [[NSApp delegate] commandDispatch:sender];
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Handler for the custom Close button.
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)closePanel {
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  windowShim_->panel()->Close();
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Handler for the custom Minimize button.
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)minimizeButtonClicked:(int)modifierFlags {
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Panel* panel = windowShim_->panel();
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  panel->OnMinimizeButtonClicked((modifierFlags & NSShiftKeyMask) ?
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 panel::APPLY_TO_ALL : panel::NO_MODIFIER);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Handler for the custom Restore button.
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)restoreButtonClicked:(int)modifierFlags {
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Panel* panel = windowShim_->panel();
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  panel->OnRestoreButtonClicked((modifierFlags & NSShiftKeyMask) ?
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                panel::APPLY_TO_ALL : panel::NO_MODIFIER);
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Called when the user wants to close the panel or from the shutdown process.
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The Panel object is in control of whether or not we're allowed to close. It
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// may defer closing due to several states, such as onbeforeUnload handlers
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// needing to be fired. If closing is deferred, the Panel will handle the
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// processing required to get us to the closing state and (by watching for
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the web content going away) will again call to close the window when it's
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// finally ready.
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (BOOL)windowShouldClose:(id)sender {
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Panel* panel = windowShim_->panel();
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Give beforeunload handlers the chance to cancel the close before we hide
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the window below.
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!panel->ShouldCloseWindow())
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NO;
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (panel->GetWebContents()) {
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Terminate any playing animations.
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [self terminateBoundsAnimation];
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    animateOnBoundsChange_ = NO;
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make panel close the web content, allowing the renderer to shut down
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // and call us back again.
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    panel->OnWindowClosing();
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NO;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No web content; it's ok to close the window.
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return YES;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When windowShouldClose returns YES (or if controller receives direct 'close'
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// signal), window will be unconditionally closed. Clean up.
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)windowWillClose:(NSNotification*)notification {
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!windowShim_->panel()->GetWebContents());
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Avoid callbacks from a nonblocking animation in progress, if any.
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [self terminateBoundsAnimation];
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  windowShim_->DidCloseNativeWindow();
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Call |-autorelease| after a zero-length delay to avoid deadlock from
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // code in the current run loop that waits on PANEL_CLOSED notification.
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The notification is sent when this object is freed, but this object
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cannot be freed until the current run loop completes.
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [self performSelector:@selector(autorelease)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             withObject:nil
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             afterDelay:0];
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)startDrag:(NSPoint)mouseLocation {
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convert from Cocoa's screen coordinates to platform-indepedent screen
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // coordinates because PanelManager method takes platform-indepedent screen
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // coordinates.
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  windowShim_->panel()->manager()->StartDragging(
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      windowShim_->panel(),
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cocoa_utils::ConvertPointFromCocoaCoordinates(mouseLocation));
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)endDrag:(BOOL)cancelled {
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  windowShim_->panel()->manager()->EndDragging(cancelled);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)drag:(NSPoint)mouseLocation {
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Convert from Cocoa's screen coordinates to platform-indepedent screen
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // coordinates because PanelManager method takes platform-indepedent screen
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // coordinates.
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  windowShim_->panel()->manager()->Drag(
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      cocoa_utils::ConvertPointFromCocoaCoordinates(mouseLocation));
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)setPanelFrame:(NSRect)frame
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              animate:(BOOL)animate {
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BOOL jumpToDestination = (!animateOnBoundsChange_ || !animate);
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If no animation is in progress, apply bounds change instantly.
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (jumpToDestination && ![self isAnimatingBounds]) {
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [[self window] setFrame:frame display:YES animate:NO];
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSDictionary *windowResize = [NSDictionary dictionaryWithObjectsAndKeys:
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      [self window], NSViewAnimationTargetKey,
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      [NSValue valueWithRect:frame], NSViewAnimationEndFrameKey, nil];
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSArray *animations = [NSArray arrayWithObjects:windowResize, nil];
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If an animation is in progress, update the animation with new target
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bounds. Also, set the destination frame bounds to the new value.
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (jumpToDestination && [self isAnimatingBounds]) {
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [boundsAnimation_ setViewAnimations:animations];
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [[self window] setFrame:frame display:YES animate:NO];
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Will be enabled back in animationDidEnd callback.
485868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  [self disableWebContentsViewAutosizing];
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Terminate previous animation, if it is still playing.
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [self terminateBoundsAnimation];
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  boundsAnimation_ =
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      [[NSViewAnimation alloc] initWithViewAnimations:animations];
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [boundsAnimation_ setDelegate:self];
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSRect currentFrame = [[self window] frame];
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Compute duration. We use constant speed of animation, however if the change
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is too large, we clip the duration (effectively increasing speed) to
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // limit total duration of animation. This makes 'small' transitions fast.
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 'distance' is the max travel between 4 potentially traveling corners.
499a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  double distanceX = std::max(std::abs(NSMinX(currentFrame) - NSMinX(frame)),
500a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                              std::abs(NSMaxX(currentFrame) - NSMaxX(frame)));
501a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  double distanceY = std::max(std::abs(NSMinY(currentFrame) - NSMinY(frame)),
502a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                              std::abs(NSMaxY(currentFrame) - NSMaxY(frame)));
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double distance = std::max(distanceX, distanceY);
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  double duration = std::min(distance / kBoundsAnimationSpeedPixelsPerSecond,
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             kBoundsAnimationMaxDurationSeconds);
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Detect animation that happens when expansion state is set to MINIMIZED
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and there is relatively big portion of the panel to hide from view.
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize animation differently in this case, using fast-pause-slow
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // method, see below for more details.
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (distanceY > 0 &&
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      windowShim_->panel()->expansion_state() == Panel::MINIMIZED) {
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    animationStopToShowTitlebarOnly_ = 1.0 -
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (windowShim_->panel()->TitleOnlyHeight() - NSHeight(frame)) / distanceY;
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (animationStopToShowTitlebarOnly_ > 0.7) {  // Relatively big movement.
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      playingMinimizeAnimation_ = YES;
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      duration = 1.5;
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [boundsAnimation_ setDuration: PanelManager::AdjustTimeInterval(duration)];
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [boundsAnimation_ setFrameRate:0.0];
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [boundsAnimation_ setAnimationBlockingMode: NSAnimationNonblocking];
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [boundsAnimation_ startAnimation];
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (float)animation:(NSAnimation*)animation
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  valueForProgress:(NSAnimationProgress)progress {
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PanelBoundsAnimation::ComputeAnimationValue(
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      progress, playingMinimizeAnimation_, animationStopToShowTitlebarOnly_);
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)cleanupAfterAnimation {
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  playingMinimizeAnimation_ = NO;
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!windowShim_->panel()->IsMinimized())
534868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    [self enableWebContentsViewAutosizing];
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)animationDidEnd:(NSAnimation*)animation {
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [self cleanupAfterAnimation];
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only invoke this callback from animationDidEnd, since animationDidStop can
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be called when we interrupt/restart animation which is in progress.
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We only need this notification when animation indeed finished moving
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the panel bounds.
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Panel* panel = windowShim_->panel();
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  panel->manager()->OnPanelAnimationEnded(panel);
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)animationDidStop:(NSAnimation*)animation {
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [self cleanupAfterAnimation];
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)terminateBoundsAnimation {
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!boundsAnimation_)
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [boundsAnimation_ stopAnimation];
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [boundsAnimation_ setDelegate:nil];
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [boundsAnimation_ release];
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  boundsAnimation_ = nil;
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (BOOL)isAnimatingBounds {
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return boundsAnimation_ && [boundsAnimation_ isAnimating];
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)onTitlebarMouseClicked:(int)modifierFlags {
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Panel* panel = windowShim_->panel();
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  panel->OnTitlebarClicked((modifierFlags & NSShiftKeyMask) ?
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           panel::APPLY_TO_ALL : panel::NO_MODIFIER);
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
571424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)- (void)onTitlebarDoubleClicked:(int)modifierFlags {
572424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Double-clicking is only allowed to minimize docked panels.
573424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  Panel* panel = windowShim_->panel();
574424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (panel->collection()->type() != PanelCollection::DOCKED ||
575424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      panel->IsMinimized())
576424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
577424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  [self minimizeButtonClicked:modifierFlags];
578424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
579424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (int)titlebarHeightInScreenCoordinates {
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSView* titlebar = [self titlebarView];
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NSHeight([titlebar convertRect:[titlebar bounds] toView:nil]);
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(dcheng): These two selectors are almost copy-and-paste from
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BrowserWindowController. Figure out the appropriate way of code sharing,
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// whether it's refactoring more things into BrowserWindowUtils or making a
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// common base controller for browser windows.
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)windowDidBecomeKey:(NSNotification*)notification {
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need to activate the controls (in the "WebView"). To do this, get the
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // selected WebContents's RenderWidgetHostView and tell it to activate.
592868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (WebContents* contents = windowShim_->panel()->GetWebContents()) {
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (content::RenderWidgetHostView* rwhv =
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        contents->GetRenderWidgetHostView())
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rwhv->SetActive(true);
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  windowShim_->panel()->OnActiveStateChanged(true);
59958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
60058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Make the window user-resizable when it gains the focus.
60158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  [[self window] setStyleMask:
60258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      [[self window] styleMask] | NSResizableWindowMask];
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)windowDidResignKey:(NSNotification*)notification {
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If our app is still active and we're still the key window, ignore this
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // message, since it just means that a menu extra (on the "system status bar")
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // was activated; we'll get another |-windowDidResignKey| if we ever really
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // lose key window status.
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ([NSApp isActive] && ([NSApp keyWindow] == [self window]))
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [self onWindowDidResignKey];
61458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
61558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Make the window not user-resizable when it loses the focus. This is to
61658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // solve the problem that the bottom edge of the active panel does not
61758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // trigger the user-resizing if this panel stacks with another inactive
61858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // panel at the bottom.
61958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  [[self window] setStyleMask:
62058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      [[self window] styleMask] & ~NSResizableWindowMask];
62158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
62258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
62358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)- (void)windowWillStartLiveResize:(NSNotification*)notification {
62458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Check if the user-resizing is allowed for the triggering edge/corner.
62558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // This is an extra safe guard because we are not able to track the mouse
62658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // movement outside the window and Cocoa could trigger the user-resizing
62758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // when the mouse moves a bit outside the edge/corner.
62858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (![self canResizeByMouseAtCurrentLocation])
62958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return;
63058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  userResizing_ = YES;
63158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  windowShim_->panel()->OnPanelStartUserResizing();
63258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
63358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
63458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)- (void)windowDidEndLiveResize:(NSNotification*)notification {
63558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!userResizing_)
63658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return;
63758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  userResizing_ = NO;
63858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
63958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  Panel* panel = windowShim_->panel();
64058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  panel->OnPanelEndUserResizing();
64158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
64258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  gfx::Rect newBounds =
64358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      cocoa_utils::ConvertRectFromCocoaCoordinates([[self window] frame]);
64458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (windowShim_->panel()->GetBounds() == newBounds)
64558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return;
64658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  windowShim_->set_cached_bounds_directly(newBounds);
64758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
64858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  panel->IncreaseMaxSize(newBounds.size());
64958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  panel->set_full_size(newBounds.size());
65058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
65158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  panel->collection()->RefreshLayout();
65258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
65358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
65458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)- (NSSize)windowWillResize:(NSWindow*)sender toSize:(NSSize)newSize {
65558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // As an extra safe guard, we avoid the user resizing if it is deemed not to
65658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // be allowed (see comment in windowWillStartLiveResize).
65758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if ([[self window] inLiveResize] && !userResizing_)
65858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return [[self window] frame].size;
65958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return newSize;
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
662868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)- (void)windowDidResize:(NSNotification*)notification {
66358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  Panel* panel = windowShim_->panel();
66458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (userResizing_) {
66558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    panel->collection()->OnPanelResizedByMouse(
66658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        panel,
66758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        cocoa_utils::ConvertRectFromCocoaCoordinates([[self window] frame]));
66858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
66958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
67058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  [self updateTrackingArea];
67158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
67258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (![self isAnimatingBounds] ||
67358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      panel->collection()->type() != PanelCollection::DOCKED)
67458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return;
67558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
676c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch  // Remove the web contents view from the view hierarchy when the panel is not
677c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch  // taller than the titlebar. Put it back when the panel grows taller than
678c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch  // the titlebar. Note that RenderWidgetHostViewMac works for the case that
679c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch  // the web contents view does not exist in the view hierarchy (i.e. the tab
680c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch  // is not the main one), but it does not work well, like causing occasional
681c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch  // crashes (http://crbug.com/265932), if the web contents view is made hidden.
682c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch  //
68358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // This is needed when the docked panels are being animated. When the
68458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // animation starts, the contents view autosizing is disabled. After the
68558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // animation ends, the contents view autosizing is reenabled and the frame
68658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // of contents view is updated. Thus it is likely that the contents view will
68758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // overlap with the titlebar view when the panel shrinks to be very small.
68858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // The implementation of the web contents view assumes that it will never
68958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // overlap with another view in order to paint the web contents view directly.
69058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  content::WebContents* webContents = panel->GetWebContents();
691c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch  if (!webContents)
6923240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch    return;
693010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  NSView* contentView = webContents->GetNativeView();
69458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (NSHeight([self contentRectForFrameRect:[[self window] frame]]) <= 0) {
695c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch    // No need to retain the view before it is removed from its superview
696c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch    // because WebContentsView keeps a reference to this view.
697c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch    if ([contentView superview])
698c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      [contentView removeFromSuperview];
699c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch  } else {
700424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (![contentView superview]) {
701c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch      [[[self window] contentView] addSubview:contentView];
702424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
703424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // When the web contents view is put back, we need to tell its render
704424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // widget host view to accept focus.
705424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      content::RenderWidgetHostView* rwhv =
706424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          webContents->GetRenderWidgetHostView();
707424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      if (rwhv) {
708424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        [[self window] makeFirstResponder:rwhv->GetNativeView()];
709424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        rwhv->SetActive([[self window] isMainWindow]);
710424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      }
711424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
712868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
713868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
714868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)activate {
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Activate the window. -|windowDidBecomeKey:| will be called when
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // window becomes active.
7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::AutoReset<BOOL> pin(&activationRequestedByPanel_, true);
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [BrowserWindowUtils activateWindowForController:self];
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)deactivate {
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (![[self window] isMainWindow])
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cocoa does not support deactivating a window, so we deactivate the app.
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [NSApp deactivate];
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Deactivating the app does not trigger windowDidResignKey. Do it manually.
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [self onWindowDidResignKey];
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)onWindowDidResignKey {
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need to deactivate the controls (in the "WebView"). To do this, get the
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // selected WebContents's RenderWidgetHostView and tell it to deactivate.
736868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (WebContents* contents = windowShim_->panel()->GetWebContents()) {
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (content::RenderWidgetHostView* rwhv =
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        contents->GetRenderWidgetHostView())
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      rwhv->SetActive(false);
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  windowShim_->panel()->OnActiveStateChanged(false);
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)preventBecomingKeyWindow:(BOOL)prevent {
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  canBecomeKeyWindow_ = !prevent;
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)fullScreenModeChanged:(bool)isFullScreen {
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [self updateWindowLevel];
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If the panel is not always on top, its z-order should not be affected if
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // some other window enters fullscreen mode.
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!windowShim_->panel()->IsAlwaysOnTop())
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The full-screen window is in normal level and changing the panel window
7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to same normal level will not move it below the full-screen window. Thus
7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // we need to reorder the panel window.
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (isFullScreen)
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    [[self window] orderOut:nil];
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [[self window] orderFrontRegardless];
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (BOOL)canBecomeKeyWindow {
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Panel can only gain focus if it is expanded. Minimized panels do not
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // participate in Cmd-~ rotation.
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(dimich): If it will be ever desired to expand/focus the Panel on
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // keyboard navigation or via main menu, the care should be taken to avoid
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cases when minimized Panel is getting keyboard input, invisibly.
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return canBecomeKeyWindow_;
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (int)numPanels {
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return windowShim_->panel()->manager()->num_panels();
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (BOOL)activationRequestedByPanel {
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return activationRequestedByPanel_;
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)updateWindowLevel {
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [self updateWindowLevel:windowShim_->panel()->IsMinimized()];
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)updateWindowLevel:(BOOL)panelIsMinimized {
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (![self isWindowLoaded])
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Panel* panel = windowShim_->panel();
7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!panel->IsAlwaysOnTop()) {
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [[self window] setLevel:NSNormalWindowLevel];
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we simply use NSStatusWindowLevel (25) for all docked panel windows,
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IME composition windows for things like CJK languages appear behind panels.
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Pre 10.7, IME composition windows have a window level of 19, which is
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // lower than the dock at level 20. Since we want panels to appear on top of
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the dock, it is impossible to enforce an ordering where IME > panel > dock,
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // since IME < dock.
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On 10.7, IME composition windows and the dock both live at level 20, so we
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // use the same window level for panels. Since newly created windows appear at
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the top of their window level, panels are typically on top of the dock, and
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the IME composition window correctly draws over the panel.
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // An autohide dock causes problems though: since it's constantly being
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // revealed, it ends up drawing on top of other windows at the same level.
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // While this is OK for expanded panels, it makes minimized panels impossible
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to activate. As a result, we still use NSStatusWindowLevel for minimized
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // panels, since it's impossible to compose IME text in them anyway.
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (panelIsMinimized) {
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    [[self window] setLevel:NSStatusWindowLevel];
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  [[self window] setLevel:NSDockWindowLevel];
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)- (void)updateWindowCollectionBehavior {
8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (![self isWindowLoaded])
8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NSWindowCollectionBehavior collectionBehavior =
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NSWindowCollectionBehaviorParticipatesInCycle;
8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (windowShim_->panel()->IsAlwaysOnTop())
8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    collectionBehavior |= NSWindowCollectionBehaviorCanJoinAllSpaces;
8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  [[self window] setCollectionBehavior:collectionBehavior];
8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
82758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)- (void)updateTrackingArea {
82858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  NSView* superview = [[[self window] contentView] superview];
82958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
83058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (trackingArea_.get())
83158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    [superview removeTrackingArea:trackingArea_.get()];
83258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
83358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  trackingArea_.reset(
83458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          [[CrTrackingArea alloc] initWithRect:[superview bounds]
83558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                       options:NSTrackingInVisibleRect |
83658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                               NSTrackingMouseMoved |
83758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                               NSTrackingActiveInKeyWindow
83858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                         owner:superview
83958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                      userInfo:nil]);
84058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  [superview addTrackingArea:trackingArea_.get()];
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
843c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)- (void)showShadow:(BOOL)show {
844c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (![self isWindowLoaded])
845c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
846c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  [[self window] setHasShadow:show];
847c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
848c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
849c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)- (void)miniaturize {
850c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  [[self window] miniaturize:nil];
851c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
852c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
853c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)- (BOOL)isMiniaturized {
854c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return [[self window] isMiniaturized];
855c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
856c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
85758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)- (BOOL)canResizeByMouseAtCurrentLocation {
85858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  panel::Resizability resizability = windowShim_->panel()->CanResizeByMouse();
85958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  NSRect frame = [[self window] frame];
86058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  NSPoint point = [NSEvent mouseLocation];
86158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
86258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (point.y < NSMinY(frame) + kWidthOfMouseResizeArea) {
86358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (point.x < NSMinX(frame) + kWidthOfMouseResizeArea &&
86458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        (resizability & panel::RESIZABLE_BOTTOM_LEFT) == 0) {
86558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return NO;
86658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
86758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (point.x > NSMaxX(frame) - kWidthOfMouseResizeArea &&
86858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        (resizability & panel::RESIZABLE_BOTTOM_RIGHT) == 0) {
86958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return NO;
87058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
87158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if ((resizability & panel::RESIZABLE_BOTTOM) == 0)
87258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return NO;
87358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  } else if (point.y > NSMaxY(frame) - kWidthOfMouseResizeArea) {
87458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (point.x < NSMinX(frame) + kWidthOfMouseResizeArea &&
87558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        (resizability & panel::RESIZABLE_TOP_LEFT) == 0) {
87658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return NO;
87758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
87858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (point.x > NSMaxX(frame) - kWidthOfMouseResizeArea &&
87958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        (resizability & panel::RESIZABLE_TOP_RIGHT) == 0) {
88058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return NO;
88158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
88258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if ((resizability & panel::RESIZABLE_TOP) == 0)
88358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return NO;
88458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  } else {
88558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (point.x < NSMinX(frame) + kWidthOfMouseResizeArea &&
88658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        (resizability & panel::RESIZABLE_LEFT) == 0) {
88758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return NO;
88858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
88958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (point.x > NSMaxX(frame) - kWidthOfMouseResizeArea &&
89058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        (resizability & panel::RESIZABLE_RIGHT) == 0) {
89158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return NO;
89258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
89358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
89458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return YES;
89558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
89658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We have custom implementation of these because our titlebar height is custom
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and does not match the standard one.
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (NSRect)frameRectForContentRect:(NSRect)contentRect {
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // contentRect is in contentView coord system. We should add a titlebar on top
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and then convert to the windows coord system.
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  contentRect.size.height += panel::kTitlebarHeight;
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSRect frameRect = [[[self window] contentView] convertRect:contentRect
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                       toView:nil];
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return frameRect;
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (NSRect)contentRectForFrameRect:(NSRect)frameRect {
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NSRect contentRect = [[[self window] contentView] convertRect:frameRect
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                       fromView:nil];
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  contentRect.size.height -= panel::kTitlebarHeight;
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (contentRect.size.height < 0)
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    contentRect.size.height = 0;
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return contentRect;
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@end
918