summaryrefslogtreecommitdiffstats
path: root/webkit
diff options
context:
space:
mode:
Diffstat (limited to 'webkit')
-rw-r--r--webkit/glue/chrome_client_impl.cc16
-rw-r--r--webkit/glue/chrome_client_impl.h3
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl.cc82
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl.h17
-rw-r--r--webkit/glue/webcursor.cc57
-rw-r--r--webkit/glue/webcursor.h59
-rw-r--r--webkit/glue/webcursor_gtk.cc24
-rw-r--r--webkit/glue/webcursor_mac.mm23
-rw-r--r--webkit/glue/webcursor_win.cc83
-rw-r--r--webkit/glue/webplugin_impl.cc9
-rw-r--r--webkit/tools/test_shell/test_webview_delegate.h8
-rw-r--r--webkit/tools/test_shell/test_webview_delegate_gtk.cc5
-rw-r--r--webkit/tools/test_shell/test_webview_delegate_win.cc16
13 files changed, 324 insertions, 78 deletions
diff --git a/webkit/glue/chrome_client_impl.cc b/webkit/glue/chrome_client_impl.cc
index b7cc3ae..471eb14 100644
--- a/webkit/glue/chrome_client_impl.cc
+++ b/webkit/glue/chrome_client_impl.cc
@@ -57,7 +57,8 @@ ChromeClientImpl::ChromeClientImpl(WebViewImpl* webview)
statusbar_visible_(true),
scrollbars_visible_(true),
menubar_visible_(true),
- resizable_(true) {
+ resizable_(true),
+ ignore_next_set_cursor_(false) {
}
ChromeClientImpl::~ChromeClientImpl() {
@@ -472,11 +473,24 @@ void ChromeClientImpl::popupOpened(WebCore::FramelessScrollView* popup_view,
}
void ChromeClientImpl::SetCursor(const WebCursor& cursor) {
+ if (ignore_next_set_cursor_) {
+ ignore_next_set_cursor_ = false;
+ return;
+ }
+
WebViewDelegate* d = webview_->delegate();
if (d)
d->SetCursor(webview_, cursor);
}
+void ChromeClientImpl::SetCursorForPlugin(const WebCursor& cursor) {
+ SetCursor(cursor);
+ // Currently, Widget::setCursor is always called after this function in
+ // EventHandler.cpp and since we don't want that we set a flag indicating
+ // that the next SetCursor call is to be ignored.
+ ignore_next_set_cursor_ = true;
+}
+
void ChromeClientImpl::enableSuddenTermination() {
WebViewDelegate* d = webview_->delegate();
if (d)
diff --git a/webkit/glue/chrome_client_impl.h b/webkit/glue/chrome_client_impl.h
index af39a51..6e059eaa 100644
--- a/webkit/glue/chrome_client_impl.h
+++ b/webkit/glue/chrome_client_impl.h
@@ -120,6 +120,7 @@ public:
bool focus_on_show);
void SetCursor(const WebCursor& cursor);
+ void SetCursorForPlugin(const WebCursor& cursor);
virtual void enableSuddenTermination();
virtual void disableSuddenTermination();
@@ -133,6 +134,8 @@ private:
bool scrollbars_visible_;
bool menubar_visible_;
bool resizable_;
+ // Set to true if the next SetCursor is to be ignored.
+ bool ignore_next_set_cursor_;
};
#endif // WEBKIT_GLUE_CHROME_CLIENT_IMPL_H__
diff --git a/webkit/glue/plugins/webplugin_delegate_impl.cc b/webkit/glue/plugins/webplugin_delegate_impl.cc
index 655a37a..364ae10 100644
--- a/webkit/glue/plugins/webplugin_delegate_impl.cc
+++ b/webkit/glue/plugins/webplugin_delegate_impl.cc
@@ -47,8 +47,8 @@ std::list<MSG> WebPluginDelegateImpl::throttle_queue_;
WebPluginDelegateImpl* WebPluginDelegateImpl::current_plugin_instance_ = NULL;
-bool WebPluginDelegateImpl::track_popup_menu_patched_ = false;
-iat_patch::IATPatchFunction WebPluginDelegateImpl::iat_patch_helper_;
+iat_patch::IATPatchFunction WebPluginDelegateImpl::iat_patch_track_popup_menu_;
+iat_patch::IATPatchFunction WebPluginDelegateImpl::iat_patch_set_cursor_;
WebPluginDelegateImpl* WebPluginDelegateImpl::Create(
const FilePath& filename,
@@ -153,6 +153,7 @@ WebPluginDelegateImpl::WebPluginDelegateImpl(
// agent.
instance_->set_use_mozilla_user_agent();
quirks_ |= PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE;
+ quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR;
} else if (filename == L"nppdf32.dll") {
// Check for the version number above or equal 9.
std::vector<std::wstring> version;
@@ -181,6 +182,7 @@ WebPluginDelegateImpl::WebPluginDelegateImpl(
// Explanation for this quirk can be found in
// WebPluginDelegateImpl::Initialize.
quirks_ |= PLUGIN_QUIRK_PATCH_TRACKPOPUP_MENU;
+ quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR;
}
plugin_module_handle_ = ::GetModuleHandle(filename.c_str());
@@ -260,12 +262,24 @@ bool WebPluginDelegateImpl::Initialize(const GURL& url,
// lives on the browser thread. Our workaround is to intercept the
// TrackPopupMenu API for Silverlight and replace the window handle
// with the dummy activation window.
- if (windowless_ && !track_popup_menu_patched_ &&
+ if (windowless_ && !iat_patch_track_popup_menu_.is_patched() &&
(quirks_ & PLUGIN_QUIRK_PATCH_TRACKPOPUP_MENU)) {
- iat_patch_helper_.Patch(plugin_module_handle_, "user32.dll",
- "TrackPopupMenu",
- WebPluginDelegateImpl::TrackPopupMenuPatch);
- track_popup_menu_patched_ = true;
+ iat_patch_track_popup_menu_.Patch(
+ plugin_module_handle_, "user32.dll", "TrackPopupMenu",
+ WebPluginDelegateImpl::TrackPopupMenuPatch);
+ }
+
+ // Windowless plugins can set cursors by calling the SetCursor API. This
+ // works because the thread inputs of the browser UI thread and the plugin
+ // thread are attached. We intercept the SetCursor API for windowless plugins
+ // and remember the cursor being set. This is shipped over to the browser
+ // in the HandleEvent call, which ensures that the cursor does not change
+ // when a windowless plugin instance changes the cursor in a background tab.
+ if (windowless_ && !iat_patch_set_cursor_.is_patched() &&
+ (quirks_ & PLUGIN_QUIRK_PATCH_SETCURSOR)) {
+ iat_patch_set_cursor_.Patch(plugin_module_handle_, "user32.dll",
+ "SetCursor",
+ WebPluginDelegateImpl::SetCursorPatch);
}
return true;
}
@@ -287,6 +301,19 @@ void WebPluginDelegateImpl::DestroyInstance() {
instance_->set_web_plugin(NULL);
+ if (instance_->plugin_lib()) {
+ // Unpatch if this is the last plugin instance.
+ if (instance_->plugin_lib()->instance_count() == 1) {
+ if (iat_patch_set_cursor_.is_patched()) {
+ iat_patch_set_cursor_.Unpatch();
+ }
+
+ if (iat_patch_track_popup_menu_.is_patched()) {
+ iat_patch_track_popup_menu_.Unpatch();
+ }
+ }
+ }
+
instance_ = 0;
}
}
@@ -801,6 +828,8 @@ LRESULT CALLBACK WebPluginDelegateImpl::NativeWndProc(
return TRUE;
}
+ current_plugin_instance_ = delegate;
+
switch (message) {
case WM_NCDESTROY: {
RemoveProp(hwnd, kWebPluginDelegateProperty);
@@ -818,6 +847,7 @@ LRESULT CALLBACK WebPluginDelegateImpl::NativeWndProc(
if (delegate->quirks() & PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE) {
WebPluginDelegateImpl::ThrottleMessage(delegate->plugin_wnd_proc_, hwnd,
message, wparam, lparam);
+ current_plugin_instance_ = NULL;
return FALSE;
}
break;
@@ -844,6 +874,7 @@ LRESULT CALLBACK WebPluginDelegateImpl::NativeWndProc(
LRESULT result = CallWindowProc(delegate->plugin_wnd_proc_, hwnd, message,
wparam, lparam);
delegate->is_calling_wndproc = false;
+ current_plugin_instance_ = NULL;
return result;
}
@@ -998,12 +1029,11 @@ bool WebPluginDelegateImpl::HandleEvent(NPEvent* event,
bool ret = instance()->NPP_HandleEvent(event) != 0;
- // Snag a reference to the current cursor ASAP in case the plugin modified
- // it. There is a nasty race condition here with the multiprocess browser
- // as someone might be setting the cursor in the main process as well.
- HCURSOR last_cursor;
- if (WM_MOUSEMOVE == event->event) {
- last_cursor = ::GetCursor();
+ if (event->event == WM_MOUSEMOVE) {
+ // Snag a reference to the current cursor ASAP in case the plugin modified
+ // it. There is a nasty race condition here with the multiprocess browser
+ // as someone might be setting the cursor in the main process as well.
+ *cursor = current_windowless_cursor_;
}
if (pop_user_gesture) {
@@ -1032,10 +1062,6 @@ bool WebPluginDelegateImpl::HandleEvent(NPEvent* event,
::SetFocus(prev_focus_window);
}
- if (WM_MOUSEMOVE == event->event) {
- cursor->InitFromCursor(last_cursor);
- }
-
return ret;
}
@@ -1124,3 +1150,25 @@ BOOL WINAPI WebPluginDelegateImpl::TrackPopupMenuPatch(
}
return TrackPopupMenu(menu, flags, x, y, reserved, window, rect);
}
+
+HCURSOR WINAPI WebPluginDelegateImpl::SetCursorPatch(HCURSOR cursor) {
+ // The windowless flash plugin periodically calls SetCursor in a wndproc
+ // instantiated on the plugin thread. This causes annoying cursor flicker
+ // when the mouse is moved on a foreground tab, with a windowless plugin
+ // instance in a background tab. We just ignore the call here.
+ if (!current_plugin_instance_)
+ return GetCursor();
+
+ if (!current_plugin_instance_->windowless()) {
+ return SetCursor(cursor);
+ }
+
+ // It is ok to pass NULL here to GetCursor as we are not looking for cursor
+ // types defined by Webkit.
+ HCURSOR previous_cursor =
+ current_plugin_instance_->current_windowless_cursor_.GetCursor(NULL);
+
+ current_plugin_instance_->current_windowless_cursor_.InitFromExternalCursor(
+ cursor);
+ return previous_cursor;
+}
diff --git a/webkit/glue/plugins/webplugin_delegate_impl.h b/webkit/glue/plugins/webplugin_delegate_impl.h
index a89189c..85c14dc 100644
--- a/webkit/glue/plugins/webplugin_delegate_impl.h
+++ b/webkit/glue/plugins/webplugin_delegate_impl.h
@@ -93,6 +93,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
PLUGIN_QUIRK_DONT_ALLOW_MULTIPLE_INSTANCES = 16,
PLUGIN_QUIRK_DIE_AFTER_UNLOAD = 32,
PLUGIN_QUIRK_PATCH_TRACKPOPUP_MENU = 64,
+ PLUGIN_QUIRK_PATCH_SETCURSOR = 128,
};
int quirks() { return quirks_; }
@@ -264,11 +265,8 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
// The plugin module handle.
HMODULE plugin_module_handle_;
- // Indicates whether we IAT patched the TrackPopupMenu function.
- static bool track_popup_menu_patched_;
-
- // Helper object for patching the import table of Silverlight.
- static iat_patch::IATPatchFunction iat_patch_helper_;
+ // Helper object for patching the TrackPopupMenu API
+ static iat_patch::IATPatchFunction iat_patch_track_popup_menu_;
// TrackPopupMenu interceptor. Parameters are the same as the Win32 function
// TrackPopupMenu.
@@ -276,6 +274,15 @@ class WebPluginDelegateImpl : public WebPluginDelegate {
int y, int reserved, HWND window,
const RECT* rect);
+ // SetCursor interceptor for windowless plugins.
+ static HCURSOR WINAPI SetCursorPatch(HCURSOR cursor);
+
+ // Helper object for patching the SetCursor API
+ static iat_patch::IATPatchFunction iat_patch_set_cursor_;
+
+ // Holds the current cursor set by the windowless plugin.
+ WebCursor current_windowless_cursor_;
+
DISALLOW_EVIL_CONSTRUCTORS(WebPluginDelegateImpl);
};
diff --git a/webkit/glue/webcursor.cc b/webkit/glue/webcursor.cc
index 4c943c3..76673e5 100644
--- a/webkit/glue/webcursor.cc
+++ b/webkit/glue/webcursor.cc
@@ -14,6 +14,7 @@
WebCursor::WebCursor()
: type_(WebCore::PlatformCursor::typePointer) {
+ InitPlatformData();
}
WebCursor::WebCursor(const WebCore::PlatformCursor& platform_cursor)
@@ -21,10 +22,31 @@ WebCursor::WebCursor(const WebCore::PlatformCursor& platform_cursor)
hotspot_(platform_cursor.hotSpot().x(), platform_cursor.hotSpot().y()) {
if (IsCustom())
SetCustomData(platform_cursor.customImage().get());
+
+ InitPlatformData();
+}
+
+WebCursor::~WebCursor() {
+ Clear();
+}
+
+WebCursor::WebCursor(const WebCursor& other) {
+ InitPlatformData();
+ Copy(other);
+}
+
+const WebCursor& WebCursor::operator=(const WebCursor& other) {
+ if (this == &other)
+ return *this;
+
+ Clear();
+ Copy(other);
+ return *this;
}
bool WebCursor::Deserialize(const Pickle* pickle, void** iter) {
int type, hotspot_x, hotspot_y, size_x, size_y, data_len;
+
const char* data;
// Leave |this| unmodified unless we are going to return success.
@@ -48,7 +70,7 @@ bool WebCursor::Deserialize(const Pickle* pickle, void** iter) {
memcpy(&custom_data_[0], data, data_len);
}
- return true;
+ return DeserializePlatformData(pickle, iter);
}
bool WebCursor::Serialize(Pickle* pickle) const {
@@ -62,7 +84,10 @@ bool WebCursor::Serialize(Pickle* pickle) const {
const char* data = NULL;
if (!custom_data_.empty())
data = &custom_data_[0];
- return pickle->WriteData(data, custom_data_.size());
+ if (!pickle->WriteData(data, custom_data_.size()))
+ return false;
+
+ return SerializePlatformData(pickle);
}
bool WebCursor::IsCustom() const {
@@ -70,19 +95,43 @@ bool WebCursor::IsCustom() const {
}
bool WebCursor::IsEqual(const WebCursor& other) const {
- if (!IsCustom())
- return type_ == other.type_;
+ if (type_ != other.type_)
+ return false;
+
+ if (!IsPlatformDataEqual(other))
+ return false;
return hotspot_ == other.hotspot_ &&
custom_size_ == other.custom_size_ &&
custom_data_ == other.custom_data_;
}
+void WebCursor::Clear() {
+ type_ = WebCore::PlatformCursor::typePointer;
+ hotspot_.set_x(0);
+ hotspot_.set_y(0);
+ custom_size_.set_width(0);
+ custom_size_.set_height(0);
+ custom_data_.clear();
+ CleanupPlatformData();
+}
+
+void WebCursor::Copy(const WebCursor& other) {
+ type_ = other.type_;
+ hotspot_ = other.hotspot_;
+ custom_size_ = other.custom_size_;
+ custom_data_ = other.custom_data_;
+ CopyPlatformData(other);
+}
+
#if !defined(OS_MACOSX)
// The Mac version of Chromium is built with PLATFORM(CG) while all other
// versions are PLATFORM(SKIA). We'll keep this Skia implementation here for
// common use and put the Mac implementation in webcursor_mac.mm.
void WebCursor::SetCustomData(WebCore::Image* image) {
+ if (!image)
+ return;
+
WebCore::NativeImagePtr image_ptr = image->nativeImageForCurrentFrame();
if (!image_ptr)
return;
diff --git a/webkit/glue/webcursor.h b/webkit/glue/webcursor.h
index a64df6c..1dbf3c3 100644
--- a/webkit/glue/webcursor.h
+++ b/webkit/glue/webcursor.h
@@ -5,6 +5,7 @@
#ifndef WEBKIT_GLUE_WEBCURSOR_H_
#define WEBKIT_GLUE_WEBCURSOR_H_
+#include "base/basictypes.h"
#include "base/gfx/point.h"
#include "base/gfx/size.h"
@@ -40,6 +41,11 @@ class WebCursor {
public:
WebCursor();
explicit WebCursor(const WebCore::PlatformCursor& platform_cursor);
+ ~WebCursor();
+
+ // Copy constructor/assignment operator combine.
+ WebCursor(const WebCursor& other);
+ const WebCursor& operator=(const WebCursor& other);
// Serialization / De-serialization
bool Deserialize(const Pickle* pickle, void** iter);
@@ -55,18 +61,16 @@ class WebCursor {
bool IsEqual(const WebCursor& other) const;
#if defined(OS_WIN)
- // If the underlying cursor type is not a custom cursor, this functions uses
- // the LoadCursor API to load the cursor and returns it. The caller SHOULD
- // NOT pass the resulting handling to DestroyCursor. Returns NULL on error.
- HCURSOR GetCursor(HINSTANCE module_handle) const;
-
- // If the underlying cursor type is a custom cursor, this function generates
- // a cursor and returns it. The responsiblity of freeing the cursor handle
- // lies with the caller. Returns NULL on error.
- HCURSOR GetCustomCursor() const;
-
- // Initialize this from the given Windows cursor.
- void InitFromCursor(HCURSOR handle);
+ // Returns a HCURSOR representing the current WebCursor instance.
+ // The ownership of the HCURSOR (does not apply to external cursors) remains
+ // with the WebCursor instance.
+ HCURSOR GetCursor(HINSTANCE module_handle);
+
+ // Initialize this from the given Windows cursor. The caller must ensure that
+ // the HCURSOR remains valid by not invoking the DestroyCursor/DestroyIcon
+ // APIs on it.
+ void InitFromExternalCursor(HCURSOR handle);
+
#elif defined(OS_LINUX)
// Return the stock GdkCursorType for this cursor, or GDK_CURSOR_IS_PIXMAP
// if it's a custom cursor.
@@ -80,6 +84,29 @@ class WebCursor {
#endif
private:
+ // Copies the contents of the WebCursor instance passed in.
+ void Copy(const WebCursor& other);
+
+ // Cleans up the WebCursor instance.
+ void Clear();
+
+ // Platform specific initialization goes here.
+ void InitPlatformData();
+
+ // Platform specific Serialization / De-serialization
+ bool SerializePlatformData(Pickle* pickle) const;
+ bool DeserializePlatformData(const Pickle* pickle, void** iter);
+
+ // Returns true if the platform data in the current cursor object
+ // matches that of the cursor passed in.
+ bool IsPlatformDataEqual(const WebCursor& other) const ;
+
+ // Copies platform specific data from the WebCursor instance passed in.
+ void CopyPlatformData(const WebCursor& other);
+
+ // Platform specific cleanup.
+ void CleanupPlatformData();
+
void SetCustomData(WebCore::Image* image);
// WebCore::PlatformCursor type.
@@ -91,6 +118,14 @@ class WebCursor {
// Platform-inspecific because it can be serialized.
gfx::Size custom_size_;
std::vector<char> custom_data_;
+
+#if defined(OS_WIN)
+ // An externally generated HCURSOR. We assume that it remains valid, i.e we
+ // don't attempt to copy the HCURSOR.
+ HCURSOR external_cursor_;
+ // A custom cursor created from custom bitmap data by Webkit.
+ HCURSOR custom_cursor_;
+#endif // OS_WIN
};
#endif // WEBKIT_GLUE_WEBCURSOR_H_
diff --git a/webkit/glue/webcursor_gtk.cc b/webkit/glue/webcursor_gtk.cc
index bb66be7..ab8fdfc 100644
--- a/webkit/glue/webcursor_gtk.cc
+++ b/webkit/glue/webcursor_gtk.cc
@@ -169,3 +169,27 @@ GdkCursor* WebCursor::GetCustomCursor() const {
return cursor;
}
+
+void WebCursor::InitPlatformData() {
+ return;
+}
+
+bool WebCursor::SerializePlatformData(Pickle* pickle) const {
+ return true;
+}
+
+bool WebCursor::DeserializePlatformData(const Pickle* pickle, void** iter) {
+ return true;
+}
+
+bool WebCursor::IsPlatformDataEqual(const WebCursor& other) const {
+ return true;
+}
+
+void WebCursor::CleanupPlatformData() {
+ return;
+}
+
+void WebCursor::CopyPlatformData(const WebCursor& other) {
+ return;
+}
diff --git a/webkit/glue/webcursor_mac.mm b/webkit/glue/webcursor_mac.mm
index 12eb0c4..9d83775 100644
--- a/webkit/glue/webcursor_mac.mm
+++ b/webkit/glue/webcursor_mac.mm
@@ -170,3 +170,26 @@ void WebCursor::SetCustomData(WebCore::Image* image) {
CGContextDrawImage(context.get(), rect, image_ptr);
}
+void WebCursor::InitPlatformData() {
+ return;
+}
+
+bool WebCursor::SerializePlatformData(Pickle* pickle) const {
+ return true;
+}
+
+bool WebCursor::DeserializePlatformData(const Pickle* pickle, void** iter) {
+ return true;
+}
+
+bool WebCursor::IsPlatformDataEqual(const WebCursor& other) const {
+ return true;
+}
+
+void WebCursor::CleanupPlatformData() {
+ return;
+}
+
+void WebCursor::CopyPlatformData(const WebCursor& other) {
+ return;
+}
diff --git a/webkit/glue/webcursor_win.cc b/webkit/glue/webcursor_win.cc
index f4d05d8..b529e06 100644
--- a/webkit/glue/webcursor_win.cc
+++ b/webkit/glue/webcursor_win.cc
@@ -9,6 +9,7 @@
#undef LOG
#include "base/gfx/gdi_util.h"
#include "base/logging.h"
+#include "base/pickle.h"
#include "skia/include/SkBitmap.h"
#include "webkit/glue/webcursor.h"
#include "webkit/glue/webkit_resources.h"
@@ -131,24 +132,27 @@ static PlatformCursor::Type ToPlatformCursorType(HCURSOR cursor) {
if (cursor == kStandardCursors[i].cursor)
return kStandardCursors[i].type;
}
- return PlatformCursor::typePointer;
+ return PlatformCursor::typeCustom;
}
-HCURSOR WebCursor::GetCursor(HINSTANCE module_handle) const {
- if (IsCustom())
- return NULL;
+HCURSOR WebCursor::GetCursor(HINSTANCE module_handle){
+ if (!IsCustom()) {
+ const wchar_t* cursor_id =
+ ToCursorID(static_cast<PlatformCursor::Type>(type_));
- LPCWSTR cursor_id = ToCursorID(static_cast<PlatformCursor::Type>(type_));
+ if (IsSystemCursorID(cursor_id))
+ module_handle = NULL;
- if (IsSystemCursorID(cursor_id))
- module_handle = NULL;
+ return LoadCursor(module_handle, cursor_id);
+ }
- return LoadCursor(module_handle, cursor_id);
-}
+ if (custom_cursor_) {
+ DCHECK(external_cursor_ == NULL);
+ return custom_cursor_;
+ }
-HCURSOR WebCursor::GetCustomCursor() const {
- if (!IsCustom())
- return NULL;
+ if (external_cursor_)
+ return external_cursor_;
BITMAPINFO cursor_bitmap_info = {0};
gfx::CreateBitmapHeader(
@@ -176,16 +180,61 @@ HCURSOR WebCursor::GetCustomCursor() const {
ii.hbmMask = mask;
ii.hbmColor = bitmap_handle;
- HCURSOR cursor_handle = CreateIconIndirect(&ii);
+ custom_cursor_ = CreateIconIndirect(&ii);
DeleteObject(mask);
DeleteObject(bitmap_handle);
DeleteDC(workingDC);
ReleaseDC(0, dc);
- return cursor_handle;
+ return custom_cursor_;
+}
+
+void WebCursor::InitFromExternalCursor(HCURSOR cursor) {
+ WebCore::PlatformCursor::Type cursor_type = ToPlatformCursorType(cursor);
+
+ *this = WebCursor(cursor_type);
+
+ if (cursor_type == WebCore::PlatformCursor::typeCustom) {
+ external_cursor_ = cursor;
+ }
}
-void WebCursor::InitFromCursor(HCURSOR cursor) {
- // TODO(iyengar) Add support for custom cursors.
- *this = WebCursor(ToPlatformCursorType(cursor));
+void WebCursor::InitPlatformData() {
+ external_cursor_ = NULL;
+ custom_cursor_ = NULL;
+}
+
+bool WebCursor::SerializePlatformData(Pickle* pickle) const {
+ // There are some issues with converting certain HCURSORS to bitmaps. The
+ // HCURSOR being a user object can be marshaled as is.
+ return pickle->WriteIntPtr(reinterpret_cast<intptr_t>(external_cursor_));
+}
+
+bool WebCursor::DeserializePlatformData(const Pickle* pickle, void** iter) {
+ return pickle->ReadIntPtr(iter,
+ reinterpret_cast<intptr_t*>(&external_cursor_));
+}
+
+bool WebCursor::IsPlatformDataEqual(const WebCursor& other) const {
+ if (!IsCustom())
+ return true;
+
+ return (external_cursor_ == other.external_cursor_);
+}
+
+void WebCursor::CopyPlatformData(const WebCursor& other) {
+ external_cursor_ = other.external_cursor_;
+ // The custom_cursor_ member will be initialized to a HCURSOR the next time
+ // the GetCursor member function is invoked on this WebCursor instance. The
+ // cursor is created using the data in the custom_data_ vector.
+ custom_cursor_ = NULL;
+}
+
+void WebCursor::CleanupPlatformData() {
+ external_cursor_ = NULL;
+
+ if (custom_cursor_) {
+ DestroyIcon(custom_cursor_);
+ custom_cursor_ = NULL;
+ }
}
diff --git a/webkit/glue/webplugin_impl.cc b/webkit/glue/webplugin_impl.cc
index 15685e4..003ece7 100644
--- a/webkit/glue/webplugin_impl.cc
+++ b/webkit/glue/webplugin_impl.cc
@@ -895,11 +895,16 @@ void WebPluginImpl::handleMouseEvent(WebCore::MouseEvent* event) {
WebCursor cursor;
if (!delegate_->HandleEvent(&np_event, &cursor))
event->setDefaultHandled();
+
+ ChromeClientImpl* chrome_client =
+ static_cast<ChromeClientImpl*>(
+ parent_view->frame()->page()->chrome()->client());
+
// A windowless plugin can change the cursor in response to the WM_MOUSEMOVE
// event. We need to reflect the changed cursor in the frame view as the
// mouse is moved in the boundaries of the windowless plugin.
- static_cast<ChromeClientImpl*>(
- parent_view->frame()->page()->chrome()->client())->SetCursor(cursor);
+ chrome_client->SetCursorForPlugin(cursor);
+
#else
NOTIMPLEMENTED();
#endif
diff --git a/webkit/tools/test_shell/test_webview_delegate.h b/webkit/tools/test_shell/test_webview_delegate.h
index 5c05e34..77c7b8e 100644
--- a/webkit/tools/test_shell/test_webview_delegate.h
+++ b/webkit/tools/test_shell/test_webview_delegate.h
@@ -22,6 +22,7 @@
#include "base/basictypes.h"
#include "base/ref_counted.h"
+#include "webkit/glue/webcursor.h"
#include "webkit/glue/webview_delegate.h"
#include "webkit/glue/webwidget_delegate.h"
#if defined(OS_WIN)
@@ -66,9 +67,7 @@ class TestWebViewDelegate : public base::RefCounted<TestWebViewDelegate>,
#else
, select_trailing_whitespace_enabled_(false)
#endif
-#if defined(OS_WIN)
- , custom_cursor_(NULL)
-#elif defined(OS_LINUX)
+#if defined(OS_LINUX)
, cursor_type_(GDK_X_CURSOR)
#endif
{
@@ -310,9 +309,8 @@ class TestWebViewDelegate : public base::RefCounted<TestWebViewDelegate>,
// true if we want to enable selection of trailing whitespaces
bool select_trailing_whitespace_enabled_;
+ WebCursor current_cursor_;
#if defined(OS_WIN)
- HCURSOR custom_cursor_;
-
// Classes needed by drag and drop.
scoped_refptr<TestDragDelegate> drag_delegate_;
scoped_refptr<TestDropDelegate> drop_delegate_;
diff --git a/webkit/tools/test_shell/test_webview_delegate_gtk.cc b/webkit/tools/test_shell/test_webview_delegate_gtk.cc
index 6db73b4..831691a 100644
--- a/webkit/tools/test_shell/test_webview_delegate_gtk.cc
+++ b/webkit/tools/test_shell/test_webview_delegate_gtk.cc
@@ -111,13 +111,14 @@ void TestWebViewDelegate::CloseWidgetSoon(WebWidget* webwidget) {
void TestWebViewDelegate::SetCursor(WebWidget* webwidget,
const WebCursor& cursor) {
- GdkCursorType cursor_type = cursor.GetCursorType();
+ current_cursor_ = cursor;
+ GdkCursorType cursor_type = current_cursor_.GetCursorType();
GdkCursor* gdk_cursor;
if (cursor_type == GDK_CURSOR_IS_PIXMAP) {
// TODO(port): WebKit bug https://bugs.webkit.org/show_bug.cgi?id=16388 is
// that calling gdk_window_set_cursor repeatedly is expensive. We should
// avoid it here where possible.
- gdk_cursor = cursor.GetCustomCursor();
+ gdk_cursor = current_cursor_.GetCustomCursor();
} else {
// Optimize the common case, where the cursor hasn't changed.
// However, we can switch between different pixmaps, so only on the
diff --git a/webkit/tools/test_shell/test_webview_delegate_win.cc b/webkit/tools/test_shell/test_webview_delegate_win.cc
index cea089a..30431f6 100644
--- a/webkit/tools/test_shell/test_webview_delegate_win.cc
+++ b/webkit/tools/test_shell/test_webview_delegate_win.cc
@@ -36,8 +36,6 @@
// WebViewDelegate -----------------------------------------------------------
TestWebViewDelegate::~TestWebViewDelegate() {
- if (custom_cursor_)
- DestroyIcon(custom_cursor_);
RevokeDragDrop(shell_->webViewWnd());
}
@@ -89,17 +87,9 @@ void TestWebViewDelegate::CloseWidgetSoon(WebWidget* webwidget) {
void TestWebViewDelegate::SetCursor(WebWidget* webwidget,
const WebCursor& cursor) {
if (WebWidgetHost* host = GetHostForWidget(webwidget)) {
- if (custom_cursor_) {
- DestroyIcon(custom_cursor_);
- custom_cursor_ = NULL;
- }
- if (cursor.IsCustom()) {
- custom_cursor_ = cursor.GetCustomCursor();
- host->SetCursor(custom_cursor_);
- } else {
- HINSTANCE mod_handle = GetModuleHandle(NULL);
- host->SetCursor(cursor.GetCursor(mod_handle));
- }
+ current_cursor_ = cursor;
+ HINSTANCE mod_handle = GetModuleHandle(NULL);
+ host->SetCursor(current_cursor_.GetCursor(mod_handle));
}
}