changeset 11201:0ee0cd385816

8215775: Scrollbars from web pages appear to be absolute, overlapping everything Reviewed-by: kcr, mbilla
author arajkumar
date Fri, 22 Feb 2019 15:36:53 +0530
parents 74dafaae4c1d
children f6e1bb859eb5
files modules/javafx.web/src/main/native/Source/WebCore/SourcesPlatformJava.txt modules/javafx.web/src/main/native/Source/WebCore/platform/graphics/java/ComplexTextControllerJava.cpp modules/javafx.web/src/main/native/Source/WebCore/platform/java/ScrollAnimatorJava.cpp modules/javafx.web/src/main/native/Source/WebCore/platform/java/ScrollAnimatorJava.h modules/javafx.web/src/main/native/Source/WebCore/platform/java/ScrollbarThemeJava.cpp modules/javafx.web/src/main/native/Source/WebCore/platform/java/ScrollbarThemeJava.h
diffstat 6 files changed, 497 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/modules/javafx.web/src/main/native/Source/WebCore/SourcesPlatformJava.txt	Tue Feb 19 13:22:46 2019 -0800
+++ b/modules/javafx.web/src/main/native/Source/WebCore/SourcesPlatformJava.txt	Fri Feb 22 15:36:53 2019 +0530
@@ -1,4 +1,4 @@
-// Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+// Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
 // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 //
 // This code is free software; you can redistribute it and/or modify it
@@ -89,8 +89,9 @@
 platform/graphics/texmap/TextureMapperJava.cpp
 platform/graphics/texmap/BitmapTextureJava.cpp
 
-platform/ScrollAnimatorSmooth.cpp
+platform/ScrollAnimationKinetic.cpp
 platform/ScrollAnimationSmooth.cpp
+platform/java/ScrollAnimatorJava.cpp
 
 platform/text/LocaleNone.cpp
 platform/text/Hyphenation.cpp
--- a/modules/javafx.web/src/main/native/Source/WebCore/platform/graphics/java/ComplexTextControllerJava.cpp	Tue Feb 19 13:22:46 2019 -0800
+++ b/modules/javafx.web/src/main/native/Source/WebCore/platform/graphics/java/ComplexTextControllerJava.cpp	Fri Feb 22 15:36:53 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,9 @@
 
 #include "ComplexTextController.h"
 #include "FloatRect.h"
-
+#include "Font.h"
+#include "FontCascade.h"
+#include "TextRun.h"
 #include <wtf/java/JavaEnv.h>
 
 namespace WebCore {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/javafx.web/src/main/native/Source/WebCore/platform/java/ScrollAnimatorJava.cpp	Fri Feb 22 15:36:53 2019 +0530
@@ -0,0 +1,369 @@
+/*
+ * Copyright (c) 2016 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ScrollAnimatorJava.h"
+
+#include "ScrollAnimationKinetic.h"
+#include "ScrollAnimationSmooth.h"
+#include "ScrollableArea.h"
+#include "ScrollbarTheme.h"
+
+// Derived from ScrollAnimatorGtk, we should move to ScrollAnimatorGeneric
+namespace WebCore {
+
+static const Seconds overflowScrollbarsAnimationDuration { 1_s };
+static const Seconds overflowScrollbarsAnimationHideDelay { 2_s };
+static const Seconds scrollCaptureThreshold { 150_ms };
+
+std::unique_ptr<ScrollAnimator> ScrollAnimator::create(ScrollableArea& scrollableArea)
+{
+    return std::make_unique<ScrollAnimatorJava>(scrollableArea);
+}
+
+ScrollAnimatorJava::ScrollAnimatorJava(ScrollableArea& scrollableArea)
+    : ScrollAnimator(scrollableArea)
+    , m_overlayScrollbarAnimationTimer(*this, &ScrollAnimatorJava::overlayScrollbarAnimationTimerFired)
+{
+    m_kineticAnimation = std::make_unique<ScrollAnimationKinetic>(m_scrollableArea, [this](FloatPoint&& position) {
+#if ENABLE(SMOOTH_SCROLLING)
+        if (m_smoothAnimation)
+            m_smoothAnimation->setCurrentPosition(position);
+#endif
+        updatePosition(WTFMove(position));
+    });
+
+#if ENABLE(SMOOTH_SCROLLING)
+    if (scrollableArea.scrollAnimatorEnabled())
+        ensureSmoothScrollingAnimation();
+#endif
+}
+
+ScrollAnimatorJava::~ScrollAnimatorJava() = default;
+
+#if ENABLE(SMOOTH_SCROLLING)
+void ScrollAnimatorJava::ensureSmoothScrollingAnimation()
+{
+    if (m_smoothAnimation)
+        return;
+
+    m_smoothAnimation = std::make_unique<ScrollAnimationSmooth>(m_scrollableArea, m_currentPosition, [this](FloatPoint&& position) {
+        updatePosition(WTFMove(position));
+    });
+}
+#endif
+
+#if ENABLE(SMOOTH_SCROLLING)
+bool ScrollAnimatorJava::scroll(ScrollbarOrientation orientation, ScrollGranularity granularity, float step, float multiplier)
+{
+    if (!m_scrollableArea.scrollAnimatorEnabled() || granularity == ScrollByPrecisePixel)
+        return ScrollAnimator::scroll(orientation, granularity, step, multiplier);
+
+    ensureSmoothScrollingAnimation();
+    return m_smoothAnimation->scroll(orientation, granularity, step, multiplier);
+}
+#endif
+
+void ScrollAnimatorJava::scrollToOffsetWithoutAnimation(const FloatPoint& offset, ScrollClamping)
+{
+    FloatPoint position = ScrollableArea::scrollPositionFromOffset(offset, toFloatSize(m_scrollableArea.scrollOrigin()));
+    m_kineticAnimation->stop();
+    m_scrollHistory.clear();
+
+#if ENABLE(SMOOTH_SCROLLING)
+    if (m_smoothAnimation)
+        m_smoothAnimation->setCurrentPosition(position);
+#endif
+
+    updatePosition(WTFMove(position));
+}
+
+FloatPoint ScrollAnimatorJava::computeVelocity()
+{
+    if (m_scrollHistory.isEmpty())
+        return { };
+
+    auto first = m_scrollHistory[0].timestamp();
+    auto last = m_scrollHistory.rbegin()->timestamp();
+
+    if (last == first)
+        return { };
+
+    FloatPoint accumDelta;
+    for (const auto& scrollEvent : m_scrollHistory)
+        accumDelta += FloatPoint(scrollEvent.deltaX(), scrollEvent.deltaY());
+
+    m_scrollHistory.clear();
+
+    return FloatPoint(accumDelta.x() * -1 / (last - first).value(), accumDelta.y() * -1 / (last - first).value());
+}
+
+bool ScrollAnimatorJava::handleWheelEvent(const PlatformWheelEvent& event)
+{
+    m_kineticAnimation->stop();
+
+    m_scrollHistory.removeAllMatching([&event] (PlatformWheelEvent& otherEvent) -> bool {
+        return (event.timestamp() - otherEvent.timestamp()) > scrollCaptureThreshold;
+    });
+
+    // if (event.isEndOfNonMomentumScroll()) {
+    //     // We don't need to add the event to the history as its delta will be (0, 0).
+    //     static_cast<ScrollAnimationKinetic*>(m_kineticAnimation.get())->start(m_currentPosition, computeVelocity(), m_scrollableArea.horizontalScrollbar(), m_scrollableArea.verticalScrollbar());
+    //     return true;
+    // }
+    // if (event.isTransitioningToMomentumScroll()) {
+    //     m_scrollHistory.clear();
+    //     static_cast<ScrollAnimationKinetic*>(m_kineticAnimation.get())->start(m_currentPosition, event.swipeVelocity(), m_scrollableArea.horizontalScrollbar(), m_scrollableArea.verticalScrollbar());
+    //     return true;
+    // }
+
+    m_scrollHistory.append(event);
+
+    return ScrollAnimator::handleWheelEvent(event);
+}
+
+void ScrollAnimatorJava::willEndLiveResize()
+{
+    m_kineticAnimation->updateVisibleLengths();
+
+#if ENABLE(SMOOTH_SCROLLING)
+    if (m_smoothAnimation)
+        m_smoothAnimation->updateVisibleLengths();
+#endif
+}
+
+void ScrollAnimatorJava::updatePosition(FloatPoint&& position)
+{
+    FloatSize delta = position - m_currentPosition;
+    m_currentPosition = WTFMove(position);
+    notifyPositionChanged(delta);
+}
+
+void ScrollAnimatorJava::didAddVerticalScrollbar(Scrollbar* scrollbar)
+{
+    m_kineticAnimation->updateVisibleLengths();
+
+#if ENABLE(SMOOTH_SCROLLING)
+    if (m_smoothAnimation)
+        m_smoothAnimation->updateVisibleLengths();
+#endif
+    if (!scrollbar->isOverlayScrollbar())
+        return;
+    m_verticalOverlayScrollbar = scrollbar;
+    if (!m_horizontalOverlayScrollbar)
+        m_overlayScrollbarAnimationCurrent = 1;
+    m_verticalOverlayScrollbar->setOpacity(m_overlayScrollbarAnimationCurrent);
+    hideOverlayScrollbars();
+}
+
+void ScrollAnimatorJava::didAddHorizontalScrollbar(Scrollbar* scrollbar)
+{
+    m_kineticAnimation->updateVisibleLengths();
+
+#if ENABLE(SMOOTH_SCROLLING)
+    if (m_smoothAnimation)
+        m_smoothAnimation->updateVisibleLengths();
+#endif
+    if (!scrollbar->isOverlayScrollbar())
+        return;
+    m_horizontalOverlayScrollbar = scrollbar;
+    if (!m_verticalOverlayScrollbar)
+        m_overlayScrollbarAnimationCurrent = 1;
+    m_horizontalOverlayScrollbar->setOpacity(m_overlayScrollbarAnimationCurrent);
+    hideOverlayScrollbars();
+}
+
+void ScrollAnimatorJava::willRemoveVerticalScrollbar(Scrollbar* scrollbar)
+{
+    if (m_verticalOverlayScrollbar != scrollbar)
+        return;
+    m_verticalOverlayScrollbar = nullptr;
+    if (!m_horizontalOverlayScrollbar)
+        m_overlayScrollbarAnimationCurrent = 0;
+}
+
+void ScrollAnimatorJava::willRemoveHorizontalScrollbar(Scrollbar* scrollbar)
+{
+    if (m_horizontalOverlayScrollbar != scrollbar)
+        return;
+    m_horizontalOverlayScrollbar = nullptr;
+    if (!m_verticalOverlayScrollbar)
+        m_overlayScrollbarAnimationCurrent = 0;
+}
+
+void ScrollAnimatorJava::updateOverlayScrollbarsOpacity()
+{
+    if (m_verticalOverlayScrollbar && m_overlayScrollbarAnimationCurrent != m_verticalOverlayScrollbar->opacity()) {
+        m_verticalOverlayScrollbar->setOpacity(m_overlayScrollbarAnimationCurrent);
+        if (m_verticalOverlayScrollbar->hoveredPart() == NoPart)
+            m_verticalOverlayScrollbar->invalidate();
+    }
+
+    if (m_horizontalOverlayScrollbar && m_overlayScrollbarAnimationCurrent != m_horizontalOverlayScrollbar->opacity()) {
+        m_horizontalOverlayScrollbar->setOpacity(m_overlayScrollbarAnimationCurrent);
+        if (m_horizontalOverlayScrollbar->hoveredPart() == NoPart)
+            m_horizontalOverlayScrollbar->invalidate();
+    }
+}
+
+static inline double easeOutCubic(double t)
+{
+    double p = t - 1;
+    return p * p * p + 1;
+}
+
+void ScrollAnimatorJava::overlayScrollbarAnimationTimerFired()
+{
+    if (!m_horizontalOverlayScrollbar && !m_verticalOverlayScrollbar)
+        return;
+    if (m_overlayScrollbarsLocked)
+        return;
+
+    MonotonicTime currentTime = MonotonicTime::now();
+    double progress = 1;
+    if (currentTime < m_overlayScrollbarAnimationEndTime)
+        progress = (currentTime - m_overlayScrollbarAnimationStartTime).value() / (m_overlayScrollbarAnimationEndTime - m_overlayScrollbarAnimationStartTime).value();
+    progress = m_overlayScrollbarAnimationSource + (easeOutCubic(progress) * (m_overlayScrollbarAnimationTarget - m_overlayScrollbarAnimationSource));
+    if (progress != m_overlayScrollbarAnimationCurrent) {
+        m_overlayScrollbarAnimationCurrent = progress;
+        updateOverlayScrollbarsOpacity();
+    }
+
+    if (m_overlayScrollbarAnimationCurrent != m_overlayScrollbarAnimationTarget) {
+        static const double frameRate = 60;
+        static const Seconds tickTime = 1_s / frameRate;
+        static const Seconds minimumTimerInterval = 1_ms;
+        Seconds deltaToNextFrame = std::max(tickTime - (MonotonicTime::now() - currentTime), minimumTimerInterval);
+        m_overlayScrollbarAnimationTimer.startOneShot(deltaToNextFrame);
+    } else
+        hideOverlayScrollbars();
+}
+
+void ScrollAnimatorJava::showOverlayScrollbars()
+{
+    if (m_overlayScrollbarsLocked)
+        return;
+
+    if (m_overlayScrollbarAnimationTimer.isActive() && m_overlayScrollbarAnimationTarget == 1)
+        return;
+    m_overlayScrollbarAnimationTimer.stop();
+
+    if (!m_horizontalOverlayScrollbar && !m_verticalOverlayScrollbar)
+        return;
+
+    m_overlayScrollbarAnimationSource = m_overlayScrollbarAnimationCurrent;
+    m_overlayScrollbarAnimationTarget = 1;
+    if (m_overlayScrollbarAnimationTarget != m_overlayScrollbarAnimationCurrent) {
+        m_overlayScrollbarAnimationStartTime = MonotonicTime::now();
+        m_overlayScrollbarAnimationEndTime = m_overlayScrollbarAnimationStartTime + overflowScrollbarsAnimationDuration;
+        m_overlayScrollbarAnimationTimer.startOneShot(0_s);
+    } else
+        hideOverlayScrollbars();
+}
+
+void ScrollAnimatorJava::hideOverlayScrollbars()
+{
+    if (m_overlayScrollbarAnimationTimer.isActive() && !m_overlayScrollbarAnimationTarget)
+        return;
+    m_overlayScrollbarAnimationTimer.stop();
+
+    if (!m_horizontalOverlayScrollbar && !m_verticalOverlayScrollbar)
+        return;
+
+    m_overlayScrollbarAnimationSource = m_overlayScrollbarAnimationCurrent;
+    m_overlayScrollbarAnimationTarget = 0;
+    if (m_overlayScrollbarAnimationTarget == m_overlayScrollbarAnimationCurrent)
+        return;
+    m_overlayScrollbarAnimationStartTime = MonotonicTime::now() + overflowScrollbarsAnimationHideDelay;
+    m_overlayScrollbarAnimationEndTime = m_overlayScrollbarAnimationStartTime + overflowScrollbarsAnimationDuration + overflowScrollbarsAnimationHideDelay;
+    m_overlayScrollbarAnimationTimer.startOneShot(overflowScrollbarsAnimationHideDelay);
+}
+
+void ScrollAnimatorJava::mouseEnteredContentArea()
+{
+    showOverlayScrollbars();
+}
+
+void ScrollAnimatorJava::mouseExitedContentArea()
+{
+    hideOverlayScrollbars();
+}
+
+void ScrollAnimatorJava::mouseMovedInContentArea()
+{
+    showOverlayScrollbars();
+}
+
+void ScrollAnimatorJava::contentAreaDidShow()
+{
+    showOverlayScrollbars();
+}
+
+void ScrollAnimatorJava::contentAreaDidHide()
+{
+    if (m_overlayScrollbarsLocked)
+        return;
+    m_overlayScrollbarAnimationTimer.stop();
+    if (m_overlayScrollbarAnimationCurrent) {
+        m_overlayScrollbarAnimationCurrent = 0;
+        updateOverlayScrollbarsOpacity();
+    }
+}
+
+void ScrollAnimatorJava::notifyContentAreaScrolled(const FloatSize&)
+{
+    showOverlayScrollbars();
+}
+
+void ScrollAnimatorJava::lockOverlayScrollbarStateToHidden(bool shouldLockState)
+{
+    if (m_overlayScrollbarsLocked == shouldLockState)
+        return;
+    m_overlayScrollbarsLocked = shouldLockState;
+
+    if (!m_horizontalOverlayScrollbar && !m_verticalOverlayScrollbar)
+        return;
+
+    if (m_overlayScrollbarsLocked) {
+        m_overlayScrollbarAnimationTimer.stop();
+        if (m_horizontalOverlayScrollbar)
+            m_horizontalOverlayScrollbar->setOpacity(0);
+        if (m_verticalOverlayScrollbar)
+            m_verticalOverlayScrollbar->setOpacity(0);
+    } else {
+        if (m_overlayScrollbarAnimationCurrent == 1)
+            updateOverlayScrollbarsOpacity();
+        else
+            showOverlayScrollbars();
+    }
+}
+
+} // namespace WebCore
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/modules/javafx.web/src/main/native/Source/WebCore/platform/java/ScrollAnimatorJava.h	Fri Feb 22 15:36:53 2019 +0530
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2016 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "ScrollAnimator.h"
+#include "Timer.h"
+
+namespace WebCore {
+
+class ScrollAnimation;
+
+class ScrollAnimatorJava final : public ScrollAnimator {
+public:
+    explicit ScrollAnimatorJava(ScrollableArea&);
+    virtual ~ScrollAnimatorJava();
+
+private:
+#if ENABLE(SMOOTH_SCROLLING)
+    bool scroll(ScrollbarOrientation, ScrollGranularity, float step, float multiplier) override;
+#endif
+    void scrollToOffsetWithoutAnimation(const FloatPoint&, ScrollClamping) override;
+    void willEndLiveResize() override;
+
+    bool handleWheelEvent(const PlatformWheelEvent&) override;
+
+    void didAddVerticalScrollbar(Scrollbar*) override;
+    void didAddHorizontalScrollbar(Scrollbar*) override;
+    void willRemoveVerticalScrollbar(Scrollbar*) override;
+    void willRemoveHorizontalScrollbar(Scrollbar*) override;
+
+    void mouseEnteredContentArea() override;
+    void mouseExitedContentArea() override;
+    void mouseMovedInContentArea() override;
+    void contentAreaDidShow() override;
+    void contentAreaDidHide() override;
+    void notifyContentAreaScrolled(const FloatSize& delta) override;
+    void lockOverlayScrollbarStateToHidden(bool) override;
+
+    void updatePosition(FloatPoint&&);
+
+    void overlayScrollbarAnimationTimerFired();
+    void showOverlayScrollbars();
+    void hideOverlayScrollbars();
+    void updateOverlayScrollbarsOpacity();
+
+    FloatPoint computeVelocity();
+
+#if ENABLE(SMOOTH_SCROLLING)
+    void ensureSmoothScrollingAnimation();
+
+    std::unique_ptr<ScrollAnimation> m_smoothAnimation;
+#endif
+    std::unique_ptr<ScrollAnimation> m_kineticAnimation;
+    Vector<PlatformWheelEvent> m_scrollHistory;
+    Scrollbar* m_horizontalOverlayScrollbar { nullptr };
+    Scrollbar* m_verticalOverlayScrollbar { nullptr };
+    bool m_overlayScrollbarsLocked { false };
+    Timer m_overlayScrollbarAnimationTimer;
+    double m_overlayScrollbarAnimationSource { 0 };
+    double m_overlayScrollbarAnimationTarget { 0 };
+    double m_overlayScrollbarAnimationCurrent { 0 };
+    MonotonicTime m_overlayScrollbarAnimationStartTime;
+    MonotonicTime m_overlayScrollbarAnimationEndTime;
+};
+
+} // namespace WebCore
--- a/modules/javafx.web/src/main/native/Source/WebCore/platform/java/ScrollbarThemeJava.cpp	Tue Feb 19 13:22:46 2019 -0800
+++ b/modules/javafx.web/src/main/native/Source/WebCore/platform/java/ScrollbarThemeJava.cpp	Fri Feb 22 15:36:53 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -130,17 +130,28 @@
 }
 
 
-bool ScrollbarThemeJava::paint(Scrollbar& scrollbar, GraphicsContext& gc, const IntRect&)
+bool ScrollbarThemeJava::paint(Scrollbar& scrollbar, GraphicsContext& gc, const IntRect& damageRect)
 {
     // platformContext() returns 0 when printing
     if (gc.paintingDisabled() || !gc.platformContext()) {
-        return true;
+        return false;
     }
 
     JLObject jtheme = getJScrollBarTheme(scrollbar);
     if (!jtheme) {
         return false;
     }
+
+    double opacity = scrollbar.hoveredPart() == NoPart ? scrollbar.opacity() : 1;
+    if (!opacity) {
+        return true;
+    }
+
+    IntRect rect = scrollbar.frameRect();
+    if (!rect.intersects(damageRect)) {
+        return true;
+    }
+
     JNIEnv* env = WebCore_GetJavaEnv();
 
     static jmethodID mid = env->GetMethodID(
@@ -162,6 +173,11 @@
     ASSERT(widgetRef.get());
     CheckAndClearException(env);
 
+    if (opacity != 1) {
+        gc.save();
+        gc.clip(damageRect);
+        gc.beginTransparencyLayer(opacity);
+    }
     // widgetRef will go into rq's inner refs vector.
     gc.platformContext()->rq().freeSpace(28)
         << (jint)com_sun_webkit_graphics_GraphicsDecoder_DRAWSCROLLBAR
@@ -172,6 +188,11 @@
         << (jint)scrollbar.pressedPart()
         << (jint)scrollbar.hoveredPart();
 
+    if (opacity != 1) {
+        gc.endTransparencyLayer();
+        gc.restore();
+    }
+
     return false;
 }
 
--- a/modules/javafx.web/src/main/native/Source/WebCore/platform/java/ScrollbarThemeJava.h	Tue Feb 19 13:22:46 2019 -0800
+++ b/modules/javafx.web/src/main/native/Source/WebCore/platform/java/ScrollbarThemeJava.h	Fri Feb 22 15:36:53 2019 +0530
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -44,6 +44,8 @@
     IntRect forwardButtonRect(Scrollbar&, ScrollbarPart, bool painting = false) override;
     IntRect trackRect(Scrollbar&, bool painting = false) override;
     bool usesOverlayScrollbars() const final { return true; }
+    // When using overlay scrollbars, always invalidate the whole scrollbar when entering/leaving.
+    bool invalidateOnMouseEnterExit() override { return usesOverlayScrollbars(); }
 };
 
 } // namespace WebCore