1 /* 2 * Copyright (C) 2013 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 #include "core/platform/mac/ScrollbarThemeMacOverlayAPI.h" 33 34 #include "core/platform/graphics/GraphicsContext.h" 35 #include "core/platform/graphics/GraphicsContextStateSaver.h" 36 #include "core/platform/mac/LocalCurrentGraphicsContext.h" 37 #include "core/platform/mac/NSScrollerImpDetails.h" 38 #include "core/platform/ScrollbarThemeClient.h" 39 40 namespace WebCore { 41 42 typedef HashMap<ScrollbarThemeClient*, RetainPtr<ScrollbarPainter> > ScrollbarPainterMap; 43 44 static ScrollbarPainterMap* scrollbarPainterMap() 45 { 46 static ScrollbarPainterMap* map = new ScrollbarPainterMap; 47 return map; 48 } 49 50 static bool supportsExpandedScrollbars() 51 { 52 // FIXME: This is temporary until all platforms that support ScrollbarPainter support this part of the API. 53 static bool globalSupportsExpandedScrollbars = [NSClassFromString(@"NSScrollerImp") instancesRespondToSelector:@selector(setExpanded:)]; 54 return globalSupportsExpandedScrollbars; 55 } 56 57 void ScrollbarThemeMacOverlayAPI::registerScrollbar(ScrollbarThemeClient* scrollbar) 58 { 59 ScrollbarThemeMacCommon::registerScrollbar(scrollbar); 60 61 bool isHorizontal = scrollbar->orientation() == HorizontalScrollbar; 62 ScrollbarPainter scrollbarPainter = [NSClassFromString(@"NSScrollerImp") scrollerImpWithStyle:recommendedScrollerStyle() controlSize:(NSControlSize)scrollbar->controlSize() horizontal:isHorizontal replacingScrollerImp:nil]; 63 scrollbarPainterMap()->add(scrollbar, scrollbarPainter); 64 updateEnabledState(scrollbar); 65 updateScrollbarOverlayStyle(scrollbar); 66 } 67 68 void ScrollbarThemeMacOverlayAPI::unregisterScrollbar(ScrollbarThemeClient* scrollbar) 69 { 70 scrollbarPainterMap()->remove(scrollbar); 71 72 ScrollbarThemeMacCommon::unregisterScrollbar(scrollbar); 73 } 74 75 void ScrollbarThemeMacOverlayAPI::setNewPainterForScrollbar(ScrollbarThemeClient* scrollbar, ScrollbarPainter newPainter) 76 { 77 scrollbarPainterMap()->set(scrollbar, newPainter); 78 updateEnabledState(scrollbar); 79 updateScrollbarOverlayStyle(scrollbar); 80 } 81 82 ScrollbarPainter ScrollbarThemeMacOverlayAPI::painterForScrollbar(ScrollbarThemeClient* scrollbar) 83 { 84 return scrollbarPainterMap()->get(scrollbar).get(); 85 } 86 87 void ScrollbarThemeMacOverlayAPI::paintTrackBackground(GraphicsContext* context, ScrollbarThemeClient* scrollbar, const IntRect& rect) { 88 ASSERT(isScrollbarOverlayAPIAvailable()); 89 90 GraphicsContextStateSaver stateSaver(*context); 91 context->translate(rect.x(), rect.y()); 92 LocalCurrentGraphicsContext localContext(context); 93 94 CGRect frameRect = scrollbar->frameRect(); 95 ScrollbarPainter scrollbarPainter = painterForScrollbar(scrollbar); 96 [scrollbarPainter setEnabled:scrollbar->enabled()]; 97 [scrollbarPainter setBoundsSize: NSSizeFromCGSize(frameRect.size)]; 98 99 NSRect trackRect = NSMakeRect(0, 0, frameRect.size.width, frameRect.size.height); 100 [scrollbarPainter drawKnobSlotInRect:trackRect highlight:NO]; 101 } 102 103 void ScrollbarThemeMacOverlayAPI::paintThumb(GraphicsContext* context, ScrollbarThemeClient* scrollbar, const IntRect& rect) { 104 ASSERT(isScrollbarOverlayAPIAvailable()); 105 106 GraphicsContextStateSaver stateSaver(*context); 107 context->translate(rect.x(), rect.y()); 108 LocalCurrentGraphicsContext localContext(context); 109 110 ScrollbarPainter scrollbarPainter = painterForScrollbar(scrollbar); 111 CGRect frameRect = scrollbar->frameRect(); 112 [scrollbarPainter setEnabled:scrollbar->enabled()]; 113 [scrollbarPainter setBoundsSize:NSSizeFromCGSize(rect.size())]; 114 [scrollbarPainter setDoubleValue:0]; 115 [scrollbarPainter setKnobProportion:1]; 116 if (scrollbar->enabled()) 117 [scrollbarPainter drawKnob]; 118 119 // If this state is not set, then moving the cursor over the scrollbar area will only cause the 120 // scrollbar to engorge when moved over the top of the scrollbar area. 121 [scrollbarPainter setBoundsSize: NSSizeFromCGSize(scrollbar->frameRect().size())]; 122 } 123 124 int ScrollbarThemeMacOverlayAPI::scrollbarThickness(ScrollbarControlSize controlSize) 125 { 126 ScrollbarPainter scrollbarPainter = [NSClassFromString(@"NSScrollerImp") scrollerImpWithStyle:recommendedScrollerStyle() controlSize:controlSize horizontal:NO replacingScrollerImp:nil]; 127 if (supportsExpandedScrollbars()) 128 [scrollbarPainter setExpanded:YES]; 129 return [scrollbarPainter trackBoxWidth]; 130 } 131 132 bool ScrollbarThemeMacOverlayAPI::usesOverlayScrollbars() const 133 { 134 return recommendedScrollerStyle() == NSScrollerStyleOverlay; 135 } 136 137 void ScrollbarThemeMacOverlayAPI::updateScrollbarOverlayStyle(ScrollbarThemeClient* scrollbar) 138 { 139 ScrollbarPainter painter = painterForScrollbar(scrollbar); 140 switch (scrollbar->scrollbarOverlayStyle()) { 141 case ScrollbarOverlayStyleDefault: 142 [painter setKnobStyle:NSScrollerKnobStyleDefault]; 143 break; 144 case ScrollbarOverlayStyleDark: 145 [painter setKnobStyle:NSScrollerKnobStyleDark]; 146 break; 147 case ScrollbarOverlayStyleLight: 148 [painter setKnobStyle:NSScrollerKnobStyleLight]; 149 break; 150 } 151 } 152 153 ScrollbarButtonsPlacement ScrollbarThemeMacOverlayAPI::buttonsPlacement() const 154 { 155 return ScrollbarButtonsNone; 156 } 157 158 bool ScrollbarThemeMacOverlayAPI::hasThumb(ScrollbarThemeClient* scrollbar) 159 { 160 ScrollbarPainter painter = painterForScrollbar(scrollbar); 161 int minLengthForThumb = [painter knobMinLength] + [painter trackOverlapEndInset] + [painter knobOverlapEndInset] 162 + 2 * ([painter trackEndInset] + [painter knobEndInset]); 163 return scrollbar->enabled() && (scrollbar->orientation() == HorizontalScrollbar ? 164 scrollbar->width() : 165 scrollbar->height()) >= minLengthForThumb; 166 } 167 168 IntRect ScrollbarThemeMacOverlayAPI::backButtonRect(ScrollbarThemeClient* scrollbar, ScrollbarPart part, bool painting) 169 { 170 ASSERT(buttonsPlacement() == ScrollbarButtonsNone); 171 return IntRect(); 172 } 173 174 IntRect ScrollbarThemeMacOverlayAPI::forwardButtonRect(ScrollbarThemeClient* scrollbar, ScrollbarPart part, bool painting) 175 { 176 ASSERT(buttonsPlacement() == ScrollbarButtonsNone); 177 return IntRect(); 178 } 179 180 IntRect ScrollbarThemeMacOverlayAPI::trackRect(ScrollbarThemeClient* scrollbar, bool painting) 181 { 182 ASSERT(!hasButtons(scrollbar)); 183 return scrollbar->frameRect(); 184 } 185 186 int ScrollbarThemeMacOverlayAPI::minimumThumbLength(ScrollbarThemeClient* scrollbar) 187 { 188 return [painterForScrollbar(scrollbar) knobMinLength]; 189 } 190 191 void ScrollbarThemeMacOverlayAPI::updateEnabledState(ScrollbarThemeClient* scrollbar) 192 { 193 [painterForScrollbar(scrollbar) setEnabled:scrollbar->enabled()]; 194 } 195 196 } // namespace WebCore 197