diff options
author | ananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-30 02:31:46 +0000 |
---|---|---|
committer | ananta@chromium.org <ananta@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-04-30 02:31:46 +0000 |
commit | 6dba9a4428541b520adaad72a60414e1ef0488bb (patch) | |
tree | 8e274010f6a5d549ed0266f8b0f6e1ce9e5496e9 /webkit/glue/plugins | |
parent | 999048c11f7541a5bcbd4ef07b69f87c56654139 (diff) | |
download | chromium_src-6dba9a4428541b520adaad72a60414e1ef0488bb.zip chromium_src-6dba9a4428541b520adaad72a60414e1ef0488bb.tar.gz chromium_src-6dba9a4428541b520adaad72a60414e1ef0488bb.tar.bz2 |
The windowed flash plugin has a bug which occurs when the plugin enters fullscreen mode. It basically captures the
mouse on WM_LBUTTONDOWN and does not release capture correctly causing it to stop receiving subsequent mouse events.
This problem is also seen in Safari where there is code to handle this in the wndproc. However the plugin subclasses the window in
WM_LBUTTONDOWN before entering full screen. As a result Safari does not receive the WM_LBUTTONUP message.
To workaround this issue we use a per thread mouse hook to capture and release the mouse. This hook is only installed
on a quirk.
This bug does not occur in Firefox and opera. Firefox has code similar to Safari where it captures the mouse on
WM_LBUTTONDOWN and releases it on WM_LBUTTONUP. It could well be a bug in the flash plugin, which only occurs in Safari and Chrome.
Fixes http://code.google.com/p/chromium/issues/detail?id=28025
Bug=28025
Review URL: http://codereview.chromium.org/1718023
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@46031 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/glue/plugins')
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl.h | 12 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl_win.cc | 56 |
2 files changed, 67 insertions, 1 deletions
diff --git a/webkit/glue/plugins/webplugin_delegate_impl.h b/webkit/glue/plugins/webplugin_delegate_impl.h index 6cf7c7b..2fef88b 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl.h +++ b/webkit/glue/plugins/webplugin_delegate_impl.h @@ -71,6 +71,7 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate { PLUGIN_QUIRK_PATCH_REGENUMKEYEXW = 2048, // Windows PLUGIN_QUIRK_ALWAYS_NOTIFY_SUCCESS = 4096, // Windows PLUGIN_QUIRK_ALLOW_FASTER_QUICKDRAW_PATH = 8192, // Mac + PLUGIN_QUIRK_HANDLE_MOUSE_CAPTURE = 16384, // Windows }; static WebPluginDelegateImpl* Create(const FilePath& filename, @@ -353,6 +354,13 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate { HKEY key, DWORD index, LPWSTR name, LPDWORD name_size, LPDWORD reserved, LPWSTR class_name, LPDWORD class_size, PFILETIME last_write_time); + // The mouse hook proc which handles mouse capture in windowed plugins. + static LRESULT CALLBACK MouseHookProc(int code, WPARAM wParam, + LPARAM lParam); + + // Calls SetCapture/ReleaseCapture based on the message type. + static void HandleCaptureForMessage(HWND window, UINT message); + #elif defined(OS_MACOSX) // Sets window_rect_ to |rect| void SetPluginRect(const gfx::Rect& rect); @@ -456,6 +464,10 @@ class WebPluginDelegateImpl : public webkit_glue::WebPluginDelegate { // Runnable Method Factory used to invoke the OnUserGestureEnd method // asynchronously. ScopedRunnableMethodFactory<WebPluginDelegateImpl> user_gesture_msg_factory_; + + // Handle to the mouse hook installed for certain windowed plugins like + // flash. + HHOOK mouse_hook_; #endif // Holds the depth of the HandleEvent callstack. diff --git a/webkit/glue/plugins/webplugin_delegate_impl_win.cc b/webkit/glue/plugins/webplugin_delegate_impl_win.cc index 98fd0ed..ed8203a 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl_win.cc +++ b/webkit/glue/plugins/webplugin_delegate_impl_win.cc @@ -227,6 +227,17 @@ LRESULT CALLBACK WebPluginDelegateImpl::HandleEventMessageFilterHook( return CallNextHookEx(NULL, code, wParam, lParam); } +LRESULT CALLBACK WebPluginDelegateImpl::MouseHookProc( + int code, WPARAM wParam, LPARAM lParam) { + if (code == HC_ACTION) { + MOUSEHOOKSTRUCT* hook_struct = reinterpret_cast<MOUSEHOOKSTRUCT*>(lParam); + if (hook_struct) + HandleCaptureForMessage(hook_struct->hwnd, wParam); + } + + return CallNextHookEx(NULL, code, wParam, lParam); +} + WebPluginDelegateImpl::WebPluginDelegateImpl( gfx::PluginWindowHandle containing_view, NPAPI::PluginInstance *instance) @@ -248,7 +259,8 @@ WebPluginDelegateImpl::WebPluginDelegateImpl( user_gesture_message_posted_(false), #pragma warning(suppress: 4355) // can use this user_gesture_msg_factory_(this), - handle_event_depth_(0) { + handle_event_depth_(0), + mouse_hook_(NULL) { memset(&window_, 0, sizeof(window_)); const WebPluginInfo& plugin_info = instance_->plugin_lib()->plugin_info(); @@ -262,6 +274,7 @@ WebPluginDelegateImpl::WebPluginDelegateImpl( quirks_ |= PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE; quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR; quirks_ |= PLUGIN_QUIRK_ALWAYS_NOTIFY_SUCCESS; + quirks_ |= PLUGIN_QUIRK_HANDLE_MOUSE_CAPTURE; } else if (filename == kAcrobatReaderPlugin) { // Check for the version number above or equal 9. std::vector<std::wstring> version; @@ -373,6 +386,20 @@ bool WebPluginDelegateImpl::PlatformInitialize() { WebPluginDelegateImpl::RegEnumKeyExWPatch); } + // The windowed flash plugin has a bug which occurs when the plugin enters + // fullscreen mode. It basically captures the mouse on WM_LBUTTONDOWN and + // does not release capture correctly causing it to stop receiving subsequent + // mouse events. This problem is also seen in Safari where there is code to + // handle this in the wndproc. However the plugin subclasses the window again + // in WM_LBUTTONDOWN before entering full screen. As a result Safari does not + // receive the WM_LBUTTONUP message. To workaround this issue we use a per + // thread mouse hook. This bug does not occur in Firefox and opera. Firefox + // has code similar to Safari. It could well be a bug in the flash plugin, + // which only occurs in webkit based browsers. + if (quirks_ & PLUGIN_QUIRK_HANDLE_MOUSE_CAPTURE) { + mouse_hook_ = SetWindowsHookEx(WH_MOUSE, MouseHookProc, NULL, + GetCurrentThreadId()); + } return true; } @@ -392,6 +419,11 @@ void WebPluginDelegateImpl::PlatformDestroyInstance() { if (g_iat_patch_reg_enum_key_ex_w.Pointer()->is_patched()) g_iat_patch_reg_enum_key_ex_w.Pointer()->Unpatch(); + + if (mouse_hook_) { + UnhookWindowsHookEx(mouse_hook_); + mouse_hook_ = NULL; + } } void WebPluginDelegateImpl::Paint(skia::PlatformCanvas* canvas, @@ -897,6 +929,8 @@ LRESULT CALLBACK WebPluginDelegateImpl::NativeWndProc( kWindowedPluginPopupTimerMs); } + HandleCaptureForMessage(hwnd, message); + // Maintain a local/global stack for the g_current_plugin_instance variable // as this may be a nested invocation. WebPluginDelegateImpl* last_plugin_instance = g_current_plugin_instance; @@ -1321,3 +1355,23 @@ LONG WINAPI WebPluginDelegateImpl::RegEnumKeyExWPatch( return rv; } + +void WebPluginDelegateImpl::HandleCaptureForMessage(HWND window, + UINT message) { + switch (message) { + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + ::SetCapture(window); + break; + + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + ::ReleaseCapture(); + break; + + default: + break; + } +} |