1/* 2 * Copyright (C) 2008 Apple 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 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27#include "ScrollbarThemeGtk.h" 28 29#ifndef GTK_API_VERSION_2 30 31#include "PlatformContextCairo.h" 32#include "PlatformMouseEvent.h" 33#include "RenderThemeGtk.h" 34#include "ScrollView.h" 35#include "Scrollbar.h" 36#include <gtk/gtk.h> 37 38namespace WebCore { 39 40static void gtkStyleChangedCallback(GtkWidget*, ScrollbarThemeGtk* scrollbarTheme) 41{ 42 scrollbarTheme->updateThemeProperties(); 43} 44 45ScrollbarThemeGtk::ScrollbarThemeGtk() 46 : m_context(static_cast<RenderThemeGtk*>(RenderTheme::defaultTheme().get())->gtkScrollbarStyle()) 47{ 48 updateThemeProperties(); 49 g_signal_connect(m_context, "changed", G_CALLBACK(gtkStyleChangedCallback), this); 50} 51 52void ScrollbarThemeGtk::updateThemeProperties() 53{ 54 gtk_style_context_get_style(m_context, 55 "min-slider-length", &m_minThumbLength, 56 "slider-width", &m_thumbFatness, 57 "trough-border", &m_troughBorderWidth, 58 "stepper-size", &m_stepperSize, 59 "stepper-spacing", &m_stepperSpacing, 60 "trough-under-steppers", &m_troughUnderSteppers, 61 "has-backward-stepper", &m_hasBackButtonStartPart, 62 "has-forward-stepper", &m_hasForwardButtonEndPart, 63 "has-secondary-backward-stepper", &m_hasBackButtonEndPart, 64 "has-secondary-forward-stepper", &m_hasForwardButtonStartPart, 65 NULL); 66 updateScrollbarsFrameThickness(); 67} 68 69static void applyScrollbarStyleContextClasses(GtkStyleContext* context, ScrollbarOrientation orientation) 70{ 71 gtk_style_context_add_class(context, GTK_STYLE_CLASS_SCROLLBAR); 72 gtk_style_context_add_class(context, orientation == VerticalScrollbar ? GTK_STYLE_CLASS_VERTICAL : GTK_STYLE_CLASS_HORIZONTAL); 73} 74 75void ScrollbarThemeGtk::paintTrackBackground(GraphicsContext* context, ScrollbarThemeClient* scrollbar, const IntRect& rect) 76{ 77 // Paint the track background. If the trough-under-steppers property is true, this 78 // should be the full size of the scrollbar, but if is false, it should only be the 79 // track rect. 80 IntRect fullScrollbarRect(rect); 81 if (m_troughUnderSteppers) 82 fullScrollbarRect = IntRect(scrollbar->x(), scrollbar->y(), scrollbar->width(), scrollbar->height()); 83 84 gtk_style_context_save(m_context); 85 86 applyScrollbarStyleContextClasses(m_context, scrollbar->orientation()); 87 gtk_style_context_add_class(m_context, GTK_STYLE_CLASS_TROUGH); 88 89 gtk_render_background(m_context, context->platformContext()->cr(), 90 fullScrollbarRect.x(), fullScrollbarRect.y(), fullScrollbarRect.width(), fullScrollbarRect.height()); 91 gtk_render_frame(m_context, context->platformContext()->cr(), 92 fullScrollbarRect.x(), fullScrollbarRect.y(), fullScrollbarRect.width(), fullScrollbarRect.height()); 93 94 gtk_style_context_restore(m_context); 95} 96 97void ScrollbarThemeGtk::paintScrollbarBackground(GraphicsContext* context, ScrollbarThemeClient* scrollbar) 98{ 99 gtk_style_context_save(m_context); 100 101 applyScrollbarStyleContextClasses(m_context, scrollbar->orientation()); 102 gtk_style_context_add_class(m_context, "scrolled-window"); 103 gtk_render_frame(m_context, context->platformContext()->cr(), scrollbar->x(), scrollbar->y(), scrollbar->width(), scrollbar->height()); 104 105 gtk_style_context_restore(m_context); 106} 107 108void ScrollbarThemeGtk::paintThumb(GraphicsContext* context, ScrollbarThemeClient* scrollbar, const IntRect& rect) 109{ 110 gtk_style_context_save(m_context); 111 112 ScrollbarOrientation orientation = scrollbar->orientation(); 113 applyScrollbarStyleContextClasses(m_context, orientation); 114 gtk_style_context_add_class(m_context, GTK_STYLE_CLASS_SLIDER); 115 116 guint flags = 0; 117 if (scrollbar->pressedPart() == ThumbPart) 118 flags |= GTK_STATE_FLAG_ACTIVE; 119 if (scrollbar->hoveredPart() == ThumbPart) 120 flags |= GTK_STATE_FLAG_PRELIGHT; 121 gtk_style_context_set_state(m_context, static_cast<GtkStateFlags>(flags)); 122 123 gtk_render_slider(m_context, context->platformContext()->cr(), rect.x(), rect.y(), rect.width(), rect.height(), 124 orientation == VerticalScrollbar ? GTK_ORIENTATION_VERTICAL : GTK_ORIENTATION_HORIZONTAL); 125 126 gtk_style_context_restore(m_context); 127} 128 129void ScrollbarThemeGtk::paintButton(GraphicsContext* context, ScrollbarThemeClient* scrollbar, const IntRect& rect, ScrollbarPart part) 130{ 131 gtk_style_context_save(m_context); 132 133 ScrollbarOrientation orientation = scrollbar->orientation(); 134 applyScrollbarStyleContextClasses(m_context, orientation); 135 136 guint flags = 0; 137 if ((BackButtonStartPart == part && scrollbar->currentPos()) 138 || (BackButtonEndPart == part && scrollbar->currentPos()) 139 || (ForwardButtonEndPart == part && scrollbar->currentPos() != scrollbar->maximum()) 140 || (ForwardButtonStartPart == part && scrollbar->currentPos() != scrollbar->maximum())) { 141 if (part == scrollbar->pressedPart()) 142 flags |= GTK_STATE_FLAG_ACTIVE; 143 if (part == scrollbar->hoveredPart()) 144 flags |= GTK_STATE_FLAG_PRELIGHT; 145 } else 146 flags |= GTK_STATE_FLAG_INSENSITIVE; 147 gtk_style_context_set_state(m_context, static_cast<GtkStateFlags>(flags)); 148 149 gtk_style_context_add_class(m_context, GTK_STYLE_CLASS_BUTTON); 150 gtk_render_background(m_context, context->platformContext()->cr(), rect.x(), rect.y(), rect.width(), rect.height()); 151 gtk_render_frame(m_context, context->platformContext()->cr(), rect.x(), rect.y(), rect.width(), rect.height()); 152 153 gfloat arrowScaling; 154 gtk_style_context_get_style(m_context, "arrow-scaling", &arrowScaling, NULL); 155 156 double arrowSize = std::min(rect.width(), rect.height()) * arrowScaling; 157 FloatPoint arrowPoint(rect.x() + (rect.width() - arrowSize) / 2, 158 rect.y() + (rect.height() - arrowSize) / 2); 159 160 if (flags & GTK_STATE_FLAG_ACTIVE) { 161 gint arrowDisplacementX, arrowDisplacementY; 162 gtk_style_context_get_style(m_context, 163 "arrow-displacement-x", &arrowDisplacementX, 164 "arrow-displacement-y", &arrowDisplacementY, 165 NULL); 166 arrowPoint.move(arrowDisplacementX, arrowDisplacementY); 167 } 168 169 gdouble angle; 170 if (orientation == VerticalScrollbar) { 171 angle = (part == ForwardButtonEndPart || part == ForwardButtonStartPart) ? G_PI : 0; 172 } else { 173 angle = (part == ForwardButtonEndPart || part == ForwardButtonStartPart) ? G_PI / 2 : 3 * (G_PI / 2); 174 } 175 176 gtk_render_arrow(m_context, context->platformContext()->cr(), angle, arrowPoint.x(), arrowPoint.y(), arrowSize); 177 178 gtk_style_context_restore(m_context); 179} 180 181} // namespace WebCore 182 183#endif // !GTK_API_VERSION_2 184