summaryrefslogtreecommitdiffstats
path: root/webkit/glue
diff options
context:
space:
mode:
authorananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-09 01:20:38 +0000
committerananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-01-09 01:20:38 +0000
commitcf4e5eb1df0fcbf192584b61e83e0b85cf23a1cf (patch)
treebce3c121d9679666d8acdf73cb082a684cf491e4 /webkit/glue
parent710e056bd5005f8d0f9f9d5f4b8623f9c9dd7004 (diff)
downloadchromium_src-cf4e5eb1df0fcbf192584b61e83e0b85cf23a1cf.zip
chromium_src-cf4e5eb1df0fcbf192584b61e83e0b85cf23a1cf.tar.gz
chromium_src-cf4e5eb1df0fcbf192584b61e83e0b85cf23a1cf.tar.bz2
Add support for custom cursors set by windowless plugins. Windowless plugins typically set the cursor in NPP_HandleEvent for WM_MOUSEMOVE.The current implementation looks for the cursor type and if the typedoes not match predefinedcursor types defaults to the pointer cursor.
The fixes are as below:- 1. Marshal the HCURSOR after copying it to ensure that it remains valid. This works as a HCURSOR is a user object and can be used across processes. Ideally we would like to convert it to a skia bitmap but there are issues with converting monochrome cursors. 2. Added support for marshaling platform specific data in the webcursor Serialize/Deserialize functions. This is in the form of functions like InitPlatformData, SerializePlatformData, DeserializePlatformData, etc. which are stubbed out for the other platforms. 3. Mimic webkit windowless plugin behavior where it sets a flag to ignore the next setCursor after HandleEvent of WM_MOUSEMOVE. If we don't do this the cursor keeps changing between a pointerCursor and the cursor set by the plugin which also causes flicker. 4. Fixed the WebCursor::IsEqual function to ensure that it checks all fields for equality. 5. The browser(RenderWidgetHostViewWin) now maintains a WebCursor instance representing the current cursor. Any cursor updates received from the renderer update the current cursor member maintained by the browser. 6. We intercept the SetCursor API for windowless plugins like Flash and Silverlight and remember the cursor being set. We don't invoke the original API as the browser UI thread would do it anyways. This fixes the annoying cursor flicker caused by the windowless flash plugin instance constantly setting the cursor even when the tab is not visible. This fixes bug http://code.google.com/p/chromium/issues/detail?id=3800. Review URL: http://codereview.chromium.org/15088 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@7798 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/glue')
-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
10 files changed, 315 insertions, 58 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