| OLD | NEW |
| (Empty) |
| 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 #import <Cocoa/Cocoa.h> | |
| 6 #include "chrome/browser/ui/browser.h" | |
| 7 #include "chrome/browser/ui/browser_list.h" | |
| 8 #include "chrome/browser/ui/browser_window.h" | |
| 9 #include "chrome/browser/window_sizer.h" | |
| 10 | |
| 11 | |
| 12 // How much horizontal and vertical offset there is between newly | |
| 13 // opened windows. | |
| 14 const int WindowSizer::kWindowTilePixels = 22; | |
| 15 | |
| 16 namespace { | |
| 17 | |
| 18 class DefaultMonitorInfoProvider : public WindowSizer::MonitorInfoProvider { | |
| 19 public: | |
| 20 DefaultMonitorInfoProvider() { } | |
| 21 | |
| 22 // Overridden from WindowSizer::MonitorInfoProvider: | |
| 23 virtual gfx::Rect GetPrimaryMonitorWorkArea() const { | |
| 24 // Primary monitor is defined as the monitor with the menubar, | |
| 25 // which is always at index 0. | |
| 26 NSScreen* primary = [[NSScreen screens] objectAtIndex:0]; | |
| 27 NSRect frame = [primary frame]; | |
| 28 NSRect visible_frame = [primary visibleFrame]; | |
| 29 | |
| 30 // Convert coordinate systems. | |
| 31 gfx::Rect rect = gfx::Rect(NSRectToCGRect(visible_frame)); | |
| 32 rect.set_y(frame.size.height - | |
| 33 visible_frame.origin.y - visible_frame.size.height); | |
| 34 return rect; | |
| 35 } | |
| 36 | |
| 37 virtual gfx::Rect GetPrimaryMonitorBounds() const { | |
| 38 // Primary monitor is defined as the monitor with the menubar, | |
| 39 // which is always at index 0. | |
| 40 NSScreen* primary = [[NSScreen screens] objectAtIndex:0]; | |
| 41 return gfx::Rect(NSRectToCGRect([primary frame])); | |
| 42 } | |
| 43 | |
| 44 virtual gfx::Rect GetMonitorWorkAreaMatching( | |
| 45 const gfx::Rect& match_rect) const { | |
| 46 NSScreen* match_screen = GetMatchingScreen(match_rect); | |
| 47 return ConvertCoordinateSystem([match_screen visibleFrame]); | |
| 48 } | |
| 49 | |
| 50 virtual gfx::Point GetBoundsOffsetMatching( | |
| 51 const gfx::Rect& match_rect) const { | |
| 52 NSScreen* match_screen = GetMatchingScreen(match_rect); | |
| 53 gfx::Rect bounds = ConvertCoordinateSystem([match_screen frame]); | |
| 54 gfx::Rect work_area = ConvertCoordinateSystem([match_screen visibleFrame]); | |
| 55 return gfx::Point(work_area.x() - bounds.x(), work_area.y() - bounds.y()); | |
| 56 } | |
| 57 | |
| 58 virtual void UpdateWorkAreas(); | |
| 59 | |
| 60 private: | |
| 61 // Returns a pointer to the screen that most closely matches the | |
| 62 // given |match_rect|. This function currently returns the screen | |
| 63 // that contains the largest amount of |match_rect| by area. | |
| 64 NSScreen* GetMatchingScreen(const gfx::Rect& match_rect) const { | |
| 65 // Default to the monitor with the current keyboard focus, in case | |
| 66 // |match_rect| is not on any screen at all. | |
| 67 NSScreen* max_screen = [NSScreen mainScreen]; | |
| 68 int max_area = 0; | |
| 69 | |
| 70 for (NSScreen* screen in [NSScreen screens]) { | |
| 71 gfx::Rect monitor_area = ConvertCoordinateSystem([screen frame]); | |
| 72 gfx::Rect intersection = monitor_area.Intersect(match_rect); | |
| 73 int area = intersection.width() * intersection.height(); | |
| 74 if (area > max_area) { | |
| 75 max_area = area; | |
| 76 max_screen = screen; | |
| 77 } | |
| 78 } | |
| 79 | |
| 80 return max_screen; | |
| 81 } | |
| 82 | |
| 83 // The lower left corner of screen 0 is always at (0, 0). The | |
| 84 // cross-platform code expects the origin to be in the upper left, | |
| 85 // so we have to translate |ns_rect| to the new coordinate | |
| 86 // system. | |
| 87 gfx::Rect ConvertCoordinateSystem(NSRect ns_rect) const; | |
| 88 | |
| 89 DISALLOW_COPY_AND_ASSIGN(DefaultMonitorInfoProvider); | |
| 90 }; | |
| 91 | |
| 92 void DefaultMonitorInfoProvider::UpdateWorkAreas() { | |
| 93 work_areas_.clear(); | |
| 94 | |
| 95 for (NSScreen* screen in [NSScreen screens]) { | |
| 96 gfx::Rect rect = ConvertCoordinateSystem([screen visibleFrame]); | |
| 97 work_areas_.push_back(rect); | |
| 98 } | |
| 99 } | |
| 100 | |
| 101 gfx::Rect DefaultMonitorInfoProvider::ConvertCoordinateSystem( | |
| 102 NSRect ns_rect) const { | |
| 103 // Primary monitor is defined as the monitor with the menubar, | |
| 104 // which is always at index 0. | |
| 105 NSScreen* primary_screen = [[NSScreen screens] objectAtIndex:0]; | |
| 106 float primary_screen_height = [primary_screen frame].size.height; | |
| 107 gfx::Rect rect(NSRectToCGRect(ns_rect)); | |
| 108 rect.set_y(primary_screen_height - rect.y() - rect.height()); | |
| 109 return rect; | |
| 110 } | |
| 111 | |
| 112 } // namespace | |
| 113 | |
| 114 // static | |
| 115 WindowSizer::MonitorInfoProvider* | |
| 116 WindowSizer::CreateDefaultMonitorInfoProvider() { | |
| 117 return new DefaultMonitorInfoProvider(); | |
| 118 } | |
| 119 | |
| 120 // static | |
| 121 gfx::Point WindowSizer::GetDefaultPopupOrigin(const gfx::Size& size) { | |
| 122 NSRect work_area = [[NSScreen mainScreen] visibleFrame]; | |
| 123 NSRect main_area = [[[NSScreen screens] objectAtIndex:0] frame]; | |
| 124 NSPoint corner = NSMakePoint(NSMinX(work_area), NSMaxY(work_area)); | |
| 125 | |
| 126 if (Browser* b = BrowserList::GetLastActive()) { | |
| 127 NSWindow* window = b->window()->GetNativeHandle(); | |
| 128 NSRect window_frame = [window frame]; | |
| 129 | |
| 130 // Limit to not overflow the work area right and bottom edges. | |
| 131 NSPoint limit = NSMakePoint( | |
| 132 std::min(NSMinX(window_frame) + kWindowTilePixels, | |
| 133 NSMaxX(work_area) - size.width()), | |
| 134 std::max(NSMaxY(window_frame) - kWindowTilePixels, | |
| 135 NSMinY(work_area) + size.height())); | |
| 136 | |
| 137 // Adjust corner to now overflow the work area left and top edges, so | |
| 138 // that if a popup does not fit the title-bar is remains visible. | |
| 139 corner = NSMakePoint(std::max(corner.x, limit.x), | |
| 140 std::min(corner.y, limit.y)); | |
| 141 } | |
| 142 | |
| 143 return gfx::Point(corner.x, NSHeight(main_area) - corner.y); | |
| 144 } | |
| OLD | NEW |