blob: 3ae556f7ec997b9e8ebf34527a37f8630bff0767 [file] [log] [blame]
// Copyright 2017 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 "ui/aura/mus/client_surface_embedder.h"
#include "base/memory/ptr_util.h"
#include "components/viz/common/surfaces/stub_surface_reference_factory.h"
#include "ui/aura/window.h"
#include "ui/gfx/geometry/dip_util.h"
namespace aura {
ClientSurfaceEmbedder::ClientSurfaceEmbedder(
Window* window,
bool inject_gutter,
const gfx::Insets& client_area_insets)
: window_(window),
inject_gutter_(inject_gutter),
client_area_insets_(client_area_insets) {
surface_layer_ = std::make_unique<ui::Layer>(ui::LAYER_TEXTURED);
surface_layer_->SetMasksToBounds(true);
// The frame provided by the parent window->layer() needs to show through
// the surface layer.
surface_layer_->SetFillsBoundsOpaquely(false);
window_->layer()->Add(surface_layer_.get());
// Window's layer may contain content from this client (the embedder), e.g.
// this is the case with window decorations provided by Window Manager.
// This content should appear underneath the content of the embedded client.
window_->layer()->StackAtTop(surface_layer_.get());
ref_factory_ = new viz::StubSurfaceReferenceFactory();
}
ClientSurfaceEmbedder::~ClientSurfaceEmbedder() = default;
void ClientSurfaceEmbedder::SetPrimarySurfaceId(
const viz::SurfaceId& surface_id) {
surface_layer_->SetShowPrimarySurface(surface_id, window_->bounds().size(),
ref_factory_);
}
void ClientSurfaceEmbedder::SetFallbackSurfaceInfo(
const viz::SurfaceInfo& surface_info) {
fallback_surface_info_ = surface_info;
surface_layer_->SetFallbackSurfaceId(surface_info.id());
UpdateSizeAndGutters();
}
void ClientSurfaceEmbedder::UpdateSizeAndGutters() {
surface_layer_->SetBounds(gfx::Rect(window_->bounds().size()));
if (!inject_gutter_)
return;
gfx::Size fallback_surface_size_in_dip;
if (fallback_surface_info_.is_valid()) {
float fallback_device_scale_factor =
fallback_surface_info_.device_scale_factor();
fallback_surface_size_in_dip = gfx::ConvertSizeToDIP(
fallback_device_scale_factor, fallback_surface_info_.size_in_pixels());
}
gfx::Rect window_bounds(window_->bounds());
if (!window_->transparent() &&
fallback_surface_size_in_dip.width() < window_bounds.width()) {
right_gutter_ = std::make_unique<ui::Layer>(ui::LAYER_SOLID_COLOR);
// TODO(fsamuel): Use the embedded client's background color.
right_gutter_->SetColor(SK_ColorWHITE);
int width = window_bounds.width() - fallback_surface_size_in_dip.width();
// The right gutter also includes the bottom-right corner, if necessary.
int height = window_bounds.height() - client_area_insets_.height();
right_gutter_->SetBounds(gfx::Rect(
client_area_insets_.left() + fallback_surface_size_in_dip.width(),
client_area_insets_.top(), width, height));
window_->layer()->Add(right_gutter_.get());
} else {
right_gutter_.reset();
}
// Only create a bottom gutter if a fallback surface is available. Otherwise,
// the right gutter will fill the whole window until a fallback is available.
if (!window_->transparent() && !fallback_surface_size_in_dip.IsEmpty() &&
fallback_surface_size_in_dip.height() < window_bounds.height()) {
bottom_gutter_ = std::make_unique<ui::Layer>(ui::LAYER_SOLID_COLOR);
// TODO(fsamuel): Use the embedded client's background color.
bottom_gutter_->SetColor(SK_ColorWHITE);
int width = fallback_surface_size_in_dip.width();
int height = window_bounds.height() - fallback_surface_size_in_dip.height();
bottom_gutter_->SetBounds(
gfx::Rect(0, fallback_surface_size_in_dip.height(), width, height));
window_->layer()->Add(bottom_gutter_.get());
} else {
bottom_gutter_.reset();
}
window_->layer()->StackAtTop(surface_layer_.get());
}
} // namespace aura