|
Packit |
f0b94e |
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
Packit |
f0b94e |
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
Packit |
f0b94e |
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
Packit |
f0b94e |
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
Packit |
f0b94e |
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
#include "WheelHandlingHelper.h"
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
#include "mozilla/EventDispatcher.h"
|
|
Packit |
f0b94e |
#include "mozilla/EventStateManager.h"
|
|
Packit |
f0b94e |
#include "mozilla/MouseEvents.h"
|
|
Packit |
f0b94e |
#include "mozilla/Preferences.h"
|
|
Packit |
f0b94e |
#include "nsCOMPtr.h"
|
|
Packit |
f0b94e |
#include "nsContentUtils.h"
|
|
Packit |
f0b94e |
#include "nsIContent.h"
|
|
Packit |
f0b94e |
#include "nsIDocument.h"
|
|
Packit |
f0b94e |
#include "nsIPresShell.h"
|
|
Packit |
f0b94e |
#include "nsIScrollableFrame.h"
|
|
Packit |
f0b94e |
#include "nsITextControlElement.h"
|
|
Packit |
f0b94e |
#include "nsITimer.h"
|
|
Packit |
f0b94e |
#include "nsPluginFrame.h"
|
|
Packit |
f0b94e |
#include "nsPresContext.h"
|
|
Packit |
f0b94e |
#include "prtime.h"
|
|
Packit |
f0b94e |
#include "Units.h"
|
|
Packit |
f0b94e |
#include "ScrollAnimationPhysics.h"
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
namespace mozilla {
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/******************************************************************/
|
|
Packit |
f0b94e |
/* mozilla::DeltaValues */
|
|
Packit |
f0b94e |
/******************************************************************/
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
DeltaValues::DeltaValues(WidgetWheelEvent* aEvent)
|
|
Packit |
f0b94e |
: deltaX(aEvent->mDeltaX), deltaY(aEvent->mDeltaY) {}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/******************************************************************/
|
|
Packit |
f0b94e |
/* mozilla::WheelHandlingUtils */
|
|
Packit |
f0b94e |
/******************************************************************/
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ bool WheelHandlingUtils::CanScrollInRange(nscoord aMin,
|
|
Packit |
f0b94e |
nscoord aValue,
|
|
Packit |
f0b94e |
nscoord aMax,
|
|
Packit |
f0b94e |
double aDirection) {
|
|
Packit |
f0b94e |
return aDirection > 0.0 ? aValue < static_cast<double>(aMax)
|
|
Packit |
f0b94e |
: static_cast<double>(aMin) < aValue;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ bool WheelHandlingUtils::CanScrollOn(nsIFrame* aFrame,
|
|
Packit |
f0b94e |
double aDirectionX,
|
|
Packit |
f0b94e |
double aDirectionY) {
|
|
Packit |
f0b94e |
nsIScrollableFrame* scrollableFrame = do_QueryFrame(aFrame);
|
|
Packit |
f0b94e |
if (scrollableFrame) {
|
|
Packit |
f0b94e |
return CanScrollOn(scrollableFrame, aDirectionX, aDirectionY);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
nsPluginFrame* pluginFrame = do_QueryFrame(aFrame);
|
|
Packit |
f0b94e |
return pluginFrame && pluginFrame->WantsToHandleWheelEventAsDefaultAction();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ bool WheelHandlingUtils::CanScrollOn(
|
|
Packit |
f0b94e |
nsIScrollableFrame* aScrollFrame, double aDirectionX, double aDirectionY) {
|
|
Packit |
f0b94e |
MOZ_ASSERT(aScrollFrame);
|
|
Packit |
f0b94e |
NS_ASSERTION(aDirectionX || aDirectionY,
|
|
Packit |
f0b94e |
"One of the delta values must be non-zero at least");
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
nsPoint scrollPt = aScrollFrame->GetScrollPosition();
|
|
Packit |
f0b94e |
nsRect scrollRange = aScrollFrame->GetScrollRange();
|
|
Packit |
f0b94e |
uint32_t directions = aScrollFrame->GetPerceivedScrollingDirections();
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
return (aDirectionX && (directions & nsIScrollableFrame::HORIZONTAL) &&
|
|
Packit |
f0b94e |
CanScrollInRange(scrollRange.x, scrollPt.x, scrollRange.XMost(),
|
|
Packit |
f0b94e |
aDirectionX)) ||
|
|
Packit |
f0b94e |
(aDirectionY && (directions & nsIScrollableFrame::VERTICAL) &&
|
|
Packit |
f0b94e |
CanScrollInRange(scrollRange.y, scrollPt.y, scrollRange.YMost(),
|
|
Packit |
f0b94e |
aDirectionY));
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/*static*/ Maybe<layers::ScrollDirection>
|
|
Packit |
f0b94e |
WheelHandlingUtils::GetDisregardedWheelScrollDirection(const nsIFrame* aFrame) {
|
|
Packit |
f0b94e |
nsIContent* content = aFrame->GetContent();
|
|
Packit |
f0b94e |
if (!content) {
|
|
Packit |
f0b94e |
return Nothing();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
nsCOMPtr<nsITextControlElement> ctrl = do_QueryInterface(
|
|
Packit |
f0b94e |
content->IsInAnonymousSubtree() ? content->GetBindingParent() : content);
|
|
Packit |
f0b94e |
if (!ctrl || !ctrl->IsSingleLineTextControl()) {
|
|
Packit |
f0b94e |
return Nothing();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
// Disregard scroll in the block-flow direction by mouse wheel on a
|
|
Packit |
f0b94e |
// single-line text control. For instance, in tranditional Chinese writing
|
|
Packit |
f0b94e |
// system, a single-line text control cannot be scrolled horizontally with
|
|
Packit |
f0b94e |
// mouse wheel even if they overflow at the right and left edges; Whereas in
|
|
Packit |
f0b94e |
// latin-based writing system, a single-line text control cannot be scrolled
|
|
Packit |
f0b94e |
// vertically with mouse wheel even if they overflow at the top and bottom
|
|
Packit |
f0b94e |
// edges
|
|
Packit |
f0b94e |
return Some(aFrame->GetWritingMode().IsVertical()
|
|
Packit |
f0b94e |
? layers::ScrollDirection::eHorizontal
|
|
Packit |
f0b94e |
: layers::ScrollDirection::eVertical);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/******************************************************************/
|
|
Packit |
f0b94e |
/* mozilla::WheelTransaction */
|
|
Packit |
f0b94e |
/******************************************************************/
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
AutoWeakFrame WheelTransaction::sTargetFrame(nullptr);
|
|
Packit |
f0b94e |
uint32_t WheelTransaction::sTime = 0;
|
|
Packit |
f0b94e |
uint32_t WheelTransaction::sMouseMoved = 0;
|
|
Packit |
f0b94e |
nsITimer* WheelTransaction::sTimer = nullptr;
|
|
Packit |
f0b94e |
int32_t WheelTransaction::sScrollSeriesCounter = 0;
|
|
Packit |
f0b94e |
bool WheelTransaction::sOwnScrollbars = false;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ bool WheelTransaction::OutOfTime(uint32_t aBaseTime,
|
|
Packit |
f0b94e |
uint32_t aThreshold) {
|
|
Packit |
f0b94e |
uint32_t now = PR_IntervalToMilliseconds(PR_IntervalNow());
|
|
Packit |
f0b94e |
return (now - aBaseTime > aThreshold);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ void WheelTransaction::OwnScrollbars(bool aOwn) {
|
|
Packit |
f0b94e |
sOwnScrollbars = aOwn;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ void WheelTransaction::BeginTransaction(
|
|
Packit |
f0b94e |
nsIFrame* aTargetFrame, const WidgetWheelEvent* aEvent) {
|
|
Packit |
f0b94e |
NS_ASSERTION(!sTargetFrame, "previous transaction is not finished!");
|
|
Packit |
f0b94e |
MOZ_ASSERT(aEvent->mMessage == eWheel,
|
|
Packit |
f0b94e |
"Transaction must be started with a wheel event");
|
|
Packit |
f0b94e |
ScrollbarsForWheel::OwnWheelTransaction(false);
|
|
Packit |
f0b94e |
sTargetFrame = aTargetFrame;
|
|
Packit |
f0b94e |
sScrollSeriesCounter = 0;
|
|
Packit |
f0b94e |
if (!UpdateTransaction(aEvent)) {
|
|
Packit |
f0b94e |
NS_ERROR("BeginTransaction is called even cannot scroll the frame");
|
|
Packit |
f0b94e |
EndTransaction();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ bool WheelTransaction::UpdateTransaction(
|
|
Packit |
f0b94e |
const WidgetWheelEvent* aEvent) {
|
|
Packit |
f0b94e |
nsIFrame* scrollToFrame = GetTargetFrame();
|
|
Packit |
f0b94e |
nsIScrollableFrame* scrollableFrame = scrollToFrame->GetScrollTargetFrame();
|
|
Packit |
f0b94e |
if (scrollableFrame) {
|
|
Packit |
f0b94e |
scrollToFrame = do_QueryFrame(scrollableFrame);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (!WheelHandlingUtils::CanScrollOn(scrollToFrame, aEvent->mDeltaX,
|
|
Packit |
f0b94e |
aEvent->mDeltaY)) {
|
|
Packit |
f0b94e |
OnFailToScrollTarget();
|
|
Packit |
f0b94e |
// We should not modify the transaction state when the view will not be
|
|
Packit |
f0b94e |
// scrolled actually.
|
|
Packit |
f0b94e |
return false;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
SetTimeout();
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (sScrollSeriesCounter != 0 && OutOfTime(sTime, kScrollSeriesTimeoutMs)) {
|
|
Packit |
f0b94e |
sScrollSeriesCounter = 0;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
sScrollSeriesCounter++;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// We should use current time instead of WidgetEvent.time.
|
|
Packit |
f0b94e |
// 1. Some events doesn't have the correct creation time.
|
|
Packit |
f0b94e |
// 2. If the computer runs slowly by other processes eating the CPU resource,
|
|
Packit |
f0b94e |
// the event creation time doesn't keep real time.
|
|
Packit |
f0b94e |
sTime = PR_IntervalToMilliseconds(PR_IntervalNow());
|
|
Packit |
f0b94e |
sMouseMoved = 0;
|
|
Packit |
f0b94e |
return true;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ void WheelTransaction::MayEndTransaction() {
|
|
Packit |
f0b94e |
if (!sOwnScrollbars && ScrollbarsForWheel::IsActive()) {
|
|
Packit |
f0b94e |
ScrollbarsForWheel::OwnWheelTransaction(true);
|
|
Packit |
f0b94e |
} else {
|
|
Packit |
f0b94e |
EndTransaction();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ void WheelTransaction::EndTransaction() {
|
|
Packit |
f0b94e |
if (sTimer) {
|
|
Packit |
f0b94e |
sTimer->Cancel();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
sTargetFrame = nullptr;
|
|
Packit |
f0b94e |
sScrollSeriesCounter = 0;
|
|
Packit |
f0b94e |
if (sOwnScrollbars) {
|
|
Packit |
f0b94e |
sOwnScrollbars = false;
|
|
Packit |
f0b94e |
ScrollbarsForWheel::OwnWheelTransaction(false);
|
|
Packit |
f0b94e |
ScrollbarsForWheel::Inactivate();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ bool WheelTransaction::WillHandleDefaultAction(
|
|
Packit |
f0b94e |
WidgetWheelEvent* aWheelEvent, AutoWeakFrame& aTargetWeakFrame) {
|
|
Packit |
f0b94e |
nsIFrame* lastTargetFrame = GetTargetFrame();
|
|
Packit |
f0b94e |
if (!lastTargetFrame) {
|
|
Packit |
f0b94e |
BeginTransaction(aTargetWeakFrame.GetFrame(), aWheelEvent);
|
|
Packit |
f0b94e |
} else if (lastTargetFrame != aTargetWeakFrame.GetFrame()) {
|
|
Packit |
f0b94e |
EndTransaction();
|
|
Packit |
f0b94e |
BeginTransaction(aTargetWeakFrame.GetFrame(), aWheelEvent);
|
|
Packit |
f0b94e |
} else {
|
|
Packit |
f0b94e |
UpdateTransaction(aWheelEvent);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// When the wheel event will not be handled with any frames,
|
|
Packit |
f0b94e |
// UpdateTransaction() fires MozMouseScrollFailed event which is for
|
|
Packit |
f0b94e |
// automated testing. In the event handler, the target frame might be
|
|
Packit |
f0b94e |
// destroyed. Then, the caller shouldn't try to handle the default action.
|
|
Packit |
f0b94e |
if (!aTargetWeakFrame.IsAlive()) {
|
|
Packit |
f0b94e |
EndTransaction();
|
|
Packit |
f0b94e |
return false;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
return true;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ void WheelTransaction::OnEvent(WidgetEvent* aEvent) {
|
|
Packit |
f0b94e |
if (!sTargetFrame) {
|
|
Packit |
f0b94e |
return;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (OutOfTime(sTime, GetTimeoutTime())) {
|
|
Packit |
f0b94e |
// Even if the scroll event which is handled after timeout, but onTimeout
|
|
Packit |
f0b94e |
// was not fired by timer, then the scroll event will scroll old frame,
|
|
Packit |
f0b94e |
// therefore, we should call OnTimeout here and ensure to finish the old
|
|
Packit |
f0b94e |
// transaction.
|
|
Packit |
f0b94e |
OnTimeout(nullptr, nullptr);
|
|
Packit |
f0b94e |
return;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
switch (aEvent->mMessage) {
|
|
Packit |
f0b94e |
case eWheel:
|
|
Packit |
f0b94e |
if (sMouseMoved != 0 &&
|
|
Packit |
f0b94e |
OutOfTime(sMouseMoved, GetIgnoreMoveDelayTime())) {
|
|
Packit |
f0b94e |
// Terminate the current mousewheel transaction if the mouse moved more
|
|
Packit |
f0b94e |
// than ignoremovedelay milliseconds ago
|
|
Packit |
f0b94e |
EndTransaction();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
return;
|
|
Packit |
f0b94e |
case eMouseMove:
|
|
Packit |
f0b94e |
case eDragOver: {
|
|
Packit |
f0b94e |
WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
|
|
Packit |
f0b94e |
if (mouseEvent->IsReal()) {
|
|
Packit |
f0b94e |
// If the cursor is moving to be outside the frame,
|
|
Packit |
f0b94e |
// terminate the scrollwheel transaction.
|
|
Packit |
f0b94e |
LayoutDeviceIntPoint pt = GetScreenPoint(mouseEvent);
|
|
Packit |
f0b94e |
auto r = LayoutDeviceIntRect::FromAppUnitsToNearest(
|
|
Packit |
f0b94e |
sTargetFrame->GetScreenRectInAppUnits(),
|
|
Packit |
f0b94e |
sTargetFrame->PresContext()->AppUnitsPerDevPixel());
|
|
Packit |
f0b94e |
if (!r.Contains(pt)) {
|
|
Packit |
f0b94e |
EndTransaction();
|
|
Packit |
f0b94e |
return;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// If the cursor is moving inside the frame, and it is less than
|
|
Packit |
f0b94e |
// ignoremovedelay milliseconds since the last scroll operation, ignore
|
|
Packit |
f0b94e |
// the mouse move; otherwise, record the current mouse move time to be
|
|
Packit |
f0b94e |
// checked later
|
|
Packit |
f0b94e |
if (!sMouseMoved && OutOfTime(sTime, GetIgnoreMoveDelayTime())) {
|
|
Packit |
f0b94e |
sMouseMoved = PR_IntervalToMilliseconds(PR_IntervalNow());
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
return;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
case eKeyPress:
|
|
Packit |
f0b94e |
case eKeyUp:
|
|
Packit |
f0b94e |
case eKeyDown:
|
|
Packit |
f0b94e |
case eMouseUp:
|
|
Packit |
f0b94e |
case eMouseDown:
|
|
Packit |
f0b94e |
case eMouseDoubleClick:
|
|
Packit |
f0b94e |
case eMouseAuxClick:
|
|
Packit |
f0b94e |
case eMouseClick:
|
|
Packit |
f0b94e |
case eContextMenu:
|
|
Packit |
f0b94e |
case eDrop:
|
|
Packit |
f0b94e |
EndTransaction();
|
|
Packit |
f0b94e |
return;
|
|
Packit |
f0b94e |
default:
|
|
Packit |
f0b94e |
break;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ void WheelTransaction::Shutdown() { NS_IF_RELEASE(sTimer); }
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ void WheelTransaction::OnFailToScrollTarget() {
|
|
Packit |
f0b94e |
NS_PRECONDITION(sTargetFrame, "We don't have mouse scrolling transaction");
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (Prefs::sTestMouseScroll) {
|
|
Packit |
f0b94e |
// This event is used for automated tests, see bug 442774.
|
|
Packit |
f0b94e |
nsContentUtils::DispatchTrustedEvent(
|
|
Packit |
f0b94e |
sTargetFrame->GetContent()->OwnerDoc(), sTargetFrame->GetContent(),
|
|
Packit |
f0b94e |
NS_LITERAL_STRING("MozMouseScrollFailed"), true, true);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
// The target frame might be destroyed in the event handler, at that time,
|
|
Packit |
f0b94e |
// we need to finish the current transaction
|
|
Packit |
f0b94e |
if (!sTargetFrame) {
|
|
Packit |
f0b94e |
EndTransaction();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ void WheelTransaction::OnTimeout(nsITimer* aTimer,
|
|
Packit |
f0b94e |
void* aClosure) {
|
|
Packit |
f0b94e |
if (!sTargetFrame) {
|
|
Packit |
f0b94e |
// The transaction target was destroyed already
|
|
Packit |
f0b94e |
EndTransaction();
|
|
Packit |
f0b94e |
return;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
// Store the sTargetFrame, the variable becomes null in EndTransaction.
|
|
Packit |
f0b94e |
nsIFrame* frame = sTargetFrame;
|
|
Packit |
f0b94e |
// We need to finish current transaction before DOM event firing. Because
|
|
Packit |
f0b94e |
// the next DOM event might create strange situation for us.
|
|
Packit |
f0b94e |
MayEndTransaction();
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (Prefs::sTestMouseScroll) {
|
|
Packit |
f0b94e |
// This event is used for automated tests, see bug 442774.
|
|
Packit |
f0b94e |
nsContentUtils::DispatchTrustedEvent(
|
|
Packit |
f0b94e |
frame->GetContent()->OwnerDoc(), frame->GetContent(),
|
|
Packit |
f0b94e |
NS_LITERAL_STRING("MozMouseScrollTransactionTimeout"), true, true);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ void WheelTransaction::SetTimeout() {
|
|
Packit |
f0b94e |
if (!sTimer) {
|
|
Packit |
f0b94e |
sTimer = NS_NewTimer().take();
|
|
Packit |
f0b94e |
if (!sTimer) {
|
|
Packit |
f0b94e |
return;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
sTimer->Cancel();
|
|
Packit |
f0b94e |
DebugOnly<nsresult> rv = sTimer->InitWithNamedFuncCallback(
|
|
Packit |
f0b94e |
OnTimeout, nullptr, GetTimeoutTime(), nsITimer::TYPE_ONE_SHOT,
|
|
Packit |
f0b94e |
"WheelTransaction::SetTimeout");
|
|
Packit |
f0b94e |
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv),
|
|
Packit |
f0b94e |
"nsITimer::InitWithFuncCallback failed");
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ LayoutDeviceIntPoint WheelTransaction::GetScreenPoint(
|
|
Packit |
f0b94e |
WidgetGUIEvent* aEvent) {
|
|
Packit |
f0b94e |
NS_ASSERTION(aEvent, "aEvent is null");
|
|
Packit |
f0b94e |
NS_ASSERTION(aEvent->mWidget, "aEvent-mWidget is null");
|
|
Packit |
f0b94e |
return aEvent->mRefPoint + aEvent->mWidget->WidgetToScreenOffset();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ DeltaValues WheelTransaction::AccelerateWheelDelta(
|
|
Packit |
f0b94e |
WidgetWheelEvent* aEvent, bool aAllowScrollSpeedOverride) {
|
|
Packit |
f0b94e |
DeltaValues result(aEvent);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// Don't accelerate the delta values if the event isn't line scrolling.
|
|
Packit |
f0b94e |
if (aEvent->mDeltaMode != nsIDOMWheelEvent::DOM_DELTA_LINE) {
|
|
Packit |
f0b94e |
return result;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (aAllowScrollSpeedOverride) {
|
|
Packit |
f0b94e |
result = OverrideSystemScrollSpeed(aEvent);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// Accelerate by the sScrollSeriesCounter
|
|
Packit |
f0b94e |
int32_t start = GetAccelerationStart();
|
|
Packit |
f0b94e |
if (start >= 0 && sScrollSeriesCounter >= start) {
|
|
Packit |
f0b94e |
int32_t factor = GetAccelerationFactor();
|
|
Packit |
f0b94e |
if (factor > 0) {
|
|
Packit |
f0b94e |
result.deltaX = ComputeAcceleratedWheelDelta(result.deltaX, factor);
|
|
Packit |
f0b94e |
result.deltaY = ComputeAcceleratedWheelDelta(result.deltaY, factor);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
return result;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ double WheelTransaction::ComputeAcceleratedWheelDelta(
|
|
Packit |
f0b94e |
double aDelta, int32_t aFactor) {
|
|
Packit |
f0b94e |
return mozilla::ComputeAcceleratedWheelDelta(aDelta, sScrollSeriesCounter,
|
|
Packit |
f0b94e |
aFactor);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ DeltaValues WheelTransaction::OverrideSystemScrollSpeed(
|
|
Packit |
f0b94e |
WidgetWheelEvent* aEvent) {
|
|
Packit |
f0b94e |
MOZ_ASSERT(sTargetFrame, "We don't have mouse scrolling transaction");
|
|
Packit |
f0b94e |
MOZ_ASSERT(aEvent->mDeltaMode == nsIDOMWheelEvent::DOM_DELTA_LINE);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
// If the event doesn't scroll to both X and Y, we don't need to do anything
|
|
Packit |
f0b94e |
// here.
|
|
Packit |
f0b94e |
if (!aEvent->mDeltaX && !aEvent->mDeltaY) {
|
|
Packit |
f0b94e |
return DeltaValues(aEvent);
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
return DeltaValues(aEvent->OverriddenDeltaX(), aEvent->OverriddenDeltaY());
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/******************************************************************/
|
|
Packit |
f0b94e |
/* mozilla::ScrollbarsForWheel */
|
|
Packit |
f0b94e |
/******************************************************************/
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
const DeltaValues ScrollbarsForWheel::directions[kNumberOfTargets] = {
|
|
Packit |
f0b94e |
DeltaValues(-1, 0), DeltaValues(+1, 0), DeltaValues(0, -1),
|
|
Packit |
f0b94e |
DeltaValues(0, +1)};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
AutoWeakFrame ScrollbarsForWheel::sActiveOwner = nullptr;
|
|
Packit |
f0b94e |
AutoWeakFrame ScrollbarsForWheel::sActivatedScrollTargets[kNumberOfTargets] = {
|
|
Packit |
f0b94e |
nullptr, nullptr, nullptr, nullptr};
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
bool ScrollbarsForWheel::sHadWheelStart = false;
|
|
Packit |
f0b94e |
bool ScrollbarsForWheel::sOwnWheelTransaction = false;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ void ScrollbarsForWheel::PrepareToScrollText(
|
|
Packit |
f0b94e |
EventStateManager* aESM, nsIFrame* aTargetFrame, WidgetWheelEvent* aEvent) {
|
|
Packit |
f0b94e |
if (aEvent->mMessage == eWheelOperationStart) {
|
|
Packit |
f0b94e |
WheelTransaction::OwnScrollbars(false);
|
|
Packit |
f0b94e |
if (!IsActive()) {
|
|
Packit |
f0b94e |
TemporarilyActivateAllPossibleScrollTargets(aESM, aTargetFrame, aEvent);
|
|
Packit |
f0b94e |
sHadWheelStart = true;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
} else {
|
|
Packit |
f0b94e |
DeactivateAllTemporarilyActivatedScrollTargets();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ void ScrollbarsForWheel::SetActiveScrollTarget(
|
|
Packit |
f0b94e |
nsIScrollableFrame* aScrollTarget) {
|
|
Packit |
f0b94e |
if (!sHadWheelStart) {
|
|
Packit |
f0b94e |
return;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
nsIScrollbarMediator* scrollbarMediator = do_QueryFrame(aScrollTarget);
|
|
Packit |
f0b94e |
if (!scrollbarMediator) {
|
|
Packit |
f0b94e |
return;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
sHadWheelStart = false;
|
|
Packit |
f0b94e |
sActiveOwner = do_QueryFrame(aScrollTarget);
|
|
Packit |
f0b94e |
scrollbarMediator->ScrollbarActivityStarted();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ void ScrollbarsForWheel::MayInactivate() {
|
|
Packit |
f0b94e |
if (!sOwnWheelTransaction && WheelTransaction::GetTargetFrame()) {
|
|
Packit |
f0b94e |
WheelTransaction::OwnScrollbars(true);
|
|
Packit |
f0b94e |
} else {
|
|
Packit |
f0b94e |
Inactivate();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ void ScrollbarsForWheel::Inactivate() {
|
|
Packit |
f0b94e |
nsIScrollbarMediator* scrollbarMediator = do_QueryFrame(sActiveOwner);
|
|
Packit |
f0b94e |
if (scrollbarMediator) {
|
|
Packit |
f0b94e |
scrollbarMediator->ScrollbarActivityStopped();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
sActiveOwner = nullptr;
|
|
Packit |
f0b94e |
DeactivateAllTemporarilyActivatedScrollTargets();
|
|
Packit |
f0b94e |
if (sOwnWheelTransaction) {
|
|
Packit |
f0b94e |
sOwnWheelTransaction = false;
|
|
Packit |
f0b94e |
WheelTransaction::OwnScrollbars(false);
|
|
Packit |
f0b94e |
WheelTransaction::EndTransaction();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ bool ScrollbarsForWheel::IsActive() {
|
|
Packit |
f0b94e |
if (sActiveOwner) {
|
|
Packit |
f0b94e |
return true;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
for (size_t i = 0; i < kNumberOfTargets; ++i) {
|
|
Packit |
f0b94e |
if (sActivatedScrollTargets[i]) {
|
|
Packit |
f0b94e |
return true;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
return false;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ void ScrollbarsForWheel::OwnWheelTransaction(bool aOwn) {
|
|
Packit |
f0b94e |
sOwnWheelTransaction = aOwn;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ void
|
|
Packit |
f0b94e |
ScrollbarsForWheel::TemporarilyActivateAllPossibleScrollTargets(
|
|
Packit |
f0b94e |
EventStateManager* aESM, nsIFrame* aTargetFrame, WidgetWheelEvent* aEvent) {
|
|
Packit |
f0b94e |
for (size_t i = 0; i < kNumberOfTargets; i++) {
|
|
Packit |
f0b94e |
const DeltaValues* dir = &directions[i];
|
|
Packit |
f0b94e |
AutoWeakFrame* scrollTarget = &sActivatedScrollTargets[i];
|
|
Packit |
f0b94e |
MOZ_ASSERT(!*scrollTarget, "scroll target still temporarily activated!");
|
|
Packit |
f0b94e |
nsIScrollableFrame* target = do_QueryFrame(aESM->ComputeScrollTarget(
|
|
Packit |
f0b94e |
aTargetFrame, dir->deltaX, dir->deltaY, aEvent,
|
|
Packit |
f0b94e |
EventStateManager::COMPUTE_DEFAULT_ACTION_TARGET));
|
|
Packit |
f0b94e |
nsIScrollbarMediator* scrollbarMediator = do_QueryFrame(target);
|
|
Packit |
f0b94e |
if (scrollbarMediator) {
|
|
Packit |
f0b94e |
nsIFrame* targetFrame = do_QueryFrame(target);
|
|
Packit |
f0b94e |
*scrollTarget = targetFrame;
|
|
Packit |
f0b94e |
scrollbarMediator->ScrollbarActivityStarted();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ void
|
|
Packit |
f0b94e |
ScrollbarsForWheel::DeactivateAllTemporarilyActivatedScrollTargets() {
|
|
Packit |
f0b94e |
for (size_t i = 0; i < kNumberOfTargets; i++) {
|
|
Packit |
f0b94e |
AutoWeakFrame* scrollTarget = &sActivatedScrollTargets[i];
|
|
Packit |
f0b94e |
if (*scrollTarget) {
|
|
Packit |
f0b94e |
nsIScrollbarMediator* scrollbarMediator = do_QueryFrame(*scrollTarget);
|
|
Packit |
f0b94e |
if (scrollbarMediator) {
|
|
Packit |
f0b94e |
scrollbarMediator->ScrollbarActivityStopped();
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
*scrollTarget = nullptr;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/******************************************************************/
|
|
Packit |
f0b94e |
/* mozilla::WheelTransaction::Prefs */
|
|
Packit |
f0b94e |
/******************************************************************/
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
int32_t WheelTransaction::Prefs::sMouseWheelAccelerationStart = -1;
|
|
Packit |
f0b94e |
int32_t WheelTransaction::Prefs::sMouseWheelAccelerationFactor = -1;
|
|
Packit |
f0b94e |
uint32_t WheelTransaction::Prefs::sMouseWheelTransactionTimeout = 1500;
|
|
Packit |
f0b94e |
uint32_t WheelTransaction::Prefs::sMouseWheelTransactionIgnoreMoveDelay = 100;
|
|
Packit |
f0b94e |
bool WheelTransaction::Prefs::sTestMouseScroll = false;
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/* static */ void WheelTransaction::Prefs::InitializeStatics() {
|
|
Packit |
f0b94e |
static bool sIsInitialized = false;
|
|
Packit |
f0b94e |
if (!sIsInitialized) {
|
|
Packit |
f0b94e |
Preferences::AddIntVarCache(&sMouseWheelAccelerationStart,
|
|
Packit |
f0b94e |
"mousewheel.acceleration.start", -1);
|
|
Packit |
f0b94e |
Preferences::AddIntVarCache(&sMouseWheelAccelerationFactor,
|
|
Packit |
f0b94e |
"mousewheel.acceleration.factor", -1);
|
|
Packit |
f0b94e |
Preferences::AddUintVarCache(&sMouseWheelTransactionTimeout,
|
|
Packit |
f0b94e |
"mousewheel.transaction.timeout", 1500);
|
|
Packit |
f0b94e |
Preferences::AddUintVarCache(&sMouseWheelTransactionIgnoreMoveDelay,
|
|
Packit |
f0b94e |
"mousewheel.transaction.ignoremovedelay", 100);
|
|
Packit |
f0b94e |
Preferences::AddBoolVarCache(&sTestMouseScroll, "test.mousescroll", false);
|
|
Packit |
f0b94e |
sIsInitialized = true;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
/******************************************************************/
|
|
Packit |
f0b94e |
/* mozilla::AutoWheelDeltaAdjuster */
|
|
Packit |
f0b94e |
/******************************************************************/
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
AutoWheelDeltaAdjuster::AutoWheelDeltaAdjuster(WidgetWheelEvent& aWheelEvent)
|
|
Packit |
f0b94e |
: mWheelEvent(aWheelEvent),
|
|
Packit |
f0b94e |
mOldDeltaX(aWheelEvent.mDeltaX),
|
|
Packit |
f0b94e |
mOldDeltaZ(aWheelEvent.mDeltaZ),
|
|
Packit |
f0b94e |
mOldOverflowDeltaX(aWheelEvent.mOverflowDeltaX),
|
|
Packit |
f0b94e |
mOldLineOrPageDeltaX(aWheelEvent.mLineOrPageDeltaX),
|
|
Packit |
f0b94e |
mTreatedVerticalWheelAsHorizontalScroll(false) {
|
|
Packit |
f0b94e |
MOZ_ASSERT(!aWheelEvent.mDeltaValuesAdjustedForDefaultHandler);
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
if (EventStateManager::WheelEventIsHorizontalScrollAction(&aWheelEvent)) {
|
|
Packit |
f0b94e |
// Move deltaY values to deltaX and set both deltaY and deltaZ to 0.
|
|
Packit |
f0b94e |
mWheelEvent.mDeltaX = mWheelEvent.mDeltaY;
|
|
Packit |
f0b94e |
mWheelEvent.mDeltaY = 0.0;
|
|
Packit |
f0b94e |
mWheelEvent.mDeltaZ = 0.0;
|
|
Packit |
f0b94e |
mWheelEvent.mOverflowDeltaX = mWheelEvent.mOverflowDeltaY;
|
|
Packit |
f0b94e |
mWheelEvent.mOverflowDeltaY = 0.0;
|
|
Packit |
f0b94e |
mWheelEvent.mLineOrPageDeltaX = mWheelEvent.mLineOrPageDeltaY;
|
|
Packit |
f0b94e |
mWheelEvent.mLineOrPageDeltaY = 0;
|
|
Packit |
f0b94e |
mWheelEvent.mDeltaValuesAdjustedForDefaultHandler = true;
|
|
Packit |
f0b94e |
mTreatedVerticalWheelAsHorizontalScroll = true;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
AutoWheelDeltaAdjuster::~AutoWheelDeltaAdjuster() {
|
|
Packit |
f0b94e |
if (mTreatedVerticalWheelAsHorizontalScroll &&
|
|
Packit |
f0b94e |
mWheelEvent.mDeltaValuesAdjustedForDefaultHandler) {
|
|
Packit |
f0b94e |
mWheelEvent.mDeltaY = mWheelEvent.mDeltaX;
|
|
Packit |
f0b94e |
mWheelEvent.mDeltaX = mOldDeltaX;
|
|
Packit |
f0b94e |
mWheelEvent.mDeltaZ = mOldDeltaZ;
|
|
Packit |
f0b94e |
mWheelEvent.mOverflowDeltaY = mWheelEvent.mOverflowDeltaX;
|
|
Packit |
f0b94e |
mWheelEvent.mOverflowDeltaX = mOldOverflowDeltaX;
|
|
Packit |
f0b94e |
mWheelEvent.mLineOrPageDeltaY = mWheelEvent.mLineOrPageDeltaX;
|
|
Packit |
f0b94e |
mWheelEvent.mLineOrPageDeltaX = mOldLineOrPageDeltaX;
|
|
Packit |
f0b94e |
mWheelEvent.mDeltaValuesAdjustedForDefaultHandler = false;
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
}
|
|
Packit |
f0b94e |
|
|
Packit |
f0b94e |
} // namespace mozilla
|