OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "webkit/glue/plugins/webplugin_delegate_impl.h" | 5 #include "webkit/glue/plugins/webplugin_delegate_impl.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
(...skipping 29 matching lines...) Expand all Loading... |
40 // I'd like to make the throttle delay variable, based on the amount of | 40 // I'd like to make the throttle delay variable, based on the amount of |
41 // time currently required to paint Flash plugins. There isn't a good | 41 // time currently required to paint Flash plugins. There isn't a good |
42 // way to count the time spent in aggregate plugin painting, however, so | 42 // way to count the time spent in aggregate plugin painting, however, so |
43 // this seems to work well enough. | 43 // this seems to work well enough. |
44 static const int kFlashWMUSERMessageThrottleDelayMs = 5; | 44 static const int kFlashWMUSERMessageThrottleDelayMs = 5; |
45 | 45 |
46 std::list<MSG> WebPluginDelegateImpl::throttle_queue_; | 46 std::list<MSG> WebPluginDelegateImpl::throttle_queue_; |
47 | 47 |
48 WebPluginDelegateImpl* WebPluginDelegateImpl::current_plugin_instance_ = NULL; | 48 WebPluginDelegateImpl* WebPluginDelegateImpl::current_plugin_instance_ = NULL; |
49 | 49 |
50 bool WebPluginDelegateImpl::track_popup_menu_patched_ = false; | 50 iat_patch::IATPatchFunction WebPluginDelegateImpl::iat_patch_track_popup_menu_; |
51 iat_patch::IATPatchFunction WebPluginDelegateImpl::iat_patch_helper_; | 51 iat_patch::IATPatchFunction WebPluginDelegateImpl::iat_patch_set_cursor_; |
52 | 52 |
53 WebPluginDelegateImpl* WebPluginDelegateImpl::Create( | 53 WebPluginDelegateImpl* WebPluginDelegateImpl::Create( |
54 const FilePath& filename, | 54 const FilePath& filename, |
55 const std::string& mime_type, | 55 const std::string& mime_type, |
56 gfx::NativeView containing_view) { | 56 gfx::NativeView containing_view) { |
57 scoped_refptr<NPAPI::PluginLib> plugin = | 57 scoped_refptr<NPAPI::PluginLib> plugin = |
58 NPAPI::PluginLib::CreatePluginLib(filename); | 58 NPAPI::PluginLib::CreatePluginLib(filename); |
59 if (plugin.get() == NULL) | 59 if (plugin.get() == NULL) |
60 return NULL; | 60 return NULL; |
61 | 61 |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
146 | 146 |
147 const WebPluginInfo& plugin_info = instance_->plugin_lib()->plugin_info(); | 147 const WebPluginInfo& plugin_info = instance_->plugin_lib()->plugin_info(); |
148 std::wstring filename = plugin_info.file.BaseName().value(); | 148 std::wstring filename = plugin_info.file.BaseName().value(); |
149 | 149 |
150 if (instance_->mime_type() == "application/x-shockwave-flash" || | 150 if (instance_->mime_type() == "application/x-shockwave-flash" || |
151 filename == L"npswf32.dll") { | 151 filename == L"npswf32.dll") { |
152 // Flash only requests windowless plugins if we return a Mozilla user | 152 // Flash only requests windowless plugins if we return a Mozilla user |
153 // agent. | 153 // agent. |
154 instance_->set_use_mozilla_user_agent(); | 154 instance_->set_use_mozilla_user_agent(); |
155 quirks_ |= PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE; | 155 quirks_ |= PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE; |
| 156 quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR; |
156 } else if (filename == L"nppdf32.dll") { | 157 } else if (filename == L"nppdf32.dll") { |
157 // Check for the version number above or equal 9. | 158 // Check for the version number above or equal 9. |
158 std::vector<std::wstring> version; | 159 std::vector<std::wstring> version; |
159 SplitString(plugin_info.version, L'.', &version); | 160 SplitString(plugin_info.version, L'.', &version); |
160 if (version.size() > 0) { | 161 if (version.size() > 0) { |
161 int major = static_cast<int>(StringToInt64(version[0])); | 162 int major = static_cast<int>(StringToInt64(version[0])); |
162 if (major >= 9) { | 163 if (major >= 9) { |
163 quirks_ |= PLUGIN_QUIRK_DIE_AFTER_UNLOAD; | 164 quirks_ |= PLUGIN_QUIRK_DIE_AFTER_UNLOAD; |
164 } | 165 } |
165 } | 166 } |
166 } else if (plugin_info.name.find(L"Windows Media Player") != | 167 } else if (plugin_info.name.find(L"Windows Media Player") != |
167 std::wstring::npos) { | 168 std::wstring::npos) { |
168 // Windows Media Player needs two NPP_SetWindow calls. | 169 // Windows Media Player needs two NPP_SetWindow calls. |
169 quirks_ |= PLUGIN_QUIRK_SETWINDOW_TWICE; | 170 quirks_ |= PLUGIN_QUIRK_SETWINDOW_TWICE; |
170 } else if (instance_->mime_type() == "audio/x-pn-realaudio-plugin" || | 171 } else if (instance_->mime_type() == "audio/x-pn-realaudio-plugin" || |
171 filename == L"nppl3260.dll") { | 172 filename == L"nppl3260.dll") { |
172 quirks_ |= PLUGIN_QUIRK_DONT_CALL_WND_PROC_RECURSIVELY; | 173 quirks_ |= PLUGIN_QUIRK_DONT_CALL_WND_PROC_RECURSIVELY; |
173 } else if (plugin_info.name.find(L"VLC Multimedia Plugin") != | 174 } else if (plugin_info.name.find(L"VLC Multimedia Plugin") != |
174 std::wstring::npos) { | 175 std::wstring::npos) { |
175 // VLC hangs on NPP_Destroy if we call NPP_SetWindow with a null window | 176 // VLC hangs on NPP_Destroy if we call NPP_SetWindow with a null window |
176 // handle | 177 // handle |
177 quirks_ |= PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY; | 178 quirks_ |= PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY; |
178 // VLC 0.8.6d and 0.8.6e crash if multiple instances are created. | 179 // VLC 0.8.6d and 0.8.6e crash if multiple instances are created. |
179 quirks_ |= PLUGIN_QUIRK_DONT_ALLOW_MULTIPLE_INSTANCES; | 180 quirks_ |= PLUGIN_QUIRK_DONT_ALLOW_MULTIPLE_INSTANCES; |
180 } else if (filename == L"npctrl.dll") { | 181 } else if (filename == L"npctrl.dll") { |
181 // Explanation for this quirk can be found in | 182 // Explanation for this quirk can be found in |
182 // WebPluginDelegateImpl::Initialize. | 183 // WebPluginDelegateImpl::Initialize. |
183 quirks_ |= PLUGIN_QUIRK_PATCH_TRACKPOPUP_MENU; | 184 quirks_ |= PLUGIN_QUIRK_PATCH_TRACKPOPUP_MENU; |
| 185 quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR; |
184 } | 186 } |
185 | 187 |
186 plugin_module_handle_ = ::GetModuleHandle(filename.c_str()); | 188 plugin_module_handle_ = ::GetModuleHandle(filename.c_str()); |
187 } | 189 } |
188 | 190 |
189 WebPluginDelegateImpl::~WebPluginDelegateImpl() { | 191 WebPluginDelegateImpl::~WebPluginDelegateImpl() { |
190 if (::IsWindow(dummy_window_for_activation_)) { | 192 if (::IsWindow(dummy_window_for_activation_)) { |
191 ::DestroyWindow(dummy_window_for_activation_); | 193 ::DestroyWindow(dummy_window_for_activation_); |
192 } | 194 } |
193 | 195 |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
253 plugin_url_ = url.spec(); | 255 plugin_url_ = url.spec(); |
254 | 256 |
255 // The windowless version of the Silverlight plugin calls the | 257 // The windowless version of the Silverlight plugin calls the |
256 // WindowFromPoint API and passes the result of that to the | 258 // WindowFromPoint API and passes the result of that to the |
257 // TrackPopupMenu API call as the owner window. This causes the API | 259 // TrackPopupMenu API call as the owner window. This causes the API |
258 // to fail as the API expects the window handle to live on the same | 260 // to fail as the API expects the window handle to live on the same |
259 // thread as the caller. It works in the other browsers as the plugin | 261 // thread as the caller. It works in the other browsers as the plugin |
260 // lives on the browser thread. Our workaround is to intercept the | 262 // lives on the browser thread. Our workaround is to intercept the |
261 // TrackPopupMenu API for Silverlight and replace the window handle | 263 // TrackPopupMenu API for Silverlight and replace the window handle |
262 // with the dummy activation window. | 264 // with the dummy activation window. |
263 if (windowless_ && !track_popup_menu_patched_ && | 265 if (windowless_ && !iat_patch_track_popup_menu_.is_patched() && |
264 (quirks_ & PLUGIN_QUIRK_PATCH_TRACKPOPUP_MENU)) { | 266 (quirks_ & PLUGIN_QUIRK_PATCH_TRACKPOPUP_MENU)) { |
265 iat_patch_helper_.Patch(plugin_module_handle_, "user32.dll", | 267 iat_patch_track_popup_menu_.Patch( |
266 "TrackPopupMenu", | 268 plugin_module_handle_, "user32.dll", "TrackPopupMenu", |
267 WebPluginDelegateImpl::TrackPopupMenuPatch); | 269 WebPluginDelegateImpl::TrackPopupMenuPatch); |
268 track_popup_menu_patched_ = true; | 270 } |
| 271 |
| 272 // Windowless plugins can set cursors by calling the SetCursor API. This |
| 273 // works because the thread inputs of the browser UI thread and the plugin |
| 274 // thread are attached. We intercept the SetCursor API for windowless plugins |
| 275 // and remember the cursor being set. This is shipped over to the browser |
| 276 // in the HandleEvent call, which ensures that the cursor does not change |
| 277 // when a windowless plugin instance changes the cursor in a background tab. |
| 278 if (windowless_ && !iat_patch_set_cursor_.is_patched() && |
| 279 (quirks_ & PLUGIN_QUIRK_PATCH_SETCURSOR)) { |
| 280 iat_patch_set_cursor_.Patch(plugin_module_handle_, "user32.dll", |
| 281 "SetCursor", |
| 282 WebPluginDelegateImpl::SetCursorPatch); |
269 } | 283 } |
270 return true; | 284 return true; |
271 } | 285 } |
272 | 286 |
273 void WebPluginDelegateImpl::DestroyInstance() { | 287 void WebPluginDelegateImpl::DestroyInstance() { |
274 if (instance_ && (instance_->npp()->ndata != NULL)) { | 288 if (instance_ && (instance_->npp()->ndata != NULL)) { |
275 // Shutdown all streams before destroying so that | 289 // Shutdown all streams before destroying so that |
276 // no streams are left "in progress". Need to do | 290 // no streams are left "in progress". Need to do |
277 // this before calling set_web_plugin(NULL) because the | 291 // this before calling set_web_plugin(NULL) because the |
278 // instance uses the helper to do the download. | 292 // instance uses the helper to do the download. |
279 instance_->CloseStreams(); | 293 instance_->CloseStreams(); |
280 | 294 |
281 window_.window = NULL; | 295 window_.window = NULL; |
282 if (!(quirks_ & PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY)) { | 296 if (!(quirks_ & PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY)) { |
283 instance_->NPP_SetWindow(&window_); | 297 instance_->NPP_SetWindow(&window_); |
284 } | 298 } |
285 | 299 |
286 instance_->NPP_Destroy(); | 300 instance_->NPP_Destroy(); |
287 | 301 |
288 instance_->set_web_plugin(NULL); | 302 instance_->set_web_plugin(NULL); |
289 | 303 |
| 304 if (instance_->plugin_lib()) { |
| 305 // Unpatch if this is the last plugin instance. |
| 306 if (instance_->plugin_lib()->instance_count() == 1) { |
| 307 if (iat_patch_set_cursor_.is_patched()) { |
| 308 iat_patch_set_cursor_.Unpatch(); |
| 309 } |
| 310 |
| 311 if (iat_patch_track_popup_menu_.is_patched()) { |
| 312 iat_patch_track_popup_menu_.Unpatch(); |
| 313 } |
| 314 } |
| 315 } |
| 316 |
290 instance_ = 0; | 317 instance_ = 0; |
291 } | 318 } |
292 } | 319 } |
293 | 320 |
294 void WebPluginDelegateImpl::UpdateGeometry( | 321 void WebPluginDelegateImpl::UpdateGeometry( |
295 const gfx::Rect& window_rect, | 322 const gfx::Rect& window_rect, |
296 const gfx::Rect& clip_rect, | 323 const gfx::Rect& clip_rect, |
297 const std::vector<gfx::Rect>& cutout_rects, | 324 const std::vector<gfx::Rect>& cutout_rects, |
298 bool visible) { | 325 bool visible) { |
299 if (windowless_) { | 326 if (windowless_) { |
(...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
794 delegate->quirks() & PLUGIN_QUIRK_DONT_CALL_WND_PROC_RECURSIVELY && | 821 delegate->quirks() & PLUGIN_QUIRK_DONT_CALL_WND_PROC_RECURSIVELY && |
795 delegate->is_calling_wndproc) { | 822 delegate->is_calling_wndproc) { |
796 // Real may go into a state where it recursively dispatches the same event | 823 // Real may go into a state where it recursively dispatches the same event |
797 // when subclassed. See https://bugzilla.mozilla.org/show_bug.cgi?id=192914 | 824 // when subclassed. See https://bugzilla.mozilla.org/show_bug.cgi?id=192914 |
798 // We only do the recursive check for Real because it's possible and valid | 825 // We only do the recursive check for Real because it's possible and valid |
799 // for a plugin to synchronously dispatch a message to itself such that it | 826 // for a plugin to synchronously dispatch a message to itself such that it |
800 // looks like it's in recursion. | 827 // looks like it's in recursion. |
801 return TRUE; | 828 return TRUE; |
802 } | 829 } |
803 | 830 |
| 831 current_plugin_instance_ = delegate; |
| 832 |
804 switch (message) { | 833 switch (message) { |
805 case WM_NCDESTROY: { | 834 case WM_NCDESTROY: { |
806 RemoveProp(hwnd, kWebPluginDelegateProperty); | 835 RemoveProp(hwnd, kWebPluginDelegateProperty); |
807 ATOM plugin_name_atom = reinterpret_cast <ATOM>( | 836 ATOM plugin_name_atom = reinterpret_cast <ATOM>( |
808 RemoveProp(hwnd, kPluginNameAtomProperty)); | 837 RemoveProp(hwnd, kPluginNameAtomProperty)); |
809 if (plugin_name_atom != 0) | 838 if (plugin_name_atom != 0) |
810 GlobalDeleteAtom(plugin_name_atom); | 839 GlobalDeleteAtom(plugin_name_atom); |
811 ClearThrottleQueueForWindow(hwnd); | 840 ClearThrottleQueueForWindow(hwnd); |
812 break; | 841 break; |
813 } | 842 } |
814 // Flash may flood the message queue with WM_USER+1 message causing 100% CPU | 843 // Flash may flood the message queue with WM_USER+1 message causing 100% CPU |
815 // usage. See https://bugzilla.mozilla.org/show_bug.cgi?id=132759. We | 844 // usage. See https://bugzilla.mozilla.org/show_bug.cgi?id=132759. We |
816 // prevent this by throttling the messages. | 845 // prevent this by throttling the messages. |
817 case WM_USER + 1: { | 846 case WM_USER + 1: { |
818 if (delegate->quirks() & PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE) { | 847 if (delegate->quirks() & PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE) { |
819 WebPluginDelegateImpl::ThrottleMessage(delegate->plugin_wnd_proc_, hwnd, | 848 WebPluginDelegateImpl::ThrottleMessage(delegate->plugin_wnd_proc_, hwnd, |
820 message, wparam, lparam); | 849 message, wparam, lparam); |
| 850 current_plugin_instance_ = NULL; |
821 return FALSE; | 851 return FALSE; |
822 } | 852 } |
823 break; | 853 break; |
824 } | 854 } |
825 default: { | 855 default: { |
826 break; | 856 break; |
827 } | 857 } |
828 } | 858 } |
829 | 859 |
830 delegate->last_message_ = message; | 860 delegate->last_message_ = message; |
831 delegate->is_calling_wndproc = true; | 861 delegate->is_calling_wndproc = true; |
832 | 862 |
833 if (!delegate->user_gesture_message_posted_ && | 863 if (!delegate->user_gesture_message_posted_ && |
834 IsUserGestureMessage(message)) { | 864 IsUserGestureMessage(message)) { |
835 delegate->user_gesture_message_posted_ = true; | 865 delegate->user_gesture_message_posted_ = true; |
836 | 866 |
837 delegate->instance()->PushPopupsEnabledState(true); | 867 delegate->instance()->PushPopupsEnabledState(true); |
838 | 868 |
839 MessageLoop::current()->PostTask(FROM_HERE, | 869 MessageLoop::current()->PostTask(FROM_HERE, |
840 delegate->user_gesture_msg_factory_.NewRunnableMethod( | 870 delegate->user_gesture_msg_factory_.NewRunnableMethod( |
841 &WebPluginDelegateImpl::OnUserGestureEnd)); | 871 &WebPluginDelegateImpl::OnUserGestureEnd)); |
842 } | 872 } |
843 | 873 |
844 LRESULT result = CallWindowProc(delegate->plugin_wnd_proc_, hwnd, message, | 874 LRESULT result = CallWindowProc(delegate->plugin_wnd_proc_, hwnd, message, |
845 wparam, lparam); | 875 wparam, lparam); |
846 delegate->is_calling_wndproc = false; | 876 delegate->is_calling_wndproc = false; |
| 877 current_plugin_instance_ = NULL; |
847 return result; | 878 return result; |
848 } | 879 } |
849 | 880 |
850 void WebPluginDelegateImpl::WindowlessUpdateGeometry( | 881 void WebPluginDelegateImpl::WindowlessUpdateGeometry( |
851 const gfx::Rect& window_rect, | 882 const gfx::Rect& window_rect, |
852 const gfx::Rect& clip_rect) { | 883 const gfx::Rect& clip_rect) { |
853 // Only resend to the instance if the geometry has changed. | 884 // Only resend to the instance if the geometry has changed. |
854 if (window_rect == window_rect_ && clip_rect == clip_rect_) | 885 if (window_rect == window_rect_ && clip_rect == clip_rect_) |
855 return; | 886 return; |
856 | 887 |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
991 | 1022 |
992 bool pop_user_gesture = false; | 1023 bool pop_user_gesture = false; |
993 | 1024 |
994 if (IsUserGestureMessage(event->event)) { | 1025 if (IsUserGestureMessage(event->event)) { |
995 pop_user_gesture = true; | 1026 pop_user_gesture = true; |
996 instance()->PushPopupsEnabledState(true); | 1027 instance()->PushPopupsEnabledState(true); |
997 } | 1028 } |
998 | 1029 |
999 bool ret = instance()->NPP_HandleEvent(event) != 0; | 1030 bool ret = instance()->NPP_HandleEvent(event) != 0; |
1000 | 1031 |
1001 // Snag a reference to the current cursor ASAP in case the plugin modified | 1032 if (event->event == WM_MOUSEMOVE) { |
1002 // it. There is a nasty race condition here with the multiprocess browser | 1033 // Snag a reference to the current cursor ASAP in case the plugin modified |
1003 // as someone might be setting the cursor in the main process as well. | 1034 // it. There is a nasty race condition here with the multiprocess browser |
1004 HCURSOR last_cursor; | 1035 // as someone might be setting the cursor in the main process as well. |
1005 if (WM_MOUSEMOVE == event->event) { | 1036 *cursor = current_windowless_cursor_; |
1006 last_cursor = ::GetCursor(); | |
1007 } | 1037 } |
1008 | 1038 |
1009 if (pop_user_gesture) { | 1039 if (pop_user_gesture) { |
1010 instance()->PopPopupsEnabledState(); | 1040 instance()->PopPopupsEnabledState(); |
1011 } | 1041 } |
1012 | 1042 |
1013 handle_event_depth_--; | 1043 handle_event_depth_--; |
1014 | 1044 |
1015 current_plugin_instance_ = NULL; | 1045 current_plugin_instance_ = NULL; |
1016 | 1046 |
1017 MessageLoop::current()->SetNestableTasksAllowed(old_task_reentrancy_state); | 1047 MessageLoop::current()->SetNestableTasksAllowed(old_task_reentrancy_state); |
1018 | 1048 |
1019 if (handle_event_message_filter_hook_) { | 1049 if (handle_event_message_filter_hook_) { |
1020 UnhookWindowsHookEx(handle_event_message_filter_hook_); | 1050 UnhookWindowsHookEx(handle_event_message_filter_hook_); |
1021 handle_event_message_filter_hook_ = NULL; | 1051 handle_event_message_filter_hook_ = NULL; |
1022 } | 1052 } |
1023 | 1053 |
1024 // We could have multiple NPP_HandleEvent calls nested together in case | 1054 // We could have multiple NPP_HandleEvent calls nested together in case |
1025 // the plugin enters a modal loop. Reset the pump messages event when | 1055 // the plugin enters a modal loop. Reset the pump messages event when |
1026 // the outermost NPP_HandleEvent call unwinds. | 1056 // the outermost NPP_HandleEvent call unwinds. |
1027 if (handle_event_depth_ == 0) { | 1057 if (handle_event_depth_ == 0) { |
1028 ResetEvent(handle_event_pump_messages_event_); | 1058 ResetEvent(handle_event_pump_messages_event_); |
1029 } | 1059 } |
1030 | 1060 |
1031 if (event->event == WM_RBUTTONUP && ::IsWindow(prev_focus_window)) { | 1061 if (event->event == WM_RBUTTONUP && ::IsWindow(prev_focus_window)) { |
1032 ::SetFocus(prev_focus_window); | 1062 ::SetFocus(prev_focus_window); |
1033 } | 1063 } |
1034 | 1064 |
1035 if (WM_MOUSEMOVE == event->event) { | |
1036 cursor->InitFromCursor(last_cursor); | |
1037 } | |
1038 | |
1039 return ret; | 1065 return ret; |
1040 } | 1066 } |
1041 | 1067 |
1042 WebPluginResourceClient* WebPluginDelegateImpl::CreateResourceClient( | 1068 WebPluginResourceClient* WebPluginDelegateImpl::CreateResourceClient( |
1043 int resource_id, const std::string &url, bool notify_needed, | 1069 int resource_id, const std::string &url, bool notify_needed, |
1044 void *notify_data, void* existing_stream) { | 1070 void *notify_data, void* existing_stream) { |
1045 // Stream already exists. This typically happens for range requests | 1071 // Stream already exists. This typically happens for range requests |
1046 // initiated via NPN_RequestRead. | 1072 // initiated via NPN_RequestRead. |
1047 if (existing_stream) { | 1073 if (existing_stream) { |
1048 NPAPI::PluginStream* plugin_stream = | 1074 NPAPI::PluginStream* plugin_stream = |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1117 unsigned long window_thread_id = | 1143 unsigned long window_thread_id = |
1118 GetWindowThreadProcessId(window, &window_process_id); | 1144 GetWindowThreadProcessId(window, &window_process_id); |
1119 // TrackPopupMenu fails if the window passed in belongs to a different | 1145 // TrackPopupMenu fails if the window passed in belongs to a different |
1120 // thread. | 1146 // thread. |
1121 if (::GetCurrentThreadId() != window_thread_id) { | 1147 if (::GetCurrentThreadId() != window_thread_id) { |
1122 window = current_plugin_instance_->dummy_window_for_activation_; | 1148 window = current_plugin_instance_->dummy_window_for_activation_; |
1123 } | 1149 } |
1124 } | 1150 } |
1125 return TrackPopupMenu(menu, flags, x, y, reserved, window, rect); | 1151 return TrackPopupMenu(menu, flags, x, y, reserved, window, rect); |
1126 } | 1152 } |
| 1153 |
| 1154 HCURSOR WINAPI WebPluginDelegateImpl::SetCursorPatch(HCURSOR cursor) { |
| 1155 // The windowless flash plugin periodically calls SetCursor in a wndproc |
| 1156 // instantiated on the plugin thread. This causes annoying cursor flicker |
| 1157 // when the mouse is moved on a foreground tab, with a windowless plugin |
| 1158 // instance in a background tab. We just ignore the call here. |
| 1159 if (!current_plugin_instance_) |
| 1160 return GetCursor(); |
| 1161 |
| 1162 if (!current_plugin_instance_->windowless()) { |
| 1163 return SetCursor(cursor); |
| 1164 } |
| 1165 |
| 1166 // It is ok to pass NULL here to GetCursor as we are not looking for cursor |
| 1167 // types defined by Webkit. |
| 1168 HCURSOR previous_cursor = |
| 1169 current_plugin_instance_->current_windowless_cursor_.GetCursor(NULL); |
| 1170 |
| 1171 current_plugin_instance_->current_windowless_cursor_.InitFromExternalCursor( |
| 1172 cursor); |
| 1173 return previous_cursor; |
| 1174 } |
OLD | NEW |