Commit 16bc5f81 authored by oshima's avatar oshima Committed by Commit bot

Close mirroring window only when necessary

always recreating was causing extra XRANR event on X11 system.

Delete WindowTreeHost asynchronously when the change can be made via input event.

BUG=484580,486190
TEST=tested manually. no flicker.

Review URL: https://codereview.chromium.org/1133323002

Cr-Commit-Position: refs/heads/master@{#329761}
parent 2e63dba0
...@@ -805,8 +805,8 @@ void DisplayController::CreateOrUpdateMirroringDisplay( ...@@ -805,8 +805,8 @@ void DisplayController::CreateOrUpdateMirroringDisplay(
} }
} }
void DisplayController::CloseMirroringDisplay() { void DisplayController::CloseMirroringDisplayIfNotNecessary() {
mirror_window_controller_->Close(); mirror_window_controller_->CloseIfNotNecessary();
// If cursor_compositing is enabled for large cursor, the cursor window is // If cursor_compositing is enabled for large cursor, the cursor window is
// always on the desktop display (the visible cursor on the non-desktop // always on the desktop display (the visible cursor on the non-desktop
// display is drawn through compositor mirroring). Therefore, it's unnecessary // display is drawn through compositor mirroring). Therefore, it's unnecessary
......
...@@ -159,7 +159,7 @@ class ASH_EXPORT DisplayController : public gfx::DisplayObserver, ...@@ -159,7 +159,7 @@ class ASH_EXPORT DisplayController : public gfx::DisplayObserver,
// aura::DisplayManager::Delegate overrides: // aura::DisplayManager::Delegate overrides:
void CreateOrUpdateMirroringDisplay( void CreateOrUpdateMirroringDisplay(
const DisplayInfoList& info_list) override; const DisplayInfoList& info_list) override;
void CloseMirroringDisplay() override; void CloseMirroringDisplayIfNotNecessary() override;
void PreDisplayConfigurationChange(bool clear_focus) override; void PreDisplayConfigurationChange(bool clear_focus) override;
void PostDisplayConfigurationChange() override; void PostDisplayConfigurationChange() override;
......
...@@ -673,12 +673,13 @@ void DisplayManager::UpdateDisplays( ...@@ -673,12 +673,13 @@ void DisplayManager::UpdateDisplays(
std::sort(new_display_info_list.begin(), std::sort(new_display_info_list.begin(),
new_display_info_list.end(), new_display_info_list.end(),
DisplayInfoSortFunctor()); DisplayInfoSortFunctor());
CreateSoftwareMirroringDisplayInfo(&new_display_info_list);
// Close the mirroring window if any here to avoid creating two compositor on // Close the mirroring window if any here to avoid creating two compositor on
// one display. // one display.
if (delegate_) if (delegate_)
delegate_->CloseMirroringDisplay(); delegate_->CloseMirroringDisplayIfNotNecessary();
CreateSoftwareMirroringDisplay(&new_display_info_list);
DisplayList new_displays; DisplayList new_displays;
DisplayList removed_displays; DisplayList removed_displays;
...@@ -1081,7 +1082,7 @@ void DisplayManager::UpdateInternalDisplayModeListForTest() { ...@@ -1081,7 +1082,7 @@ void DisplayManager::UpdateInternalDisplayModeListForTest() {
SetInternalDisplayModeList(info); SetInternalDisplayModeList(info);
} }
void DisplayManager::CreateSoftwareMirroringDisplay( void DisplayManager::CreateSoftwareMirroringDisplayInfo(
DisplayInfoList* display_info_list) { DisplayInfoList* display_info_list) {
// Use the internal display or 1st as the mirror source, then scale // Use the internal display or 1st as the mirror source, then scale
// the root window so that it matches the external display's // the root window so that it matches the external display's
......
...@@ -65,8 +65,8 @@ class ASH_EXPORT DisplayManager ...@@ -65,8 +65,8 @@ class ASH_EXPORT DisplayManager
virtual void CreateOrUpdateMirroringDisplay( virtual void CreateOrUpdateMirroringDisplay(
const DisplayInfoList& display_info_list) = 0; const DisplayInfoList& display_info_list) = 0;
// Closes the mirror window if exists. // Closes the mirror window if not necessary.
virtual void CloseMirroringDisplay() = 0; virtual void CloseMirroringDisplayIfNotNecessary() = 0;
// Called before and after the display configuration changes. // Called before and after the display configuration changes.
// When |clear_focus| is true, the implementation should // When |clear_focus| is true, the implementation should
...@@ -343,7 +343,7 @@ private: ...@@ -343,7 +343,7 @@ private:
// Creates software mirroring display related information. The display // Creates software mirroring display related information. The display
// used to mirror the content is removed from the |display_info_list|. // used to mirror the content is removed from the |display_info_list|.
void CreateSoftwareMirroringDisplay(DisplayInfoList* display_info_list); void CreateSoftwareMirroringDisplayInfo(DisplayInfoList* display_info_list);
gfx::Display* FindDisplayForId(int64 id); gfx::Display* FindDisplayForId(int64 id);
......
...@@ -136,12 +136,13 @@ MirrorWindowController::MirroringHostInfo::~MirroringHostInfo() { ...@@ -136,12 +136,13 @@ MirrorWindowController::MirroringHostInfo::~MirroringHostInfo() {
} }
MirrorWindowController::MirrorWindowController() MirrorWindowController::MirrorWindowController()
: screen_position_client_(new MirroringScreenPositionClient(this)) { : multi_display_mode_(DisplayManager::EXTENDED),
screen_position_client_(new MirroringScreenPositionClient(this)) {
} }
MirrorWindowController::~MirrorWindowController() { MirrorWindowController::~MirrorWindowController() {
// Make sure the root window gets deleted before cursor_window_delegate. // Make sure the root window gets deleted before cursor_window_delegate.
Close(); Close(false);
} }
void MirrorWindowController::UpdateWindow( void MirrorWindowController::UpdateWindow(
...@@ -247,7 +248,7 @@ void MirrorWindowController::UpdateWindow( ...@@ -247,7 +248,7 @@ void MirrorWindowController::UpdateWindow(
[iter](const DisplayInfo& info) { [iter](const DisplayInfo& info) {
return info.id() == iter->first; return info.id() == iter->first;
}) == display_info_list.end()) { }) == display_info_list.end()) {
CloseAndDeleteHost(iter->second); CloseAndDeleteHost(iter->second, true);
iter = mirroring_host_info_map_.erase(iter); iter = mirroring_host_info_map_.erase(iter);
} else { } else {
++iter; ++iter;
...@@ -266,10 +267,23 @@ void MirrorWindowController::UpdateWindow() { ...@@ -266,10 +267,23 @@ void MirrorWindowController::UpdateWindow() {
UpdateWindow(display_info_list); UpdateWindow(display_info_list);
} }
void MirrorWindowController::Close() { void MirrorWindowController::CloseIfNotNecessary() {
for (auto& info : mirroring_host_info_map_) { DisplayManager* display_manager = Shell::GetInstance()->display_manager();
CloseAndDeleteHost(info.second);
} DisplayManager::MultiDisplayMode new_mode =
display_manager->IsInUnifiedMode()
? DisplayManager::UNIFIED
: (display_manager->IsInMirrorMode() ? DisplayManager::MIRRORING
: DisplayManager::EXTENDED);
if (multi_display_mode_ != new_mode)
Close(true);
multi_display_mode_ = new_mode;
}
void MirrorWindowController::Close(bool delay_host_deletion) {
for (auto& info : mirroring_host_info_map_)
CloseAndDeleteHost(info.second, delay_host_deletion);
mirroring_host_info_map_.clear(); mirroring_host_info_map_.clear();
if (reflector_) { if (reflector_) {
aura::Env::GetInstance()->context_factory()->RemoveReflector( aura::Env::GetInstance()->context_factory()->RemoveReflector(
...@@ -342,7 +356,8 @@ aura::Window::Windows MirrorWindowController::GetAllRootWindows() const { ...@@ -342,7 +356,8 @@ aura::Window::Windows MirrorWindowController::GetAllRootWindows() const {
return root_windows; return root_windows;
} }
void MirrorWindowController::CloseAndDeleteHost(MirroringHostInfo* host_info) { void MirrorWindowController::CloseAndDeleteHost(MirroringHostInfo* host_info,
bool delay_host_deletion) {
aura::WindowTreeHost* host = host_info->ash_host->AsWindowTreeHost(); aura::WindowTreeHost* host = host_info->ash_host->AsWindowTreeHost();
aura::client::SetScreenPositionClient(host->window(), nullptr); aura::client::SetScreenPositionClient(host->window(), nullptr);
...@@ -357,6 +372,12 @@ void MirrorWindowController::CloseAndDeleteHost(MirroringHostInfo* host_info) { ...@@ -357,6 +372,12 @@ void MirrorWindowController::CloseAndDeleteHost(MirroringHostInfo* host_info) {
host_info->ash_host->PrepareForShutdown(); host_info->ash_host->PrepareForShutdown();
reflector_->RemoveMirroringLayer(host_info->mirror_window->layer()); reflector_->RemoveMirroringLayer(host_info->mirror_window->layer());
// EventProcessor may be accessed after this call if the mirroring window
// was deleted as a result of input event (e.g. shortcut), so don't delete
// now.
if (delay_host_deletion)
base::MessageLoop::current()->DeleteSoon(FROM_HERE, host_info);
else
delete host_info; delete host_info;
} }
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <vector> #include <vector>
#include "ash/ash_export.h" #include "ash/ash_export.h"
#include "ash/display/display_manager.h"
#include "base/compiler_specific.h" #include "base/compiler_specific.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
...@@ -57,8 +58,8 @@ class ASH_EXPORT MirrorWindowController : public aura::WindowTreeHostObserver { ...@@ -57,8 +58,8 @@ class ASH_EXPORT MirrorWindowController : public aura::WindowTreeHostObserver {
// for the mirrored display. // for the mirrored display.
void UpdateWindow(); void UpdateWindow();
// Close the mirror window. // Close the mirror window if they're not necessary any longer.
void Close(); void CloseIfNotNecessary();
// aura::WindowTreeHostObserver overrides: // aura::WindowTreeHostObserver overrides:
void OnHostResized(const aura::WindowTreeHost* host) override; void OnHostResized(const aura::WindowTreeHost* host) override;
...@@ -81,7 +82,13 @@ class ASH_EXPORT MirrorWindowController : public aura::WindowTreeHostObserver { ...@@ -81,7 +82,13 @@ class ASH_EXPORT MirrorWindowController : public aura::WindowTreeHostObserver {
struct MirroringHostInfo; struct MirroringHostInfo;
void CloseAndDeleteHost(MirroringHostInfo* host_info); // Close the mirror window. When |delay_host_deletion| is true, the window
// tree host will be deleted in an another task on UI thread. This is
// necessary to safely delete the WTH that is currently handling input events.
void Close(bool delay_host_deletion);
void CloseAndDeleteHost(MirroringHostInfo* host_info,
bool delay_host_deletion);
// Creates a RootWindowTransformer for current display // Creates a RootWindowTransformer for current display
// configuration. // configuration.
...@@ -90,6 +97,8 @@ class ASH_EXPORT MirrorWindowController : public aura::WindowTreeHostObserver { ...@@ -90,6 +97,8 @@ class ASH_EXPORT MirrorWindowController : public aura::WindowTreeHostObserver {
typedef std::map<int64_t, MirroringHostInfo*> MirroringHostInfoMap; typedef std::map<int64_t, MirroringHostInfo*> MirroringHostInfoMap;
MirroringHostInfoMap mirroring_host_info_map_; MirroringHostInfoMap mirroring_host_info_map_;
DisplayManager::MultiDisplayMode multi_display_mode_;
scoped_ptr<aura::client::ScreenPositionClient> screen_position_client_; scoped_ptr<aura::client::ScreenPositionClient> screen_position_client_;
scoped_ptr<ui::Reflector> reflector_; scoped_ptr<ui::Reflector> reflector_;
......
...@@ -758,7 +758,6 @@ Shell::~Shell() { ...@@ -758,7 +758,6 @@ Shell::~Shell() {
// Destroy all child windows including widgets. // Destroy all child windows including widgets.
display_controller_->CloseChildWindows(); display_controller_->CloseChildWindows();
display_controller_->CloseMirroringDisplay();
// Chrome implementation of shelf delegate depends on FocusClient, // Chrome implementation of shelf delegate depends on FocusClient,
// so must be deleted before |focus_client_|. // so must be deleted before |focus_client_|.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment