Home | History | Annotate | Download | only in ui
      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