| 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 |