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: michael@0: #include "nsFormControlFrame.h" michael@0: #include "nsGkAtoms.h" michael@0: #include "nsLayoutUtils.h" michael@0: #include "nsIDOMHTMLInputElement.h" michael@0: #include "mozilla/EventStateManager.h" michael@0: #include "mozilla/LookAndFeel.h" michael@0: #include "nsDeviceContext.h" michael@0: michael@0: using namespace mozilla; michael@0: michael@0: //#define FCF_NOISY michael@0: michael@0: nsFormControlFrame::nsFormControlFrame(nsStyleContext* aContext) : michael@0: nsLeafFrame(aContext) michael@0: { michael@0: } michael@0: michael@0: nsFormControlFrame::~nsFormControlFrame() michael@0: { michael@0: } michael@0: michael@0: nsIAtom* michael@0: nsFormControlFrame::GetType() const michael@0: { michael@0: return nsGkAtoms::formControlFrame; michael@0: } michael@0: michael@0: void michael@0: nsFormControlFrame::DestroyFrom(nsIFrame* aDestructRoot) michael@0: { michael@0: // Unregister the access key registered in reflow michael@0: nsFormControlFrame::RegUnRegAccessKey(static_cast(this), false); michael@0: nsLeafFrame::DestroyFrom(aDestructRoot); michael@0: } michael@0: michael@0: NS_QUERYFRAME_HEAD(nsFormControlFrame) michael@0: NS_QUERYFRAME_ENTRY(nsIFormControlFrame) michael@0: NS_QUERYFRAME_TAIL_INHERITING(nsLeafFrame) michael@0: michael@0: NS_IMPL_FRAMEARENA_HELPERS(nsFormControlFrame) michael@0: michael@0: nscoord michael@0: nsFormControlFrame::GetIntrinsicWidth() michael@0: { michael@0: // Provide a reasonable default for sites that use an "auto" height. michael@0: // Note that if you change this, you should change the values in forms.css michael@0: // as well. This is the 13px default width minus the 2px default border. michael@0: return nsPresContext::CSSPixelsToAppUnits(13 - 2 * 2); michael@0: } michael@0: michael@0: nscoord michael@0: nsFormControlFrame::GetIntrinsicHeight() michael@0: { michael@0: // Provide a reasonable default for sites that use an "auto" height. michael@0: // Note that if you change this, you should change the values in forms.css michael@0: // as well. This is the 13px default width minus the 2px default border. michael@0: return nsPresContext::CSSPixelsToAppUnits(13 - 2 * 2); michael@0: } michael@0: michael@0: nscoord michael@0: nsFormControlFrame::GetBaseline() const michael@0: { michael@0: NS_ASSERTION(!NS_SUBTREE_DIRTY(this), michael@0: "frame must not be dirty"); michael@0: // Treat radio buttons and checkboxes as having an intrinsic baseline michael@0: // at the bottom of the control (use the bottom content edge rather michael@0: // than the bottom margin edge). michael@0: return mRect.height - GetUsedBorderAndPadding().bottom; michael@0: } michael@0: michael@0: nsresult michael@0: nsFormControlFrame::Reflow(nsPresContext* aPresContext, michael@0: nsHTMLReflowMetrics& aDesiredSize, michael@0: const nsHTMLReflowState& aReflowState, michael@0: nsReflowStatus& aStatus) michael@0: { michael@0: DO_GLOBAL_REFLOW_COUNT("nsFormControlFrame"); michael@0: DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); michael@0: michael@0: if (mState & NS_FRAME_FIRST_REFLOW) { michael@0: RegUnRegAccessKey(static_cast(this), true); michael@0: } michael@0: michael@0: nsresult rv = nsLeafFrame::Reflow(aPresContext, aDesiredSize, aReflowState, michael@0: aStatus); michael@0: if (NS_FAILED(rv)) { michael@0: return rv; michael@0: } michael@0: michael@0: if (nsLayoutUtils::FontSizeInflationEnabled(aPresContext)) { michael@0: float inflation = nsLayoutUtils::FontSizeInflationFor(this); michael@0: aDesiredSize.Width() *= inflation; michael@0: aDesiredSize.Height() *= inflation; michael@0: aDesiredSize.UnionOverflowAreasWithDesiredBounds(); michael@0: FinishAndStoreOverflow(&aDesiredSize); michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: nsFormControlFrame::RegUnRegAccessKey(nsIFrame * aFrame, bool aDoReg) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aFrame); michael@0: michael@0: nsPresContext* presContext = aFrame->PresContext(); michael@0: michael@0: NS_ASSERTION(presContext, "aPresContext is NULL in RegUnRegAccessKey!"); michael@0: michael@0: nsAutoString accessKey; michael@0: michael@0: nsIContent* content = aFrame->GetContent(); michael@0: content->GetAttr(kNameSpaceID_None, nsGkAtoms::accesskey, accessKey); michael@0: if (!accessKey.IsEmpty()) { michael@0: EventStateManager* stateManager = presContext->EventStateManager(); michael@0: if (aDoReg) { michael@0: stateManager->RegisterAccessKey(content, (uint32_t)accessKey.First()); michael@0: } else { michael@0: stateManager->UnregisterAccessKey(content, (uint32_t)accessKey.First()); michael@0: } michael@0: return NS_OK; michael@0: } michael@0: return NS_ERROR_FAILURE; michael@0: } michael@0: michael@0: void michael@0: nsFormControlFrame::SetFocus(bool aOn, bool aRepaint) michael@0: { michael@0: } michael@0: michael@0: nsresult michael@0: nsFormControlFrame::HandleEvent(nsPresContext* aPresContext, michael@0: WidgetGUIEvent* aEvent, michael@0: nsEventStatus* aEventStatus) michael@0: { michael@0: // Check for user-input:none style michael@0: const nsStyleUserInterface* uiStyle = StyleUserInterface(); michael@0: if (uiStyle->mUserInput == NS_STYLE_USER_INPUT_NONE || michael@0: uiStyle->mUserInput == NS_STYLE_USER_INPUT_DISABLED) michael@0: return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: void michael@0: nsFormControlFrame::GetCurrentCheckState(bool *aState) michael@0: { michael@0: nsCOMPtr inputElement = do_QueryInterface(mContent); michael@0: if (inputElement) { michael@0: inputElement->GetChecked(aState); michael@0: } michael@0: } michael@0: michael@0: nsresult michael@0: nsFormControlFrame::SetFormProperty(nsIAtom* aName, const nsAString& aValue) michael@0: { michael@0: return NS_OK; michael@0: } michael@0: michael@0: // static michael@0: nsRect michael@0: nsFormControlFrame::GetUsableScreenRect(nsPresContext* aPresContext) michael@0: { michael@0: nsRect screen; michael@0: michael@0: nsDeviceContext *context = aPresContext->DeviceContext(); michael@0: int32_t dropdownCanOverlapOSBar = michael@0: LookAndFeel::GetInt(LookAndFeel::eIntID_MenusCanOverlapOSBar, 0); michael@0: if ( dropdownCanOverlapOSBar ) michael@0: context->GetRect(screen); michael@0: else michael@0: context->GetClientRect(screen); michael@0: michael@0: return screen; michael@0: }