surface_augmenter.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  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 "components/exo/wayland/surface_augmenter.h"
  5. #include <surface-augmenter-server-protocol.h>
  6. #include <memory>
  7. #include "components/exo/buffer.h"
  8. #include "components/exo/sub_surface.h"
  9. #include "components/exo/sub_surface_observer.h"
  10. #include "components/exo/surface.h"
  11. #include "components/exo/surface_observer.h"
  12. #include "components/exo/wayland/server_util.h"
  13. #include "ui/gfx/geometry/rounded_corners_f.h"
  14. #include "ui/gfx/geometry/rrect_f.h"
  15. #include "ui/gfx/geometry/size.h"
  16. namespace exo {
  17. namespace wayland {
  18. namespace {
  19. // A property key containing a boolean set to true if a surface augmenter is
  20. // associated with with surface object.
  21. DEFINE_UI_CLASS_PROPERTY_KEY(bool, kSurfaceHasAugmentedSurfaceKey, false)
  22. DEFINE_UI_CLASS_PROPERTY_KEY(bool, kSubSurfaceHasAugmentedSubSurfaceKey, false)
  23. ////////////////////////////////////////////////////////////////////////////////
  24. // augmented_surface_interface:
  25. // Implements the augmenter interface to a Surface. The "augmented"-state is set
  26. // to null upon destruction. A window property will be set during the lifetime
  27. // of this class to prevent multiple instances from being created for the same
  28. // Surface.
  29. class AugmentedSurface : public SurfaceObserver {
  30. public:
  31. explicit AugmentedSurface(Surface* surface) : surface_(surface) {
  32. surface_->AddSurfaceObserver(this);
  33. surface_->SetProperty(kSurfaceHasAugmentedSurfaceKey, true);
  34. }
  35. AugmentedSurface(const AugmentedSurface&) = delete;
  36. AugmentedSurface& operator=(const AugmentedSurface&) = delete;
  37. ~AugmentedSurface() override {
  38. if (surface_) {
  39. surface_->RemoveSurfaceObserver(this);
  40. surface_->SetProperty(kSurfaceHasAugmentedSurfaceKey, false);
  41. }
  42. }
  43. void SetCorners(int32_t x,
  44. int32_t y,
  45. int32_t width,
  46. int32_t height,
  47. double top_left,
  48. double top_right,
  49. double bottom_right,
  50. double bottom_left) {
  51. surface_->SetRoundedCorners(gfx::RRectF(
  52. gfx::RectF(x, y, width, height),
  53. gfx::RoundedCornersF(top_left, top_right, bottom_right, bottom_left)));
  54. }
  55. void SetDestination(float width, float height) {
  56. surface_->SetViewport(gfx::SizeF(width, height));
  57. }
  58. void SetBackgroundColor(absl::optional<SkColor4f> background_color) {
  59. surface_->SetBackgroundColor(background_color);
  60. }
  61. // SurfaceObserver:
  62. void OnSurfaceDestroying(Surface* surface) override {
  63. surface->RemoveSurfaceObserver(this);
  64. surface_ = nullptr;
  65. }
  66. private:
  67. Surface* surface_;
  68. };
  69. void augmented_surface_destroy(wl_client* client, wl_resource* resource) {
  70. wl_resource_destroy(resource);
  71. }
  72. void augmented_surface_set_corners_DEPRECATED(wl_client* client,
  73. wl_resource* resource,
  74. wl_fixed_t top_left,
  75. wl_fixed_t top_right,
  76. wl_fixed_t bottom_right,
  77. wl_fixed_t bottom_left) {
  78. LOG(WARNING) << "Deprecated. The server doesn't support this request.";
  79. }
  80. void augmented_surface_set_destination_size(wl_client* client,
  81. wl_resource* resource,
  82. wl_fixed_t width,
  83. wl_fixed_t height) {
  84. if (width < 0 || height < 0) {
  85. wl_resource_post_error(resource, AUGMENTED_SURFACE_ERROR_BAD_VALUE,
  86. "Dimension can't be negative (%d, %d)", width,
  87. height);
  88. return;
  89. }
  90. GetUserDataAs<AugmentedSurface>(resource)->SetDestination(
  91. wl_fixed_to_double(width), wl_fixed_to_double(height));
  92. }
  93. void augmented_surface_set_rounded_corners_bounds(wl_client* client,
  94. wl_resource* resource,
  95. int32_t x,
  96. int32_t y,
  97. int32_t width,
  98. int32_t height,
  99. wl_fixed_t top_left,
  100. wl_fixed_t top_right,
  101. wl_fixed_t bottom_right,
  102. wl_fixed_t bottom_left) {
  103. if (width < 0 || height < 0 || top_left < 0 || bottom_left < 0 ||
  104. bottom_right < 0 || top_right < 0) {
  105. wl_resource_post_error(resource, AUGMENTED_SURFACE_ERROR_BAD_VALUE,
  106. "The size and corners must have positive values "
  107. "(%d, %d, %d, %d, %d, %d)",
  108. width, height, top_left, top_right, bottom_right,
  109. bottom_left);
  110. return;
  111. }
  112. GetUserDataAs<AugmentedSurface>(resource)->SetCorners(
  113. x, y, width, height, wl_fixed_to_double(top_left),
  114. wl_fixed_to_double(top_right), wl_fixed_to_double(bottom_right),
  115. wl_fixed_to_double(bottom_left));
  116. }
  117. void augmented_surface_set_background_color(wl_client* client,
  118. wl_resource* resource,
  119. wl_array* color_data) {
  120. absl::optional<SkColor4f> sk_color;
  121. // Empty data means no color.
  122. if (color_data->size) {
  123. float* data = reinterpret_cast<float*>(color_data->data);
  124. sk_color = {data[0], data[1], data[2], data[3]};
  125. }
  126. GetUserDataAs<AugmentedSurface>(resource)->SetBackgroundColor(sk_color);
  127. }
  128. const struct augmented_surface_interface augmented_implementation = {
  129. augmented_surface_destroy, augmented_surface_set_corners_DEPRECATED,
  130. augmented_surface_set_destination_size,
  131. augmented_surface_set_rounded_corners_bounds,
  132. augmented_surface_set_background_color};
  133. ////////////////////////////////////////////////////////////////////////////////
  134. // augmented_sub_surface_interface:
  135. // Implements the augmenter interface to a Surface. The "augmented"-state is set
  136. // to null upon destruction. A window property will be set during the lifetime
  137. // of this class to prevent multiple instances from being created for the same
  138. // Surface.
  139. class AugmentedSubSurface : public SubSurfaceObserver {
  140. public:
  141. explicit AugmentedSubSurface(SubSurface* sub_surface)
  142. : sub_surface_(sub_surface) {
  143. sub_surface_->AddSubSurfaceObserver(this);
  144. sub_surface_->SetProperty(kSubSurfaceHasAugmentedSubSurfaceKey, true);
  145. }
  146. AugmentedSubSurface(const AugmentedSubSurface&) = delete;
  147. AugmentedSubSurface& operator=(const AugmentedSubSurface&) = delete;
  148. ~AugmentedSubSurface() override {
  149. if (sub_surface_) {
  150. sub_surface_->SetProperty(kSubSurfaceHasAugmentedSubSurfaceKey, false);
  151. sub_surface_->RemoveSubSurfaceObserver(this);
  152. }
  153. }
  154. void SetPosition(float x, float y) {
  155. sub_surface_->SetPosition(gfx::PointF(x, y));
  156. }
  157. // SurfaceObserver:
  158. void OnSubSurfaceDestroying(SubSurface* sub_surface) override {
  159. sub_surface->RemoveSubSurfaceObserver(this);
  160. sub_surface_ = nullptr;
  161. }
  162. private:
  163. SubSurface* sub_surface_;
  164. };
  165. void augmented_sub_surface_destroy(wl_client* client, wl_resource* resource) {
  166. wl_resource_destroy(resource);
  167. }
  168. void augmented_sub_surface_set_position(wl_client* client,
  169. wl_resource* resource,
  170. wl_fixed_t x,
  171. wl_fixed_t y) {
  172. GetUserDataAs<AugmentedSubSurface>(resource)->SetPosition(
  173. wl_fixed_to_double(x), wl_fixed_to_double(y));
  174. }
  175. const struct augmented_sub_surface_interface
  176. augmented_sub_surface_implementation = {augmented_sub_surface_destroy,
  177. augmented_sub_surface_set_position};
  178. ////////////////////////////////////////////////////////////////////////////////
  179. // wl_buffer_interface:
  180. void buffer_destroy(wl_client* client, wl_resource* resource) {
  181. wl_resource_destroy(resource);
  182. }
  183. const struct wl_buffer_interface buffer_implementation = {buffer_destroy};
  184. ////////////////////////////////////////////////////////////////////////////////
  185. // surface_augmenter_interface:
  186. void augmenter_destroy(wl_client* client, wl_resource* resource) {
  187. wl_resource_destroy(resource);
  188. }
  189. void HandleBufferReleaseCallback(wl_resource* resource) {
  190. wl_buffer_send_release(resource);
  191. wl_client_flush(wl_resource_get_client(resource));
  192. }
  193. void augmenter_create_solid_color_buffer(wl_client* client,
  194. wl_resource* resource,
  195. uint32_t id,
  196. wl_array* color_data,
  197. int width,
  198. int height) {
  199. float* data = reinterpret_cast<float*>(color_data->data);
  200. SkColor4f color = {data[0], data[1], data[2], data[3]};
  201. std::unique_ptr<SolidColorBuffer> buffer =
  202. std::make_unique<SolidColorBuffer>(color, gfx::Size(width, height));
  203. wl_resource* buffer_resource = wl_resource_create(
  204. client, &wl_buffer_interface, wl_resource_get_version(resource), id);
  205. buffer->set_release_callback(base::BindRepeating(
  206. &HandleBufferReleaseCallback, base::Unretained(buffer_resource)));
  207. SetImplementation(buffer_resource, &buffer_implementation, std::move(buffer));
  208. }
  209. void augmenter_get_augmented_surface(wl_client* client,
  210. wl_resource* resource,
  211. uint32_t id,
  212. wl_resource* surface_resource) {
  213. Surface* surface = GetUserDataAs<Surface>(surface_resource);
  214. if (surface->GetProperty(kSurfaceHasAugmentedSurfaceKey)) {
  215. wl_resource_post_error(resource,
  216. SURFACE_AUGMENTER_ERROR_AUGMENTED_SURFACE_EXISTS,
  217. "an augmenter for that surface already exists");
  218. return;
  219. }
  220. wl_resource* augmented_resource =
  221. wl_resource_create(client, &augmented_surface_interface,
  222. wl_resource_get_version(resource), id);
  223. SetImplementation(augmented_resource, &augmented_implementation,
  224. std::make_unique<AugmentedSurface>(surface));
  225. }
  226. void augmenter_get_augmented_sub_surface(wl_client* client,
  227. wl_resource* resource,
  228. uint32_t id,
  229. wl_resource* sub_surface_resource) {
  230. SubSurface* sub_surface = GetUserDataAs<SubSurface>(sub_surface_resource);
  231. if (sub_surface->GetProperty(kSubSurfaceHasAugmentedSubSurfaceKey)) {
  232. wl_resource_post_error(resource,
  233. SURFACE_AUGMENTER_ERROR_AUGMENTED_SURFACE_EXISTS,
  234. "an augmenter for that sub-surface already exists");
  235. return;
  236. }
  237. wl_resource* augmented_resource =
  238. wl_resource_create(client, &augmented_sub_surface_interface,
  239. wl_resource_get_version(resource), id);
  240. SetImplementation(augmented_resource, &augmented_sub_surface_implementation,
  241. std::make_unique<AugmentedSubSurface>(sub_surface));
  242. }
  243. const struct surface_augmenter_interface augmenter_implementation = {
  244. augmenter_destroy, augmenter_create_solid_color_buffer,
  245. augmenter_get_augmented_surface, augmenter_get_augmented_sub_surface};
  246. } // namespace
  247. void bind_surface_augmenter(wl_client* client,
  248. void* data,
  249. uint32_t version,
  250. uint32_t id) {
  251. wl_resource* resource =
  252. wl_resource_create(client, &surface_augmenter_interface,
  253. std::min(version, kSurfaceAugmenterVersion), id);
  254. wl_resource_set_implementation(resource, &augmenter_implementation, data,
  255. nullptr);
  256. }
  257. } // namespace wayland
  258. } // namespace exo