blob: 952f7648806482a90444a87bcfab15c567c29b41 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/display/display_synchronizer.h"
#include "ash/display/mirror_window_controller.h"
#include "ash/host/ash_window_tree_host.h"
#include "ash/shell.h"
#include "services/ui/public/interfaces/window_manager_constants.mojom.h"
#include "ui/aura/mus/window_manager_delegate.h"
#include "ui/aura/mus/window_tree_host_mus.h"
#include "ui/base/ui_base_switches_util.h"
#include "ui/display/manager/display_manager.h"
#include "ui/display/manager/managed_display_info.h"
namespace ash {
namespace {
aura::WindowTreeHostMus* ToWindowTreeHostMus(AshWindowTreeHost* ash_host) {
return static_cast<aura::WindowTreeHostMus*>(ash_host->AsWindowTreeHost());
}
// Get the metrics for the display with the given |id|.
ui::mojom::WmViewportMetricsPtr GetMetricsForDisplay(int64_t id) {
ui::mojom::WmViewportMetricsPtr metrics = ui::mojom::WmViewportMetrics::New();
const display::ManagedDisplayInfo& display_info =
Shell::Get()->display_manager()->GetDisplayInfo(id);
metrics->bounds_in_pixels = display_info.bounds_in_native();
metrics->device_scale_factor = display_info.device_scale_factor();
metrics->ui_scale_factor = display_info.configured_ui_scale();
return metrics;
}
} // namespace
DisplaySynchronizer::DisplaySynchronizer(
aura::WindowManagerClient* window_manager_client)
: window_manager_client_(window_manager_client) {
Shell::Get()->window_tree_host_manager()->AddObserver(this);
Shell::Get()->display_manager()->AddObserver(this);
SendDisplayConfigurationToServer();
}
DisplaySynchronizer::~DisplaySynchronizer() {
Shell::Get()->display_manager()->RemoveObserver(this);
Shell::Get()->window_tree_host_manager()->RemoveObserver(this);
}
void DisplaySynchronizer::SendDisplayConfigurationToServer() {
if (processing_display_changes_)
return;
display::DisplayManager* display_manager = Shell::Get()->display_manager();
const size_t display_count = display_manager->GetNumDisplays();
if (display_count == 0)
return;
std::vector<display::Display> displays;
std::vector<ui::mojom::WmViewportMetricsPtr> metrics;
for (size_t i = 0; i < display_count; ++i) {
displays.push_back(display_manager->GetDisplayAt(i));
metrics.push_back(GetMetricsForDisplay(displays[i].id()));
}
std::vector<display::Display> mirrors;
MirrorWindowController* mirror_window_controller =
Shell::Get()->window_tree_host_manager()->mirror_window_controller();
for (const auto& mirror :
display_manager->software_mirroring_display_list()) {
if (::switches::IsMusHostingViz()) {
// If mus is hosting viz, the window server handle mirrors internally.
mirrors.push_back(mirror);
metrics.push_back(GetMetricsForDisplay(mirror.id()));
} else if (mirror_window_controller->GetAshWindowTreeHostForDisplayId(
mirror.id())) {
// Otherwise, if MirrorWindowController constructed a window tree host
// the window server should construct a normal ws::Display for the mirror.
displays.push_back(mirror);
metrics.push_back(GetMetricsForDisplay(mirror.id()));
}
}
window_manager_client_->SetDisplayConfiguration(
displays, std::move(metrics),
WindowTreeHostManager::GetPrimaryDisplayId(), mirrors);
sent_initial_config_ = true;
}
void DisplaySynchronizer::OnDisplaysInitialized() {
SendDisplayConfigurationToServer();
}
void DisplaySynchronizer::OnDisplayConfigurationChanged() {
SendDisplayConfigurationToServer();
}
void DisplaySynchronizer::OnWindowTreeHostReusedForDisplay(
AshWindowTreeHost* window_tree_host,
const display::Display& display) {
aura::WindowTreeHostMus* window_tree_host_mus =
ToWindowTreeHostMus(window_tree_host);
if (window_tree_host_mus->display_id() == display.id())
return;
const display::ManagedDisplayInfo& display_info =
Shell::Get()->display_manager()->GetDisplayInfo(display.id());
ui::mojom::WmViewportMetricsPtr viewport_metrics =
ui::mojom::WmViewportMetrics::New();
viewport_metrics->bounds_in_pixels = display_info.bounds_in_native();
viewport_metrics->device_scale_factor = display.device_scale_factor();
viewport_metrics->ui_scale_factor = display_info.configured_ui_scale();
window_manager_client_->AddDisplayReusingWindowTreeHost(
ToWindowTreeHostMus(window_tree_host), display,
std::move(viewport_metrics));
}
void DisplaySynchronizer::OnWindowTreeHostsSwappedDisplays(
AshWindowTreeHost* host1,
AshWindowTreeHost* host2) {
DCHECK(host1);
DCHECK(host2);
window_manager_client_->SwapDisplayRoots(ToWindowTreeHostMus(host1),
ToWindowTreeHostMus(host2));
}
void DisplaySynchronizer::OnWillProcessDisplayChanges() {
DCHECK(!processing_display_changes_);
processing_display_changes_ = true;
}
void DisplaySynchronizer::OnDidProcessDisplayChanges() {
DCHECK(processing_display_changes_);
processing_display_changes_ = false;
SendDisplayConfigurationToServer();
}
void DisplaySynchronizer::OnDisplayMetricsChanged(
const display::Display& display,
uint32_t changed_metrics) {
// Changing only the work area doesn't trigger
// OnDisplayConfigurationChanged().
// Wait for the initial config before sending anything as initial display
// creation may trigger numerous calls to OnDisplayConfigurationChanged().
if (sent_initial_config_ && changed_metrics == DISPLAY_METRIC_WORK_AREA)
SendDisplayConfigurationToServer();
}
} // namespace ash