blob: 2cb960196d4a5405b28749c265c0809c3d4811f5 [file]
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/wm/core/cursor_loader.h"
#include "base/memory/scoped_refptr.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/aura/client/cursor_shape_client.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/cursor/cursor_factory.h"
#include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
#include "ui/base/cursor/platform_cursor.h"
#include "ui/base/layout.h"
#include "ui/base/resource/resource_scale_factor.h"
#include "ui/display/display.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/image/image_unittest_util.h"
#include "ui/gfx/skia_util.h"
#include "ui/wm/core/cursor_util.h"
namespace wm {
using ::ui::mojom::CursorType;
TEST(CursorLoaderTest, InvisibleCursor) {
CursorLoader cursor_loader;
ui::Cursor invisible_cursor(CursorType::kNone);
cursor_loader.SetPlatformCursor(&invisible_cursor);
EXPECT_EQ(
invisible_cursor.platform(),
ui::CursorFactory::GetInstance()->GetDefaultCursor(CursorType::kNone));
}
TEST(CursorLoaderTest, GetCursorData) {
// Make sure we always use the fallback cursors, so the test works the same
// in all platforms.
CursorLoader cursor_loader(/*use_platform_cursors=*/false);
display::Display display = display::Display::GetDefaultDisplay();
for (const float scale : {0.8f, 1.0f, 1.25f, 1.5f, 2.0f, 3.0f}) {
SCOPED_TRACE(testing::Message() << "scale " << scale);
display.set_device_scale_factor(scale);
cursor_loader.SetDisplay(display);
const float resource_scale = ui::GetScaleForResourceScaleFactor(
ui::GetSupportedResourceScaleFactor(scale));
for (const ui::CursorSize cursor_size :
{ui::CursorSize::kNormal, ui::CursorSize::kLarge}) {
SCOPED_TRACE(testing::Message()
<< "size " << static_cast<int>(cursor_size));
cursor_loader.SetSize(cursor_size);
const ui::Cursor invisible_cursor = CursorType::kNone;
absl::optional<ui::CursorData> cursor_loader_data =
cursor_loader.GetCursorData(invisible_cursor);
ASSERT_TRUE(cursor_loader_data);
EXPECT_TRUE(cursor_loader_data->bitmaps[0].isNull());
EXPECT_TRUE(cursor_loader_data->hotspot.IsOrigin());
for (const ui::Cursor cursor :
{CursorType::kPointer, CursorType::kWait}) {
SCOPED_TRACE(cursor.type());
cursor_loader_data = cursor_loader.GetCursorData(cursor);
ASSERT_TRUE(cursor_loader_data);
const auto cursor_data =
GetCursorData(cursor.type(), cursor_size, resource_scale,
display.panel_rotation());
ASSERT_TRUE(cursor_data);
ASSERT_EQ(cursor_loader_data->bitmaps.size(),
cursor_data->bitmaps.size());
for (size_t i = 0; i < cursor_data->bitmaps.size(); i++) {
EXPECT_TRUE(gfx::BitmapsAreEqual(cursor_loader_data->bitmaps[i],
cursor_data->bitmaps[i]));
}
EXPECT_EQ(cursor_loader_data->hotspot, cursor_data->hotspot);
}
}
}
const SkBitmap kBitmap = gfx::test::CreateBitmap(20, 20);
constexpr gfx::Point kHotspot = gfx::Point(10, 10);
const ui::Cursor custom_cursor = ui::Cursor::NewCustom(kBitmap, kHotspot);
absl::optional<ui::CursorData> cursor_data =
cursor_loader.GetCursorData(custom_cursor);
ASSERT_TRUE(cursor_data);
EXPECT_EQ(cursor_data->bitmaps[0].getGenerationID(),
kBitmap.getGenerationID());
EXPECT_EQ(cursor_data->hotspot, kHotspot);
}
// Test the cursor image cache when fallbacks for system cursors are used.
TEST(CursorLoaderTest, ImageCursorCache) {
display::Display display = display::Display::GetDefaultDisplay();
CursorLoader cursor_loader(/*use_platform_cursors=*/false);
cursor_loader.SetDisplay(display);
ui::Cursor cursor(CursorType::kPointer);
cursor_loader.SetPlatformCursor(&cursor);
// CursorLoader should keep a ref in its cursor cache.
auto platform_cursor = cursor.platform();
cursor.SetPlatformCursor(nullptr);
EXPECT_FALSE(platform_cursor->HasOneRef());
// Invalidate the cursor cache by changing the rotation.
display.set_panel_rotation(display::Display::ROTATE_90);
cursor_loader.SetDisplay(display);
EXPECT_TRUE(platform_cursor->HasOneRef());
// Invalidate the cursor cache by changing the scale.
cursor_loader.SetPlatformCursor(&cursor);
platform_cursor = cursor.platform();
cursor.SetPlatformCursor(nullptr);
EXPECT_FALSE(platform_cursor->HasOneRef());
display.set_device_scale_factor(display.device_scale_factor() * 2);
cursor_loader.SetDisplay(display);
EXPECT_TRUE(platform_cursor->HasOneRef());
}
} // namespace wm