diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 058ef3444aa..65a1f677ef1 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -7488,7 +7488,7 @@ PresShell::DoReflow(nsIFrame* target, bool aInterruptible) target->GetView(), boundsRelativeToTarget); nsContainerFrame::SyncWindowProperties(mPresContext, target, - target->GetView()); + target->GetView(), rcx); target->DidReflow(mPresContext, nullptr, NS_FRAME_REFLOW_FINISHED); if (target == rootFrame && size.height == NS_UNCONSTRAINEDSIZE) { diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp index d5e581494d4..ebd0dd4a51f 100644 --- a/layout/generic/nsContainerFrame.cpp +++ b/layout/generic/nsContainerFrame.cpp @@ -34,6 +34,8 @@ #include "nsListControlFrame.h" #include "nsIBaseWindow.h" #include "nsThemeConstants.h" +#include "nsBoxLayoutState.h" +#include "nsRenderingContext.h" #include "nsCSSFrameConstructor.h" #include "mozilla/dom/Element.h" @@ -632,7 +634,8 @@ IsTopLevelWidget(nsIWidget* aWidget) void nsContainerFrame::SyncWindowProperties(nsPresContext* aPresContext, nsIFrame* aFrame, - nsIView* aView) + nsIView* aView, + nsRenderingContext* aRC) { #ifdef MOZ_XUL if (!aView || !nsCSSRendering::IsCanvasFrame(aFrame) || !aView->HasWidget()) @@ -676,9 +679,47 @@ nsContainerFrame::SyncWindowProperties(nsPresContext* aPresContext, nsIWidget* viewWidget = aView->GetWidget(); viewWidget->SetTransparencyMode(mode); windowWidget->SetWindowShadowStyle(rootFrame->GetStyleUIReset()->mWindowShadow); + + if (!aRC) + return; + + nsBoxLayoutState aState(aPresContext, aRC); + nsSize minSize = rootFrame->GetMinSize(aState); + nsSize maxSize = rootFrame->GetMaxSize(aState); + + SetSizeConstraints(aPresContext, windowWidget, minSize, maxSize); #endif } +void nsContainerFrame::SetSizeConstraints(nsPresContext* aPresContext, + nsIWidget* aWidget, + const nsSize& aMinSize, + const nsSize& aMaxSize) +{ + nsIntSize devMinSize(aPresContext->AppUnitsToDevPixels(aMinSize.width), + aPresContext->AppUnitsToDevPixels(aMinSize.height)); + nsIntSize devMaxSize(aMaxSize.width == NS_INTRINSICSIZE ? NS_MAXSIZE : + aPresContext->AppUnitsToDevPixels(aMaxSize.width), + aMaxSize.height == NS_INTRINSICSIZE ? NS_MAXSIZE : + aPresContext->AppUnitsToDevPixels(aMaxSize.height)); + widget::SizeConstraints constraints(devMinSize, devMaxSize); + + // The sizes are in inner window sizes, so convert them into outer window sizes. + // Use a size of (200, 200) as only the difference between the inner and outer + // size is needed. + nsIntSize windowSize = aWidget->ClientToWindowSize(nsIntSize(200, 200)); + if (constraints.mMinSize.width) + constraints.mMinSize.width += windowSize.width - 200; + if (constraints.mMinSize.height) + constraints.mMinSize.height += windowSize.height - 200; + if (constraints.mMaxSize.width != NS_MAXSIZE) + constraints.mMaxSize.width += windowSize.width - 200; + if (constraints.mMaxSize.height != NS_MAXSIZE) + constraints.mMaxSize.height += windowSize.height - 200; + + aWidget->SetSizeConstraints(constraints); +} + void nsContainerFrame::SyncFrameViewAfterReflow(nsPresContext* aPresContext, nsIFrame* aFrame, diff --git a/layout/generic/nsContainerFrame.h b/layout/generic/nsContainerFrame.h index 96f996c81de..b1473f21f34 100644 --- a/layout/generic/nsContainerFrame.h +++ b/layout/generic/nsContainerFrame.h @@ -141,7 +141,8 @@ public: // shadow. static void SyncWindowProperties(nsPresContext* aPresContext, nsIFrame* aFrame, - nsIView* aView); + nsIView* aView, + nsRenderingContext* aRC = nullptr); // Sets the view's attributes from the frame style. // - visibility @@ -155,6 +156,20 @@ public: nsIView* aView, PRUint32 aFlags = 0); + /** + * Converts the minimum and maximum sizes given in inner window app units to + * outer window device pixel sizes and assigns these constraints to the widget. + * + * @param aPresContext pres context + * @param aWidget widget for this frame + * @param minimum size of the window in app units + * @param maxmimum size of the window in app units + */ + static void SetSizeConstraints(nsPresContext* aPresContext, + nsIWidget* aWidget, + const nsSize& aMinSize, + const nsSize& aMaxSize); + // Used by both nsInlineFrame and nsFirstLetterFrame. void DoInlineIntrinsicWidth(nsRenderingContext *aRenderingContext, InlineIntrinsicWidthData *aData, diff --git a/layout/xul/base/src/nsMenuPopupFrame.cpp b/layout/xul/base/src/nsMenuPopupFrame.cpp index b052908cff8..4271875f161 100644 --- a/layout/xul/base/src/nsMenuPopupFrame.cpp +++ b/layout/xul/base/src/nsMenuPopupFrame.cpp @@ -450,6 +450,14 @@ nsMenuPopupFrame::LayoutPopup(nsBoxLayoutState& aState, nsIFrame* aParentMenu, b nsRect rect = GetRect(); rect.x = rect.y = 0; + if (sizeChanged) { + // If the size of the popup changed, apply any size constraints. + nsIWidget* widget = view->GetWidget(); + if (widget) { + SetSizeConstraints(pc, widget, minSize, maxSize); + } + } + viewManager->ResizeView(view, rect); viewManager->SetViewVisibility(view, nsViewVisibility_kShow); diff --git a/layout/xul/base/src/nsResizerFrame.cpp b/layout/xul/base/src/nsResizerFrame.cpp index aaf9dac60db..6d2647d7abe 100644 --- a/layout/xul/base/src/nsResizerFrame.cpp +++ b/layout/xul/base/src/nsResizerFrame.cpp @@ -29,6 +29,7 @@ #include "mozilla/dom/Element.h" #include "nsContentErrors.h" +using namespace mozilla; // // NS_NewResizerFrame @@ -186,8 +187,19 @@ nsResizerFrame::HandleEvent(nsPresContext* aPresContext, } nsIntRect rect = mMouseDownRect; - AdjustDimensions(&rect.x, &rect.width, mouseMove.x, direction.mHorizontal); - AdjustDimensions(&rect.y, &rect.height, mouseMove.y, direction.mVertical); + + // Check if there are any size constraints on this window. + widget::SizeConstraints sizeConstraints; + if (window) { + nsCOMPtr widget; + window->GetMainWidget(getter_AddRefs(widget)); + sizeConstraints = widget->GetSizeConstraints(); + } + + AdjustDimensions(&rect.x, &rect.width, sizeConstraints.mMinSize.width, + sizeConstraints.mMaxSize.width, mouseMove.x, direction.mHorizontal); + AdjustDimensions(&rect.y, &rect.height, sizeConstraints.mMinSize.height, + sizeConstraints.mMaxSize.height, mouseMove.y, direction.mVertical); // Don't allow resizing a window or a popup past the edge of the screen, // so adjust the rectangle to fit within the available screen area. @@ -249,6 +261,10 @@ nsResizerFrame::HandleEvent(nsPresContext* aPresContext, ResizeContent(contentToResize, direction, sizeInfo, &originalSizeInfo); MaybePersistOriginalSize(contentToResize, originalSizeInfo); + // Move the popup to the new location unless it is anchored, since + // the position shouldn't change. nsMenuPopupFrame::SetPopupPosition + // will instead ensure that the popup's position is anchored at the + // right place. if (weakFrame.IsAlive() && (oldRect.x != rect.x || oldRect.y != rect.y) && (!menuPopupFrame->IsAnchored() || @@ -365,25 +381,25 @@ nsResizerFrame::GetContentToResize(nsIPresShell* aPresShell, nsIBaseWindow** aWi return aPresShell->GetDocument()->GetElementById(elementid); } -/* adjust the window position and size according to the mouse movement and - * the resizer direction - */ void nsResizerFrame::AdjustDimensions(PRInt32* aPos, PRInt32* aSize, + PRInt32 aMinSize, PRInt32 aMaxSize, PRInt32 aMovement, PRInt8 aResizerDirection) { - switch(aResizerDirection) - { - case -1: - // only move the window when the direction is top and/or left - *aPos+= aMovement; - // falling through: the window is resized in both cases - case 1: - *aSize+= aResizerDirection*aMovement; - // use one as a minimum size or the element could disappear - if (*aSize < 1) - *aSize = 1; - } + PRInt32 oldSize = *aSize; + + *aSize += aResizerDirection * aMovement; + // use one as a minimum size or the element could disappear + if (*aSize < 1) + *aSize = 1; + + // Constrain the size within the minimum and maximum size. + *aSize = NS_MAX(aMinSize, NS_MIN(aMaxSize, *aSize)); + + // For left and top resizers, the window must be moved left by the same + // amount that the window was resized. + if (aResizerDirection == -1) + *aPos += oldSize - *aSize; } /* static */ void diff --git a/layout/xul/base/src/nsResizerFrame.h b/layout/xul/base/src/nsResizerFrame.h index 330713b0a5b..ef5f0772d64 100644 --- a/layout/xul/base/src/nsResizerFrame.h +++ b/layout/xul/base/src/nsResizerFrame.h @@ -35,8 +35,22 @@ protected: nsIContent* GetContentToResize(nsIPresShell* aPresShell, nsIBaseWindow** aWindow); Direction GetDirection(); + + /** + * Adjust the window position and size in a direction according to the mouse + * movement and the resizer direction. The minimum and maximum size is used + * to constrain the size. + * + * @param aPos left or top position + * @param aSize width or height + * @param aMinSize minimum width or height + * @param aMacSize maximum width or height + * @param aMovement the amount the mouse was moved + * @param aResizerDirection resizer direction returned by GetDirection + */ static void AdjustDimensions(PRInt32* aPos, PRInt32* aSize, - PRInt32 aMovement, PRInt8 aResizerDirection); + PRInt32 aMinSize, PRInt32 aMaxSize, + PRInt32 aMovement, PRInt8 aResizerDirection); struct SizeInfo { nsString width, height; diff --git a/widget/cocoa/nsCocoaWindow.h b/widget/cocoa/nsCocoaWindow.h index b6baaa66019..6b71d71e052 100644 --- a/widget/cocoa/nsCocoaWindow.h +++ b/widget/cocoa/nsCocoaWindow.h @@ -224,6 +224,7 @@ public: NS_IMETHOD ConstrainPosition(bool aAllowSlop, PRInt32 *aX, PRInt32 *aY); + virtual void SetSizeConstraints(const SizeConstraints& aConstraints); NS_IMETHOD Move(PRInt32 aX, PRInt32 aY); NS_IMETHOD PlaceBehind(nsTopLevelWidgetZPlacement aPlacement, nsIWidget *aWidget, bool aActivate); diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm index ac40789e817..8b74f8d448a 100644 --- a/widget/cocoa/nsCocoaWindow.mm +++ b/widget/cocoa/nsCocoaWindow.mm @@ -1072,6 +1072,32 @@ NS_IMETHODIMP nsCocoaWindow::ConstrainPosition(bool aAllowSlop, return NS_OK; } +void nsCocoaWindow::SetSizeConstraints(const SizeConstraints& aConstraints) +{ + NS_OBJC_BEGIN_TRY_ABORT_BLOCK; + + // Popups can be smaller than (60, 60) + NSRect rect = + (mWindowType == eWindowType_popup) ? NSZeroRect : NSMakeRect(0.0, 0.0, 60, 60); + rect = [mWindow frameRectForContentRect:rect]; + + SizeConstraints c = aConstraints; + c.mMinSize.width = NS_MAX(PRInt32(rect.size.width), c.mMinSize.width); + c.mMinSize.height = NS_MAX(PRInt32(rect.size.height), c.mMinSize.height); + + NSSize minSize = { static_cast(c.mMinSize.width), + static_cast(c.mMinSize.height) }; + [mWindow setMinSize:minSize]; + + NSSize maxSize = { c.mMaxSize.width == NS_MAXSIZE ? FLT_MAX : c.mMaxSize.width, + c.mMaxSize.height == NS_MAXSIZE ? FLT_MAX : c.mMaxSize.height }; + [mWindow setMaxSize:maxSize]; + + nsBaseWidget::SetSizeConstraints(c); + + NS_OBJC_END_TRY_ABORT_BLOCK; +} + NS_IMETHODIMP nsCocoaWindow::Move(PRInt32 aX, PRInt32 aY) { if (!mWindow || (mBounds.x == aX && mBounds.y == aY)) @@ -1250,6 +1276,8 @@ NS_IMETHODIMP nsCocoaWindow::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRIn { NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT; + ConstrainSize(&aWidth, &aHeight); + nsIntRect newBounds = nsIntRect(aX, aY, aWidth, aHeight); FitRectToVisibleAreaForScreen(newBounds, [mWindow screen]); @@ -1617,11 +1645,6 @@ nsIntSize nsCocoaWindow::ClientToWindowSize(const nsIntSize& aClientSize) if (!mWindow) return nsIntSize(0, 0); - // this is only called for popups currently. If needed, expand this to support - // other types of windows - if (!IsPopupWithTitleBar()) - return aClientSize; - NSRect rect(NSMakeRect(0.0, 0.0, aClientSize.width, aClientSize.height)); NSRect inflatedRect = [mWindow frameRectForContentRect:rect]; diff --git a/widget/gtk2/nsWindow.cpp b/widget/gtk2/nsWindow.cpp index 7fbf461bb2a..722cef4eadb 100644 --- a/widget/gtk2/nsWindow.cpp +++ b/widget/gtk2/nsWindow.cpp @@ -944,6 +944,23 @@ nsWindow::ConstrainPosition(bool aAllowSlop, PRInt32 *aX, PRInt32 *aY) return NS_OK; } +void nsWindow::SetSizeConstraints(const SizeConstraints& aConstraints) +{ + if (mShell) { + GdkGeometry geometry; + geometry.min_width = aConstraints.mMinSize.width; + geometry.min_height = aConstraints.mMinSize.height; + geometry.max_width = aConstraints.mMaxSize.width; + geometry.max_height = aConstraints.mMaxSize.height; + + PRUint32 hints = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE; + gtk_window_set_geometry_hints(GTK_WINDOW(mShell), nullptr, + &geometry, GdkWindowHints(hints)); + } + + nsBaseWidget::SetSizeConstraints(aConstraints); +} + NS_IMETHODIMP nsWindow::Show(bool aState) { @@ -1002,6 +1019,8 @@ nsWindow::Show(bool aState) NS_IMETHODIMP nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, bool aRepaint) { + ConstrainSize(&aWidth, &aHeight); + // For top-level windows, aWidth and aHeight should possibly be // interpreted as frame bounds, but NativeResize treats these as window // bounds (Bug 581866). @@ -1079,6 +1098,8 @@ NS_IMETHODIMP nsWindow::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, bool aRepaint) { + ConstrainSize(&aWidth, &aHeight); + mBounds.x = aX; mBounds.y = aY; mBounds.SizeTo(GetSafeWindowSize(nsIntSize(aWidth, aHeight))); diff --git a/widget/gtk2/nsWindow.h b/widget/gtk2/nsWindow.h index da4e95eea5d..c0119b0255d 100644 --- a/widget/gtk2/nsWindow.h +++ b/widget/gtk2/nsWindow.h @@ -111,6 +111,7 @@ public: NS_IMETHOD ConstrainPosition(bool aAllowSlop, PRInt32 *aX, PRInt32 *aY); + virtual void SetSizeConstraints(const SizeConstraints& aConstraints); NS_IMETHOD Move(PRInt32 aX, PRInt32 aY); NS_IMETHOD Show (bool aState); diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h index c3b42809379..e03aaca8746 100644 --- a/widget/nsIWidget.h +++ b/widget/nsIWidget.h @@ -163,7 +163,6 @@ enum nsTopLevelWidgetZPlacement { // for PlaceBehind() eZPlacementTop // top of the window stack }; - /** * Preference for receiving IME updates * @@ -351,6 +350,27 @@ struct InputContextAction { } }; +/** + * Size constraints for setting the minimum and maximum size of a widget. + * Values are in device pixels. + */ +struct SizeConstraints { + SizeConstraints() + : mMaxSize(NS_MAXSIZE, NS_MAXSIZE) + { + } + + SizeConstraints(nsIntSize aMinSize, + nsIntSize aMaxSize) + : mMinSize(aMinSize), + mMaxSize(aMaxSize) + { + } + + nsIntSize mMinSize; + nsIntSize mMaxSize; +}; + } // namespace widget } // namespace mozilla @@ -369,6 +389,7 @@ class nsIWidget : public nsISupports { typedef mozilla::widget::IMEState IMEState; typedef mozilla::widget::InputContext InputContext; typedef mozilla::widget::InputContextAction InputContextAction; + typedef mozilla::widget::SizeConstraints SizeConstraints; // Used in UpdateThemeGeometries. struct ThemeGeometry { @@ -658,7 +679,8 @@ class nsIWidget : public nsISupports { NS_IMETHOD MoveClient(PRInt32 aX, PRInt32 aY) = 0; /** - * Resize this widget. + * Resize this widget. Any size constraints set for the window by a + * previous call to SetSizeConstraints will be applied. * * @param aWidth the new width expressed in the parent's coordinate system * @param aHeight the new height expressed in the parent's coordinate system @@ -670,7 +692,8 @@ class nsIWidget : public nsISupports { bool aRepaint) = 0; /** - * Move or resize this widget. + * Move or resize this widget. Any size constraints set for the window by + * a previous call to SetSizeConstraints will be applied. * * @param aX the new x position expressed in the parent's coordinate system * @param aY the new y position expressed in the parent's coordinate system @@ -1588,6 +1611,26 @@ class nsIWidget : public nsISupports { return bounds; } + /** + * Set size constraints on the window size such that it is never less than + * the specified minimum size and never larger than the specified maximum + * size. The size constraints are sizes of the outer rectangle including + * the window frame and title bar. Use 0 for an unconstrained minimum size + * and NS_MAXSIZE for an unconstrained maximum size. Note that this method + * does not necessarily change the size of a window to conform to this size, + * thus Resize should be called afterwards. + * + * @param aConstraints: the size constraints in device pixels + */ + virtual void SetSizeConstraints(const SizeConstraints& aConstraints) = 0; + + /** + * Return the size constraints currently observed by the widget. + * + * @return the constraints in device pixels + */ + virtual const SizeConstraints& GetSizeConstraints() const = 0; + protected: // keep the list of children. We also keep track of our siblings. diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index 0417e29bc55..cd1cb5dfb25 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -1286,6 +1286,18 @@ BOOL CALLBACK nsWindow::UnregisterTouchForDescendants(HWND aWnd, LPARAM aMsg) { * **************************************************************/ +void +nsWindow::SetSizeConstraints(const SizeConstraints& aConstraints) +{ + SizeConstraints c = aConstraints; + if (mWindowType != eWindowType_popup) { + c.mMinSize.width = NS_MAX(PRInt32(::GetSystemMetrics(SM_CXMINTRACK)), c.mMinSize.width); + c.mMinSize.height = NS_MAX(PRInt32(::GetSystemMetrics(SM_CYMINTRACK)), c.mMinSize.height); + } + + nsBaseWidget::SetSizeConstraints(c); +} + // Move this component NS_METHOD nsWindow::Move(PRInt32 aX, PRInt32 aY) { @@ -1356,6 +1368,7 @@ NS_METHOD nsWindow::Resize(PRInt32 aWidth, PRInt32 aHeight, bool aRepaint) { NS_ASSERTION((aWidth >=0 ) , "Negative width passed to nsWindow::Resize"); NS_ASSERTION((aHeight >=0 ), "Negative height passed to nsWindow::Resize"); + ConstrainSize(&aWidth, &aHeight); // Avoid unnecessary resizing calls if (mBounds.width == aWidth && mBounds.height == aHeight && !aRepaint) @@ -1394,6 +1407,7 @@ NS_METHOD nsWindow::Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeig { NS_ASSERTION((aWidth >=0 ), "Negative width passed to nsWindow::Resize"); NS_ASSERTION((aHeight >=0 ), "Negative height passed to nsWindow::Resize"); + ConstrainSize(&aWidth, &aHeight); // Avoid unnecessary resizing calls if (mBounds.x == aX && mBounds.y == aY && @@ -2883,7 +2897,7 @@ nsIntPoint nsWindow::WidgetToScreenOffset() nsIntSize nsWindow::ClientToWindowSize(const nsIntSize& aClientSize) { - if (!IsPopupWithTitleBar()) + if (mWindowType == eWindowType_popup && !IsPopupWithTitleBar()) return aClientSize; // just use (200, 200) as the position @@ -5063,6 +5077,22 @@ bool nsWindow::ProcessMessage(UINT msg, WPARAM &wParam, LPARAM &lParam, } break; + case WM_GETMINMAXINFO: + { + MINMAXINFO* mmi = (MINMAXINFO*)lParam; + // Set the constraints. The minimum size should also be constrained to the + // default window maximum size so that it fits on screen. + mmi->ptMinTrackSize.x = + NS_MIN((PRInt32)mmi->ptMaxTrackSize.x, + NS_MAX((PRInt32)mmi->ptMinTrackSize.x, mSizeConstraints.mMinSize.width)); + mmi->ptMinTrackSize.y = + NS_MIN((PRInt32)mmi->ptMaxTrackSize.y, + NS_MAX((PRInt32)mmi->ptMinTrackSize.y, mSizeConstraints.mMinSize.height)); + mmi->ptMaxTrackSize.x = NS_MIN((PRInt32)mmi->ptMaxTrackSize.x, mSizeConstraints.mMaxSize.width); + mmi->ptMaxTrackSize.y = NS_MIN((PRInt32)mmi->ptMaxTrackSize.y, mSizeConstraints.mMaxSize.height); + } + break; + case WM_SETFOCUS: // If previous focused window isn't ours, it must have received the // redirected message. So, we should forget it. diff --git a/widget/windows/nsWindow.h b/widget/windows/nsWindow.h index 83be8537d3d..5db78226954 100644 --- a/widget/windows/nsWindow.h +++ b/widget/windows/nsWindow.h @@ -94,6 +94,7 @@ public: NS_IMETHOD Show(bool bState); virtual bool IsVisible() const; NS_IMETHOD ConstrainPosition(bool aAllowSlop, PRInt32 *aX, PRInt32 *aY); + virtual void SetSizeConstraints(const SizeConstraints& aConstraints); NS_IMETHOD Move(PRInt32 aX, PRInt32 aY); NS_IMETHOD Resize(PRInt32 aWidth, PRInt32 aHeight, bool aRepaint); NS_IMETHOD Resize(PRInt32 aX, PRInt32 aY, PRInt32 aWidth, PRInt32 aHeight, bool aRepaint); diff --git a/widget/xpwidgets/nsBaseWidget.cpp b/widget/xpwidgets/nsBaseWidget.cpp index e2c6db93521..0038727b360 100644 --- a/widget/xpwidgets/nsBaseWidget.cpp +++ b/widget/xpwidgets/nsBaseWidget.cpp @@ -1323,6 +1323,18 @@ nsBaseWidget::GetGLFrameBufferFormat() return LOCAL_GL_NONE; } +void nsBaseWidget::SetSizeConstraints(const SizeConstraints& aConstraints) +{ + mSizeConstraints = aConstraints; + // We can't ensure that the size is honored at this point because we're + // probably in the middle of a reflow. +} + +const widget::SizeConstraints& nsBaseWidget::GetSizeConstraints() const +{ + return mSizeConstraints; +} + #ifdef DEBUG ////////////////////////////////////////////////////////////// // diff --git a/widget/xpwidgets/nsBaseWidget.h b/widget/xpwidgets/nsBaseWidget.h index 8c17a3b0544..76c40a6f177 100644 --- a/widget/xpwidgets/nsBaseWidget.h +++ b/widget/xpwidgets/nsBaseWidget.h @@ -179,6 +179,9 @@ public: virtual PRUint32 GetGLFrameBufferFormat() MOZ_OVERRIDE; + virtual const SizeConstraints& GetSizeConstraints() const; + virtual void SetSizeConstraints(const SizeConstraints& aConstraints); + /** * Use this when GetLayerManager() returns a BasicLayerManager * (nsBaseWidget::GetLayerManager() does). This sets up the widget's @@ -283,6 +286,20 @@ protected: } } + /** + * Apply the current size constraints to the given size. + * + * @param aWidth width to constrain + * @param aHeight height to constrain + */ + void ConstrainSize(PRInt32* aWidth, PRInt32* aHeight) const + { + *aWidth = NS_MAX(mSizeConstraints.mMinSize.width, + NS_MIN(mSizeConstraints.mMaxSize.width, *aWidth)); + *aHeight = NS_MAX(mSizeConstraints.mMinSize.height, + NS_MIN(mSizeConstraints.mMaxSize.height, *aHeight)); + } + protected: /** * Starts the OMTC compositor destruction sequence. @@ -322,6 +339,7 @@ protected: nsSizeMode mSizeMode; nsPopupLevel mPopupLevel; nsPopupType mPopupType; + SizeConstraints mSizeConstraints; // the last rolled up popup. Only set this when an nsAutoRollup is in scope, // so it can be cleared automatically.