Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(418)

Side by Side Diff: webkit/glue/plugins/webplugin_delegate_impl.cc

Issue 15088: Add support for custom cursors set by windowless plugins. Windowless plugins... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « webkit/glue/plugins/webplugin_delegate_impl.h ('k') | webkit/glue/webcursor.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « webkit/glue/plugins/webplugin_delegate_impl.h ('k') | webkit/glue/webcursor.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698