summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
authorrohitrao@chromium.org <rohitrao@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-14 15:24:31 +0000
committerrohitrao@chromium.org <rohitrao@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-14 15:24:31 +0000
commit96649a0f3cafe764eb191532f635d99c234ea005 (patch)
tree4450b4a03d498df44850ef549814a458cbc77be9 /chrome/browser
parent3313359d46d2a4f0e0dc8c4dc476462dec8c988a (diff)
downloadchromium_src-96649a0f3cafe764eb191532f635d99c234ea005.zip
chromium_src-96649a0f3cafe764eb191532f635d99c234ea005.tar.gz
chromium_src-96649a0f3cafe764eb191532f635d99c234ea005.tar.bz2
Enable basic saving/restoring window placements on Mac.
Refactors the existing WindowSizer code to move platform-specific code into separate files. Future CLs will add Mac support for muliple monitors. TEST=Browser windows should remember their position on Mac. The corresponding behavior on Windows should not have changed. Review URL: http://codereview.chromium.org/113286 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16056 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r--chrome/browser/browser.cc5
-rw-r--r--chrome/browser/browser.vcproj4
-rw-r--r--chrome/browser/cocoa/browser_window_controller.mm51
-rw-r--r--chrome/browser/cocoa/browser_window_controller_unittest.mm53
-rw-r--r--chrome/browser/extensions/extension_tabs_module.cc2
-rw-r--r--chrome/browser/window_sizer.cc106
-rw-r--r--chrome/browser/window_sizer.h45
-rw-r--r--chrome/browser/window_sizer_mac.mm70
-rw-r--r--chrome/browser/window_sizer_win.cc112
9 files changed, 327 insertions, 121 deletions
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc
index dc35140..c59f21e 100644
--- a/chrome/browser/browser.cc
+++ b/chrome/browser/browser.cc
@@ -74,10 +74,13 @@
#include "chrome/browser/user_data_manager.h"
#include "chrome/browser/view_ids.h"
#include "chrome/browser/views/location_bar_view.h"
-#include "chrome/browser/window_sizer.h"
#include "chrome/common/child_process_host.h"
#endif // OS_WIN
+#if defined(OS_WIN) || defined(OS_MACOSX)
+#include "chrome/browser/window_sizer.h"
+#endif
+
using base::TimeDelta;
// How long we wait before updating the browser chrome while loading a page.
diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj
index 9c7094a..6653ca2 100644
--- a/chrome/browser/browser.vcproj
+++ b/chrome/browser/browser.vcproj
@@ -825,6 +825,10 @@
RelativePath=".\window_sizer.h"
>
</File>
+ <File
+ RelativePath=".\window_sizer_win.cc"
+ >
+ </File>
</Filter>
<Filter
Name="Automation"
diff --git a/chrome/browser/cocoa/browser_window_controller.mm b/chrome/browser/cocoa/browser_window_controller.mm
index 6d87b9d..283eb1e 100644
--- a/chrome/browser/cocoa/browser_window_controller.mm
+++ b/chrome/browser/cocoa/browser_window_controller.mm
@@ -7,6 +7,7 @@
#include "chrome/app/chrome_dll_resource.h" // IDC_*
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
+#include "chrome/browser/browser_process.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tab_contents/tab_contents_view.h"
#include "chrome/browser/tabs/tab_strip_model.h"
@@ -21,6 +22,7 @@
#import "chrome/browser/cocoa/tab_strip_controller.h"
#import "chrome/browser/cocoa/tab_view.h"
#import "chrome/browser/cocoa/toolbar_controller.h"
+#include "chrome/common/pref_service.h"
namespace {
@@ -44,6 +46,12 @@ const int kWindowGradientHeight = 24;
// frame changes. Re-positions the bookmark bar and the find bar.
- (void)tabContentAreaFrameChanged:(id)sender;
+// Saves the window's position in the local state preferences.
+- (void)saveWindowPositionIfNeeded;
+
+// Saves the window's position to the given pref service.
+- (void)saveWindowPositionToPrefs:(PrefService*)prefs;
+
// We need to adjust where sheets come out of the window, as by default they
// erupt from the omnibox, which is rather weird.
- (NSRect)window:(NSWindow *)window
@@ -166,7 +174,7 @@ willPositionSheet:(NSWindow *)sheet
- (void)windowWillClose:(NSNotification *)notification {
DCHECK(!browser_->tabstrip_model()->count());
- // We can't acutally use |-autorelease| here because there's an embedded
+ // We can't actually use |-autorelease| here because there's an embedded
// run loop in the |-performClose:| which contains its own autorelease pool.
// Instead we use call it after a zero-length delay, which gets us back
// to the main event loop.
@@ -187,6 +195,11 @@ willPositionSheet:(NSWindow *)sheet
if (!browser_->ShouldCloseWindow())
return NO;
+ // saveWindowPositionIfNeeded: only works if we are the last active
+ // window, but orderOut: ends up activating another window, so we
+ // have to save the window position before we call orderOut:.
+ [self saveWindowPositionIfNeeded];
+
if (!browser_->tabstrip_model()->empty()) {
// Tab strip isn't empty. Hide the frame (so it appears to have closed
// immediately) and close all the tabs, allowing the renderers to shut
@@ -203,6 +216,7 @@ willPositionSheet:(NSWindow *)sheet
// Called right after our window became the main window.
- (void)windowDidBecomeMain:(NSNotification *)notification {
BrowserList::SetLastActive(browser_.get());
+ [self saveWindowPositionIfNeeded];
}
// Called when the user clicks the zoom button (or selects it from the Window
@@ -580,6 +594,41 @@ willPositionSheet:(NSWindow *)sheet
}
}
+- (void)saveWindowPositionIfNeeded {
+ if (browser_ != BrowserList::GetLastActive())
+ return;
+
+ if (!g_browser_process || !g_browser_process->local_state() ||
+ !browser_->ShouldSaveWindowPlacement())
+ return;
+
+ [self saveWindowPositionToPrefs:g_browser_process->local_state()];
+}
+
+- (void)saveWindowPositionToPrefs:(PrefService*)prefs {
+ // Window placements are stored relative to the work area bounds,
+ // not the monitor bounds.
+ NSRect workFrame = [[[self window] screen] visibleFrame];
+
+ // Start with the window's frame, which is in virtual coordinates.
+ // Subtract the origin of the visibleFrame to get the window frame
+ // relative to the work area.
+ gfx::Rect bounds(NSRectToCGRect([[self window] frame]));
+ bounds.Offset(-workFrame.origin.x, -workFrame.origin.y);
+
+ // Do some y twiddling to flip the coordinate system.
+ bounds.set_y(workFrame.size.height - bounds.y() - bounds.height());
+
+ DictionaryValue* windowPreferences = prefs->GetMutableDictionary(
+ browser_->GetWindowPlacementKey().c_str());
+ windowPreferences->SetInteger(L"left", bounds.x());
+ windowPreferences->SetInteger(L"top", bounds.y());
+ windowPreferences->SetInteger(L"right", bounds.right());
+ windowPreferences->SetInteger(L"bottom", bounds.bottom());
+ windowPreferences->SetBoolean(L"maximized", false);
+ windowPreferences->SetBoolean(L"always_on_top", false);
+}
+
- (NSRect)window:(NSWindow *)window
willPositionSheet:(NSWindow *)sheet
usingRect:(NSRect)defaultSheetRect {
diff --git a/chrome/browser/cocoa/browser_window_controller_unittest.mm b/chrome/browser/cocoa/browser_window_controller_unittest.mm
new file mode 100644
index 0000000..0dff06d
--- /dev/null
+++ b/chrome/browser/cocoa/browser_window_controller_unittest.mm
@@ -0,0 +1,53 @@
+// 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 "base/scoped_nsobject.h"
+#include "base/scoped_nsautorelease_pool.h"
+#include "base/scoped_ptr.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/cocoa/browser_test_helper.h"
+#include "chrome/browser/cocoa/browser_window_controller.h"
+#include "chrome/browser/cocoa/cocoa_test_helper.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/pref_service.h"
+#include "chrome/test/testing_browser_process.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+@interface BrowserWindowController (ExposedForTesting)
+- (void)saveWindowPositionToPrefs:(PrefService*)prefs;
+@end
+
+class BrowserWindowControllerTest : public testing::Test {
+ virtual void SetUp() {
+ controller_.reset([[BrowserWindowController alloc]
+ initWithBrowser:browser_helper_.browser()
+ takeOwnership:NO]);
+ }
+
+ public:
+ // Order is very important here. We want the controller deleted
+ // before the pool, and want the pool deleted before
+ // BrowserTestHelper.
+ CocoaTestHelper cocoa_helper_;
+ BrowserTestHelper browser_helper_;
+ base::ScopedNSAutoreleasePool pool_;
+ scoped_nsobject<BrowserWindowController> controller_;
+};
+
+TEST_F(BrowserWindowControllerTest, TestSaveWindowPosition) {
+ PrefService* prefs = browser_helper_.profile()->GetPrefs();
+ ASSERT_TRUE(prefs != NULL);
+
+ // Check to make sure there is no existing pref for window placement.
+ ASSERT_TRUE(prefs->GetDictionary(prefs::kBrowserWindowPlacement) == NULL);
+
+ // Ask the window to save its position, then check that a preference
+ // exists. We're technically passing in a pointer to the user prefs
+ // and not the local state prefs, but a PrefService* is a
+ // PrefService*, and this is a unittest.
+ [controller_ saveWindowPositionToPrefs:prefs];
+ EXPECT_TRUE(prefs->GetDictionary(prefs::kBrowserWindowPlacement) != NULL);
+}
+
+/* TODO(???): test other methods of BrowserWindowController */
diff --git a/chrome/browser/extensions/extension_tabs_module.cc b/chrome/browser/extensions/extension_tabs_module.cc
index 09415f4..782bfe8 100644
--- a/chrome/browser/extensions/extension_tabs_module.cc
+++ b/chrome/browser/extensions/extension_tabs_module.cc
@@ -13,7 +13,7 @@
#include "chrome/browser/tab_contents/navigation_entry.h"
// TODO(port): Port these files.
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(OS_MACOSX)
#include "chrome/browser/window_sizer.h"
#else
#include "chrome/common/temp_scaffolding_stubs.h"
diff --git a/chrome/browser/window_sizer.cc b/chrome/browser/window_sizer.cc
index ce34b71..300e5c5 100644
--- a/chrome/browser/window_sizer.cc
+++ b/chrome/browser/window_sizer.cc
@@ -1,13 +1,9 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// 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/window_sizer.h"
-#include <atlbase.h>
-#include <atlapp.h>
-#include <atlmisc.h>
-
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_process.h"
@@ -15,73 +11,10 @@
#include "chrome/common/pref_names.h"
#include "chrome/common/pref_service.h"
-// How much horizontal and vertical offset there is between newly opened
-// windows.
-static const int kWindowTilePixels = 10;
-
-///////////////////////////////////////////////////////////////////////////////
-// An implementation of WindowSizer::MonitorInfoProvider that gets the actual
-// monitor information from Windows.
-class DefaultMonitorInfoProvider : public WindowSizer::MonitorInfoProvider {
- public:
- DefaultMonitorInfoProvider() { }
-
- // Overridden from WindowSizer::MonitorInfoProvider:
- virtual gfx::Rect GetPrimaryMonitorWorkArea() const {
- return gfx::Rect(GetMonitorInfoForMonitor(MonitorFromWindow(NULL,
- MONITOR_DEFAULTTOPRIMARY)).rcWork);
- }
-
- virtual gfx::Rect GetPrimaryMonitorBounds() const {
- return gfx::Rect(GetMonitorInfoForMonitor(MonitorFromWindow(NULL,
- MONITOR_DEFAULTTOPRIMARY)).rcMonitor);
- }
-
- virtual gfx::Rect GetMonitorWorkAreaMatching(
- const gfx::Rect& match_rect) const {
- CRect other_bounds_crect = match_rect.ToRECT();
- MONITORINFO monitor_info = GetMonitorInfoForMonitor(MonitorFromRect(
- &other_bounds_crect, MONITOR_DEFAULTTONEAREST));
- return gfx::Rect(monitor_info.rcWork);
- }
-
- virtual gfx::Point GetBoundsOffsetMatching(
- const gfx::Rect& match_rect) const {
- CRect other_bounds_crect = match_rect.ToRECT();
- MONITORINFO monitor_info = GetMonitorInfoForMonitor(MonitorFromRect(
- &other_bounds_crect, MONITOR_DEFAULTTONEAREST));
- return gfx::Point(monitor_info.rcWork.left - monitor_info.rcMonitor.left,
- monitor_info.rcWork.top - monitor_info.rcMonitor.top);
- }
-
- void UpdateWorkAreas() {
- work_areas_.clear();
- EnumDisplayMonitors(NULL, NULL,
- &DefaultMonitorInfoProvider::MonitorEnumProc,
- reinterpret_cast<LPARAM>(&work_areas_));
- }
-
- private:
- // A callback for EnumDisplayMonitors that records the work area of the
- // current monitor in the enumeration.
- static BOOL CALLBACK MonitorEnumProc(HMONITOR monitor,
- HDC monitor_dc,
- LPRECT monitor_rect,
- LPARAM data) {
- reinterpret_cast<std::vector<gfx::Rect>*>(data)->push_back(
- gfx::Rect(GetMonitorInfoForMonitor(monitor).rcWork));
- return TRUE;
- }
-
- static MONITORINFO GetMonitorInfoForMonitor(HMONITOR monitor) {
- MONITORINFO monitor_info = { 0 };
- monitor_info.cbSize = sizeof(monitor_info);
- GetMonitorInfo(monitor, &monitor_info);
- return monitor_info;
- }
-
- DISALLOW_COPY_AND_ASSIGN(DefaultMonitorInfoProvider);
-};
+// TODO(port): Port this to Linux.
+// This requires creating window_sizer_linux.cc, creating a subclass
+// of WindowSizer::MonitorInfoProvider, and providing implementations
+// of GetDefaultMonitorInfoProvider() and GetDefaultPopupOrigin().
///////////////////////////////////////////////////////////////////////////////
// An implementation of WindowSizer::StateProvider that gets the last active
@@ -184,41 +117,16 @@ void WindowSizer::GetBrowserWindowBounds(const std::wstring& app_name,
gfx::Rect* window_bounds,
bool* maximized) {
const WindowSizer sizer(new DefaultStateProvider(app_name, browser),
- new DefaultMonitorInfoProvider);
+ CreateDefaultMonitorInfoProvider());
sizer.DetermineWindowBounds(specified_bounds, window_bounds, maximized);
}
-gfx::Point WindowSizer::GetDefaultPopupOrigin(const gfx::Size& size) {
- RECT area;
- SystemParametersInfo(SPI_GETWORKAREA, 0, &area, 0);
- gfx::Point corner(area.left, area.top);
-
- if (Browser* b = BrowserList::GetLastActive()) {
- RECT browser;
- HWND window = reinterpret_cast<HWND>(b->window()->GetNativeHandle());
- if (GetWindowRect(window, &browser)) {
- // Limit to not overflow the work area right and bottom edges.
- gfx::Point limit(
- std::min(browser.left + kWindowTilePixels, area.right-size.width()),
- std::min(browser.top + kWindowTilePixels, area.bottom-size.height())
- );
- // Adjust corner to now overflow the work area left and top edges, so
- // that if a popup does not fit the title-bar is remains visible.
- corner = gfx::Point(
- std::max(corner.x(), limit.x()),
- std::max(corner.y(), limit.y())
- );
- }
- }
- return corner;
-}
-
///////////////////////////////////////////////////////////////////////////////
// WindowSizer, private:
WindowSizer::WindowSizer(const std::wstring& app_name) {
Init(new DefaultStateProvider(app_name, NULL),
- new DefaultMonitorInfoProvider);
+ CreateDefaultMonitorInfoProvider());
}
void WindowSizer::Init(StateProvider* state_provider,
diff --git a/chrome/browser/window_sizer.h b/chrome/browser/window_sizer.h
index 5153f6d..d1db1db 100644
--- a/chrome/browser/window_sizer.h
+++ b/chrome/browser/window_sizer.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// 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.
-#ifndef CHROME_BROWSER_WINDOW_SIZER_H__
-#define CHROME_BROWSER_WINDOW_SIZER_H__
+#ifndef CHROME_BROWSER_WINDOW_SIZER_H_
+#define CHROME_BROWSER_WINDOW_SIZER_H_
#include <vector>
@@ -33,6 +33,10 @@ class WindowSizer {
MonitorInfoProvider* monitor_info_provider);
virtual ~WindowSizer();
+ // Static factory methods to create default MonitorInfoProvider
+ // instances. The returned object is owned by the caller.
+ static MonitorInfoProvider* CreateDefaultMonitorInfoProvider();
+
// An interface implemented by an object that can retrieve information about
// the monitors on the system.
class MonitorInfoProvider {
@@ -92,20 +96,6 @@ class WindowSizer {
virtual bool GetLastActiveWindowState(gfx::Rect* bounds) const = 0;
};
- // Determines the size, position and maximized state for the browser window.
- // See documentation for DetermineWindowBounds below. Normally,
- // |window_bounds| is calculated by calling GetLastActiveWindowState(). To
- // explicitly specify a particular window to base the bounds on, pass in a
- // non-NULL value for |browser|.
- static void GetBrowserWindowBounds(const std::wstring& app_name,
- const gfx::Rect& specified_bounds,
- Browser* browser,
- gfx::Rect* window_bounds,
- bool* maximized);
-
- // Returns the default origin for popups of the given size.
- static gfx::Point GetDefaultPopupOrigin(const gfx::Size& size);
-
// Determines the position, size and maximized state for a window as it is
// created. This function uses several strategies to figure out optimal size
// and placement, first looking for an existing active window, then falling
@@ -121,6 +111,24 @@ class WindowSizer {
gfx::Rect* bounds,
bool* maximized) const;
+ // Determines the size, position and maximized state for the browser window.
+ // See documentation for DetermineWindowBounds below. Normally,
+ // |window_bounds| is calculated by calling GetLastActiveWindowState(). To
+ // explicitly specify a particular window to base the bounds on, pass in a
+ // non-NULL value for |browser|.
+ static void GetBrowserWindowBounds(const std::wstring& app_name,
+ const gfx::Rect& specified_bounds,
+ Browser* browser,
+ gfx::Rect* window_bounds,
+ bool* maximized);
+
+ // Returns the default origin for popups of the given size.
+ static gfx::Point GetDefaultPopupOrigin(const gfx::Size& size);
+
+ // How much horizontal and vertical offset there is between newly
+ // opened windows. This value may be different on each platform.
+ static const int kWindowTilePixels;
+
private:
// The edge of the screen to check for out-of-bounds.
enum Edge { TOP, LEFT, BOTTOM, RIGHT };
@@ -165,5 +173,4 @@ class WindowSizer {
DISALLOW_EVIL_CONSTRUCTORS(WindowSizer);
};
-
-#endif // #ifndef CHROME_BROWSER_WINDOW_SIZER_H__
+#endif // #ifndef CHROME_BROWSER_WINDOW_SIZER_H_
diff --git a/chrome/browser/window_sizer_mac.mm b/chrome/browser/window_sizer_mac.mm
new file mode 100644
index 0000000..8ff0223
--- /dev/null
+++ b/chrome/browser/window_sizer_mac.mm
@@ -0,0 +1,70 @@
+// 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.
+
+#import <Cocoa/Cocoa.h>
+
+#include "chrome/browser/window_sizer.h"
+
+// How much horizontal and vertical offset there is between newly
+// opened windows.
+const int WindowSizer::kWindowTilePixels = 22;
+
+class DefaultMonitorInfoProvider : public WindowSizer::MonitorInfoProvider {
+ public:
+ DefaultMonitorInfoProvider() { }
+
+ // Overridden from WindowSizer::MonitorInfoProvider:
+ virtual gfx::Rect GetPrimaryMonitorWorkArea() const {
+ // Primary monitor is defined as the monitor with the menubar,
+ // which is always at index 0.
+ NSScreen* primary = [[NSScreen screens] objectAtIndex:0];
+ NSRect frame = [primary frame];
+ NSRect visible_frame = [primary visibleFrame];
+
+ // Convert coordinate systems.
+ gfx::Rect rect = gfx::Rect(NSRectToCGRect(visible_frame));
+ rect.set_y(frame.size.height -
+ visible_frame.origin.y - visible_frame.size.height);
+ return rect;
+ }
+
+ virtual gfx::Rect GetPrimaryMonitorBounds() const {
+ // Primary monitor is defined as the monitor with the menubar,
+ // which is always at index 0.
+ NSScreen* primary = [[NSScreen screens] objectAtIndex:0];
+ return gfx::Rect(NSRectToCGRect([primary frame]));
+ }
+
+ virtual gfx::Rect GetMonitorWorkAreaMatching(
+ const gfx::Rect& match_rect) const {
+ // TODO(rohitrao): Support multiple monitors.
+ return GetPrimaryMonitorWorkArea();
+ }
+
+ virtual gfx::Point GetBoundsOffsetMatching(
+ const gfx::Rect& match_rect) const {
+ // TODO(rohitrao): Support multiple monitors.
+ return GetPrimaryMonitorWorkArea().origin();
+ }
+
+ void UpdateWorkAreas() {
+ // TODO(rohitrao): Support multiple monitors.
+ work_areas_.clear();
+ work_areas_.push_back(GetPrimaryMonitorWorkArea());
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DefaultMonitorInfoProvider);
+};
+
+// static
+WindowSizer::MonitorInfoProvider*
+WindowSizer::CreateDefaultMonitorInfoProvider() {
+ return new DefaultMonitorInfoProvider();
+}
+
+// static
+gfx::Point WindowSizer::GetDefaultPopupOrigin(const gfx::Size& size) {
+ return gfx::Point(0, 0);
+}
diff --git a/chrome/browser/window_sizer_win.cc b/chrome/browser/window_sizer_win.cc
new file mode 100644
index 0000000..249af74
--- /dev/null
+++ b/chrome/browser/window_sizer_win.cc
@@ -0,0 +1,112 @@
+// 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/window_sizer.h"
+
+#include <atlbase.h>
+#include <atlapp.h>
+#include <atlmisc.h>
+
+#include "chrome/browser/browser.h"
+#include "chrome/browser/browser_list.h"
+#include "chrome/browser/browser_window.h"
+
+// How much horizontal and vertical offset there is between newly
+// opened windows.
+const int WindowSizer::kWindowTilePixels = 10;
+
+// An implementation of WindowSizer::MonitorInfoProvider that gets the actual
+// monitor information from Windows.
+class DefaultMonitorInfoProvider : public WindowSizer::MonitorInfoProvider {
+ public:
+ DefaultMonitorInfoProvider() { }
+
+ // Overridden from WindowSizer::MonitorInfoProvider:
+ virtual gfx::Rect GetPrimaryMonitorWorkArea() const {
+ return gfx::Rect(GetMonitorInfoForMonitor(MonitorFromWindow(NULL,
+ MONITOR_DEFAULTTOPRIMARY)).rcWork);
+ }
+
+ virtual gfx::Rect GetPrimaryMonitorBounds() const {
+ return gfx::Rect(GetMonitorInfoForMonitor(MonitorFromWindow(NULL,
+ MONITOR_DEFAULTTOPRIMARY)).rcMonitor);
+ }
+
+ virtual gfx::Rect GetMonitorWorkAreaMatching(
+ const gfx::Rect& match_rect) const {
+ CRect other_bounds_crect = match_rect.ToRECT();
+ MONITORINFO monitor_info = GetMonitorInfoForMonitor(MonitorFromRect(
+ &other_bounds_crect, MONITOR_DEFAULTTONEAREST));
+ return gfx::Rect(monitor_info.rcWork);
+ }
+
+ virtual gfx::Point GetBoundsOffsetMatching(
+ const gfx::Rect& match_rect) const {
+ CRect other_bounds_crect = match_rect.ToRECT();
+ MONITORINFO monitor_info = GetMonitorInfoForMonitor(MonitorFromRect(
+ &other_bounds_crect, MONITOR_DEFAULTTONEAREST));
+ return gfx::Point(monitor_info.rcWork.left - monitor_info.rcMonitor.left,
+ monitor_info.rcWork.top - monitor_info.rcMonitor.top);
+ }
+
+ void UpdateWorkAreas() {
+ work_areas_.clear();
+ EnumDisplayMonitors(NULL, NULL,
+ &DefaultMonitorInfoProvider::MonitorEnumProc,
+ reinterpret_cast<LPARAM>(&work_areas_));
+ }
+
+ private:
+ // A callback for EnumDisplayMonitors that records the work area of the
+ // current monitor in the enumeration.
+ static BOOL CALLBACK MonitorEnumProc(HMONITOR monitor,
+ HDC monitor_dc,
+ LPRECT monitor_rect,
+ LPARAM data) {
+ reinterpret_cast<std::vector<gfx::Rect>*>(data)->push_back(
+ gfx::Rect(GetMonitorInfoForMonitor(monitor).rcWork));
+ return TRUE;
+ }
+
+ static MONITORINFO GetMonitorInfoForMonitor(HMONITOR monitor) {
+ MONITORINFO monitor_info = { 0 };
+ monitor_info.cbSize = sizeof(monitor_info);
+ GetMonitorInfo(monitor, &monitor_info);
+ return monitor_info;
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(DefaultMonitorInfoProvider);
+};
+
+// static
+WindowSizer::MonitorInfoProvider*
+WindowSizer::CreateDefaultMonitorInfoProvider() {
+ return new DefaultMonitorInfoProvider();
+}
+
+// static
+gfx::Point WindowSizer::GetDefaultPopupOrigin(const gfx::Size& size) {
+ RECT area;
+ SystemParametersInfo(SPI_GETWORKAREA, 0, &area, 0);
+ gfx::Point corner(area.left, area.top);
+
+ if (Browser* b = BrowserList::GetLastActive()) {
+ RECT browser;
+ HWND window = reinterpret_cast<HWND>(b->window()->GetNativeHandle());
+ if (GetWindowRect(window, &browser)) {
+ // Limit to not overflow the work area right and bottom edges.
+ gfx::Point limit(
+ std::min(browser.left + kWindowTilePixels, area.right-size.width()),
+ std::min(browser.top + kWindowTilePixels, area.bottom-size.height())
+ );
+ // Adjust corner to now overflow the work area left and top edges, so
+ // that if a popup does not fit the title-bar is remains visible.
+ corner = gfx::Point(
+ std::max(corner.x(), limit.x()),
+ std::max(corner.y(), limit.y())
+ );
+ }
+ }
+ return corner;
+}