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

Side by Side Diff: plugin/win/main_win.cc

Issue 210005: Rewrote full-screen support on Windows. O3D now always creates its own... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/o3d/
Patch Set: '' Created 11 years, 3 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 | « plugin/npapi_host_control/win/np_plugin_proxy.cc ('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 /* 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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « plugin/npapi_host_control/win/np_plugin_proxy.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698