summaryrefslogtreecommitdiffstats
path: root/chrome/browser/ui/views/browser_bubble.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/ui/views/browser_bubble.cc')
-rw-r--r--chrome/browser/ui/views/browser_bubble.cc126
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());
+}