зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1328658 - Notify main thread of a failed attempt to start an APZ scrollbar drag. r=kats,tnikkel
MozReview-Commit-ID: ERm1sVNfoKL --HG-- extra : rebase_source : 0b57987a2a15533fad577dd2d363ec386f6bfeae
This commit is contained in:
Родитель
d034427bd2
Коммит
a98321305e
|
@ -157,6 +157,8 @@ public:
|
|||
*/
|
||||
virtual void NotifyFlushComplete() = 0;
|
||||
|
||||
virtual void NotifyAsyncScrollbarDragRejected(const FrameMetrics::ViewID& aScrollId) = 0;
|
||||
|
||||
virtual void UpdateOverscrollVelocity(float aX, float aY, bool aIsRootContent) {}
|
||||
virtual void UpdateOverscrollOffset(float aX, float aY, bool aIsRootContent) {}
|
||||
virtual void SetScrollingRootContent(bool isRootContent) {}
|
||||
|
|
|
@ -53,10 +53,12 @@ typedef mozilla::gfx::Point Point;
|
|||
typedef mozilla::gfx::Point4D Point4D;
|
||||
typedef mozilla::gfx::Matrix4x4 Matrix4x4;
|
||||
|
||||
typedef CompositorBridgeParent::LayerTreeState LayerTreeState;
|
||||
|
||||
float APZCTreeManager::sDPI = 160.0;
|
||||
|
||||
struct APZCTreeManager::TreeBuildingState {
|
||||
TreeBuildingState(const CompositorBridgeParent::LayerTreeState* const aLayerTreeState,
|
||||
TreeBuildingState(const LayerTreeState* const aLayerTreeState,
|
||||
bool aIsFirstPaint, uint64_t aOriginatingLayersId,
|
||||
APZTestData* aTestData, uint32_t aPaintSequence)
|
||||
: mLayerTreeState(aLayerTreeState)
|
||||
|
@ -67,7 +69,7 @@ struct APZCTreeManager::TreeBuildingState {
|
|||
}
|
||||
|
||||
// State that doesn't change as we recurse in the tree building
|
||||
const CompositorBridgeParent::LayerTreeState* const mLayerTreeState;
|
||||
const LayerTreeState* const mLayerTreeState;
|
||||
const bool mIsFirstPaint;
|
||||
const uint64_t mOriginatingLayersId;
|
||||
const APZPaintLogHelper mPaintLogger;
|
||||
|
@ -226,13 +228,13 @@ APZCTreeManager::UpdateHitTestingTree(uint64_t aRootLayerTreeId,
|
|||
// the layers id that originated this update.
|
||||
APZTestData* testData = nullptr;
|
||||
if (gfxPrefs::APZTestLoggingEnabled()) {
|
||||
if (CompositorBridgeParent::LayerTreeState* state = CompositorBridgeParent::GetIndirectShadowTree(aOriginatingLayersId)) {
|
||||
if (LayerTreeState* state = CompositorBridgeParent::GetIndirectShadowTree(aOriginatingLayersId)) {
|
||||
testData = &state->mApzTestData;
|
||||
testData->StartNewPaint(aPaintSequenceNumber);
|
||||
}
|
||||
}
|
||||
|
||||
const CompositorBridgeParent::LayerTreeState* treeState =
|
||||
const LayerTreeState* treeState =
|
||||
CompositorBridgeParent::GetIndirectShadowTree(aRootLayerTreeId);
|
||||
MOZ_ASSERT(treeState);
|
||||
TreeBuildingState state(treeState, aIsFirstPaint, aOriginatingLayersId,
|
||||
|
@ -439,6 +441,7 @@ APZCTreeManager::StartScrollbarDrag(const ScrollableLayerGuid& aGuid,
|
|||
|
||||
RefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aGuid);
|
||||
if (!apzc) {
|
||||
NotifyScrollbarDragRejected(aGuid);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -446,6 +449,14 @@ APZCTreeManager::StartScrollbarDrag(const ScrollableLayerGuid& aGuid,
|
|||
mInputQueue->ConfirmDragBlock(inputBlockId, apzc, aDragMetrics);
|
||||
}
|
||||
|
||||
void
|
||||
APZCTreeManager::NotifyScrollbarDragRejected(const ScrollableLayerGuid& aGuid) const
|
||||
{
|
||||
const LayerTreeState* state = CompositorBridgeParent::GetIndirectShadowTree(aGuid.mLayersId);
|
||||
MOZ_ASSERT(state && state->mController);
|
||||
state->mController->NotifyAsyncScrollbarDragRejected(aGuid.mScrollId);
|
||||
}
|
||||
|
||||
HitTestingTreeNode*
|
||||
APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer,
|
||||
const FrameMetrics& aMetrics,
|
||||
|
@ -462,7 +473,7 @@ APZCTreeManager::PrepareNodeForLayer(const LayerMetricsWrapper& aLayer,
|
|||
needsApzc = false;
|
||||
}
|
||||
|
||||
const CompositorBridgeParent::LayerTreeState* state = CompositorBridgeParent::GetIndirectShadowTree(aLayersId);
|
||||
const LayerTreeState* state = CompositorBridgeParent::GetIndirectShadowTree(aLayersId);
|
||||
if (!(state && state->mController.get())) {
|
||||
needsApzc = false;
|
||||
}
|
||||
|
@ -690,7 +701,7 @@ APZCTreeManager::FlushApzRepaints(uint64_t aLayersId)
|
|||
// ensure any pending paints were flushed. Now, paints are flushed
|
||||
// immediately, so it is safe to simply send a notification now.
|
||||
APZCTM_LOG("Flushing repaints for layers id %" PRIu64, aLayersId);
|
||||
const CompositorBridgeParent::LayerTreeState* state =
|
||||
const LayerTreeState* state =
|
||||
CompositorBridgeParent::GetIndirectShadowTree(aLayersId);
|
||||
MOZ_ASSERT(state && state->mController);
|
||||
state->mController->DispatchToRepaintThread(NewRunnableMethod(
|
||||
|
|
|
@ -477,6 +477,8 @@ private:
|
|||
void PrintAPZCInfo(const LayerMetricsWrapper& aLayer,
|
||||
const AsyncPanZoomController* apzc);
|
||||
|
||||
void NotifyScrollbarDragRejected(const ScrollableLayerGuid& aGuid) const;
|
||||
|
||||
protected:
|
||||
/* The input queue where input events are held until we know enough to
|
||||
* figure out where they're going. Protected so gtests can access it.
|
||||
|
|
|
@ -91,6 +91,7 @@ public:
|
|||
}
|
||||
MOCK_METHOD3(NotifyAPZStateChange, void(const ScrollableLayerGuid& aGuid, APZStateChange aChange, int aArg));
|
||||
MOCK_METHOD0(NotifyFlushComplete, void());
|
||||
MOCK_METHOD1(NotifyAsyncScrollbarDragRejected, void(const FrameMetrics::ViewID&));
|
||||
};
|
||||
|
||||
class MockContentControllerDelayed : public MockContentController {
|
||||
|
|
|
@ -912,6 +912,15 @@ APZCCallbackHelper::IsScrollInProgress(nsIScrollableFrame* aFrame)
|
|||
|| aFrame->LastSmoothScrollOrigin();
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
APZCCallbackHelper::NotifyAsyncScrollbarDragRejected(const FrameMetrics::ViewID& aScrollId)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (nsIScrollableFrame* scrollFrame = nsLayoutUtils::FindScrollableFrameFor(aScrollId)) {
|
||||
scrollFrame->AsyncScrollbarDragRejected();
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
APZCCallbackHelper::NotifyPinchGesture(PinchGestureInput::PinchGestureType aType,
|
||||
LayoutDeviceCoord aSpanChange,
|
||||
|
|
|
@ -164,6 +164,8 @@ public:
|
|||
/* Notify content that the repaint flush is complete. */
|
||||
static void NotifyFlushComplete(nsIPresShell* aShell);
|
||||
|
||||
static void NotifyAsyncScrollbarDragRejected(const FrameMetrics::ViewID& aScrollId);
|
||||
|
||||
/* Temporarily ignore the Displayport for better paint performance. If at
|
||||
* all possible, pass in a presShell if you have one at the call site, we
|
||||
* use it to trigger a repaint once suppression is disabled. Without that
|
||||
|
|
|
@ -274,3 +274,16 @@ ChromeProcessController::NotifyFlushComplete()
|
|||
|
||||
APZCCallbackHelper::NotifyFlushComplete(GetPresShell());
|
||||
}
|
||||
|
||||
void
|
||||
ChromeProcessController::NotifyAsyncScrollbarDragRejected(const FrameMetrics::ViewID& aScrollId)
|
||||
{
|
||||
if (MessageLoop::current() != mUILoop) {
|
||||
mUILoop->PostTask(NewRunnableMethod<FrameMetrics::ViewID>(this,
|
||||
&ChromeProcessController::NotifyAsyncScrollbarDragRejected,
|
||||
aScrollId));
|
||||
return;
|
||||
}
|
||||
|
||||
APZCCallbackHelper::NotifyAsyncScrollbarDragRejected(aScrollId);
|
||||
}
|
||||
|
|
|
@ -63,6 +63,7 @@ public:
|
|||
virtual void NotifyMozMouseScrollEvent(const FrameMetrics::ViewID& aScrollId,
|
||||
const nsString& aEvent) override;
|
||||
virtual void NotifyFlushComplete() override;
|
||||
virtual void NotifyAsyncScrollbarDragRejected(const FrameMetrics::ViewID& aScrollId) override;
|
||||
private:
|
||||
nsCOMPtr<nsIWidget> mWidget;
|
||||
RefPtr<APZEventState> mAPZEventState;
|
||||
|
|
|
@ -85,6 +85,12 @@ ContentProcessController::NotifyFlushComplete()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
ContentProcessController::NotifyAsyncScrollbarDragRejected(const FrameMetrics::ViewID& aScrollId)
|
||||
{
|
||||
APZCCallbackHelper::NotifyAsyncScrollbarDragRejected(aScrollId);
|
||||
}
|
||||
|
||||
void
|
||||
ContentProcessController::PostDelayedTask(already_AddRefed<Runnable> aRunnable, int aDelayMs)
|
||||
{
|
||||
|
|
|
@ -62,6 +62,8 @@ public:
|
|||
|
||||
void NotifyFlushComplete() override;
|
||||
|
||||
void NotifyAsyncScrollbarDragRejected(const FrameMetrics::ViewID& aScrollId) override;
|
||||
|
||||
void PostDelayedTask(already_AddRefed<Runnable> aRunnable, int aDelayMs) override;
|
||||
|
||||
bool IsRepaintThread() override;
|
||||
|
|
|
@ -85,6 +85,13 @@ APZChild::RecvNotifyFlushComplete()
|
|||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
APZChild::RecvNotifyAsyncScrollbarDragRejected(const ViewID& aScrollId)
|
||||
{
|
||||
mController->NotifyAsyncScrollbarDragRejected(aScrollId);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
APZChild::RecvDestroy()
|
||||
{
|
||||
|
|
|
@ -42,6 +42,8 @@ public:
|
|||
|
||||
mozilla::ipc::IPCResult RecvNotifyFlushComplete() override;
|
||||
|
||||
mozilla::ipc::IPCResult RecvNotifyAsyncScrollbarDragRejected(const ViewID& aScrollId) override;
|
||||
|
||||
mozilla::ipc::IPCResult RecvDestroy() override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -64,6 +64,8 @@ child:
|
|||
|
||||
async NotifyFlushComplete();
|
||||
|
||||
async NotifyAsyncScrollbarDragRejected(ViewID aScrollId);
|
||||
|
||||
async Destroy();
|
||||
};
|
||||
|
||||
|
|
|
@ -244,6 +244,21 @@ RemoteContentController::NotifyFlushComplete()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
RemoteContentController::NotifyAsyncScrollbarDragRejected(const FrameMetrics::ViewID& aScrollId)
|
||||
{
|
||||
if (MessageLoop::current() != mCompositorThread) {
|
||||
// We have to send messages from the compositor thread
|
||||
mCompositorThread->PostTask(NewRunnableMethod<FrameMetrics::ViewID>(this,
|
||||
&RemoteContentController::NotifyAsyncScrollbarDragRejected, aScrollId));
|
||||
return;
|
||||
}
|
||||
|
||||
if (mCanSend) {
|
||||
Unused << SendNotifyAsyncScrollbarDragRejected(aScrollId);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RemoteContentController::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
|
|
|
@ -74,6 +74,8 @@ public:
|
|||
|
||||
virtual void NotifyFlushComplete() override;
|
||||
|
||||
virtual void NotifyAsyncScrollbarDragRejected(const FrameMetrics::ViewID& aScrollId) override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
|
||||
|
||||
virtual void Destroy() override;
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
#include "ScrollSnap.h"
|
||||
#include "UnitTransforms.h"
|
||||
#include "nsPluginFrame.h"
|
||||
#include "nsSliderFrame.h"
|
||||
#include "mozilla/layers/APZCCallbackHelper.h"
|
||||
#include <mozilla/layers/AxisPhysicsModel.h>
|
||||
#include <mozilla/layers/AxisPhysicsMSDModel.h>
|
||||
|
@ -6215,3 +6216,30 @@ ScrollFrameHelper::DragScroll(WidgetEvent* aEvent)
|
|||
|
||||
return willScroll;
|
||||
}
|
||||
|
||||
static void
|
||||
AsyncScrollbarDragRejected(nsIFrame* aScrollbar)
|
||||
{
|
||||
if (!aScrollbar) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (nsIFrame::ChildListIterator childLists(aScrollbar);
|
||||
!childLists.IsDone();
|
||||
childLists.Next()) {
|
||||
for (nsIFrame* frame : childLists.CurrentList()) {
|
||||
if (nsSliderFrame* sliderFrame = do_QueryFrame(frame)) {
|
||||
sliderFrame->AsyncScrollbarDragRejected();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ScrollFrameHelper::AsyncScrollbarDragRejected()
|
||||
{
|
||||
// We don't get told which scrollbar requested the async drag,
|
||||
// so we notify both.
|
||||
::AsyncScrollbarDragRejected(mHScrollbarBox);
|
||||
::AsyncScrollbarDragRejected(mVScrollbarBox);
|
||||
}
|
||||
|
|
|
@ -461,6 +461,8 @@ public:
|
|||
|
||||
bool DragScroll(WidgetEvent* aEvent);
|
||||
|
||||
void AsyncScrollbarDragRejected();
|
||||
|
||||
// owning references to the nsIAnonymousContentCreator-built content
|
||||
nsCOMPtr<nsIContent> mHScrollbarContent;
|
||||
nsCOMPtr<nsIContent> mVScrollbarContent;
|
||||
|
@ -1039,6 +1041,10 @@ public:
|
|||
return mHelper.DragScroll(aEvent);
|
||||
}
|
||||
|
||||
virtual void AsyncScrollbarDragRejected() override {
|
||||
return mHelper.AsyncScrollbarDragRejected();
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FRAME_DUMP
|
||||
virtual nsresult GetFrameName(nsAString& aResult) const override;
|
||||
#endif
|
||||
|
@ -1469,6 +1475,10 @@ public:
|
|||
return mHelper.DragScroll(aEvent);
|
||||
}
|
||||
|
||||
virtual void AsyncScrollbarDragRejected() override {
|
||||
return mHelper.AsyncScrollbarDragRejected();
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FRAME_DUMP
|
||||
virtual nsresult GetFrameName(nsAString& aResult) const override;
|
||||
#endif
|
||||
|
|
|
@ -481,6 +481,8 @@ public:
|
|||
* caller should look for an ancestor to scroll.
|
||||
*/
|
||||
virtual bool DragScroll(mozilla::WidgetEvent* aEvent) = 0;
|
||||
|
||||
virtual void AsyncScrollbarDragRejected() = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -994,36 +994,36 @@ ScrollFrameWillBuildScrollInfoLayer(nsIFrame* aScrollFrame)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
nsSliderFrame::StartAPZDrag(WidgetGUIEvent* aEvent)
|
||||
{
|
||||
if (!aEvent->mFlags.mHandledByAPZ) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gfxPlatform::GetPlatform()->SupportsApzDragInput()) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
nsContainerFrame* scrollFrame = GetScrollbar()->GetParent();
|
||||
if (!scrollFrame) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
nsIContent* scrollableContent = scrollFrame->GetContent();
|
||||
if (!scrollableContent) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
nsIScrollableFrame* scrollFrameAsScrollable = do_QueryFrame(scrollFrame);
|
||||
if (!scrollFrameAsScrollable) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
// APZ dragging requires the scrollbar to be layerized, which doesn't
|
||||
// happen for scroll info layers.
|
||||
if (ScrollFrameWillBuildScrollInfoLayer(scrollFrame)) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
mozilla::layers::FrameMetrics::ViewID scrollTargetId;
|
||||
|
@ -1031,7 +1031,7 @@ nsSliderFrame::StartAPZDrag(WidgetGUIEvent* aEvent)
|
|||
bool hasAPZView = hasID && (scrollTargetId != layers::FrameMetrics::NULL_SCROLL_ID);
|
||||
|
||||
if (!hasAPZView) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
nsIFrame* scrollbarBox = GetScrollbar();
|
||||
|
@ -1056,9 +1056,15 @@ nsSliderFrame::StartAPZDrag(WidgetGUIEvent* aEvent)
|
|||
AsyncDragMetrics::VERTICAL);
|
||||
|
||||
if (!nsLayoutUtils::HasDisplayPort(scrollableContent)) {
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
// It's important to set this before calling nsIWidget::StartAsyncScrollbarDrag(),
|
||||
// because in some configurations, that can call AsyncScrollbarDragRejected()
|
||||
// synchronously, which clears the flag (and we want it to stay cleared in
|
||||
// that case).
|
||||
mScrollingWithAPZ = true;
|
||||
|
||||
// When we start an APZ drag, we wont get mouse events for the drag.
|
||||
// APZ will consume them all and only notify us of the new scroll position.
|
||||
bool waitForRefresh = InputAPZContext::HavePendingLayerization();
|
||||
|
@ -1070,7 +1076,6 @@ nsSliderFrame::StartAPZDrag(WidgetGUIEvent* aEvent)
|
|||
if (!waitForRefresh) {
|
||||
widget->StartAsyncScrollbarDrag(dragMetrics);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -1140,16 +1145,15 @@ nsSliderFrame::StartDrag(nsIDOMEvent* aEvent)
|
|||
|
||||
mDragStart = pos - mThumbStart;
|
||||
|
||||
mScrollingWithAPZ = StartAPZDrag(event);
|
||||
mScrollingWithAPZ = false;
|
||||
StartAPZDrag(event); // sets mScrollingWithAPZ=true if appropriate
|
||||
|
||||
#ifdef DEBUG_SLIDER
|
||||
printf("Pressed mDragStart=%d\n",mDragStart);
|
||||
#endif
|
||||
|
||||
if (!mScrollingWithAPZ && !mSuppressionActive) {
|
||||
MOZ_ASSERT(PresContext()->PresShell());
|
||||
APZCCallbackHelper::SuppressDisplayport(true, PresContext()->PresShell());
|
||||
mSuppressionActive = true;
|
||||
if (!mScrollingWithAPZ) {
|
||||
SuppressDisplayport();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
@ -1163,11 +1167,7 @@ nsSliderFrame::StopDrag()
|
|||
|
||||
mScrollingWithAPZ = false;
|
||||
|
||||
if (mSuppressionActive) {
|
||||
MOZ_ASSERT(PresContext()->PresShell());
|
||||
APZCCallbackHelper::SuppressDisplayport(false, PresContext()->PresShell());
|
||||
mSuppressionActive = false;
|
||||
}
|
||||
UnsuppressDisplayport();
|
||||
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
nsIFrame* thumbFrame = mFrames.FirstChild();
|
||||
|
@ -1539,5 +1539,36 @@ nsSliderFrame::GetThumbRatio() const
|
|||
return mRatio / mozilla::AppUnitsPerCSSPixel();
|
||||
}
|
||||
|
||||
void
|
||||
nsSliderFrame::AsyncScrollbarDragRejected()
|
||||
{
|
||||
mScrollingWithAPZ = false;
|
||||
// Only suppress the displayport if we're still dragging the thumb.
|
||||
// Otherwise, no one will unsuppress it.
|
||||
if (isDraggingThumb()) {
|
||||
SuppressDisplayport();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsSliderFrame::SuppressDisplayport()
|
||||
{
|
||||
if (!mSuppressionActive) {
|
||||
MOZ_ASSERT(PresContext()->PresShell());
|
||||
APZCCallbackHelper::SuppressDisplayport(true, PresContext()->PresShell());
|
||||
mSuppressionActive = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsSliderFrame::UnsuppressDisplayport()
|
||||
{
|
||||
if (mSuppressionActive) {
|
||||
MOZ_ASSERT(PresContext()->PresShell());
|
||||
APZCCallbackHelper::SuppressDisplayport(false, PresContext()->PresShell());
|
||||
mSuppressionActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsSliderMediator,
|
||||
nsIDOMEventListener)
|
||||
|
|
|
@ -100,7 +100,7 @@ public:
|
|||
nsresult StartDrag(nsIDOMEvent* aEvent);
|
||||
nsresult StopDrag();
|
||||
|
||||
bool StartAPZDrag(WidgetGUIEvent* aEvent);
|
||||
void StartAPZDrag(mozilla::WidgetGUIEvent* aEvent);
|
||||
|
||||
static int32_t GetCurrentPosition(nsIContent* content);
|
||||
static int32_t GetMinPosition(nsIContent* content);
|
||||
|
@ -137,6 +137,11 @@ public:
|
|||
// scrolled frame.
|
||||
float GetThumbRatio() const;
|
||||
|
||||
// Notify the slider frame than an async scrollbar drag requested in
|
||||
// StartAPZDrag() was rejected by APZ, and the slider frame should
|
||||
// fall back to main-thread dragging.
|
||||
void AsyncScrollbarDragRejected();
|
||||
|
||||
private:
|
||||
|
||||
bool GetScrollToClick();
|
||||
|
@ -158,6 +163,9 @@ private:
|
|||
void RemoveListener();
|
||||
bool isDraggingThumb();
|
||||
|
||||
void SuppressDisplayport();
|
||||
void UnsuppressDisplayport();
|
||||
|
||||
void StartRepeat() {
|
||||
nsRepeatService::GetInstance()->Start(Notify, this);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче