summaryrefslogtreecommitdiff
path: root/chromium/ui/aura/mus/client_surface_embedder.cc
blob: 21913636c500310e2d4820ae7536a13a8d869fbf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// 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 "ui/aura/window.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_owner.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),
      surface_layer_owner_(std::make_unique<ui::LayerOwner>(
          std::make_unique<ui::Layer>(ui::LAYER_TEXTURED))),
      inject_gutter_(inject_gutter),
      client_area_insets_(client_area_insets) {
  surface_layer_owner_->layer()->SetMasksToBounds(true);
  // The frame provided by the parent window->layer() needs to show through
  // the surface layer.
  surface_layer_owner_->layer()->SetFillsBoundsOpaquely(false);

  window_->layer()->Add(surface_layer_owner_->layer());

  // 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_owner_->layer());
}

ClientSurfaceEmbedder::~ClientSurfaceEmbedder() = default;

void ClientSurfaceEmbedder::SetPrimarySurfaceId(
    const viz::SurfaceId& surface_id) {
  surface_layer_owner_->layer()->SetShowPrimarySurface(
      surface_id, window_->bounds().size(), SK_ColorWHITE,
      cc::DeadlinePolicy::UseDefaultDeadline(),
      false /* stretch_content_to_fill_bounds */);
}

void ClientSurfaceEmbedder::SetFallbackSurfaceInfo(
    const viz::SurfaceInfo& surface_info) {
  fallback_surface_info_ = surface_info;
  surface_layer_owner_->layer()->SetFallbackSurfaceId(surface_info.id());
  UpdateSizeAndGutters();
}

void ClientSurfaceEmbedder::UpdateSizeAndGutters() {
  surface_layer_owner_->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_owner_ = std::make_unique<ui::LayerOwner>(
        std::make_unique<ui::Layer>(ui::LAYER_SOLID_COLOR));
    // TODO(fsamuel): Use the embedded client's background color.
    right_gutter_owner_->layer()->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_owner_->layer()->SetBounds(gfx::Rect(
        client_area_insets_.left() + fallback_surface_size_in_dip.width(),
        client_area_insets_.top(), width, height));
    window_->layer()->Add(right_gutter_owner_->layer());
  } else {
    right_gutter_owner_.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_owner_ = std::make_unique<ui::LayerOwner>(
        std::make_unique<ui::Layer>(ui::LAYER_SOLID_COLOR));
    // TODO(fsamuel): Use the embedded client's background color.
    bottom_gutter_owner_->layer()->SetColor(SK_ColorWHITE);
    int width = fallback_surface_size_in_dip.width();
    int height = window_bounds.height() - fallback_surface_size_in_dip.height();
    bottom_gutter_owner_->layer()->SetBounds(
        gfx::Rect(0, fallback_surface_size_in_dip.height(), width, height));
    window_->layer()->Add(bottom_gutter_owner_->layer());
  } else {
    bottom_gutter_owner_.reset();
  }
  window_->layer()->StackAtTop(surface_layer_owner_->layer());
}

ui::Layer* ClientSurfaceEmbedder::RightGutterForTesting() {
  return right_gutter_owner_ ? right_gutter_owner_->layer() : nullptr;
}

ui::Layer* ClientSurfaceEmbedder::BottomGutterForTesting() {
  return bottom_gutter_owner_ ? bottom_gutter_owner_->layer() : nullptr;
}

const viz::SurfaceId& ClientSurfaceEmbedder::GetPrimarySurfaceIdForTesting()
    const {
  return *surface_layer_owner_->layer()->GetPrimarySurfaceId();
}

}  // namespace aura