| Index: chrome/browser/ui/views/extensions/extension_popup.cc
|
| ===================================================================
|
| --- chrome/browser/ui/views/extensions/extension_popup.cc (revision 74596)
|
| +++ chrome/browser/ui/views/extensions/extension_popup.cc (working copy)
|
| @@ -14,15 +14,12 @@
|
| #include "chrome/browser/renderer_host/render_widget_host_view.h"
|
| #include "chrome/browser/renderer_host/render_view_host.h"
|
| #include "chrome/browser/ui/browser.h"
|
| -#include "chrome/browser/ui/browser_list.h"
|
| #include "chrome/browser/ui/browser_window.h"
|
| #include "chrome/browser/ui/views/frame/browser_view.h"
|
| -#include "chrome/browser/ui/window_sizer.h"
|
| #include "chrome/common/extensions/extension.h"
|
| #include "chrome/common/notification_details.h"
|
| #include "chrome/common/notification_source.h"
|
| #include "chrome/common/notification_type.h"
|
| -#include "third_party/skia/include/core/SkColor.h"
|
| #include "views/widget/root_view.h"
|
| #include "views/window/window.h"
|
|
|
| @@ -38,10 +35,9 @@
|
| using std::vector;
|
| using views::Widget;
|
|
|
| -// The minimum, and default maximum dimensions of the popup.
|
| +// The minimum/maximum dimensions of the popup.
|
| // The minimum is just a little larger than the size of the button itself.
|
| -// The default maximum is an arbitrary number that should be smaller than most
|
| -// screens.
|
| +// The maximum is an arbitrary number that should be smaller than most screens.
|
| const int ExtensionPopup::kMinWidth = 25;
|
| const int ExtensionPopup::kMinHeight = 25;
|
| const int ExtensionPopup::kMaxWidth = 800;
|
| @@ -60,31 +56,20 @@
|
| views::Widget* frame,
|
| const gfx::Rect& relative_to,
|
| BubbleBorder::ArrowLocation arrow_location,
|
| - bool activate_on_show,
|
| bool inspect_with_devtools,
|
| - PopupChrome chrome,
|
| Observer* observer)
|
| : BrowserBubble(host->view(),
|
| frame,
|
| - gfx::Point(),
|
| - RECTANGLE_CHROME == chrome), // If no bubble chrome is to
|
| - // be displayed, then enable a
|
| - // drop-shadow on the bubble
|
| - // widget.
|
| + gfx::Point()),
|
| relative_to_(relative_to),
|
| extension_host_(host),
|
| - activate_on_show_(activate_on_show),
|
| inspect_with_devtools_(inspect_with_devtools),
|
| close_on_lost_focus_(true),
|
| closing_(false),
|
| border_widget_(NULL),
|
| border_(NULL),
|
| border_view_(NULL),
|
| - popup_chrome_(chrome),
|
| - max_size_(kMaxWidth, kMaxHeight),
|
| - observer_(observer),
|
| - anchor_position_(arrow_location),
|
| - instance_lifetime_(new InternalRefCounter()){
|
| + observer_(observer) {
|
| AddRef(); // Balanced in Close();
|
| set_delegate(this);
|
| host->view()->SetContainer(this);
|
| @@ -108,67 +93,47 @@
|
| relative_to_.set_origin(origin);
|
|
|
| // The bubble chrome requires a separate window, so construct it here.
|
| - if (BUBBLE_CHROME == popup_chrome_) {
|
| - gfx::NativeView native_window = frame->GetNativeView();
|
| + gfx::NativeView native_window = frame->GetNativeView();
|
| #if defined(OS_LINUX)
|
| - border_widget_ = new views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW);
|
| - static_cast<views::WidgetGtk*>(border_widget_)->MakeTransparent();
|
| - static_cast<views::WidgetGtk*>(border_widget_)->make_transient_to_parent();
|
| + border_widget_ = new views::WidgetGtk(views::WidgetGtk::TYPE_WINDOW);
|
| + static_cast<views::WidgetGtk*>(border_widget_)->MakeTransparent();
|
| + static_cast<views::WidgetGtk*>(border_widget_)->make_transient_to_parent();
|
| #else
|
| - border_widget_ = Widget::CreatePopupWidget(Widget::Transparent,
|
| - Widget::NotAcceptEvents,
|
| - Widget::DeleteOnDestroy,
|
| - Widget::MirrorOriginInRTL);
|
| + border_widget_ = Widget::CreatePopupWidget(Widget::Transparent,
|
| + Widget::NotAcceptEvents,
|
| + Widget::DeleteOnDestroy,
|
| + Widget::MirrorOriginInRTL);
|
| #endif
|
| - border_widget_->Init(native_window, bounds());
|
| + border_widget_->Init(native_window, bounds());
|
| #if defined(OS_CHROMEOS)
|
| - {
|
| - vector<int> params;
|
| - params.push_back(0); // don't show while screen is locked
|
| - chromeos::WmIpc::instance()->SetWindowType(
|
| - border_widget_->GetNativeView(),
|
| - chromeos::WM_IPC_WINDOW_CHROME_INFO_BUBBLE,
|
| - ¶ms);
|
| - }
|
| + {
|
| + vector<int> params;
|
| + params.push_back(0); // don't show while screen is locked
|
| + chromeos::WmIpc::instance()->SetWindowType(
|
| + border_widget_->GetNativeView(),
|
| + chromeos::WM_IPC_WINDOW_CHROME_INFO_BUBBLE,
|
| + ¶ms);
|
| + }
|
| #endif
|
| - border_ = new BubbleBorder(arrow_location);
|
| - border_view_ = new views::View;
|
| - border_view_->set_background(new BubbleBackground(border_));
|
| + border_ = new BubbleBorder(arrow_location);
|
| + border_view_ = new views::View;
|
| + border_view_->set_background(new BubbleBackground(border_));
|
|
|
| - border_view_->set_border(border_);
|
| - border_widget_->SetContentsView(border_view_);
|
| - // Ensure that the popup contents are always displayed ontop of the border
|
| - // widget.
|
| - border_widget_->MoveAbove(popup_);
|
| - } else {
|
| - // Otherwise simply set a black-border on the view containing the popup
|
| - // extension view.
|
| - views::Border* border = views::Border::CreateSolidBorder(kPopupBorderWidth,
|
| - SK_ColorBLACK);
|
| - view()->set_border(border);
|
| - }
|
| + border_view_->set_border(border_);
|
| + border_widget_->SetContentsView(border_view_);
|
| + // Ensure that the popup contents are always displayed ontop of the border
|
| + // widget.
|
| + border_widget_->MoveAbove(popup_);
|
| }
|
|
|
| ExtensionPopup::~ExtensionPopup() {
|
| // The widget is set to delete on destroy, so no leak here.
|
| - if (border_widget_)
|
| - border_widget_->Close();
|
| + border_widget_->Close();
|
| }
|
|
|
| -void ExtensionPopup::SetArrowPosition(
|
| - BubbleBorder::ArrowLocation arrow_location) {
|
| - DCHECK_NE(BubbleBorder::NONE, arrow_location) <<
|
| - "Extension popups must be positioned relative to an arrow.";
|
| -
|
| - anchor_position_ = arrow_location;
|
| - if (border_)
|
| - border_->set_arrow_location(anchor_position_);
|
| -}
|
| -
|
| void ExtensionPopup::Hide() {
|
| BrowserBubble::Hide();
|
| - if (border_widget_)
|
| - border_widget_->Hide();
|
| + border_widget_->Hide();
|
| }
|
|
|
| void ExtensionPopup::Show(bool activate) {
|
| @@ -176,46 +141,43 @@
|
| return;
|
|
|
| #if defined(OS_WIN)
|
| - if (frame_->GetWindow())
|
| - frame_->GetWindow()->DisableInactiveRendering();
|
| + frame_->GetWindow()->DisableInactiveRendering();
|
| #endif
|
|
|
| ResizeToView();
|
|
|
| // Show the border first, then the popup overlaid on top.
|
| - if (border_widget_)
|
| - border_widget_->Show();
|
| + border_widget_->Show();
|
| BrowserBubble::Show(activate);
|
| }
|
|
|
| void ExtensionPopup::ResizeToView() {
|
| - if (observer_)
|
| - observer_->ExtensionPopupResized(this);
|
| + // We'll be sizing ourselves to this size shortly, but wait until we
|
| + // know our position to do it.
|
| + gfx::Size new_size = view()->size();
|
|
|
| - gfx::Rect rect = GetOuterBounds();
|
| + // The rounded corners cut off more of the view than the border insets claim.
|
| + // Since we can't clip the ExtensionView's corners, we need to increase the
|
| + // inset by half the corner radius as well as lying about the size of the
|
| + // contents size to compensate.
|
| + int corner_inset = BubbleBorder::GetCornerRadius() / 2;
|
| + gfx::Size adjusted_size = new_size;
|
| + adjusted_size.Enlarge(2 * corner_inset, 2 * corner_inset);
|
| + gfx::Rect rect = border_->GetBounds(relative_to_, adjusted_size);
|
| + border_widget_->SetBounds(rect);
|
|
|
| + // Now calculate the inner bounds. This is a bit more convoluted than
|
| + // it should be because BrowserBubble coordinates are in Browser coordinates
|
| + // while |rect| is in screen coordinates.
|
| + gfx::Insets border_insets;
|
| + border_->GetInsets(&border_insets);
|
| gfx::Point origin = rect.origin();
|
| views::View::ConvertPointToView(NULL, frame_->GetRootView(), &origin);
|
|
|
| - if (border_widget_) {
|
| - // Set the bubble-chrome widget according to the outer bounds of the entire
|
| - // popup.
|
| - border_widget_->SetBounds(rect);
|
| + origin.set_x(origin.x() + border_insets.left() + corner_inset);
|
| + origin.set_y(origin.y() + border_insets.top() + corner_inset);
|
|
|
| - // Now calculate the inner bounds. This is a bit more convoluted than
|
| - // it should be because BrowserBubble coordinates are in Browser coordinates
|
| - // while |rect| is in screen coordinates.
|
| - gfx::Insets border_insets;
|
| - border_->GetInsets(&border_insets);
|
| -
|
| - origin.set_x(origin.x() + border_insets.left() + kPopupBubbleCornerRadius);
|
| - origin.set_y(origin.y() + border_insets.top() + kPopupBubbleCornerRadius);
|
| -
|
| - gfx::Size new_size = view()->size();
|
| - SetBounds(origin.x(), origin.y(), new_size.width(), new_size.height());
|
| - } else {
|
| - SetBounds(origin.x(), origin.y(), rect.width(), rect.height());
|
| - }
|
| + SetBounds(origin.x(), origin.y(), new_size.width(), new_size.height());
|
| }
|
|
|
| void ExtensionPopup::BubbleBrowserWindowMoved(BrowserBubble* bubble) {
|
| @@ -259,7 +221,7 @@
|
| // Once we receive did stop loading, the content will be complete and
|
| // the width will have been computed. Now it's safe to show.
|
| if (extension_host_.get() == Details<ExtensionHost>(details).ptr()) {
|
| - Show(activate_on_show_);
|
| + Show(true);
|
|
|
| if (inspect_with_devtools_) {
|
| // Listen for the the devtools window closing.
|
| @@ -299,121 +261,38 @@
|
| void ExtensionPopup::OnExtensionPreferredSizeChanged(ExtensionView* view) {
|
| // Constrain the size to popup min/max.
|
| gfx::Size sz = view->GetPreferredSize();
|
| -
|
| - // Enforce that the popup never resizes to larger than the working monitor
|
| - // bounds.
|
| - scoped_ptr<WindowSizer::MonitorInfoProvider> monitor_provider(
|
| - WindowSizer::CreateDefaultMonitorInfoProvider());
|
| - gfx::Rect monitor_bounds(
|
| - monitor_provider->GetMonitorWorkAreaMatching(relative_to_));
|
| -
|
| - int max_width = std::min(max_size_.width(), monitor_bounds.width());
|
| - int max_height = std::min(max_size_.height(), monitor_bounds.height());
|
| view->SetBounds(view->x(), view->y(),
|
| - std::max(kMinWidth, std::min(max_width, sz.width())),
|
| - std::max(kMinHeight, std::min(max_height, sz.height())));
|
| + std::max(kMinWidth, std::min(kMaxWidth, sz.width())),
|
| + std::max(kMinHeight, std::min(kMaxHeight, sz.height())));
|
|
|
| - // If popup_chrome_ == RECTANGLE_CHROME, the border is drawn in the client
|
| - // area of the ExtensionView, rather than in a window which sits behind it.
|
| - // In this case, the actual size of the view must be enlarged so that the
|
| - // web contents portion of the view gets its full PreferredSize area.
|
| - if (view->border()) {
|
| - gfx::Insets border_insets;
|
| - view->border()->GetInsets(&border_insets);
|
| -
|
| - gfx::Rect bounds(view->bounds());
|
| - gfx::Size size(bounds.size());
|
| - size.Enlarge(border_insets.width(), border_insets.height());
|
| - view->SetBounds(bounds.x(), bounds.y(), size.width(), size.height());
|
| - }
|
| -
|
| ResizeToView();
|
| }
|
|
|
| -gfx::Rect ExtensionPopup::GetOuterBounds() const {
|
| - gfx::Rect relative_rect = relative_to_;
|
| - gfx::Point origin = relative_rect.origin();
|
| - views::View::ConvertPointToScreen(frame_->GetRootView(), &origin);
|
| - relative_rect.set_origin(origin);
|
| -
|
| - gfx::Size contents_size = view()->size();
|
| -
|
| - // If the popup has a bubble-chrome, then let the BubbleBorder compute
|
| - // the bounds.
|
| - if (BUBBLE_CHROME == popup_chrome_) {
|
| - // The rounded corners cut off more of the view than the border insets
|
| - // claim. Since we can't clip the ExtensionView's corners, we need to
|
| - // increase the inset by half the corner radius as well as lying about the
|
| - // size of the contents size to compensate.
|
| - contents_size.Enlarge(2 * kPopupBubbleCornerRadius,
|
| - 2 * kPopupBubbleCornerRadius);
|
| - return border_->GetBounds(relative_rect, contents_size);
|
| - }
|
| -
|
| - // Position the bounds according to the location of the |anchor_position_|.
|
| - int y;
|
| - if (BubbleBorder::is_arrow_on_top(anchor_position_))
|
| - y = relative_rect.bottom();
|
| - else
|
| - y = relative_rect.y() - contents_size.height();
|
| -
|
| - int x;
|
| - if (BubbleBorder::is_arrow_on_left(anchor_position_))
|
| - x = relative_rect.x();
|
| - else
|
| - // Note that if the arrow is on the right, that the x position of the popup
|
| - // is assigned so that the rightmost edge of the popup is aligned with the
|
| - // rightmost edge of the relative region.
|
| - x = relative_rect.right() - contents_size.width();
|
| -
|
| - return gfx::Rect(x, y, contents_size.width(), contents_size.height());
|
| -}
|
| -
|
| // static
|
| ExtensionPopup* ExtensionPopup::Show(
|
| const GURL& url,
|
| Browser* browser,
|
| - Profile* profile,
|
| - gfx::NativeWindow frame_window,
|
| const gfx::Rect& relative_to,
|
| BubbleBorder::ArrowLocation arrow_location,
|
| - bool activate_on_show,
|
| bool inspect_with_devtools,
|
| - PopupChrome chrome,
|
| Observer* observer) {
|
| - DCHECK(profile);
|
| - DCHECK(frame_window);
|
| - ExtensionProcessManager* manager = profile->GetExtensionProcessManager();
|
| + ExtensionProcessManager* manager =
|
| + browser->profile()->GetExtensionProcessManager();
|
| DCHECK(manager);
|
| if (!manager)
|
| return NULL;
|
|
|
| - // If no Browser instance was given, attempt to look up one matching the given
|
| - // profile.
|
| - if (!browser)
|
| - browser = BrowserList::FindBrowserWithProfile(profile);
|
| -
|
| - Widget* frame_widget = Widget::GetWidgetFromNativeWindow(frame_window);
|
| - DCHECK(frame_widget);
|
| - if (!frame_widget)
|
| - return NULL;
|
| -
|
| ExtensionHost* host = manager->CreatePopup(url, browser);
|
| - if (observer)
|
| - observer->ExtensionHostCreated(host);
|
| + views::Widget* frame = BrowserView::GetBrowserViewForNativeWindow(
|
| + browser->window()->GetNativeHandle())->GetWidget();
|
| + ExtensionPopup* popup = new ExtensionPopup(host, frame, relative_to,
|
| + arrow_location,
|
| + inspect_with_devtools, observer);
|
|
|
| - ExtensionPopup* popup = new ExtensionPopup(host, frame_widget, relative_to,
|
| - arrow_location, activate_on_show,
|
| - inspect_with_devtools, chrome,
|
| - observer);
|
| -
|
| - if (observer)
|
| - observer->ExtensionPopupCreated(popup);
|
| -
|
| // If the host had somehow finished loading, then we'd miss the notification
|
| // and not show. This seems to happen in single-process mode.
|
| if (host->did_stop_loading())
|
| - popup->Show(activate_on_show);
|
| + popup->Show(true);
|
|
|
| return popup;
|
| }
|
| @@ -429,18 +308,3 @@
|
|
|
| Release(); // Balanced in ctor.
|
| }
|
| -
|
| -void ExtensionPopup::Release() {
|
| - bool final_release = instance_lifetime_->HasOneRef();
|
| - instance_lifetime_->Release();
|
| - if (final_release) {
|
| - DCHECK(closing_) << "ExtensionPopup to be destroyed before being closed.";
|
| - ExtensionPopup::Observer* observer = observer_;
|
| - delete this;
|
| -
|
| - // |this| is passed only as a 'cookie'. The observer API explicitly takes a
|
| - // void* argument to emphasize this.
|
| - if (observer)
|
| - observer->ExtensionPopupClosed(this);
|
| - }
|
| -}
|
|
|