ScrollbarOverlayUtilitiesMac.mm [plain text]
/*
* Copyright (C) 2008, 2011 Apple Inc. All Rights Reserved.
* Copyright (C) 2011 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:
* 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. ``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
* 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"
#if USE(WK_SCROLLBAR_PAINTER)
#include "ScrollbarOverlayUtilitiesMac.h"
#include "ScrollTypes.h"
#include <Cocoa/Cocoa.h>
// -----------------------------------------------------------------------------
// This file contains utilities to draw overlay scrollbars. There are no public
// APIs yet on the Mac to draw overlay scrollbars so we use private APIs that
// we look up at runtime. If the private APIs don't exist then the wkMake*
// functions will return nil.
//
// Note, this file contains functions copied from WebCoreSystemInterface.h.
// Using the same names makes the code easier to maintain.
// -----------------------------------------------------------------------------
// Public APIs not available on versions of Mac on which we build
#if (defined(BUILDING_ON_LEOPARD) || defined(BUILDING_ON_SNOW_LEOPARD))
@interface NSScroller (NSObject)
+ (NSScrollerStyle)preferredScrollerStyle;
@end
#endif
// These are private APIs to draw overlay scrollbars.
@interface NSScrollerImp : NSObject
+ (id)scrollerImpWithStyle:(NSScrollerStyle)style
controlSize:(NSControlSize)size
horizontal:(BOOL)horizontal
replacingScrollerImp:(id)scroller;
@property CGFloat knobAlpha;
@property CGFloat trackAlpha;
@property CGFloat knobProportion;
@property(getter=isEnabled) BOOL enabled;
@property(getter=isHorizontal) BOOL horizontal;
@property double doubleValue;
@property(assign) id delegate;
- (CGFloat)knobMinLength;
- (CGFloat)trackBoxWidth;
- (CGFloat)trackWidth;
- (void)setBoundsSize:(NSSize)size;
- (void)drawKnobSlotInRect:(NSRect)rect
highlight:(BOOL)flag;
- (void)drawKnob;
- (void)setOverlayScrollerState:(NSScrollerStyle)state
forceImmediately:(BOOL)flag;
- (void)setDelegate:(id)delegate;
@end
// These are private APIs to manage overlay scrollbars.
@interface NSScrollerImpPair : NSObject
@property NSScrollerStyle scrollerStyle;
@property(retain) NSScrollerImp *horizontalScrollerImp;
@property(retain) NSScrollerImp *verticalScrollerImp;
@property(assign) id delegate;
- (void)flashScrollers;
- (void)contentAreaScrolled;
- (void)contentAreaWillDraw;
- (void)contentAreaDidHide;
- (void)windowOrderedOut;
- (void)windowOrderedIn;
- (void)mouseEnteredContentArea;
- (void)mouseMovedInContentArea;
- (void)mouseExitedContentArea;
- (void)startLiveResize;
- (void)contentAreaDidResize;
- (void)endLiveResize;
- (void)beginScrollGesture;
- (void)endScrollGesture;
@end
static Class lookUpNSScrollerImpClass()
{
static Class result = NSClassFromString(@"NSScrollerImp");
return result;
}
static Class lookUpNSScrollerImpPairClass()
{
static Class result = NSClassFromString(@"NSScrollerImpPair");
return result;
}
static NSControlSize scrollbarControlSizeToNSControlSize(int controlSize)
{
return controlSize == WebCore::RegularScrollbar ? NSRegularControlSize : NSSmallControlSize;
}
static NSScrollerStyle preferredScrollerStyle()
{
if ([NSScroller respondsToSelector:@selector(preferredScrollerStyle)])
return [NSScroller preferredScrollerStyle];
return NSScrollerStyleLegacy;
}
bool wkScrollbarPainterUsesOverlayScrollers(void)
{
return preferredScrollerStyle() == NSScrollerStyleOverlay;
}
bool wkScrollbarPainterIsHorizontal(WKScrollbarPainterRef painter)
{
return [painter isHorizontal];
}
CGFloat wkScrollbarPainterKnobAlpha(WKScrollbarPainterRef painter)
{
return [painter knobAlpha];
}
void wkScrollbarPainterSetOverlayState(WKScrollbarPainterRef painter, int overlayScrollerState)
{
[painter setOverlayScrollerState:overlayScrollerState
forceImmediately:YES];
}
void wkScrollbarPainterPaint(WKScrollbarPainterRef painter, bool enabled, double value, CGFloat proportion, NSRect frameRect)
{
[painter setEnabled:enabled];
[painter setBoundsSize:frameRect.size];
[painter setDoubleValue:value];
[painter setKnobProportion:proportion];
if ([painter isHorizontal])
frameRect.size.height = [painter trackWidth];
else
frameRect.size.width = [painter trackWidth];
[painter drawKnobSlotInRect:frameRect highlight:NO];
[painter drawKnob];
}
int wkScrollbarMinimumThumbLength(WKScrollbarPainterRef painter)
{
return [painter knobMinLength];
}
void wkScrollbarPainterSetDelegate(WKScrollbarPainterRef painter, id scrollbarPainterDelegate)
{
[painter setDelegate:scrollbarPainterDelegate];
}
CGFloat wkScrollbarPainterTrackAlpha(WKScrollbarPainterRef painter)
{
return [painter trackAlpha];
}
WKScrollbarPainterRef wkMakeScrollbarPainter(int controlSize, bool isHorizontal)
{
return wkMakeScrollbarReplacementPainter(nil, preferredScrollerStyle(), controlSize, isHorizontal);
}
int wkScrollbarThickness(int controlSize)
{
return [wkMakeScrollbarPainter(controlSize, false) trackBoxWidth];
}
int wkScrollbarMinimumTotalLengthNeededForThumb(WKScrollbarPainterRef painter)
{
// TODO(sail): This doesn't match the implementation in WebKitSystemInterface.
return wkScrollbarMinimumThumbLength(painter);
}
WKScrollbarPainterRef wkVerticalScrollbarPainterForController(WKScrollbarPainterControllerRef controller)
{
return [controller verticalScrollerImp];
}
WKScrollbarPainterRef wkHorizontalScrollbarPainterForController(WKScrollbarPainterControllerRef controller)
{
return [controller horizontalScrollerImp];
}
WKScrollbarPainterRef wkMakeScrollbarReplacementPainter(WKScrollbarPainterRef oldPainter, int newStyle, int controlSize, bool isHorizontal)
{
if (!isScrollbarOverlayAPIAvailable())
return nil;
return [lookUpNSScrollerImpClass() scrollerImpWithStyle:newStyle
controlSize:scrollbarControlSizeToNSControlSize(controlSize)
horizontal:isHorizontal
replacingScrollerImp:oldPainter];
}
void wkSetPainterForPainterController(WKScrollbarPainterControllerRef controller, WKScrollbarPainterRef painter, bool isHorizontal)
{
if (isHorizontal)
[controller setHorizontalScrollerImp:painter];
else
[controller setVerticalScrollerImp:painter];
}
void wkSetScrollbarPainterControllerStyle(WKScrollbarPainterControllerRef painter, int newStyle)
{
[painter setScrollerStyle:newStyle];
}
CGRect wkScrollbarPainterKnobRect(WKScrollbarPainterRef painter)
{
return NSRectToCGRect(NSZeroRect);
}
void wkSetScrollbarPainterKnobAlpha(WKScrollbarPainterRef painter, CGFloat alpha)
{
[painter setKnobAlpha:alpha];
}
void wkSetScrollbarPainterTrackAlpha(WKScrollbarPainterRef painter, CGFloat alpha)
{
[painter setTrackAlpha:alpha];
}
void wkSetScrollbarPainterKnobStyle(WKScrollbarPainterRef painter, wkScrollerKnobStyle style)
{
// TODO(sail): A knob style API doesn't exist in the seeds currently available.
}
WKScrollbarPainterControllerRef wkMakeScrollbarPainterController(id painterControllerDelegate)
{
if (!isScrollbarOverlayAPIAvailable())
return nil;
NSScrollerImpPair* controller = [[[lookUpNSScrollerImpPairClass() alloc] init] autorelease];
[controller setDelegate:painterControllerDelegate];
[controller setScrollerStyle:preferredScrollerStyle()];
return controller;
}
void wkContentAreaScrolled(WKScrollbarPainterControllerRef controller)
{
[controller contentAreaScrolled];
}
void wkContentAreaWillPaint(WKScrollbarPainterControllerRef controller)
{
[controller contentAreaWillDraw];
}
void wkMouseEnteredContentArea(WKScrollbarPainterControllerRef controller)
{
[controller mouseEnteredContentArea];
}
void wkMouseExitedContentArea(WKScrollbarPainterControllerRef controller)
{
[controller mouseExitedContentArea];
}
void wkMouseMovedInContentArea(WKScrollbarPainterControllerRef controller)
{
[controller mouseMovedInContentArea];
}
void wkWillStartLiveResize(WKScrollbarPainterControllerRef controller)
{
[controller startLiveResize];
}
void wkContentAreaResized(WKScrollbarPainterControllerRef controller)
{
[controller contentAreaDidResize];
}
void wkWillEndLiveResize(WKScrollbarPainterControllerRef controller)
{
[controller endLiveResize];
}
void wkContentAreaDidShow(WKScrollbarPainterControllerRef controller)
{
[controller windowOrderedIn];
}
void wkContentAreaDidHide(WKScrollbarPainterControllerRef controller)
{
[controller windowOrderedOut];
}
void wkDidBeginScrollGesture(WKScrollbarPainterControllerRef controller)
{
[controller beginScrollGesture];
}
void wkDidEndScrollGesture(WKScrollbarPainterControllerRef controller)
{
[controller endScrollGesture];
}
void wkScrollbarPainterForceFlashScrollers(WKScrollbarPainterControllerRef controller)
{
[controller flashScrollers];
}
bool isScrollbarOverlayAPIAvailable()
{
// TODO(sail): Disable overlay scrollbars for now until the following issues are fixed:
// #1: Invalidation issues causes the scrollbar to leave trailing artifacts.
// #2: Various messages such as live resize started/ended need to be piped from the UI.
// #3: Find tick marks need to be drawn on the scrollbar track.
// #4: Need to have the theme engine draw the thumb.
return false;
static bool apiAvailable = [lookUpNSScrollerImpClass() respondsToSelector:@selector(scrollerImpWithStyle:controlSize:horizontal:replacingScrollerImp:)] &&
[lookUpNSScrollerImpPairClass() instancesRespondToSelector:@selector(scrollerStyle)];
return apiAvailable;
}
#endif // USE(WK_SCROLLBAR_PAINTER)