wayland_display_output.cc 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. // Copyright 2018 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 "components/exo/wayland/wayland_display_output.h"
  5. #include <cstring>
  6. #include <wayland-server-core.h>
  7. #include <wayland-server-protocol-core.h>
  8. #include "base/containers/cxx20_erase.h"
  9. #include "base/logging.h"
  10. #include "base/task/thread_pool.h"
  11. #include "components/exo/surface.h"
  12. #include "components/exo/wayland/server_util.h"
  13. namespace exo {
  14. namespace wayland {
  15. namespace {
  16. base::TimeDelta kDeleteTaskDelay = base::Seconds(3);
  17. void DoDelete(WaylandDisplayOutput* output, int retry_count) {
  18. if (retry_count > 0 && output->output_counts() > 0) {
  19. // Try a few times to give a client chance to release it.
  20. base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
  21. FROM_HERE, base::BindOnce(&DoDelete, output, retry_count - 1),
  22. kDeleteTaskDelay);
  23. } else {
  24. delete output;
  25. }
  26. }
  27. } // namespace
  28. WaylandDisplayOutput::WaylandDisplayOutput(int64_t id) : id_(id) {}
  29. WaylandDisplayOutput::~WaylandDisplayOutput() {
  30. // Empty the output_ids_ so that Unregister will be no op.
  31. auto ids = std::move(output_ids_);
  32. for (auto pair : ids)
  33. wl_resource_destroy(pair.second);
  34. if (global_)
  35. wl_global_destroy(global_);
  36. }
  37. void WaylandDisplayOutput::OnDisplayRemoved() {
  38. if (global_)
  39. wl_global_remove(global_);
  40. base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
  41. FROM_HERE, base::BindOnce(&DoDelete, this, /*retry_count=*/3),
  42. kDeleteTaskDelay);
  43. }
  44. int64_t WaylandDisplayOutput::id() const {
  45. return id_;
  46. }
  47. void WaylandDisplayOutput::set_global(wl_global* global) {
  48. global_ = global;
  49. }
  50. void WaylandDisplayOutput::UnregisterOutput(wl_resource* output_resource) {
  51. base::EraseIf(output_ids_, [output_resource](auto& pair) {
  52. return pair.second == output_resource;
  53. });
  54. }
  55. void WaylandDisplayOutput::RegisterOutput(wl_resource* output_resource) {
  56. auto* client = wl_resource_get_client(output_resource);
  57. output_ids_.insert(std::make_pair(client, output_resource));
  58. // Notify All wl surfaces that a new output was added.
  59. wl_client_for_each_resource(
  60. client,
  61. [](wl_resource* resource, void*) {
  62. constexpr char kWlSurfaceClass[] = "wl_surface";
  63. const char* class_name = wl_resource_get_class(resource);
  64. if (std::strcmp(kWlSurfaceClass, class_name) == 0) {
  65. auto* surface = GetUserDataAs<Surface>(resource);
  66. if (surface)
  67. surface->OnNewOutputAdded();
  68. }
  69. return WL_ITERATOR_CONTINUE;
  70. },
  71. nullptr);
  72. }
  73. wl_resource* WaylandDisplayOutput::GetOutputResourceForClient(
  74. wl_client* client) {
  75. auto iter = output_ids_.find(client);
  76. if (iter == output_ids_.end())
  77. return nullptr;
  78. return iter->second;
  79. }
  80. } // namespace wayland
  81. } // namespace exo