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