blob: 225d5267556bcd595f061f55f58957cf6cd43357 [file] [log] [blame]
// Copyright 2021 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/views/widget/desktop_aura/window_shape_updater.h"
#include "ui/gfx/skia_util.h"
#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h"
namespace {
std::unique_ptr<ui::Layer::ShapeRects> ConvertToShapeRects(const SkPath& path) {
// Converts to ShapeRects from SkPath.
auto shape_rects = std::make_unique<ui::Layer::ShapeRects>();
SkRegion clip_region;
clip_region.setRect(path.getBounds().round());
SkRegion region;
region.setPath(path, clip_region);
for (SkRegion::Iterator it(region); !it.done(); it.next())
shape_rects->push_back(gfx::SkIRectToRect(it.rect()));
return shape_rects;
}
} // namespace
namespace views {
// static
WindowShapeUpdater* WindowShapeUpdater::CreateWindowShapeUpdater(
DesktopWindowTreeHostPlatform* tree_host,
DesktopNativeWidgetAura* native_widget_aura) {
return new WindowShapeUpdater(tree_host, native_widget_aura);
}
WindowShapeUpdater::WindowShapeUpdater(
DesktopWindowTreeHostPlatform* tree_host,
DesktopNativeWidgetAura* native_widget_aura)
: tree_host_(tree_host), native_widget_aura_(native_widget_aura) {
tree_host_->GetContentWindow()->AddObserver(this);
UpdateWindowShapeFromWindowMask(tree_host_->GetContentWindow());
}
void WindowShapeUpdater::OnWindowBoundsChanged(
aura::Window* window,
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds,
ui::PropertyChangeReason reason) {
UpdateWindowShapeFromWindowMask(window);
}
void WindowShapeUpdater::OnWindowDestroying(aura::Window* window) {
window->RemoveObserver(this);
delete this;
}
void WindowShapeUpdater::UpdateWindowShapeFromWindowMask(aura::Window* window) {
// If |ui::Layer::alpha_shape_| is set explicitly from SetShape,
// we don't need to set default window mask from non_client_view.
if (tree_host_->is_shape_explicitly_set())
return;
// WindowTransparency should be updated as well when the window shape is
// changed. When a window mask exists, transparent should be true to prevent
// compositor from filling the entire screen in AppendQuadsToFillScreen.
// Otherwise, transparent should be false.
native_widget_aura_->UpdateWindowTransparency();
base::Optional<SkPath> path =
tree_host_->GetWindowMaskForWindowShape(window->bounds().size());
if (path.has_value()) {
// SetAlphaShape to the layer of |content_window_|
window->layer()->SetAlphaShape(ConvertToShapeRects(path.value()));
} else {
window->layer()->SetAlphaShape(nullptr);
}
}
} // namespace views