Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/layout/forms/nsComboboxControlFrame.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#ifndef nsComboboxControlFrame_h___
8
#define nsComboboxControlFrame_h___
9
10
#ifdef DEBUG_evaughan
11
//#define DEBUG_rods
12
#endif
13
14
#ifdef DEBUG_rods
15
//#define DO_REFLOW_DEBUG
16
//#define DO_REFLOW_COUNTER
17
//#define DO_UNCONSTRAINED_CHECK
18
//#define DO_PIXELS
19
//#define DO_NEW_REFLOW
20
#endif
21
22
//Mark used to indicate when onchange has been fired for current combobox item
23
0
#define NS_SKIP_NOTIFY_INDEX -2
24
25
#include "mozilla/Attributes.h"
26
#include "nsBlockFrame.h"
27
#include "nsIFormControlFrame.h"
28
#include "nsIComboboxControlFrame.h"
29
#include "nsIAnonymousContentCreator.h"
30
#include "nsISelectControlFrame.h"
31
#include "nsIRollupListener.h"
32
#include "nsIStatefulFrame.h"
33
#include "nsThreadUtils.h"
34
35
class nsIListControlFrame;
36
class nsComboboxDisplayFrame;
37
class nsIDOMEventListener;
38
class nsIScrollableFrame;
39
class nsTextNode;
40
41
namespace mozilla {
42
namespace gfx {
43
class DrawTarget;
44
} // namespace gfx
45
} // namespace mozilla
46
47
class nsComboboxControlFrame final : public nsBlockFrame,
48
                                     public nsIFormControlFrame,
49
                                     public nsIComboboxControlFrame,
50
                                     public nsIAnonymousContentCreator,
51
                                     public nsISelectControlFrame,
52
                                     public nsIRollupListener,
53
                                     public nsIStatefulFrame
54
{
55
  typedef mozilla::gfx::DrawTarget DrawTarget;
56
57
public:
58
  friend nsComboboxControlFrame* NS_NewComboboxControlFrame(nsIPresShell* aPresShell,
59
                                                            ComputedStyle* aStyle,
60
                                                            nsFrameState aFlags);
61
  friend class nsComboboxDisplayFrame;
62
63
  explicit nsComboboxControlFrame(ComputedStyle* aStyle);
64
  ~nsComboboxControlFrame();
65
66
  NS_DECL_QUERYFRAME
67
  NS_DECL_FRAMEARENA_HELPERS(nsComboboxControlFrame)
68
69
  // nsIAnonymousContentCreator
70
  virtual nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) override;
71
  virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
72
                                        uint32_t aFilter) override;
73
74
  nsIContent* GetDisplayNode() const;
75
  nsIFrame* CreateFrameForDisplayNode();
76
77
#ifdef ACCESSIBILITY
78
  virtual mozilla::a11y::AccType AccessibleType() override;
79
#endif
80
81
  virtual nscoord GetMinISize(gfxContext *aRenderingContext) override;
82
83
  virtual nscoord GetPrefISize(gfxContext *aRenderingContext) override;
84
85
  virtual void Reflow(nsPresContext*           aCX,
86
                      ReflowOutput&     aDesiredSize,
87
                      const ReflowInput& aReflowInput,
88
                      nsReflowStatus&          aStatus) override;
89
90
  virtual nsresult HandleEvent(nsPresContext* aPresContext,
91
                               mozilla::WidgetGUIEvent* aEvent,
92
                               nsEventStatus* aEventStatus) override;
93
94
  virtual void BuildDisplayList(nsDisplayListBuilder*   aBuilder,
95
                                const nsDisplayListSet& aLists) override;
96
97
  void PaintFocus(DrawTarget& aDrawTarget, nsPoint aPt);
98
99
  virtual bool IsFrameOfType(uint32_t aFlags) const override
100
0
  {
101
0
    return nsBlockFrame::IsFrameOfType(aFlags &
102
0
      ~(nsIFrame::eReplaced | nsIFrame::eReplacedContainsBlock));
103
0
  }
104
105
0
  virtual nsIScrollableFrame* GetScrollTargetFrame() override {
106
0
    return do_QueryFrame(mDropdownFrame);
107
0
  }
108
109
#ifdef DEBUG_FRAME_DUMP
110
  virtual nsresult GetFrameName(nsAString& aResult) const override;
111
#endif
112
  virtual void DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData) override;
113
  virtual void SetInitialChildList(ChildListID     aListID,
114
                                   nsFrameList&    aChildList) override;
115
  virtual const nsFrameList& GetChildList(ChildListID aListID) const override;
116
  virtual void GetChildLists(nsTArray<ChildList>* aLists) const override;
117
118
  virtual nsContainerFrame* GetContentInsertionFrame() override;
119
120
  // Return the dropdown and display frame.
121
  void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) override;
122
123
  // nsIFormControlFrame
124
  virtual nsresult SetFormProperty(nsAtom* aName, const nsAString& aValue) override;
125
  /**
126
   * Inform the control that it got (or lost) focus.
127
   * If it lost focus, the dropdown menu will be rolled up if needed,
128
   * and FireOnChange() will be called.
129
   * @param aOn true if got focus, false if lost focus.
130
   * @param aRepaint if true then force repaint (NOTE: we always force repaint currently)
131
   * @note This method might destroy |this|.
132
   */
133
  virtual void SetFocus(bool aOn, bool aRepaint) override;
134
135
  //nsIComboboxControlFrame
136
0
  virtual bool IsDroppedDown() override { return mDroppedDown; }
137
  /**
138
   * @note This method might destroy |this|.
139
   */
140
  virtual void ShowDropDown(bool aDoDropDown) override;
141
  virtual nsIFrame* GetDropDown() override;
142
  virtual void SetDropDown(nsIFrame* aDropDownFrame) override;
143
  /**
144
   * @note This method might destroy |this|.
145
   */
146
  virtual void RollupFromList() override;
147
148
  /**
149
   * Return the available space before and after this frame for
150
   * placing the drop-down list, and the current 2D translation.
151
   * Note that either or both can be less than or equal to zero,
152
   * if both are then the drop-down should be closed.
153
   */
154
  void GetAvailableDropdownSpace(mozilla::WritingMode aWM,
155
                                 nscoord* aBefore,
156
                                 nscoord* aAfter,
157
                                 mozilla::LogicalPoint* aTranslation);
158
  virtual int32_t GetIndexOfDisplayArea() override;
159
  /**
160
   * @note This method might destroy |this|.
161
   */
162
  NS_IMETHOD RedisplaySelectedText() override;
163
  virtual int32_t UpdateRecentIndex(int32_t aIndex) override;
164
  virtual void OnContentReset() override;
165
166
167
  bool IsOpenInParentProcess() override
168
0
  {
169
0
    return mIsOpenInParentProcess;
170
0
  }
171
172
  void SetOpenInParentProcess(bool aVal) override
173
0
  {
174
0
    mIsOpenInParentProcess = aVal;
175
0
  }
176
177
  // nsISelectControlFrame
178
  NS_IMETHOD AddOption(int32_t index) override;
179
  NS_IMETHOD RemoveOption(int32_t index) override;
180
  NS_IMETHOD DoneAddingChildren(bool aIsDone) override;
181
  NS_IMETHOD OnOptionSelected(int32_t aIndex, bool aSelected) override;
182
  NS_IMETHOD OnSetSelectedIndex(int32_t aOldIndex, int32_t aNewIndex) override;
183
184
  //nsIRollupListener
185
  /**
186
   * Hide the dropdown menu and stop capturing mouse events.
187
   * @note This method might destroy |this|.
188
   */
189
  virtual bool Rollup(uint32_t aCount, bool aFlush,
190
                      const nsIntPoint* pos, nsIContent** aLastRolledUp) override;
191
  virtual void NotifyGeometryChange() override;
192
193
  /**
194
   * A combobox should roll up if a mousewheel event happens outside of
195
   * the popup area.
196
   */
197
  virtual bool ShouldRollupOnMouseWheelEvent() override
198
0
    { return true; }
199
200
  virtual bool ShouldConsumeOnMouseWheelEvent() override
201
0
    { return false; }
202
203
  /**
204
   * A combobox should not roll up if activated by a mouse activate message
205
   * (eg. X-mouse).
206
   */
207
  virtual bool ShouldRollupOnMouseActivate() override
208
0
    { return false; }
209
210
  virtual uint32_t GetSubmenuWidgetChain(nsTArray<nsIWidget*> *aWidgetChain) override
211
0
    { return 0; }
212
213
  virtual nsIWidget* GetRollupWidget() override;
214
215
  //nsIStatefulFrame
216
  mozilla::UniquePtr<mozilla::PresState> SaveState() override;
217
  NS_IMETHOD RestoreState(mozilla::PresState* aState) override;
218
  NS_IMETHOD GenerateStateKey(nsIContent* aContent,
219
                              nsIDocument* aDocument,
220
                              nsACString& aKey) override;
221
222
  static bool ToolkitHasNativePopup();
223
224
protected:
225
  friend class RedisplayTextEvent;
226
  friend class nsAsyncResize;
227
  friend class nsResizeDropdownAtFinalPosition;
228
229
  // Utilities
230
  void ReflowDropdown(nsPresContext*          aPresContext,
231
                      const ReflowInput& aReflowInput);
232
233
  // Return true if we should render a dropdown button.
234
  bool HasDropDownButton() const;
235
236
  enum DropDownPositionState {
237
    // can't show the dropdown at its current position
238
    eDropDownPositionSuppressed,
239
    // a resize reflow is pending, don't show it yet
240
    eDropDownPositionPendingResize,
241
    // the dropdown has its final size and position and can be displayed here
242
    eDropDownPositionFinal
243
  };
244
  DropDownPositionState AbsolutelyPositionDropDown();
245
246
  // Helper for GetMinISize/GetPrefISize
247
  nscoord GetIntrinsicISize(gfxContext* aRenderingContext,
248
                            nsLayoutUtils::IntrinsicISizeType aType);
249
250
  class RedisplayTextEvent : public mozilla::Runnable {
251
  public:
252
    NS_DECL_NSIRUNNABLE
253
    explicit RedisplayTextEvent(nsComboboxControlFrame* c)
254
      : mozilla::Runnable("nsComboboxControlFrame::RedisplayTextEvent")
255
      , mControlFrame(c)
256
0
    {
257
0
    }
258
0
    void Revoke() { mControlFrame = nullptr; }
259
  private:
260
    nsComboboxControlFrame *mControlFrame;
261
  };
262
263
  /**
264
   * Show or hide the dropdown list.
265
   * @note This method might destroy |this|.
266
   */
267
  void ShowPopup(bool aShowPopup);
268
269
  /**
270
   * Show or hide the dropdown list.
271
   * @param aShowList true to show, false to hide the dropdown.
272
   * @note This method might destroy |this|.
273
   * @return false if this frame is destroyed, true if still alive.
274
   */
275
  bool ShowList(bool aShowList);
276
  void CheckFireOnChange();
277
  void FireValueChangeEvent();
278
  nsresult RedisplayText();
279
  void HandleRedisplayTextEvent();
280
  void ActuallyDisplayText(bool aNotify);
281
282
private:
283
  // If our total transform to the root frame of the root document is only a 2d
284
  // translation then return that translation, otherwise returns (0,0).
285
  nsPoint GetCSSTransformTranslation();
286
287
protected:
288
  nsFrameList              mPopupFrames;             // additional named child list
289
  RefPtr<nsTextNode>       mDisplayContent;          // Anonymous content used to display the current selection
290
  RefPtr<Element>     mButtonContent;                // Anonymous content for the button
291
  nsContainerFrame*        mDisplayFrame;            // frame to display selection
292
  nsIFrame*                mButtonFrame;             // button frame
293
  nsIFrame*                mDropdownFrame;           // dropdown list frame
294
  nsIListControlFrame *    mListControlFrame;        // ListControl Interface for the dropdown frame
295
296
  // The inline size of our display area.  Used by that frame's reflow
297
  // to size to the full inline size except the drop-marker.
298
  nscoord mDisplayISize;
299
300
  nsRevocableEventPtr<RedisplayTextEvent> mRedisplayTextEvent;
301
302
  int32_t               mRecentSelectedIndex;
303
  int32_t               mDisplayedIndex;
304
  nsString              mDisplayedOptionTextOrPreview;
305
306
  // make someone to listen to the button. If its programmatically pressed by someone like Accessibility
307
  // then open or close the combo box.
308
  nsCOMPtr<nsIDOMEventListener> mButtonListener;
309
310
  // The last y-positions used for estimating available space before and
311
  // after for the dropdown list in GetAvailableDropdownSpace.  These are
312
  // reset to nscoord_MIN in AbsolutelyPositionDropDown when placing the
313
  // dropdown at its actual position.  The GetAvailableDropdownSpace call
314
  // from nsListControlFrame::ReflowAsDropdown use the last position.
315
  nscoord               mLastDropDownBeforeScreenBCoord;
316
  nscoord               mLastDropDownAfterScreenBCoord;
317
  // Current state of the dropdown list, true is dropped down.
318
  bool                  mDroppedDown;
319
  // See comment in HandleRedisplayTextEvent().
320
  bool                  mInRedisplayText;
321
  // Acting on ShowDropDown(true) is delayed until we're focused.
322
  bool                  mDelayedShowDropDown;
323
324
  bool                  mIsOpenInParentProcess;
325
326
  // static class data member for Bug 32920
327
  // only one control can be focused at a time
328
  static nsComboboxControlFrame* sFocused;
329
330
#ifdef DO_REFLOW_COUNTER
331
  int32_t mReflowId;
332
#endif
333
};
334
335
#endif