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); |