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

Unified Diff: ash/display/display_controller.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/display_controller.h ('k') | ash/display/display_controller_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ash/display/display_controller.cc
diff --git a/ash/display/display_controller.cc b/ash/display/display_controller.cc
index 11c76073eb2db87f056607ba0039c92537d0370f..0277844ecb24611875983d1c9e89957eb9ad9741 100644
--- a/ash/display/display_controller.cc
+++ b/ash/display/display_controller.cc
@@ -9,7 +9,6 @@
#include "ash/ash_switches.h"
#include "ash/display/multi_display_manager.h"
#include "ash/root_window_controller.h"
-#include "ash/screen_ash.h"
#include "ash/shell.h"
#include "ash/wm/coordinate_conversion.h"
#include "ash/wm/property_util.h"
@@ -17,6 +16,7 @@
#include "base/command_line.h"
#include "base/json/json_value_converter.h"
#include "base/string_piece.h"
+#include "base/stringprintf.h"
#include "base/values.h"
#include "ui/aura/client/screen_position_client.h"
#include "ui/aura/env.h"
@@ -57,10 +57,28 @@ bool GetPositionFromString(const base::StringPiece& position,
return true;
}
LOG(ERROR) << "Invalid position value: " << position;
-
return false;
}
+std::string GetStringFromPosition(DisplayLayout::Position position) {
+ switch (position) {
+ case DisplayLayout::TOP:
+ return std::string("top");
+ case DisplayLayout::BOTTOM:
+ return std::string("bottom");
+ case DisplayLayout::RIGHT:
+ return std::string("right");
+ case DisplayLayout::LEFT:
+ return std::string("left");
+ }
+ return std::string("unknown");
+}
+
+internal::MultiDisplayManager* GetDisplayManager() {
+ return static_cast<internal::MultiDisplayManager*>(
+ aura::Env::GetInstance()->display_manager());
+}
+
} // namespace
DisplayLayout::DisplayLayout()
@@ -81,6 +99,25 @@ DisplayLayout::DisplayLayout(DisplayLayout::Position position, int offset)
DCHECK_GE(kMaxValidOffset, abs(offset));
}
+DisplayLayout DisplayLayout::Invert() const {
+ Position inverted_position = RIGHT;
+ switch (position) {
+ case TOP:
+ inverted_position = BOTTOM;
+ break;
+ case BOTTOM:
+ inverted_position = TOP;
+ break;
+ case RIGHT:
+ inverted_position = LEFT;
+ break;
+ case LEFT:
+ inverted_position = RIGHT;
+ break;
+ }
+ return DisplayLayout(inverted_position, -offset);
+}
+
// static
bool DisplayLayout::ConvertFromValue(const base::Value& value,
DisplayLayout* layout) {
@@ -95,29 +132,17 @@ bool DisplayLayout::ConvertToValue(const DisplayLayout& layout,
if (!value->GetAsDictionary(&dict_value) || dict_value == NULL)
return false;
- std::string position_value;
- switch (layout.position) {
- case TOP:
- position_value = "top";
- break;
- case BOTTOM:
- position_value = "bottom";
- break;
- case RIGHT:
- position_value = "right";
- break;
- case LEFT:
- position_value = "left";
- break;
- default:
- return false;
- }
-
- dict_value->SetString("position", position_value);
+ const std::string position_str = GetStringFromPosition(layout.position);
+ dict_value->SetString("position", position_str);
dict_value->SetInteger("offset", layout.offset);
return true;
}
+std::string DisplayLayout::ToString() const {
+ const std::string position_str = GetStringFromPosition(position);
+ return StringPrintf("%s, %d", position_str.c_str(), offset);
+}
+
// static
void DisplayLayout::RegisterJSONConverter(
base::JSONValueConverter<DisplayLayout>* converter) {
@@ -127,11 +152,11 @@ void DisplayLayout::RegisterJSONConverter(
}
DisplayController::DisplayController() {
- aura::Env::GetInstance()->display_manager()->AddObserver(this);
+ GetDisplayManager()->AddObserver(this);
}
DisplayController::~DisplayController() {
- aura::Env::GetInstance()->display_manager()->RemoveObserver(this);
+ GetDisplayManager()->RemoveObserver(this);
// Delete all root window controllers, which deletes root window
// from the last so that the primary root window gets deleted last.
for (std::map<int64, aura::RootWindow*>::const_reverse_iterator it =
@@ -144,20 +169,40 @@ DisplayController::~DisplayController() {
}
void DisplayController::InitPrimaryDisplay() {
- aura::DisplayManager* display_manager =
- aura::Env::GetInstance()->display_manager();
- const gfx::Display* display = display_manager->GetDisplayAt(0);
- aura::RootWindow* root = AddRootWindowForDisplay(*display);
- root->SetHostBounds(display->bounds_in_pixel());
+ const gfx::Display* primary_candidate = GetDisplayManager()->GetDisplayAt(0);
+#if defined(OS_CHROMEOS)
+ if (base::chromeos::IsRunningOnChromeOS()) {
+ internal::MultiDisplayManager* display_manager = GetDisplayManager();
+ // On ChromeOS device, root windows are stacked vertically, and
+ // default primary is the one on top.
+ int count = display_manager->GetNumDisplays();
+ int y = primary_candidate->bounds_in_pixel().y();
+ for (int i = 1; i < count; ++i) {
+ const gfx::Display* display = display_manager->GetDisplayAt(i);
+ if (display_manager->IsInternalDisplayId(display->id())) {
+ primary_candidate = display;
+ break;
+ } else if (display->bounds_in_pixel().y() < y) {
+ primary_candidate = display;
+ y = display->bounds_in_pixel().y();
+ }
+ }
+ }
+#endif
+ primary_display_ = *primary_candidate;
+ aura::RootWindow* root = AddRootWindowForDisplay(primary_display_);
+ root->SetHostBounds(primary_display_.bounds_in_pixel());
+ UpdateDisplayBoundsForLayout();
}
void DisplayController::InitSecondaryDisplays() {
- aura::DisplayManager* display_manager =
- aura::Env::GetInstance()->display_manager();
- for (size_t i = 1; i < display_manager->GetNumDisplays(); ++i) {
+ internal::MultiDisplayManager* display_manager = GetDisplayManager();
+ for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
const gfx::Display* display = display_manager->GetDisplayAt(i);
- aura::RootWindow* root = AddRootWindowForDisplay(*display);
- Shell::GetInstance()->InitRootWindowForSecondaryDisplay(root);
+ if (primary_display_.id() != display->id()) {
+ aura::RootWindow* root = AddRootWindowForDisplay(*display);
+ Shell::GetInstance()->InitRootWindowForSecondaryDisplay(root);
+ }
}
CommandLine* command_line = CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kAshSecondaryDisplayLayout)) {
@@ -190,9 +235,7 @@ void DisplayController::RemoveObserver(Observer* observer) {
aura::RootWindow* DisplayController::GetPrimaryRootWindow() {
DCHECK(!root_windows_.empty());
- aura::DisplayManager* display_manager =
- aura::Env::GetInstance()->display_manager();
- return root_windows_[display_manager->GetDisplayAt(0)->id()];
+ return root_windows_[primary_display_.id()];
}
aura::RootWindow* DisplayController::GetRootWindowForDisplayId(int64 id) {
@@ -260,8 +303,9 @@ void DisplayController::SetLayoutForDisplayName(const std::string& name,
}
}
-const DisplayLayout& DisplayController::GetLayoutForDisplayName(
- const std::string& name) {
+const DisplayLayout& DisplayController::GetLayoutForDisplay(
+ const gfx::Display& display) const {
+ const std::string& name = GetDisplayManager()->GetDisplayNameFor(display);
std::map<std::string, DisplayLayout>::const_iterator it =
secondary_layouts_.find(name);
@@ -270,10 +314,84 @@ const DisplayLayout& DisplayController::GetLayoutForDisplayName(
return default_display_layout_;
}
+const DisplayLayout& DisplayController::GetCurrentDisplayLayout() const {
+ DCHECK_EQ(2U, GetDisplayManager()->GetNumDisplays());
+ if (GetDisplayManager()->GetNumDisplays() > 1) {
+ DisplayController* non_const = const_cast<DisplayController*>(this);
+ return GetLayoutForDisplay(*(non_const->GetSecondaryDisplay()));
+ }
+ // On release build, just fallback to default instead of blowing up.
+ return default_display_layout_;
+}
+
+void DisplayController::SetPrimaryDisplay(
+ const gfx::Display& new_primary_display) {
+ internal::MultiDisplayManager* display_manager = GetDisplayManager();
+ DCHECK(new_primary_display.is_valid());
+ DCHECK(display_manager->IsActiveDisplay(new_primary_display));
+
+ if (!new_primary_display.is_valid() ||
+ !display_manager->IsActiveDisplay(new_primary_display)) {
+ LOG(ERROR) << "Invalid or non-existent display is requested:"
+ << new_primary_display.ToString();
+ return;
+ }
+
+ if (primary_display_.id() == new_primary_display.id() ||
+ root_windows_.size() < 2) {
+ return;
+ }
+
+ aura::RootWindow* non_primary_root = root_windows_[new_primary_display.id()];
+ LOG_IF(ERROR, !non_primary_root)
+ << "Unknown display is requested in SetPrimaryDisplay: id="
+ << new_primary_display.id();
+ if (!non_primary_root)
+ return;
+
+ gfx::Display old_primary_display = primary_display_;
+
+ // Swap root windows between current and new primary display.
+ aura::RootWindow* primary_root = root_windows_[primary_display_.id()];
+ DCHECK(primary_root);
+ DCHECK_NE(primary_root, non_primary_root);
+
+ root_windows_[new_primary_display.id()] = primary_root;
+ primary_root->SetProperty(internal::kDisplayIdKey, new_primary_display.id());
+
+ root_windows_[old_primary_display.id()] = non_primary_root;
+ non_primary_root->SetProperty(internal::kDisplayIdKey,
+ old_primary_display.id());
+
+ primary_display_ = new_primary_display;
+
+ // Update the layout.
+ SetLayoutForDisplayName(
+ display_manager->GetDisplayNameFor(old_primary_display),
+ GetLayoutForDisplay(new_primary_display).Invert());
+
+ // Update the dispay manager with new display info.
+ std::vector<gfx::Display> displays;
+ displays.push_back(primary_display_);
+ displays.push_back(*GetSecondaryDisplay());
+ GetDisplayManager()->set_force_bounds_changed(true);
+ GetDisplayManager()->OnNativeDisplaysChanged(displays);
+ GetDisplayManager()->set_force_bounds_changed(false);
+}
+
+gfx::Display* DisplayController::GetSecondaryDisplay() {
+ internal::MultiDisplayManager* display_manager = GetDisplayManager();
+ CHECK_EQ(2U, display_manager->GetNumDisplays());
+ return display_manager->GetDisplayAt(0)->id() == primary_display_.id() ?
+ display_manager->GetDisplayAt(1) : display_manager->GetDisplayAt(0);
+}
+
void DisplayController::OnDisplayBoundsChanged(const gfx::Display& display) {
+ if (display.id() == primary_display_.id())
+ primary_display_ = display;
NotifyDisplayConfigurationChanging();
- root_windows_[display.id()]->SetHostBounds(display.bounds_in_pixel());
UpdateDisplayBoundsForLayout();
+ root_windows_[display.id()]->SetHostBounds(display.bounds_in_pixel());
}
void DisplayController::OnDisplayAdded(const gfx::Display& display) {
@@ -285,30 +403,45 @@ void DisplayController::OnDisplayAdded(const gfx::Display& display) {
}
void DisplayController::OnDisplayRemoved(const gfx::Display& display) {
- aura::RootWindow* root = root_windows_[display.id()];
- DCHECK(root);
- // Primary display should never be removed by DisplayManager.
- DCHECK(root != GetPrimaryRootWindow());
+ aura::RootWindow* root_to_delete = root_windows_[display.id()];
+ DCHECK(root_to_delete) << display.ToString();
NotifyDisplayConfigurationChanging();
+
// Display for root window will be deleted when the Primary RootWindow
// is deleted by the Shell.
- if (root != GetPrimaryRootWindow()) {
- root_windows_.erase(display.id());
- internal::RootWindowController* controller =
- GetRootWindowController(root);
- DCHECK(controller);
- controller->MoveWindowsTo(GetPrimaryRootWindow());
- // Delete most of root window related objects, but don't delete
- // root window itself yet because the stak may be using it.
- controller->Shutdown();
- MessageLoop::current()->DeleteSoon(FROM_HERE, controller);
+ root_windows_.erase(display.id());
+
+ // When the primary root window's display is removed, move the primary
+ // root to the other display.
+ if (primary_display_.id() == display.id()) {
+ DCHECK_EQ(1U, root_windows_.size());
+ primary_display_ = *GetSecondaryDisplay();
+ aura::RootWindow* primary_root = root_to_delete;
+
+ // Delete the other root instead.
+ root_to_delete = root_windows_[primary_display_.id()];
+ root_to_delete->SetProperty(internal::kDisplayIdKey, display.id());
+
+ // Setup primary root.
+ root_windows_[primary_display_.id()] = primary_root;
+ primary_root->SetProperty(internal::kDisplayIdKey, primary_display_.id());
+
+ OnDisplayBoundsChanged(primary_display_);
}
+ internal::RootWindowController* controller =
+ GetRootWindowController(root_to_delete);
+ DCHECK(controller);
+ controller->MoveWindowsTo(GetPrimaryRootWindow());
+ // Delete most of root window related objects, but don't delete
+ // root window itself yet because the stak may be using it.
+ controller->Shutdown();
+ MessageLoop::current()->DeleteSoon(FROM_HERE, controller);
}
aura::RootWindow* DisplayController::AddRootWindowForDisplay(
const gfx::Display& display) {
- aura::RootWindow* root = aura::Env::GetInstance()->display_manager()->
- CreateRootWindowForDisplay(display);
+ aura::RootWindow* root =
+ GetDisplayManager()->CreateRootWindowForDisplay(display);
root_windows_[display.id()] = root;
#if defined(OS_CHROMEOS)
@@ -326,25 +459,18 @@ void DisplayController::UpdateDisplayBoundsForLayout() {
return;
DCHECK_EQ(2, gfx::Screen::GetNumDisplays());
- aura::DisplayManager* display_manager =
- aura::Env::GetInstance()->display_manager();
- const gfx::Rect& primary_bounds = display_manager->GetDisplayAt(0)->bounds();
- gfx::Display* secondary_display = display_manager->GetDisplayAt(1);
- const std::string& secondary_name = display_manager->GetDisplayNameAt(1);
+ const gfx::Rect& primary_bounds = primary_display_.bounds();
+
+ gfx::Display* secondary_display = GetSecondaryDisplay();
const gfx::Rect& secondary_bounds = secondary_display->bounds();
gfx::Point new_secondary_origin = primary_bounds.origin();
- const DisplayLayout* layout = &default_display_layout_;
- std::map<std::string, DisplayLayout>::const_iterator iter =
- secondary_layouts_.find(secondary_name);
- if (iter != secondary_layouts_.end())
- layout = &iter->second;
-
- DisplayLayout::Position position = layout->position;
+ const DisplayLayout& layout = GetLayoutForDisplay(*secondary_display);
+ DisplayLayout::Position position = layout.position;
// Ignore the offset in case the secondary display doesn't share edges with
// the primary display.
- int offset = layout->offset;
+ int offset = layout.offset;
if (position == DisplayLayout::TOP || position == DisplayLayout::BOTTOM) {
offset = std::min(
offset, primary_bounds.width() - kMinimumOverlapForInvalidOffset);
« no previous file with comments | « ash/display/display_controller.h ('k') | ash/display/display_controller_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698