summaryrefslogtreecommitdiffstats
path: root/chrome/browser/extensions
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/extensions')
-rw-r--r--chrome/browser/extensions/extension_popup_api.cc70
1 files changed, 70 insertions, 0 deletions
diff --git a/chrome/browser/extensions/extension_popup_api.cc b/chrome/browser/extensions/extension_popup_api.cc
index 6dbae99..acc47e3 100644
--- a/chrome/browser/extensions/extension_popup_api.cc
+++ b/chrome/browser/extensions/extension_popup_api.cc
@@ -16,6 +16,7 @@
#include "chrome/browser/renderer_host/render_view_host_delegate.h"
#include "chrome/browser/renderer_host/render_widget_host_view.h"
#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/window_sizer.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/notification_details.h"
#include "chrome/common/notification_service.h"
@@ -25,6 +26,7 @@
#include "gfx/point.h"
#if defined(TOOLKIT_VIEWS)
+#include "chrome/browser/views/bubble_border.h"
#include "chrome/browser/views/extensions/extension_popup.h"
#include "views/view.h"
#include "views/focus/focus_manager.h"
@@ -58,6 +60,35 @@ const wchar_t kBorderStyleKey[] = L"borderStyle";
// chrome enumeration values
const char kRectangleChrome[] = "rectangle";
+#if defined(TOOLKIT_VIEWS)
+// Returns an updated arrow location, conditioned on the type of intersection
+// between the popup window, and the screen. |location| is the current position
+// of the arrow on the popup. |intersection| is the rect representing the
+// intersection between the popup view and its working screen. |popup_rect|
+// is the rect of the popup window in screen space coordinates.
+// The returned location will be horizontally or vertically inverted based on
+// if the popup has been clipped horizontally or vertically.
+BubbleBorder::ArrowLocation ToggleArrowLocation(
+ BubbleBorder::ArrowLocation location, const gfx::Rect& intersection,
+ const gfx::Rect& popup_rect) {
+ // If the popup has been clipped horizontally, flip the right-left position
+ // of the arrow.
+ if (intersection.right() != popup_rect.right() ||
+ intersection.x() != popup_rect.x()) {
+ location = BubbleBorder::horizontal_mirror(location);
+ }
+
+ // If the popup has been clipped vertically, flip the bottom-top position
+ // of the arrow.
+ if (intersection.y() != popup_rect.y() ||
+ intersection.bottom() != popup_rect.bottom()) {
+ location = BubbleBorder::vertical_mirror(location);
+ }
+
+ return location;
+}
+#endif // TOOLKIT_VIEWS
+
}; // namespace
#if defined(TOOLKIT_VIEWS)
@@ -124,6 +155,45 @@ class ExtensionPopupHost : public ExtensionPopup::Observer,
router->RegisterRenderViewHost(host->render_view_host());
}
+ virtual void ExtensionPopupResized(ExtensionPopup* popup) {
+ // Reposition the location of the arrow on the popup so that the popup
+ // better fits on the working monitor.
+ gfx::Rect popup_rect = popup->GetOuterBounds();
+ if (popup_rect.IsEmpty())
+ return;
+
+ scoped_ptr<WindowSizer::MonitorInfoProvider> monitor_provider(
+ WindowSizer::CreateDefaultMonitorInfoProvider());
+ gfx::Rect monitor_bounds(
+ monitor_provider->GetMonitorWorkAreaMatching(popup_rect));
+ gfx::Rect intersection = monitor_bounds.Intersect(popup_rect);
+
+ // If the popup is totally out of the bounds of the monitor, then toggling
+ // the arrow location will not result in an un-clipped window.
+ if (intersection.IsEmpty())
+ return;
+
+ if (!intersection.Equals(popup_rect)) {
+ // The popup was clipped by the monitor. Toggle the arrow position
+ // to see if that improves visibility. Note: The assignment and
+ // re-assignment of the arrow-position will not trigger an intermittent
+ // display.
+ BubbleBorder::ArrowLocation previous_location = popup->arrow_position();
+ BubbleBorder::ArrowLocation flipped_location = ToggleArrowLocation(
+ previous_location, intersection, popup_rect);
+ popup->SetArrowPosition(flipped_location);
+
+ // Double check that toggling the position actually improved the
+ // situation - the popup will be contained entirely in its working monitor
+ // bounds.
+ gfx::Rect flipped_bounds = popup->GetOuterBounds();
+ gfx::Rect updated_monitor_bounds =
+ monitor_provider->GetMonitorWorkAreaMatching(flipped_bounds);
+ if (!updated_monitor_bounds.Contains(flipped_bounds))
+ popup->SetArrowPosition(previous_location);
+ }
+ }
+
virtual void DispatchPopupClosedEvent() {
PopupEventRouter::OnPopupClosed(
dispatcher_->profile(), dispatcher_->render_view_host()->routing_id());