Commit be8f1450 authored by Minju Kim's avatar Minju Kim Committed by Chromium LUCI CQ

ozone/wayland: Set opaque/input region for non-rectangular window shape.

In ozone/x11, the region is set to a non-rectangular shape from
GetDefaultWindowMask for the rounded corner of browser frame.
The window region is updated in XWindow::UpdateWindowRegion and
sets in shape of X11 ExtensionManager.

In ozone/wayland, it doesn't get any shape information
from the platform window.

In this CL,
- Introduce PlatformWindowDelegate::GetWindowMaskForWindowShape to get
  the window mask information.
- Create |window_shape_| from window mask for non-rectangular window
  shape.
- Create region from |window_shape_| if it exists and set opaque/input
  region.
- Update |window_shape_| and update opaque/input region

Bug: 1126828
Change-Id: I56c928986526b88cd4b2c5e8fc3b4921f50a372c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2578501Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarMaksim Sisov <msisov@igalia.com>
Reviewed-by: default avatarAntonio Gomes <tonikitoo@igalia.com>
Commit-Queue: MINJU KIM <mkim@igalia.com>
Cr-Commit-Position: refs/heads/master@{#841778}
parent 6425d870
......@@ -369,6 +369,7 @@ source_set("wayland_unittests") {
testonly = true
sources = [
"common/wayland_util_unittest.cc",
"gpu/wayland_overlay_manager_unittest.cc",
"host/wayland_connection_unittest.cc",
"host/wayland_data_device_unittest.cc",
......
......@@ -7,7 +7,10 @@
#include <xdg-shell-client-protocol.h>
#include <xdg-shell-unstable-v6-client-protocol.h>
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkRegion.h"
#include "ui/base/hit_test.h"
#include "ui/gfx/skia_util.h"
#include "ui/ozone/platform/wayland/host/wayland_connection.h"
#include "ui/ozone/platform/wayland/host/wayland_shm_buffer.h"
#include "ui/ozone/platform/wayland/host/wayland_surface.h"
......@@ -276,4 +279,17 @@ gfx::Rect TranslateWindowBoundsToParentDIP(ui::WaylandWindow* window,
1.0 / window->buffer_scale());
}
std::vector<gfx::Rect> CreateRectsFromSkPath(const SkPath& path) {
SkRegion clip_region;
clip_region.setRect(path.getBounds().round());
SkRegion region;
region.setPath(path, clip_region);
std::vector<gfx::Rect> rects;
for (SkRegion::Iterator it(region); !it.done(); it.next())
rects.push_back(gfx::SkIRectToRect(it.rect()));
return rects;
}
} // namespace wl
......@@ -17,6 +17,7 @@
#include "ui/platform_window/platform_window_init_properties.h"
class SkBitmap;
class SkPath;
namespace ui {
class WaylandConnection;
......@@ -87,6 +88,9 @@ ui::WaylandWindow* RootWindowFromWlSurface(wl_surface* surface);
gfx::Rect TranslateWindowBoundsToParentDIP(ui::WaylandWindow* window,
ui::WaylandWindow* parent_window);
// Returns rectangles dictated by SkPath.
std::vector<gfx::Rect> CreateRectsFromSkPath(const SkPath& path);
} // namespace wl
#endif // UI_OZONE_PLATFORM_WAYLAND_COMMON_WAYLAND_UTIL_H_
// Copyright 2020 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/ozone/platform/wayland/common/wayland_util.h"
#include <memory>
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkRect.h"
namespace ui {
class WaylandUtilTest : public testing::Test {};
TEST_F(WaylandUtilTest, TestCreateRectsFromSkPath) {
constexpr int width = 100;
constexpr int height = 100;
// Test1 consists of 2 rectangles from SkPath.
std::vector<gfx::Rect> expectedFor2Rects = {gfx::Rect(1, 0, 98, 1),
gfx::Rect(0, 1, 100, 99)};
SkPath pathFor2Rects;
const SkRect rect = SkRect::MakeIWH(width, height);
constexpr SkScalar corner_radius_scalar = 2.0;
constexpr SkScalar radii[8] = {corner_radius_scalar,
corner_radius_scalar, // top-left
corner_radius_scalar,
corner_radius_scalar, // top-right
0,
0, // bottom-right
0,
0}; // bottom-left
pathFor2Rects.addRoundRect(rect, radii, SkPathDirection::kCW);
EXPECT_EQ(expectedFor2Rects, wl::CreateRectsFromSkPath(pathFor2Rects));
// Test2 consists of 5 rectangles from SkPath.
std::vector<gfx::Rect> expectedFor5Rects = {
gfx::Rect(3, 0, 94, 1), gfx::Rect(1, 1, 98, 2), gfx::Rect(0, 3, 100, 94),
gfx::Rect(1, 97, 98, 2), gfx::Rect(3, 99, 94, 1)};
SkPath pathFor5Rects;
pathFor5Rects.moveTo(0, 3);
pathFor5Rects.lineTo(1, 3);
pathFor5Rects.lineTo(1, 1);
pathFor5Rects.lineTo(3, 1);
pathFor5Rects.lineTo(3, 0);
pathFor5Rects.lineTo(width - 3, 0);
pathFor5Rects.lineTo(width - 3, 1);
pathFor5Rects.lineTo(width - 1, 1);
pathFor5Rects.lineTo(width - 1, 3);
pathFor5Rects.lineTo(width, 3);
pathFor5Rects.lineTo(width, height - 3);
pathFor5Rects.lineTo(width - 1, height - 3);
pathFor5Rects.lineTo(width - 1, height - 1);
pathFor5Rects.lineTo(width - 3, height - 1);
pathFor5Rects.lineTo(width - 3, height);
pathFor5Rects.lineTo(3, height);
pathFor5Rects.lineTo(3, height - 1);
pathFor5Rects.lineTo(1, height - 1);
pathFor5Rects.lineTo(1, height - 3);
pathFor5Rects.lineTo(0, height - 3);
pathFor5Rects.close();
EXPECT_EQ(expectedFor5Rects, wl::CreateRectsFromSkPath(pathFor5Rects));
}
} // namespace ui
......@@ -7,6 +7,7 @@
#include <linux-explicit-synchronization-unstable-v1-client-protocol.h>
#include <viewporter-client-protocol.h>
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/native_widget_types.h"
......@@ -191,16 +192,47 @@ void WaylandSurface::SetOpaqueRegion(const gfx::Rect& region_px) {
if (!root_window_ || !root_window_->IsOpaqueWindow())
return;
wl_surface_set_opaque_region(surface_.get(),
CreateAndAddRegion(region_px).get());
connection_->ScheduleFlush();
}
void WaylandSurface::SetInputRegion(const gfx::Rect& region_px) {
// Don't set input region when use_native_frame is enabled.
if (!root_window_ || root_window_->ShouldUseNativeFrame())
return;
// Sets input region for input events to allow go through and
// for the compositor to ignore the parts of the input region that fall
// outside of the surface.
wl_surface_set_input_region(surface_.get(),
CreateAndAddRegion(region_px).get());
connection_->ScheduleFlush();
}
wl::Object<wl_region> WaylandSurface::CreateAndAddRegion(
const gfx::Rect& region_px) {
DCHECK(root_window_);
wl::Object<wl_region> region(
wl_compositor_create_region(connection_->compositor()));
gfx::Rect region_dip =
gfx::ScaleToEnclosingRect(region_px, 1.f / buffer_scale_);
wl_region_add(region.get(), region_dip.x(), region_dip.y(),
region_dip.width(), region_dip.height());
wl_surface_set_opaque_region(surface_.get(), region.get());
auto add_region = [&](const gfx::Rect& r) {
gfx::Rect region_dip = gfx::ScaleToEnclosingRect(r, 1.f / buffer_scale_);
wl_region_add(region.get(), region_dip.x(), region_dip.y(),
region_dip.width(), region_dip.height());
};
connection_->ScheduleFlush();
if (root_window_->GetWindowShape().has_value()) {
std::vector<gfx::Rect> rectangles = root_window_->GetWindowShape().value();
for (const auto& rect : rectangles)
add_region(rect);
} else {
add_region(region_px);
}
return region;
}
void WaylandSurface::SetViewportSource(const gfx::RectF& src_rect) {
......
......@@ -79,6 +79,13 @@ class WaylandSurface {
// pixels.
void SetOpaqueRegion(const gfx::Rect& region_px);
// Sets the input region on this surface in physical pixels.
// The input region indicates which parts of the surface accept pointer and
// touch input events. This is expected to be called from ToplevelWindow
// whenever the region that the surface span changes or window state changes
// when custom frame is used.
void SetInputRegion(const gfx::Rect& region_px);
// Set the source rectangle of the associated wl_surface.
// See:
// https://cgit.freedesktop.org/wayland/wayland-protocols/tree/stable/viewporter/viewporter.xml
......@@ -98,6 +105,8 @@ class WaylandSurface {
wl::Object<wl_subsurface> CreateSubsurface(WaylandSurface* parent);
private:
wl::Object<wl_region> CreateAndAddRegion(const gfx::Rect& region_px);
WaylandConnection* const connection_;
WaylandWindow* root_window_ = nullptr;
wl::Object<wl_surface> surface_;
......
......@@ -9,6 +9,7 @@
#include "base/run_loop.h"
#include "base/unguessable_token.h"
#include "build/chromeos_buildflags.h"
#include "third_party/skia/include/core/SkPath.h"
#include "ui/base/hit_test.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/ozone/platform/wayland/host/shell_object_factory.h"
......@@ -58,6 +59,10 @@ bool WaylandToplevelWindow::CreateShellToplevel() {
SetSizeConstraints();
TriggerStateChanges();
InitializeAuraShellSurface();
// This could be the proper time to update window mask using
// NonClientView::GetWindowMask, since |non_client_view| is not created yet
// during the call to WaylandWindow::Initialize().
UpdateWindowMask();
return true;
}
......@@ -211,6 +216,8 @@ void WaylandToplevelWindow::SetUseNativeFrame(bool use_native_frame) {
use_native_frame_ = use_native_frame;
if (shell_toplevel_)
SetDecorationMode();
UpdateWindowMask();
}
bool WaylandToplevelWindow::ShouldUseNativeFrame() const {
......@@ -222,6 +229,11 @@ bool WaylandToplevelWindow::ShouldUseNativeFrame() const {
->xdg_decoration_manager_v1();
}
base::Optional<std::vector<gfx::Rect>> WaylandToplevelWindow::GetWindowShape()
const {
return window_shape_;
}
void WaylandToplevelWindow::HandleSurfaceConfigure(int32_t width,
int32_t height,
bool is_maximized,
......@@ -409,4 +421,23 @@ void WaylandToplevelWindow::SetDecorationMode() {
}
}
void WaylandToplevelWindow::UpdateWindowMask() {
// TODO(http://crbug.com/1158733): When supporting PlatformWindow::SetShape,
// update window region with the given |shape|.
WaylandWindow::UpdateWindowMask();
root_surface()->SetInputRegion(GetBounds());
}
void WaylandToplevelWindow::UpdateWindowShape() {
// Create |window_shape_| using the window mask of PlatformWindowDelegate
// otherwise resets it.
base::Optional<SkPath> window_mask = delegate()->GetWindowMaskForWindowShape(
gfx::Size(GetBounds().width(), GetBounds().height()));
if (window_mask.has_value()) {
window_shape_ = wl::CreateRectsFromSkPath(window_mask.value());
} else {
window_shape_.reset();
}
}
} // namespace ui
......@@ -38,7 +38,7 @@ class WaylandToplevelWindow : public WaylandWindow,
int hittest,
const gfx::Point& pointer_location_in_px) override;
// PlatformWindow
// PlatformWindow:
void Show(bool inactive) override;
void Hide() override;
bool IsVisible() const override;
......@@ -55,6 +55,9 @@ class WaylandToplevelWindow : public WaylandWindow,
void SetUseNativeFrame(bool use_native_frame) override;
bool ShouldUseNativeFrame() const override;
// WaylandWindow overrides:
base::Optional<std::vector<gfx::Rect>> GetWindowShape() const override;
private:
// WaylandWindow overrides:
void HandleSurfaceConfigure(int32_t widht,
......@@ -64,6 +67,11 @@ class WaylandToplevelWindow : public WaylandWindow,
bool is_activated) override;
bool OnInitialize(PlatformWindowInitProperties properties) override;
bool IsActive() const override;
// Calls UpdateWindowShape, set_input_region and set_opaque_region
// for this toplevel window.
void UpdateWindowMask() override;
// Update the window shape using the window mask of PlatformWindowDelegate.
void UpdateWindowShape() override;
// WmMoveLoopHandler:
bool RunMoveLoop(const gfx::Vector2d& drag_offset) override;
......@@ -141,6 +149,8 @@ class WaylandToplevelWindow : public WaylandWindow,
// When use_native_frame is true, server-side decoration is set,
// e.g. lacros-taskmanager.
bool use_native_frame_ = false;
base::Optional<std::vector<gfx::Rect>> window_shape_;
};
} // namespace ui
......
......@@ -191,7 +191,7 @@ void WaylandWindow::SetBounds(const gfx::Rect& bounds_px) {
return;
bounds_px_ = bounds_px;
root_surface_->SetOpaqueRegion(gfx::Rect(bounds_px_.size()));
UpdateWindowMask();
delegate_->OnBoundsChanged(bounds_px_);
}
......@@ -394,6 +394,17 @@ void WaylandWindow::OnCloseRequest() {
delegate_->OnCloseRequest();
}
base::Optional<std::vector<gfx::Rect>> WaylandWindow::GetWindowShape() const {
return base::nullopt;
}
void WaylandWindow::UpdateWindowMask() {
UpdateWindowShape();
root_surface_->SetOpaqueRegion(bounds_px_);
}
void WaylandWindow::UpdateWindowShape() {}
void WaylandWindow::OnDragEnter(const gfx::PointF& point,
std::unique_ptr<OSExchangeData> data,
int operation) {
......
......@@ -177,6 +177,8 @@ class WaylandWindow : public PlatformWindow,
virtual void OnDragLeave();
virtual void OnDragSessionClose(uint32_t dnd_action);
virtual base::Optional<std::vector<gfx::Rect>> GetWindowShape() const;
// Returns a root parent window within the same hierarchy.
WaylandWindow* GetRootParentWindow();
......@@ -211,6 +213,9 @@ class WaylandWindow : public PlatformWindow,
void set_ui_scale(int32_t ui_scale) { ui_scale_ = ui_scale; }
// Calls set_opaque_region for this window.
virtual void UpdateWindowMask();
private:
FRIEND_TEST_ALL_PREFIXES(WaylandScreenTest, SetBufferScale);
......@@ -226,6 +231,8 @@ class WaylandWindow : public PlatformWindow,
// Additional initialization of derived classes.
virtual bool OnInitialize(PlatformWindowInitProperties properties) = 0;
virtual void UpdateWindowShape();
// WaylandWindowDragController might need to take ownership of the wayland
// surface whether the window that originated the DND session gets destroyed
// in the middle of that session (e.g: when it is snapped into a tab strip).
......
......@@ -815,6 +815,51 @@ TEST_P(WaylandWindowTest, SendsBoundsOnRequest) {
EXPECT_EQ(restored_bounds, gfx::Rect());
}
TEST_P(WaylandWindowTest, UpdateWindowRegion) {
wl::MockSurface* mock_surface = server_.GetObject<wl::MockSurface>(
window_->root_surface()->GetSurfaceId());
// Change bounds.
const gfx::Rect initial_bounds = window_->GetBounds();
const gfx::Rect new_bounds = gfx::Rect(0, 0, initial_bounds.width() + 10,
initial_bounds.height() + 10);
EXPECT_CALL(*mock_surface, SetOpaqueRegion(_)).Times(1);
EXPECT_CALL(*mock_surface, SetInputRegion(_)).Times(1);
window_->SetBounds(new_bounds);
Sync();
VerifyAndClearExpectations();
EXPECT_EQ(mock_surface->opaque_region(), new_bounds);
EXPECT_EQ(mock_surface->input_region(), new_bounds);
// Maximize.
ScopedWlArray states = InitializeWlArrayWithActivatedState();
EXPECT_CALL(*mock_surface, SetOpaqueRegion(_)).Times(1);
EXPECT_CALL(*mock_surface, SetInputRegion(_)).Times(1);
const gfx::Rect maximized_bounds = gfx::Rect(0, 0, 1024, 768);
window_->Maximize();
AddStateToWlArray(XDG_TOPLEVEL_STATE_MAXIMIZED, states.get());
SendConfigureEvent(xdg_surface_, maximized_bounds.width(),
maximized_bounds.height(), 1, states.get());
Sync();
VerifyAndClearExpectations();
EXPECT_EQ(mock_surface->opaque_region(), maximized_bounds);
EXPECT_EQ(mock_surface->input_region(), maximized_bounds);
// Restore.
const gfx::Rect restored_bounds = window_->GetRestoredBoundsInPixels();
EXPECT_CALL(*mock_surface, SetOpaqueRegion(_)).Times(1);
EXPECT_CALL(*mock_surface, SetInputRegion(_)).Times(1);
window_->Restore();
// Reinitialize wl_array, which removes previous old states.
auto active = InitializeWlArrayWithActivatedState();
SendConfigureEvent(xdg_surface_, 0, 0, 2, active.get());
Sync();
VerifyAndClearExpectations();
EXPECT_EQ(mock_surface->opaque_region(), restored_bounds);
EXPECT_EQ(mock_surface->input_region(), restored_bounds);
}
TEST_P(WaylandWindowTest, CanDispatchMouseEventDefault) {
EXPECT_FALSE(window_->CanDispatchEvent(&test_mouse_event_));
}
......
......@@ -28,7 +28,7 @@ void SetOpaqueRegion(wl_client* client,
void SetInputRegion(wl_client* client,
wl_resource* resource,
wl_resource* region) {
GetUserDataAs<MockSurface>(resource)->SetInputRegion(region);
GetUserDataAs<MockSurface>(resource)->SetInputRegionImpl(region);
}
void Damage(wl_client* client,
......@@ -103,6 +103,10 @@ MockSurface* MockSurface::FromResource(wl_resource* resource) {
}
void MockSurface::SetOpaqueRegionImpl(wl_resource* region) {
if (!region) {
opaque_region_ = gfx::Rect(-1, -1, 0, 0);
return;
}
auto bounds = GetUserDataAs<TestRegion>(region)->getBounds();
opaque_region_ =
gfx::Rect(bounds.fLeft, bounds.fTop, bounds.fRight - bounds.fLeft,
......@@ -111,6 +115,22 @@ void MockSurface::SetOpaqueRegionImpl(wl_resource* region) {
SetOpaqueRegion(region);
}
void MockSurface::SetInputRegionImpl(wl_resource* region) {
// It is unsafe to always treat |region| as a valid pointer.
// According to the protocol about wl_surface::set_input_region
// "A NULL wl_region cuases the input region to be set to infinite."
if (!region) {
input_region_ = gfx::Rect(-1, -1, 0, 0);
return;
}
auto bounds = GetUserDataAs<TestRegion>(region)->getBounds();
input_region_ =
gfx::Rect(bounds.fLeft, bounds.fTop, bounds.fRight - bounds.fLeft,
bounds.fBottom - bounds.fTop);
SetInputRegion(region);
}
void MockSurface::AttachNewBuffer(wl_resource* buffer_resource,
int32_t x,
int32_t y) {
......
......@@ -57,6 +57,7 @@ class MockSurface : public ServerObject {
TestViewport* viewport() { return viewport_; }
gfx::Rect opaque_region() const { return opaque_region_; }
gfx::Rect input_region() const { return input_region_; }
void set_frame_callback(wl_resource* callback_resource) {
DCHECK(!frame_callback_);
......@@ -69,6 +70,7 @@ class MockSurface : public ServerObject {
bool has_role() const { return !!xdg_surface_ || !!sub_surface_; }
void SetOpaqueRegionImpl(wl_resource* region);
void SetInputRegionImpl(wl_resource* region);
void AttachNewBuffer(wl_resource* buffer_resource, int32_t x, int32_t y);
void DestroyPrevAttachedBuffer();
void ReleaseBuffer(wl_resource* buffer);
......@@ -79,6 +81,7 @@ class MockSurface : public ServerObject {
TestSubSurface* sub_surface_ = nullptr;
TestViewport* viewport_ = nullptr;
gfx::Rect opaque_region_ = {-1, -1, 0, 0};
gfx::Rect input_region_ = {-1, -1, 0, 0};
wl_resource* frame_callback_ = nullptr;
......
include_rules = [
"+third_party/skia/include",
"+ui/base",
"+ui/gfx",
]
......@@ -12,12 +12,6 @@
using AtkKeyEventStruct = struct _AtkKeyEventStruct;
#endif
class SkPath;
namespace gfx {
class Size;
}
namespace ui {
class COMPONENT_EXPORT(PLATFORM_WINDOW) X11ExtensionDelegate {
......@@ -30,10 +24,6 @@ class COMPONENT_EXPORT(PLATFORM_WINDOW) X11ExtensionDelegate {
// (menu) windows.
virtual void OnLostMouseGrab() = 0;
// Returns a mask to be used to clip the window for the given
// size. This is used to create the non-rectangular window shape.
virtual void GetWindowMask(const gfx::Size& size, SkPath* window_mask) = 0;
#if BUILDFLAG(USE_ATK)
// Notifies an ATK key event to be processed. The transient parameter will be
// true if the event target is a transient window (e.g. a modal dialog)
......
......@@ -4,6 +4,7 @@
#include "ui/platform_window/platform_window_delegate.h"
#include "third_party/skia/include/core/SkPath.h"
#include "ui/gfx/geometry/size.h"
namespace ui {
......@@ -20,4 +21,9 @@ base::Optional<gfx::Size> PlatformWindowDelegate::GetMaximumSizeForWindow() {
return base::nullopt;
}
base::Optional<SkPath> PlatformWindowDelegate::GetWindowMaskForWindowShape(
const gfx::Size& size_in_pixels) {
return base::nullopt;
}
} // namespace ui
......@@ -14,6 +14,8 @@ class Rect;
class Size;
} // namespace gfx
class SkPath;
namespace ui {
class Event;
......@@ -63,6 +65,11 @@ class COMPONENT_EXPORT(PLATFORM_WINDOW) PlatformWindowDelegate {
virtual base::Optional<gfx::Size> GetMinimumSizeForWindow();
virtual base::Optional<gfx::Size> GetMaximumSizeForWindow();
// Returns a mask to be used to clip the window for the given
// size. This is used to create the non-rectangular window shape.
virtual base::Optional<SkPath> GetWindowMaskForWindowShape(
const gfx::Size& size_in_pixels);
// Called when the location of mouse pointer entered the window. This is
// different from ui::ET_MOUSE_ENTERED which may not be generated when mouse
// is captured either by implicitly or explicitly.
......
......@@ -73,6 +73,21 @@ class TestPlatformWindowDelegate : public PlatformWindowDelegate {
}
void OnActivationChanged(bool active) override {}
void OnMouseEnter() override {}
base::Optional<SkPath> GetWindowMaskForWindowShape(
const gfx::Size& size_in_pixels) override {
SkPath window_mask;
int right = size_in_pixels.width();
int bottom = size_in_pixels.height();
window_mask.moveTo(0, 0);
window_mask.lineTo(0, bottom);
window_mask.lineTo(right, bottom);
window_mask.lineTo(right, 10);
window_mask.lineTo(right - 10, 10);
window_mask.lineTo(right - 10, 0);
window_mask.close();
return window_mask;
}
private:
gfx::AcceleratedWidget widget_ = gfx::kNullAcceleratedWidget;
......@@ -90,18 +105,6 @@ class ShapedX11ExtensionDelegate : public X11ExtensionDelegate {
~ShapedX11ExtensionDelegate() override = default;
void OnLostMouseGrab() override {}
void GetWindowMask(const gfx::Size& size, SkPath* window_mask) override {
int right = size.width();
int bottom = size.height();
window_mask->moveTo(0, 0);
window_mask->lineTo(0, bottom);
window_mask->lineTo(right, bottom);
window_mask->lineTo(right, 10);
window_mask->lineTo(right - 10, 10);
window_mask->lineTo(right - 10, 0);
window_mask->close();
}
#if BUILDFLAG(USE_ATK)
bool OnAtkKeyEvent(AtkKeyEventStruct* atk_key_event,
bool transient) override {
......
......@@ -765,8 +765,10 @@ base::Optional<gfx::Size> X11Window::GetMaximumSizeForXWindow() {
void X11Window::GetWindowMaskForXWindow(const gfx::Size& size,
SkPath* window_mask) {
if (x11_extension_delegate_)
x11_extension_delegate_->GetWindowMask(size, window_mask);
base::Optional<SkPath> path =
platform_window_delegate_->GetWindowMaskForWindowShape(size);
if (path.has_value())
*window_mask = path.value();
}
void X11Window::DispatchHostWindowDragMovement(
......
......@@ -339,17 +339,6 @@ void DesktopWindowTreeHostLinux::DestroyNonClientEventFilter() {
non_client_window_event_filter_.reset();
}
void DesktopWindowTreeHostLinux::GetWindowMask(const gfx::Size& size,
SkPath* window_mask) {
DCHECK(window_mask);
Widget* widget = native_widget_delegate()->AsWidget();
if (widget->non_client_view()) {
// Some frame views define a custom (non-rectangular) window mask. If
// so, use it to define the window shape. If not, fall through.
widget->non_client_view()->GetWindowMask(size, window_mask);
}
}
void DesktopWindowTreeHostLinux::OnLostMouseGrab() {
dispatcher()->OnHostLostMouseGrab();
}
......
......@@ -19,8 +19,6 @@
#include "ui/views/views_export.h"
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h"
class SkPath;
namespace aura {
class ScopedWindowTargeter;
} // namespace aura
......@@ -106,7 +104,6 @@ class VIEWS_EXPORT DesktopWindowTreeHostLinux
void DestroyNonClientEventFilter();
// X11ExtensionDelegate overrides:
void GetWindowMask(const gfx::Size& size, SkPath* window_mask) override;
void OnLostMouseGrab() override;
#if BUILDFLAG(USE_ATK)
bool OnAtkKeyEvent(AtkKeyEventStruct* atk_key_event, bool transient) override;
......
......@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "third_party/skia/include/core/SkPath.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/drag_drop_client.h"
#include "ui/aura/client/focus_client.h"
......@@ -738,6 +739,20 @@ DesktopWindowTreeHostPlatform::GetMaximumSizeForWindow() {
.size();
}
base::Optional<SkPath>
DesktopWindowTreeHostPlatform::GetWindowMaskForWindowShape(
const gfx::Size& size_in_pixels) {
if (GetWidget()->non_client_view()) {
SkPath window_mask;
// Some frame views define a custom (non-rectanguar) window mask.
// If so, use it to define the window shape. If not, fall through.
GetWidget()->non_client_view()->GetWindowMask(size_in_pixels, &window_mask);
if (!window_mask.isEmpty())
return window_mask;
}
return base::nullopt;
}
void DesktopWindowTreeHostPlatform::OnWorkspaceChanged() {
OnHostWorkspaceChanged();
}
......
......@@ -121,6 +121,8 @@ class VIEWS_EXPORT DesktopWindowTreeHostPlatform
void OnActivationChanged(bool active) override;
base::Optional<gfx::Size> GetMinimumSizeForWindow() override;
base::Optional<gfx::Size> GetMaximumSizeForWindow() override;
base::Optional<SkPath> GetWindowMaskForWindowShape(
const gfx::Size& size_in_pixels) override;
// ui::WorkspaceExtensionDelegate:
void OnWorkspaceChanged() override;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment