wp_viewporter.cc 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  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 "components/exo/wayland/wp_viewporter.h"
  5. #include <viewporter-server-protocol.h>
  6. #include <memory>
  7. #include "components/exo/surface_observer.h"
  8. #include "components/exo/wayland/server_util.h"
  9. #include "ui/gfx/geometry/size_f.h"
  10. namespace exo {
  11. namespace wayland {
  12. namespace {
  13. // A property key containing a boolean set to true if a viewport is associated
  14. // with with surface object.
  15. DEFINE_UI_CLASS_PROPERTY_KEY(bool, kSurfaceHasViewportKey, false)
  16. ////////////////////////////////////////////////////////////////////////////////
  17. // wp_viewport_interface:
  18. // Implements the viewport interface to a Surface. The "viewport"-state is set
  19. // to null upon destruction. A window property will be set during the lifetime
  20. // of this class to prevent multiple instances from being created for the same
  21. // Surface.
  22. class Viewport : public SurfaceObserver {
  23. public:
  24. explicit Viewport(Surface* surface) : surface_(surface) {
  25. surface_->AddSurfaceObserver(this);
  26. surface_->SetProperty(kSurfaceHasViewportKey, true);
  27. }
  28. Viewport(const Viewport&) = delete;
  29. Viewport& operator=(const Viewport&) = delete;
  30. ~Viewport() override {
  31. if (surface_) {
  32. surface_->RemoveSurfaceObserver(this);
  33. surface_->SetCrop(gfx::RectF());
  34. surface_->SetViewport(gfx::SizeF());
  35. surface_->SetProperty(kSurfaceHasViewportKey, false);
  36. }
  37. }
  38. void SetSource(const gfx::RectF& rect) {
  39. if (surface_)
  40. surface_->SetCrop(rect);
  41. }
  42. void SetDestination(const gfx::Size& size) {
  43. if (surface_)
  44. surface_->SetViewport(gfx::SizeF(size));
  45. }
  46. // Overridden from SurfaceObserver:
  47. void OnSurfaceDestroying(Surface* surface) override {
  48. surface->RemoveSurfaceObserver(this);
  49. surface_ = nullptr;
  50. }
  51. private:
  52. Surface* surface_;
  53. };
  54. void viewport_destroy(wl_client* client, wl_resource* resource) {
  55. wl_resource_destroy(resource);
  56. }
  57. void viewport_set_source(wl_client* client,
  58. wl_resource* resource,
  59. wl_fixed_t x,
  60. wl_fixed_t y,
  61. wl_fixed_t width,
  62. wl_fixed_t height) {
  63. if (x == wl_fixed_from_int(-1) && y == wl_fixed_from_int(-1) &&
  64. width == wl_fixed_from_int(-1) && height == wl_fixed_from_int(-1)) {
  65. GetUserDataAs<Viewport>(resource)->SetSource(gfx::RectF());
  66. return;
  67. }
  68. if (x < 0 || y < 0 || width <= 0 || height <= 0) {
  69. wl_resource_post_error(resource, WP_VIEWPORT_ERROR_BAD_VALUE,
  70. "source rectangle must be non-empty (%dx%d) and"
  71. "have positive origin (%d,%d)",
  72. width, height, x, y);
  73. return;
  74. }
  75. GetUserDataAs<Viewport>(resource)->SetSource(
  76. gfx::RectF(wl_fixed_to_double(x), wl_fixed_to_double(y),
  77. wl_fixed_to_double(width), wl_fixed_to_double(height)));
  78. }
  79. void viewport_set_destination(wl_client* client,
  80. wl_resource* resource,
  81. int32_t width,
  82. int32_t height) {
  83. if (width == -1 && height == -1) {
  84. GetUserDataAs<Viewport>(resource)->SetDestination(gfx::Size());
  85. return;
  86. }
  87. if (width <= 0 || height <= 0) {
  88. wl_resource_post_error(resource, WP_VIEWPORT_ERROR_BAD_VALUE,
  89. "destination size must be positive (%dx%d)", width,
  90. height);
  91. return;
  92. }
  93. GetUserDataAs<Viewport>(resource)->SetDestination(gfx::Size(width, height));
  94. }
  95. const struct wp_viewport_interface viewport_implementation = {
  96. viewport_destroy, viewport_set_source, viewport_set_destination};
  97. ////////////////////////////////////////////////////////////////////////////////
  98. // wp_viewporter_interface:
  99. void viewporter_destroy(wl_client* client, wl_resource* resource) {
  100. wl_resource_destroy(resource);
  101. }
  102. void viewporter_get_viewport(wl_client* client,
  103. wl_resource* resource,
  104. uint32_t id,
  105. wl_resource* surface_resource) {
  106. Surface* surface = GetUserDataAs<Surface>(surface_resource);
  107. if (surface->GetProperty(kSurfaceHasViewportKey)) {
  108. wl_resource_post_error(resource, WP_VIEWPORTER_ERROR_VIEWPORT_EXISTS,
  109. "a viewport for that surface already exists");
  110. return;
  111. }
  112. wl_resource* viewport_resource = wl_resource_create(
  113. client, &wp_viewport_interface, wl_resource_get_version(resource), id);
  114. SetImplementation(viewport_resource, &viewport_implementation,
  115. std::make_unique<Viewport>(surface));
  116. }
  117. const struct wp_viewporter_interface viewporter_implementation = {
  118. viewporter_destroy, viewporter_get_viewport};
  119. } // namespace
  120. void bind_viewporter(wl_client* client,
  121. void* data,
  122. uint32_t version,
  123. uint32_t id) {
  124. wl_resource* resource =
  125. wl_resource_create(client, &wp_viewporter_interface, 1, id);
  126. wl_resource_set_implementation(resource, &viewporter_implementation, data,
  127. nullptr);
  128. }
  129. } // namespace wayland
  130. } // namespace exo