author | Neil Deakin <neil@mozilla.com> |
Mon, 17 Jan 2011 09:35:32 -0500 | |
changeset 60693 | 70f1fbe19abb1196bba45b335e2a35fbe512e7bb |
parent 60692 | 48e1cb943266114c9e943dc756f1a8d7c0641d4e |
child 60694 | b27366868c807e07a11741a7a2eb404ebc08e5e7 |
push id | unknown |
push user | unknown |
push date | unknown |
reviewers | roc, gavin, blocking |
bugs | 489303 |
milestone | 2.0b10pre |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/accessible/tests/mochitest/events/test_scroll.xul +++ b/accessible/tests/mochitest/events/test_scroll.xul @@ -123,11 +123,12 @@ setfocus="false"> <tab class="tabbrowser-tab" selected="true"/> </tabs> <tabbrowser id="tabBrowser" type="content-primary" tabcontainer="tabbrowser-tabs" flex="1"/> </vbox> + <toolbar id="addon-bar"/> </hbox> </window>
--- a/accessible/tests/mochitest/relations/test_tabbrowser.xul +++ b/accessible/tests/mochitest/relations/test_tabbrowser.xul @@ -115,12 +115,13 @@ tabbrowser="tabbrowser" setfocus="false"> <tab class="tabbrowser-tab" selected="true"/> </tabs> <tabbrowser id="tabbrowser" type="content-primary" tabcontainer="tabbrowser-tabs" flex="1"/> + <toolbar id="addon-bar"/> </vbox> </window>
--- a/accessible/tests/mochitest/tree/test_tabbrowser.xul +++ b/accessible/tests/mochitest/tree/test_tabbrowser.xul @@ -149,12 +149,13 @@ tabbrowser="tabbrowser" setfocus="false"> <tab class="tabbrowser-tab" selected="true" fadein="true"/> </tabs> <tabbrowser id="tabbrowser" type="content-primary" tabcontainer="tabbrowser-tabs" flex="1"/> + <toolbar id="addon-bar"/> </vbox> </window>
--- a/browser/base/content/browser.css +++ b/browser/base/content/browser.css @@ -501,15 +501,15 @@ window[chromehidden~="toolbar"] toolbar: /* override hidden="true" for the status bar compatibility shim in case it was persisted for the real status bar */ #status-bar { display: -moz-box; } /* Remove the resizer from the statusbar compatibility shim */ -#status-bar > .statusbar-resizerpanel { +#status-bar[hideresizer] > .statusbar-resizerpanel { display: none; } browser[tabmodalPromptShowing] { -moz-user-focus: none !important; }
--- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -1259,16 +1259,19 @@ function BrowserStartup() { // border. Use 28px as a guess (titlebar + bottom window border) defaultHeight -= 28; #endif } document.documentElement.setAttribute("width", defaultWidth); document.documentElement.setAttribute("height", defaultHeight); } + if (!gShowPageResizers) + document.getElementById("status-bar").setAttribute("hideresizer", "true"); + if (!window.toolbar.visible) { // adjust browser UI for popups if (gURLBar) { gURLBar.setAttribute("readonly", "true"); gURLBar.setAttribute("enablehistory", "false"); } goSetCommandEnabled("Browser:OpenLocation", false); goSetCommandEnabled("cmd_newNavigatorTab", false); @@ -2771,34 +2774,37 @@ var PrintPreviewListener = { var notificationBox = gBrowser.getNotificationBox(); this._chromeState.notificationsOpen = !notificationBox.notificationsHidden; notificationBox.notificationsHidden = true; document.getElementById("sidebar").setAttribute("src", "about:blank"); var addonBar = document.getElementById("addon-bar"); this._chromeState.addonBarOpen = !addonBar.collapsed; addonBar.collapsed = true; + gBrowser.updateWindowResizers(); this._chromeState.findOpen = gFindBarInitialized && !gFindBar.hidden; if (gFindBarInitialized) gFindBar.close(); this._chromeState.syncNotificationsOpen = false; var syncNotifications = document.getElementById("sync-notifications"); if (syncNotifications) { this._chromeState.syncNotificationsOpen = !syncNotifications.notificationsHidden; syncNotifications.notificationsHidden = true; } }, _showChrome: function () { if (this._chromeState.notificationsOpen) gBrowser.getNotificationBox().notificationsHidden = false; - if (this._chromeState.addonBarOpen) + if (this._chromeState.addonBarOpen) { document.getElementById("addon-bar").collapsed = false; + gBrowser.updateWindowResizers(); + } if (this._chromeState.findOpen) gFindBar.open(); if (this._chromeState.syncNotificationsOpen) document.getElementById("sync-notifications").notificationsHidden = false; } } @@ -4762,16 +4768,17 @@ function setToolbarVisibility(toolbar, i var hidingAttribute = toolbar.getAttribute("type") == "menubar" ? "autohide" : "collapsed"; toolbar.setAttribute(hidingAttribute, !isVisible); document.persist(toolbar.id, hidingAttribute); PlacesToolbarHelper.init(); BookmarksMenuButton.updatePosition(); + gBrowser.updateWindowResizers(); #ifdef MENUBAR_CAN_AUTOHIDE updateAppButtonDisplay(); #endif } var TabsOnTop = { toggle: function () { @@ -8324,8 +8331,20 @@ let AddonsMgrListener = { onUninstalling: function(aAddon) { this.lastAddonBarCount = this.getAddonBarItemCount(); }, onUninstalled: function(aAddon) { if (this.lastAddonBarCount > 0 && this.getAddonBarItemCount() == 0) setToolbarVisibility(this.addonBar, false); } }; + +XPCOMUtils.defineLazyGetter(window, "gShowPageResizers", function () { +#ifdef XP_WIN + // Only show resizers on Windows 2000 and XP + let sysInfo = Components.classes["@mozilla.org/system-info;1"] + .getService(Components.interfaces.nsIPropertyBag2); + return parseFloat(sysInfo.getProperty("version")) < 6; +#else + return false; +#endif +}); +
--- a/browser/base/content/tabbrowser.xml +++ b/browser/base/content/tabbrowser.xml @@ -172,16 +172,28 @@ for (var i = 0; i < this.tabs.length; i++) { if (!this.tabs[i].pinned) break; } return i; ]]></getter> </property> + <method name="updateWindowResizers"> + <body><![CDATA[ + if (!window.gShowPageResizers) + return; + + var show = document.getElementById("addon-bar").collapsed; + for (let i = 0; i < this.browsers.length; i++) { + this.browsers[i].showWindowResizer = show; + } + ]]></body> + </method> + <method name="pinTab"> <parameter name="aTab"/> <body><![CDATA[ if (aTab.pinned) return; if (aTab.hidden) this.showTab(aTab); @@ -1231,16 +1243,21 @@ var b = document.createElementNS( "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "browser"); b.setAttribute("type", "content-targetable"); b.setAttribute("message", "true"); b.setAttribute("contextmenu", this.getAttribute("contentcontextmenu")); b.setAttribute("tooltip", this.getAttribute("contenttooltip")); + + if (window.gShowPageResizers && document.getElementById("addon-bar").collapsed) { + b.setAttribute("showresizer", "true"); + } + if (this.hasAttribute("autocompletepopup")) b.setAttribute("autocompletepopup", this.getAttribute("autocompletepopup")); b.setAttribute("autoscrollpopup", this._autoScrollPopup.id); // Create the browserStack container var stack = document.createElementNS( "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "stack"); @@ -2424,16 +2441,17 @@ this.mCurrentTab.linkedBrowser = this.mCurrentBrowser; // set up the shared autoscroll popup this._autoScrollPopup = this.mCurrentBrowser._createAutoScrollPopup(); this._autoScrollPopup.id = "autoscroller"; this.appendChild(this._autoScrollPopup); this.mCurrentBrowser.setAttribute("autoscrollpopup", this._autoScrollPopup.id); this.mCurrentBrowser.droppedLinkHandler = handleDroppedLink; + this.updateWindowResizers(); ]]> </constructor> <destructor> <![CDATA[ for (var i = 0; i < this.mTabListeners.length; ++i) { let browser = this.getBrowserAtIndex(i); if (browser.registeredOpenURI) {
--- a/content/base/src/nsGkAtomList.h +++ b/content/base/src/nsGkAtomList.h @@ -881,16 +881,17 @@ GK_ATOM(selectedIndex, "selectedIndex") GK_ATOM(selectedindex, "selectedindex") GK_ATOM(self, "self") GK_ATOM(seltype, "seltype") GK_ATOM(setcookie, "set-cookie") GK_ATOM(setter, "setter") GK_ATOM(shape, "shape") GK_ATOM(show, "show") GK_ATOM(showcaret, "showcaret") +GK_ATOM(showresizer, "showresizer") GK_ATOM(simple, "simple") GK_ATOM(single, "single") GK_ATOM(size, "size") GK_ATOM(sizemode, "sizemode") GK_ATOM(sizetopopup, "sizetopopup") GK_ATOM(slider, "slider") GK_ATOM(small, "small") GK_ATOM(smooth, "smooth")
--- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -779,16 +779,37 @@ nsHTMLScrollFrame::GetPadding(nsMargin& PRBool nsHTMLScrollFrame::IsCollapsed(nsBoxLayoutState& aBoxLayoutState) { // We're never collapsed in the box sense. return PR_FALSE; } +// Return the <browser> if the scrollframe is for the root frame directly +// inside a <browser>. +static nsIContent* +GetBrowserRoot(nsIContent* aContent) +{ + if (aContent) { + nsIDocument* doc = aContent->GetCurrentDoc(); + nsPIDOMWindow* win = doc->GetWindow(); + if (win) { + nsCOMPtr<nsIContent> frameContent = + do_QueryInterface(win->GetFrameElementInternal()); + if (frameContent && + frameContent->NodeInfo()->Equals(nsGkAtoms::browser, kNameSpaceID_XUL)) + return frameContent; + } + } + + return nsnull; +} + + NS_IMETHODIMP nsHTMLScrollFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { DO_GLOBAL_REFLOW_COUNT("nsHTMLScrollFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); @@ -808,21 +829,33 @@ nsHTMLScrollFrame::Reflow(nsPresContext* PRBool reflowScrollCorner = PR_TRUE; if (!aReflowState.ShouldReflowAllKids()) { #define NEEDS_REFLOW(frame_) \ ((frame_) && NS_SUBTREE_DIRTY(frame_)) reflowContents = NEEDS_REFLOW(mInner.mScrolledFrame); reflowHScrollbar = NEEDS_REFLOW(mInner.mHScrollbarBox); reflowVScrollbar = NEEDS_REFLOW(mInner.mVScrollbarBox); - reflowScrollCorner = NEEDS_REFLOW(mInner.mScrollCornerBox); + reflowScrollCorner = NEEDS_REFLOW(mInner.mScrollCornerBox) || + NEEDS_REFLOW(mInner.mResizerBox); #undef NEEDS_REFLOW } + if (mInner.mIsRoot) { + mInner.mCollapsedResizer = PR_TRUE; + + nsIContent* browserRoot = GetBrowserRoot(mContent); + if (browserRoot) { + PRBool showResizer = browserRoot->HasAttr(kNameSpaceID_None, nsGkAtoms::showresizer); + reflowScrollCorner = showResizer == mInner.mCollapsedResizer; + mInner.mCollapsedResizer = !showResizer; + } + } + nsRect oldScrollAreaBounds = mInner.mScrollPort; nsRect oldScrolledAreaBounds = mInner.mScrolledFrame->GetScrollableOverflowRectRelativeToParent(); // Adjust to a multiple of device pixels to restore the invariant that // oldScrollPosition is a multiple of device pixels. This could have been // thrown out by a zoom change. nsIntPoint ptDevPx; nsPoint oldScrollPosition = mInner.GetScrollPosition(); @@ -1320,16 +1353,17 @@ static ScrollFrameActivityTracker *gScro nsGfxScrollFrameInner::nsGfxScrollFrameInner(nsContainerFrame* aOuter, PRBool aIsRoot, PRBool aIsXUL) : mHScrollbarBox(nsnull), mVScrollbarBox(nsnull), mScrolledFrame(nsnull), mScrollCornerBox(nsnull), + mResizerBox(nsnull), mOuter(aOuter), mAsyncScroll(nsnull), mDestination(0, 0), mScrollPosAtLastPaint(0, 0), mRestorePos(-1, -1), mLastPos(-1, -1), mNeverHasVerticalScrollbar(PR_FALSE), mNeverHasHorizontalScrollbar(PR_FALSE), @@ -1341,17 +1375,18 @@ nsGfxScrollFrameInner::nsGfxScrollFrameI mIsXUL(aIsXUL), mSupppressScrollbarUpdate(PR_FALSE), mSkippedScrollbarLayout(PR_FALSE), mHadNonInitialReflow(PR_FALSE), mHorizontalOverflow(PR_FALSE), mVerticalOverflow(PR_FALSE), mPostedReflowCallback(PR_FALSE), mMayHaveDirtyFixedChildren(PR_FALSE), - mUpdateScrollbarAttributes(PR_FALSE) + mUpdateScrollbarAttributes(PR_FALSE), + mCollapsedResizer(PR_FALSE) { // lookup if we're allowed to overlap the content from the look&feel object PRBool canOverlap; nsPresContext* presContext = mOuter->PresContext(); presContext->LookAndFeel()-> GetMetric(nsILookAndFeel::eMetric_ScrollbarsCanOverlapContent, canOverlap); mScrollbarsCanOverlapContent = canOverlap; mScrollingActive = IsAlwaysActive(); @@ -1763,17 +1798,17 @@ nsGfxScrollFrameInner::AppendScrollParts const nsDisplayListSet& aLists, const nsDisplayListCollection& aDest, PRBool& aCreateLayer) { nsresult rv = NS_OK; PRBool hasResizer = HasResizer(); for (nsIFrame* kid = mOuter->GetFirstChild(nsnull); kid; kid = kid->GetNextSibling()) { if (kid != mScrolledFrame) { - if (kid == mScrollCornerBox && hasResizer) { + if (kid == mResizerBox && hasResizer) { // skip the resizer as this will be drawn later on top of the scrolled content continue; } rv = mOuter->BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aDest, nsIFrame::DISPLAY_CHILD_FORCE_STACKING_CONTEXT); NS_ENSURE_SUCCESS(rv, rv); // DISPLAY_CHILD_FORCE_STACKING_CONTEXT put everything into the // PositionedDescendants list. @@ -1867,24 +1902,24 @@ nsGfxScrollFrameInner::BuildDisplayList( AppendScrollPartsTo(aBuilder, aDirtyRect, aLists, scrollParts, createLayersForScrollbars); } // Place the resizer in the display list in our Content() list above // scrolled content in the Content() list. // This ensures that the resizer appears above the content and the mouse can // still target the resizer even when scrollbars are hidden. - if (HasResizer() && mScrollCornerBox) { - rv = mOuter->BuildDisplayListForChild(aBuilder, mScrollCornerBox, aDirtyRect, scrollParts, + if (HasResizer() && mResizerBox) { + rv = mOuter->BuildDisplayListForChild(aBuilder, mResizerBox, aDirtyRect, scrollParts, nsIFrame::DISPLAY_CHILD_FORCE_STACKING_CONTEXT); NS_ENSURE_SUCCESS(rv, rv); // DISPLAY_CHILD_FORCE_STACKING_CONTEXT puts everything into the // PositionedDescendants list. ::AppendToTop(aBuilder, aLists.Content(), - scrollParts.PositionedDescendants(), mScrollCornerBox, + scrollParts.PositionedDescendants(), mResizerBox, createLayersForScrollbars); } return NS_OK; } static void HandleScrollPref(nsIScrollable *aScrollable, PRInt32 aOrientation, PRUint8& aValue) @@ -2147,16 +2182,17 @@ nsGfxScrollFrameInner::FireScrollPortEve void nsGfxScrollFrameInner::ReloadChildFrames() { mScrolledFrame = nsnull; mHScrollbarBox = nsnull; mVScrollbarBox = nsnull; mScrollCornerBox = nsnull; + mResizerBox = nsnull; nsIFrame* frame = mOuter->GetFirstChild(nsnull); while (frame) { nsIContent* content = frame->GetContent(); if (content == mOuter->GetContent()) { NS_ASSERTION(!mScrolledFrame, "Already found the scrolled frame"); mScrolledFrame = frame; } else { @@ -2166,16 +2202,19 @@ nsGfxScrollFrameInner::ReloadChildFrames // probably a scrollbar then if (value.LowerCaseEqualsLiteral("horizontal")) { NS_ASSERTION(!mHScrollbarBox, "Found multiple horizontal scrollbars?"); mHScrollbarBox = frame; } else { NS_ASSERTION(!mVScrollbarBox, "Found multiple vertical scrollbars?"); mVScrollbarBox = frame; } + } else if (content->Tag() == nsGkAtoms::resizer) { + NS_ASSERTION(!mResizerBox, "Found multiple resizers"); + mResizerBox = frame; } else { // probably a scrollcorner NS_ASSERTION(!mScrollCornerBox, "Found multiple scrollcorners"); mScrollCornerBox = frame; } } frame = frame->GetNextSibling(); @@ -2267,17 +2306,17 @@ nsGfxScrollFrameInner::CreateAnonymousCo } if (isResizable) { nsCOMPtr<nsINodeInfo> nodeInfo; nodeInfo = nodeInfoManager->GetNodeInfo(nsGkAtoms::resizer, nsnull, kNameSpaceID_XUL); NS_ENSURE_TRUE(nodeInfo, NS_ERROR_OUT_OF_MEMORY); - NS_TrustedNewXULElement(getter_AddRefs(mScrollCornerContent), nodeInfo.forget()); + NS_TrustedNewXULElement(getter_AddRefs(mResizerContent), nodeInfo.forget()); nsAutoString dir; switch (resizeStyle) { case NS_STYLE_RESIZE_HORIZONTAL: if (IsScrollbarOnRight()) { dir.AssignLiteral("right"); } else { @@ -2288,26 +2327,36 @@ nsGfxScrollFrameInner::CreateAnonymousCo dir.AssignLiteral("bottom"); break; case NS_STYLE_RESIZE_BOTH: dir.AssignLiteral("bottomend"); break; default: NS_WARNING("only resizable types should have resizers"); } - mScrollCornerContent->SetAttr(kNameSpaceID_None, nsGkAtoms::dir, dir, PR_FALSE); - mScrollCornerContent->SetAttr(kNameSpaceID_None, nsGkAtoms::element, - NS_LITERAL_STRING("_parent"), PR_FALSE); - mScrollCornerContent->SetAttr(kNameSpaceID_None, nsGkAtoms::clickthrough, + mResizerContent->SetAttr(kNameSpaceID_None, nsGkAtoms::dir, dir, PR_FALSE); + + if (mIsRoot) { + nsIContent* browserRoot = GetBrowserRoot(mOuter->GetContent()); + mCollapsedResizer = !(browserRoot && + browserRoot->HasAttr(kNameSpaceID_None, nsGkAtoms::showresizer)); + } + else { + mResizerContent->SetAttr(kNameSpaceID_None, nsGkAtoms::element, + NS_LITERAL_STRING("_parent"), PR_FALSE); + } + + mResizerContent->SetAttr(kNameSpaceID_None, nsGkAtoms::clickthrough, NS_LITERAL_STRING("always"), PR_FALSE); - if (!aElements.AppendElement(mScrollCornerContent)) + if (!aElements.AppendElement(mResizerContent)) return NS_ERROR_OUT_OF_MEMORY; } - else if (canHaveHorizontal && canHaveVertical) { + + if (canHaveHorizontal && canHaveVertical) { nodeInfo = nodeInfoManager->GetNodeInfo(nsGkAtoms::scrollcorner, nsnull, kNameSpaceID_XUL); NS_TrustedNewXULElement(getter_AddRefs(mScrollCornerContent), nodeInfo.forget()); if (!aElements.AppendElement(mScrollCornerContent)) return NS_ERROR_OUT_OF_MEMORY; } return NS_OK; @@ -2315,25 +2364,27 @@ nsGfxScrollFrameInner::CreateAnonymousCo void nsGfxScrollFrameInner::AppendAnonymousContentTo(nsBaseContentList& aElements, PRUint32 aFilter) { aElements.MaybeAppendElement(mHScrollbarContent); aElements.MaybeAppendElement(mVScrollbarContent); aElements.MaybeAppendElement(mScrollCornerContent); + aElements.MaybeAppendElement(mResizerContent); } void nsGfxScrollFrameInner::Destroy() { // Unbind any content created in CreateAnonymousContent from the tree nsContentUtils::DestroyAnonymousContent(&mHScrollbarContent); nsContentUtils::DestroyAnonymousContent(&mVScrollbarContent); nsContentUtils::DestroyAnonymousContent(&mScrollCornerContent); + nsContentUtils::DestroyAnonymousContent(&mResizerContent); if (mPostedReflowCallback) { mOuter->PresContext()->PresShell()->CancelReflowCallback(this); mPostedReflowCallback = PR_FALSE; } } /** @@ -3063,18 +3114,18 @@ nsGfxScrollFrameInner::AdjustScrollbarRe nsRect& aRect, PRBool aHasResizer, PRBool aVertical) { if ((aVertical ? aRect.width : aRect.height) == 0) return; // if a content resizer is present, use its size. Otherwise, check if the // widget has a resizer. nsRect resizerRect; - if (aHasResizer && mScrollCornerBox) { - resizerRect = mScrollCornerBox->GetRect(); + if (aHasResizer) { + resizerRect = mResizerBox->GetRect(); } else { nsPoint offset; nsIWidget* widget = aFrame->GetNearestWidget(offset); nsIntRect widgetRect; if (!widget || !widget->ShowsResizeIndicator(&widgetRect)) return; @@ -3100,54 +3151,70 @@ nsGfxScrollFrameInner::LayoutScrollbars( { NS_ASSERTION(!mSupppressScrollbarUpdate, "This should have been suppressed"); PRBool hasResizer = HasResizer(); PRBool scrollbarOnLeft = !IsScrollbarOnRight(); // place the scrollcorner - if (mScrollCornerBox) { - NS_PRECONDITION(mScrollCornerBox->IsBoxFrame(), "Must be a box frame!"); - - // if a resizer is present, get its size - nsSize resizerSize; - if (HasResizer()) { - // just assume a default size of 15 pixels - nscoord defaultSize = nsPresContext::CSSPixelsToAppUnits(15); - resizerSize.width = - mVScrollbarBox ? mVScrollbarBox->GetMinSize(aState).width : defaultSize; - resizerSize.height = - mHScrollbarBox ? mHScrollbarBox->GetMinSize(aState).height : defaultSize; - } - else { - resizerSize = nsSize(0, 0); - } + if (mScrollCornerBox || mResizerBox) { + NS_PRECONDITION(!mScrollCornerBox || mScrollCornerBox->IsBoxFrame(), "Must be a box frame!"); nsRect r(0, 0, 0, 0); if (aContentArea.x != mScrollPort.x || scrollbarOnLeft) { // scrollbar (if any) on left r.x = aContentArea.x; - r.width = PR_MAX(resizerSize.width, mScrollPort.x - aContentArea.x); + r.width = mScrollPort.x - aContentArea.x; NS_ASSERTION(r.width >= 0, "Scroll area should be inside client rect"); } else { // scrollbar (if any) on right - r.width = PR_MAX(resizerSize.width, aContentArea.XMost() - mScrollPort.XMost()); + r.width = aContentArea.XMost() - mScrollPort.XMost(); r.x = aContentArea.XMost() - r.width; NS_ASSERTION(r.width >= 0, "Scroll area should be inside client rect"); } if (aContentArea.y != mScrollPort.y) { NS_ERROR("top scrollbars not supported"); } else { // scrollbar (if any) on bottom - r.height = PR_MAX(resizerSize.height, aContentArea.YMost() - mScrollPort.YMost()); + r.height = aContentArea.YMost() - mScrollPort.YMost(); r.y = aContentArea.YMost() - r.height; NS_ASSERTION(r.height >= 0, "Scroll area should be inside client rect"); } - LayoutAndInvalidate(aState, mScrollCornerBox, r, PR_FALSE); + + if (mScrollCornerBox) { + LayoutAndInvalidate(aState, mScrollCornerBox, r, PR_FALSE); + } + + if (hasResizer) { + // if a resizer is present, get its size. Assume a default size of 15 pixels. + nsSize resizerSize; + nscoord defaultSize = nsPresContext::CSSPixelsToAppUnits(15); + resizerSize.width = + mVScrollbarBox ? mVScrollbarBox->GetMinSize(aState).width : defaultSize; + if (resizerSize.width > r.width) { + r.width = resizerSize.width; + if (aContentArea.x == mScrollPort.x && !scrollbarOnLeft) + r.x = aContentArea.XMost() - r.width; + } + + resizerSize.height = + mHScrollbarBox ? mHScrollbarBox->GetMinSize(aState).height : defaultSize; + if (resizerSize.height > r.height) { + r.height = resizerSize.height; + if (aContentArea.y == mScrollPort.y) + r.y = aContentArea.YMost() - r.height; + } + + LayoutAndInvalidate(aState, mResizerBox, r, PR_FALSE); + } + else if (mResizerBox) { + // otherwise lay out the resizer with an empty rectangle + LayoutAndInvalidate(aState, mResizerBox, nsRect(), PR_FALSE); + } } nsPresContext* presContext = mScrolledFrame->PresContext(); if (mVScrollbarBox) { NS_PRECONDITION(mVScrollbarBox->IsBoxFrame(), "Must be a box frame!"); nsRect vRect(mScrollPort); vRect.width = aContentArea.width - mScrollPort.width; vRect.x = scrollbarOnLeft ? aContentArea.x : mScrollPort.XMost();
--- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -225,40 +225,40 @@ public: PRBool IsScrollbarOnRight() const; PRBool IsScrollingActive() const { return mScrollingActive; } // adjust the scrollbar rectangle aRect to account for any visible resizer. // aHasResizer specifies if there is a content resizer, however this method // will also check if a widget resizer is present as well. void AdjustScrollbarRectForResizer(nsIFrame* aFrame, nsPresContext* aPresContext, nsRect& aRect, PRBool aHasResizer, PRBool aVertical); // returns true if a resizer should be visible - PRBool HasResizer() { - return mScrollCornerContent && mScrollCornerContent->Tag() == nsGkAtoms::resizer; - } + PRBool HasResizer() { return mResizerBox && !mCollapsedResizer; } void LayoutScrollbars(nsBoxLayoutState& aState, const nsRect& aContentArea, const nsRect& aOldScrollArea); PRBool IsAlwaysActive() const; void MarkActive(); void MarkInactive(); nsExpirationState* GetExpirationState() { return &mActivityExpirationState; } // owning references to the nsIAnonymousContentCreator-built content nsCOMPtr<nsIContent> mHScrollbarContent; nsCOMPtr<nsIContent> mVScrollbarContent; nsCOMPtr<nsIContent> mScrollCornerContent; + nsCOMPtr<nsIContent> mResizerContent; nsRevocableEventPtr<ScrollEvent> mScrollEvent; nsRevocableEventPtr<AsyncScrollPortEvent> mAsyncScrollPortEvent; nsRevocableEventPtr<ScrolledAreaEvent> mScrolledAreaEvent; nsIBox* mHScrollbarBox; nsIBox* mVScrollbarBox; nsIFrame* mScrolledFrame; nsIBox* mScrollCornerBox; + nsIBox* mResizerBox; nsContainerFrame* mOuter; AsyncScroll* mAsyncScroll; nsTArray<nsIScrollPositionListener*> mListeners; nsRect mScrollPort; // Where we're currently scrolling to, if we're scrolling asynchronously. // If we're not in the middle of an asynchronous scroll then this is // just the current scroll position. ScrollBy will choose its // destination based on this value. @@ -301,16 +301,18 @@ public: // reflow callback. PRPackedBool mUpdateScrollbarAttributes:1; // If true, we should be prepared to scroll using this scrollframe // by placing descendant content into its own layer(s) PRPackedBool mScrollingActive:1; // If true, scrollbars are stacked on the top of the display list and can // float above the content as a result PRPackedBool mScrollbarsCanOverlapContent:1; + // If true, the resizer is collapsed and not displayed + PRPackedBool mCollapsedResizer:1; }; /** * The scroll frame creates and manages the scrolling view * * It only supports having a single child frame that typically is an area * frame, but doesn't have to be. The child frame must have a view, though *
--- a/layout/generic/nsSubDocumentFrame.cpp +++ b/layout/generic/nsSubDocumentFrame.cpp @@ -736,16 +736,23 @@ nsSubDocumentFrame::AttributeChanged(PRI // concrete class, yay! nsHTMLFramesetFrame* framesetFrame = do_QueryFrame(parentFrame); if (framesetFrame) { framesetFrame->RecalculateBorderResize(); } } } } + else if (aAttribute == nsGkAtoms::showresizer) { + nsIFrame* rootFrame = GetSubdocumentRootFrame(); + if (rootFrame) { + rootFrame->PresContext()->PresShell()-> + FrameNeedsReflow(rootFrame, nsIPresShell::eResize, NS_FRAME_IS_DIRTY); + } + } else if (aAttribute == nsGkAtoms::type) { if (!mFrameLoader) return NS_OK; if (!mContent->IsXUL()) { return NS_OK; }
--- a/layout/style/jar.mn +++ b/layout/style/jar.mn @@ -1,8 +1,8 @@ toolkit.jar: - res/ua.css (ua.css) +* res/ua.css (ua.css) res/html.css (html.css) res/quirk.css (quirk.css) res/viewsource.css (viewsource.css) * res/forms.css (forms.css) res/arrow.gif (arrow.gif) res/arrowd.gif (arrowd.gif)
--- a/layout/style/ua.css +++ b/layout/style/ua.css @@ -162,16 +162,19 @@ *|*::-moz-viewport, *|*::-moz-viewport-scroll, *|*::-moz-canvas, *|*::-moz-scrolled-canvas { display: block !important; background-color: inherit; } *|*::-moz-viewport-scroll { overflow: auto; +%ifdef XP_WIN + resize: both; +%endif } *|*::-moz-column-content { /* the column boxes inside a column-flowed block */ /* make unicode-bidi inherit, otherwise it has no effect on column boxes */ unicode-bidi: inherit; /* inherit the outer frame's display, otherwise we turn into an inline */ display: inherit !important;
--- a/layout/xul/base/src/nsResizerFrame.cpp +++ b/layout/xul/base/src/nsResizerFrame.cpp @@ -356,18 +356,24 @@ nsResizerFrame::GetContentToResize(nsIPr nsCOMPtr<nsISupports> cont = aPresShell->GetPresContext()->GetContainer(); nsCOMPtr<nsIDocShellTreeItem> dsti = do_QueryInterface(cont); if (dsti) { PRInt32 type = -1; isChromeShell = (NS_SUCCEEDED(dsti->GetItemType(&type)) && type == nsIDocShellTreeItem::typeChrome); } - if (!isChromeShell) - return nsnull; + if (!isChromeShell) { + // don't allow resizers in content shells, except for the viewport + // scrollbar which doesn't have a parent + nsIContent* nonNativeAnon = mContent->FindFirstNonNativeAnonymous(); + if (nonNativeAnon && !nonNativeAnon->GetParent()) { + return nsnull; + } + } // get the document and the window - should this be cached? nsPIDOMWindow *domWindow = aPresShell->GetDocument()->GetWindow(); if (domWindow) { nsCOMPtr<nsIDocShellTreeItem> docShellAsItem = do_QueryInterface(domWindow->GetDocShell()); if (docShellAsItem) { nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
--- a/toolkit/content/widgets/browser.xml +++ b/toolkit/content/widgets/browser.xml @@ -357,16 +357,22 @@ <property name="contentTitle" onget="return this.contentDocument.title;" readonly="true"/> <property name="contentPrincipal" onget="return this.contentDocument.nodePrincipal;" readonly="true"/> + <property name="showWindowResizer" + onset="if (val) this.setAttribute('showresizer', 'true'); + else this.removeAttribute('showresizer'); + return val;" + onget="return this.getAttribute('showresizer') == 'true';"/> + <field name="mPrefs" readonly="true"> Components.classes['@mozilla.org/preferences-service;1'] .getService(Components.interfaces.nsIPrefService) .getBranch(null); </field> <field name="mAtomService" readonly="true"> Components.classes['@mozilla.org/atom-service;1']
--- a/toolkit/content/widgets/resizer.xml +++ b/toolkit/content/widgets/resizer.xml @@ -5,16 +5,21 @@ <binding id="resizer"> <resources> <stylesheet src="chrome://global/skin/resizer.css"/> </resources> <implementation> <constructor> <![CDATA[ + // don't do this for viewport resizers; causes a crash related to + // bugs 563665 and 581536 otherwise + if (this.parentNode == this.ownerDocument.documentElement) + return; + // if the direction is rtl, set the rtl attribute so that the // stylesheet can use this to make the cursor appear properly var direction = window.getComputedStyle(this, "").direction; if (direction == "rtl") { this.setAttribute("rtl", "true"); } ]]> </constructor>