Bug 542337 - '[OOPP] hang in test_plugin_clipping2.xhtml' r=jimm.
--- a/modules/plugin/base/src/nsPluginNativeWindowWin.cpp
+++ b/modules/plugin/base/src/nsPluginNativeWindowWin.cpp
@@ -540,17 +540,24 @@ nsresult nsPluginNativeWindowWin::Subcla
return NS_ERROR_FAILURE;
// check if we need to re-subclass
WNDPROC currentWndProc = (WNDPROC)::GetWindowLongPtr(hWnd, GWLP_WNDPROC);
if (PluginWndProc == currentWndProc)
return NS_OK;
LONG style = GetWindowLongPtr(hWnd, GWL_STYLE);
+#ifdef MOZ_IPC
+ // Out of process plugins must not have the WS_CLIPCHILDREN style set on their
+ // parent windows or else synchronous paints (via UpdateWindow() and others)
+ // will cause deadlocks.
+ style &= ~WS_CLIPCHILDREN;
+#else
style |= WS_CLIPCHILDREN;
+#endif
SetWindowLongPtr(hWnd, GWL_STYLE, style);
mPluginWinProc = SubclassWindow(hWnd, (LONG_PTR)PluginWndProc);
if (!mPluginWinProc)
return NS_ERROR_FAILURE;
nsPluginNativeWindowWin * win = (nsPluginNativeWindowWin *)::GetProp(hWnd, NS_PLUGIN_WINDOW_PROPERTY_ASSOCIATION);
NS_ASSERTION(!win || (win == this), "plugin window already has property and this is not us");
--- a/widget/src/windows/nsWindow.cpp
+++ b/widget/src/windows/nsWindow.cpp
@@ -101,18 +101,16 @@
**
** Include headers.
**
**************************************************************
**************************************************************/
#ifdef MOZ_IPC
#include "mozilla/ipc/SyncChannel.h"
-#include "mozilla/plugins/PluginInstanceParent.h"
-using mozilla::plugins::PluginInstanceParent;
#endif
#include "nsWindow.h"
#include <windows.h>
#include <process.h>
#include <commctrl.h>
#include <unknwn.h>
@@ -2104,17 +2102,17 @@ NS_METHOD nsWindow::Invalidate(PRBool aI
// We need to keep track of our own invalidated region for Windows CE
RECT r;
GetClientRect(mWnd, &r);
AddRECTToRegion(r, mInvalidatedRegion);
#endif
VERIFY(::InvalidateRect(mWnd, NULL, FALSE));
if (aIsSynchronous) {
- UpdateWindowInternal(mWnd);
+ VERIFY(::UpdateWindow(mWnd));
}
}
return NS_OK;
}
// Invalidate this component visible area
NS_METHOD nsWindow::Invalidate(const nsIntRect & aRect, PRBool aIsSynchronous)
{
@@ -2138,17 +2136,17 @@ NS_METHOD nsWindow::Invalidate(const nsI
#ifdef WINCE_WINDOWS_MOBILE
// We need to keep track of our own invalidated region for Windows CE
AddRECTToRegion(rect, mInvalidatedRegion);
#endif
VERIFY(::InvalidateRect(mWnd, &rect, FALSE));
if (aIsSynchronous) {
- UpdateWindowInternal(mWnd);
+ VERIFY(::UpdateWindow(mWnd));
}
}
return NS_OK;
}
NS_IMETHODIMP
nsWindow::MakeFullScreen(PRBool aFullScreen)
{
@@ -2182,17 +2180,17 @@ nsWindow::MakeFullScreen(PRBool aFullScr
NS_IMETHODIMP nsWindow::Update()
{
nsresult rv = NS_OK;
// updates can come through for windows no longer holding an mWnd during
// deletes triggered by JavaScript in buttons with mouse feedback
if (mWnd)
- UpdateWindowInternal(mWnd);
+ VERIFY(::UpdateWindow(mWnd));
return rv;
}
/**************************************************************
*
* SECTION: nsIWidget::Scroll
*
@@ -3142,24 +3140,18 @@ PRBool nsWindow::DispatchCommandEvent(PR
// descendants with invalidated rectangles.
BOOL CALLBACK nsWindow::DispatchStarvedPaints(HWND aWnd, LPARAM aMsg)
{
LONG_PTR proc = ::GetWindowLongPtrW(aWnd, GWLP_WNDPROC);
if (proc == (LONG_PTR)&nsWindow::WindowProc) {
// its one of our windows so check to see if it has a
// invalidated rect. If it does. Dispatch a synchronous
// paint.
- if (GetUpdateRect(aWnd, NULL, FALSE)) {
- nsWindow* win = GetNSWindowPtr(aWnd);
- if (win)
- win->UpdateWindowInternal(aWnd);
- else
- // Bad, this could hang a plugin process. Is this possible?
- VERIFY(::UpdateWindow(aWnd));
- }
+ if (GetUpdateRect(aWnd, NULL, FALSE))
+ VERIFY(::UpdateWindow(aWnd));
}
return TRUE;
}
// Check for pending paints and dispatch any pending paint
// messages for any nsIWidget which is a descendant of the
// top-level window that *this* window is embedded within.
//
@@ -7112,41 +7104,16 @@ LPARAM nsWindow::lParamToClient(LPARAM l
{
POINT pt;
pt.x = GET_X_LPARAM(lParam);
pt.y = GET_Y_LPARAM(lParam);
::ScreenToClient(mWnd, &pt);
return MAKELPARAM(pt.x, pt.y);
}
-// If this window hosts a plugin window from another process then we cannot use
-// the windows UpdateWindow function to update it. Doing so sends a synchronous
-// WM_PAINT message to the plugin process which may call back to this process
-// in response. As this process is waiting for the UpdateWindow call to return
-// we deadlock. To work around this we issue an IPC call to the plugin process
-// to force the redraw since the IPC call handles reentrancy properly.
-void nsWindow::UpdateWindowInternal(HWND aWnd)
-{
- if (aWnd) {
-#ifdef MOZ_IPC
- if (mWindowType == eWindowType_plugin) {
- PluginInstanceParent* instance = reinterpret_cast<PluginInstanceParent*>(
- ::GetPropW(aWnd, L"PluginInstanceParentProperty"));
- if (instance) {
- if (!instance->CallUpdateWindow())
- NS_ERROR("Failed to send message!");
- ValidateRect(aWnd, NULL);
- return;
- }
- }
-#endif
- VERIFY(::UpdateWindow(aWnd));
- }
-}
-
/**************************************************************
**************************************************************
**
** BLOCK: ChildWindow impl.
**
** Child window overrides.
**
**************************************************************
--- a/widget/src/windows/nsWindow.h
+++ b/widget/src/windows/nsWindow.h
@@ -398,18 +398,16 @@ protected:
PAINTSTRUCT ps, HDC aDC);
#if !defined(WINCE)
static void ActivateOtherWindowHelper(HWND aWnd);
#endif
#ifdef ACCESSIBILITY
static STDMETHODIMP_(LRESULT) LresultFromObject(REFIID riid, WPARAM wParam, LPUNKNOWN pAcc);
#endif // ACCESSIBILITY
- void UpdateWindowInternal(HWND aWnd);
-
protected:
nsIntSize mLastSize;
nsIntPoint mLastPoint;
HWND mWnd;
WNDPROC mPrevWndProc;
HBRUSH mBrush;
PRPackedBool mIsTopWidgetWindow;
PRPackedBool mHas3DBorder;
--- a/widget/src/windows/nsWindowGfx.cpp
+++ b/widget/src/windows/nsWindowGfx.cpp
@@ -48,16 +48,21 @@
**
** BLOCK: Includes
**
** Include headers.
**
**************************************************************
**************************************************************/
+#ifdef MOZ_IPC
+#include "mozilla/plugins/PluginInstanceParent.h"
+using mozilla::plugins::PluginInstanceParent;
+#endif
+
#include "nsWindowGfx.h"
#include <windows.h>
#include "nsIRegion.h"
#include "gfxImageSurface.h"
#include "gfxWindowsSurface.h"
#include "gfxWindowsPlatform.h"
#include "nsGfxCIID.h"
#include "gfxContext.h"
@@ -317,16 +322,29 @@ EnsureSharedSurfaceSize(gfxIntSize size)
sSharedSurfaceData = (PRUint8 *)malloc(WORDSSIZE(sSharedSurfaceSize) * 4);
}
return (sSharedSurfaceData != nsnull);
}
PRBool nsWindow::OnPaint(HDC aDC)
{
+#ifdef MOZ_IPC
+ if (mWindowType == eWindowType_plugin) {
+ PluginInstanceParent* instance = reinterpret_cast<PluginInstanceParent*>(
+ ::GetPropW(mWnd, L"PluginInstanceParentProperty"));
+ if (instance) {
+ if (!instance->CallUpdateWindow())
+ NS_ERROR("Failed to send message!");
+ ValidateRect(mWnd, NULL);
+ return PR_TRUE;
+ }
+ }
+#endif
+
nsPaintEvent willPaintEvent(PR_TRUE, NS_WILL_PAINT, this);
DispatchWindowEvent(&willPaintEvent);
#ifdef CAIRO_HAS_DDRAW_SURFACE
if (IsRenderMode(gfxWindowsPlatform::RENDER_IMAGE_DDRAW16)) {
return OnPaintImageDDraw16();
}
#endif