gecko-dev/layout/forms/nsComboboxControlFrame.h

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

251 строка
8.2 KiB
C
Исходник Обычный вид История

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
2012-05-21 15:12:37 +04:00
/* 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/. */
1999-01-18 18:14:00 +03:00
#ifndef nsComboboxControlFrame_h___
#define nsComboboxControlFrame_h___
#ifdef DEBUG_evaughan
//#define DEBUG_rods
#endif
#ifdef DEBUG_rods
//#define DO_REFLOW_DEBUG
//#define DO_REFLOW_COUNTER
2000-03-15 18:47:11 +03:00
//#define DO_UNCONSTRAINED_CHECK
//#define DO_PIXELS
//#define DO_NEW_REFLOW
#endif
// Mark used to indicate when onchange has been fired for current combobox item
#define NS_SKIP_NOTIFY_INDEX -2
#include "mozilla/Attributes.h"
#include "nsBlockFrame.h"
1999-01-18 18:14:00 +03:00
#include "nsIFormControlFrame.h"
#include "nsIAnonymousContentCreator.h"
#include "nsISelectControlFrame.h"
#include "nsIRollupListener.h"
#include "nsThreadUtils.h"
1999-01-18 18:14:00 +03:00
class nsComboboxDisplayFrame;
class nsTextNode;
1999-01-18 18:14:00 +03:00
namespace mozilla {
class PresShell;
Bug 1744009 - Simplify combobox <select> code. r=mconley,dholbert With this patch on its own we get some a11y tests failures, but those are fixed on a later patch. Combobox select no longer creates frames for its <options>, nor an nsListControlFrame. Instead, it computes its right intrinsic size using the largest size of the options. This is better, because we render the option text using the select style so if the select and option styles are mismatched it'd cause changes in the size of the select when text changes. See the following in a build without the patch, for example: <select> <option>ABC</option> <option style="font-size: 1px">Something long</option> </select> This seems like a rather obscure case, but it's important to get it right, see bug 1741888. With this patch we use the same setup in content and parent processes (this needs bug 1596852 and bug 1744152). This means we can remove a bunch of the native view and popup code in nsListControlFrame. A couple browser_* tests are affected by this change and have been tweaked appropriately (the changes there are trivial). Not creating an nsListControlFrame for dropdown select means that we need to move a bunch of the event handling code from nsListControlFrame to a common place that nsComboboxControlFrame can also use. That place is HTMLSelectEventListener, and I think the setup is much nicer than having the code intertwined with nsListControlFrame. It should be relatively straight-forward to review, mostly moving code from one part to another. Another thing that we need to do in HTMLSelectEventListener that we didn't use to do is listening for DOM mutations on the dropdown. Before, we were relying on changes like text mutations triggering a reflow of the listcontrolframe, which also triggered a reflow of the comboboxcontrolframe, which in turn updated the text of the anonymous content. Now we need to trigger that reflow manually. There are some further simplifications that can be done after this lands (cleanup naming of openInParentProcess and so on, among others), but I'd rather land this first (after the merge of course) and work on them separately. Differential Revision: https://phabricator.services.mozilla.com/D132719
2022-01-17 14:10:05 +03:00
class HTMLSelectEventListener;
namespace dom {
class HTMLSelectElement;
}
namespace gfx {
class DrawTarget;
} // namespace gfx
} // namespace mozilla
class nsComboboxControlFrame final : public nsBlockFrame,
public nsIFormControlFrame,
public nsIAnonymousContentCreator,
Bug 1744009 - Simplify combobox <select> code. r=mconley,dholbert With this patch on its own we get some a11y tests failures, but those are fixed on a later patch. Combobox select no longer creates frames for its <options>, nor an nsListControlFrame. Instead, it computes its right intrinsic size using the largest size of the options. This is better, because we render the option text using the select style so if the select and option styles are mismatched it'd cause changes in the size of the select when text changes. See the following in a build without the patch, for example: <select> <option>ABC</option> <option style="font-size: 1px">Something long</option> </select> This seems like a rather obscure case, but it's important to get it right, see bug 1741888. With this patch we use the same setup in content and parent processes (this needs bug 1596852 and bug 1744152). This means we can remove a bunch of the native view and popup code in nsListControlFrame. A couple browser_* tests are affected by this change and have been tweaked appropriately (the changes there are trivial). Not creating an nsListControlFrame for dropdown select means that we need to move a bunch of the event handling code from nsListControlFrame to a common place that nsComboboxControlFrame can also use. That place is HTMLSelectEventListener, and I think the setup is much nicer than having the code intertwined with nsListControlFrame. It should be relatively straight-forward to review, mostly moving code from one part to another. Another thing that we need to do in HTMLSelectEventListener that we didn't use to do is listening for DOM mutations on the dropdown. Before, we were relying on changes like text mutations triggering a reflow of the listcontrolframe, which also triggered a reflow of the comboboxcontrolframe, which in turn updated the text of the anonymous content. Now we need to trigger that reflow manually. There are some further simplifications that can be done after this lands (cleanup naming of openInParentProcess and so on, among others), but I'd rather land this first (after the merge of course) and work on them separately. Differential Revision: https://phabricator.services.mozilla.com/D132719
2022-01-17 14:10:05 +03:00
public nsISelectControlFrame {
using DrawTarget = mozilla::gfx::DrawTarget;
using Element = mozilla::dom::Element;
1999-01-18 18:14:00 +03:00
public:
friend nsComboboxControlFrame* NS_NewComboboxControlFrame(
mozilla::PresShell* aPresShell, ComputedStyle* aStyle,
nsFrameState aFlags);
friend class nsComboboxDisplayFrame;
explicit nsComboboxControlFrame(ComputedStyle* aStyle,
nsPresContext* aPresContext);
1999-01-18 18:14:00 +03:00
~nsComboboxControlFrame();
NS_DECL_QUERYFRAME
NS_DECL_FRAMEARENA_HELPERS(nsComboboxControlFrame)
// nsIAnonymousContentCreator
nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) final;
void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
uint32_t aFilter) final;
nsIContent* GetDisplayNode() const;
nsIFrame* CreateFrameForDisplayNode();
2001-08-17 07:13:07 +04:00
#ifdef ACCESSIBILITY
mozilla::a11y::AccType AccessibleType() final;
2001-08-17 07:13:07 +04:00
#endif
nscoord GetMinISize(gfxContext* aRenderingContext) final;
nscoord GetPrefISize(gfxContext* aRenderingContext) final;
void Reflow(nsPresContext* aCX, ReflowOutput& aDesiredSize,
const ReflowInput& aReflowInput, nsReflowStatus& aStatus) final;
1999-01-18 18:14:00 +03:00
MOZ_CAN_RUN_SCRIPT_BOUNDARY
nsresult HandleEvent(nsPresContext* aPresContext,
mozilla::WidgetGUIEvent* aEvent,
nsEventStatus* aEventStatus) final;
1999-07-29 01:38:08 +04:00
void BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsDisplayListSet& aLists) final;
void PaintFocus(DrawTarget& aDrawTarget, nsPoint aPt);
bool IsFrameOfType(uint32_t aFlags) const final {
return nsBlockFrame::IsFrameOfType(
aFlags & ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
}
Bug 1744009 - Simplify combobox <select> code. r=mconley,dholbert With this patch on its own we get some a11y tests failures, but those are fixed on a later patch. Combobox select no longer creates frames for its <options>, nor an nsListControlFrame. Instead, it computes its right intrinsic size using the largest size of the options. This is better, because we render the option text using the select style so if the select and option styles are mismatched it'd cause changes in the size of the select when text changes. See the following in a build without the patch, for example: <select> <option>ABC</option> <option style="font-size: 1px">Something long</option> </select> This seems like a rather obscure case, but it's important to get it right, see bug 1741888. With this patch we use the same setup in content and parent processes (this needs bug 1596852 and bug 1744152). This means we can remove a bunch of the native view and popup code in nsListControlFrame. A couple browser_* tests are affected by this change and have been tweaked appropriately (the changes there are trivial). Not creating an nsListControlFrame for dropdown select means that we need to move a bunch of the event handling code from nsListControlFrame to a common place that nsComboboxControlFrame can also use. That place is HTMLSelectEventListener, and I think the setup is much nicer than having the code intertwined with nsListControlFrame. It should be relatively straight-forward to review, mostly moving code from one part to another. Another thing that we need to do in HTMLSelectEventListener that we didn't use to do is listening for DOM mutations on the dropdown. Before, we were relying on changes like text mutations triggering a reflow of the listcontrolframe, which also triggered a reflow of the comboboxcontrolframe, which in turn updated the text of the anonymous content. Now we need to trigger that reflow manually. There are some further simplifications that can be done after this lands (cleanup naming of openInParentProcess and so on, among others), but I'd rather land this first (after the merge of course) and work on them separately. Differential Revision: https://phabricator.services.mozilla.com/D132719
2022-01-17 14:10:05 +03:00
void Init(nsIContent* aContent, nsContainerFrame* aParent,
nsIFrame* aPrevInFlow) final;
#ifdef DEBUG_FRAME_DUMP
nsresult GetFrameName(nsAString& aResult) const final;
#endif
void DestroyFrom(nsIFrame* aDestructRoot,
PostDestroyData& aPostDestroyData) final;
void SetInitialChildList(ChildListID aListID, nsFrameList& aChildList) final;
const nsFrameList& GetChildList(ChildListID aListID) const final;
void GetChildLists(nsTArray<ChildList>* aLists) const final;
nsContainerFrame* GetContentInsertionFrame() final;
// Return the dropdown and display frame.
void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) final;
// nsIFormControlFrame
Bug 1744009 - Simplify combobox <select> code. r=mconley,dholbert With this patch on its own we get some a11y tests failures, but those are fixed on a later patch. Combobox select no longer creates frames for its <options>, nor an nsListControlFrame. Instead, it computes its right intrinsic size using the largest size of the options. This is better, because we render the option text using the select style so if the select and option styles are mismatched it'd cause changes in the size of the select when text changes. See the following in a build without the patch, for example: <select> <option>ABC</option> <option style="font-size: 1px">Something long</option> </select> This seems like a rather obscure case, but it's important to get it right, see bug 1741888. With this patch we use the same setup in content and parent processes (this needs bug 1596852 and bug 1744152). This means we can remove a bunch of the native view and popup code in nsListControlFrame. A couple browser_* tests are affected by this change and have been tweaked appropriately (the changes there are trivial). Not creating an nsListControlFrame for dropdown select means that we need to move a bunch of the event handling code from nsListControlFrame to a common place that nsComboboxControlFrame can also use. That place is HTMLSelectEventListener, and I think the setup is much nicer than having the code intertwined with nsListControlFrame. It should be relatively straight-forward to review, mostly moving code from one part to another. Another thing that we need to do in HTMLSelectEventListener that we didn't use to do is listening for DOM mutations on the dropdown. Before, we were relying on changes like text mutations triggering a reflow of the listcontrolframe, which also triggered a reflow of the comboboxcontrolframe, which in turn updated the text of the anonymous content. Now we need to trigger that reflow manually. There are some further simplifications that can be done after this lands (cleanup naming of openInParentProcess and so on, among others), but I'd rather land this first (after the merge of course) and work on them separately. Differential Revision: https://phabricator.services.mozilla.com/D132719
2022-01-17 14:10:05 +03:00
nsresult SetFormProperty(nsAtom* aName, const nsAString& aValue) final {
return NS_OK;
}
/**
* Inform the control that it got (or lost) focus.
* If it lost focus, the dropdown menu will be rolled up if needed,
* and FireOnChange() will be called.
* @param aOn true if got focus, false if lost focus.
* @param aRepaint if true then force repaint (NOTE: we always force repaint
* currently)
* @note This method might destroy |this|.
*/
MOZ_CAN_RUN_SCRIPT_BOUNDARY
void SetFocus(bool aOn, bool aRepaint) final;
2012-06-23 05:13:56 +04:00
/**
* Return the available space before and after this frame for
2012-06-23 05:13:56 +04:00
* placing the drop-down list, and the current 2D translation.
* Note that either or both can be less than or equal to zero,
* if both are then the drop-down should be closed.
*/
void GetAvailableDropdownSpace(mozilla::WritingMode aWM, nscoord* aBefore,
nscoord* aAfter,
mozilla::LogicalPoint* aTranslation);
int32_t GetIndexOfDisplayArea();
/**
* @note This method might destroy |this|.
*/
nsresult RedisplaySelectedText();
int32_t UpdateRecentIndex(int32_t aIndex);
bool IsDroppedDown() const;
// nsISelectControlFrame
NS_IMETHOD AddOption(int32_t index) final;
NS_IMETHOD RemoveOption(int32_t index) final;
NS_IMETHOD DoneAddingChildren(bool aIsDone) final;
NS_IMETHOD OnOptionSelected(int32_t aIndex, bool aSelected) final;
NS_IMETHOD_(void)
OnSetSelectedIndex(int32_t aOldIndex, int32_t aNewIndex) final;
Bug 1744009 - Simplify combobox <select> code. r=mconley,dholbert With this patch on its own we get some a11y tests failures, but those are fixed on a later patch. Combobox select no longer creates frames for its <options>, nor an nsListControlFrame. Instead, it computes its right intrinsic size using the largest size of the options. This is better, because we render the option text using the select style so if the select and option styles are mismatched it'd cause changes in the size of the select when text changes. See the following in a build without the patch, for example: <select> <option>ABC</option> <option style="font-size: 1px">Something long</option> </select> This seems like a rather obscure case, but it's important to get it right, see bug 1741888. With this patch we use the same setup in content and parent processes (this needs bug 1596852 and bug 1744152). This means we can remove a bunch of the native view and popup code in nsListControlFrame. A couple browser_* tests are affected by this change and have been tweaked appropriately (the changes there are trivial). Not creating an nsListControlFrame for dropdown select means that we need to move a bunch of the event handling code from nsListControlFrame to a common place that nsComboboxControlFrame can also use. That place is HTMLSelectEventListener, and I think the setup is much nicer than having the code intertwined with nsListControlFrame. It should be relatively straight-forward to review, mostly moving code from one part to another. Another thing that we need to do in HTMLSelectEventListener that we didn't use to do is listening for DOM mutations on the dropdown. Before, we were relying on changes like text mutations triggering a reflow of the listcontrolframe, which also triggered a reflow of the comboboxcontrolframe, which in turn updated the text of the anonymous content. Now we need to trigger that reflow manually. There are some further simplifications that can be done after this lands (cleanup naming of openInParentProcess and so on, among others), but I'd rather land this first (after the merge of course) and work on them separately. Differential Revision: https://phabricator.services.mozilla.com/D132719
2022-01-17 14:10:05 +03:00
int32_t CharCountOfLargestOptionForInflation() const;
protected:
2012-06-23 05:13:56 +04:00
friend class RedisplayTextEvent;
friend class nsAsyncResize;
friend class nsResizeDropdownAtFinalPosition;
// Return true if we should render a dropdown button.
bool HasDropDownButton() const;
nscoord DropDownButtonISize();
2012-06-23 05:13:56 +04:00
enum DropDownPositionState {
// can't show the dropdown at its current position
eDropDownPositionSuppressed,
// a resize reflow is pending, don't show it yet
eDropDownPositionPendingResize,
// the dropdown has its final size and position and can be displayed here
eDropDownPositionFinal
};
DropDownPositionState AbsolutelyPositionDropDown();
nscoord GetLongestOptionISize(gfxContext*) const;
// Helper for GetMinISize/GetPrefISize
nscoord GetIntrinsicISize(gfxContext* aRenderingContext,
mozilla::IntrinsicISizeType aType);
class RedisplayTextEvent : public mozilla::Runnable {
public:
NS_DECL_NSIRUNNABLE
explicit RedisplayTextEvent(nsComboboxControlFrame* c)
: mozilla::Runnable("nsComboboxControlFrame::RedisplayTextEvent"),
mControlFrame(c) {}
void Revoke() { mControlFrame = nullptr; }
private:
nsComboboxControlFrame* mControlFrame;
};
void CheckFireOnChange();
void FireValueChangeEvent();
nsresult RedisplayText();
void HandleRedisplayTextEvent();
void ActuallyDisplayText(bool aNotify);
1999-01-18 18:14:00 +03:00
// If our total transform to the root frame of the root document is only a 2d
// translation then return that translation, otherwise returns (0,0).
nsPoint GetCSSTransformTranslation();
Bug 1744009 - Simplify combobox <select> code. r=mconley,dholbert With this patch on its own we get some a11y tests failures, but those are fixed on a later patch. Combobox select no longer creates frames for its <options>, nor an nsListControlFrame. Instead, it computes its right intrinsic size using the largest size of the options. This is better, because we render the option text using the select style so if the select and option styles are mismatched it'd cause changes in the size of the select when text changes. See the following in a build without the patch, for example: <select> <option>ABC</option> <option style="font-size: 1px">Something long</option> </select> This seems like a rather obscure case, but it's important to get it right, see bug 1741888. With this patch we use the same setup in content and parent processes (this needs bug 1596852 and bug 1744152). This means we can remove a bunch of the native view and popup code in nsListControlFrame. A couple browser_* tests are affected by this change and have been tweaked appropriately (the changes there are trivial). Not creating an nsListControlFrame for dropdown select means that we need to move a bunch of the event handling code from nsListControlFrame to a common place that nsComboboxControlFrame can also use. That place is HTMLSelectEventListener, and I think the setup is much nicer than having the code intertwined with nsListControlFrame. It should be relatively straight-forward to review, mostly moving code from one part to another. Another thing that we need to do in HTMLSelectEventListener that we didn't use to do is listening for DOM mutations on the dropdown. Before, we were relying on changes like text mutations triggering a reflow of the listcontrolframe, which also triggered a reflow of the comboboxcontrolframe, which in turn updated the text of the anonymous content. Now we need to trigger that reflow manually. There are some further simplifications that can be done after this lands (cleanup naming of openInParentProcess and so on, among others), but I'd rather land this first (after the merge of course) and work on them separately. Differential Revision: https://phabricator.services.mozilla.com/D132719
2022-01-17 14:10:05 +03:00
mozilla::dom::HTMLSelectElement& Select() const;
void GetOptionText(uint32_t aIndex, nsAString& aText) const;
RefPtr<nsTextNode> mDisplayContent; // Anonymous content used to display the
// current selection
RefPtr<Element> mButtonContent; // Anonymous content for the button
nsContainerFrame* mDisplayFrame; // frame to display selection
nsIFrame* mButtonFrame; // button frame
1999-01-18 18:14:00 +03:00
// The inline size of our display area. Used by that frame's reflow
// to size to the full inline size except the drop-marker.
nscoord mDisplayISize;
// The maximum inline size of our display area, which is the
// nsComoboxControlFrame's border-box.
//
// Going over this would be observable via DOM APIs like client / scrollWidth.
nscoord mMaxDisplayISize;
nsRevocableEventPtr<RedisplayTextEvent> mRedisplayTextEvent;
int32_t mRecentSelectedIndex;
int32_t mDisplayedIndex;
nsString mDisplayedOptionTextOrPreview;
Bug 1744009 - Simplify combobox <select> code. r=mconley,dholbert With this patch on its own we get some a11y tests failures, but those are fixed on a later patch. Combobox select no longer creates frames for its <options>, nor an nsListControlFrame. Instead, it computes its right intrinsic size using the largest size of the options. This is better, because we render the option text using the select style so if the select and option styles are mismatched it'd cause changes in the size of the select when text changes. See the following in a build without the patch, for example: <select> <option>ABC</option> <option style="font-size: 1px">Something long</option> </select> This seems like a rather obscure case, but it's important to get it right, see bug 1741888. With this patch we use the same setup in content and parent processes (this needs bug 1596852 and bug 1744152). This means we can remove a bunch of the native view and popup code in nsListControlFrame. A couple browser_* tests are affected by this change and have been tweaked appropriately (the changes there are trivial). Not creating an nsListControlFrame for dropdown select means that we need to move a bunch of the event handling code from nsListControlFrame to a common place that nsComboboxControlFrame can also use. That place is HTMLSelectEventListener, and I think the setup is much nicer than having the code intertwined with nsListControlFrame. It should be relatively straight-forward to review, mostly moving code from one part to another. Another thing that we need to do in HTMLSelectEventListener that we didn't use to do is listening for DOM mutations on the dropdown. Before, we were relying on changes like text mutations triggering a reflow of the listcontrolframe, which also triggered a reflow of the comboboxcontrolframe, which in turn updated the text of the anonymous content. Now we need to trigger that reflow manually. There are some further simplifications that can be done after this lands (cleanup naming of openInParentProcess and so on, among others), but I'd rather land this first (after the merge of course) and work on them separately. Differential Revision: https://phabricator.services.mozilla.com/D132719
2022-01-17 14:10:05 +03:00
RefPtr<mozilla::HTMLSelectEventListener> mEventListener;
2012-06-23 05:13:56 +04:00
// See comment in HandleRedisplayTextEvent().
bool mInRedisplayText;
bool mIsOpenInParentProcess;
// static class data member for Bug 32920
// only one control can be focused at a time
static nsComboboxControlFrame* sFocused;
#ifdef DO_REFLOW_COUNTER
int32_t mReflowId;
#endif
1999-01-18 18:14:00 +03:00
};
#endif