diff options
Diffstat (limited to 'webkit')
-rw-r--r-- | webkit/glue/chrome_client_impl.cc | 16 | ||||
-rw-r--r-- | webkit/glue/chrome_client_impl.h | 3 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl.cc | 82 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl.h | 17 | ||||
-rw-r--r-- | webkit/glue/webcursor.cc | 57 | ||||
-rw-r--r-- | webkit/glue/webcursor.h | 59 | ||||
-rw-r--r-- | webkit/glue/webcursor_gtk.cc | 24 | ||||
-rw-r--r-- | webkit/glue/webcursor_mac.mm | 23 | ||||
-rw-r--r-- | webkit/glue/webcursor_win.cc | 83 | ||||
-rw-r--r-- | webkit/glue/webplugin_impl.cc | 9 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_webview_delegate.h | 8 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_webview_delegate_gtk.cc | 5 | ||||
-rw-r--r-- | webkit/tools/test_shell/test_webview_delegate_win.cc | 16 |
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)); } } |