blob: 7e2007d97bd9222e8a2fbd8e9ca4bb2c8ea88a66 [file] [log] [blame]
// Copyright 2021 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 "remoting/host/desktop_display_info_monitor.h"
#include <utility>
#include "base/bind.h"
#include "base/task/sequenced_task_runner.h"
#include "base/time/time.h"
#include "remoting/base/logging.h"
#include "remoting/host/client_session_control.h"
namespace remoting {
namespace {
// Polling interval for querying the OS for changes to the multi-monitor
// configuration. Before this class was written, the DesktopCapturerProxy would
// poll after each captured frame, which could occur up to 30x per second. The
// value chosen here is slower than this (to reduce the load on the OS), but
// still fast enough to be responsive to any changes.
constexpr base::TimeDelta kPollingInterval = base::Milliseconds(100);
} // namespace
DesktopDisplayInfoMonitor::DesktopDisplayInfoMonitor(
scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
base::WeakPtr<ClientSessionControl> client_session_control)
: ui_task_runner_(ui_task_runner),
client_session_control_(client_session_control),
desktop_display_info_loader_(DesktopDisplayInfoLoader::Create()) {
// The loader must be initialized and used on the UI thread (though it can be
// created on any thread).
ui_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&DesktopDisplayInfoLoader::Init,
base::Unretained(desktop_display_info_loader_.get())));
}
DesktopDisplayInfoMonitor::~DesktopDisplayInfoMonitor() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
ui_task_runner_->DeleteSoon(FROM_HERE,
desktop_display_info_loader_.release());
}
void DesktopDisplayInfoMonitor::Start() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
timer_.Start(FROM_HERE, kPollingInterval, this,
&DesktopDisplayInfoMonitor::QueryDisplayInfo);
}
void DesktopDisplayInfoMonitor::QueryDisplayInfo() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (client_session_control_) {
ui_task_runner_->PostTaskAndReplyWithResult(
FROM_HERE,
base::BindOnce(&DesktopDisplayInfoLoader::GetCurrentDisplayInfo,
base::Unretained(desktop_display_info_loader_.get())),
base::BindOnce(&DesktopDisplayInfoMonitor::OnDisplayInfoLoaded,
weak_factory_.GetWeakPtr()));
}
}
void DesktopDisplayInfoMonitor::OnDisplayInfoLoaded(DesktopDisplayInfo info) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!client_session_control_ || desktop_display_info_ == info) {
return;
}
desktop_display_info_ = std::move(info);
auto layout = std::make_unique<protocol::VideoLayout>();
HOST_LOG << "DDIM::OnDisplayInfoLoaded";
for (const auto& display : desktop_display_info_.displays()) {
protocol::VideoTrackLayout* track = layout->add_video_track();
track->set_position_x(display.x);
track->set_position_y(display.y);
track->set_width(display.width);
track->set_height(display.height);
track->set_x_dpi(display.dpi);
track->set_y_dpi(display.dpi);
track->set_screen_id(display.id);
HOST_LOG << " Display: " << display.x << "," << display.y << " "
<< display.width << "x" << display.height << " @ " << display.dpi
<< ", id=" << display.id;
}
client_session_control_->OnDesktopDisplayChanged(std::move(layout));
}
} // namespace remoting