| /* |
| * Copyright (C) 2013 Google 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: |
| * |
| * * 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 "platform/scroll/ScrollbarThemeMacOverlayAPI.h" |
| |
| #include "platform/graphics/GraphicsContext.h" |
| #include "platform/graphics/GraphicsContextStateSaver.h" |
| #include "platform/graphics/paint/DrawingRecorder.h" |
| #include "platform/mac/LocalCurrentGraphicsContext.h" |
| #include "platform/mac/NSScrollerImpDetails.h" |
| #include "platform/scroll/ScrollbarThemeClient.h" |
| #include "wtf/RetainPtr.h" |
| |
| @interface WebCoreScrollbarObserver : NSObject { |
| blink::ScrollbarThemeClient* _scrollbar; |
| RetainPtr<ScrollbarPainter> _scrollbarPainter; |
| BOOL _visible; |
| } |
| - (id)initWithScrollbar:(blink::ScrollbarThemeClient*)scrollbar painter:(ScrollbarPainter)painter; |
| @end |
| |
| @implementation WebCoreScrollbarObserver |
| |
| - (id)initWithScrollbar:(blink::ScrollbarThemeClient*)scrollbar painter:(ScrollbarPainter)painter |
| { |
| if (!(self = [super init])) |
| return nil; |
| _scrollbar = scrollbar; |
| _scrollbarPainter = painter; |
| |
| [_scrollbarPainter.get() addObserver:self forKeyPath:@"knobAlpha" options:0 context:nil]; |
| return self; |
| } |
| |
| - (id)painter |
| { |
| return _scrollbarPainter.get(); |
| } |
| |
| - (void)dealloc |
| { |
| |
| [_scrollbarPainter.get() removeObserver:self forKeyPath:@"knobAlpha"]; |
| [super dealloc]; |
| } |
| |
| - (void)observeValueForKeyPath:(NSString*)keyPath |
| ofObject:(id)object |
| change:(NSDictionary*)change |
| context:(void*)context |
| { |
| if ([keyPath isEqualToString:@"knobAlpha"]) { |
| BOOL visible = [_scrollbarPainter.get() knobAlpha] > 0; |
| if (_visible != visible) { |
| _visible = visible; |
| _scrollbar->visibilityChanged(); |
| } |
| } |
| } |
| |
| @end |
| |
| namespace blink { |
| |
| typedef HashMap<ScrollbarThemeClient*, RetainPtr<WebCoreScrollbarObserver> > ScrollbarPainterMap; |
| |
| static ScrollbarPainterMap* scrollbarPainterMap() |
| { |
| static ScrollbarPainterMap* map = new ScrollbarPainterMap; |
| return map; |
| } |
| |
| static bool supportsExpandedScrollbars() |
| { |
| // FIXME: This is temporary until all platforms that support ScrollbarPainter support this part of the API. |
| static bool globalSupportsExpandedScrollbars = [NSClassFromString(@"NSScrollerImp") instancesRespondToSelector:@selector(setExpanded:)]; |
| return globalSupportsExpandedScrollbars; |
| } |
| |
| void ScrollbarThemeMacOverlayAPI::registerScrollbar(ScrollbarThemeClient* scrollbar) |
| { |
| ScrollbarThemeMacCommon::registerScrollbar(scrollbar); |
| |
| bool isHorizontal = scrollbar->orientation() == HorizontalScrollbar; |
| ScrollbarPainter scrollbarPainter = [NSClassFromString(@"NSScrollerImp") scrollerImpWithStyle:recommendedScrollerStyle() controlSize:(NSControlSize)scrollbar->controlSize() horizontal:isHorizontal replacingScrollerImp:nil]; |
| RetainPtr<WebCoreScrollbarObserver> observer = [[WebCoreScrollbarObserver alloc] initWithScrollbar:scrollbar painter:scrollbarPainter]; |
| |
| scrollbarPainterMap()->add(scrollbar, observer); |
| updateEnabledState(scrollbar); |
| updateScrollbarOverlayStyle(scrollbar); |
| } |
| |
| void ScrollbarThemeMacOverlayAPI::unregisterScrollbar(ScrollbarThemeClient* scrollbar) |
| { |
| scrollbarPainterMap()->remove(scrollbar); |
| |
| ScrollbarThemeMacCommon::unregisterScrollbar(scrollbar); |
| } |
| |
| void ScrollbarThemeMacOverlayAPI::setNewPainterForScrollbar(ScrollbarThemeClient* scrollbar, ScrollbarPainter newPainter) |
| { |
| RetainPtr<WebCoreScrollbarObserver> observer = [[WebCoreScrollbarObserver alloc] initWithScrollbar:scrollbar painter:newPainter]; |
| scrollbarPainterMap()->set(scrollbar, observer); |
| updateEnabledState(scrollbar); |
| updateScrollbarOverlayStyle(scrollbar); |
| } |
| |
| ScrollbarPainter ScrollbarThemeMacOverlayAPI::painterForScrollbar(const ScrollbarThemeClient* scrollbar) |
| { |
| return [scrollbarPainterMap()->get(const_cast<ScrollbarThemeClient*>(scrollbar)).get() painter]; |
| } |
| |
| void ScrollbarThemeMacOverlayAPI::paintTrackBackground(GraphicsContext* context, const ScrollbarThemeClient* scrollbar, const IntRect& rect) { |
| if (DrawingRecorder::useCachedDrawingIfPossible(*context, *scrollbar, DisplayItem::ScrollbarTrackBackground)) |
| return; |
| |
| DrawingRecorder recorder(*context, *scrollbar, DisplayItem::ScrollbarTrackBackground, rect); |
| |
| ASSERT(isOverlayAPIAvailable()); |
| |
| GraphicsContextStateSaver stateSaver(*context); |
| context->translate(rect.x(), rect.y()); |
| LocalCurrentGraphicsContext localContext(context, IntRect(IntPoint(), rect.size())); |
| |
| CGRect frameRect = scrollbar->frameRect(); |
| ScrollbarPainter scrollbarPainter = painterForScrollbar(scrollbar); |
| [scrollbarPainter setEnabled:scrollbar->enabled()]; |
| [scrollbarPainter setBoundsSize: NSSizeFromCGSize(frameRect.size)]; |
| |
| NSRect trackRect = NSMakeRect(0, 0, frameRect.size.width, frameRect.size.height); |
| [scrollbarPainter drawKnobSlotInRect:trackRect highlight:NO]; |
| } |
| |
| void ScrollbarThemeMacOverlayAPI::paintThumb(GraphicsContext* context, const ScrollbarThemeClient* scrollbar, const IntRect& rect) { |
| if (DrawingRecorder::useCachedDrawingIfPossible(*context, *scrollbar, DisplayItem::ScrollbarThumb)) |
| return; |
| |
| // Expand dirty rect to allow for scroll thumb anti-aliasing in minimum thumb size case. |
| IntRect dirtyRect = IntRect(rect); |
| dirtyRect.inflate(1); |
| DrawingRecorder recorder(*context, *scrollbar, DisplayItem::ScrollbarThumb, dirtyRect); |
| |
| ASSERT(isOverlayAPIAvailable()); |
| |
| GraphicsContextStateSaver stateSaver(*context); |
| context->translate(rect.x(), rect.y()); |
| LocalCurrentGraphicsContext localContext(context, IntRect(IntPoint(), rect.size())); |
| |
| ScrollbarPainter scrollbarPainter = painterForScrollbar(scrollbar); |
| [scrollbarPainter setEnabled:scrollbar->enabled()]; |
| [scrollbarPainter setBoundsSize:NSSizeFromCGSize(rect.size())]; |
| [scrollbarPainter setDoubleValue:0]; |
| [scrollbarPainter setKnobProportion:1]; |
| if (scrollbar->enabled()) |
| [scrollbarPainter drawKnob]; |
| |
| // If this state is not set, then moving the cursor over the scrollbar area will only cause the |
| // scrollbar to engorge when moved over the top of the scrollbar area. |
| [scrollbarPainter setBoundsSize: NSSizeFromCGSize(scrollbar->frameRect().size())]; |
| } |
| |
| int ScrollbarThemeMacOverlayAPI::scrollbarThickness(ScrollbarControlSize controlSize) |
| { |
| NSControlSize nsControlSize = static_cast<NSControlSize>(controlSize); |
| ScrollbarPainter scrollbarPainter = [NSClassFromString(@"NSScrollerImp") scrollerImpWithStyle:recommendedScrollerStyle() controlSize:nsControlSize horizontal:NO replacingScrollerImp:nil]; |
| if (supportsExpandedScrollbars()) |
| [scrollbarPainter setExpanded:YES]; |
| return [scrollbarPainter trackBoxWidth]; |
| } |
| |
| bool ScrollbarThemeMacOverlayAPI::usesOverlayScrollbars() const |
| { |
| return recommendedScrollerStyle() == NSScrollerStyleOverlay; |
| } |
| |
| void ScrollbarThemeMacOverlayAPI::updateScrollbarOverlayStyle(const ScrollbarThemeClient* scrollbar) |
| { |
| ScrollbarPainter painter = painterForScrollbar(scrollbar); |
| switch (scrollbar->scrollbarOverlayStyle()) { |
| case ScrollbarOverlayStyleDefault: |
| [painter setKnobStyle:NSScrollerKnobStyleDefault]; |
| break; |
| case ScrollbarOverlayStyleDark: |
| [painter setKnobStyle:NSScrollerKnobStyleDark]; |
| break; |
| case ScrollbarOverlayStyleLight: |
| [painter setKnobStyle:NSScrollerKnobStyleLight]; |
| break; |
| } |
| } |
| |
| ScrollbarButtonsPlacement ScrollbarThemeMacOverlayAPI::buttonsPlacement() const |
| { |
| return ScrollbarButtonsPlacementNone; |
| } |
| |
| bool ScrollbarThemeMacOverlayAPI::hasThumb(const ScrollbarThemeClient* scrollbar) |
| { |
| ScrollbarPainter painter = painterForScrollbar(scrollbar); |
| int minLengthForThumb = [painter knobMinLength] + [painter trackOverlapEndInset] + [painter knobOverlapEndInset] |
| + 2 * ([painter trackEndInset] + [painter knobEndInset]); |
| return scrollbar->enabled() && (scrollbar->orientation() == HorizontalScrollbar ? |
| scrollbar->width() : |
| scrollbar->height()) >= minLengthForThumb; |
| } |
| |
| IntRect ScrollbarThemeMacOverlayAPI::backButtonRect(const ScrollbarThemeClient* scrollbar, ScrollbarPart part, bool painting) |
| { |
| ASSERT(buttonsPlacement() == ScrollbarButtonsPlacementNone); |
| return IntRect(); |
| } |
| |
| IntRect ScrollbarThemeMacOverlayAPI::forwardButtonRect(const ScrollbarThemeClient* scrollbar, ScrollbarPart part, bool painting) |
| { |
| ASSERT(buttonsPlacement() == ScrollbarButtonsPlacementNone); |
| return IntRect(); |
| } |
| |
| IntRect ScrollbarThemeMacOverlayAPI::trackRect(const ScrollbarThemeClient* scrollbar, bool painting) |
| { |
| ASSERT(!hasButtons(scrollbar)); |
| return scrollbar->frameRect(); |
| } |
| |
| int ScrollbarThemeMacOverlayAPI::minimumThumbLength(const ScrollbarThemeClient* scrollbar) |
| { |
| return [painterForScrollbar(scrollbar) knobMinLength]; |
| } |
| |
| void ScrollbarThemeMacOverlayAPI::updateEnabledState(const ScrollbarThemeClient* scrollbar) |
| { |
| [painterForScrollbar(scrollbar) setEnabled:scrollbar->enabled()]; |
| } |
| |
| } // namespace blink |
| |