diff options
Diffstat (limited to 'o3d/plugin')
-rw-r--r-- | o3d/plugin/cross/o3d_glue.cc | 6 | ||||
-rw-r--r-- | o3d/plugin/cross/o3d_glue.h | 32 | ||||
-rw-r--r-- | o3d/plugin/npapi_host_control/win/host_control.cc | 19 | ||||
-rw-r--r-- | o3d/plugin/npapi_host_control/win/host_control.h | 3 | ||||
-rw-r--r-- | o3d/plugin/npapi_host_control/win/np_plugin_proxy.cc | 13 | ||||
-rw-r--r-- | o3d/plugin/npapi_host_control/win/np_plugin_proxy.h | 5 | ||||
-rw-r--r-- | o3d/plugin/win/main_win.cc | 382 |
7 files changed, 229 insertions, 231 deletions
diff --git a/o3d/plugin/cross/o3d_glue.cc b/o3d/plugin/cross/o3d_glue.cc index 9053255..5911285 100644 --- a/o3d/plugin/cross/o3d_glue.cc +++ b/o3d/plugin/cross/o3d_glue.cc @@ -110,10 +110,8 @@ PluginObject::PluginObject(NPP npp) pending_ticks_(0), #ifdef OS_WIN hWnd_(NULL), - fullscreen_hWnd_(NULL), - parent_hWnd_(NULL), plugin_hWnd_(NULL), - default_plugin_window_proc_(NULL), + content_hWnd_(NULL), got_dblclick_(false), painted_once_(false), #endif @@ -743,11 +741,11 @@ void PluginObject::StorePluginProperty(HWND hWnd, PluginObject *obj) { if (obj->GetHWnd()) { // Clear out the record from the old window first. ClearPluginProperty(obj->GetHWnd()); } + obj->SetHWnd(hWnd); StorePluginPropertyUnsafe(hWnd, obj); } void PluginObject::StorePluginPropertyUnsafe(HWND hWnd, PluginObject *obj) { - obj->SetHWnd(hWnd); if (hWnd) { SetProp(hWnd, kWindowPropertyName, static_cast<HANDLE>(obj)); ::DragAcceptFiles(hWnd, true); diff --git a/o3d/plugin/cross/o3d_glue.h b/o3d/plugin/cross/o3d_glue.h index 6143db2..12fb572 100644 --- a/o3d/plugin/cross/o3d_glue.h +++ b/o3d/plugin/cross/o3d_glue.h @@ -158,36 +158,24 @@ class PluginObject: public NPObject { public: #ifdef OS_WIN - void SetDefaultPluginWindowProc(WNDPROC proc) { - default_plugin_window_proc_ = proc; - } - WNDPROC GetDefaultPluginWindowProc() { - return default_plugin_window_proc_; - } void SetHWnd(HWND hWnd) { hWnd_ = hWnd; } HWND GetHWnd() { return hWnd_; } - void SetFullscreenHWnd(HWND hWnd) { - fullscreen_hWnd_ = hWnd; - } - HWND GetFullscreenHWnd() { - return fullscreen_hWnd_; - } - void SetParentHWnd(HWND hWnd) { - parent_hWnd_ = hWnd; - } - HWND GetParentHWnd() { - return parent_hWnd_; - } void SetPluginHWnd(HWND hWnd) { plugin_hWnd_ = hWnd; } HWND GetPluginHWnd() { return plugin_hWnd_; } + void SetContentHWnd(HWND hWnd) { + content_hWnd_ = hWnd; + } + HWND GetContentHWnd() { + return content_hWnd_; + } bool RecordPaint() { bool painted = painted_once_; painted_once_ = true; @@ -431,13 +419,11 @@ class PluginObject: public NPObject { int fullscreen_region_height_; int fullscreen_region_mode_id_; #ifdef OS_WIN - HWND hWnd_; // The window we are currenlty drawing to (use this) - HWND fullscreen_hWnd_; // The fullscreen window if we are fullscreen - HWND parent_hWnd_; - HWND plugin_hWnd_; // The window we were given inside the browser. + HWND hWnd_; // The window we are currently drawing to (use this). + HWND plugin_hWnd_; // The window we were given inside the browser. + HWND content_hWnd_; // The window containing the D3D or OpenGL content. HCURSOR cursors_[o3d::Cursor::NUM_CURSORS]; // loaded windows cursors. HCURSOR hCursor_; - WNDPROC default_plugin_window_proc_; bool painted_once_; #endif // OS_WIN }; diff --git a/o3d/plugin/npapi_host_control/win/host_control.cc b/o3d/plugin/npapi_host_control/win/host_control.cc index 957f465..47a4040 100644 --- a/o3d/plugin/npapi_host_control/win/host_control.cc +++ b/o3d/plugin/npapi_host_control/win/host_control.cc @@ -553,6 +553,25 @@ STDMETHODIMP CHostControl::Load(IPropertyBag* property_bag, return IPersistPropertyBagImpl<CHostControl>::Load(property_bag, error_log); } +STDMETHODIMP CHostControl::SetObjectRects(LPCRECT lprcPosRect, + LPCRECT lprcClipRect) { + if (plugin_proxy_.get()) { + NPWindow window = {0}; + window.window = m_hWnd; + window.type = NPWindowTypeWindow; + window.x = lprcPosRect->left; + window.y = lprcPosRect->top; + window.width = lprcPosRect->right - lprcPosRect->left; + window.height = lprcPosRect->bottom - lprcPosRect->top; + if (!plugin_proxy_->SetWindow(window)) { + return E_FAIL; + } + } + + return IOleInPlaceObjectWindowlessImpl::SetObjectRects(lprcPosRect, + lprcClipRect); +} + HRESULT CHostControl::GetStringProperty(NPPVariable np_property_variable, BSTR* string) { HRESULT hr; diff --git a/o3d/plugin/npapi_host_control/win/host_control.h b/o3d/plugin/npapi_host_control/win/host_control.h index ae37487..9a4fc68 100644 --- a/o3d/plugin/npapi_host_control/win/host_control.h +++ b/o3d/plugin/npapi_host_control/win/host_control.h @@ -170,6 +170,9 @@ END_PROP_MAP() // Method overridden from IPersistPropertyBagImpl. STDMETHOD(Load(IPropertyBag *pPropBag, IErrorLog *pErrorLog)); + STDMETHOD(SetObjectRects(LPCRECT lprcPosRect, + LPCRECT lprcClipRect)); + // Returns the properties associated with the NPPVpluginNameString, and // NPPVpluginDescriptionString identifiers of the loaded plug-in. These // properties can be used for plug-in introspection and version-dependent diff --git a/o3d/plugin/npapi_host_control/win/np_plugin_proxy.cc b/o3d/plugin/npapi_host_control/win/np_plugin_proxy.cc index 04cd24a..7de9d67 100644 --- a/o3d/plugin/npapi_host_control/win/np_plugin_proxy.cc +++ b/o3d/plugin/npapi_host_control/win/np_plugin_proxy.cc @@ -286,6 +286,19 @@ bool NPPluginProxy::Init(NPBrowserProxy* browser_proxy, return true; } +bool NPPluginProxy::SetWindow(const NPWindow& window) { + if (plugin_funcs_.setwindow != NULL && + NPERR_NO_ERROR != plugin_funcs_.setwindow( + GetNPP(), + const_cast<NPWindow*>(&window))) { + plugin_funcs_.destroy(GetNPP(), NULL); + NP_Shutdown_(); + ATLASSERT(false && "Unknown failure re-setting plugin window."); + return false; + } + return true; +} + void NPPluginProxy::TearDown() { // Block until all stream operations requested by this plug-in have // completed. diff --git a/o3d/plugin/npapi_host_control/win/np_plugin_proxy.h b/o3d/plugin/npapi_host_control/win/np_plugin_proxy.h index 6f122d1..e3f1c9e 100644 --- a/o3d/plugin/npapi_host_control/win/np_plugin_proxy.h +++ b/o3d/plugin/npapi_host_control/win/np_plugin_proxy.h @@ -69,6 +69,11 @@ class NPPluginProxy { const std::vector<CStringA>& argument_names, const std::vector<CStringA>& argument_values); + // Sets the target window of the npapi plugin. This may be called + // repeatedly during its lifetime, in particular to set the plugin's + // size. + bool SetWindow(const NPWindow& window); + // Frees all resources allocated in Init, and blocks on all pending stream // operations. void TearDown(); diff --git a/o3d/plugin/win/main_win.cc b/o3d/plugin/win/main_win.cc index f2feeae..85bc28c 100644 --- a/o3d/plugin/win/main_win.cc +++ b/o3d/plugin/win/main_win.cc @@ -87,7 +87,7 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, #endif // O3D_INTERNAL_PLUGIN namespace { -const wchar_t* const kFullScreenWindowClassName = L"O3DFullScreenWindowClass"; +const wchar_t* const kO3DWindowClassName = L"O3DWindowClass"; // We would normally make this a stack variable in main(), but in a // plugin, that's not possible, so we make it a global. When the DLL is loaded @@ -352,79 +352,6 @@ void HandleMouseEvent(PluginObject *obj, } } -// This returns 0 on success, 1 on failure, to match WindowProc. -LRESULT ForwardEvent(PluginObject *obj, - HWND hWnd, - UINT Msg, - WPARAM wParam, - LPARAM lParam, - bool translateCoords) { - DCHECK(obj); - DCHECK(obj->GetPluginHWnd()); - HWND dest_hwnd = obj->GetParentHWnd(); - DCHECK(hWnd); - DCHECK(dest_hwnd); - bool fullscreen = hWnd == obj->GetFullscreenHWnd(); - if (fullscreen) { - dest_hwnd = obj->GetPluginHWnd(); - } else if (obj->IsChrome()) { - // When trying to find the parent window of the Chrome plugin, new Chrome is - // different than old Chrome; it's got an extra wrapper window around the - // plugin that didn't used to be there. The wrapper won't listen to events, - // so if we see it, we have to go one window up the tree from there in order - // to find someone who'll listen to us. The new behavior is seen in nightly - // builds of Chromium as of 2.0.163.0 (9877) [but went in some time before - // that]; the old behavior is still exhibited by Chrome as of 1.0.154.48. - wchar_t chrome_class_name[] = L"WrapperNativeWindowClass"; - wchar_t buffer[sizeof(chrome_class_name) / sizeof(chrome_class_name[0])]; - if (!GetClassName(dest_hwnd, buffer, sizeof(buffer) / sizeof(buffer[0]))) { - return 1; - } - if (!wcscmp(chrome_class_name, buffer)) { - dest_hwnd = ::GetParent(dest_hwnd); - } - } - if (translateCoords) { - int x = GET_X_LPARAM(lParam); - int y = GET_Y_LPARAM(lParam); - - RECT rect0, rect1; - if (!::GetWindowRect(hWnd, &rect0)) { - DCHECK(false); - return 1; - } - if (!::GetWindowRect(dest_hwnd, &rect1)) { - DCHECK(false); - return 1; - } - int width = rect0.right - rect0.left; - int width_1 = rect1.right - rect1.left; - - int x_1; - int y_1; - - if (!fullscreen) { // Translate from plugin to browser offset coords. - x_1 = x - rect1.left + rect0.left; - } else { // Translate from screen to plugin offset coords. - // The plugin and the fullscreen window each fill their respective entire - // window, so there aren't any offsets to add or subtract. - x_1 = x * width_1 / width; - } - int height = rect0.bottom - rect0.top; - int height_1 = rect1.bottom - rect1.top; - if (!fullscreen) { // Translate from plugin to browser offset coords. - y_1 = y - rect1.top + rect0.top; - } else { // Translate from screen to plugin offset coords. - // The plugin and the fullscreen window each fill their respective entire - // window, so there aren't any offsets to add or subtract. - y_1 = y * height_1 / height; - } - - lParam = MAKELPARAM(x_1, y_1); - } - return !::PostMessage(dest_hwnd, Msg, wParam, lParam); -} - LRESULT HandleDragAndDrop(PluginObject *obj, WPARAM wParam) { HDROP hDrop = reinterpret_cast<HDROP>(wParam); UINT num_files = ::DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0); @@ -507,11 +434,10 @@ LRESULT CALLBACK WindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { if (!obj->RecordPaint()) { ::SetPixelV(hdc, 0, 0, RGB(0, 0, 0)); } - obj->renderer()->set_need_to_render(true); } else { - // If there Client has no Renderer associated with it, paint the draw - // area gray. + // If the Client has no Renderer associated with it, paint the + // draw area gray. ::SelectObject(paint_struct.hdc, GetStockObject(DKGRAY_BRUSH)); ::Rectangle(paint_struct.hdc, paint_struct.rcPaint.left, @@ -521,29 +447,17 @@ LRESULT CALLBACK WindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { } } ::EndPaint(hWnd, &paint_struct); - break; + return 0; } case WM_SETCURSOR: { obj->set_cursor(obj->cursor()); return 1; } case WM_ERASEBKGND: { - return 1; // tell windows we don't need the background cleared + // Tell windows we don't need the background cleared. + return 1; } - case WM_SIZE: { - // Resize event called - if (reentrance_count.get() > 1) { - break; // Ignore this message; we're reentrant. - } - - // get new dimensions of window - int window_width = LOWORD(lParam); - int window_height = HIWORD(lParam); - // Tell the plugin that it has been resized - obj->Resize(window_width, window_height); - break; - } case WM_TIMER: { if (reentrance_count.get() > 1) { break; // Ignore this message; we're reentrant. @@ -619,20 +533,28 @@ LRESULT CALLBACK WindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { case WM_SYSKEYUP: return HandleKeyboardEvent(obj, hWnd, Msg, wParam, lParam); -#if(_WIN32_WINNT >= 0x0500) - case WM_APPCOMMAND: -#endif /* _WIN32_WINNT >= 0x0500 */ - return ForwardEvent(obj, hWnd, Msg, wParam, lParam, false); - case WM_DROPFILES: return HandleDragAndDrop(obj, wParam); + case WM_ACTIVATE: + // We don't receive WM_KILLFOCUS when Alt-Tabbing away from a + // full-screen window. We do however get WM_ACTIVATE. + if (LOWORD(wParam) == WA_INACTIVE) { + if (obj->fullscreen()) { + obj->CancelFullscreenDisplay(); + } + } + return 0; + case WM_KILLFOCUS: // If we lose focus [which also happens on alt+f4 killing the fullscreen // window] fall back to plugin mode to avoid lost-device awkwardness. // TODO: We'll have problems with this when dealing with e.g. // Japanese text input IME windows. - if (hWnd == obj->GetFullscreenHWnd()) { + if (obj->fullscreen()) { + // TODO(kbr): consider doing this somehow more asynchronously; + // not supposed to cause window activation in the WM_KILLFOCUS + // handler obj->CancelFullscreenDisplay(); return 0; } @@ -645,34 +567,63 @@ LRESULT CALLBACK WindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { // manually, its destructor will know not to. reentrance_count.decrement(); - if (hWnd == obj->GetFullscreenHWnd()) { - return ::CallWindowProc(::DefWindowProc, - hWnd, - Msg, - wParam, - lParam); - } else { - return ::CallWindowProc(obj->GetDefaultPluginWindowProc(), - hWnd, - Msg, - wParam, - lParam); - } + return ::CallWindowProc(::DefWindowProc, + hWnd, + Msg, + wParam, + lParam); } return 0; } -bool RegisterFullScreenWindowClass() { - WNDCLASSEX window_class = { sizeof(WNDCLASSEX) }; +static const wchar_t* kOrigWndProcName = L"o3dOrigWndProc"; + +LRESULT CALLBACK PluginWindowInterposer(HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam) { + switch (Msg) { + case WM_PAINT: { + // For nicer startup appearance, allow the browser to paint the + // plugin window until we start to draw 3D content. Forbid the + // browser from painting once we have started to draw to prevent + // a flash in Firefox upon our receiving focus the first time. + PluginObject *obj = PluginObject::GetPluginProperty(hWnd); + if (obj != NULL && obj->renderer() != NULL) { + if (obj->renderer()->presented_once()) { + // Tell Windows we painted the window region. + ::ValidateRect(hWnd, NULL); + return 0; + } + } + // Break out to call the original window procedure to paint the + // window. + break; + } + + default: + break; + } + + WNDPROC proc = static_cast<WNDPROC>(GetProp(hWnd, kOrigWndProcName)); + DCHECK(proc != NULL); + return CallWindowProc(proc, hWnd, Msg, wParam, lParam); +} + +bool RegisterO3DWindowClass() { + WNDCLASSEX window_class; + ZeroMemory(&window_class, sizeof(window_class)); + window_class.cbSize = sizeof(window_class); window_class.hInstance = g_module_instance; window_class.lpfnWndProc = WindowProc; - window_class.lpszClassName = kFullScreenWindowClassName; - window_class.style = CS_DBLCLKS; + window_class.lpszClassName = kO3DWindowClassName; + // We use CS_OWNDC in case we are rendering OpenGL into this window. + window_class.style = CS_DBLCLKS | CS_OWNDC; return RegisterClassEx(&window_class) != 0; } -void UnregisterFullScreenWindowClass() { - UnregisterClass(kFullScreenWindowClassName, g_module_instance); +void UnregisterO3DWindowClass() { + UnregisterClass(kO3DWindowClassName, g_module_instance); } NPError InitializePlugin() { @@ -696,58 +647,41 @@ NPError InitializePlugin() { DLOG(INFO) << "NP_Initialize"; - if (!RegisterFullScreenWindowClass()) + if (!RegisterO3DWindowClass()) return NPERR_MODULE_LOAD_FAILED_ERROR; return NPERR_NO_ERROR; } -void CleanupFullscreenWindow(PluginObject *obj) { - DCHECK(obj->GetFullscreenHWnd()); - obj->StorePluginProperty(obj->GetPluginHWnd(), obj); - ::DestroyWindow(obj->GetFullscreenHWnd()); - obj->SetFullscreenHWnd(NULL); -} - void CleanupAllWindows(PluginObject *obj) { - DCHECK(obj->GetHWnd()); + DCHECK(obj->GetContentHWnd()); DCHECK(obj->GetPluginHWnd()); - ::KillTimer(obj->GetHWnd(), 0); - if (obj->GetFullscreenHWnd()) { - CleanupFullscreenWindow(obj); - } - PluginObject::ClearPluginProperty(obj->GetHWnd()); - ::SetWindowLongPtr(obj->GetPluginHWnd(), - GWL_WNDPROC, - reinterpret_cast<LONG_PTR>( - obj->GetDefaultPluginWindowProc())); + ::KillTimer(obj->GetContentHWnd(), 0); + PluginObject::ClearPluginProperty(obj->GetContentHWnd()); + PluginObject::ClearPluginProperty(obj->GetPluginHWnd()); + ::DestroyWindow(obj->GetContentHWnd()); + obj->SetContentHWnd(NULL); obj->SetPluginHWnd(NULL); obj->SetHWnd(NULL); } -HWND CreateFullscreenWindow(PluginObject *obj, - int mode_id) { - o3d::DisplayMode mode; - if (!obj->renderer()->GetDisplayMode(mode_id, &mode)) { - return NULL; - } - CHECK(mode.width() > 0 && mode.height() > 0); - - HWND hWnd = CreateWindowEx(NULL, - kFullScreenWindowClassName, - L"O3D Test Fullscreen Window", - WS_POPUP, - 0, 0, - mode.width(), - mode.height(), - NULL, - NULL, - g_module_instance, - NULL); - - ShowWindow(hWnd, SW_SHOW); - return hWnd; +// Re-parents the content_hwnd into the containing_hwnd, resizing the +// content_hwnd to the given width and height in the process. +void ReplaceContentWindow(HWND content_hwnd, + HWND containing_hwnd, + int width, int height) { + ::ShowWindow(content_hwnd, SW_HIDE); + LONG_PTR style = ::GetWindowLongPtr(content_hwnd, GWL_STYLE); + style |= WS_CHILD; + ::SetWindowLongPtr(content_hwnd, GWL_STYLE, style); + ::SetParent(content_hwnd, containing_hwnd); + BOOL res = ::SetWindowPos(content_hwnd, containing_hwnd, + 0, 0, width, height, + SWP_NOZORDER | SWP_ASYNCWINDOWPOS); + DCHECK(res); + ::ShowWindow(content_hwnd, SW_SHOW); } + } // namespace anonymous #if defined(O3D_INTERNAL_PLUGIN) @@ -767,7 +701,7 @@ NPError OSCALL NP_Shutdown(void) { HANDLE_CRASHES; DLOG(INFO) << "NP_Shutdown"; - UnregisterFullScreenWindowClass(); + UnregisterO3DWindowClass(); #if !defined(O3D_INTERNAL_PLUGIN) @@ -870,30 +804,62 @@ NPError NPP_SetWindow(NPP instance, NPWindow *window) { } return NPERR_NO_ERROR; } - if (obj->GetHWnd() == hWnd) { - return NPERR_NO_ERROR; - } - if (obj->fullscreen()) { - // We can get here if the user alt+tabs away from the fullscreen plugin - // window or JavaScript resizes the plugin window. - DCHECK(obj->GetPluginHWnd()); - DCHECK(obj->GetFullscreenHWnd()); - DCHECK(obj->GetPluginHWnd() == hWnd); - - // Exit full screen if the plugin window is being modified. - obj->CancelFullscreenDisplay(); + if (obj->GetPluginHWnd() == hWnd) { + // May need to resize the content window. + DCHECK(obj->GetContentHWnd()); + // Avoid spurious resize requests. + if (window->width != obj->width() || + window->height != obj->height()) { + if (!obj->fullscreen()) { + ::SetWindowPos(obj->GetContentHWnd(), obj->GetPluginHWnd(), 0, 0, + window->width, window->height, + SWP_NOZORDER | SWP_NOREPOSITION); + } + // Even if we are in full-screen mode, store off the new width + // and height to restore to them later. + obj->Resize(window->width, window->height); + // Only propagate this resize event to the client if it isn't in + // full-screen mode. + if (!obj->fullscreen()) { + obj->client()->SendResizeEvent(obj->width(), obj->height(), false); + } + } return NPERR_NO_ERROR; } + DCHECK(!obj->GetPluginHWnd()); obj->SetPluginHWnd(hWnd); - obj->SetParentHWnd(::GetParent(hWnd)); - PluginObject::StorePluginProperty(hWnd, obj); - obj->SetDefaultPluginWindowProc( - reinterpret_cast<WNDPROC>( - ::SetWindowLongPtr(hWnd, - GWL_WNDPROC, - reinterpret_cast<LONG_PTR>(WindowProc)))); + + // Subclass the plugin window's window procedure to avoid processing + // WM_PAINT. This seems to only be necessary for Firefox, which + // overdraws our plugin the first time it gains focus. + SetProp(hWnd, kOrigWndProcName, + reinterpret_cast<HANDLE>(GetWindowLongPtr(hWnd, GWLP_WNDPROC))); + PluginObject::StorePluginPropertyUnsafe(hWnd, obj); + SetWindowLongPtr(hWnd, GWLP_WNDPROC, + reinterpret_cast<LONG_PTR>(PluginWindowInterposer)); + + // Create the content window, into which O3D always renders, rather + // than alternating rendering between the browser's window and a + // separate full-screen window. The O3D window is removed from the + // browser's hierarchy and made top-level in order to go to + // full-screen mode via Direct3D. This solves fundamental focus + // fighting problems seen on Windows Vista. + HWND content_window = + CreateWindow(kO3DWindowClassName, + L"O3D Window", + WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, + 0, 0, + window->width, window->height, + hWnd, + NULL, + g_module_instance, + NULL); + obj->Resize(window->width, window->height); + obj->SetContentHWnd(content_window); + PluginObject::StorePluginProperty(content_window, obj); + ::ShowWindow(content_window, SW_SHOW); // create and assign the graphics context DisplayWindowWindows default_display; @@ -937,32 +903,43 @@ bool PluginObject::GetDisplayMode(int mode_id, o3d::DisplayMode *mode) { bool PluginObject::RequestFullscreenDisplay() { bool success = false; DCHECK(GetPluginHWnd()); + DCHECK(GetContentHWnd()); if (!fullscreen_ && renderer_ && fullscreen_region_valid_) { DCHECK(renderer_->fullscreen() == fullscreen_); - DCHECK(!GetFullscreenHWnd()); - HWND drawing_hwnd = - CreateFullscreenWindow(this, fullscreen_region_mode_id_); - if (drawing_hwnd) { - ::KillTimer(GetHWnd(), 0); - SetFullscreenHWnd(drawing_hwnd); - StorePluginPropertyUnsafe(drawing_hwnd, this); - + // The focus window we pass into IDirect3D9::CreateDevice must not + // fight with the full-screen window for the focus. The best way + // to achieve this is to re-use the content window for full-screen + // mode. + ::ShowWindow(GetContentHWnd(), SW_HIDE); + ::SetParent(GetContentHWnd(), NULL); + // Remove WS_CHILD from the window style + LONG_PTR style = ::GetWindowLongPtr(GetContentHWnd(), GWL_STYLE); + style &= ~WS_CHILD; + ::SetWindowLongPtr(GetContentHWnd(), GWL_STYLE, style); + ::ShowWindow(GetContentHWnd(), SW_SHOW); + // We need to resize the full-screen window to the desired size of + // the display mode early, before calling + // Renderer::GoFullscreen(). + o3d::DisplayMode mode; + if (GetDisplayMode(fullscreen_region_mode_id_, &mode)) { + ::SetWindowPos(GetContentHWnd(), HWND_TOP, 0, 0, + mode.width(), mode.height(), + SWP_NOZORDER | SWP_NOREPOSITION | SWP_ASYNCWINDOWPOS); DisplayWindowWindows display; - display.set_hwnd(GetHWnd()); - if (renderer_->SetFullscreen(true, display, - fullscreen_region_mode_id_)) { + display.set_hwnd(GetContentHWnd()); + if (renderer_->GoFullscreen(display, + fullscreen_region_mode_id_)) { fullscreen_ = true; client()->SendResizeEvent(renderer_->width(), renderer_->height(), - true); + true); success = true; - } else { - CleanupFullscreenWindow(this); } - prev_width_ = renderer_->width(); - prev_height_ = renderer_->height(); - ::SetTimer(GetHWnd(), 0, 10, NULL); - } else { - LOG(ERROR) << "Failed to create fullscreen window."; + } + + if (!success) { + ReplaceContentWindow(GetContentHWnd(), GetPluginHWnd(), + prev_width_, prev_height_); + LOG(ERROR) << "Failed to switch to fullscreen mode."; } } return success; @@ -973,18 +950,15 @@ void PluginObject::CancelFullscreenDisplay() { if (fullscreen_) { DCHECK(renderer()); DCHECK(renderer()->fullscreen()); - ::KillTimer(GetHWnd(), 0); + fullscreen_ = false; DisplayWindowWindows display; - display.set_hwnd(GetPluginHWnd()); - if (!renderer_->SetFullscreen(false, display, 0)) { + display.set_hwnd(GetContentHWnd()); + if (!renderer_->CancelFullscreen(display, prev_width_, prev_height_)) { LOG(FATAL) << "Failed to get the renderer out of fullscreen mode!"; } - CleanupFullscreenWindow(this); - prev_width_ = renderer_->width(); - prev_height_ = renderer_->height(); + ReplaceContentWindow(GetContentHWnd(), GetPluginHWnd(), + prev_width_, prev_height_); client()->SendResizeEvent(prev_width_, prev_height_, false); - ::SetTimer(GetHWnd(), 0, 10, NULL); - fullscreen_ = false; } } } // namespace _o3d |