| 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" | 15 #include "ui/aura/monitor.h" |
| 16 #include "ui/aura/root_window.h" | 16 #include "ui/aura/root_window.h" |
| 17 #include "ui/aura/root_window_host.h" | 17 #include "ui/aura/root_window_host.h" |
| 18 #include "ui/gfx/rect.h" | 18 #include "ui/gfx/rect.h" |
| 19 #include "ui/aura/window_property.h" | 19 #include "ui/aura/window_property.h" |
| 20 | 20 |
| 21 DECLARE_WINDOW_PROPERTY_TYPE(aura::Monitor*); | 21 DECLARE_WINDOW_PROPERTY_TYPE(aura::Monitor*); |
| 22 | 22 |
| 23 namespace ash { | 23 namespace ash { |
| 24 namespace internal { | 24 namespace internal { |
| 25 namespace { |
| 26 |
| 27 aura::Monitor* Copy(aura::Monitor* m) { |
| 28 aura::Monitor* monitor = new aura::Monitor; |
| 29 monitor->set_bounds(m->bounds()); |
| 30 return monitor; |
| 31 } |
| 32 |
| 33 } // namespace |
| 25 | 34 |
| 26 DEFINE_WINDOW_PROPERTY_KEY(aura::Monitor*, kMonitorKey, NULL); | 35 DEFINE_WINDOW_PROPERTY_KEY(aura::Monitor*, kMonitorKey, NULL); |
| 27 | 36 |
| 28 using std::string; | 37 using std::string; |
| 29 using std::vector; | 38 using std::vector; |
| 30 using aura::Monitor; | 39 using aura::Monitor; |
| 31 using aura::RootWindow; | 40 using aura::RootWindow; |
| 32 using aura::Window; | 41 using aura::Window; |
| 33 | 42 |
| 34 MultiMonitorManager::MultiMonitorManager() { | 43 MultiMonitorManager::MultiMonitorManager() { |
| 35 Init(); | 44 Init(); |
| 36 } | 45 } |
| 37 | 46 |
| 38 MultiMonitorManager::~MultiMonitorManager() { | 47 MultiMonitorManager::~MultiMonitorManager() { |
| 39 STLDeleteContainerPointers(monitors_.begin(), monitors_.end()); | 48 // All monitors must have been deleted when monitor manager is deleted. |
| 49 CHECK(!monitors_.size()); |
| 40 } | 50 } |
| 41 | 51 |
| 42 void MultiMonitorManager::OnNativeMonitorResized(const gfx::Size& size) { | 52 // static |
| 43 // TODO(oshima): Update monitors using xrandr and notify observers | 53 void MultiMonitorManager::AddRemoveMonitor() { |
| 44 // Just update the primary for now. | 54 MultiMonitorManager* manager = static_cast<MultiMonitorManager*>( |
| 45 if (use_fullscreen_host_window()) { | 55 aura::Env::GetInstance()->monitor_manager()); |
| 46 Monitor* monitor = | 56 manager->AddRemoveMonitorImpl(); |
| 47 aura::Env::GetInstance()->monitor_manager()->GetMonitorAt(0); | 57 } |
| 48 monitor->set_size(size); | 58 |
| 49 NotifyBoundsChanged(monitor); | 59 void MultiMonitorManager::CycleMonitor() { |
| 60 MultiMonitorManager* manager = static_cast<MultiMonitorManager*>( |
| 61 aura::Env::GetInstance()->monitor_manager()); |
| 62 manager->CycleMonitorImpl(); |
| 63 } |
| 64 |
| 65 void MultiMonitorManager::OnNativeMonitorsChanged( |
| 66 const std::vector<const aura::Monitor*>& new_monitors) { |
| 67 size_t min = std::min(monitors_.size(), new_monitors.size()); |
| 68 |
| 69 // For m19, we only care about 1st monitor as primary, and |
| 70 // don't differentiate the rest of monitors as all secondary |
| 71 // monitors have the same content. |
| 72 // TODO(oshima): Fix this so that we can differentiate outputs |
| 73 // and keep a content on one monitor stays on the same monitor |
| 74 // when a monitor is added or removed. |
| 75 for (size_t i = 0; i < min; ++i) { |
| 76 Monitor* current_monitor = monitors_[i]; |
| 77 const Monitor* new_monitor = new_monitors[i]; |
| 78 if (current_monitor->bounds() != new_monitor->bounds()) { |
| 79 current_monitor->set_bounds(new_monitor->bounds()); |
| 80 NotifyBoundsChanged(current_monitor); |
| 81 } |
| 82 } |
| 83 |
| 84 if (monitors_.size() < new_monitors.size()) { |
| 85 // New monitors added |
| 86 for (size_t i = min; i < new_monitors.size(); ++i) { |
| 87 Monitor* monitor = new Monitor(); |
| 88 monitor->set_bounds(new_monitors[i]->bounds()); |
| 89 monitors_.push_back(monitor); |
| 90 NotifyMonitorAdded(monitor); |
| 91 } |
| 92 } else { |
| 93 // Monitors are removed. |
| 94 while (monitors_.size() > new_monitors.size()) { |
| 95 Monitor* monitor = monitors_.back(); |
| 96 // Monitor object is deleted in OnWindowDestroying. |
| 97 NotifyMonitorRemoved(monitor); |
| 98 } |
| 50 } | 99 } |
| 51 } | 100 } |
| 52 | 101 |
| 53 RootWindow* MultiMonitorManager::CreateRootWindowForMonitor( | 102 RootWindow* MultiMonitorManager::CreateRootWindowForMonitor( |
| 54 Monitor* monitor) { | 103 Monitor* monitor) { |
| 55 RootWindow* root_window = new RootWindow(monitor->bounds()); | 104 RootWindow* root_window = new RootWindow(monitor->bounds()); |
| 56 root_window->AddObserver(this); | 105 root_window->AddObserver(this); |
| 106 root_window->AddRootWindowObserver(this); |
| 57 root_window->SetProperty(kMonitorKey, monitor); | 107 root_window->SetProperty(kMonitorKey, monitor); |
| 58 return root_window; | 108 return root_window; |
| 59 } | 109 } |
| 60 | 110 |
| 61 const Monitor* MultiMonitorManager::GetMonitorNearestWindow( | 111 const Monitor* MultiMonitorManager::GetMonitorNearestWindow( |
| 62 const Window* window) const { | 112 const Window* window) const { |
| 63 if (!window) { | 113 if (!window) { |
| 64 MultiMonitorManager* manager = const_cast<MultiMonitorManager*>(this); | 114 MultiMonitorManager* manager = const_cast<MultiMonitorManager*>(this); |
| 65 return manager->GetMonitorAt(0); | 115 return manager->GetMonitorAt(0); |
| 66 } | 116 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 82 | 132 |
| 83 size_t MultiMonitorManager::GetNumMonitors() const { | 133 size_t MultiMonitorManager::GetNumMonitors() const { |
| 84 return monitors_.size(); | 134 return monitors_.size(); |
| 85 } | 135 } |
| 86 | 136 |
| 87 Monitor* MultiMonitorManager::GetMonitorNearestWindow(const Window* window) { | 137 Monitor* MultiMonitorManager::GetMonitorNearestWindow(const Window* window) { |
| 88 const MonitorManager* manager = this; | 138 const MonitorManager* manager = this; |
| 89 return const_cast<Monitor*>(manager->GetMonitorNearestWindow(window)); | 139 return const_cast<Monitor*>(manager->GetMonitorNearestWindow(window)); |
| 90 } | 140 } |
| 91 | 141 |
| 92 void MultiMonitorManager::OnWindowBoundsChanged( | 142 void MultiMonitorManager::OnRootWindowResized(const aura::RootWindow* root, |
| 93 Window* window, const gfx::Rect& bounds) { | 143 const gfx::Size& old_size) { |
| 94 if (!use_fullscreen_host_window()) { | 144 if (!use_fullscreen_host_window()) { |
| 95 Monitor* monitor = window->GetProperty(kMonitorKey); | 145 Monitor* monitor = root->GetProperty(kMonitorKey); |
| 96 monitor->set_size(bounds.size()); | 146 monitor->set_size(root->GetHostSize()); |
| 97 NotifyBoundsChanged(monitor); | 147 NotifyBoundsChanged(monitor); |
| 98 } | 148 } |
| 99 } | 149 } |
| 100 | 150 |
| 101 void MultiMonitorManager::OnWindowDestroying(Window* window) { | 151 void MultiMonitorManager::OnWindowDestroying(Window* window) { |
| 152 RootWindow* root = static_cast<RootWindow*>(window); |
| 153 root->RemoveObserver(this); |
| 154 // Don't remove RootWindowObserver because the observer list in |
| 155 // RootWindowObserver class has already been destroyed by this time. |
| 156 |
| 102 Monitor* monitor = window->GetProperty(kMonitorKey); | 157 Monitor* monitor = window->GetProperty(kMonitorKey); |
| 103 monitors_.erase(std::find(monitors_.begin(), monitors_.end(), monitor)); | 158 monitors_.erase(std::find(monitors_.begin(), monitors_.end(), monitor)); |
| 104 delete monitor; | 159 delete monitor; |
| 105 } | 160 } |
| 106 | 161 |
| 107 void MultiMonitorManager::Init() { | 162 void MultiMonitorManager::Init() { |
| 163 // TODO(oshima): Move this logic to MonitorChangeObserver. |
| 108 const string size_str = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( | 164 const string size_str = CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
| 109 switches::kAuraHostWindowSize); | 165 switches::kAuraHostWindowSize); |
| 110 vector<string> parts; | 166 vector<string> parts; |
| 111 base::SplitString(size_str, ',', &parts); | 167 base::SplitString(size_str, ',', &parts); |
| 112 for (vector<string>::const_iterator iter = parts.begin(); | 168 for (vector<string>::const_iterator iter = parts.begin(); |
| 113 iter != parts.end(); ++iter) { | 169 iter != parts.end(); ++iter) { |
| 114 monitors_.push_back(CreateMonitorFromSpec(*iter)); | 170 monitors_.push_back(CreateMonitorFromSpec(*iter)); |
| 115 } | 171 } |
| 116 if (monitors_.empty()) | 172 if (monitors_.empty()) |
| 117 monitors_.push_back(CreateMonitorFromSpec("" /* default */)); | 173 monitors_.push_back(CreateMonitorFromSpec("" /* default */)); |
| 118 } | 174 } |
| 119 | 175 |
| 176 void MultiMonitorManager::AddRemoveMonitorImpl() { |
| 177 std::vector<const Monitor*> new_monitors; |
| 178 if (monitors_.size() > 1) { |
| 179 // Remove if there is more than one monitor. |
| 180 int count = monitors_.size() - 1; |
| 181 for (Monitors::const_iterator iter = monitors_.begin(); count-- > 0; ++iter) |
| 182 new_monitors.push_back(Copy(*iter)); |
| 183 } else { |
| 184 // Add if there is only one monitor. |
| 185 new_monitors.push_back(Copy(monitors_[0])); |
| 186 aura::Monitor* extra_monitor = new Monitor; |
| 187 extra_monitor->set_bounds(gfx::Rect(100, 100, 1440, 800)); |
| 188 new_monitors.push_back(extra_monitor); |
| 189 } |
| 190 if (new_monitors.size()) |
| 191 OnNativeMonitorsChanged(new_monitors); |
| 192 STLDeleteContainerPointers(new_monitors.begin(), new_monitors.end()); |
| 193 } |
| 194 |
| 195 void MultiMonitorManager::CycleMonitorImpl() { |
| 196 if (monitors_.size() > 1) { |
| 197 std::vector<const Monitor*> new_monitors; |
| 198 for (Monitors::const_iterator iter = monitors_.begin() + 1; |
| 199 iter != monitors_.end(); ++iter) |
| 200 new_monitors.push_back(Copy(*iter)); |
| 201 new_monitors.push_back(Copy(monitors_.front())); |
| 202 OnNativeMonitorsChanged(new_monitors); |
| 203 STLDeleteContainerPointers(new_monitors.begin(), new_monitors.end()); |
| 204 } |
| 205 } |
| 206 |
| 120 } // namespace internal | 207 } // namespace internal |
| 121 } // namespace ash | 208 } // namespace ash |
| OLD | NEW |