Files
palemoon27/layout/forms/nsSelectsAreaFrame.cpp
T
roytam1 7d12d066b1 import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 766345 - Part 1 - Implement DEAA Antialiasing for transformed layers (v5 Patch). r=vladimir, r=djg (a5b4175d8)
- Bug 766345 - Part 2 - Implement Matrix4x4::TransformAndClipRect (v2 Patch). r=vladimir (fba290751)
- Bug 766345 - Part 3 - Implement correct clipping of DEAA edges for quads that cross the w=0 plane (v3 Patch). r=vlad (1574cd5e8)
- Bug 766345 - Part 4: Adjust reftests (v3 patch). r=vlad (8a78cc3c4)
- Bug 1158120 - Replace nsIntSize by mozilla::gfx::IntSize in gfx/layers. r=nical (39b6ad475)
- Bug 1170189 - Simplify TiledContentHost's render loop. r=BenWa (040aac295)
- Bug 1170189 - Simplify the client-side tiling code. r=BenWa (069820cf1)
- Bug 1170189 - Remove the TiledLayerComposer interface. r=BenWa (843da52ff)
- Bug 1158122 - Remove some of the occurences of nsIntRect in gfx. r=nical (600608f14)
- Bug 1181240 - Part 3: Replace gfx3DMatrix with Matrix4x4 in gfx,r=vlad (e27a99500)
- Bug 1181240 - Part 4: Remove gfx3DMatrix,r=vlad (36138a985)
- Bug 997709 part 1 - nsComboboxDisplayFrame can't be split so its reflow status is always NS_FRAME_COMPLETE. r=heycam (15696aad1)
- Bug 997709 part 2 - Prevent the nsComboboxDisplayFrame from being blockified if the parent context has display:flex/grid. r=heycam (7bedb6d69)
- Bug 1140216. Remove asserts that stuff that we never create is not null, since it clearly is null. r=jwatt (aad9d387b)
- Bug 997709 part 3 - tests. (50f3e3a16)
- Bug 1113206: Make nsComboboxControlFrame and nsListControlFrame use logical coordinates and support vertical writing modes - patch by smontagu with additions by jfkthame. r=jfkthame,smontagu (aaaff31e9)
- Bug 1181890 - Center children of ruby content frame if necessary after the bidi reposition. r=jfkthame (8b3b5fdb2)
- Bug 1123284 - pt 1 - Make nsTextBoxFrame somewhat aware of vertical writing mode, to allow <input type=file> to display properly. r=smontagu (b395ba174)
- Bug 1123284 - pt 2 - Fix Get{Min,Pref}ISize in nsLeafBoxFrame for vertical mode. r=smontagu (4a828e0ab)
- Bug 1079151 - patch 1 - Update constraint calculations in nsHTMLReflowState to work with logical coordinates. r=smontagu (ce11e8f6b)
- Bug 1079151 - patch 2 - Convert nsAbsoluteContainingBlock to use logial coordinates. r=smontagu (ad2b0000c)
- Bug 1079151 - patch 3 - Remove failure annotations from the vertical abs-pos reftests. r=smontagu (d95333230)
- Bug 1079151 - patch 4 - Handle unconstrained inline-size when computing constraints for an orthogonal absolutely-positioned block. r=smontagu (99ffede00)
- Bug 1079151 - Updated test files with corrected comments and references as needed. r=jfkthame (c655a98d0)
- Bug 1175492 - unpref transform-origin percentage handling for SVG elements r=jwatt (cda2fffa7)
- Bug 1175094 - Include borderPadding in the combobox's containerWidth, so that dropdown arrow is positioned correctly in RTL. r=smontagu (e93ccaa34)
- Bug 1177614 - Provide a utility method on nsHTMLReflowState to return the computed size including border-padding, for use as a container for logical coordinate conversions, or zero if unconstrained. r=dholbert (89feb2d8a)
- Bug 1180178: Add writing-mode and logical coordinates to frame dumps, r=jfkthame (786a6d878)
- Bug 1157569 - part 12 - Convert physical values from BCPropertyData to logical when returning from Get[Included]OuterBCBorder. r=roc (2d5790f2a)
- Bug 1157569 - part 13 - More conversion of physical to logical terminology in border-collapse calculations. r=dholbert (a85618bf4)
- Bug 1176523 - Convert Get/SetContinuousBCBorderWidth in nsTableColFrame and nsTableColGroupFrame to logical coordinates. r=dholbert (6198c6eb3)
- Bug 1157569 - part 14 - Finish conversion of border-collapse code in nsTableFrame to logical coordinates. r=dholbert (700bbf09b)
- Bug 1157569 - Reftest for RTL table with border-collapse. r=roc (aa4fc0092)
- Bug 1157569 - Followup to address review nits (renamings, comment updates) from parts 13 and 14. (6cccb95df)
- Bug 903135 - Multi platform MAR verification updater support. r=rstrong (7643732df)
- Bug 991993: Disable NSS for updater on OSX and enable native APIs. r=smichaud,rstrong (1490dead8)
2021-03-05 09:13:17 +08:00

206 lines
7.5 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsSelectsAreaFrame.h"
#include "nsIContent.h"
#include "nsListControlFrame.h"
#include "nsDisplayList.h"
#include "WritingModes.h"
using namespace mozilla;
nsContainerFrame*
NS_NewSelectsAreaFrame(nsIPresShell* aShell, nsStyleContext* aContext, nsFrameState aFlags)
{
nsSelectsAreaFrame* it = new (aShell) nsSelectsAreaFrame(aContext);
// We need NS_BLOCK_FLOAT_MGR to ensure that the options inside the select
// aren't expanded by right floats outside the select.
it->SetFlags(aFlags | NS_BLOCK_FLOAT_MGR);
return it;
}
NS_IMPL_FRAMEARENA_HELPERS(nsSelectsAreaFrame)
//---------------------------------------------------------
/**
* This wrapper class lets us redirect mouse hits from the child frame of
* an option element to the element's own frame.
* REVIEW: This is what nsSelectsAreaFrame::GetFrameForPoint used to do
*/
class nsDisplayOptionEventGrabber : public nsDisplayWrapList {
public:
nsDisplayOptionEventGrabber(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayItem* aItem)
: nsDisplayWrapList(aBuilder, aFrame, aItem) {}
nsDisplayOptionEventGrabber(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList)
: nsDisplayWrapList(aBuilder, aFrame, aList) {}
virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames) override;
virtual bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override {
return false;
}
NS_DISPLAY_DECL_NAME("OptionEventGrabber", TYPE_OPTION_EVENT_GRABBER)
};
void nsDisplayOptionEventGrabber::HitTest(nsDisplayListBuilder* aBuilder,
const nsRect& aRect, HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
{
nsTArray<nsIFrame*> outFrames;
mList.HitTest(aBuilder, aRect, aState, &outFrames);
for (uint32_t i = 0; i < outFrames.Length(); i++) {
nsIFrame* selectedFrame = outFrames.ElementAt(i);
while (selectedFrame &&
!(selectedFrame->GetContent() &&
selectedFrame->GetContent()->IsHTMLElement(nsGkAtoms::option))) {
selectedFrame = selectedFrame->GetParent();
}
if (selectedFrame) {
aOutFrames->AppendElement(selectedFrame);
} else {
// keep the original result, which could be this frame
aOutFrames->AppendElement(outFrames.ElementAt(i));
}
}
}
class nsOptionEventGrabberWrapper : public nsDisplayWrapper
{
public:
nsOptionEventGrabberWrapper() {}
virtual nsDisplayItem* WrapList(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList) {
return new (aBuilder) nsDisplayOptionEventGrabber(aBuilder, aFrame, aList);
}
virtual nsDisplayItem* WrapItem(nsDisplayListBuilder* aBuilder,
nsDisplayItem* aItem) {
return new (aBuilder) nsDisplayOptionEventGrabber(aBuilder, aItem->Frame(), aItem);
}
};
static nsListControlFrame* GetEnclosingListFrame(nsIFrame* aSelectsAreaFrame)
{
nsIFrame* frame = aSelectsAreaFrame->GetParent();
while (frame) {
if (frame->GetType() == nsGkAtoms::listControlFrame)
return static_cast<nsListControlFrame*>(frame);
frame = frame->GetParent();
}
return nullptr;
}
class nsDisplayListFocus : public nsDisplayItem {
public:
nsDisplayListFocus(nsDisplayListBuilder* aBuilder,
nsSelectsAreaFrame* aFrame) :
nsDisplayItem(aBuilder, aFrame) {
MOZ_COUNT_CTOR(nsDisplayListFocus);
}
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayListFocus() {
MOZ_COUNT_DTOR(nsDisplayListFocus);
}
#endif
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) override {
*aSnap = false;
// override bounds because the list item focus ring may extend outside
// the nsSelectsAreaFrame
nsListControlFrame* listFrame = GetEnclosingListFrame(Frame());
return listFrame->GetVisualOverflowRectRelativeToSelf() +
listFrame->GetOffsetToCrossDoc(ReferenceFrame());
}
virtual void Paint(nsDisplayListBuilder* aBuilder,
nsRenderingContext* aCtx) override {
nsListControlFrame* listFrame = GetEnclosingListFrame(Frame());
// listFrame must be non-null or we wouldn't get called.
listFrame->PaintFocus(*aCtx, aBuilder->ToReferenceFrame(listFrame));
}
NS_DISPLAY_DECL_NAME("ListFocus", TYPE_LIST_FOCUS)
};
void
nsSelectsAreaFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
if (!aBuilder->IsForEventDelivery()) {
BuildDisplayListInternal(aBuilder, aDirtyRect, aLists);
return;
}
nsDisplayListCollection set;
BuildDisplayListInternal(aBuilder, aDirtyRect, set);
nsOptionEventGrabberWrapper wrapper;
wrapper.WrapLists(aBuilder, this, set, aLists);
}
void
nsSelectsAreaFrame::BuildDisplayListInternal(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists)
{
nsBlockFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
nsListControlFrame* listFrame = GetEnclosingListFrame(this);
if (listFrame && listFrame->IsFocused()) {
// we can't just associate the display item with the list frame,
// because then the list's scrollframe won't clip it (the scrollframe
// only clips contained descendants).
aLists.Outlines()->AppendNewToTop(new (aBuilder)
nsDisplayListFocus(aBuilder, this));
}
}
void
nsSelectsAreaFrame::Reflow(nsPresContext* aPresContext,
nsHTMLReflowMetrics& aDesiredSize,
const nsHTMLReflowState& aReflowState,
nsReflowStatus& aStatus)
{
nsListControlFrame* list = GetEnclosingListFrame(this);
NS_ASSERTION(list,
"Must have an nsListControlFrame! Frame constructor is "
"broken");
bool isInDropdownMode = list->IsInDropDownMode();
// See similar logic in nsListControlFrame::Reflow and
// nsListControlFrame::ReflowAsDropdown. We need to match it here.
WritingMode wm = aReflowState.GetWritingMode();
nscoord oldBSize;
if (isInDropdownMode) {
// Store the block size now in case it changes during
// nsBlockFrame::Reflow for some odd reason.
if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) {
oldBSize = BSize(wm);
} else {
oldBSize = NS_UNCONSTRAINEDSIZE;
}
}
nsBlockFrame::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus);
// Check whether we need to suppress scrollbar updates. We want to do
// that if we're in a possible first pass and our block size of a row
// has changed.
if (list->MightNeedSecondPass()) {
nscoord newBSizeOfARow = list->CalcBSizeOfARow();
// We'll need a second pass if our block size of a row changed. For
// comboboxes, we'll also need it if our block size changed. If
// we're going to do a second pass, suppress scrollbar updates for
// this pass.
if (newBSizeOfARow != mBSizeOfARow ||
(isInDropdownMode && (oldBSize != aDesiredSize.BSize(wm) ||
oldBSize != BSize(wm)))) {
mBSizeOfARow = newBSizeOfARow;
list->SetSuppressScrollbarUpdate(true);
}
}
}