surface.cc 58 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650
  1. // Copyright 2015 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/surface.h"
  5. #include <utility>
  6. #include "ash/public/cpp/shell_window_ids.h"
  7. #include "ash/public/cpp/window_properties.h"
  8. #include "base/callback_helpers.h"
  9. #include "base/containers/adapters.h"
  10. #include "base/logging.h"
  11. #include "base/memory/ptr_util.h"
  12. #include "base/notreached.h"
  13. #include "base/numerics/safe_conversions.h"
  14. #include "base/strings/stringprintf.h"
  15. #include "base/trace_event/trace_event.h"
  16. #include "base/trace_event/traced_value.h"
  17. #include "build/build_config.h"
  18. #include "build/chromeos_buildflags.h"
  19. #include "components/exo/buffer.h"
  20. #include "components/exo/frame_sink_resource_manager.h"
  21. #include "components/exo/shell_surface_util.h"
  22. #include "components/exo/surface_delegate.h"
  23. #include "components/exo/surface_observer.h"
  24. #include "components/exo/window_properties.h"
  25. #include "components/exo/wm_helper.h"
  26. #include "components/viz/common/quads/compositor_render_pass.h"
  27. #include "components/viz/common/quads/shared_quad_state.h"
  28. #include "components/viz/common/quads/solid_color_draw_quad.h"
  29. #include "components/viz/common/quads/surface_draw_quad.h"
  30. #include "components/viz/common/quads/texture_draw_quad.h"
  31. #include "components/viz/common/quads/tile_draw_quad.h"
  32. #include "components/viz/common/resources/resource_id.h"
  33. #include "media/media_buildflags.h"
  34. #include "third_party/khronos/GLES2/gl2.h"
  35. #include "third_party/skia/include/core/SkColor.h"
  36. #include "third_party/skia/include/core/SkPath.h"
  37. #include "ui/aura/client/aura_constants.h"
  38. #include "ui/aura/client/drag_drop_delegate.h"
  39. #include "ui/aura/window_delegate.h"
  40. #include "ui/aura/window_occlusion_tracker.h"
  41. #include "ui/aura/window_targeter.h"
  42. #include "ui/base/class_property.h"
  43. #include "ui/base/cursor/cursor.h"
  44. #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
  45. #include "ui/base/hit_test.h"
  46. #include "ui/compositor/layer.h"
  47. #include "ui/display/display.h"
  48. #include "ui/display/screen.h"
  49. #include "ui/events/event.h"
  50. #include "ui/gfx/buffer_format_util.h"
  51. #include "ui/gfx/buffer_types.h"
  52. #include "ui/gfx/geometry/dip_util.h"
  53. #include "ui/gfx/geometry/point.h"
  54. #include "ui/gfx/geometry/point_conversions.h"
  55. #include "ui/gfx/geometry/point_f.h"
  56. #include "ui/gfx/geometry/rect.h"
  57. #include "ui/gfx/geometry/rect_conversions.h"
  58. #include "ui/gfx/geometry/rect_f.h"
  59. #include "ui/gfx/geometry/size_conversions.h"
  60. #include "ui/gfx/geometry/transform_util.h"
  61. #include "ui/gfx/geometry/vector2d_f.h"
  62. #include "ui/gfx/gpu_fence.h"
  63. #include "ui/gfx/gpu_memory_buffer.h"
  64. #include "ui/gfx/presentation_feedback.h"
  65. #include "ui/views/widget/widget.h"
  66. #if BUILDFLAG(IS_CHROMEOS_ASH)
  67. #include "ash/display/output_protection_delegate.h"
  68. #include "ash/wm/desks/desks_util.h"
  69. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  70. DEFINE_UI_CLASS_PROPERTY_TYPE(exo::Surface*)
  71. namespace exo {
  72. namespace {
  73. // A property key containing the surface that is associated with
  74. // window. If unset, no surface is associated with window.
  75. DEFINE_UI_CLASS_PROPERTY_KEY(Surface*, kSurfaceKey, nullptr)
  76. // A property key to store whether the surface should only consume
  77. // stylus input events.
  78. DEFINE_UI_CLASS_PROPERTY_KEY(bool, kStylusOnlyKey, false)
  79. // Helper function that returns an iterator to the first entry in |list|
  80. // with |key|.
  81. template <typename T, typename U>
  82. typename T::iterator FindListEntry(T& list, U key) {
  83. return std::find_if(list.begin(), list.end(),
  84. [key](const typename T::value_type& entry) {
  85. return entry.first == key;
  86. });
  87. }
  88. // Helper function that returns true if |list| contains an entry with |key|.
  89. template <typename T, typename U>
  90. bool ListContainsEntry(T& list, U key) {
  91. return FindListEntry(list, key) != list.end();
  92. }
  93. // Helper function that returns true if |format| may have an alpha channel.
  94. // Note: False positives are allowed but false negatives are not.
  95. bool FormatHasAlpha(gfx::BufferFormat format) {
  96. switch (format) {
  97. case gfx::BufferFormat::BGR_565:
  98. case gfx::BufferFormat::RGBX_8888:
  99. case gfx::BufferFormat::BGRX_8888:
  100. case gfx::BufferFormat::YVU_420:
  101. case gfx::BufferFormat::YUV_420_BIPLANAR:
  102. return false;
  103. default:
  104. return true;
  105. }
  106. }
  107. // Helper function that returns |size| after adjusting for |transform|.
  108. gfx::Size ToTransformedSize(const gfx::Size& size, Transform transform) {
  109. switch (transform) {
  110. case Transform::NORMAL:
  111. case Transform::ROTATE_180:
  112. case Transform::FLIPPED:
  113. case Transform::FLIPPED_ROTATE_180:
  114. return size;
  115. case Transform::ROTATE_90:
  116. case Transform::ROTATE_270:
  117. case Transform::FLIPPED_ROTATE_90:
  118. case Transform::FLIPPED_ROTATE_270:
  119. return gfx::Size(size.height(), size.width());
  120. }
  121. NOTREACHED();
  122. }
  123. bool IsDeskContainer(aura::Window* container) {
  124. #if BUILDFLAG(IS_CHROMEOS_ASH)
  125. return ash::desks_util::IsDeskContainer(container);
  126. #else
  127. return container->GetId() == ash::kShellWindowId_DefaultContainerDeprecated;
  128. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  129. }
  130. class CustomWindowDelegate : public aura::WindowDelegate {
  131. public:
  132. explicit CustomWindowDelegate(Surface* surface) : surface_(surface) {}
  133. CustomWindowDelegate(const CustomWindowDelegate&) = delete;
  134. CustomWindowDelegate& operator=(const CustomWindowDelegate&) = delete;
  135. ~CustomWindowDelegate() override {}
  136. // Overridden from aura::WindowDelegate:
  137. gfx::Size GetMinimumSize() const override { return gfx::Size(); }
  138. gfx::Size GetMaximumSize() const override { return gfx::Size(); }
  139. void OnBoundsChanged(const gfx::Rect& old_bounds,
  140. const gfx::Rect& new_bounds) override {}
  141. gfx::NativeCursor GetCursor(const gfx::Point& point) override {
  142. views::Widget* widget =
  143. views::Widget::GetTopLevelWidgetForNativeView(surface_->window());
  144. if (widget)
  145. return widget->GetNativeWindow()->GetCursor(point /* not used */);
  146. return ui::mojom::CursorType::kNull;
  147. }
  148. int GetNonClientComponent(const gfx::Point& point) const override {
  149. views::Widget* widget =
  150. views::Widget::GetTopLevelWidgetForNativeView(surface_->window());
  151. if (widget && IsDeskContainer(widget->GetNativeView()->parent()) &&
  152. surface_->HitTest(point)) {
  153. return HTCLIENT;
  154. }
  155. return HTNOWHERE;
  156. }
  157. bool ShouldDescendIntoChildForEventHandling(
  158. aura::Window* child,
  159. const gfx::Point& location) override {
  160. return true;
  161. }
  162. bool CanFocus() override { return true; }
  163. void OnCaptureLost() override {}
  164. void OnPaint(const ui::PaintContext& context) override {}
  165. void OnDeviceScaleFactorChanged(float old_device_scale_factor,
  166. float new_device_scale_factor) override {}
  167. void OnWindowDestroying(aura::Window* window) override {}
  168. void OnWindowDestroyed(aura::Window* window) override { delete this; }
  169. void OnWindowTargetVisibilityChanged(bool visible) override {}
  170. void OnWindowOcclusionChanged(
  171. aura::Window::OcclusionState GetOcclusionState) override {
  172. surface_->OnWindowOcclusionChanged();
  173. }
  174. bool HasHitTestMask() const override { return true; }
  175. void GetHitTestMask(SkPath* mask) const override {
  176. surface_->GetHitTestMask(mask);
  177. }
  178. void OnKeyEvent(ui::KeyEvent* event) override {
  179. // Propagates the key event upto the top-level views Widget so that we can
  180. // trigger proper events in the views/ash level there. Event handling for
  181. // Surfaces is done in a post event handler in keyboard.cc.
  182. views::Widget* widget =
  183. views::Widget::GetTopLevelWidgetForNativeView(surface_->window());
  184. if (widget)
  185. widget->OnKeyEvent(event);
  186. }
  187. private:
  188. Surface* const surface_;
  189. };
  190. class CustomWindowTargeter : public aura::WindowTargeter {
  191. public:
  192. CustomWindowTargeter() {}
  193. CustomWindowTargeter(const CustomWindowTargeter&) = delete;
  194. CustomWindowTargeter& operator=(const CustomWindowTargeter&) = delete;
  195. ~CustomWindowTargeter() override {}
  196. // Overridden from aura::WindowTargeter:
  197. bool EventLocationInsideBounds(aura::Window* window,
  198. const ui::LocatedEvent& event) const override {
  199. Surface* surface = Surface::AsSurface(window);
  200. if (!surface || !surface->IsInputEnabled(surface))
  201. return false;
  202. gfx::Point local_point =
  203. ConvertEventLocationToWindowCoordinates(window, event);
  204. return surface->HitTest(local_point);
  205. }
  206. };
  207. const std::string& GetApplicationId(aura::Window* window) {
  208. static const std::string empty_app_id;
  209. if (!window)
  210. return empty_app_id;
  211. while (window) {
  212. const std::string* app_id = exo::GetShellApplicationId(window);
  213. if (app_id)
  214. return *app_id;
  215. window = window->parent();
  216. }
  217. return empty_app_id;
  218. }
  219. int surface_id = 0;
  220. void ImmediateExplicitRelease(
  221. Buffer::PerCommitExplicitReleaseCallback callback) {
  222. if (callback)
  223. std::move(callback).Run(/*release_fence=*/gfx::GpuFenceHandle());
  224. }
  225. } // namespace
  226. DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(std::string, kClientSurfaceIdKey, nullptr)
  227. // A property key to store the window session Id set by client or full_restore
  228. // component.
  229. DEFINE_UI_CLASS_PROPERTY_KEY(int32_t, kWindowSessionId, -1)
  230. ScopedSurface::ScopedSurface(Surface* surface, SurfaceObserver* observer)
  231. : surface_(surface), observer_(observer) {
  232. surface_->AddSurfaceObserver(observer_);
  233. }
  234. ScopedSurface::~ScopedSurface() {
  235. surface_->RemoveSurfaceObserver(observer_);
  236. }
  237. ////////////////////////////////////////////////////////////////////////////////
  238. // Surface, public:
  239. Surface::Surface()
  240. : window_(
  241. std::make_unique<aura::Window>(new CustomWindowDelegate(this),
  242. aura::client::WINDOW_TYPE_CONTROL)) {
  243. window_->SetName(base::StringPrintf("ExoSurface-%d", surface_id++));
  244. window_->SetProperty(kSurfaceKey, this);
  245. window_->Init(ui::LAYER_NOT_DRAWN);
  246. window_->SetEventTargeter(std::make_unique<CustomWindowTargeter>());
  247. window_->set_owned_by_parent(false);
  248. WMHelper::GetInstance()->SetDragDropDelegate(window_.get());
  249. }
  250. Surface::~Surface() {
  251. for (SurfaceObserver& observer : observers_)
  252. observer.OnSurfaceDestroying(this);
  253. // Call all frame callbacks with a null frame time to indicate that they
  254. // have been cancelled.
  255. state_.frame_callbacks.splice(state_.frame_callbacks.end(),
  256. cached_state_.frame_callbacks);
  257. state_.frame_callbacks.splice(state_.frame_callbacks.end(),
  258. pending_state_.frame_callbacks);
  259. for (const auto& frame_callback : state_.frame_callbacks)
  260. frame_callback.Run(base::TimeTicks());
  261. // Call all presentation callbacks with a null presentation time to indicate
  262. // that they have been cancelled.
  263. state_.presentation_callbacks.splice(state_.presentation_callbacks.end(),
  264. cached_state_.presentation_callbacks);
  265. state_.presentation_callbacks.splice(state_.presentation_callbacks.end(),
  266. pending_state_.presentation_callbacks);
  267. for (const auto& presentation_callback : state_.presentation_callbacks)
  268. presentation_callback.Run(gfx::PresentationFeedback());
  269. // Call explicit release on all explicit release callbacks that have been
  270. // committed.
  271. ImmediateExplicitRelease(
  272. std::move(state_.per_commit_explicit_release_callback_));
  273. ImmediateExplicitRelease(
  274. std::move(cached_state_.per_commit_explicit_release_callback_));
  275. // Do not reset the DragDropDelegate in order to handle exit upon deletion.
  276. }
  277. // static
  278. Surface* Surface::AsSurface(const aura::Window* window) {
  279. return window->GetProperty(kSurfaceKey);
  280. }
  281. void Surface::Attach(Buffer* buffer) {
  282. Attach(buffer, gfx::Vector2d());
  283. }
  284. void Surface::Attach(Buffer* buffer, gfx::Vector2d offset) {
  285. TRACE_EVENT2(
  286. "exo", "Surface::Attach", "buffer_id",
  287. buffer ? static_cast<const void*>(buffer->gfx_buffer()) : nullptr,
  288. "app_id", GetApplicationId(window_.get()));
  289. has_pending_contents_ = true;
  290. if (!pending_state_.buffer.has_value())
  291. pending_state_.buffer.emplace();
  292. pending_state_.buffer->Reset(buffer ? buffer->AsWeakPtr()
  293. : base::WeakPtr<Buffer>());
  294. pending_state_.basic_state.offset = offset;
  295. }
  296. gfx::Vector2d Surface::GetBufferOffset() {
  297. return state_.basic_state.offset;
  298. }
  299. bool Surface::HasPendingAttachedBuffer() const {
  300. return pending_state_.buffer.has_value() &&
  301. pending_state_.buffer->buffer() != nullptr;
  302. }
  303. void Surface::Damage(const gfx::Rect& damage) {
  304. TRACE_EVENT1("exo", "Surface::Damage", "damage", damage.ToString());
  305. pending_state_.damage.Union(damage);
  306. }
  307. void Surface::RequestFrameCallback(const FrameCallback& callback) {
  308. TRACE_EVENT0("exo", "Surface::RequestFrameCallback");
  309. pending_state_.frame_callbacks.push_back(callback);
  310. }
  311. void Surface::RequestPresentationCallback(
  312. const PresentationCallback& callback) {
  313. TRACE_EVENT0("exo", "Surface::RequestPresentationCallback");
  314. pending_state_.presentation_callbacks.push_back(callback);
  315. }
  316. void Surface::SetOpaqueRegion(const cc::Region& region) {
  317. TRACE_EVENT1("exo", "Surface::SetOpaqueRegion", "region", region.ToString());
  318. pending_state_.basic_state.opaque_region = region;
  319. }
  320. void Surface::SetInputRegion(const cc::Region& region) {
  321. TRACE_EVENT1("exo", "Surface::SetInputRegion", "region", region.ToString());
  322. pending_state_.basic_state.input_region = region;
  323. }
  324. void Surface::ResetInputRegion() {
  325. TRACE_EVENT0("exo", "Surface::ResetInputRegion");
  326. pending_state_.basic_state.input_region = absl::nullopt;
  327. }
  328. void Surface::SetInputOutset(int outset) {
  329. TRACE_EVENT1("exo", "Surface::SetInputOutset", "outset", outset);
  330. pending_state_.basic_state.input_outset = outset;
  331. }
  332. void Surface::SetBufferScale(float scale) {
  333. TRACE_EVENT1("exo", "Surface::SetBufferScale", "scale", scale);
  334. pending_state_.basic_state.buffer_scale = scale;
  335. }
  336. void Surface::SetBufferTransform(Transform transform) {
  337. TRACE_EVENT1("exo", "Surface::SetBufferTransform", "transform",
  338. static_cast<int>(transform));
  339. pending_state_.basic_state.buffer_transform = transform;
  340. }
  341. void Surface::AddSubSurface(Surface* sub_surface) {
  342. TRACE_EVENT1("exo", "Surface::AddSubSurface", "sub_surface",
  343. sub_surface->AsTracedValue());
  344. DCHECK(!sub_surface->window()->parent());
  345. sub_surface->window()->SetBounds(
  346. gfx::Rect(sub_surface->window()->bounds().size()));
  347. window_->AddChild(sub_surface->window());
  348. DCHECK(!ListContainsEntry(pending_sub_surfaces_, sub_surface));
  349. pending_sub_surfaces_.push_back(std::make_pair(sub_surface, gfx::PointF()));
  350. sub_surfaces_.push_back(std::make_pair(sub_surface, gfx::PointF()));
  351. sub_surfaces_changed_ = true;
  352. // Propagate the kSkipImeProcessing property to the new child.
  353. if (window_->GetProperty(aura::client::kSkipImeProcessing))
  354. sub_surface->window()->SetProperty(aura::client::kSkipImeProcessing, true);
  355. // The shell might have not be added to the root yet.
  356. if (window_->GetRootWindow()) {
  357. auto display =
  358. display::Screen::GetScreen()->GetDisplayNearestWindow(window_.get());
  359. sub_surface->UpdateDisplay(display::kInvalidDisplayId, display.id());
  360. }
  361. }
  362. void Surface::OnNewOutputAdded() {
  363. if (delegate_)
  364. delegate_->OnNewOutputAdded();
  365. }
  366. void Surface::RemoveSubSurface(Surface* sub_surface) {
  367. TRACE_EVENT1("exo", "Surface::RemoveSubSurface", "sub_surface",
  368. sub_surface->AsTracedValue());
  369. if (sub_surface->window()->IsVisible())
  370. sub_surface->window()->Hide();
  371. window_->RemoveChild(sub_surface->window());
  372. DCHECK(ListContainsEntry(pending_sub_surfaces_, sub_surface));
  373. pending_sub_surfaces_.erase(
  374. FindListEntry(pending_sub_surfaces_, sub_surface));
  375. DCHECK(ListContainsEntry(sub_surfaces_, sub_surface));
  376. auto it = FindListEntry(sub_surfaces_, sub_surface);
  377. sub_surfaces_.erase(it);
  378. // Force recreating resources when the surface is added to a tree again.
  379. sub_surface->SurfaceHierarchyResourcesLost();
  380. sub_surfaces_changed_ = true;
  381. }
  382. void Surface::SetSubSurfacePosition(Surface* sub_surface,
  383. const gfx::PointF& position) {
  384. TRACE_EVENT2("exo", "Surface::SetSubSurfacePosition", "sub_surface",
  385. sub_surface->AsTracedValue(), "position", position.ToString());
  386. auto it = FindListEntry(pending_sub_surfaces_, sub_surface);
  387. DCHECK(it != pending_sub_surfaces_.end());
  388. if (it->second == position)
  389. return;
  390. it->second = position;
  391. sub_surfaces_changed_ = true;
  392. }
  393. void Surface::PlaceSubSurfaceAbove(Surface* sub_surface, Surface* reference) {
  394. TRACE_EVENT2("exo", "Surface::PlaceSubSurfaceAbove", "sub_surface",
  395. sub_surface->AsTracedValue(), "reference",
  396. reference->AsTracedValue());
  397. if (sub_surface == reference) {
  398. DLOG(WARNING) << "Client tried to place sub-surface above itself";
  399. return;
  400. }
  401. auto position_it = pending_sub_surfaces_.begin();
  402. if (reference != this) {
  403. position_it = FindListEntry(pending_sub_surfaces_, reference);
  404. if (position_it == pending_sub_surfaces_.end()) {
  405. DLOG(WARNING) << "Client tried to place sub-surface above a reference "
  406. "surface that is neither a parent nor a sibling";
  407. return;
  408. }
  409. // Advance iterator to have |position_it| point to the sibling surface
  410. // above |reference|.
  411. ++position_it;
  412. }
  413. DCHECK(ListContainsEntry(pending_sub_surfaces_, sub_surface));
  414. auto it = FindListEntry(pending_sub_surfaces_, sub_surface);
  415. if (it == position_it)
  416. return;
  417. pending_sub_surfaces_.splice(position_it, pending_sub_surfaces_, it);
  418. sub_surfaces_changed_ = true;
  419. }
  420. void Surface::PlaceSubSurfaceBelow(Surface* sub_surface, Surface* sibling) {
  421. TRACE_EVENT2("exo", "Surface::PlaceSubSurfaceBelow", "sub_surface",
  422. sub_surface->AsTracedValue(), "sibling",
  423. sibling->AsTracedValue());
  424. if (sub_surface == sibling) {
  425. DLOG(WARNING) << "Client tried to place sub-surface below itself";
  426. return;
  427. }
  428. auto position_it = FindListEntry(pending_sub_surfaces_, sibling);
  429. if (position_it == pending_sub_surfaces_.end()) {
  430. DLOG(WARNING) << "Client tried to place sub-surface below a surface that "
  431. "is not a sibling";
  432. return;
  433. }
  434. DCHECK(ListContainsEntry(pending_sub_surfaces_, sub_surface));
  435. auto it = FindListEntry(pending_sub_surfaces_, sub_surface);
  436. // If |sub_surface| is already immediately below |sibling|, do not do
  437. // anything.
  438. if (it == --position_it)
  439. return;
  440. pending_sub_surfaces_.splice(++position_it, pending_sub_surfaces_, it);
  441. sub_surfaces_changed_ = true;
  442. }
  443. void Surface::OnSubSurfaceCommit() {
  444. if (delegate_)
  445. delegate_->OnSurfaceCommit();
  446. }
  447. void Surface::SetRoundedCorners(const gfx::RRectF& rounded_corners_bounds) {
  448. TRACE_EVENT1("exo", "Surface::SetRoundedCorner", "corners",
  449. rounded_corners_bounds.ToString());
  450. if (rounded_corners_bounds != pending_state_.rounded_corners_bounds) {
  451. has_pending_contents_ = true;
  452. pending_state_.rounded_corners_bounds = rounded_corners_bounds;
  453. }
  454. }
  455. void Surface::SetOverlayPriorityHint(OverlayPriority hint) {
  456. TRACE_EVENT0("exo", "Surface::SetOverlayPriorityHint");
  457. pending_state_.overlay_priority_hint = hint;
  458. }
  459. void Surface::SetBackgroundColor(absl::optional<SkColor4f> background_color) {
  460. TRACE_EVENT0("exo", "Surface::SetBackgroundColor");
  461. pending_state_.basic_state.background_color = background_color;
  462. }
  463. void Surface::SetViewport(const gfx::SizeF& viewport) {
  464. TRACE_EVENT1("exo", "Surface::SetViewport", "viewport", viewport.ToString());
  465. pending_state_.basic_state.viewport = viewport;
  466. }
  467. void Surface::SetCrop(const gfx::RectF& crop) {
  468. TRACE_EVENT1("exo", "Surface::SetCrop", "crop", crop.ToString());
  469. pending_state_.basic_state.crop = crop;
  470. }
  471. void Surface::SetOnlyVisibleOnSecureOutput(bool only_visible_on_secure_output) {
  472. TRACE_EVENT1("exo", "Surface::SetOnlyVisibleOnSecureOutput",
  473. "only_visible_on_secure_output", only_visible_on_secure_output);
  474. pending_state_.basic_state.only_visible_on_secure_output =
  475. only_visible_on_secure_output;
  476. }
  477. void Surface::SetBlendMode(SkBlendMode blend_mode) {
  478. TRACE_EVENT1("exo", "Surface::SetBlendMode", "blend_mode",
  479. static_cast<int>(blend_mode));
  480. pending_state_.basic_state.blend_mode = blend_mode;
  481. }
  482. void Surface::SetAlpha(float alpha) {
  483. TRACE_EVENT1("exo", "Surface::SetAlpha", "alpha", alpha);
  484. pending_state_.basic_state.alpha = alpha;
  485. }
  486. void Surface::SetFrame(SurfaceFrameType type) {
  487. TRACE_EVENT1("exo", "Surface::SetFrame", "type", static_cast<uint32_t>(type));
  488. if (delegate_)
  489. delegate_->OnSetFrame(type);
  490. }
  491. void Surface::SetServerStartResize() {
  492. if (delegate_)
  493. delegate_->OnSetServerStartResize();
  494. SetFrame(SurfaceFrameType::SHADOW);
  495. }
  496. void Surface::SetFrameColors(SkColor active_color, SkColor inactive_color) {
  497. TRACE_EVENT2("exo", "Surface::SetFrameColors", "active_color", active_color,
  498. "inactive_color", inactive_color);
  499. if (delegate_)
  500. delegate_->OnSetFrameColors(active_color, inactive_color);
  501. }
  502. void Surface::SetStartupId(const char* startup_id) {
  503. TRACE_EVENT1("exo", "Surface::SetStartupId", "startup_id", startup_id);
  504. if (delegate_)
  505. delegate_->OnSetStartupId(startup_id);
  506. }
  507. void Surface::SetApplicationId(const char* application_id) {
  508. TRACE_EVENT1("exo", "Surface::SetApplicationId", "application_id",
  509. application_id);
  510. if (delegate_)
  511. delegate_->OnSetApplicationId(application_id);
  512. }
  513. void Surface::SetUseImmersiveForFullscreen(bool value) {
  514. TRACE_EVENT1("exo", "Surface::SetUseImmersiveForFullscreen", "value", value);
  515. if (delegate_)
  516. delegate_->SetUseImmersiveForFullscreen(value);
  517. }
  518. void Surface::ShowSnapPreviewToSecondary() {
  519. if (delegate_)
  520. delegate_->ShowSnapPreviewToSecondary();
  521. }
  522. void Surface::ShowSnapPreviewToPrimary() {
  523. if (delegate_)
  524. delegate_->ShowSnapPreviewToPrimary();
  525. }
  526. void Surface::HideSnapPreview() {
  527. if (delegate_)
  528. delegate_->HideSnapPreview();
  529. }
  530. void Surface::SetSnappedToSecondary() {
  531. if (delegate_)
  532. delegate_->SetSnappedToSecondary();
  533. }
  534. void Surface::SetSnappedToPrimary() {
  535. if (delegate_)
  536. delegate_->SetSnappedToPrimary();
  537. }
  538. void Surface::UnsetSnap() {
  539. if (delegate_)
  540. delegate_->UnsetSnap();
  541. }
  542. void Surface::SetCanGoBack() {
  543. if (delegate_)
  544. delegate_->SetCanGoBack();
  545. }
  546. void Surface::UnsetCanGoBack() {
  547. if (delegate_)
  548. delegate_->UnsetCanGoBack();
  549. }
  550. void Surface::SetColorSpace(gfx::ColorSpace color_space) {
  551. TRACE_EVENT1("exo", "Surface::SetColorSpace", "color_space",
  552. color_space.ToString());
  553. pending_state_.basic_state.color_space = color_space;
  554. }
  555. void Surface::SetParent(Surface* parent, const gfx::Point& position) {
  556. TRACE_EVENT2("exo", "Surface::SetParent", "parent", !!parent, "position",
  557. position.ToString());
  558. if (delegate_)
  559. delegate_->OnSetParent(parent, position);
  560. }
  561. void Surface::RequestActivation() {
  562. TRACE_EVENT0("exo", "Surface::RequestActivation");
  563. if (delegate_)
  564. delegate_->OnActivationRequested();
  565. }
  566. void Surface::SetClientSurfaceId(const char* client_surface_id) {
  567. if (client_surface_id && strlen(client_surface_id) > 0)
  568. window_->SetProperty(kClientSurfaceIdKey,
  569. new std::string(client_surface_id));
  570. else
  571. window_->ClearProperty(kClientSurfaceIdKey);
  572. }
  573. std::string Surface::GetClientSurfaceId() const {
  574. std::string* value = window_->GetProperty(kClientSurfaceIdKey);
  575. return value ? *value : std::string();
  576. }
  577. void Surface::SetWindowSessionId(int32_t window_session_id) {
  578. if (window_session_id > 0)
  579. window_->SetProperty(kWindowSessionId, window_session_id);
  580. else
  581. window_->ClearProperty(kWindowSessionId);
  582. }
  583. int32_t Surface::GetWindowSessionId() {
  584. return window_->GetProperty(kWindowSessionId);
  585. }
  586. void Surface::SetPip() {
  587. if (delegate_)
  588. delegate_->SetPip();
  589. }
  590. void Surface::UnsetPip() {
  591. if (delegate_)
  592. delegate_->UnsetPip();
  593. }
  594. void Surface::SetAspectRatio(const gfx::SizeF& aspect_ratio) {
  595. if (delegate_)
  596. delegate_->SetAspectRatio(aspect_ratio);
  597. }
  598. void Surface::SetEmbeddedSurfaceId(
  599. base::RepeatingCallback<viz::SurfaceId()> surface_id_callback) {
  600. get_current_surface_id_ = std::move(surface_id_callback);
  601. first_embedded_surface_id_ = viz::SurfaceId();
  602. }
  603. void Surface::SetEmbeddedSurfaceSize(const gfx::Size& size) {
  604. embedded_surface_size_ = size;
  605. }
  606. void Surface::SetAcquireFence(std::unique_ptr<gfx::GpuFence> gpu_fence) {
  607. #if BUILDFLAG(IS_POSIX)
  608. TRACE_EVENT1("exo", "Surface::SetAcquireFence", "fence_fd",
  609. gpu_fence ? gpu_fence->GetGpuFenceHandle().owned_fd.get() : -1);
  610. #endif // BUILDFLAG(IS_POSIX)
  611. pending_state_.acquire_fence = std::move(gpu_fence);
  612. }
  613. bool Surface::HasPendingAcquireFence() const {
  614. return !!pending_state_.acquire_fence;
  615. }
  616. void Surface::SetPerCommitBufferReleaseCallback(
  617. Buffer::PerCommitExplicitReleaseCallback callback) {
  618. TRACE_EVENT0("exo", "Surface::SetPerCommitBufferReleaseCallback");
  619. pending_state_.per_commit_explicit_release_callback_ = std::move(callback);
  620. }
  621. bool Surface::HasPendingPerCommitBufferReleaseCallback() const {
  622. return !!pending_state_.per_commit_explicit_release_callback_;
  623. }
  624. void Surface::Commit() {
  625. TRACE_EVENT1(
  626. "exo", "Surface::Commit", "buffer_id",
  627. static_cast<const void*>(
  628. pending_state_.buffer.has_value() && pending_state_.buffer->buffer()
  629. ? pending_state_.buffer->buffer()->gfx_buffer()
  630. : nullptr));
  631. for (auto& observer : observers_)
  632. observer.OnCommit(this);
  633. needs_commit_surface_ = true;
  634. // Transfer pending state to cached state.
  635. cached_state_.basic_state = pending_state_.basic_state;
  636. pending_state_.basic_state.only_visible_on_secure_output = false;
  637. has_cached_contents_ |= has_pending_contents_;
  638. has_pending_contents_ = false;
  639. if (pending_state_.buffer.has_value()) {
  640. cached_state_.buffer = std::move(pending_state_.buffer);
  641. pending_state_.buffer.reset();
  642. }
  643. cached_state_.rounded_corners_bounds = pending_state_.rounded_corners_bounds;
  644. cached_state_.overlay_priority_hint = pending_state_.overlay_priority_hint;
  645. cached_state_.acquire_fence = std::move(pending_state_.acquire_fence);
  646. cached_state_.per_commit_explicit_release_callback_ =
  647. std::move(pending_state_.per_commit_explicit_release_callback_);
  648. cached_state_.frame_callbacks.splice(cached_state_.frame_callbacks.end(),
  649. pending_state_.frame_callbacks);
  650. cached_state_.damage.Union(pending_state_.damage);
  651. pending_state_.damage.Clear();
  652. // Existing presentation callbacks in the cached state when a new pending
  653. // state is merged in should end up delivered as "discarded".
  654. for (const auto& presentation_callback : cached_state_.presentation_callbacks)
  655. presentation_callback.Run(gfx::PresentationFeedback());
  656. cached_state_.presentation_callbacks.clear();
  657. cached_state_.presentation_callbacks.splice(
  658. cached_state_.presentation_callbacks.end(),
  659. pending_state_.presentation_callbacks);
  660. if (delegate_)
  661. delegate_->OnSurfaceCommit();
  662. else
  663. CommitSurfaceHierarchy(false);
  664. }
  665. bool Surface::UpdateDisplay(int64_t old_display, int64_t new_display) {
  666. if (!leave_enter_callback_.is_null()) {
  667. if (!leave_enter_callback_.Run(old_display, new_display))
  668. return false;
  669. }
  670. for (const auto& sub_surface_entry : base::Reversed(sub_surfaces_)) {
  671. auto* sub_surface = sub_surface_entry.first;
  672. if (!sub_surface->UpdateDisplay(old_display, new_display))
  673. return false;
  674. }
  675. for (auto& observer : observers_) {
  676. observer.OnDisplayChanged(this, old_display, new_display);
  677. }
  678. return true;
  679. }
  680. void Surface::CommitSurfaceHierarchy(bool synchronized) {
  681. TRACE_EVENT0("exo", "Surface::CommitSurfaceHierarchy");
  682. if (needs_commit_surface_ && (synchronized || !IsSynchronized())) {
  683. needs_commit_surface_ = false;
  684. synchronized = true;
  685. // TODO(penghuang): Make the damage more precise for sub surface changes.
  686. // https://crbug.com/779704
  687. bool needs_full_damage =
  688. sub_surfaces_changed_ ||
  689. cached_state_.basic_state.opaque_region !=
  690. state_.basic_state.opaque_region ||
  691. cached_state_.basic_state.buffer_scale !=
  692. state_.basic_state.buffer_scale ||
  693. cached_state_.basic_state.buffer_transform !=
  694. state_.basic_state.buffer_transform ||
  695. cached_state_.basic_state.viewport != state_.basic_state.viewport ||
  696. cached_state_.rounded_corners_bounds != state_.rounded_corners_bounds ||
  697. cached_state_.basic_state.crop != state_.basic_state.crop ||
  698. cached_state_.basic_state.only_visible_on_secure_output !=
  699. state_.basic_state.only_visible_on_secure_output ||
  700. cached_state_.basic_state.blend_mode != state_.basic_state.blend_mode ||
  701. cached_state_.basic_state.alpha != state_.basic_state.alpha ||
  702. cached_state_.basic_state.color_space !=
  703. state_.basic_state.color_space ||
  704. cached_state_.basic_state.is_tracking_occlusion !=
  705. state_.basic_state.is_tracking_occlusion;
  706. bool needs_update_buffer_transform =
  707. cached_state_.basic_state.buffer_scale !=
  708. state_.basic_state.buffer_scale ||
  709. cached_state_.basic_state.buffer_transform !=
  710. state_.basic_state.buffer_transform;
  711. #if BUILDFLAG(IS_CHROMEOS_ASH)
  712. bool needs_output_protection =
  713. cached_state_.basic_state.only_visible_on_secure_output !=
  714. state_.basic_state.only_visible_on_secure_output;
  715. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  716. bool cached_invert_y = false;
  717. // If the current state is fully transparent, the last submitted frame will
  718. // not include the TextureDrawQuad for the resource, so the resource might
  719. // have been released and needs to be updated again.
  720. if (!state_.basic_state.alpha && cached_state_.basic_state.alpha)
  721. needs_update_resource_ = true;
  722. state_.basic_state = cached_state_.basic_state;
  723. cached_state_.basic_state.only_visible_on_secure_output = false;
  724. window_->SetEventTargetingPolicy(
  725. (state_.basic_state.input_region.has_value() &&
  726. state_.basic_state.input_region->IsEmpty())
  727. ? aura::EventTargetingPolicy::kDescendantsOnly
  728. : aura::EventTargetingPolicy::kTargetAndDescendants);
  729. if (state_.basic_state.is_tracking_occlusion) {
  730. // TODO(edcourtney): Currently, it doesn't seem to be possible to stop
  731. // tracking the occlusion state once started, but it would be nice to stop
  732. // if the tracked occlusion region becomes empty.
  733. window_->TrackOcclusionState();
  734. }
  735. #if BUILDFLAG(IS_CHROMEOS_ASH)
  736. if (needs_output_protection) {
  737. if (!output_protection_) {
  738. output_protection_ =
  739. std::make_unique<ash::OutputProtectionDelegate>(window_.get());
  740. }
  741. uint32_t protection_mask =
  742. state_.basic_state.only_visible_on_secure_output
  743. ? display::CONTENT_PROTECTION_METHOD_HDCP
  744. : display::CONTENT_PROTECTION_METHOD_NONE;
  745. output_protection_->SetProtection(protection_mask, base::DoNothing());
  746. }
  747. #endif // BUILDFLAG(IS_CHROMEOS_ASH)
  748. // We update contents if Attach() has been called since last commit.
  749. if (has_cached_contents_) {
  750. has_cached_contents_ = false;
  751. bool current_invert_y = state_.buffer.has_value() &&
  752. state_.buffer->buffer() &&
  753. state_.buffer->buffer()->y_invert();
  754. cached_invert_y = cached_state_.buffer.has_value() &&
  755. cached_state_.buffer->buffer() &&
  756. cached_state_.buffer->buffer()->y_invert();
  757. if (current_invert_y != cached_invert_y)
  758. needs_update_buffer_transform = true;
  759. if (cached_state_.buffer.has_value()) {
  760. state_.buffer = std::move(cached_state_.buffer);
  761. cached_state_.buffer.reset();
  762. }
  763. state_.rounded_corners_bounds = cached_state_.rounded_corners_bounds;
  764. state_.overlay_priority_hint = cached_state_.overlay_priority_hint;
  765. state_.acquire_fence = std::move(cached_state_.acquire_fence);
  766. state_.per_commit_explicit_release_callback_ =
  767. std::move(cached_state_.per_commit_explicit_release_callback_);
  768. if (state_.basic_state.alpha)
  769. needs_update_resource_ = true;
  770. }
  771. // Either we didn't have a pending acquire fence, or we had one along with
  772. // a new buffer, and it was already moved to state_.acquire_fence. Note that
  773. // it is a commit-time client error to commit a fence without a buffer.
  774. DCHECK(!cached_state_.acquire_fence);
  775. // Similarly for the per commit buffer release callback.
  776. DCHECK(!cached_state_.per_commit_explicit_release_callback_);
  777. if (needs_update_buffer_transform)
  778. UpdateBufferTransform(cached_invert_y);
  779. // Move pending frame callbacks to the end of |state_.frame_callbacks|.
  780. state_.frame_callbacks.splice(state_.frame_callbacks.end(),
  781. cached_state_.frame_callbacks);
  782. // Move pending presentation callbacks to the end of
  783. // |state_.presentation_callbacks|.
  784. state_.presentation_callbacks.splice(state_.presentation_callbacks.end(),
  785. cached_state_.presentation_callbacks);
  786. UpdateContentSize();
  787. // Synchronize window hierarchy. This will position and update the stacking
  788. // order of all sub-surfaces after committing all pending state of
  789. // sub-surface descendants.
  790. // Changes to sub_surface stack is immediately applied to pending, which
  791. // will be copied to active directly when parent surface is committed,
  792. // skipping the cached state.
  793. if (sub_surfaces_changed_) {
  794. sub_surfaces_.clear();
  795. aura::Window* stacking_target = nullptr;
  796. for (const auto& sub_surface_entry : pending_sub_surfaces_) {
  797. Surface* sub_surface = sub_surface_entry.first;
  798. sub_surfaces_.push_back(sub_surface_entry);
  799. // Move sub-surface to its new position in the stack.
  800. if (stacking_target)
  801. window_->StackChildAbove(sub_surface->window(), stacking_target);
  802. // Stack next sub-surface above this sub-surface.
  803. stacking_target = sub_surface->window();
  804. // Update sub-surface position relative to surface origin.
  805. sub_surface->window()->SetBounds(
  806. gfx::Rect(gfx::ToFlooredPoint(sub_surface_entry.second),
  807. sub_surface->window()->bounds().size()));
  808. }
  809. sub_surfaces_changed_ = false;
  810. }
  811. gfx::Rect output_rect(gfx::ToCeiledSize(content_size_));
  812. if (needs_full_damage) {
  813. state_.damage = output_rect;
  814. } else {
  815. // cached_state_.damage is in Surface coordinates.
  816. state_.damage.Swap(&cached_state_.damage);
  817. state_.damage.Intersect(output_rect);
  818. }
  819. cached_state_.damage.Clear();
  820. }
  821. surface_hierarchy_content_bounds_ =
  822. gfx::Rect(gfx::ToCeiledSize(content_size_));
  823. if (state_.basic_state.input_region) {
  824. hit_test_region_ = *state_.basic_state.input_region;
  825. hit_test_region_.Intersect(surface_hierarchy_content_bounds_);
  826. } else {
  827. hit_test_region_ = surface_hierarchy_content_bounds_;
  828. }
  829. int outset = state_.basic_state.input_outset;
  830. if (outset > 0) {
  831. gfx::Rect input_rect = surface_hierarchy_content_bounds_;
  832. input_rect.Inset(-outset);
  833. hit_test_region_ = input_rect;
  834. }
  835. for (const auto& sub_surface_entry : base::Reversed(sub_surfaces_)) {
  836. auto* sub_surface = sub_surface_entry.first;
  837. gfx::Vector2d offset =
  838. gfx::ToRoundedPoint(sub_surface_entry.second).OffsetFromOrigin();
  839. // Synchronously commit all pending state of the sub-surface and its
  840. // descendants.
  841. sub_surface->CommitSurfaceHierarchy(synchronized);
  842. surface_hierarchy_content_bounds_.Union(
  843. sub_surface->surface_hierarchy_content_bounds() + offset);
  844. hit_test_region_.Union(sub_surface->hit_test_region_ + offset);
  845. }
  846. }
  847. void Surface::AppendSurfaceHierarchyCallbacks(
  848. std::list<FrameCallback>* frame_callbacks,
  849. std::list<PresentationCallback>* presentation_callbacks) {
  850. // Move frame callbacks to the end of |frame_callbacks|.
  851. frame_callbacks->splice(frame_callbacks->end(), state_.frame_callbacks);
  852. // Move presentation callbacks to the end of |presentation_callbacks|.
  853. presentation_callbacks->splice(presentation_callbacks->end(),
  854. state_.presentation_callbacks);
  855. for (const auto& sub_surface_entry : base::Reversed(sub_surfaces_)) {
  856. auto* sub_surface = sub_surface_entry.first;
  857. sub_surface->AppendSurfaceHierarchyCallbacks(frame_callbacks,
  858. presentation_callbacks);
  859. }
  860. }
  861. void Surface::AppendSurfaceHierarchyContentsToFrame(
  862. const gfx::PointF& origin,
  863. float device_scale_factor,
  864. FrameSinkResourceManager* resource_manager,
  865. viz::CompositorFrame* frame) {
  866. // The top most sub-surface is at the front of the RenderPass's quad_list,
  867. // so we need composite sub-surface in reversed order.
  868. for (const auto& sub_surface_entry : base::Reversed(sub_surfaces_)) {
  869. auto* sub_surface = sub_surface_entry.first;
  870. // Synchronsouly commit all pending state of the sub-surface and its
  871. // decendents.
  872. sub_surface->AppendSurfaceHierarchyContentsToFrame(
  873. origin + sub_surface_entry.second.OffsetFromOrigin(),
  874. device_scale_factor, resource_manager, frame);
  875. }
  876. // Update the resource, or if not required, ensure we call the buffer release
  877. // callback, since the buffer will not be used for this commit.
  878. if (needs_update_resource_) {
  879. UpdateResource(resource_manager);
  880. } else {
  881. ImmediateExplicitRelease(
  882. std::move(state_.per_commit_explicit_release_callback_));
  883. }
  884. AppendContentsToFrame(origin, device_scale_factor, frame);
  885. DCHECK(!current_resource_.id ||
  886. resource_manager->HasReleaseCallbackForResource(current_resource_.id));
  887. }
  888. bool Surface::IsSynchronized() const {
  889. return delegate_ && delegate_->IsSurfaceSynchronized();
  890. }
  891. bool Surface::IsInputEnabled(Surface* surface) const {
  892. return !delegate_ || delegate_->IsInputEnabled(surface);
  893. }
  894. bool Surface::HasHitTestRegion() const {
  895. return !hit_test_region_.IsEmpty();
  896. }
  897. bool Surface::HitTest(const gfx::Point& point) const {
  898. return hit_test_region_.Contains(point);
  899. }
  900. void Surface::GetHitTestMask(SkPath* mask) const {
  901. hit_test_region_.GetBoundaryPath(mask);
  902. }
  903. void Surface::SetSurfaceDelegate(SurfaceDelegate* delegate) {
  904. DCHECK(!delegate_ || !delegate);
  905. delegate_ = delegate;
  906. }
  907. bool Surface::HasSurfaceDelegate() const {
  908. return !!delegate_;
  909. }
  910. void Surface::AddSurfaceObserver(SurfaceObserver* observer) {
  911. observers_.AddObserver(observer);
  912. }
  913. void Surface::RemoveSurfaceObserver(SurfaceObserver* observer) {
  914. observers_.RemoveObserver(observer);
  915. }
  916. bool Surface::HasSurfaceObserver(const SurfaceObserver* observer) const {
  917. return observers_.HasObserver(observer);
  918. }
  919. std::unique_ptr<base::trace_event::TracedValue> Surface::AsTracedValue() const {
  920. std::unique_ptr<base::trace_event::TracedValue> value(
  921. new base::trace_event::TracedValue());
  922. value->SetString("name", window_->layer()->name());
  923. return value;
  924. }
  925. bool Surface::IsStylusOnly() {
  926. return window_->GetProperty(kStylusOnlyKey);
  927. }
  928. void Surface::SetStylusOnly() {
  929. window_->SetProperty(kStylusOnlyKey, true);
  930. }
  931. void Surface::SurfaceHierarchyResourcesLost() {
  932. // Update resource and full damage are needed for next frame.
  933. needs_update_resource_ = true;
  934. for (const auto& sub_surface : sub_surfaces_)
  935. sub_surface.first->SurfaceHierarchyResourcesLost();
  936. }
  937. bool Surface::FillsBoundsOpaquely() const {
  938. return !current_resource_has_alpha_ ||
  939. state_.basic_state.blend_mode == SkBlendMode::kSrc ||
  940. state_.basic_state.opaque_region.Contains(
  941. gfx::ToEnclosingRect(gfx::RectF(content_size_)));
  942. }
  943. void Surface::SetOcclusionTracking(bool tracking) {
  944. pending_state_.basic_state.is_tracking_occlusion = tracking;
  945. }
  946. bool Surface::IsTrackingOcclusion() {
  947. return state_.basic_state.is_tracking_occlusion;
  948. }
  949. void Surface::SetSurfaceHierarchyContentBoundsForTest(
  950. const gfx::Rect& content_bounds) {
  951. surface_hierarchy_content_bounds_ = content_bounds;
  952. }
  953. ////////////////////////////////////////////////////////////////////////////////
  954. // Buffer, private:
  955. Surface::State::State() {}
  956. Surface::State::~State() = default;
  957. bool Surface::State::operator==(const State& other) const {
  958. return other.opaque_region == opaque_region &&
  959. other.input_region == input_region &&
  960. other.buffer_scale == buffer_scale &&
  961. other.buffer_transform == buffer_transform &&
  962. other.viewport == viewport && other.crop == crop &&
  963. other.only_visible_on_secure_output == only_visible_on_secure_output &&
  964. other.blend_mode == blend_mode && other.alpha == alpha;
  965. }
  966. Surface::BufferAttachment::BufferAttachment() = default;
  967. Surface::BufferAttachment::~BufferAttachment() {
  968. if (buffer_)
  969. buffer_->OnDetach();
  970. }
  971. Surface::BufferAttachment::BufferAttachment(BufferAttachment&& other) {
  972. *this = std::move(other);
  973. }
  974. Surface::BufferAttachment& Surface::BufferAttachment::operator=(
  975. BufferAttachment&& other) {
  976. if (buffer_)
  977. buffer_->OnDetach();
  978. buffer_ = other.buffer_;
  979. size_ = other.size_;
  980. other.buffer_ = base::WeakPtr<Buffer>();
  981. other.size_ = gfx::Size();
  982. return *this;
  983. }
  984. base::WeakPtr<Buffer>& Surface::BufferAttachment::buffer() {
  985. return buffer_;
  986. }
  987. const base::WeakPtr<Buffer>& Surface::BufferAttachment::buffer() const {
  988. return buffer_;
  989. }
  990. const gfx::Size& Surface::BufferAttachment::size() const {
  991. return size_;
  992. }
  993. void Surface::BufferAttachment::Reset(base::WeakPtr<Buffer> buffer) {
  994. size_ = gfx::Size();
  995. if (buffer) {
  996. buffer->OnAttach();
  997. size_ = buffer->GetSize();
  998. }
  999. if (buffer_)
  1000. buffer_->OnDetach();
  1001. buffer_ = buffer;
  1002. }
  1003. Surface::ExtendedState::ExtendedState() = default;
  1004. Surface::ExtendedState::~ExtendedState() = default;
  1005. void Surface::UpdateResource(FrameSinkResourceManager* resource_manager) {
  1006. DCHECK(needs_update_resource_);
  1007. needs_update_resource_ = false;
  1008. if (state_.buffer.has_value() && state_.buffer->buffer()) {
  1009. if (state_.buffer->buffer()->ProduceTransferableResource(
  1010. resource_manager, std::move(state_.acquire_fence),
  1011. state_.basic_state.only_visible_on_secure_output,
  1012. &current_resource_,
  1013. window_->GetToplevelWindow()->GetProperty(
  1014. kProtectedNativePixmapQueryDelegate),
  1015. std::move(state_.per_commit_explicit_release_callback_))) {
  1016. current_resource_has_alpha_ =
  1017. FormatHasAlpha(state_.buffer->buffer()->GetFormat());
  1018. current_resource_.color_space = state_.basic_state.color_space;
  1019. } else {
  1020. current_resource_.id = viz::kInvalidResourceId;
  1021. // Use the buffer's size, so the AppendContentsToFrame() will append
  1022. // a SolidColorDrawQuad with the buffer's size.
  1023. current_resource_.size = state_.buffer->size();
  1024. SkColor4f color = state_.buffer->buffer()->GetColor();
  1025. current_resource_has_alpha_ = !color.isOpaque();
  1026. }
  1027. } else {
  1028. current_resource_.id = viz::kInvalidResourceId;
  1029. current_resource_.size = gfx::Size();
  1030. current_resource_has_alpha_ = false;
  1031. ImmediateExplicitRelease(
  1032. std::move(state_.per_commit_explicit_release_callback_));
  1033. }
  1034. }
  1035. void Surface::UpdateBufferTransform(bool y_invert) {
  1036. SkMatrix buffer_matrix;
  1037. Transform transform = state_.basic_state.buffer_transform;
  1038. switch (transform) {
  1039. case Transform::ROTATE_90:
  1040. case Transform::FLIPPED_ROTATE_90:
  1041. buffer_matrix.setSinCos(-1, 0, 0.5f, 0.5f);
  1042. break;
  1043. case Transform::ROTATE_180:
  1044. case Transform::FLIPPED_ROTATE_180:
  1045. buffer_matrix.setSinCos(0, -1, 0.5f, 0.5f);
  1046. break;
  1047. case Transform::ROTATE_270:
  1048. case Transform::FLIPPED_ROTATE_270:
  1049. buffer_matrix.setSinCos(1, 0, 0.5f, 0.5f);
  1050. break;
  1051. default:
  1052. break;
  1053. }
  1054. bool x_invert = false;
  1055. switch (transform) {
  1056. case Transform::FLIPPED:
  1057. case Transform::FLIPPED_ROTATE_90:
  1058. case Transform::FLIPPED_ROTATE_180:
  1059. case Transform::FLIPPED_ROTATE_270:
  1060. x_invert = true;
  1061. break;
  1062. default:
  1063. break;
  1064. }
  1065. if (x_invert)
  1066. buffer_matrix.preScale(-1, 1, 0.5f, 0.5f);
  1067. if (y_invert)
  1068. buffer_matrix.preScale(1, -1, 0.5f, 0.5f);
  1069. if (state_.basic_state.buffer_scale != 0)
  1070. buffer_matrix.postScale(1.0f / state_.basic_state.buffer_scale,
  1071. 1.0f / state_.basic_state.buffer_scale);
  1072. buffer_transform_ = gfx::Transform(buffer_matrix);
  1073. }
  1074. void Surface::AppendContentsToFrame(const gfx::PointF& origin,
  1075. float device_scale_factor,
  1076. viz::CompositorFrame* frame) {
  1077. const std::unique_ptr<viz::CompositorRenderPass>& render_pass =
  1078. frame->render_pass_list.back();
  1079. gfx::RectF output_rect(origin, content_size_);
  1080. gfx::Rect quad_rect(0, 0, 1, 1);
  1081. // Surface bounds are in DIPs, but |damage_rect| and |output_rect| are in
  1082. // pixels, so we need to scale by the |device_scale_factor|.
  1083. gfx::RectF damage_rect = gfx::RectF(state_.damage.bounds());
  1084. if (!damage_rect.IsEmpty()) {
  1085. // Outset damage by 1 DIP to as damage is in surface coordinate space and
  1086. // client might not be aware of |device_scale_factor| and the
  1087. // scaling/filtering it requires.
  1088. damage_rect.Inset(-1);
  1089. damage_rect += origin.OffsetFromOrigin();
  1090. damage_rect.Intersect(output_rect);
  1091. if (device_scale_factor <= 1) {
  1092. damage_rect = gfx::ConvertRectToPixels(damage_rect, device_scale_factor);
  1093. } else {
  1094. // The damage will eventually be rescaled by 1/device_scale_factor. Since
  1095. // that scale factor is <1, taking the enclosed rect here means that that
  1096. // rescaled RectF is <1px smaller than |damage_rect| in each dimension,
  1097. // which makes the enclosing rect equal to |damage_rect|.
  1098. damage_rect.Scale(device_scale_factor);
  1099. }
  1100. }
  1101. state_.damage.Clear();
  1102. gfx::PointF scale(content_size_.width(), content_size_.height());
  1103. gfx::Vector2dF translate(0.0f, 0.0f);
  1104. // Surface quads require the quad rect to be appropriately sized and need to
  1105. // use the shared quad clip rect.
  1106. if (get_current_surface_id_) {
  1107. quad_rect = gfx::Rect(embedded_surface_size_);
  1108. scale = gfx::PointF(1.0f, 1.0f);
  1109. if (!state_.basic_state.crop.IsEmpty()) {
  1110. // In order to crop an AxB rect to CxD we need to scale by A/C, B/D.
  1111. // We achieve clipping by scaling it up and then drawing only in the
  1112. // output rectangle.
  1113. scale.Scale(content_size_.width() / state_.basic_state.crop.width(),
  1114. content_size_.height() / state_.basic_state.crop.height());
  1115. auto offset = state_.basic_state.crop.origin().OffsetFromOrigin();
  1116. translate =
  1117. gfx::Vector2dF(-offset.x() * scale.x(), -offset.y() * scale.y());
  1118. }
  1119. } else {
  1120. scale.Scale(state_.basic_state.buffer_scale);
  1121. }
  1122. // Compute the total transformation from post-transform buffer coordinates to
  1123. // target coordinates.
  1124. SkMatrix viewport_to_target_matrix;
  1125. // Scale and offset the normalized space to fit the content size rectangle.
  1126. viewport_to_target_matrix.setScale(scale.x(), scale.y());
  1127. gfx::PointF target = gfx::PointF(origin) + translate;
  1128. viewport_to_target_matrix.postTranslate(target.x(), target.y());
  1129. // Convert from DPs to pixels.
  1130. viewport_to_target_matrix.postScale(device_scale_factor, device_scale_factor);
  1131. gfx::Transform quad_to_target_transform(buffer_transform_);
  1132. quad_to_target_transform.ConcatTransform(
  1133. gfx::Transform(viewport_to_target_matrix));
  1134. bool are_contents_opaque =
  1135. !current_resource_has_alpha_ ||
  1136. state_.basic_state.blend_mode == SkBlendMode::kSrc ||
  1137. state_.basic_state.opaque_region.Contains(
  1138. gfx::ToEnclosedRect(output_rect));
  1139. gfx::MaskFilterInfo msk;
  1140. if (!state_.rounded_corners_bounds.IsEmpty()) {
  1141. DCHECK(sub_surfaces_.empty());
  1142. auto rounded_corners_rect = state_.rounded_corners_bounds;
  1143. // Convert from dip to px.
  1144. gfx::Transform scale_transform;
  1145. scale_transform.Scale(device_scale_factor, device_scale_factor);
  1146. scale_transform.TransformRRectF(&rounded_corners_rect);
  1147. // Set the mask.
  1148. msk = gfx::MaskFilterInfo(rounded_corners_rect);
  1149. }
  1150. // The overdraw algorithm in 'Display::RemoveOverdrawQuads' operates in
  1151. // content space and, due to the discretized nature of the |gfx::Rect|, cannot
  1152. // work with 0,0 1x1 quads. This also means that quads that do not fall on
  1153. // pixel boundaries (rotated or subpixel rects) cannot be removed by the
  1154. // algorithm.
  1155. gfx::RectF target_space_rect(quad_rect);
  1156. quad_to_target_transform.TransformRect(&target_space_rect);
  1157. CHECK(quad_to_target_transform.Preserves2dAxisAlignment());
  1158. // This simple rect representation cannot mathematically express a rotation
  1159. // (and currently does not express flip/mirror) hence the
  1160. // 'IsPositiveScaleOrTranslation' check.
  1161. if (gfx::IsNearestRectWithinDistance(target_space_rect, 0.001f) &&
  1162. quad_to_target_transform.IsPositiveScaleOrTranslation()) {
  1163. quad_rect = gfx::ToNearestRect(target_space_rect);
  1164. // Later in 'SurfaceAggregator' this transform will have 2d translation.
  1165. quad_to_target_transform = gfx::Transform();
  1166. }
  1167. viz::SharedQuadState* quad_state =
  1168. render_pass->CreateAndAppendSharedQuadState();
  1169. quad_state->SetAll(/*quad_layer_rect=*/quad_to_target_transform, quad_rect,
  1170. /*visible_quad_layer_rect=*/quad_rect,
  1171. /*mask_filter_info=*/msk, /*clip_rect=*/absl::nullopt,
  1172. /*contents_opaque=*/are_contents_opaque,
  1173. /*opacity=*/state_.basic_state.alpha,
  1174. /*blend_mode=*/SkBlendMode::kSrcOver,
  1175. /*sorting_context_id=*/0);
  1176. if (current_resource_.id) {
  1177. gfx::RectF uv_crop(gfx::SizeF(1, 1));
  1178. if (!state_.basic_state.crop.IsEmpty()) {
  1179. // The crop rectangle is a post-transformation rectangle. To get the UV
  1180. // coordinates, we need to convert it to normalized buffer coordinates and
  1181. // pass them through the inverse of the buffer transformation.
  1182. uv_crop = gfx::RectF(state_.basic_state.crop);
  1183. gfx::Size transformed_buffer_size(ToTransformedSize(
  1184. current_resource_.size, state_.basic_state.buffer_transform));
  1185. if (!transformed_buffer_size.IsEmpty())
  1186. uv_crop.Scale(1.f / transformed_buffer_size.width(),
  1187. 1.f / transformed_buffer_size.height());
  1188. buffer_transform_.TransformRectReverse(&uv_crop);
  1189. }
  1190. SkColor4f background_color = SkColors::kTransparent;
  1191. if (state_.basic_state.background_color.has_value())
  1192. background_color = state_.basic_state.background_color.value();
  1193. else if (current_resource_has_alpha_ && are_contents_opaque)
  1194. background_color = SkColors::kBlack; // Avoid writing alpha < 1
  1195. // If this surface is being replaced by a SurfaceId emit a SurfaceDrawQuad.
  1196. if (get_current_surface_id_) {
  1197. auto current_surface_id = get_current_surface_id_.Run();
  1198. // If the surface ID is valid update it, otherwise keep showing the old
  1199. // one for now.
  1200. if (current_surface_id.is_valid()) {
  1201. latest_embedded_surface_id_ = current_surface_id;
  1202. if (!current_surface_id.HasSameEmbedTokenAs(
  1203. first_embedded_surface_id_)) {
  1204. first_embedded_surface_id_ = current_surface_id;
  1205. }
  1206. }
  1207. if (latest_embedded_surface_id_.is_valid() &&
  1208. !embedded_surface_size_.IsEmpty()) {
  1209. if (!state_.basic_state.crop.IsEmpty()) {
  1210. quad_state->clip_rect = gfx::ToEnclosedRect(output_rect);
  1211. }
  1212. viz::SurfaceDrawQuad* surface_quad =
  1213. render_pass->CreateAndAppendDrawQuad<viz::SurfaceDrawQuad>();
  1214. surface_quad->SetNew(quad_state, quad_rect, quad_rect,
  1215. viz::SurfaceRange(first_embedded_surface_id_,
  1216. latest_embedded_surface_id_),
  1217. background_color,
  1218. /*stretch_content_to_fill_bounds=*/false);
  1219. }
  1220. // A resource was still produced for this so we still need to release it
  1221. // later.
  1222. frame->resource_list.push_back(current_resource_);
  1223. } else if (state_.basic_state.alpha != 0.0f) {
  1224. // Draw quad is only needed if buffer is not fully transparent.
  1225. const bool requires_texture_draw_quad =
  1226. state_.basic_state.only_visible_on_secure_output ||
  1227. state_.overlay_priority_hint != OverlayPriority::LOW;
  1228. if (requires_texture_draw_quad) {
  1229. viz::TextureDrawQuad* texture_quad =
  1230. render_pass->CreateAndAppendDrawQuad<viz::TextureDrawQuad>();
  1231. float vertex_opacity[4] = {1.0, 1.0, 1.0, 1.0};
  1232. texture_quad->SetNew(
  1233. quad_state, quad_rect, quad_rect,
  1234. /* needs_blending=*/!are_contents_opaque, current_resource_.id,
  1235. /* premultiplied*/ true, uv_crop.origin(), uv_crop.bottom_right(),
  1236. background_color, vertex_opacity,
  1237. /* flipped=*/false, /* nearest*/ false,
  1238. state_.basic_state.only_visible_on_secure_output,
  1239. gfx::ProtectedVideoType::kClear);
  1240. if (current_resource_.is_overlay_candidate)
  1241. texture_quad->set_resource_size_in_pixels(current_resource_.size);
  1242. switch (state_.overlay_priority_hint) {
  1243. case OverlayPriority::LOW:
  1244. texture_quad->overlay_priority_hint = viz::OverlayPriority::kLow;
  1245. break;
  1246. case OverlayPriority::REQUIRED:
  1247. texture_quad->overlay_priority_hint =
  1248. viz::OverlayPriority::kRequired;
  1249. break;
  1250. case OverlayPriority::REGULAR:
  1251. texture_quad->overlay_priority_hint =
  1252. viz::OverlayPriority::kRegular;
  1253. break;
  1254. }
  1255. #if BUILDFLAG(USE_ARC_PROTECTED_MEDIA)
  1256. if (state_.basic_state.only_visible_on_secure_output &&
  1257. state_.buffer.has_value() && state_.buffer->buffer() &&
  1258. state_.buffer->buffer()->NeedsHardwareProtection()) {
  1259. texture_quad->protected_video_type =
  1260. gfx::ProtectedVideoType::kHardwareProtected;
  1261. }
  1262. #endif // BUILDFLAG(USE_ARC_PROTECTED_MEDIA)
  1263. if (!damage_rect.IsEmpty()) {
  1264. texture_quad->damage_rect = gfx::ToEnclosedRect(damage_rect);
  1265. render_pass->has_per_quad_damage = true;
  1266. // Clear handled damage so it will not be added to the |render_pass|.
  1267. damage_rect = gfx::RectF();
  1268. }
  1269. } else {
  1270. viz::TileDrawQuad* tile_quad =
  1271. render_pass->CreateAndAppendDrawQuad<viz::TileDrawQuad>();
  1272. // TODO(crbug.com/1339335): Support AA quads coming from exo.
  1273. constexpr bool kForceAntiAliasingOff = true;
  1274. tile_quad->SetNew(
  1275. quad_state, quad_rect, quad_rect,
  1276. /* needs_blending=*/!are_contents_opaque, current_resource_.id,
  1277. gfx::ScaleRect(uv_crop, current_resource_.size.width(),
  1278. current_resource_.size.height()),
  1279. current_resource_.size,
  1280. /* is_premultiplied=*/true,
  1281. /* nearest_neighbor */ false, kForceAntiAliasingOff);
  1282. }
  1283. frame->resource_list.push_back(current_resource_);
  1284. }
  1285. } else {
  1286. SkColor4f color = state_.buffer.has_value() && state_.buffer->buffer()
  1287. ? state_.buffer->buffer()->GetColor()
  1288. : SkColors::kBlack;
  1289. viz::SolidColorDrawQuad* solid_quad =
  1290. render_pass->CreateAndAppendDrawQuad<viz::SolidColorDrawQuad>();
  1291. solid_quad->SetNew(quad_state, quad_rect, quad_rect, color,
  1292. false /* force_anti_aliasing_off */);
  1293. }
  1294. render_pass->damage_rect.Union(gfx::ToEnclosedRect(damage_rect));
  1295. }
  1296. void Surface::UpdateContentSize() {
  1297. gfx::SizeF content_size;
  1298. // Enable/disable sub-surface based on if it has contents.
  1299. if (has_contents()) {
  1300. if (!state_.basic_state.viewport.IsEmpty()) {
  1301. content_size = state_.basic_state.viewport;
  1302. } else if (!state_.basic_state.crop.IsEmpty()) {
  1303. DLOG_IF(WARNING, !base::IsValueInRangeForNumericType<int>(
  1304. state_.basic_state.crop.width()) ||
  1305. !base::IsValueInRangeForNumericType<int>(
  1306. state_.basic_state.crop.height()))
  1307. << "Crop rectangle size ("
  1308. << state_.basic_state.crop.size().ToString()
  1309. << ") most be expressible using integers when viewport is not set";
  1310. content_size = state_.basic_state.crop.size();
  1311. } else {
  1312. content_size = gfx::ScaleSize(
  1313. gfx::SizeF(ToTransformedSize(
  1314. state_.buffer.has_value() ? state_.buffer->size() : gfx::Size(),
  1315. state_.basic_state.buffer_transform)),
  1316. 1.0f / state_.basic_state.buffer_scale);
  1317. }
  1318. window_->Show();
  1319. } else {
  1320. window_->Hide();
  1321. }
  1322. if (content_size_ != content_size) {
  1323. content_size_ = content_size;
  1324. // TODO(b/191414141) : Check is temporary to isolate damage issue.
  1325. if (!gfx::ToRoundedSize(content_size_).GetCheckedArea().IsValid()) {
  1326. DCHECK(false) << " content_size_=" << content_size_.ToString();
  1327. constexpr int kMaxSizeScalar = 1 << 15;
  1328. // Forceably restrict |content_size_| to 32kx32k.
  1329. content_size_.SetToMin(gfx::SizeF(kMaxSizeScalar, kMaxSizeScalar));
  1330. }
  1331. window_->SetBounds(gfx::Rect(window_->bounds().origin(),
  1332. gfx::ToCeiledSize(content_size_)));
  1333. for (SurfaceObserver& observer : observers_)
  1334. observer.OnContentSizeChanged(this);
  1335. }
  1336. }
  1337. void Surface::SetFrameLocked(bool lock) {
  1338. for (SurfaceObserver& observer : observers_)
  1339. observer.OnFrameLockingChanged(this, lock);
  1340. }
  1341. void Surface::OnWindowOcclusionChanged() {
  1342. if (!state_.basic_state.is_tracking_occlusion)
  1343. return;
  1344. for (SurfaceObserver& observer : observers_)
  1345. observer.OnWindowOcclusionChanged(this);
  1346. }
  1347. void Surface::OnDeskChanged(int state) {
  1348. for (SurfaceObserver& observer : observers_)
  1349. observer.OnDeskChanged(this, state);
  1350. }
  1351. void Surface::MoveToDesk(int desk_index) {
  1352. if (delegate_)
  1353. delegate_->MoveToDesk(desk_index);
  1354. }
  1355. void Surface::SetVisibleOnAllWorkspaces() {
  1356. if (delegate_)
  1357. delegate_->SetVisibleOnAllWorkspaces();
  1358. }
  1359. void Surface::SetInitialWorkspace(const char* initial_workspace) {
  1360. if (delegate_)
  1361. delegate_->SetInitialWorkspace(initial_workspace);
  1362. }
  1363. void Surface::Pin(bool trusted) {
  1364. if (delegate_)
  1365. delegate_->Pin(trusted);
  1366. }
  1367. void Surface::Unpin() {
  1368. if (delegate_)
  1369. delegate_->Unpin();
  1370. }
  1371. void Surface::ThrottleFrameRate(bool on) {
  1372. for (SurfaceObserver& observer : observers_)
  1373. observer.ThrottleFrameRate(on);
  1374. }
  1375. void Surface::SetKeyboardShortcutsInhibited(bool inhibited) {
  1376. if (keyboard_shortcuts_inhibited_ == inhibited)
  1377. return;
  1378. keyboard_shortcuts_inhibited_ = inhibited;
  1379. #if BUILDFLAG(IS_CHROMEOS_ASH)
  1380. // Also set kCanConsumeSystemKeysKey property, so that the key event
  1381. // is also forwarded to exo::Keyboard.
  1382. // TODO(hidehiko): Support capability on migrating ARC/Crostini.
  1383. window_->SetProperty(ash::kCanConsumeSystemKeysKey, inhibited);
  1384. #endif
  1385. }
  1386. SecurityDelegate* Surface::GetSecurityDelegate() {
  1387. if (delegate_)
  1388. return delegate_->GetSecurityDelegate();
  1389. return nullptr;
  1390. }
  1391. } // namespace exo