1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/ui/window_sizer.h" 6 7 #include "chrome/browser/ui/browser.h" 8 #include "chrome/browser/ui/browser_list.h" 9 #include "chrome/browser/ui/browser_window.h" 10 11 // How much horizontal and vertical offset there is between newly 12 // opened windows. 13 const int WindowSizer::kWindowTilePixels = 10; 14 15 // An implementation of WindowSizer::MonitorInfoProvider that gets the actual 16 // monitor information from Windows. 17 class DefaultMonitorInfoProvider : public WindowSizer::MonitorInfoProvider { 18 public: 19 DefaultMonitorInfoProvider() { } 20 21 // Overridden from WindowSizer::MonitorInfoProvider: 22 virtual gfx::Rect GetPrimaryMonitorWorkArea() const { 23 return gfx::Rect(GetMonitorInfoForMonitor(MonitorFromWindow(NULL, 24 MONITOR_DEFAULTTOPRIMARY)).rcWork); 25 } 26 27 virtual gfx::Rect GetPrimaryMonitorBounds() const { 28 return gfx::Rect(GetMonitorInfoForMonitor(MonitorFromWindow(NULL, 29 MONITOR_DEFAULTTOPRIMARY)).rcMonitor); 30 } 31 32 virtual gfx::Rect GetMonitorWorkAreaMatching( 33 const gfx::Rect& match_rect) const { 34 RECT other_bounds_rect = match_rect.ToRECT(); 35 MONITORINFO monitor_info = GetMonitorInfoForMonitor(MonitorFromRect( 36 &other_bounds_rect, MONITOR_DEFAULTTONEAREST)); 37 return gfx::Rect(monitor_info.rcWork); 38 } 39 40 virtual gfx::Point GetBoundsOffsetMatching( 41 const gfx::Rect& match_rect) const { 42 RECT other_bounds_rect = match_rect.ToRECT(); 43 MONITORINFO monitor_info = GetMonitorInfoForMonitor(MonitorFromRect( 44 &other_bounds_rect, MONITOR_DEFAULTTONEAREST)); 45 return gfx::Point(monitor_info.rcWork.left - monitor_info.rcMonitor.left, 46 monitor_info.rcWork.top - monitor_info.rcMonitor.top); 47 } 48 49 void UpdateWorkAreas() { 50 work_areas_.clear(); 51 EnumDisplayMonitors(NULL, NULL, 52 &DefaultMonitorInfoProvider::MonitorEnumProc, 53 reinterpret_cast<LPARAM>(&work_areas_)); 54 } 55 56 private: 57 // A callback for EnumDisplayMonitors that records the work area of the 58 // current monitor in the enumeration. 59 static BOOL CALLBACK MonitorEnumProc(HMONITOR monitor, 60 HDC monitor_dc, 61 LPRECT monitor_rect, 62 LPARAM data) { 63 reinterpret_cast<std::vector<gfx::Rect>*>(data)->push_back( 64 gfx::Rect(GetMonitorInfoForMonitor(monitor).rcWork)); 65 return TRUE; 66 } 67 68 static MONITORINFO GetMonitorInfoForMonitor(HMONITOR monitor) { 69 MONITORINFO monitor_info = { 0 }; 70 monitor_info.cbSize = sizeof(monitor_info); 71 GetMonitorInfo(monitor, &monitor_info); 72 return monitor_info; 73 } 74 75 DISALLOW_COPY_AND_ASSIGN(DefaultMonitorInfoProvider); 76 }; 77 78 // static 79 WindowSizer::MonitorInfoProvider* 80 WindowSizer::CreateDefaultMonitorInfoProvider() { 81 return new DefaultMonitorInfoProvider(); 82 } 83 84 // static 85 gfx::Point WindowSizer::GetDefaultPopupOrigin(const gfx::Size& size) { 86 RECT area; 87 SystemParametersInfo(SPI_GETWORKAREA, 0, &area, 0); 88 gfx::Point corner(area.left, area.top); 89 90 if (Browser* b = BrowserList::GetLastActive()) { 91 RECT browser; 92 HWND window = reinterpret_cast<HWND>(b->window()->GetNativeHandle()); 93 if (GetWindowRect(window, &browser)) { 94 // Limit to not overflow the work area right and bottom edges. 95 gfx::Point limit( 96 std::min(browser.left + kWindowTilePixels, area.right-size.width()), 97 std::min(browser.top + kWindowTilePixels, area.bottom-size.height()) 98 ); 99 // Adjust corner to now overflow the work area left and top edges, so 100 // that if a popup does not fit the title-bar is remains visible. 101 corner = gfx::Point( 102 std::max(corner.x(), limit.x()), 103 std::max(corner.y(), limit.y()) 104 ); 105 } 106 } 107 return corner; 108 } 109