// Copyright (c) 2009 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/views/browser_bubble.h" #include "app/l10n_util.h" #include "chrome/browser/views/frame/browser_view.h" #if defined(OS_WIN) #include "chrome/browser/external_tab_container.h" #endif #include "views/widget/root_view.h" #include "views/window/window.h" namespace { BrowserBubbleHost* GetBubbleHostFromFrame(views::Widget* frame) { if (!frame) return NULL; BrowserBubbleHost* bubble_host = NULL; views::Window* window = frame->GetWindow(); if (window) { bubble_host = BrowserView::GetBrowserViewForNativeWindow( window->GetNativeWindow()); DCHECK(bubble_host); } #if defined(OS_WIN) // The frame may also be an ExternalTabContainer, which is also capable of // hosting BrowserBubbles. gfx::NativeView native_view = frame->GetNativeView(); if (!bubble_host) { bubble_host = ExternalTabContainer::GetExternalContainerFromNativeWindow(native_view); } #endif return bubble_host; } } // namespace BrowserBubble::BrowserBubble(views::View* view, views::Widget* frame, const gfx::Point& origin, bool drop_shadow) : frame_(frame), view_(view), visible_(false), delegate_(NULL), attached_(false), drop_shadow_enabled_(drop_shadow), bubble_host_(GetBubbleHostFromFrame(frame)) { gfx::Size size = view->GetPreferredSize(); bounds_.SetRect(origin.x(), origin.y(), size.width(), size.height()); InitPopup(); } BrowserBubble::~BrowserBubble() { DCHECK(!attached_); popup_->Close(); // Don't call DetachFromBrowser from here. It needs to talk to the // BrowserView to deregister itself, and if BrowserBubble is owned // by a child of BrowserView, then it's possible that this stack frame // is a descendant of BrowserView's destructor, which leads to problems. // In that case, Detach doesn't need to get called anyway since BrowserView // will do the necessary cleanup. } void BrowserBubble::DetachFromBrowser() { DCHECK(attached_); if (!attached_) return; attached_ = false; if (bubble_host_) bubble_host_->DetachBrowserBubble(this); } void BrowserBubble::AttachToBrowser() { DCHECK(!attached_); if (attached_) return; if (bubble_host_) bubble_host_->AttachBrowserBubble(this); attached_ = true; } void BrowserBubble::BrowserWindowMoved() { if (delegate_) delegate_->BubbleBrowserWindowMoved(this); else Hide(); if (visible_) Reposition(); } void BrowserBubble::BrowserWindowClosing() { if (delegate_) delegate_->BubbleBrowserWindowClosing(this); else Hide(); } void BrowserBubble::SetBounds(int x, int y, int w, int h) { // If the UI layout is RTL, we don't need to mirror coordinates, since // View logic will do that for us. bounds_.SetRect(x, y, w, h); Reposition(); } void BrowserBubble::MoveTo(int x, int y) { SetBounds(x, y, bounds_.width(), bounds_.height()); } void BrowserBubble::Reposition() { gfx::Point top_left; views::View::ConvertPointToScreen(frame_->GetRootView(), &top_left); MovePopup(top_left.x() + bounds_.x(), top_left.y() + bounds_.y(), bounds_.width(), bounds_.height()); } void BrowserBubble::ResizeToView() { SetBounds(bounds_.x(), bounds_.y(), view_->width(), view_->height()); }