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

Unified Diff: ash/display/display_manager.cc

Issue 15367003: Create a mirror window. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: win fix Created 7 years, 7 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
Index: ash/display/display_manager.cc
diff --git a/ash/display/display_manager.cc b/ash/display/display_manager.cc
index c776e79ef689ec3a02088544b5db9ab0c84effdb..82e6f51edb225411ca5bde53dc7ecb612e333722 100644
--- a/ash/display/display_manager.cc
+++ b/ash/display/display_manager.cc
@@ -11,6 +11,7 @@
#include "ash/ash_switches.h"
#include "ash/display/display_controller.h"
+#include "ash/display/mirror_window_controller.h"
#include "ash/screen_ash.h"
#include "ash/shell.h"
#include "base/auto_reset.h"
@@ -38,6 +39,7 @@
#endif
#if defined(OS_CHROMEOS)
+#include "ash/display/output_configurator_animation.h"
#include "base/chromeos/chromeos_version.h"
#include "chromeos/display/output_configurator.h"
#endif
@@ -117,6 +119,41 @@ gfx::Display& GetInvalidDisplay() {
return *invalid_display;
}
+// Used to either create or close the mirror window
+// after all displays and associated RootWidows are
+// configured in UpdateDisplay.
+class MirrorWindowUpdater {
+ public:
+ virtual ~MirrorWindowUpdater() {}
+};
+
+class MirrorWindowCreater : public MirrorWindowUpdater {
James Cook 2013/05/21 08:07:41 nit: either Creator or Builder
oshima 2013/05/21 14:41:50 Done.
+ public:
+ explicit MirrorWindowCreater(const DisplayInfo& display_info)
+ : display_info_(display_info) {
+ }
+
+ virtual ~MirrorWindowCreater() {
+ Shell::GetInstance()->mirror_window_controller()->
+ UpdateWindow(display_info_);
+ }
+
+ private:
+ const DisplayInfo display_info_;
+ DISALLOW_COPY_AND_ASSIGN(MirrorWindowCreater);
+};
+
+class MirrorWindowCloser : public MirrorWindowUpdater {
+ public:
+ MirrorWindowCloser() {}
+ virtual ~MirrorWindowCloser() {
+ Shell::GetInstance()->mirror_window_controller()->Close();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MirrorWindowCloser);
+};
+
} // namespace
using aura::RootWindow;
@@ -129,10 +166,10 @@ DEFINE_WINDOW_PROPERTY_KEY(int64, kDisplayIdKey,
DisplayManager::DisplayManager()
: first_display_id_(gfx::Display::kInvalidDisplayID),
- mirrored_display_id_(gfx::Display::kInvalidDisplayID),
num_connected_displays_(0),
force_bounds_changed_(false),
- change_display_upon_host_resize_(false) {
+ change_display_upon_host_resize_(false),
+ software_mirroring_enabled_(false) {
#if defined(OS_CHROMEOS)
change_display_upon_host_resize_ = !base::chromeos::IsRunningOnChromeOS();
#endif
@@ -335,7 +372,7 @@ void DisplayManager::OnNativeDisplaysChanged(
bool internal_display_connected = false;
num_connected_displays_ = updated_displays.size();
- mirrored_display_id_ = gfx::Display::kInvalidDisplayID;
+ mirrored_display_ = gfx::Display();
DisplayInfoList new_display_info_list;
for (DisplayInfoList::const_iterator iter = updated_displays.begin();
iter != updated_displays.end();
@@ -346,7 +383,7 @@ void DisplayManager::OnNativeDisplaysChanged(
int y = iter->bounds_in_pixel().y();
if (y_coords.find(y) != y_coords.end()) {
InsertAndUpdateDisplayInfo(*iter);
- mirrored_display_id_ = iter->id();
+ mirrored_display_ = CreateDisplayFromDisplayInfoById(iter->id());
} else {
y_coords.insert(y);
new_display_info_list.push_back(*iter);
@@ -392,8 +429,31 @@ void DisplayManager::UpdateDisplays(
DisplayList new_displays;
bool update_mouse_location = false;
+ scoped_ptr<MirrorWindowUpdater> mirror_window_updater;
+ // TODO(oshima): We may want to use external as the source.
+ int mirrored_display_id = gfx::Display::kInvalidDisplayID;
+ if (software_mirroring_enabled_ && updated_display_info_list.size() == 2)
+ mirrored_display_id = updated_display_info_list[1].id();
+
while (curr_iter != displays_.end() ||
new_info_iter != new_display_info_list.end()) {
+ if (new_info_iter != new_display_info_list.end() &&
+ mirrored_display_id == new_info_iter->id()) {
+ InsertAndUpdateDisplayInfo(*new_info_iter);
+ mirrored_display_ = CreateDisplayFromDisplayInfoById(new_info_iter->id());
+ mirror_window_updater.reset(
+ new MirrorWindowCreater(display_info_[new_info_iter->id()]));
James Cook 2013/05/21 08:07:41 Does this need to choose the higher resolution mon
oshima 2013/05/21 14:41:50 Considering the typical usage, I think this should
+ ++new_info_iter;
+ // Remove existing external dispaly if it is going to be mirrored.
+ if (curr_iter != displays_.end() &&
+ curr_iter->id() == mirrored_display_id) {
+ removed_displays.push_back(*curr_iter);
+ ++curr_iter;
+ }
+ update_mouse_location = true;
+ continue;
+ }
+
if (curr_iter == displays_.end()) {
// more displays in new list.
added_display_indices.push_back(new_displays.size());
@@ -420,16 +480,13 @@ void DisplayManager::UpdateDisplays(
current_display_info.bounds_in_pixel() !=
new_display_info.bounds_in_pixel();
- // TODO(oshima): Rotating square dislay doesn't work as the size
- // won't change. This doesn't cause a problem now as there is no
- // such display. This will be fixed by comparing the rotation as
- // well when the rotation variable is added to gfx::Display.
if (force_bounds_changed_ ||
host_window_bounds_changed ||
(current_display.device_scale_factor() !=
new_display.device_scale_factor()) ||
(current_display_info.size_in_pixel() !=
- new_display.GetSizeInPixel())) {
+ new_display.GetSizeInPixel()) ||
+ (current_display.rotation() != new_display.rotation())) {
// Don't update mouse location if the display size has
// changed due to rotation or zooming.
@@ -458,6 +515,10 @@ void DisplayManager::UpdateDisplays(
}
}
+ // Try to close mirror window unless mirror window is necessary.
+ if (!mirror_window_updater.get())
+ mirror_window_updater.reset(new MirrorWindowCloser);
+
// Do not update |displays_| if there's nothing to be updated. Without this,
// it will not update the display layout, which causes the bug
// http://crbug.com/155948.
@@ -539,7 +600,7 @@ size_t DisplayManager::GetNumDisplays() const {
}
bool DisplayManager::IsMirrored() const {
- return mirrored_display_id_ != gfx::Display::kInvalidDisplayID;
+ return mirrored_display_.id() != gfx::Display::kInvalidDisplayID;
}
const gfx::Display& DisplayManager::GetDisplayNearestWindow(
@@ -600,21 +661,6 @@ std::string DisplayManager::GetDisplayNameForId(int64 id) {
return base::StringPrintf("Display %d", static_cast<int>(id));
}
-void DisplayManager::OnRootWindowResized(const aura::RootWindow* root,
- const gfx::Size& old_size) {
- if (change_display_upon_host_resize_) {
- gfx::Display& display = FindDisplayForRootWindow(root);
- gfx::Size old_display_size_in_pixel = display.GetSizeInPixel();
- display_info_[display.id()].SetBounds(
- gfx::Rect(root->GetHostOrigin(), root->GetHostSize()));
- const gfx::Size& new_root_size = root->bounds().size();
- if (old_size != new_root_size) {
- display.SetSize(display_info_[display.id()].size_in_pixel());
- Shell::GetInstance()->screen()->NotifyBoundsChanged(display);
- }
- }
-}
-
void DisplayManager::SetMirrorMode(bool mirrored) {
if (num_connected_displays() <= 1)
return;
@@ -625,7 +671,19 @@ void DisplayManager::SetMirrorMode(bool mirrored) {
chromeos::STATE_DUAL_MIRROR : chromeos::STATE_DUAL_EXTENDED;
Shell::GetInstance()->output_configurator()->SetDisplayMode(new_state);
} else {
- // TODO(oshima): Compositor based mirroring.
+ SetSoftwareMirroring(mirrored);
+ DisplayInfoList display_info_list;
+ int count = 0;
+ for (std::map<int64, DisplayInfo>::const_iterator iter =
+ display_info_.begin();
+ count < 2; ++iter, ++count) {
+ display_info_list.push_back(GetDisplayInfo(iter->second.id()));
+ }
+ UpdateDisplays(display_info_list);
+ if (Shell::GetInstance()->output_configurator_animation()) {
+ Shell::GetInstance()->output_configurator_animation()->
+ StartFadeInAnimation();
+ }
}
#endif
}
@@ -635,8 +693,8 @@ void DisplayManager::AddRemoveDisplay() {
std::vector<DisplayInfo> new_display_info_list;
new_display_info_list.push_back(
GetDisplayInfo(DisplayController::GetPrimaryDisplay().id()));
- // Add if there is only one display.
- if (displays_.size() == 1) {
+ // Add if there is only one display connected.
+ if (num_connected_displays() == 1) {
// Layout the 2nd display below the primary as with the real device.
aura::RootWindow* primary = Shell::GetPrimaryRootWindow();
gfx::Rect host_bounds =
@@ -662,6 +720,26 @@ void DisplayManager::ToggleDisplayScaleFactor() {
UpdateDisplays(new_display_info_list);
}
+void DisplayManager::OnRootWindowResized(const aura::RootWindow* root,
+ const gfx::Size& old_size) {
+ if (change_display_upon_host_resize_) {
+ gfx::Display& display = FindDisplayForRootWindow(root);
+ gfx::Size old_display_size_in_pixel = display.GetSizeInPixel();
+ display_info_[display.id()].SetBounds(
+ gfx::Rect(root->GetHostOrigin(), root->GetHostSize()));
+ const gfx::Size& new_root_size = root->bounds().size();
+ if (old_size != new_root_size) {
+ display.SetSize(display_info_[display.id()].size_in_pixel());
+ Shell::GetInstance()->screen()->NotifyBoundsChanged(display);
+ }
+ }
+}
+
+void DisplayManager::SetSoftwareMirroring(bool enabled) {
+ software_mirroring_enabled_ = enabled;
+ mirrored_display_ = gfx::Display();
+}
+
int64 DisplayManager::GetDisplayIdForUIScaling() const {
// UI Scaling is effective only on internal display.
int64 display_id = gfx::Display::InternalDisplayId();
@@ -693,6 +771,12 @@ void DisplayManager::Init() {
gfx::Display& DisplayManager::FindDisplayForRootWindow(
const aura::RootWindow* root_window) {
int64 id = root_window->GetProperty(kDisplayIdKey);
+ // RootWindow needs Display to determine it's device scale factor.
+ // TODO(oshima): We don't need full display info for mirror
+ // window. Refactor so that RootWindow doesn't use it.
+ if (mirrored_display_.id() == id)
+ return mirrored_display_;
+
// if id is |kInvaildDisplayID|, it's being deleted.
DCHECK(id != gfx::Display::kInvalidDisplayID);
gfx::Display& display = FindDisplayForId(id);

Powered by Google App Engine
This is Rietveld 408576698