diff options
author | twiz@chromium.org <twiz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-12 20:27:10 +0000 |
---|---|---|
committer | twiz@chromium.org <twiz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-12 20:27:10 +0000 |
commit | c7bf140b32a1a6504e48716b90c6a13fd5c421d3 (patch) | |
tree | 876ada1f8ca6320060aab4db3790522989829d31 /chrome/browser | |
parent | 1be7eadb032256687abda35ae4b2ba4770757c70 (diff) | |
download | chromium_src-c7bf140b32a1a6504e48716b90c6a13fd5c421d3.zip chromium_src-c7bf140b32a1a6504e48716b90c6a13fd5c421d3.tar.gz chromium_src-c7bf140b32a1a6504e48716b90c6a13fd5c421d3.tar.bz2 |
Clone of issue 577015.
See http://codereview.chromium.org/577015 for the review status of this CL.
BUG=None
TEST=ExtensionApiTest.Popup
Review URL: http://codereview.chromium.org/600101
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@38927 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/extensions/extension_popup_api.cc | 19 | ||||
-rw-r--r-- | chrome/browser/views/browser_actions_container.cc | 16 | ||||
-rw-r--r-- | chrome/browser/views/browser_bubble.cc | 5 | ||||
-rw-r--r-- | chrome/browser/views/browser_bubble.h | 8 | ||||
-rw-r--r-- | chrome/browser/views/browser_bubble_gtk.cc | 4 | ||||
-rw-r--r-- | chrome/browser/views/browser_bubble_win.cc | 5 | ||||
-rw-r--r-- | chrome/browser/views/extensions/extension_popup.cc | 157 | ||||
-rw-r--r-- | chrome/browser/views/extensions/extension_popup.h | 31 | ||||
-rw-r--r-- | chrome/browser/views/extensions/extension_shelf.cc | 3 | ||||
-rw-r--r-- | chrome/browser/views/location_bar_view.cc | 16 |
10 files changed, 195 insertions, 69 deletions
diff --git a/chrome/browser/extensions/extension_popup_api.cc b/chrome/browser/extensions/extension_popup_api.cc index f68553c..48e414c 100644 --- a/chrome/browser/extensions/extension_popup_api.cc +++ b/chrome/browser/extensions/extension_popup_api.cc @@ -44,6 +44,10 @@ const wchar_t kTopKey[] = L"top"; const wchar_t kLeftKey[] = L"left"; const wchar_t kGiveFocusKey[] = L"giveFocus"; const wchar_t kDomAnchorKey[] = L"domAnchor"; +const wchar_t kBorderStyleKey[] = L"borderStyle"; + +// chrome enumeration values +const char kRectangleChrome[] = "rectangle"; }; // namespace @@ -111,6 +115,18 @@ bool PopupShowFunction::RunImpl() { &give_focus)); } +#if defined(TOOLKIT_VIEWS) + // The default behaviour is to provide the bubble-chrome to the popup. + ExtensionPopup::PopupChrome chrome = ExtensionPopup::BUBBLE_CHROME; + if (show_details->HasKey(kBorderStyleKey)) { + std::string chrome_string; + EXTENSION_FUNCTION_VALIDATE(show_details->GetString(kBorderStyleKey, + &chrome_string)); + if (chrome_string == kRectangleChrome) + chrome = ExtensionPopup::RECTANGLE_CHROME; + } +#endif + GURL url = dispatcher()->url().Resolve(url_string); if (!url.is_valid()) { error_ = kInvalidURLError; @@ -144,7 +160,8 @@ bool PopupShowFunction::RunImpl() { dispatcher()->GetFrameNativeWindow(), rect, arrow_location, - give_focus); + give_focus, + chrome); ExtensionPopupHost* popup_host = dispatcher()->GetPopupHost(); DCHECK(popup_host); diff --git a/chrome/browser/views/browser_actions_container.cc b/chrome/browser/views/browser_actions_container.cc index 5a1ae90..be8cf1b 100644 --- a/chrome/browser/views/browser_actions_container.cc +++ b/chrome/browser/views/browser_actions_container.cc @@ -534,13 +534,15 @@ void BrowserActionsContainer::OnBrowserActionExecuted( BubbleBorder::ArrowLocation arrow_location = UILayoutIsRightToLeft() ? BubbleBorder::TOP_LEFT : BubbleBorder::TOP_RIGHT; - popup_ = ExtensionPopup::Show(button->GetPopupUrl(), - browser_, - browser_->profile(), - frame_window, - rect, - arrow_location, - true); // Activate the popup window. + popup_ = ExtensionPopup::Show( + button->GetPopupUrl(), + browser_, + browser_->profile(), + frame_window, + rect, + arrow_location, + true, // Activate the popup window. + ExtensionPopup::BUBBLE_CHROME); popup_->set_delegate(this); popup_button_ = button; popup_button_->SetButtonPushed(); diff --git a/chrome/browser/views/browser_bubble.cc b/chrome/browser/views/browser_bubble.cc index 26dff82..1b690db 100644 --- a/chrome/browser/views/browser_bubble.cc +++ b/chrome/browser/views/browser_bubble.cc @@ -25,12 +25,13 @@ BrowserView* GetBrowserViewFromFrame(views::Widget* frame) { } // namespace BrowserBubble::BrowserBubble(views::View* view, views::Widget* frame, - const gfx::Point& origin) + const gfx::Point& origin, bool drop_shadow) : frame_(frame), view_(view), visible_(false), delegate_(NULL), - attached_(false) { + attached_(false), + drop_shadow_enabled_(drop_shadow) { gfx::Size size = view->GetPreferredSize(); bounds_.SetRect(origin.x(), origin.y(), size.width(), size.height()); InitPopup(); diff --git a/chrome/browser/views/browser_bubble.h b/chrome/browser/views/browser_bubble.h index 25b91e9..012c552 100644 --- a/chrome/browser/views/browser_bubble.h +++ b/chrome/browser/views/browser_bubble.h @@ -38,9 +38,10 @@ class BrowserBubble { // Note that the bubble will size itself to the preferred size of |view|. // |view| is the embedded view, |frame| is widget that the bubble is being // positioned relative to, |origin| is the location that the bubble will - // be positioned relative to |frame|. + // be positioned relative to |frame|. Pass true through |drop_shadow| to + // surround the bubble widget with a drop-shadow. BrowserBubble(views::View* view, views::Widget* frame, - const gfx::Point& origin); + const gfx::Point& origin, bool drop_shadow); virtual ~BrowserBubble(); // Call manually if you need to detach the bubble from tracking the browser's @@ -116,6 +117,9 @@ class BrowserBubble { // Is the bubble attached to a Browser window. bool attached_; + // Does the bubble have a drop-shadow. + bool drop_shadow_enabled_; + DISALLOW_COPY_AND_ASSIGN(BrowserBubble); }; diff --git a/chrome/browser/views/browser_bubble_gtk.cc b/chrome/browser/views/browser_bubble_gtk.cc index ebc343a..66b07c1 100644 --- a/chrome/browser/views/browser_bubble_gtk.cc +++ b/chrome/browser/views/browser_bubble_gtk.cc @@ -76,6 +76,10 @@ class BubbleWidget : public views::WidgetGtk { } // namespace void BrowserBubble::InitPopup() { + // TODO(port) + DCHECK(!drop_shadow_enabled_) << + "Drop shadows not supported on GTK browser bubbles."; + views::WidgetGtk* pop = new BubbleWidget(this); pop->SetOpacity(0xFF); pop->make_transient_to_parent(); diff --git a/chrome/browser/views/browser_bubble_win.cc b/chrome/browser/views/browser_bubble_win.cc index 2a2a4c2..a74b84a 100644 --- a/chrome/browser/views/browser_bubble_win.cc +++ b/chrome/browser/views/browser_bubble_win.cc @@ -79,6 +79,11 @@ void BrowserBubble::InitPopup() { // popup_ is a Widget, but we need to do some WidgetWin stuff first, then // we'll assign it into popup_. views::WidgetWin* pop = new BubbleWidget(this); + + // Enable the drop-shadow through the native windows drop-shadow support. + if (drop_shadow_enabled_) + pop->set_initial_class_style(CS_DROPSHADOW | pop->initial_class_style()); + pop->Init(frame_->GetNativeView(), bounds_); pop->SetContentsView(view_); diff --git a/chrome/browser/views/extensions/extension_popup.cc b/chrome/browser/views/extensions/extension_popup.cc index 9fc5ae7..70c9222 100644 --- a/chrome/browser/views/extensions/extension_popup.cc +++ b/chrome/browser/views/extensions/extension_popup.cc @@ -14,6 +14,7 @@ #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" @@ -32,17 +33,32 @@ const int ExtensionPopup::kMinHeight = 25; const int ExtensionPopup::kMaxWidth = 800; const int ExtensionPopup::kMaxHeight = 600; +// The width, in pixels, of the black-border on a popup. +const int kPopupBorderWidth = 1; + +const int kPopupBubbleCornerRadius = BubbleBorder::GetCornerRadius() / 2; + ExtensionPopup::ExtensionPopup(ExtensionHost* host, views::Widget* frame, const gfx::Rect& relative_to, BubbleBorder::ArrowLocation arrow_location, - bool activate_on_show) + bool activate_on_show, + PopupChrome chrome) : BrowserBubble(host->view(), frame, - gfx::Point()), + gfx::Point(), + RECTANGLE_CHROME == chrome), // If no bubble chrome is to + // be displayed, then enable a + // drop-shadow on the bubble + // widget. relative_to_(relative_to), extension_host_(host), - activate_on_show_(activate_on_show) { + activate_on_show_(activate_on_show), + border_widget_(NULL), + border_(NULL), + border_view_(NULL), + popup_chrome_(chrome), + anchor_position_(arrow_location) { host->view()->SetContainer(this); registrar_.Add(this, NotificationType::EXTENSION_HOST_DID_STOP_LOADING, @@ -51,45 +67,56 @@ ExtensionPopup::ExtensionPopup(ExtensionHost* host, // TODO(erikkay) Some of this border code is derived from InfoBubble. // We should see if we can unify these classes. - gfx::NativeView native_window = frame->GetNativeView(); + // The bubble chrome requires a separate window, so construct it here. + if (BUBBLE_CHROME == popup_chrome_) { + 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); + border_widget_ = Widget::CreatePopupWidget(Widget::Transparent, + Widget::NotAcceptEvents, + Widget::DeleteOnDestroy); #endif - border_widget_->Init(native_window, bounds()); + border_widget_->Init(native_window, bounds()); #if defined(OS_LINUX) - TabOverviewTypes::instance()->SetWindowType( - border_widget_->GetNativeView(), - TabOverviewTypes::WINDOW_TYPE_CHROME_INFO_BUBBLE, - NULL); + TabOverviewTypes::instance()->SetWindowType( + border_widget_->GetNativeView(), + TabOverviewTypes::WINDOW_TYPE_CHROME_INFO_BUBBLE, + NULL); #endif - border_ = new BubbleBorder; - border_->set_arrow_location(arrow_location); + border_ = new BubbleBorder; + border_->set_arrow_location(arrow_location); - border_view_ = new views::View; - border_view_->set_background(new BubbleBackground(border_)); - border_view_->set_border(border_); - border_widget_->SetContentsView(border_view_); + border_view_ = new views::View; + border_view_->set_background(new BubbleBackground(border_)); - // Ensure that the popup contents are always displayed ontop of the border - // widget. - border_widget_->MoveAbove(popup_); + 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); + } } ExtensionPopup::~ExtensionPopup() { // The widget is set to delete on destroy, so no leak here. - border_widget_->Close(); + if (border_widget_) + border_widget_->Close(); } void ExtensionPopup::Hide() { BrowserBubble::Hide(); - border_widget_->Hide(); + if (border_widget_) + border_widget_->Hide(); } void ExtensionPopup::Show(bool activate) { @@ -104,7 +131,8 @@ void ExtensionPopup::Show(bool activate) { ResizeToView(); // Show the border first, then the popup overlaid on top. - border_widget_->Show(); + if (border_widget_) + border_widget_->Show(); BrowserBubble::Show(activate); } @@ -113,27 +141,27 @@ void ExtensionPopup::ResizeToView() { // know our position to do it. gfx::Size new_size = view()->size(); - // 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::Rect rect = GetOuterBounds(relative_to_, new_size); gfx::Point origin = rect.origin(); views::View::ConvertPointToView(NULL, frame_->GetRootView(), &origin); - origin.set_x(origin.x() + border_insets.left() + corner_inset); - origin.set_y(origin.y() + border_insets.top() + corner_inset); + if (border_widget_) { + // Set the bubble-chrome widget according to the outer bounds of the entire + // popup. + border_widget_->SetBounds(rect); - SetBounds(origin.x(), origin.y(), new_size.width(), new_size.height()); + // 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); + + SetBounds(origin.x(), origin.y(), new_size.width(), new_size.height()); + } else { + SetBounds(origin.x(), origin.y(), rect.width(), rect.height()); + } } void ExtensionPopup::Observe(NotificationType type, @@ -159,6 +187,39 @@ void ExtensionPopup::OnExtensionPreferredSizeChanged(ExtensionView* view) { ResizeToView(); } +gfx::Rect ExtensionPopup::GetOuterBounds(const gfx::Rect& position_relative_to, + const gfx::Size& contents_size) const { + gfx::Size adjusted_size = contents_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. + adjusted_size.Enlarge(2 * kPopupBubbleCornerRadius, + 2 * kPopupBubbleCornerRadius); + return border_->GetBounds(position_relative_to, adjusted_size); + } + + // Otherwise, enlarge the bounds by the size of the local border. + gfx::Insets border_insets; + view()->border()->GetInsets(&border_insets); + adjusted_size.Enlarge(border_insets.width(), border_insets.height()); + + // Position the bounds according to the location of the |anchor_position_|. + int y; + if ((anchor_position_ == BubbleBorder::TOP_LEFT) || + (anchor_position_ == BubbleBorder::TOP_RIGHT)) { + y = position_relative_to.bottom(); + } else { + y = position_relative_to.y() - adjusted_size.height(); + } + + return gfx::Rect(position_relative_to.x(), y, adjusted_size.width(), + adjusted_size.height()); +} + // static ExtensionPopup* ExtensionPopup::Show( const GURL& url, @@ -167,7 +228,8 @@ ExtensionPopup* ExtensionPopup::Show( gfx::NativeWindow frame_window, const gfx::Rect& relative_to, BubbleBorder::ArrowLocation arrow_location, - bool activate_on_show) { + bool activate_on_show, + PopupChrome chrome) { DCHECK(profile); DCHECK(frame_window); ExtensionProcessManager* manager = profile->GetExtensionProcessManager(); @@ -187,7 +249,8 @@ ExtensionPopup* ExtensionPopup::Show( ExtensionHost* host = manager->CreatePopup(url, browser); ExtensionPopup* popup = new ExtensionPopup(host, frame_widget, relative_to, - arrow_location, activate_on_show); + arrow_location, activate_on_show, + chrome); // If the host had somehow finished loading, then we'd miss the notification // and not show. This seems to happen in single-process mode. diff --git a/chrome/browser/views/extensions/extension_popup.h b/chrome/browser/views/extensions/extension_popup.h index 92eab93..72df7b2 100644 --- a/chrome/browser/views/extensions/extension_popup.h +++ b/chrome/browser/views/extensions/extension_popup.h @@ -26,6 +26,11 @@ class ExtensionPopup : public BrowserBubble, public NotificationObserver, public ExtensionView::Container { public: + enum PopupChrome { + BUBBLE_CHROME, + RECTANGLE_CHROME + }; + virtual ~ExtensionPopup(); // Create and show a popup with |url| positioned adjacent to |relative_to| in @@ -42,6 +47,12 @@ class ExtensionPopup : public BrowserBubble, // If |arrow_location| is BOTTOM_*, then the popup 'pops up', otherwise // the popup 'drops down'. // Pass |activate_on_show| as true to activate the popup window. + // The |chrome| argument controls the chrome that surrounds the pop-up. + // Passing BUBBLE_CHROME will give the pop-up a bubble-like appearance, + // including the arrow mentioned above. Passing RECTANGLE_CHROME will give + // the popup a rectangular, black border with a drop-shadow with no arrow. + // The positioning of the popup is still governed by the arrow-location + // parameter. // // The actual display of the popup is delayed until the page contents // finish loading in order to minimize UI flashing and resizing. @@ -50,7 +61,8 @@ class ExtensionPopup : public BrowserBubble, gfx::NativeWindow frame_window, const gfx::Rect& relative_to, BubbleBorder::ArrowLocation arrow_location, - bool activate_on_show); + bool activate_on_show, + PopupChrome chrome); ExtensionHost* host() const { return extension_host_.get(); } @@ -80,7 +92,14 @@ class ExtensionPopup : public BrowserBubble, views::Widget* frame, const gfx::Rect& relative_to, BubbleBorder::ArrowLocation arrow_location, - bool activate_on_show); + bool activate_on_show, + PopupChrome chrome); + + // Gives the desired bounds (in screen coordinates) given the rect to point + // to and the size of the contained contents. Includes all of the + // border-chrome surrounding the pop-up as well. + gfx::Rect GetOuterBounds(const gfx::Rect& position_relative_to, + const gfx::Size& contents_size) const; // The area on the screen that the popup should be positioned relative to. gfx::Rect relative_to_; @@ -101,6 +120,14 @@ class ExtensionPopup : public BrowserBubble, BubbleBorder* border_; views::View* border_view_; + // The type of chrome associated with the popup window. + PopupChrome popup_chrome_; + + // A cached copy of the arrow-position for the bubble chrome. + // If a black-border was requested, we still need this value to determine + // the position of the pop-up in relation to |relative_to_|. + BubbleBorder::ArrowLocation anchor_position_; + DISALLOW_COPY_AND_ASSIGN(ExtensionPopup); }; diff --git a/chrome/browser/views/extensions/extension_shelf.cc b/chrome/browser/views/extensions/extension_shelf.cc index 69b6dc1..640dfed 100644 --- a/chrome/browser/views/extensions/extension_shelf.cc +++ b/chrome/browser/views/extensions/extension_shelf.cc @@ -428,7 +428,8 @@ void ExtensionShelf::Toolstrip::LayoutWindow() { if (!window_.get()) { window_.reset(new BrowserBubble(this, shelf_->GetWidget(), - gfx::Point(0, 0))); + gfx::Point(0, 0), + false)); // Do not add a drop-shadow. window_->set_delegate(this); } diff --git a/chrome/browser/views/location_bar_view.cc b/chrome/browser/views/location_bar_view.cc index fef451d..18d0f1a 100644 --- a/chrome/browser/views/location_bar_view.cc +++ b/chrome/browser/views/location_bar_view.cc @@ -1501,13 +1501,15 @@ void LocationBarView::PageActionImageView::ExecuteAction(int button) { rect.set_x(origin.x()); rect.set_y(origin.y()); - popup_ = ExtensionPopup::Show(page_action_->GetPopupUrl(current_tab_id_), - browser, - browser->profile(), - browser->window()->GetNativeHandle(), - rect, - BubbleBorder::TOP_RIGHT, - true); // Activate the popup window. + popup_ = ExtensionPopup::Show( + page_action_->GetPopupUrl(current_tab_id_), + browser, + browser->profile(), + browser->window()->GetNativeHandle(), + rect, + BubbleBorder::TOP_RIGHT, + true, // Activate the popup window. + ExtensionPopup::BUBBLE_CHROME); popup_->set_delegate(this); } else { ExtensionBrowserEventRouter::GetInstance()->PageActionExecuted( |