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 // HACK: we need this #define in place before npapi.h is included for | 5 // HACK: we need this #define in place before npapi.h is included for |
6 // plugins to work. However, all sorts of headers include npapi.h, so | 6 // plugins to work. However, all sorts of headers include npapi.h, so |
7 // the only way to be certain the define is in place is to put it | 7 // the only way to be certain the define is in place is to put it |
8 // here. You might ask, "Why not set it in npapi.h directly, or in | 8 // here. You might ask, "Why not set it in npapi.h directly, or in |
9 // this directory's SConscript, then?" but it turns out this define | 9 // this directory's SConscript, then?" but it turns out this define |
10 // makes npapi.h include Xlib.h, which in turn defines a ton of symbols | 10 // makes npapi.h include Xlib.h, which in turn defines a ton of symbols |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 | 57 |
58 WebPluginDelegateImpl::WebPluginDelegateImpl( | 58 WebPluginDelegateImpl::WebPluginDelegateImpl( |
59 gfx::NativeView containing_view, | 59 gfx::NativeView containing_view, |
60 NPAPI::PluginInstance *instance) | 60 NPAPI::PluginInstance *instance) |
61 : | 61 : |
62 windowed_handle_(0), | 62 windowed_handle_(0), |
63 windowed_did_set_window_(false), | 63 windowed_did_set_window_(false), |
64 windowless_(false), | 64 windowless_(false), |
65 plugin_(NULL), | 65 plugin_(NULL), |
66 instance_(instance), | 66 instance_(instance), |
| 67 pixmap_(NULL), |
67 parent_(containing_view), | 68 parent_(containing_view), |
68 quirks_(0) | 69 quirks_(0) |
69 { | 70 { |
70 memset(&window_, 0, sizeof(window_)); | 71 memset(&window_, 0, sizeof(window_)); |
71 | 72 |
72 } | 73 } |
73 | 74 |
74 WebPluginDelegateImpl::~WebPluginDelegateImpl() { | 75 WebPluginDelegateImpl::~WebPluginDelegateImpl() { |
75 DestroyInstance(); | 76 DestroyInstance(); |
76 | 77 |
77 if (!windowless_) | 78 if (!windowless_) |
78 WindowedDestroyWindow(); | 79 WindowedDestroyWindow(); |
| 80 |
| 81 if (window_.ws_info) { |
| 82 // We only ever use ws_info as an NPSetWindowCallbackStruct. |
| 83 delete static_cast<NPSetWindowCallbackStruct*>(window_.ws_info); |
| 84 } |
| 85 |
| 86 if (pixmap_) { |
| 87 g_object_unref(gdk_drawable_get_colormap(pixmap_)); |
| 88 g_object_unref(pixmap_); |
| 89 pixmap_ = NULL; |
| 90 } |
79 } | 91 } |
80 | 92 |
81 void WebPluginDelegateImpl::PluginDestroyed() { | 93 void WebPluginDelegateImpl::PluginDestroyed() { |
82 delete this; | 94 delete this; |
83 } | 95 } |
84 | 96 |
85 bool WebPluginDelegateImpl::Initialize(const GURL& url, | 97 bool WebPluginDelegateImpl::Initialize(const GURL& url, |
86 char** argn, | 98 char** argn, |
87 char** argv, | 99 char** argv, |
88 int argc, | 100 int argc, |
(...skipping 12 matching lines...) Expand all Loading... |
101 if (!start_result) | 113 if (!start_result) |
102 return false; | 114 return false; |
103 | 115 |
104 windowless_ = instance_->windowless(); | 116 windowless_ = instance_->windowless(); |
105 if (windowless_) { | 117 if (windowless_) { |
106 // For windowless plugins we should set the containing window handle | 118 // For windowless plugins we should set the containing window handle |
107 // as the instance window handle. This is what Safari does. Not having | 119 // as the instance window handle. This is what Safari does. Not having |
108 // a valid window handle causes subtle bugs with plugins which retreive | 120 // a valid window handle causes subtle bugs with plugins which retreive |
109 // the window handle and validate the same. The window handle can be | 121 // the window handle and validate the same. The window handle can be |
110 // retreived via NPN_GetValue of NPNVnetscapeWindow. | 122 // retreived via NPN_GetValue of NPNVnetscapeWindow. |
111 NOTIMPLEMENTED() << "windowless not implemented"; | |
112 return false; | |
113 // instance_->set_window_handle(parent_); | 123 // instance_->set_window_handle(parent_); |
114 // CreateDummyWindowForActivation(); | 124 // CreateDummyWindowForActivation(); |
115 // handle_event_pump_messages_event_ = CreateEvent(NULL, TRUE, FALSE, NULL); | 125 // handle_event_pump_messages_event_ = CreateEvent(NULL, TRUE, FALSE, NULL); |
116 } else { | 126 } else { |
117 if (!WindowedCreatePlugin()) | 127 if (!WindowedCreatePlugin()) |
118 return false; | 128 return false; |
119 } | 129 } |
120 | 130 |
121 plugin->SetWindow(windowed_handle_, /* unused event param */ NULL); | 131 plugin->SetWindow(windowed_handle_, /* unused event param */ NULL); |
122 plugin_url_ = url.spec(); | 132 plugin_url_ = url.spec(); |
(...skipping 29 matching lines...) Expand all Loading... |
152 void WebPluginDelegateImpl::UpdateGeometry( | 162 void WebPluginDelegateImpl::UpdateGeometry( |
153 const gfx::Rect& window_rect, | 163 const gfx::Rect& window_rect, |
154 const gfx::Rect& clip_rect) { | 164 const gfx::Rect& clip_rect) { |
155 if (windowless_) { | 165 if (windowless_) { |
156 WindowlessUpdateGeometry(window_rect, clip_rect); | 166 WindowlessUpdateGeometry(window_rect, clip_rect); |
157 } else { | 167 } else { |
158 WindowedUpdateGeometry(window_rect, clip_rect); | 168 WindowedUpdateGeometry(window_rect, clip_rect); |
159 } | 169 } |
160 } | 170 } |
161 | 171 |
162 void WebPluginDelegateImpl::Paint(void* dc, const gfx::Rect& rect) { | 172 void WebPluginDelegateImpl::Paint(cairo_surface_t* context, |
| 173 const gfx::Rect& rect) { |
163 if (windowless_) { | 174 if (windowless_) { |
164 // TODO(port): windowless painting. | 175 WindowlessPaint(context, rect); |
165 // WindowlessPaint(dc, rect); | |
166 } | 176 } |
167 } | 177 } |
168 | 178 |
169 void WebPluginDelegateImpl::Print(void* dc) { | 179 void WebPluginDelegateImpl::Print(cairo_surface_t* context) { |
170 NOTIMPLEMENTED(); | 180 NOTIMPLEMENTED(); |
171 } | 181 } |
172 | 182 |
173 NPObject* WebPluginDelegateImpl::GetPluginScriptableObject() { | 183 NPObject* WebPluginDelegateImpl::GetPluginScriptableObject() { |
174 return instance_->GetPluginScriptableObject(); | 184 return instance_->GetPluginScriptableObject(); |
175 } | 185 } |
176 | 186 |
177 void WebPluginDelegateImpl::DidFinishLoadWithReason(NPReason reason) { | 187 void WebPluginDelegateImpl::DidFinishLoadWithReason(NPReason reason) { |
178 instance()->DidFinishLoadWithReason(reason); | 188 instance()->DidFinishLoadWithReason(reason); |
179 } | 189 } |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
314 gtk_container_add(GTK_CONTAINER(parent_), windowed_handle_); | 324 gtk_container_add(GTK_CONTAINER(parent_), windowed_handle_); |
315 // TODO(evanm): connect to signals on the socket, like when the other side | 325 // TODO(evanm): connect to signals on the socket, like when the other side |
316 // goes away. | 326 // goes away. |
317 | 327 |
318 gtk_widget_show(windowed_handle_); | 328 gtk_widget_show(windowed_handle_); |
319 gtk_widget_realize(windowed_handle_); | 329 gtk_widget_realize(windowed_handle_); |
320 | 330 |
321 window_.window = GINT_TO_POINTER( | 331 window_.window = GINT_TO_POINTER( |
322 gtk_socket_get_id(GTK_SOCKET(windowed_handle_))); | 332 gtk_socket_get_id(GTK_SOCKET(windowed_handle_))); |
323 | 333 |
324 NPSetWindowCallbackStruct* extra = new NPSetWindowCallbackStruct; | 334 if (!window_.ws_info) |
| 335 window_.ws_info = new NPSetWindowCallbackStruct; |
| 336 NPSetWindowCallbackStruct* extra = |
| 337 static_cast<NPSetWindowCallbackStruct*>(window_.ws_info); |
325 extra->display = GDK_WINDOW_XDISPLAY(windowed_handle_->window); | 338 extra->display = GDK_WINDOW_XDISPLAY(windowed_handle_->window); |
326 GdkVisual* visual = gdk_drawable_get_visual(windowed_handle_->window); | 339 GdkVisual* visual = gdk_drawable_get_visual(windowed_handle_->window); |
327 extra->visual = GDK_VISUAL_XVISUAL(visual); | 340 extra->visual = GDK_VISUAL_XVISUAL(visual); |
328 extra->depth = visual->depth; | 341 extra->depth = visual->depth; |
329 extra->colormap = GDK_COLORMAP_XCOLORMAP(gdk_drawable_get_colormap(windowed_ha
ndle_->window)); | 342 extra->colormap = GDK_COLORMAP_XCOLORMAP(gdk_drawable_get_colormap(windowed_ha
ndle_->window)); |
330 window_.ws_info = extra; | |
331 | 343 |
332 return true; | 344 return true; |
333 } | 345 } |
334 | 346 |
335 void WebPluginDelegateImpl::WindowedDestroyWindow() { | 347 void WebPluginDelegateImpl::WindowedDestroyWindow() { |
336 if (windowed_handle_ != NULL) { | 348 if (windowed_handle_ != NULL) { |
337 gtk_widget_destroy(windowed_handle_); | 349 gtk_widget_destroy(windowed_handle_); |
338 windowed_handle_ = NULL; | 350 windowed_handle_ = NULL; |
339 } | 351 } |
340 } | 352 } |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
404 NPError err = instance()->NPP_SetWindow(&window_); | 416 NPError err = instance()->NPP_SetWindow(&window_); |
405 DCHECK(err == NPERR_NO_ERROR); | 417 DCHECK(err == NPERR_NO_ERROR); |
406 } | 418 } |
407 | 419 |
408 void WebPluginDelegateImpl::WindowlessUpdateGeometry( | 420 void WebPluginDelegateImpl::WindowlessUpdateGeometry( |
409 const gfx::Rect& window_rect, | 421 const gfx::Rect& window_rect, |
410 const gfx::Rect& clip_rect) { | 422 const gfx::Rect& clip_rect) { |
411 // Only resend to the instance if the geometry has changed. | 423 // Only resend to the instance if the geometry has changed. |
412 if (window_rect == window_rect_ && clip_rect == clip_rect_) | 424 if (window_rect == window_rect_ && clip_rect == clip_rect_) |
413 return; | 425 return; |
414 /* | 426 |
415 // Set this flag before entering the instance in case of side-effects. | 427 // Set this flag before entering the instance in case of side-effects. |
416 windowless_needs_set_window_ = true; | 428 windowless_needs_set_window_ = true; |
417 | 429 |
418 // We will inform the instance of this change when we call NPP_SetWindow. | 430 // We will inform the instance of this change when we call NPP_SetWindow. |
419 clip_rect_ = clip_rect; | 431 clip_rect_ = clip_rect; |
420 cutout_rects_.clear(); | 432 cutout_rects_.clear(); |
421 | 433 |
422 if (window_rect_ != window_rect) { | 434 if (window_rect_ != window_rect) { |
423 window_rect_ = window_rect; | 435 window_rect_ = window_rect; |
424 | 436 |
425 WindowlessSetWindow(true); | 437 WindowlessSetWindow(true); |
426 | |
427 WINDOWPOS win_pos = {0}; | |
428 win_pos.x = window_rect_.x(); | |
429 win_pos.y = window_rect_.y(); | |
430 win_pos.cx = window_rect_.width(); | |
431 win_pos.cy = window_rect_.height(); | |
432 | |
433 NPEvent pos_changed_event; | |
434 pos_changed_event.event = WM_WINDOWPOSCHANGED; | |
435 pos_changed_event.wParam = 0; | |
436 pos_changed_event.lParam = PtrToUlong(&win_pos); | |
437 | |
438 instance()->NPP_HandleEvent(&pos_changed_event); | |
439 } | 438 } |
440 */ | |
441 } | 439 } |
442 | 440 |
443 #if 0 | 441 void WebPluginDelegateImpl::EnsurePixmapAtLeastSize(int width, int height) { |
444 void WebPluginDelegateImpl::WindowlessPaint(HDC hdc, | 442 if (pixmap_) { |
| 443 gint cur_width, cur_height; |
| 444 gdk_drawable_get_size(pixmap_, &cur_width, &cur_height); |
| 445 if (cur_width >= width && cur_height >= height) |
| 446 return; // We are already the appropriate size. |
| 447 |
| 448 // Otherwise, we need to recreate ourselves. |
| 449 g_object_unref(gdk_drawable_get_colormap(pixmap_)); |
| 450 g_object_unref(pixmap_); |
| 451 pixmap_ = NULL; |
| 452 } |
| 453 |
| 454 // |sys_visual| is owned by gdk; we shouldn't free it. |
| 455 GdkVisual* sys_visual = gdk_visual_get_system(); |
| 456 pixmap_ = gdk_pixmap_new(NULL, // use width/height/depth params |
| 457 width, height, sys_visual->depth); |
| 458 GdkColormap* colormap = gdk_colormap_new(gdk_visual_get_system(), |
| 459 FALSE); |
| 460 gdk_drawable_set_colormap(GDK_DRAWABLE(pixmap_), colormap); |
| 461 } |
| 462 |
| 463 void WebPluginDelegateImpl::WindowlessPaint(cairo_surface_t* context, |
445 const gfx::Rect& damage_rect) { | 464 const gfx::Rect& damage_rect) { |
446 DCHECK(hdc); | 465 // Compare to: |
| 466 // http://mxr.mozilla.org/firefox/source/layout/generic/nsObjectFrame.cpp: |
| 467 // nsPluginInstanceOwner::Renderer::NativeDraw(). |
447 | 468 |
448 RECT damage_rect_win; | 469 DCHECK(context); |
449 damage_rect_win.left = damage_rect.x(); // + window_rect_.x(); | |
450 damage_rect_win.top = damage_rect.y(); // + window_rect_.y(); | |
451 damage_rect_win.right = damage_rect_win.left + damage_rect.width(); | |
452 damage_rect_win.bottom = damage_rect_win.top + damage_rect.height(); | |
453 | 470 |
454 // We need to pass the HDC to the plugin via NPP_SetWindow in the | 471 // We need to pass the DC to the plugin via NPP_SetWindow in the |
455 // first paint to ensure that it initiates rect invalidations. | 472 // first paint to ensure that it initiates rect invalidations. |
456 if (window_.window == NULL) | 473 // TODO(evanm): for now, it appears we always need to do this. |
| 474 if (true) |
457 windowless_needs_set_window_ = true; | 475 windowless_needs_set_window_ = true; |
458 | 476 |
459 window_.window = hdc; | |
460 // TODO(darin): we should avoid calling NPP_SetWindow here since it may | 477 // TODO(darin): we should avoid calling NPP_SetWindow here since it may |
461 // cause page layout to be invalidated. | 478 // cause page layout to be invalidated. |
462 | 479 |
463 // We really don't need to continually call SetWindow. | 480 // We really don't need to continually call SetWindow. |
464 // m_needsSetWindow flags when the geometry has changed. | 481 // m_needsSetWindow flags when the geometry has changed. |
465 if (windowless_needs_set_window_) | 482 if (windowless_needs_set_window_) |
466 WindowlessSetWindow(false); | 483 WindowlessSetWindow(false); |
467 | 484 |
468 NPEvent paint_event; | 485 EnsurePixmapAtLeastSize(damage_rect.width(), damage_rect.height()); |
469 paint_event.event = WM_PAINT; | 486 |
470 // NOTE: NPAPI is not 64bit safe. It puts pointers into 32bit values. | 487 // Copy the current image into the pixmap, so the plugin can draw over |
471 paint_event.wParam = PtrToUlong(hdc); | 488 // this background. |
472 paint_event.lParam = PtrToUlong(&damage_rect_win); | 489 cairo_t* cairo = gdk_cairo_create(pixmap_); |
| 490 cairo_set_source_surface(cairo, context, 0, 0); |
| 491 cairo_paint(cairo); |
| 492 cairo_destroy(cairo); |
| 493 |
| 494 // Construct the paint message, targeting the pixmap. |
| 495 XGraphicsExposeEvent event = {0}; |
| 496 event.type = GraphicsExpose; |
| 497 event.display = GDK_DISPLAY(); |
| 498 event.drawable = GDK_PIXMAP_XID(pixmap_); |
| 499 event.x = damage_rect.x(); |
| 500 event.y = damage_rect.y(); |
| 501 event.width = damage_rect.width(); |
| 502 event.height = damage_rect.height(); |
| 503 |
| 504 // Tell the plugin to paint into the pixmap. |
473 static StatsRate plugin_paint("Plugin.Paint"); | 505 static StatsRate plugin_paint("Plugin.Paint"); |
474 StatsScope<StatsRate> scope(plugin_paint); | 506 StatsScope<StatsRate> scope(plugin_paint); |
475 instance()->NPP_HandleEvent(&paint_event); | 507 NPError err = instance()->NPP_HandleEvent(reinterpret_cast<XEvent*>(&event)); |
| 508 DCHECK_EQ(err, NPERR_NO_ERROR); |
| 509 |
| 510 // Now copy the rendered image pixmap back into the drawing buffer. |
| 511 cairo = cairo_create(context); |
| 512 gdk_cairo_set_source_pixmap(cairo, pixmap_, 0, 0); |
| 513 cairo_paint(cairo); |
| 514 cairo_destroy(cairo); |
476 } | 515 } |
477 #endif | |
478 | 516 |
479 void WebPluginDelegateImpl::WindowlessSetWindow(bool force_set_window) { | 517 void WebPluginDelegateImpl::WindowlessSetWindow(bool force_set_window) { |
480 if (!instance()) | 518 if (!instance()) |
481 return; | 519 return; |
482 | 520 |
483 if (window_rect_.IsEmpty()) // wait for geometry to be set. | 521 if (window_rect_.IsEmpty()) // wait for geometry to be set. |
484 return; | 522 return; |
485 | 523 |
486 DCHECK(instance()->windowless()); | 524 DCHECK(instance()->windowless()); |
| 525 // Mozilla docs say that this window param is not used for windowless |
| 526 // plugins; rather, the window is passed during the GraphicsExpose event. |
| 527 DCHECK(window_.window == 0); |
487 | 528 |
488 window_.clipRect.top = clip_rect_.y(); | 529 window_.clipRect.top = clip_rect_.y(); |
489 window_.clipRect.left = clip_rect_.x(); | 530 window_.clipRect.left = clip_rect_.x(); |
490 window_.clipRect.bottom = clip_rect_.y() + clip_rect_.height(); | 531 window_.clipRect.bottom = clip_rect_.y() + clip_rect_.height(); |
491 window_.clipRect.right = clip_rect_.x() + clip_rect_.width(); | 532 window_.clipRect.right = clip_rect_.x() + clip_rect_.width(); |
492 window_.height = window_rect_.height(); | 533 window_.height = window_rect_.height(); |
493 window_.width = window_rect_.width(); | 534 window_.width = window_rect_.width(); |
494 window_.x = window_rect_.x(); | 535 window_.x = window_rect_.x(); |
495 window_.y = window_rect_.y(); | 536 window_.y = window_rect_.y(); |
496 window_.type = NPWindowTypeDrawable; | 537 window_.type = NPWindowTypeDrawable; |
497 | 538 |
| 539 if (!window_.ws_info) |
| 540 window_.ws_info = new NPSetWindowCallbackStruct; |
| 541 NPSetWindowCallbackStruct* extra = |
| 542 static_cast<NPSetWindowCallbackStruct*>(window_.ws_info); |
| 543 extra->display = GDK_DISPLAY(); |
| 544 GdkVisual* visual = gdk_visual_get_system(); |
| 545 extra->visual = GDK_VISUAL_XVISUAL(visual); |
| 546 extra->depth = visual->depth; |
| 547 GdkColormap* colormap = gdk_colormap_new(gdk_visual_get_system(), FALSE); |
| 548 extra->colormap = GDK_COLORMAP_XCOLORMAP(colormap); |
| 549 |
| 550 if (!force_set_window) |
| 551 windowless_needs_set_window_ = false; |
| 552 |
498 NPError err = instance()->NPP_SetWindow(&window_); | 553 NPError err = instance()->NPP_SetWindow(&window_); |
499 DCHECK(err == NPERR_NO_ERROR); | 554 DCHECK(err == NPERR_NO_ERROR); |
500 } | 555 } |
501 | 556 |
502 void WebPluginDelegateImpl::SetFocus() { | 557 void WebPluginDelegateImpl::SetFocus() { |
503 DCHECK(instance()->windowless()); | 558 DCHECK(instance()->windowless()); |
504 | 559 |
505 NOTIMPLEMENTED(); | 560 NOTIMPLEMENTED(); |
506 /* NPEvent focus_event; | 561 /* NPEvent focus_event; |
507 focus_event.event = WM_SETFOCUS; | 562 focus_event.event = WM_SETFOCUS; |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
622 return stream; | 677 return stream; |
623 } | 678 } |
624 | 679 |
625 void WebPluginDelegateImpl::URLRequestRouted(const std::string&url, | 680 void WebPluginDelegateImpl::URLRequestRouted(const std::string&url, |
626 bool notify_needed, | 681 bool notify_needed, |
627 void* notify_data) { | 682 void* notify_data) { |
628 if (notify_needed) { | 683 if (notify_needed) { |
629 instance()->SetURLLoadData(GURL(url.c_str()), notify_data); | 684 instance()->SetURLLoadData(GURL(url.c_str()), notify_data); |
630 } | 685 } |
631 } | 686 } |
OLD | NEW |