Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7010)

Unified Diff: ash/display/multi_display_manager.cc

Issue 10905288: Switch primary display (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: sync Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ash/display/multi_display_manager.h ('k') | ash/display/multi_display_manager_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ash/display/multi_display_manager.cc
diff --git a/ash/display/multi_display_manager.cc b/ash/display/multi_display_manager.cc
index 37509be0e82e2522f11a472ae805ca36da0b220d..79729f159c829bed60e75cc6c4d774b940fc9a9d 100644
--- a/ash/display/multi_display_manager.cc
+++ b/ash/display/multi_display_manager.cc
@@ -8,6 +8,7 @@
#include <vector>
#include "ash/display/display_controller.h"
+#include "ash/shell.h"
#include "base/command_line.h"
#include "base/stl_util.h"
#include "base/string_split.h"
@@ -18,6 +19,7 @@
#include "ui/aura/root_window_host.h"
#include "ui/aura/window_property.h"
#include "ui/gfx/display.h"
+#include "ui/gfx/screen.h"
#include "ui/gfx/rect.h"
#if defined(USE_X11)
@@ -30,16 +32,33 @@
#endif
DECLARE_WINDOW_PROPERTY_TYPE(int64);
+typedef std::vector<gfx::Display> DisplayList;
namespace ash {
namespace internal {
namespace {
+struct DisplaySortFunctor {
+ bool operator()(const gfx::Display& a, const gfx::Display& b) {
+ return a.id() < b.id();
+ }
+};
+
gfx::Display& GetInvalidDisplay() {
static gfx::Display* invalid_display = new gfx::Display();
return *invalid_display;
}
+#if defined(OS_CHROMEOS)
+int64 GetDisplayIdForOutput(XID output) {
+ uint16 manufacturer_id = 0;
+ uint32 serial_number = 0;
+ ui::GetOutputDeviceData(
+ output, &manufacturer_id, &serial_number, NULL);
+ return gfx::Display::GetID(manufacturer_id, serial_number);
+}
+#endif
+
} // namespace
using aura::RootWindow;
@@ -51,7 +70,8 @@ DEFINE_WINDOW_PROPERTY_KEY(int64, kDisplayIdKey,
gfx::Display::kInvalidDisplayID);
MultiDisplayManager::MultiDisplayManager() :
- internal_display_id_(gfx::Display::kInvalidDisplayID) {
+ internal_display_id_(gfx::Display::kInvalidDisplayID),
+ force_bounds_changed_(false) {
Init();
}
@@ -72,33 +92,23 @@ void MultiDisplayManager::ToggleDisplayScale() {
manager->ScaleDisplayImpl();
}
-void MultiDisplayManager::InitInternalDisplayInfo() {
-#if defined(OS_CHROMEOS)
- if (!base::chromeos::IsRunningOnChromeOS())
- return;
- std::vector<XID> outputs;
- ui::GetOutputDeviceHandles(&outputs);
- std::vector<std::string> output_names = ui::GetOutputNames(outputs);
- for (size_t i = 0; i < output_names.size(); ++i) {
- if (chromeos::OutputConfigurator::IsInternalOutputName(
- output_names[i])) {
- XID internal_output = outputs[i];
- uint16 manufacturer_id = 0;
- uint32 serial_number = 0;
- ui::GetOutputDeviceData(
- internal_output, &manufacturer_id, &serial_number, NULL);
- internal_display_id_ =
- gfx::Display::GetID(manufacturer_id, serial_number);
- return;
- }
+bool MultiDisplayManager::IsActiveDisplay(const gfx::Display& display) const {
+ for (DisplayList::const_iterator iter = displays_.begin();
+ iter != displays_.end(); ++iter) {
+ if ((*iter).id() == display.id())
+ return true;
}
-#endif
+ return false;
}
bool MultiDisplayManager::HasInternalDisplay() const {
return internal_display_id_ != gfx::Display::kInvalidDisplayID;
}
+bool MultiDisplayManager::IsInternalDisplayId(int64 id) const {
+ return internal_display_id_ == id;
+}
+
bool MultiDisplayManager::UpdateWorkAreaOfDisplayNearestWindow(
const aura::Window* window,
const gfx::Insets& insets) {
@@ -111,7 +121,7 @@ bool MultiDisplayManager::UpdateWorkAreaOfDisplayNearestWindow(
const gfx::Display& MultiDisplayManager::FindDisplayContainingPoint(
const gfx::Point& point_in_screen) const {
- for (std::vector<gfx::Display>::const_iterator iter = displays_.begin();
+ for (DisplayList::const_iterator iter = displays_.begin();
iter != displays_.end(); ++iter) {
const gfx::Display& display = *iter;
if (display.bounds().Contains(point_in_screen))
@@ -122,7 +132,7 @@ const gfx::Display& MultiDisplayManager::FindDisplayContainingPoint(
void MultiDisplayManager::OnNativeDisplaysChanged(
const std::vector<gfx::Display>& updated_displays) {
- if (updated_displays.size() == 0) {
+ if (updated_displays.empty()) {
// Don't update the displays when all displays are disconnected.
// This happens when:
// - the device is idle and powerd requested to turn off all displays.
@@ -135,10 +145,10 @@ void MultiDisplayManager::OnNativeDisplaysChanged(
// display list will be updated correctly.
return;
}
- std::vector<gfx::Display> new_displays;
+ DisplayList new_displays = updated_displays;
if (internal_display_id_ != gfx::Display::kInvalidDisplayID) {
bool internal_display_connected = false;
- for (Displays::const_iterator iter = updated_displays.begin();
+ for (DisplayList::const_iterator iter = updated_displays.begin();
iter != updated_displays.end(); ++iter) {
if ((*iter).id() == internal_display_id_) {
internal_display_connected = true;
@@ -149,50 +159,88 @@ void MultiDisplayManager::OnNativeDisplaysChanged(
}
}
// If the internal display wasn't connected, use the cached value.
- if (!internal_display_connected)
+ if (!internal_display_connected) {
+ // Internal display may be reported as disconnect during startup time.
+ if (!internal_display_.get()) {
+ internal_display_.reset(new gfx::Display(internal_display_id_,
+ gfx::Rect(800, 600)));
+ }
new_displays.push_back(*internal_display_.get());
- new_displays.insert(
- new_displays.end(), updated_displays.begin(), updated_displays.end());
+ }
} else {
new_displays = updated_displays;
}
- size_t min = std::min(displays_.size(), new_displays.size());
-
- // TODO(oshima): Fix this so that we can differentiate outputs
- // and keep a content on one display stays on the same display
- // when a display is added or removed.
- for (size_t i = 0; i < min; ++i) {
- gfx::Display& current_display = displays_[i];
- const gfx::Display& new_display = new_displays[i];
- if (current_display.bounds_in_pixel() != new_display.bounds_in_pixel() ||
- current_display.device_scale_factor() !=
- new_display.device_scale_factor()) {
- current_display.SetScaleAndBounds(new_display.device_scale_factor(),
- new_display.bounds_in_pixel());
- NotifyBoundsChanged(current_display);
+ std::sort(displays_.begin(), displays_.end(), DisplaySortFunctor());
+ std::sort(new_displays.begin(), new_displays.end(), DisplaySortFunctor());
+ DisplayList removed_displays;
+ std::vector<size_t> changed_display_indices;
+ std::vector<size_t> added_display_indices;
+ gfx::Display current_primary;
+ if (Shell::HasInstance())
+ current_primary = gfx::Screen::GetPrimaryDisplay();
+
+ for (DisplayList::iterator curr_iter = displays_.begin(),
+ new_iter = new_displays.begin();
+ curr_iter != displays_.end() || new_iter != new_displays.end();) {
+ if (curr_iter == displays_.end()) {
+ // more displays in new list.
+ added_display_indices.push_back(new_iter - new_displays.begin());
+ ++new_iter;
+ } else if (new_iter == new_displays.end()) {
+ // more displays in current list.
+ removed_displays.push_back(*curr_iter);
+ ++curr_iter;
+ } else if ((*curr_iter).id() == (*new_iter).id()) {
+ const gfx::Display& current_display = *curr_iter;
+ gfx::Display& new_display = *new_iter;
+ if (force_bounds_changed_ ||
+ current_display.bounds_in_pixel() != new_display.bounds_in_pixel() ||
+ current_display.device_scale_factor() !=
+ new_display.device_scale_factor()) {
+ changed_display_indices.push_back(new_iter - new_displays.begin());
+ }
+ // TODO(oshima): This is ugly. Simplify these operations.
+ new_display.SetScaleAndBounds(
+ new_display.device_scale_factor(),
+ new_display.bounds_in_pixel());
+ // If the display is primary, then simpy use 0,0. Otherwise,
+ // use the origin currently used.
+ if ((*new_iter).id() != current_primary.id()) {
+ new_display.set_bounds(gfx::Rect(current_display.bounds().origin(),
+ new_display.bounds().size()));
+ }
+ new_display.UpdateWorkAreaFromInsets(current_display.GetWorkAreaInsets());
+ ++curr_iter;
+ ++new_iter;
+ } else if ((*curr_iter).id() < (*new_iter).id()) {
+ // more displays in current list between ids, which means it is deleted.
+ removed_displays.push_back(*curr_iter);
+ ++curr_iter;
+ } else {
+ // more displays in new list between ids, which means it is added.
+ added_display_indices.push_back(new_iter - new_displays.begin());
+ ++new_iter;
}
}
+ displays_ = new_displays;
+ // Temporarily add displays to be removed because display object
+ // being removed are accessed during shutting down the root.
+ displays_.insert(displays_.end(), removed_displays.begin(),
+ removed_displays.end());
+ for (std::vector<size_t>::iterator iter = changed_display_indices.begin();
+ iter != changed_display_indices.end(); ++iter) {
+ NotifyBoundsChanged(displays_[*iter]);
+ }
+ for (std::vector<size_t>::iterator iter = added_display_indices.begin();
+ iter != added_display_indices.end(); ++iter) {
+ NotifyDisplayAdded(displays_[*iter]);
+ }
- if (displays_.size() < new_displays.size()) {
- // New displays added
- for (size_t i = min; i < new_displays.size(); ++i) {
- const gfx::Display& new_display = new_displays[i];
- displays_.push_back(gfx::Display(new_display.id()));
- gfx::Display& display = displays_.back();
- display.SetScaleAndBounds(new_display.device_scale_factor(),
- new_display.bounds_in_pixel());
- NotifyDisplayAdded(display);
- }
- } else {
- // Displays are removed. We keep the display for the primary
- // display (at index 0) because it needs the display information
- // even if it doesn't exit.
- while (displays_.size() > new_displays.size() && displays_.size() > 1) {
- Displays::reverse_iterator iter = displays_.rbegin();
- NotifyDisplayRemoved(*iter);
- displays_.erase(iter.base() - 1);
- }
+ for (DisplayList::const_reverse_iterator iter = removed_displays.rbegin();
+ iter != removed_displays.rend(); ++iter) {
+ NotifyDisplayRemoved(displays_.back());
+ displays_.pop_back();
}
}
@@ -254,11 +302,11 @@ const gfx::Display& MultiDisplayManager::GetDisplayMatching(
return matching ? *matching : displays_[0];
}
-std::string MultiDisplayManager::GetDisplayNameAt(size_t index) {
+std::string MultiDisplayManager::GetDisplayNameFor(
+ const gfx::Display& display) {
#if defined(USE_X11)
- gfx::Display* display = GetDisplayAt(index);
std::vector<XID> outputs;
- if (display && display->id() != gfx::Display::kInvalidDisplayID &&
+ if (display.id() != gfx::Display::kInvalidDisplayID &&
ui::GetOutputDeviceHandles(&outputs)) {
for (size_t i = 0; i < outputs.size(); ++i) {
uint16 manufacturer_id = 0;
@@ -266,15 +314,14 @@ std::string MultiDisplayManager::GetDisplayNameAt(size_t index) {
std::string name;
if (ui::GetOutputDeviceData(
outputs[i], &manufacturer_id, &serial_number, &name) &&
- display->id() ==
+ display.id() ==
gfx::Display::GetID(manufacturer_id, serial_number)) {
return name;
}
}
}
#endif
-
- return base::StringPrintf("Display %d", static_cast<int>(index + 1));
+ return base::StringPrintf("Display %d", static_cast<int>(display.id()));
}
void MultiDisplayManager::OnRootWindowResized(const aura::RootWindow* root,
@@ -289,6 +336,21 @@ void MultiDisplayManager::OnRootWindowResized(const aura::RootWindow* root,
}
void MultiDisplayManager::Init() {
+#if defined(OS_CHROMEOS)
+ if (base::chromeos::IsRunningOnChromeOS()) {
+ std::vector<XID> outputs;
+ ui::GetOutputDeviceHandles(&outputs);
+ std::vector<std::string> output_names = ui::GetOutputNames(outputs);
+ for (size_t i = 0; i < output_names.size(); ++i) {
+ if (chromeos::OutputConfigurator::IsInternalOutputName(
+ output_names[i])) {
+ internal_display_id_ = GetDisplayIdForOutput(outputs[i]);
+ break;
+ }
+ }
+ }
+#endif
+
// TODO(oshima): Move this logic to DisplayChangeObserver.
const string size_str = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kAuraHostWindowSize);
@@ -307,8 +369,10 @@ void MultiDisplayManager::CycleDisplayImpl() {
if (displays_.size() > 1) {
// Remove if there is more than one display.
int count = displays_.size() - 1;
- for (Displays::const_iterator iter = displays_.begin(); count-- > 0; ++iter)
+ for (DisplayList::const_iterator iter = displays_.begin();
+ count-- > 0; ++iter) {
new_displays.push_back(*iter);
+ }
} else {
// Add if there is only one display.
new_displays.push_back(displays_[0]);
@@ -321,7 +385,7 @@ void MultiDisplayManager::CycleDisplayImpl() {
void MultiDisplayManager::ScaleDisplayImpl() {
if (displays_.size() > 0) {
std::vector<gfx::Display> new_displays;
- for (Displays::const_iterator iter = displays_.begin();
+ for (DisplayList::const_iterator iter = displays_.begin();
iter != displays_.end(); ++iter) {
gfx::Display display = *iter;
float factor = display.device_scale_factor() == 1.0f ? 2.0f : 1.0f;
@@ -339,12 +403,16 @@ gfx::Display& MultiDisplayManager::FindDisplayForRootWindow(
int64 id = root_window->GetProperty(kDisplayIdKey);
// if id is |kInvaildDisplayID|, it's being deleted.
DCHECK(id != gfx::Display::kInvalidDisplayID);
- for (Displays::iterator iter = displays_.begin();
+ return FindDisplayForId(id);
+}
+
+gfx::Display& MultiDisplayManager::FindDisplayForId(int64 id) {
+ for (DisplayList::iterator iter = displays_.begin();
iter != displays_.end(); ++iter) {
if ((*iter).id() == id)
return *iter;
}
- DLOG(FATAL) << "Could not find display by id:" << id;
+ DLOG(FATAL) << "Could not find display:" << id;
return GetInvalidDisplay();
}
@@ -358,12 +426,20 @@ void MultiDisplayManager::AddDisplayFromSpec(const std::string& spec) {
displays_.push_back(display);
}
-int64 MultiDisplayManager::EnableInternalDisplayForTest() {
- const int64 kInternalDisplayIdForTest = 9999;
- internal_display_id_ = kInternalDisplayIdForTest;
- internal_display_.reset(new gfx::Display(internal_display_id_,
- gfx::Rect(800, 600)));
- return kInternalDisplayIdForTest;
+int64 MultiDisplayManager::SetFirstDisplayAsInternalDisplayForTest() {
+ internal_display_id_ = displays_[0].id();
+ internal_display_.reset(new gfx::Display);
+ *internal_display_ = displays_[0];
+ return internal_display_id_;
+}
+
+void MultiDisplayManager::SetDisplayIdsForTest(DisplayList* to_update) const {
+ DisplayList::iterator iter_to_update = to_update->begin();
+ DisplayList::const_iterator iter = displays_.begin();
+ for (; iter != displays_.end() && iter_to_update != to_update->end();
+ ++iter, ++iter_to_update) {
+ (*iter_to_update).set_id((*iter).id());
+ }
}
} // namespace internal
« no previous file with comments | « ash/display/multi_display_manager.h ('k') | ash/display/multi_display_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698