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" 2403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#import "chrome/browser/ui/cocoa/sprite_view.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#import "chrome/browser/ui/cocoa/tab_contents/favicon_util_mac.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#import "chrome/browser/ui/cocoa/tab_contents/tab_contents_controller.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 "ui/base/resource/resource_bundle.h" 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/image/image.h" 3803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "ui/resources/grit/ui_resources.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 9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)- (void)mouseMoved:(NSEvent*)event { 10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Cocoa does not support letting the application determine the edges that 10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // can trigger the user resizing. To work around this, we track the mouse 10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // location. When it is close to the edge/corner where the user resizing 10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // is not desired, we force the min and max size of the window to be same 10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // as current window size. For all other cases, we restore the min and max 10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // size. 10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) PanelWindowControllerCocoa* controller = 10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) base::mac::ObjCCast<PanelWindowControllerCocoa>([self windowController]); 10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) NSRect frame = [self frame]; 10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if ([controller canResizeByMouseAtCurrentLocation]) { 11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Mac window server limits window sizes to 10000. 11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) NSSize maxSize = NSMakeSize(10000, 10000); 11258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 11358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // If the user is resizing a stacked panel by its bottom edge, make sure its 11458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // height cannot grow more than what the panel below it could offer. This is 11558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // because growing a stacked panel by y amount will shrink the panel below 11658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // it by same amount and we do not want the panel below it being shrunk to 11758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // be smaller than the titlebar. 11858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) Panel* panel = [controller panel]; 11958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) NSPoint point = [NSEvent mouseLocation]; 12058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (point.y < NSMinY(frame) + kWidthOfMouseResizeArea && panel->stack()) { 12158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) Panel* belowPanel = panel->stack()->GetPanelBelow(panel); 12258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (belowPanel && !belowPanel->IsMinimized()) { 12358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) maxSize.height = panel->GetBounds().height() + 12458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) belowPanel->GetBounds().height() - panel::kTitlebarHeight; 12558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 12658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Enable the user-resizing by setting both min and max size to the right 12958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // values. 13058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) [self setMinSize:NSMakeSize(panel::kPanelMinWidth, 13158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) panel::kPanelMinHeight)]; 13258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) [self setMaxSize:maxSize]; 13358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } else { 13458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Disable the user-resizing by setting both min and max size to be same as 13558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // current window size. 13658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) [self setMinSize:frame.size]; 13758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) [self setMaxSize:frame.size]; 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) [super mouseMoved:event]; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@end 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ChromeEventProcessingWindow expects its controller to implement the 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BrowserCommandExecutor protocol. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@interface PanelWindowControllerCocoa (InternalAPI) <BrowserCommandExecutor> 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BrowserCommandExecutor methods. 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)executeCommand:(int)command; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@end 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@implementation PanelWindowControllerCocoa (InternalAPI) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This gets called whenever a browser-specific keyboard shortcut is performed 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in the Panel window. We simply swallow all those events. 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)executeCommand:(int)command {} 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@end 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@implementation PanelWindowControllerCocoa 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (id)initWithPanel:(PanelCocoa*)window { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NSString* nibpath = 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [base::mac::FrameworkBundle() pathForResource:@"Panel" ofType:@"nib"]; 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((self = [super initWithWindowNibPath:nibpath owner:self])) { 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windowShim_.reset(window); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animateOnBoundsChange_ = YES; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canBecomeKeyWindow_ = YES; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) activationRequestedByPanel_ = NO; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return self; 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)- (Panel*)panel { 17658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return windowShim_->panel(); 17758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 17858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)awakeFromNib { 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NSWindow* window = [self window]; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(window); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(titlebar_view_); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(self, [window delegate]); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [self updateWindowLevel]; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) [self updateWindowCollectionBehavior]; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [titlebar_view_ attach]; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set initial size of the window to match the size of the panel to give 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the renderer the proper size to work with earlier, avoiding a resize 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // after the window is revealed. 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect panelBounds = windowShim_->panel()->GetBounds(); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NSRect frame = [window frame]; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame.size.width = panelBounds.width(); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) frame.size.height = panelBounds.height(); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [window setFrame:frame display:NO]; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // MacOS will turn the user-resizing to the user-dragging if the direction of 20258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // the dragging is orthogonal to the direction of the arrow cursor. We do not 20358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // want this since it will bypass our dragging logic. The panel window is 20458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // still draggable because we track and handle the dragging in our custom way. 20558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) [[self window] setMovable:NO]; 20658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 20758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) [self updateTrackingArea]; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)- (void)updateWebContentsViewFrame { 211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) content::WebContents* webContents = windowShim_->panel()->GetWebContents(); 212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!webContents) 213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) // Compute the size of the web contents view. Don't assume it's similar to the 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // size of the contentView, because the contentView is managed by the Cocoa 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to be (window - standard titlebar), while we have taller custom titlebar 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // instead. In coordinate system of window's contentView. 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NSRect contentFrame = [self contentRectForFrameRect:[[self window] frame]]; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contentFrame.origin = NSZeroPoint; 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 222010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) NSView* contentView = webContents->GetNativeView(); 223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!NSEqualRects([contentView frame], contentFrame)) 224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) [contentView setFrame:contentFrame]; 225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)- (void)disableWebContentsViewAutosizing { 228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) [[[self window] contentView] setAutoresizesSubviews:NO]; 229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)- (void)enableWebContentsViewAutosizing { 232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) [self updateWebContentsViewFrame]; 233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) [[[self window] contentView] setAutoresizesSubviews:YES]; 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)revealAnimatedWithFrame:(const NSRect&)frame { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NSWindow* window = [self window]; // This ensures loading the nib. 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Disable subview resizing while resizing the window to avoid renderer 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // resizes during intermediate stages of animation. 241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) [self disableWebContentsViewAutosizing]; 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We grow the window from the bottom up to produce a 'reveal' animation. 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NSRect startFrame = NSMakeRect(NSMinX(frame), NSMinY(frame), 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NSWidth(frame), kMinimumWindowSize); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [window setFrame:startFrame display:NO animate:NO]; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Shows the window without making it key, on top of its layer, even if 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Chromium is not an active app. 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [window orderFrontRegardless]; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(dcheng): Temporary hack to work around the fact that 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // orderFrontRegardless causes us to become the first responder. The usual 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Chrome assumption is that becoming the first responder = you have focus, so 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we always deactivate the controls here. If we're created as an active 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // panel, we'll get a NSWindowDidBecomeKeyNotification and reactivate the web 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // view properly. See crbug.com/97831 for more details. 256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) WebContents* web_contents = windowShim_->panel()->GetWebContents(); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // RWHV may be NULL in unit tests. 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (web_contents && web_contents->GetRenderWidgetHostView()) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_contents->GetRenderWidgetHostView()->SetActive(false); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This will re-enable the content resizing after it finishes. 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [self setPanelFrame:frame animate:YES]; 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)updateTitleBar { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NSString* newTitle = base::SysUTF16ToNSString( 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windowShim_->panel()->GetWindowTitle()); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pendingWindowTitle_.reset( 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [BrowserWindowUtils scheduleReplaceOldTitle:pendingWindowTitle_.get() 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) withNewTitle:newTitle 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) forWindow:[self window]]); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [titlebar_view_ setTitle:newTitle]; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [self updateIcon]; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)updateIcon { 277a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::scoped_nsobject<NSView> iconView; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (throbberShouldSpin_) { 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the throbber is spinning now, no need to replace it. 280a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if ([[titlebar_view_ icon] isKindOfClass:[SpriteView class]]) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NSImage* iconImage = 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResourceBundle::GetSharedInstance().GetNativeImageNamed( 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_THROBBER).ToNSImage(); 286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SpriteView* spriteView = [[SpriteView alloc] init]; 287a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) [spriteView setImage:iconImage]; 288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) iconView.reset(spriteView); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Image& page_icon = windowShim_->panel()->GetCurrentPageIcon(); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NSRect iconFrame = [[titlebar_view_ icon] frame]; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NSImage* iconImage = page_icon.IsEmpty() ? 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rb.GetNativeImageNamed(IDR_DEFAULT_FAVICON).ToNSImage() : 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) page_icon.ToNSImage(); 296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NSImageView* imageView = [[NSImageView alloc] initWithFrame:iconFrame]; 297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) [imageView setImage:iconImage]; 298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) iconView.reset(imageView); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) [titlebar_view_ setIcon:iconView]; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)updateThrobber:(BOOL)shouldSpin { 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (throbberShouldSpin_ == shouldSpin) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) throbberShouldSpin_ = shouldSpin; 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the titlebar view has not been attached, bail out. 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!titlebar_view_) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [self updateIcon]; 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)updateTitleBarMinimizeRestoreButtonVisibility { 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Panel* panel = windowShim_->panel(); 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) [titlebar_view_ setMinimizeButtonVisibility:panel->CanShowMinimizeButton()]; 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) [titlebar_view_ setRestoreButtonVisibility:panel->CanShowRestoreButton()]; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)webContentsInserted:(WebContents*)contents { 322010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) NSView* view = contents->GetNativeView(); 323868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) [[[self window] contentView] addSubview:view]; 324868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) [view setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable]; 325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) [self enableWebContentsViewAutosizing]; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)webContentsDetached:(WebContents*)contents { 330010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) [contents->GetNativeView() removeFromSuperview]; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (PanelTitlebarViewCocoa*)titlebarView { 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return titlebar_view_; 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Called to validate menu and toolbar items when this window is key. All the 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// items we care about have been set with the |-commandDispatch:| 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// action and a target of FirstResponder in IB. 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Delegate to the NSApp delegate if Panel does not care about the command or 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// shortcut, to make sure the global items in Chrome main app menu still work. 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item { 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ([item action] == @selector(commandDispatch:)) { 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NSInteger tag = [item tag]; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CommandUpdater* command_updater = windowShim_->panel()->command_updater(); 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (command_updater->SupportsCommand(tag)) 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return command_updater->IsCommandEnabled(tag); 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return [[NSApp delegate] validateUserInterfaceItem:item]; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NO; 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Called when the user picks a menu or toolbar item when this window is key. 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Calls through to the panel object to execute the command or delegates up. 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)commandDispatch:(id)sender { 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(sender); 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NSInteger tag = [sender tag]; 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CommandUpdater* command_updater = windowShim_->panel()->command_updater(); 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (command_updater->SupportsCommand(tag)) 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) windowShim_->panel()->ExecuteCommandIfEnabled(tag); 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) [[NSApp delegate] commandDispatch:sender]; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Handler for the custom Close button. 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)closePanel { 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windowShim_->panel()->Close(); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Handler for the custom Minimize button. 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)minimizeButtonClicked:(int)modifierFlags { 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Panel* panel = windowShim_->panel(); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) panel->OnMinimizeButtonClicked((modifierFlags & NSShiftKeyMask) ? 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) panel::APPLY_TO_ALL : panel::NO_MODIFIER); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Handler for the custom Restore button. 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)restoreButtonClicked:(int)modifierFlags { 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Panel* panel = windowShim_->panel(); 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) panel->OnRestoreButtonClicked((modifierFlags & NSShiftKeyMask) ? 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) panel::APPLY_TO_ALL : panel::NO_MODIFIER); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Called when the user wants to close the panel or from the shutdown process. 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The Panel object is in control of whether or not we're allowed to close. It 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// may defer closing due to several states, such as onbeforeUnload handlers 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// needing to be fired. If closing is deferred, the Panel will handle the 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// processing required to get us to the closing state and (by watching for 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the web content going away) will again call to close the window when it's 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// finally ready. 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (BOOL)windowShouldClose:(id)sender { 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Panel* panel = windowShim_->panel(); 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Give beforeunload handlers the chance to cancel the close before we hide 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the window below. 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!panel->ShouldCloseWindow()) 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NO; 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (panel->GetWebContents()) { 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Terminate any playing animations. 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [self terminateBoundsAnimation]; 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animateOnBoundsChange_ = NO; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make panel close the web content, allowing the renderer to shut down 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and call us back again. 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) panel->OnWindowClosing(); 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NO; 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No web content; it's ok to close the window. 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return YES; 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When windowShouldClose returns YES (or if controller receives direct 'close' 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// signal), window will be unconditionally closed. Clean up. 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)windowWillClose:(NSNotification*)notification { 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!windowShim_->panel()->GetWebContents()); 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Avoid callbacks from a nonblocking animation in progress, if any. 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [self terminateBoundsAnimation]; 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windowShim_->DidCloseNativeWindow(); 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Call |-autorelease| after a zero-length delay to avoid deadlock from 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // code in the current run loop that waits on PANEL_CLOSED notification. 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The notification is sent when this object is freed, but this object 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cannot be freed until the current run loop completes. 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [self performSelector:@selector(autorelease) 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) withObject:nil 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) afterDelay:0]; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)startDrag:(NSPoint)mouseLocation { 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Convert from Cocoa's screen coordinates to platform-indepedent screen 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // coordinates because PanelManager method takes platform-indepedent screen 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // coordinates. 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windowShim_->panel()->manager()->StartDragging( 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windowShim_->panel(), 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cocoa_utils::ConvertPointFromCocoaCoordinates(mouseLocation)); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)endDrag:(BOOL)cancelled { 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windowShim_->panel()->manager()->EndDragging(cancelled); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)drag:(NSPoint)mouseLocation { 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Convert from Cocoa's screen coordinates to platform-indepedent screen 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // coordinates because PanelManager method takes platform-indepedent screen 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // coordinates. 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windowShim_->panel()->manager()->Drag( 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cocoa_utils::ConvertPointFromCocoaCoordinates(mouseLocation)); 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)setPanelFrame:(NSRect)frame 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animate:(BOOL)animate { 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BOOL jumpToDestination = (!animateOnBoundsChange_ || !animate); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If no animation is in progress, apply bounds change instantly. 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (jumpToDestination && ![self isAnimatingBounds]) { 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [[self window] setFrame:frame display:YES animate:NO]; 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NSDictionary *windowResize = [NSDictionary dictionaryWithObjectsAndKeys: 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [self window], NSViewAnimationTargetKey, 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [NSValue valueWithRect:frame], NSViewAnimationEndFrameKey, nil]; 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NSArray *animations = [NSArray arrayWithObjects:windowResize, nil]; 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If an animation is in progress, update the animation with new target 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bounds. Also, set the destination frame bounds to the new value. 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (jumpToDestination && [self isAnimatingBounds]) { 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [boundsAnimation_ setViewAnimations:animations]; 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [[self window] setFrame:frame display:YES animate:NO]; 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Will be enabled back in animationDidEnd callback. 474868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) [self disableWebContentsViewAutosizing]; 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Terminate previous animation, if it is still playing. 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [self terminateBoundsAnimation]; 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) boundsAnimation_ = 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [[NSViewAnimation alloc] initWithViewAnimations:animations]; 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [boundsAnimation_ setDelegate:self]; 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NSRect currentFrame = [[self window] frame]; 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Compute duration. We use constant speed of animation, however if the change 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is too large, we clip the duration (effectively increasing speed) to 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // limit total duration of animation. This makes 'small' transitions fast. 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 'distance' is the max travel between 4 potentially traveling corners. 488a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) double distanceX = std::max(std::abs(NSMinX(currentFrame) - NSMinX(frame)), 489a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::abs(NSMaxX(currentFrame) - NSMaxX(frame))); 490a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) double distanceY = std::max(std::abs(NSMinY(currentFrame) - NSMinY(frame)), 491a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) std::abs(NSMaxY(currentFrame) - NSMaxY(frame))); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double distance = std::max(distanceX, distanceY); 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double duration = std::min(distance / kBoundsAnimationSpeedPixelsPerSecond, 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kBoundsAnimationMaxDurationSeconds); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Detect animation that happens when expansion state is set to MINIMIZED 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and there is relatively big portion of the panel to hide from view. 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initialize animation differently in this case, using fast-pause-slow 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // method, see below for more details. 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (distanceY > 0 && 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windowShim_->panel()->expansion_state() == Panel::MINIMIZED) { 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animationStopToShowTitlebarOnly_ = 1.0 - 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (windowShim_->panel()->TitleOnlyHeight() - NSHeight(frame)) / distanceY; 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (animationStopToShowTitlebarOnly_ > 0.7) { // Relatively big movement. 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) playingMinimizeAnimation_ = YES; 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) duration = 1.5; 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [boundsAnimation_ setDuration: PanelManager::AdjustTimeInterval(duration)]; 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [boundsAnimation_ setFrameRate:0.0]; 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [boundsAnimation_ setAnimationBlockingMode: NSAnimationNonblocking]; 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [boundsAnimation_ startAnimation]; 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (float)animation:(NSAnimation*)animation 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) valueForProgress:(NSAnimationProgress)progress { 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return PanelBoundsAnimation::ComputeAnimationValue( 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) progress, playingMinimizeAnimation_, animationStopToShowTitlebarOnly_); 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)cleanupAfterAnimation { 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) playingMinimizeAnimation_ = NO; 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!windowShim_->panel()->IsMinimized()) 523868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) [self enableWebContentsViewAutosizing]; 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)animationDidEnd:(NSAnimation*)animation { 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [self cleanupAfterAnimation]; 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only invoke this callback from animationDidEnd, since animationDidStop can 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // be called when we interrupt/restart animation which is in progress. 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We only need this notification when animation indeed finished moving 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the panel bounds. 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Panel* panel = windowShim_->panel(); 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) panel->manager()->OnPanelAnimationEnded(panel); 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)animationDidStop:(NSAnimation*)animation { 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [self cleanupAfterAnimation]; 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)terminateBoundsAnimation { 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!boundsAnimation_) 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [boundsAnimation_ stopAnimation]; 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [boundsAnimation_ setDelegate:nil]; 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [boundsAnimation_ release]; 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) boundsAnimation_ = nil; 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (BOOL)isAnimatingBounds { 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return boundsAnimation_ && [boundsAnimation_ isAnimating]; 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)onTitlebarMouseClicked:(int)modifierFlags { 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Panel* panel = windowShim_->panel(); 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) panel->OnTitlebarClicked((modifierFlags & NSShiftKeyMask) ? 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) panel::APPLY_TO_ALL : panel::NO_MODIFIER); 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 560424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)- (void)onTitlebarDoubleClicked:(int)modifierFlags { 561424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Double-clicking is only allowed to minimize docked panels. 562424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) Panel* panel = windowShim_->panel(); 563424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (panel->collection()->type() != PanelCollection::DOCKED || 564424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) panel->IsMinimized()) 565424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return; 566424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) [self minimizeButtonClicked:modifierFlags]; 567424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 568424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (int)titlebarHeightInScreenCoordinates { 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NSView* titlebar = [self titlebarView]; 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NSHeight([titlebar convertRect:[titlebar bounds] toView:nil]); 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(dcheng): These two selectors are almost copy-and-paste from 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BrowserWindowController. Figure out the appropriate way of code sharing, 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// whether it's refactoring more things into BrowserWindowUtils or making a 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// common base controller for browser windows. 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)windowDidBecomeKey:(NSNotification*)notification { 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need to activate the controls (in the "WebView"). To do this, get the 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // selected WebContents's RenderWidgetHostView and tell it to activate. 581868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (WebContents* contents = windowShim_->panel()->GetWebContents()) { 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (content::RenderWidgetHostView* rwhv = 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents->GetRenderWidgetHostView()) 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rwhv->SetActive(true); 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windowShim_->panel()->OnActiveStateChanged(true); 58858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 58958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Make the window user-resizable when it gains the focus. 59058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) [[self window] setStyleMask: 59158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) [[self window] styleMask] | NSResizableWindowMask]; 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)windowDidResignKey:(NSNotification*)notification { 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If our app is still active and we're still the key window, ignore this 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // message, since it just means that a menu extra (on the "system status bar") 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // was activated; we'll get another |-windowDidResignKey| if we ever really 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // lose key window status. 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ([NSApp isActive] && ([NSApp keyWindow] == [self window])) 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [self onWindowDidResignKey]; 60358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 60458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 60558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)- (void)windowWillStartLiveResize:(NSNotification*)notification { 60658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // Check if the user-resizing is allowed for the triggering edge/corner. 60758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // This is an extra safe guard because we are not able to track the mouse 60858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // movement outside the window and Cocoa could trigger the user-resizing 60958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // when the mouse moves a bit outside the edge/corner. 61058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (![self canResizeByMouseAtCurrentLocation]) 61158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 61258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) userResizing_ = YES; 61358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) windowShim_->panel()->OnPanelStartUserResizing(); 61458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 61558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 61658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)- (void)windowDidEndLiveResize:(NSNotification*)notification { 61758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (!userResizing_) 61858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 61958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) userResizing_ = NO; 62058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 62158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) Panel* panel = windowShim_->panel(); 62258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) panel->OnPanelEndUserResizing(); 62358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 62458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) gfx::Rect newBounds = 62558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) cocoa_utils::ConvertRectFromCocoaCoordinates([[self window] frame]); 62658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (windowShim_->panel()->GetBounds() == newBounds) 62758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 62858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) windowShim_->set_cached_bounds_directly(newBounds); 62958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 63058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) panel->IncreaseMaxSize(newBounds.size()); 63158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) panel->set_full_size(newBounds.size()); 63258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 63358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) panel->collection()->RefreshLayout(); 63458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 63558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 63658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)- (NSSize)windowWillResize:(NSWindow*)sender toSize:(NSSize)newSize { 63758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // As an extra safe guard, we avoid the user resizing if it is deemed not to 63858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // be allowed (see comment in windowWillStartLiveResize). 63958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if ([[self window] inLiveResize] && !userResizing_) 64058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return [[self window] frame].size; 64158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return newSize; 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 644868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)- (void)windowDidResize:(NSNotification*)notification { 64558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) Panel* panel = windowShim_->panel(); 64658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (userResizing_) { 64758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) panel->collection()->OnPanelResizedByMouse( 64858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) panel, 64958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) cocoa_utils::ConvertRectFromCocoaCoordinates([[self window] frame])); 65058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 65158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 65258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) [self updateTrackingArea]; 65358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 65458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (![self isAnimatingBounds] || 65558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) panel->collection()->type() != PanelCollection::DOCKED) 65658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return; 65758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 658c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // Remove the web contents view from the view hierarchy when the panel is not 659c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // taller than the titlebar. Put it back when the panel grows taller than 660c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // the titlebar. Note that RenderWidgetHostViewMac works for the case that 661c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // the web contents view does not exist in the view hierarchy (i.e. the tab 662c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // is not the main one), but it does not work well, like causing occasional 663c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // crashes (http://crbug.com/265932), if the web contents view is made hidden. 664c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // 66558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // This is needed when the docked panels are being animated. When the 66658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // animation starts, the contents view autosizing is disabled. After the 66758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // animation ends, the contents view autosizing is reenabled and the frame 66858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // of contents view is updated. Thus it is likely that the contents view will 66958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // overlap with the titlebar view when the panel shrinks to be very small. 67058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // The implementation of the web contents view assumes that it will never 67158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // overlap with another view in order to paint the web contents view directly. 67258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) content::WebContents* webContents = panel->GetWebContents(); 673c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if (!webContents) 6743240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch return; 675010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) NSView* contentView = webContents->GetNativeView(); 67658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (NSHeight([self contentRectForFrameRect:[[self window] frame]]) <= 0) { 677c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // No need to retain the view before it is removed from its superview 678c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch // because WebContentsView keeps a reference to this view. 679c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch if ([contentView superview]) 680c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch [contentView removeFromSuperview]; 681c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch } else { 682424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (![contentView superview]) { 683c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch [[[self window] contentView] addSubview:contentView]; 684424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 685424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // When the web contents view is put back, we need to tell its render 686424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // widget host view to accept focus. 687424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) content::RenderWidgetHostView* rwhv = 688424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) webContents->GetRenderWidgetHostView(); 689424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (rwhv) { 690424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) [[self window] makeFirstResponder:rwhv->GetNativeView()]; 691424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) rwhv->SetActive([[self window] isMainWindow]); 692424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 693424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 694868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 695868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)} 696868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)activate { 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Activate the window. -|windowDidBecomeKey:| will be called when 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // window becomes active. 7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoReset<BOOL> pin(&activationRequestedByPanel_, true); 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [BrowserWindowUtils activateWindowForController:self]; 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)deactivate { 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (![[self window] isMainWindow]) 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [NSApp deactivate]; 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 710cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Cocoa does not support deactivating a NSWindow explicitly. To work around 711cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // this, we call orderOut and orderFront to force the window to lose its key 712cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // window state. 713cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 714cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Before doing this, we need to disable screen updates to prevent flickering. 715cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NSDisableScreenUpdates(); 716cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 717cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // If a panel is in stacked mode, the window has a background parent window. 718cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // We need to detach it from its parent window before applying the ordering 719cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // change and then put it back because otherwise tha background parent window 720cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // might show up. 721cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NSWindow* parentWindow = [[self window] parentWindow]; 722cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (parentWindow) 723cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) [parentWindow removeChildWindow:[self window]]; 724cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 725cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) [[self window] orderOut:nil]; 726cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) [[self window] orderFront:nil]; 727cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 728cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (parentWindow) 729cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) [parentWindow addChildWindow:[self window] ordered:NSWindowAbove]; 730cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 731cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NSEnableScreenUpdates(); 732cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 733cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Though the above workaround causes the window to lose its key window state, 734cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // it does not trigger the system to call windowDidResignKey. 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [self onWindowDidResignKey]; 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)onWindowDidResignKey { 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need to deactivate the controls (in the "WebView"). To do this, get the 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // selected WebContents's RenderWidgetHostView and tell it to deactivate. 741868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (WebContents* contents = windowShim_->panel()->GetWebContents()) { 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (content::RenderWidgetHostView* rwhv = 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents->GetRenderWidgetHostView()) 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rwhv->SetActive(false); 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) windowShim_->panel()->OnActiveStateChanged(false); 748cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 749cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Make the window not user-resizable when it loses the focus. This is to 750cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // solve the problem that the bottom edge of the active panel does not 751cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // trigger the user-resizing if this panel stacks with another inactive 752cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // panel at the bottom. 753cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) [[self window] setStyleMask: 754cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) [[self window] styleMask] & ~NSResizableWindowMask]; 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)preventBecomingKeyWindow:(BOOL)prevent { 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canBecomeKeyWindow_ = !prevent; 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)fullScreenModeChanged:(bool)isFullScreen { 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [self updateWindowLevel]; 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the panel is not always on top, its z-order should not be affected if 7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // some other window enters fullscreen mode. 7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!windowShim_->panel()->IsAlwaysOnTop()) 7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The full-screen window is in normal level and changing the panel window 7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to same normal level will not move it below the full-screen window. Thus 7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // we need to reorder the panel window. 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (isFullScreen) 7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) [[self window] orderOut:nil]; 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [[self window] orderFrontRegardless]; 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (BOOL)canBecomeKeyWindow { 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Panel can only gain focus if it is expanded. Minimized panels do not 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // participate in Cmd-~ rotation. 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(dimich): If it will be ever desired to expand/focus the Panel on 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // keyboard navigation or via main menu, the care should be taken to avoid 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cases when minimized Panel is getting keyboard input, invisibly. 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return canBecomeKeyWindow_; 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (int)numPanels { 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return windowShim_->panel()->manager()->num_panels(); 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (BOOL)activationRequestedByPanel { 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return activationRequestedByPanel_; 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)updateWindowLevel { 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [self updateWindowLevel:windowShim_->panel()->IsMinimized()]; 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (void)updateWindowLevel:(BOOL)panelIsMinimized { 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (![self isWindowLoaded]) 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Panel* panel = windowShim_->panel(); 8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!panel->IsAlwaysOnTop()) { 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [[self window] setLevel:NSNormalWindowLevel]; 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we simply use NSStatusWindowLevel (25) for all docked panel windows, 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // IME composition windows for things like CJK languages appear behind panels. 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Pre 10.7, IME composition windows have a window level of 19, which is 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // lower than the dock at level 20. Since we want panels to appear on top of 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the dock, it is impossible to enforce an ordering where IME > panel > dock, 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // since IME < dock. 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // On 10.7, IME composition windows and the dock both live at level 20, so we 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // use the same window level for panels. Since newly created windows appear at 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the top of their window level, panels are typically on top of the dock, and 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the IME composition window correctly draws over the panel. 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // An autohide dock causes problems though: since it's constantly being 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // revealed, it ends up drawing on top of other windows at the same level. 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // While this is OK for expanded panels, it makes minimized panels impossible 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to activate. As a result, we still use NSStatusWindowLevel for minimized 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // panels, since it's impossible to compose IME text in them anyway. 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (panelIsMinimized) { 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [[self window] setLevel:NSStatusWindowLevel]; 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [[self window] setLevel:NSDockWindowLevel]; 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)- (void)updateWindowCollectionBehavior { 8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (![self isWindowLoaded]) 8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 8322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NSWindowCollectionBehavior collectionBehavior = 8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) NSWindowCollectionBehaviorParticipatesInCycle; 8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (windowShim_->panel()->IsAlwaysOnTop()) 8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) collectionBehavior |= NSWindowCollectionBehaviorCanJoinAllSpaces; 8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) [[self window] setCollectionBehavior:collectionBehavior]; 8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 83958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)- (void)updateTrackingArea { 84058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) NSView* superview = [[[self window] contentView] superview]; 84158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 84258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (trackingArea_.get()) 84358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) [superview removeTrackingArea:trackingArea_.get()]; 84458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 84558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) trackingArea_.reset( 84658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) [[CrTrackingArea alloc] initWithRect:[superview bounds] 84758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) options:NSTrackingInVisibleRect | 84858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) NSTrackingMouseMoved | 84958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) NSTrackingActiveInKeyWindow 85058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) owner:superview 85158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) userInfo:nil]); 85258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) [superview addTrackingArea:trackingArea_.get()]; 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 855c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)- (void)showShadow:(BOOL)show { 856c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (![self isWindowLoaded]) 857c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 858c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) [[self window] setHasShadow:show]; 859c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 860c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 861c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)- (void)miniaturize { 862c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) [[self window] miniaturize:nil]; 863c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 864c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 865c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)- (BOOL)isMiniaturized { 866c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return [[self window] isMiniaturized]; 867c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 868c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 86958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)- (BOOL)canResizeByMouseAtCurrentLocation { 87058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) panel::Resizability resizability = windowShim_->panel()->CanResizeByMouse(); 87158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) NSRect frame = [[self window] frame]; 87258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) NSPoint point = [NSEvent mouseLocation]; 87358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 87458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (point.y < NSMinY(frame) + kWidthOfMouseResizeArea) { 87558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (point.x < NSMinX(frame) + kWidthOfMouseResizeArea && 87658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) (resizability & panel::RESIZABLE_BOTTOM_LEFT) == 0) { 87758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return NO; 87858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 87958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (point.x > NSMaxX(frame) - kWidthOfMouseResizeArea && 88058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) (resizability & panel::RESIZABLE_BOTTOM_RIGHT) == 0) { 88158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return NO; 88258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 88358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if ((resizability & panel::RESIZABLE_BOTTOM) == 0) 88458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return NO; 88558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } else if (point.y > NSMaxY(frame) - kWidthOfMouseResizeArea) { 88658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (point.x < NSMinX(frame) + kWidthOfMouseResizeArea && 88758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) (resizability & panel::RESIZABLE_TOP_LEFT) == 0) { 88858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return NO; 88958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 89058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (point.x > NSMaxX(frame) - kWidthOfMouseResizeArea && 89158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) (resizability & panel::RESIZABLE_TOP_RIGHT) == 0) { 89258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return NO; 89358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 89458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if ((resizability & panel::RESIZABLE_TOP) == 0) 89558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return NO; 89658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } else { 89758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (point.x < NSMinX(frame) + kWidthOfMouseResizeArea && 89858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) (resizability & panel::RESIZABLE_LEFT) == 0) { 89958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return NO; 90058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 90158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (point.x > NSMaxX(frame) - kWidthOfMouseResizeArea && 90258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) (resizability & panel::RESIZABLE_RIGHT) == 0) { 90358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return NO; 90458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 90558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 90658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return YES; 90758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 90858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We have custom implementation of these because our titlebar height is custom 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and does not match the standard one. 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (NSRect)frameRectForContentRect:(NSRect)contentRect { 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // contentRect is in contentView coord system. We should add a titlebar on top 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // and then convert to the windows coord system. 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contentRect.size.height += panel::kTitlebarHeight; 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NSRect frameRect = [[[self window] contentView] convertRect:contentRect 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) toView:nil]; 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return frameRect; 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)- (NSRect)contentRectForFrameRect:(NSRect)frameRect { 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NSRect contentRect = [[[self window] contentView] convertRect:frameRect 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fromView:nil]; 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contentRect.size.height -= panel::kTitlebarHeight; 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (contentRect.size.height < 0) 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contentRect.size.height = 0; 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return contentRect; 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)@end 930