1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/forms/nsComboboxControlFrame.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,300 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#ifndef nsComboboxControlFrame_h___ 1.10 +#define nsComboboxControlFrame_h___ 1.11 + 1.12 +#ifdef DEBUG_evaughan 1.13 +//#define DEBUG_rods 1.14 +#endif 1.15 + 1.16 +#ifdef DEBUG_rods 1.17 +//#define DO_REFLOW_DEBUG 1.18 +//#define DO_REFLOW_COUNTER 1.19 +//#define DO_UNCONSTRAINED_CHECK 1.20 +//#define DO_PIXELS 1.21 +//#define DO_NEW_REFLOW 1.22 +#endif 1.23 + 1.24 +//Mark used to indicate when onchange has been fired for current combobox item 1.25 +#define NS_SKIP_NOTIFY_INDEX -2 1.26 + 1.27 +#include "mozilla/Attributes.h" 1.28 +#include "nsBlockFrame.h" 1.29 +#include "nsIFormControlFrame.h" 1.30 +#include "nsIComboboxControlFrame.h" 1.31 +#include "nsIAnonymousContentCreator.h" 1.32 +#include "nsISelectControlFrame.h" 1.33 +#include "nsIRollupListener.h" 1.34 +#include "nsIStatefulFrame.h" 1.35 +#include "nsThreadUtils.h" 1.36 + 1.37 +class nsStyleContext; 1.38 +class nsIListControlFrame; 1.39 +class nsComboboxDisplayFrame; 1.40 +class nsIDOMEventListener; 1.41 +class nsIScrollableFrame; 1.42 + 1.43 +class nsComboboxControlFrame : public nsBlockFrame, 1.44 + public nsIFormControlFrame, 1.45 + public nsIComboboxControlFrame, 1.46 + public nsIAnonymousContentCreator, 1.47 + public nsISelectControlFrame, 1.48 + public nsIRollupListener, 1.49 + public nsIStatefulFrame 1.50 +{ 1.51 +public: 1.52 + friend nsIFrame* NS_NewComboboxControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext, nsFrameState aFlags); 1.53 + friend class nsComboboxDisplayFrame; 1.54 + 1.55 + nsComboboxControlFrame(nsStyleContext* aContext); 1.56 + ~nsComboboxControlFrame(); 1.57 + 1.58 + NS_DECL_QUERYFRAME 1.59 + NS_DECL_FRAMEARENA_HELPERS 1.60 + 1.61 + // nsIAnonymousContentCreator 1.62 + virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) MOZ_OVERRIDE; 1.63 + virtual void AppendAnonymousContentTo(nsBaseContentList& aElements, 1.64 + uint32_t aFilter) MOZ_OVERRIDE; 1.65 + virtual nsIFrame* CreateFrameFor(nsIContent* aContent) MOZ_OVERRIDE; 1.66 + 1.67 +#ifdef ACCESSIBILITY 1.68 + virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE; 1.69 +#endif 1.70 + 1.71 + virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE; 1.72 + 1.73 + virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE; 1.74 + 1.75 + virtual nsresult Reflow(nsPresContext* aCX, 1.76 + nsHTMLReflowMetrics& aDesiredSize, 1.77 + const nsHTMLReflowState& aReflowState, 1.78 + nsReflowStatus& aStatus) MOZ_OVERRIDE; 1.79 + 1.80 + virtual nsresult HandleEvent(nsPresContext* aPresContext, 1.81 + mozilla::WidgetGUIEvent* aEvent, 1.82 + nsEventStatus* aEventStatus) MOZ_OVERRIDE; 1.83 + 1.84 + virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, 1.85 + const nsRect& aDirtyRect, 1.86 + const nsDisplayListSet& aLists) MOZ_OVERRIDE; 1.87 + 1.88 + void PaintFocus(nsRenderingContext& aRenderingContext, nsPoint aPt); 1.89 + 1.90 + // XXXbz this is only needed to prevent the quirk percent height stuff from 1.91 + // leaking out of the combobox. We may be able to get rid of this as more 1.92 + // things move to IsFrameOfType. 1.93 + virtual nsIAtom* GetType() const MOZ_OVERRIDE; 1.94 + 1.95 + virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE 1.96 + { 1.97 + return nsBlockFrame::IsFrameOfType(aFlags & 1.98 + ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock)); 1.99 + } 1.100 + 1.101 + virtual nsIScrollableFrame* GetScrollTargetFrame() MOZ_OVERRIDE { 1.102 + return do_QueryFrame(mDropdownFrame); 1.103 + } 1.104 + 1.105 +#ifdef DEBUG_FRAME_DUMP 1.106 + virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; 1.107 +#endif 1.108 + virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE; 1.109 + virtual nsresult SetInitialChildList(ChildListID aListID, 1.110 + nsFrameList& aChildList) MOZ_OVERRIDE; 1.111 + virtual const nsFrameList& GetChildList(ChildListID aListID) const MOZ_OVERRIDE; 1.112 + virtual void GetChildLists(nsTArray<ChildList>* aLists) const MOZ_OVERRIDE; 1.113 + 1.114 + virtual nsIFrame* GetContentInsertionFrame() MOZ_OVERRIDE; 1.115 + 1.116 + // nsIFormControlFrame 1.117 + virtual nsresult SetFormProperty(nsIAtom* aName, const nsAString& aValue) MOZ_OVERRIDE; 1.118 + /** 1.119 + * Inform the control that it got (or lost) focus. 1.120 + * If it lost focus, the dropdown menu will be rolled up if needed, 1.121 + * and FireOnChange() will be called. 1.122 + * @param aOn true if got focus, false if lost focus. 1.123 + * @param aRepaint if true then force repaint (NOTE: we always force repaint currently) 1.124 + * @note This method might destroy |this|. 1.125 + */ 1.126 + virtual void SetFocus(bool aOn, bool aRepaint) MOZ_OVERRIDE; 1.127 + 1.128 + //nsIComboboxControlFrame 1.129 + virtual bool IsDroppedDown() MOZ_OVERRIDE { return mDroppedDown; } 1.130 + /** 1.131 + * @note This method might destroy |this|. 1.132 + */ 1.133 + virtual void ShowDropDown(bool aDoDropDown) MOZ_OVERRIDE; 1.134 + virtual nsIFrame* GetDropDown() MOZ_OVERRIDE; 1.135 + virtual void SetDropDown(nsIFrame* aDropDownFrame) MOZ_OVERRIDE; 1.136 + /** 1.137 + * @note This method might destroy |this|. 1.138 + */ 1.139 + virtual void RollupFromList() MOZ_OVERRIDE; 1.140 + 1.141 + /** 1.142 + * Return the available space above and below this frame for 1.143 + * placing the drop-down list, and the current 2D translation. 1.144 + * Note that either or both can be less than or equal to zero, 1.145 + * if both are then the drop-down should be closed. 1.146 + */ 1.147 + void GetAvailableDropdownSpace(nscoord* aAbove, 1.148 + nscoord* aBelow, 1.149 + nsPoint* aTranslation); 1.150 + virtual int32_t GetIndexOfDisplayArea() MOZ_OVERRIDE; 1.151 + /** 1.152 + * @note This method might destroy |this|. 1.153 + */ 1.154 + NS_IMETHOD RedisplaySelectedText() MOZ_OVERRIDE; 1.155 + virtual int32_t UpdateRecentIndex(int32_t aIndex) MOZ_OVERRIDE; 1.156 + virtual void OnContentReset() MOZ_OVERRIDE; 1.157 + 1.158 + // nsISelectControlFrame 1.159 + NS_IMETHOD AddOption(int32_t index) MOZ_OVERRIDE; 1.160 + NS_IMETHOD RemoveOption(int32_t index) MOZ_OVERRIDE; 1.161 + NS_IMETHOD DoneAddingChildren(bool aIsDone) MOZ_OVERRIDE; 1.162 + NS_IMETHOD OnOptionSelected(int32_t aIndex, bool aSelected) MOZ_OVERRIDE; 1.163 + NS_IMETHOD OnSetSelectedIndex(int32_t aOldIndex, int32_t aNewIndex) MOZ_OVERRIDE; 1.164 + 1.165 + //nsIRollupListener 1.166 + /** 1.167 + * Hide the dropdown menu and stop capturing mouse events. 1.168 + * @note This method might destroy |this|. 1.169 + */ 1.170 + virtual bool Rollup(uint32_t aCount, const nsIntPoint* pos, nsIContent** aLastRolledUp) MOZ_OVERRIDE; 1.171 + virtual void NotifyGeometryChange() MOZ_OVERRIDE; 1.172 + 1.173 + /** 1.174 + * A combobox should roll up if a mousewheel event happens outside of 1.175 + * the popup area. 1.176 + */ 1.177 + virtual bool ShouldRollupOnMouseWheelEvent() MOZ_OVERRIDE 1.178 + { return true; } 1.179 + 1.180 + virtual bool ShouldConsumeOnMouseWheelEvent() MOZ_OVERRIDE 1.181 + { return false; } 1.182 + 1.183 + /** 1.184 + * A combobox should not roll up if activated by a mouse activate message 1.185 + * (eg. X-mouse). 1.186 + */ 1.187 + virtual bool ShouldRollupOnMouseActivate() MOZ_OVERRIDE 1.188 + { return false; } 1.189 + 1.190 + virtual uint32_t GetSubmenuWidgetChain(nsTArray<nsIWidget*> *aWidgetChain) MOZ_OVERRIDE 1.191 + { return 0; } 1.192 + 1.193 + virtual nsIWidget* GetRollupWidget() MOZ_OVERRIDE; 1.194 + 1.195 + //nsIStatefulFrame 1.196 + NS_IMETHOD SaveState(nsPresState** aState) MOZ_OVERRIDE; 1.197 + NS_IMETHOD RestoreState(nsPresState* aState) MOZ_OVERRIDE; 1.198 + 1.199 + static bool ToolkitHasNativePopup(); 1.200 + 1.201 +protected: 1.202 + friend class RedisplayTextEvent; 1.203 + friend class nsAsyncResize; 1.204 + friend class nsResizeDropdownAtFinalPosition; 1.205 + 1.206 + // Utilities 1.207 + nsresult ReflowDropdown(nsPresContext* aPresContext, 1.208 + const nsHTMLReflowState& aReflowState); 1.209 + 1.210 + enum DropDownPositionState { 1.211 + // can't show the dropdown at its current position 1.212 + eDropDownPositionSuppressed, 1.213 + // a resize reflow is pending, don't show it yet 1.214 + eDropDownPositionPendingResize, 1.215 + // the dropdown has its final size and position and can be displayed here 1.216 + eDropDownPositionFinal 1.217 + }; 1.218 + DropDownPositionState AbsolutelyPositionDropDown(); 1.219 + 1.220 + // Helper for GetMinWidth/GetPrefWidth 1.221 + nscoord GetIntrinsicWidth(nsRenderingContext* aRenderingContext, 1.222 + nsLayoutUtils::IntrinsicWidthType aType); 1.223 + 1.224 + class RedisplayTextEvent : public nsRunnable { 1.225 + public: 1.226 + NS_DECL_NSIRUNNABLE 1.227 + RedisplayTextEvent(nsComboboxControlFrame *c) : mControlFrame(c) {} 1.228 + void Revoke() { mControlFrame = nullptr; } 1.229 + private: 1.230 + nsComboboxControlFrame *mControlFrame; 1.231 + }; 1.232 + 1.233 + /** 1.234 + * Show or hide the dropdown list. 1.235 + * @note This method might destroy |this|. 1.236 + */ 1.237 + void ShowPopup(bool aShowPopup); 1.238 + 1.239 + /** 1.240 + * Show or hide the dropdown list. 1.241 + * @param aShowList true to show, false to hide the dropdown. 1.242 + * @note This method might destroy |this|. 1.243 + * @return false if this frame is destroyed, true if still alive. 1.244 + */ 1.245 + bool ShowList(bool aShowList); 1.246 + void CheckFireOnChange(); 1.247 + void FireValueChangeEvent(); 1.248 + nsresult RedisplayText(int32_t aIndex); 1.249 + void HandleRedisplayTextEvent(); 1.250 + void ActuallyDisplayText(bool aNotify); 1.251 + 1.252 +private: 1.253 + // If our total transform to the root frame of the root document is only a 2d 1.254 + // translation then return that translation, otherwise returns (0,0). 1.255 + nsPoint GetCSSTransformTranslation(); 1.256 + 1.257 +protected: 1.258 + nsFrameList mPopupFrames; // additional named child list 1.259 + nsCOMPtr<nsIContent> mDisplayContent; // Anonymous content used to display the current selection 1.260 + nsCOMPtr<nsIContent> mButtonContent; // Anonymous content for the button 1.261 + nsIFrame* mDisplayFrame; // frame to display selection 1.262 + nsIFrame* mButtonFrame; // button frame 1.263 + nsIFrame* mDropdownFrame; // dropdown list frame 1.264 + nsIListControlFrame * mListControlFrame; // ListControl Interface for the dropdown frame 1.265 + 1.266 + // The width of our display area. Used by that frame's reflow to 1.267 + // size to the full width except the drop-marker. 1.268 + nscoord mDisplayWidth; 1.269 + 1.270 + nsRevocableEventPtr<RedisplayTextEvent> mRedisplayTextEvent; 1.271 + 1.272 + int32_t mRecentSelectedIndex; 1.273 + int32_t mDisplayedIndex; 1.274 + nsString mDisplayedOptionText; 1.275 + 1.276 + // make someone to listen to the button. If its programmatically pressed by someone like Accessibility 1.277 + // then open or close the combo box. 1.278 + nsCOMPtr<nsIDOMEventListener> mButtonListener; 1.279 + 1.280 + // The last y-positions used for estimating available space above and 1.281 + // below for the dropdown list in GetAvailableDropdownSpace. These are 1.282 + // reset to nscoord_MIN in AbsolutelyPositionDropDown when placing the 1.283 + // dropdown at its actual position. The GetAvailableDropdownSpace call 1.284 + // from nsListControlFrame::ReflowAsDropdown use the last position. 1.285 + nscoord mLastDropDownAboveScreenY; 1.286 + nscoord mLastDropDownBelowScreenY; 1.287 + // Current state of the dropdown list, true is dropped down. 1.288 + bool mDroppedDown; 1.289 + // See comment in HandleRedisplayTextEvent(). 1.290 + bool mInRedisplayText; 1.291 + // Acting on ShowDropDown(true) is delayed until we're focused. 1.292 + bool mDelayedShowDropDown; 1.293 + 1.294 + // static class data member for Bug 32920 1.295 + // only one control can be focused at a time 1.296 + static nsComboboxControlFrame* sFocused; 1.297 + 1.298 +#ifdef DO_REFLOW_COUNTER 1.299 + int32_t mReflowId; 1.300 +#endif 1.301 +}; 1.302 + 1.303 +#endif