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 |