Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/layout/forms/nsCheckboxRadioFrame.cpp
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
#include "nsCheckboxRadioFrame.h"
8
9
#include "nsGkAtoms.h"
10
#include "nsLayoutUtils.h"
11
#include "mozilla/dom/HTMLInputElement.h"
12
#include "mozilla/EventStateManager.h"
13
#include "mozilla/LookAndFeel.h"
14
#include "nsDeviceContext.h"
15
#include "nsIContent.h"
16
#include "nsStyleConsts.h"
17
18
using namespace mozilla;
19
using mozilla::dom::HTMLInputElement;
20
21
//#define FCF_NOISY
22
23
nsCheckboxRadioFrame*
24
NS_NewCheckboxRadioFrame(nsIPresShell* aPresShell, ComputedStyle* aStyle)
25
0
{
26
0
  return new (aPresShell) nsCheckboxRadioFrame(aStyle);
27
0
}
28
29
nsCheckboxRadioFrame::nsCheckboxRadioFrame(ComputedStyle* aStyle)
30
  : nsAtomicContainerFrame(aStyle, kClassID)
31
0
{
32
0
}
33
34
nsCheckboxRadioFrame::~nsCheckboxRadioFrame()
35
0
{
36
0
}
37
38
void
39
nsCheckboxRadioFrame::DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData)
40
0
{
41
0
  // Unregister the access key registered in reflow
42
0
  nsCheckboxRadioFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), false);
43
0
  nsAtomicContainerFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
44
0
}
45
46
NS_IMPL_FRAMEARENA_HELPERS(nsCheckboxRadioFrame)
47
48
0
NS_QUERYFRAME_HEAD(nsCheckboxRadioFrame)
49
0
  NS_QUERYFRAME_ENTRY(nsIFormControlFrame)
50
0
NS_QUERYFRAME_TAIL_INHERITING(nsAtomicContainerFrame)
51
52
/* virtual */ nscoord
53
nsCheckboxRadioFrame::GetMinISize(gfxContext *aRenderingContext)
54
0
{
55
0
  nscoord result;
56
0
  DISPLAY_MIN_INLINE_SIZE(this, result);
57
0
  result = StyleDisplay()->HasAppearance() ? DefaultSize() : 0;
58
0
  return result;
59
0
}
60
61
/* virtual */ nscoord
62
nsCheckboxRadioFrame::GetPrefISize(gfxContext* aRenderingContext)
63
0
{
64
0
  nscoord result;
65
0
  DISPLAY_PREF_INLINE_SIZE(this, result);
66
0
  result = StyleDisplay()->HasAppearance() ? DefaultSize() : 0;
67
0
  return result;
68
0
}
69
70
/* virtual */
71
LogicalSize
72
nsCheckboxRadioFrame::ComputeAutoSize(gfxContext*         aRC,
73
                                      WritingMode         aWM,
74
                                      const LogicalSize&  aCBSize,
75
                                      nscoord             aAvailableISize,
76
                                      const LogicalSize&  aMargin,
77
                                      const LogicalSize&  aBorder,
78
                                      const LogicalSize&  aPadding,
79
                                      ComputeSizeFlags    aFlags)
80
0
{
81
0
  LogicalSize size(aWM, 0, 0);
82
0
  if (!StyleDisplay()->HasAppearance()) {
83
0
    return size;
84
0
  }
85
0
86
0
  // Note: this call always set the BSize to NS_UNCONSTRAINEDSIZE.
87
0
  size = nsAtomicContainerFrame::ComputeAutoSize(aRC, aWM, aCBSize,
88
0
                                                 aAvailableISize, aMargin,
89
0
                                                 aBorder, aPadding, aFlags);
90
0
  size.BSize(aWM) = DefaultSize();
91
0
  return size;
92
0
}
93
94
nscoord
95
nsCheckboxRadioFrame::GetLogicalBaseline(WritingMode aWritingMode) const
96
0
{
97
0
  NS_ASSERTION(!NS_SUBTREE_DIRTY(this),
98
0
               "frame must not be dirty");
99
0
100
0
  // For appearance:none we use a standard CSS baseline, i.e. synthesized from
101
0
  // our margin-box.
102
0
  if (!StyleDisplay()->HasAppearance()) {
103
0
    return nsAtomicContainerFrame::GetLogicalBaseline(aWritingMode);
104
0
  }
105
0
106
0
  // This is for compatibility with Chrome, Safari and Edge (Dec 2016).
107
0
  // Treat radio buttons and checkboxes as having an intrinsic baseline
108
0
  // at the block-end of the control (use the block-end content edge rather
109
0
  // than the margin edge).
110
0
  // For "inverted" lines (typically in writing-mode:vertical-lr), use the
111
0
  // block-start end instead.
112
0
  return aWritingMode.IsLineInverted()
113
0
    ? GetLogicalUsedBorderAndPadding(aWritingMode).BStart(aWritingMode)
114
0
    : BSize(aWritingMode) -
115
0
         GetLogicalUsedBorderAndPadding(aWritingMode).BEnd(aWritingMode);
116
0
}
117
118
void
119
nsCheckboxRadioFrame::Reflow(nsPresContext*     aPresContext,
120
                             ReflowOutput&      aDesiredSize,
121
                             const ReflowInput& aReflowInput,
122
                             nsReflowStatus&    aStatus)
123
0
{
124
0
  MarkInReflow();
125
0
  DO_GLOBAL_REFLOW_COUNT("nsCheckboxRadioFrame");
126
0
  DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
127
0
  MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");
128
0
  NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
129
0
                 ("enter nsCheckboxRadioFrame::Reflow: aMaxSize=%d,%d",
130
0
                  aReflowInput.AvailableWidth(), aReflowInput.AvailableHeight()));
131
0
132
0
  if (mState & NS_FRAME_FIRST_REFLOW) {
133
0
    RegUnRegAccessKey(static_cast<nsIFrame*>(this), true);
134
0
  }
135
0
136
0
  aDesiredSize.SetSize(aReflowInput.GetWritingMode(),
137
0
                       aReflowInput.ComputedSizeWithBorderPadding());
138
0
139
0
  if (nsLayoutUtils::FontSizeInflationEnabled(aPresContext)) {
140
0
    float inflation = nsLayoutUtils::FontSizeInflationFor(this);
141
0
    aDesiredSize.Width() *= inflation;
142
0
    aDesiredSize.Height() *= inflation;
143
0
  }
144
0
145
0
  NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
146
0
                 ("exit nsCheckboxRadioFrame::Reflow: size=%d,%d",
147
0
                  aDesiredSize.Width(), aDesiredSize.Height()));
148
0
  NS_FRAME_SET_TRUNCATION(aStatus, aReflowInput, aDesiredSize);
149
0
150
0
  aDesiredSize.SetOverflowAreasToDesiredBounds();
151
0
  FinishAndStoreOverflow(&aDesiredSize);
152
0
}
153
154
nsresult
155
nsCheckboxRadioFrame::RegUnRegAccessKey(nsIFrame* aFrame, bool aDoReg)
156
0
{
157
0
  NS_ENSURE_ARG_POINTER(aFrame);
158
0
159
0
  nsPresContext* presContext = aFrame->PresContext();
160
0
161
0
  NS_ASSERTION(presContext, "aPresContext is NULL in RegUnRegAccessKey!");
162
0
163
0
  nsAutoString accessKey;
164
0
165
0
  Element* content = aFrame->GetContent()->AsElement();
166
0
  content->GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey, accessKey);
167
0
  if (!accessKey.IsEmpty()) {
168
0
    EventStateManager* stateManager = presContext->EventStateManager();
169
0
    if (aDoReg) {
170
0
      stateManager->RegisterAccessKey(content, (uint32_t)accessKey.First());
171
0
    } else {
172
0
      stateManager->UnregisterAccessKey(content, (uint32_t)accessKey.First());
173
0
    }
174
0
    return NS_OK;
175
0
  }
176
0
  return NS_ERROR_FAILURE;
177
0
}
178
179
void
180
nsCheckboxRadioFrame::SetFocus(bool aOn, bool aRepaint)
181
0
{
182
0
}
183
184
nsresult
185
nsCheckboxRadioFrame::HandleEvent(nsPresContext* aPresContext,
186
                                  WidgetGUIEvent* aEvent,
187
                                  nsEventStatus* aEventStatus)
188
0
{
189
0
  // Check for disabled content so that selection works properly (?).
190
0
  if (IsContentDisabled()) {
191
0
    return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
192
0
  }
193
0
  return NS_OK;
194
0
}
195
196
void
197
nsCheckboxRadioFrame::GetCurrentCheckState(bool* aState)
198
0
{
199
0
  HTMLInputElement* inputElement = HTMLInputElement::FromNode(mContent);
200
0
  if (inputElement) {
201
0
    *aState = inputElement->Checked();
202
0
  }
203
0
}
204
205
nsresult
206
nsCheckboxRadioFrame::SetFormProperty(nsAtom* aName, const nsAString& aValue)
207
0
{
208
0
  return NS_OK;
209
0
}
210
211
// static
212
nsRect
213
nsCheckboxRadioFrame::GetUsableScreenRect(nsPresContext* aPresContext)
214
0
{
215
0
  nsRect screen;
216
0
217
0
  nsDeviceContext *context = aPresContext->DeviceContext();
218
0
  int32_t dropdownCanOverlapOSBar =
219
0
    LookAndFeel::GetInt(LookAndFeel::eIntID_MenusCanOverlapOSBar, 0);
220
0
  if ( dropdownCanOverlapOSBar )
221
0
    context->GetRect(screen);
222
0
  else
223
0
    context->GetClientRect(screen);
224
0
225
0
  return screen;
226
0
}