From db0df3ee8dcb3243400560f3d1761e2c332861ff Mon Sep 17 00:00:00 2001 From: "peterlubczynski%netscape.com" Date: Thu, 2 May 2002 20:46:22 +0000 Subject: [PATCH] Adding extra event call (WM_WINDOWPOSCHANGED) for windowless plugins on Windows so that they are updated with their position and bounds. Bug 135737, r=av, sr=attinasi git-svn-id: svn://10.0.0.236/trunk@120569 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/layout/generic/nsObjectFrame.cpp | 96 +++++++++++++++++-- mozilla/layout/generic/nsObjectFrame.h | 3 +- .../layout/html/base/src/nsObjectFrame.cpp | 96 +++++++++++++++++-- mozilla/layout/html/base/src/nsObjectFrame.h | 3 +- 4 files changed, 184 insertions(+), 14 deletions(-) diff --git a/mozilla/layout/generic/nsObjectFrame.cpp b/mozilla/layout/generic/nsObjectFrame.cpp index 69f3094e925..f36b7807487 100644 --- a/mozilla/layout/generic/nsObjectFrame.cpp +++ b/mozilla/layout/generic/nsObjectFrame.cpp @@ -786,8 +786,6 @@ nsObjectFrame::CreateWidget(nsIPresContext* aPresContext, view->GetWidget(*getter_AddRefs(win)); if (win) win->SetBackgroundColor(color->mBackgroundColor); - else - NS_ASSERTION(win, "failed to get widget to set background color on"); break; } } @@ -1400,7 +1398,7 @@ nsObjectFrame::ContentChanged(nsIPresContext* aPresContext, return rv; } -nsresult nsObjectFrame::GetWindowOriginInPixels(nsIPresContext * aPresContext, nsPoint * aOrigin) +nsresult nsObjectFrame::GetWindowOriginInPixels(nsIPresContext * aPresContext, PRBool aWindowless, nsPoint * aOrigin) { NS_ENSURE_ARG_POINTER(aPresContext); NS_ENSURE_ARG_POINTER(aOrigin); @@ -1411,6 +1409,29 @@ nsresult nsObjectFrame::GetWindowOriginInPixels(nsIPresContext * aPresContext, n GetOffsetFromView(aPresContext, origin, &parentWithView); + // if it's windowless, let's make sure we have our origin set right + // it may need to be corrected, like after scrolling + if (aWindowless && parentWithView) { + nsPoint correction(0,0); + nsCOMPtr parentVM; + parentWithView->GetViewManager(*getter_AddRefs(parentVM)); + + // Walk up all the views and add up their positions. This will give us our + // absolute position which is what we want to give the plugin + nsIView* theView = parentWithView; + while (theView) { + nsCOMPtr vm; + theView->GetViewManager(*getter_AddRefs(vm)); + if (vm != parentVM) + break; + + theView->GetPosition(&correction.x, &correction.y); + origin += correction; + + theView->GetParent(theView); + } + } + float t2p; aPresContext->GetTwipsToPixels(&t2p); aOrigin->x = NSTwipsToIntPixels(origin.x, t2p); @@ -1466,7 +1487,7 @@ nsObjectFrame::DidReflow(nsIPresContext* aPresContext, return rv; nsPoint origin; - GetWindowOriginInPixels(aPresContext, &origin); + GetWindowOriginInPixels(aPresContext, windowless, &origin); window->x = origin.x; window->y = origin.y; @@ -1688,6 +1709,15 @@ nsObjectFrame::Paint(nsIPresContext* aPresContext, doupdatewindow = PR_TRUE; } + /* + * Layout now has an optimized way of painting. Now we always get + * a new drawing surface, sized to be just what's needed. Windowsless + * plugins need a transform applied to their origin so they paint + * in the right place. Since |SetWindow| is no longer being used + * to tell the plugin where it is, we dispatch a NPWindow through + * |HandleEvent| to tell the plugin when its window moved + */ + // Get the offset of the DC nsTransform2D* rcTransform; aRenderingContext.GetCurrentTransform(rcTransform); @@ -1700,8 +1730,62 @@ nsObjectFrame::Paint(nsIPresContext* aPresContext, doupdatewindow = PR_TRUE; } - if(doupdatewindow) - inst->SetWindow(window); + // if our location or visible area has changed, we need to tell the plugin + if(doupdatewindow) { +#ifdef XP_WIN // Windowless plugins on windows need a special event to update their location, see bug 135737 + + // first, lets find out how big the window is, in pixels + nsCOMPtr shell; + nsCOMPtr vm; + aPresContext->GetShell(getter_AddRefs(shell)); + if (shell) { + shell->GetViewManager(getter_AddRefs(vm)); + if (vm) { + nsIView* view; + vm->GetRootView(view); + if (view) { + nsCOMPtr win; + view->GetWidget(*getter_AddRefs(win)); + if (win) { + nsRect visibleRect; + win->GetBounds(visibleRect); + + // next, get our plugin's rect so we can intersect it with the visible rect so we + // can tell the plugin where and how much to paint + GetWindowOriginInPixels(aPresContext, window->type, &origin); + nsRect winlessRect = nsRect(origin, nsSize(window->width, window->height)); + winlessRect.IntersectRect(winlessRect, visibleRect); + + // now check our cached window and only update plugin if something has changed + if (mWindowlessRect != winlessRect) { + mWindowlessRect = winlessRect; + + WINDOWPOS winpos; + memset(&winpos, 0, sizeof(winpos)); + winpos.x = mWindowlessRect.x; + winpos.y = mWindowlessRect.y; + winpos.cx = mWindowlessRect.width; + winpos.cy = mWindowlessRect.height; + + // finally, update the plugin by sending it a WM_WINDOWPOSCHANGED event + nsPluginEvent pluginEvent; + pluginEvent.event = 0x0047; + pluginEvent.wParam = 0; + pluginEvent.lParam = (uint32)&winpos; + PRBool eventHandled = PR_FALSE; + + inst->HandleEvent(&pluginEvent, &eventHandled); + + mInstanceOwner->ReleasePluginPort((nsPluginPort *)winpos.hwnd); + } + } + } + } + } +#endif + + inst->SetWindow(window); + } mInstanceOwner->Paint(aDirtyRect, hdc); } diff --git a/mozilla/layout/generic/nsObjectFrame.h b/mozilla/layout/generic/nsObjectFrame.h index 6708d5c3f60..9efd19908f2 100644 --- a/mozilla/layout/generic/nsObjectFrame.h +++ b/mozilla/layout/generic/nsObjectFrame.h @@ -161,13 +161,14 @@ protected: nsresult NotifyContentObjectWrapper(); - nsresult GetWindowOriginInPixels(nsIPresContext * aPresContext, nsPoint* aOrigin); + nsresult GetWindowOriginInPixels(nsIPresContext * aPresContext, PRBool aWindoless, nsPoint* aOrigin); private: nsPluginInstanceOwner *mInstanceOwner; nsIURI *mFullURL; nsIFrame *mFirstChild; nsIWidget *mWidget; + nsRect mWindowlessRect; }; diff --git a/mozilla/layout/html/base/src/nsObjectFrame.cpp b/mozilla/layout/html/base/src/nsObjectFrame.cpp index 69f3094e925..f36b7807487 100644 --- a/mozilla/layout/html/base/src/nsObjectFrame.cpp +++ b/mozilla/layout/html/base/src/nsObjectFrame.cpp @@ -786,8 +786,6 @@ nsObjectFrame::CreateWidget(nsIPresContext* aPresContext, view->GetWidget(*getter_AddRefs(win)); if (win) win->SetBackgroundColor(color->mBackgroundColor); - else - NS_ASSERTION(win, "failed to get widget to set background color on"); break; } } @@ -1400,7 +1398,7 @@ nsObjectFrame::ContentChanged(nsIPresContext* aPresContext, return rv; } -nsresult nsObjectFrame::GetWindowOriginInPixels(nsIPresContext * aPresContext, nsPoint * aOrigin) +nsresult nsObjectFrame::GetWindowOriginInPixels(nsIPresContext * aPresContext, PRBool aWindowless, nsPoint * aOrigin) { NS_ENSURE_ARG_POINTER(aPresContext); NS_ENSURE_ARG_POINTER(aOrigin); @@ -1411,6 +1409,29 @@ nsresult nsObjectFrame::GetWindowOriginInPixels(nsIPresContext * aPresContext, n GetOffsetFromView(aPresContext, origin, &parentWithView); + // if it's windowless, let's make sure we have our origin set right + // it may need to be corrected, like after scrolling + if (aWindowless && parentWithView) { + nsPoint correction(0,0); + nsCOMPtr parentVM; + parentWithView->GetViewManager(*getter_AddRefs(parentVM)); + + // Walk up all the views and add up their positions. This will give us our + // absolute position which is what we want to give the plugin + nsIView* theView = parentWithView; + while (theView) { + nsCOMPtr vm; + theView->GetViewManager(*getter_AddRefs(vm)); + if (vm != parentVM) + break; + + theView->GetPosition(&correction.x, &correction.y); + origin += correction; + + theView->GetParent(theView); + } + } + float t2p; aPresContext->GetTwipsToPixels(&t2p); aOrigin->x = NSTwipsToIntPixels(origin.x, t2p); @@ -1466,7 +1487,7 @@ nsObjectFrame::DidReflow(nsIPresContext* aPresContext, return rv; nsPoint origin; - GetWindowOriginInPixels(aPresContext, &origin); + GetWindowOriginInPixels(aPresContext, windowless, &origin); window->x = origin.x; window->y = origin.y; @@ -1688,6 +1709,15 @@ nsObjectFrame::Paint(nsIPresContext* aPresContext, doupdatewindow = PR_TRUE; } + /* + * Layout now has an optimized way of painting. Now we always get + * a new drawing surface, sized to be just what's needed. Windowsless + * plugins need a transform applied to their origin so they paint + * in the right place. Since |SetWindow| is no longer being used + * to tell the plugin where it is, we dispatch a NPWindow through + * |HandleEvent| to tell the plugin when its window moved + */ + // Get the offset of the DC nsTransform2D* rcTransform; aRenderingContext.GetCurrentTransform(rcTransform); @@ -1700,8 +1730,62 @@ nsObjectFrame::Paint(nsIPresContext* aPresContext, doupdatewindow = PR_TRUE; } - if(doupdatewindow) - inst->SetWindow(window); + // if our location or visible area has changed, we need to tell the plugin + if(doupdatewindow) { +#ifdef XP_WIN // Windowless plugins on windows need a special event to update their location, see bug 135737 + + // first, lets find out how big the window is, in pixels + nsCOMPtr shell; + nsCOMPtr vm; + aPresContext->GetShell(getter_AddRefs(shell)); + if (shell) { + shell->GetViewManager(getter_AddRefs(vm)); + if (vm) { + nsIView* view; + vm->GetRootView(view); + if (view) { + nsCOMPtr win; + view->GetWidget(*getter_AddRefs(win)); + if (win) { + nsRect visibleRect; + win->GetBounds(visibleRect); + + // next, get our plugin's rect so we can intersect it with the visible rect so we + // can tell the plugin where and how much to paint + GetWindowOriginInPixels(aPresContext, window->type, &origin); + nsRect winlessRect = nsRect(origin, nsSize(window->width, window->height)); + winlessRect.IntersectRect(winlessRect, visibleRect); + + // now check our cached window and only update plugin if something has changed + if (mWindowlessRect != winlessRect) { + mWindowlessRect = winlessRect; + + WINDOWPOS winpos; + memset(&winpos, 0, sizeof(winpos)); + winpos.x = mWindowlessRect.x; + winpos.y = mWindowlessRect.y; + winpos.cx = mWindowlessRect.width; + winpos.cy = mWindowlessRect.height; + + // finally, update the plugin by sending it a WM_WINDOWPOSCHANGED event + nsPluginEvent pluginEvent; + pluginEvent.event = 0x0047; + pluginEvent.wParam = 0; + pluginEvent.lParam = (uint32)&winpos; + PRBool eventHandled = PR_FALSE; + + inst->HandleEvent(&pluginEvent, &eventHandled); + + mInstanceOwner->ReleasePluginPort((nsPluginPort *)winpos.hwnd); + } + } + } + } + } +#endif + + inst->SetWindow(window); + } mInstanceOwner->Paint(aDirtyRect, hdc); } diff --git a/mozilla/layout/html/base/src/nsObjectFrame.h b/mozilla/layout/html/base/src/nsObjectFrame.h index 6708d5c3f60..9efd19908f2 100644 --- a/mozilla/layout/html/base/src/nsObjectFrame.h +++ b/mozilla/layout/html/base/src/nsObjectFrame.h @@ -161,13 +161,14 @@ protected: nsresult NotifyContentObjectWrapper(); - nsresult GetWindowOriginInPixels(nsIPresContext * aPresContext, nsPoint* aOrigin); + nsresult GetWindowOriginInPixels(nsIPresContext * aPresContext, PRBool aWindoless, nsPoint* aOrigin); private: nsPluginInstanceOwner *mInstanceOwner; nsIURI *mFullURL; nsIFrame *mFirstChild; nsIWidget *mWidget; + nsRect mWindowlessRect; };