diff -r 000000000000 -r 6474c204b198 layout/forms/nsListControlFrame.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/layout/forms/nsListControlFrame.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,2453 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nscore.h" +#include "nsCOMPtr.h" +#include "nsUnicharUtils.h" +#include "nsListControlFrame.h" +#include "nsFormControlFrame.h" // for COMPARE macro +#include "nsGkAtoms.h" +#include "nsIDOMHTMLSelectElement.h" +#include "nsIDOMHTMLOptionElement.h" +#include "nsComboboxControlFrame.h" +#include "nsIDOMHTMLOptGroupElement.h" +#include "nsIPresShell.h" +#include "nsIDOMMouseEvent.h" +#include "nsIXULRuntime.h" +#include "nsFontMetrics.h" +#include "nsIScrollableFrame.h" +#include "nsCSSRendering.h" +#include "nsIDOMEventListener.h" +#include "nsLayoutUtils.h" +#include "nsDisplayList.h" +#include "nsContentUtils.h" +#include "mozilla/Attributes.h" +#include "mozilla/dom/HTMLOptionsCollection.h" +#include "mozilla/dom/HTMLSelectElement.h" +#include "mozilla/EventStateManager.h" +#include "mozilla/EventStates.h" +#include "mozilla/LookAndFeel.h" +#include "mozilla/MouseEvents.h" +#include "mozilla/Preferences.h" +#include "mozilla/TextEvents.h" +#include + +using namespace mozilla; + +// Constants +const uint32_t kMaxDropDownRows = 20; // This matches the setting for 4.x browsers +const int32_t kNothingSelected = -1; + +// Static members +nsListControlFrame * nsListControlFrame::mFocused = nullptr; +nsString * nsListControlFrame::sIncrementalString = nullptr; + +// Using for incremental typing navigation +#define INCREMENTAL_SEARCH_KEYPRESS_TIME 1000 +// XXX, kyle.yuan@sun.com, there are 4 definitions for the same purpose: +// nsMenuPopupFrame.h, nsListControlFrame.cpp, listbox.xml, tree.xml +// need to find a good place to put them together. +// if someone changes one, please also change the other. + +DOMTimeStamp nsListControlFrame::gLastKeyTime = 0; + +/****************************************************************************** + * nsListEventListener + * This class is responsible for propagating events to the nsListControlFrame. + * Frames are not refcounted so they can't be used as event listeners. + *****************************************************************************/ + +class nsListEventListener MOZ_FINAL : public nsIDOMEventListener +{ +public: + nsListEventListener(nsListControlFrame *aFrame) + : mFrame(aFrame) { } + + void SetFrame(nsListControlFrame *aFrame) { mFrame = aFrame; } + + NS_DECL_ISUPPORTS + NS_DECL_NSIDOMEVENTLISTENER + +private: + nsListControlFrame *mFrame; +}; + +//--------------------------------------------------------- +nsIFrame* +NS_NewListControlFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) +{ + nsListControlFrame* it = + new (aPresShell) nsListControlFrame(aPresShell, aPresShell->GetDocument(), aContext); + + it->AddStateBits(NS_FRAME_INDEPENDENT_SELECTION); + + return it; +} + +NS_IMPL_FRAMEARENA_HELPERS(nsListControlFrame) + +//--------------------------------------------------------- +nsListControlFrame::nsListControlFrame( + nsIPresShell* aShell, nsIDocument* aDocument, nsStyleContext* aContext) + : nsHTMLScrollFrame(aShell, aContext, false), + mMightNeedSecondPass(false), + mHasPendingInterruptAtStartOfReflow(false), + mDropdownCanGrow(false), + mLastDropdownComputedHeight(NS_UNCONSTRAINEDSIZE) +{ + mComboboxFrame = nullptr; + mChangesSinceDragStart = false; + mButtonDown = false; + + mIsAllContentHere = false; + mIsAllFramesHere = false; + mHasBeenInitialized = false; + mNeedToReset = true; + mPostChildrenLoadedReset = false; + + mControlSelectMode = false; +} + +//--------------------------------------------------------- +nsListControlFrame::~nsListControlFrame() +{ + mComboboxFrame = nullptr; +} + +// for Bug 47302 (remove this comment later) +void +nsListControlFrame::DestroyFrom(nsIFrame* aDestructRoot) +{ + // get the receiver interface from the browser button's content node + ENSURE_TRUE(mContent); + + // Clear the frame pointer on our event listener, just in case the + // event listener can outlive the frame. + + mEventListener->SetFrame(nullptr); + + mContent->RemoveSystemEventListener(NS_LITERAL_STRING("keydown"), + mEventListener, false); + mContent->RemoveSystemEventListener(NS_LITERAL_STRING("keypress"), + mEventListener, false); + mContent->RemoveSystemEventListener(NS_LITERAL_STRING("mousedown"), + mEventListener, false); + mContent->RemoveSystemEventListener(NS_LITERAL_STRING("mouseup"), + mEventListener, false); + mContent->RemoveSystemEventListener(NS_LITERAL_STRING("mousemove"), + mEventListener, false); + + nsFormControlFrame::RegUnRegAccessKey(static_cast(this), false); + nsHTMLScrollFrame::DestroyFrom(aDestructRoot); +} + +void +nsListControlFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, + const nsRect& aDirtyRect, + const nsDisplayListSet& aLists) +{ + // We allow visibility:hidden . So if the mouse goes over an option just before + // he leaves the box and clicks, that's what the