tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsScrollbarButtonFrame.cpp (6771B)


      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 //
      8 // Eric Vaughan
      9 // Netscape Communications
     10 //
     11 // See documentation in associated header file
     12 //
     13 
     14 #include "nsScrollbarButtonFrame.h"
     15 
     16 #include "mozilla/LookAndFeel.h"
     17 #include "mozilla/MouseEvents.h"
     18 #include "mozilla/PresShell.h"
     19 #include "nsCOMPtr.h"
     20 #include "nsGkAtoms.h"
     21 #include "nsIContent.h"
     22 #include "nsIScrollbarMediator.h"
     23 #include "nsLayoutUtils.h"
     24 #include "nsNameSpaceManager.h"
     25 #include "nsPresContext.h"
     26 #include "nsRepeatService.h"
     27 #include "nsScrollbarFrame.h"
     28 #include "nsSliderFrame.h"
     29 
     30 using namespace mozilla;
     31 
     32 //
     33 // NS_NewToolbarFrame
     34 //
     35 // Creates a new Toolbar frame and returns it
     36 //
     37 nsIFrame* NS_NewScrollbarButtonFrame(PresShell* aPresShell,
     38                                     ComputedStyle* aStyle) {
     39  return new (aPresShell)
     40      nsScrollbarButtonFrame(aStyle, aPresShell->GetPresContext());
     41 }
     42 NS_IMPL_FRAMEARENA_HELPERS(nsScrollbarButtonFrame)
     43 
     44 nsresult nsScrollbarButtonFrame::HandleEvent(nsPresContext* aPresContext,
     45                                             WidgetGUIEvent* aEvent,
     46                                             nsEventStatus* aEventStatus) {
     47  NS_ENSURE_ARG_POINTER(aEventStatus);
     48 
     49  // If a web page calls event.preventDefault() we still want to
     50  // scroll when scroll arrow is clicked. See bug 511075.
     51  if (!mContent->IsInNativeAnonymousSubtree() &&
     52      nsEventStatus_eConsumeNoDefault == *aEventStatus) {
     53    return NS_OK;
     54  }
     55 
     56  switch (aEvent->mMessage) {
     57    case eMouseDown:
     58      mCursorOnThis = true;
     59      // if we didn't handle the press ourselves, pass it on to the superclass
     60      if (HandleButtonPress(aPresContext, aEvent, aEventStatus)) {
     61        return NS_OK;
     62      }
     63      break;
     64    case eMouseUp:
     65      HandleRelease(aPresContext, aEvent, aEventStatus);
     66      break;
     67    case eMouseOut:
     68      mCursorOnThis = false;
     69      break;
     70    case eMouseMove: {
     71      nsPoint cursor = nsLayoutUtils::GetEventCoordinatesRelativeTo(
     72          aEvent, RelativeTo{this});
     73      nsRect frameRect(nsPoint(0, 0), GetSize());
     74      mCursorOnThis = frameRect.Contains(cursor);
     75      break;
     76    }
     77    default:
     78      break;
     79  }
     80 
     81  return SimpleXULLeafFrame::HandleEvent(aPresContext, aEvent, aEventStatus);
     82 }
     83 
     84 bool nsScrollbarButtonFrame::HandleButtonPress(nsPresContext* aPresContext,
     85                                               WidgetGUIEvent* aEvent,
     86                                               nsEventStatus* aEventStatus) {
     87  // Get the desired action for the scrollbar button.
     88  LookAndFeel::IntID tmpAction;
     89  uint16_t button = aEvent->AsMouseEvent()->mButton;
     90  if (button == MouseButton::ePrimary) {
     91    tmpAction = LookAndFeel::IntID::ScrollButtonLeftMouseButtonAction;
     92  } else if (button == MouseButton::eMiddle) {
     93    tmpAction = LookAndFeel::IntID::ScrollButtonMiddleMouseButtonAction;
     94  } else if (button == MouseButton::eSecondary) {
     95    tmpAction = LookAndFeel::IntID::ScrollButtonRightMouseButtonAction;
     96  } else {
     97    return false;
     98  }
     99 
    100  // Get the button action metric from the pres. shell.
    101  int32_t pressedButtonAction;
    102  if (NS_FAILED(LookAndFeel::GetInt(tmpAction, &pressedButtonAction))) {
    103    return false;
    104  }
    105 
    106  // get the scrollbar control
    107  nsScrollbarFrame* scrollbar = GetScrollbar();
    108  if (!scrollbar) {
    109    return false;
    110  }
    111 
    112  static dom::Element::AttrValuesArray strings[] = {
    113      nsGkAtoms::increment, nsGkAtoms::decrement, nullptr};
    114  int32_t index = mContent->AsElement()->FindAttrValueIn(
    115      kNameSpaceID_None, nsGkAtoms::type, strings, eCaseMatters);
    116  int32_t direction;
    117  if (index == 0) {
    118    direction = 1;
    119  } else if (index == 1) {
    120    direction = -1;
    121  } else {
    122    return false;
    123  }
    124 
    125  const bool repeat = pressedButtonAction != 2;
    126 
    127  PresShell::SetCapturingContent(mContent, CaptureFlags::IgnoreAllowedState);
    128 
    129  AutoWeakFrame weakFrame(this);
    130 
    131  nsIScrollbarMediator* m = scrollbar->GetScrollbarMediator();
    132  switch (pressedButtonAction) {
    133    case 0:
    134      scrollbar->SetButtonScrollDirectionAndUnit(direction, ScrollUnit::LINES);
    135      if (m) {
    136        m->ScrollByLine(scrollbar, direction,
    137                        ScrollSnapFlags::IntendedDirection);
    138      }
    139      break;
    140    case 1:
    141      scrollbar->SetButtonScrollDirectionAndUnit(direction, ScrollUnit::PAGES);
    142      if (m) {
    143        m->ScrollByPage(scrollbar, direction,
    144                        ScrollSnapFlags::IntendedDirection |
    145                            ScrollSnapFlags::IntendedEndPosition);
    146      }
    147      break;
    148    case 2:
    149      scrollbar->SetButtonScrollDirectionAndUnit(direction, ScrollUnit::WHOLE);
    150      if (m) {
    151        m->ScrollByWhole(scrollbar, direction,
    152                         ScrollSnapFlags::IntendedEndPosition);
    153      }
    154      break;
    155    case 3:
    156    default:
    157      // We were told to ignore this click, or someone assigned a non-standard
    158      // value to the button's action.
    159      return false;
    160  }
    161  if (!weakFrame.IsAlive()) {
    162    return false;
    163  }
    164  if (repeat) {
    165    StartRepeat();
    166  }
    167  return true;
    168 }
    169 
    170 NS_IMETHODIMP
    171 nsScrollbarButtonFrame::HandleRelease(nsPresContext* aPresContext,
    172                                      WidgetGUIEvent* aEvent,
    173                                      nsEventStatus* aEventStatus) {
    174  PresShell::ReleaseCapturingContent();
    175  StopRepeat();
    176  if (nsScrollbarFrame* scrollbar = GetScrollbar()) {
    177    if (nsIScrollbarMediator* m = scrollbar->GetScrollbarMediator()) {
    178      m->ScrollbarReleased(scrollbar);
    179    }
    180  }
    181  return NS_OK;
    182 }
    183 
    184 void nsScrollbarButtonFrame::Notify() {
    185  if (mCursorOnThis ||
    186      LookAndFeel::GetInt(LookAndFeel::IntID::ScrollbarButtonAutoRepeatBehavior,
    187                          0)) {
    188    // get the scrollbar control
    189    if (nsScrollbarFrame* sb = GetScrollbar()) {
    190      if (nsIScrollbarMediator* m = sb->GetScrollbarMediator()) {
    191        m->RepeatButtonScroll(sb);
    192      }
    193    }
    194  }
    195 }
    196 
    197 nsIScrollbarMediator* nsScrollbarButtonFrame::GetMediator() {
    198  if (auto* sb = GetScrollbar()) {
    199    return sb->GetScrollbarMediator();
    200  }
    201  return nullptr;
    202 }
    203 
    204 nsScrollbarFrame* nsScrollbarButtonFrame::GetScrollbar() {
    205  for (nsIFrame* cur = GetParent(); cur; cur = cur->GetParent()) {
    206    if (cur->IsScrollbarFrame()) {
    207      return static_cast<nsScrollbarFrame*>(cur);
    208    }
    209  }
    210  return nullptr;
    211 }
    212 
    213 void nsScrollbarButtonFrame::Destroy(DestroyContext& aContext) {
    214  // Ensure our repeat service isn't going... it's possible that a scrollbar can
    215  // disappear out from under you while you're in the process of scrolling.
    216  StopRepeat();
    217  SimpleXULLeafFrame::Destroy(aContext);
    218 }