diff options
Diffstat (limited to 'chrome/browser/ui/views/browser_bubble.cc')
-rw-r--r-- | chrome/browser/ui/views/browser_bubble.cc | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/chrome/browser/ui/views/browser_bubble.cc b/chrome/browser/ui/views/browser_bubble.cc new file mode 100644 index 0000000..a118852 --- /dev/null +++ b/chrome/browser/ui/views/browser_bubble.cc @@ -0,0 +1,126 @@ +// 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 "chrome/browser/views/frame/browser_view.h" +#if defined(OS_WIN) +#include "chrome/browser/external_tab_container_win.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()); +} |