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

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

Issue 42056: Basic windowless plugins, try 2. (Closed)
Patch Set: review comments Created 11 years, 9 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
« no previous file with comments | « webkit/glue/plugins/webplugin_delegate_impl.h ('k') | webkit/glue/webplugin_impl.cc » ('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 // 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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « webkit/glue/plugins/webplugin_delegate_impl.h ('k') | webkit/glue/webplugin_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698