| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2009, Google Inc. | 2 * Copyright 2009, Google Inc. |
| 3 * All rights reserved. | 3 * All rights reserved. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions are | 6 * modification, are permitted provided that the following conditions are |
| 7 * met: | 7 * met: |
| 8 * | 8 * |
| 9 * * Redistributions of source code must retain the above copyright | 9 * * Redistributions of source code must retain the above copyright |
| 10 * notice, this list of conditions and the following disclaimer. | 10 * notice, this list of conditions and the following disclaimer. |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 80 bool v8_disposed = v8::V8::Dispose(); | 80 bool v8_disposed = v8::V8::Dispose(); |
| 81 if (!v8_disposed) | 81 if (!v8_disposed) |
| 82 DLOG(ERROR) << "Failed to release V8 resources."; | 82 DLOG(ERROR) << "Failed to release V8 resources."; |
| 83 return true; | 83 return true; |
| 84 } | 84 } |
| 85 return true; | 85 return true; |
| 86 } | 86 } |
| 87 #endif // O3D_INTERNAL_PLUGIN | 87 #endif // O3D_INTERNAL_PLUGIN |
| 88 | 88 |
| 89 namespace { | 89 namespace { |
| 90 const wchar_t* const kFullScreenWindowClassName = L"O3DFullScreenWindowClass"; | 90 const wchar_t* const kO3DWindowClassName = L"O3DWindowClass"; |
| 91 | 91 |
| 92 // We would normally make this a stack variable in main(), but in a | 92 // We would normally make this a stack variable in main(), but in a |
| 93 // plugin, that's not possible, so we make it a global. When the DLL is loaded | 93 // plugin, that's not possible, so we make it a global. When the DLL is loaded |
| 94 // this it gets constructed and when it is unlooaded it is destructed. Note | 94 // this it gets constructed and when it is unlooaded it is destructed. Note |
| 95 // that this cannot be done in NP_Initialize and NP_Shutdown because those | 95 // that this cannot be done in NP_Initialize and NP_Shutdown because those |
| 96 // calls do not necessarily signify the DLL being loaded and unloaded. If the | 96 // calls do not necessarily signify the DLL being loaded and unloaded. If the |
| 97 // DLL is not unloaded then the values of global variables are preserved. | 97 // DLL is not unloaded then the values of global variables are preserved. |
| 98 base::AtExitManager g_at_exit_manager; | 98 base::AtExitManager g_at_exit_manager; |
| 99 | 99 |
| 100 static int HandleKeyboardEvent(PluginObject *obj, | 100 static int HandleKeyboardEvent(PluginObject *obj, |
| (...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 if (fake_dblclick) { | 345 if (fake_dblclick) { |
| 346 event.set_type(Event::TYPE_DBLCLICK); | 346 event.set_type(Event::TYPE_DBLCLICK); |
| 347 obj->client()->AddEventToQueue(event); | 347 obj->client()->AddEventToQueue(event); |
| 348 } | 348 } |
| 349 if (in_plugin && type == Event::TYPE_MOUSEDOWN && | 349 if (in_plugin && type == Event::TYPE_MOUSEDOWN && |
| 350 obj->HitFullscreenClickRegion(x, y)) { | 350 obj->HitFullscreenClickRegion(x, y)) { |
| 351 obj->RequestFullscreenDisplay(); | 351 obj->RequestFullscreenDisplay(); |
| 352 } | 352 } |
| 353 } | 353 } |
| 354 | 354 |
| 355 // This returns 0 on success, 1 on failure, to match WindowProc. | |
| 356 LRESULT ForwardEvent(PluginObject *obj, | |
| 357 HWND hWnd, | |
| 358 UINT Msg, | |
| 359 WPARAM wParam, | |
| 360 LPARAM lParam, | |
| 361 bool translateCoords) { | |
| 362 DCHECK(obj); | |
| 363 DCHECK(obj->GetPluginHWnd()); | |
| 364 HWND dest_hwnd = obj->GetParentHWnd(); | |
| 365 DCHECK(hWnd); | |
| 366 DCHECK(dest_hwnd); | |
| 367 bool fullscreen = hWnd == obj->GetFullscreenHWnd(); | |
| 368 if (fullscreen) { | |
| 369 dest_hwnd = obj->GetPluginHWnd(); | |
| 370 } else if (obj->IsChrome()) { | |
| 371 // When trying to find the parent window of the Chrome plugin, new Chrome is | |
| 372 // different than old Chrome; it's got an extra wrapper window around the | |
| 373 // plugin that didn't used to be there. The wrapper won't listen to events, | |
| 374 // so if we see it, we have to go one window up the tree from there in order | |
| 375 // to find someone who'll listen to us. The new behavior is seen in nightly | |
| 376 // builds of Chromium as of 2.0.163.0 (9877) [but went in some time before | |
| 377 // that]; the old behavior is still exhibited by Chrome as of 1.0.154.48. | |
| 378 wchar_t chrome_class_name[] = L"WrapperNativeWindowClass"; | |
| 379 wchar_t buffer[sizeof(chrome_class_name) / sizeof(chrome_class_name[0])]; | |
| 380 if (!GetClassName(dest_hwnd, buffer, sizeof(buffer) / sizeof(buffer[0]))) { | |
| 381 return 1; | |
| 382 } | |
| 383 if (!wcscmp(chrome_class_name, buffer)) { | |
| 384 dest_hwnd = ::GetParent(dest_hwnd); | |
| 385 } | |
| 386 } | |
| 387 if (translateCoords) { | |
| 388 int x = GET_X_LPARAM(lParam); | |
| 389 int y = GET_Y_LPARAM(lParam); | |
| 390 | |
| 391 RECT rect0, rect1; | |
| 392 if (!::GetWindowRect(hWnd, &rect0)) { | |
| 393 DCHECK(false); | |
| 394 return 1; | |
| 395 } | |
| 396 if (!::GetWindowRect(dest_hwnd, &rect1)) { | |
| 397 DCHECK(false); | |
| 398 return 1; | |
| 399 } | |
| 400 int width = rect0.right - rect0.left; | |
| 401 int width_1 = rect1.right - rect1.left; | |
| 402 | |
| 403 int x_1; | |
| 404 int y_1; | |
| 405 | |
| 406 if (!fullscreen) { // Translate from plugin to browser offset coords. | |
| 407 x_1 = x - rect1.left + rect0.left; | |
| 408 } else { // Translate from screen to plugin offset coords. | |
| 409 // The plugin and the fullscreen window each fill their respective entire | |
| 410 // window, so there aren't any offsets to add or subtract. | |
| 411 x_1 = x * width_1 / width; | |
| 412 } | |
| 413 int height = rect0.bottom - rect0.top; | |
| 414 int height_1 = rect1.bottom - rect1.top; | |
| 415 if (!fullscreen) { // Translate from plugin to browser offset coords. | |
| 416 y_1 = y - rect1.top + rect0.top; | |
| 417 } else { // Translate from screen to plugin offset coords. | |
| 418 // The plugin and the fullscreen window each fill their respective entire | |
| 419 // window, so there aren't any offsets to add or subtract. | |
| 420 y_1 = y * height_1 / height; | |
| 421 } | |
| 422 | |
| 423 lParam = MAKELPARAM(x_1, y_1); | |
| 424 } | |
| 425 return !::PostMessage(dest_hwnd, Msg, wParam, lParam); | |
| 426 } | |
| 427 | |
| 428 LRESULT HandleDragAndDrop(PluginObject *obj, WPARAM wParam) { | 355 LRESULT HandleDragAndDrop(PluginObject *obj, WPARAM wParam) { |
| 429 HDROP hDrop = reinterpret_cast<HDROP>(wParam); | 356 HDROP hDrop = reinterpret_cast<HDROP>(wParam); |
| 430 UINT num_files = ::DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0); | 357 UINT num_files = ::DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0); |
| 431 if (!num_files) { | 358 if (!num_files) { |
| 432 ::DragFinish(hDrop); | 359 ::DragFinish(hDrop); |
| 433 return 0; | 360 return 0; |
| 434 } | 361 } |
| 435 UINT path_len = ::DragQueryFile(hDrop, 0, NULL, 0); | 362 UINT path_len = ::DragQueryFile(hDrop, 0, NULL, 0); |
| 436 // Let's limit that length, just in case. | 363 // Let's limit that length, just in case. |
| 437 if (!path_len || path_len > 4096) { | 364 if (!path_len || path_len > 4096) { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 500 PAINTSTRUCT paint_struct; | 427 PAINTSTRUCT paint_struct; |
| 501 HDC hdc = ::BeginPaint(hWnd, &paint_struct); | 428 HDC hdc = ::BeginPaint(hWnd, &paint_struct); |
| 502 if (paint_struct.rcPaint.right - paint_struct.rcPaint.left != 0 || | 429 if (paint_struct.rcPaint.right - paint_struct.rcPaint.left != 0 || |
| 503 paint_struct.rcPaint.bottom - paint_struct.rcPaint.top != 0) { | 430 paint_struct.rcPaint.bottom - paint_struct.rcPaint.top != 0) { |
| 504 if (obj->renderer()) { | 431 if (obj->renderer()) { |
| 505 // It appears to be necessary to use GDI to paint something at least | 432 // It appears to be necessary to use GDI to paint something at least |
| 506 // once before D3D rendering will work in Vista with Aero. | 433 // once before D3D rendering will work in Vista with Aero. |
| 507 if (!obj->RecordPaint()) { | 434 if (!obj->RecordPaint()) { |
| 508 ::SetPixelV(hdc, 0, 0, RGB(0, 0, 0)); | 435 ::SetPixelV(hdc, 0, 0, RGB(0, 0, 0)); |
| 509 } | 436 } |
| 510 | |
| 511 obj->renderer()->set_need_to_render(true); | 437 obj->renderer()->set_need_to_render(true); |
| 512 } else { | 438 } else { |
| 513 // If there Client has no Renderer associated with it, paint the draw | 439 // If the Client has no Renderer associated with it, paint the |
| 514 // area gray. | 440 // draw area gray. |
| 515 ::SelectObject(paint_struct.hdc, GetStockObject(DKGRAY_BRUSH)); | 441 ::SelectObject(paint_struct.hdc, GetStockObject(DKGRAY_BRUSH)); |
| 516 ::Rectangle(paint_struct.hdc, | 442 ::Rectangle(paint_struct.hdc, |
| 517 paint_struct.rcPaint.left, | 443 paint_struct.rcPaint.left, |
| 518 paint_struct.rcPaint.top, | 444 paint_struct.rcPaint.top, |
| 519 paint_struct.rcPaint.right, | 445 paint_struct.rcPaint.right, |
| 520 paint_struct.rcPaint.bottom); | 446 paint_struct.rcPaint.bottom); |
| 521 } | 447 } |
| 522 } | 448 } |
| 523 ::EndPaint(hWnd, &paint_struct); | 449 ::EndPaint(hWnd, &paint_struct); |
| 524 break; | 450 return 0; |
| 525 } | 451 } |
| 526 case WM_SETCURSOR: { | 452 case WM_SETCURSOR: { |
| 527 obj->set_cursor(obj->cursor()); | 453 obj->set_cursor(obj->cursor()); |
| 528 return 1; | 454 return 1; |
| 529 } | 455 } |
| 530 case WM_ERASEBKGND: { | 456 case WM_ERASEBKGND: { |
| 531 return 1; // tell windows we don't need the background cleared | 457 // Tell windows we don't need the background cleared. |
| 458 return 1; |
| 532 } | 459 } |
| 533 case WM_SIZE: { | |
| 534 // Resize event called | |
| 535 if (reentrance_count.get() > 1) { | |
| 536 break; // Ignore this message; we're reentrant. | |
| 537 } | |
| 538 | 460 |
| 539 // get new dimensions of window | |
| 540 int window_width = LOWORD(lParam); | |
| 541 int window_height = HIWORD(lParam); | |
| 542 | |
| 543 // Tell the plugin that it has been resized | |
| 544 obj->Resize(window_width, window_height); | |
| 545 break; | |
| 546 } | |
| 547 case WM_TIMER: { | 461 case WM_TIMER: { |
| 548 if (reentrance_count.get() > 1) { | 462 if (reentrance_count.get() > 1) { |
| 549 break; // Ignore this message; we're reentrant. | 463 break; // Ignore this message; we're reentrant. |
| 550 } | 464 } |
| 551 | 465 |
| 552 #if !defined(O3D_INTERNAL_PLUGIN) | 466 #if !defined(O3D_INTERNAL_PLUGIN) |
| 553 // TODO: Only logging for windows until we figure out the proper | 467 // TODO: Only logging for windows until we figure out the proper |
| 554 // mac way | 468 // mac way |
| 555 if (g_logger) g_logger->UpdateLogging(); | 469 if (g_logger) g_logger->UpdateLogging(); |
| 556 #endif | 470 #endif |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 612 break; | 526 break; |
| 613 | 527 |
| 614 case WM_CHAR: | 528 case WM_CHAR: |
| 615 case WM_SYSCHAR: | 529 case WM_SYSCHAR: |
| 616 case WM_KEYDOWN: | 530 case WM_KEYDOWN: |
| 617 case WM_KEYUP: | 531 case WM_KEYUP: |
| 618 case WM_SYSKEYDOWN: | 532 case WM_SYSKEYDOWN: |
| 619 case WM_SYSKEYUP: | 533 case WM_SYSKEYUP: |
| 620 return HandleKeyboardEvent(obj, hWnd, Msg, wParam, lParam); | 534 return HandleKeyboardEvent(obj, hWnd, Msg, wParam, lParam); |
| 621 | 535 |
| 622 #if(_WIN32_WINNT >= 0x0500) | |
| 623 case WM_APPCOMMAND: | |
| 624 #endif /* _WIN32_WINNT >= 0x0500 */ | |
| 625 return ForwardEvent(obj, hWnd, Msg, wParam, lParam, false); | |
| 626 | |
| 627 case WM_DROPFILES: | 536 case WM_DROPFILES: |
| 628 return HandleDragAndDrop(obj, wParam); | 537 return HandleDragAndDrop(obj, wParam); |
| 629 | 538 |
| 539 case WM_ACTIVATE: |
| 540 // We don't receive WM_KILLFOCUS when Alt-Tabbing away from a |
| 541 // full-screen window. We do however get WM_ACTIVATE. |
| 542 if (LOWORD(wParam) == WA_INACTIVE) { |
| 543 if (obj->fullscreen()) { |
| 544 obj->CancelFullscreenDisplay(); |
| 545 } |
| 546 } |
| 547 return 0; |
| 548 |
| 630 case WM_KILLFOCUS: | 549 case WM_KILLFOCUS: |
| 631 // If we lose focus [which also happens on alt+f4 killing the fullscreen | 550 // If we lose focus [which also happens on alt+f4 killing the fullscreen |
| 632 // window] fall back to plugin mode to avoid lost-device awkwardness. | 551 // window] fall back to plugin mode to avoid lost-device awkwardness. |
| 633 // TODO: We'll have problems with this when dealing with e.g. | 552 // TODO: We'll have problems with this when dealing with e.g. |
| 634 // Japanese text input IME windows. | 553 // Japanese text input IME windows. |
| 635 if (hWnd == obj->GetFullscreenHWnd()) { | 554 if (obj->fullscreen()) { |
| 555 // TODO(kbr): consider doing this somehow more asynchronously; |
| 556 // not supposed to cause window activation in the WM_KILLFOCUS |
| 557 // handler |
| 636 obj->CancelFullscreenDisplay(); | 558 obj->CancelFullscreenDisplay(); |
| 637 return 0; | 559 return 0; |
| 638 } | 560 } |
| 639 // FALL THROUGH | 561 // FALL THROUGH |
| 640 case WM_SETFOCUS: | 562 case WM_SETFOCUS: |
| 641 default: | 563 default: |
| 642 // Decrement reentrance_count here. It's OK if this call | 564 // Decrement reentrance_count here. It's OK if this call |
| 643 // boomerangs back to us, given that we're not in the middle of doing | 565 // boomerangs back to us, given that we're not in the middle of doing |
| 644 // anything caused by this message. Since we decrement reentrance_count | 566 // anything caused by this message. Since we decrement reentrance_count |
| 645 // manually, its destructor will know not to. | 567 // manually, its destructor will know not to. |
| 646 reentrance_count.decrement(); | 568 reentrance_count.decrement(); |
| 647 | 569 |
| 648 if (hWnd == obj->GetFullscreenHWnd()) { | 570 return ::CallWindowProc(::DefWindowProc, |
| 649 return ::CallWindowProc(::DefWindowProc, | 571 hWnd, |
| 650 hWnd, | 572 Msg, |
| 651 Msg, | 573 wParam, |
| 652 wParam, | 574 lParam); |
| 653 lParam); | |
| 654 } else { | |
| 655 return ::CallWindowProc(obj->GetDefaultPluginWindowProc(), | |
| 656 hWnd, | |
| 657 Msg, | |
| 658 wParam, | |
| 659 lParam); | |
| 660 } | |
| 661 } | 575 } |
| 662 return 0; | 576 return 0; |
| 663 } | 577 } |
| 664 | 578 |
| 665 bool RegisterFullScreenWindowClass() { | 579 static const wchar_t* kOrigWndProcName = L"o3dOrigWndProc"; |
| 666 WNDCLASSEX window_class = { sizeof(WNDCLASSEX) }; | 580 |
| 581 LRESULT CALLBACK PluginWindowInterposer(HWND hWnd, |
| 582 UINT Msg, |
| 583 WPARAM wParam, |
| 584 LPARAM lParam) { |
| 585 switch (Msg) { |
| 586 case WM_PAINT: { |
| 587 // For nicer startup appearance, allow the browser to paint the |
| 588 // plugin window until we start to draw 3D content. Forbid the |
| 589 // browser from painting once we have started to draw to prevent |
| 590 // a flash in Firefox upon our receiving focus the first time. |
| 591 PluginObject *obj = PluginObject::GetPluginProperty(hWnd); |
| 592 if (obj != NULL && obj->renderer() != NULL) { |
| 593 if (obj->renderer()->presented_once()) { |
| 594 // Tell Windows we painted the window region. |
| 595 ::ValidateRect(hWnd, NULL); |
| 596 return 0; |
| 597 } |
| 598 } |
| 599 // Break out to call the original window procedure to paint the |
| 600 // window. |
| 601 break; |
| 602 } |
| 603 |
| 604 default: |
| 605 break; |
| 606 } |
| 607 |
| 608 WNDPROC proc = static_cast<WNDPROC>(GetProp(hWnd, kOrigWndProcName)); |
| 609 DCHECK(proc != NULL); |
| 610 return CallWindowProc(proc, hWnd, Msg, wParam, lParam); |
| 611 } |
| 612 |
| 613 bool RegisterO3DWindowClass() { |
| 614 WNDCLASSEX window_class; |
| 615 ZeroMemory(&window_class, sizeof(window_class)); |
| 616 window_class.cbSize = sizeof(window_class); |
| 667 window_class.hInstance = g_module_instance; | 617 window_class.hInstance = g_module_instance; |
| 668 window_class.lpfnWndProc = WindowProc; | 618 window_class.lpfnWndProc = WindowProc; |
| 669 window_class.lpszClassName = kFullScreenWindowClassName; | 619 window_class.lpszClassName = kO3DWindowClassName; |
| 670 window_class.style = CS_DBLCLKS; | 620 // We use CS_OWNDC in case we are rendering OpenGL into this window. |
| 621 window_class.style = CS_DBLCLKS | CS_OWNDC; |
| 671 return RegisterClassEx(&window_class) != 0; | 622 return RegisterClassEx(&window_class) != 0; |
| 672 } | 623 } |
| 673 | 624 |
| 674 void UnregisterFullScreenWindowClass() { | 625 void UnregisterO3DWindowClass() { |
| 675 UnregisterClass(kFullScreenWindowClassName, g_module_instance); | 626 UnregisterClass(kO3DWindowClassName, g_module_instance); |
| 676 } | 627 } |
| 677 | 628 |
| 678 NPError InitializePlugin() { | 629 NPError InitializePlugin() { |
| 679 #if !defined(O3D_INTERNAL_PLUGIN) | 630 #if !defined(O3D_INTERNAL_PLUGIN) |
| 680 if (!o3d::SetupOutOfMemoryHandler()) | 631 if (!o3d::SetupOutOfMemoryHandler()) |
| 681 return NPERR_MODULE_LOAD_FAILED_ERROR; | 632 return NPERR_MODULE_LOAD_FAILED_ERROR; |
| 682 | 633 |
| 683 // Setup crash handler | 634 // Setup crash handler |
| 684 if (!g_exception_manager) { | 635 if (!g_exception_manager) { |
| 685 g_exception_manager = new ExceptionManager(false); | 636 g_exception_manager = new ExceptionManager(false); |
| 686 g_exception_manager->StartMonitoring(); | 637 g_exception_manager->StartMonitoring(); |
| 687 } | 638 } |
| 688 | 639 |
| 689 // Turn on the logging. | 640 // Turn on the logging. |
| 690 CommandLine::Init(0, NULL); | 641 CommandLine::Init(0, NULL); |
| 691 InitLogging(L"debug.log", | 642 InitLogging(L"debug.log", |
| 692 logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG, | 643 logging::LOG_TO_BOTH_FILE_AND_SYSTEM_DEBUG_LOG, |
| 693 logging::DONT_LOCK_LOG_FILE, | 644 logging::DONT_LOCK_LOG_FILE, |
| 694 logging::APPEND_TO_OLD_LOG_FILE); | 645 logging::APPEND_TO_OLD_LOG_FILE); |
| 695 #endif // O3D_INTERNAL_PLUGIN | 646 #endif // O3D_INTERNAL_PLUGIN |
| 696 | 647 |
| 697 DLOG(INFO) << "NP_Initialize"; | 648 DLOG(INFO) << "NP_Initialize"; |
| 698 | 649 |
| 699 if (!RegisterFullScreenWindowClass()) | 650 if (!RegisterO3DWindowClass()) |
| 700 return NPERR_MODULE_LOAD_FAILED_ERROR; | 651 return NPERR_MODULE_LOAD_FAILED_ERROR; |
| 701 | 652 |
| 702 return NPERR_NO_ERROR; | 653 return NPERR_NO_ERROR; |
| 703 } | 654 } |
| 704 | 655 |
| 705 void CleanupFullscreenWindow(PluginObject *obj) { | |
| 706 DCHECK(obj->GetFullscreenHWnd()); | |
| 707 obj->StorePluginProperty(obj->GetPluginHWnd(), obj); | |
| 708 ::DestroyWindow(obj->GetFullscreenHWnd()); | |
| 709 obj->SetFullscreenHWnd(NULL); | |
| 710 } | |
| 711 | |
| 712 void CleanupAllWindows(PluginObject *obj) { | 656 void CleanupAllWindows(PluginObject *obj) { |
| 713 DCHECK(obj->GetHWnd()); | 657 DCHECK(obj->GetContentHWnd()); |
| 714 DCHECK(obj->GetPluginHWnd()); | 658 DCHECK(obj->GetPluginHWnd()); |
| 715 ::KillTimer(obj->GetHWnd(), 0); | 659 ::KillTimer(obj->GetContentHWnd(), 0); |
| 716 if (obj->GetFullscreenHWnd()) { | 660 PluginObject::ClearPluginProperty(obj->GetContentHWnd()); |
| 717 CleanupFullscreenWindow(obj); | 661 PluginObject::ClearPluginProperty(obj->GetPluginHWnd()); |
| 718 } | 662 ::DestroyWindow(obj->GetContentHWnd()); |
| 719 PluginObject::ClearPluginProperty(obj->GetHWnd()); | 663 obj->SetContentHWnd(NULL); |
| 720 ::SetWindowLongPtr(obj->GetPluginHWnd(), | |
| 721 GWL_WNDPROC, | |
| 722 reinterpret_cast<LONG_PTR>( | |
| 723 obj->GetDefaultPluginWindowProc())); | |
| 724 obj->SetPluginHWnd(NULL); | 664 obj->SetPluginHWnd(NULL); |
| 725 obj->SetHWnd(NULL); | 665 obj->SetHWnd(NULL); |
| 726 } | 666 } |
| 727 | 667 |
| 728 HWND CreateFullscreenWindow(PluginObject *obj, | 668 // Re-parents the content_hwnd into the containing_hwnd, resizing the |
| 729 int mode_id) { | 669 // content_hwnd to the given width and height in the process. |
| 730 o3d::DisplayMode mode; | 670 void ReplaceContentWindow(HWND content_hwnd, |
| 731 if (!obj->renderer()->GetDisplayMode(mode_id, &mode)) { | 671 HWND containing_hwnd, |
| 732 return NULL; | 672 int width, int height) { |
| 733 } | 673 ::ShowWindow(content_hwnd, SW_HIDE); |
| 734 CHECK(mode.width() > 0 && mode.height() > 0); | 674 LONG_PTR style = ::GetWindowLongPtr(content_hwnd, GWL_STYLE); |
| 675 style |= WS_CHILD; |
| 676 ::SetWindowLongPtr(content_hwnd, GWL_STYLE, style); |
| 677 ::SetParent(content_hwnd, containing_hwnd); |
| 678 BOOL res = ::SetWindowPos(content_hwnd, containing_hwnd, |
| 679 0, 0, width, height, |
| 680 SWP_NOZORDER | SWP_ASYNCWINDOWPOS); |
| 681 DCHECK(res); |
| 682 ::ShowWindow(content_hwnd, SW_SHOW); |
| 683 } |
| 735 | 684 |
| 736 HWND hWnd = CreateWindowEx(NULL, | |
| 737 kFullScreenWindowClassName, | |
| 738 L"O3D Test Fullscreen Window", | |
| 739 WS_POPUP, | |
| 740 0, 0, | |
| 741 mode.width(), | |
| 742 mode.height(), | |
| 743 NULL, | |
| 744 NULL, | |
| 745 g_module_instance, | |
| 746 NULL); | |
| 747 | |
| 748 ShowWindow(hWnd, SW_SHOW); | |
| 749 return hWnd; | |
| 750 } | |
| 751 } // namespace anonymous | 685 } // namespace anonymous |
| 752 | 686 |
| 753 #if defined(O3D_INTERNAL_PLUGIN) | 687 #if defined(O3D_INTERNAL_PLUGIN) |
| 754 namespace o3d { | 688 namespace o3d { |
| 755 #else | 689 #else |
| 756 extern "C" { | 690 extern "C" { |
| 757 #endif | 691 #endif |
| 758 | 692 |
| 759 NPError OSCALL NP_Initialize(NPNetscapeFuncs *browserFuncs) { | 693 NPError OSCALL NP_Initialize(NPNetscapeFuncs *browserFuncs) { |
| 760 HANDLE_CRASHES; | 694 HANDLE_CRASHES; |
| 761 NPError retval = InitializeNPNApi(browserFuncs); | 695 NPError retval = InitializeNPNApi(browserFuncs); |
| 762 if (retval != NPERR_NO_ERROR) return retval; | 696 if (retval != NPERR_NO_ERROR) return retval; |
| 763 return InitializePlugin(); | 697 return InitializePlugin(); |
| 764 } | 698 } |
| 765 | 699 |
| 766 NPError OSCALL NP_Shutdown(void) { | 700 NPError OSCALL NP_Shutdown(void) { |
| 767 HANDLE_CRASHES; | 701 HANDLE_CRASHES; |
| 768 DLOG(INFO) << "NP_Shutdown"; | 702 DLOG(INFO) << "NP_Shutdown"; |
| 769 | 703 |
| 770 UnregisterFullScreenWindowClass(); | 704 UnregisterO3DWindowClass(); |
| 771 | 705 |
| 772 #if !defined(O3D_INTERNAL_PLUGIN) | 706 #if !defined(O3D_INTERNAL_PLUGIN) |
| 773 | 707 |
| 774 if (g_logger) { | 708 if (g_logger) { |
| 775 // Do a last sweep to aggregate metrics before we shut down | 709 // Do a last sweep to aggregate metrics before we shut down |
| 776 g_logger->ProcessMetrics(true, false); | 710 g_logger->ProcessMetrics(true, false); |
| 777 delete g_logger; | 711 delete g_logger; |
| 778 g_logger = NULL; | 712 g_logger = NULL; |
| 779 g_logging_initialized = false; | 713 g_logging_initialized = false; |
| 780 stats_report::g_global_metrics.Uninitialize(); | 714 stats_report::g_global_metrics.Uninitialize(); |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 863 PluginObject *obj = static_cast<PluginObject*>(instance->pdata); | 797 PluginObject *obj = static_cast<PluginObject*>(instance->pdata); |
| 864 | 798 |
| 865 HWND hWnd = static_cast<HWND>(window->window); | 799 HWND hWnd = static_cast<HWND>(window->window); |
| 866 if (!hWnd) { | 800 if (!hWnd) { |
| 867 // Chrome calls us this way before NPP_Destroy. | 801 // Chrome calls us this way before NPP_Destroy. |
| 868 if (obj->GetHWnd()) { | 802 if (obj->GetHWnd()) { |
| 869 CleanupAllWindows(obj); | 803 CleanupAllWindows(obj); |
| 870 } | 804 } |
| 871 return NPERR_NO_ERROR; | 805 return NPERR_NO_ERROR; |
| 872 } | 806 } |
| 873 if (obj->GetHWnd() == hWnd) { | 807 |
| 808 if (obj->GetPluginHWnd() == hWnd) { |
| 809 // May need to resize the content window. |
| 810 DCHECK(obj->GetContentHWnd()); |
| 811 // Avoid spurious resize requests. |
| 812 if (window->width != obj->width() || |
| 813 window->height != obj->height()) { |
| 814 if (!obj->fullscreen()) { |
| 815 ::SetWindowPos(obj->GetContentHWnd(), obj->GetPluginHWnd(), 0, 0, |
| 816 window->width, window->height, |
| 817 SWP_NOZORDER | SWP_NOREPOSITION); |
| 818 } |
| 819 // Even if we are in full-screen mode, store off the new width |
| 820 // and height to restore to them later. |
| 821 obj->Resize(window->width, window->height); |
| 822 // Only propagate this resize event to the client if it isn't in |
| 823 // full-screen mode. |
| 824 if (!obj->fullscreen()) { |
| 825 obj->client()->SendResizeEvent(obj->width(), obj->height(), false); |
| 826 } |
| 827 } |
| 874 return NPERR_NO_ERROR; | 828 return NPERR_NO_ERROR; |
| 875 } | 829 } |
| 876 if (obj->fullscreen()) { | |
| 877 // We can get here if the user alt+tabs away from the fullscreen plugin | |
| 878 // window or JavaScript resizes the plugin window. | |
| 879 DCHECK(obj->GetPluginHWnd()); | |
| 880 DCHECK(obj->GetFullscreenHWnd()); | |
| 881 DCHECK(obj->GetPluginHWnd() == hWnd); | |
| 882 | 830 |
| 883 // Exit full screen if the plugin window is being modified. | |
| 884 obj->CancelFullscreenDisplay(); | |
| 885 | |
| 886 return NPERR_NO_ERROR; | |
| 887 } | |
| 888 DCHECK(!obj->GetPluginHWnd()); | 831 DCHECK(!obj->GetPluginHWnd()); |
| 889 obj->SetPluginHWnd(hWnd); | 832 obj->SetPluginHWnd(hWnd); |
| 890 obj->SetParentHWnd(::GetParent(hWnd)); | 833 |
| 891 PluginObject::StorePluginProperty(hWnd, obj); | 834 // Subclass the plugin window's window procedure to avoid processing |
| 892 obj->SetDefaultPluginWindowProc( | 835 // WM_PAINT. This seems to only be necessary for Firefox, which |
| 893 reinterpret_cast<WNDPROC>( | 836 // overdraws our plugin the first time it gains focus. |
| 894 ::SetWindowLongPtr(hWnd, | 837 SetProp(hWnd, kOrigWndProcName, |
| 895 GWL_WNDPROC, | 838 reinterpret_cast<HANDLE>(GetWindowLongPtr(hWnd, GWLP_WNDPROC))); |
| 896 reinterpret_cast<LONG_PTR>(WindowProc)))); | 839 PluginObject::StorePluginPropertyUnsafe(hWnd, obj); |
| 840 SetWindowLongPtr(hWnd, GWLP_WNDPROC, |
| 841 reinterpret_cast<LONG_PTR>(PluginWindowInterposer)); |
| 842 |
| 843 // Create the content window, into which O3D always renders, rather |
| 844 // than alternating rendering between the browser's window and a |
| 845 // separate full-screen window. The O3D window is removed from the |
| 846 // browser's hierarchy and made top-level in order to go to |
| 847 // full-screen mode via Direct3D. This solves fundamental focus |
| 848 // fighting problems seen on Windows Vista. |
| 849 HWND content_window = |
| 850 CreateWindow(kO3DWindowClassName, |
| 851 L"O3D Window", |
| 852 WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, |
| 853 0, 0, |
| 854 window->width, window->height, |
| 855 hWnd, |
| 856 NULL, |
| 857 g_module_instance, |
| 858 NULL); |
| 859 obj->Resize(window->width, window->height); |
| 860 obj->SetContentHWnd(content_window); |
| 861 PluginObject::StorePluginProperty(content_window, obj); |
| 862 ::ShowWindow(content_window, SW_SHOW); |
| 897 | 863 |
| 898 // create and assign the graphics context | 864 // create and assign the graphics context |
| 899 DisplayWindowWindows default_display; | 865 DisplayWindowWindows default_display; |
| 900 default_display.set_hwnd(obj->GetHWnd()); | 866 default_display.set_hwnd(obj->GetHWnd()); |
| 901 | 867 |
| 902 obj->CreateRenderer(default_display); | 868 obj->CreateRenderer(default_display); |
| 903 obj->client()->Init(); | 869 obj->client()->Init(); |
| 904 | 870 |
| 905 // we set the timer to 10ms or 100fps. At the time of this comment | 871 // we set the timer to 10ms or 100fps. At the time of this comment |
| 906 // the renderer does a vsync the max fps it will run will be the refresh | 872 // the renderer does a vsync the max fps it will run will be the refresh |
| (...skipping 23 matching lines...) Expand all Loading... |
| 930 namespace _o3d { | 896 namespace _o3d { |
| 931 bool PluginObject::GetDisplayMode(int mode_id, o3d::DisplayMode *mode) { | 897 bool PluginObject::GetDisplayMode(int mode_id, o3d::DisplayMode *mode) { |
| 932 return renderer()->GetDisplayMode(mode_id, mode); | 898 return renderer()->GetDisplayMode(mode_id, mode); |
| 933 } | 899 } |
| 934 | 900 |
| 935 // TODO: Where should this really live? It's platform-specific, but in | 901 // TODO: Where should this really live? It's platform-specific, but in |
| 936 // PluginObject, which mainly lives in cross/o3d_glue.h+cc. | 902 // PluginObject, which mainly lives in cross/o3d_glue.h+cc. |
| 937 bool PluginObject::RequestFullscreenDisplay() { | 903 bool PluginObject::RequestFullscreenDisplay() { |
| 938 bool success = false; | 904 bool success = false; |
| 939 DCHECK(GetPluginHWnd()); | 905 DCHECK(GetPluginHWnd()); |
| 906 DCHECK(GetContentHWnd()); |
| 940 if (!fullscreen_ && renderer_ && fullscreen_region_valid_) { | 907 if (!fullscreen_ && renderer_ && fullscreen_region_valid_) { |
| 941 DCHECK(renderer_->fullscreen() == fullscreen_); | 908 DCHECK(renderer_->fullscreen() == fullscreen_); |
| 942 DCHECK(!GetFullscreenHWnd()); | 909 // The focus window we pass into IDirect3D9::CreateDevice must not |
| 943 HWND drawing_hwnd = | 910 // fight with the full-screen window for the focus. The best way |
| 944 CreateFullscreenWindow(this, fullscreen_region_mode_id_); | 911 // to achieve this is to re-use the content window for full-screen |
| 945 if (drawing_hwnd) { | 912 // mode. |
| 946 ::KillTimer(GetHWnd(), 0); | 913 ::ShowWindow(GetContentHWnd(), SW_HIDE); |
| 947 SetFullscreenHWnd(drawing_hwnd); | 914 ::SetParent(GetContentHWnd(), NULL); |
| 948 StorePluginPropertyUnsafe(drawing_hwnd, this); | 915 // Remove WS_CHILD from the window style |
| 949 | 916 LONG_PTR style = ::GetWindowLongPtr(GetContentHWnd(), GWL_STYLE); |
| 917 style &= ~WS_CHILD; |
| 918 ::SetWindowLongPtr(GetContentHWnd(), GWL_STYLE, style); |
| 919 ::ShowWindow(GetContentHWnd(), SW_SHOW); |
| 920 // We need to resize the full-screen window to the desired size of |
| 921 // the display mode early, before calling |
| 922 // Renderer::GoFullscreen(). |
| 923 o3d::DisplayMode mode; |
| 924 if (GetDisplayMode(fullscreen_region_mode_id_, &mode)) { |
| 925 ::SetWindowPos(GetContentHWnd(), HWND_TOP, 0, 0, |
| 926 mode.width(), mode.height(), |
| 927 SWP_NOZORDER | SWP_NOREPOSITION | SWP_ASYNCWINDOWPOS); |
| 950 DisplayWindowWindows display; | 928 DisplayWindowWindows display; |
| 951 display.set_hwnd(GetHWnd()); | 929 display.set_hwnd(GetContentHWnd()); |
| 952 if (renderer_->SetFullscreen(true, display, | 930 if (renderer_->GoFullscreen(display, |
| 953 fullscreen_region_mode_id_)) { | 931 fullscreen_region_mode_id_)) { |
| 954 fullscreen_ = true; | 932 fullscreen_ = true; |
| 955 client()->SendResizeEvent(renderer_->width(), renderer_->height(), | 933 client()->SendResizeEvent(renderer_->width(), renderer_->height(), |
| 956 true); | 934 true); |
| 957 success = true; | 935 success = true; |
| 958 } else { | |
| 959 CleanupFullscreenWindow(this); | |
| 960 } | 936 } |
| 961 prev_width_ = renderer_->width(); | 937 } |
| 962 prev_height_ = renderer_->height(); | 938 |
| 963 ::SetTimer(GetHWnd(), 0, 10, NULL); | 939 if (!success) { |
| 964 } else { | 940 ReplaceContentWindow(GetContentHWnd(), GetPluginHWnd(), |
| 965 LOG(ERROR) << "Failed to create fullscreen window."; | 941 prev_width_, prev_height_); |
| 942 LOG(ERROR) << "Failed to switch to fullscreen mode."; |
| 966 } | 943 } |
| 967 } | 944 } |
| 968 return success; | 945 return success; |
| 969 } | 946 } |
| 970 | 947 |
| 971 void PluginObject::CancelFullscreenDisplay() { | 948 void PluginObject::CancelFullscreenDisplay() { |
| 972 DCHECK(GetPluginHWnd()); | 949 DCHECK(GetPluginHWnd()); |
| 973 if (fullscreen_) { | 950 if (fullscreen_) { |
| 974 DCHECK(renderer()); | 951 DCHECK(renderer()); |
| 975 DCHECK(renderer()->fullscreen()); | 952 DCHECK(renderer()->fullscreen()); |
| 976 ::KillTimer(GetHWnd(), 0); | 953 fullscreen_ = false; |
| 977 DisplayWindowWindows display; | 954 DisplayWindowWindows display; |
| 978 display.set_hwnd(GetPluginHWnd()); | 955 display.set_hwnd(GetContentHWnd()); |
| 979 if (!renderer_->SetFullscreen(false, display, 0)) { | 956 if (!renderer_->CancelFullscreen(display, prev_width_, prev_height_)) { |
| 980 LOG(FATAL) << "Failed to get the renderer out of fullscreen mode!"; | 957 LOG(FATAL) << "Failed to get the renderer out of fullscreen mode!"; |
| 981 } | 958 } |
| 982 CleanupFullscreenWindow(this); | 959 ReplaceContentWindow(GetContentHWnd(), GetPluginHWnd(), |
| 983 prev_width_ = renderer_->width(); | 960 prev_width_, prev_height_); |
| 984 prev_height_ = renderer_->height(); | |
| 985 client()->SendResizeEvent(prev_width_, prev_height_, false); | 961 client()->SendResizeEvent(prev_width_, prev_height_, false); |
| 986 ::SetTimer(GetHWnd(), 0, 10, NULL); | |
| 987 fullscreen_ = false; | |
| 988 } | 962 } |
| 989 } | 963 } |
| 990 } // namespace _o3d | 964 } // namespace _o3d |
| 991 } // namespace glue | 965 } // namespace glue |
| OLD | NEW |