LCOV - code coverage report
Current view: directory - layout/xul/base/src - nsSliderFrame.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 474 0 0.0 %
Date: 2012-06-02 Functions: 57 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is Mozilla Communicator client code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Dean Tessman <dean_tessman@hotmail.com>
      24                 :  *   Stan Shebs <stanshebs@earthlink.net>
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      28                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : //
      41                 : // Eric Vaughan
      42                 : // Netscape Communications
      43                 : //
      44                 : // See documentation in associated header file
      45                 : //
      46                 : 
      47                 : #include "nsSliderFrame.h"
      48                 : #include "nsStyleContext.h"
      49                 : #include "nsPresContext.h"
      50                 : #include "nsIContent.h"
      51                 : #include "nsCOMPtr.h"
      52                 : #include "nsINameSpaceManager.h"
      53                 : #include "nsGkAtoms.h"
      54                 : #include "nsHTMLParts.h"
      55                 : #include "nsIPresShell.h"
      56                 : #include "nsCSSRendering.h"
      57                 : #include "nsEventListenerManager.h"
      58                 : #include "nsIDOMEventTarget.h"
      59                 : #include "nsIDOMMouseEvent.h"
      60                 : #include "nsIDocument.h"
      61                 : #include "nsScrollbarButtonFrame.h"
      62                 : #include "nsISliderListener.h"
      63                 : #include "nsIScrollbarMediator.h"
      64                 : #include "nsScrollbarFrame.h"
      65                 : #include "nsRepeatService.h"
      66                 : #include "nsBoxLayoutState.h"
      67                 : #include "nsSprocketLayout.h"
      68                 : #include "nsIServiceManager.h"
      69                 : #include "nsGUIEvent.h"
      70                 : #include "nsContentUtils.h"
      71                 : #include "nsLayoutUtils.h"
      72                 : #include "nsDisplayList.h"
      73                 : #include "mozilla/Preferences.h"
      74                 : #include "mozilla/LookAndFeel.h"
      75                 : 
      76                 : using namespace mozilla;
      77                 : 
      78                 : bool nsSliderFrame::gMiddlePref = false;
      79                 : PRInt32 nsSliderFrame::gSnapMultiplier;
      80                 : 
      81                 : // Turn this on if you want to debug slider frames.
      82                 : #undef DEBUG_SLIDER
      83                 : 
      84                 : static already_AddRefed<nsIContent>
      85               0 : GetContentOfBox(nsIBox *aBox)
      86                 : {
      87               0 :   nsIContent* content = aBox->GetContent();
      88               0 :   NS_IF_ADDREF(content);
      89               0 :   return content;
      90                 : }
      91                 : 
      92                 : nsIFrame*
      93               0 : NS_NewSliderFrame (nsIPresShell* aPresShell, nsStyleContext* aContext)
      94                 : {
      95               0 :   return new (aPresShell) nsSliderFrame(aPresShell, aContext);
      96                 : }
      97                 : 
      98               0 : NS_IMPL_FRAMEARENA_HELPERS(nsSliderFrame)
      99                 : 
     100               0 : nsSliderFrame::nsSliderFrame(nsIPresShell* aPresShell, nsStyleContext* aContext):
     101                 :   nsBoxFrame(aPresShell, aContext),
     102                 :   mCurPos(0),
     103                 :   mChange(0),
     104               0 :   mUserChanged(false)
     105                 : {
     106               0 : }
     107                 : 
     108                 : // stop timer
     109               0 : nsSliderFrame::~nsSliderFrame()
     110                 : {
     111               0 : }
     112                 : 
     113                 : NS_IMETHODIMP
     114               0 : nsSliderFrame::Init(nsIContent*      aContent,
     115                 :                     nsIFrame*        aParent,
     116                 :                     nsIFrame*        aPrevInFlow)
     117                 : {
     118               0 :   nsresult rv = nsBoxFrame::Init(aContent, aParent, aPrevInFlow);
     119                 : 
     120                 :   static bool gotPrefs = false;
     121               0 :   if (!gotPrefs) {
     122               0 :     gotPrefs = true;
     123                 : 
     124               0 :     gMiddlePref = Preferences::GetBool("middlemouse.scrollbarPosition");
     125               0 :     gSnapMultiplier = Preferences::GetInt("slider.snapMultiplier");
     126                 :   }
     127                 : 
     128               0 :   mCurPos = GetCurrentPosition(aContent);
     129                 : 
     130               0 :   return rv;
     131                 : }
     132                 : 
     133                 : NS_IMETHODIMP
     134               0 : nsSliderFrame::RemoveFrame(ChildListID     aListID,
     135                 :                            nsIFrame*       aOldFrame)
     136                 : {
     137               0 :   nsresult rv = nsBoxFrame::RemoveFrame(aListID, aOldFrame);
     138               0 :   if (mFrames.IsEmpty())
     139               0 :     RemoveListener();
     140                 : 
     141               0 :   return rv;
     142                 : }
     143                 : 
     144                 : NS_IMETHODIMP
     145               0 : nsSliderFrame::InsertFrames(ChildListID     aListID,
     146                 :                             nsIFrame*       aPrevFrame,
     147                 :                             nsFrameList&    aFrameList)
     148                 : {
     149               0 :   bool wasEmpty = mFrames.IsEmpty();
     150               0 :   nsresult rv = nsBoxFrame::InsertFrames(aListID, aPrevFrame, aFrameList);
     151               0 :   if (wasEmpty)
     152               0 :     AddListener();
     153                 : 
     154               0 :   return rv;
     155                 : }
     156                 : 
     157                 : NS_IMETHODIMP
     158               0 : nsSliderFrame::AppendFrames(ChildListID     aListID,
     159                 :                             nsFrameList&    aFrameList)
     160                 : {
     161                 :   // if we have no children and on was added then make sure we add the
     162                 :   // listener
     163               0 :   bool wasEmpty = mFrames.IsEmpty();
     164               0 :   nsresult rv = nsBoxFrame::AppendFrames(aListID, aFrameList);
     165               0 :   if (wasEmpty)
     166               0 :     AddListener();
     167                 : 
     168               0 :   return rv;
     169                 : }
     170                 : 
     171                 : PRInt32
     172               0 : nsSliderFrame::GetCurrentPosition(nsIContent* content)
     173                 : {
     174               0 :   return GetIntegerAttribute(content, nsGkAtoms::curpos, 0);
     175                 : }
     176                 : 
     177                 : PRInt32
     178               0 : nsSliderFrame::GetMinPosition(nsIContent* content)
     179                 : {
     180               0 :   return GetIntegerAttribute(content, nsGkAtoms::minpos, 0);
     181                 : }
     182                 : 
     183                 : PRInt32
     184               0 : nsSliderFrame::GetMaxPosition(nsIContent* content)
     185                 : {
     186               0 :   return GetIntegerAttribute(content, nsGkAtoms::maxpos, 100);
     187                 : }
     188                 : 
     189                 : PRInt32
     190               0 : nsSliderFrame::GetIncrement(nsIContent* content)
     191                 : {
     192               0 :   return GetIntegerAttribute(content, nsGkAtoms::increment, 1);
     193                 : }
     194                 : 
     195                 : 
     196                 : PRInt32
     197               0 : nsSliderFrame::GetPageIncrement(nsIContent* content)
     198                 : {
     199               0 :   return GetIntegerAttribute(content, nsGkAtoms::pageincrement, 10);
     200                 : }
     201                 : 
     202                 : PRInt32
     203               0 : nsSliderFrame::GetIntegerAttribute(nsIContent* content, nsIAtom* atom, PRInt32 defaultValue)
     204                 : {
     205               0 :     nsAutoString value;
     206               0 :     content->GetAttr(kNameSpaceID_None, atom, value);
     207               0 :     if (!value.IsEmpty()) {
     208                 :       PRInt32 error;
     209                 : 
     210                 :       // convert it to an integer
     211               0 :       defaultValue = value.ToInteger(&error);
     212                 :     }
     213                 : 
     214               0 :     return defaultValue;
     215                 : }
     216                 : 
     217                 : class nsValueChangedRunnable : public nsRunnable
     218               0 : {
     219                 : public:
     220               0 :   nsValueChangedRunnable(nsISliderListener* aListener,
     221                 :                          nsIAtom* aWhich,
     222                 :                          PRInt32 aValue,
     223                 :                          bool aUserChanged)
     224                 :   : mListener(aListener), mWhich(aWhich),
     225               0 :     mValue(aValue), mUserChanged(aUserChanged)
     226               0 :   {}
     227                 : 
     228               0 :   NS_IMETHODIMP Run()
     229                 :   {
     230               0 :     return mListener->ValueChanged(nsDependentAtomString(mWhich),
     231               0 :                                    mValue, mUserChanged);
     232                 :   }
     233                 : 
     234                 :   nsCOMPtr<nsISliderListener> mListener;
     235                 :   nsCOMPtr<nsIAtom> mWhich;
     236                 :   PRInt32 mValue;
     237                 :   bool mUserChanged;
     238                 : };
     239                 : 
     240                 : class nsDragStateChangedRunnable : public nsRunnable
     241               0 : {
     242                 : public:
     243               0 :   nsDragStateChangedRunnable(nsISliderListener* aListener,
     244                 :                              bool aDragBeginning)
     245                 :   : mListener(aListener),
     246               0 :     mDragBeginning(aDragBeginning)
     247               0 :   {}
     248                 : 
     249               0 :   NS_IMETHODIMP Run()
     250                 :   {
     251               0 :     return mListener->DragStateChanged(mDragBeginning);
     252                 :   }
     253                 : 
     254                 :   nsCOMPtr<nsISliderListener> mListener;
     255                 :   bool mDragBeginning;
     256                 : };
     257                 : 
     258                 : NS_IMETHODIMP
     259               0 : nsSliderFrame::AttributeChanged(PRInt32 aNameSpaceID,
     260                 :                                 nsIAtom* aAttribute,
     261                 :                                 PRInt32 aModType)
     262                 : {
     263                 :   nsresult rv = nsBoxFrame::AttributeChanged(aNameSpaceID, aAttribute,
     264               0 :                                              aModType);
     265                 :   // if the current position changes
     266               0 :   if (aAttribute == nsGkAtoms::curpos) {
     267               0 :      rv = CurrentPositionChanged(PresContext(), false);
     268               0 :      NS_ASSERTION(NS_SUCCEEDED(rv), "failed to change position");
     269               0 :      if (NS_FAILED(rv))
     270               0 :         return rv;
     271               0 :   } else if (aAttribute == nsGkAtoms::minpos ||
     272                 :              aAttribute == nsGkAtoms::maxpos) {
     273                 :       // bounds check it.
     274                 : 
     275               0 :       nsIBox* scrollbarBox = GetScrollbar();
     276               0 :       nsCOMPtr<nsIContent> scrollbar;
     277               0 :       scrollbar = GetContentOfBox(scrollbarBox);
     278               0 :       PRInt32 current = GetCurrentPosition(scrollbar);
     279               0 :       PRInt32 min = GetMinPosition(scrollbar);
     280               0 :       PRInt32 max = GetMaxPosition(scrollbar);
     281                 : 
     282                 :       // inform the parent <scale> that the minimum or maximum changed
     283               0 :       nsIFrame* parent = GetParent();
     284               0 :       if (parent) {
     285               0 :         nsCOMPtr<nsISliderListener> sliderListener = do_QueryInterface(parent->GetContent());
     286               0 :         if (sliderListener) {
     287                 :           nsContentUtils::AddScriptRunner(
     288                 :             new nsValueChangedRunnable(sliderListener, aAttribute,
     289               0 :                                        aAttribute == nsGkAtoms::minpos ? min : max, false));
     290                 :         }
     291                 :       }
     292                 : 
     293               0 :       if (current < min || current > max)
     294                 :       {
     295               0 :         if (current < min || max < min)
     296               0 :             current = min;
     297               0 :         else if (current > max)
     298               0 :             current = max;
     299                 : 
     300                 :         // set the new position and notify observers
     301               0 :         nsScrollbarFrame* scrollbarFrame = do_QueryFrame(scrollbarBox);
     302               0 :         if (scrollbarFrame) {
     303               0 :           nsIScrollbarMediator* mediator = scrollbarFrame->GetScrollbarMediator();
     304               0 :           if (mediator) {
     305               0 :             mediator->PositionChanged(scrollbarFrame, GetCurrentPosition(scrollbar), current);
     306                 :           }
     307                 :         }
     308                 : 
     309                 :         nsContentUtils::AddScriptRunner(
     310               0 :           new nsSetAttrRunnable(scrollbar, nsGkAtoms::curpos, current));
     311                 :       }
     312                 :   }
     313                 : 
     314               0 :   if (aAttribute == nsGkAtoms::minpos ||
     315                 :       aAttribute == nsGkAtoms::maxpos ||
     316                 :       aAttribute == nsGkAtoms::pageincrement ||
     317                 :       aAttribute == nsGkAtoms::increment) {
     318                 : 
     319               0 :       PresContext()->PresShell()->
     320               0 :         FrameNeedsReflow(this, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY);
     321                 :   }
     322                 : 
     323               0 :   return rv;
     324                 : }
     325                 : 
     326                 : NS_IMETHODIMP
     327               0 : nsSliderFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
     328                 :                                 const nsRect&           aDirtyRect,
     329                 :                                 const nsDisplayListSet& aLists)
     330                 : {
     331               0 :   if (aBuilder->IsForEventDelivery() && isDraggingThumb()) {
     332                 :     // This is EVIL, we shouldn't be messing with event delivery just to get
     333                 :     // thumb mouse drag events to arrive at the slider!
     334                 :     return aLists.Outlines()->AppendNewToTop(new (aBuilder)
     335               0 :         nsDisplayEventReceiver(aBuilder, this));
     336                 :   }
     337                 :   
     338               0 :   return nsBoxFrame::BuildDisplayList(aBuilder, aDirtyRect, aLists);
     339                 : }
     340                 : 
     341                 : NS_IMETHODIMP
     342               0 : nsSliderFrame::BuildDisplayListForChildren(nsDisplayListBuilder*   aBuilder,
     343                 :                                            const nsRect&           aDirtyRect,
     344                 :                                            const nsDisplayListSet& aLists)
     345                 : {
     346                 :   // if we are too small to have a thumb don't paint it.
     347               0 :   nsIBox* thumb = GetChildBox();
     348                 : 
     349               0 :   if (thumb) {
     350               0 :     nsRect thumbRect(thumb->GetRect());
     351               0 :     nsMargin m;
     352               0 :     thumb->GetMargin(m);
     353               0 :     thumbRect.Inflate(m);
     354                 : 
     355               0 :     nsRect crect;
     356               0 :     GetClientRect(crect);
     357                 : 
     358               0 :     if (crect.width < thumbRect.width || crect.height < thumbRect.height)
     359               0 :       return NS_OK;
     360                 :   }
     361                 :   
     362               0 :   return nsBoxFrame::BuildDisplayListForChildren(aBuilder, aDirtyRect, aLists);
     363                 : }
     364                 : 
     365                 : NS_IMETHODIMP
     366               0 : nsSliderFrame::DoLayout(nsBoxLayoutState& aState)
     367                 : {
     368                 :   // get the thumb should be our only child
     369               0 :   nsIBox* thumbBox = GetChildBox();
     370                 : 
     371               0 :   if (!thumbBox) {
     372               0 :     SyncLayout(aState);
     373               0 :     return NS_OK;
     374                 :   }
     375                 : 
     376               0 :   EnsureOrient();
     377                 : 
     378                 : #ifdef DEBUG_LAYOUT
     379                 :   if (mState & NS_STATE_DEBUG_WAS_SET) {
     380                 :       if (mState & NS_STATE_SET_TO_DEBUG)
     381                 :           SetDebug(aState, true);
     382                 :       else
     383                 :           SetDebug(aState, false);
     384                 :   }
     385                 : #endif
     386                 : 
     387                 :   // get the content area inside our borders
     388               0 :   nsRect clientRect;
     389               0 :   GetClientRect(clientRect);
     390                 : 
     391                 :   // get the scrollbar
     392               0 :   nsIBox* scrollbarBox = GetScrollbar();
     393               0 :   nsCOMPtr<nsIContent> scrollbar;
     394               0 :   scrollbar = GetContentOfBox(scrollbarBox);
     395                 : 
     396                 :   // get the thumb's pref size
     397               0 :   nsSize thumbSize = thumbBox->GetPrefSize(aState);
     398                 : 
     399               0 :   if (IsHorizontal())
     400               0 :     thumbSize.height = clientRect.height;
     401                 :   else
     402               0 :     thumbSize.width = clientRect.width;
     403                 : 
     404               0 :   PRInt32 curPos = GetCurrentPosition(scrollbar);
     405               0 :   PRInt32 minPos = GetMinPosition(scrollbar);
     406               0 :   PRInt32 maxPos = GetMaxPosition(scrollbar);
     407               0 :   PRInt32 pageIncrement = GetPageIncrement(scrollbar);
     408                 : 
     409               0 :   maxPos = NS_MAX(minPos, maxPos);
     410               0 :   curPos = clamped(curPos, minPos, maxPos);
     411                 : 
     412               0 :   nscoord& availableLength = IsHorizontal() ? clientRect.width : clientRect.height;
     413               0 :   nscoord& thumbLength = IsHorizontal() ? thumbSize.width : thumbSize.height;
     414                 : 
     415               0 :   if ((pageIncrement + maxPos - minPos) > 0 && thumbBox->GetFlex(aState) > 0) {
     416               0 :     float ratio = float(pageIncrement) / float(maxPos - minPos + pageIncrement);
     417               0 :     thumbLength = NS_MAX(thumbLength, NSToCoordRound(availableLength * ratio));
     418                 :   }
     419                 : 
     420                 :   // Round the thumb's length to device pixels.
     421               0 :   nsPresContext* presContext = PresContext();
     422                 :   thumbLength = presContext->DevPixelsToAppUnits(
     423               0 :                   presContext->AppUnitsToDevPixels(thumbLength));
     424                 : 
     425                 :   // mRatio translates the thumb position in app units to the value.
     426               0 :   mRatio = (minPos != maxPos) ? float(availableLength - thumbLength) / float(maxPos - minPos) : 1;
     427                 : 
     428                 :   // in reverse mode, curpos is reversed such that lower values are to the
     429                 :   // right or bottom and increase leftwards or upwards. In this case, use the
     430                 :   // offset from the end instead of the beginning.
     431                 :   bool reverse = mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::dir,
     432               0 :                                          nsGkAtoms::reverse, eCaseMatters);
     433               0 :   nscoord pos = reverse ? (maxPos - curPos) : (curPos - minPos);
     434                 : 
     435                 :   // set the thumb's coord to be the current pos * the ratio.
     436               0 :   nsRect thumbRect(clientRect.x, clientRect.y, thumbSize.width, thumbSize.height);
     437               0 :   PRInt32& thumbPos = (IsHorizontal() ? thumbRect.x : thumbRect.y);
     438               0 :   thumbPos += NSToCoordRound(pos * mRatio);
     439                 : 
     440               0 :   nsRect oldThumbRect(thumbBox->GetRect());
     441               0 :   LayoutChildAt(aState, thumbBox, thumbRect);
     442                 : 
     443               0 :   SyncLayout(aState);
     444                 : 
     445                 :   // Redraw only if thumb changed size.
     446               0 :   if (!oldThumbRect.IsEqualInterior(thumbRect))
     447               0 :     Redraw(aState);
     448                 : 
     449               0 :   return NS_OK;
     450                 : }
     451                 : 
     452                 : 
     453                 : NS_IMETHODIMP
     454               0 : nsSliderFrame::HandleEvent(nsPresContext* aPresContext,
     455                 :                                       nsGUIEvent* aEvent,
     456                 :                                       nsEventStatus* aEventStatus)
     457                 : {
     458               0 :   NS_ENSURE_ARG_POINTER(aEventStatus);
     459                 : 
     460                 :   // If a web page calls event.preventDefault() we still want to
     461                 :   // scroll when scroll arrow is clicked. See bug 511075.
     462               0 :   if (!mContent->IsInNativeAnonymousSubtree() &&
     463                 :       nsEventStatus_eConsumeNoDefault == *aEventStatus) {
     464               0 :     return NS_OK;
     465                 :   }
     466                 : 
     467               0 :   nsIBox* scrollbarBox = GetScrollbar();
     468               0 :   nsCOMPtr<nsIContent> scrollbar;
     469               0 :   scrollbar = GetContentOfBox(scrollbarBox);
     470               0 :   bool isHorizontal = IsHorizontal();
     471                 : 
     472               0 :   if (isDraggingThumb())
     473                 :   {
     474               0 :     switch (aEvent->message) {
     475                 :     case NS_MOUSE_MOVE: {
     476                 :       nsPoint eventPoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent,
     477               0 :                                                                          this);
     478               0 :       if (mChange) {
     479                 :         // We're in the process of moving the thumb to the mouse,
     480                 :         // but the mouse just moved.  Make sure to update our
     481                 :         // destination point.
     482               0 :         mDestinationPoint = eventPoint;
     483               0 :         StopRepeat();
     484               0 :         StartRepeat();
     485               0 :         break;
     486                 :       }
     487                 : 
     488               0 :       nscoord pos = isHorizontal ? eventPoint.x : eventPoint.y;
     489                 : 
     490               0 :       nsIFrame* thumbFrame = mFrames.FirstChild();
     491               0 :       if (!thumbFrame) {
     492               0 :         return NS_OK;
     493                 :       }
     494                 : 
     495                 :       // take our current position and subtract the start location
     496               0 :       pos -= mDragStart;
     497               0 :       bool isMouseOutsideThumb = false;
     498               0 :       if (gSnapMultiplier) {
     499               0 :         nsSize thumbSize = thumbFrame->GetSize();
     500               0 :         if (isHorizontal) {
     501                 :           // horizontal scrollbar - check if mouse is above or below thumb
     502                 :           // XXXbz what about looking at the .y of the thumb's rect?  Is that
     503                 :           // always zero here?
     504               0 :           if (eventPoint.y < -gSnapMultiplier * thumbSize.height ||
     505                 :               eventPoint.y > thumbSize.height +
     506                 :                                gSnapMultiplier * thumbSize.height)
     507               0 :             isMouseOutsideThumb = true;
     508                 :         }
     509                 :         else {
     510                 :           // vertical scrollbar - check if mouse is left or right of thumb
     511               0 :           if (eventPoint.x < -gSnapMultiplier * thumbSize.width ||
     512                 :               eventPoint.x > thumbSize.width +
     513                 :                                gSnapMultiplier * thumbSize.width)
     514               0 :             isMouseOutsideThumb = true;
     515                 :         }
     516                 :       }
     517               0 :       if (isMouseOutsideThumb)
     518                 :       {
     519               0 :         SetCurrentThumbPosition(scrollbar, mThumbStart, false, true, false);
     520               0 :         return NS_OK;
     521                 :       }
     522                 : 
     523                 :       // set it
     524               0 :       SetCurrentThumbPosition(scrollbar, pos, false, true, true); // with snapping
     525                 :     }
     526               0 :     break;
     527                 : 
     528                 :     case NS_MOUSE_BUTTON_UP:
     529               0 :       if (static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eLeftButton ||
     530                 :           (static_cast<nsMouseEvent*>(aEvent)->button == nsMouseEvent::eMiddleButton &&
     531                 :            gMiddlePref)) {
     532                 :         // stop capturing
     533               0 :         AddListener();
     534               0 :         DragThumb(false);
     535               0 :         if (mChange) {
     536               0 :           StopRepeat();
     537               0 :           mChange = 0;
     538                 :         }
     539                 :         //we MUST call nsFrame HandleEvent for mouse ups to maintain the selection state and capture state.
     540               0 :         return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
     541                 :       }
     542                 :     }
     543                 : 
     544                 :     //return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
     545               0 :     return NS_OK;
     546               0 :   } else if ((aEvent->message == NS_MOUSE_BUTTON_DOWN &&
     547                 :               static_cast<nsMouseEvent*>(aEvent)->button ==
     548                 :                 nsMouseEvent::eLeftButton &&
     549                 : #ifdef XP_MACOSX
     550                 :               // On Mac the option key inverts the scroll-to-here preference.
     551                 :               (static_cast<nsMouseEvent*>(aEvent)->isAlt != GetScrollToClick())) ||
     552                 : #else
     553               0 :               (static_cast<nsMouseEvent*>(aEvent)->isShift != GetScrollToClick())) ||
     554                 : #endif
     555                 :              (gMiddlePref && aEvent->message == NS_MOUSE_BUTTON_DOWN &&
     556                 :               static_cast<nsMouseEvent*>(aEvent)->button ==
     557                 :                 nsMouseEvent::eMiddleButton)) {
     558                 : 
     559                 :     nsPoint eventPoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent,
     560               0 :                                                                       this);
     561               0 :     nscoord pos = isHorizontal ? eventPoint.x : eventPoint.y;
     562                 : 
     563                 :     // adjust so that the middle of the thumb is placed under the click
     564               0 :     nsIFrame* thumbFrame = mFrames.FirstChild();
     565               0 :     if (!thumbFrame) {
     566               0 :       return NS_OK;
     567                 :     }
     568               0 :     nsSize thumbSize = thumbFrame->GetSize();
     569               0 :     nscoord thumbLength = isHorizontal ? thumbSize.width : thumbSize.height;
     570                 : 
     571                 :     // set it
     572               0 :     nsWeakFrame weakFrame(this);
     573                 :     // should aMaySnap be true here?
     574               0 :     SetCurrentThumbPosition(scrollbar, pos - thumbLength/2, false, false, false);
     575               0 :     NS_ENSURE_TRUE(weakFrame.IsAlive(), NS_OK);
     576                 : 
     577               0 :     DragThumb(true);
     578                 : 
     579               0 :     if (isHorizontal)
     580               0 :       mThumbStart = thumbFrame->GetPosition().x;
     581                 :     else
     582               0 :       mThumbStart = thumbFrame->GetPosition().y;
     583                 : 
     584               0 :     mDragStart = pos - mThumbStart;
     585                 :   }
     586                 : 
     587                 :   // XXX hack until handle release is actually called in nsframe.
     588                 : //  if (aEvent->message == NS_MOUSE_EXIT_SYNTH || aEvent->message == NS_MOUSE_RIGHT_BUTTON_UP || aEvent->message == NS_MOUSE_LEFT_BUTTON_UP)
     589                 :   //   HandleRelease(aPresContext, aEvent, aEventStatus);
     590                 : 
     591               0 :   if (aEvent->message == NS_MOUSE_EXIT_SYNTH && mChange)
     592               0 :      HandleRelease(aPresContext, aEvent, aEventStatus);
     593                 : 
     594               0 :   return nsFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
     595                 : }
     596                 : 
     597                 : // Helper function to collect the "scroll to click" metric. Beware of
     598                 : // caching this, users expect to be able to change the system preference
     599                 : // and see the browser change its behavior immediately.
     600                 : bool
     601               0 : nsSliderFrame::GetScrollToClick()
     602                 : {
     603                 :   // if there is no parent scrollbar, check the movetoclick attribute. If set
     604                 :   // to true, always scroll to the click point. If false, never do this.
     605                 :   // Otherwise, the default is true on Mac and false on other platforms.
     606               0 :   if (GetScrollbar() == this)
     607                 : #ifdef XP_MACOSX
     608                 :     return !mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::movetoclick,
     609                 :                                    nsGkAtoms::_false, eCaseMatters);
     610                 :  
     611                 :   // if there was no scrollbar, always scroll on click
     612                 :   bool scrollToClick = false;
     613                 :   PRInt32 scrollToClickMetric;
     614                 :   nsresult rv = LookAndFeel::GetInt(LookAndFeel::eIntID_ScrollToClick,
     615                 :                                     &scrollToClickMetric);
     616                 :   if (NS_SUCCEEDED(rv) && scrollToClickMetric == 1)
     617                 :     scrollToClick = true;
     618                 :   return scrollToClick;
     619                 : 
     620                 : #else
     621                 :     return mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::movetoclick,
     622               0 :                                   nsGkAtoms::_true, eCaseMatters);
     623               0 :   return false;
     624                 : #endif
     625                 : }
     626                 : 
     627                 : nsIBox*
     628               0 : nsSliderFrame::GetScrollbar()
     629                 : {
     630                 :   // if we are in a scrollbar then return the scrollbar's content node
     631                 :   // if we are not then return ours.
     632                 :    nsIFrame* scrollbar;
     633               0 :    nsScrollbarButtonFrame::GetParentWithTag(nsGkAtoms::scrollbar, this, scrollbar);
     634                 : 
     635               0 :    if (scrollbar == nsnull)
     636               0 :        return this;
     637                 : 
     638               0 :    return scrollbar->IsBoxFrame() ? scrollbar : this;
     639                 : }
     640                 : 
     641                 : void
     642               0 : nsSliderFrame::PageUpDown(nscoord change)
     643                 : {
     644                 :   // on a page up or down get our page increment. We get this by getting the scrollbar we are in and
     645                 :   // asking it for the current position and the page increment. If we are not in a scrollbar we will
     646                 :   // get the values from our own node.
     647               0 :   nsIBox* scrollbarBox = GetScrollbar();
     648               0 :   nsCOMPtr<nsIContent> scrollbar;
     649               0 :   scrollbar = GetContentOfBox(scrollbarBox);
     650                 : 
     651               0 :   if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::dir,
     652               0 :                             nsGkAtoms::reverse, eCaseMatters))
     653               0 :     change = -change;
     654                 : 
     655               0 :   nscoord pageIncrement = GetPageIncrement(scrollbar);
     656               0 :   PRInt32 curpos = GetCurrentPosition(scrollbar);
     657               0 :   PRInt32 minpos = GetMinPosition(scrollbar);
     658               0 :   PRInt32 maxpos = GetMaxPosition(scrollbar);
     659                 : 
     660                 :   // get the new position and make sure it is in bounds
     661               0 :   PRInt32 newpos = curpos + change * pageIncrement;
     662               0 :   if (newpos < minpos || maxpos < minpos)
     663               0 :     newpos = minpos;
     664               0 :   else if (newpos > maxpos)
     665               0 :     newpos = maxpos;
     666                 : 
     667               0 :   SetCurrentPositionInternal(scrollbar, newpos, true, false);
     668               0 : }
     669                 : 
     670                 : // called when the current position changed and we need to update the thumb's location
     671                 : nsresult
     672               0 : nsSliderFrame::CurrentPositionChanged(nsPresContext* aPresContext,
     673                 :                                       bool aImmediateRedraw)
     674                 : {
     675               0 :   nsIBox* scrollbarBox = GetScrollbar();
     676               0 :   nsCOMPtr<nsIContent> scrollbar;
     677               0 :   scrollbar = GetContentOfBox(scrollbarBox);
     678                 : 
     679                 :   // get the current position
     680               0 :   PRInt32 curPos = GetCurrentPosition(scrollbar);
     681                 : 
     682                 :   // do nothing if the position did not change
     683               0 :   if (mCurPos == curPos)
     684               0 :       return NS_OK;
     685                 : 
     686                 :   // get our current min and max position from our content node
     687               0 :   PRInt32 minPos = GetMinPosition(scrollbar);
     688               0 :   PRInt32 maxPos = GetMaxPosition(scrollbar);
     689                 : 
     690               0 :   maxPos = NS_MAX(minPos, maxPos);
     691               0 :   curPos = clamped(curPos, minPos, maxPos);
     692                 : 
     693                 :   // get the thumb's rect
     694               0 :   nsIFrame* thumbFrame = mFrames.FirstChild();
     695               0 :   if (!thumbFrame)
     696               0 :     return NS_OK; // The thumb may stream in asynchronously via XBL.
     697                 : 
     698               0 :   nsRect thumbRect = thumbFrame->GetRect();
     699                 : 
     700               0 :   nsRect clientRect;
     701               0 :   GetClientRect(clientRect);
     702                 : 
     703                 :   // figure out the new rect
     704               0 :   nsRect newThumbRect(thumbRect);
     705                 : 
     706                 :   bool reverse = mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::dir,
     707               0 :                                          nsGkAtoms::reverse, eCaseMatters);
     708               0 :   nscoord pos = reverse ? (maxPos - curPos) : (curPos - minPos);
     709                 : 
     710               0 :   if (IsHorizontal())
     711               0 :      newThumbRect.x = clientRect.x + NSToCoordRound(pos * mRatio);
     712                 :   else
     713               0 :      newThumbRect.y = clientRect.y + NSToCoordRound(pos * mRatio);
     714                 : 
     715                 :   // set the rect
     716               0 :   thumbFrame->SetRect(newThumbRect);
     717                 : 
     718                 :   // Redraw the scrollbar
     719               0 :   InvalidateWithFlags(clientRect, aImmediateRedraw ? INVALIDATE_IMMEDIATE : 0);
     720                 : 
     721               0 :   mCurPos = curPos;
     722                 : 
     723                 :   // inform the parent <scale> if it exists that the value changed
     724               0 :   nsIFrame* parent = GetParent();
     725               0 :   if (parent) {
     726               0 :     nsCOMPtr<nsISliderListener> sliderListener = do_QueryInterface(parent->GetContent());
     727               0 :     if (sliderListener) {
     728                 :       nsContentUtils::AddScriptRunner(
     729               0 :         new nsValueChangedRunnable(sliderListener, nsGkAtoms::curpos, mCurPos, mUserChanged));
     730                 :     }
     731                 :   }
     732                 : 
     733               0 :   return NS_OK;
     734                 : }
     735                 : 
     736               0 : static void UpdateAttribute(nsIContent* aScrollbar, nscoord aNewPos, bool aNotify, bool aIsSmooth) {
     737               0 :   nsAutoString str;
     738               0 :   str.AppendInt(aNewPos);
     739                 :   
     740               0 :   if (aIsSmooth) {
     741               0 :     aScrollbar->SetAttr(kNameSpaceID_None, nsGkAtoms::smooth, NS_LITERAL_STRING("true"), false);
     742                 :   }
     743               0 :   aScrollbar->SetAttr(kNameSpaceID_None, nsGkAtoms::curpos, str, aNotify);
     744               0 :   if (aIsSmooth) {
     745               0 :     aScrollbar->UnsetAttr(kNameSpaceID_None, nsGkAtoms::smooth, false);
     746                 :   }
     747               0 : }
     748                 : 
     749                 : // Use this function when you want to set the scroll position via the position
     750                 : // of the scrollbar thumb, e.g. when dragging the slider. This function scrolls
     751                 : // the content in such a way that thumbRect.x/.y becomes aNewThumbPos.
     752                 : void
     753               0 : nsSliderFrame::SetCurrentThumbPosition(nsIContent* aScrollbar, nscoord aNewThumbPos,
     754                 :                                        bool aIsSmooth, bool aImmediateRedraw, bool aMaySnap)
     755                 : {
     756               0 :   nsRect crect;
     757               0 :   GetClientRect(crect);
     758               0 :   nscoord offset = IsHorizontal() ? crect.x : crect.y;
     759               0 :   PRInt32 newPos = NSToIntRound((aNewThumbPos - offset) / mRatio);
     760                 :   
     761               0 :   if (aMaySnap && mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::snap,
     762               0 :                                         nsGkAtoms::_true, eCaseMatters)) {
     763                 :     // If snap="true", then the slider may only be set to min + (increment * x).
     764                 :     // Otherwise, the slider may be set to any positive integer.
     765               0 :     PRInt32 increment = GetIncrement(aScrollbar);
     766               0 :     newPos = NSToIntRound(newPos / float(increment)) * increment;
     767                 :   }
     768                 :   
     769               0 :   SetCurrentPosition(aScrollbar, newPos, aIsSmooth, aImmediateRedraw);
     770               0 : }
     771                 : 
     772                 : // Use this function when you know the target scroll position of the scrolled content.
     773                 : // aNewPos should be passed to this function as a position as if the minpos is 0.
     774                 : // That is, the minpos will be added to the position by this function. In a reverse
     775                 : // direction slider, the newpos should be the distance from the end.
     776                 : void
     777               0 : nsSliderFrame::SetCurrentPosition(nsIContent* aScrollbar, PRInt32 aNewPos,
     778                 :                                   bool aIsSmooth, bool aImmediateRedraw)
     779                 : {
     780                 :    // get min and max position from our content node
     781               0 :   PRInt32 minpos = GetMinPosition(aScrollbar);
     782               0 :   PRInt32 maxpos = GetMaxPosition(aScrollbar);
     783                 : 
     784                 :   // in reverse direction sliders, flip the value so that it goes from
     785                 :   // right to left, or bottom to top.
     786               0 :   if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::dir,
     787               0 :                             nsGkAtoms::reverse, eCaseMatters))
     788               0 :     aNewPos = maxpos - aNewPos;
     789                 :   else
     790               0 :     aNewPos += minpos;
     791                 : 
     792                 :   // get the new position and make sure it is in bounds
     793               0 :   if (aNewPos < minpos || maxpos < minpos)
     794               0 :     aNewPos = minpos;
     795               0 :   else if (aNewPos > maxpos)
     796               0 :     aNewPos = maxpos;
     797                 : 
     798               0 :   SetCurrentPositionInternal(aScrollbar, aNewPos, aIsSmooth, aImmediateRedraw);
     799               0 : }
     800                 : 
     801                 : void
     802               0 : nsSliderFrame::SetCurrentPositionInternal(nsIContent* aScrollbar, PRInt32 aNewPos,
     803                 :                                           bool aIsSmooth,
     804                 :                                           bool aImmediateRedraw)
     805                 : {
     806               0 :   nsCOMPtr<nsIContent> scrollbar = aScrollbar;
     807               0 :   nsIBox* scrollbarBox = GetScrollbar();
     808                 : 
     809               0 :   mUserChanged = true;
     810                 : 
     811               0 :   nsScrollbarFrame* scrollbarFrame = do_QueryFrame(scrollbarBox);
     812               0 :   if (scrollbarFrame) {
     813                 :     // See if we have a mediator.
     814               0 :     nsIScrollbarMediator* mediator = scrollbarFrame->GetScrollbarMediator();
     815               0 :     if (mediator) {
     816               0 :       nsRefPtr<nsPresContext> context = PresContext();
     817               0 :       nsCOMPtr<nsIContent> content = GetContent();
     818               0 :       mediator->PositionChanged(scrollbarFrame, GetCurrentPosition(scrollbar), aNewPos);
     819                 :       // 'mediator' might be dangling now...
     820               0 :       UpdateAttribute(scrollbar, aNewPos, false, aIsSmooth);
     821               0 :       nsIFrame* frame = content->GetPrimaryFrame();
     822               0 :       if (frame && frame->GetType() == nsGkAtoms::sliderFrame) {
     823                 :         static_cast<nsSliderFrame*>(frame)->
     824               0 :           CurrentPositionChanged(frame->PresContext(), aImmediateRedraw);
     825                 :       }
     826               0 :       mUserChanged = false;
     827                 :       return;
     828                 :     }
     829                 :   }
     830                 : 
     831               0 :   UpdateAttribute(scrollbar, aNewPos, true, aIsSmooth);
     832               0 :   mUserChanged = false;
     833                 : 
     834                 : #ifdef DEBUG_SLIDER
     835                 :   printf("Current Pos=%d\n",aNewPos);
     836                 : #endif
     837                 : 
     838                 : }
     839                 : 
     840                 : nsIAtom*
     841               0 : nsSliderFrame::GetType() const
     842                 : {
     843               0 :   return nsGkAtoms::sliderFrame;
     844                 : }
     845                 : 
     846                 : NS_IMETHODIMP
     847               0 : nsSliderFrame::SetInitialChildList(ChildListID     aListID,
     848                 :                                    nsFrameList&    aChildList)
     849                 : {
     850               0 :   nsresult r = nsBoxFrame::SetInitialChildList(aListID, aChildList);
     851                 : 
     852               0 :   AddListener();
     853                 : 
     854               0 :   return r;
     855                 : }
     856                 : 
     857                 : nsresult
     858               0 : nsSliderMediator::HandleEvent(nsIDOMEvent* aEvent)
     859                 : {
     860                 :   // Only process the event if the thumb is not being dragged.
     861               0 :   if (mSlider && !mSlider->isDraggingThumb())
     862               0 :     return mSlider->MouseDown(aEvent);
     863                 : 
     864               0 :   return NS_OK;
     865                 : }
     866                 : 
     867                 : nsresult
     868               0 : nsSliderFrame::MouseDown(nsIDOMEvent* aMouseEvent)
     869                 : {
     870                 : #ifdef DEBUG_SLIDER
     871                 :   printf("Begin dragging\n");
     872                 : #endif
     873                 : 
     874               0 :   nsCOMPtr<nsIDOMMouseEvent> mouseEvent(do_QueryInterface(aMouseEvent));
     875               0 :   if (!mouseEvent)
     876               0 :     return NS_OK;
     877                 : 
     878               0 :   if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled,
     879               0 :                             nsGkAtoms::_true, eCaseMatters))
     880               0 :     return NS_OK;
     881                 : 
     882               0 :   PRUint16 button = 0;
     883               0 :   mouseEvent->GetButton(&button);
     884               0 :   if (!(button == 0 || (button == 1 && gMiddlePref)))
     885               0 :     return NS_OK;
     886                 : 
     887               0 :   bool isHorizontal = IsHorizontal();
     888                 : 
     889               0 :   bool scrollToClick = false;
     890                 : #ifndef XP_MACOSX
     891                 :   // On Mac there's no scroll-to-here when clicking the thumb
     892               0 :   mouseEvent->GetShiftKey(&scrollToClick);
     893               0 :   if (button != 0) {
     894               0 :     scrollToClick = true;
     895                 :   }
     896                 : #endif
     897                 : 
     898                 :   nsPoint pt =  nsLayoutUtils::GetDOMEventCoordinatesRelativeTo(mouseEvent,
     899               0 :                                                                 this);
     900               0 :   nscoord pos = isHorizontal ? pt.x : pt.y;
     901                 : 
     902                 :   // If shift click or middle button, first
     903                 :   // place the middle of the slider thumb under the click
     904               0 :   nsCOMPtr<nsIContent> scrollbar;
     905               0 :   nscoord newpos = pos;
     906               0 :   if (scrollToClick) {
     907                 :     // adjust so that the middle of the thumb is placed under the click
     908               0 :     nsIFrame* thumbFrame = mFrames.FirstChild();
     909               0 :     if (!thumbFrame) {
     910               0 :       return NS_OK;
     911                 :     }
     912               0 :     nsSize thumbSize = thumbFrame->GetSize();
     913               0 :     nscoord thumbLength = isHorizontal ? thumbSize.width : thumbSize.height;
     914                 : 
     915               0 :     newpos -= (thumbLength/2);
     916                 : 
     917               0 :     nsIBox* scrollbarBox = GetScrollbar();
     918               0 :     scrollbar = GetContentOfBox(scrollbarBox);
     919                 :   }
     920                 : 
     921               0 :   DragThumb(true);
     922                 : 
     923               0 :   if (scrollToClick) {
     924                 :     // should aMaySnap be true here?
     925               0 :     SetCurrentThumbPosition(scrollbar, newpos, false, false, false);
     926                 :   }
     927                 : 
     928               0 :   nsIFrame* thumbFrame = mFrames.FirstChild();
     929               0 :   if (!thumbFrame) {
     930               0 :     return NS_OK;
     931                 :   }
     932                 : 
     933               0 :   if (isHorizontal)
     934               0 :     mThumbStart = thumbFrame->GetPosition().x;
     935                 :   else
     936               0 :     mThumbStart = thumbFrame->GetPosition().y;
     937                 : 
     938               0 :   mDragStart = pos - mThumbStart;
     939                 : 
     940                 : #ifdef DEBUG_SLIDER
     941                 :   printf("Pressed mDragStart=%d\n",mDragStart);
     942                 : #endif
     943                 : 
     944               0 :   return NS_OK;
     945                 : }
     946                 : 
     947                 : void
     948               0 : nsSliderFrame::DragThumb(bool aGrabMouseEvents)
     949                 : {
     950                 :   // inform the parent <scale> that a drag is beginning or ending
     951               0 :   nsIFrame* parent = GetParent();
     952               0 :   if (parent) {
     953               0 :     nsCOMPtr<nsISliderListener> sliderListener = do_QueryInterface(parent->GetContent());
     954               0 :     if (sliderListener) {
     955                 :       nsContentUtils::AddScriptRunner(
     956               0 :         new nsDragStateChangedRunnable(sliderListener, aGrabMouseEvents));
     957                 :     }
     958                 :   }
     959                 : 
     960               0 :   nsIPresShell::SetCapturingContent(aGrabMouseEvents ? GetContent() : nsnull,
     961               0 :                                     aGrabMouseEvents ? CAPTURE_IGNOREALLOWED : 0);
     962               0 : }
     963                 : 
     964                 : bool
     965               0 : nsSliderFrame::isDraggingThumb()
     966                 : {
     967               0 :   return (nsIPresShell::GetCapturingContent() == GetContent());
     968                 : }
     969                 : 
     970                 : void
     971               0 : nsSliderFrame::AddListener()
     972                 : {
     973               0 :   if (!mMediator) {
     974               0 :     mMediator = new nsSliderMediator(this);
     975                 :   }
     976                 : 
     977               0 :   nsIFrame* thumbFrame = mFrames.FirstChild();
     978               0 :   if (!thumbFrame) {
     979               0 :     return;
     980                 :   }
     981               0 :   thumbFrame->GetContent()->
     982               0 :     AddSystemEventListener(NS_LITERAL_STRING("mousedown"), mMediator,
     983               0 :                            false, false);
     984                 : }
     985                 : 
     986                 : void
     987               0 : nsSliderFrame::RemoveListener()
     988                 : {
     989               0 :   NS_ASSERTION(mMediator, "No listener was ever added!!");
     990                 : 
     991               0 :   nsIFrame* thumbFrame = mFrames.FirstChild();
     992               0 :   if (!thumbFrame)
     993               0 :     return;
     994                 : 
     995               0 :   thumbFrame->GetContent()->
     996               0 :     RemoveSystemEventListener(NS_LITERAL_STRING("mousedown"), mMediator, false);
     997                 : }
     998                 : 
     999                 : NS_IMETHODIMP
    1000               0 : nsSliderFrame::HandlePress(nsPresContext* aPresContext,
    1001                 :                            nsGUIEvent*     aEvent,
    1002                 :                            nsEventStatus*  aEventStatus)
    1003                 : {
    1004                 : #ifdef XP_MACOSX
    1005                 :   // On Mac the option key inverts the scroll-to-here preference.
    1006                 :   if (((nsMouseEvent *)aEvent)->isAlt != GetScrollToClick())
    1007                 : #else
    1008               0 :   if (((nsMouseEvent *)aEvent)->isShift != GetScrollToClick())
    1009                 : #endif
    1010               0 :     return NS_OK;
    1011                 : 
    1012               0 :   nsIFrame* thumbFrame = mFrames.FirstChild();
    1013               0 :   if (!thumbFrame) // display:none?
    1014               0 :     return NS_OK;
    1015                 : 
    1016               0 :   if (mContent->AttrValueIs(kNameSpaceID_None, nsGkAtoms::disabled,
    1017               0 :                             nsGkAtoms::_true, eCaseMatters))
    1018               0 :     return NS_OK;
    1019                 :   
    1020               0 :   nsRect thumbRect = thumbFrame->GetRect();
    1021                 :   
    1022               0 :   nscoord change = 1;
    1023                 :   nsPoint eventPoint = nsLayoutUtils::GetEventCoordinatesRelativeTo(aEvent,
    1024               0 :                                                                     this);
    1025               0 :   if (IsHorizontal() ? eventPoint.x < thumbRect.x 
    1026                 :                      : eventPoint.y < thumbRect.y)
    1027               0 :     change = -1;
    1028                 : 
    1029               0 :   mChange = change;
    1030               0 :   DragThumb(true);
    1031               0 :   mDestinationPoint = eventPoint;
    1032               0 :   StartRepeat();
    1033               0 :   PageUpDown(change);
    1034               0 :   return NS_OK;
    1035                 : }
    1036                 : 
    1037                 : NS_IMETHODIMP
    1038               0 : nsSliderFrame::HandleRelease(nsPresContext* aPresContext,
    1039                 :                                  nsGUIEvent*     aEvent,
    1040                 :                                  nsEventStatus*  aEventStatus)
    1041                 : {
    1042               0 :   StopRepeat();
    1043                 : 
    1044               0 :   return NS_OK;
    1045                 : }
    1046                 : 
    1047                 : void
    1048               0 : nsSliderFrame::DestroyFrom(nsIFrame* aDestructRoot)
    1049                 : {
    1050                 :   // tell our mediator if we have one we are gone.
    1051               0 :   if (mMediator) {
    1052               0 :     mMediator->SetSlider(nsnull);
    1053               0 :     mMediator = nsnull;
    1054                 :   }
    1055               0 :   StopRepeat();
    1056                 : 
    1057                 :   // call base class Destroy()
    1058               0 :   nsBoxFrame::DestroyFrom(aDestructRoot);
    1059               0 : }
    1060                 : 
    1061                 : nsSize
    1062               0 : nsSliderFrame::GetPrefSize(nsBoxLayoutState& aState)
    1063                 : {
    1064               0 :   EnsureOrient();
    1065               0 :   return nsBoxFrame::GetPrefSize(aState);
    1066                 : }
    1067                 : 
    1068                 : nsSize
    1069               0 : nsSliderFrame::GetMinSize(nsBoxLayoutState& aState)
    1070                 : {
    1071               0 :   EnsureOrient();
    1072                 : 
    1073                 :   // our min size is just our borders and padding
    1074               0 :   return nsBox::GetMinSize(aState);
    1075                 : }
    1076                 : 
    1077                 : nsSize
    1078               0 : nsSliderFrame::GetMaxSize(nsBoxLayoutState& aState)
    1079                 : {
    1080               0 :   EnsureOrient();
    1081               0 :   return nsBoxFrame::GetMaxSize(aState);
    1082                 : }
    1083                 : 
    1084                 : void
    1085               0 : nsSliderFrame::EnsureOrient()
    1086                 : {
    1087               0 :   nsIBox* scrollbarBox = GetScrollbar();
    1088                 : 
    1089               0 :   bool isHorizontal = (scrollbarBox->GetStateBits() & NS_STATE_IS_HORIZONTAL) != 0;
    1090               0 :   if (isHorizontal)
    1091               0 :       mState |= NS_STATE_IS_HORIZONTAL;
    1092                 :   else
    1093               0 :       mState &= ~NS_STATE_IS_HORIZONTAL;
    1094               0 : }
    1095                 : 
    1096                 : 
    1097               0 : void nsSliderFrame::Notify(void)
    1098                 : {
    1099               0 :     bool stop = false;
    1100                 : 
    1101               0 :     nsIFrame* thumbFrame = mFrames.FirstChild();
    1102               0 :     if (!thumbFrame) {
    1103               0 :       StopRepeat();
    1104               0 :       return;
    1105                 :     }
    1106               0 :     nsRect thumbRect = thumbFrame->GetRect();
    1107                 : 
    1108               0 :     bool isHorizontal = IsHorizontal();
    1109                 : 
    1110                 :     // See if the thumb has moved past our destination point.
    1111                 :     // if it has we want to stop.
    1112               0 :     if (isHorizontal) {
    1113               0 :         if (mChange < 0) {
    1114               0 :             if (thumbRect.x < mDestinationPoint.x)
    1115               0 :                 stop = true;
    1116                 :         } else {
    1117               0 :             if (thumbRect.x + thumbRect.width > mDestinationPoint.x)
    1118               0 :                 stop = true;
    1119                 :         }
    1120                 :     } else {
    1121               0 :          if (mChange < 0) {
    1122               0 :             if (thumbRect.y < mDestinationPoint.y)
    1123               0 :                 stop = true;
    1124                 :         } else {
    1125               0 :             if (thumbRect.y + thumbRect.height > mDestinationPoint.y)
    1126               0 :                 stop = true;
    1127                 :         }
    1128                 :     }
    1129                 : 
    1130                 : 
    1131               0 :     if (stop) {
    1132               0 :       StopRepeat();
    1133                 :     } else {
    1134               0 :       PageUpDown(mChange);
    1135                 :     }
    1136                 : }
    1137                 : 
    1138               0 : NS_IMPL_ISUPPORTS1(nsSliderMediator,
    1139                 :                    nsIDOMEventListener)

Generated by: LCOV version 1.7