зеркало из https://github.com/mozilla/gecko-dev.git
Bug 352093. Part 15: Rework scrolling so that we don't need a dedicated native widget for scrollframes. r=dbaron,joshmoz,karlt,jmathies
This commit is contained in:
Родитель
e992230f78
Коммит
933f110f1a
|
@ -93,7 +93,8 @@ public:
|
|||
// nsIScrollPositionListener
|
||||
NS_IMETHOD ScrollPositionWillChange(nsIScrollableView *aView,
|
||||
nscoord aX, nscoord aY);
|
||||
virtual void ViewPositionDidChange(nsIScrollableView* aScrollable) {}
|
||||
virtual void ViewPositionDidChange(nsIScrollableView* aScrollable,
|
||||
nsTArray<nsIWidget::Configuration>* aConfigurations) {}
|
||||
NS_IMETHOD ScrollPositionDidChange(nsIScrollableView *aView,
|
||||
nscoord aX, nscoord aY);
|
||||
|
||||
|
|
|
@ -1381,40 +1381,6 @@ nsGfxScrollFrameInner::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsGfxScrollFrameInner::NeedsClipWidget() const
|
||||
{
|
||||
// Scrollports contained in form controls (e.g., listboxes) don't get
|
||||
// widgets. Also, transformed elements don't need clip widgets since they
|
||||
// result in graphical glitches.
|
||||
for (nsIFrame* parentFrame = mOuter; parentFrame;
|
||||
parentFrame = nsLayoutUtils::GetCrossDocParentFrame(parentFrame)) {
|
||||
|
||||
/* See if we have a transform... we should have no widget if that's the case. */
|
||||
if (parentFrame->GetStyleDisplay()->HasTransform())
|
||||
return PR_FALSE;
|
||||
|
||||
/* If we're a form element, we don't need a widget. */
|
||||
nsIFormControlFrame* fcFrame = do_QueryFrame(parentFrame);
|
||||
if (fcFrame) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Scrollports that don't ever show associated scrollbars don't get
|
||||
// widgets, because they will seldom actually be scrolled.
|
||||
nsIScrollableFrame *scrollableFrame = do_QueryFrame(mOuter);
|
||||
ScrollbarStyles scrollbars = scrollableFrame->GetScrollbarStyles();
|
||||
if ((scrollbars.mHorizontal == NS_STYLE_OVERFLOW_HIDDEN
|
||||
|| scrollbars.mHorizontal == NS_STYLE_OVERFLOW_VISIBLE)
|
||||
&& (scrollbars.mVertical == NS_STYLE_OVERFLOW_HIDDEN
|
||||
|| scrollbars.mVertical == NS_STYLE_OVERFLOW_VISIBLE)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
nsGfxScrollFrameInner::CreateScrollableView()
|
||||
{
|
||||
|
@ -1429,11 +1395,6 @@ nsGfxScrollFrameInner::CreateScrollableView()
|
|||
|
||||
// Insert the view into the view hierarchy
|
||||
viewManager->InsertChild(outerView, view, nsnull, PR_TRUE);
|
||||
|
||||
// Have the scrolling view create its internal widgets
|
||||
if (NeedsClipWidget()) {
|
||||
mScrollableView->CreateScrollControls();
|
||||
}
|
||||
}
|
||||
|
||||
static void HandleScrollPref(nsIScrollable *aScrollable, PRInt32 aOrientation,
|
||||
|
@ -1792,11 +1753,15 @@ nsGfxScrollFrameInner::InternalScrollPositionDidChange(nscoord aX, nscoord aY)
|
|||
}
|
||||
|
||||
void
|
||||
nsGfxScrollFrameInner::ViewPositionDidChange(nsIScrollableView* aScrollable)
|
||||
nsGfxScrollFrameInner::ViewPositionDidChange(nsIScrollableView* aScrollable,
|
||||
nsTArray<nsIWidget::Configuration>* aConfigurations)
|
||||
{
|
||||
// Update frame position to match view offsets
|
||||
nsPoint childOffset = mScrolledFrame->GetView()->GetOffsetTo(mOuter->GetView());
|
||||
mScrolledFrame->SetPosition(childOffset);
|
||||
|
||||
mOuter->PresContext()->RootPresContext()->
|
||||
GetPluginGeometryUpdates(mOuter, aConfigurations);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1817,8 +1782,6 @@ nsGfxScrollFrameInner::ScrollPositionDidChange(nsIScrollableView* aScrollable, n
|
|||
mOuter->InvalidateWithFlags(nsRect(nsPoint(0, 0), mOuter->GetSize()),
|
||||
nsIFrame::INVALIDATE_NOTIFY_ONLY);
|
||||
|
||||
mOuter->PresContext()->RootPresContext()->UpdatePluginGeometry(mOuter);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -79,7 +79,6 @@ public:
|
|||
// reload our child frame list.
|
||||
// We need this if a scrollbar frame is recreated.
|
||||
void ReloadChildFrames();
|
||||
PRBool NeedsClipWidget() const;
|
||||
void CreateScrollableView();
|
||||
|
||||
nsresult CreateAnonymousContent(nsTArray<nsIContent*>& aElements);
|
||||
|
@ -98,7 +97,8 @@ public:
|
|||
// nsIScrollPositionListener
|
||||
|
||||
NS_IMETHOD ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY);
|
||||
virtual void ViewPositionDidChange(nsIScrollableView* aScrollable);
|
||||
virtual void ViewPositionDidChange(nsIScrollableView* aScrollable,
|
||||
nsTArray<nsIWidget::Configuration>* aConfigurations);
|
||||
NS_IMETHOD ScrollPositionDidChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY);
|
||||
|
||||
// This gets called when the 'curpos' attribute on one of the scrollbars changes
|
||||
|
|
|
@ -130,7 +130,8 @@ public:
|
|||
|
||||
// nsIScrollPositionListener
|
||||
NS_IMETHOD ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY);
|
||||
virtual void ViewPositionDidChange(nsIScrollableView* aScrollable) {}
|
||||
virtual void ViewPositionDidChange(nsIScrollableView* aScrollable,
|
||||
nsTArray<nsIWidget::Configuration>* aConfigurations) {}
|
||||
NS_IMETHOD ScrollPositionDidChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY);
|
||||
|
||||
// nsICanvasFrame
|
||||
|
|
|
@ -362,7 +362,8 @@ public:
|
|||
|
||||
// nsIScrollPositionListener interface
|
||||
NS_IMETHOD ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY);
|
||||
virtual void ViewPositionDidChange(nsIScrollableView* aScrollable) {}
|
||||
virtual void ViewPositionDidChange(nsIScrollableView* aScrollable,
|
||||
nsTArray<nsIWidget::Configuration>* aConfigurations) {}
|
||||
NS_IMETHOD ScrollPositionDidChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY);
|
||||
|
||||
//locals
|
||||
|
|
|
@ -4128,7 +4128,24 @@ nsTreeBodyFrame::ScrollInternal(const ScrollParts& aParts, PRInt32 aRow)
|
|||
if (widget) {
|
||||
nscoord rowHeightAsPixels =
|
||||
PresContext()->AppUnitsToDevPixels(mRowHeight);
|
||||
widget->Scroll(0, -delta*rowHeightAsPixels, nsnull);
|
||||
nsIntPoint deltaPt = nsIntPoint(0, -delta*rowHeightAsPixels);
|
||||
nsIntRect bounds;
|
||||
widget->GetBounds(bounds);
|
||||
bounds.x = bounds.y = 0;
|
||||
nsIntRect source;
|
||||
source.IntersectRect(bounds, bounds - deltaPt);
|
||||
// No plugins have a tree widget as a parent so we don't need
|
||||
// configurations here.
|
||||
nsTArray<nsIWidget::Configuration> emptyConfigurations;
|
||||
widget->Scroll(deltaPt, source, emptyConfigurations);
|
||||
nsIntRect invalid = bounds;
|
||||
if (deltaPt.y < 0) {
|
||||
invalid.y = bounds.height + deltaPt.y;
|
||||
invalid.height = -deltaPt.y;
|
||||
} else {
|
||||
invalid.height = deltaPt.y;
|
||||
}
|
||||
widget->Invalidate(invalid, PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4166,7 +4183,24 @@ nsTreeBodyFrame::ScrollHorzInternal(const ScrollParts& aParts, PRInt32 aPosition
|
|||
} else {
|
||||
nsIWidget* widget = nsLeafBoxFrame::GetView()->GetWidget();
|
||||
if (widget) {
|
||||
widget->Scroll(PresContext()->AppUnitsToDevPixels(-delta), 0, nsnull);
|
||||
nsIntPoint deltaPt(PresContext()->AppUnitsToDevPixels(-delta), 0);
|
||||
nsIntRect bounds;
|
||||
widget->GetBounds(bounds);
|
||||
bounds.x = bounds.y = 0;
|
||||
nsIntRect source;
|
||||
source.IntersectRect(bounds, bounds - deltaPt);
|
||||
// No plugins have a tree widget as a parent so we don't need
|
||||
// configurations here.
|
||||
nsTArray<nsIWidget::Configuration> emptyConfigurations;
|
||||
widget->Scroll(deltaPt, source, emptyConfigurations);
|
||||
nsIntRect invalid = bounds;
|
||||
if (deltaPt.x < 0) {
|
||||
invalid.x = bounds.width + deltaPt.x;
|
||||
invalid.width = -deltaPt.x;
|
||||
} else {
|
||||
invalid.width = deltaPt.x;
|
||||
}
|
||||
widget->Invalidate(invalid, PR_FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,16 +42,16 @@
|
|||
|
||||
#include "nsISupports.h"
|
||||
#include "nsCoord.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsIWidget.h"
|
||||
|
||||
// forward declarations
|
||||
class nsIScrollableView;
|
||||
|
||||
// IID for the nsIScrollPositionListener interface
|
||||
// {98a0c040-09cf-408b-b55f-321b4f8d9d67}
|
||||
|
||||
#define NS_ISCROLLPOSITIONLISTENER_IID \
|
||||
{ 0x98a0c040, 0x09cf, 0x408b, \
|
||||
{ 0xb5, 0x5f, 0x32, 0x1b, 0x4f, 0x8d, 0x9d, 0x67 } }
|
||||
{ 0x9654a477, 0x49a7, 0x4aea, \
|
||||
{ 0xb7, 0xe3, 0x90, 0xe5, 0xe5, 0xd4, 0x28, 0xcd } }
|
||||
|
||||
/**
|
||||
* Provides a way for a client of an nsIScrollableView to learn about scroll position
|
||||
|
@ -62,7 +62,11 @@ public:
|
|||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCROLLPOSITIONLISTENER_IID)
|
||||
|
||||
NS_IMETHOD ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY) = 0;
|
||||
virtual void ViewPositionDidChange(nsIScrollableView* aScrollable) = 0;
|
||||
// The scrollframe implementation of this method appends a list of widget
|
||||
// configuration requests to aConfigurations. No other implementor
|
||||
// should touch it.
|
||||
virtual void ViewPositionDidChange(nsIScrollableView* aScrollable,
|
||||
nsTArray<nsIWidget::Configuration>* aConfigurations) = 0;
|
||||
NS_IMETHOD ScrollPositionDidChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY) = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -64,14 +64,6 @@ class nsIScrollableView {
|
|||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_ISCROLLABLEVIEW_IID)
|
||||
|
||||
/**
|
||||
* Create the controls used to allow scrolling. Call this method
|
||||
* before anything else is done with the scrollable view.
|
||||
* @param aNative native widget to use as parent for control widgets
|
||||
* @return error status
|
||||
*/
|
||||
NS_IMETHOD CreateScrollControls(nsNativeWidget aNative = nsnull) = 0;
|
||||
|
||||
/**
|
||||
* Get the dimensions of the container
|
||||
* @param aWidth return value for width of container
|
||||
|
|
|
@ -143,18 +143,6 @@ NS_IMETHODIMP nsScrollPortView::RemoveScrollPositionListener(nsIScrollPositionLi
|
|||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsScrollPortView::CreateScrollControls(nsNativeWidget aNative)
|
||||
{
|
||||
nsWidgetInitData initData;
|
||||
initData.clipChildren = PR_TRUE;
|
||||
initData.clipSiblings = PR_TRUE;
|
||||
|
||||
CreateWidget(kWidgetCID, &initData,
|
||||
mWindow ? nsnull : aNative);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsScrollPortView::GetContainerSize(nscoord *aWidth, nscoord *aHeight) const
|
||||
{
|
||||
if (!aWidth || !aHeight)
|
||||
|
@ -330,9 +318,9 @@ static void AdjustChildWidgets(nsView *aView,
|
|||
widget->Show(PR_TRUE);
|
||||
}
|
||||
}
|
||||
// Don't recurse if the view has a widget, because we adjusted the view's
|
||||
// widget position, and its child widgets are relative to its position
|
||||
} else {
|
||||
// Don't recurse if the view haLs a widget, because we adjusted the view's
|
||||
// widget position, and its child widgets are relative to its positon
|
||||
nsPoint widgetToViewOrigin = aWidgetToParentViewOrigin
|
||||
+ aView->GetPosition();
|
||||
|
||||
|
@ -553,8 +541,9 @@ NS_IMETHODIMP nsScrollPortView::CanScroll(PRBool aHorizontal,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void nsScrollPortView::Scroll(nsView *aScrolledView, nsPoint aTwipsDelta, nsIntPoint aPixDelta,
|
||||
PRInt32 aP2A)
|
||||
void nsScrollPortView::Scroll(nsView *aScrolledView, nsPoint aTwipsDelta,
|
||||
nsIntPoint aPixDelta, PRInt32 aP2A,
|
||||
const nsTArray<nsIWidget::Configuration>& aConfigurations)
|
||||
{
|
||||
if (aTwipsDelta.x != 0 || aTwipsDelta.y != 0)
|
||||
{
|
||||
|
@ -564,37 +553,20 @@ void nsScrollPortView::Scroll(nsView *aScrolledView, nsPoint aTwipsDelta, nsIntP
|
|||
if (aScrolledView->NeedsInvalidateFrameOnScroll())
|
||||
GetViewManager()->GetViewObserver()->InvalidateFrameForView(aScrolledView);
|
||||
|
||||
nsIWidget *scrollWidget = GetWidget();
|
||||
nsPoint nearestWidgetOffset;
|
||||
nsIWidget *nearestWidget = GetNearestWidget(&nearestWidgetOffset);
|
||||
nsRegion updateRegion;
|
||||
PRBool canBitBlit = scrollWidget &&
|
||||
PRBool canBitBlit = nearestWidget &&
|
||||
mViewManager->CanScrollWithBitBlt(aScrolledView, aTwipsDelta, &updateRegion) &&
|
||||
scrollWidget->GetTransparencyMode() != eTransparencyTransparent;
|
||||
nearestWidget->GetTransparencyMode() != eTransparencyTransparent;
|
||||
|
||||
if (canBitBlit) {
|
||||
// We're going to bit-blit. Let the viewmanager know so it can
|
||||
// adjust dirty regions appropriately.
|
||||
mViewManager->WillBitBlit(this, aTwipsDelta);
|
||||
}
|
||||
|
||||
if (!scrollWidget)
|
||||
{
|
||||
NS_ASSERTION(!canBitBlit, "Someone screwed up");
|
||||
nsPoint offsetToWidget;
|
||||
GetNearestWidget(&offsetToWidget);
|
||||
// We're moving the child widgets because we are scrolling. But
|
||||
// the child widgets may stick outside our bounds, so their area
|
||||
// may include area that's not supposed to be scrolled. We need
|
||||
// to invalidate to ensure that any such area is properly
|
||||
// repainted back to the right rendering.
|
||||
AdjustChildWidgets(aScrolledView, offsetToWidget, aP2A, PR_TRUE);
|
||||
// If we don't have a scroll widget then we must just update.
|
||||
// We should call this after fixing up the widget positions to be
|
||||
// consistent with the view hierarchy.
|
||||
mViewManager->UpdateView(this, NS_VMREFRESH_DEFERRED);
|
||||
} else if (!canBitBlit) {
|
||||
if (!canBitBlit) {
|
||||
// We can't blit for some reason.
|
||||
// Just update the view and adjust widgets
|
||||
// Recall that our widget's origin is at our bounds' top-left
|
||||
if (nearestWidget) {
|
||||
nearestWidget->ConfigureChildren(aConfigurations);
|
||||
}
|
||||
nsRect bounds(GetBounds());
|
||||
nsPoint topLeft(bounds.x, bounds.y);
|
||||
AdjustChildWidgets(aScrolledView,
|
||||
|
@ -602,34 +574,45 @@ void nsScrollPortView::Scroll(nsView *aScrolledView, nsPoint aTwipsDelta, nsIntP
|
|||
// We should call this after fixing up the widget positions to be
|
||||
// consistent with the view hierarchy.
|
||||
mViewManager->UpdateView(this, NS_VMREFRESH_DEFERRED);
|
||||
} else { // if we can blit and have a scrollwidget then scroll.
|
||||
nsIntRect* toScrollPtr = nsnull;
|
||||
} else {
|
||||
// We're going to bit-blit. Let the viewmanager know so it can
|
||||
// adjust dirty regions appropriately.
|
||||
mViewManager->WillBitBlit(this, aTwipsDelta);
|
||||
|
||||
#ifdef XP_WIN
|
||||
nsIntRect toScroll;
|
||||
if (!updateRegion.IsEmpty()) {
|
||||
nsRegion regionToScroll;
|
||||
regionToScroll.Sub(nsRect(nsPoint(0,0), GetBounds().Size()),
|
||||
updateRegion);
|
||||
nsRegionRectIterator iter(regionToScroll);
|
||||
nsRect biggestRect(0,0,0,0);
|
||||
const nsRect* r;
|
||||
for (r = iter.Next(); r; r = iter.Next()) {
|
||||
if (PRInt64(r->width)*PRInt64(r->height) > PRInt64(biggestRect.width)*PRInt64(biggestRect.height)) {
|
||||
biggestRect = *r;
|
||||
}
|
||||
// Compute the region that needs to be updated by the bit-blit scroll
|
||||
nsRect bounds(nsPoint(0,0), GetBounds().Size());
|
||||
nsRegion regionToScroll;
|
||||
regionToScroll.Sub(bounds, updateRegion);
|
||||
// Only the area corresponding to the widget bounds, translated
|
||||
// by the scroll amount, will actually be filled by the blit
|
||||
regionToScroll.And(regionToScroll, bounds - aTwipsDelta);
|
||||
// Find the largest rectangle in that region
|
||||
nsRegionRectIterator iter(regionToScroll);
|
||||
nsRect biggestRect(0,0,0,0);
|
||||
const nsRect* r;
|
||||
for (r = iter.Next(); r; r = iter.Next()) {
|
||||
if (PRInt64(r->width)*PRInt64(r->height) > PRInt64(biggestRect.width)*PRInt64(biggestRect.height)) {
|
||||
biggestRect = *r;
|
||||
}
|
||||
toScrollPtr = &toScroll;
|
||||
toScroll = biggestRect.ToInsidePixels(aP2A);
|
||||
biggestRect = toScroll.ToAppUnits(aP2A);
|
||||
regionToScroll.Sub(regionToScroll, biggestRect);
|
||||
updateRegion.Or(updateRegion, regionToScroll);
|
||||
}
|
||||
#endif
|
||||
// Convert the largest rectangle to widget device pixel coordinates
|
||||
nsIntRect destScroll = (biggestRect + nearestWidgetOffset).ToInsidePixels(aP2A);
|
||||
// Convert it back to view-relative appunits, since we shrank it in
|
||||
// ToInsidePixels
|
||||
biggestRect = destScroll.ToAppUnits(aP2A) - nearestWidgetOffset;
|
||||
// Make sure we repaint the area we've decided not to bit-blit to
|
||||
regionToScroll.Sub(regionToScroll, biggestRect);
|
||||
updateRegion.Or(updateRegion, regionToScroll);
|
||||
|
||||
// Scroll the contents of the widget by the specified amount, and scroll
|
||||
// the child widgets
|
||||
scrollWidget->Scroll(aPixDelta.x, aPixDelta.y, toScrollPtr);
|
||||
// Compute the area that's being exposed by the scroll operation
|
||||
// and make sure it gets repainted
|
||||
nsRegion exposedArea;
|
||||
exposedArea.Sub(bounds, bounds - aTwipsDelta);
|
||||
updateRegion.Or(updateRegion, exposedArea);
|
||||
|
||||
nearestWidget->Scroll(aPixDelta, destScroll - aPixDelta,
|
||||
aConfigurations);
|
||||
AdjustChildWidgets(aScrolledView, nearestWidgetOffset, aP2A, PR_TRUE);
|
||||
mViewManager->UpdateViewAfterScroll(this, updateRegion);
|
||||
}
|
||||
}
|
||||
|
@ -686,16 +669,15 @@ NS_IMETHODIMP nsScrollPortView::ScrollToImpl(nscoord aX, nscoord aY)
|
|||
if (!scrolledView) return NS_ERROR_FAILURE;
|
||||
|
||||
// move the scrolled view to the new location
|
||||
// Note that child widgets may be scrolled by the native widget scrolling,
|
||||
// so don't update their positions
|
||||
scrolledView->SetPositionIgnoringChildWidgets(-aX, -aY);
|
||||
|
||||
// notify the listeners.
|
||||
nsTArray<nsIWidget::Configuration> configurations;
|
||||
if (nsnull != mListeners) {
|
||||
if (NS_SUCCEEDED(mListeners->Count(&listenerCount))) {
|
||||
for (PRUint32 i = 0; i < listenerCount; i++) {
|
||||
if (NS_SUCCEEDED(mListeners->QueryElementAt(i, kScrollPositionListenerIID, (void**)&listener))) {
|
||||
listener->ViewPositionDidChange(this);
|
||||
listener->ViewPositionDidChange(this, &configurations);
|
||||
NS_RELEASE(listener);
|
||||
}
|
||||
}
|
||||
|
@ -708,7 +690,7 @@ NS_IMETHODIMP nsScrollPortView::ScrollToImpl(nscoord aX, nscoord aY)
|
|||
mOffsetX = aX;
|
||||
mOffsetY = aY;
|
||||
|
||||
Scroll(scrolledView, twipsDelta, nsIntPoint(dxPx, dyPx), p2a);
|
||||
Scroll(scrolledView, twipsDelta, nsIntPoint(dxPx, dyPx), p2a, configurations);
|
||||
|
||||
mViewManager->SynthesizeMouseMove(PR_TRUE);
|
||||
|
||||
|
|
|
@ -60,7 +60,6 @@ public:
|
|||
void** aInstancePtr);
|
||||
|
||||
//nsIScrollableView interface
|
||||
NS_IMETHOD CreateScrollControls(nsNativeWidget aNative = nsnull);
|
||||
NS_IMETHOD GetContainerSize(nscoord *aWidth, nscoord *aHeight) const;
|
||||
NS_IMETHOD SetScrolledView(nsIView *aScrolledView);
|
||||
NS_IMETHOD GetScrolledView(nsIView *&aScrolledView) const;
|
||||
|
@ -107,7 +106,9 @@ protected:
|
|||
virtual ~nsScrollPortView();
|
||||
|
||||
//private
|
||||
void Scroll(nsView *aScrolledView, nsPoint aTwipsDelta, nsIntPoint aPixDelta, nscoord aP2A);
|
||||
void Scroll(nsView *aScrolledView, nsPoint aTwipsDelta,
|
||||
nsIntPoint aPixDelta, nscoord aP2A,
|
||||
const nsTArray<nsIWidget::Configuration>& aConfigurations);
|
||||
PRBool CannotBitBlt(nsView* aScrolledView);
|
||||
nsresult CalcScrollOverflow(nscoord aX, nscoord aY, PRInt32& aOverflowX, PRInt32& aOverflowY);
|
||||
|
||||
|
|
|
@ -654,7 +654,6 @@ nsViewManager::WillBitBlit(nsView* aView, nsPoint aScrollAmount)
|
|||
|
||||
NS_PRECONDITION(aView, "Must have a view");
|
||||
NS_PRECONDITION(!aView->NeedsInvalidateFrameOnScroll(), "We shouldn't be BitBlting.");
|
||||
NS_PRECONDITION(aView->HasWidget(), "View must have a widget");
|
||||
|
||||
++mScrollCnt;
|
||||
|
||||
|
@ -670,24 +669,10 @@ nsViewManager::UpdateViewAfterScroll(nsView *aView, const nsRegion& aUpdateRegio
|
|||
{
|
||||
NS_ASSERTION(RootViewManager()->mScrollCnt > 0,
|
||||
"Someone forgot to call WillBitBlit()");
|
||||
// Look at the view's clipped rect. It may be that part of the view is clipped out
|
||||
// in which case we don't need to worry about invalidating the clipped-out part.
|
||||
nsRect damageRect = aView->GetDimensions();
|
||||
if (damageRect.IsEmpty()) {
|
||||
// Don't forget to undo mScrollCnt!
|
||||
--RootViewManager()->mScrollCnt;
|
||||
return;
|
||||
}
|
||||
|
||||
nsView* displayRoot = GetDisplayRootFor(aView);
|
||||
nsPoint offset = aView->GetOffsetTo(displayRoot);
|
||||
damageRect.MoveBy(offset);
|
||||
|
||||
UpdateWidgetArea(displayRoot, displayRoot->GetWidget(),
|
||||
nsRegion(damageRect), aView);
|
||||
if (!aUpdateRegion.IsEmpty()) {
|
||||
// XXX We should update the region, not the bounds rect, but that requires
|
||||
// a little more work. Fix this when we reshuffle this code.
|
||||
nsView* displayRoot = GetDisplayRootFor(aView);
|
||||
nsPoint offset = aView->GetOffsetTo(displayRoot);
|
||||
nsRegion update(aUpdateRegion);
|
||||
update.MoveBy(offset);
|
||||
UpdateWidgetArea(displayRoot, displayRoot->GetWidget(),
|
||||
|
@ -1572,11 +1557,7 @@ PRBool nsViewManager::CanScrollWithBitBlt(nsView* aView, nsPoint aDelta,
|
|||
|
||||
aUpdateRegion->MoveBy(-displayOffset);
|
||||
|
||||
#if defined(MOZ_WIDGET_GTK2) || defined(XP_OS2)
|
||||
return aUpdateRegion->IsEmpty();
|
||||
#else
|
||||
return GetArea(aUpdateRegion->GetBounds()) < GetArea(parentBounds)/2;
|
||||
#endif
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsViewManager::SetViewFloating(nsIView *aView, PRBool aFloating)
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "nsColor.h"
|
||||
#include "nsCoord.h"
|
||||
#include "nsRect.h"
|
||||
#include "nsPoint.h"
|
||||
|
||||
#include "prthread.h"
|
||||
#include "nsEvent.h"
|
||||
|
@ -102,8 +103,8 @@ typedef nsEventStatus (* EVENT_CALLBACK)(nsGUIEvent *event);
|
|||
#endif
|
||||
|
||||
#define NS_IWIDGET_IID \
|
||||
{ 0x8f0869be, 0x6a53, 0x4f21, \
|
||||
{ 0xa9, 0x64, 0x90, 0xd9, 0x26, 0x04, 0x05, 0xa3 } }
|
||||
{ 0x9b8d70bd, 0x068e, 0x4465, \
|
||||
{ 0x8a, 0xd2, 0x4c, 0xf7, 0x96, 0x67, 0xe4, 0xfc } }
|
||||
|
||||
/*
|
||||
* Window shadow styles
|
||||
|
@ -708,15 +709,25 @@ class nsIWidget : public nsISupports {
|
|||
virtual nsIToolkit* GetToolkit() = 0;
|
||||
|
||||
/**
|
||||
* Scroll this widget.
|
||||
*
|
||||
* @param aDx amount to scroll along the x-axis
|
||||
* @param aDy amount to scroll along the y-axis.
|
||||
* @param aClipRect clipping rectangle to limit the scroll to.
|
||||
* Scroll a rectangle in this widget and (as simultaneously as
|
||||
* possible) modify the specified child widgets.
|
||||
*
|
||||
* This will invalidate areas of the children that have changed, unless
|
||||
* they have just moved by the scroll amount, but does not need to
|
||||
* invalidate any part of this widget, except where the scroll
|
||||
* operation fails to blit because part of the window is unavailable
|
||||
* (e.g. partially offscreen).
|
||||
*
|
||||
* @param aDelta amount to scroll (device pixels)
|
||||
* @param aSource rectangle to copy (device pixels relative to this
|
||||
* widget)
|
||||
* @param aReconfigureChildren commands to set the bounds and clip
|
||||
* region of a subset of the children of this widget; these should
|
||||
* be performed simultaneously with the scrolling, as far as possible,
|
||||
* to avoid visual artifacts.
|
||||
*/
|
||||
|
||||
NS_IMETHOD Scroll(PRInt32 aDx, PRInt32 aDy, nsIntRect *aClipRect) = 0;
|
||||
virtual void Scroll(const nsIntPoint& aDelta, const nsIntRect& aSource,
|
||||
const nsTArray<Configuration>& aReconfigureChildren) = 0;
|
||||
|
||||
/**
|
||||
* Internal methods
|
||||
|
|
|
@ -350,7 +350,9 @@ public:
|
|||
|
||||
virtual void* GetNativeData(PRUint32 aDataType);
|
||||
virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations);
|
||||
NS_IMETHOD Scroll(PRInt32 aDx, PRInt32 aDy, nsIntRect *aClipRect);
|
||||
virtual void Scroll(const nsIntPoint& aDelta,
|
||||
const nsIntRect& aSource,
|
||||
const nsTArray<Configuration>& aConfigurations);
|
||||
virtual nsIntPoint WidgetToScreenOffset();
|
||||
NS_IMETHOD BeginResizingChildren(void);
|
||||
NS_IMETHOD EndResizingChildren(void);
|
||||
|
|
|
@ -1727,143 +1727,43 @@ nsresult nsChildView::ConfigureChildren(const nsTArray<Configuration>& aConfigur
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Scroll the bits of a view and its children
|
||||
// FIXME: I'm sure the invalidating can be optimized, just no time now.
|
||||
NS_IMETHODIMP nsChildView::Scroll(PRInt32 aDx, PRInt32 aDy, nsIntRect *aClipRect)
|
||||
void nsChildView::Scroll(const nsIntPoint& aDelta, const nsIntRect& aSource,
|
||||
const nsTArray<Configuration>& aConfigurations)
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
|
||||
|
||||
NS_ASSERTION(mParentView, "Attempting to scroll a view that does not have a parent");
|
||||
if (!mParentView)
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
return;
|
||||
|
||||
BOOL viewWasDirty = NO;
|
||||
if (mVisible) {
|
||||
viewWasDirty = [mView needsDisplay];
|
||||
|
||||
NSSize scrollVector = {aDx,aDy};
|
||||
[mView scrollRect: [mView visibleRect] by:scrollVector];
|
||||
NSRect rect;
|
||||
GeckoRectToNSRect(aSource, rect);
|
||||
NSSize scrollVector = {aDelta.x, aDelta.y};
|
||||
[mView scrollRect:rect by:scrollVector];
|
||||
}
|
||||
|
||||
// Scroll the children (even if the widget is not visible)
|
||||
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) {
|
||||
// We use resize rather than move since it gives us control
|
||||
// over repainting. We can scroll like a bat out of hell
|
||||
// by not wasting time invalidating the widgets, since it's
|
||||
// completely unnecessary to do so.
|
||||
nsIntRect bounds;
|
||||
kid->GetBounds(bounds);
|
||||
kid->Resize(bounds.x + aDx, bounds.y + aDy, bounds.width, bounds.height, PR_FALSE);
|
||||
|
||||
// Don't force invalidation of the child if it's moving by the scroll
|
||||
// amount and not changing size
|
||||
for (PRUint32 i = 0; i < aConfigurations.Length(); ++i) {
|
||||
const Configuration& configuration = aConfigurations[i];
|
||||
nsIntRect oldBounds;
|
||||
configuration.mChild->GetBounds(oldBounds);
|
||||
ApplyConfiguration(this, aConfigurations[i],
|
||||
oldBounds + aDelta != configuration.mBounds);
|
||||
}
|
||||
|
||||
if (mOnDestroyCalled)
|
||||
return NS_OK;
|
||||
return;
|
||||
|
||||
if (mVisible) {
|
||||
if (viewWasDirty) {
|
||||
[mView setNeedsDisplay:YES];
|
||||
}
|
||||
else {
|
||||
NSRect frame = [mView visibleRect];
|
||||
NSRect horizInvalid = frame;
|
||||
NSRect vertInvalid = frame;
|
||||
|
||||
if (aDx != 0) {
|
||||
horizInvalid.size.width = abs(aDx);
|
||||
if (aDx < 0)
|
||||
horizInvalid.origin.x = frame.origin.x + frame.size.width + aDx;
|
||||
[mView setNeedsDisplayInRect: horizInvalid];
|
||||
}
|
||||
|
||||
if (aDy != 0) {
|
||||
vertInvalid.size.height = abs(aDy);
|
||||
if (aDy < 0)
|
||||
vertInvalid.origin.y = frame.origin.y + frame.size.height + aDy;
|
||||
[mView setNeedsDisplayInRect: vertInvalid];
|
||||
}
|
||||
|
||||
// We also need to check for any ChildViews which overlap this widget
|
||||
// but are not descendent widgets. If there are any, we need to
|
||||
// invalidate the area of this view that these ChildViews will have been
|
||||
// blitted into, since these widgets aren't supposed to scroll with
|
||||
// this widget.
|
||||
|
||||
// To do this, start at the root Gecko NSView, and walk down along
|
||||
// our ancestor view chain, looking at all the subviews in each level
|
||||
// of the hierarchy. If we find a non-ancestor view that overlaps
|
||||
// this view, invalidate the area around it.
|
||||
|
||||
// We need to convert all rects to a common ancestor view to intersect
|
||||
// them, since a view's frame is in the coordinate space of its parent.
|
||||
// Use mParentView as the frame of reference.
|
||||
NSRect selfFrame = [mParentView convertRect:[mView frame] fromView:[mView superview]];
|
||||
NSView* view = mParentView;
|
||||
BOOL selfLevel = NO;
|
||||
|
||||
while (!selfLevel) {
|
||||
NSView* nextAncestorView = nil;
|
||||
NSArray* subviews = [view subviews];
|
||||
for (unsigned int i = 0; i < [subviews count]; ++i) {
|
||||
NSView* subView = [subviews objectAtIndex: i];
|
||||
if (subView == mView)
|
||||
selfLevel = YES;
|
||||
else if ([mView isDescendantOf:subView])
|
||||
nextAncestorView = subView;
|
||||
else {
|
||||
NSRect intersectArea = NSIntersectionRect([mParentView convertRect:[subView frame] fromView:[subView superview]], selfFrame);
|
||||
if (!NSIsEmptyRect(intersectArea)) {
|
||||
NSPoint origin = [mView convertPoint:intersectArea.origin fromView:mParentView];
|
||||
|
||||
if (aDy != 0) {
|
||||
vertInvalid.origin.x = origin.x;
|
||||
if (aDy < 0) // scrolled down, invalidate above
|
||||
vertInvalid.origin.y = origin.y + aDy;
|
||||
else // invalidate below
|
||||
vertInvalid.origin.y = origin.y + intersectArea.size.height;
|
||||
vertInvalid.size.width = intersectArea.size.width;
|
||||
[mView setNeedsDisplayInRect: vertInvalid];
|
||||
}
|
||||
|
||||
if (aDx != 0) {
|
||||
horizInvalid.origin.y = origin.y;
|
||||
if (aDx < 0) // scrolled right, invalidate to the left
|
||||
horizInvalid.origin.x = origin.x + aDx;
|
||||
else // invalidate to the right
|
||||
horizInvalid.origin.x = origin.x + intersectArea.size.width;
|
||||
horizInvalid.size.height = intersectArea.size.height;
|
||||
[mView setNeedsDisplayInRect: horizInvalid];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
view = nextAncestorView;
|
||||
}
|
||||
}
|
||||
[mView setNeedsDisplay:viewWasDirty];
|
||||
}
|
||||
|
||||
// This is an evil hack that doesn't always work.
|
||||
//
|
||||
// Drawing plugins in a Cocoa environment is tricky, because the
|
||||
// plugins are living in a Carbon WindowRef/BeginUpdate/EndUpdate
|
||||
// world, and Cocoa has its own notion of dirty rectangles. Throw
|
||||
// Quartz Extreme and QuickTime into the mix, and things get bad.
|
||||
//
|
||||
// This code is working around a cosmetic issue seen when Quartz Extreme
|
||||
// is active, and you're scrolling a page with a QuickTime plugin; areas
|
||||
// outside the plugin fail to scroll properly. This [display] ensures that
|
||||
// the view is properly drawn before the next Scroll call.
|
||||
//
|
||||
// The time this doesn't work is when you're scrolling a page containing
|
||||
// an iframe which in turn contains a plugin.
|
||||
//
|
||||
// This is turned off because it makes scrolling pages with plugins slow.
|
||||
//
|
||||
//if ([mView childViewHasPlugin])
|
||||
// [mView display];
|
||||
|
||||
return NS_OK;
|
||||
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
|
||||
NS_OBJC_END_TRY_ABORT_BLOCK;
|
||||
}
|
||||
|
||||
// Invokes callback and ProcessEvent methods on Event Listener object
|
||||
|
|
|
@ -227,7 +227,8 @@ public:
|
|||
NS_IMETHOD Invalidate(PRBool aIsSynchronous);
|
||||
NS_IMETHOD Update();
|
||||
virtual nsresult ConfigureChildren(const nsTArray<Configuration>& aConfigurations);
|
||||
NS_IMETHOD Scroll(PRInt32 aDx, PRInt32 aDy, nsIntRect *alCipRect) { return NS_OK; }
|
||||
virtual void Scroll(const nsIntPoint& aDelta, const nsIntRect& aSource,
|
||||
const nsTArray<Configuration>& aConfigurations);
|
||||
NS_IMETHOD BeginResizingChildren(void) { return NS_OK; }
|
||||
NS_IMETHOD EndResizingChildren(void) { return NS_OK; }
|
||||
NS_IMETHOD DispatchEvent(nsGUIEvent* event, nsEventStatus & aStatus) ;
|
||||
|
|
|
@ -813,11 +813,20 @@ NS_IMETHODIMP nsCocoaWindow::Show(PRBool bState)
|
|||
nsresult
|
||||
nsCocoaWindow::ConfigureChildren(const nsTArray<Configuration>& aConfigurations)
|
||||
{
|
||||
for (PRUint32 i = 0; i < aConfigurations.Length(); ++i) {
|
||||
nsChildView::ApplyConfiguration(this, aConfigurations[i], PR_TRUE);
|
||||
if (mPopupContentView) {
|
||||
mPopupContentView->ConfigureChildren(aConfigurations);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsCocoaWindow::Scroll(const nsIntPoint& aDelta, const nsIntRect& aSource,
|
||||
const nsTArray<Configuration>& aConfigurations)
|
||||
{
|
||||
if (mPopupContentView) {
|
||||
mPopupContentView->Scroll(aDelta, aSource, aConfigurations);
|
||||
}
|
||||
}
|
||||
|
||||
void nsCocoaWindow::MakeBackgroundTransparent(PRBool aTransparent)
|
||||
{
|
||||
|
|
|
@ -1731,35 +1731,46 @@ nsWindow::Update()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWindow::Scroll(PRInt32 aDx,
|
||||
PRInt32 aDy,
|
||||
nsIntRect *aClipRect)
|
||||
void
|
||||
nsWindow::Scroll(const nsIntPoint& aDelta, const nsIntRect& aSource,
|
||||
const nsTArray<Configuration>& aConfigurations)
|
||||
{
|
||||
if (!mDrawingarea)
|
||||
return NS_OK;
|
||||
|
||||
D_DEBUG_AT( ns_Window, "%s( %4d,%4d )\n", __FUNCTION__, aDx, aDy );
|
||||
|
||||
if (aClipRect) {
|
||||
D_DEBUG_AT( ns_Window, " -> aClipRect: %4d,%4d-%4dx%4d\n",
|
||||
aClipRect->x, aClipRect->y, aClipRect->width, aClipRect->height );
|
||||
if (!mDrawingarea) {
|
||||
NS_ERROR("Cannot scroll widget");
|
||||
return;
|
||||
}
|
||||
|
||||
moz_drawingarea_scroll(mDrawingarea, aDx, aDy);
|
||||
|
||||
// Update bounds on our child windows
|
||||
for (nsIWidget* kid = mFirstChild; kid; kid = kid->GetNextSibling()) {
|
||||
nsIntRect bounds;
|
||||
kid->GetBounds(bounds);
|
||||
bounds.x += aDx;
|
||||
bounds.y += aDy;
|
||||
static_cast<nsBaseWidget*>(kid)->SetBounds(bounds);
|
||||
nsAutoTArray<nsWindow*,1> windowsToShow;
|
||||
// Hide any widgets that are becoming invisible or that are moving.
|
||||
// Moving widgets are hidden for the duration of the scroll so that
|
||||
// the XCopyArea treats their drawn pixels as part of the window
|
||||
// that should be scrolled. This works well when the widgets are
|
||||
// moving because they're being scrolled, which is normally true.
|
||||
for (PRUint32 i = 0; i < aConfigurations.Length(); ++i) {
|
||||
const Configuration& configuration = aConfigurations[i];
|
||||
nsWindow* w = static_cast<nsWindow*>(configuration.mChild);
|
||||
NS_ASSERTION(w->GetParent() == this,
|
||||
"Configured widget is not a child");
|
||||
if (w->mIsShown &&
|
||||
(configuration.mClipRegion.IsEmpty() ||
|
||||
configuration.mBounds != w->mBounds)) {
|
||||
w->NativeShow(PR_FALSE);
|
||||
windowsToShow.AppendElement(w);
|
||||
}
|
||||
}
|
||||
|
||||
// Process all updates so that everything is drawn.
|
||||
gdk_window_process_all_updates();
|
||||
return NS_OK;
|
||||
GdkRectangle gdkSource =
|
||||
{ aSource.x, aSource.y, aSource.width, aSource.height };
|
||||
GdkRegion* region = gdk_region_rectangle(&gdkSource);
|
||||
gdk_window_move_region(GDK_WINDOW(mDrawingarea->inner_window),
|
||||
region, aDelta.x, aDelta.y);
|
||||
gdk_region_destroy(region);
|
||||
|
||||
ConfigureChildren(aConfigurations);
|
||||
|
||||
for (PRUint32 i = 0; i < windowsToShow.Length(); ++i) {
|
||||
windowsToShow[i]->NativeShow(PR_TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
void*
|
||||
|
|
|
@ -187,9 +187,8 @@ public:
|
|||
NS_IMETHOD Invalidate(const nsIntRect &aRect,
|
||||
PRBool aIsSynchronous);
|
||||
NS_IMETHOD Update();
|
||||
NS_IMETHOD Scroll(PRInt32 aDx,
|
||||
PRInt32 aDy,
|
||||
nsIntRect *aClipRect);
|
||||
virtual void Scroll(const nsIntPoint& aDelta, const nsIntRect& aSource,
|
||||
const nsTArray<Configuration>& aReconfigureChildren);
|
||||
virtual void* GetNativeData(PRUint32 aDataType);
|
||||
NS_IMETHOD SetBorderStyle(nsBorderStyle aBorderStyle);
|
||||
NS_IMETHOD SetTitle(const nsAString& aTitle);
|
||||
|
|
|
@ -147,6 +147,8 @@
|
|||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsWidgetsCID.h"
|
||||
#include "nsTHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
||||
#if defined(WINCE)
|
||||
#include "nsWindowCE.h"
|
||||
|
@ -2297,43 +2299,54 @@ NS_IMETHODIMP nsWindow::Update()
|
|||
*
|
||||
**************************************************************/
|
||||
|
||||
// Invalidates a window if it's not one of ours, for example
|
||||
// a window created by a plugin.
|
||||
BOOL CALLBACK nsWindow::InvalidateForeignChildWindows(HWND aWnd, LPARAM aMsg)
|
||||
void
|
||||
nsWindow::Scroll(const nsIntPoint& aDelta, const nsIntRect& aSource,
|
||||
const nsTArray<Configuration>& aConfigurations)
|
||||
{
|
||||
LONG_PTR proc = ::GetWindowLongPtrW(aWnd, GWLP_WNDPROC);
|
||||
if (proc != (LONG_PTR)&nsWindow::WindowProc) {
|
||||
// This window is not one of our windows so invalidate it.
|
||||
VERIFY(::InvalidateRect(aWnd, NULL, FALSE));
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Scroll
|
||||
NS_METHOD nsWindow::Scroll(PRInt32 aDx, PRInt32 aDy, nsIntRect *aClipRect)
|
||||
{
|
||||
RECT trect;
|
||||
|
||||
if (nsnull != aClipRect)
|
||||
{
|
||||
trect.left = aClipRect->x;
|
||||
trect.top = aClipRect->y;
|
||||
trect.right = aClipRect->XMost();
|
||||
trect.bottom = aClipRect->YMost();
|
||||
// We can use SW_SCROLLCHILDREN if all the windows that intersect the
|
||||
// affected area are moving by the scroll amount.
|
||||
// First, build the set of widgets that are to be moved by the scroll
|
||||
// amount.
|
||||
// At the same time, set the clip region of all changed windows to the
|
||||
// intersection of the current and new regions.
|
||||
nsTHashtable<nsPtrHashKey<nsWindow> > scrolledWidgets;
|
||||
scrolledWidgets.Init();
|
||||
for (PRUint32 i = 0; i < aConfigurations.Length(); ++i) {
|
||||
const Configuration& configuration = aConfigurations[i];
|
||||
nsWindow* w = static_cast<nsWindow*>(configuration.mChild);
|
||||
NS_ASSERTION(w->GetParent() == this,
|
||||
"Configured widget is not a child");
|
||||
if (configuration.mBounds == w->mBounds + aDelta) {
|
||||
scrolledWidgets.PutEntry(w);
|
||||
}
|
||||
w->SetWindowClipRegion(configuration.mClipRegion, PR_TRUE);
|
||||
}
|
||||
|
||||
::ScrollWindowEx(mWnd, aDx, aDy, NULL, (nsnull != aClipRect) ? &trect : NULL,
|
||||
NULL, NULL, SW_INVALIDATE | SW_SCROLLCHILDREN);
|
||||
// Invalidate all child windows that aren't ours; we're moving them, and we
|
||||
// expect them to be painted at the new location even if they're outside the
|
||||
// region we're bit-blit scrolling. See bug 387701.
|
||||
#if !defined(WINCE)
|
||||
::EnumChildWindows(GetWindowHandle(), nsWindow::InvalidateForeignChildWindows, NULL);
|
||||
#else
|
||||
nsWindowCE::EnumChildWindows(GetWindowHandle(), nsWindow::InvalidateForeignChildWindows, NULL);
|
||||
#endif
|
||||
::UpdateWindow(mWnd);
|
||||
return NS_OK;
|
||||
// Now check if any of our children would be affected by
|
||||
// SW_SCROLLCHILDREN but not supposed to scroll.
|
||||
nsIntRect affectedRect;
|
||||
affectedRect.UnionRect(aSource, aSource + aDelta);
|
||||
// We pass SW_INVALIDATE because areas that get scrolled into view
|
||||
// from offscreen (but inside the scroll area) need to be repainted.
|
||||
UINT flags = SW_SCROLLCHILDREN | SW_INVALIDATE;
|
||||
for (nsWindow* w = static_cast<nsWindow*>(GetFirstChild()); w;
|
||||
w = static_cast<nsWindow*>(w->GetNextSibling())) {
|
||||
if (w->mBounds.Intersects(affectedRect) &&
|
||||
!scrolledWidgets.GetEntry(w)) {
|
||||
flags &= ~SW_SCROLLCHILDREN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nsIntRect destRect = aSource + aDelta;
|
||||
RECT clip = { affectedRect.x, affectedRect.y, affectedRect.XMost(), affectedRect.YMost() };
|
||||
::ScrollWindowEx(mWnd, aDelta.x, aDelta.y, &clip, &clip, NULL, NULL, flags);
|
||||
|
||||
// Now make sure all children actually get positioned, sized and clipped
|
||||
// correctly. If SW_SCROLLCHILDREN already moved widgets to their correct
|
||||
// locations, then the SetWindowPos calls this triggers will just be
|
||||
// no-ops.
|
||||
ConfigureChildren(aConfigurations);
|
||||
}
|
||||
|
||||
/**************************************************************
|
||||
|
|
|
@ -147,7 +147,8 @@ public:
|
|||
NS_IMETHOD Invalidate(PRBool aIsSynchronous);
|
||||
NS_IMETHOD Invalidate(const nsIntRect & aRect, PRBool aIsSynchronous);
|
||||
NS_IMETHOD Update();
|
||||
NS_IMETHOD Scroll(PRInt32 aDx, PRInt32 aDy, nsIntRect *aClipRect);
|
||||
virtual void Scroll(const nsIntPoint& aDelta, const nsIntRect& aSource,
|
||||
const nsTArray<Configuration>& aReconfigureChildren);
|
||||
virtual void* GetNativeData(PRUint32 aDataType);
|
||||
virtual void FreeNativeData(void * data, PRUint32 aDataType);
|
||||
NS_IMETHOD SetTitle(const nsAString& aTitle);
|
||||
|
@ -246,7 +247,6 @@ protected:
|
|||
static BOOL CALLBACK BroadcastMsgToChildren(HWND aWnd, LPARAM aMsg);
|
||||
static BOOL CALLBACK BroadcastMsg(HWND aTopWindow, LPARAM aMsg);
|
||||
static BOOL CALLBACK DispatchStarvedPaints(HWND aTopWindow, LPARAM aMsg);
|
||||
static BOOL CALLBACK InvalidateForeignChildWindows(HWND aWnd, LPARAM aMsg);
|
||||
static LRESULT CALLBACK MozSpecialMsgFilter(int code, WPARAM wParam, LPARAM lParam);
|
||||
static LRESULT CALLBACK MozSpecialWndProc(int code, WPARAM wParam, LPARAM lParam);
|
||||
static LRESULT CALLBACK MozSpecialMouseProc(int code, WPARAM wParam, LPARAM lParam);
|
||||
|
|
Загрузка…
Ссылка в новой задаче