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 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
|
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/common/cursors/webcursor.h"
#include <stddef.h>
#include <optional>
#include "build/build_config.h"
#include "content/public/test/test_renderer_host.h"
#include "testing/gtest/include/gtest/gtest.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/mojom/cursor_type.mojom-shared.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/display/screen_base.h"
#include "ui/display/test/test_screen.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/skia_conversions.h"
#include "ui/gfx/image/image_unittest_util.h"
#include "ui/wm/core/cursor_loader.h"
#if BUILDFLAG(IS_WIN)
#include <windows.h>
#include "ui/base/win/win_cursor.h"
#endif
namespace content {
namespace {
class TestScreen : public display::test::TestScreen {
public:
explicit TestScreen(display::Display display)
: display::test::TestScreen(/*create_display=*/false,
/*register_screen=*/true) {
display_list().AddDisplay(display, display::DisplayList::Type::PRIMARY);
}
};
TEST(WebCursorTest, DefaultConstructor) {
WebCursor webcursor;
EXPECT_EQ(ui::mojom::CursorType::kNull, webcursor.cursor().type());
}
TEST(WebCursorTest, WebCursorCursorConstructor) {
ui::Cursor cursor(ui::mojom::CursorType::kHand);
WebCursor webcursor(cursor);
EXPECT_EQ(cursor, webcursor.cursor());
}
TEST(WebCursorTest, WebCursorCursorConstructorCustom) {
const ui::Cursor cursor = ui::Cursor::NewCustom(
gfx::test::CreateBitmap(/*size=*/32), gfx::Point(10, 20), 2.0f);
WebCursor webcursor(cursor);
EXPECT_EQ(cursor, webcursor.cursor());
#if defined(USE_AURA)
auto cursor_shape_client = std::make_unique<wm::CursorLoader>();
aura::client::SetCursorShapeClient(cursor_shape_client.get());
// Test if the custom cursor is correctly cached and updated
// on aura platform.
EXPECT_FALSE(webcursor.has_custom_cursor_for_test());
gfx::NativeCursor native_cursor = webcursor.GetNativeCursor();
EXPECT_EQ(gfx::Point(5, 10), native_cursor.custom_hotspot());
EXPECT_TRUE(webcursor.has_custom_cursor_for_test());
// Test if the rotating custom cursor works correctly.
display::Display display(/*id=*/1);
display.set_panel_rotation(display::Display::ROTATE_90);
TestScreen screen(display);
webcursor.UpdateDisplayInfoForWindow(nullptr);
#if BUILDFLAG(IS_CHROMEOS)
EXPECT_FALSE(webcursor.has_custom_cursor_for_test());
#else
EXPECT_TRUE(webcursor.has_custom_cursor_for_test());
#endif
native_cursor = webcursor.GetNativeCursor();
EXPECT_TRUE(webcursor.has_custom_cursor_for_test());
#if BUILDFLAG(IS_CHROMEOS)
// Hotspot should be scaled & rotated. We're using the icon created for 2.0,
// on the display with dsf=1.0, so the hotspot should be
// ((32 - 20) / 2, 10 / 2) = (6, 5).
EXPECT_EQ(gfx::Point(6, 5), native_cursor.custom_hotspot());
#else
// For non-CrOS platforms, the cursor mustn't be rotated as logical and
// physical location is the same.
EXPECT_EQ(gfx::Point(5, 10), native_cursor.custom_hotspot());
#endif
aura::client::SetCursorShapeClient(nullptr);
#endif // defined(USE_AURA)
}
#if defined(USE_AURA)
TEST(WebCursorTest, CursorScaleFactor) {
auto cursor_shape_client = std::make_unique<wm::CursorLoader>();
aura::client::SetCursorShapeClient(cursor_shape_client.get());
constexpr float kImageScale = 2.0f;
constexpr float kDeviceScale = 4.2f;
WebCursor webcursor(ui::Cursor::NewCustom(
gfx::test::CreateBitmap(/*size=*/128), gfx::Point(0, 1), kImageScale));
display::Display display(/*id=*/1);
display.set_device_scale_factor(kDeviceScale);
TestScreen screen(display);
webcursor.UpdateDisplayInfoForWindow(nullptr);
#if BUILDFLAG(IS_CHROMEOS)
// In Ash, the size of the cursor is capped at 64px unless the hardware
// advertises support for bigger cursors.
const gfx::Size kDefaultMaxSize = gfx::Size(64, 64);
EXPECT_EQ(gfx::SkISizeToSize(
webcursor.GetNativeCursor().custom_bitmap().dimensions()),
kDefaultMaxSize);
#else
EXPECT_EQ(
gfx::SkISizeToSize(
webcursor.GetNativeCursor().custom_bitmap().dimensions()),
gfx::ScaleToFlooredSize(gfx::Size(128, 128), kDeviceScale / kImageScale));
#endif
// The scale factor of the cursor image should match the device scale factor,
// regardless of the cursor size.
EXPECT_EQ(webcursor.GetNativeCursor().image_scale_factor(), kDeviceScale);
aura::client::SetCursorShapeClient(nullptr);
}
#endif // defined(USE_AURA)
#if BUILDFLAG(IS_WIN)
void ScaleCursor(float scale, int hotspot_x, int hotspot_y) {
WebCursor webcursor(ui::Cursor::NewCustom(
gfx::test::CreateBitmap(/*size=*/10), gfx::Point(hotspot_x, hotspot_y)));
display::Display display(/*id=*/1);
display.set_device_scale_factor(scale);
TestScreen screen(display);
webcursor.UpdateDisplayInfoForWindow(nullptr);
HCURSOR windows_cursor_handle =
ui::WinCursor::FromPlatformCursor(webcursor.GetNativeCursor().platform())
->hcursor();
EXPECT_NE(nullptr, windows_cursor_handle);
ICONINFO windows_icon_info;
EXPECT_TRUE(GetIconInfo(windows_cursor_handle, &windows_icon_info));
EXPECT_FALSE(windows_icon_info.fIcon);
EXPECT_EQ(static_cast<DWORD>(scale * hotspot_x), windows_icon_info.xHotspot);
EXPECT_EQ(static_cast<DWORD>(scale * hotspot_y), windows_icon_info.yHotspot);
}
TEST(WebCursorTest, WindowsCursorScaledAtHiDpi) {
auto cursor_shape_client = std::make_unique<wm::CursorLoader>();
aura::client::SetCursorShapeClient(cursor_shape_client.get());
ScaleCursor(2.0f, 4, 6);
ScaleCursor(1.5f, 2, 8);
ScaleCursor(1.25f, 3, 7);
aura::client::SetCursorShapeClient(nullptr);
}
#endif
} // namespace
} // namespace content
|