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