blob: e4bd759fcfe9fcd15bd1b3e81e4d3adfa49373df [file] [log] [blame]
// 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<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;
}