Bumping manifests a=b2g-bump
[gecko.git] / layout / xul / nsScrollbarButtonFrame.cpp
blob22117a8ccbce30220c2040be8814f29e51cb461a
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 //
7 // Eric Vaughan
8 // Netscape Communications
9 //
10 // See documentation in associated header file
13 #include "nsScrollbarButtonFrame.h"
14 #include "nsPresContext.h"
15 #include "nsIContent.h"
16 #include "nsCOMPtr.h"
17 #include "nsNameSpaceManager.h"
18 #include "nsGkAtoms.h"
19 #include "nsSliderFrame.h"
20 #include "nsScrollbarFrame.h"
21 #include "nsIScrollbarMediator.h"
22 #include "nsRepeatService.h"
23 #include "mozilla/LookAndFeel.h"
24 #include "mozilla/MouseEvents.h"
26 using namespace mozilla;
29 // NS_NewToolbarFrame
31 // Creates a new Toolbar frame and returns it
33 nsIFrame*
34 NS_NewScrollbarButtonFrame (nsIPresShell* aPresShell, nsStyleContext* aContext)
36 return new (aPresShell) nsScrollbarButtonFrame(aContext);
39 NS_IMPL_FRAMEARENA_HELPERS(nsScrollbarButtonFrame)
41 nsresult
42 nsScrollbarButtonFrame::HandleEvent(nsPresContext* aPresContext,
43 WidgetGUIEvent* aEvent,
44 nsEventStatus* aEventStatus)
46 NS_ENSURE_ARG_POINTER(aEventStatus);
48 // If a web page calls event.preventDefault() we still want to
49 // scroll when scroll arrow is clicked. See bug 511075.
50 if (!mContent->IsInNativeAnonymousSubtree() &&
51 nsEventStatus_eConsumeNoDefault == *aEventStatus) {
52 return NS_OK;
55 switch (aEvent->message) {
56 case NS_MOUSE_BUTTON_DOWN:
57 mCursorOnThis = true;
58 // if we didn't handle the press ourselves, pass it on to the superclass
59 if (HandleButtonPress(aPresContext, aEvent, aEventStatus)) {
60 return NS_OK;
62 break;
63 case NS_MOUSE_BUTTON_UP:
64 HandleRelease(aPresContext, aEvent, aEventStatus);
65 break;
66 case NS_MOUSE_EXIT_SYNTH:
67 mCursorOnThis = false;
68 break;
69 case NS_MOUSE_MOVE: {
70 nsPoint cursor =
71 nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this);
72 nsRect frameRect(nsPoint(0, 0), GetSize());
73 mCursorOnThis = frameRect.Contains(cursor);
74 break;
78 return nsButtonBoxFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
81 bool
82 nsScrollbarButtonFrame::HandleButtonPress(nsPresContext* aPresContext,
83 WidgetGUIEvent* aEvent,
84 nsEventStatus* aEventStatus)
86 // Get the desired action for the scrollbar button.
87 LookAndFeel::IntID tmpAction;
88 uint16_t button = aEvent->AsMouseEvent()->button;
89 if (button == WidgetMouseEvent::eLeftButton) {
90 tmpAction = LookAndFeel::eIntID_ScrollButtonLeftMouseButtonAction;
91 } else if (button == WidgetMouseEvent::eMiddleButton) {
92 tmpAction = LookAndFeel::eIntID_ScrollButtonMiddleMouseButtonAction;
93 } else if (button == WidgetMouseEvent::eRightButton) {
94 tmpAction = LookAndFeel::eIntID_ScrollButtonRightMouseButtonAction;
95 } else {
96 return false;
99 // Get the button action metric from the pres. shell.
100 int32_t pressedButtonAction;
101 if (NS_FAILED(LookAndFeel::GetInt(tmpAction, &pressedButtonAction))) {
102 return false;
105 // get the scrollbar control
106 nsIFrame* scrollbar;
107 GetParentWithTag(nsGkAtoms::scrollbar, this, scrollbar);
109 if (scrollbar == nullptr)
110 return false;
112 static nsIContent::AttrValuesArray strings[] = { &nsGkAtoms::increment,
113 &nsGkAtoms::decrement,
114 nullptr };
115 int32_t index = mContent->FindAttrValueIn(kNameSpaceID_None,
116 nsGkAtoms::type,
117 strings, eCaseMatters);
118 int32_t direction;
119 if (index == 0)
120 direction = 1;
121 else if (index == 1)
122 direction = -1;
123 else
124 return false;
126 bool repeat = pressedButtonAction != 2;
127 // set this attribute so we can style it later
128 nsWeakFrame weakFrame(this);
129 mContent->SetAttr(kNameSpaceID_None, nsGkAtoms::active, NS_LITERAL_STRING("true"), true);
131 nsIPresShell::SetCapturingContent(mContent, CAPTURE_IGNOREALLOWED);
133 if (!weakFrame.IsAlive()) {
134 return false;
137 nsScrollbarFrame* sb = do_QueryFrame(scrollbar);
138 if (sb) {
139 nsIScrollbarMediator* m = sb->GetScrollbarMediator();
140 switch (pressedButtonAction) {
141 case 0:
142 sb->SetIncrementToLine(direction);
143 if (m) {
144 m->ScrollByLine(sb, direction);
146 break;
147 case 1:
148 sb->SetIncrementToPage(direction);
149 if (m) {
150 m->ScrollByPage(sb, direction);
152 break;
153 case 2:
154 sb->SetIncrementToWhole(direction);
155 if (m) {
156 m->ScrollByWhole(sb, direction);
158 break;
159 case 3:
160 default:
161 // We were told to ignore this click, or someone assigned a non-standard
162 // value to the button's action.
163 return false;
165 if (!weakFrame.IsAlive()) {
166 return false;
168 if (!m) {
169 sb->MoveToNewPosition();
170 if (!weakFrame.IsAlive()) {
171 return false;
175 if (repeat) {
176 StartRepeat();
178 return true;
181 NS_IMETHODIMP
182 nsScrollbarButtonFrame::HandleRelease(nsPresContext* aPresContext,
183 WidgetGUIEvent* aEvent,
184 nsEventStatus* aEventStatus)
186 nsIPresShell::SetCapturingContent(nullptr, 0);
187 // we're not active anymore
188 mContent->UnsetAttr(kNameSpaceID_None, nsGkAtoms::active, true);
189 StopRepeat();
190 return NS_OK;
193 void nsScrollbarButtonFrame::Notify()
195 if (mCursorOnThis ||
196 LookAndFeel::GetInt(
197 LookAndFeel::eIntID_ScrollbarButtonAutoRepeatBehavior, 0)) {
198 // get the scrollbar control
199 nsIFrame* scrollbar;
200 GetParentWithTag(nsGkAtoms::scrollbar, this, scrollbar);
201 nsScrollbarFrame* sb = do_QueryFrame(scrollbar);
202 if (sb) {
203 nsIScrollbarMediator* m = sb->GetScrollbarMediator();
204 if (m) {
205 m->RepeatButtonScroll(sb);
206 } else {
207 sb->MoveToNewPosition();
213 void
214 nsScrollbarButtonFrame::MouseClicked(nsPresContext* aPresContext,
215 WidgetGUIEvent* aEvent)
217 nsButtonBoxFrame::MouseClicked(aPresContext, aEvent);
218 //MouseClicked();
221 nsresult
222 nsScrollbarButtonFrame::GetChildWithTag(nsPresContext* aPresContext,
223 nsIAtom* atom, nsIFrame* start,
224 nsIFrame*& result)
226 // recursively search our children
227 nsIFrame* childFrame = start->GetFirstPrincipalChild();
228 while (nullptr != childFrame)
230 // get the content node
231 nsIContent* child = childFrame->GetContent();
233 if (child) {
234 // see if it is the child
235 if (child->Tag() == atom)
237 result = childFrame;
239 return NS_OK;
243 // recursive search the child
244 GetChildWithTag(aPresContext, atom, childFrame, result);
245 if (result != nullptr)
246 return NS_OK;
248 childFrame = childFrame->GetNextSibling();
251 result = nullptr;
252 return NS_OK;
255 nsresult
256 nsScrollbarButtonFrame::GetParentWithTag(nsIAtom* toFind, nsIFrame* start,
257 nsIFrame*& result)
259 while (start)
261 start = start->GetParent();
263 if (start) {
264 // get the content node
265 nsIContent* child = start->GetContent();
267 if (child && child->Tag() == toFind) {
268 result = start;
269 return NS_OK;
274 result = nullptr;
275 return NS_OK;
278 void
279 nsScrollbarButtonFrame::DestroyFrom(nsIFrame* aDestructRoot)
281 // Ensure our repeat service isn't going... it's possible that a scrollbar can disappear out
282 // from under you while you're in the process of scrolling.
283 StopRepeat();
284 nsButtonBoxFrame::DestroyFrom(aDestructRoot);