OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "ash/monitor/multi_monitor_manager.h" | 5 #include "ash/monitor/multi_monitor_manager.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
11 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
12 #include "base/string_split.h" | 12 #include "base/string_split.h" |
13 #include "ui/aura/aura_switches.h" | 13 #include "ui/aura/aura_switches.h" |
14 #include "ui/aura/env.h" | 14 #include "ui/aura/env.h" |
15 #include "ui/aura/monitor.h" | |
16 #include "ui/aura/root_window.h" | 15 #include "ui/aura/root_window.h" |
17 #include "ui/aura/root_window_host.h" | 16 #include "ui/aura/root_window_host.h" |
| 17 #include "ui/aura/window_property.h" |
| 18 #include "ui/gfx/monitor.h" |
18 #include "ui/gfx/rect.h" | 19 #include "ui/gfx/rect.h" |
19 #include "ui/aura/window_property.h" | |
20 | 20 |
21 DECLARE_WINDOW_PROPERTY_TYPE(aura::Monitor*); | 21 DECLARE_WINDOW_PROPERTY_TYPE(int); |
22 | 22 |
23 namespace ash { | 23 namespace ash { |
24 namespace internal { | 24 namespace internal { |
25 namespace { | 25 namespace { |
26 | 26 gfx::Monitor& GetInvalidMonitor() { |
27 aura::Monitor* Copy(aura::Monitor* m) { | 27 static gfx::Monitor* invalid_monitor = new gfx::Monitor(); |
28 aura::Monitor* monitor = new aura::Monitor; | 28 return *invalid_monitor; |
29 monitor->set_bounds(m->bounds()); | |
30 return monitor; | |
31 } | 29 } |
32 | |
33 } // namespace | 30 } // namespace |
34 | 31 |
35 DEFINE_WINDOW_PROPERTY_KEY(aura::Monitor*, kMonitorKey, NULL); | 32 using aura::RootWindow; |
36 | 33 using aura::Window; |
| 34 using gfx::Monitor; |
37 using std::string; | 35 using std::string; |
38 using std::vector; | 36 using std::vector; |
39 using aura::Monitor; | 37 |
40 using aura::RootWindow; | 38 DEFINE_WINDOW_PROPERTY_KEY(int, kMonitorIdKey, -1); |
41 using aura::Window; | |
42 | 39 |
43 MultiMonitorManager::MultiMonitorManager() { | 40 MultiMonitorManager::MultiMonitorManager() { |
44 Init(); | 41 Init(); |
45 } | 42 } |
46 | 43 |
47 MultiMonitorManager::~MultiMonitorManager() { | 44 MultiMonitorManager::~MultiMonitorManager() { |
48 STLDeleteContainerPointers(monitors_.begin(), monitors_.end()); | |
49 } | 45 } |
50 | 46 |
51 // static | 47 // static |
52 void MultiMonitorManager::AddRemoveMonitor() { | 48 void MultiMonitorManager::AddRemoveMonitor() { |
53 MultiMonitorManager* manager = static_cast<MultiMonitorManager*>( | 49 MultiMonitorManager* manager = static_cast<MultiMonitorManager*>( |
54 aura::Env::GetInstance()->monitor_manager()); | 50 aura::Env::GetInstance()->monitor_manager()); |
55 manager->AddRemoveMonitorImpl(); | 51 manager->AddRemoveMonitorImpl(); |
56 } | 52 } |
57 | 53 |
58 void MultiMonitorManager::CycleMonitor() { | 54 void MultiMonitorManager::CycleMonitor() { |
59 MultiMonitorManager* manager = static_cast<MultiMonitorManager*>( | 55 MultiMonitorManager* manager = static_cast<MultiMonitorManager*>( |
60 aura::Env::GetInstance()->monitor_manager()); | 56 aura::Env::GetInstance()->monitor_manager()); |
61 manager->CycleMonitorImpl(); | 57 manager->CycleMonitorImpl(); |
62 } | 58 } |
63 | 59 |
64 void MultiMonitorManager::OnNativeMonitorsChanged( | 60 void MultiMonitorManager::OnNativeMonitorsChanged( |
65 const std::vector<const aura::Monitor*>& new_monitors) { | 61 const std::vector<Monitor>& new_monitors) { |
66 size_t min = std::min(monitors_.size(), new_monitors.size()); | 62 size_t min = std::min(monitors_.size(), new_monitors.size()); |
67 | 63 |
68 // For m19, we only care about 1st monitor as primary, and | 64 // For m19, we only care about 1st monitor as primary, and |
69 // don't differentiate the rest of monitors as all secondary | 65 // don't differentiate the rest of monitors as all secondary |
70 // monitors have the same content. | 66 // monitors have the same content. ID for primary monitor stays the same |
| 67 // because we never remove it, we don't update IDs for other monitors |
| 68 // , for now, because they're the same. |
71 // TODO(oshima): Fix this so that we can differentiate outputs | 69 // TODO(oshima): Fix this so that we can differentiate outputs |
72 // and keep a content on one monitor stays on the same monitor | 70 // and keep a content on one monitor stays on the same monitor |
73 // when a monitor is added or removed. | 71 // when a monitor is added or removed. |
74 for (size_t i = 0; i < min; ++i) { | 72 for (size_t i = 0; i < min; ++i) { |
75 Monitor* current_monitor = monitors_[i]; | 73 Monitor& current_monitor = monitors_[i]; |
76 const Monitor* new_monitor = new_monitors[i]; | 74 const Monitor& new_monitor = new_monitors[i]; |
77 if (current_monitor->bounds() != new_monitor->bounds()) { | 75 if (current_monitor.bounds() != new_monitor.bounds()) { |
78 current_monitor->set_bounds(new_monitor->bounds()); | 76 current_monitor.SetBoundsAndUpdateWorkArea(new_monitor.bounds()); |
79 NotifyBoundsChanged(current_monitor); | 77 NotifyBoundsChanged(current_monitor); |
80 } | 78 } |
81 } | 79 } |
82 | 80 |
83 if (monitors_.size() < new_monitors.size()) { | 81 if (monitors_.size() < new_monitors.size()) { |
84 // New monitors added | 82 // New monitors added |
85 for (size_t i = min; i < new_monitors.size(); ++i) { | 83 for (size_t i = min; i < new_monitors.size(); ++i) { |
86 Monitor* monitor = new Monitor(); | 84 // |
87 monitor->set_bounds(new_monitors[i]->bounds()); | 85 monitors_.push_back(Monitor(i)); |
88 monitors_.push_back(monitor); | 86 gfx::Monitor& monitor = monitors_.back(); |
| 87 monitor.SetBoundsAndUpdateWorkArea(new_monitors[i].bounds()); |
89 NotifyMonitorAdded(monitor); | 88 NotifyMonitorAdded(monitor); |
90 } | 89 } |
91 } else { | 90 } else { |
92 // Monitors are removed. We keep the monitor for the primary | 91 // Monitors are removed. We keep the monitor for the primary |
93 // monitor (at index 0) because it needs the monitor information | 92 // monitor (at index 0) because it needs the monitor information |
94 // even if it doesn't exit. | 93 // even if it doesn't exit. |
95 while (monitors_.size() > new_monitors.size() && monitors_.size() > 1) { | 94 while (monitors_.size() > new_monitors.size() && monitors_.size() > 1) { |
96 Monitor* monitor = monitors_.back(); | 95 Monitors::reverse_iterator iter = monitors_.rbegin(); |
97 NotifyMonitorRemoved(monitor); | 96 NotifyMonitorRemoved(*iter); |
98 monitors_.erase(std::find(monitors_.begin(), monitors_.end(), monitor)); | 97 monitors_.erase(iter.base() - 1); |
99 delete monitor; | |
100 } | 98 } |
101 } | 99 } |
102 } | 100 } |
103 | 101 |
104 RootWindow* MultiMonitorManager::CreateRootWindowForMonitor( | 102 RootWindow* MultiMonitorManager::CreateRootWindowForMonitor( |
105 Monitor* monitor) { | 103 const Monitor& monitor) { |
106 RootWindow* root_window = new RootWindow(monitor->bounds()); | 104 RootWindow* root_window = new RootWindow(monitor.bounds()); |
107 // No need to remove RootWindowObserver because | 105 // No need to remove RootWindowObserver because |
108 // the MonitorManager object outlives RootWindow objects. | 106 // the MonitorManager object outlives RootWindow objects. |
109 root_window->AddRootWindowObserver(this); | 107 root_window->AddRootWindowObserver(this); |
110 root_window->SetProperty(kMonitorKey, monitor); | 108 root_window->SetProperty(kMonitorIdKey, monitor.id()); |
111 return root_window; | 109 return root_window; |
112 } | 110 } |
113 | 111 |
114 const Monitor* MultiMonitorManager::GetMonitorNearestWindow( | 112 const Monitor& MultiMonitorManager::GetMonitorAt(size_t index) { |
| 113 return index < monitors_.size() ? monitors_[index] : GetInvalidMonitor(); |
| 114 } |
| 115 |
| 116 size_t MultiMonitorManager::GetNumMonitors() const { |
| 117 return monitors_.size(); |
| 118 } |
| 119 |
| 120 const Monitor& MultiMonitorManager::GetMonitorNearestWindow( |
115 const Window* window) const { | 121 const Window* window) const { |
116 if (!window) { | 122 if (!window) { |
117 MultiMonitorManager* manager = const_cast<MultiMonitorManager*>(this); | 123 MultiMonitorManager* manager = const_cast<MultiMonitorManager*>(this); |
118 return manager->GetMonitorAt(0); | 124 return manager->GetMonitorAt(0); |
119 } | 125 } |
120 const RootWindow* root = window->GetRootWindow(); | 126 const RootWindow* root = window->GetRootWindow(); |
121 return root ? root->GetProperty(kMonitorKey) : NULL; | 127 MultiMonitorManager* that = const_cast<MultiMonitorManager*>(this); |
| 128 return root ? |
| 129 that->FindMonitorById(root->GetProperty(kMonitorIdKey)) : |
| 130 GetInvalidMonitor(); |
122 } | 131 } |
123 | 132 |
124 const Monitor* MultiMonitorManager::GetMonitorNearestPoint( | 133 const Monitor& MultiMonitorManager::GetMonitorNearestPoint( |
125 const gfx::Point& point) const { | 134 const gfx::Point& point) const { |
126 // TODO(oshima): For m19, mouse is constrained within | 135 // TODO(oshima): For m19, mouse is constrained within |
127 // the primary window. | 136 // the primary window. |
128 MultiMonitorManager* manager = const_cast<MultiMonitorManager*>(this); | 137 MultiMonitorManager* manager = const_cast<MultiMonitorManager*>(this); |
129 return manager->GetMonitorAt(0); | 138 return manager->GetMonitorAt(0); |
130 } | 139 } |
131 | 140 |
132 Monitor* MultiMonitorManager::GetMonitorAt(size_t index) { | |
133 return index < monitors_.size() ? monitors_[index] : NULL; | |
134 } | |
135 | |
136 size_t MultiMonitorManager::GetNumMonitors() const { | |
137 return monitors_.size(); | |
138 } | |
139 | |
140 Monitor* MultiMonitorManager::GetMonitorNearestWindow(const Window* window) { | |
141 const MonitorManager* manager = this; | |
142 return const_cast<Monitor*>(manager->GetMonitorNearestWindow(window)); | |
143 } | |
144 | |
145 void MultiMonitorManager::OnRootWindowResized(const aura::RootWindow* root, | 141 void MultiMonitorManager::OnRootWindowResized(const aura::RootWindow* root, |
146 const gfx::Size& old_size) { | 142 const gfx::Size& old_size) { |
147 if (!use_fullscreen_host_window()) { | 143 if (!use_fullscreen_host_window()) { |
148 Monitor* monitor = root->GetProperty(kMonitorKey); | 144 int monitor_id = root->GetProperty(kMonitorIdKey); |
149 monitor->set_size(root->GetHostSize()); | 145 Monitor& monitor = FindMonitorById(monitor_id); |
| 146 monitor.SetSizeAndUpdateWorkArea(root->GetHostSize()); |
150 NotifyBoundsChanged(monitor); | 147 NotifyBoundsChanged(monitor); |
151 } | 148 } |
152 } | 149 } |
153 | 150 |
| 151 bool MultiMonitorManager::UpdateWorkAreaOfMonitorNearestWindow( |
| 152 const aura::Window* window, |
| 153 const gfx::Insets& insets) { |
| 154 const RootWindow* root = window->GetRootWindow(); |
| 155 Monitor& monitor = FindMonitorById(root->GetProperty(kMonitorIdKey)); |
| 156 gfx::Rect old_work_area = monitor.work_area(); |
| 157 monitor.UpdateWorkAreaWithInsets(insets); |
| 158 return old_work_area != monitor.work_area(); |
| 159 } |
| 160 |
154 void MultiMonitorManager::Init() { | 161 void MultiMonitorManager::Init() { |
155 // TODO(oshima): Move this logic to MonitorChangeObserver. | 162 // TODO(oshima): Move this logic to MonitorChangeObserver. |
156 const string size_str = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 163 const string size_str = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
157 switches::kAuraHostWindowSize); | 164 switches::kAuraHostWindowSize); |
158 vector<string> parts; | 165 vector<string> parts; |
159 base::SplitString(size_str, ',', &parts); | 166 base::SplitString(size_str, ',', &parts); |
160 for (vector<string>::const_iterator iter = parts.begin(); | 167 for (vector<string>::const_iterator iter = parts.begin(); |
161 iter != parts.end(); ++iter) { | 168 iter != parts.end(); ++iter) { |
162 monitors_.push_back(CreateMonitorFromSpec(*iter)); | 169 monitors_.push_back(CreateMonitorFromSpec(*iter)); |
163 } | 170 } |
164 if (monitors_.empty()) | 171 if (monitors_.empty()) |
165 monitors_.push_back(CreateMonitorFromSpec("" /* default */)); | 172 monitors_.push_back(CreateMonitorFromSpec("" /* default */)); |
166 } | 173 } |
167 | 174 |
168 void MultiMonitorManager::AddRemoveMonitorImpl() { | 175 void MultiMonitorManager::AddRemoveMonitorImpl() { |
169 std::vector<const Monitor*> new_monitors; | 176 std::vector<Monitor> new_monitors; |
170 if (monitors_.size() > 1) { | 177 if (monitors_.size() > 1) { |
171 // Remove if there is more than one monitor. | 178 // Remove if there is more than one monitor. |
172 int count = monitors_.size() - 1; | 179 int count = monitors_.size() - 1; |
173 for (Monitors::const_iterator iter = monitors_.begin(); count-- > 0; ++iter) | 180 for (Monitors::const_iterator iter = monitors_.begin(); count-- > 0; ++iter) |
174 new_monitors.push_back(Copy(*iter)); | 181 new_monitors.push_back(*iter); |
175 } else { | 182 } else { |
176 // Add if there is only one monitor. | 183 // Add if there is only one monitor. |
177 new_monitors.push_back(Copy(monitors_[0])); | 184 new_monitors.push_back(monitors_[0]); |
178 aura::Monitor* extra_monitor = new Monitor; | 185 new_monitors.push_back(CreateMonitorFromSpec("50+50-1280x768")); |
179 extra_monitor->set_bounds(gfx::Rect(100, 100, 1440, 800)); | |
180 new_monitors.push_back(extra_monitor); | |
181 } | 186 } |
182 if (new_monitors.size()) | 187 if (new_monitors.size()) |
183 OnNativeMonitorsChanged(new_monitors); | 188 OnNativeMonitorsChanged(new_monitors); |
184 STLDeleteContainerPointers(new_monitors.begin(), new_monitors.end()); | |
185 } | 189 } |
186 | 190 |
187 void MultiMonitorManager::CycleMonitorImpl() { | 191 void MultiMonitorManager::CycleMonitorImpl() { |
188 if (monitors_.size() > 1) { | 192 if (monitors_.size() > 1) { |
189 std::vector<const Monitor*> new_monitors; | 193 std::vector<Monitor> new_monitors; |
190 for (Monitors::const_iterator iter = monitors_.begin() + 1; | 194 for (Monitors::const_iterator iter = monitors_.begin() + 1; |
191 iter != monitors_.end(); ++iter) | 195 iter != monitors_.end(); ++iter) { |
192 new_monitors.push_back(Copy(*iter)); | 196 gfx::Monitor monitor = *iter; |
193 new_monitors.push_back(Copy(monitors_.front())); | 197 new_monitors.push_back(monitor); |
| 198 } |
| 199 new_monitors.push_back(monitors_.front()); |
194 OnNativeMonitorsChanged(new_monitors); | 200 OnNativeMonitorsChanged(new_monitors); |
195 STLDeleteContainerPointers(new_monitors.begin(), new_monitors.end()); | |
196 } | 201 } |
197 } | 202 } |
198 | 203 |
| 204 gfx::Monitor& MultiMonitorManager::FindMonitorById(int id) { |
| 205 for (Monitors::iterator iter = monitors_.begin(); |
| 206 iter != monitors_.end(); ++iter) { |
| 207 if ((*iter).id() == id) |
| 208 return *iter; |
| 209 } |
| 210 DLOG(FATAL) << "Could not find monitor by id:" << id; |
| 211 return GetInvalidMonitor(); |
| 212 } |
| 213 |
199 } // namespace internal | 214 } // namespace internal |
200 } // namespace ash | 215 } // namespace ash |
OLD | NEW |