123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- // Copyright 2016 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "components/exo/notification_surface.h"
- #include <cmath>
- #include "components/exo/notification_surface_manager.h"
- #include "components/exo/shell_surface_util.h"
- #include "components/exo/surface.h"
- #include "components/viz/host/host_frame_sink_manager.h"
- #include "ui/aura/client/aura_constants.h"
- #include "ui/aura/env.h"
- #include "ui/aura/window.h"
- #include "ui/compositor/compositor.h"
- #include "ui/compositor/layer.h"
- #include "ui/gfx/geometry/rect.h"
- #include "ui/gfx/geometry/size_conversions.h"
- namespace exo {
- NotificationSurface::NotificationSurface(NotificationSurfaceManager* manager,
- Surface* surface,
- const std::string& notification_key)
- : SurfaceTreeHost("ExoNotificationSurface"),
- manager_(manager),
- notification_key_(notification_key) {
- surface->AddSurfaceObserver(this);
- SetRootSurface(surface);
- host_window()->Show();
- host_window()->AddObserver(this);
- }
- NotificationSurface::~NotificationSurface() {
- if (host_window())
- host_window()->RemoveObserver(this);
- if (added_to_manager_)
- manager_->RemoveSurface(this);
- if (root_surface())
- root_surface()->RemoveSurfaceObserver(this);
- }
- gfx::Size NotificationSurface::GetContentSize() const {
- float int_part;
- DCHECK(std::modf(root_surface()->content_size().width(), &int_part) == 0.0f &&
- std::modf(root_surface()->content_size().height(), &int_part) == 0.0f);
- return gfx::ToRoundedSize(root_surface()->content_size());
- }
- void NotificationSurface::SetApplicationId(const char* application_id) {
- SetShellApplicationId(host_window(), absl::make_optional(application_id));
- }
- void NotificationSurface::OnSurfaceCommit() {
- SurfaceTreeHost::OnSurfaceCommit();
- // Defer AddSurface until there are contents to show.
- if (!added_to_manager_ && !host_window()->bounds().IsEmpty()) {
- added_to_manager_ = true;
- manager_->AddSurface(this);
- }
- // Only submit a compositor frame if the notification is being shown.
- // Submitting compositor frames while invisible causes Viz to hold on to
- // references to each notification buffer while it waits for an embedding (
- // or a timeout occurs). This can cause buffer starvation on the Android side,
- // leading to ANRs.
- if (is_embedded_)
- SubmitCompositorFrame();
- }
- void NotificationSurface::OnSurfaceDestroying(Surface* surface) {
- DCHECK_EQ(surface, root_surface());
- surface->RemoveSurfaceObserver(this);
- SetRootSurface(nullptr);
- }
- void NotificationSurface::OnWindowDestroying(aura::Window* window) {
- window->RemoveObserver(this);
- }
- void NotificationSurface::OnWindowPropertyChanged(aura::Window* window,
- const void* key,
- intptr_t old_value) {
- if (key == aura::client::kSkipImeProcessing) {
- SetSkipImeProcessingToDescendentSurfaces(
- window, window->GetProperty(aura::client::kSkipImeProcessing));
- }
- }
- void NotificationSurface::OnWindowAddedToRootWindow(aura::Window* window) {
- // Force recreating resources to submit the compositor frame w/o
- // commit request.
- root_surface()->SurfaceHierarchyResourcesLost();
- SubmitCompositorFrame();
- is_embedded_ = true;
- }
- void NotificationSurface::OnWindowRemovingFromRootWindow(
- aura::Window* window,
- aura::Window* new_root) {
- if (!new_root) {
- // Submit an empty compositor frame if the notification becomes invisible to
- // notify Viz that it can release its reference to the existing notification
- // buffer. We can't just evict the surface, because LayerTreeFrameSinkHolder
- // needs to hold on to resources that were used in the previous frame, if it
- // was associated with a different local surface id.
- SubmitEmptyCompositorFrame();
- // Evict the current surface. We can't only submit
- // an empty compositor frame, because then when re-opening the message
- // center, Viz may think it can use the empty compositor frame to display.
- // This will force viz to wait the given deadline for the next notification
- // compositor frame when showing the message center. This is to prevent
- // flashes when opening the message center.
- aura::Env::GetInstance()
- ->context_factory()
- ->GetHostFrameSinkManager()
- ->EvictSurfaces({host_window()->GetSurfaceId()});
- // Allocate a new local surface id for the next compositor frame.
- host_window()->AllocateLocalSurfaceId();
- is_embedded_ = false;
- // Set the deadline to default so Viz waits a while for the notification
- // compositor frame to arrive before showing the message center.
- host_window()->layer()->SetShowSurface(
- host_window()->GetSurfaceId(), host_window()->bounds().size(),
- SK_ColorWHITE, cc::DeadlinePolicy::UseDefaultDeadline(),
- /*stretch_content_to_fill_bounds=*/false);
- }
- }
- } // namespace exo
|