From 4605be79a582881a1987b79694437be52df959af Mon Sep 17 00:00:00 2001 From: "estade@chromium.org" Date: Wed, 11 Aug 2010 04:17:09 +0000 Subject: Clamp the hotspot on custom cursors to the custom cursor image's dimensions. Current behavior: windows chrome - respect the crazy hotspot linux chrome - crash mac chrome - fall back to normal cursor firefox - clamp the hotspot to the custom cursor image bounds. So this unifies the behavior of all 3 chrome platforms and matches firefox. BUG=51709 TEST=see bug for reduction Review URL: http://codereview.chromium.org/3168003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@55669 0039d316-1c4b-4281-b951-d872f2087c98 --- webkit/glue/webcursor.cc | 13 +++++++++++++ webkit/glue/webcursor.h | 3 +++ webkit/glue/webcursor_unittest.cc | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+) (limited to 'webkit/glue') diff --git a/webkit/glue/webcursor.cc b/webkit/glue/webcursor.cc index f09372c..8f76ef9 100644 --- a/webkit/glue/webcursor.cc +++ b/webkit/glue/webcursor.cc @@ -57,6 +57,7 @@ void WebCursor::InitFromCursorInfo(const WebCursorInfo& cursor_info) { hotspot_ = cursor_info.hotSpot; if (IsCustom()) SetCustomData(cursor_info.customImage); + ClampHotspot(); } void WebCursor::GetCursorInfo(WebCursorInfo* cursor_info) const { @@ -100,6 +101,7 @@ bool WebCursor::Deserialize(const Pickle* pickle, void** iter) { hotspot_.set_y(hotspot_y); custom_size_.set_width(size_x); custom_size_.set_height(size_y); + ClampHotspot(); custom_data_.clear(); if (data_len > 0) { @@ -192,3 +194,14 @@ void WebCursor::ImageFromCustomData(WebImage* image) const { image->assign(bitmap); } #endif + +void WebCursor::ClampHotspot() { + if (!IsCustom()) + return; + + // Clamp the hotspot to the custom image's dimensions. + hotspot_.set_x(std::max(0, + std::min(custom_size_.width() - 1, hotspot_.x()))); + hotspot_.set_y(std::max(0, + std::min(custom_size_.height() - 1, hotspot_.y()))); +} diff --git a/webkit/glue/webcursor.h b/webkit/glue/webcursor.h index 293bd74..35eb001 100644 --- a/webkit/glue/webcursor.h +++ b/webkit/glue/webcursor.h @@ -127,6 +127,9 @@ class WebCursor { void SetCustomData(const WebKit::WebImage& image); void ImageFromCustomData(WebKit::WebImage* image) const; + // Clamp the hotspot to the custom image's bounds, if this is a custom cursor. + void ClampHotspot(); + // WebCore::PlatformCursor type. int type_; diff --git a/webkit/glue/webcursor_unittest.cc b/webkit/glue/webcursor_unittest.cc index 5c1ddfe..6e7701d 100644 --- a/webkit/glue/webcursor_unittest.cc +++ b/webkit/glue/webcursor_unittest.cc @@ -4,9 +4,12 @@ #include "base/pickle.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/WebKit/WebKit/chromium/public/WebCursorInfo.h" #include "webkit/glue/webcursor.h" #include "webkit/tools/test_shell/test_shell_test.h" +using WebKit::WebCursorInfo; + TEST(WebCursorTest, CursorSerialization) { WebCursor custom_cursor; // This is a valid custom cursor. @@ -80,3 +83,36 @@ TEST(WebCursorTest, CursorSerialization) { EXPECT_FALSE(custom_cursor.Deserialize(&neg_custom_pickle, &iter)); } +TEST(WebCursorTest, ClampHotspot) { + WebCursor custom_cursor; + // This is a valid custom cursor. + Pickle ok_custom_pickle; + // Type and hotspots. + ok_custom_pickle.WriteInt(WebCursorInfo::TypeCustom); + // Hotspot is invalid --- outside the bounds of the image. + ok_custom_pickle.WriteInt(5); + ok_custom_pickle.WriteInt(5); + // X & Y + ok_custom_pickle.WriteInt(2); + ok_custom_pickle.WriteInt(2); + // Data len including enough data for a 2x2 image. + ok_custom_pickle.WriteInt(4 * 4); + for (size_t i = 0; i < 4; i++) + ok_custom_pickle.WriteUInt32(0); + // Custom Windows message. + ok_custom_pickle.WriteUInt32(0); + void* iter = NULL; + ASSERT_TRUE(custom_cursor.Deserialize(&ok_custom_pickle, &iter)); + + // Convert to WebCursorInfo, make sure the hotspot got clamped. + WebCursorInfo info; + custom_cursor.GetCursorInfo(&info); + EXPECT_EQ(gfx::Point(1, 1), gfx::Point(info.hotSpot)); + + // Set hotspot to an invalid point again, pipe back through WebCursor, + // and make sure the hotspot got clamped again. + info.hotSpot = gfx::Point(-1, -1); + custom_cursor.InitFromCursorInfo(info); + custom_cursor.GetCursorInfo(&info); + EXPECT_EQ(gfx::Point(0, 0), gfx::Point(info.hotSpot)); +} -- cgit v1.1