// 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 "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 { RECT other_bounds_rect = match_rect.ToRECT(); MONITORINFO monitor_info = GetMonitorInfoForMonitor(MonitorFromRect( &other_bounds_rect, MONITOR_DEFAULTTONEAREST)); return gfx::Rect(monitor_info.rcWork); } virtual gfx::Point GetBoundsOffsetMatching( const gfx::Rect& match_rect) const { RECT other_bounds_rect = match_rect.ToRECT(); MONITORINFO monitor_info = GetMonitorInfoForMonitor(MonitorFromRect( &other_bounds_rect, 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(&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*>(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(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; }