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

Side by Side Diff: webkit/glue/plugins/webplugin_delegate_impl_mac.mm

Issue 113637: Wire up windowless plugins. Mostly Mac related, some cross (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 5 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') | no next file » | 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 #import <Cocoa/Cocoa.h>
6
5 #include "config.h" 7 #include "config.h"
6 #include "webkit/glue/plugins/webplugin_delegate_impl.h" 8 #include "webkit/glue/plugins/webplugin_delegate_impl.h"
7 9
8 #include <string> 10 #include <string>
9 #include <vector> 11 #include <vector>
10 12
11 #include "base/file_util.h" 13 #include "base/file_util.h"
12 #include "base/lazy_instance.h" 14 #include "base/lazy_instance.h"
13 #include "base/message_loop.h" 15 #include "base/message_loop.h"
14 #include "base/stats_counters.h" 16 #include "base/stats_counters.h"
15 #include "base/string_util.h" 17 #include "base/string_util.h"
16 #include "webkit/api/public/WebInputEvent.h" 18 #include "webkit/api/public/WebInputEvent.h"
17 #include "webkit/default_plugin/plugin_impl.h" 19 #include "webkit/default_plugin/plugin_impl.h"
18 #include "webkit/glue/glue_util.h" 20 #include "webkit/glue/glue_util.h"
19 #include "webkit/glue/webplugin.h" 21 #include "webkit/glue/webplugin.h"
20 #include "webkit/glue/plugins/plugin_constants_win.h" 22 #include "webkit/glue/plugins/plugin_constants_win.h"
21 #include "webkit/glue/plugins/plugin_instance.h" 23 #include "webkit/glue/plugins/plugin_instance.h"
22 #include "webkit/glue/plugins/plugin_lib.h" 24 #include "webkit/glue/plugins/plugin_lib.h"
23 #include "webkit/glue/plugins/plugin_list.h" 25 #include "webkit/glue/plugins/plugin_list.h"
24 #include "webkit/glue/plugins/plugin_stream_url.h" 26 #include "webkit/glue/plugins/plugin_stream_url.h"
25 #include "webkit/glue/webkit_glue.h" 27 #include "webkit/glue/webkit_glue.h"
26 28
27 using WebKit::WebCursorInfo; 29 using WebKit::WebCursorInfo;
28 using WebKit::WebKeyboardEvent; 30 using WebKit::WebKeyboardEvent;
29 using WebKit::WebInputEvent; 31 using WebKit::WebInputEvent;
30 using WebKit::WebMouseEvent; 32 using WebKit::WebMouseEvent;
31 33
34 // Important implementation notes: The Mac definition of NPAPI, particularly
35 // the distinction between windowed and windowless modes, differs from the
36 // Windows and Linux definitions. Most of those differences are
37 // accomodated by the WebPluginDelegate class.
38
32 namespace { 39 namespace {
33 40
34 const wchar_t kWebPluginDelegateProperty[] = L"WebPluginDelegateProperty"; 41 // The fastest we are willing to process idle events for Flash.
35 const wchar_t kPluginNameAtomProperty[] = L"PluginNameAtom";
36 const wchar_t kDummyActivationWindowName[] = L"DummyWindowForActivation";
37 const wchar_t kPluginOrigProc[] = L"OriginalPtr";
38 const wchar_t kPluginFlashThrottle[] = L"FlashThrottle";
39
40 // The fastest we are willing to process WM_USER+1 events for Flash.
41 // Flash can easily exceed the limits of our CPU if we don't throttle it. 42 // Flash can easily exceed the limits of our CPU if we don't throttle it.
42 // The throttle has been chosen by testing various delays and compromising 43 // The throttle has been chosen by testing various delays and compromising
43 // on acceptable Flash performance and reasonable CPU consumption. 44 // on acceptable Flash performance and reasonable CPU consumption.
44 // 45 //
45 // I'd like to make the throttle delay variable, based on the amount of 46 // We'd like to make the throttle delay variable, based on the amount of
46 // time currently required to paint Flash plugins. There isn't a good 47 // time currently required to paint Flash plugins. There isn't a good
47 // way to count the time spent in aggregate plugin painting, however, so 48 // way to count the time spent in aggregate plugin painting, however, so
48 // this seems to work well enough. 49 // this seems to work well enough.
49 const int kFlashWMUSERMessageThrottleDelayMs = 5; 50 const int kFlashIdleThrottleDelayMs = 20; // 20ms (50Hz)
50 51
51 // The current instance of the plugin which entered the modal loop. 52 // The current instance of the plugin which entered the modal loop.
52 WebPluginDelegateImpl* g_current_plugin_instance = NULL; 53 WebPluginDelegateImpl* g_current_plugin_instance = NULL;
53 54
54 // base::LazyInstance<std::list<MSG> > g_throttle_queue(base::LINKER_INITIALIZED );
55
56
57 } // namespace 55 } // namespace
58 56
59 WebPluginDelegate* WebPluginDelegate::Create( 57 WebPluginDelegate* WebPluginDelegate::Create(
60 const FilePath& filename, 58 const FilePath& filename,
61 const std::string& mime_type, 59 const std::string& mime_type,
62 gfx::PluginWindowHandle containing_view) { 60 gfx::PluginWindowHandle containing_view) {
63 scoped_refptr<NPAPI::PluginLib> plugin = 61 scoped_refptr<NPAPI::PluginLib> plugin =
64 NPAPI::PluginLib::CreatePluginLib(filename); 62 NPAPI::PluginLib::CreatePluginLib(filename);
65 if (plugin.get() == NULL) 63 if (plugin.get() == NULL)
66 return NULL; 64 return NULL;
67 65
68 NPError err = plugin->NP_Initialize(); 66 NPError err = plugin->NP_Initialize();
69 if (err != NPERR_NO_ERROR) 67 if (err != NPERR_NO_ERROR)
70 return NULL; 68 return NULL;
71 69
72 scoped_refptr<NPAPI::PluginInstance> instance = 70 scoped_refptr<NPAPI::PluginInstance> instance =
73 plugin->CreateInstance(mime_type); 71 plugin->CreateInstance(mime_type);
74 return new WebPluginDelegateImpl(containing_view, instance.get()); 72 return new WebPluginDelegateImpl(containing_view, instance.get());
75 } 73 }
76 74
77 WebPluginDelegateImpl::WebPluginDelegateImpl( 75 WebPluginDelegateImpl::WebPluginDelegateImpl(
78 gfx::PluginWindowHandle containing_view, 76 gfx::PluginWindowHandle containing_view,
79 NPAPI::PluginInstance *instance) 77 NPAPI::PluginInstance *instance)
80 : parent_(containing_view), 78 : parent_(containing_view),
81 instance_(instance), 79 instance_(instance),
82 quirks_(0), 80 quirks_(0),
83 plugin_(NULL), 81 plugin_(NULL),
84 windowless_(false), 82 // all Mac plugins are "windowless" in the Windows/X11 sense
85 windowed_handle_(NULL), 83 windowless_(true),
86 windowed_did_set_window_(false),
87 windowless_needs_set_window_(true), 84 windowless_needs_set_window_(true),
88 handle_event_depth_(0), 85 handle_event_depth_(0),
89 user_gesture_message_posted_(this), 86 user_gesture_message_posted_(this),
90 user_gesture_msg_factory_(this) { 87 user_gesture_msg_factory_(this) {
91 memset(&window_, 0, sizeof(window_)); 88 memset(&window_, 0, sizeof(window_));
92
93 const WebPluginInfo& plugin_info = instance_->plugin_lib()->plugin_info();
94 std::string filename =
95 StringToLowerASCII(plugin_info.path.BaseName().value());
96
97 // plugin_module_handle_ = ::GetModuleHandle(plugin_info.path.value().c_str()) ;
98 } 89 }
99 90
100 WebPluginDelegateImpl::~WebPluginDelegateImpl() { 91 WebPluginDelegateImpl::~WebPluginDelegateImpl() {
101 DestroyInstance(); 92 DestroyInstance();
102 93
103 if (!windowless_) 94 if (cg_context_.window)
104 WindowedDestroyWindow(); 95 DisposeWindow(cg_context_.window);
105 } 96 }
106 97
107 void WebPluginDelegateImpl::PluginDestroyed() { 98 void WebPluginDelegateImpl::PluginDestroyed() {
108 delete this; 99 delete this;
109 } 100 }
110 101
111 bool WebPluginDelegateImpl::Initialize(const GURL& url, 102 bool WebPluginDelegateImpl::Initialize(const GURL& url,
112 char** argn, 103 char** argn,
113 char** argv, 104 char** argv,
114 int argc, 105 int argc,
115 WebPlugin* plugin, 106 WebPlugin* plugin,
116 bool load_manually) { 107 bool load_manually) {
117 plugin_ = plugin; 108 plugin_ = plugin;
118 109
119 instance_->set_web_plugin(plugin); 110 instance_->set_web_plugin(plugin);
120 NPAPI::PluginInstance* old_instance = 111 NPAPI::PluginInstance* old_instance =
121 NPAPI::PluginInstance::SetInitializingInstance(instance_); 112 NPAPI::PluginInstance::SetInitializingInstance(instance_);
122 113
123 114
124 bool start_result = instance_->Start(url, argn, argv, argc, load_manually); 115 bool start_result = instance_->Start(url, argn, argv, argc, load_manually);
125 116
126 NPAPI::PluginInstance::SetInitializingInstance(old_instance); 117 NPAPI::PluginInstance::SetInitializingInstance(old_instance);
127 118
128 if (!start_result) 119 if (!start_result)
129 return false; 120 return false;
130 121
131 windowless_ = instance_->windowless(); 122 cg_context_.window = NULL;
132 if (windowless_) { 123 window_.window = &cg_context_;
133 // For windowless plugins we should set the containing window handle 124 window_.type = NPWindowTypeDrawable;
134 // as the instance window handle. This is what Safari does. Not having
135 // a valid window handle causes subtle bugs with plugins which retreive
136 // the window handle and validate the same. The window handle can be
137 // retreived via NPN_GetValue of NPNVnetscapeWindow.
138 // instance_->set_window_handle(parent_);
139 } else {
140 if (!WindowedCreatePlugin())
141 return false;
142 }
143 125
144 // plugin->SetWindow(windowed_handle_); 126 plugin->SetWindow(NULL);
145 plugin_url_ = url.spec(); 127 plugin_url_ = url.spec();
146 128
147 return true; 129 return true;
148 } 130 }
149 131
150 void WebPluginDelegateImpl::DestroyInstance() { 132 void WebPluginDelegateImpl::DestroyInstance() {
151 if (instance_ && (instance_->npp()->ndata != NULL)) { 133 if (instance_ && (instance_->npp()->ndata != NULL)) {
152 // Shutdown all streams before destroying so that 134 // Shutdown all streams before destroying so that
153 // no streams are left "in progress". Need to do 135 // no streams are left "in progress". Need to do
154 // this before calling set_web_plugin(NULL) because the 136 // this before calling set_web_plugin(NULL) because the
155 // instance uses the helper to do the download. 137 // instance uses the helper to do the download.
156 instance_->CloseStreams(); 138 instance_->CloseStreams();
157
158 window_.window = NULL;
159 instance_->NPP_SetWindow(&window_);
160
161 instance_->NPP_Destroy(); 139 instance_->NPP_Destroy();
162
163 instance_->set_web_plugin(NULL); 140 instance_->set_web_plugin(NULL);
164
165 if (instance_->plugin_lib()) {
166 // Unpatch if this is the last plugin instance.
167 }
168
169 instance_ = 0; 141 instance_ = 0;
170 } 142 }
171 } 143 }
172 144
173 void WebPluginDelegateImpl::UpdateGeometry( 145 void WebPluginDelegateImpl::UpdateGeometry(
174 const gfx::Rect& window_rect, 146 const gfx::Rect& window_rect,
175 const gfx::Rect& clip_rect) { 147 const gfx::Rect& clip_rect) {
176 if (windowless_) { 148
177 WindowlessUpdateGeometry(window_rect, clip_rect); 149 if (!window_rect.IsEmpty()) {
178 } else { 150 NSPoint windowOffset = {0.0, 0.0};
179 WindowedUpdateGeometry(window_rect, clip_rect); 151 Rect window_bounds;
152 window_bounds.top = window_rect.y() + windowOffset.y;
153 window_bounds.left = window_rect.x() + windowOffset.x;
154 window_bounds.bottom = window_rect.y() + window_rect.height();
155 window_bounds.right = window_rect.x() + window_rect.width();
156
157 if (!cg_context_.window) {
158 // For all plugins we create a placeholder offscreen window for the use
159 // of NPWindow. NPAPI on the Mac requires a Carbon WindowRef for the
160 // "browser window", even if we're not using the Quickdraw drawing model.
161 // Not having a valid window reference causes subtle bugs with plugins
162 // which retreive the NPWindow and validate the same. The NPWindow
163 // can be retreived via NPN_GetValue of NPNVnetscapeWindow.
164
165 WindowRef window_ref;
166 if (CreateNewWindow(kDocumentWindowClass,
167 kWindowStandardDocumentAttributes,
168 &window_bounds,
169 &window_ref) == noErr) {
170 cg_context_.window = window_ref;
171 }
172 } else {
173 SetWindowBounds(cg_context_.window, kWindowContentRgn, &window_bounds);
174 }
180 } 175 }
176
177 WindowlessUpdateGeometry(window_rect, clip_rect);
181 } 178 }
182 179
183 void WebPluginDelegateImpl::Paint(CGContextRef context, const gfx::Rect& rect) { 180 void WebPluginDelegateImpl::Paint(CGContextRef context, const gfx::Rect& rect) {
184 if (windowless_) 181 if (windowless_)
185 WindowlessPaint(context, rect); 182 WindowlessPaint(context, rect);
186 } 183 }
187 184
188 void WebPluginDelegateImpl::Print(CGContextRef context) { 185 void WebPluginDelegateImpl::Print(CGContextRef context) {
189 // Disabling the call to NPP_Print as it causes a crash in 186 // Disabling the call to NPP_Print as it causes a crash in
190 // flash in some cases. In any case this does not work as expected 187 // flash in some cases. In any case this does not work as expected
(...skipping 20 matching lines...) Expand all
211 bool success, 208 bool success,
212 bool notify_needed, 209 bool notify_needed,
213 intptr_t notify_data) { 210 intptr_t notify_data) {
214 instance()->SendJavaScriptStream(url, result, success, notify_needed, 211 instance()->SendJavaScriptStream(url, result, success, notify_needed,
215 notify_data); 212 notify_data);
216 } 213 }
217 214
218 void WebPluginDelegateImpl::DidReceiveManualResponse( 215 void WebPluginDelegateImpl::DidReceiveManualResponse(
219 const std::string& url, const std::string& mime_type, 216 const std::string& url, const std::string& mime_type,
220 const std::string& headers, uint32 expected_length, uint32 last_modified) { 217 const std::string& headers, uint32 expected_length, uint32 last_modified) {
221 if (!windowless_) {
222 // Calling NPP_WriteReady before NPP_SetWindow causes movies to not load in
223 // Flash. See http://b/issue?id=892174.
224 DCHECK(windowed_did_set_window_);
225 }
226
227 instance()->DidReceiveManualResponse(url, mime_type, headers, 218 instance()->DidReceiveManualResponse(url, mime_type, headers,
228 expected_length, last_modified); 219 expected_length, last_modified);
229 } 220 }
230 221
231 void WebPluginDelegateImpl::DidReceiveManualData(const char* buffer, 222 void WebPluginDelegateImpl::DidReceiveManualData(const char* buffer,
232 int length) { 223 int length) {
233 instance()->DidReceiveManualData(buffer, length); 224 instance()->DidReceiveManualData(buffer, length);
234 } 225 }
235 226
236 void WebPluginDelegateImpl::DidFinishManualLoading() { 227 void WebPluginDelegateImpl::DidFinishManualLoading() {
237 instance()->DidFinishManualLoading(); 228 instance()->DidFinishManualLoading();
238 } 229 }
239 230
240 void WebPluginDelegateImpl::DidManualLoadFail() { 231 void WebPluginDelegateImpl::DidManualLoadFail() {
241 instance()->DidManualLoadFail(); 232 instance()->DidManualLoadFail();
242 } 233 }
243 234
244 FilePath WebPluginDelegateImpl::GetPluginPath() { 235 FilePath WebPluginDelegateImpl::GetPluginPath() {
245 return instance()->plugin_lib()->plugin_info().path; 236 return instance()->plugin_lib()->plugin_info().path;
246 } 237 }
247 238
248 void WebPluginDelegateImpl::InstallMissingPlugin() { 239 void WebPluginDelegateImpl::InstallMissingPlugin() {
249 NPEvent evt; 240 NPEvent evt;
250 instance()->NPP_HandleEvent(&evt); 241 instance()->NPP_HandleEvent(&evt);
251 } 242 }
252 243
253 void WebPluginDelegateImpl::WindowedUpdateGeometry(
254 const gfx::Rect& window_rect,
255 const gfx::Rect& clip_rect) {
256 if (WindowedReposition(window_rect, clip_rect) ||
257 !windowed_did_set_window_) {
258 // Let the plugin know that it has been moved
259 WindowedSetWindow();
260 }
261 }
262
263 bool WebPluginDelegateImpl::WindowedCreatePlugin() {
264 DCHECK(!windowed_handle_);
265
266 // create window
267 if (windowed_handle_ == 0)
268 return false;
269
270 return true;
271 }
272
273 void WebPluginDelegateImpl::WindowedDestroyWindow() {
274 if (windowed_handle_ != NULL) {
275 // destroy the window
276 windowed_handle_ = 0;
277 }
278 }
279
280 bool WebPluginDelegateImpl::WindowedReposition(
281 const gfx::Rect& window_rect,
282 const gfx::Rect& clip_rect) {
283 if (!windowed_handle_) {
284 NOTREACHED();
285 return false;
286 }
287
288 if (window_rect_ == window_rect && clip_rect_ == clip_rect)
289 return false;
290
291 // Clipping is handled by WebPlugin.
292 if (window_rect.size() != window_rect_.size()) {
293 // resize window
294 }
295
296 window_rect_ = window_rect;
297 clip_rect_ = clip_rect;
298
299 // Ensure that the entire window gets repainted.
300 // invalidate entire window
301
302 return true;
303 }
304
305 void WebPluginDelegateImpl::WindowedSetWindow() {
306 if (!instance_)
307 return;
308
309 if (!windowed_handle_) {
310 NOTREACHED();
311 return;
312 }
313
314 // instance()->set_window_handle(windowed_handle_);
315
316 DCHECK(!instance()->windowless());
317
318 window_.clipRect.top = clip_rect_.y();
319 window_.clipRect.left = clip_rect_.x();
320 window_.clipRect.bottom = clip_rect_.y() + clip_rect_.height();
321 window_.clipRect.right = clip_rect_.x() + clip_rect_.width();
322 window_.height = window_rect_.height();
323 window_.width = window_rect_.width();
324 window_.x = window_rect_.x();
325 window_.y = window_rect_.y();
326
327 cg_context_.context = NULL;
328 cg_context_.window = NULL;
329 window_.window = &cg_context_;
330 window_.type = NPWindowTypeDrawable; // NPWindowTypeWindow;
331
332 // Reset this flag before entering the instance in case of side-effects.
333 windowed_did_set_window_ = true;
334
335 NPError err = instance()->NPP_SetWindow(&window_);
336 }
337
338 void WebPluginDelegateImpl::WindowlessUpdateGeometry( 244 void WebPluginDelegateImpl::WindowlessUpdateGeometry(
339 const gfx::Rect& window_rect, 245 const gfx::Rect& window_rect,
340 const gfx::Rect& clip_rect) { 246 const gfx::Rect& clip_rect) {
341 // Only resend to the instance if the geometry has changed. 247 // Only resend to the instance if the geometry has changed.
342 if (window_rect == window_rect_ && clip_rect == clip_rect_) 248 if (window_rect == window_rect_ && clip_rect == clip_rect_)
343 return; 249 return;
344 250
345 // We will inform the instance of this change when we call NPP_SetWindow. 251 // We will inform the instance of this change when we call NPP_SetWindow.
346 clip_rect_ = clip_rect; 252 clip_rect_ = clip_rect;
347 cutout_rects_.clear(); 253 cutout_rects_.clear();
348 254
349 if (window_rect_ != window_rect) { 255 if (window_rect_ != window_rect) {
350 window_rect_ = window_rect; 256 window_rect_ = window_rect;
351 257
352 WindowlessSetWindow(true); 258 window_.clipRect.top = clip_rect_.y();
353 259 window_.clipRect.left = clip_rect_.x();
354 NPEvent pos_changed_event; 260 window_.clipRect.bottom = clip_rect_.y() + clip_rect_.height();
355 261 window_.clipRect.right = clip_rect_.x() + clip_rect_.width();
356 instance()->NPP_HandleEvent(&pos_changed_event); 262 window_.height = window_rect_.height();
263 window_.width = window_rect_.width();
264 window_.x = window_rect_.x();
265 window_.y = window_rect_.y();
266 window_.type = NPWindowTypeDrawable;
267 windowless_needs_set_window_ = true;
357 } 268 }
358 } 269 }
359 270
360 void WebPluginDelegateImpl::WindowlessPaint(gfx::NativeDrawingContext hdc, 271 void WebPluginDelegateImpl::WindowlessPaint(gfx::NativeDrawingContext context,
361 const gfx::Rect& damage_rect) { 272 const gfx::Rect& damage_rect) {
362 static StatsRate plugin_paint("Plugin.Paint"); 273 static StatsRate plugin_paint("Plugin.Paint");
363 StatsScope<StatsRate> scope(plugin_paint); 274 StatsScope<StatsRate> scope(plugin_paint);
275
276 // We save and restore the NSGraphicsContext state in case the plugin uses
277 // Cocoa drawing.
278 [NSGraphicsContext saveGraphicsState];
279 [NSGraphicsContext setCurrentContext:[NSGraphicsContext
280 graphicsContextWithGraphicsPort:context
281 flipped:NO]];
282
283 CGContextSaveGState(context);
284 cg_context_.context = context;
285 window_.window = &cg_context_;
286 window_.type = NPWindowTypeDrawable;
287 if (windowless_needs_set_window_) {
288 Rect window_bounds;
289 window_bounds.top = window_rect_.y();
290 window_bounds.left = window_rect_.x();
291 window_bounds.bottom = window_rect_.y() + window_rect_.height();
292 window_bounds.right = window_rect_.x() + window_rect_.width();
293 if (!cg_context_.window) {
294 // For all plugins we create a placeholder offscreen window for the use
295 // of NPWindow. NPAPI on the Mac requires a Carbon WindowRef for the
296 // "browser window", even if we're not using the Quickdraw drawing model.
297 // Not having a valid window reference causes subtle bugs with plugins
298 // which retreive the NPWindow and validate the same. The NPWindow
299 // can be retreived via NPN_GetValue of NPNVnetscapeWindow.
300
301 WindowRef window_ref;
302 if (CreateNewWindow(kDocumentWindowClass,
303 kWindowStandardDocumentAttributes,
304 &window_bounds,
305 &window_ref) == noErr) {
306 cg_context_.window = window_ref;
307 }
308 } else {
309 SetWindowBounds(cg_context_.window, kWindowContentRgn, &window_bounds);
310 }
311 instance()->NPP_SetWindow(&window_);
312 windowless_needs_set_window_ = false;
313 }
364 NPEvent paint_event; 314 NPEvent paint_event;
315 paint_event.what = updateEvt;
316 paint_event.message = reinterpret_cast<uint32>(cg_context_.window);
317 paint_event.when = TickCount();
318 paint_event.where.h = 0;
319 paint_event.where.v = 0;
320 paint_event.modifiers = 0;
365 instance()->NPP_HandleEvent(&paint_event); 321 instance()->NPP_HandleEvent(&paint_event);
322 CGContextRestoreGState(context);
323 [NSGraphicsContext restoreGraphicsState];
366 } 324 }
367 325
368 void WebPluginDelegateImpl::WindowlessSetWindow(bool force_set_window) { 326 void WebPluginDelegateImpl::WindowlessSetWindow(bool force_set_window) {
369 if (!instance()) 327 if (!instance())
370 return; 328 return;
371 329
372 if (window_rect_.IsEmpty()) // wait for geometry to be set. 330 if (window_rect_.IsEmpty()) // wait for geometry to be set.
373 return; 331 return;
374 332
375 DCHECK(instance()->windowless());
376
377 window_.clipRect.top = clip_rect_.y(); 333 window_.clipRect.top = clip_rect_.y();
378 window_.clipRect.left = clip_rect_.x(); 334 window_.clipRect.left = clip_rect_.x();
379 window_.clipRect.bottom = clip_rect_.y() + clip_rect_.height(); 335 window_.clipRect.bottom = clip_rect_.y() + clip_rect_.height();
380 window_.clipRect.right = clip_rect_.x() + clip_rect_.width(); 336 window_.clipRect.right = clip_rect_.x() + clip_rect_.width();
381 window_.height = window_rect_.height(); 337 window_.height = window_rect_.height();
382 window_.width = window_rect_.width(); 338 window_.width = window_rect_.width();
383 window_.x = window_rect_.x(); 339 window_.x = window_rect_.x();
384 window_.y = window_rect_.y(); 340 window_.y = window_rect_.y();
385 window_.type = NPWindowTypeDrawable; 341 window_.type = NPWindowTypeDrawable;
386 342
387 if (!force_set_window) 343 if (!force_set_window)
388 // Reset this flag before entering the instance in case of side-effects. 344 // Reset this flag before entering the instance in case of side-effects.
389 windowless_needs_set_window_ = false; 345 windowless_needs_set_window_ = false;
390 346
347 Rect window_bounds;
348 window_bounds.top = window_rect_.y();
349 window_bounds.left = window_rect_.x();
350 window_bounds.bottom = window_rect_.y() + window_rect_.height();
351 window_bounds.right = window_rect_.x() + window_rect_.width();
352 if (!cg_context_.window) {
353 // For all plugins we create a placeholder offscreen window for the use
354 // of NPWindow. NPAPI on the Mac requires a Carbon WindowRef for the
355 // "browser window", even if we're not using the Quickdraw drawing model.
356 // Not having a valid window reference causes subtle bugs with plugins
357 // which retreive the NPWindow and validate the same. The NPWindow
358 // can be retreived via NPN_GetValue of NPNVnetscapeWindow.
359
360 WindowRef window_ref;
361 if (CreateNewWindow(kDocumentWindowClass,
362 kWindowStandardDocumentAttributes,
363 &window_bounds,
364 &window_ref) == noErr) {
365 cg_context_.window = window_ref;
366 }
367 } else {
368 SetWindowBounds(cg_context_.window, kWindowContentRgn, &window_bounds);
369 }
370
391 NPError err = instance()->NPP_SetWindow(&window_); 371 NPError err = instance()->NPP_SetWindow(&window_);
392 DCHECK(err == NPERR_NO_ERROR); 372 DCHECK(err == NPERR_NO_ERROR);
393 } 373 }
394 374
395 void WebPluginDelegateImpl::SetFocus() { 375 void WebPluginDelegateImpl::SetFocus() {
396 DCHECK(instance()->windowless()); 376 NPEvent focus_event = { 0 };
377 focus_event.what = NPEventType_GetFocusEvent;
378 focus_event.when = TickCount();
379 instance()->NPP_HandleEvent(&focus_event);
380 }
397 381
398 NPEvent focus_event; 382 static bool NPEventFromWebMouseEvent(const WebMouseEvent& event,
383 NPEvent *np_event) {
384 np_event->where.h = event.windowX;
385 np_event->where.v = event.windowY;
399 386
400 instance()->NPP_HandleEvent(&focus_event); 387 if (event.modifiers & WebInputEvent::ControlKey)
388 np_event->modifiers |= controlKey;
389 if (event.modifiers & WebInputEvent::ShiftKey)
390 np_event->modifiers |= shiftKey;
391
392 switch (event.type) {
393 case WebInputEvent::MouseMove:
394 case WebInputEvent::MouseLeave:
395 case WebInputEvent::MouseEnter:
396 np_event->what = NPEventType_AdjustCursorEvent;
397 return true;
398 case WebInputEvent::MouseDown:
399 switch (event.button) {
400 case WebMouseEvent::ButtonLeft:
401 case WebMouseEvent::ButtonMiddle:
402 case WebMouseEvent::ButtonRight:
403 np_event->what = mouseDown;
404 break;
405 }
406 return true;
407 case WebInputEvent::MouseUp:
408 switch (event.button) {
409 case WebMouseEvent::ButtonLeft:
410 case WebMouseEvent::ButtonMiddle:
411 case WebMouseEvent::ButtonRight:
412 np_event->what = mouseUp;
413 break;
414 }
415 return true;
416 default:
417 NOTREACHED();
418 return false;
419 }
420 }
421
422 static bool NPEventFromWebKeyboardEvent(const WebKeyboardEvent& event,
423 NPEvent *np_event) {
424 np_event->message = event.nativeKeyCode;
425
426 switch (event.type) {
427 case WebInputEvent::KeyDown:
428 np_event->what = keyDown;
429 return true;
430 case WebInputEvent::KeyUp:
431 np_event->what = keyUp;
432 return true;
433 default:
434 NOTREACHED();
435 return false;
436 }
437 }
438
439 static bool NPEventFromWebInputEvent(const WebInputEvent& event,
440 NPEvent* np_event) {
441 switch (event.type) {
442 case WebInputEvent::MouseMove:
443 case WebInputEvent::MouseLeave:
444 case WebInputEvent::MouseEnter:
445 case WebInputEvent::MouseDown:
446 case WebInputEvent::MouseUp:
447 if (event.size < sizeof(WebMouseEvent)) {
448 NOTREACHED();
449 return false;
450 }
451 return NPEventFromWebMouseEvent(*static_cast<const WebMouseEvent*>(&event) , np_event);
452 case WebInputEvent::KeyDown:
453 case WebInputEvent::KeyUp:
454 if (event.size < sizeof(WebKeyboardEvent)) {
455 NOTREACHED();
456 return false;
457 }
458 return NPEventFromWebKeyboardEvent(*static_cast<const WebKeyboardEvent*>(& event), np_event);
459 default:
460 DLOG(WARNING) << "unknown event type" << event.type;
461 return false;
462 }
401 } 463 }
402 464
403 bool WebPluginDelegateImpl::HandleInputEvent(const WebInputEvent& event, 465 bool WebPluginDelegateImpl::HandleInputEvent(const WebInputEvent& event,
404 WebCursorInfo* cursor) { 466 WebCursorInfo* cursor) {
405 DCHECK(windowless_) << "events should only be received in windowless mode"; 467 DCHECK(windowless_) << "events should only be received in windowless mode";
406 DCHECK(cursor != NULL); 468 DCHECK(cursor != NULL);
407 // TODO: convert event into a NPEvent, and call NPP_HandleEvent(np_event).
408 469
409 return true; 470 NPEvent np_event = {0};
471 if (!NPEventFromWebInputEvent(event, &np_event)) {
472 return false;
473 }
474 np_event.when = TickCount();
475 bool ret = instance()->NPP_HandleEvent(&np_event) != 0;
476 return ret;
410 } 477 }
411 478
412 WebPluginResourceClient* WebPluginDelegateImpl::CreateResourceClient( 479 WebPluginResourceClient* WebPluginDelegateImpl::CreateResourceClient(
413 int resource_id, const std::string &url, bool notify_needed, 480 int resource_id, const std::string &url, bool notify_needed,
414 intptr_t notify_data, intptr_t existing_stream) { 481 intptr_t notify_data, intptr_t existing_stream) {
415 // Stream already exists. This typically happens for range requests 482 // Stream already exists. This typically happens for range requests
416 // initiated via NPN_RequestRead. 483 // initiated via NPN_RequestRead.
417 if (existing_stream) { 484 if (existing_stream) {
418 NPAPI::PluginStream* plugin_stream = 485 NPAPI::PluginStream* plugin_stream =
419 reinterpret_cast<NPAPI::PluginStream*>(existing_stream); 486 reinterpret_cast<NPAPI::PluginStream*>(existing_stream);
(...skipping 13 matching lines...) Expand all
433 return stream; 500 return stream;
434 } 501 }
435 502
436 void WebPluginDelegateImpl::URLRequestRouted(const std::string&url, 503 void WebPluginDelegateImpl::URLRequestRouted(const std::string&url,
437 bool notify_needed, 504 bool notify_needed,
438 intptr_t notify_data) { 505 intptr_t notify_data) {
439 if (notify_needed) { 506 if (notify_needed) {
440 instance()->SetURLLoadData(GURL(url.c_str()), notify_data); 507 instance()->SetURLLoadData(GURL(url.c_str()), notify_data);
441 } 508 }
442 } 509 }
OLDNEW
« no previous file with comments | « webkit/glue/plugins/webplugin_delegate_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698