michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: #include "nsImageFrame.h" michael@0: #include "nsIFormControlFrame.h" michael@0: #include "nsPresContext.h" michael@0: #include "nsGkAtoms.h" michael@0: #include "nsStyleConsts.h" michael@0: #include "nsFormControlFrame.h" michael@0: #include "nsLayoutUtils.h" michael@0: #include "mozilla/MouseEvents.h" michael@0: michael@0: using namespace mozilla; michael@0: michael@0: typedef nsImageFrame nsImageControlFrameSuper; michael@0: class nsImageControlFrame : public nsImageControlFrameSuper, michael@0: public nsIFormControlFrame michael@0: { michael@0: public: michael@0: nsImageControlFrame(nsStyleContext* aContext); michael@0: ~nsImageControlFrame(); michael@0: michael@0: virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE; michael@0: virtual void Init(nsIContent* aContent, michael@0: nsIFrame* aParent, michael@0: nsIFrame* aPrevInFlow) MOZ_OVERRIDE; michael@0: michael@0: NS_DECL_QUERYFRAME michael@0: NS_DECL_FRAMEARENA_HELPERS michael@0: michael@0: virtual nsresult Reflow(nsPresContext* aPresContext, michael@0: nsHTMLReflowMetrics& aDesiredSize, michael@0: const nsHTMLReflowState& aReflowState, michael@0: nsReflowStatus& aStatus) MOZ_OVERRIDE; michael@0: michael@0: virtual nsresult HandleEvent(nsPresContext* aPresContext, michael@0: WidgetGUIEvent* aEvent, michael@0: nsEventStatus* aEventStatus) MOZ_OVERRIDE; michael@0: michael@0: virtual nsIAtom* GetType() const MOZ_OVERRIDE; michael@0: michael@0: #ifdef ACCESSIBILITY michael@0: virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE; michael@0: #endif michael@0: michael@0: #ifdef DEBUG_FRAME_DUMP michael@0: virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE { michael@0: return MakeFrameName(NS_LITERAL_STRING("ImageControl"), aResult); michael@0: } michael@0: #endif michael@0: michael@0: virtual nsresult GetCursor(const nsPoint& aPoint, michael@0: nsIFrame::Cursor& aCursor) MOZ_OVERRIDE; michael@0: // nsIFormContromFrame michael@0: virtual void SetFocus(bool aOn, bool aRepaint) MOZ_OVERRIDE; michael@0: virtual nsresult SetFormProperty(nsIAtom* aName, michael@0: const nsAString& aValue) MOZ_OVERRIDE; michael@0: }; michael@0: michael@0: michael@0: nsImageControlFrame::nsImageControlFrame(nsStyleContext* aContext): michael@0: nsImageControlFrameSuper(aContext) michael@0: { michael@0: } michael@0: michael@0: nsImageControlFrame::~nsImageControlFrame() michael@0: { michael@0: } michael@0: michael@0: void michael@0: nsImageControlFrame::DestroyFrom(nsIFrame* aDestructRoot) michael@0: { michael@0: if (!GetPrevInFlow()) { michael@0: nsFormControlFrame::RegUnRegAccessKey(this, false); michael@0: } michael@0: nsImageControlFrameSuper::DestroyFrom(aDestructRoot); michael@0: } michael@0: michael@0: nsIFrame* michael@0: NS_NewImageControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) michael@0: { michael@0: return new (aPresShell) nsImageControlFrame(aContext); michael@0: } michael@0: michael@0: NS_IMPL_FRAMEARENA_HELPERS(nsImageControlFrame) michael@0: michael@0: void michael@0: nsImageControlFrame::Init(nsIContent* aContent, michael@0: nsIFrame* aParent, michael@0: nsIFrame* aPrevInFlow) michael@0: { michael@0: nsImageControlFrameSuper::Init(aContent, aParent, aPrevInFlow); michael@0: michael@0: if (aPrevInFlow) { michael@0: return; michael@0: } michael@0: michael@0: mContent->SetProperty(nsGkAtoms::imageClickedPoint, michael@0: new nsIntPoint(0, 0), michael@0: nsINode::DeleteProperty); michael@0: } michael@0: michael@0: NS_QUERYFRAME_HEAD(nsImageControlFrame) michael@0: NS_QUERYFRAME_ENTRY(nsIFormControlFrame) michael@0: NS_QUERYFRAME_TAIL_INHERITING(nsImageControlFrameSuper) michael@0: michael@0: #ifdef ACCESSIBILITY michael@0: a11y::AccType michael@0: nsImageControlFrame::AccessibleType() michael@0: { michael@0: if (mContent->Tag() == nsGkAtoms::button || michael@0: mContent->Tag() == nsGkAtoms::input) { michael@0: return a11y::eHTMLButtonType; michael@0: } michael@0: michael@0: return a11y::eNoType; michael@0: } michael@0: #endif michael@0: michael@0: nsIAtom* michael@0: nsImageControlFrame::GetType() const michael@0: { michael@0: return nsGkAtoms::imageControlFrame; michael@0: } michael@0: michael@0: nsresult michael@0: nsImageControlFrame::Reflow(nsPresContext* aPresContext, michael@0: nsHTMLReflowMetrics& aDesiredSize, michael@0: const nsHTMLReflowState& aReflowState, michael@0: nsReflowStatus& aStatus) michael@0: { michael@0: DO_GLOBAL_REFLOW_COUNT("nsImageControlFrame"); michael@0: DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); michael@0: if (!GetPrevInFlow() && (mState & NS_FRAME_FIRST_REFLOW)) { michael@0: nsFormControlFrame::RegUnRegAccessKey(this, true); michael@0: } michael@0: return nsImageControlFrameSuper::Reflow(aPresContext, aDesiredSize, aReflowState, aStatus); michael@0: } michael@0: michael@0: nsresult michael@0: nsImageControlFrame::HandleEvent(nsPresContext* aPresContext, michael@0: WidgetGUIEvent* aEvent, michael@0: nsEventStatus* aEventStatus) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aEventStatus); michael@0: michael@0: // Don't do anything if the event has already been handled by someone michael@0: if (nsEventStatus_eConsumeNoDefault == *aEventStatus) { michael@0: return NS_OK; michael@0: } michael@0: michael@0: // do we have user-input style? michael@0: const nsStyleUserInterface* uiStyle = StyleUserInterface(); michael@0: if (uiStyle->mUserInput == NS_STYLE_USER_INPUT_NONE || uiStyle->mUserInput == NS_STYLE_USER_INPUT_DISABLED) michael@0: return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus); michael@0: michael@0: if (mContent->HasAttr(kNameSpaceID_None, nsGkAtoms::disabled)) { // XXX cache disabled michael@0: return NS_OK; michael@0: } michael@0: michael@0: *aEventStatus = nsEventStatus_eIgnore; michael@0: michael@0: if (aEvent->message == NS_MOUSE_BUTTON_UP && michael@0: aEvent->AsMouseEvent()->button == WidgetMouseEvent::eLeftButton) { michael@0: // Store click point for HTMLInputElement::SubmitNamesValues michael@0: // Do this on MouseUp because the specs don't say and that's what IE does michael@0: nsIntPoint* lastClickPoint = michael@0: static_cast michael@0: (mContent->GetProperty(nsGkAtoms::imageClickedPoint)); michael@0: if (lastClickPoint) { michael@0: // normally lastClickedPoint is not null, as it's allocated in Init() michael@0: nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent, this); michael@0: TranslateEventCoords(pt, *lastClickPoint); michael@0: } michael@0: } michael@0: return nsImageControlFrameSuper::HandleEvent(aPresContext, aEvent, michael@0: aEventStatus); michael@0: } michael@0: michael@0: void michael@0: nsImageControlFrame::SetFocus(bool aOn, bool aRepaint) michael@0: { michael@0: } michael@0: michael@0: nsresult michael@0: nsImageControlFrame::GetCursor(const nsPoint& aPoint, michael@0: nsIFrame::Cursor& aCursor) michael@0: { michael@0: // Use style defined cursor if one is provided, otherwise when michael@0: // the cursor style is "auto" we use the pointer cursor. michael@0: FillCursorInformationFromStyle(StyleUserInterface(), aCursor); michael@0: michael@0: if (NS_STYLE_CURSOR_AUTO == aCursor.mCursor) { michael@0: aCursor.mCursor = NS_STYLE_CURSOR_POINTER; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: nsImageControlFrame::SetFormProperty(nsIAtom* aName, michael@0: const nsAString& aValue) michael@0: { michael@0: return NS_OK; michael@0: }