// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/ui/cocoa/constrained_window_mac.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h" #include "chrome/browser/ui/constrained_window_tab_helper.h" #include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents_view.h" #import "third_party/GTM/AppKit/GTMWindowSheetController.h" ConstrainedWindowMacDelegateSystemSheet:: ConstrainedWindowMacDelegateSystemSheet(id delegate, SEL didEndSelector) : systemSheet_(nil), delegate_([delegate retain]), didEndSelector_(didEndSelector) {} ConstrainedWindowMacDelegateSystemSheet:: ~ConstrainedWindowMacDelegateSystemSheet() {} void ConstrainedWindowMacDelegateSystemSheet::set_sheet(id sheet) { systemSheet_.reset([sheet retain]); } NSArray* ConstrainedWindowMacDelegateSystemSheet::GetSheetParameters( id delegate, SEL didEndSelector) { return @[[NSNull null], // window, must be [NSNull null] delegate, [NSValue valueWithPointer:didEndSelector], [NSValue valueWithPointer:NULL]]; // context info for didEndSelector_. } void ConstrainedWindowMacDelegateSystemSheet::RunSheet( GTMWindowSheetController* sheetController, NSView* view) { NSArray* params = GetSheetParameters(delegate_.get(), didEndSelector_); [sheetController beginSystemSheet:systemSheet_ modalForView:view withParameters:params]; } ConstrainedWindowMacDelegateCustomSheet:: ConstrainedWindowMacDelegateCustomSheet() : customSheet_(nil), delegate_(nil), didEndSelector_(NULL) {} ConstrainedWindowMacDelegateCustomSheet:: ConstrainedWindowMacDelegateCustomSheet(id delegate, SEL didEndSelector) : customSheet_(nil), delegate_([delegate retain]), didEndSelector_(didEndSelector) {} ConstrainedWindowMacDelegateCustomSheet:: ~ConstrainedWindowMacDelegateCustomSheet() {} void ConstrainedWindowMacDelegateCustomSheet::init(NSWindow* sheet, id delegate, SEL didEndSelector) { DCHECK(!delegate_.get()); DCHECK(!didEndSelector_); customSheet_.reset([sheet retain]); delegate_.reset([delegate retain]); didEndSelector_ = didEndSelector; DCHECK(delegate_.get()); DCHECK(didEndSelector_); } void ConstrainedWindowMacDelegateCustomSheet::set_sheet(NSWindow* sheet) { customSheet_.reset([sheet retain]); } void ConstrainedWindowMacDelegateCustomSheet::RunSheet( GTMWindowSheetController* sheetController, NSView* view) { [sheetController beginSheet:customSheet_.get() modalForView:view modalDelegate:delegate_.get() didEndSelector:didEndSelector_ contextInfo:NULL]; } ConstrainedWindowMac::ConstrainedWindowMac( content::WebContents* web_contents, ConstrainedWindowMacDelegate* delegate) : web_contents_(web_contents), delegate_(delegate), controller_(nil), should_be_visible_(false), closing_(false) { DCHECK(web_contents); DCHECK(delegate); ConstrainedWindowTabHelper* constrained_window_tab_helper = ConstrainedWindowTabHelper::FromWebContents(web_contents); constrained_window_tab_helper->AddConstrainedDialog(this); } ConstrainedWindowMac::~ConstrainedWindowMac() {} void ConstrainedWindowMac::ShowConstrainedWindow() { should_be_visible_ = true; // The WebContents only has a native window if it is currently visible. In // this case, open the sheet now. Else, Realize() will be called later, when // our tab becomes visible. NSWindow* window = web_contents_->GetView()->GetTopLevelNativeWindow(); NSWindowController* window_controller = nil; while (window) { if ([[window windowController] conformsToProtocol: @protocol(ConstrainedWindowSupport)]) { window_controller = [window windowController]; break; } window = [window parentWindow]; } // It's valid for the window to be nil. For example, background tabs don't // have a window set. However, if a window exists then there should always // be a window controller that implements the ConstrainedWindowSupport // protocol. DCHECK(!window || window_controller); if (window_controller) Realize(window_controller); } void ConstrainedWindowMac::CloseConstrainedWindow() { // Protection against reentrancy, which might otherwise become a problem if // DeleteDelegate forcibly closes a constrained window in a way that results // in CloseConstrainedWindow being called again. if (closing_) return; closing_ = true; delegate_->DeleteDelegate(); ConstrainedWindowTabHelper* constrained_window_tab_helper = ConstrainedWindowTabHelper::FromWebContents(web_contents_); constrained_window_tab_helper->WillClose(this); delete this; } bool ConstrainedWindowMac::CanShowConstrainedWindow() { Browser* browser = browser::FindBrowserWithWebContents(web_contents_); if (!browser) return true; return !browser->window()->IsInstantTabShowing(); } void ConstrainedWindowMac::Realize( NSWindowController* controller) { if (!should_be_visible_) return; if (controller_ != nil) { DCHECK(controller_ == controller); return; } DCHECK(controller != nil); // Remember the controller we're adding ourselves to, so that we can later // remove us from it. controller_ = controller; delegate_->RunSheet([controller_ sheetController], GetSheetParentViewForWebContents(web_contents_)); delegate_->set_sheet_open(true); }