nsImageControlFrame.cpp (4605B)
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 "mozilla/MouseEvents.h" 8 #include "mozilla/PresShell.h" 9 #include "nsGkAtoms.h" 10 #include "nsIContent.h" 11 #include "nsImageFrame.h" 12 #include "nsLayoutUtils.h" 13 #include "nsPresContext.h" 14 #include "nsStyleConsts.h" 15 16 using namespace mozilla; 17 18 class nsImageControlFrame final : public nsImageFrame { 19 public: 20 explicit nsImageControlFrame(ComputedStyle* aStyle, 21 nsPresContext* aPresContext); 22 ~nsImageControlFrame() final; 23 24 void Init(nsIContent* aContent, nsContainerFrame* aParent, 25 nsIFrame* aPrevInFlow) final; 26 27 NS_DECL_QUERYFRAME 28 NS_DECL_FRAMEARENA_HELPERS(nsImageControlFrame) 29 30 void Reflow(nsPresContext*, ReflowOutput&, const ReflowInput&, 31 nsReflowStatus&) final; 32 33 nsresult HandleEvent(nsPresContext*, WidgetGUIEvent*, nsEventStatus*) final; 34 35 #ifdef ACCESSIBILITY 36 mozilla::a11y::AccType AccessibleType() final; 37 #endif 38 39 #ifdef DEBUG_FRAME_DUMP 40 nsresult GetFrameName(nsAString& aResult) const final { 41 return MakeFrameName(u"ImageControl"_ns, aResult); 42 } 43 #endif 44 45 Cursor GetCursor(const nsPoint&) final; 46 }; 47 48 nsImageControlFrame::nsImageControlFrame(ComputedStyle* aStyle, 49 nsPresContext* aPresContext) 50 : nsImageFrame(aStyle, aPresContext, kClassID) {} 51 52 nsImageControlFrame::~nsImageControlFrame() = default; 53 54 nsIFrame* NS_NewImageControlFrame(PresShell* aPresShell, 55 ComputedStyle* aStyle) { 56 return new (aPresShell) 57 nsImageControlFrame(aStyle, aPresShell->GetPresContext()); 58 } 59 60 NS_IMPL_FRAMEARENA_HELPERS(nsImageControlFrame) 61 62 void nsImageControlFrame::Init(nsIContent* aContent, nsContainerFrame* aParent, 63 nsIFrame* aPrevInFlow) { 64 nsImageFrame::Init(aContent, aParent, aPrevInFlow); 65 66 if (aPrevInFlow) { 67 return; 68 } 69 70 mContent->SetProperty(nsGkAtoms::imageClickedPoint, new CSSIntPoint(0, 0), 71 nsINode::DeleteProperty<CSSIntPoint>); 72 } 73 74 NS_QUERYFRAME_HEAD(nsImageControlFrame) 75 NS_QUERYFRAME_TAIL_INHERITING(nsImageFrame) 76 77 #ifdef ACCESSIBILITY 78 a11y::AccType nsImageControlFrame::AccessibleType() { 79 if (mContent->IsAnyOfHTMLElements(nsGkAtoms::button, nsGkAtoms::input)) { 80 return a11y::eHTMLButtonType; 81 } 82 83 return a11y::eNoType; 84 } 85 #endif 86 87 void nsImageControlFrame::Reflow(nsPresContext* aPresContext, 88 ReflowOutput& aDesiredSize, 89 const ReflowInput& aReflowInput, 90 nsReflowStatus& aStatus) { 91 DO_GLOBAL_REFLOW_COUNT("nsImageControlFrame"); 92 MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!"); 93 return nsImageFrame::Reflow(aPresContext, aDesiredSize, aReflowInput, 94 aStatus); 95 } 96 97 nsresult nsImageControlFrame::HandleEvent(nsPresContext* aPresContext, 98 WidgetGUIEvent* aEvent, 99 nsEventStatus* aEventStatus) { 100 NS_ENSURE_ARG_POINTER(aEventStatus); 101 102 // Don't do anything if the event has already been handled by someone 103 if (nsEventStatus_eConsumeNoDefault == *aEventStatus) { 104 return NS_OK; 105 } 106 107 if (IsContentDisabled()) { 108 return nsIFrame::HandleEvent(aPresContext, aEvent, aEventStatus); 109 } 110 111 *aEventStatus = nsEventStatus_eIgnore; 112 113 if (aEvent->mMessage == eMouseUp && 114 aEvent->AsMouseEvent()->mButton == MouseButton::ePrimary) { 115 // Store click point for HTMLInputElement::SubmitNamesValues 116 // Do this on MouseUp because the specs don't say and that's what IE does 117 auto* lastClickedPoint = static_cast<CSSIntPoint*>( 118 mContent->GetProperty(nsGkAtoms::imageClickedPoint)); 119 if (lastClickedPoint) { 120 // normally lastClickedPoint is not null, as it's allocated in Init() 121 nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo( 122 aEvent, RelativeTo{this}); 123 *lastClickedPoint = TranslateEventCoords(pt); 124 } 125 } 126 return nsImageFrame::HandleEvent(aPresContext, aEvent, aEventStatus); 127 } 128 129 nsIFrame::Cursor nsImageControlFrame::GetCursor(const nsPoint&) { 130 StyleCursorKind kind = StyleUI()->Cursor().keyword; 131 if (kind == StyleCursorKind::Auto) { 132 kind = StyleCursorKind::Pointer; 133 } 134 return Cursor{kind, AllowCustomCursorImage::Yes}; 135 }