desktop_display_info_monitor.cc 3.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // Copyright 2021 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "remoting/host/desktop_display_info_monitor.h"
  5. #include <utility>
  6. #include "base/bind.h"
  7. #include "base/task/sequenced_task_runner.h"
  8. #include "base/time/time.h"
  9. #include "remoting/base/logging.h"
  10. #include "remoting/proto/control.pb.h"
  11. namespace remoting {
  12. namespace {
  13. // Polling interval for querying the OS for changes to the multi-monitor
  14. // configuration. Before this class was written, the DesktopCapturerProxy would
  15. // poll after each captured frame, which could occur up to 30x per second. The
  16. // value chosen here is slower than this (to reduce the load on the OS), but
  17. // still fast enough to be responsive to any changes.
  18. constexpr base::TimeDelta kPollingInterval = base::Milliseconds(100);
  19. } // namespace
  20. DesktopDisplayInfoMonitor::DesktopDisplayInfoMonitor(
  21. scoped_refptr<base::SequencedTaskRunner> ui_task_runner)
  22. : ui_task_runner_(ui_task_runner),
  23. desktop_display_info_loader_(DesktopDisplayInfoLoader::Create()) {
  24. // The loader must be initialized and used on the UI thread (though it can be
  25. // created on any thread).
  26. ui_task_runner_->PostTask(
  27. FROM_HERE,
  28. base::BindOnce(&DesktopDisplayInfoLoader::Init,
  29. base::Unretained(desktop_display_info_loader_.get())));
  30. }
  31. DesktopDisplayInfoMonitor::~DesktopDisplayInfoMonitor() {
  32. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  33. ui_task_runner_->DeleteSoon(FROM_HERE,
  34. desktop_display_info_loader_.release());
  35. }
  36. void DesktopDisplayInfoMonitor::Start() {
  37. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  38. timer_running_ = true;
  39. timer_.Start(FROM_HERE, kPollingInterval, this,
  40. &DesktopDisplayInfoMonitor::QueryDisplayInfoImpl);
  41. }
  42. void DesktopDisplayInfoMonitor::QueryDisplayInfo() {
  43. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  44. if (!timer_running_) {
  45. QueryDisplayInfoImpl();
  46. }
  47. }
  48. void DesktopDisplayInfoMonitor::AddCallback(
  49. DesktopDisplayInfoMonitor::Callback callback) {
  50. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  51. // Adding callbacks is not supported after displays have already been
  52. // loaded.
  53. DCHECK_EQ(desktop_display_info_.NumDisplays(), 0);
  54. callback_list_.AddUnsafe(std::move(callback));
  55. }
  56. void DesktopDisplayInfoMonitor::QueryDisplayInfoImpl() {
  57. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  58. if (!callback_list_.empty()) {
  59. ui_task_runner_->PostTaskAndReplyWithResult(
  60. FROM_HERE,
  61. base::BindOnce(&DesktopDisplayInfoLoader::GetCurrentDisplayInfo,
  62. base::Unretained(desktop_display_info_loader_.get())),
  63. base::BindOnce(&DesktopDisplayInfoMonitor::OnDisplayInfoLoaded,
  64. weak_factory_.GetWeakPtr()));
  65. }
  66. }
  67. void DesktopDisplayInfoMonitor::OnDisplayInfoLoaded(DesktopDisplayInfo info) {
  68. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  69. if (callback_list_.empty() || desktop_display_info_ == info) {
  70. return;
  71. }
  72. desktop_display_info_ = std::move(info);
  73. callback_list_.Notify(desktop_display_info_);
  74. }
  75. } // namespace remoting