summaryrefslogtreecommitdiffstats
path: root/layout/forms/nsComboboxControlFrame.h
diff options
context:
space:
mode:
Diffstat (limited to 'layout/forms/nsComboboxControlFrame.h')
-rw-r--r--layout/forms/nsComboboxControlFrame.h328
1 files changed, 328 insertions, 0 deletions
diff --git a/layout/forms/nsComboboxControlFrame.h b/layout/forms/nsComboboxControlFrame.h
new file mode 100644
index 000000000..22849e8d1
--- /dev/null
+++ b/layout/forms/nsComboboxControlFrame.h
@@ -0,0 +1,328 @@
+/* -*- 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/. */
+
+#ifndef nsComboboxControlFrame_h___
+#define nsComboboxControlFrame_h___
+
+#ifdef DEBUG_evaughan
+//#define DEBUG_rods
+#endif
+
+#ifdef DEBUG_rods
+//#define DO_REFLOW_DEBUG
+//#define DO_REFLOW_COUNTER
+//#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"
+#include "nsIFormControlFrame.h"
+#include "nsIComboboxControlFrame.h"
+#include "nsIAnonymousContentCreator.h"
+#include "nsISelectControlFrame.h"
+#include "nsIRollupListener.h"
+#include "nsIStatefulFrame.h"
+#include "nsThreadUtils.h"
+
+class nsStyleContext;
+class nsIListControlFrame;
+class nsComboboxDisplayFrame;
+class nsIDOMEventListener;
+class nsIScrollableFrame;
+
+namespace mozilla {
+namespace gfx {
+class DrawTarget;
+} // namespace gfx
+} // namespace mozilla
+
+class nsComboboxControlFrame final : public nsBlockFrame,
+ public nsIFormControlFrame,
+ public nsIComboboxControlFrame,
+ public nsIAnonymousContentCreator,
+ public nsISelectControlFrame,
+ public nsIRollupListener,
+ public nsIStatefulFrame
+{
+ typedef mozilla::gfx::DrawTarget DrawTarget;
+
+public:
+ friend nsContainerFrame* NS_NewComboboxControlFrame(nsIPresShell* aPresShell,
+ nsStyleContext* aContext,
+ nsFrameState aFlags);
+ friend class nsComboboxDisplayFrame;
+
+ explicit nsComboboxControlFrame(nsStyleContext* aContext);
+ ~nsComboboxControlFrame();
+
+ NS_DECL_QUERYFRAME
+ NS_DECL_FRAMEARENA_HELPERS
+
+ // nsIAnonymousContentCreator
+ virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
+ virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
+ uint32_t aFilter) override;
+ virtual nsIFrame* CreateFrameFor(nsIContent* aContent) override;
+
+#ifdef ACCESSIBILITY
+ virtual mozilla::a11y::AccType AccessibleType() override;
+#endif
+
+ virtual nscoord GetMinISize(nsRenderingContext *aRenderingContext) override;
+
+ virtual nscoord GetPrefISize(nsRenderingContext *aRenderingContext) override;
+
+ virtual void Reflow(nsPresContext* aCX,
+ ReflowOutput& aDesiredSize,
+ const ReflowInput& aReflowInput,
+ nsReflowStatus& aStatus) override;
+
+ virtual nsresult HandleEvent(nsPresContext* aPresContext,
+ mozilla::WidgetGUIEvent* aEvent,
+ nsEventStatus* aEventStatus) override;
+
+ virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
+ const nsRect& aDirtyRect,
+ const nsDisplayListSet& aLists) override;
+
+ void PaintFocus(DrawTarget& aDrawTarget, nsPoint aPt);
+
+ // XXXbz this is only needed to prevent the quirk percent height stuff from
+ // leaking out of the combobox. We may be able to get rid of this as more
+ // things move to IsFrameOfType.
+ virtual nsIAtom* GetType() const override;
+
+ virtual bool IsFrameOfType(uint32_t aFlags) const override
+ {
+ return nsBlockFrame::IsFrameOfType(aFlags &
+ ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
+ }
+
+ virtual nsIScrollableFrame* GetScrollTargetFrame() override {
+ return do_QueryFrame(mDropdownFrame);
+ }
+
+#ifdef DEBUG_FRAME_DUMP
+ virtual nsresult GetFrameName(nsAString& aResult) const override;
+#endif
+ virtual void DestroyFrom(nsIFrame* aDestructRoot) override;
+ virtual void SetInitialChildList(ChildListID aListID,
+ nsFrameList& aChildList) override;
+ virtual const nsFrameList& GetChildList(ChildListID aListID) const override;
+ virtual void GetChildLists(nsTArray<ChildList>* aLists) const override;
+
+ virtual nsContainerFrame* GetContentInsertionFrame() override;
+
+ // nsIFormControlFrame
+ virtual nsresult SetFormProperty(nsIAtom* aName, const nsAString& aValue) override;
+ /**
+ * 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|.
+ */
+ virtual void SetFocus(bool aOn, bool aRepaint) override;
+
+ //nsIComboboxControlFrame
+ virtual bool IsDroppedDown() override { return mDroppedDown; }
+ /**
+ * @note This method might destroy |this|.
+ */
+ virtual void ShowDropDown(bool aDoDropDown) override;
+ virtual nsIFrame* GetDropDown() override;
+ virtual void SetDropDown(nsIFrame* aDropDownFrame) override;
+ /**
+ * @note This method might destroy |this|.
+ */
+ virtual void RollupFromList() override;
+
+ /**
+ * Return the available space before and after this frame for
+ * 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);
+ virtual int32_t GetIndexOfDisplayArea() override;
+ /**
+ * @note This method might destroy |this|.
+ */
+ NS_IMETHOD RedisplaySelectedText() override;
+ virtual int32_t UpdateRecentIndex(int32_t aIndex) override;
+ virtual void OnContentReset() override;
+
+
+ bool IsOpenInParentProcess() override
+ {
+ return mIsOpenInParentProcess;
+ }
+
+ void SetOpenInParentProcess(bool aVal) override
+ {
+ mIsOpenInParentProcess = aVal;
+ }
+
+ // nsISelectControlFrame
+ NS_IMETHOD AddOption(int32_t index) override;
+ NS_IMETHOD RemoveOption(int32_t index) override;
+ NS_IMETHOD DoneAddingChildren(bool aIsDone) override;
+ NS_IMETHOD OnOptionSelected(int32_t aIndex, bool aSelected) override;
+ NS_IMETHOD OnSetSelectedIndex(int32_t aOldIndex, int32_t aNewIndex) override;
+
+ //nsIRollupListener
+ /**
+ * Hide the dropdown menu and stop capturing mouse events.
+ * @note This method might destroy |this|.
+ */
+ virtual bool Rollup(uint32_t aCount, bool aFlush,
+ const nsIntPoint* pos, nsIContent** aLastRolledUp) override;
+ virtual void NotifyGeometryChange() override;
+
+ /**
+ * A combobox should roll up if a mousewheel event happens outside of
+ * the popup area.
+ */
+ virtual bool ShouldRollupOnMouseWheelEvent() override
+ { return true; }
+
+ virtual bool ShouldConsumeOnMouseWheelEvent() override
+ { return false; }
+
+ /**
+ * A combobox should not roll up if activated by a mouse activate message
+ * (eg. X-mouse).
+ */
+ virtual bool ShouldRollupOnMouseActivate() override
+ { return false; }
+
+ virtual uint32_t GetSubmenuWidgetChain(nsTArray<nsIWidget*> *aWidgetChain) override
+ { return 0; }
+
+ virtual nsIWidget* GetRollupWidget() override;
+
+ //nsIStatefulFrame
+ NS_IMETHOD SaveState(nsPresState** aState) override;
+ NS_IMETHOD RestoreState(nsPresState* aState) override;
+ NS_IMETHOD GenerateStateKey(nsIContent* aContent,
+ nsIDocument* aDocument,
+ nsACString& aKey) override;
+
+ static bool ToolkitHasNativePopup();
+
+protected:
+ friend class RedisplayTextEvent;
+ friend class nsAsyncResize;
+ friend class nsResizeDropdownAtFinalPosition;
+
+ // Utilities
+ void ReflowDropdown(nsPresContext* aPresContext,
+ const ReflowInput& aReflowInput);
+
+ 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();
+
+ // Helper for GetMinISize/GetPrefISize
+ nscoord GetIntrinsicISize(nsRenderingContext* aRenderingContext,
+ nsLayoutUtils::IntrinsicISizeType aType);
+
+ class RedisplayTextEvent : public mozilla::Runnable {
+ public:
+ NS_DECL_NSIRUNNABLE
+ explicit RedisplayTextEvent(nsComboboxControlFrame *c) : mControlFrame(c) {}
+ void Revoke() { mControlFrame = nullptr; }
+ private:
+ nsComboboxControlFrame *mControlFrame;
+ };
+
+ /**
+ * Show or hide the dropdown list.
+ * @note This method might destroy |this|.
+ */
+ void ShowPopup(bool aShowPopup);
+
+ /**
+ * Show or hide the dropdown list.
+ * @param aShowList true to show, false to hide the dropdown.
+ * @note This method might destroy |this|.
+ * @return false if this frame is destroyed, true if still alive.
+ */
+ bool ShowList(bool aShowList);
+ void CheckFireOnChange();
+ void FireValueChangeEvent();
+ nsresult RedisplayText(int32_t aIndex);
+ void HandleRedisplayTextEvent();
+ void ActuallyDisplayText(bool aNotify);
+
+private:
+ // 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();
+
+protected:
+ nsFrameList mPopupFrames; // additional named child list
+ nsCOMPtr<nsIContent> mDisplayContent; // Anonymous content used to display the current selection
+ nsCOMPtr<nsIContent> mButtonContent; // Anonymous content for the button
+ nsContainerFrame* mDisplayFrame; // frame to display selection
+ nsIFrame* mButtonFrame; // button frame
+ nsIFrame* mDropdownFrame; // dropdown list frame
+ nsIListControlFrame * mListControlFrame; // ListControl Interface for the dropdown frame
+
+ // 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;
+
+ nsRevocableEventPtr<RedisplayTextEvent> mRedisplayTextEvent;
+
+ int32_t mRecentSelectedIndex;
+ int32_t mDisplayedIndex;
+ nsString mDisplayedOptionText;
+
+ // make someone to listen to the button. If its programmatically pressed by someone like Accessibility
+ // then open or close the combo box.
+ nsCOMPtr<nsIDOMEventListener> mButtonListener;
+
+ // The last y-positions used for estimating available space before and
+ // after for the dropdown list in GetAvailableDropdownSpace. These are
+ // reset to nscoord_MIN in AbsolutelyPositionDropDown when placing the
+ // dropdown at its actual position. The GetAvailableDropdownSpace call
+ // from nsListControlFrame::ReflowAsDropdown use the last position.
+ nscoord mLastDropDownBeforeScreenBCoord;
+ nscoord mLastDropDownAfterScreenBCoord;
+ // Current state of the dropdown list, true is dropped down.
+ bool mDroppedDown;
+ // See comment in HandleRedisplayTextEvent().
+ bool mInRedisplayText;
+ // Acting on ShowDropDown(true) is delayed until we're focused.
+ bool mDelayedShowDropDown;
+
+ 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
+};
+
+#endif