summaryrefslogtreecommitdiffstats
path: root/chrome/browser/ui/views/frame/contents_container.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/ui/views/frame/contents_container.cc')
-rw-r--r--chrome/browser/ui/views/frame/contents_container.cc144
1 files changed, 139 insertions, 5 deletions
diff --git a/chrome/browser/ui/views/frame/contents_container.cc b/chrome/browser/ui/views/frame/contents_container.cc
index c3056f7..fd80e3b 100644
--- a/chrome/browser/ui/views/frame/contents_container.cc
+++ b/chrome/browser/ui/views/frame/contents_container.cc
@@ -4,20 +4,77 @@
#include "chrome/browser/views/frame/contents_container.h"
-ContentsContainer::ContentsContainer(views::View* active)
- : active_(active),
+#include "app/resource_bundle.h"
+#include "chrome/browser/location_bar.h"
+#include "chrome/browser/views/frame/browser_view.h"
+#include "grit/theme_resources.h"
+#include "views/controls/image_view.h"
+#include "views/widget/root_view.h"
+
+#if defined(OS_WIN)
+#include "views/widget/widget_win.h"
+#elif defined(OS_LINUX)
+#include "chrome/browser/gtk/gtk_util.h"
+#include "views/window/window_gtk.h"
+#endif
+
+#if defined(OS_WIN)
+
+class ContentsContainer::TearWindow : public views::WidgetWin {
+ public:
+ explicit TearWindow(ContentsContainer* contents_container)
+ : contents_container_(contents_container) {
+ set_window_style(WS_POPUP | WS_CLIPCHILDREN);
+ set_window_ex_style(WS_EX_TOOLWINDOW | WS_EX_LAYERED);
+ }
+
+ virtual ~TearWindow() {
+ // On windows it's possible for us to be deleted before the
+ // ContentsContainer. If this happens make sure contents_container_ doesn't
+ // attempt to delete us too.
+ if (contents_container_)
+ contents_container_->TearWindowDestroyed();
+ }
+
+ void set_contents_container(ContentsContainer* contents_container) {
+ contents_container_ = contents_container;
+ }
+
+ virtual LRESULT OnMouseActivate(HWND window,
+ UINT hit_test,
+ UINT mouse_message) {
+ // Don't activate the window when the user clicks it.
+ contents_container_->browser_view_->GetLocationBar()->Revert();
+ return MA_NOACTIVATE;
+ }
+
+ private:
+ ContentsContainer* contents_container_;
+
+ DISALLOW_COPY_AND_ASSIGN(TearWindow);
+};
+
+#endif
+
+ContentsContainer::ContentsContainer(BrowserView* browser_view,
+ views::View* active)
+ : browser_view_(browser_view),
+ active_(active),
preview_(NULL),
preview_tab_contents_(NULL),
+ tear_window_(NULL),
active_top_margin_(0) {
AddChildView(active_);
}
ContentsContainer::~ContentsContainer() {
+ DeleteTearWindow();
}
void ContentsContainer::MakePreviewContentsActiveContents() {
active_ = preview_;
preview_ = NULL;
+ DeleteTearWindow();
Layout();
}
@@ -26,14 +83,21 @@ void ContentsContainer::SetPreview(views::View* preview,
if (preview == preview_)
return;
- if (preview_)
+ if (preview_) {
RemoveChildView(preview_);
+ DeleteTearWindow();
+ }
preview_ = preview;
preview_tab_contents_ = preview_tab_contents;
- if (preview_)
+ if (preview_) {
AddChildView(preview_);
+ CreateTearWindow();
+ }
Layout();
+
+ if (preview_)
+ tear_window_->Show(); // Show after we'ved positioned it in Layout.
}
void ContentsContainer::SetActiveTopMargin(int margin) {
@@ -57,10 +121,80 @@ void ContentsContainer::Layout() {
active_->SetBounds(0, active_top_margin_, width(),
std::max(0, height() - active_top_margin_));
- if (preview_)
+ if (preview_) {
preview_->SetBounds(0, 0, width(), height());
+ PositionTearWindow();
+ }
// Need to invoke views::View in case any views whose bounds didn't change
// still need a layout.
views::View::Layout();
}
+
+void ContentsContainer::CreateTearWindow() {
+ DCHECK(preview_);
+ tear_window_ = CreateTearWindowImpl();
+
+ views::ImageView* image_view = new views::ImageView();
+ image_view->SetImage(ResourceBundle::GetSharedInstance().GetBitmapNamed(
+ IDR_MATCH_PREVIEW_TEAR));
+ tear_window_->SetContentsView(image_view);
+}
+
+#if defined(OS_WIN)
+
+ContentsContainer::TearWindow* ContentsContainer::CreateTearWindowImpl() {
+ TearWindow* widget = new TearWindow(this);
+ widget->Init(browser_view_->GetNativeHandle(), gfx::Rect());
+ return widget;
+}
+
+#elif defined(OS_LINUX)
+
+ContentsContainer::TearWindow* ContentsContainer::CreateTearWindowImpl() {
+ views::WidgetGtk* widget = new views::WidgetGtk(views::WidgetGtk::TYPE_POPUP);
+ widget->MakeTransparent();
+ widget->Init(NULL, gfx::Rect());
+ gtk_util::StackPopupWindow(widget->GetNativeView(),
+ GTK_WIDGET(browser_view_->GetNativeHandle()));
+ return widget;
+}
+
+#endif
+
+void ContentsContainer::PositionTearWindow() {
+ if (!tear_window_)
+ return;
+
+ gfx::Rect vis_bounds = GetVisibleBounds();
+
+ gfx::Size pref = tear_window_->GetRootView()->GetPreferredSize();
+ // Constrain to the the visible bounds as we may be given a different size
+ // than is actually visible.
+ pref.SetSize(std::min(pref.width(), vis_bounds.width()),
+ std::min(pref.height(), vis_bounds.height()));
+
+ gfx::Rect bounds(0, 0, pref.width(), pref.height());
+ bounds.set_x(MirroredLeftPointForRect(bounds));
+
+ gfx::Point origin(bounds.origin());
+ views::View::ConvertPointToScreen(this, &origin);
+
+ tear_window_->SetBounds(gfx::Rect(origin, pref));
+}
+
+void ContentsContainer::DeleteTearWindow() {
+ if (!tear_window_)
+ return;
+
+ tear_window_->Close();
+#if defined(OS_WIN)
+ tear_window_->set_contents_container(NULL);
+#endif
+ // Close deletes the tear window.
+ tear_window_ = NULL;
+}
+
+void ContentsContainer::TearWindowDestroyed() {
+ tear_window_ = NULL;
+}