summaryrefslogtreecommitdiffstats
path: root/o3d/plugin
diff options
context:
space:
mode:
Diffstat (limited to 'o3d/plugin')
-rw-r--r--o3d/plugin/cross/o3d_glue.cc6
-rw-r--r--o3d/plugin/cross/o3d_glue.h32
-rw-r--r--o3d/plugin/npapi_host_control/win/host_control.cc19
-rw-r--r--o3d/plugin/npapi_host_control/win/host_control.h3
-rw-r--r--o3d/plugin/npapi_host_control/win/np_plugin_proxy.cc13
-rw-r--r--o3d/plugin/npapi_host_control/win/np_plugin_proxy.h5
-rw-r--r--o3d/plugin/win/main_win.cc382
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