blob: c42fea7d4f69988cabb46b5c045f5228008188ea [file] [log] [blame]
/*
* Copyright (C) 2019 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS 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 APPLE INC. OR ITS 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 "ScrollerPairMac.h"
#if PLATFORM(MAC)
#include "RemoteScrollingTree.h"
#include <WebCore/FloatPoint.h>
#include <WebCore/IntRect.h>
#include <WebCore/NSScrollerImpDetails.h>
#include <WebCore/PlatformMouseEvent.h>
#include <WebCore/PlatformWheelEvent.h>
#include <WebCore/ScrollTypes.h>
#include <WebCore/ScrollableArea.h>
#include <WebCore/ScrollingTreeScrollingNode.h>
#include <pal/spi/mac/NSScrollerImpSPI.h>
@interface WKScrollerImpPairDelegate : NSObject <NSScrollerImpPairDelegate> {
WebKit::ScrollerPairMac* _scrollerPair;
}
- (id)initWithScrollerPair:(WebKit::ScrollerPairMac*)scrollerPair;
@end
@implementation WKScrollerImpPairDelegate
- (id)initWithScrollerPair:(WebKit::ScrollerPairMac*)scrollerPair
{
self = [super init];
if (!self)
return nil;
_scrollerPair = scrollerPair;
return self;
}
- (void)invalidate
{
_scrollerPair = nullptr;
}
- (NSRect)contentAreaRectForScrollerImpPair:(NSScrollerImpPair *)scrollerImpPair
{
UNUSED_PARAM(scrollerImpPair);
if (!_scrollerPair)
return NSZeroRect;
auto size = _scrollerPair->visibleSize();
return NSMakeRect(0, 0, size.width(), size.height());
}
- (BOOL)inLiveResizeForScrollerImpPair:(NSScrollerImpPair *)scrollerImpPair
{
// FIMXE: Not implemented.
return NO;
}
- (NSPoint)mouseLocationInContentAreaForScrollerImpPair:(NSScrollerImpPair *)scrollerImpPair
{
UNUSED_PARAM(scrollerImpPair);
if (!_scrollerPair)
return NSZeroPoint;
return _scrollerPair->lastKnownMousePosition();
}
- (NSPoint)scrollerImpPair:(NSScrollerImpPair *)scrollerImpPair convertContentPoint:(NSPoint)pointInContentArea toScrollerImp:(NSScrollerImp *)scrollerImp
{
UNUSED_PARAM(scrollerImpPair);
if (!_scrollerPair || !scrollerImp)
return NSZeroPoint;
WebKit::ScrollerMac* scroller = nullptr;
if ([scrollerImp isHorizontal])
scroller = &_scrollerPair->horizontalScroller();
else
scroller = &_scrollerPair->verticalScroller();
ASSERT(scrollerImp == scroller->scrollerImp());
return scroller->convertFromContent(WebCore::IntPoint(pointInContentArea));
}
- (void)scrollerImpPair:(NSScrollerImpPair *)scrollerImpPair setContentAreaNeedsDisplayInRect:(NSRect)rect
{
UNUSED_PARAM(scrollerImpPair);
UNUSED_PARAM(rect);
}
- (void)scrollerImpPair:(NSScrollerImpPair *)scrollerImpPair updateScrollerStyleForNewRecommendedScrollerStyle:(NSScrollerStyle)newRecommendedScrollerStyle
{
[scrollerImpPair setScrollerStyle:newRecommendedScrollerStyle];
}
@end
namespace WebKit {
ScrollerPairMac::ScrollerPairMac(WebCore::ScrollingTreeScrollingNode& node)
: m_scrollingNode(node)
, m_verticalScroller(*this, ScrollerMac::Orientation::Vertical)
, m_horizontalScroller(*this, ScrollerMac::Orientation::Horizontal)
{
m_scrollerImpPairDelegate = adoptNS([[WKScrollerImpPairDelegate alloc] initWithScrollerPair:this]);
m_scrollerImpPair = adoptNS([[NSScrollerImpPair alloc] init]);
[m_scrollerImpPair.get() setDelegate:m_scrollerImpPairDelegate.get()];
[m_scrollerImpPair setScrollerStyle:WebCore::ScrollerStyle::recommendedScrollerStyle()];
m_verticalScroller.attach();
m_horizontalScroller.attach();
}
ScrollerPairMac::~ScrollerPairMac()
{
[m_scrollerImpPairDelegate invalidate];
[m_scrollerImpPair setDelegate:nil];
}
bool ScrollerPairMac::handleWheelEvent(const WebCore::PlatformWheelEvent& event)
{
switch (event.phase()) {
case WebCore::PlatformWheelEventPhaseBegan:
[m_scrollerImpPair beginScrollGesture];
break;
case WebCore::PlatformWheelEventPhaseEnded:
case WebCore::PlatformWheelEventPhaseCancelled:
[m_scrollerImpPair endScrollGesture];
break;
case WebCore::PlatformWheelEventPhaseMayBegin:
[m_scrollerImpPair beginScrollGesture];
[m_scrollerImpPair contentAreaScrolled];
break;
default:
break;
}
// FIXME: this needs to return whether the event was handled.
return true;
}
bool ScrollerPairMac::handleMouseEvent(const WebCore::PlatformMouseEvent& event)
{
if (event.type() != WebCore::PlatformEvent::MouseMoved)
return false;
m_lastKnownMousePosition = event.position();
[m_scrollerImpPair mouseMovedInContentArea];
// FIXME: this needs to return whether the event was handled.
return true;
}
void ScrollerPairMac::updateValues()
{
auto position = m_scrollingNode.currentScrollPosition();
if (position != m_lastScrollPosition) {
if (m_lastScrollPosition) {
auto delta = position - *m_lastScrollPosition;
[m_scrollerImpPair contentAreaScrolledInDirection:NSMakePoint(delta.width(), delta.height())];
}
m_lastScrollPosition = position;
}
m_verticalScroller.updateValues();
m_horizontalScroller.updateValues();
}
WebCore::FloatSize ScrollerPairMac::visibleSize() const
{
return m_scrollingNode.scrollableAreaSize();
}
bool ScrollerPairMac::useDarkAppearance() const
{
return m_scrollingNode.useDarkAppearanceForScrollbars();
}
ScrollerPairMac::Values ScrollerPairMac::valuesForOrientation(ScrollerMac::Orientation orientation)
{
float position;
float totalSize;
float visibleSize;
if (orientation == ScrollerMac:: Orientation::Vertical) {
position = m_scrollingNode.currentScrollPosition().y();
totalSize = m_scrollingNode.totalContentsSize().height();
visibleSize = m_scrollingNode.scrollableAreaSize().height();
} else {
position = m_scrollingNode.currentScrollPosition().x();
totalSize = m_scrollingNode.totalContentsSize().width();
visibleSize = m_scrollingNode.scrollableAreaSize().width();
}
float value;
float overhang;
WebCore::ScrollableArea::computeScrollbarValueAndOverhang(position, totalSize, visibleSize, value, overhang);
float proportion = totalSize ? (visibleSize - overhang) / totalSize : 1;
return { value, proportion };
}
}
#endif