x11_display_manager.cc 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. // Copyright 2019 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 "ui/base/x/x11_display_manager.h"
  5. #include <utility>
  6. #include "base/bind.h"
  7. #include "base/threading/thread_task_runner_handle.h"
  8. #include "ui/base/x/x11_display_util.h"
  9. #include "ui/gfx/x/future.h"
  10. #include "ui/gfx/x/randr.h"
  11. #include "ui/gfx/x/x11_atom_cache.h"
  12. #include "ui/gfx/x/xproto.h"
  13. namespace ui {
  14. namespace {
  15. constexpr int kMinXrandrVersion = 103; // Need at least xrandr version 1.3
  16. } // namespace
  17. XDisplayManager::XDisplayManager(Delegate* delegate)
  18. : delegate_(delegate),
  19. connection_(x11::Connection::Get()),
  20. x_root_window_(connection_->default_screen().root),
  21. xrandr_version_(GetXrandrVersion()),
  22. workspace_handler_(this) {}
  23. XDisplayManager::~XDisplayManager() = default;
  24. void XDisplayManager::Init() {
  25. if (IsXrandrAvailable()) {
  26. auto& randr = connection_->randr();
  27. randr.SelectInput(
  28. {x_root_window_, x11::RandR::NotifyMask::ScreenChange |
  29. x11::RandR::NotifyMask::OutputChange |
  30. x11::RandR::NotifyMask::CrtcChange});
  31. }
  32. FetchDisplayList();
  33. }
  34. // Need at least xrandr version 1.3
  35. bool XDisplayManager::IsXrandrAvailable() const {
  36. return xrandr_version_ >= kMinXrandrVersion;
  37. }
  38. display::Display XDisplayManager::GetPrimaryDisplay() const {
  39. DCHECK(!displays_.empty());
  40. return displays_[primary_display_index_];
  41. }
  42. void XDisplayManager::AddObserver(display::DisplayObserver* observer) {
  43. change_notifier_.AddObserver(observer);
  44. }
  45. void XDisplayManager::RemoveObserver(display::DisplayObserver* observer) {
  46. change_notifier_.RemoveObserver(observer);
  47. }
  48. void XDisplayManager::OnEvent(const x11::Event& xev) {
  49. auto* prop = xev.As<x11::PropertyNotifyEvent>();
  50. if (xev.As<x11::RandR::NotifyEvent>() ||
  51. (prop && prop->atom == x11::GetAtom("_NET_WORKAREA"))) {
  52. DispatchDelayedDisplayListUpdate();
  53. }
  54. }
  55. void XDisplayManager::SetDisplayList(std::vector<display::Display> displays) {
  56. displays_ = std::move(displays);
  57. delegate_->OnXDisplayListUpdated();
  58. }
  59. // Talks to xrandr to get the information of the outputs for a screen and
  60. // updates display::Display list. The minimum required version of xrandr is
  61. // 1.3.
  62. void XDisplayManager::FetchDisplayList() {
  63. std::vector<display::Display> displays;
  64. float scale = delegate_->GetXDisplayScaleFactor();
  65. if (IsXrandrAvailable()) {
  66. displays = BuildDisplaysFromXRandRInfo(xrandr_version_, scale,
  67. &primary_display_index_);
  68. } else {
  69. displays = GetFallbackDisplayList(scale);
  70. }
  71. SetDisplayList(std::move(displays));
  72. }
  73. void XDisplayManager::OnCurrentWorkspaceChanged(
  74. const std::string& new_workspace) {
  75. change_notifier_.NotifyCurrentWorkspaceChanged(new_workspace);
  76. }
  77. void XDisplayManager::UpdateDisplayList() {
  78. std::vector<display::Display> old_displays = displays_;
  79. FetchDisplayList();
  80. change_notifier_.NotifyDisplaysChanged(old_displays, displays_);
  81. }
  82. void XDisplayManager::DispatchDelayedDisplayListUpdate() {
  83. update_task_.Reset(base::BindOnce(&XDisplayManager::UpdateDisplayList,
  84. base::Unretained(this)));
  85. base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
  86. update_task_.callback());
  87. }
  88. gfx::Point XDisplayManager::GetCursorLocation() const {
  89. if (auto response = connection_->QueryPointer({x_root_window_}).Sync())
  90. return {response->root_x, response->root_y};
  91. return {};
  92. }
  93. std::string XDisplayManager::GetCurrentWorkspace() {
  94. return workspace_handler_.GetCurrentWorkspace();
  95. }
  96. } // namespace ui