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